Size KeyInfo objects so that IdxInserts always compare the correct number of
fields. FossilOrigin-Name: 302a81390f039fc23eeb8510e95b9d9fa0b41edd
This commit is contained in:
parent
7913e41f6d
commit
1153c7b25d
20
manifest
20
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\ssqlite3_analyzer\sso\sthat\sit\sworks\swith\sWITHOUT\sROWID\stables.\nFix\sindex\sgeneration\sfor\ssecondary\sindices\sthat\sinclude\sfields\sfrom\nthe\sPRIMARY\sKEY.
|
||||
D 2013-11-01T20:30:36.718
|
||||
C Size\sKeyInfo\sobjects\sso\sthat\sIdxInserts\salways\scompare\sthe\scorrect\snumber\sof\nfields.
|
||||
D 2013-11-01T22:02:56.824
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -168,7 +168,7 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c 509722ce305471b626d3401c0631a808fd33237b
|
||||
F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf
|
||||
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
|
||||
F src/build.c 7a940e5e3ee55b3036be294571770c144751ee82
|
||||
F src/build.c bc63356abffdde0271f8d7667bad32e0566debe1
|
||||
F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
|
||||
@ -279,14 +279,14 @@ F src/update.c 94d63d3e06b09df3618655a841dc95d5b9466dc6
|
||||
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
||||
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
|
||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||
F src/vdbe.c 613af4c9ac24b1bf70fe35484502e74183492802
|
||||
F src/vdbe.c 9f3dc84302556f7731e53d64b5e6723b1e568b8d
|
||||
F src/vdbe.h c18a2dd91c838601b867a214e43c5f66d5d001ba
|
||||
F src/vdbeInt.h 42dcff74dbeb2b071e569b53f885fc9c2e4b4cb0
|
||||
F src/vdbeInt.h f2fa3ceccceeb757773921fb08af7c6e9f3caa1c
|
||||
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
|
||||
F src/vdbeaux.c cf6d0bc68fd1783747909cd14387bc06ac10a4e2
|
||||
F src/vdbeblob.c ef973d8d9f8170015343dd8824f795da675caa87
|
||||
F src/vdbemem.c 6087553f2c61c06c8e1ab3959a60e174d6240c98
|
||||
F src/vdbesort.c 3937e06b2a0e354500e17dc206ef4c35770a5017
|
||||
F src/vdbemem.c e62206af9efa102c5bae58269955cae1965ad728
|
||||
F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147
|
||||
F src/vdbetrace.c e7ec40e1999ff3c6414424365d5941178966dcbc
|
||||
F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d
|
||||
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
|
||||
@ -1128,7 +1128,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||
P 65384ae0f027d05cf9208faed56575870d63c486
|
||||
R b82044a07d71eebf83fb22f28eefd449
|
||||
P f9769d701c65770f4b8488f541c59e508393e6c2
|
||||
R 71880bd74bc5edec870109286fe9bf00
|
||||
U drh
|
||||
Z 66f9c600d762e843b5b86dd8d9c3ba4d
|
||||
Z 951dd2ac14cd893ffdc1dceac85de36b
|
||||
|
@ -1 +1 @@
|
||||
f9769d701c65770f4b8488f541c59e508393e6c2
|
||||
302a81390f039fc23eeb8510e95b9d9fa0b41edd
|
12
src/build.c
12
src/build.c
@ -2644,11 +2644,13 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
|
||||
|
||||
addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0);
|
||||
if( pIndex->onError!=OE_None ){
|
||||
assert( pKey!=0 || db->mallocFailed || pParse->nErr );
|
||||
if( pIndex->onError!=OE_None && pKey!=0 ){
|
||||
int j2 = sqlite3VdbeCurrentAddr(v) + 3;
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
|
||||
addr2 = sqlite3VdbeCurrentAddr(v);
|
||||
sqlite3VdbeAddOp3(v, OP_SorterCompare, iSorter, j2, regRecord);
|
||||
sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord,
|
||||
pKey->nField - pIndex->nKeyCol);
|
||||
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
|
||||
OE_Abort, "indexed columns are not unique", P4_STATIC
|
||||
);
|
||||
@ -4072,7 +4074,11 @@ KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){
|
||||
int nKey = pIdx->nKeyCol;
|
||||
KeyInfo *pKey;
|
||||
|
||||
pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey);
|
||||
if( pIdx->uniqNotNull ){
|
||||
pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey);
|
||||
}else{
|
||||
pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0);
|
||||
}
|
||||
if( pKey ){
|
||||
for(i=0; i<nCol; i++){
|
||||
char *zColl = pIdx->azColl[i];
|
||||
|
27
src/vdbe.c
27
src/vdbe.c
@ -3358,8 +3358,7 @@ case OP_OpenEphemeral: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: SorterOpen P1 P2 * P4 *
|
||||
** Synopsis: nColumn=P2
|
||||
/* Opcode: SorterOpen P1 * * P4 *
|
||||
**
|
||||
** This opcode works like OP_OpenEphemeral except that it opens
|
||||
** a transient index that is specifically designed to sort large
|
||||
@ -4194,22 +4193,32 @@ case OP_ResetCount: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: SorterCompare P1 P2 P3
|
||||
** Synopsis: if key(P1)!=r[P3] goto P2
|
||||
/* Opcode: SorterCompare P1 P2 P3 P4
|
||||
** Synopsis: if key(P1)!=rtrim(r[P3],P4) goto P2
|
||||
**
|
||||
** P1 is a sorter cursor. This instruction compares the record blob in
|
||||
** register P3 with the entry that the sorter cursor currently points to.
|
||||
** If, excluding the rowid fields at the end, the two records are a match,
|
||||
** fall through to the next instruction. Otherwise, jump to instruction P2.
|
||||
** P1 is a sorter cursor. This instruction compares a prefix of the
|
||||
** the record blob in register P3 against a prefix of the entry that
|
||||
** the sorter cursor currently points to. The final P4 fields of both
|
||||
** the P3 and sorter record are ignored.
|
||||
**
|
||||
** If either P3 or the sorter contains a NULL in one of their significant
|
||||
** fields (not counting the P4 fields at the end which are ignored) then
|
||||
** the comparison is assumed to be equal.
|
||||
**
|
||||
** Fall through to next instruction if the two records compare equal to
|
||||
** each other. Jump to P2 if they are different.
|
||||
*/
|
||||
case OP_SorterCompare: {
|
||||
VdbeCursor *pC;
|
||||
int res;
|
||||
int nIgnore;
|
||||
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( isSorter(pC) );
|
||||
assert( pOp->p4type==P4_INT32 );
|
||||
pIn3 = &aMem[pOp->p3];
|
||||
rc = sqlite3VdbeSorterCompare(pC, pIn3, &res);
|
||||
nIgnore = pOp->p4.i;
|
||||
rc = sqlite3VdbeSorterCompare(pC, pIn3, nIgnore, &res);
|
||||
if( res ){
|
||||
pc = pOp->p2-1;
|
||||
}
|
||||
|
@ -447,7 +447,7 @@ int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
|
||||
int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
|
||||
int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *);
|
||||
int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *);
|
||||
int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int *);
|
||||
int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
|
||||
|
||||
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
|
||||
void sqlite3VdbeEnter(Vdbe*);
|
||||
|
@ -1038,7 +1038,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
|
||||
if( pRec ){
|
||||
pRec->pKeyInfo = sqlite3IndexKeyinfo(p->pParse, pIdx);
|
||||
if( pRec->pKeyInfo ){
|
||||
assert( pRec->pKeyInfo->nField+1==nCol );
|
||||
assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol );
|
||||
pRec->pKeyInfo->enc = ENC(db);
|
||||
pRec->flags = UNPACKED_PREFIX_MATCH;
|
||||
pRec->aMem = (Mem *)&pRec[1];
|
||||
@ -1362,7 +1362,7 @@ int sqlite3Stat4ProbeSetValue(
|
||||
void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){
|
||||
if( pRec ){
|
||||
int i;
|
||||
int nCol = pRec->pKeyInfo->nField+1;
|
||||
int nCol = pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField;
|
||||
Mem *aMem = pRec->aMem;
|
||||
sqlite3 *db = aMem[0].db;
|
||||
for(i=0; i<nCol; i++){
|
||||
|
@ -386,7 +386,7 @@ static int vdbeSorterIterInit(
|
||||
*/
|
||||
static void vdbeSorterCompare(
|
||||
const VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */
|
||||
int bOmitRowid, /* Ignore rowid field at end of keys */
|
||||
int nIgnore, /* Ignore the last nIgnore fields */
|
||||
const void *pKey1, int nKey1, /* Left side of comparison */
|
||||
const void *pKey2, int nKey2, /* Right side of comparison */
|
||||
int *pRes /* OUT: Result of comparison */
|
||||
@ -400,8 +400,8 @@ static void vdbeSorterCompare(
|
||||
sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, r2);
|
||||
}
|
||||
|
||||
if( bOmitRowid ){
|
||||
r2->nField = pKeyInfo->nField;
|
||||
if( nIgnore ){
|
||||
r2->nField = pKeyInfo->nField - nIgnore;
|
||||
assert( r2->nField>0 );
|
||||
for(i=0; i<r2->nField; i++){
|
||||
if( r2->aMem[i].flags & MEM_Null ){
|
||||
@ -1027,12 +1027,13 @@ int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){
|
||||
int sqlite3VdbeSorterCompare(
|
||||
const VdbeCursor *pCsr, /* Sorter cursor */
|
||||
Mem *pVal, /* Value to compare to current sorter key */
|
||||
int nIgnore, /* Ignore this many fields at the end */
|
||||
int *pRes /* OUT: Result of comparison */
|
||||
){
|
||||
VdbeSorter *pSorter = pCsr->pSorter;
|
||||
void *pKey; int nKey; /* Sorter key to compare pVal with */
|
||||
|
||||
pKey = vdbeSorterRowkey(pSorter, &nKey);
|
||||
vdbeSorterCompare(pCsr, 1, pVal->z, pVal->n, pKey, nKey, pRes);
|
||||
vdbeSorterCompare(pCsr, nIgnore, pVal->z, pVal->n, pKey, nKey, pRes);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user