Size KeyInfo objects so that IdxInserts always compare the correct number of

fields.

FossilOrigin-Name: 302a81390f039fc23eeb8510e95b9d9fa0b41edd
This commit is contained in:
drh 2013-11-01 22:02:56 +00:00
parent 7913e41f6d
commit 1153c7b25d
7 changed files with 46 additions and 30 deletions

View File

@ -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

View File

@ -1 +1 @@
f9769d701c65770f4b8488f541c59e508393e6c2
302a81390f039fc23eeb8510e95b9d9fa0b41edd

View File

@ -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];

View File

@ -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;
}

View File

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

View File

@ -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++){

View File

@ -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;
}