SQLite

Check-in [8a4195c746]
Login

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

Overview
Comment:Style fixes to triggers code in various *.c files (partial fix to ticket #39) (CVS 571)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 8a4195c7466962291a296e8f53034ea8cb25005f
User & Date: danielk1977 2002-05-19 23:43:13.000
Context
2002-05-21
11:38
Additional code cleanup resulting from a review of the new trigger code. (CVS 572) (check-in: 37dbdd551e user: drh tags: trunk)
2002-05-19
23:43
Style fixes to triggers code in various *.c files (partial fix to ticket #39) (CVS 571) (check-in: 8a4195c746 user: danielk1977 tags: trunk)
2002-05-17
00:05
Stylistic changes to src/trigger.c (partial fix to ticket #39). Also more comments. (CVS 570) (check-in: b1d72cb584 user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/build.c.
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.90 2002/05/15 12:45:43 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the VDBE code to implement 







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.91 2002/05/19 23:43:14 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the VDBE code to implement 
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
  for(pElem=sqliteHashFirst(&db->trigHash); pElem; pElem=sqliteHashNext(pElem)){
    Trigger *pTrigger = sqliteHashData(pElem);
    pTrigger->isCommit = 1;
  }

  /* Delete the structures for triggers removed this transaction */
  pElem = sqliteHashFirst(&db->trigDrop);
  while (pElem) {
    Trigger *pTrigger = sqliteHashData(pElem);
    sqliteDeleteTrigger(pTrigger);
    pElem = sqliteHashNext(pElem);
  }
  sqliteHashClear(&db->trigDrop);

  db->flags &= ~SQLITE_InternChanges;







|







255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
  for(pElem=sqliteHashFirst(&db->trigHash); pElem; pElem=sqliteHashNext(pElem)){
    Trigger *pTrigger = sqliteHashData(pElem);
    pTrigger->isCommit = 1;
  }

  /* Delete the structures for triggers removed this transaction */
  pElem = sqliteHashFirst(&db->trigDrop);
  while( pElem ){
    Trigger *pTrigger = sqliteHashData(pElem);
    sqliteDeleteTrigger(pTrigger);
    pElem = sqliteHashNext(pElem);
  }
  sqliteHashClear(&db->trigDrop);

  db->flags &= ~SQLITE_InternChanges;
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
    pOld = sqliteHashInsert(&db->idxHash, p->zName, strlen(p->zName)+1, p);
    assert( pOld==0 || pOld==p );
  }
  sqliteHashClear(&db->idxDrop);

  /* Remove any triggers that haven't been commited yet */
  for(pElem = sqliteHashFirst(&db->trigHash); pElem; 
      pElem = (pElem?sqliteHashNext(pElem):0)) {
    Trigger *pTrigger = sqliteHashData(pElem);
    if( !pTrigger->isCommit ){
      Table *pTbl = sqliteFindTable(db, pTrigger->table);
      if( pTbl ){
        if( pTbl->pTrigger == pTrigger ){
          pTbl->pTrigger = pTrigger->pNext;
        }else{
          Trigger *cc = pTbl->pTrigger;
          while( cc ){
            if (cc->pNext == pTrigger) {
              cc->pNext = cc->pNext->pNext;
              break;
            }
            cc = cc->pNext;
          }
          assert(cc);
        }
      }
      sqliteHashInsert(&db->trigHash, pTrigger->name,
              1 + strlen(pTrigger->name), 0);
      sqliteDeleteTrigger(pTrigger);
      pElem = sqliteHashFirst(&db->trigHash);
    }
  }

  /* Any triggers that were dropped - put 'em back in place */
  for(pElem = sqliteHashFirst(&db->trigDrop); pElem; 
      pElem = sqliteHashNext(pElem)) {
    Trigger * pTrigger = sqliteHashData(pElem);
    Table * tab = sqliteFindTable(db, pTrigger->table);
    sqliteHashInsert(&db->trigHash, pTrigger->name, 
        strlen(pTrigger->name) + 1, pTrigger);
    pTrigger->pNext = tab->pTrigger;
    tab->pTrigger = pTrigger;
  }

  sqliteHashClear(&db->trigDrop);
  db->flags &= ~SQLITE_InternChanges;
}

/*







|









|

















|
|
|


|
|







319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
    pOld = sqliteHashInsert(&db->idxHash, p->zName, strlen(p->zName)+1, p);
    assert( pOld==0 || pOld==p );
  }
  sqliteHashClear(&db->idxDrop);

  /* Remove any triggers that haven't been commited yet */
  for(pElem = sqliteHashFirst(&db->trigHash); pElem; 
      pElem = (pElem?sqliteHashNext(pElem):0)){
    Trigger *pTrigger = sqliteHashData(pElem);
    if( !pTrigger->isCommit ){
      Table *pTbl = sqliteFindTable(db, pTrigger->table);
      if( pTbl ){
        if( pTbl->pTrigger == pTrigger ){
          pTbl->pTrigger = pTrigger->pNext;
        }else{
          Trigger *cc = pTbl->pTrigger;
          while( cc ){
            if( cc->pNext == pTrigger ){
              cc->pNext = cc->pNext->pNext;
              break;
            }
            cc = cc->pNext;
          }
          assert(cc);
        }
      }
      sqliteHashInsert(&db->trigHash, pTrigger->name,
              1 + strlen(pTrigger->name), 0);
      sqliteDeleteTrigger(pTrigger);
      pElem = sqliteHashFirst(&db->trigHash);
    }
  }

  /* Any triggers that were dropped - put 'em back in place */
  for(pElem = sqliteHashFirst(&db->trigDrop); pElem; 
      pElem = sqliteHashNext(pElem)){
    Trigger *pTrigger = sqliteHashData(pElem);
    Table *pTbl = sqliteFindTable(db, pTrigger->table);
    sqliteHashInsert(&db->trigHash, pTrigger->name, 
        strlen(pTrigger->name) + 1, pTrigger);
    pTrigger->pNext = pTbl->pTrigger;
    pTbl->pTrigger = pTrigger;
  }

  sqliteHashClear(&db->trigDrop);
  db->flags &= ~SQLITE_InternChanges;
}

/*
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
** Generate code that concludes an operation that may have changed
** the database.  This is a companion function to BeginWriteOperation().
** If a transaction was started, then commit it.  If a checkpoint was
** started then commit that.
*/
void sqliteEndWriteOperation(Parse *pParse){
  Vdbe *v;
  if (pParse->trigStack) return; /* if this is in a trigger */
  v = sqliteGetVdbe(pParse);
  if( v==0 ) return;
  if( pParse->db->flags & SQLITE_InTrans ){
    /* Do Nothing */
  }else{
    sqliteVdbeAddOp(v, OP_Commit, 0, 0);
  }







|







1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
** Generate code that concludes an operation that may have changed
** the database.  This is a companion function to BeginWriteOperation().
** If a transaction was started, then commit it.  If a checkpoint was
** started then commit that.
*/
void sqliteEndWriteOperation(Parse *pParse){
  Vdbe *v;
  if( pParse->trigStack ) return; /* if this is in a trigger */
  v = sqliteGetVdbe(pParse);
  if( v==0 ) return;
  if( pParse->db->flags & SQLITE_InTrans ){
    /* Do Nothing */
  }else{
    sqliteVdbeAddOp(v, OP_Commit, 0, 0);
  }
Changes to src/delete.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.32 2002/05/15 11:44:14 drh Exp $
*/
#include "sqliteInt.h"


/*
** Given a table name, find the corresponding table and make sure the
** table is writeable.  Generate an error and return NULL if not.  If







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.33 2002/05/19 23:43:14 danielk1977 Exp $
*/
#include "sqliteInt.h"


/*
** Given a table name, find the corresponding table and make sure the
** table is writeable.  Generate an error and return NULL if not.  If
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149

150

151
152
153
154

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
  if( pParse->nErr || sqlite_malloc_failed ){
    pTabList = 0;
    goto delete_from_cleanup;
  }
  db = pParse->db;

  /* Check for the special case of a VIEW with one or more ON DELETE triggers 
   * defined 
   */
  {
    Table * pTab;
    char * zTab = sqliteTableNameFromToken(pTableName);

    if(zTab != 0) {
      pTab = sqliteFindTable(pParse->db, zTab);
      if (pTab) {
        row_triggers_exist = 
          sqliteTriggersExist(pParse, pTab->pTrigger, 
              TK_DELETE, TK_BEFORE, TK_ROW, 0) ||
          sqliteTriggersExist(pParse, pTab->pTrigger, 
              TK_DELETE, TK_AFTER, TK_ROW, 0);
      }
      sqliteFree(zTab);
      if (row_triggers_exist &&  pTab->pSelect ) {
        /* Just fire VIEW triggers */
        sqliteViewTriggers(pParse, pTab, pWhere, OE_Replace, 0);
        return;
      }
    }
  }

  /* Locate the table which we want to delete.  This table has to be
  ** put in an IdList structure because some of the subroutines we
  ** will be calling are designed to work with multiple tables and expect
  ** an IdList* parameter instead of just a Table* parameger.
  */
  pTabList = sqliteTableTokenToIdList(pParse, pTableName);
  if( pTabList==0 ) goto delete_from_cleanup;
  assert( pTabList->nId==1 );
  pTab = pTabList->a[0].pTab;
  assert( pTab->pSelect==0 );  /* This table is not a view */

  if (row_triggers_exist) 
    oldIdx = pParse->nTab++;


  /* Resolve the column names in all the expressions.
  */
  base = pParse->nTab++;
  if( pWhere ){
    if( sqliteExprResolveIds(pParse, base, pTabList, 0, pWhere) ){
      goto delete_from_cleanup;
    }
    if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
      goto delete_from_cleanup;
    }
  }

  /* Begin generating code.
  */
  v = sqliteGetVdbe(pParse);

  if( v==0 ) goto delete_from_cleanup;

  if (row_triggers_exist) 
    sqliteBeginMultiWriteOperation(pParse);
  else 
    sqliteBeginWriteOperation(pParse);


  /* Initialize the counter of the number of rows deleted, if
  ** we are counting rows.
  */
  if( db->flags & SQLITE_CountRows ){
    sqliteVdbeAddOp(v, OP_Integer, 0, 0);
  }

  /* Special case: A DELETE without a WHERE clause deletes everything.
  ** It is easier just to erase the whole table.
  */
  if( pWhere==0 && !row_triggers_exist){
    if( db->flags & SQLITE_CountRows ){
      /* If counting rows deleted, just count the total number of
      ** entries in the table. */
      int endOfLoop = sqliteVdbeMakeLabel(v);
      int addr;
      openOp = pTab->isTemp ? OP_OpenAux : OP_Open;
      assert( base==0 );







|
|

|
|

|

|







|


















|

>
















>
|
>
|

|

>











|







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
  if( pParse->nErr || sqlite_malloc_failed ){
    pTabList = 0;
    goto delete_from_cleanup;
  }
  db = pParse->db;

  /* Check for the special case of a VIEW with one or more ON DELETE triggers 
  ** defined 
  */
  {
    Table *pTab;
    char *zTab = sqliteTableNameFromToken(pTableName);

    if( zTab != 0 ){
      pTab = sqliteFindTable(pParse->db, zTab);
      if( pTab ){
        row_triggers_exist = 
          sqliteTriggersExist(pParse, pTab->pTrigger, 
              TK_DELETE, TK_BEFORE, TK_ROW, 0) ||
          sqliteTriggersExist(pParse, pTab->pTrigger, 
              TK_DELETE, TK_AFTER, TK_ROW, 0);
      }
      sqliteFree(zTab);
      if( row_triggers_exist &&  pTab->pSelect ){
        /* Just fire VIEW triggers */
        sqliteViewTriggers(pParse, pTab, pWhere, OE_Replace, 0);
        return;
      }
    }
  }

  /* Locate the table which we want to delete.  This table has to be
  ** put in an IdList structure because some of the subroutines we
  ** will be calling are designed to work with multiple tables and expect
  ** an IdList* parameter instead of just a Table* parameger.
  */
  pTabList = sqliteTableTokenToIdList(pParse, pTableName);
  if( pTabList==0 ) goto delete_from_cleanup;
  assert( pTabList->nId==1 );
  pTab = pTabList->a[0].pTab;
  assert( pTab->pSelect==0 );  /* This table is not a view */

  if( row_triggers_exist ){ 
    oldIdx = pParse->nTab++;
  }

  /* Resolve the column names in all the expressions.
  */
  base = pParse->nTab++;
  if( pWhere ){
    if( sqliteExprResolveIds(pParse, base, pTabList, 0, pWhere) ){
      goto delete_from_cleanup;
    }
    if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
      goto delete_from_cleanup;
    }
  }

  /* Begin generating code.
  */
  v = sqliteGetVdbe(pParse);
  if( v==0 ){
    goto delete_from_cleanup;
  }
  if( row_triggers_exist ){ 
    sqliteBeginMultiWriteOperation(pParse);
  } else {
    sqliteBeginWriteOperation(pParse);
  }

  /* Initialize the counter of the number of rows deleted, if
  ** we are counting rows.
  */
  if( db->flags & SQLITE_CountRows ){
    sqliteVdbeAddOp(v, OP_Integer, 0, 0);
  }

  /* Special case: A DELETE without a WHERE clause deletes everything.
  ** It is easier just to erase the whole table.
  */
  if( pWhere==0 && !row_triggers_exist ){
    if( db->flags & SQLITE_CountRows ){
      /* If counting rows deleted, just count the total number of
      ** entries in the table. */
      int endOfLoop = sqliteVdbeMakeLabel(v);
      int addr;
      openOp = pTab->isTemp ? OP_OpenAux : OP_Open;
      assert( base==0 );
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229

230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
    /* Delete every item whose key was written to the list during the
    ** database scan.  We have to delete items after the scan is complete
    ** because deleting an item can change the scan order.
    */
    sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
    end = sqliteVdbeMakeLabel(v);

    if (row_triggers_exist) {
      int ii;
      addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
      sqliteVdbeAddOp(v, OP_Dup, 0, 0);

      openOp = pTab->isTemp ? OP_OpenAux : OP_Open;
      sqliteVdbeAddOp(v, openOp, base, pTab->tnum);
      sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
      sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0);

      sqliteVdbeAddOp(v, OP_Integer, 13, 0);
      for (ii = 0; ii < pTab->nCol; ii++) {
        if (ii == pTab->iPKey) 
          sqliteVdbeAddOp(v, OP_Recno, base, 0);
        else
          sqliteVdbeAddOp(v, OP_Column, base, ii);

      }
      sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
      sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
      sqliteVdbeAddOp(v, OP_Close, base, 0);
      sqliteVdbeAddOp(v, OP_Rewind, oldIdx, 0);

      sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, 
          oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default);
    }

    pParse->nTab = base + 1;
    openOp = pTab->isTemp ? OP_OpenWrAux : OP_OpenWrite;
    sqliteVdbeAddOp(v, openOp, base, pTab->tnum);
    for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
      sqliteVdbeAddOp(v, openOp, pParse->nTab++, pIdx->tnum);
    }

    if (!row_triggers_exist) 
      addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);


    sqliteGenerateRowDelete(v, pTab, base, pParse->trigStack?0:1);

    if (row_triggers_exist) {
      for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
        sqliteVdbeAddOp(v, OP_Close, base + i, pIdx->tnum);
      }
      sqliteVdbeAddOp(v, OP_Close, base, 0);
      sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, 
          oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default);
    }

    sqliteVdbeAddOp(v, OP_Goto, 0, addr);
    sqliteVdbeResolveLabel(v, end);
    sqliteVdbeAddOp(v, OP_ListReset, 0, 0);

    if (!row_triggers_exist) {
      for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
        sqliteVdbeAddOp(v, OP_Close, base + i, pIdx->tnum);
      }
      sqliteVdbeAddOp(v, OP_Close, base, 0);
      pParse->nTab = base;
    }
  }







|










|
|

|

>

















|

>



|












|







211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
    /* Delete every item whose key was written to the list during the
    ** database scan.  We have to delete items after the scan is complete
    ** because deleting an item can change the scan order.
    */
    sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
    end = sqliteVdbeMakeLabel(v);

    if( row_triggers_exist ){
      int ii;
      addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
      sqliteVdbeAddOp(v, OP_Dup, 0, 0);

      openOp = pTab->isTemp ? OP_OpenAux : OP_Open;
      sqliteVdbeAddOp(v, openOp, base, pTab->tnum);
      sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
      sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0);

      sqliteVdbeAddOp(v, OP_Integer, 13, 0);
      for(ii = 0; ii<pTab->nCol; ii++){
        if( ii==pTab->iPKey ){ 
          sqliteVdbeAddOp(v, OP_Recno, base, 0);
	} else {
          sqliteVdbeAddOp(v, OP_Column, base, ii);
	}
      }
      sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
      sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
      sqliteVdbeAddOp(v, OP_Close, base, 0);
      sqliteVdbeAddOp(v, OP_Rewind, oldIdx, 0);

      sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, 
          oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default);
    }

    pParse->nTab = base + 1;
    openOp = pTab->isTemp ? OP_OpenWrAux : OP_OpenWrite;
    sqliteVdbeAddOp(v, openOp, base, pTab->tnum);
    for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
      sqliteVdbeAddOp(v, openOp, pParse->nTab++, pIdx->tnum);
    }

    if( !row_triggers_exist ){ 
      addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
    }

    sqliteGenerateRowDelete(v, pTab, base, pParse->trigStack?0:1);

    if( row_triggers_exist ){
      for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
        sqliteVdbeAddOp(v, OP_Close, base + i, pIdx->tnum);
      }
      sqliteVdbeAddOp(v, OP_Close, base, 0);
      sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, 
          oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default);
    }

    sqliteVdbeAddOp(v, OP_Goto, 0, addr);
    sqliteVdbeResolveLabel(v, end);
    sqliteVdbeAddOp(v, OP_ListReset, 0, 0);

    if( !row_triggers_exist ){
      for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
        sqliteVdbeAddOp(v, OP_Close, base + i, pIdx->tnum);
      }
      sqliteVdbeAddOp(v, OP_Close, base, 0);
      pParse->nTab = base;
    }
  }
Changes to src/expr.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.59 2002/05/15 08:30:13 danielk1977 Exp $
*/
#include "sqliteInt.h"


/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqliteMalloc().  The calling function







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.60 2002/05/19 23:43:14 danielk1977 Exp $
*/
#include "sqliteInt.h"


/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqliteMalloc().  The calling function
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502

503
504
505
506
507
508

509
510
511
512
513
514
515
            }
          }
        }
      }

      /* If we have not already resolved this *.* expression, then maybe 
       * it is a new.* or old.* trigger argument reference */
      if (cnt == 0 && pParse->trigStack != 0) {
        TriggerStack * tt = pParse->trigStack;
        int j;
        int t = 0;
        if (tt->newIdx != -1 && sqliteStrICmp("new", zLeft) == 0) {
          pExpr->iTable = tt->newIdx;
          cntTab++;
          t = 1;
        }
        if (tt->oldIdx != -1 && sqliteStrICmp("old", zLeft) == 0) {
          pExpr->iTable = tt->oldIdx;
          cntTab++;
          t = 1;
        }

        if (t) 

          for(j=0; j<tt->pTab->nCol; j++) {
            if( sqliteStrICmp(tt->pTab->aCol[j].zName, zRight)==0 ){
              cnt++;
              pExpr->iColumn = j;
            }
          }

      }

      if( cnt==0 && cntTab==1 && sqliteIsRowid(zRight) ){
        cnt = 1;
        pExpr->iColumn = -1;
      }
      sqliteFree(zLeft);







|
|
<

|
|



|
|




|
>
|
|




>







480
481
482
483
484
485
486
487
488

489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
            }
          }
        }
      }

      /* If we have not already resolved this *.* expression, then maybe 
       * it is a new.* or old.* trigger argument reference */
      if( cnt == 0 && pParse->trigStack != 0 ){
        TriggerStack *pTriggerStack = pParse->trigStack;

        int t = 0;
        if( pTriggerStack->newIdx != -1 && sqliteStrICmp("new", zLeft) == 0 ){
          pExpr->iTable = pTriggerStack->newIdx;
          cntTab++;
          t = 1;
        }
        if( pTriggerStack->oldIdx != -1 && sqliteStrICmp("old", zLeft) == 0 ){
          pExpr->iTable = pTriggerStack->oldIdx;
          cntTab++;
          t = 1;
        }

        if( t ){ 
	  int j;
          for(j=0; j < pTriggerStack->pTab->nCol; j++) {
            if( sqliteStrICmp(pTriggerStack->pTab->aCol[j].zName, zRight)==0 ){
              cnt++;
              pExpr->iColumn = j;
            }
          }
	}
      }

      if( cnt==0 && cntTab==1 && sqliteIsRowid(zRight) ){
        cnt = 1;
        pExpr->iColumn = -1;
      }
      sqliteFree(zLeft);
Changes to src/insert.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.54 2002/05/15 11:44:14 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is call to handle SQL of the following forms:
**
**    insert into TABLE (IDLIST) values(EXPRLIST)







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.55 2002/05/19 23:43:14 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** This routine is call to handle SQL of the following forms:
**
**    insert into TABLE (IDLIST) values(EXPRLIST)
98
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
  if( pSelect || row_triggers_exist ){
    sqliteBeginMultiWriteOperation(pParse);
  }else{
    sqliteBeginWriteOperation(pParse);
  }

  /* if there are row triggers, allocate a temp table for new.* references. */
  if (row_triggers_exist)
    newIdx = pParse->nTab++;


  /* Figure out how many columns of data are supplied.  If the data
  ** is coming from a SELECT statement, then this step has to generate
  ** all the code to implement the SELECT statement and leave the data
  ** in a temporary table.  If data is coming from an expression list,
  ** then we just have to count the number of expressions.
  */







|

>







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
  if( pSelect || row_triggers_exist ){
    sqliteBeginMultiWriteOperation(pParse);
  }else{
    sqliteBeginWriteOperation(pParse);
  }

  /* if there are row triggers, allocate a temp table for new.* references. */
  if( row_triggers_exist ){
    newIdx = pParse->nTab++;
  }

  /* Figure out how many columns of data are supplied.  If the data
  ** is coming from a SELECT statement, then this step has to generate
  ** all the code to implement the SELECT statement and leave the data
  ** in a temporary table.  If data is coming from an expression list,
  ** then we just have to count the number of expressions.
  */
200
201
202
203
204
205
206
207
208

209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  ** in the original table definition.
  */
  if( pColumn==0 ){
    keyColumn = pTab->iPKey;
  }

  /* Open the temp table for FOR EACH ROW triggers */
  if (row_triggers_exist)
    sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);

    
  /* Initialize the count of rows to be inserted
  */
  if( db->flags & SQLITE_CountRows && !pParse->trigStack){
    sqliteVdbeAddOp(v, OP_Integer, 0, 0);  /* Initialize the row count */
  }

  /* Open tables and indices if there are no row triggers */
  if (!row_triggers_exist) {
    base = pParse->nTab;
    openOp = pTab->isTemp ? OP_OpenWrAux : OP_OpenWrite;
    sqliteVdbeAddOp(v, openOp, base, pTab->tnum);
    sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
    for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
      sqliteVdbeAddOp(v, openOp, idx+base, pIdx->tnum);
      sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);







|

>



|




|







201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
  ** in the original table definition.
  */
  if( pColumn==0 ){
    keyColumn = pTab->iPKey;
  }

  /* Open the temp table for FOR EACH ROW triggers */
  if( row_triggers_exist ){
    sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);
  }
    
  /* Initialize the count of rows to be inserted
  */
  if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
    sqliteVdbeAddOp(v, OP_Integer, 0, 0);  /* Initialize the row count */
  }

  /* Open tables and indices if there are no row triggers */
  if( !row_triggers_exist ){
    base = pParse->nTab;
    openOp = pTab->isTemp ? OP_OpenWrAux : OP_OpenWrite;
    sqliteVdbeAddOp(v, openOp, base, pTab->tnum);
    sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
    for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
      sqliteVdbeAddOp(v, openOp, idx+base, pIdx->tnum);
      sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
  */
  if( srcTab>=0 ){
    iBreak = sqliteVdbeMakeLabel(v);
    sqliteVdbeAddOp(v, OP_Rewind, srcTab, iBreak);
    iCont = sqliteVdbeCurrentAddr(v);
  }

  if (row_triggers_exist) {

    /* build the new.* reference row */
    sqliteVdbeAddOp(v, OP_Integer, 13, 0);
    for(i=0; i<pTab->nCol; i++){
      if( pColumn==0 ){
        j = i;
      }else{







|







235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
  */
  if( srcTab>=0 ){
    iBreak = sqliteVdbeMakeLabel(v);
    sqliteVdbeAddOp(v, OP_Rewind, srcTab, iBreak);
    iCont = sqliteVdbeCurrentAddr(v);
  }

  if( row_triggers_exist ){

    /* build the new.* reference row */
    sqliteVdbeAddOp(v, OP_Integer, 13, 0);
    for(i=0; i<pTab->nCol; i++){
      if( pColumn==0 ){
        j = i;
      }else{
259
260
261
262
263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
      }
    }
    sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
    sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
    sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);

    /* Fire BEFORE triggers */
    if (
    sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_BEFORE, pTab, newIdx, -1, 
        onError)
       ) goto insert_cleanup;


    /* Open the tables and indices for the INSERT */
    if (!pTab->pSelect) {
      base = pParse->nTab;
      openOp = pTab->isTemp ? OP_OpenWrAux : OP_OpenWrite;
      sqliteVdbeAddOp(v, openOp, base, pTab->tnum);
      sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
      for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
        sqliteVdbeAddOp(v, openOp, idx+base, pIdx->tnum);
        sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
      }
      pParse->nTab += idx;
    }
  }

  /* Push the record number for the new entry onto the stack.  The
  ** record number is a randomly generate integer created by NewRecno
  ** except when the table has an INTEGER PRIMARY KEY column, in which
  ** case the record number is the same as that column. 
  */
  if (!pTab->pSelect) {
    if( keyColumn>=0 ){
      if( srcTab>=0 ){
        sqliteVdbeAddOp(v, OP_Column, srcTab, keyColumn);
      }else{
        int addr;
        sqliteExprCode(pParse, pList->a[keyColumn].pExpr);

        /* If the PRIMARY KEY expression is NULL, then use OP_NewRecno
         ** to generate a unique primary key value.
         */
        addr = sqliteVdbeAddOp(v, OP_Dup, 0, 1);
        sqliteVdbeAddOp(v, OP_NotNull, 0, addr+4);
        sqliteVdbeAddOp(v, OP_Pop, 1, 0);
        sqliteVdbeAddOp(v, OP_NewRecno, base, 0);
      }
      sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
    }else{
      sqliteVdbeAddOp(v, OP_NewRecno, base, 0);
    }

    /* Push onto the stack, data for all columns of the new entry, beginning
     ** with the first column.
     */
    for(i=0; i<pTab->nCol; i++){
      if( i==pTab->iPKey ){
        /* The value of the INTEGER PRIMARY KEY column is always a NULL.
         ** Whenever this column is read, the record number will be substituted
         ** in its place.  So will fill this column with a NULL to avoid
         ** taking up data space with information that will never be used. */
        sqliteVdbeAddOp(v, OP_String, 0, 0);
        continue;
      }
      if( pColumn==0 ){
        j = i;
      }else{
        for(j=0; j<pColumn->nId; j++){







<
|
|
|
|
>

|

















|








|
|











|
|



|
|
|







261
262
263
264
265
266
267

268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
      }
    }
    sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
    sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
    sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);

    /* Fire BEFORE triggers */

    if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_BEFORE, pTab, newIdx, -1, 
        onError) ){
      goto insert_cleanup;
    }

    /* Open the tables and indices for the INSERT */
    if( !pTab->pSelect ){
      base = pParse->nTab;
      openOp = pTab->isTemp ? OP_OpenWrAux : OP_OpenWrite;
      sqliteVdbeAddOp(v, openOp, base, pTab->tnum);
      sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
      for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
        sqliteVdbeAddOp(v, openOp, idx+base, pIdx->tnum);
        sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
      }
      pParse->nTab += idx;
    }
  }

  /* Push the record number for the new entry onto the stack.  The
  ** record number is a randomly generate integer created by NewRecno
  ** except when the table has an INTEGER PRIMARY KEY column, in which
  ** case the record number is the same as that column. 
  */
  if( !pTab->pSelect ){
    if( keyColumn>=0 ){
      if( srcTab>=0 ){
        sqliteVdbeAddOp(v, OP_Column, srcTab, keyColumn);
      }else{
        int addr;
        sqliteExprCode(pParse, pList->a[keyColumn].pExpr);

        /* If the PRIMARY KEY expression is NULL, then use OP_NewRecno
        ** to generate a unique primary key value.
        */
        addr = sqliteVdbeAddOp(v, OP_Dup, 0, 1);
        sqliteVdbeAddOp(v, OP_NotNull, 0, addr+4);
        sqliteVdbeAddOp(v, OP_Pop, 1, 0);
        sqliteVdbeAddOp(v, OP_NewRecno, base, 0);
      }
      sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
    }else{
      sqliteVdbeAddOp(v, OP_NewRecno, base, 0);
    }

    /* Push onto the stack, data for all columns of the new entry, beginning
    ** with the first column.
    */
    for(i=0; i<pTab->nCol; i++){
      if( i==pTab->iPKey ){
        /* The value of the INTEGER PRIMARY KEY column is always a NULL.
        ** Whenever this column is read, the record number will be substituted
        ** in its place.  So will fill this column with a NULL to avoid
        ** taking up data space with information that will never be used. */
        sqliteVdbeAddOp(v, OP_String, 0, 0);
        continue;
      }
      if( pColumn==0 ){
        j = i;
      }else{
        for(j=0; j<pColumn->nId; j++){
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367

368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
        sqliteVdbeAddOp(v, OP_Column, srcTab, j); 
      }else{
        sqliteExprCode(pParse, pList->a[j].pExpr);
      }
    }

    /* Generate code to check constraints and generate index keys and
     ** do the insertion.
     */
    endOfLoop = sqliteVdbeMakeLabel(v);
    sqliteGenerateConstraintChecks(pParse, pTab, base, 0,0,0,onError,endOfLoop);
    sqliteCompleteInsertion(pParse, pTab, base, 0,0,0);

    /* Update the count of rows that are inserted
     */
    if( (db->flags & SQLITE_CountRows)!=0 && !pParse->trigStack){
      sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
    }
  }

  if (row_triggers_exist) {
    /* Close all tables opened */
    if (!pTab->pSelect) {
      sqliteVdbeAddOp(v, OP_Close, base, 0);
      for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
        sqliteVdbeAddOp(v, OP_Close, idx+base, 0);
      }
    }

    /* Code AFTER triggers */
    if (
        sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_AFTER, pTab, newIdx, -1, 
          onError)
       ) goto insert_cleanup;

  }

  /* The bottom of the loop, if the data source is a SELECT statement
   */
  sqliteVdbeResolveLabel(v, endOfLoop);
  if( srcTab>=0 ){
    sqliteVdbeAddOp(v, OP_Next, srcTab, iCont);
    sqliteVdbeResolveLabel(v, iBreak);
    sqliteVdbeAddOp(v, OP_Close, srcTab, 0);
  }

  if (!row_triggers_exist) {
    /* Close all tables opened */
    sqliteVdbeAddOp(v, OP_Close, base, 0);
    for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
      sqliteVdbeAddOp(v, OP_Close, idx+base, 0);
    }
  }

  sqliteEndWriteOperation(pParse);

  /*
   ** Return the number of rows inserted.
  */
  if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
    sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
    sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);
    sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC);
    sqliteVdbeAddOp(v, OP_Callback, 1, 0);
  }







|
|





|





|

|







<
|
|
|
>



|







|










|







336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365

366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
        sqliteVdbeAddOp(v, OP_Column, srcTab, j); 
      }else{
        sqliteExprCode(pParse, pList->a[j].pExpr);
      }
    }

    /* Generate code to check constraints and generate index keys and
    ** do the insertion.
    */
    endOfLoop = sqliteVdbeMakeLabel(v);
    sqliteGenerateConstraintChecks(pParse, pTab, base, 0,0,0,onError,endOfLoop);
    sqliteCompleteInsertion(pParse, pTab, base, 0,0,0);

    /* Update the count of rows that are inserted
    */
    if( (db->flags & SQLITE_CountRows)!=0 && !pParse->trigStack){
      sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
    }
  }

  if( row_triggers_exist ){
    /* Close all tables opened */
    if( !pTab->pSelect ){
      sqliteVdbeAddOp(v, OP_Close, base, 0);
      for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
        sqliteVdbeAddOp(v, OP_Close, idx+base, 0);
      }
    }

    /* Code AFTER triggers */

    if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_AFTER, pTab, newIdx, -1, 
          onError) ){
      goto insert_cleanup;
    }
  }

  /* The bottom of the loop, if the data source is a SELECT statement
  */
  sqliteVdbeResolveLabel(v, endOfLoop);
  if( srcTab>=0 ){
    sqliteVdbeAddOp(v, OP_Next, srcTab, iCont);
    sqliteVdbeResolveLabel(v, iBreak);
    sqliteVdbeAddOp(v, OP_Close, srcTab, 0);
  }

  if( !row_triggers_exist ){
    /* Close all tables opened */
    sqliteVdbeAddOp(v, OP_Close, base, 0);
    for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
      sqliteVdbeAddOp(v, OP_Close, idx+base, 0);
    }
  }

  sqliteEndWriteOperation(pParse);

  /*
  ** Return the number of rows inserted.
  */
  if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
    sqliteVdbeAddOp(v, OP_ColumnCount, 1, 0);
    sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);
    sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC);
    sqliteVdbeAddOp(v, OP_Callback, 1, 0);
  }
Changes to src/main.c.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.74 2002/05/15 14:17:45 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** This is the callback routine for the code that initializes the







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.75 2002/05/19 23:43:14 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** This is the callback routine for the code that initializes the
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
  assert( sqliteHashFirst(&db->tblDrop)==0 ); /* There can not be uncommitted */
  assert( sqliteHashFirst(&db->idxDrop)==0 ); /*   DROP TABLEs or DROP INDEXs */
  temp1 = db->tblHash;
  temp2 = db->trigHash;
  sqliteHashInit(&db->trigHash, SQLITE_HASH_STRING, 0);
  sqliteHashClear(&db->idxHash);

  for (pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
    Trigger * pTrigger = sqliteHashData(pElem);
    Table *pTab = sqliteFindTable(db, pTrigger->table);
    assert(pTab);
    if (pTab->isTemp) { 
      sqliteHashInsert(&db->trigHash, pTrigger->name, strlen(pTrigger->name), 
          pTrigger);
    } else {
      sqliteDeleteTrigger(pTrigger);
    }
  }
  sqliteHashClear(&temp2);

  sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0);








|



|


|







390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
  assert( sqliteHashFirst(&db->tblDrop)==0 ); /* There can not be uncommitted */
  assert( sqliteHashFirst(&db->idxDrop)==0 ); /*   DROP TABLEs or DROP INDEXs */
  temp1 = db->tblHash;
  temp2 = db->trigHash;
  sqliteHashInit(&db->trigHash, SQLITE_HASH_STRING, 0);
  sqliteHashClear(&db->idxHash);

  for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
    Trigger * pTrigger = sqliteHashData(pElem);
    Table *pTab = sqliteFindTable(db, pTrigger->table);
    assert(pTab);
    if( pTab->isTemp ){ 
      sqliteHashInsert(&db->trigHash, pTrigger->name, strlen(pTrigger->name), 
          pTrigger);
    }else{
      sqliteDeleteTrigger(pTrigger);
    }
  }
  sqliteHashClear(&temp2);

  sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0);

430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
        }
      }
    }else{
      sqliteDeleteTable(db, pTab);
    }
  }
  sqliteHashClear(&temp1);

  db->flags &= ~SQLITE_Initialized;
}

/*
** Return the ROWID of the most recent insert
*/
int sqlite_last_insert_rowid(sqlite *db){







<







430
431
432
433
434
435
436

437
438
439
440
441
442
443
        }
      }
    }else{
      sqliteDeleteTable(db, pTab);
    }
  }
  sqliteHashClear(&temp1);

  db->flags &= ~SQLITE_Initialized;
}

/*
** Return the ROWID of the most recent insert
*/
int sqlite_last_insert_rowid(sqlite *db){
Changes to src/trigger.c.
76
77
78
79
80
81
82
83
84

85

86
87
88
89
90
91
92

  nt->strings = sqliteStrNDup(zData, zDataLen);
  offset = (int)(nt->strings - zData);

  sqliteExprMoveStrings(nt->pWhen, offset);

  ss = nt->step_list;
  while (ss) {
    sqliteSelectMoveStrings(ss->pSelect, offset);

    if (ss->target.z) ss->target.z += offset;

    sqliteExprMoveStrings(ss->pWhere, offset);
    sqliteExprListMoveStrings(ss->pExprList, offset);

    ss = ss->pNext;
  }

  /* if we are not initializing, and this trigger is not on a TEMP table, 







|

>
|
>







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

  nt->strings = sqliteStrNDup(zData, zDataLen);
  offset = (int)(nt->strings - zData);

  sqliteExprMoveStrings(nt->pWhen, offset);

  ss = nt->step_list;
  while( ss ){
    sqliteSelectMoveStrings(ss->pSelect, offset);
    if( ss->target.z ){
      ss->target.z += offset;
    }
    sqliteExprMoveStrings(ss->pWhere, offset);
    sqliteExprListMoveStrings(ss->pExprList, offset);

    ss = ss->pNext;
  }

  /* if we are not initializing, and this trigger is not on a TEMP table, 
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
    /* Stick it in the hash-table */
    sqliteHashInsert(&(pParse->db->trigHash), nt->name, pName->n + 1, nt);

    /* Attach it to the table object */
    nt->pNext = tab->pTrigger;
    tab->pTrigger = nt;
    return;
  } else {
    sqliteFree(nt->strings);
    sqliteFree(nt->name);
    sqliteFree(nt->table);
    sqliteFree(nt);
  }

trigger_cleanup:

  sqliteIdListDelete(pColumns);
  sqliteExprDelete(pWhen);
  {
    TriggerStep * pp;
    TriggerStep * nn;

    pp = pStepList;
    while (pp) {
      nn = pp->pNext;
      sqliteExprDelete(pp->pWhere);
      sqliteExprListDelete(pp->pExprList);
      sqliteSelectDelete(pp->pSelect);
      sqliteIdListDelete(pp->pIdList);
      sqliteFree(pp);
      pp = nn;







|















|







128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
    /* Stick it in the hash-table */
    sqliteHashInsert(&(pParse->db->trigHash), nt->name, pName->n + 1, nt);

    /* Attach it to the table object */
    nt->pNext = tab->pTrigger;
    tab->pTrigger = nt;
    return;
  }else{
    sqliteFree(nt->strings);
    sqliteFree(nt->name);
    sqliteFree(nt->table);
    sqliteFree(nt);
  }

trigger_cleanup:

  sqliteIdListDelete(pColumns);
  sqliteExprDelete(pWhen);
  {
    TriggerStep * pp;
    TriggerStep * nn;

    pp = pStepList;
    while( pp ){
      nn = pp->pNext;
      sqliteExprDelete(pp->pWhere);
      sqliteExprListDelete(pp->pExprList);
      sqliteSelectDelete(pp->pSelect);
      sqliteIdListDelete(pp->pIdList);
      sqliteFree(pp);
      pp = nn;
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
** Recursively delete a Trigger structure
*/
void sqliteDeleteTrigger(Trigger *pTrigger)
{
  TriggerStep *pTriggerStep;

  pTriggerStep = pTrigger->step_list;
  while (pTriggerStep) {
    TriggerStep * pTmp = pTriggerStep;
    pTriggerStep = pTriggerStep->pNext;

    sqliteExprDelete(pTmp->pWhere);
    sqliteExprListDelete(pTmp->pExprList);
    sqliteSelectDelete(pTmp->pSelect);
    sqliteIdListDelete(pTmp->pIdList);







|







226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
** Recursively delete a Trigger structure
*/
void sqliteDeleteTrigger(Trigger *pTrigger)
{
  TriggerStep *pTriggerStep;

  pTriggerStep = pTrigger->step_list;
  while( pTriggerStep ){
    TriggerStep * pTmp = pTriggerStep;
    pTriggerStep = pTriggerStep->pNext;

    sqliteExprDelete(pTmp->pWhere);
    sqliteExprListDelete(pTmp->pExprList);
    sqliteSelectDelete(pTmp->pSelect);
    sqliteIdListDelete(pTmp->pIdList);
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
   */
  if( !pParse->explain ){
    /* 1 */
    pTable = sqliteFindTable(pParse->db, pTrigger->table);
    assert(pTable);
    if( pTable->pTrigger == pTrigger ){
      pTable->pTrigger = pTrigger->pNext;
    } else {
      Trigger *cc = pTable->pTrigger;
      while( cc ){ 
        if( cc->pNext == pTrigger ){
          cc->pNext = cc->pNext->pNext;
          break;
        }
        cc = cc->pNext;







|







285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
   */
  if( !pParse->explain ){
    /* 1 */
    pTable = sqliteFindTable(pParse->db, pTrigger->table);
    assert(pTable);
    if( pTable->pTrigger == pTrigger ){
      pTable->pTrigger = pTrigger->pNext;
    }else{
      Trigger *cc = pTable->pTrigger;
      while( cc ){ 
        if( cc->pNext == pTrigger ){
          cc->pNext = cc->pNext->pNext;
          break;
        }
        cc = cc->pNext;
342
343
344
345
346
347
348
349
350
351
352
353
354
355



356
357
358
359
360
361
362

  sqliteFree(zName);
}

static int checkColumnOverLap(IdList * pIdList, ExprList * pEList)
{
  int i, e;
  if (!pIdList) return 1;
  if (!pEList) return 1;

  for (i = 0; i < pIdList->nId; i++) 
    for (e = 0; e < pEList->nExpr; e++) 
      if (!sqliteStrICmp(pIdList->a[i].zName, pEList->a[e].zName))
        return 1;




  return 0; 
}

/* A global variable that is TRUE if we should always set up temp tables for
 * for triggers, even if there are no triggers to code. This is used to test 
 * how much overhead the triggers algorithm is causing.







|
|

|
|
|

>
>
>







344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367

  sqliteFree(zName);
}

static int checkColumnOverLap(IdList * pIdList, ExprList * pEList)
{
  int i, e;
  if( !pIdList )return 1;
  if( !pEList )return 1;

  for(i = 0; i < pIdList->nId; i++){ 
    for(e = 0; e < pEList->nExpr; e++){ 
      if( !sqliteStrICmp(pIdList->a[i].zName, pEList->a[e].zName) ){
        return 1;
      }
    }
  }

  return 0; 
}

/* A global variable that is TRUE if we should always set up temp tables for
 * for triggers, even if there are no triggers to code. This is used to test 
 * how much overhead the triggers algorithm is causing.
390
391
392
393
394
395
396
397


398
399
400
401
402
403
404
405
  while( pTriggerCursor ){
    if( pTriggerCursor->op == op && 
	pTriggerCursor->tr_tm == tr_tm && 
	pTriggerCursor->foreach == foreach &&
	checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
      TriggerStack * ss;
      ss = pParse->trigStack;
      while (ss && ss->pTrigger != pTrigger) ss = ss->pNext;


      if (!ss) return 1;
    }
    pTriggerCursor = pTriggerCursor->pNext;
  }

  return 0;
}








|
>
>
|







395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
  while( pTriggerCursor ){
    if( pTriggerCursor->op == op && 
	pTriggerCursor->tr_tm == tr_tm && 
	pTriggerCursor->foreach == foreach &&
	checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
      TriggerStack * ss;
      ss = pParse->trigStack;
      while( ss && ss->pTrigger != pTrigger ){
	ss = ss->pNext;
      }
      if( !ss )return 1;
    }
    pTriggerCursor = pTriggerCursor->pNext;
  }

  return 0;
}

489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505


506
507
508
509
510
511
512

513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540

  assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
  assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);

  assert(newIdx != -1 || oldIdx != -1);

  pTrigger = pTab->pTrigger;
  while (pTrigger) {
    int fire_this = 0;

    /* determine whether we should code this trigger */
    if (pTrigger->op == op && pTrigger->tr_tm == tr_tm && 
        pTrigger->foreach == TK_ROW) {
      fire_this = 1;
      pTriggerStack = pParse->trigStack;
      while (pTriggerStack) {
        if (pTriggerStack->pTrigger == pTrigger) fire_this = 0;


        pTriggerStack = pTriggerStack->pNext;
      }
      if (op == TK_UPDATE && pTrigger->pColumns &&
          !checkColumnOverLap(pTrigger->pColumns, pChanges))
        fire_this = 0;
    }


    if (fire_this) {
      int endTrigger;
      IdList dummyTablist;
      Expr * whenExpr;

      dummyTablist.nId = 0;
      dummyTablist.a = 0;

      /* Push an entry on to the trigger stack */
      pTriggerStack = sqliteMalloc(sizeof(TriggerStack));
      pTriggerStack->pTrigger = pTrigger;
      pTriggerStack->newIdx = newIdx;
      pTriggerStack->oldIdx = oldIdx;
      pTriggerStack->pTab = pTab;
      pTriggerStack->pNext = pParse->trigStack;
      pParse->trigStack = pTriggerStack;

      /* code the WHEN clause */
      endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
      whenExpr = sqliteExprDup(pTrigger->pWhen);
      if (sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr)) {
        pParse->trigStack = pParse->trigStack->pNext;
        sqliteFree(pTriggerStack);
        sqliteExprDelete(whenExpr);
        return 1;
      }
      sqliteExprIfFalse(pParse, whenExpr, endTrigger);
      sqliteExprDelete(whenExpr);







|



|
|


|
|
>
>


|
|

|
|
>
|



















|







496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550

  assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
  assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER);

  assert(newIdx != -1 || oldIdx != -1);

  pTrigger = pTab->pTrigger;
  while( pTrigger ){
    int fire_this = 0;

    /* determine whether we should code this trigger */
    if( pTrigger->op == op && pTrigger->tr_tm == tr_tm && 
        pTrigger->foreach == TK_ROW ){
      fire_this = 1;
      pTriggerStack = pParse->trigStack;
      while( pTriggerStack ){
        if( pTriggerStack->pTrigger == pTrigger ){
	  fire_this = 0;
	}
        pTriggerStack = pTriggerStack->pNext;
      }
      if( op == TK_UPDATE && pTrigger->pColumns &&
          !checkColumnOverLap(pTrigger->pColumns, pChanges) ){
        fire_this = 0;
      }
    }

    if( fire_this ){
      int endTrigger;
      IdList dummyTablist;
      Expr * whenExpr;

      dummyTablist.nId = 0;
      dummyTablist.a = 0;

      /* Push an entry on to the trigger stack */
      pTriggerStack = sqliteMalloc(sizeof(TriggerStack));
      pTriggerStack->pTrigger = pTrigger;
      pTriggerStack->newIdx = newIdx;
      pTriggerStack->oldIdx = oldIdx;
      pTriggerStack->pTab = pTab;
      pTriggerStack->pNext = pParse->trigStack;
      pParse->trigStack = pTriggerStack;

      /* code the WHEN clause */
      endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
      whenExpr = sqliteExprDup(pTrigger->pWhen);
      if( sqliteExprResolveIds(pParse, 0, &dummyTablist, 0, whenExpr) ){
        pParse->trigStack = pParse->trigStack->pNext;
        sqliteFree(pTriggerStack);
        sqliteExprDelete(whenExpr);
        return 1;
      }
      sqliteExprIfFalse(pParse, whenExpr, endTrigger);
      sqliteExprDelete(whenExpr);
632
633
634
635
636
637
638
639
640

641
642
643
644
645
646
647
    for(ii = 0; ii < pTab->nCol; ii++){
      aXRef[ii] = -1;
    }

    for(ii=0; ii<pChanges->nExpr; ii++){
      int jj;
      if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0, 
            pChanges->a[ii].pExpr) )
        goto trigger_cleanup;


      if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
        goto trigger_cleanup;

      for(jj=0; jj<pTab->nCol; jj++){
        if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
          aXRef[jj] = ii;







|

>







642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
    for(ii = 0; ii < pTab->nCol; ii++){
      aXRef[ii] = -1;
    }

    for(ii=0; ii<pChanges->nExpr; ii++){
      int jj;
      if( sqliteExprResolveIds(pParse, oldIdx, theSelect.pSrc , 0, 
            pChanges->a[ii].pExpr) ){
        goto trigger_cleanup;
      }

      if( sqliteExprCheck(pParse, pChanges->a[ii].pExpr, 0, 0) )
        goto trigger_cleanup;

      for(jj=0; jj<pTab->nCol; jj++){
        if( sqliteStrICmp(pTab->aCol[jj].zName, pChanges->a[ii].zName)==0 ){
          aXRef[jj] = ii;
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
    }

    sqliteVdbeAddOp(v, OP_Integer, 13, 0);

    for(ii = 0; ii<pTab->nCol; ii++){
      if( aXRef[ii] < 0 ){ 
        sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
      } else {
        sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
      }
    }

    sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
    sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
    sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);

    sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, 
        pTab, newIdx, oldIdx, orconf);
    sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, 
        pTab, newIdx, oldIdx, orconf);
  } else {
    sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx, 
        orconf);
    sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx, 
        orconf);
  }

  sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);







|












|







668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
    }

    sqliteVdbeAddOp(v, OP_Integer, 13, 0);

    for(ii = 0; ii<pTab->nCol; ii++){
      if( aXRef[ii] < 0 ){ 
        sqliteVdbeAddOp(v, OP_Column, oldIdx, ii);
      }else{
        sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
      }
    }

    sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
    sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
    sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);

    sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, 
        pTab, newIdx, oldIdx, orconf);
    sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, 
        pTab, newIdx, oldIdx, orconf);
  }else{
    sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1, oldIdx, 
        orconf);
    sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1, oldIdx, 
        orconf);
  }

  sqliteVdbeAddOp(v, OP_Next, oldIdx, startOfLoop);
Changes to src/update.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.38 2002/05/15 11:44:15 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
*/
void sqliteUpdate(







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.39 2002/05/19 23:43:14 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
*/
void sqliteUpdate(
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102
  if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup;
  db = pParse->db;

  /* Check for the special case of a VIEW with one or more ON UPDATE triggers 
   * defined 
   */
  {
    char * zTab = sqliteTableNameFromToken(pTableName);

    if(zTab != 0) {
      pTab = sqliteFindTable(pParse->db, zTab);
      if (pTab) {
        row_triggers_exist = 
          sqliteTriggersExist(pParse, pTab->pTrigger, 
              TK_UPDATE, TK_BEFORE, TK_ROW, pChanges) ||
          sqliteTriggersExist(pParse, pTab->pTrigger, 
              TK_UPDATE, TK_AFTER, TK_ROW, pChanges);
      }
      sqliteFree(zTab);
      if (row_triggers_exist &&  pTab->pSelect ) {
        /* Just fire VIEW triggers */
        sqliteViewTriggers(pParse, pTab, pWhere, onError, pChanges);
        return;
      }
    }
  }

  /* Locate the table which we want to update.  This table has to be
  ** put in an IdList structure because some of the subroutines we
  ** will be calling are designed to work with multiple tables and expect
  ** an IdList* parameter instead of just a Table* parameter.
  */
  pTabList = sqliteTableTokenToIdList(pParse, pTableName);
  if( pTabList==0 ) goto update_cleanup;
  pTab = pTabList->a[0].pTab;
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
  aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
  if( aXRef==0 ) goto update_cleanup;
  for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;


  if (row_triggers_exist) {
    newIdx = pParse->nTab++;
    oldIdx = pParse->nTab++;
  }

  /* Resolve the column names in all the expressions in both the
  ** WHERE clause and in the new values.  Also find the column index
  ** for each column to be updated in the pChanges array.







|

|

|







|




















>
|







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
  if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup;
  db = pParse->db;

  /* Check for the special case of a VIEW with one or more ON UPDATE triggers 
   * defined 
   */
  {
    char *zTab = sqliteTableNameFromToken(pTableName);

    if( zTab != 0 ){
      pTab = sqliteFindTable(pParse->db, zTab);
      if( pTab ){
        row_triggers_exist = 
          sqliteTriggersExist(pParse, pTab->pTrigger, 
              TK_UPDATE, TK_BEFORE, TK_ROW, pChanges) ||
          sqliteTriggersExist(pParse, pTab->pTrigger, 
              TK_UPDATE, TK_AFTER, TK_ROW, pChanges);
      }
      sqliteFree(zTab);
      if( row_triggers_exist &&  pTab->pSelect ){
        /* Just fire VIEW triggers */
        sqliteViewTriggers(pParse, pTab, pWhere, onError, pChanges);
        return;
      }
    }
  }

  /* Locate the table which we want to update.  This table has to be
  ** put in an IdList structure because some of the subroutines we
  ** will be calling are designed to work with multiple tables and expect
  ** an IdList* parameter instead of just a Table* parameter.
  */
  pTabList = sqliteTableTokenToIdList(pParse, pTableName);
  if( pTabList==0 ) goto update_cleanup;
  pTab = pTabList->a[0].pTab;
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
  aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
  if( aXRef==0 ) goto update_cleanup;
  for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;

  /* If there are FOR EACH ROW triggers, allocate temp tables */
  if( row_triggers_exist ){
    newIdx = pParse->nTab++;
    oldIdx = pParse->nTab++;
  }

  /* Resolve the column names in all the expressions in both the
  ** WHERE clause and in the new values.  Also find the column index
  ** for each column to be updated in the pChanges array.
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227
228
229
230

231
232
233
234
235
236
237
238
239
240
241
242
243


244
245
246
247
248
249
250

  /* Initialize the count of updated rows
  */
  if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
    sqliteVdbeAddOp(v, OP_Integer, 0, 0);
  }

  if (row_triggers_exist) {
    int ii;

    sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0);
    sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);

    sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
    addr = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
    sqliteVdbeAddOp(v, OP_Dup, 0, 0);

    sqliteVdbeAddOp(v, OP_Dup, 0, 0);
    sqliteVdbeAddOp(v, OP_Open, base, pTab->tnum);
    sqliteVdbeAddOp(v, OP_MoveTo, base, 0);

    sqliteVdbeAddOp(v, OP_Integer, 13, 0);
    for (ii = 0; ii < pTab->nCol; ii++) {
        if (ii == pTab->iPKey) 
            sqliteVdbeAddOp(v, OP_Recno, base, 0);
        else
            sqliteVdbeAddOp(v, OP_Column, base, ii);

    }
    sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
    sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);

    sqliteVdbeAddOp(v, OP_Integer, 13, 0);
    for (ii = 0; ii < pTab->nCol; ii++){
      if( aXRef[ii] < 0 ){
        if (ii == pTab->iPKey)
          sqliteVdbeAddOp(v, OP_Recno, base, 0);
        else
          sqliteVdbeAddOp(v, OP_Column, base, ii);

      }else{
        sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
      }
    }
    sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
    sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
    sqliteVdbeAddOp(v, OP_Close, base, 0);

    sqliteVdbeAddOp(v, OP_Rewind, oldIdx, 0);
    sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);

    if (sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab, 
          newIdx, oldIdx, onError)) goto update_cleanup;


  }

  /* Rewind the list of records that need to be updated and
  ** open every index that needs updating.  Note that if any
  ** index could potentially invoke a REPLACE conflict resolution 
  ** action, then we need to open all indices because we might need
  ** to be deleting some records.







|














|
|
|
|
|
>





|

|

|

>











|
|
>
>







194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255

  /* Initialize the count of updated rows
  */
  if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
    sqliteVdbeAddOp(v, OP_Integer, 0, 0);
  }

  if( row_triggers_exist ){
    int ii;

    sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0);
    sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);

    sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
    addr = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
    sqliteVdbeAddOp(v, OP_Dup, 0, 0);

    sqliteVdbeAddOp(v, OP_Dup, 0, 0);
    sqliteVdbeAddOp(v, OP_Open, base, pTab->tnum);
    sqliteVdbeAddOp(v, OP_MoveTo, base, 0);

    sqliteVdbeAddOp(v, OP_Integer, 13, 0);
    for(ii = 0; ii < pTab->nCol; ii++){
      if( ii == pTab->iPKey ){
	sqliteVdbeAddOp(v, OP_Recno, base, 0);
      }else{
	sqliteVdbeAddOp(v, OP_Column, base, ii);
      }
    }
    sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
    sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);

    sqliteVdbeAddOp(v, OP_Integer, 13, 0);
    for(ii = 0; ii < pTab->nCol; ii++){
      if( aXRef[ii] < 0 ){
        if( ii == pTab->iPKey ){
          sqliteVdbeAddOp(v, OP_Recno, base, 0);
	}else{
          sqliteVdbeAddOp(v, OP_Column, base, ii);
	}
      }else{
        sqliteExprCode(pParse, pChanges->a[aXRef[ii]].pExpr);
      }
    }
    sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
    sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
    sqliteVdbeAddOp(v, OP_Close, base, 0);

    sqliteVdbeAddOp(v, OP_Rewind, oldIdx, 0);
    sqliteVdbeAddOp(v, OP_Rewind, newIdx, 0);

    if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab, 
          newIdx, oldIdx, onError) ){
      goto update_cleanup;
    }
  }

  /* Rewind the list of records that need to be updated and
  ** open every index that needs updating.  Note that if any
  ** index could potentially invoke a REPLACE conflict resolution 
  ** action, then we need to open all indices because we might need
  ** to be deleting some records.
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286

  /* Loop over every record that needs updating.  We have to load
  ** the old data for each record to be updated because some columns
  ** might not change and we will need to copy the old value.
  ** Also, the old data is needed to delete the old index entires.
  ** So make the cursor point at the old record.
  */
  if (!row_triggers_exist) {
    int ii;
    sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
    addr = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
    sqliteVdbeAddOp(v, OP_Dup, 0, 0);
  }
  sqliteVdbeAddOp(v, OP_MoveTo, base, 0);








|







277
278
279
280
281
282
283
284
285
286
287
288
289
290
291

  /* Loop over every record that needs updating.  We have to load
  ** the old data for each record to be updated because some columns
  ** might not change and we will need to copy the old value.
  ** Also, the old data is needed to delete the old index entires.
  ** So make the cursor point at the old record.
  */
  if( !row_triggers_exist ){
    int ii;
    sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
    addr = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
    sqliteVdbeAddOp(v, OP_Dup, 0, 0);
  }
  sqliteVdbeAddOp(v, OP_MoveTo, base, 0);

333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349


350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375

  /* Increment the row counter 
  */
  if( db->flags & SQLITE_CountRows && !pParse->trigStack){
    sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
  }

  if (row_triggers_exist) {
    for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
      if( openAll || aIdxUsed[i] )
        sqliteVdbeAddOp(v, OP_Close, base+i+1, 0);
    }
    sqliteVdbeAddOp(v, OP_Close, base, 0);
    pParse->nTab = base;

    if (sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab, 
          newIdx, oldIdx, onError)) goto update_cleanup;


  }

  /* Repeat the above with the next record to be updated, until
  ** all record selected by the WHERE clause have been updated.
  */
  sqliteVdbeAddOp(v, OP_Goto, 0, addr);
  sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
  sqliteVdbeAddOp(v, OP_ListReset, 0, 0);

  /* Close all tables if there were no FOR EACH ROW triggers */
  if (!row_triggers_exist) {
    for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
      if( openAll || aIdxUsed[i] ){
        sqliteVdbeAddOp(v, OP_Close, base+i+1, 0);
      }
    }
    sqliteVdbeAddOp(v, OP_Close, base, 0);
    pParse->nTab = base;
  } else {
    sqliteVdbeAddOp(v, OP_Close, newIdx, 0);
    sqliteVdbeAddOp(v, OP_Close, oldIdx, 0);
  }

  sqliteEndWriteOperation(pParse);

  /*







|







|
|
>
>










|







|







338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382

  /* Increment the row counter 
  */
  if( db->flags & SQLITE_CountRows && !pParse->trigStack){
    sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
  }

  if( row_triggers_exist ){
    for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
      if( openAll || aIdxUsed[i] )
        sqliteVdbeAddOp(v, OP_Close, base+i+1, 0);
    }
    sqliteVdbeAddOp(v, OP_Close, base, 0);
    pParse->nTab = base;

    if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab, 
          newIdx, oldIdx, onError) ){
      goto update_cleanup;
    }
  }

  /* Repeat the above with the next record to be updated, until
  ** all record selected by the WHERE clause have been updated.
  */
  sqliteVdbeAddOp(v, OP_Goto, 0, addr);
  sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
  sqliteVdbeAddOp(v, OP_ListReset, 0, 0);

  /* Close all tables if there were no FOR EACH ROW triggers */
  if( !row_triggers_exist ){
    for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
      if( openAll || aIdxUsed[i] ){
        sqliteVdbeAddOp(v, OP_Close, base+i+1, 0);
      }
    }
    sqliteVdbeAddOp(v, OP_Close, base, 0);
    pParse->nTab = base;
  }else{
    sqliteVdbeAddOp(v, OP_Close, newIdx, 0);
    sqliteVdbeAddOp(v, OP_Close, oldIdx, 0);
  }

  sqliteEndWriteOperation(pParse);

  /*
Changes to src/vdbe.c.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
** type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.143 2002/05/15 11:44:15 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test







|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
** type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.144 2002/05/19 23:43:14 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
  Mem *aMem;          /* The memory locations */
  Agg agg;            /* Aggregate information */
  int nSet;           /* Number of sets allocated */
  Set *aSet;          /* An array of sets */
  int nCallback;      /* Number of callbacks invoked so far */
  int iLimit;         /* Limit on the number of callbacks remaining */
  int iOffset;        /* Offset before beginning to do callbacks */

  int keylistStackDepth; 
  Keylist ** keylistStack;
};

/*
** Create a new virtual database engine.
*/
Vdbe *sqliteVdbeCreate(sqlite *db){
  Vdbe *p;







<
|
|







245
246
247
248
249
250
251

252
253
254
255
256
257
258
259
260
  Mem *aMem;          /* The memory locations */
  Agg agg;            /* Aggregate information */
  int nSet;           /* Number of sets allocated */
  Set *aSet;          /* An array of sets */
  int nCallback;      /* Number of callbacks invoked so far */
  int iLimit;         /* Limit on the number of callbacks remaining */
  int iOffset;        /* Offset before beginning to do callbacks */

  int keylistStackDepth;  /* The size of the "keylist" stack */
  Keylist **keylistStack; /* The stack used by opcodes PushList & PopList */
};

/*
** Create a new virtual database engine.
*/
Vdbe *sqliteVdbeCreate(sqlite *db){
  Vdbe *p;
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
  AggReset(&p->agg);
  for(i=0; i<p->nSet; i++){
    sqliteHashClear(&p->aSet[i].hash);
  }
  sqliteFree(p->aSet);
  p->aSet = 0;
  p->nSet = 0;
  if (p->keylistStackDepth > 0) {
    int ii;
    for (ii = 0; ii < p->keylistStackDepth; ii++) {
      KeylistFree(p->keylistStack[ii]);
    }
    sqliteFree(p->keylistStack);
    p->keylistStackDepth = 0;
    p->keylistStack = 0;
  }
}







|

|







997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
  AggReset(&p->agg);
  for(i=0; i<p->nSet; i++){
    sqliteHashClear(&p->aSet[i].hash);
  }
  sqliteFree(p->aSet);
  p->aSet = 0;
  p->nSet = 0;
  if( p->keylistStackDepth > 0 ){
    int ii;
    for(ii = 0; ii < p->keylistStackDepth; ii++){
      KeylistFree(p->keylistStack[ii]);
    }
    sqliteFree(p->keylistStack);
    p->keylistStackDepth = 0;
    p->keylistStack = 0;
  }
}
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
*/
case OP_PopList: {
  assert(p->keylistStackDepth > 0);
  p->keylistStackDepth--;
  KeylistFree(p->pList);
  p->pList = p->keylistStack[p->keylistStackDepth];
  p->keylistStack[p->keylistStackDepth] = 0;
  if (p->keylistStackDepth == 0) {
    sqliteFree(p->keylistStack);
    p->keylistStack = 0;
  }
  break;
}

/* Opcode: SetNotFound P1 P2 *







|







4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
*/
case OP_PopList: {
  assert(p->keylistStackDepth > 0);
  p->keylistStackDepth--;
  KeylistFree(p->pList);
  p->pList = p->keylistStack[p->keylistStackDepth];
  p->keylistStack[p->keylistStackDepth] = 0;
  if( p->keylistStackDepth == 0 ){
    sqliteFree(p->keylistStack);
    p->keylistStack = 0;
  }
  break;
}

/* Opcode: SetNotFound P1 P2 *
Changes to src/where.c.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  Also found here are subroutines
** to generate VDBE code to evaluate expressions.
**
** $Id: where.c,v 1.43 2002/05/15 11:44:15 drh Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  Also found here are subroutines
** to generate VDBE code to evaluate expressions.
**
** $Id: where.c,v 1.44 2002/05/19 23:43:14 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  memset(aExpr, 0, sizeof(aExpr));
  nExpr = exprSplit(ARRAYSIZE(aExpr), aExpr, pWhere);

  /* Analyze all of the subexpressions.
  */
  for(i=0; i<nExpr; i++){
    exprAnalyze(base, &aExpr[i]);
    if (pParse->trigStack && pParse->trigStack->newIdx >= 0) {
        aExpr[i].prereqRight = 
            aExpr[i].prereqRight & ~(1 << pParse->trigStack->newIdx - base);
        aExpr[i].prereqLeft = 
            aExpr[i].prereqLeft & ~(1 << pParse->trigStack->newIdx - base);
        aExpr[i].prereqAll = 
            aExpr[i].prereqAll & ~(1 << pParse->trigStack->newIdx - base);
    }
    if (pParse->trigStack && pParse->trigStack->oldIdx >= 0) {
        aExpr[i].prereqRight = 
            aExpr[i].prereqRight & ~(1 << pParse->trigStack->oldIdx - base);
        aExpr[i].prereqLeft = 
            aExpr[i].prereqLeft & ~(1 << pParse->trigStack->oldIdx - base);
        aExpr[i].prereqAll = 
            aExpr[i].prereqAll & ~(1 << pParse->trigStack->oldIdx - base);
    }







|







|







212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  memset(aExpr, 0, sizeof(aExpr));
  nExpr = exprSplit(ARRAYSIZE(aExpr), aExpr, pWhere);

  /* Analyze all of the subexpressions.
  */
  for(i=0; i<nExpr; i++){
    exprAnalyze(base, &aExpr[i]);
    if( pParse->trigStack && pParse->trigStack->newIdx >= 0 ){
        aExpr[i].prereqRight = 
            aExpr[i].prereqRight & ~(1 << pParse->trigStack->newIdx - base);
        aExpr[i].prereqLeft = 
            aExpr[i].prereqLeft & ~(1 << pParse->trigStack->newIdx - base);
        aExpr[i].prereqAll = 
            aExpr[i].prereqAll & ~(1 << pParse->trigStack->newIdx - base);
    }
    if( pParse->trigStack && pParse->trigStack->oldIdx >= 0 ){
        aExpr[i].prereqRight = 
            aExpr[i].prereqRight & ~(1 << pParse->trigStack->oldIdx - base);
        aExpr[i].prereqLeft = 
            aExpr[i].prereqLeft & ~(1 << pParse->trigStack->oldIdx - base);
        aExpr[i].prereqAll = 
            aExpr[i].prereqAll & ~(1 << pParse->trigStack->oldIdx - base);
    }