From: drh Date: Wed, 23 Oct 2013 22:23:03 +0000 (+0000) Subject: Construct secondary indices on WITHOUT ROWID tables. X-Git-Tag: version-3.8.2~137^2~63 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4415628a4acddca6a12c2d42a66e922168191578;p=thirdparty%2Fsqlite.git Construct secondary indices on WITHOUT ROWID tables. FossilOrigin-Name: 2c028ddc85cb45746cad6ab0cefd99134fbd50d7 --- diff --git a/manifest b/manifest index e5b4e80626..e5466cac3a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Report\san\serror\swhen\strying\sto\sresolve\scolumn\sname\s"rowid"\sin\sa\nWITHOUT\sROWID\stable. -D 2013-10-23T17:39:41.217 +C Construct\ssecondary\sindices\son\sWITHOUT\sROWID\stables. +D 2013-10-23T22:23:03.281 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -168,12 +168,12 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btree.c 509722ce305471b626d3401c0631a808fd33237b F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0 -F src/build.c 029e1709651df95c75477c334be7bc1ea9332e6d +F src/build.c 6970691b8d22c6eb2c1ab0078e4d25c939acfdad F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c F src/date.c 593c744b2623971e45affd0bde347631bdfa4625 -F src/delete.c c1547dbf732c9987d109b6f45729b4a70e14659e +F src/delete.c 5dcd957b7af5b67b4cce125dd2b580248678db8a F src/expr.c 3180b6332072b263f845592e72e92971af562ab0 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c 628f81177299660a86e40359b3689b81f517e125 @@ -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 ab815d27690d24e87c953355a765edb546c47708 +F src/pragma.c 575a4462366b371076dd14bd93df21f325a10995 F src/prepare.c f47ba2bba7ac5650881ab6c41f6d33a6de1a8d52 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 dc7c57e1d792cda4af5a21bc9566a9afe63f977f +F src/sqliteInt.h 62dee86c51c7b2dc73b0f2cbdfa332a4b79f9bcf F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -292,7 +292,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74 -F src/where.c f9e7662714d776a929683d813a2496fbca8b9087 +F src/where.c 13add0a866a75adb345abfa2ad25585322d472f3 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 579815fff1737552d2077255862b8f4fd220927c -R d63ce5fb7a4f24abe25c071303585c0a +P 36bcc9cb885523fba2f3b0d152de9e08073668c1 +R 5319af9bbb603de112b9787a2a60f8ed U drh -Z 3ecb7889d41fd9bb93bb233d04c44ce3 +Z 289de8cc66e2b52514de0b537df4236c diff --git a/manifest.uuid b/manifest.uuid index 8767ec035b..aa82b4848c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -36bcc9cb885523fba2f3b0d152de9e08073668c1 \ No newline at end of file +2c028ddc85cb45746cad6ab0cefd99134fbd50d7 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 1f6315ec5e..0062dd5370 100644 --- a/src/build.c +++ b/src/build.c @@ -748,6 +748,27 @@ int sqlite3CheckObjectName(Parse *pParse, const char *zName){ return SQLITE_OK; } +/* +** Return the PRIMARY KEY index of a table +*/ +Index *sqlite3PrimaryKeyIndex(Table *pTab){ + Index *p; + for(p=pTab->pIndex; p && p->autoIndex!=2; p=p->pNext){} + return p; +} + +/* +** Return the column of index pIdx that corresponds to table +** column iCol. Return -1 if not found. +*/ +i16 sqlite3ColumnOfIndex(Index *pIdx, i16 iCol){ + int i; + for(i=0; inColumn; i++){ + if( iCol==pIdx->aiColumn[i] ) return i; + } + return -1; +} + /* ** Begin constructing a new table representation in memory. This is ** the first of several action routines that get called in response @@ -1610,8 +1631,9 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ pPk = sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0); if( pPk==0 ) return; pTab->iPKey = -1; + }else{ + pPk = sqlite3PrimaryKeyIndex(pTab); } - for(pPk=pTab->pIndex; pPk && pPk->autoIndex<2; pPk=pPk->pNext){} assert( pPk!=0 ); nPk = pPk->nKeyCol; @@ -2600,12 +2622,8 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ tnum = memRootPage; }else{ tnum = pIndex->tnum; - sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb); } pKey = sqlite3IndexKeyinfo(pParse, pIndex); - sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, - (char *)pKey, P4_KEYINFO_HANDOFF); - sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0)); /* Open the sorter cursor if we are to use one. */ iSorter = pParse->nTab++; @@ -2613,7 +2631,16 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ /* Open the table. Loop through all rows of the table, inserting index ** records into the sorter. */ - sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); + if( HasRowid(pTab) ){ + sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); + }else{ + Index *pPk = sqlite3PrimaryKeyIndex(pTab); + assert( pPk!=0 ); + assert( pPk->tnum=pTab->tnum ); + sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pPk->tnum, iDb, + (char*)sqlite3IndexKeyinfo(pParse, pPk), + P4_KEYINFO_HANDOFF); + } addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); regRecord = sqlite3GetTempReg(pParse); @@ -2622,6 +2649,11 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ sqlite3VdbeResolveLabel(v, iPartIdxLabel); sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); sqlite3VdbeJumpHere(v, addr1); + if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb); + sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, + (char *)pKey, P4_KEYINFO_HANDOFF); + sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0)); + addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); if( pIndex->onError!=OE_None ){ int j2 = sqlite3VdbeCurrentAddr(v) + 3; @@ -2724,7 +2756,9 @@ Index *sqlite3CreateIndex( struct ExprList_item *pListItem; /* For looping over pList */ const Column *pTabCol; /* A column in the table */ int nExtra = 0; /* Space allocated for zExtra[] */ + int nExtraCol; /* Number of extra columns needed */ char *zExtra; /* Extra space after the Index object */ + Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */ assert( pParse->nErr==0 ); /* Never called with prior errors */ if( db->mallocFailed || IN_DECLARE_VTAB ){ @@ -2776,6 +2810,7 @@ Index *sqlite3CreateIndex( pTab->zName); goto exit_create_index; } + if( !HasRowid(pTab) ) pPk = sqlite3PrimaryKeyIndex(pTab); }else{ assert( pName==0 ); assert( pStart==0 ); @@ -2893,7 +2928,8 @@ Index *sqlite3CreateIndex( ** Allocate the index structure. */ nName = sqlite3Strlen30(zName); - pIndex = sqlite3AllocateIndexObject(db, pList->nExpr + 1, + nExtraCol = pPk ? pPk->nKeyCol : 1; + pIndex = sqlite3AllocateIndexObject(db, pList->nExpr + nExtraCol, nName + nExtra + 1, &zExtra); if( db->mallocFailed ){ goto exit_create_index; @@ -2971,8 +3007,16 @@ Index *sqlite3CreateIndex( pIndex->aSortOrder[i] = (u8)requestedSortOrder; if( pTab->aCol[j].notNull==0 ) pIndex->uniqNotNull = 0; } - pIndex->aiColumn[i] = -1; - pIndex->azColl[i] = "BINARY"; + if( pPk ){ + for(j=0; jnKeyCol; j++, i++){ + pIndex->aiColumn[i] = pPk->aiColumn[j]; + pIndex->azColl[i] = pPk->azColl[j]; + pIndex->aSortOrder[i] = pPk->aSortOrder[j]; + } + }else{ + pIndex->aiColumn[i] = -1; + pIndex->azColl[i] = "BINARY"; + } sqlite3DefaultRowEst(pIndex); if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex); diff --git a/src/delete.c b/src/delete.c index 38257a1af1..1a38f79e70 100644 --- a/src/delete.c +++ b/src/delete.c @@ -634,6 +634,7 @@ int sqlite3GenerateIndexKey( Table *pTab = pIdx->pTable; int regBase; int nCol; + Index *pPk; if( piPartIdxLabel ){ if( pIdx->pPartIdxWhere ){ @@ -645,13 +646,14 @@ int sqlite3GenerateIndexKey( *piPartIdxLabel = 0; } } - nCol = pIdx->nKeyCol; - regBase = sqlite3GetTempRange(pParse, nCol+1); - sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+nCol); + nCol = pIdx->nColumn; + regBase = sqlite3GetTempRange(pParse, nCol); + pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab); for(j=0; jaiColumn[j]; - if( idx==pTab->iPKey ){ - sqlite3VdbeAddOp2(v, OP_SCopy, regBase+nCol, regBase+j); + if( pPk ) idx = sqlite3ColumnOfIndex(pPk, idx); + if( idx<0 || idx==pTab->iPKey ){ + sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+j); }else{ sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j); sqlite3ColumnDefault(v, pTab, idx, -1); @@ -666,9 +668,9 @@ int sqlite3GenerateIndexKey( }else{ zAff = sqlite3IndexAffinityStr(v, pIdx); } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut); sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT); } - sqlite3ReleaseTempRange(pParse, regBase, nCol+1); + sqlite3ReleaseTempRange(pParse, regBase, nCol); return regBase; } diff --git a/src/pragma.c b/src/pragma.c index b6f9ae191c..21f1e1a720 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1391,8 +1391,7 @@ void sqlite3Pragma( int i, k; int nHidden = 0; Column *pCol; - Index *pPk; - for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){} + Index *pPk = sqlite3PrimaryKeyIndex(pTab); sqlite3VdbeSetNumCols(v, 6); pParse->nMem = 6; sqlite3CodeVerifySchema(pParse, iDb); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 0522171ca5..fec5f230b8 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2774,6 +2774,8 @@ void sqlite3BeginParse(Parse*,int); void sqlite3CommitInternalChanges(sqlite3*); Table *sqlite3ResultSetOfSelect(Parse*,Select*); void sqlite3OpenMasterTable(Parse *, int); +Index *sqlite3PrimaryKeyIndex(Table*); +i16 sqlite3ColumnOfIndex(Index*, i16); void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int); void sqlite3AddColumn(Parse*,Token*); void sqlite3AddNotNull(Parse*, int); diff --git a/src/where.c b/src/where.c index bccb980b7a..b293de4790 100644 --- a/src/where.c +++ b/src/where.c @@ -2125,6 +2125,8 @@ static void constructAutomaticIndex( } } assert( n==nKeyCol ); + pIdx->aiColumn[n] = -1; + pIdx->azColl[n] = "BINARY"; /* Create the automatic index */ pKeyinfo = sqlite3IndexKeyinfo(pParse, pIdx); @@ -6113,7 +6115,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ pIdx = pLevel->u.pCovidx; } if( pIdx && !db->mallocFailed ){ - int k, j, last; + int k, last; VdbeOp *pOp; last = sqlite3VdbeCurrentAddr(v); @@ -6122,14 +6124,12 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ for(; kp1!=pLevel->iTabCur ) continue; if( pOp->opcode==OP_Column ){ - for(j=0; jnColumn; j++){ - if( pOp->p2==pIdx->aiColumn[j] ){ - pOp->p2 = j; - pOp->p1 = pLevel->iIdxCur; - break; - } + i16 x = sqlite3ColumnOfIndex(pIdx, pOp->p2); + if( x>=0 ){ + pOp->p2 = x; + pOp->p1 = pLevel->iIdxCur; } - assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || jnColumn ); + assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0 ); }else if( pOp->opcode==OP_Rowid ){ pOp->p1 = pLevel->iIdxCur; pOp->opcode = OP_IdxRowid;