1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-12-24 14:17:58 +03:00

The Index object now has nKeyCol and nColumn. nColumn is the total number

of columns and nKeyCol is the number of key columns.  Currently these always
differ by one.  Refactor aiColumn[] to be of type i16 instead of int.

FossilOrigin-Name: a106ce86cd4afd1f81603826de77df1fb25e9ab5
This commit is contained in:
drh
2013-10-22 18:01:40 +00:00
parent 77e57dfbc8
commit bbbdc83b52
14 changed files with 128 additions and 124 deletions

View File

@@ -1,5 +1,5 @@
C Add\sa\sprocedure\sto\shandle\sthe\smessy\sdetails\sof\sallocating\san\sIndex\sobject\nfrom\sthe\sheap.
D 2013-10-22T14:28:02.309
C The\sIndex\sobject\snow\shas\snKeyCol\sand\snColumn.\s\snColumn\sis\sthe\stotal\snumber\nof\scolumns\sand\snKeyCol\sis\sthe\snumber\sof\skey\scolumns.\s\sCurrently\sthese\salways\ndiffer\sby\sone.\s\sRefactor\saiColumn[]\sto\sbe\sof\stype\si16\sinstead\sof\sint.
D 2013-10-22T18:01:40.210
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -159,7 +159,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083
F src/analyze.c f1c5ed1fe128c3f106dcd95e97ee9ef94db7a3fa
F src/analyze.c ee880a4c0deb1c4090a4bbff03adfbf934451f50
F src/attach.c 0a17c9364895316ca4f52d06a97a72c0af1ae8b3
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3
@@ -168,21 +168,21 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 509722ce305471b626d3401c0631a808fd33237b
F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
F src/build.c 1c522019071838e71ab67366105d2e79860aaf4b
F src/build.c c29b38fb05dcd6c17990b3d2f2e6cdd66b5c42b7
F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
F src/delete.c 45788c5e48734f2af4acd75a876466e5b9838e34
F src/expr.c e7338ccffdc391c53ba2d51c5eb6a2f5299e040e
F src/delete.c c1547dbf732c9987d109b6f45729b4a70e14659e
F src/expr.c 040c0d340c6eed1d7316407fcd8ea6d4a50dc9d9
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 5dc10cbaa355753903cd2a64da040f948997ebf8
F src/fkey.c 628f81177299660a86e40359b3689b81f517e125
F src/func.c 2c47b65e6e00e3e9374942f28254faf8adafe398
F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c 9a3f578ffe37f18ef695a06764320db5dc1f0011
F src/insert.c c9db86093430946d08186117dab197fddf621a75
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
@@ -212,7 +212,7 @@ F src/parse.y 073a8294e1826f1b1656e84806b77e4199f4bb57
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
F src/pragma.c 64d3d1f8b4ed144ba85c061d00d96d6be8aa2fea
F src/pragma.c ab815d27690d24e87c953355a765edb546c47708
F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
@@ -223,7 +223,7 @@ F src/shell.c 6f11f0e9ded63d48e306f2c6858c521e568a47bb
F src/sqlite.h.in 547a44dd4ff4d975e92a645ea2d609e543a83d0f
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h bf4e57f30d67a0720fe7bc35926fdd0f0f07972f
F src/sqliteInt.h b365e0f5ae7e22a433be5d1595f62a9db66d11cc
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -275,7 +275,7 @@ F src/test_vfstrace.c 34b544e80ba7fb77be15395a609c669df2e660a2
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c 70061085a51f2f4fc15ece94f32c03bcb78e63b2
F src/trigger.c ba0a883cd536b7dfdd4df3733001f5372a4299da
F src/update.c f5182157f5d0d0a97bc5f5e3c9bdba0dfbe08f08
F src/update.c 2bb5a267796e6d0177ef5689487c3688de5c309e
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
F src/vacuum.c f313bc97123a4dd4bfd3f50a00c4d44c08a5b1b7
@@ -284,15 +284,15 @@ F src/vdbe.h 4f554b5627f26710c4c36d919110a3fc611ca5c4
F src/vdbeInt.h ff57f67aee1ba26a3a47e786533dab155ab6dad6
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
F src/vdbeaux.c 55f4858fe6abd84bd7311acbf30a75a28903ec25
F src/vdbeblob.c 5dc79627775bd9a9b494dd956e26297946417d69
F src/vdbemem.c 649933bad3e922465b726eaf85c72a75acba2ab7
F src/vdbeblob.c ef973d8d9f8170015343dd8824f795da675caa87
F src/vdbemem.c 6087553f2c61c06c8e1ab3959a60e174d6240c98
F src/vdbesort.c 3937e06b2a0e354500e17dc206ef4c35770a5017
F src/vdbetrace.c e7ec40e1999ff3c6414424365d5941178966dcbc
F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
F src/where.c a5253015dc9ad53e9b811affa062cac6fef47729
F src/where.c 32b6e99b4343958f5ca641e3d62fe3da072f7128
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
@@ -1127,7 +1127,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 5ca0ea2e9b40a7fa133d2af8a2ecc676de7a8723
R af47abc49940901bd05e026560bdb4b9
P 45efc94f9a8169433ffcb4aa35760551c55df4c4
R 01cd56332e89d0bc92e41f690b42402c
U drh
Z 079ab6bb649eb152e2879418f011e61b
Z 6297f61b2d795cc46624c31a3c77d60c

View File

@@ -1 +1 @@
45efc94f9a8169433ffcb4aa35760551c55df4c4
a106ce86cd4afd1f81603826de77df1fb25e9ab5

View File

@@ -916,7 +916,7 @@ static void analyzeOneTable(
if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
if( pIdx->pPartIdxWhere==0 ) needTableCnt = 0;
VdbeNoopComment((v, "Begin analysis of %s", pIdx->zName));
nCol = pIdx->nColumn;
nCol = pIdx->nKeyCol;
aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*(nCol+1));
if( aGotoChng==0 ) continue;
pKey = sqlite3IndexKeyinfo(pParse, pIdx);
@@ -1081,7 +1081,7 @@ static void analyzeOneTable(
pIdx->aiColumn[0], regSample);
#else
for(i=0; i<nCol; i++){
int iCol = pIdx->aiColumn[i];
i16 iCol = pIdx->aiColumn[i];
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, iCol, regCol+i);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol+1, regSample);
@@ -1337,7 +1337,7 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
z = argv[2];
if( pIndex ){
decodeIntArray((char*)z, pIndex->nColumn+1, pIndex->aiRowEst, pIndex);
decodeIntArray((char*)z, pIndex->nKeyCol+1, pIndex->aiRowEst, pIndex);
if( pIndex->pPartIdxWhere==0 ) pTable->nRowEst = pIndex->aiRowEst[0];
}else{
Index fakeIdx;
@@ -1383,7 +1383,7 @@ static void initAvgEq(Index *pIdx){
IndexSample *aSample = pIdx->aSample;
IndexSample *pFinal = &aSample[pIdx->nSample-1];
int iCol;
for(iCol=0; iCol<pIdx->nColumn; iCol++){
for(iCol=0; iCol<pIdx->nKeyCol; iCol++){
int i; /* Used to iterate through samples */
tRowcnt sumEq = 0; /* Sum of the nEq values */
tRowcnt nSum = 0; /* Number of terms contributing to sumEq */
@@ -1466,8 +1466,8 @@ static int loadStatTbl(
** loaded from the stat4 table. In this case ignore stat3 data. */
if( pIdx==0 || pIdx->nSample ) continue;
if( bStat3==0 ){
nIdxCol = pIdx->nColumn+1;
nAvgCol = pIdx->nColumn;
nIdxCol = pIdx->nKeyCol+1;
nAvgCol = pIdx->nKeyCol;
}
pIdx->nSampleCol = nIdxCol;
nByte = sizeof(IndexSample) * nSample;

View File

@@ -1314,7 +1314,7 @@ void sqlite3AddCollateType(Parse *pParse, Token *pToken){
** collation type was added. Correct this if it is the case.
*/
for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
assert( pIdx->nColumn==1 );
assert( pIdx->nKeyCol==1 );
if( pIdx->aiColumn[0]==i ){
pIdx->azColl[0] = p->aCol[i].zColl;
}
@@ -1524,12 +1524,13 @@ static void estimateTableWidth(Table *pTab){
** Estimate the average size of a row for an index.
*/
static void estimateIndexWidth(Index *pIdx){
unsigned wIndex = 1;
unsigned wIndex = 0;
int i;
const Column *aCol = pIdx->pTable->aCol;
for(i=0; i<pIdx->nColumn; i++){
assert( pIdx->aiColumn[i]>=0 && pIdx->aiColumn[i]<pIdx->pTable->nCol );
wIndex += aCol[pIdx->aiColumn[i]].szEst;
i16 x = pIdx->aiColumn[i];
assert( x<pIdx->pTable->nCol );
wIndex += x<0 ? 1 : aCol[pIdx->aiColumn[i]].szEst;
}
pIdx->szIdxRow = sqlite3LogEst(wIndex*4);
}
@@ -2524,7 +2525,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
*/
Index *sqlite3AllocateIndexObject(
sqlite3 *db, /* Database connection */
int nCol, /* Number of columns in the index */
i16 nCol, /* Total number of columns in the index */
int nExtra, /* Number of bytes of extra space to alloc */
char **ppExtra /* Pointer to the "extra" space */
){
@@ -2534,16 +2535,17 @@ Index *sqlite3AllocateIndexObject(
nByte = ROUND8(sizeof(Index)) + /* Index structure */
ROUND8(sizeof(char*)*nCol) + /* Index.azColl */
ROUND8(sizeof(tRowcnt)*(nCol+1) + /* Index.aiRowEst */
sizeof(int)*nCol + /* Index.aiColumn */
sizeof(i16)*nCol + /* Index.aiColumn */
sizeof(u8)*nCol); /* Index.aSortOrder */
p = sqlite3DbMallocZero(db, nByte + nExtra);
if( p ){
char *pExtra = ((char*)p)+ROUND8(sizeof(Index));
p->azColl = (char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol);
p->aiRowEst = (tRowcnt*)pExtra; pExtra += sizeof(tRowcnt)*(nCol+1);
p->aiColumn = (int*)pExtra; pExtra += sizeof(int)*nCol;
p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol;
p->aSortOrder = (u8*)pExtra;
p->nColumn = nCol;
p->nKeyCol = nCol - 1;
*ppExtra = ((char*)p) + nByte;
}
return p;
@@ -2763,7 +2765,7 @@ Index *sqlite3CreateIndex(
** Allocate the index structure.
*/
nName = sqlite3Strlen30(zName);
pIndex = sqlite3AllocateIndexObject(db, pList->nExpr,
pIndex = sqlite3AllocateIndexObject(db, pList->nExpr + 1,
nName + nExtra + 1, &zExtra);
if( db->mallocFailed ){
goto exit_create_index;
@@ -2774,7 +2776,6 @@ Index *sqlite3CreateIndex(
zExtra += nName + 1;
memcpy(pIndex->zName, zName, nName+1);
pIndex->pTable = pTab;
pIndex->nColumn = pList->nExpr;
pIndex->onError = (u8)onError;
pIndex->uniqNotNull = onError==OE_Abort;
pIndex->autoIndex = (u8)(pName==0);
@@ -2818,7 +2819,8 @@ Index *sqlite3CreateIndex(
pParse->checkSchema = 1;
goto exit_create_index;
}
pIndex->aiColumn[i] = j;
assert( pTab->nCol<=0x7fff && j<=0x7fff );
pIndex->aiColumn[i] = (i16)j;
if( pListItem->pExpr ){
int nColl;
assert( pListItem->pExpr->op==TK_COLLATE );
@@ -2841,6 +2843,8 @@ Index *sqlite3CreateIndex(
pIndex->aSortOrder[i] = (u8)requestedSortOrder;
if( pTab->aCol[j].notNull==0 ) pIndex->uniqNotNull = 0;
}
pIndex->aiColumn[i] = -1;
pIndex->azColl[i] = "BINARY";
sqlite3DefaultRowEst(pIndex);
if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex);
@@ -2873,8 +2877,8 @@ Index *sqlite3CreateIndex(
assert( pIdx->autoIndex );
assert( pIndex->onError!=OE_None );
if( pIdx->nColumn!=pIndex->nColumn ) continue;
for(k=0; k<pIdx->nColumn; k++){
if( pIdx->nKeyCol!=pIndex->nKeyCol ) continue;
for(k=0; k<pIdx->nKeyCol; k++){
const char *z1;
const char *z2;
if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break;
@@ -2882,7 +2886,7 @@ Index *sqlite3CreateIndex(
z2 = pIndex->azColl[k];
if( z1!=z2 && sqlite3StrICmp(z1, z2) ) break;
}
if( k==pIdx->nColumn ){
if( k==pIdx->nKeyCol ){
if( pIdx->onError!=pIndex->onError ){
/* This constraint creates the same index as a previous
** constraint specified somewhere in the CREATE TABLE statement.
@@ -3051,12 +3055,12 @@ void sqlite3DefaultRowEst(Index *pIdx){
a[0] = pIdx->pTable->nRowEst;
if( a[0]<10 ) a[0] = 10;
n = 10;
for(i=1; i<=pIdx->nColumn; i++){
for(i=1; i<=pIdx->nKeyCol; i++){
a[i] = n;
if( n>5 ) n--;
}
if( pIdx->onError!=OE_None ){
a[pIdx->nColumn] = 1;
a[pIdx->nKeyCol] = 1;
}
}
@@ -3764,8 +3768,8 @@ static int collationMatch(const char *zColl, Index *pIndex){
assert( zColl!=0 );
for(i=0; i<pIndex->nColumn; i++){
const char *z = pIndex->azColl[i];
assert( z!=0 );
if( 0==sqlite3StrICmp(z, zColl) ){
assert( z!=0 || pIndex->aiColumn[i]<0 );
if( pIndex->aiColumn[i]>=0 && 0==sqlite3StrICmp(z, zColl) ){
return 1;
}
}
@@ -3895,7 +3899,7 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
*/
KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){
int i;
int nCol = pIdx->nColumn;
int nCol = pIdx->nKeyCol;
KeyInfo *pKey;
pKey = sqlite3KeyInfoAlloc(pParse->db, nCol);

View File

@@ -598,7 +598,7 @@ void sqlite3GenerateRowIndexDelete(
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 0, &iPartIdxLabel);
sqlite3VdbeAddOp3(v, OP_IdxDelete, iCur+i, r1, pIdx->nColumn+1);
sqlite3VdbeAddOp3(v, OP_IdxDelete, iCur+i, r1, pIdx->nKeyCol+1);
sqlite3VdbeResolveLabel(v, iPartIdxLabel);
}
}
@@ -645,11 +645,11 @@ int sqlite3GenerateIndexKey(
*piPartIdxLabel = 0;
}
}
nCol = pIdx->nColumn;
nCol = pIdx->nKeyCol;
regBase = sqlite3GetTempRange(pParse, nCol+1);
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+nCol);
for(j=0; j<nCol; j++){
int idx = pIdx->aiColumn[j];
i16 idx = pIdx->aiColumn[j];
if( idx==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_SCopy, regBase+nCol, regBase+j);
}else{

View File

@@ -1532,8 +1532,8 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
sqlite3 *db = pParse->db; /* Database connection */
Table *pTab; /* Table <table>. */
Expr *pExpr; /* Expression <column> */
int iCol; /* Index of column <column> */
int iDb; /* Database idx for pTab */
i16 iCol; /* Index of column <column> */
i16 iDb; /* Database idx for pTab */
assert( p ); /* Because of isCandidateForInOpt(p) */
assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */
@@ -1541,7 +1541,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */
pTab = p->pSrc->a[0].pTab;
pExpr = p->pEList->a[0].pExpr;
iCol = pExpr->iColumn;
iCol = (i16)pExpr->iColumn;
/* Code an OP_VerifyCookie and OP_TableLock for <table>. */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -1579,7 +1579,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){
if( (pIdx->aiColumn[0]==iCol)
&& sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq
&& (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None))
&& (!mustBeUnique || (pIdx->nKeyCol==1 && pIdx->onError!=OE_None))
){
int iAddr;
char *pKey;

View File

@@ -225,7 +225,7 @@ int sqlite3FkLocateIndex(
}
for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){
if( pIdx->nColumn==nCol && pIdx->onError!=OE_None ){
if( pIdx->nKeyCol==nCol && pIdx->onError!=OE_None ){
/* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number
** of columns. If each indexed column corresponds to a foreign key
** column of pFKey, then this index is a winner. */
@@ -248,7 +248,7 @@ int sqlite3FkLocateIndex(
** the default collation sequences for each column. */
int i, j;
for(i=0; i<nCol; i++){
int iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */
i16 iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */
char *zDfltColl; /* Def. collation for column */
char *zIdxCol; /* Name of indexed column */
@@ -509,7 +509,7 @@ static void fkScanChildren(
Expr *pLeft; /* Value from parent table row */
Expr *pRight; /* Column ref to child table */
Expr *pEq; /* Expression (pLeft = pRight) */
int iCol; /* Index of column in child table */
i16 iCol; /* Index of column in child table */
const char *zCol; /* Name of column in child table */
pLeft = sqlite3Expr(db, TK_REGISTER, 0);
@@ -966,7 +966,7 @@ u32 sqlite3FkOldmask(
Index *pIdx = 0;
sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
if( pIdx ){
for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
for(i=0; i<pIdx->nKeyCol; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
}
}
}

View File

@@ -67,12 +67,12 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
int n;
Table *pTab = pIdx->pTable;
sqlite3 *db = sqlite3VdbeDb(v);
pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+2);
pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nKeyCol+2);
if( !pIdx->zColAff ){
db->mallocFailed = 1;
return 0;
}
for(n=0; n<pIdx->nColumn; n++){
for(n=0; n<pIdx->nKeyCol; n++){
pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity;
}
pIdx->zColAff[n++] = SQLITE_AFF_INTEGER;
@@ -1393,24 +1393,23 @@ void sqlite3GenerateConstraintChecks(
}
/* Create a key for accessing the index entry */
regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn+1);
regIdx = sqlite3GetTempRange(pParse, pIdx->nKeyCol+1);
for(i=0; i<pIdx->nColumn; i++){
int idx = pIdx->aiColumn[i];
if( idx==pTab->iPKey ){
i16 idx = pIdx->aiColumn[i];
if( idx<0 || idx==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
}else{
sqlite3VdbeAddOp2(v, OP_SCopy, regData+idx, regIdx+i);
}
}
sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[iCur]);
sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), P4_TRANSIENT);
sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1);
sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn);
/* Find out what action to take in case there is an indexing conflict */
onError = pIdx->onError;
if( onError==OE_None ){
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nKeyCol+1);
sqlite3VdbeResolveLabel(v, addrSkipRow);
continue; /* pIdx is not a UNIQUE index */
}
@@ -1430,7 +1429,7 @@ void sqlite3GenerateConstraintChecks(
j3 = sqlite3VdbeAddOp4(v, OP_IsUnique, baseCur+iCur+1, 0,
regR, SQLITE_INT_TO_PTR(regIdx),
P4_INT32);
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nKeyCol+1);
/* Generate code that executes if the new index entry is not unique */
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
@@ -1446,15 +1445,15 @@ void sqlite3GenerateConstraintChecks(
sqlite3StrAccumInit(&errMsg, 0, 0, 200);
errMsg.db = db;
zSep = pIdx->nColumn>1 ? "columns " : "column ";
for(j=0; j<pIdx->nColumn; j++){
zSep = pIdx->nKeyCol>1 ? "columns " : "column ";
for(j=0; j<pIdx->nKeyCol; j++){
char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
sqlite3StrAccumAppend(&errMsg, zSep, -1);
zSep = ", ";
sqlite3StrAccumAppend(&errMsg, zCol, -1);
}
sqlite3StrAccumAppend(&errMsg,
pIdx->nColumn>1 ? " are not unique" : " is not unique", -1);
pIdx->nKeyCol>1 ? " are not unique" : " is not unique", -1);
zErr = sqlite3StrAccumFinish(&errMsg);
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
onError, zErr, 0);
@@ -1631,13 +1630,13 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){
int i;
assert( pDest && pSrc );
assert( pDest->pTable!=pSrc->pTable );
if( pDest->nColumn!=pSrc->nColumn ){
if( pDest->nKeyCol!=pSrc->nKeyCol ){
return 0; /* Different number of columns */
}
if( pDest->onError!=pSrc->onError ){
return 0; /* Different conflict resolution strategies */
}
for(i=0; i<pSrc->nColumn; i++){
for(i=0; i<pSrc->nKeyCol; i++){
if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){
return 0; /* Different columns indexed */
}

View File

@@ -1475,8 +1475,8 @@ void sqlite3Pragma(
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC);
for(i=0; i<pIdx->nColumn; i++){
int cnum = pIdx->aiColumn[i];
for(i=0; i<pIdx->nKeyCol; i++){
i16 cnum = pIdx->aiColumn[i];
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2);
assert( pTab->nCol>cnum );
@@ -1872,7 +1872,7 @@ void sqlite3Pragma(
};
r1 = sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 0, &jmp3);
sqlite3VdbeAddOp2(v, OP_AddImm, 7+j, 1); /* increment entry count */
jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, j+2, 0, r1, pIdx->nColumn+1);
jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, j+2, 0, r1, pIdx->nKeyCol+1);
addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC);
sqlite3VdbeChangeP4(v, addr+3, " missing from index ", P4_STATIC);

View File

@@ -1577,7 +1577,7 @@ struct UnpackedRecord {
*/
struct Index {
char *zName; /* Name of this index */
int *aiColumn; /* Which columns are used by this index. 1st is 0 */
i16 *aiColumn; /* Which columns are used by this index. 1st is 0 */
tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */
Table *pTable; /* The SQL table being indexed */
char *zColAff; /* String defining the affinity of each column */
@@ -1588,7 +1588,8 @@ struct Index {
Expr *pPartIdxWhere; /* WHERE clause for partial indices */
int tnum; /* DB Page containing root of this index */
LogEst szIdxRow; /* Estimated average row size in bytes */
u16 nColumn; /* Number of columns in table used by this index */
u16 nKeyCol; /* Number of columns forming the key */
u16 nColumn; /* Number of columns stored in the index */
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
unsigned bUnordered:1; /* Use this index for == or IN queries only */
@@ -2826,7 +2827,7 @@ void sqlite3SrcListShiftJoinType(SrcList*);
void sqlite3SrcListAssignCursors(Parse*, SrcList*);
void sqlite3IdListDelete(sqlite3*, IdList*);
void sqlite3SrcListDelete(sqlite3*, SrcList*);
Index *sqlite3AllocateIndexObject(sqlite3*,int,int,char**);
Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**);
Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
Expr*, int, int);
void sqlite3DropIndex(Parse*, SrcList*, int);

View File

@@ -250,7 +250,7 @@ void sqlite3Update(
reg = ++pParse->nMem;
}else{
reg = 0;
for(i=0; i<pIdx->nColumn; i++){
for(i=0; i<pIdx->nKeyCol; i++){
if( aXRef[pIdx->aiColumn[i]]>=0 ){
reg = ++pParse->nMem;
break;

View File

@@ -235,7 +235,7 @@ int sqlite3_blob_open(
#endif
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
int j;
for(j=0; j<pIdx->nColumn; j++){
for(j=0; j<pIdx->nKeyCol; j++){
if( pIdx->aiColumn[j]==iCol ){
zFault = "indexed";
}

View File

@@ -1031,7 +1031,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
Index *pIdx = p->pIdx; /* Index being probed */
int nByte; /* Bytes of space to allocate */
int i; /* Counter variable */
int nCol = pIdx->nColumn+1; /* Number of index columns including rowid */
int nCol = pIdx->nKeyCol+1; /* Number of index columns including rowid */
nByte = sizeof(Mem) * nCol + sizeof(UnpackedRecord);
pRec = (UnpackedRecord*)sqlite3DbMallocZero(db, nByte);

View File

@@ -968,7 +968,7 @@ static WhereTerm *whereScanInit(
if( pIdx && iColumn>=0 ){
pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
if( NEVER(j>=pIdx->nColumn) ) return 0;
if( NEVER(j>=pIdx->nKeyCol) ) return 0;
}
pScan->zCollName = pIdx->azColl[j];
}else{
@@ -1898,16 +1898,16 @@ static int isDistinctRedundant(
*/
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( pIdx->onError==OE_None ) continue;
for(i=0; i<pIdx->nColumn; i++){
int iCol = pIdx->aiColumn[i];
for(i=0; i<pIdx->nKeyCol; i++){
i16 iCol = pIdx->aiColumn[i];
if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx) ){
int iIdxCol = findIndexCol(pParse, pDistinct, iBase, pIdx, i);
if( iIdxCol<0 || pTab->aCol[pIdx->aiColumn[i]].notNull==0 ){
if( iIdxCol<0 || pTab->aCol[iCol].notNull==0 ){
break;
}
}
}
if( i==pIdx->nColumn ){
if( i==pIdx->nKeyCol ){
/* This index implies that the DISTINCT qualifier is redundant. */
return 1;
}
@@ -2005,7 +2005,7 @@ static void constructAutomaticIndex(
Bitmask notReady, /* Mask of cursors that are not available */
WhereLevel *pLevel /* Write new index here */
){
int nColumn; /* Number of columns in the constructed index */
int nKeyCol; /* Number of columns in the constructed index */
WhereTerm *pTerm; /* A single term of the WHERE clause */
WhereTerm *pWCEnd; /* End of pWC->a[] */
Index *pIdx; /* Object describing the transient index */
@@ -2033,7 +2033,7 @@ static void constructAutomaticIndex(
/* Count the number of columns that will be added to the index
** and used to match WHERE clause constraints */
nColumn = 0;
nKeyCol = 0;
pTable = pSrc->pTab;
pWCEnd = &pWC->a[pWC->nTerm];
pLoop = pLevel->pWLoop;
@@ -2051,14 +2051,14 @@ static void constructAutomaticIndex(
sentWarning = 1;
}
if( (idxCols & cMask)==0 ){
if( whereLoopResize(pParse->db, pLoop, nColumn+1) ) return;
pLoop->aLTerm[nColumn++] = pTerm;
if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ) return;
pLoop->aLTerm[nKeyCol++] = pTerm;
idxCols |= cMask;
}
}
}
assert( nColumn>0 );
pLoop->u.btree.nEq = pLoop->nLTerm = nColumn;
assert( nKeyCol>0 );
pLoop->u.btree.nEq = pLoop->nLTerm = nKeyCol;
pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED
| WHERE_AUTO_INDEX;
@@ -2075,15 +2075,15 @@ static void constructAutomaticIndex(
testcase( pTable->nCol==BMS-1 );
testcase( pTable->nCol==BMS-2 );
for(i=0; i<mxBitCol; i++){
if( extraCols & MASKBIT(i) ) nColumn++;
if( extraCols & MASKBIT(i) ) nKeyCol++;
}
if( pSrc->colUsed & MASKBIT(BMS-1) ){
nColumn += pTable->nCol - BMS + 1;
nKeyCol += pTable->nCol - BMS + 1;
}
pLoop->wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY;
/* Construct the Index object to describe this index */
pIdx = sqlite3AllocateIndexObject(pParse->db, nColumn, 0, &zNotUsed);
pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+1, 0, &zNotUsed);
if( pIdx==0 ) return;
pLoop->u.btree.pIndex = pIdx;
pIdx->zName = "auto-index";
@@ -2124,13 +2124,13 @@ static void constructAutomaticIndex(
n++;
}
}
assert( n==nColumn );
assert( n==nKeyCol );
/* Create the automatic index */
pKeyinfo = sqlite3IndexKeyinfo(pParse, pIdx);
assert( pLevel->iIdxCur>=0 );
pLevel->iIdxCur = pParse->nTab++;
sqlite3VdbeAddOp4(v, OP_OpenAutoindex, pLevel->iIdxCur, nColumn+1, 0,
sqlite3VdbeAddOp4(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1, 0,
(char*)pKeyinfo, P4_KEYINFO_HANDOFF);
VdbeComment((v, "for %s", pTable->zName));
@@ -2384,7 +2384,7 @@ static void whereKeyStats(
iUpper = i>=pIdx->nSample ? pIdx->aiRowEst[0] : aSample[i].anLt[iCol];
iLower = aSample[i-1].anEq[iCol] + aSample[i-1].anLt[iCol];
}
aStat[1] = (pIdx->nColumn>iCol ? pIdx->aAvgEq[iCol] : 1);
aStat[1] = (pIdx->nKeyCol>iCol ? pIdx->aAvgEq[iCol] : 1);
if( iLower>=iUpper ){
iGap = 0;
}else{
@@ -2484,7 +2484,7 @@ static int whereRangeScanEst(
tRowcnt iLower;
tRowcnt iUpper;
if( nEq==p->nColumn ){
if( nEq==p->nKeyCol ){
aff = SQLITE_AFF_INTEGER;
}else{
aff = p->pTable->aCol[p->aiColumn[nEq]].affinity;
@@ -2602,7 +2602,7 @@ static int whereEqualScanEst(
int bOk;
assert( nEq>=1 );
assert( nEq<=(p->nColumn+1) );
assert( nEq<=(p->nKeyCol+1) );
assert( p->aSample!=0 );
assert( p->nSample>0 );
assert( pBuilder->nRecValid<nEq );
@@ -2615,7 +2615,7 @@ static int whereEqualScanEst(
/* This is an optimization only. The call to sqlite3Stat4ProbeSetValue()
** below would return the same value. */
if( nEq>p->nColumn ){
if( nEq>p->nKeyCol ){
*pnRow = 1;
return SQLITE_OK;
}
@@ -3002,7 +3002,7 @@ static char *explainIndexRange(sqlite3 *db, WhereLoop *pLoop, Table *pTab){
int nEq = pLoop->u.btree.nEq;
int i, j;
Column *aCol = pTab->aCol;
int *aiColumn = pIndex->aiColumn;
i16 *aiColumn = pIndex->aiColumn;
StrAccum txt;
if( nEq==0 && (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){
@@ -3012,17 +3012,17 @@ static char *explainIndexRange(sqlite3 *db, WhereLoop *pLoop, Table *pTab){
txt.db = db;
sqlite3StrAccumAppend(&txt, " (", 2);
for(i=0; i<nEq; i++){
char *z = (i==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[i]].zName;
char *z = (i==pIndex->nKeyCol ) ? "rowid" : aCol[aiColumn[i]].zName;
explainAppendTerm(&txt, i, z, "=");
}
j = i;
if( pLoop->wsFlags&WHERE_BTM_LIMIT ){
char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
char *z = (j==pIndex->nKeyCol ) ? "rowid" : aCol[aiColumn[j]].zName;
explainAppendTerm(&txt, i++, z, ">");
}
if( pLoop->wsFlags&WHERE_TOP_LIMIT ){
char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
char *z = (j==pIndex->nKeyCol ) ? "rowid" : aCol[aiColumn[j]].zName;
explainAppendTerm(&txt, i, z, "<");
}
sqlite3StrAccumAppend(&txt, ")", 1);
@@ -3406,7 +3406,7 @@ static Bitmask codeOneLoopStart(
*/
if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0
&& (pWInfo->bOBSat!=0)
&& (pIdx->nColumn>nEq)
&& (pIdx->nKeyCol>nEq)
){
/* assert( pOrderBy->nExpr==1 ); */
/* assert( pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq] ); */
@@ -3439,8 +3439,8 @@ static Bitmask codeOneLoopStart(
** a forward order scan on a descending index, interchange the
** start and end terms (pRangeStart and pRangeEnd).
*/
if( (nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC))
|| (bRev && pIdx->nColumn==nEq)
if( (nEq<pIdx->nKeyCol && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC))
|| (bRev && pIdx->nKeyCol==nEq)
){
SWAP(WhereTerm *, pRangeEnd, pRangeStart);
}
@@ -4243,8 +4243,8 @@ static int whereLoopAddBtreeIndex(
}
if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
assert( pNew->u.btree.nEq<=pProbe->nColumn );
if( pNew->u.btree.nEq < pProbe->nColumn ){
assert( pNew->u.btree.nEq<=pProbe->nKeyCol );
if( pNew->u.btree.nEq < pProbe->nKeyCol ){
iCol = pProbe->aiColumn[pNew->u.btree.nEq];
nRowEst = sqlite3LogEst(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1;
@@ -4301,7 +4301,7 @@ static int whereLoopAddBtreeIndex(
pNew->wsFlags |= WHERE_COLUMN_EQ;
if( iCol<0
|| (pProbe->onError!=OE_None && nInMul==0
&& pNew->u.btree.nEq==pProbe->nColumn-1)
&& pNew->u.btree.nEq==pProbe->nKeyCol-1)
){
assert( (pNew->wsFlags & WHERE_COLUMN_IN)==0 || iCol<0 );
pNew->wsFlags |= WHERE_ONEROW;
@@ -4367,7 +4367,7 @@ static int whereLoopAddBtreeIndex(
whereLoopOutputAdjust(pBuilder->pWC, pNew);
rc = whereLoopInsert(pBuilder, pNew);
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
&& pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0))
&& pNew->u.btree.nEq<(pProbe->nKeyCol + (pProbe->zName!=0))
){
whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
}
@@ -4406,7 +4406,7 @@ static int indexMightHelpWithOrderBy(
Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr);
if( pExpr->op!=TK_COLUMN ) return 0;
if( pExpr->iTable==iCursor ){
for(jj=0; jj<pIndex->nColumn; jj++){
for(jj=0; jj<pIndex->nKeyCol; jj++){
if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1;
}
}
@@ -4421,7 +4421,7 @@ static int indexMightHelpWithOrderBy(
static Bitmask columnsInIndex(Index *pIdx){
Bitmask m = 0;
int j;
for(j=pIdx->nColumn-1; j>=0; j--){
for(j=pIdx->nKeyCol-1; j>=0; j--){
int x = pIdx->aiColumn[j];
assert( x>=0 );
testcase( x==BMS-1 );
@@ -4456,7 +4456,7 @@ static int whereLoopAddBtree(
Index *pProbe; /* An index we are evaluating */
Index sPk; /* A fake index object for the primary key */
tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */
int aiColumnPk = -1; /* The aColumn[] value for the sPk index */
i16 aiColumnPk = -1; /* The aColumn[] value for the sPk index */
SrcList *pTabList; /* The FROM clause */
struct SrcList_item *pSrc; /* The FROM clause btree term to add */
WhereLoop *pNew; /* Template WhereLoop object */
@@ -4486,7 +4486,7 @@ static int whereLoopAddBtree(
** indices to follow */
Index *pFirst; /* First of real indices on the table */
memset(&sPk, 0, sizeof(Index));
sPk.nColumn = 1;
sPk.nKeyCol = 1;
sPk.aiColumn = &aiColumnPk;
sPk.aiRowEst = aiRowEstPk;
sPk.onError = OE_Replace;
@@ -4961,7 +4961,7 @@ static int wherePathSatisfiesOrderBy(
u8 isOrderDistinct; /* All prior WhereLoops are order-distinct */
u8 distinctColumns; /* True if the loop has UNIQUE NOT NULL columns */
u8 isMatch; /* iColumn matches a term of the ORDER BY clause */
u16 nColumn; /* Number of columns in pIndex */
u16 nKeyCol; /* Number of columns in pIndex */
u16 nOrderBy; /* Number terms in the ORDER BY clause */
int iLoop; /* Index of WhereLoop in pPath being processed */
int i, j; /* Loop counters */
@@ -5053,11 +5053,11 @@ static int wherePathSatisfiesOrderBy(
if( (pLoop->wsFlags & WHERE_ONEROW)==0 ){
if( pLoop->wsFlags & WHERE_IPK ){
pIndex = 0;
nColumn = 0;
nKeyCol = 0;
}else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){
return 0;
}else{
nColumn = pIndex->nColumn;
nKeyCol = pIndex->nKeyCol;
isOrderDistinct = pIndex->onError!=OE_None;
}
@@ -5066,7 +5066,7 @@ static int wherePathSatisfiesOrderBy(
*/
rev = revSet = 0;
distinctColumns = 0;
for(j=0; j<=nColumn; j++){
for(j=0; j<=nKeyCol; j++){
u8 bOnce; /* True to run the ORDER BY search loop */
/* Skip over == and IS NULL terms */
@@ -5083,14 +5083,14 @@ static int wherePathSatisfiesOrderBy(
/* Get the column number in the table (iColumn) and sort order
** (revIdx) for the j-th column of the index.
*/
if( j<nColumn ){
if( j<nKeyCol ){
/* Normal index columns */
iColumn = pIndex->aiColumn[j];
revIdx = pIndex->aSortOrder[j];
if( iColumn==pIndex->pTable->iPKey ) iColumn = -1;
}else{
/* The ROWID column at the end */
assert( j==nColumn );
assert( j==nKeyCol );
iColumn = -1;
revIdx = 0;
}
@@ -5147,7 +5147,7 @@ static int wherePathSatisfiesOrderBy(
}
}else{
/* No match found */
if( j==0 || j<nColumn ){
if( j==0 || j<nKeyCol ){
testcase( isOrderDistinct!=0 );
isOrderDistinct = 0;
}
@@ -5513,14 +5513,14 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
assert( ArraySize(pLoop->aLTermSpace)==4 );
if( pIdx->onError==OE_None
|| pIdx->pPartIdxWhere!=0
|| pIdx->nColumn>ArraySize(pLoop->aLTermSpace)
|| pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace)
) continue;
for(j=0; j<pIdx->nColumn; j++){
for(j=0; j<pIdx->nKeyCol; j++){
pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx);
if( pTerm==0 ) break;
pLoop->aLTerm[j] = pTerm;
}
if( j!=pIdx->nColumn ) continue;
if( j!=pIdx->nKeyCol ) continue;
pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED;
if( (pItem->colUsed & ~columnsInIndex(pIdx))==0 ){
pLoop->wsFlags |= WHERE_IDX_ONLY;
@@ -6112,14 +6112,14 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
for(; k<last; k++, pOp++){
if( pOp->p1!=pLevel->iTabCur ) continue;
if( pOp->opcode==OP_Column ){
for(j=0; j<pIdx->nColumn; j++){
for(j=0; j<pIdx->nKeyCol; j++){
if( pOp->p2==pIdx->aiColumn[j] ){
pOp->p2 = j;
pOp->p1 = pLevel->iIdxCur;
break;
}
}
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || j<pIdx->nColumn );
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || j<pIdx->nKeyCol );
}else if( pOp->opcode==OP_Rowid ){
pOp->p1 = pLevel->iIdxCur;
pOp->opcode = OP_IdxRowid;