SQLite4
Check-in [a70fb0629b]
Not logged in

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

Overview
Comment:Fix various bugs.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | primary-keys
Files: files | file ages | folders
SHA1: a70fb0629b2889c5ebe45ebd40b67b1b0088b569
User & Date: dan 2012-04-11 15:01:13
Context
2012-04-11
18:48
Fix some problems with REPLACE and other conflict handling. check-in: ff493aaa41 user: dan tags: primary-keys
15:01
Fix various bugs. check-in: a70fb0629b user: dan tags: primary-keys
2012-04-10
19:52
Changes to support "real" user-defined primary keys. This is quite broken at present. check-in: 3841829752 user: dan tags: primary-keys
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/auth.c.

166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
  }
  iCol = pExpr->iColumn;
  if( NEVER(pTab==0) ) return;

  if( iCol>=0 ){
    assert( iCol<pTab->nCol );
    zCol = pTab->aCol[iCol].zName;
  }else if( pTab->iPKey>=0 ){
    assert( pTab->iPKey<pTab->nCol );
    zCol = pTab->aCol[pTab->iPKey].zName;
  }else{
    zCol = "ROWID";
  }
  assert( iDb>=0 && iDb<db->nDb );
  if( SQLITE_IGNORE==sqlite4AuthReadCol(pParse, pTab->zName, zCol, iDb) ){
    pExpr->op = TK_NULL;
  }







<
<
<







166
167
168
169
170
171
172



173
174
175
176
177
178
179
  }
  iCol = pExpr->iColumn;
  if( NEVER(pTab==0) ) return;

  if( iCol>=0 ){
    assert( iCol<pTab->nCol );
    zCol = pTab->aCol[iCol].zName;



  }else{
    zCol = "ROWID";
  }
  assert( iDb>=0 && iDb<db->nDb );
  if( SQLITE_IGNORE==sqlite4AuthReadCol(pParse, pTab->zName, zCol, iDb) ){
    pExpr->op = TK_NULL;
  }

Changes to src/build.c.

841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
  if( pTable==0 ){
    db->mallocFailed = 1;
    pParse->rc = SQLITE_NOMEM;
    pParse->nErr++;
    goto begin_table_error;
  }
  pTable->zName = zName;
  pTable->iPKey = -1;
  pTable->pSchema = db->aDb[iDb].pSchema;
  pTable->nRef = 1;
  pTable->nRowEst = 1000000;
  assert( pParse->pNewTable==0 );
  pParse->pNewTable = pTable;

  /* If this is the magic sqlite_sequence table used by autoincrement,







<







841
842
843
844
845
846
847

848
849
850
851
852
853
854
  if( pTable==0 ){
    db->mallocFailed = 1;
    pParse->rc = SQLITE_NOMEM;
    pParse->nErr++;
    goto begin_table_error;
  }
  pTable->zName = zName;

  pTable->pSchema = db->aDb[iDb].pSchema;
  pTable->nRef = 1;
  pTable->nRowEst = 1000000;
  assert( pParse->pNewTable==0 );
  pParse->pNewTable = pTable;

  /* If this is the magic sqlite_sequence table used by autoincrement,

Changes to src/delete.c.

680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
  int nCol;

  nCol = pIdx->nColumn;
  regBase = sqlite4GetTempRange(pParse, nCol+1);
  sqlite4VdbeAddOp2(v, OP_Rowid, iCur, regBase+nCol);
  for(j=0; j<nCol; j++){
    int idx = pIdx->aiColumn[j];
    if( idx==pTab->iPKey ){
      sqlite4VdbeAddOp2(v, OP_SCopy, regBase+nCol, regBase+j);
    }else{
      sqlite4VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
      sqlite4ColumnDefault(v, pTab, idx, -1);
    }
  }
  if( doMakeRec ){







|







680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
  int nCol;

  nCol = pIdx->nColumn;
  regBase = sqlite4GetTempRange(pParse, nCol+1);
  sqlite4VdbeAddOp2(v, OP_Rowid, iCur, regBase+nCol);
  for(j=0; j<nCol; j++){
    int idx = pIdx->aiColumn[j];
    if( idx<0 ){
      sqlite4VdbeAddOp2(v, OP_SCopy, regBase+nCol, regBase+j);
    }else{
      sqlite4VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
      sqlite4ColumnDefault(v, pTab, idx, -1);
    }
  }
  if( doMakeRec ){

Changes to src/expr.c.

2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
....
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
void sqlite4ExprCodeGetColumnOfTable(
  Vdbe *v,        /* The VDBE under construction */
  Table *pTab,    /* The table containing the value */
  int iTabCur,    /* The cursor for this table */
  int iCol,       /* Index of the column to extract */
  int regOut      /* Extract the valud into this register */
){
  if( iCol<0 || iCol==pTab->iPKey ){
    sqlite4VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
  }else{
    int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
    sqlite4VdbeAddOp3(v, op, iTabCur, iCol, regOut);
  }
  if( iCol>=0 ){
    sqlite4ColumnDefault(v, pTab, iCol, regOut);
................................................................................
      **   p1==2   ->    old.b         p1==5   ->    new.b       
      */
      Table *pTab = pExpr->pTab;
      int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;

      assert( pExpr->iTable==0 || pExpr->iTable==1 );
      assert( pExpr->iColumn>=-1 && pExpr->iColumn<pTab->nCol );
      assert( pTab->iPKey<0 || pExpr->iColumn!=pTab->iPKey );
      assert( p1>=0 && p1<(pTab->nCol*2+2) );

      sqlite4VdbeAddOp2(v, OP_Param, p1, target);
      VdbeComment((v, "%s.%s -> $%d",
        (pExpr->iTable ? "new" : "old"),
        (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName),
        target







|







 







<







2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
....
2729
2730
2731
2732
2733
2734
2735

2736
2737
2738
2739
2740
2741
2742
void sqlite4ExprCodeGetColumnOfTable(
  Vdbe *v,        /* The VDBE under construction */
  Table *pTab,    /* The table containing the value */
  int iTabCur,    /* The cursor for this table */
  int iCol,       /* Index of the column to extract */
  int regOut      /* Extract the valud into this register */
){
  if( iCol<0 ){
    sqlite4VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
  }else{
    int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
    sqlite4VdbeAddOp3(v, op, iTabCur, iCol, regOut);
  }
  if( iCol>=0 ){
    sqlite4ColumnDefault(v, pTab, iCol, regOut);
................................................................................
      **   p1==2   ->    old.b         p1==5   ->    new.b       
      */
      Table *pTab = pExpr->pTab;
      int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;

      assert( pExpr->iTable==0 || pExpr->iTable==1 );
      assert( pExpr->iColumn>=-1 && pExpr->iColumn<pTab->nCol );

      assert( p1>=0 && p1<(pTab->nCol*2+2) );

      sqlite4VdbeAddOp2(v, OP_Param, p1, target);
      VdbeComment((v, "%s.%s -> $%d",
        (pExpr->iTable ? "new" : "old"),
        (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName),
        target

Changes to src/kvmem.c.

185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
*/
static int kvmemKeyCompare(
  const KVByteArray *aK1, KVSize nK1,
  const KVByteArray *aK2, KVSize nK2
){
  int c;
  c = memcmp(aK1, aK2, nK1<nK2 ? nK1 : nK2);
  if( c==0 ) c = nK2 - nK1;
  return c;
}

/*
** Create a new KVMemData object
*/
static KVMemData *kvmemDataNew(const KVByteArray *aData, KVSize nData){







|







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
*/
static int kvmemKeyCompare(
  const KVByteArray *aK1, KVSize nK1,
  const KVByteArray *aK2, KVSize nK2
){
  int c;
  c = memcmp(aK1, aK2, nK1<nK2 ? nK1 : nK2);
  if( c==0 ) c = nK1 - nK2;
  return c;
}

/*
** Create a new KVMemData object
*/
static KVMemData *kvmemDataNew(const KVByteArray *aData, KVSize nData){

Changes to src/resolve.c.

216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
...
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
              if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
            }
            cnt++;
            pExpr->iTable = pItem->iCursor;
            pExpr->pTab = pTab;
            pMatch = pItem;
            pSchema = pTab->pSchema;
            /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
            pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
            break;
          }
        }
      }
    }

#ifndef SQLITE_OMIT_TRIGGER
................................................................................
      if( pTab ){ 
        int iCol;
        pSchema = pTab->pSchema;
        cntTab++;
        for(iCol=0; iCol<pTab->nCol; iCol++){
          Column *pCol = &pTab->aCol[iCol];
          if( sqlite4StrICmp(pCol->zName, zCol)==0 ){
            if( iCol==pTab->iPKey ){
              iCol = -1;
            }
            break;
          }
        }
        if( iCol>=pTab->nCol && sqlite4IsRowid(zCol) ){
          iCol = -1;        /* IMP: R-44911-55124 */
        }
        if( iCol<pTab->nCol ){
................................................................................
*/
Expr *sqlite4CreateColumnExpr(sqlite4 *db, SrcList *pSrc, int iSrc, int iCol){
  Expr *p = sqlite4ExprAlloc(db, TK_COLUMN, 0, 0);
  if( p ){
    struct SrcList_item *pItem = &pSrc->a[iSrc];
    p->pTab = pItem->pTab;
    p->iTable = pItem->iCursor;
    if( p->pTab->iPKey==iCol ){
      p->iColumn = -1;
    }else{
      p->iColumn = (ynVar)iCol;
      testcase( iCol==BMS );
      testcase( iCol==BMS-1 );
      pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol);
    }
    ExprSetProperty(p, EP_Resolved);
  }
  return p;
}

/*
** This routine is callback for sqlite4WalkExpr().







<
|







 







<
<
<







 







<
<
<
|
|
|
|
<







216
217
218
219
220
221
222

223
224
225
226
227
228
229
230
...
246
247
248
249
250
251
252



253
254
255
256
257
258
259
...
409
410
411
412
413
414
415



416
417
418
419

420
421
422
423
424
425
426
              if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
            }
            cnt++;
            pExpr->iTable = pItem->iCursor;
            pExpr->pTab = pTab;
            pMatch = pItem;
            pSchema = pTab->pSchema;

            pExpr->iColumn = (i16)j;
            break;
          }
        }
      }
    }

#ifndef SQLITE_OMIT_TRIGGER
................................................................................
      if( pTab ){ 
        int iCol;
        pSchema = pTab->pSchema;
        cntTab++;
        for(iCol=0; iCol<pTab->nCol; iCol++){
          Column *pCol = &pTab->aCol[iCol];
          if( sqlite4StrICmp(pCol->zName, zCol)==0 ){



            break;
          }
        }
        if( iCol>=pTab->nCol && sqlite4IsRowid(zCol) ){
          iCol = -1;        /* IMP: R-44911-55124 */
        }
        if( iCol<pTab->nCol ){
................................................................................
*/
Expr *sqlite4CreateColumnExpr(sqlite4 *db, SrcList *pSrc, int iSrc, int iCol){
  Expr *p = sqlite4ExprAlloc(db, TK_COLUMN, 0, 0);
  if( p ){
    struct SrcList_item *pItem = &pSrc->a[iSrc];
    p->pTab = pItem->pTab;
    p->iTable = pItem->iCursor;



    p->iColumn = (ynVar)iCol;
    testcase( iCol==BMS );
    testcase( iCol==BMS-1 );
    pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol);

    ExprSetProperty(p, EP_Resolved);
  }
  return p;
}

/*
** This routine is callback for sqlite4WalkExpr().

Changes to src/select.c.

1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
....
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
....
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
....
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
....
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
          sNC.pNext = pNC;
          sNC.pParse = pNC->pParse;
          zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); 
        }
      }else if( ALWAYS(pTab->pSchema) ){
        /* A real table */
        assert( !pS );
        if( iCol<0 ) iCol = pTab->iPKey;
        assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
        if( iCol<0 ){
          zType = "INTEGER";
          zOriginCol = "rowid";
        }else{
          zType = pTab->aCol[iCol].zType;
          zOriginCol = pTab->aCol[iCol].zName;
................................................................................
      char *zCol;
      int iCol = p->iColumn;
      for(j=0; ALWAYS(j<pTabList->nSrc); j++){
        if( pTabList->a[j].iCursor==p->iTable ) break;
      }
      assert( j<pTabList->nSrc );
      pTab = pTabList->a[j].pTab;
      if( iCol<0 ) iCol = pTab->iPKey;
      assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
      if( iCol<0 ){
        zCol = "rowid";
      }else{
        zCol = pTab->aCol[iCol].zName;
      }
      sqlite4VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT);
................................................................................
        pColExpr = pColExpr->pRight;
        assert( pColExpr!=0 );
      }
      if( pColExpr->op==TK_COLUMN && ALWAYS(pColExpr->pTab!=0) ){
        /* For columns use the column name name */
        int iCol = pColExpr->iColumn;
        pTab = pColExpr->pTab;
        if( iCol<0 ) iCol = pTab->iPKey;
        zName = sqlite4MPrintf(db, "%s",
                 iCol>=0 ? pTab->aCol[iCol].zName : "rowid");
      }else if( pColExpr->op==TK_ID ){
        assert( !ExprHasProperty(pColExpr, EP_IntValue) );
        zName = sqlite4MPrintf(db, "%s", pColExpr->u.zToken);
      }else{
        /* Use the original text of the column expression as its name */
................................................................................
  ** is disabled */
  assert( db->lookaside.bEnabled==0 );
  pTab->nRef = 1;
  pTab->zName = 0;
  pTab->nRowEst = 1000000;
  selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
  selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
  pTab->iPKey = -1;
  if( db->mallocFailed ){
    sqlite4DeleteTable(db, pTab);
    return 0;
  }
  return pTab;
}

................................................................................
      sqlite4WalkSelect(pWalker, pSel);
      pFrom->pTab = pTab = sqlite4DbMallocZero(db, sizeof(Table));
      if( pTab==0 ) return WRC_Abort;
      pTab->nRef = 1;
      pTab->zName = sqlite4MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
      while( pSel->pPrior ){ pSel = pSel->pPrior; }
      selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
      pTab->iPKey = -1;
      pTab->nRowEst = 1000000;
      pTab->tabFlags |= TF_Ephemeral;
#endif
    }else{
      /* An ordinary table or view name in the FROM clause */
      assert( pFrom->pTab==0 );
      pFrom->pTab = pTab = 







<







 







<







 







<







 







<







 







<







1088
1089
1090
1091
1092
1093
1094

1095
1096
1097
1098
1099
1100
1101
....
1211
1212
1213
1214
1215
1216
1217

1218
1219
1220
1221
1222
1223
1224
....
1277
1278
1279
1280
1281
1282
1283

1284
1285
1286
1287
1288
1289
1290
....
1388
1389
1390
1391
1392
1393
1394

1395
1396
1397
1398
1399
1400
1401
....
3231
3232
3233
3234
3235
3236
3237

3238
3239
3240
3241
3242
3243
3244
          sNC.pNext = pNC;
          sNC.pParse = pNC->pParse;
          zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); 
        }
      }else if( ALWAYS(pTab->pSchema) ){
        /* A real table */
        assert( !pS );

        assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
        if( iCol<0 ){
          zType = "INTEGER";
          zOriginCol = "rowid";
        }else{
          zType = pTab->aCol[iCol].zType;
          zOriginCol = pTab->aCol[iCol].zName;
................................................................................
      char *zCol;
      int iCol = p->iColumn;
      for(j=0; ALWAYS(j<pTabList->nSrc); j++){
        if( pTabList->a[j].iCursor==p->iTable ) break;
      }
      assert( j<pTabList->nSrc );
      pTab = pTabList->a[j].pTab;

      assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
      if( iCol<0 ){
        zCol = "rowid";
      }else{
        zCol = pTab->aCol[iCol].zName;
      }
      sqlite4VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT);
................................................................................
        pColExpr = pColExpr->pRight;
        assert( pColExpr!=0 );
      }
      if( pColExpr->op==TK_COLUMN && ALWAYS(pColExpr->pTab!=0) ){
        /* For columns use the column name name */
        int iCol = pColExpr->iColumn;
        pTab = pColExpr->pTab;

        zName = sqlite4MPrintf(db, "%s",
                 iCol>=0 ? pTab->aCol[iCol].zName : "rowid");
      }else if( pColExpr->op==TK_ID ){
        assert( !ExprHasProperty(pColExpr, EP_IntValue) );
        zName = sqlite4MPrintf(db, "%s", pColExpr->u.zToken);
      }else{
        /* Use the original text of the column expression as its name */
................................................................................
  ** is disabled */
  assert( db->lookaside.bEnabled==0 );
  pTab->nRef = 1;
  pTab->zName = 0;
  pTab->nRowEst = 1000000;
  selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
  selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);

  if( db->mallocFailed ){
    sqlite4DeleteTable(db, pTab);
    return 0;
  }
  return pTab;
}

................................................................................
      sqlite4WalkSelect(pWalker, pSel);
      pFrom->pTab = pTab = sqlite4DbMallocZero(db, sizeof(Table));
      if( pTab==0 ) return WRC_Abort;
      pTab->nRef = 1;
      pTab->zName = sqlite4MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
      while( pSel->pPrior ){ pSel = pSel->pPrior; }
      selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);

      pTab->nRowEst = 1000000;
      pTab->tabFlags |= TF_Ephemeral;
#endif
    }else{
      /* An ordinary table or view name in the FROM clause */
      assert( pFrom->pTab==0 );
      pFrom->pTab = pTab = 

Changes to src/sqliteInt.h.

1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
** refers VDBE cursor number that holds the table open, not to the root
** page number.  Transient tables are used to hold the results of a
** sub-query that appears instead of a real table name in the FROM clause 
** of a SELECT statement.
*/
struct Table {
  char *zName;         /* Name of the table or view */
  int iPKey;           /* If not negative, use aCol[iPKey] as the primary key */
  int nCol;            /* Number of columns in this table */
  Column *aCol;        /* Information about each column */
  Index *pIndex;       /* List of SQL indexes on this table. */
#if 0
  int tnum;            /* Root BTree node for this table (see note above) */
#endif
  tRowcnt nRowEst;     /* Estimated rows in table - from sqlite_stat1 table */
  Select *pSelect;     /* NULL for tables.  Points to definition if a view. */
  u16 nRef;            /* Number of pointers to this Table */
  u8 tabFlags;         /* Mask of TF_* values */
  u8 keyConf;          /* What to do in case of uniqueness conflict on iPKey */
  FKey *pFKey;         /* Linked list of all foreign keys in this table */
  char *zColAff;       /* String defining the affinity of each column */
#ifndef SQLITE_OMIT_CHECK
  Expr *pCheck;        /* The AND of all CHECK constraints */
#endif
#ifndef SQLITE_OMIT_ALTERTABLE
  int addColOffset;    /* Offset in CREATE TABLE stmt to add a new column */







<



<
<
<




<







1291
1292
1293
1294
1295
1296
1297

1298
1299
1300



1301
1302
1303
1304

1305
1306
1307
1308
1309
1310
1311
** refers VDBE cursor number that holds the table open, not to the root
** page number.  Transient tables are used to hold the results of a
** sub-query that appears instead of a real table name in the FROM clause 
** of a SELECT statement.
*/
struct Table {
  char *zName;         /* Name of the table or view */

  int nCol;            /* Number of columns in this table */
  Column *aCol;        /* Information about each column */
  Index *pIndex;       /* List of SQL indexes on this table. */



  tRowcnt nRowEst;     /* Estimated rows in table - from sqlite_stat1 table */
  Select *pSelect;     /* NULL for tables.  Points to definition if a view. */
  u16 nRef;            /* Number of pointers to this Table */
  u8 tabFlags;         /* Mask of TF_* values */

  FKey *pFKey;         /* Linked list of all foreign keys in this table */
  char *zColAff;       /* String defining the affinity of each column */
#ifndef SQLITE_OMIT_CHECK
  Expr *pCheck;        /* The AND of all CHECK constraints */
#endif
#ifndef SQLITE_OMIT_ALTERTABLE
  int addColOffset;    /* Offset in CREATE TABLE stmt to add a new column */

Changes to src/update.c.

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
...
281
282
283
284
285
286
287

288
289
290


291
292
293
294
295
296
297
...
436
437
438
439
440
441
442



443
444
445
446
447
448
449
...
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
  int regOld = 0;        /* Content of OLD.* table in triggers */

  int regKeySet = 0;              /* Register containing KeySet object */
  Index *pPk;                     /* The primary key index of this table */
  int iPk;                        /* Offset of primary key in aRegIdx[] */
  int bChngPk = 0;                /* True if any PK columns are updated */
  int bOpenAll = 0;               /* True if all indexes were opened */


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

  /* Locate the table which we want to update. */
  pTab = sqlite4SrcListLookup(pParse, pSrc);
  if( pTab==0 ) goto update_cleanup;
  iDb = sqlite4SchemaToIndex(pParse->db, pTab->pSchema);
  pPk = sqlite4FindPrimaryKey(pTab, &iPk);


  /* Figure out if we have any triggers and if the table being
  ** updated is a view.
  */
#ifndef SQLITE_OMIT_TRIGGER
  pTrigger = sqlite4TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask);
  isView = pTab->pSelect!=0;
................................................................................
  /* Allocate other required registers. */
  regKeySet = ++pParse->nMem;
  regOldKey = ++pParse->nMem;
  if( pTrigger || hasFK ){
    regOld = pParse->nMem + 1;
    pParse->nMem += pTab->nCol;
  }

  if( chngRowid || pTrigger || hasFK ){
    regNewRowid = ++pParse->nMem;
  }


  regNew = pParse->nMem + 1;
  pParse->nMem += pTab->nCol;

  /* Start the view context. */
  if( isView ){
    sqlite4AuthContextPush(pParse, &sContext, pTab->zName);
  }
................................................................................
       */
      testcase( i==31 );
      testcase( i==32 );
      sqlite4VdbeAddOp3(v, OP_Column, iCur+iPk, i, regNew+i);
      sqlite4ColumnDefault(v, pTab, i, regNew+i);
    }
  }




  /* Fire any BEFORE UPDATE triggers. This happens before constraints are
  ** verified. One could argue that this is wrong.
  */
  if( tmask&TRIGGER_BEFORE ){
    sqlite4VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol);
    sqlite4TableAffinityStr(v, pTab);
................................................................................

    /* If it did not delete it, the row-trigger may still have modified 
    ** some of the columns of the row being updated. Load the values for 
    ** all columns not modified by the update statement into their 
    ** registers in case this has happened.
    */
    for(i=0; i<pTab->nCol; i++){
      if( aXRef[i]<0 && i!=pTab->iPKey ){
        sqlite4VdbeAddOp3(v, OP_Column, iCur, i, regNew+i);
        sqlite4ColumnDefault(v, pTab, i, regNew+i);
      }
    }
  }

  if( !isView ){
    int j1;                       /* Address of jump instruction */


    /* Do constraint checks. */
    assert( bChngPk==0 || pPk->aiColumn[0]>=0 );
    if( bChngPk==0 ) aRegIdx[iPk] = 0;
    sqlite4GenerateConstraintChecks(
        pParse, pTab, iCur, regNew, aRegIdx, 0, 1, onError, addr, 0
    );
    if( bChngPk==0 ) aRegIdx[iPk] = regOldKey;

    /* Do FK constraint checks. */







>













>







 







>



>
>







 







>
>
>







 







|











|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
...
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
...
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
  int regOld = 0;        /* Content of OLD.* table in triggers */

  int regKeySet = 0;              /* Register containing KeySet object */
  Index *pPk;                     /* The primary key index of this table */
  int iPk;                        /* Offset of primary key in aRegIdx[] */
  int bChngPk = 0;                /* True if any PK columns are updated */
  int bOpenAll = 0;               /* True if all indexes were opened */
  int bImplicitPk;                /* True if pTab has an implicit PK */

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

  /* Locate the table which we want to update. */
  pTab = sqlite4SrcListLookup(pParse, pSrc);
  if( pTab==0 ) goto update_cleanup;
  iDb = sqlite4SchemaToIndex(pParse->db, pTab->pSchema);
  pPk = sqlite4FindPrimaryKey(pTab, &iPk);
  bImplicitPk = (pPk->aiColumn[0]<0);

  /* Figure out if we have any triggers and if the table being
  ** updated is a view.
  */
#ifndef SQLITE_OMIT_TRIGGER
  pTrigger = sqlite4TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask);
  isView = pTab->pSelect!=0;
................................................................................
  /* Allocate other required registers. */
  regKeySet = ++pParse->nMem;
  regOldKey = ++pParse->nMem;
  if( pTrigger || hasFK ){
    regOld = pParse->nMem + 1;
    pParse->nMem += pTab->nCol;
  }
#if 0
  if( chngRowid || pTrigger || hasFK ){
    regNewRowid = ++pParse->nMem;
  }
#endif
  if( bImplicitPk ) pParse->nMem++;
  regNew = pParse->nMem + 1;
  pParse->nMem += pTab->nCol;

  /* Start the view context. */
  if( isView ){
    sqlite4AuthContextPush(pParse, &sContext, pTab->zName);
  }
................................................................................
       */
      testcase( i==31 );
      testcase( i==32 );
      sqlite4VdbeAddOp3(v, OP_Column, iCur+iPk, i, regNew+i);
      sqlite4ColumnDefault(v, pTab, i, regNew+i);
    }
  }
  if( bImplicitPk ){
    sqlite4VdbeAddOp2(v, OP_Rowid, iCur+iPk, regNew-1);
  }

  /* Fire any BEFORE UPDATE triggers. This happens before constraints are
  ** verified. One could argue that this is wrong.
  */
  if( tmask&TRIGGER_BEFORE ){
    sqlite4VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol);
    sqlite4TableAffinityStr(v, pTab);
................................................................................

    /* If it did not delete it, the row-trigger may still have modified 
    ** some of the columns of the row being updated. Load the values for 
    ** all columns not modified by the update statement into their 
    ** registers in case this has happened.
    */
    for(i=0; i<pTab->nCol; i++){
      if( aXRef[i]<0 ){
        sqlite4VdbeAddOp3(v, OP_Column, iCur, i, regNew+i);
        sqlite4ColumnDefault(v, pTab, i, regNew+i);
      }
    }
  }

  if( !isView ){
    int j1;                       /* Address of jump instruction */


    /* Do constraint checks. */
    assert( bChngPk==0 || bImplicitPk==0 );
    if( bChngPk==0 ) aRegIdx[iPk] = 0;
    sqlite4GenerateConstraintChecks(
        pParse, pTab, iCur, regNew, aRegIdx, 0, 1, onError, addr, 0
    );
    if( bChngPk==0 ) aRegIdx[iPk] = regOldKey;

    /* Do FK constraint checks. */

Changes to src/vdbe.c.

3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
    rc = SQLITE_OK;
    pc = pOp->p2-1;
  }else if( rc==SQLITE_INEXACT ){
    assert( nShort<pProbe->n );
    rc = sqlite4KVCursorKey(pC->pKVCur, &aKey, &nKey);
    if( rc==SQLITE_OK ){
      if( nKey<nShort 
       || memcmp(pProbe->z, aKey, nKey)
       || (nKey==pProbe->n && 0==memcmp(pProbe->z, aKey, nKey))
      ){
        pc = pOp->p2-1;
      }
    }
  }








|







3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
    rc = SQLITE_OK;
    pc = pOp->p2-1;
  }else if( rc==SQLITE_INEXACT ){
    assert( nShort<pProbe->n );
    rc = sqlite4KVCursorKey(pC->pKVCur, &aKey, &nKey);
    if( rc==SQLITE_OK ){
      if( nKey<nShort 
       || memcmp(pProbe->z, aKey, nShort)
       || (nKey==pProbe->n && 0==memcmp(pProbe->z, aKey, nKey))
      ){
        pc = pOp->p2-1;
      }
    }
  }

Changes to src/where.c.

1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
    }
    pColl = sqlite4ExprCollSeq(pParse, pExpr);
    if( !pColl ){
      pColl = db->pDfltColl;
    }
    if( pIdx->zName && i<pIdx->nColumn ){
      iColumn = pIdx->aiColumn[i];
      if( iColumn==pIdx->pTable->iPKey ){
        iColumn = -1;
      }
      iSortOrder = pIdx->aSortOrder[i];
      zColl = pIdx->azColl[i];
    }else{
      iColumn = -1;
      iSortOrder = 0;
      zColl = pColl->zName;
    }







<
<
<







1650
1651
1652
1653
1654
1655
1656



1657
1658
1659
1660
1661
1662
1663
    }
    pColl = sqlite4ExprCollSeq(pParse, pExpr);
    if( !pColl ){
      pColl = db->pDfltColl;
    }
    if( pIdx->zName && i<pIdx->nColumn ){
      iColumn = pIdx->aiColumn[i];



      iSortOrder = pIdx->aSortOrder[i];
      zColl = pIdx->azColl[i];
    }else{
      iColumn = -1;
      iSortOrder = 0;
      zColl = pColl->zName;
    }

Changes to test/simple.test.

242
243
244
245
246
247
248
249
250

251



252
253
254
255


256
257
258




259
260
261
262
263
264
265
  CREATE INDEX i1 ON t1(b);
}
do_execsql_test 10.2 {
  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t1 VALUES(3, 4);
}

# explain { UPDATE t1 SET b = 10 WHERE a=3 }
#  execsql { PRAGMA vdbe_trace = 1 }





do_execsql_test 10.3 { 
  UPDATE t1 SET b = 10 WHERE a=3;
  SELECT * FROM t1;
} {1 2 3 10}



do_execsql_test 10.4 { PRAGMA integrity_check } {ok}
execsql { PRAGMA kvdump }





finish_test

#proc populate_t1 {} {
#  db eval {
#    INSERT INTO t1(a, b) VALUES(4, 'four');
#    INSERT INTO t1(a, b) VALUES(9, 'nine');







|
|
>

>
>
>
|
<
<
<
>
>
|
<
<
>
>
>
>







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
  CREATE INDEX i1 ON t1(b);
}
do_execsql_test 10.2 {
  INSERT INTO t1 VALUES(1, 2);
  INSERT INTO t1 VALUES(3, 4);
}

do_execsql_test 10.3 { UPDATE t1 SET b = 10 WHERE a=3 }
do_execsql_test 10.4 { SELECT * FROM t1 } {1 2 3 10}
do_execsql_test 10.5 { PRAGMA integrity_check } {ok}

#-------------------------------------------------------------------------
reset_db

do_execsql_test 11.1 {



  CREATE TABLE t1(a, b, c, UNIQUE(a));
  INSERT INTO t1 VALUES(1,2,3);
}


do_catchsql_test 11.2 { 
  INSERT INTO t1 VALUES(1,2,4)
} {1 {column a is not unique}}


finish_test

#proc populate_t1 {} {
#  db eval {
#    INSERT INTO t1(a, b) VALUES(4, 'four');
#    INSERT INTO t1(a, b) VALUES(9, 'nine');