/ Check-in [699cf362]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Make the LIMIT clause work even if the destination of the SELECT is something other than a callback. (Ticket #66) (CVS 619)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 699cf362083043615eb88635a228bfa46a315c9c
User & Date: drh 2002-06-14 22:38:42
Context
2002-06-16
04:54
Changed sqlite_mprintf_str to allow a NULL string parameter. Command template now is cmd FORMAT INT INT ?STRING?. When STRING omitted a NULL is passed to sqlite_mprintf. (CVS 620) check-in: 8bc71157 user: chw tags: trunk
2002-06-14
22:38
Make the LIMIT clause work even if the destination of the SELECT is something other than a callback. (Ticket #66) (CVS 619) check-in: 699cf362 user: drh tags: trunk
20:58
Improvements to comments. No code changes. (CVS 618) check-in: 7e10e60b user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/select.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle SELECT statements in SQLite.
    14     14   **
    15         -** $Id: select.c,v 1.92 2002/06/06 23:42:28 drh Exp $
           15  +** $Id: select.c,v 1.93 2002/06/14 22:38:42 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   /*
    20     20   ** Allocate a new Select structure and return a pointer to that
    21     21   ** structure.
    22     22   */
................................................................................
   290    290   **
   291    291   ** The pEList is used to determine the values for each column in the
   292    292   ** result row.  Except  if pEList==NULL, then we just read nColumn
   293    293   ** elements from the srcTab table.
   294    294   */
   295    295   static int selectInnerLoop(
   296    296     Parse *pParse,          /* The parser context */
          297  +  Select *p,              /* The complete select statement being coded */
   297    298     ExprList *pEList,       /* List of values being extracted */
   298    299     int srcTab,             /* Pull data from this table */
   299    300     int nColumn,            /* Number of columns in the source table */
   300    301     ExprList *pOrderBy,     /* If not NULL, sort results using this key */
   301    302     int distinct,           /* If >=0, make sure results are distinct */
   302    303     int eDest,              /* How to dispose of the results */
   303    304     int iParm,              /* An argument to the disposal method */
   304    305     int iContinue,          /* Jump here to continue with next row */
   305    306     int iBreak              /* Jump here to break out of the inner loop */
   306    307   ){
   307    308     Vdbe *v = pParse->pVdbe;
   308    309     int i;
   309    310     if( v==0 ) return 0;
          311  +
          312  +  /* If there was a LIMIT clause on the SELECT statement, then do the check
          313  +  ** to see if this row should be output.
          314  +  */
          315  +  if( pOrderBy==0 ){
          316  +    if( p->nOffset>0 ){
          317  +      sqliteVdbeAddOp(v, OP_LimitCk, 1, iContinue);
          318  +    }
          319  +    if( p->nLimit>0 ){
          320  +      sqliteVdbeAddOp(v, OP_LimitCk, 0, iBreak);
          321  +    }
          322  +  }
   310    323   
   311    324     /* Pull the requested columns.
   312    325     */
   313    326     if( pEList ){
   314    327       for(i=0; i<pEList->nExpr; i++){
   315    328         sqliteExprCode(pParse, pEList->a[i].pExpr);
   316    329       }
................................................................................
   415    428     if( eDest==SRT_Discard ){
   416    429       sqliteVdbeAddOp(v, OP_Pop, nColumn, 0);
   417    430     }else
   418    431   
   419    432     /* If none of the above, send the data to the callback function.
   420    433     */
   421    434     {
   422         -    sqliteVdbeAddOp(v, OP_Callback, nColumn, iBreak);
          435  +    assert( eDest==SRT_Callback );
          436  +    sqliteVdbeAddOp(v, OP_Callback, nColumn, 0);
   423    437     }
   424    438     return 0;
   425    439   }
   426    440   
   427    441   /*
   428    442   ** If the inner loop was generated using a non-null pOrderBy argument,
   429    443   ** then the results were placed in a sorter.  After the loop is terminated
   430    444   ** we need to run the sorter and output the results.  The following
   431    445   ** routine generates the code needed to do that.
   432    446   */
   433         -static void generateSortTail(Vdbe *v, int nColumn){
          447  +static void generateSortTail(Select *p, Vdbe *v, int nColumn){
   434    448     int end = sqliteVdbeMakeLabel(v);
   435    449     int addr;
   436    450     sqliteVdbeAddOp(v, OP_Sort, 0, 0);
   437    451     addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end);
   438         -  sqliteVdbeAddOp(v, OP_SortCallback, nColumn, end);
          452  +  if( p->nOffset>0 ){
          453  +    sqliteVdbeAddOp(v, OP_LimitCk, 1, addr);
          454  +  }
          455  +  if( p->nLimit>0 ){
          456  +    sqliteVdbeAddOp(v, OP_LimitCk, 0, end);
          457  +  }
          458  +  sqliteVdbeAddOp(v, OP_SortCallback, nColumn, 0);
   439    459     sqliteVdbeAddOp(v, OP_Goto, 0, addr);
   440    460     sqliteVdbeResolveLabel(v, end);
   441    461     sqliteVdbeAddOp(v, OP_SortReset, 0, 0);
   442    462   }
   443    463   
   444    464   /*
   445    465   ** Generate code that will tell the VDBE how many columns there
................................................................................
   971    991           if( eDest==SRT_Callback ){
   972    992             generateColumnNames(pParse, p->base, 0, p->pEList);
   973    993           }
   974    994           iBreak = sqliteVdbeMakeLabel(v);
   975    995           iCont = sqliteVdbeMakeLabel(v);
   976    996           sqliteVdbeAddOp(v, OP_Rewind, unionTab, iBreak);
   977    997           iStart = sqliteVdbeCurrentAddr(v);
   978         -        rc = selectInnerLoop(pParse, 0, unionTab, p->pEList->nExpr,
          998  +        rc = selectInnerLoop(pParse, p, 0, unionTab, p->pEList->nExpr,
   979    999                                p->pOrderBy, -1, eDest, iParm, 
   980   1000                                iCont, iBreak);
   981   1001           if( rc ) return 1;
   982   1002           sqliteVdbeResolveLabel(v, iCont);
   983   1003           sqliteVdbeAddOp(v, OP_Next, unionTab, iStart);
   984   1004           sqliteVdbeResolveLabel(v, iBreak);
   985   1005           sqliteVdbeAddOp(v, OP_Close, unionTab, 0);
   986   1006           if( p->pOrderBy ){
   987         -          generateSortTail(v, p->pEList->nExpr);
         1007  +          generateSortTail(p, v, p->pEList->nExpr);
   988   1008           }
   989   1009         }
   990   1010         break;
   991   1011       }
   992   1012       case TK_INTERSECT: {
   993   1013         int tab1, tab2;
   994   1014         int iCont, iBreak, iStart;
................................................................................
  1027   1047           generateColumnNames(pParse, p->base, 0, p->pEList);
  1028   1048         }
  1029   1049         iBreak = sqliteVdbeMakeLabel(v);
  1030   1050         iCont = sqliteVdbeMakeLabel(v);
  1031   1051         sqliteVdbeAddOp(v, OP_Rewind, tab1, iBreak);
  1032   1052         iStart = sqliteVdbeAddOp(v, OP_FullKey, tab1, 0);
  1033   1053         sqliteVdbeAddOp(v, OP_NotFound, tab2, iCont);
  1034         -      rc = selectInnerLoop(pParse, 0, tab1, p->pEList->nExpr,
         1054  +      rc = selectInnerLoop(pParse, p, 0, tab1, p->pEList->nExpr,
  1035   1055                                p->pOrderBy, -1, eDest, iParm, 
  1036   1056                                iCont, iBreak);
  1037   1057         if( rc ) return 1;
  1038   1058         sqliteVdbeResolveLabel(v, iCont);
  1039   1059         sqliteVdbeAddOp(v, OP_Next, tab1, iStart);
  1040   1060         sqliteVdbeResolveLabel(v, iBreak);
  1041   1061         sqliteVdbeAddOp(v, OP_Close, tab2, 0);
  1042   1062         sqliteVdbeAddOp(v, OP_Close, tab1, 0);
  1043   1063         if( p->pOrderBy ){
  1044         -        generateSortTail(v, p->pEList->nExpr);
         1064  +        generateSortTail(p, v, p->pEList->nExpr);
  1045   1065         }
  1046   1066         break;
  1047   1067       }
  1048   1068     }
  1049   1069     assert( p->pEList && pPrior->pEList );
  1050   1070     if( p->pEList->nExpr!=pPrior->pEList->nExpr ){
  1051   1071       sqliteSetString(&pParse->zErrMsg, "SELECTs to the left and right of ",
................................................................................
  1171   1191   **   (5)  The subquery is not DISTINCT or the outer query does not use
  1172   1192   **        aggregates.
  1173   1193   **
  1174   1194   **   (6)  The subquery does not use aggregates or the outer query is not
  1175   1195   **        DISTINCT.
  1176   1196   **
  1177   1197   **   (7)  The subquery has a FROM clause.
         1198  +**
         1199  +**   (8)  The subquery does not use LIMIT or the outer query is not a join.
         1200  +**
         1201  +**   (9)  The subquery does not use LIMIT or the outer query does not use
         1202  +**        aggregates.
         1203  +**
         1204  +**  (10)  The subquery does not use aggregates or the outer query does not
         1205  +**        use LIMIT.
  1178   1206   **
  1179   1207   ** In this routine, the "p" parameter is a pointer to the outer query.
  1180   1208   ** The subquery is p->pSrc->a[iFrom].  isAgg is true if the outer query
  1181   1209   ** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
  1182   1210   **
  1183   1211   ** If flattening is not attempted, this routine is a no-op and return 0.
  1184   1212   ** If flattening is attempted this routine returns 1.
................................................................................
  1203   1231     pSub = pSrc->a[iFrom].pSelect;
  1204   1232     assert( pSub!=0 );
  1205   1233     if( isAgg && subqueryIsAgg ) return 0;
  1206   1234     if( subqueryIsAgg && pSrc->nSrc>1 ) return 0;
  1207   1235     pSubSrc = pSub->pSrc;
  1208   1236     assert( pSubSrc );
  1209   1237     if( pSubSrc->nSrc!=1 ) return 0;
  1210         -  if( pSub->isDistinct && pSrc->nSrc>1 ) return 0;
  1211         -  if( pSub->isDistinct && isAgg ) return 0;
  1212         -  if( p->isDistinct && subqueryIsAgg ) return 0;
         1238  +  if( (pSub->isDistinct || pSub->nLimit>=0) &&  (pSrc->nSrc>1 || isAgg) ){
         1239  +     return 0;
         1240  +  }
         1241  +  if( (p->isDistinct || p->nLimit) && subqueryIsAgg ) return 0;
  1213   1242   
  1214   1243     /* If we reach this point, it means flattening is permitted for the
  1215   1244     ** i-th entry of the FROM clause in the outer query.
  1216   1245     */
  1217   1246     iParent = p->base + iFrom;
  1218   1247     iSub = pSub->base;
  1219   1248     substExprList(p->pEList, iParent, pSub->pEList, iSub);
................................................................................
  1263   1292     }else{
  1264   1293       substExpr(p->pWhere, iParent, pSub->pEList, iSub);
  1265   1294       if( pWhere ){
  1266   1295         p->pWhere = sqliteExpr(TK_AND, p->pWhere, pWhere, 0);
  1267   1296       }
  1268   1297     }
  1269   1298     p->isDistinct = p->isDistinct || pSub->isDistinct;
         1299  +  if( pSub->nLimit>=0 ){
         1300  +    if( p->nLimit<0 ){
         1301  +      p->nLimit = pSub->nLimit;
         1302  +    }else if( p->nLimit+p->nOffset > pSub->nLimit+pSub->nOffset ){
         1303  +      p->nLimit = pSub->nLimit + pSub->nOffset - p->nOffset;
         1304  +    }
         1305  +  }
         1306  +  p->nOffset += pSub->nOffset;
  1270   1307     if( pSrc->a[iFrom].pTab && pSrc->a[iFrom].pTab->isTransient ){
  1271   1308       sqliteDeleteTable(0, pSrc->a[iFrom].pTab);
  1272   1309     }
  1273   1310     pSrc->a[iFrom].pTab = pSubSrc->a[0].pTab;
  1274   1311     pSubSrc->a[0].pTab = 0;
  1275   1312     pSrc->a[iFrom].pSelect = pSubSrc->a[0].pSelect;
  1276   1313     pSubSrc->a[0].pSelect = 0;
................................................................................
  1382   1419       sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
  1383   1420     }
  1384   1421     eList.nExpr = 1;
  1385   1422     memset(&eListItem, 0, sizeof(eListItem));
  1386   1423     eList.a = &eListItem;
  1387   1424     eList.a[0].pExpr = pExpr;
  1388   1425     cont = sqliteVdbeMakeLabel(v);
  1389         -  selectInnerLoop(pParse, &eList, base, 1, 0, -1, eDest, iParm, cont, cont);
         1426  +  selectInnerLoop(pParse, p, &eList, base, 1, 0, -1, eDest, iParm, cont, cont);
  1390   1427     sqliteVdbeResolveLabel(v, cont);
  1391   1428     sqliteVdbeAddOp(v, OP_Close, base, 0);
  1392   1429     return 1;
  1393   1430   }
  1394   1431   
  1395   1432   /*
  1396   1433   ** Generate code for the given SELECT statement.
................................................................................
  1716   1753     pWInfo = sqliteWhereBegin(pParse, p->base, pTabList, pWhere, 0);
  1717   1754     if( pWInfo==0 ) goto select_end;
  1718   1755   
  1719   1756     /* Use the standard inner loop if we are not dealing with
  1720   1757     ** aggregates
  1721   1758     */
  1722   1759     if( !isAgg ){
  1723         -    if( selectInnerLoop(pParse, pEList, 0, 0, pOrderBy, distinct, eDest, iParm,
  1724         -                    pWInfo->iContinue, pWInfo->iBreak) ){
         1760  +    if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest,
         1761  +                    iParm, pWInfo->iContinue, pWInfo->iBreak) ){
  1725   1762          goto select_end;
  1726   1763       }
  1727   1764     }
  1728   1765   
  1729   1766     /* If we are dealing with aggregates, then to the special aggregate
  1730   1767     ** processing.  
  1731   1768     */
................................................................................
  1775   1812       int endagg = sqliteVdbeMakeLabel(v);
  1776   1813       int startagg;
  1777   1814       startagg = sqliteVdbeAddOp(v, OP_AggNext, 0, endagg);
  1778   1815       pParse->useAgg = 1;
  1779   1816       if( pHaving ){
  1780   1817         sqliteExprIfFalse(pParse, pHaving, startagg, 1);
  1781   1818       }
  1782         -    if( selectInnerLoop(pParse, pEList, 0, 0, pOrderBy, distinct, eDest, iParm,
  1783         -                    startagg, endagg) ){
         1819  +    if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest,
         1820  +                    iParm, startagg, endagg) ){
  1784   1821         goto select_end;
  1785   1822       }
  1786   1823       sqliteVdbeAddOp(v, OP_Goto, 0, startagg);
  1787   1824       sqliteVdbeResolveLabel(v, endagg);
  1788   1825       sqliteVdbeAddOp(v, OP_Noop, 0, 0);
  1789   1826       pParse->useAgg = 0;
  1790   1827     }
  1791   1828   
  1792   1829     /* If there is an ORDER BY clause, then we need to sort the results
  1793   1830     ** and send them to the callback one by one.
  1794   1831     */
  1795   1832     if( pOrderBy ){
  1796         -    generateSortTail(v, pEList->nExpr);
         1833  +    generateSortTail(p, v, pEList->nExpr);
  1797   1834     }
  1798   1835   
  1799   1836   
  1800   1837     /* Issue a null callback if that is what the user wants.
  1801   1838     */
  1802   1839     if( (pParse->db->flags & SQLITE_NullCallback)!=0 && eDest==SRT_Callback ){
  1803   1840       sqliteVdbeAddOp(v, OP_NullCallback, pEList->nExpr, 0);

Changes to src/vdbe.c.

    26     26   ** type to the other occurs as necessary.
    27     27   ** 
    28     28   ** Most of the code in this file is taken up by the sqliteVdbeExec()
    29     29   ** function which does the work of interpreting a VDBE program.
    30     30   ** But other routines are also provided to help in building up
    31     31   ** a program instruction by instruction.
    32     32   **
    33         -** $Id: vdbe.c,v 1.155 2002/06/11 02:25:42 danielk1977 Exp $
           33  +** $Id: vdbe.c,v 1.156 2002/06/14 22:38:43 drh Exp $
    34     34   */
    35     35   #include "sqliteInt.h"
    36     36   #include <ctype.h>
    37     37   
    38     38   /*
    39     39   ** The following global variable is incremented every time a cursor
    40     40   ** moves, either by the OP_MoveTo or the OP_Next opcode.  The test
................................................................................
  1076   1076     "Add",               "AddImm",            "Subtract",          "Multiply",
  1077   1077     "Divide",            "Remainder",         "BitAnd",            "BitOr",
  1078   1078     "BitNot",            "ShiftLeft",         "ShiftRight",        "AbsValue",
  1079   1079     "Eq",                "Ne",                "Lt",                "Le",
  1080   1080     "Gt",                "Ge",                "IsNull",            "NotNull",
  1081   1081     "Negative",          "And",               "Or",                "Not",
  1082   1082     "Concat",            "Noop",              "Function",          "Limit",
         1083  +  "LimitCk",
  1083   1084   };
  1084   1085   
  1085   1086   /*
  1086   1087   ** Given the name of an opcode, return its number.  Return 0 if
  1087   1088   ** there is no match.
  1088   1089   **
  1089   1090   ** This routine is used for testing and debugging.
................................................................................
  1581   1582   */
  1582   1583   case OP_ColumnName: {
  1583   1584     p->azColName[pOp->p1] = pOp->p3 ? pOp->p3 : "";
  1584   1585     p->nCallback = 0;
  1585   1586     break;
  1586   1587   }
  1587   1588   
  1588         -/* Opcode: Callback P1 P2 *
         1589  +/* Opcode: Callback P1 * *
  1589   1590   **
  1590   1591   ** Pop P1 values off the stack and form them into an array.  Then
  1591   1592   ** invoke the callback function using the newly formed array as the
  1592   1593   ** 3rd parameter.
  1593         -**
  1594         -** If the offset counter (set by the OP_Limit opcode) is positive,
  1595         -** then decrement the counter and do not invoke the callback.
  1596         -** 
  1597         -** If the callback is invoked, then after the callback returns
  1598         -** decrement the limit counter.  When the limit counter reaches
  1599         -** zero, jump to address P2.
  1600   1594   */
  1601   1595   case OP_Callback: {
  1602   1596     int i = p->tos - pOp->p1 + 1;
  1603   1597     int j;
  1604   1598     VERIFY( if( i<0 ) goto not_enough_stack; )
  1605   1599     VERIFY( if( NeedStack(p, p->tos+2) ) goto no_mem; )
  1606   1600     for(j=i; j<=p->tos; j++){
................................................................................
  1608   1602         zStack[j] = 0;
  1609   1603       }else{
  1610   1604         if( Stringify(p, j) ) goto no_mem;
  1611   1605       }
  1612   1606     }
  1613   1607     zStack[p->tos+1] = 0;
  1614   1608     if( xCallback!=0 ){
  1615         -    if( p->iOffset>0 ){
  1616         -      p->iOffset--;
  1617         -    }else{
  1618         -      if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; 
  1619         -      if( xCallback(pArg, pOp->p1, &zStack[i], p->azColName)!=0 ){
  1620         -        rc = SQLITE_ABORT;
  1621         -      }
  1622         -      if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
  1623         -      p->nCallback++;
  1624         -      if( p->iLimit>0 ){
  1625         -        p->iLimit--;
  1626         -        if( p->iLimit==0 ){
  1627         -          pc = pOp->p2 - 1;
  1628         -        }
  1629         -      }
         1609  +    if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; 
         1610  +    if( xCallback(pArg, pOp->p1, &zStack[i], p->azColName)!=0 ){
         1611  +      rc = SQLITE_ABORT;
  1630   1612       }
         1613  +    if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
         1614  +    p->nCallback++;
  1631   1615     }
  1632   1616     PopStack(p, pOp->p1);
  1633   1617     if( sqlite_malloc_failed ) goto no_mem;
  1634   1618     break;
  1635   1619   }
  1636   1620   
  1637   1621   /* Opcode: NullCallback P1 * *
................................................................................
  3912   3896   ** of a SELECT statement.
  3913   3897   */
  3914   3898   case OP_Limit: {
  3915   3899     p->iLimit = pOp->p1;
  3916   3900     p->iOffset = pOp->p2;
  3917   3901     break;
  3918   3902   }
         3903  +
         3904  +/* Opcode: LimitCk P1 P2 *
         3905  +**
         3906  +** If P1 is 1, then check to see if the offset counter (set by the
         3907  +** P2 argument of OP_Limit) is positive.  If the offset counter is
         3908  +** positive then decrement the counter and jump immediately to P2.
         3909  +** Otherwise fall straight through.
         3910  +**
         3911  +** If P1 is 0, then check the value of the limit counter (set by the
         3912  +** P1 argument of OP_Limit).  If the limit counter is negative or
         3913  +** zero then jump immedately to P2.  Otherwise decrement the limit
         3914  +** counter and fall through.
         3915  +*/
         3916  +case OP_LimitCk: {
         3917  +  if( pOp->p1 ){
         3918  +    if( p->iOffset ){
         3919  +      p->iOffset--;
         3920  +      pc = pOp->p2 - 1;
         3921  +    }
         3922  +  }else{
         3923  +    if( p->iLimit>0 ){
         3924  +      p->iLimit--;
         3925  +    }else{
         3926  +      pc = pOp->p2 - 1;
         3927  +    }
         3928  +  }
         3929  +  break;
         3930  +}
         3931  +
  3919   3932   
  3920   3933   /* Opcode: ListWrite * * *
  3921   3934   **
  3922   3935   ** Write the integer on the top of the stack
  3923   3936   ** into the temporary storage list.
  3924   3937   */
  3925   3938   case OP_ListWrite: {
................................................................................
  4203   4216       sqliteFree(pSorter);
  4204   4217     }else{
  4205   4218       pc = pOp->p2 - 1;
  4206   4219     }
  4207   4220     break;
  4208   4221   }
  4209   4222   
  4210         -/* Opcode: SortCallback P1 P2 *
         4223  +/* Opcode: SortCallback P1 * *
  4211   4224   **
  4212   4225   ** The top of the stack contains a callback record built using
  4213   4226   ** the SortMakeRec operation with the same P1 value as this
  4214   4227   ** instruction.  Pop this record from the stack and invoke the
  4215   4228   ** callback on it.
  4216         -**
  4217         -** If the offset counter (set by the OP_Limit opcode) is positive,
  4218         -** then decrement the counter and do not invoke the callback.
  4219         -** 
  4220         -** If the callback is invoked, then after the callback returns
  4221         -** decrement the limit counter.  When the limit counter reaches
  4222         -** zero, jump to address P2.
  4223   4229   */
  4224   4230   case OP_SortCallback: {
  4225   4231     int i = p->tos;
  4226   4232     VERIFY( if( i<0 ) goto not_enough_stack; )
  4227   4233     if( xCallback!=0 ){
  4228         -    if( p->iOffset>0 ){
  4229         -      p->iOffset--;
  4230         -    }else{
  4231         -      if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
  4232         -      if( xCallback(pArg, pOp->p1, (char**)zStack[i], p->azColName)!=0 ){
  4233         -        rc = SQLITE_ABORT;
  4234         -      }
  4235         -      if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
  4236         -      p->nCallback++;
  4237         -      if( p->iLimit>0 ){
  4238         -        p->iLimit--;
  4239         -        if( p->iLimit==0 ){
  4240         -          pc = pOp->p2 - 1;
  4241         -        }
  4242         -      }
         4234  +    if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
         4235  +    if( xCallback(pArg, pOp->p1, (char**)zStack[i], p->azColName)!=0 ){
         4236  +      rc = SQLITE_ABORT;
  4243   4237       }
         4238  +    if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
  4244   4239       p->nCallback++;
  4245   4240     }
  4246   4241     POPSTACK;
  4247   4242     if( sqlite_malloc_failed ) goto no_mem;
  4248   4243     break;
  4249   4244   }
  4250   4245   

Changes to src/vdbe.h.

    11     11   *************************************************************************
    12     12   ** Header file for the Virtual DataBase Engine (VDBE)
    13     13   **
    14     14   ** This header defines the interface to the virtual database engine
    15     15   ** or VDBE.  The VDBE implements an abstract machine that runs a
    16     16   ** simple program to access and modify the underlying database.
    17     17   **
    18         -** $Id: vdbe.h,v 1.54 2002/06/08 23:25:09 drh Exp $
           18  +** $Id: vdbe.h,v 1.55 2002/06/14 22:38:43 drh Exp $
    19     19   */
    20     20   #ifndef _SQLITE_VDBE_H_
    21     21   #define _SQLITE_VDBE_H_
    22     22   #include <stdio.h>
    23     23   
    24     24   /*
    25     25   ** A single VDBE is an opaque structure named "Vdbe".  Only routines
................................................................................
   200    200   #define OP_Or                115
   201    201   #define OP_Not               116
   202    202   #define OP_Concat            117
   203    203   #define OP_Noop              118
   204    204   #define OP_Function          119
   205    205   
   206    206   #define OP_Limit             120
          207  +#define OP_LimitCk           121
   207    208   
   208    209   
   209         -#define OP_MAX               120
          210  +#define OP_MAX               121
   210    211   
   211    212   /*
   212    213   ** Prototypes for the VDBE interface.  See comments on the implementation
   213    214   ** for a description of what each of these routines does.
   214    215   */
   215    216   Vdbe *sqliteVdbeCreate(sqlite*);
   216    217   void sqliteVdbeCreateCallback(Vdbe*, int*);

Changes to src/where.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This module contains C code that generates VDBE code used to process
    13     13   ** the WHERE clause of SQL statements.  Also found here are subroutines
    14     14   ** to generate VDBE code to evaluate expressions.
    15     15   **
    16         -** $Id: where.c,v 1.51 2002/06/14 20:58:45 drh Exp $
           16  +** $Id: where.c,v 1.52 2002/06/14 22:38:43 drh Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   
    20     20   /*
    21     21   ** The query generator uses an array of instances of this structure to
    22     22   ** help it analyze the subexpressions of the WHERE clause.  Each WHERE
    23     23   ** clause subexpression is separated from the others by an AND operator.
................................................................................
   254    254     pWInfo->iBreak = sqliteVdbeMakeLabel(v);
   255    255   
   256    256     /* Special case: a WHERE clause that is constant.  Evaluate the
   257    257     ** expression and either jump over all of the code or fall thru.
   258    258     */
   259    259     if( pWhere && sqliteExprIsConstant(pWhere) ){
   260    260       sqliteExprIfFalse(pParse, pWhere, pWInfo->iBreak, 1);
          261  +    pWhere = 0;
   261    262     }
   262    263   
   263    264     /* Split the WHERE clause into as many as 32 separate subexpressions
   264    265     ** where each subexpression is separated by an AND operator.  Any additional
   265    266     ** subexpressions are attached in the aExpr[32] and will not enter
   266    267     ** into the query optimizer computations.  32 is chosen as the cutoff
   267    268     ** since that is the number of bits in an integer that we use for an

Changes to test/limit.test.

     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing the LIMIT ... OFFSET ... clause
    13     13   #  of SELECT statements.
    14     14   #
    15         -# $Id: limit.test,v 1.2 2002/05/24 16:14:16 drh Exp $
           15  +# $Id: limit.test,v 1.3 2002/06/14 22:38:43 drh Exp $
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
    19     19   
    20     20   # Build some test data
    21     21   #
    22     22   set fd [open data1.txt w]
................................................................................
    51     51   } {}
    52     52   do_test limit-1.6 {
    53     53     execsql {SELECT * FROM t1 AS a, t1 AS b ORDER BY a.x, b.x LIMIT 5}
    54     54   } {0 5 0 5 0 5 1 5 0 5 2 5 0 5 3 5 0 5 4 5}
    55     55   do_test limit-1.7 {
    56     56     execsql {SELECT * FROM t1 AS a, t1 AS b ORDER BY a.x, b.x LIMIT 5 OFFSET 32}
    57     57   } {1 5 0 5 1 5 1 5 1 5 2 5 1 5 3 5 1 5 4 5}
           58  +
           59  +do_test limit-2.1 {
           60  +  execsql {
           61  +    CREATE VIEW v1 AS SELECT * FROM t1 LIMIT 2;
           62  +    SELECT count(*) FROM (SELECT * FROM v1);
           63  +  }
           64  +} 2
           65  +do_test limit-2.2 {
           66  +  execsql {
           67  +    CREATE TABLE t2 AS SELECT * FROM t1 LIMIT 2;
           68  +    SELECT count(*) FROM t2;
           69  +  }
           70  +} 2
           71  +do_test limit-2.3 {
           72  +  execsql {
           73  +    SELECT count(*) FROM t1 WHERE rowid IN (SELECT rowid FROM t1 LIMIT 2);
           74  +  }
           75  +} 2
    58     76   
    59     77   
    60     78   finish_test

Changes to test/where.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing the use of indices in WHERE clases.
    13     13   #
    14         -# $Id: where.test,v 1.7 2002/06/09 01:55:20 drh Exp $
           14  +# $Id: where.test,v 1.8 2002/06/14 22:38:43 drh Exp $
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   
    19     19   # Build some test data
    20     20   #
    21     21   do_test where-1.0 {
................................................................................
   245    245       SELECT * FROM t1 WHERE 0
   246    246     }
   247    247   } {0}
   248    248   do_test where-4.2 {
   249    249     count {
   250    250       SELECT * FROM t1 WHERE 1 LIMIT 1
   251    251     }
   252         -} {1 0 4 0}
          252  +} {1 0 4 1}
   253    253   do_test where-4.3 {
   254    254     execsql {
   255    255       SELECT 99 WHERE 0
   256    256     }
   257    257   } {}
   258    258   do_test where-4.4 {
   259    259     execsql {