/ Check-in [6d9af606]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Make sure KeyInfo objects on multi-column indices of WITHOUT ROWID tables have the correct nField and nXField values. Also, add the SQLITE_ENABLE_MODULE_COMMENT compile-time option and the VdbeModuleComment() macro and use it to label entry and exit points of some key routines.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | omit-rowid
Files: files | file ages | folders
SHA1: 6d9af6065fc0da8337aee2297a8da7511eecccf1
User & Date: drh 2013-10-30 15:52:32
Context
2013-10-30
20:22
Continue working to get UPDATE operational for WITHOUT ROWID tables. Fix PRAGMA integrity_check so that it works on WITHOUT ROWID tables. check-in: 0d4fea74 user: drh tags: omit-rowid
15:52
Make sure KeyInfo objects on multi-column indices of WITHOUT ROWID tables have the correct nField and nXField values. Also, add the SQLITE_ENABLE_MODULE_COMMENT compile-time option and the VdbeModuleComment() macro and use it to label entry and exit points of some key routines. check-in: 6d9af606 user: drh tags: omit-rowid
13:46
In the P4 column of the EXPLAIN listing, abbreviate "keyinfo" as just "k" and "BINARY" as just "B". check-in: 72d45eb7 user: drh tags: omit-rowid
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

2931
2932
2933
2934
2935
2936
2937

2938
2939
2940
2941
2942
2943
2944
  zExtra += nName + 1;
  memcpy(pIndex->zName, zName, nName+1);
  pIndex->pTable = pTab;
  pIndex->onError = (u8)onError;
  pIndex->uniqNotNull = onError!=OE_None;
  pIndex->autoIndex = (u8)(pName==0);
  pIndex->pSchema = db->aDb[iDb].pSchema;

  if( pPIWhere ){
    sqlite3ResolveSelfReference(pParse, pTab, NC_PartIdx, pPIWhere, 0);
    pIndex->pPartIdxWhere = pPIWhere;
    pPIWhere = 0;
  }
  assert( sqlite3SchemaMutexHeld(db, iDb, 0) );








>







2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
  zExtra += nName + 1;
  memcpy(pIndex->zName, zName, nName+1);
  pIndex->pTable = pTab;
  pIndex->onError = (u8)onError;
  pIndex->uniqNotNull = onError!=OE_None;
  pIndex->autoIndex = (u8)(pName==0);
  pIndex->pSchema = db->aDb[iDb].pSchema;
  pIndex->nKeyCol = pList->nExpr;
  if( pPIWhere ){
    sqlite3ResolveSelfReference(pParse, pTab, NC_PartIdx, pPIWhere, 0);
    pIndex->pPartIdxWhere = pPIWhere;
    pPIWhere = 0;
  }
  assert( sqlite3SchemaMutexHeld(db, iDb, 0) );

Changes to src/delete.c.

545
546
547
548
549
550
551


552
553
554
555
556
557
558
...
619
620
621
622
623
624
625

626
627
628
629
630
631
632
  Vdbe *v = pParse->pVdbe;        /* Vdbe */
  int iOld = 0;                   /* First register in OLD.* array */
  int iLabel;                     /* Label resolved to end of generated code */
  u8 opSeek;                      /* Seek opcode */

  /* Vdbe is guaranteed to have been allocated by this stage. */
  assert( v );



  /* Seek cursor iCur to the row to delete. If this row no longer exists 
  ** (this can happen if a trigger program has already deleted it), do
  ** not attempt to delete it or fire any DELETE triggers.  */
  iLabel = sqlite3VdbeMakeLabel(v);
  opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
  sqlite3VdbeAddOp4Int(v, opSeek, iCur, iLabel, iPk, nPk);
................................................................................
      TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel
  );

  /* Jump here if the row had already been deleted before any BEFORE
  ** trigger programs were invoked. Or if a trigger program throws a 
  ** RAISE(IGNORE) exception.  */
  sqlite3VdbeResolveLabel(v, iLabel);

}

/*
** This routine generates VDBE code that causes the deletion of all
** index entries associated with a single row of a single table.
**
** The VDBE must be in a particular state when this routine is called.







>
>







 







>







545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
...
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
  Vdbe *v = pParse->pVdbe;        /* Vdbe */
  int iOld = 0;                   /* First register in OLD.* array */
  int iLabel;                     /* Label resolved to end of generated code */
  u8 opSeek;                      /* Seek opcode */

  /* Vdbe is guaranteed to have been allocated by this stage. */
  assert( v );
  VdbeModuleComment((v, "BEGIN: GenerateRowDelete(%d,%d,%d)",
                         iCur, iPk, (int)nPk));

  /* Seek cursor iCur to the row to delete. If this row no longer exists 
  ** (this can happen if a trigger program has already deleted it), do
  ** not attempt to delete it or fire any DELETE triggers.  */
  iLabel = sqlite3VdbeMakeLabel(v);
  opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
  sqlite3VdbeAddOp4Int(v, opSeek, iCur, iLabel, iPk, nPk);
................................................................................
      TK_DELETE, 0, TRIGGER_AFTER, pTab, iOld, onconf, iLabel
  );

  /* Jump here if the row had already been deleted before any BEFORE
  ** trigger programs were invoked. Or if a trigger program throws a 
  ** RAISE(IGNORE) exception.  */
  sqlite3VdbeResolveLabel(v, iLabel);
  VdbeModuleComment((v, "END: GenerateRowDelete()"));
}

/*
** This routine generates VDBE code that causes the deletion of all
** index entries associated with a single row of a single table.
**
** The VDBE must be in a particular state when this routine is called.

Changes to src/insert.c.

1267
1268
1269
1270
1271
1272
1273


1274
1275
1276
1277
1278
1279
1280
....
1583
1584
1585
1586
1587
1588
1589

1590
1591
1592
1593
1594
1595
1596
  regOldPk = (pkChng && isUpdate) ? pkChng : regRowid;
  db = pParse->db;
  v = sqlite3GetVdbe(pParse);
  assert( v!=0 );
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
  nCol = pTab->nCol;
  regData = regRowid + 1;



  /* For WITHOUT ROWID tables, we'll need to know the Index and the cursor
  ** number for the PRIMARY KEY index */
  if( !HasRowid(pTab) ){
    assert( pkChng==0 || isUpdate!=0 );
    pkCur = baseCur+1;
    pPk = pTab->pIndex;
................................................................................
    sqlite3VdbeResolveLabel(v, addrUniqueOk);
    sqlite3ReleaseTempReg(pParse, regR);
  }
  
  if( pbMayReplace ){
    *pbMayReplace = seenReplace;
  }

}

/*
** This routine generates code to finish the INSERT or UPDATE operation
** that was started by a prior call to sqlite3GenerateConstraintChecks.
** A consecutive range of registers starting at regRowid contains the
** rowid and the content to be inserted.







>
>







 







>







1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
....
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
  regOldPk = (pkChng && isUpdate) ? pkChng : regRowid;
  db = pParse->db;
  v = sqlite3GetVdbe(pParse);
  assert( v!=0 );
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
  nCol = pTab->nCol;
  regData = regRowid + 1;
  VdbeModuleComment((v, "BEGIN: GenerateConstraintChecks(%d,%d,%d)",
                     baseCur, regRowid, pkChng));

  /* For WITHOUT ROWID tables, we'll need to know the Index and the cursor
  ** number for the PRIMARY KEY index */
  if( !HasRowid(pTab) ){
    assert( pkChng==0 || isUpdate!=0 );
    pkCur = baseCur+1;
    pPk = pTab->pIndex;
................................................................................
    sqlite3VdbeResolveLabel(v, addrUniqueOk);
    sqlite3ReleaseTempReg(pParse, regR);
  }
  
  if( pbMayReplace ){
    *pbMayReplace = seenReplace;
  }
  VdbeModuleComment((v, "END: GenerateConstraintChecks()"));
}

/*
** This routine generates code to finish the INSERT or UPDATE operation
** that was started by a prior call to sqlite3GenerateConstraintChecks.
** A consecutive range of registers starting at regRowid contains the
** rowid and the content to be inserted.

Changes to src/vdbe.h.

214
215
216
217
218
219
220
221







222
223
224
225
226





227
228
229

230
231
232
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);

#ifndef SQLITE_OMIT_TRIGGER
void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
#endif









#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
  void sqlite3VdbeComment(Vdbe*, const char*, ...);
# define VdbeComment(X)  sqlite3VdbeComment X
  void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
# define VdbeNoopComment(X)  sqlite3VdbeNoopComment X





#else
# define VdbeComment(X)
# define VdbeNoopComment(X)

#endif

#endif







<
>
>
>
>
>
>
>





>
>
>
>
>



>



214
215
216
217
218
219
220

221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);

#ifndef SQLITE_OMIT_TRIGGER
void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
#endif


/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
** each VDBE opcode.
**
** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
** comments in VDBE programs that show key decision points in the code
** generator.
*/
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
  void sqlite3VdbeComment(Vdbe*, const char*, ...);
# define VdbeComment(X)  sqlite3VdbeComment X
  void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
# define VdbeNoopComment(X)  sqlite3VdbeNoopComment X
# ifdef SQLITE_ENABLE_MODULE_COMMENTS
#   define VdbeModuleComment(X)  sqlite3VdbeNoopComment X
# else
#   define VdbeModuleComment(X)
# endif
#else
# define VdbeComment(X)
# define VdbeNoopComment(X)
# define VdbeModuleComment(X)
#endif

#endif

Changes to src/vdbeaux.c.

3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
  ** impact, since this routine is a very high runner.  And so, we choose
  ** to ignore the compiler warnings and leave this variable uninitialized.
  */
  /*  mem1.u.i = 0;  // not needed, here to silence compiler warning */
  
  idx1 = getVarint32(aKey1, szHdr1);
  d1 = szHdr1;
  assert( pKeyInfo->nField+1>=pPKey2->nField );
  assert( pKeyInfo->aSortOrder!=0 );
  while( idx1<szHdr1 && i<pPKey2->nField ){
    u32 serial_type1;

    /* Read the serial types for the next element in each key. */
    idx1 += getVarint32( aKey1+idx1, serial_type1 );








|







3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
  ** impact, since this routine is a very high runner.  And so, we choose
  ** to ignore the compiler warnings and leave this variable uninitialized.
  */
  /*  mem1.u.i = 0;  // not needed, here to silence compiler warning */
  
  idx1 = getVarint32(aKey1, szHdr1);
  d1 = szHdr1;
  assert( pKeyInfo->nField+pKeyInfo->nXField>=pPKey2->nField );
  assert( pKeyInfo->aSortOrder!=0 );
  while( idx1<szHdr1 && i<pPKey2->nField ){
    u32 serial_type1;

    /* Read the serial types for the next element in each key. */
    idx1 += getVarint32( aKey1+idx1, serial_type1 );