diff --git a/manifest b/manifest index f1b1389523..3aa8bdc554 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\sin\sthe\sshell\swhen\simporting\sCSV\sfiles.\sIf\sthe\sleftmost\sfield\sof\sthe\sfirst\srow\sin\sthe\sCSV\sfile\swas\sboth\szero\sbytes\sin\ssize\sand\sunquoted,\sno\sdata\swas\simported. -D 2014-05-26T18:27:12.472 +C Enable\sthe\sOR\soptimization\sfor\sWITHOUT\sROWID\stables.\sUse\sa\stemp\stable\sinstead\sof\sthe\sRowSet\sobject\sto\strack\sthe\srows\sthat\shave\salready\sbeen\sincluded\sin\sthe\sresult\sset. +D 2014-05-26T20:06:45.481 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in dd2b1aba364ff9b05de41086f74407f285c57670 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -294,7 +294,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 -F src/where.c 9d351a5ecefdcc104d0bb7d9b5631dce4d60757c +F src/where.c a911a484ed86fc4a3d52219c8adb64b19f7afeb7 F src/whereInt.h 6804c2e5010378568c2bb1350477537755296a46 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1106,6 +1106,7 @@ F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7 F test/whereG.test 0ac23e5e8311b69d87245f4a85112de321031658 F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2 +F test/whereI.test 6cc613df883a17ca3df36021c6d6e514f5f3bd23 F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31 F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c @@ -1172,7 +1173,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P d90c4964fcf46b0b043dbfd58267098582267001 -R 4f49cf43bba70559a864b8b79fde7303 +P 856d44a206d82e96265103556dedda39ca3602b1 +R 9e568de169ca65397feb1345691b1a68 +T *branch * without-rowid-or-opt +T *sym-without-rowid-or-opt * +T -sym-trunk * U dan -Z b7657af7a09e4e39091c8340eac623cc +Z 2a22ab55186c5c60531d14f3d4d18429 diff --git a/manifest.uuid b/manifest.uuid index daf356e5f4..6244887898 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -856d44a206d82e96265103556dedda39ca3602b1 \ No newline at end of file +2c7e277bbebd5c93dec53d381d9737909d40d846 \ No newline at end of file diff --git a/src/where.c b/src/where.c index b9385a5ecd..d52aed834f 100644 --- a/src/where.c +++ b/src/where.c @@ -3307,6 +3307,7 @@ static Bitmask codeOneLoopStart( int untestedTerms = 0; /* Some terms not completely tested */ int ii; /* Loop counter */ Expr *pAndExpr = 0; /* An ".. AND (...)" expression */ + Table *pTab = pTabItem->pTab; pTerm = pLoop->aLTerm[0]; assert( pTerm!=0 ); @@ -3350,9 +3351,16 @@ static Bitmask codeOneLoopStart( ** called on an uninitialized cursor. */ if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ - regRowset = ++pParse->nMem; + if( HasRowid(pTab) ){ + regRowset = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset); + }else{ + Index *pPk = sqlite3PrimaryKeyIndex(pTab); + regRowset = pParse->nTab++; + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, regRowset, pPk->nKeyCol); + sqlite3VdbeSetP4KeyInfo(pParse, pPk); + } regRowid = ++pParse->nMem; - sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset); } iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn); @@ -3408,13 +3416,52 @@ static Bitmask codeOneLoopStart( pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0 ); if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ - int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); int r; - r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur, - regRowid, 0); - sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, - sqlite3VdbeCurrentAddr(v)+2, r, iSet); - VdbeCoverage(v); + int addr; /* Address just past Gosub coded below */ + int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); + if( HasRowid(pTab) ){ + r = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, regRowid, 0); + addr = sqlite3VdbeCurrentAddr(v)+2; + sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, addr, r, iSet); + VdbeCoverage(v); + }else{ + Index *pPk = sqlite3PrimaryKeyIndex(pTab); + int nPk = pPk->nKeyCol; + int iPk; + + /* Read the PK into an array of temp registers. */ + r = sqlite3GetTempRange(pParse, nPk); + for(iPk=0; iPkaiColumn[iPk]; + sqlite3ExprCodeGetColumn(pParse, pTab, iCol, iCur, r+iPk, 0); + } + + /* Check if the temp table already contains this key. If so, + ** the row has already been included in the result set and + ** can be ignored (by jumping past the Gosub below). Otherwise, + ** insert the key into the temp table and proceed with processing + ** the row. + ** + ** Use some of the same optimizations as OP_RowSetTest: If iSet + ** is zero, assume that the key cannot already be present in + ** the temp table. And if iSet is -1, assume that there is no + ** need to insert the key into the temp table, as it will never + ** be tested for. */ + if( iSet ){ + addr = sqlite3VdbeCurrentAddr(v) + 2 + ((iSet>0) ? 2 : 0); + sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, addr, r, nPk); + } + if( iSet>=0 ){ + sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, regRowid); + sqlite3VdbeAddOp3(v, OP_IdxInsert, regRowset, regRowid, 0); + if( iSet ) sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); + } + + /* Release the array of temp registers */ + sqlite3ReleaseTempRange(pParse, r, nPk); + } + assert( db->mallocFailed + || iSet==0 || addr==(sqlite3VdbeCurrentAddr(v)+1) ); } sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody); @@ -4766,7 +4813,6 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){ pNew = pBuilder->pNew; memset(&sSum, 0, sizeof(sSum)); pItem = pWInfo->pTabList->a + pNew->iTab; - if( !HasRowid(pItem->pTab) ) return SQLITE_OK; iCur = pItem->iCursor; for(pTerm=pWC->a; pTerm