/ Check-in [85d9f23b]
Login

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

Overview
Comment:More fixes for test cases.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 85d9f23be1e8673dbda42e43b9b23332ada9225f
User & Date: dan 2009-08-31 15:27:28
Context
2009-09-01
12:16
More fixes and comment updates. check-in: 38a9327b user: dan tags: trunk
2009-08-31
15:27
More fixes for test cases. check-in: 85d9f23b user: dan tags: trunk
08:22
Fix some authorization callback problems. check-in: 8a746fbf user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/delete.c.

387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406

    addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid);

    /* If there are triggers, populate an array of registers with the
    ** data required by the old.* references in the trigger bodies.  */
    if( pTrigger ){
      u32 mask = 0;         /* Mask of OLD.* columns in use */
      u32 dummy = 0;        /* Unused. Initialized to prevent valgrind error. */
      pParse->nMem += pTab->nCol;

      /* Open the pseudo-table used to store OLD if there are triggers. */
      sqlite3TriggerUses(
          pParse, pTrigger, TK_DELETE, 0, pTab, OE_Default, &mask, &dummy);

      /* If the record is no longer present in the table, jump to the
      ** next iteration of the loop through the contents of the fifo.
      */
      sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid);

      /* Populate the OLD.* pseudo-table */







<



|
|







387
388
389
390
391
392
393

394
395
396
397
398
399
400
401
402
403
404
405

    addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid);

    /* If there are triggers, populate an array of registers with the
    ** data required by the old.* references in the trigger bodies.  */
    if( pTrigger ){
      u32 mask = 0;         /* Mask of OLD.* columns in use */

      pParse->nMem += pTab->nCol;

      /* Open the pseudo-table used to store OLD if there are triggers. */
      mask = sqlite3TriggerOldmask(
          pParse, pTrigger, TK_DELETE, 0, pTab, OE_Default);

      /* If the record is no longer present in the table, jump to the
      ** next iteration of the loop through the contents of the fifo.
      */
      sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid);

      /* Populate the OLD.* pseudo-table */

Changes to src/expr.c.

2555
2556
2557
2558
2559
2560
2561

2562
2563
2564
2565
2566
2567
2568





2569
2570
2571
2572
2573
2574
2575
    }
    case TK_UPLUS: {
      inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
      break;
    }

    case TK_TRIGGER: {

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





      break;
    }


    /*
    ** Form A:
    **   CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END







>
|






>
>
>
>
>







2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
    }
    case TK_UPLUS: {
      inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
      break;
    }

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


    /*
    ** Form A:
    **   CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END

Changes to src/insert.c.

975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
....
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
#endif
    {
      int isReplace;    /* Set to true if constraints may cause a replace */
      sqlite3GenerateConstraintChecks(pParse, pTab, baseCur, regIns, aRegIdx,
          keyColumn>=0, 0, onError, endOfLoop, &isReplace
      );
      sqlite3CompleteInsertion(
          pParse, pTab, baseCur, regIns, aRegIdx, 0,
          (tmask&TRIGGER_AFTER) ? newIdx : -1, appendFlag, isReplace==0
      );
    }
  }

  /* Update the count of rows that are inserted
  */
  if( (db->flags & SQLITE_CountRows)!=0 ){
................................................................................
void sqlite3CompleteInsertion(
  Parse *pParse,      /* The parser context */
  Table *pTab,        /* the table into which we are inserting */
  int baseCur,        /* Index of a read/write cursor pointing at pTab */
  int regRowid,       /* Range of content */
  int *aRegIdx,       /* Register used by each index.  0 for unused indices */
  int isUpdate,       /* True for UPDATE, False for INSERT */
  int newIdx,         /* Index of NEW table for triggers.  -1 if none */
  int appendBias,     /* True if this is likely to be an append */
  int useSeekResult   /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */
){
  int i;
  Vdbe *v;
  int nIdx;
  Index *pIdx;







|
<







 







<







975
976
977
978
979
980
981
982

983
984
985
986
987
988
989
....
1371
1372
1373
1374
1375
1376
1377

1378
1379
1380
1381
1382
1383
1384
#endif
    {
      int isReplace;    /* Set to true if constraints may cause a replace */
      sqlite3GenerateConstraintChecks(pParse, pTab, baseCur, regIns, aRegIdx,
          keyColumn>=0, 0, onError, endOfLoop, &isReplace
      );
      sqlite3CompleteInsertion(
          pParse, pTab, baseCur, regIns, aRegIdx, 0, appendFlag, isReplace==0

      );
    }
  }

  /* Update the count of rows that are inserted
  */
  if( (db->flags & SQLITE_CountRows)!=0 ){
................................................................................
void sqlite3CompleteInsertion(
  Parse *pParse,      /* The parser context */
  Table *pTab,        /* the table into which we are inserting */
  int baseCur,        /* Index of a read/write cursor pointing at pTab */
  int regRowid,       /* Range of content */
  int *aRegIdx,       /* Register used by each index.  0 for unused indices */
  int isUpdate,       /* True for UPDATE, False for INSERT */

  int appendBias,     /* True if this is likely to be an append */
  int useSeekResult   /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */
){
  int i;
  Vdbe *v;
  int nIdx;
  Index *pIdx;

Changes to src/prepare.c.

672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
  if( zErrMsg ){
    sqlite3Error(db, rc, "%s", zErrMsg);
    sqlite3DbFree(db, zErrMsg);
  }else{
    sqlite3Error(db, rc, 0);
  }

  while( pParse->pCodedTrigger ){
    CodedTrigger *pT = pParse->pCodedTrigger;
    pParse->pCodedTrigger = pT->pNext;
    sqlite3VdbeProgramDelete(db, pT->pProgram, 0);
    sqlite3DbFree(db, pT);
  }

end_prepare:

  sqlite3StackFree(db, pParse);







|
|
|







672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
  if( zErrMsg ){
    sqlite3Error(db, rc, "%s", zErrMsg);
    sqlite3DbFree(db, zErrMsg);
  }else{
    sqlite3Error(db, rc, 0);
  }

  while( pParse->pTriggerPrg ){
    TriggerPrg *pT = pParse->pTriggerPrg;
    pParse->pTriggerPrg = pT->pNext;
    sqlite3VdbeProgramDelete(db, pT->pProgram, 0);
    sqlite3DbFree(db, pT);
  }

end_prepare:

  sqlite3StackFree(db, pParse);

Changes to src/resolve.c.

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

#ifndef SQLITE_OMIT_TRIGGER
    /* If we have not already resolved the name, then maybe 
    ** it is a new.* or old.* trigger argument reference
    */
    if( zDb==0 && zTab!=0 && cnt==0 && pParse->pTriggerTab!=0 ){
      Table *pTab = 0;
      u32 *piColMask = 0;
      if( pParse->triggerOp!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){
        pExpr->iTable = 1;
        pTab = pParse->pTriggerTab;
        piColMask = &(pParse->newmask);
      }else if( pParse->triggerOp!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){
        pExpr->iTable = 0;
        pTab = pParse->pTriggerTab;
        piColMask = &(pParse->oldmask);
      }

      if( pTab ){ 
        int iCol;
        pSchema = pTab->pSchema;
        cntTab++;
        if( sqlite3IsRowid(zCol) ){
          iCol = -1;
        }else{
          for(iCol=0; iCol<pTab->nCol; iCol++){
            Column *pCol = &pTab->aCol[iCol];
            if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
              testcase( iCol==31 );
              testcase( iCol==32 );
              if( iCol>=32 ){
                *piColMask = 0xffffffff;
              }else{
                *piColMask |= ((u32)1)<<iCol;
              }
              if( iCol==pTab->iPKey ){
                iCol = -1;
              }
              break;
            }
          }
        }
        if( iCol<pTab->nCol ){
          cnt++;
          if( iCol<0 ){
            pExpr->affinity = SQLITE_AFF_INTEGER;




          }
          pExpr->iColumn = iCol;
          pExpr->pTab = pTab;
          isTrigger = 1;
        }
      }
    }







<



<



<












<
<
<
<
<
<
<











>
>
>
>







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

#ifndef SQLITE_OMIT_TRIGGER
    /* If we have not already resolved the name, then maybe 
    ** it is a new.* or old.* trigger argument reference
    */
    if( zDb==0 && zTab!=0 && cnt==0 && pParse->pTriggerTab!=0 ){
      Table *pTab = 0;

      if( pParse->triggerOp!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){
        pExpr->iTable = 1;
        pTab = pParse->pTriggerTab;

      }else if( pParse->triggerOp!=TK_INSERT && sqlite3StrICmp("old",zTab)==0 ){
        pExpr->iTable = 0;
        pTab = pParse->pTriggerTab;

      }

      if( pTab ){ 
        int iCol;
        pSchema = pTab->pSchema;
        cntTab++;
        if( sqlite3IsRowid(zCol) ){
          iCol = -1;
        }else{
          for(iCol=0; iCol<pTab->nCol; iCol++){
            Column *pCol = &pTab->aCol[iCol];
            if( sqlite3StrICmp(pCol->zName, zCol)==0 ){







              if( iCol==pTab->iPKey ){
                iCol = -1;
              }
              break;
            }
          }
        }
        if( iCol<pTab->nCol ){
          cnt++;
          if( iCol<0 ){
            pExpr->affinity = SQLITE_AFF_INTEGER;
          }else if( pExpr->iTable==0 ){
            testcase( iCol==31 );
            testcase( iCol==32 );
            pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
          }
          pExpr->iColumn = iCol;
          pExpr->pTab = pTab;
          isTrigger = 1;
        }
      }
    }

Changes to src/sqliteInt.h.

607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
....
1573
1574
1575
1576
1577
1578
1579
1580

1581
1582
1583
1584
1585
1586
1587
....
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026











2027
2028
2029
2030
2031
2032
2033
....
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
....
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
....
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
....
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
typedef struct Savepoint Savepoint;
typedef struct Select Select;
typedef struct SrcList SrcList;
typedef struct StrAccum StrAccum;
typedef struct Table Table;
typedef struct TableLock TableLock;
typedef struct Token Token;
typedef struct TriggerStack TriggerStack;
typedef struct TriggerStep TriggerStep;
typedef struct Trigger Trigger;
typedef struct UnpackedRecord UnpackedRecord;
typedef struct VTable VTable;
typedef struct Walker Walker;
typedef struct WherePlan WherePlan;
typedef struct WhereInfo WhereInfo;
................................................................................

  /* If the EP_Reduced flag is set in the Expr.flags mask, then no
  ** space is allocated for the fields below this point. An attempt to
  ** access them will result in a segfault or malfunction.
  *********************************************************************/

  int iTable;            /* TK_COLUMN: cursor number of table holding column
                         ** TK_REGISTER: register number */

  i16 iColumn;           /* TK_COLUMN: column index.  -1 for rowid */
  i16 iAgg;              /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
  i16 iRightJoinTable;   /* If EP_FromJoin, the right table of the join */
  u8 flags2;             /* Second set of flags.  EP2_... */
  u8 op2;                /* If a TK_REGISTER, the original value of Expr.op */
  AggInfo *pAggInfo;     /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
  Table *pTab;           /* Table for TK_COLUMN expressions. */
................................................................................
/*
** Size of the column cache
*/
#ifndef SQLITE_N_COLCACHE
# define SQLITE_N_COLCACHE 10
#endif

typedef struct CodedTrigger CodedTrigger;
struct CodedTrigger {
  SubProgram *pProgram;
  Trigger *pTrigger;
  u32 oldmask;            /* Mask of old.* columns accessed */
  u32 newmask;            /* Mask of new.* columns accessed */
  int orconf;             /* Default ON CONFLICT policy */
  CodedTrigger *pNext;











};

/*
** An SQL parser context.  A copy of this structure is passed through
** the parser and down into all the parser action routine in order to
** carry around information that is global to the entire parse.
**
................................................................................
  int *aAlias;         /* Register used to hold aliased result */
  u8 explain;          /* True if the EXPLAIN flag is found on the query */
  Token sNameToken;    /* Token with unqualified schema object name */
  Token sLastToken;    /* The last token parsed */
  const char *zTail;   /* All SQL text past the last semicolon parsed */
  Table *pNewTable;    /* A table being constructed by CREATE TABLE */
  Trigger *pNewTrigger;     /* Trigger under construct by a CREATE TRIGGER */
#if 0
  TriggerStack *trigStack;  /* Trigger actions being coded */
#endif
  const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
#ifndef SQLITE_OMIT_VIRTUALTABLE
  Token sArg;                /* Complete text of a module argument */
  u8 declareVtab;            /* True if inside sqlite3_declare_vtab() */
  int nVtabLock;             /* Number of virtual tables to lock */
  Table **apVtabLock;        /* Pointer to virtual tables needing locking */
#endif
  int nHeight;            /* Expression tree height of current sub-select */
  Table *pZombieTab;      /* List of Table objects to delete after code gen */
  CodedTrigger *pCodedTrigger;    /* Linked list of coded triggers */
};

#ifdef SQLITE_OMIT_VIRTUALTABLE
  #define IN_DECLARE_VTAB 0
#else
  #define IN_DECLARE_VTAB (pParse->declareVtab)
#endif
................................................................................
  Expr *pWhere;        /* The WHERE clause for DELETE or UPDATE steps */
  ExprList *pExprList; /* SET clause for UPDATE.  VALUES clause for INSERT */
  IdList *pIdList;     /* Column names for INSERT */
  TriggerStep *pNext;  /* Next in the link-list */
  TriggerStep *pLast;  /* Last element in link-list. Valid for 1st elem only */
};

/*
 * An instance of struct TriggerStack stores information required during code
 * generation of a single trigger program. While the trigger program is being
 * coded, its associated TriggerStack instance is pointed to by the
 * "pTriggerStack" member of the Parse structure.
 *
 * The pTab member points to the table that triggers are being coded on. The 
 * newIdx member contains the index of the vdbe cursor that points at the temp
 * table that stores the new.* references. If new.* references are not valid
 * for the trigger being coded (for example an ON DELETE trigger), then newIdx
 * is set to -1. The oldIdx member is analogous to newIdx, for old.* references.
 *
 * The ON CONFLICT policy to be used for the trigger program steps is stored 
 * as the orconf member. If this is OE_Default, then the ON CONFLICT clause 
 * specified for individual triggers steps is used.
 *
 * struct TriggerStack has a "pNext" member, to allow linked lists to be
 * constructed. When coding nested triggers (triggers fired by other triggers)
 * each nested trigger stores its parent trigger's TriggerStack as the "pNext" 
 * pointer. Once the nested trigger has been coded, the pNext value is restored
 * to the pTriggerStack member of the Parse stucture and coding of the parent
 * trigger continues.
 *
 * Before a nested trigger is coded, the linked list pointed to by the 
 * pTriggerStack is scanned to ensure that the trigger is not about to be coded
 * recursively. If this condition is detected, the nested trigger is not coded.
 */
struct TriggerStack {
  Table *pTab;         /* Table that triggers are currently being coded on */
  int newIdx;          /* Index of vdbe cursor to "new" temp table */
  int oldIdx;          /* Index of vdbe cursor to "old" temp table */
  u32 newColMask;
  u32 oldColMask;
  int orconf;          /* Current orconf policy */
  int ignoreJump;      /* where to jump to for a RAISE(IGNORE) */
  Trigger *pTrigger;   /* The trigger currently being coded */
  TriggerStack *pNext; /* Next trigger down on the trigger stack */
};

/*
** The following structure contains information used by the sqliteFix...
** routines as they walk the parse tree to make database references
** explicit.  
*/
typedef struct DbFixer DbFixer;
struct DbFixer {
................................................................................
int sqlite3ExprIsInteger(Expr*, int*);
int sqlite3IsRowid(const char*);
void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int);
void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int*);
int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int);
void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
                                     int*,int,int,int,int,int*);
void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int,int,int);
int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
void sqlite3BeginWriteOperation(Parse*, int, int);
Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
IdList *sqlite3IdListDup(sqlite3*,IdList*);
Select *sqlite3SelectDup(sqlite3*,Select*,int);
................................................................................
  TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*);
  TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*,
                                        ExprList*,Select*,u8);
  TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8);
  TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*);
  void sqlite3DeleteTrigger(sqlite3*, Trigger*);
  void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
  void sqlite3TriggerUses(Parse*,Trigger*,int,ExprList*,Table*,int,u32*,u32*);
#else
# define sqlite3TriggersExist(B,C,D,E,F) 0
# define sqlite3DeleteTrigger(A,B)
# define sqlite3DropTriggerPtr(A,B)
# define sqlite3UnlinkAndDeleteTrigger(A,B,C)
# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I,J)
# define sqlite3TriggerList(X, Y) 0







|







 







|
>







 







|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<









|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|







 







|







607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
....
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
....
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
....
2120
2121
2122
2123
2124
2125
2126



2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
....
2246
2247
2248
2249
2250
2251
2252







































2253
2254
2255
2256
2257
2258
2259
....
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
....
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
typedef struct Savepoint Savepoint;
typedef struct Select Select;
typedef struct SrcList SrcList;
typedef struct StrAccum StrAccum;
typedef struct Table Table;
typedef struct TableLock TableLock;
typedef struct Token Token;
typedef struct TriggerPrg TriggerPrg;
typedef struct TriggerStep TriggerStep;
typedef struct Trigger Trigger;
typedef struct UnpackedRecord UnpackedRecord;
typedef struct VTable VTable;
typedef struct Walker Walker;
typedef struct WherePlan WherePlan;
typedef struct WhereInfo WhereInfo;
................................................................................

  /* If the EP_Reduced flag is set in the Expr.flags mask, then no
  ** space is allocated for the fields below this point. An attempt to
  ** access them will result in a segfault or malfunction.
  *********************************************************************/

  int iTable;            /* TK_COLUMN: cursor number of table holding column
                         ** TK_REGISTER: register number
                         ** TK_TRIGGER: 1 -> new, 0 -> old */
  i16 iColumn;           /* TK_COLUMN: column index.  -1 for rowid */
  i16 iAgg;              /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
  i16 iRightJoinTable;   /* If EP_FromJoin, the right table of the join */
  u8 flags2;             /* Second set of flags.  EP2_... */
  u8 op2;                /* If a TK_REGISTER, the original value of Expr.op */
  AggInfo *pAggInfo;     /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
  Table *pTab;           /* Table for TK_COLUMN expressions. */
................................................................................
/*
** Size of the column cache
*/
#ifndef SQLITE_N_COLCACHE
# define SQLITE_N_COLCACHE 10
#endif

/*
** At least one instance of the following structure is created for each 
** trigger that may be fired while parsing an INSERT, UPDATE or DELETE
** statement. All such objects are stored in the linked list headed at
** Parse.pTriggerPrg and deleted once statement compilation has been
** completed.
**
** A Vdbe sub-program that implements the body and WHEN clause of trigger
** TriggerPrg.pTrigger, assuming a default ON CONFLICT clause of
** TriggerPrg.orconf, is stored in the TriggerPrg.pProgram variable.
** The Parse.pTriggerPrg list never contains two entries with the same
** values for both pTrigger and orconf.
*/
struct TriggerPrg {
  Trigger *pTrigger;      /* Trigger this program was coded from */
  int orconf;             /* Default ON CONFLICT policy */
  SubProgram *pProgram;   /* Program implementing pTrigger/orconf */
  u32 oldmask;            /* Mask of old.* columns accessed */
  TriggerPrg *pNext;      /* Next entry in Parse.pTriggerPrg list */
};

/*
** An SQL parser context.  A copy of this structure is passed through
** the parser and down into all the parser action routine in order to
** carry around information that is global to the entire parse.
**
................................................................................
  int *aAlias;         /* Register used to hold aliased result */
  u8 explain;          /* True if the EXPLAIN flag is found on the query */
  Token sNameToken;    /* Token with unqualified schema object name */
  Token sLastToken;    /* The last token parsed */
  const char *zTail;   /* All SQL text past the last semicolon parsed */
  Table *pNewTable;    /* A table being constructed by CREATE TABLE */
  Trigger *pNewTrigger;     /* Trigger under construct by a CREATE TRIGGER */



  const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
#ifndef SQLITE_OMIT_VIRTUALTABLE
  Token sArg;                /* Complete text of a module argument */
  u8 declareVtab;            /* True if inside sqlite3_declare_vtab() */
  int nVtabLock;             /* Number of virtual tables to lock */
  Table **apVtabLock;        /* Pointer to virtual tables needing locking */
#endif
  int nHeight;            /* Expression tree height of current sub-select */
  Table *pZombieTab;      /* List of Table objects to delete after code gen */
  TriggerPrg *pTriggerPrg;    /* Linked list of coded triggers */
};

#ifdef SQLITE_OMIT_VIRTUALTABLE
  #define IN_DECLARE_VTAB 0
#else
  #define IN_DECLARE_VTAB (pParse->declareVtab)
#endif
................................................................................
  Expr *pWhere;        /* The WHERE clause for DELETE or UPDATE steps */
  ExprList *pExprList; /* SET clause for UPDATE.  VALUES clause for INSERT */
  IdList *pIdList;     /* Column names for INSERT */
  TriggerStep *pNext;  /* Next in the link-list */
  TriggerStep *pLast;  /* Last element in link-list. Valid for 1st elem only */
};








































/*
** The following structure contains information used by the sqliteFix...
** routines as they walk the parse tree to make database references
** explicit.  
*/
typedef struct DbFixer DbFixer;
struct DbFixer {
................................................................................
int sqlite3ExprIsInteger(Expr*, int*);
int sqlite3IsRowid(const char*);
void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int);
void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int*);
int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int);
void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
                                     int*,int,int,int,int,int*);
void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
void sqlite3BeginWriteOperation(Parse*, int, int);
Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
IdList *sqlite3IdListDup(sqlite3*,IdList*);
Select *sqlite3SelectDup(sqlite3*,Select*,int);
................................................................................
  TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*);
  TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*,
                                        ExprList*,Select*,u8);
  TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8);
  TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*);
  void sqlite3DeleteTrigger(sqlite3*, Trigger*);
  void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
  u32 sqlite3TriggerOldmask(Parse*,Trigger*,int,ExprList*,Table*,int);
#else
# define sqlite3TriggersExist(B,C,D,E,F) 0
# define sqlite3DeleteTrigger(A,B)
# define sqlite3DropTriggerPtr(A,B)
# define sqlite3UnlinkAndDeleteTrigger(A,B,C)
# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I,J)
# define sqlite3TriggerList(X, Y) 0

Changes to src/trigger.c.

677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
...
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
...
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
...
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
...
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
...
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987



















988
989
990
991
992
993
994
995
996
997

998
999
1000

1001
1002
1003
1004
1005
1006
1007
1008
1009
1010


1011
1012
1013
  TriggerStep * pStep = pStepList;
  Vdbe *v = pParse->pVdbe;
  sqlite3 *db = pParse->db;

  assert( pParse->pRoot );
  assert( pStep!=0 );
  assert( v!=0 );
/* sqlite3VdbeAddOp2(v, OP_ContextPush, 0, 0); */
  while( pStep ){
    /* Figure out the ON CONFLICT policy that will be used for this step
    ** of the trigger program. If the statement that caused this trigger
    ** to fire had an explicit ON CONFLICT, then use it. Otherwise, use
    ** the ON CONFLICT policy that was specified as part of the trigger
    ** step statement. Example:
    **
................................................................................
    **   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), 
          pParse->orconf
................................................................................
      }
    } 
    if( pStep->op!=TK_SELECT ){
      sqlite3VdbeAddOp1(v, OP_ResetCount, 1);
    }
    pStep = pStep->pNext;
  }
/* sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0); */

  return 0;
}

#ifdef SQLITE_DEBUG
/*
** This function is used to add VdbeComment() annotations to a VDBE
................................................................................
    pTo->zErrMsg = pFrom->zErrMsg;
    pTo->nErr = pFrom->nErr;
  }else{
    sqlite3DbFree(pFrom->db, pFrom->zErrMsg);
  }
}

static CodedTrigger *codeRowTrigger(
  Parse *pRoot,        /* Root parse context */
  Parse *pParse,       /* Current parse context */
  Trigger *pTrigger,   /* Trigger to code */
  int op,              /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
  Table *pTab,         /* The table to code triggers from */
  int orconf
){
  sqlite3 *db = pParse->db;
  CodedTrigger *pC;
  Expr *pWhen = 0;            /* Duplicate of trigger WHEN expression */
  Vdbe *v;                    /* Temporary VM */
  AuthContext sContext;       /* Auth context for sub-vdbe */
  NameContext sNC;            /* Name context for sub-vdbe */
  SubProgram *pProgram = 0;   /* Sub-vdbe for trigger program */
  Parse *pSubParse;           /* Parse context for sub-vdbe */
  int iEndTrigger = 0;        /* Label to jump to if WHEN is false */

  pC = sqlite3DbMallocZero(db, sizeof(CodedTrigger));
  if( !pC ) return 0;
  pC->pNext = pRoot->pCodedTrigger;
  pRoot->pCodedTrigger = pC;
  pC->pProgram = pProgram = sqlite3DbMallocZero(db, sizeof(SubProgram));
  if( !pProgram ) return 0;
  pProgram->nRef = 1;
  pSubParse = sqlite3StackAllocZero(db, sizeof(Parse));
  if( !pSubParse ) return 0;

  pC->pProgram = pProgram;
  pC->pTrigger = pTrigger;
  pC->orconf = orconf;

  memset(&sNC, 0, sizeof(sNC));
  sNC.pParse = pSubParse;
  pSubParse->db = db;
  pSubParse->pTriggerTab = pTab;
  pSubParse->pRoot = pRoot;
  pSubParse->zAuthContext = pTrigger->zName;
................................................................................
    transferParseError(pParse, pSubParse);
    if( db->mallocFailed==0 ){
      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;
    sqlite3VdbeDelete(v);

    while( pSubParse->pAinc ){
      AutoincInfo *p = pSubParse->pAinc;
      pSubParse->pAinc = p->pNext;
      sqlite3DbFree(db, p);
    }
  }
  sqlite3StackFree(db, pSubParse);

  return pC;
}
    
static CodedTrigger *getRowTrigger(
  Parse *pParse,
  Trigger *pTrigger,   /* Trigger to code */
  int op,              /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
  Table *pTab,         /* The table to code triggers from */
  int orconf
){
  CodedTrigger *pC;
  Parse *pRoot = pParse;

  /* It may be that this trigger has already been coded (or is in the
  ** process of being coded). If this is the case, then an entry with
  ** a matching CodedTrigger.pTrigger field will be present somewhere
  ** in the Parse.pCodedTrigger list. Search for such an entry.  */
  if( pParse->pRoot ){
    pRoot = pParse->pRoot;
  }
  for(pC=pRoot->pCodedTrigger; 
      pC && (pC->pTrigger!=pTrigger || pC->orconf!=orconf); 
      pC=pC->pNext
  );

  if( !pC ){
    pC = codeRowTrigger(pRoot, pParse, pTrigger, op, pTab, orconf);
  }

  return pC;
}

/*
** This is called to code FOR EACH ROW triggers.
**
** When the code that this function generates is executed, the following 
** must be true:
................................................................................

    /* Determine whether we should code this trigger */
    if( p->op==op 
     && p->tr_tm==tr_tm 
     && checkColumnOverlap(p->pColumns,pChanges)
    ){
      Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */
      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, ignoreJump, ++pParse->nMem);
        pC->pProgram->nRef++;
        sqlite3VdbeChangeP4(v, -1, (const char *)pC->pProgram, P4_SUBPROGRAM);
        VdbeComment((v, "Call: %s.%s", p->zName, onErrorText(orconf)));
      }
    }
  }
}




















void sqlite3TriggerUses(
  Parse *pParse,       /* Parse context */
  Trigger *pTrigger,   /* List of triggers on table pTab */
  int op,              /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
  ExprList *pChanges,  /* Changes list for any UPDATE OF triggers */
  Table *pTab,         /* The table to code triggers from */
  int orconf,          /* Default ON CONFLICT policy for trigger steps */
  u32 *piOldColMask,   /* OUT: Mask of columns used from the OLD.* table */
  u32 *piNewColMask    /* OUT: Mask of columns used from the NEW.* table */
){

  Trigger *p;
  assert(op==TK_UPDATE || op==TK_INSERT || op==TK_DELETE);


  for(p=pTrigger; p; p=p->pNext){
    if( p->op==op && checkColumnOverlap(p->pColumns,pChanges) ){
      CodedTrigger *pC;
      pC = getRowTrigger(pParse, p, op, pTab, orconf);
      if( pC ){
        *piOldColMask |= pC->oldmask;
        *piNewColMask |= pC->newmask;
      }
    }
  }


}

#endif /* !defined(SQLITE_OMIT_TRIGGER) */







<







 







<
<
<
<







 







<







 







|








|


<





|
|
|
|
|





|
|
|







 







|
<










|


|






|




|
|



|
|
|


|
|


|







 







|
|
|



|

|
|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|


|


|
<
<

>

<

>


|
|
|
|
<



>
>



677
678
679
680
681
682
683

684
685
686
687
688
689
690
...
693
694
695
696
697
698
699




700
701
702
703
704
705
706
...
734
735
736
737
738
739
740

741
742
743
744
745
746
747
...
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790

791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
...
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
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
...
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005


1006
1007
1008

1009
1010
1011
1012
1013
1014
1015
1016

1017
1018
1019
1020
1021
1022
1023
1024
  TriggerStep * pStep = pStepList;
  Vdbe *v = pParse->pVdbe;
  sqlite3 *db = pParse->db;

  assert( pParse->pRoot );
  assert( pStep!=0 );
  assert( v!=0 );

  while( pStep ){
    /* Figure out the ON CONFLICT policy that will be used for this step
    ** of the trigger program. If the statement that caused this trigger
    ** to fire had an explicit ON CONFLICT, then use it. Otherwise, use
    ** the ON CONFLICT policy that was specified as part of the trigger
    ** step statement. Example:
    **
................................................................................
    **   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;





    switch( pStep->op ){
      case TK_UPDATE: {
        sqlite3Update(pParse, 
          targetSrcList(pParse, pStep),
          sqlite3ExprListDup(db, pStep->pExprList, 0), 
          sqlite3ExprDup(db, pStep->pWhere, 0), 
          pParse->orconf
................................................................................
      }
    } 
    if( pStep->op!=TK_SELECT ){
      sqlite3VdbeAddOp1(v, OP_ResetCount, 1);
    }
    pStep = pStep->pNext;
  }


  return 0;
}

#ifdef SQLITE_DEBUG
/*
** This function is used to add VdbeComment() annotations to a VDBE
................................................................................
    pTo->zErrMsg = pFrom->zErrMsg;
    pTo->nErr = pFrom->nErr;
  }else{
    sqlite3DbFree(pFrom->db, pFrom->zErrMsg);
  }
}

static TriggerPrg *codeRowTrigger(
  Parse *pRoot,        /* Root parse context */
  Parse *pParse,       /* Current parse context */
  Trigger *pTrigger,   /* Trigger to code */
  int op,              /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
  Table *pTab,         /* The table to code triggers from */
  int orconf
){
  sqlite3 *db = pParse->db;
  TriggerPrg *pPrg;
  Expr *pWhen = 0;            /* Duplicate of trigger WHEN expression */
  Vdbe *v;                    /* Temporary VM */

  NameContext sNC;            /* Name context for sub-vdbe */
  SubProgram *pProgram = 0;   /* Sub-vdbe for trigger program */
  Parse *pSubParse;           /* Parse context for sub-vdbe */
  int iEndTrigger = 0;        /* Label to jump to if WHEN is false */

  pPrg = sqlite3DbMallocZero(db, sizeof(TriggerPrg));
  if( !pPrg ) return 0;
  pPrg->pNext = pRoot->pTriggerPrg;
  pRoot->pTriggerPrg = pPrg;
  pPrg->pProgram = pProgram = sqlite3DbMallocZero(db, sizeof(SubProgram));
  if( !pProgram ) return 0;
  pProgram->nRef = 1;
  pSubParse = sqlite3StackAllocZero(db, sizeof(Parse));
  if( !pSubParse ) return 0;

  pPrg->pProgram = pProgram;
  pPrg->pTrigger = pTrigger;
  pPrg->orconf = orconf;

  memset(&sNC, 0, sizeof(sNC));
  sNC.pParse = pSubParse;
  pSubParse->db = db;
  pSubParse->pTriggerTab = pTab;
  pSubParse->pRoot = pRoot;
  pSubParse->zAuthContext = pTrigger->zName;
................................................................................
    transferParseError(pParse, pSubParse);
    if( db->mallocFailed==0 ){
      pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pParse->nArg);
    }
    pProgram->nMem = pSubParse->nMem;
    pProgram->nCsr = pSubParse->nTab;
    pProgram->token = (void *)pTrigger;
    pPrg->oldmask = pSubParse->oldmask;

    sqlite3VdbeDelete(v);

    while( pSubParse->pAinc ){
      AutoincInfo *p = pSubParse->pAinc;
      pSubParse->pAinc = p->pNext;
      sqlite3DbFree(db, p);
    }
  }
  sqlite3StackFree(db, pSubParse);

  return pPrg;
}
    
static TriggerPrg *getRowTrigger(
  Parse *pParse,
  Trigger *pTrigger,   /* Trigger to code */
  int op,              /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
  Table *pTab,         /* The table to code triggers from */
  int orconf
){
  TriggerPrg *pPrg;
  Parse *pRoot = pParse;

  /* It may be that this trigger has already been coded (or is in the
  ** process of being coded). If this is the case, then an entry with
  ** a matching TriggerPrg.pTrigger field will be present somewhere
  ** in the Parse.pTriggerPrg list. Search for such an entry.  */
  if( pParse->pRoot ){
    pRoot = pParse->pRoot;
  }
  for(pPrg=pRoot->pTriggerPrg; 
      pPrg && (pPrg->pTrigger!=pTrigger || pPrg->orconf!=orconf); 
      pPrg=pPrg->pNext
  );

  if( !pPrg ){
    pPrg = codeRowTrigger(pRoot, pParse, pTrigger, op, pTab, orconf);
  }

  return pPrg;
}

/*
** This is called to code FOR EACH ROW triggers.
**
** When the code that this function generates is executed, the following 
** must be true:
................................................................................

    /* Determine whether we should code this trigger */
    if( p->op==op 
     && p->tr_tm==tr_tm 
     && checkColumnOverlap(p->pColumns,pChanges)
    ){
      Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */
      TriggerPrg *pPrg;
      pPrg = getRowTrigger(pParse, p, op, pTab, orconf);
      assert( pPrg || 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( pPrg ){
        sqlite3VdbeAddOp3(v, OP_Program, oldIdx, ignoreJump, ++pParse->nMem);
        pPrg->pProgram->nRef++;
        sqlite3VdbeChangeP4(v, -1, (const char *)pPrg->pProgram, P4_SUBPROGRAM);
        VdbeComment((v, "Call: %s.%s", p->zName, onErrorText(orconf)));
      }
    }
  }
}

/*
** Triggers fired by UPDATE or DELETE statements may access values stored
** in the old.* pseudo-table. This function returns a 32-bit bitmask
** indicating which columns of the old.* table actually are used by
** triggers. This information may be used by the caller to avoid having
** to load the entire old.* record into memory when executing an UPDATE
** or DELETE command.
**
** Bit 0 of the returned mask is set if the left-most column of the
** table may be accessed using an old.<col> reference. Bit 1 is set if
** the second leftmost column value is required, and so on. If there
** are more than 32 columns in the table, and at least one of the columns
** with an index greater than 32 may be accessed, 0xffffffff is returned.
**
** It is not possible to determine if the old.rowid column is accessed
** by triggers. The caller must always assume that it is.
**
** There is no equivalent function for new.* references.
*/
u32 sqlite3TriggerOldmask(
  Parse *pParse,       /* Parse context */
  Trigger *pTrigger,   /* List of triggers on table pTab */
  int op,              /* Either TK_UPDATE or TK_DELETE */
  ExprList *pChanges,  /* Changes list for any UPDATE OF triggers */
  Table *pTab,         /* The table to code triggers from */
  int orconf           /* Default ON CONFLICT policy for trigger steps */


){
  u32 mask = 0;
  Trigger *p;


  assert(op==TK_UPDATE || op==TK_DELETE);
  for(p=pTrigger; p; p=p->pNext){
    if( p->op==op && checkColumnOverlap(p->pColumns,pChanges) ){
      TriggerPrg *pPrg;
      pPrg = getRowTrigger(pParse, p, op, pTab, orconf);
      if( pPrg ){
        mask |= pPrg->oldmask;

      }
    }
  }

  return mask;
}

#endif /* !defined(SQLITE_OMIT_TRIGGER) */

Changes to src/update.c.

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
...
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
...
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
...
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
...
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
  int j1;                /* Addresses of jump instructions */
  int okOnePass;         /* True for one-pass algorithm without the FIFO */

#ifndef SQLITE_OMIT_TRIGGER
  int isView;                  /* Trying to update a view */
  Trigger *pTrigger;           /* List of triggers on pTab, if required */
#endif
  u32 old_col_mask = 0;        /* Mask of OLD.* columns in use */
  u32 new_col_mask = 0;        /* Mask of NEW.* columns in use */

  /* Register Allocations */
  int regRowCount = 0;   /* A count of rows changed */
  int regOldRowid;       /* The old rowid */
  int regNewRowid;       /* The new rowid */
  int regNew;
  int regOld;
................................................................................
  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. */
  sqlite3TriggerUses(pParse, 
      pTrigger, TK_UPDATE, pChanges, pTab, onError, &old_col_mask, &new_col_mask
  );

  /* If we are trying to update a view, realize that view into
  ** a ephemeral table.
  */
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
  if( isView ){
    sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
................................................................................
  ** for example, then jump to the next iteration of the RowSet loop.  */
  sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid);

  /* If there are triggers on this table, populate an array of registers 
  ** with the required old.* column data.  */
  if( pTrigger ){
    for(i=0; i<pTab->nCol; i++){
      if( aXRef[i]<0 || old_col_mask==0xffffffff || (old_col_mask & (1<<i)) ){
        sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regOld+i);
        sqlite3ColumnDefault(v, pTab, i, regOld+i);
      }else{
        sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+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, -1, regOldRowid, onError, addr);


  if( !isView ){

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

................................................................................
    /* If changing the record number, delete the old record.  */
    if( chngRowid ){
      sqlite3VdbeAddOp2(v, OP_Delete, iCur, 0);
    }
    sqlite3VdbeJumpHere(v, j1);
  
    /* 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);
  }







|
<







 







|
|
|
<







 







|







 







<
<
<
<
<
<
<
<
<
<
<
<
<


>
>
>
|
|
>







 







|
<
<
<
<
<
<
<
<
<
<
<
<
<







116
117
118
119
120
121
122
123

124
125
126
127
128
129
130
...
285
286
287
288
289
290
291
292
293
294

295
296
297
298
299
300
301
...
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
...
417
418
419
420
421
422
423













424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
...
443
444
445
446
447
448
449
450













451
452
453
454
455
456
457
  int j1;                /* Addresses of jump instructions */
  int okOnePass;         /* True for one-pass algorithm without the FIFO */

#ifndef SQLITE_OMIT_TRIGGER
  int isView;                  /* Trying to update a view */
  Trigger *pTrigger;           /* List of triggers on pTab, if required */
#endif
  u32 oldmask = 0;        /* Mask of OLD.* columns in use */


  /* Register Allocations */
  int regRowCount = 0;   /* A count of rows changed */
  int regOldRowid;       /* The old rowid */
  int regNewRowid;       /* The new rowid */
  int regNew;
  int regOld;
................................................................................
  regRec = ++pParse->nMem;

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

  /* If there are any triggers, set oldmask and new_col_mask. */
  oldmask = sqlite3TriggerOldmask(
      pParse, pTrigger, TK_UPDATE, pChanges, pTab, onError);


  /* If we are trying to update a view, realize that view into
  ** a ephemeral table.
  */
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
  if( isView ){
    sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
................................................................................
  ** for example, then jump to the next iteration of the RowSet loop.  */
  sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid);

  /* If there are triggers on this table, populate an array of registers 
  ** with the required old.* column data.  */
  if( pTrigger ){
    for(i=0; i<pTab->nCol; i++){
      if( aXRef[i]<0 || oldmask==0xffffffff || (oldmask & (1<<i)) ){
        sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regOld+i);
        sqlite3ColumnDefault(v, pTab, i, regOld+i);
      }else{
        sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
      }
    }
  }
................................................................................
        sqlite3ColumnDefault(v, pTab, i, regNew+i);
      }else{
        sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
      }
    }
  }














  /* Fire any BEFORE UPDATE triggers. This happens before constraints are
  ** verified. One could argue that this is wrong.  */
  if( pTrigger ){
    sqlite3VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol);
    sqlite3TableAffinityStr(v, pTab);
    sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, 
        TRIGGER_BEFORE, pTab, -1, regOldRowid, onError, addr);
  }

  if( !isView ){

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

................................................................................
    /* If changing the record number, delete the old record.  */
    if( chngRowid ){
      sqlite3VdbeAddOp2(v, OP_Delete, iCur, 0);
    }
    sqlite3VdbeJumpHere(v, j1);
  
    /* Insert the new index entries and the new record. */
    sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid, aRegIdx, 1, 0, 0);













  }

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

Changes to src/vdbe.c.

843
844
845
846
847
848
849

850
851
852

853
854





855
856
857
858

859
860
861
862
863
864
865
....
4842
4843
4844
4845
4846
4847
4848

4849
4850
4851
4852
4853
4854
4855
**
** There is an implied "Halt 0 0 0" instruction inserted at the very end of
** every program.  So a jump past the last instruction of the program
** is the same as executing Halt.
*/
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 ){
    sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z);
  }
  rc = sqlite3VdbeHalt(p);
................................................................................
    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;







>



>


>
>
>
>
>




>







 







>







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
....
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
**
** There is an implied "Halt 0 0 0" instruction inserted at the very end of
** every program.  So a jump past the last instruction of the program
** is the same as executing Halt.
*/
case OP_Halt: {
  if( pOp->p1==SQLITE_OK && p->pFrame ){
    /* Halt the sub-program. Return control to the parent frame. */
    VdbeFrame *pFrame = p->pFrame;
    p->pFrame = pFrame->pParent;
    p->nFrame--;
    sqlite3VdbeSetChanges(db, p->nChange);
    pc = sqlite3VdbeFrameRestore(pFrame);
    if( pOp->p2==OE_Ignore ){
      /* Instruction pc is the OP_Program that invoked the sub-program 
      ** currently being halted. If the p2 instruction of this OP_Halt
      ** instruction is set to OE_Ignore, then the sub-program is throwing
      ** an IGNORE exception. In this case jump to the address specified
      ** as the p2 of the calling OP_Program.  */
      pc = p->aOp[pc].p2-1;
    }
    break;
  }

  p->rc = pOp->p1;
  p->errorAction = (u8)pOp->p2;
  p->pc = pc;
  if( pOp->p4.z ){
    sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z);
  }
  rc = sqlite3VdbeHalt(p);
................................................................................
    assert( pc==pFrame->pc );
  }

  p->nFrame++;
  pFrame->pParent = p->pFrame;
  pFrame->lastRowid = db->lastRowid;
  pFrame->nChange = p->nChange;
  p->nChange = 0;
  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;

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
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);







<









<
<

<

<







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
    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);
  }
} {}


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

do_test tkt3992-1.3 {


  execsql {

    UPDATE parameters2 SET mountcnt = mountcnt + 1;

    SELECT * FROM parameters2;
  }
} {2 1.0}

do_test tkt3992-2.1 {
  execsql {
    CREATE TABLE t1(a, b);