SQLite

Check-in [9eb91efda5]
Login

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

Overview
Comment:Fixes for new triggers scheme.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 9eb91efda5241609ff18ff15ef5eaa0e86788eab
User & Date: dan 2009-08-30 11:42:52.000
Context
2009-08-31
05:23
Fix another test problem and some instances where an OOM may cause a segfault. (check-in: 31199db0f7 user: dan tags: trunk)
2009-08-30
11:42
Fixes for new triggers scheme. (check-in: 9eb91efda5 user: dan tags: trunk)
2009-08-28
18:53
Changes to support recursive triggers. (check-in: 9b9c192115 user: dan tags: trunk)
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to src/delete.c.
404
405
406
407
408
409
410

411
412


413
414
415

416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435

436
437
438
439
440
441
442
404
405
406
407
408
409
410
411
412
413
414
415
416
417

418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437

438
439
440
441
442
443
444
445







+


+
+


-
+



















-
+







      sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid);

      /* Populate the OLD.* pseudo-table */
      assert( regOld==iRowid+1 );
      for(i=0; i<pTab->nCol; i++){
        if( mask==0xffffffff || mask&(1<<i) ){
          sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regOld+i);
          sqlite3ColumnDefault(v, pTab, i, regOld+i);
        }
      }
      sqlite3VdbeAddOp2(v, OP_Affinity, regOld, pTab->nCol);
      sqlite3TableAffinityStr(v, pTab);

      sqlite3CodeRowTrigger(pParse, pTrigger, 
          TK_DELETE, 0, TRIGGER_BEFORE, pTab, -1, regOld, OE_Default, addr
          TK_DELETE, 0, TRIGGER_BEFORE, pTab, -1, iRowid, OE_Default, addr
      );
    }

    if( !isView ){
      /* Delete the row */
#ifndef SQLITE_OMIT_VIRTUALTABLE
      if( IsVirtual(pTab) ){
        const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
        sqlite3VtabMakeWritable(pParse, pTab);
        sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVTab, P4_VTAB);
      }else
#endif
      {
        sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, pParse->nested==0);
      }
    }

    /* Code the AFTER triggers. This is a no-op if there are no triggers. */
    sqlite3CodeRowTrigger(pParse, 
      pTrigger, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1, regOld, OE_Default, addr
      pTrigger, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1, iRowid, OE_Default, addr
    );

    /* End of the delete loop */
    sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
    sqlite3VdbeResolveLabel(v, end);

    /* Close the cursors open on the table and its indexes. */
Changes to src/expr.c.
86
87
88
89
90
91
92

93


94
95
96
97
98
99
100
86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
101
102







+
-
+
+







  CollSeq *pColl = 0;
  Expr *p = pExpr;
  while( ALWAYS(p) ){
    int op;
    pColl = p->pColl;
    if( pColl ) break;
    op = p->op;
    if( p->pTab!=0 && (
    if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER) && p->pTab!=0 ){
        op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER
    )){
      /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
      ** a TK_COLUMN but was previously evaluated and cached in a register */
      const char *zColl;
      int j = p->iColumn;
      if( j>=0 ){
        sqlite3 *db = pParse->db;
        zColl = p->pTab->aCol[j].zColl;
2553
2554
2555
2556
2557
2558
2559

2560

2561
2562

2563
2564


2565
2566
2567
2568
2569
2570
2571
2555
2556
2557
2558
2559
2560
2561
2562

2563


2564
2565

2566
2567
2568
2569
2570
2571
2572
2573
2574







+
-
+
-
-
+

-
+
+







    }
    case TK_UPLUS: {
      inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
      break;
    }

    case TK_TRIGGER: {
      int iVal = pExpr->iTable * (pExpr->pTab->nCol+1) + 1 + pExpr->iColumn;
      sqlite3VdbeAddOp3(v, OP_TriggerVal, pExpr->iColumn, target,pExpr->iTable);
      sqlite3VdbeAddOp2(v, OP_Param, iVal, target);
      assert( pExpr->pTab );
      VdbeComment((v, "%s.%s", 
      VdbeComment((v, "%s.%s -> $%d", 
        (pExpr->iTable ? "new" : "old"), 
        (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName)
        (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName),
	target
      ));
      break;
    }


    /*
    ** Form A:
Changes to src/insert.c.
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
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







+


-
+




-
-
+
+


-
-
-
+
+
+

















+
+
+







static int autoIncBegin(
  Parse *pParse,      /* Parsing context */
  int iDb,            /* Index of the database holding pTab */
  Table *pTab         /* The table we are writing to */
){
  int memId = 0;      /* Register holding maximum rowid */
  if( pTab->tabFlags & TF_Autoincrement ){
    Parse *pRoot = (pParse->pRoot ? pParse->pRoot : pParse);
    AutoincInfo *pInfo;

    pInfo = pParse->pAinc;
    pInfo = pRoot->pAinc;
    while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; }
    if( pInfo==0 ){
      pInfo = sqlite3DbMallocRaw(pParse->db, sizeof(*pInfo));
      if( pInfo==0 ) return 0;
      pInfo->pNext = pParse->pAinc;
      pParse->pAinc = pInfo;
      pInfo->pNext = pRoot->pAinc;
      pRoot->pAinc = pInfo;
      pInfo->pTab = pTab;
      pInfo->iDb = iDb;
      pParse->nMem++;                  /* Register to hold name of table */
      pInfo->regCtr = ++pParse->nMem;  /* Max rowid register */
      pParse->nMem++;                  /* Rowid in sqlite_sequence */
      pRoot->nMem++;                  /* Register to hold name of table */
      pInfo->regCtr = ++pRoot->nMem;  /* Max rowid register */
      pRoot->nMem++;                  /* Rowid in sqlite_sequence */
    }
    memId = pInfo->regCtr;
  }
  return memId;
}

/*
** This routine generates code that will initialize all of the
** register used by the autoincrement tracker.  
*/
void sqlite3AutoincrementBegin(Parse *pParse){
  AutoincInfo *p;            /* Information about an AUTOINCREMENT */
  sqlite3 *db = pParse->db;  /* The database connection */
  Db *pDb;                   /* Database only autoinc table */
  int memId;                 /* Register holding max rowid */
  int addr;                  /* A VDBE address */
  Vdbe *v = pParse->pVdbe;   /* VDBE under construction */

  /* If currently generating a trigger program, this call is a no-op */
  if( pParse->pTriggerTab ) return;

  assert( v );   /* We failed long ago if this is not so */
  for(p = pParse->pAinc; p; p = p->pNext){
    pDb = &db->aDb[p->iDb];
    memId = p->regCtr;
    sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
    addr = sqlite3VdbeCurrentAddr(v);
801
802
803
804
805
806
807
808
809

810
811
812
813
814
815
816
817
818
819

820
821
822
823

824
825
826

827
828
829


830
831

832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851

852
853

854
855
856

857
858
859
860
861
862
863
864
865
866

867
868
869
870
871
872

873
874
875

876
877
878
879
880
881
882
805
806
807
808
809
810
811


812
813
814
815
816
817
818
819

820

821
822
823
824

825
826
827

828
829


830
831
832

833
834
835
836
837
838
839
840
841
842

843
844
845
846
847
848
849
850
851

852
853

854
855
856

857
858
859
860
861
862
863
864
865
866

867
868
869
870
871
872

873
874


875
876
877
878
879
880
881
882







-
-
+







-

-
+



-
+


-
+

-
-
+
+

-
+









-









-
+

-
+


-
+









-
+





-
+

-
-
+







  }
  regData = regRowid+1;

  /* Run the BEFORE and INSTEAD OF triggers, if there are any
  */
  endOfLoop = sqlite3VdbeMakeLabel(v);
  if( tmask & TRIGGER_BEFORE ){
    int regTrigRowid;
    int regCols;
    int regCols = sqlite3GetTempRange(pParse, pTab->nCol+1);

    /* build the NEW.* reference row.  Note that if there is an INTEGER
    ** PRIMARY KEY into which a NULL is being inserted, that NULL will be
    ** translated into a unique ID for the row.  But on a BEFORE trigger,
    ** we do not know what the unique ID will be (because the insert has
    ** not happened yet) so we substitute a rowid of -1
    */
    regTrigRowid = sqlite3GetTempReg(pParse);
    if( keyColumn<0 ){
      sqlite3VdbeAddOp2(v, OP_Integer, -1, regTrigRowid);
      sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols);
    }else{
      int j1;
      if( useTempTable ){
        sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regTrigRowid);
        sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regCols);
      }else{
        assert( pSelect==0 );  /* Otherwise useTempTable is true */
        sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regTrigRowid);
        sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regCols);
      }
      j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regTrigRowid);
      sqlite3VdbeAddOp2(v, OP_Integer, -1, regTrigRowid);
      j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols);
      sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols);
      sqlite3VdbeJumpHere(v, j1);
      sqlite3VdbeAddOp1(v, OP_MustBeInt, regTrigRowid);
      sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols);
    }

    /* Cannot have triggers on a virtual table. If it were possible,
    ** this block would have to account for hidden column.
    */
    assert( !IsVirtual(pTab) );

    /* Create the new column data
    */
    regCols = sqlite3GetTempRange(pParse, pTab->nCol);
    for(i=0; i<pTab->nCol; i++){
      if( pColumn==0 ){
        j = i;
      }else{
        for(j=0; j<pColumn->nId; j++){
          if( pColumn->a[j].idx==i ) break;
        }
      }
      if( pColumn && j>=pColumn->nId ){
        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i);
        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1);
      }else if( useTempTable ){
        sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i); 
        sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1); 
      }else{
        assert( pSelect==0 ); /* Otherwise useTempTable is true */
        sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i);
        sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i+1);
      }
    }

    /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger,
    ** do not attempt any conversions before assembling the record.
    ** If this is a real table, attempt conversions as required by the
    ** table column affinities.
    */
    if( !isView ){
      sqlite3VdbeAddOp2(v, OP_Affinity, regCols, pTab->nCol);
      sqlite3VdbeAddOp2(v, OP_Affinity, regCols+1, pTab->nCol);
      sqlite3TableAffinityStr(v, pTab);
    }

    /* Fire BEFORE or INSTEAD OF triggers */
    sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE, 
        pTab, regCols, -1, onError, endOfLoop);
        pTab, -1, regCols-pTab->nCol-1, onError, endOfLoop);

    sqlite3ReleaseTempReg(pParse, regTrigRowid);
    sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol);
    sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1);
  }

  /* Push the record number for the new entry onto the stack.  The
  ** record number is a randomly generate integer created by NewRowid
  ** except when the table has an INTEGER PRIMARY KEY column, in which
  ** case the record number is the same as that column. 
  */
990
991
992
993
994
995
996
997

998
999
1000
1001
1002
1003
1004
990
991
992
993
994
995
996

997
998
999
1000
1001
1002
1003
1004







-
+







  if( (db->flags & SQLITE_CountRows)!=0 ){
    sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
  }

  if( pTrigger ){
    /* Code AFTER triggers */
    sqlite3CodeRowTrigger(pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER, 
          pTab, regData, -1, onError, endOfLoop);
        pTab, -1, regData-2-pTab->nCol, onError, endOfLoop);
  }

  /* The bottom of the main insertion loop, if the data source
  ** is a SELECT statement.
  */
  sqlite3VdbeResolveLabel(v, endOfLoop);
  if( useTempTable ){
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1149
1150
1151
1152
1153
1154
1155

1156
1157
1158
1159
1160
1161
1162







-








  v = sqlite3GetVdbe(pParse);
  assert( v!=0 );
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
  nCol = pTab->nCol;
  regData = regRowid + 1;


  /* Test all NOT NULL constraints.
  */
  for(i=0; i<nCol; i++){
    if( i==pTab->iPKey ){
      continue;
    }
    onError = pTab->aCol[i].notNull;
1225
1226
1227
1228
1229
1230
1231
1232

1233
1234
1235
1236
1237
1238
1239
1224
1225
1226
1227
1228
1229
1230

1231
1232
1233
1234
1235
1236
1237
1238







-
+







      onError = overrideError;
    }else if( onError==OE_Default ){
      onError = OE_Abort;
    }
    
    if( onError!=OE_Replace || pTab->pIndex ){
      if( isUpdate ){
        j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, regRowid-1);
        j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, rowidChng);
      }
      j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
      switch( onError ){
        default: {
          onError = OE_Abort;
          /* Fall thru into the next case */
        }
Changes to src/main.c.
1586
1587
1588
1589
1590
1591
1592



1593
1594
1595
1596
1597
1598
1599
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602







+
+
+







  db->nextPagesize = 0;
  db->flags |= SQLITE_ShortColNames
#if SQLITE_DEFAULT_FILE_FORMAT<4
                 | SQLITE_LegacyFileFmt
#endif
#ifdef SQLITE_ENABLE_LOAD_EXTENSION
                 | SQLITE_LoadExtension
#endif
#ifdef SQLITE_DISABLE_RECURSIVE_TRIGGERS
                 | SQLITE_NoRecTriggers
#endif
      ;
  sqlite3HashInit(&db->aCollSeq);
#ifndef SQLITE_OMIT_VIRTUALTABLE
  sqlite3HashInit(&db->aModule);
#endif

Changes to src/pragma.c.
186
187
188
189
190
191
192

193
194
195
196
197
198
199
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200







+







    /* The following is VERY experimental */
    { "writable_schema",          SQLITE_WriteSchema|SQLITE_RecoveryMode },
    { "omit_readlock",            SQLITE_NoReadlock    },

    /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted
    ** flag if there are any active statements. */
    { "read_uncommitted",         SQLITE_ReadUncommitted },
    { "disable_recursive_triggers", SQLITE_NoRecTriggers },
  };
  int i;
  const struct sPragmaType *p;
  for(i=0, p=aPragma; i<ArraySize(aPragma); i++, p++){
    if( sqlite3StrICmp(zLeft, p->zName)==0 ){
      sqlite3 *db = pParse->db;
      Vdbe *v;
Changes to src/sqliteInt.h.
907
908
909
910
911
912
913

914
915
916
917
918
919
920
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921







+







#define SQLITE_ReadUncommitted 0x00004000 /* For shared-cache mode */
#define SQLITE_LegacyFileFmt  0x00008000  /* Create new databases in format 1 */
#define SQLITE_FullFSync      0x00010000  /* Use full fsync on the backend */
#define SQLITE_LoadExtension  0x00020000  /* Enable load_extension */

#define SQLITE_RecoveryMode   0x00040000  /* Ignore schema errors */
#define SQLITE_ReverseOrder   0x00100000  /* Reverse unordered SELECTs */
#define SQLITE_NoRecTriggers  0x00200000  /* Disable recursive triggers */

/*
** Possible values for the sqlite.magic field.
** The numbers are obtained at random and have no special meaning, other
** than being distinct from one another.
*/
#define SQLITE_MAGIC_OPEN     0xa029a697  /* Database is open */
Changes to src/trigger.c.
693
694
695
696
697
698
699




700
701
702
703
704
705
706
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710







+
+
+
+







    **     INSERT OR REPLACE INTO t2 VALUES(new.a, new.b);
    **   END;
    **
    **   INSERT INTO t1 ... ;            -- insert into t2 uses REPLACE policy
    **   INSERT OR IGNORE INTO t1 ... ;  -- insert into t2 uses IGNORE policy
    */
    pParse->orconf = (orconfin==OE_Default)?pStep->orconf:orconfin;

    if( pStep->op!=TK_SELECT ){
      sqlite3VdbeAddOp1(v, OP_ResetCount, 0);
    }

    switch( pStep->op ){
      case TK_UPDATE: {
        sqlite3Update(pParse, 
          targetSrcList(pParse, pStep),
          sqlite3ExprListDup(db, pStep->pExprList, 0), 
          sqlite3ExprDup(db, pStep->pWhere, 0), 
730
731
732
733
734
735
736



737
738
739
740
741
742
743
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750







+
+
+







        Select *pSelect = sqlite3SelectDup(db, pStep->pSelect, 0);
        sqlite3SelectDestInit(&sDest, SRT_Discard, 0);
        sqlite3Select(pParse, pSelect, &sDest);
        sqlite3SelectDelete(db, pSelect);
        break;
      }
    } 
    if( pStep->op!=TK_SELECT ){
      sqlite3VdbeAddOp1(v, OP_ResetCount, 1);
    }
    pStep = pStep->pNext;
  }
/* sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0); */

  return 0;
}

814
815
816
817
818
819
820

821

822
823
824
825
826

827





828
829
830
831
832
833
834
835
836
837
838
839
840
841

842
843
844
845


846
847
848
849
850
851
852
821
822
823
824
825
826
827
828

829
830
831
832
833

834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853

854
855
856
857
858
859
860
861
862
863
864
865
866
867







+
-
+




-
+

+
+
+
+
+













-
+




+
+







  pSubParse->pRoot = pRoot;

  /* Push an entry on to the auth context stack */
  sqlite3AuthContextPush(pParse, &sContext, pTrigger->name);

  v = sqlite3GetVdbe(pSubParse);
  if( v ){
    VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)", 
    VdbeComment((v, "Trigger: %s (%s %s%s%s ON %s) (%s)", pTrigger->zName,
      pTrigger->zName, onErrorText(orconf),
      (pTrigger->tr_tm==TRIGGER_BEFORE ? "BEFORE" : "AFTER"),
        (op==TK_UPDATE ? "UPDATE" : ""),
        (op==TK_INSERT ? "INSERT" : ""),
        (op==TK_DELETE ? "DELETE" : ""),
      pTab->zName, onErrorText(orconf)
      pTab->zName
    ));
#ifndef SQLITE_OMIT_TRACE
    sqlite3VdbeChangeP4(v, -1, 
      sqlite3MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC
    );
#endif

    if( pTrigger->pWhen ){
      /* Code the WHEN clause. If it evaluates to false (or NULL) the 
      ** sub-vdbe is immediately halted.  */
      pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0);
      if( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen) ){
        iEndTrigger = sqlite3VdbeMakeLabel(v);
        sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
      }
      sqlite3ExprDelete(db, pWhen);
    }

    /* Code the trigger program into the sub-vdbe. */
    codeTriggerProgram(pSubParse, pTrigger->step_list, OE_Default);
    codeTriggerProgram(pSubParse, pTrigger->step_list, orconf);
    if( iEndTrigger ){
      sqlite3VdbeResolveLabel(v, iEndTrigger);
    }
    sqlite3VdbeAddOp0(v, OP_Halt);
    VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf)));

    transferParseError(pParse, pSubParse);
    pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pParse->nArg);
    pProgram->nMem = pSubParse->nMem;
    pProgram->nCsr = pSubParse->nTab;
    pProgram->token = (void *)pTrigger;
    pC->oldmask = pSubParse->oldmask;
    pC->newmask = pSubParse->newmask;
957
958
959
960
961
962
963
964

965
966
967

968
969
970
971
972
973
974
972
973
974
975
976
977
978

979
980
981

982
983
984
985
986
987
988
989







-
+


-
+







      CodedTrigger *pC;
      pC = getRowTrigger(pParse, p, op, pTab, orconf);
      assert( pC || pParse->nErr || pParse->db->mallocFailed );

      /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program 
      ** is a pointer to the sub-vdbe containing the trigger program.  */
      if( pC ){
        sqlite3VdbeAddOp3(v, OP_Program, oldIdx, newIdx, ++pParse->nMem);
        sqlite3VdbeAddOp3(v, OP_Program, oldIdx, ignoreJump, ++pParse->nMem);
        pC->pProgram->nRef++;
        sqlite3VdbeChangeP4(v, -1, (const char *)pC->pProgram, P4_SUBPROGRAM);
        VdbeComment((v, "Call trigger: %s (%s)", p->zName,onErrorText(orconf)));
        VdbeComment((v, "Call: %s.%s", p->zName, onErrorText(orconf)));
      }
    }
  }
}

void sqlite3TriggerUses(
  Parse *pParse,       /* Parse context */
Changes to src/update.c.
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
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







+















-
+







  /* Register Allocations */
  int regRowCount = 0;   /* A count of rows changed */
  int regOldRowid;       /* The old rowid */
  int regNewRowid;       /* The new rowid */
  int regNew;
  int regOld;
  int regRowSet = 0;     /* Rowset of rows to be updated */
  int regRec;            /* Register used for new table record to insert */

  memset(&sContext, 0, sizeof(sContext));
  db = pParse->db;
  if( pParse->nErr || db->mallocFailed ){
    goto update_cleanup;
  }
  assert( pTabList->nSrc==1 );

  /* Locate the table which we want to update. 
  */
  pTab = sqlite3SrcListLookup(pParse, pTabList);
  if( pTab==0 ) goto update_cleanup;
  iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);

  /* Figure out if we have any triggers and if the table being
  ** updated is a view
  ** updated is a view.
  */
#ifndef SQLITE_OMIT_TRIGGER
  pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, 0);
  isView = pTab->pSelect!=0;
#else
# define pTrigger 0
# define isView 0
278
279
280
281
282
283
284

285
286
287
288
289
290
291
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293







+







    pParse->nMem += pTab->nCol;
  }
  if( chngRowid || pTrigger ){
    regNewRowid = ++pParse->nMem;
  }
  regNew = pParse->nMem + 1;
  pParse->nMem += pTab->nCol;
  regRec = ++pParse->nMem;

  /* Start the view context. */
  if( isView ){
    sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
  }

  /* If there are any triggers, set old_col_mask and new_col_mask. */
416
417
418
419
420
421
422













423
424
425
426
427

428
429
430
431
432
433

434
435
436
437
438
439
440
441
442
443
444
445
446















447
448
449
450
451
452
453
454
455
456

457
458
459
460
461
462
463
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441

442
443
444
445
446
447

448
449
450
451
452
453
454
455
456
457
458
459


460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491







+
+
+
+
+
+
+
+
+
+
+
+
+




-
+





-
+











-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+









-
+







        sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew+i);
        sqlite3ColumnDefault(v, pTab, i, regNew+i);
      }else{
        sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
      }
    }
  }

  /* If this is not a view, create the record that will be inserted into
  ** the table (assuming no constraint checks fail). A side effect of
  ** creating the record is applying affinity transformations to the
  ** array of registers populated by the block above. This needs to be
  ** done before the BEFORE triggers are fired.  */
#if 0
  if( !isView ){
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regNew, pTab->nCol, regRec);
    sqlite3TableAffinityStr(v, pTab);
    sqlite3ExprCacheAffinityChange(pParse, regNew, pTab->nCol);
  }
#endif

  /* Fire any BEFORE UPDATE triggers. This happens before constraints are
  ** verified. One could argue that this is wrong.  */
  sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, 
      TRIGGER_BEFORE, pTab, regNew, regOld, onError, addr);
      TRIGGER_BEFORE, pTab, -1, regOldRowid, onError, addr);

  if( !isView ){

    /* Do constraint checks. */
    sqlite3GenerateConstraintChecks(pParse, pTab, iCur, regNewRowid,
        aRegIdx, chngRowid, 1, onError, addr, 0);
        aRegIdx, (chngRowid?regOldRowid:0), 1, onError, addr, 0);

    /* Delete the index entries associated with the current record.  */
    j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regOldRowid);
    sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx);
  
    /* If changing the record number, delete the old record.  */
    if( chngRowid ){
      sqlite3VdbeAddOp2(v, OP_Delete, iCur, 0);
    }
    sqlite3VdbeJumpHere(v, j1);
  
    /* Create the new index entries and the new record.  */
    sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid, aRegIdx,1,-1,0,0);
    /* Insert the new index entries and the new record. */
    sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid, aRegIdx, 1, -1, 0, 0);

#if 0
    for(i=0; i<nIdx; i++){
      if( aRegIdx[i] ){
        sqlite3VdbeAddOp2(v, OP_IdxInsert, iCur+1+i, aRegIdx[i]);
      }
    }
    sqlite3VdbeAddOp3(v, OP_Insert, iCur, regRec, regNewRowid);
    if( !pParse->nested ){
      sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);
      sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_ISUPDATE);
    }
#endif
  }

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

  sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, 
      TRIGGER_AFTER, pTab, regNew, regOld, onError, addr);
      TRIGGER_AFTER, pTab, -1, regOldRowid, onError, addr);

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

Changes to src/vdbe.c.
848
849
850
851
852
853
854

855
856
857
858
859
860
861
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862







+







case OP_Halt: {
  if( pOp->p1==SQLITE_OK && p->pFrame ){
    VdbeFrame *pFrame = p->pFrame;
    p->pFrame = pFrame->pParent;
    p->nFrame--;
    pc = sqlite3VdbeFrameRestore(pFrame);
    if( pOp->p2==OE_Ignore ){
      pc = p->aOp[pc].p2-1;
    }
    break;
  }
  p->rc = pOp->p1;
  p->errorAction = (u8)pOp->p2;
  p->pc = pc;
  if( pOp->p4.z ){
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553





3554
3555
3556
3557
3558
3559
3560
3561

3562
3563
3564
3565
3566
3567
3568
3543
3544
3545
3546
3547
3548
3549





3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570







-
-
-
-
-
+
+
+
+
+








+







/* Opcode: NewRowid P1 P2 P3 * *
**
** Get a new integer record number (a.k.a "rowid") used as the key to a table.
** The record number is not previously used as a key in the database
** table that cursor P1 points to.  The new record number is written
** written to register P2.
**
** If P3>0 then P3 is a register that holds the largest previously
** generated record number.  No new record numbers are allowed to be less
** than this value.  When this value reaches its maximum, a SQLITE_FULL
** error is generated.  The P3 register is updated with the generated
** record number.  This P3 mechanism is used to help implement the
** If P3>0 then P3 is a register in the root frame of this VDBE that holds 
** the largest previously generated record number. No new record numbers are
** allowed to be less than this value. When this value reaches its maximum, 
** a SQLITE_FULL error is generated. The P3 register is updated with the '
** generated record number. This P3 mechanism is used to help implement the
** AUTOINCREMENT feature.
*/
case OP_NewRowid: {           /* out2-prerelease */
  i64 v;                 /* The new rowid */
  VdbeCursor *pC;        /* Cursor of table to get the new rowid */
  int res;               /* Result of an sqlite3BtreeLast() */
  int cnt;               /* Counter to limit the number of searches */
  Mem *pMem;             /* Register holding largest rowid for AUTOINCREMENT */
  VdbeFrame *pFrame;     /* Root frame of VDBE */

  v = 0;
  res = 0;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  if( NEVER(pC->pCursor==0) ){
3613
3614
3615
3616
3617
3618
3619


3620
3621
3622








3623
3624
3625
3626
3627
3628
3629
3615
3616
3617
3618
3619
3620
3621
3622
3623



3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638







+
+
-
-
-
+
+
+
+
+
+
+
+







            v++;
          }
        }
      }

#ifndef SQLITE_OMIT_AUTOINCREMENT
      if( pOp->p3 ){
        if( p->pFrame ){
          for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
        assert( pOp->p3>0 && pOp->p3<=p->nMem ); /* P3 is a valid memory cell */
        pMem = &p->aMem[pOp->p3];
	REGISTER_TRACE(pOp->p3, pMem);
          pMem = &pFrame->aMem[pOp->p3];
        }else{
          pMem = &p->aMem[pOp->p3];
        }
        /* Assert that P3 is a valid memory cell. */
        assert( pOp->p3>0 && pOp->p3<=(p->pFrame ? pFrame->nMem : p->nMem) );

        REGISTER_TRACE(pOp->p3, pMem);
        sqlite3VdbeMemIntegerify(pMem);
        assert( (pMem->flags & MEM_Int)!=0 );  /* mem(P3) holds an integer */
        if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){
          rc = SQLITE_FULL;
          goto abort_due_to_error;
        }
        if( v<pMem->u.i+1 ){
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768

4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782

4783
4784
4785
4786
4787




4788
4789
4790
4791
4792


4793
4794
4795
4796
4797

4798
4799
4800
4801
4802
4803
4804



4805
4806
4807
4808
4809
4810
4811
4812
4813

4814
4815
4816
4817
4818
4819
4820
4745
4746
4747
4748
4749
4750
4751









4752
















4753
4754













4755

4756



4757
4758
4759
4760





4761
4762

4763
4764
4765

4766
4767
4768
4769
4770
4771


4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782

4783
4784
4785
4786
4787
4788
4789
4790







-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
+
-

-
-
-
+
+
+
+
-
-
-
-
-
+
+
-



-
+





-
-
+
+
+








-
+







    sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
  }
  break;
}


#ifndef SQLITE_OMIT_TRIGGER
/* Opcode: ContextPush * * * 
**
** Save the current Vdbe context such that it can be restored by a ContextPop
** opcode. The context stores the last insert row id, the last statement change
** count, and the current statement change count.
*/
case OP_ContextPush: {
  int i;
  Context *pContext;

  i = p->contextStackTop++;
  assert( i>=0 );
  /* FIX ME: This should be allocated as part of the vdbe at compile-time */
  if( i>=p->contextStackDepth ){
    p->contextStackDepth = i+1;
    p->contextStack = sqlite3DbReallocOrFree(db, p->contextStack,
                                          sizeof(Context)*(i+1));
    if( p->contextStack==0 ) goto no_mem;
  }
  pContext = &p->contextStack[i];
  pContext->lastRowid = db->lastRowid;
  pContext->nChange = p->nChange;
  break;
}

/* Opcode: ContextPop * * * 
/* Opcode: Program P1 P2 P3 P4 *
**
** Restore the Vdbe context to the state it was in when contextPush was last
** executed. The context stores the last insert row id, the last statement
** change count, and the current statement change count.
*/
case OP_ContextPop: {
  Context *pContext;
  pContext = &p->contextStack[--p->contextStackTop];
  assert( p->contextStackTop>=0 );
  db->lastRowid = pContext->lastRowid;
  p->nChange = pContext->nChange;
  break;
}

** Execute the trigger program passed as P4 (type P4_SUBPROGRAM). 
/* Opcode: Program P1 P2 P3 P4 *
**
** Execute a trigger program. P1 contains the address of the memory cell
** that contains the left-most column of the old.* table (unless the trigger
** program is firing as a result of an INSERT statement). P2 is the address 
** P1 contains the address of the memory cell that contains the first memory 
** cell in an array of values used as arguments to the sub-program. P2 
** contains the address to jump to if the sub-program throws an IGNORE 
** exception using the RAISE() function. Register P3 contains the address 
** of the corresponding column in the new.* table (unless the trigger 
** program is being fired due to a DELETE).
**
** Register P3 contains the address of a memory cell in this (the parent)
** VM that is used to allocate the memory required by the sub-vdbe at 
** of a memory cell in this (the parent) VM that is used to allocate the 
** memory required by the sub-vdbe at runtime.
** runtime.
**
** P4 is a pointer to the VM containing the trigger program.
*/
case OP_Program: {
case OP_Program: {        /* jump */
  VdbeFrame *pFrame;
  SubProgram *pProgram = pOp->p4.pProgram;
  Mem *pRt = &p->aMem[pOp->p3];        /* Register to allocate runtime space */
  assert( pProgram->nOp>0 );
  
  /* If noRecTrigger is true, then recursive invocation of triggers is
  ** disabled for backwards compatibility. 
  /* If the SQLITE_NoRecTriggers flag it set, then recursive invocation of
  ** triggers is disabled for backwards compatibility (flag set/cleared by
  ** the "PRAGMA disable_recursive_triggers" command). 
  ** 
  ** It is recursive invocation of triggers, at the SQL level, that is 
  ** disabled. In some cases a single trigger may generate more than one 
  ** SubProgram (if the trigger may be executed with more than one different 
  ** ON CONFLICT algorithm). SubProgram structures associated with a
  ** single trigger all have the same value for the SubProgram.token 
  ** variable.
  */
  if( 1 || p->noRecTrigger ){
  if( db->flags&SQLITE_NoRecTriggers ){
    void *t = pProgram->token;
    for(pFrame=p->pFrame; pFrame && pFrame->token!=t; pFrame=pFrame->pParent);
    if( pFrame ) break;
  }

  /* TODO: This constant should be configurable. */
  if( p->nFrame>1000 ){
4870
4871
4872
4873
4874
4875
4876


4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889

4890

4891
4892
4893




4894
4895
4896
4897

4898
4899
4900
4901


4902
4903
4904
4905



4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917


4918
4919


4920
4921
4922
4923
4924









4925
4926
4927
4928
4929
4930
4931
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860

4861
4862
4863



4864
4865
4866
4867
4868



4869




4870
4871
4872



4873
4874
4875



4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886


4887
4888
4889
4890
4891
4892

4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908







+
+












-
+

+
-
-
-
+
+
+
+

-
-
-
+
-
-
-
-
+
+

-
-
-
+
+
+
-
-
-









+
+
-
-
+
+




-
+
+
+
+
+
+
+
+
+







    assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem );
    assert( pProgram->nCsr==pFrame->nChildCsr );
    assert( pc==pFrame->pc );
  }

  p->nFrame++;
  pFrame->pParent = p->pFrame;
  pFrame->lastRowid = db->lastRowid;
  pFrame->nChange = p->nChange;
  p->pFrame = pFrame;
  p->aMem = &VdbeFrameMem(pFrame)[-1];
  p->nMem = pFrame->nChildMem;
  p->nCursor = pFrame->nChildCsr;
  p->apCsr = (VdbeCursor **)&p->aMem[p->nMem+1];
  p->aOp = pProgram->aOp;
  p->nOp = pProgram->nOp;
  pc = -1;

  break;
}

/* Opcode: TriggerVal P1 P2 P3 * *
/* Opcode: Param P1 P2 * * *
**
** This opcode is only ever present in sub-programs called via the 
** Copy a value currently stored in a memory cell of the parent VM to
** a cell in this VMs address space. This is used by trigger programs
** to access the new.* and old.* values.
** OP_Program instruction. Copy a value currently stored in a memory 
** cell of the calling (parent) frame to cell P2 in the current frames 
** address space. This is used by trigger programs to access the new.* 
** and old.* values.
**
** If parameter P3 is non-zero, then the value read is from the new.*
** table. If P3 is zero, then the value is read from the old.* table.
** Parameter P1 is the index of the required new.* or old.* column (or
** The address of the cell in the parent frame is determined by adding
** -1 for rowid). 
**
** Parameter P2 is the index of the memory cell in this VM to copy the 
** value to.
** the value of the P1 argument to the value of the P1 argument to the
** calling OP_Program instruction.
*/
case OP_TriggerVal: {           /* out2-prerelease */
  VdbeFrame *pF = p->pFrame;
  Mem *pIn;
case OP_Param: {           /* out2-prerelease */
  VdbeFrame *pFrame = p->pFrame;
  Mem *pIn = &pFrame->aMem[pOp->p1 + pFrame->aOp[pFrame->pc].p1];   
  int iFrom = pOp->p1;           /* Memory cell in parent frame */
  iFrom += (pOp->p3 ? pF->aOp[pF->pc].p2 : pF->aOp[pF->pc].p1);
  pIn = &pF->aMem[iFrom];
  sqlite3VdbeMemShallowCopy(pOut, pIn, MEM_Ephem);
  break;
}

#endif /* #ifndef SQLITE_OMIT_TRIGGER */

#ifndef SQLITE_OMIT_AUTOINCREMENT
/* Opcode: MemMax P1 P2 * * *
**
** P1 is a register in the root frame of this VM (the root frame is
** different from the current frame if this instruction is being executed
** Set the value of register P1 to the maximum of its current value
** and the value in register P2.
** within a sub-program). Set the value of register P1 to the maximum of 
** its current value and the value in register P2.
**
** This instruction throws an error if the memory cell is not initially
** an integer.
*/
case OP_MemMax: {        /* in1, in2 */
case OP_MemMax: {        /* in2 */
  Mem *pIn1;
  VdbeFrame *pFrame;
  if( p->pFrame ){
    for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
    pIn1 = &pFrame->aMem[pOp->p1];
  }else{
    pIn1 = &p->aMem[pOp->p1];
  }
  sqlite3VdbeMemIntegerify(pIn1);
  sqlite3VdbeMemIntegerify(pIn2);
  if( pIn1->u.i<pIn2->u.i){
    pIn1->u.i = pIn2->u.i;
  }
  break;
}
Changes to src/vdbeInt.h.
99
100
101
102
103
104
105


106
107
108
109
110
111
112
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114







+
+







  int nMem;               /* Number of entries in aMem */
  VdbeCursor **apCsr;     /* Element of Vdbe cursors */
  u16 nCursor;            /* Number of entries in apCsr */
  VdbeFrame *pParent;     /* Parent of this frame */
  void *token;            /* Copy of SubProgram.token */
  int nChildMem;          /* Number of memory cells for child frame */
  int nChildCsr;          /* Number of cursors for child frame */
  i64 lastRowid;    /* Last insert rowid (sqlite3.lastRowid) */
  int nChange;      /* Statement changes (Vdbe.nChanges)     */
};

#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])

/*
** A value for VdbeCursor.cacheValid that means the cache is always invalid.
*/
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
241
242
243
244
245
246
247















248
249
250
251
252
253
254







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







*/
typedef struct Set Set;
struct Set {
  Hash hash;             /* A set is just a hash table */
  HashElem *prev;        /* Previously accessed hash elemen */
};

/*
** A Context stores the last insert rowid, the last statement change count,
** and the current statement change count (i.e. changes since last statement).
** The current keylist is also stored in the context.
** Elements of Context structure type make up the ContextStack, which is
** updated by the ContextPush and ContextPop opcodes (used by triggers).
** The context is pushed before executing a trigger a popped when the
** trigger finishes.
*/
typedef struct Context Context;
struct Context {
  i64 lastRowid;    /* Last insert rowid (sqlite3.lastRowid) */
  int nChange;      /* Statement changes (Vdbe.nChanges)     */
};

/*
** An instance of the virtual machine.  This structure contains the complete
** state of the virtual machine.
**
** The "sqlite3_stmt" structure pointer that is returned by sqlite3_compile()
** is really a pointer to an instance of this structure.
**
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
280
281
282
283
284
285
286



287
288
289
290
291
292
293







-
-
-







  u16 nVar;               /* Number of entries in aVar[] */
  Mem *aVar;              /* Values for the OP_Variable opcode. */
  char **azVar;           /* Name of variables */
  u32 magic;              /* Magic number for sanity checking */
  int nMem;               /* Number of memory locations currently allocated */
  Mem *aMem;              /* The memory locations */
  int cacheCtr;           /* VdbeCursor row cache generation counter */
  int contextStackTop;    /* Index of top element in the context stack */
  int contextStackDepth;  /* The size of the "context" stack */
  Context *contextStack;  /* Stack used by opcodes ContextPush & ContextPop*/
  int pc;                 /* The program counter */
  int rc;                 /* Value to return */
  char *zErrMsg;          /* Error message written here */
  u8 explain;             /* True if EXPLAIN present on SQL command */
  u8 changeCntOn;         /* True to update the change-counter */
  u8 expired;             /* True if the VM needs to be recompiled */
  u8 minWriteFileFormat;  /* Minimum file format for writable database files */
Changes to src/vdbeaux.c.
291
292
293
294
295
296
297
298

299
300
301
302
303
304
305
291
292
293
294
295
296
297

298
299
300
301
302
303
304
305







-
+







      hasStatementBegin = 1;
      p->usesStmtJournal = 1;
    }else if( opcode==OP_Destroy ){
      doesStatementRollback = 1;
    }else if( opcode==OP_Transaction && pOp->p2!=0 ){
      p->readOnly = 0;
#ifndef SQLITE_OMIT_VIRTUALTABLE
    }else if( opcode==OP_VUpdate || opcode==OP_VRename ){
    }else if( opcode==OP_VUpdate || opcode==OP_VRename || opcode==OP_Program ){
      doesStatementRollback = 1;
    }else if( opcode==OP_VFilter ){
      int n;
      assert( p->nOp - i >= 3 );
      assert( pOp[-1].opcode==OP_Integer );
      n = pOp[-1].p1;
      if( n>nMaxArgs ) nMaxArgs = n;
1332
1333
1334
1335
1336
1337
1338


1339
1340
1341
1342
1343
1344
1345
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347







+
+







  Vdbe *v = pFrame->v;
  v->aOp = pFrame->aOp;
  v->nOp = pFrame->nOp;
  v->aMem = pFrame->aMem;
  v->nMem = pFrame->nMem;
  v->apCsr = pFrame->apCsr;
  v->nCursor = pFrame->nCursor;
  v->db->lastRowid = pFrame->lastRowid;
  v->nChange = pFrame->nChange;
  return pFrame->pc;
}

/*
** Close all cursors. 
**
** Also release any dynamic memory held by the VM in the Vdbe.aMem memory 
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1385
1386
1387
1388
1389
1390
1391






1392
1393
1394
1395
1396
1397
1398







-
-
-
-
-
-







  /* Execute assert() statements to ensure that the Vdbe.apCsr[] and 
  ** Vdbe.aMem[] arrays have already been cleaned up.  */
  int i;
  for(i=0; i<p->nCursor; i++){ assert( p->apCsr[i]==0 ); }
  for(i=1; i<=p->nMem; i++){ assert( p->aMem[i].flags==MEM_Null ); }
#endif

  if( p->contextStack ){
    sqlite3DbFree(db, p->contextStack);
  }
  p->contextStack = 0;
  p->contextStackDepth = 0;
  p->contextStackTop = 0;
  sqlite3DbFree(db, p->zErrMsg);
  p->zErrMsg = 0;
  p->pResultSet = 0;
}

/*
** Set the number of result columns that will be returned by this SQL
Changes to test/autoinc.test.
553
554
555
556
557
558
559


560
561
562
563
564
565
566
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568







+
+







    INSERT INTO t2 VALUES(NULL, 1);
    CREATE TABLE t3(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
    INSERT INTO t3 SELECT * FROM t2 WHERE y>1;

    SELECT * FROM sqlite_sequence WHERE name='t3';
  }
} {t3 0}

catchsql { pragma disable_recursive_triggers = 1 } 

# Ticket #3928.  Make sure that triggers to not make extra slots in
# the SQLITE_SEQUENCE table.
#
do_test autoinc-3928.1 {
  db eval {
    CREATE TABLE t3928(a INTEGER PRIMARY KEY AUTOINCREMENT, b);
Changes to test/misc2.test.
14
15
16
17
18
19
20





21
22
23
24
25
26
27
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32







+
+
+
+
+







# left out of other test files.
#
# $Id: misc2.test,v 1.28 2007/09/12 17:01:45 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# The tests in this file were written before SQLite supported recursive
# trigger invocation, and some tests depend on that to pass. So disable
# recursive triggers for this file.
catchsql { pragma disable_recursive_triggers = 1 } 

ifcapable {trigger} {
# Test for ticket #360
#
do_test misc2-1.1 {
  catchsql {
    CREATE TABLE FOO(bar integer);
    CREATE TRIGGER foo_insert BEFORE INSERT ON foo BEGIN
354
355
356
357
358
359
360

361
362
363
364
365
366
367
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373







+







    execsql {SELECT * FROM t1}
  } {1 2 3 4 5 6 7 8 9 10}
}

db close
file delete -force test.db
sqlite3 db test.db
catchsql { pragma disable_recursive_triggers = 1 } 

# Ticket #453.  If the SQL ended with "-", the tokenizer was calling that
# an incomplete token, which caused problem.  The solution was to just call
# it a minus sign.
#
do_test misc2-8.1 {
  catchsql {-}
Changes to test/tkt3731.test.
13
14
15
16
17
18
19





20
21
22
23
24
25
26
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31







+
+
+
+
+








set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable {!trigger} {
  finish_test
  return
}

# The tests in this file were written before SQLite supported recursive
# trigger invocation, and some tests depend on that to pass. So disable
# recursive triggers for this file.
catchsql { pragma disable_recursive_triggers = 1 } 

do_test tkt3731-1.1 {
  execsql {
    CREATE TABLE t1(a PRIMARY KEY, b);
    CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
      INSERT INTO t1 VALUES(new.a || '+', new.b || '+');
    END;
Changes to test/tkt3992.test.
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39
40


41

42

43
44
45
46
47
48
49
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54







+









+
+

+

+







    CREATE TABLE parameters2(
       mountcnt    INT NOT NULL CHECK (typeof(mountcnt) == 'integer'),
       version     REAL CHECK (typeof(version) == 'real')
    );
    INSERT INTO parameters2(mountcnt, version) VALUES(1, 1.0);
  }
} {}
puts [execsql { SELECT *,typeof(mountcnt),typeof(version) FROM parameters1 }]

do_test tkt3992-1.2 {
  execsql {
    UPDATE parameters1 SET mountcnt = mountcnt + 1;
    SELECT * FROM parameters1;
  }
} {2 1.0}

do_test tkt3992-1.3 {
    explain { UPDATE parameters2 SET mountcnt = mountcnt + 1 }
breakpoint
  execsql {
  pragma vdbe_trace = 1;
    UPDATE parameters2 SET mountcnt = mountcnt + 1;
  pragma vdbe_trace = 0;
    SELECT * FROM parameters2;
  }
} {2 1.0}

do_test tkt3992-2.1 {
  execsql {
    CREATE TABLE t1(a, b);
68
69
70
71
72
73
74
75
76
77
78
79
80
73
74
75
76
77
78
79



80
81
82







-
-
-



      SELECT tcl('set res', typeof(new.c));
    END;

    UPDATE t2 SET a = 'I';
  }
  set res
} {real}
explain {
    UPDATE t2 SET a = 'I';
}


finish_test
Changes to test/trigger2.test.
49
50
51
52
53
54
55





56
57
58
59
60
61
62
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67







+
+
+
+
+








set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable {!trigger} {
  finish_test
  return
}

# The tests in this file were written before SQLite supported recursive
# trigger invocation, and some tests depend on that to pass. So disable
# recursive triggers for this file.
catchsql { pragma disable_recursive_triggers = 1 } 

# 1.
ifcapable subquery {
  set ii 0
  set tbl_definitions [list \
  	{CREATE TABLE tbl (a, b);}                                      \
  	{CREATE TABLE tbl (a INTEGER PRIMARY KEY, b);}                  \
Changes to test/trigger3.test.
13
14
15
16
17
18
19
20





21
22
23
24


25
26
27
28
29
30
31
13
14
15
16
17
18
19
20
21
22
23
24
25
26



27
28
29
30
31
32
33
34
35








+
+
+
+
+

-
-
-
+
+








set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable {!trigger} {
  finish_test
  return
}

# The tests in this file were written before SQLite supported recursive }
# trigger invocation, and some tests depend on that to pass. So disable
# recursive triggers for this file.
catchsql { pragma disable_recursive_triggers = 1 } 

# Test that we can cause ROLLBACK, FAIL and ABORT correctly
# catchsql { DROP TABLE tbl; }
catchsql { CREATE TABLE tbl (a, b, c) }

#
catchsql { CREATE TABLE tbl(a, b ,c) }
execsql {
    CREATE TRIGGER before_tbl_insert BEFORE INSERT ON tbl BEGIN SELECT CASE 
	WHEN (new.a = 4) THEN RAISE(IGNORE) END;
    END;

    CREATE TRIGGER after_tbl_insert AFTER INSERT ON tbl BEGIN SELECT CASE 
	WHEN (new.a = 1) THEN RAISE(ABORT,    'Trigger abort') 
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68







-
+







do_test trigger3-1.3 {
    execsql {SELECT * FROM tbl}
} {}

# FAIL
do_test trigger3-2.1 {
    catchsql {
	BEGIN;
        BEGIN;
        INSERT INTO tbl VALUES (5, 5, 6);
        INSERT INTO tbl VALUES (2, 5, 6);
    }
} {1 {Trigger fail}}
do_test trigger3-2.2 {
    execsql {
	SELECT * FROM tbl;
Changes to test/trigger9.test.
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
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







-
+














-
+







      END;
      DELETE FROM t1;
      SELECT * FROM t2;
  }
} {1 2 3}
do_test trigger9-1.3.2 {
  has_rowdata {DELETE FROM t1}
} 1
} 0
do_test trigger9-1.3.3 { execsql { ROLLBACK } } {}

do_test trigger9-1.4.1 {
  execsql {
    BEGIN;
      CREATE TRIGGER trig1 BEFORE DELETE ON t1 WHEN old.x='1' BEGIN
        INSERT INTO t2 VALUES(old.rowid);
      END;
      DELETE FROM t1;
      SELECT * FROM t2;
  }
} {1}
do_test trigger9-1.4.2 {
  has_rowdata {DELETE FROM t1}
} 1
} 0
do_test trigger9-1.4.3 { execsql { ROLLBACK } } {}

do_test trigger9-1.5.1 {
  execsql {
    BEGIN;
      CREATE TRIGGER trig1 BEFORE UPDATE ON t1 BEGIN
        INSERT INTO t2 VALUES(old.rowid);
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
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







-
+














-
+







      END;
      UPDATE t1 SET y = '';
      SELECT * FROM t2;
  }
} {1 2 3}
do_test trigger9-1.6.2 {
  has_rowdata {UPDATE t1 SET y = ''}
} 1
} 0
do_test trigger9-1.6.3 { execsql { ROLLBACK } } {}

do_test trigger9-1.7.1 {
  execsql {
    BEGIN;
      CREATE TRIGGER trig1 BEFORE UPDATE ON t1 WHEN old.x>='2' BEGIN
        INSERT INTO t2 VALUES(old.x);
      END;
      UPDATE t1 SET y = '';
      SELECT * FROM t2;
  }
} {2 3}
do_test trigger9-1.7.2 {
  has_rowdata {UPDATE t1 SET y = ''}
} 1
} 0
do_test trigger9-1.7.3 { execsql { ROLLBACK } } {}

do_test trigger9-3.1 {
  execsql {
    CREATE TABLE t3(a, b);
    INSERT INTO t3 VALUES(1, 'one');
    INSERT INTO t3 VALUES(2, 'two');