mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Work on the UPDATE and INSERT logic. This is an incremental check-in so that
can switch over to trunk to work on an unrelated issue there. FossilOrigin-Name: 086ec2a177b24ad90d5d705a99d93aa0c1545217
This commit is contained in:
16
manifest
16
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Replace\sthe\sOP_IsUnique\sopcode\swith\sOP_NoConflict.\s\sThis\scode\ssimplification\nmight\sbe\suseful\sto\smove\sonto\strunk\seven\sif\sthis\sbranch\sis\snever\smerged.
|
C Work\son\sthe\sUPDATE\sand\sINSERT\slogic.\s\sThis\sis\san\sincremental\scheck-in\sso\sthat\ncan\sswitch\sover\sto\strunk\sto\swork\son\san\sunrelated\sissue\sthere.
|
||||||
D 2013-10-26T13:36:51.811
|
D 2013-10-26T15:40:48.224
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
|
F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -182,7 +182,7 @@ F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759
|
|||||||
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
|
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
|
||||||
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
||||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||||
F src/insert.c e87728415d32d6f572f5578c2107e382d1dd8203
|
F src/insert.c 14ae816acbebd927bc070bf684de638f78cfccba
|
||||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||||
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
||||||
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
||||||
@@ -279,9 +279,9 @@ F src/update.c e39378bc5ed0c42e80624229703e59b5c7a4d50a
|
|||||||
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
||||||
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
|
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
|
||||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||||
F src/vdbe.c 115f2c06e4d943d289599a46634514bf94479db4
|
F src/vdbe.c 7d23d61c84cb1116e36a70b050f2a4ae1a2aaae3
|
||||||
F src/vdbe.h 4f554b5627f26710c4c36d919110a3fc611ca5c4
|
F src/vdbe.h 4f554b5627f26710c4c36d919110a3fc611ca5c4
|
||||||
F src/vdbeInt.h ff57f67aee1ba26a3a47e786533dab155ab6dad6
|
F src/vdbeInt.h 42dcff74dbeb2b071e569b53f885fc9c2e4b4cb0
|
||||||
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
|
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
|
||||||
F src/vdbeaux.c 4ccdfd27f97fec98385f53fc8c880f1873137d95
|
F src/vdbeaux.c 4ccdfd27f97fec98385f53fc8c880f1873137d95
|
||||||
F src/vdbeblob.c ef973d8d9f8170015343dd8824f795da675caa87
|
F src/vdbeblob.c ef973d8d9f8170015343dd8824f795da675caa87
|
||||||
@@ -1127,7 +1127,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||||
P ae61a34378d3ed2f454ba8768029d6f5fef849e4
|
P e6650e16dd11327afd25961b2feb29ec8778c2ca
|
||||||
R 4e2e179014c5b2ce47e50b4ad5c73b59
|
R bb18c22d259a405d56d9b91ea7100e63
|
||||||
U drh
|
U drh
|
||||||
Z bf09176aa6b2dce2a1f786b527e72d8e
|
Z 6434b0048c9e4cb6010b12b4a2aa5b2d
|
||||||
|
@@ -1 +1 @@
|
|||||||
e6650e16dd11327afd25961b2feb29ec8778c2ca
|
086ec2a177b24ad90d5d705a99d93aa0c1545217
|
122
src/insert.c
122
src/insert.c
@@ -1123,14 +1123,50 @@ insert_cleanup:
|
|||||||
#undef tmask
|
#undef tmask
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
** If regFirst is a set of value for a table row in table order and pPk
|
||||||
|
** is the PRIMARY KEY index for that table, then return the index of the
|
||||||
|
** first register in a contiguous array of registers that are the primary
|
||||||
|
** key values for the table row.
|
||||||
|
**
|
||||||
|
** For the common cases where the PRIMARY KEY has only a single value or
|
||||||
|
** where a multi-value PRIMARY KEY is contiguous in table order, this
|
||||||
|
** routine simply returns a pointer into the regFirst array. But if there
|
||||||
|
** is a multi-value PRIMARY KEY with the values out-of-order, this routine
|
||||||
|
** has to generate code that will copy PRIMARY KEY values into newly
|
||||||
|
** allocated contiguous registers.
|
||||||
|
*/
|
||||||
|
static int sqlite3PrimaryKeyRegisters(Parse *pParse, Index *pPk, int regFirst){
|
||||||
|
int i;
|
||||||
|
int nKeyCol = pPk->nKeyCol;
|
||||||
|
int regPk;
|
||||||
|
assert( pParse->pVdbe!=0 );
|
||||||
|
if( nKeyCol==1 ){
|
||||||
|
return regFirst + pPk->aiColumn[0];
|
||||||
|
}
|
||||||
|
for(i=1; i<nKeyCol; i++){
|
||||||
|
if( pPk->aiColumn[i-1]+1!=pPk->aiColumn[i] ) break;
|
||||||
|
}
|
||||||
|
if( i==nKeyCol ){
|
||||||
|
return regFirst + pPk->aiColumn[0];
|
||||||
|
}
|
||||||
|
regPk = pParse->nMem+1;
|
||||||
|
pParse->nMem += nKeyCol;
|
||||||
|
for(i=0; i<nKeyCol; i++){
|
||||||
|
int x = pPk->aiColumn[i];
|
||||||
|
sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, regFirst+x, regPk+i);
|
||||||
|
}
|
||||||
|
return regPk;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Generate code to do constraint checks prior to an INSERT or an UPDATE.
|
** Generate code to do constraint checks prior to an INSERT or an UPDATE.
|
||||||
**
|
**
|
||||||
** The input is a range of consecutive registers as follows:
|
** The input is a range of consecutive registers as follows:
|
||||||
**
|
**
|
||||||
** 1. The rowid of the row after the update. (This register
|
** 1. The rowid of the row after the update, or NULL
|
||||||
** contains a NULL for WITHOUT ROWID tables.)
|
** for WITHOUT ROWID tables.
|
||||||
**
|
**
|
||||||
** 2. The data in the first column of the entry after the update.
|
** 2. The data in the first column of the entry after the update.
|
||||||
**
|
**
|
||||||
@@ -1207,7 +1243,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
int baseCur, /* A read/write cursor pointing at pTab */
|
int baseCur, /* A read/write cursor pointing at pTab */
|
||||||
int regRowid, /* First register in a range holding values to insert */
|
int regRowid, /* First register in a range holding values to insert */
|
||||||
int *aRegIdx, /* Register used by each index. 0 for unused indices */
|
int *aRegIdx, /* Register used by each index. 0 for unused indices */
|
||||||
int pkChng, /* Non-zero if the PRIMARY KEY might collide */
|
int pkChng, /* Non-zero if the rowid or PRIMARY KEY changed */
|
||||||
int isUpdate, /* True for UPDATE, False for INSERT */
|
int isUpdate, /* True for UPDATE, False for INSERT */
|
||||||
int overrideError, /* Override onError to this if not OE_Default */
|
int overrideError, /* Override onError to this if not OE_Default */
|
||||||
int ignoreDest, /* Jump to this label on an OE_Ignore resolution */
|
int ignoreDest, /* Jump to this label on an OE_Ignore resolution */
|
||||||
@@ -1218,14 +1254,17 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
int nCol; /* Number of columns */
|
int nCol; /* Number of columns */
|
||||||
int onError; /* Conflict resolution strategy */
|
int onError; /* Conflict resolution strategy */
|
||||||
int j1; /* Addresss of jump instruction */
|
int j1; /* Addresss of jump instruction */
|
||||||
int j2 = 0, j3; /* Addresses of jump instructions */
|
|
||||||
int regData; /* Register containing first data column */
|
int regData; /* Register containing first data column */
|
||||||
int iCur; /* Table cursor number */
|
int iCur; /* Table cursor number */
|
||||||
Index *pIdx; /* Pointer to one of the indices */
|
Index *pIdx; /* Pointer to one of the indices */
|
||||||
|
Index *pPk = 0; /* The PRIMARY KEY index */
|
||||||
sqlite3 *db; /* Database connection */
|
sqlite3 *db; /* Database connection */
|
||||||
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
|
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
|
||||||
int regOldRowid = (pkChng && isUpdate) ? pkChng : regRowid;
|
int regOldPk; /* Previous rowid or PRIMARY KEY value */
|
||||||
|
int regNewPk = 0; /* New PRIMARY KEY value */
|
||||||
|
int pkCur = 0; /* Cursor used by the PRIMARY KEY */
|
||||||
|
|
||||||
|
regOldPk = (pkChng && isUpdate) ? pkChng : regRowid;
|
||||||
db = pParse->db;
|
db = pParse->db;
|
||||||
v = sqlite3GetVdbe(pParse);
|
v = sqlite3GetVdbe(pParse);
|
||||||
assert( v!=0 );
|
assert( v!=0 );
|
||||||
@@ -1233,6 +1272,17 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
nCol = pTab->nCol;
|
nCol = pTab->nCol;
|
||||||
regData = regRowid + 1;
|
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) ){
|
||||||
|
pkCur = baseCur+1;
|
||||||
|
pPk = pTab->pIndex;
|
||||||
|
while( ALWAYS(pPk) && pPk->autoIndex!=2 ){
|
||||||
|
pPk=pPk->pNext;
|
||||||
|
pkCur++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Test all NOT NULL constraints.
|
/* Test all NOT NULL constraints.
|
||||||
*/
|
*/
|
||||||
for(i=0; i<nCol; i++){
|
for(i=0; i<nCol; i++){
|
||||||
@@ -1309,19 +1359,23 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
/* If we have an INTEGER PRIMARY KEY, make sure the primary key
|
/* If we have an INTEGER PRIMARY KEY, make sure the primary key
|
||||||
** of the new record does not previously exist. Except, if this
|
** of the new record does not previously exist. Except, if this
|
||||||
** is an UPDATE and the primary key is not changing, that is OK.
|
** is an UPDATE and the primary key is not changing, that is OK.
|
||||||
|
**
|
||||||
|
** This block only runs for tables that have a rowid.
|
||||||
*/
|
*/
|
||||||
if( pkChng ){
|
if( pkChng && pkCur==0 ){
|
||||||
|
int addrRowidOk = sqlite3VdbeMakeLabel(v);
|
||||||
|
|
||||||
onError = pTab->keyConf;
|
onError = pTab->keyConf;
|
||||||
if( overrideError!=OE_Default ){
|
if( overrideError!=OE_Default ){
|
||||||
onError = overrideError;
|
onError = overrideError;
|
||||||
}else if( onError==OE_Default ){
|
}else if( onError==OE_Default ){
|
||||||
onError = OE_Abort;
|
onError = OE_Abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( isUpdate ){
|
if( isUpdate ){
|
||||||
j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, pkChng);
|
sqlite3VdbeAddOp3(v, OP_Eq, regRowid, addrRowidOk, pkChng);
|
||||||
}
|
}
|
||||||
j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
|
sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, addrRowidOk, regRowid);
|
||||||
switch( onError ){
|
switch( onError ){
|
||||||
default: {
|
default: {
|
||||||
onError = OE_Abort;
|
onError = OE_Abort;
|
||||||
@@ -1379,33 +1433,31 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3VdbeJumpHere(v, j3);
|
sqlite3VdbeResolveLabel(v, addrRowidOk);
|
||||||
if( isUpdate ){
|
|
||||||
sqlite3VdbeJumpHere(v, j2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test all UNIQUE constraints by creating entries for each UNIQUE
|
/* Test all UNIQUE constraints by creating entries for each UNIQUE
|
||||||
** index and making sure that duplicate entries do not already exist.
|
** index and making sure that duplicate entries do not already exist.
|
||||||
** Add the new records to the indices as we go.
|
** Compute the revised record entries for indices as we go.
|
||||||
*/
|
*/
|
||||||
for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
|
for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
|
||||||
int regIdx;
|
int regIdx;
|
||||||
int regR;
|
int regR;
|
||||||
int addrSkipRow = sqlite3VdbeMakeLabel(v);
|
int idxCur = baseCur+iCur+1;
|
||||||
|
int addrUniqueOk = sqlite3VdbeMakeLabel(v);
|
||||||
|
|
||||||
if( aRegIdx[iCur]==0 ) continue; /* Skip unused indices */
|
if( aRegIdx[iCur]==0 ) continue; /* Skip unused indices */
|
||||||
|
|
||||||
if( pIdx->pPartIdxWhere ){
|
if( pIdx->pPartIdxWhere ){
|
||||||
sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[iCur]);
|
sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[iCur]);
|
||||||
pParse->ckBase = regData;
|
pParse->ckBase = regData;
|
||||||
sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, addrSkipRow,
|
sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, addrUniqueOk,
|
||||||
SQLITE_JUMPIFNULL);
|
SQLITE_JUMPIFNULL);
|
||||||
pParse->ckBase = 0;
|
pParse->ckBase = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a key for accessing the index entry */
|
/* Create a key for accessing the index entry */
|
||||||
regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn+1);
|
regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn);
|
||||||
for(i=0; i<pIdx->nColumn; i++){
|
for(i=0; i<pIdx->nColumn; i++){
|
||||||
i16 idx = pIdx->aiColumn[i];
|
i16 idx = pIdx->aiColumn[i];
|
||||||
if( idx<0 || idx==pTab->iPKey ){
|
if( idx<0 || idx==pTab->iPKey ){
|
||||||
@@ -1422,7 +1474,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
onError = pIdx->onError;
|
onError = pIdx->onError;
|
||||||
if( onError==OE_None ){
|
if( onError==OE_None ){
|
||||||
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nKeyCol+1);
|
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nKeyCol+1);
|
||||||
sqlite3VdbeResolveLabel(v, addrSkipRow);
|
sqlite3VdbeResolveLabel(v, addrUniqueOk);
|
||||||
continue; /* pIdx is not a UNIQUE index */
|
continue; /* pIdx is not a UNIQUE index */
|
||||||
}
|
}
|
||||||
if( overrideError!=OE_Default ){
|
if( overrideError!=OE_Default ){
|
||||||
@@ -1437,11 +1489,35 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
|
|
||||||
/* Check to see if the new index entry will be unique */
|
/* Check to see if the new index entry will be unique */
|
||||||
regR = sqlite3GetTempReg(pParse);
|
regR = sqlite3GetTempReg(pParse);
|
||||||
sqlite3VdbeAddOp4Int(v, OP_NoConflict, baseCur+iCur+1, addrSkipRow,
|
sqlite3VdbeAddOp4Int(v, OP_NoConflict, idxCur, addrUniqueOk,
|
||||||
regIdx, pIdx->nKeyCol);
|
regIdx, pIdx->nKeyCol);
|
||||||
sqlite3VdbeAddOp2(v, OP_IdxRowid, baseCur+iCur+1, regR);
|
if( HasRowid(pTab) ){
|
||||||
sqlite3VdbeAddOp3(v, OP_Eq, regR, addrSkipRow, regOldRowid);
|
/* Conflict only if the rowid of the existing entry with the matching
|
||||||
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nKeyCol+1);
|
** key is different from old-rowid */
|
||||||
|
sqlite3VdbeAddOp2(v, OP_IdxRowid, idxCur, regR);
|
||||||
|
sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldPk);
|
||||||
|
}else if( pIdx->autoIndex==2 ){
|
||||||
|
/* If there is a matching entry on the PRIMARY KEY index ... */
|
||||||
|
int addrPkConflict = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol;
|
||||||
|
for(i=0; i<pPk->nKeyCol-1; i++){
|
||||||
|
sqlite3VdbeAddOp3(v, OP_Ne,
|
||||||
|
regOldPk+pPk->aiColumn[i], addrPkConflict, regIdx+i);
|
||||||
|
}
|
||||||
|
sqlite3VdbeAddOp3(v, OP_Eq,
|
||||||
|
regOldPk+pPk->aiColumn[i], addrUniqueOk, regIdx+i);
|
||||||
|
}else{
|
||||||
|
int addrConflict = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol*2;
|
||||||
|
assert( pIdx->nKeyCol + pPk->nKeyCol == pIdx->nColumn );
|
||||||
|
for(i=0; i<pPk->nKeyCol-1; i++){
|
||||||
|
sqlite3VdbeAddOp3(v, OP_Column, idxCur, pIdx->nKeyCol+i, regR);
|
||||||
|
sqlite3VdbeAddOp3(v, OP_Ne,
|
||||||
|
regOldPk+pPk->aiColumn[i], addrConflict, regR);
|
||||||
|
}
|
||||||
|
sqlite3VdbeAddOp3(v, OP_Column, idxCur, pIdx->nKeyCol+i, regR);
|
||||||
|
sqlite3VdbeAddOp3(v, OP_Eq,
|
||||||
|
regOldPk+pPk->aiColumn[i], addrUniqueOk, regR);
|
||||||
|
}
|
||||||
|
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
|
||||||
|
|
||||||
/* Generate code that executes if the new index entry is not unique */
|
/* Generate code that executes if the new index entry is not unique */
|
||||||
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|
||||||
@@ -1491,7 +1567,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3VdbeResolveLabel(v, addrSkipRow);
|
sqlite3VdbeResolveLabel(v, addrUniqueOk);
|
||||||
sqlite3ReleaseTempReg(pParse, regR);
|
sqlite3ReleaseTempReg(pParse, regR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3737,7 +3737,7 @@ case OP_Found: { /* jump, in3 */
|
|||||||
** The OP_NotFound opcode performs the same operation on index btrees
|
** The OP_NotFound opcode performs the same operation on index btrees
|
||||||
** (with arbitrary multi-value keys).
|
** (with arbitrary multi-value keys).
|
||||||
**
|
**
|
||||||
** See also: Found, NotFound, IsUnique
|
** See also: Found, NotFound, NoConflict
|
||||||
*/
|
*/
|
||||||
case OP_NotExists: { /* jump, in3 */
|
case OP_NotExists: { /* jump, in3 */
|
||||||
VdbeCursor *pC;
|
VdbeCursor *pC;
|
||||||
|
@@ -82,8 +82,7 @@ struct VdbeCursor {
|
|||||||
i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
|
i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
|
||||||
VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
|
VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
|
||||||
|
|
||||||
/* Result of last sqlite3BtreeMoveto() done by an OP_NotExists or
|
/* Result of last sqlite3BtreeMoveto() done by an OP_NotExists */
|
||||||
** OP_IsUnique opcode on this cursor. */
|
|
||||||
int seekResult;
|
int seekResult;
|
||||||
|
|
||||||
/* Cached information about the header for the data record that the
|
/* Cached information about the header for the data record that the
|
||||||
|
Reference in New Issue
Block a user