/ Check-in [723362e7]
Login

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

Overview
Comment:Slightly faster INSERTs from a SELECT by avoiding an intermediate table. But it didn't make nearly as much difference as I had hoped. (CVS 732)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 723362e74f79c784314d042e3a8c8a9bf07cbd5e
User & Date: drh 2002-08-28 03:00:58
Context
2002-08-29
23:59
If the database is locked when sqlite_open() is called, sqlite_exec() should still honor the busy callback and should return an error message together with the SQLITE_BUSY result code. (CVS 733) check-in: 78a0229a user: drh tags: trunk
2002-08-28
03:00
Slightly faster INSERTs from a SELECT by avoiding an intermediate table. But it didn't make nearly as much difference as I had hoped. (CVS 732) check-in: 723362e7 user: drh tags: trunk
2002-08-27
14:28
Change the tokenizer to ignore C-style comments /*...*/ in accordance with SQL99. (CVS 731) check-in: f1534489 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/insert.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 INSERT statements in SQLite.
    14     14   **
    15         -** $Id: insert.c,v 1.65 2002/07/31 00:32:50 drh Exp $
           15  +** $Id: insert.c,v 1.66 2002/08/28 03:00:58 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   /*
    20     20   ** This routine is call to handle SQL of the following forms:
    21     21   **
    22     22   **    insert into TABLE (IDLIST) values(EXPRLIST)
................................................................................
    26     26   ** then a list of all columns for the table is substituted.  The IDLIST
    27     27   ** appears in the pColumn parameter.  pColumn is NULL if IDLIST is omitted.
    28     28   **
    29     29   ** The pList parameter holds EXPRLIST in the first form of the INSERT
    30     30   ** statement above, and pSelect is NULL.  For the second form, pList is
    31     31   ** NULL and pSelect is a pointer to the select statement used to generate
    32     32   ** data for the insert.
           33  +**
           34  +** The code generated follows one of three templates.  For a simple
           35  +** select with data coming from a VALUES clause, the code executes
           36  +** once straight down through.  The template looks like this:
           37  +**
           38  +**         open write cursor to <table> and its indices
           39  +**         puts VALUES clause expressions onto the stack
           40  +**         write the resulting record into <table>
           41  +**         cleanup
           42  +**
           43  +** If the statement is of the form
           44  +**
           45  +**   INSERT INTO <table> SELECT ...
           46  +**
           47  +** And the SELECT clause does not read from <table> at any time, then
           48  +** the generated code follows this template:
           49  +**
           50  +**         goto B
           51  +**      A: setup for the SELECT
           52  +**         loop over the tables in the SELECT
           53  +**           gosub C
           54  +**         end loop
           55  +**         cleanup after the SELECT
           56  +**         goto D
           57  +**      B: open write cursor to <table> and its indices
           58  +**         goto A
           59  +**      C: insert the select result into <table>
           60  +**         return
           61  +**      D: cleanup
           62  +**
           63  +** The third template is used if the insert statement takes its
           64  +** values from a SELECT but the data is being inserted into a table
           65  +** that is also read as part of the SELECT.  In the third form,
           66  +** we have to use a intermediate table to store the results of
           67  +** the select.  The template is like this:
           68  +**
           69  +**         goto B
           70  +**      A: setup for the SELECT
           71  +**         loop over the tables in the SELECT
           72  +**           gosub C
           73  +**         end loop
           74  +**         cleanup after the SELECT
           75  +**         goto D
           76  +**      C: insert the select result into the intermediate table
           77  +**         return
           78  +**      B: open a cursor to an intermediate table
           79  +**         goto A
           80  +**      D: open write cursor to <table> and its indices
           81  +**         loop over the intermediate table
           82  +**           transfer values form intermediate table into <table>
           83  +**         end the loop
           84  +**         cleanup
    33     85   */
    34     86   void sqliteInsert(
    35     87     Parse *pParse,        /* Parser context */
    36     88     Token *pTableName,    /* Name of table into which we are inserting */
    37     89     ExprList *pList,      /* List of values to be inserted */
    38     90     Select *pSelect,      /* A SELECT statement to use as the data source */
    39     91     IdList *pColumn,      /* Column names corresponding to IDLIST. */
................................................................................
    40     92     int onError           /* How to handle constraint errors */
    41     93   ){
    42     94     Table *pTab;          /* The table to insert into */
    43     95     char *zTab = 0;       /* Name of the table into which we are inserting */
    44     96     int i, j, idx;        /* Loop counters */
    45     97     Vdbe *v;              /* Generate code into this virtual machine */
    46     98     Index *pIdx;          /* For looping over indices of the table */
    47         -  int srcTab;           /* Date comes from this temporary cursor if >=0 */
    48     99     int nColumn;          /* Number of columns in the data */
    49    100     int base;             /* First available cursor */
    50    101     int iCont, iBreak;    /* Beginning and end of the loop over srcTab */
    51    102     sqlite *db;           /* The main database structure */
    52    103     int openOp;           /* Opcode used to open cursors */
    53    104     int keyColumn = -1;   /* Column that is the INTEGER PRIMARY KEY */
    54    105     int endOfLoop;        /* Label for the end of the insertion loop */
          106  +  int useTempTable;     /* Store SELECT results in intermediate table */
          107  +  int srcTab;           /* Data comes from this temporary cursor if >=0 */
          108  +  int iSelectLoop;      /* Address of code that implements the SELECT */
          109  +  int iCleanup;         /* Address of the cleanup code */
          110  +  int iInsertBlock;     /* Address of the subroutine used to insert data */
          111  +  int iCntMem;          /* Memory cell used for the row counter */
    55    112   
    56    113     int row_triggers_exist = 0; /* True if there are FOR EACH ROW triggers */
    57    114     int newIdx = -1;
    58    115   
    59    116     if( pParse->nErr || sqlite_malloc_failed ) goto insert_cleanup;
    60    117     db = pParse->db;
    61    118   
................................................................................
   107    164   
   108    165     /* if there are row triggers, allocate a temp table for new.* references. */
   109    166     if( row_triggers_exist ){
   110    167       newIdx = pParse->nTab++;
   111    168     }
   112    169   
   113    170     /* Figure out how many columns of data are supplied.  If the data
   114         -  ** is coming from a SELECT statement, then this step has to generate
   115         -  ** all the code to implement the SELECT statement and leave the data
   116         -  ** in a temporary table.  If data is coming from an expression list,
   117         -  ** then we just have to count the number of expressions.
          171  +  ** is coming from a SELECT statement, then this step also generates
          172  +  ** all the code to implement the SELECT statement and invoke a subroutine
          173  +  ** to process each row of the result. (Template 2.) If the SELECT
          174  +  ** statement uses the the table that is being inserted into, then the
          175  +  ** subroutine is also coded here.  That subroutine stores the SELECT
          176  +  ** results in a temporary table. (Template 3.)
   118    177     */
   119    178     if( pSelect ){
   120         -    int rc;
   121         -    srcTab = pParse->nTab++;
   122         -    sqliteVdbeAddOp(v, OP_OpenTemp, srcTab, 0);
   123         -    rc = sqliteSelect(pParse, pSelect, SRT_Table, srcTab, 0,0,0);
          179  +    /* Data is coming from a SELECT.  Generate code to implement that SELECT
          180  +    */
          181  +    int rc, iInitCode;
          182  +    int opCode;
          183  +    iInitCode = sqliteVdbeAddOp(v, OP_Goto, 0, 0);
          184  +    iSelectLoop = sqliteVdbeCurrentAddr(v);
          185  +    iInsertBlock = sqliteVdbeMakeLabel(v);
          186  +    rc = sqliteSelect(pParse, pSelect, SRT_Subroutine, iInsertBlock, 0,0,0);
   124    187       if( rc || pParse->nErr || sqlite_malloc_failed ) goto insert_cleanup;
          188  +    iCleanup = sqliteVdbeMakeLabel(v);
          189  +    sqliteVdbeAddOp(v, OP_Goto, 0, iCleanup);
   125    190       assert( pSelect->pEList );
   126    191       nColumn = pSelect->pEList->nExpr;
          192  +
          193  +    /* Set useTempTable to TRUE if the result of the SELECT statement
          194  +    ** should be written into a temporary table.  Set to FALSE if each
          195  +    ** row of the SELECT can be written directly into the result table.
          196  +    */
          197  +    opCode = pTab->isTemp ? OP_OpenTemp : OP_Open;
          198  +    useTempTable = row_triggers_exist || sqliteVdbeFindOp(v,opCode,pTab->tnum);
          199  +
          200  +    if( useTempTable ){
          201  +      /* Generate the subroutine that SELECT calls to process each row of
          202  +      ** the result.  Store the result in a temporary table
          203  +      */
          204  +      srcTab = pParse->nTab++;
          205  +      sqliteVdbeResolveLabel(v, iInsertBlock);
          206  +      sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);
          207  +      sqliteVdbeAddOp(v, OP_NewRecno, srcTab, 0);
          208  +      sqliteVdbeAddOp(v, OP_Pull, 1, 0);
          209  +      sqliteVdbeAddOp(v, OP_PutIntKey, srcTab, 0);
          210  +      sqliteVdbeAddOp(v, OP_Return, 0, 0);
          211  +
          212  +      /* The following code runs first because the GOTO at the very top
          213  +      ** of the program jumps to it.  Create the temporary table, then jump
          214  +      ** back up and execute the SELECT code above.
          215  +      */
          216  +      sqliteVdbeChangeP2(v, iInitCode, sqliteVdbeCurrentAddr(v));
          217  +      sqliteVdbeAddOp(v, OP_OpenTemp, srcTab, 0);
          218  +      sqliteVdbeAddOp(v, OP_Goto, 0, iSelectLoop);
          219  +      sqliteVdbeResolveLabel(v, iCleanup);
          220  +    }else{
          221  +      sqliteVdbeChangeP2(v, iInitCode, sqliteVdbeCurrentAddr(v));
          222  +    }
   127    223     }else{
          224  +    /* This is the case if the data for the INSERT is coming from a VALUES
          225  +    ** clause
          226  +    */
   128    227       SrcList dummy;
   129    228       assert( pList!=0 );
   130    229       srcTab = -1;
          230  +    useTempTable = 0;
   131    231       assert( pList );
   132    232       nColumn = pList->nExpr;
   133    233       dummy.nSrc = 0;
   134    234       for(i=0; i<nColumn; i++){
   135    235         if( sqliteExprResolveIds(pParse, 0, &dummy, 0, pList->a[i].pExpr) ){
   136    236           goto insert_cleanup;
   137    237         }
................................................................................
   204    304     ** key, the set the keyColumn variable to the primary key column index
   205    305     ** in the original table definition.
   206    306     */
   207    307     if( pColumn==0 ){
   208    308       keyColumn = pTab->iPKey;
   209    309     }
   210    310   
   211         -  /* Open the temp table for FOR EACH ROW triggers */
          311  +  /* Open the temp table for FOR EACH ROW triggers
          312  +  */
   212    313     if( row_triggers_exist ){
   213    314       sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);
   214    315     }
   215    316       
   216    317     /* Initialize the count of rows to be inserted
   217    318     */
   218         -  if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
   219         -    sqliteVdbeAddOp(v, OP_Integer, 0, 0);  /* Initialize the row count */
          319  +  if( db->flags & SQLITE_CountRows ){
          320  +    iCntMem = pParse->nMem++;
          321  +    sqliteVdbeAddOp(v, OP_Integer, 0, 0);
          322  +    sqliteVdbeAddOp(v, OP_MemStore, iCntMem, 1);
   220    323     }
   221    324   
   222    325     /* Open tables and indices if there are no row triggers */
   223    326     if( !row_triggers_exist ){
   224    327       base = pParse->nTab;
   225    328       openOp = pTab->isTemp ? OP_OpenWrAux : OP_OpenWrite;
   226    329       sqliteVdbeAddOp(v, openOp, base, pTab->tnum);
................................................................................
   228    331       for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
   229    332         sqliteVdbeAddOp(v, openOp, idx+base, pIdx->tnum);
   230    333         sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
   231    334       }
   232    335       pParse->nTab += idx;
   233    336     }
   234    337   
   235         -  /* If the data source is a SELECT statement, then we have to create
          338  +  /* If the data source is a temporary table, then we have to create
   236    339     ** a loop because there might be multiple rows of data.  If the data
   237         -  ** source is an expression list, then exactly one row will be inserted
   238         -  ** and the loop is not used.
          340  +  ** source is a subroutine call from the SELECT statement, then we need
          341  +  ** to launch the SELECT statement processing.
   239    342     */
   240         -  if( srcTab>=0 ){
          343  +  if( useTempTable ){
   241    344       iBreak = sqliteVdbeMakeLabel(v);
   242    345       sqliteVdbeAddOp(v, OP_Rewind, srcTab, iBreak);
   243    346       iCont = sqliteVdbeCurrentAddr(v);
          347  +  }else if( pSelect ){
          348  +    sqliteVdbeAddOp(v, OP_Goto, 0, iSelectLoop);
          349  +    sqliteVdbeResolveLabel(v, iInsertBlock);
   244    350     }
   245    351   
   246    352     endOfLoop = sqliteVdbeMakeLabel(v);
   247    353     if( row_triggers_exist ){
   248    354   
   249    355       /* build the new.* reference row */
   250    356       sqliteVdbeAddOp(v, OP_Integer, 13, 0);
................................................................................
   255    361           for(j=0; j<pColumn->nId; j++){
   256    362             if( pColumn->a[j].idx==i ) break;
   257    363           }
   258    364         }
   259    365         if( pColumn && j>=pColumn->nId ){
   260    366           sqliteVdbeAddOp(v, OP_String, 0, 0);
   261    367           sqliteVdbeChangeP3(v, -1, pTab->aCol[i].zDflt, P3_STATIC);
   262         -      }else if( srcTab>=0 ){
          368  +      }else if( useTempTable ){
   263    369           sqliteVdbeAddOp(v, OP_Column, srcTab, j); 
          370  +      }else if( pSelect ){
          371  +        sqliteVdbeAddOp(v, OP_Dup, nColumn-j-1, 1);
   264    372         }else{
   265    373           sqliteExprCode(pParse, pList->a[j].pExpr);
   266    374         }
   267    375       }
   268    376       sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
   269    377       sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
   270    378       sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);
................................................................................
   292    400     /* Push the record number for the new entry onto the stack.  The
   293    401     ** record number is a randomly generate integer created by NewRecno
   294    402     ** except when the table has an INTEGER PRIMARY KEY column, in which
   295    403     ** case the record number is the same as that column. 
   296    404     */
   297    405     if( !pTab->pSelect ){
   298    406       if( keyColumn>=0 ){
   299         -      if( srcTab>=0 ){
          407  +      if( useTempTable ){
   300    408           sqliteVdbeAddOp(v, OP_Column, srcTab, keyColumn);
          409  +      }else if( pSelect ){
          410  +        sqliteVdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1);
   301    411         }else{
   302    412           sqliteExprCode(pParse, pList->a[keyColumn].pExpr);
   303    413         }
   304    414         /* If the PRIMARY KEY expression is NULL, then use OP_NewRecno
   305    415         ** to generate a unique primary key value.
   306    416         */
   307    417         sqliteVdbeAddOp(v, OP_NotNull, -1, sqliteVdbeCurrentAddr(v)+3);
................................................................................
   330    440           for(j=0; j<pColumn->nId; j++){
   331    441             if( pColumn->a[j].idx==i ) break;
   332    442           }
   333    443         }
   334    444         if( pColumn && j>=pColumn->nId ){
   335    445           sqliteVdbeAddOp(v, OP_String, 0, 0);
   336    446           sqliteVdbeChangeP3(v, -1, pTab->aCol[i].zDflt, P3_STATIC);
   337         -      }else if( srcTab>=0 ){
          447  +      }else if( useTempTable ){
   338    448           sqliteVdbeAddOp(v, OP_Column, srcTab, j); 
          449  +      }else if( pSelect ){
          450  +        sqliteVdbeAddOp(v, OP_Dup, i+nColumn-j, 1);
   339    451         }else{
   340    452           sqliteExprCode(pParse, pList->a[j].pExpr);
   341    453         }
   342    454       }
   343    455   
   344    456       /* Generate code to check constraints and generate index keys and
   345    457       ** do the insertion.
   346    458       */
   347    459       sqliteGenerateConstraintChecks(pParse, pTab, base, 0,0,0,onError,endOfLoop);
   348    460       sqliteCompleteInsertion(pParse, pTab, base, 0,0,0);
   349    461   
   350    462       /* Update the count of rows that are inserted
   351    463       */
   352         -    if( (db->flags & SQLITE_CountRows)!=0 && !pParse->trigStack){
   353         -      sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
          464  +    if( (db->flags & SQLITE_CountRows)!=0 ){
          465  +      sqliteVdbeAddOp(v, OP_MemIncr, iCntMem, 0);
   354    466       }
   355    467     }
   356    468   
   357    469     if( row_triggers_exist ){
   358    470       /* Close all tables opened */
   359    471       if( !pTab->pSelect ){
   360    472         sqliteVdbeAddOp(v, OP_Close, base, 0);
................................................................................
   369    481         goto insert_cleanup;
   370    482       }
   371    483     }
   372    484   
   373    485     /* The bottom of the loop, if the data source is a SELECT statement
   374    486     */
   375    487     sqliteVdbeResolveLabel(v, endOfLoop);
   376         -  if( srcTab>=0 ){
          488  +  if( useTempTable ){
   377    489       sqliteVdbeAddOp(v, OP_Next, srcTab, iCont);
   378    490       sqliteVdbeResolveLabel(v, iBreak);
   379    491       sqliteVdbeAddOp(v, OP_Close, srcTab, 0);
          492  +  }else if( pSelect ){
          493  +    sqliteVdbeAddOp(v, OP_Pop, nColumn, 0);
          494  +    sqliteVdbeAddOp(v, OP_Return, 0, 0);
          495  +    sqliteVdbeResolveLabel(v, iCleanup);
   380    496     }
   381    497   
   382    498     if( !row_triggers_exist ){
   383    499       /* Close all tables opened */
   384    500       sqliteVdbeAddOp(v, OP_Close, base, 0);
   385    501       for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
   386    502         sqliteVdbeAddOp(v, OP_Close, idx+base, 0);
................................................................................
   388    504     }
   389    505   
   390    506     sqliteEndWriteOperation(pParse);
   391    507   
   392    508     /*
   393    509     ** Return the number of rows inserted.
   394    510     */
   395         -  if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
          511  +  if( db->flags & SQLITE_CountRows ){
   396    512       sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
   397    513       sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);
   398    514       sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC);
          515  +    sqliteVdbeAddOp(v, OP_MemLoad, iCntMem, 0);
   399    516       sqliteVdbeAddOp(v, OP_Callback, 1, 0);
   400    517     }
   401    518   
   402    519   insert_cleanup:
   403    520     if( pList ) sqliteExprListDelete(pList);
   404    521     if( pSelect ) sqliteSelectDelete(pSelect);
   405    522     if ( zTab ) sqliteFree(zTab);

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.110 2002/08/25 19:20:40 drh Exp $
           15  +** $Id: select.c,v 1.111 2002/08/28 03:00:59 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   */
................................................................................
   515    515           pushOntoSorter(pParse, v, pOrderBy);
   516    516         }else{
   517    517           assert( eDest==SRT_Callback );
   518    518           sqliteVdbeAddOp(v, OP_Callback, nColumn, 0);
   519    519         }
   520    520         break;
   521    521       }
          522  +
          523  +    /* Invoke a subroutine to handle the results.  The subroutine itself
          524  +    ** is responsible for popping the results off of the stack.
          525  +    */
          526  +    case SRT_Subroutine: {
          527  +      sqliteVdbeAddOp(v, OP_Gosub, 0, iParm);
          528  +      break;
          529  +    }
   522    530   
   523    531       /* Discard the results.  This is used for SELECT statements inside
   524    532       ** the body of a TRIGGER.  The purpose of such selects is to call
   525    533       ** user-defined functions that have side effects.  We do not care
   526    534       ** about the actual results of the select.
   527    535       */
   528    536       default: {
................................................................................
  1071   1079   ** "p" points to the right-most of the two queries.  The results should
  1072   1080   ** be stored in eDest with parameter iParm.
  1073   1081   */
  1074   1082   static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
  1075   1083     int rc;             /* Success code from a subroutine */
  1076   1084     Select *pPrior;     /* Another SELECT immediately to our left */
  1077   1085     Vdbe *v;            /* Generate code to this VDBE */
  1078         -  int base;           /* Baseline value for pParse->nTab */
  1079   1086   
  1080   1087     /* Make sure there is no ORDER BY clause on prior SELECTs.  Only the 
  1081   1088     ** last SELECT in the series may have an ORDER BY.
  1082   1089     */
  1083   1090     if( p==0 || p->pPrior==0 ) return 1;
  1084   1091     pPrior = p->pPrior;
  1085   1092     if( pPrior->pOrderBy ){
................................................................................
  1099   1106     if( eDest==SRT_TempTable ){
  1100   1107       sqliteVdbeAddOp(v, OP_OpenTemp, iParm, 0);
  1101   1108       eDest = SRT_Table;
  1102   1109     }
  1103   1110   
  1104   1111     /* Generate code for the left and right SELECT statements.
  1105   1112     */
  1106         -  base = pParse->nTab;
  1107   1113     switch( p->op ){
  1108   1114       case TK_ALL: {
  1109   1115         if( p->pOrderBy==0 ){
  1110   1116           rc = sqliteSelect(pParse, pPrior, eDest, iParm, 0, 0, 0);
  1111   1117           if( rc ) return rc;
  1112   1118           p->pPrior = 0;
  1113   1119           rc = sqliteSelect(pParse, p, eDest, iParm, 0, 0, 0);
................................................................................
  1254   1260     assert( p->pEList && pPrior->pEList );
  1255   1261     if( p->pEList->nExpr!=pPrior->pEList->nExpr ){
  1256   1262       sqliteSetString(&pParse->zErrMsg, "SELECTs to the left and right of ",
  1257   1263         selectOpName(p->op), " do not have the same number of result columns", 0);
  1258   1264       pParse->nErr++;
  1259   1265       return 1;
  1260   1266     }
  1261         -  pParse->nTab = base;
  1262   1267     return 0;
  1263   1268   }
  1264   1269   
  1265   1270   /*
  1266   1271   ** Recursively scan through an expression tree.  For every reference
  1267   1272   ** to a column in table number iFrom, change that reference to the
  1268   1273   ** same column in table number iTo.
................................................................................
  2076   2081     */
  2077   2082     rc = 0;
  2078   2083   
  2079   2084     /* Control jumps to here if an error is encountered above, or upon
  2080   2085     ** successful coding of the SELECT.
  2081   2086     */
  2082   2087   select_end:
  2083         -  pParse->nTab = base;
         2088  +  /* pParse->nTab = base; */
  2084   2089     sqliteAggregateInfoReset(pParse);
  2085   2090     return rc;
  2086   2091   }

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     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   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.143 2002/08/24 18:24:55 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.144 2002/08/28 03:00:59 drh Exp $
    15     15   */
    16     16   #include "sqlite.h"
    17     17   #include "hash.h"
    18     18   #include "vdbe.h"
    19     19   #include "parse.h"
    20     20   #include "btree.h"
    21     21   #include <stdio.h>
................................................................................
   606    606   #define SRT_Set          3  /* Store result as unique keys in a table */
   607    607   #define SRT_Union        5  /* Store result as keys in a table */
   608    608   #define SRT_Except       6  /* Remove result from a UNION table */
   609    609   #define SRT_Table        7  /* Store result as data with a unique key */
   610    610   #define SRT_TempTable    8  /* Store result in a trasient table */
   611    611   #define SRT_Discard      9  /* Do not save the results anywhere */
   612    612   #define SRT_Sorter      10  /* Store results in the sorter */
          613  +#define SRT_Subroutine  11  /* Call a subroutine to handle results */
   613    614   
   614    615   /*
   615    616   ** When a SELECT uses aggregate functions (like "count(*)" or "avg(f1)")
   616    617   ** we have to do some additional analysis of expressions.  An instance
   617    618   ** of the following structure holds information about a single subexpression
   618    619   ** somewhere in the SELECT statement.  An array of these structures holds
   619    620   ** all the information we need to generate code for aggregate

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.172 2002/08/26 19:55:08 drh Exp $
           33  +** $Id: vdbe.c,v 1.173 2002/08/28 03:01:00 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
................................................................................
   534    534       }else{
   535    535         z[j++] = z[i++];
   536    536       }
   537    537     }
   538    538     while( j>0 && isspace(z[j-1]) ){ j--; }
   539    539     z[j] = 0;
   540    540   }
          541  +
          542  +/*
          543  +** Search for the current program for the given opcode and P2
          544  +** value.  Return 1 if found and 0 if not found.
          545  +*/
          546  +int sqliteVdbeFindOp(Vdbe *p, int op, int p2){
          547  +  int i;
          548  +  for(i=0; i<p->nOp; i++){
          549  +    if( p->aOp[i].opcode==op && p->aOp[i].p2==p2 ) return 1;
          550  +  }
          551  +  return 0;
          552  +}
   541    553   
   542    554   /*
   543    555   ** The following group or routines are employed by installable functions
   544    556   ** to return their results.
   545    557   **
   546    558   ** The sqlite_set_result_string() routine can be used to return a string
   547    559   ** value or to return a NULL.  To return a NULL, pass in NULL for zResult.
................................................................................
  5227   5239           break;
  5228   5240         }
  5229   5241       }
  5230   5242       sqliteRollbackInternalChanges(db);
  5231   5243     }
  5232   5244     sqliteBtreeCommitCkpt(pBt);
  5233   5245     if( db->pBeTemp ) sqliteBtreeCommitCkpt(db->pBeTemp);
  5234         -  assert( p->tos<pc );
         5246  +  assert( p->tos<pc || sqlite_malloc_failed==1 );
  5235   5247     return rc;
  5236   5248   
  5237   5249     /* Jump to here if a malloc() fails.  It's hard to get a malloc()
  5238   5250     ** to fail on a modern VM computer, so this code is untested.
  5239   5251     */
  5240   5252   no_mem:
  5241   5253     sqliteSetString(pzErrMsg, "out of memory", 0);

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.58 2002/08/25 19:20:42 drh Exp $
           18  +** $Id: vdbe.h,v 1.59 2002/08/28 03:01:01 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
................................................................................
   227    227   void sqliteVdbeCreateCallback(Vdbe*, int*);
   228    228   int sqliteVdbeAddOp(Vdbe*,int,int,int);
   229    229   int sqliteVdbeAddOpList(Vdbe*, int nOp, VdbeOp const *aOp);
   230    230   void sqliteVdbeChangeP1(Vdbe*, int addr, int P1);
   231    231   void sqliteVdbeChangeP2(Vdbe*, int addr, int P2);
   232    232   void sqliteVdbeChangeP3(Vdbe*, int addr, const char *zP1, int N);
   233    233   void sqliteVdbeDequoteP3(Vdbe*, int addr);
          234  +int sqliteVdbeFindOp(Vdbe*, int, int);
   234    235   int sqliteVdbeMakeLabel(Vdbe*);
   235    236   void sqliteVdbeDelete(Vdbe*);
   236    237   int sqliteVdbeOpcode(const char *zName);
   237    238   int sqliteVdbeExec(Vdbe*,sqlite_callback,void*,char**,void*,
   238    239                      int(*)(void*,const char*,int));
   239    240   int sqliteVdbeList(Vdbe*,sqlite_callback,void*,char**);
   240    241   void sqliteVdbeResolveLabel(Vdbe*, int);
   241    242   int sqliteVdbeCurrentAddr(Vdbe*);
   242    243   void sqliteVdbeTrace(Vdbe*,FILE*);
   243    244   void sqliteVdbeCompressSpace(Vdbe*,int);
   244    245   
   245    246   #endif

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.63 2002/08/15 13:50:50 drh Exp $
           16  +** $Id: where.c,v 1.64 2002/08/28 03:01:01 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.
................................................................................
  1098   1098       if( pTabList->a[i].pTab->isTransient ) continue;
  1099   1099       pLevel = &pWInfo->a[i];
  1100   1100       sqliteVdbeAddOp(v, OP_Close, base+i, 0);
  1101   1101       if( pLevel->pIdx!=0 ){
  1102   1102         sqliteVdbeAddOp(v, OP_Close, pLevel->iCur, 0);
  1103   1103       }
  1104   1104     }
         1105  +#if 0  /* Never reuse a cursor */
  1105   1106     if( pWInfo->pParse->nTab==pWInfo->peakNTab ){
  1106   1107       pWInfo->pParse->nTab = pWInfo->savedNTab;
  1107   1108     }
         1109  +#endif
  1108   1110     sqliteFree(pWInfo);
  1109   1111     return;
  1110   1112   }