Merge all the latest trunk changes into the experimental STAT3 branch.
FossilOrigin-Name: 51908c8f2bc6c086570f7493a29b096f0a40ce34
This commit is contained in:
commit
5c4e5e53fe
@ -2066,7 +2066,37 @@ static int fts3DoclistOrMerge(
|
||||
|
||||
*paOut = 0;
|
||||
*pnOut = 0;
|
||||
aOut = sqlite3_malloc(n1+n2);
|
||||
|
||||
/* Allocate space for the output. Both the input and output doclists
|
||||
** are delta encoded. If they are in ascending order (bDescDoclist==0),
|
||||
** then the first docid in each list is simply encoded as a varint. For
|
||||
** each subsequent docid, the varint stored is the difference between the
|
||||
** current and previous docid (a positive number - since the list is in
|
||||
** ascending order).
|
||||
**
|
||||
** The first docid written to the output is therefore encoded using the
|
||||
** same number of bytes as it is in whichever of the input lists it is
|
||||
** read from. And each subsequent docid read from the same input list
|
||||
** consumes either the same or less bytes as it did in the input (since
|
||||
** the difference between it and the previous value in the output must
|
||||
** be a positive value less than or equal to the delta value read from
|
||||
** the input list). The same argument applies to all but the first docid
|
||||
** read from the 'other' list. And to the contents of all position lists
|
||||
** that will be copied and merged from the input to the output.
|
||||
**
|
||||
** However, if the first docid copied to the output is a negative number,
|
||||
** then the encoding of the first docid from the 'other' input list may
|
||||
** be larger in the output than it was in the input (since the delta value
|
||||
** may be a larger positive integer than the actual docid).
|
||||
**
|
||||
** The space required to store the output is therefore the sum of the
|
||||
** sizes of the two inputs, plus enough space for exactly one of the input
|
||||
** docids to grow.
|
||||
**
|
||||
** A symetric argument may be made if the doclists are in descending
|
||||
** order.
|
||||
*/
|
||||
aOut = sqlite3_malloc(n1+n2+FTS3_VARINT_MAX-1);
|
||||
if( !aOut ) return SQLITE_NOMEM;
|
||||
|
||||
p = aOut;
|
||||
@ -2093,6 +2123,7 @@ static int fts3DoclistOrMerge(
|
||||
|
||||
*paOut = aOut;
|
||||
*pnOut = (p-aOut);
|
||||
assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 );
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
39
manifest
39
manifest
@ -1,5 +1,5 @@
|
||||
C Merge\sthe\slatest\strunk\schanges\sinto\sthe\sstat3-trunk\sbranch.
|
||||
D 2011-09-13T19:09:28.865
|
||||
C Merge\sall\sthe\slatest\strunk\schanges\sinto\sthe\sexperimental\sSTAT3\sbranch.
|
||||
D 2011-09-16T19:29:58.199
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in d314143fa6be24828021d3f583ad37d9afdce505
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -62,7 +62,7 @@ F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c f45ad45053a587ad1c005459b704b7ade8bd504e
|
||||
F ext/fts3/fts3.c 195e4da669741c1f097434ec48c0ba5739193af9
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h 30063fdd0bc433b5db1532e3a363cb0f2f7e8eb3
|
||||
F ext/fts3/fts3_aux.c 0ebfa7b86cf8ff6a0861605fcc63b83ec1b70691
|
||||
@ -124,7 +124,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 28a4fe55327ff708bfaf9d4326d02686f7a553c3
|
||||
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
|
||||
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c 4cb13cf019d1978b62494b970d20e9555211094b
|
||||
F src/btree.c 77b09c69d4849a90361e6fe5db36d167f20600c0
|
||||
F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce
|
||||
F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3
|
||||
F src/build.c 57e3b27c26e6754393cd63a2774a6c673df1e804
|
||||
@ -133,7 +133,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c dde6a9b835b9e8cc067b713de1a7f6a0c9ff807e
|
||||
F src/date.c a3c6842bad7ae632281811de112a8ba63ff08ab3
|
||||
F src/delete.c ff68e5ef23aee08c0ff528f699a19397ed8bbed8
|
||||
F src/expr.c cbcd8c2f1588a9862291a081699854c5e1cb28ab
|
||||
F src/expr.c fd54c517869919c9b0b11dcadd43c66540ffa682
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 9f00ea98f6b360d477b5a78b5b59a1fbde82431c
|
||||
F src/func.c 59bb046d7e3df1ab512ac339ccb0a6f996a17cb7
|
||||
@ -179,11 +179,11 @@ F src/printf.c 585a36b6a963df832cfb69505afa3a34ed5ef8a1
|
||||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||
F src/resolve.c 36368f44569208fa074e61f4dd0b6c4fb60ca2b4
|
||||
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
|
||||
F src/select.c bf7b7ea6befb483619da5f597b0864668b828c3c
|
||||
F src/select.c d9b7d20b0365f80761846f00ef3638d4b33eeaf2
|
||||
F src/shell.c bbe7818ff5bc8614105ceb81ad67b8bdc0b671dd
|
||||
F src/sqlite.h.in 3f531daa04457e83bc13765c98c06c7d71c27fa5
|
||||
F src/sqlite3ext.h 1a1a4f784aa9c3b00edd287940197de52487cd93
|
||||
F src/sqliteInt.h b7f41c29477dfa18b18c0aa3e9230c7a4c775de2
|
||||
F src/sqliteInt.h dea1be7eccbc4c4e28fffebae19ab5e2af2b3a26
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
@ -238,20 +238,20 @@ F src/update.c 74a6cfb34e9732c1e2a86278b229913b4b51eeec
|
||||
F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84
|
||||
F src/util.c 06302ffd2b80408d4f6c7af71f7090e0cf8d8ff7
|
||||
F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e
|
||||
F src/vdbe.c 7008edbf8f608d82c035dcb1c56367ad85e68aaa
|
||||
F src/vdbe.h a10b360bf69474babc8aba8fcc64b824c5e97d38
|
||||
F src/vdbe.c 60340bfb23f456ea0791cb28262a887363773371
|
||||
F src/vdbe.h f0725ee997db869ecae5bb70a71612aabeca7755
|
||||
F src/vdbeInt.h 693d6ac6810298fc6b4c503cfbe3f99a240f40af
|
||||
F src/vdbeapi.c 11dc47987abacb76ad016dcf5abc0dc422482a98
|
||||
F src/vdbeaux.c 316409c6878363525a2835aab15e0505c951a16d
|
||||
F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3
|
||||
F src/vdbeaux.c 461e3e39cc6084e23412f3ff85ef73839dae90e2
|
||||
F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb
|
||||
F src/vdbemem.c 2fc78b3e0fabcc1eaa23cd79dd2e30e6dcfe1e56
|
||||
F src/vdbesort.c 667bc65254a9ebaf7bc466ebb7e58884933e351f
|
||||
F src/vdbesort.c 468d43c057063e54da4f1988b38b4f46d60e7790
|
||||
F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114
|
||||
F src/vtab.c 901791a47318c0562cd0c676a2c6ff1bc530e582
|
||||
F src/wal.c 3154756177d6219e233d84291d5b05f4e06ff5e9
|
||||
F src/wal.h 66b40bd91bc29a5be1c88ddd1f5ade8f3f48728a
|
||||
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
|
||||
F src/where.c 3d9a78a422726c1b3a57188c3099e537cb18e18a
|
||||
F src/where.c 4d7321662f1d23c73fce7245470f4a41c18665df
|
||||
F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||
@ -484,7 +484,7 @@ F test/fts3query.test ef79d31fdb355d094baec1c1b24b60439a1fb8a2
|
||||
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
|
||||
F test/fts3shared.test 8bb266521d7c5495c0ae522bb4d376ad5387d4a2
|
||||
F test/fts3snippet.test 8e956051221a34c7daeb504f023cb54d5fa5a8b2
|
||||
F test/fts3sort.test 63d52c1812904b751f9e1ff487472e44833f5402
|
||||
F test/fts3sort.test 9a5176c9317bb545ec5f144d62e6fedb4da6c66e
|
||||
F test/fts4aa.test 6e7f90420b837b2c685f3bcbe84c868492d40a68
|
||||
F test/func.test 6c5ce11e3a0021ca3c0649234e2d4454c89110ca
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
@ -689,6 +689,7 @@ F test/stat.test 0997f6a57a35866b14111ed361ed8851ce7978ae
|
||||
F test/stat3.test 986d735f70ef62a1daf98e8762f35fa3b062c5c3
|
||||
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
|
||||
F test/subquery.test b524f57c9574b2c0347045b4510ef795d4686796
|
||||
F test/subquery2.test edcad5c118f0531c2e21bf16a09bbb105252d4cd
|
||||
F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
|
||||
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
|
||||
F test/superlock.test 5d7a4954b0059c903f82c7b67867bc5451a7c082
|
||||
@ -717,7 +718,7 @@ F test/tkt-02a8e81d44.test 58494de77be2cf249228ada3f313fa399821c6ab
|
||||
F test/tkt-26ff0c2d1e.test 888324e751512972c6e0d1a09df740d8f5aaf660
|
||||
F test/tkt-2d1a5c67d.test b028a811049eb472cb2d3a43fc8ce4f6894eebda
|
||||
F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28
|
||||
F test/tkt-31338dca7e.test 5741cd48de500347a437ba1be58c8335e83c5a5e
|
||||
F test/tkt-31338dca7e.test 1f714c14b6682c5db715e0bda347926a3456f7a9
|
||||
F test/tkt-313723c356.test c47f8a9330523e6f35698bf4489bcb29609b53ac
|
||||
F test/tkt-38cb5df375.test 9e9b19857dba0896a8efdaf334d405ba423492f2
|
||||
F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7
|
||||
@ -952,7 +953,7 @@ F tool/showjournal.c b62cecaab86a4053d944c276bb5232e4d17ece02
|
||||
F tool/showwal.c f09e5a80a293919290ec85a6a37c85a5ddcf37d9
|
||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||
F tool/space_used.tcl f714c41a59e326b8b9042f415b628b561bafa06b
|
||||
F tool/spaceanal.tcl 1ee4df4e190675ba67b8c60cf304496d0021cfb4
|
||||
F tool/spaceanal.tcl fe02dede3d29ef0fefcf80a685644fdf4d9a768e
|
||||
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
|
||||
F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
|
||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
@ -963,7 +964,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5
|
||||
F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
P 63f2c7859fa6e5d0e2cdd218ff52a3ec2d44c61d a9db247b752bcda0131b8f01c6f0182f3101d154
|
||||
R 2e9e259494c37eae338f4a7f0467a2a7
|
||||
P 11ca4ed8bf850dae1a24b7182f70039f32bd8dd1 cf51ef8ab8a610ddf64f66970dd689fe1df405b8
|
||||
R d21205869b95de630ee29bd2fddfacf5
|
||||
U drh
|
||||
Z 16b18ce61af4e2a2021001a6e69294e0
|
||||
Z cf2b3cc9409ff7ff8b423ef999aa2d40
|
||||
|
@ -1 +1 @@
|
||||
11ca4ed8bf850dae1a24b7182f70039f32bd8dd1
|
||||
51908c8f2bc6c086570f7493a29b096f0a40ce34
|
@ -664,7 +664,7 @@ static int btreeMoveto(
|
||||
pCur->pKeyInfo, aSpace, sizeof(aSpace), &pFree
|
||||
);
|
||||
if( pIdxKey==0 ) return SQLITE_NOMEM;
|
||||
sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey, pIdxKey);
|
||||
sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
|
||||
}else{
|
||||
pIdxKey = 0;
|
||||
}
|
||||
|
17
src/expr.c
17
src/expr.c
@ -901,7 +901,8 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
|
||||
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
|
||||
pNewItem->jointype = pOldItem->jointype;
|
||||
pNewItem->iCursor = pOldItem->iCursor;
|
||||
pNewItem->isPopulated = pOldItem->isPopulated;
|
||||
pNewItem->addrFillSub = pOldItem->addrFillSub;
|
||||
pNewItem->regReturn = pOldItem->regReturn;
|
||||
pNewItem->isCorrelated = pOldItem->isCorrelated;
|
||||
pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
|
||||
pNewItem->notIndexed = pOldItem->notIndexed;
|
||||
@ -1461,8 +1462,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
|
||||
int iMem = ++pParse->nMem;
|
||||
int iAddr;
|
||||
|
||||
iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
|
||||
iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
|
||||
|
||||
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
|
||||
eType = IN_INDEX_ROWID;
|
||||
@ -1493,8 +1493,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
|
||||
char *pKey;
|
||||
|
||||
pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
|
||||
iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
|
||||
iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem);
|
||||
|
||||
sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
|
||||
pKey,P4_KEYINFO_HANDOFF);
|
||||
@ -1579,6 +1578,7 @@ int sqlite3CodeSubselect(
|
||||
int rReg = 0; /* Register storing resulting */
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
if( NEVER(v==0) ) return 0;
|
||||
assert( sqlite3VdbeCurrentAddr(v)>0 );
|
||||
sqlite3ExprCachePush(pParse);
|
||||
|
||||
/* This code must be run in its entirety every time it is encountered
|
||||
@ -1593,8 +1593,7 @@ int sqlite3CodeSubselect(
|
||||
*/
|
||||
if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){
|
||||
int mem = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp1(v, OP_If, mem);
|
||||
testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem);
|
||||
testAddr = sqlite3VdbeAddOp1(v, OP_Once, mem);
|
||||
assert( testAddr>0 || pParse->db->mallocFailed );
|
||||
}
|
||||
|
||||
@ -1694,7 +1693,7 @@ int sqlite3CodeSubselect(
|
||||
** expression we need to rerun this code each time.
|
||||
*/
|
||||
if( testAddr && !sqlite3ExprIsConstant(pE2) ){
|
||||
sqlite3VdbeChangeToNoop(v, testAddr-1, 2);
|
||||
sqlite3VdbeChangeToNoop(v, testAddr);
|
||||
testAddr = 0;
|
||||
}
|
||||
|
||||
@ -1765,7 +1764,7 @@ int sqlite3CodeSubselect(
|
||||
}
|
||||
|
||||
if( testAddr ){
|
||||
sqlite3VdbeJumpHere(v, testAddr-1);
|
||||
sqlite3VdbeJumpHere(v, testAddr);
|
||||
}
|
||||
sqlite3ExprCachePop(pParse, 1);
|
||||
|
||||
|
41
src/select.c
41
src/select.c
@ -89,6 +89,8 @@ Select *sqlite3SelectNew(
|
||||
clearSelect(db, pNew);
|
||||
if( pNew!=&standin ) sqlite3DbFree(db, pNew);
|
||||
pNew = 0;
|
||||
}else{
|
||||
assert( pNew->pSrc!=0 || pParse->nErr>0 );
|
||||
}
|
||||
return pNew;
|
||||
}
|
||||
@ -3801,7 +3803,11 @@ int sqlite3Select(
|
||||
Select *pSub = pItem->pSelect;
|
||||
int isAggSub;
|
||||
|
||||
if( pSub==0 || pItem->isPopulated ) continue;
|
||||
if( pSub==0 ) continue;
|
||||
if( pItem->addrFillSub ){
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Increment Parse.nHeight by the height of the largest expression
|
||||
** tree refered to by this, the parent select. The child select
|
||||
@ -3812,21 +3818,44 @@ int sqlite3Select(
|
||||
*/
|
||||
pParse->nHeight += sqlite3SelectExprHeight(p);
|
||||
|
||||
/* Check to see if the subquery can be absorbed into the parent. */
|
||||
isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
|
||||
if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
|
||||
/* This subquery can be absorbed into its parent. */
|
||||
if( isAggSub ){
|
||||
isAgg = 1;
|
||||
p->selFlags |= SF_Aggregate;
|
||||
}
|
||||
i = -1;
|
||||
}else{
|
||||
/* Generate a subroutine that will fill an ephemeral table with
|
||||
** the content of this subquery. pItem->addrFillSub will point
|
||||
** to the address of the generated subroutine. pItem->regReturn
|
||||
** is a register allocated to hold the subroutine return address
|
||||
*/
|
||||
int topAddr;
|
||||
int onceAddr = 0;
|
||||
int retAddr;
|
||||
assert( pItem->addrFillSub==0 );
|
||||
pItem->regReturn = ++pParse->nMem;
|
||||
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
|
||||
pItem->addrFillSub = topAddr+1;
|
||||
VdbeNoopComment((v, "materialize %s", pItem->pTab->zName));
|
||||
if( pItem->isCorrelated==0 && pParse->pTriggerTab==0 ){
|
||||
/* If the subquery is no correlated and if we are not inside of
|
||||
** a trigger, then we only need to compute the value of the subquery
|
||||
** once. */
|
||||
int regOnce = ++pParse->nMem;
|
||||
onceAddr = sqlite3VdbeAddOp1(v, OP_Once, regOnce);
|
||||
}
|
||||
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
|
||||
assert( pItem->isPopulated==0 );
|
||||
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
|
||||
sqlite3Select(pParse, pSub, &dest);
|
||||
pItem->isPopulated = 1;
|
||||
pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
|
||||
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
|
||||
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
|
||||
VdbeComment((v, "end %s", pItem->pTab->zName));
|
||||
sqlite3VdbeChangeP1(v, topAddr, retAddr);
|
||||
|
||||
}
|
||||
if( /*pParse->nErr ||*/ db->mallocFailed ){
|
||||
goto select_end;
|
||||
@ -3967,7 +3996,7 @@ int sqlite3Select(
|
||||
** into an OP_Noop.
|
||||
*/
|
||||
if( addrSortIndex>=0 && pOrderBy==0 ){
|
||||
sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
|
||||
sqlite3VdbeChangeToNoop(v, addrSortIndex);
|
||||
p->addrOpenEphm[2] = -1;
|
||||
}
|
||||
|
||||
@ -4250,7 +4279,7 @@ int sqlite3Select(
|
||||
sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop);
|
||||
}else{
|
||||
sqlite3WhereEnd(pWInfo);
|
||||
sqlite3VdbeChangeToNoop(v, addrSortingIdx, 1);
|
||||
sqlite3VdbeChangeToNoop(v, addrSortingIdx);
|
||||
}
|
||||
|
||||
/* Output the final row of result
|
||||
|
@ -1872,7 +1872,8 @@ struct SrcList {
|
||||
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
|
||||
Table *pTab; /* An SQL table corresponding to zName */
|
||||
Select *pSelect; /* A SELECT statement used in place of a table name */
|
||||
u8 isPopulated; /* Temporary table associated with SELECT is populated */
|
||||
int addrFillSub; /* Address of subroutine to manifest a subquery */
|
||||
int regReturn; /* Register holding return address of addrFillSub */
|
||||
u8 jointype; /* Type of join between this able and the previous */
|
||||
u8 notIndexed; /* True if there is a NOT INDEXED clause */
|
||||
u8 isCorrelated; /* True if sub-query is correlated */
|
||||
|
17
src/vdbe.c
17
src/vdbe.c
@ -2021,6 +2021,16 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Once P1 P2 * * *
|
||||
**
|
||||
** Jump to P2 if the value in register P1 is a not null or zero. If
|
||||
** the value is NULL or zero, fall through and change the P1 register
|
||||
** to an integer 1.
|
||||
**
|
||||
** When P1 is not used otherwise in a program, this opcode falls through
|
||||
** once and jumps on all subsequent invocations. It is the equivalent
|
||||
** of "OP_If P1 P2", followed by "OP_Integer 1 P1".
|
||||
*/
|
||||
/* Opcode: If P1 P2 P3 * *
|
||||
**
|
||||
** Jump to P2 if the value in register P1 is true. The value
|
||||
@ -2033,6 +2043,7 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
|
||||
** is considered true if it has a numeric value of zero. If the value
|
||||
** in P1 is NULL then take the jump if P3 is true.
|
||||
*/
|
||||
case OP_Once: /* jump, in1 */
|
||||
case OP_If: /* jump, in1 */
|
||||
case OP_IfNot: { /* jump, in1 */
|
||||
int c;
|
||||
@ -2049,6 +2060,12 @@ case OP_IfNot: { /* jump, in1 */
|
||||
}
|
||||
if( c ){
|
||||
pc = pOp->p2-1;
|
||||
}else if( pOp->opcode==OP_Once ){
|
||||
assert( (pIn1->flags & (MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))==0 );
|
||||
memAboutToChange(p, pIn1);
|
||||
pIn1->flags = MEM_Int;
|
||||
pIn1->u.i = 1;
|
||||
REGISTER_TRACE(pOp->p1, pIn1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
|
||||
void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
|
||||
void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
|
||||
void sqlite3VdbeJumpHere(Vdbe*, int addr);
|
||||
void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N);
|
||||
void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
|
||||
void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
|
||||
void sqlite3VdbeUsesBtree(Vdbe*, int);
|
||||
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
|
||||
|
@ -670,18 +670,15 @@ void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
|
||||
}
|
||||
|
||||
/*
|
||||
** Change N opcodes starting at addr to No-ops.
|
||||
** Change the opcode at addr into OP_Noop
|
||||
*/
|
||||
void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
|
||||
void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
|
||||
if( p->aOp ){
|
||||
VdbeOp *pOp = &p->aOp[addr];
|
||||
sqlite3 *db = p->db;
|
||||
while( N-- ){
|
||||
freeP4(db, pOp->p4type, pOp->p4.p);
|
||||
memset(pOp, 0, sizeof(pOp[0]));
|
||||
pOp->opcode = OP_Noop;
|
||||
pOp++;
|
||||
}
|
||||
freeP4(db, pOp->p4type, pOp->p4.p);
|
||||
memset(pOp, 0, sizeof(pOp[0]));
|
||||
pOp->opcode = OP_Noop;
|
||||
}
|
||||
}
|
||||
|
||||
@ -837,7 +834,7 @@ void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
|
||||
VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
|
||||
/* C89 specifies that the constant "dummy" will be initialized to all
|
||||
** zeros, which is correct. MSVC generates a warning, nevertheless. */
|
||||
static const VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
|
||||
static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
|
||||
assert( p->magic==VDBE_MAGIC_INIT );
|
||||
if( addr<0 ){
|
||||
#ifdef SQLITE_OMIT_TRACE
|
||||
|
@ -273,7 +273,7 @@ int sqlite3_blob_open(
|
||||
|
||||
/* Configure the OP_TableLock instruction */
|
||||
#ifdef SQLITE_OMIT_SHARED_CACHE
|
||||
sqlite3VdbeChangeToNoop(v, 2, 1);
|
||||
sqlite3VdbeChangeToNoop(v, 2);
|
||||
#else
|
||||
sqlite3VdbeChangeP1(v, 2, iDb);
|
||||
sqlite3VdbeChangeP2(v, 2, pTab->tnum);
|
||||
@ -283,7 +283,7 @@ int sqlite3_blob_open(
|
||||
|
||||
/* Remove either the OP_OpenWrite or OpenRead. Set the P2
|
||||
** parameter of the other to pTab->tnum. */
|
||||
sqlite3VdbeChangeToNoop(v, 4 - flags, 1);
|
||||
sqlite3VdbeChangeToNoop(v, 4 - flags);
|
||||
sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
|
||||
sqlite3VdbeChangeP3(v, 3 + flags, iDb);
|
||||
|
||||
|
@ -160,8 +160,12 @@ static int vdbeSorterIterNext(
|
||||
int nRec = 0; /* Size of record in bytes */
|
||||
int iOff = 0; /* Size of serialized size varint in bytes */
|
||||
|
||||
nRead = pIter->iEof - pIter->iReadOff;
|
||||
if( nRead>5 ) nRead = 5;
|
||||
assert( pIter->iEof>=pIter->iReadOff );
|
||||
if( pIter->iEof-pIter->iReadOff>5 ){
|
||||
nRead = 5;
|
||||
}else{
|
||||
nRead = (int)(pIter->iEof - pIter->iReadOff);
|
||||
}
|
||||
if( nRead<=0 ){
|
||||
/* This is an EOF condition */
|
||||
vdbeSorterIterZero(db, pIter);
|
||||
@ -298,7 +302,7 @@ static int vdbeSorterIterInit(
|
||||
** If pKey2 is passed a NULL pointer, then it is assumed that the pCsr->aSpace
|
||||
** has been allocated and contains an unpacked record that is used as key2.
|
||||
*/
|
||||
static int vdbeSorterCompare(
|
||||
static void vdbeSorterCompare(
|
||||
VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */
|
||||
int bOmitRowid, /* Ignore rowid field at end of keys */
|
||||
void *pKey1, int nKey1, /* Left side of comparison */
|
||||
@ -320,14 +324,13 @@ static int vdbeSorterCompare(
|
||||
for(i=0; i<r2->nField; i++){
|
||||
if( r2->aMem[i].flags & MEM_Null ){
|
||||
*pRes = -1;
|
||||
return SQLITE_OK;
|
||||
return;
|
||||
}
|
||||
}
|
||||
r2->flags |= UNPACKED_PREFIX_MATCH;
|
||||
}
|
||||
|
||||
*pRes = sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -362,15 +365,10 @@ static int vdbeSorterDoCompare(VdbeCursor *pCsr, int iOut){
|
||||
iRes = i1;
|
||||
}else{
|
||||
int res;
|
||||
int rc;
|
||||
assert( pCsr->pSorter->pUnpacked!=0 ); /* allocated in vdbeSorterMerge() */
|
||||
rc = vdbeSorterCompare(
|
||||
vdbeSorterCompare(
|
||||
pCsr, 0, p1->aKey, p1->nKey, p2->aKey, p2->nKey, &res
|
||||
);
|
||||
/* The vdbeSorterCompare() call cannot fail since pCsr->pSorter->pUnpacked
|
||||
** has already been allocated. */
|
||||
assert( rc==SQLITE_OK );
|
||||
|
||||
if( res<=0 ){
|
||||
iRes = i1;
|
||||
}else{
|
||||
@ -462,32 +460,22 @@ static int vdbeSorterOpenTempFile(sqlite3 *db, sqlite3_file **ppFile){
|
||||
}
|
||||
|
||||
/*
|
||||
** Attemp to merge the two sorted lists p1 and p2 into a single list. If no
|
||||
** error occurs set *ppOut to the head of the new list and return SQLITE_OK.
|
||||
** Merge the two sorted lists p1 and p2 into a single list.
|
||||
** Set *ppOut to the head of the new list.
|
||||
*/
|
||||
static int vdbeSorterMerge(
|
||||
sqlite3 *db, /* Database handle */
|
||||
static void vdbeSorterMerge(
|
||||
VdbeCursor *pCsr, /* For pKeyInfo */
|
||||
SorterRecord *p1, /* First list to merge */
|
||||
SorterRecord *p2, /* Second list to merge */
|
||||
SorterRecord **ppOut /* OUT: Head of merged list */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
SorterRecord *pFinal = 0;
|
||||
SorterRecord **pp = &pFinal;
|
||||
void *pVal2 = p2 ? p2->pVal : 0;
|
||||
|
||||
while( p1 && p2 ){
|
||||
int res;
|
||||
rc = vdbeSorterCompare(pCsr, 0, p1->pVal, p1->nVal, pVal2, p2->nVal, &res);
|
||||
if( rc!=SQLITE_OK ){
|
||||
*pp = 0;
|
||||
vdbeSorterRecordFree(db, p1);
|
||||
vdbeSorterRecordFree(db, p2);
|
||||
vdbeSorterRecordFree(db, pFinal);
|
||||
*ppOut = 0;
|
||||
return rc;
|
||||
}
|
||||
vdbeSorterCompare(pCsr, 0, p1->pVal, p1->nVal, pVal2, p2->nVal, &res);
|
||||
if( res<=0 ){
|
||||
*pp = p1;
|
||||
pp = &p1->pNext;
|
||||
@ -502,9 +490,7 @@ static int vdbeSorterMerge(
|
||||
}
|
||||
}
|
||||
*pp = p1 ? p1 : p2;
|
||||
|
||||
*ppOut = pFinal;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -512,8 +498,7 @@ static int vdbeSorterMerge(
|
||||
** if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if an error
|
||||
** occurs.
|
||||
*/
|
||||
static int vdbeSorterSort(sqlite3 *db, VdbeCursor *pCsr){
|
||||
int rc = SQLITE_OK;
|
||||
static int vdbeSorterSort(VdbeCursor *pCsr){
|
||||
int i;
|
||||
SorterRecord **aSlot;
|
||||
SorterRecord *p;
|
||||
@ -528,30 +513,22 @@ static int vdbeSorterSort(sqlite3 *db, VdbeCursor *pCsr){
|
||||
while( p ){
|
||||
SorterRecord *pNext = p->pNext;
|
||||
p->pNext = 0;
|
||||
for(i=0; rc==SQLITE_OK && aSlot[i]; i++){
|
||||
rc = vdbeSorterMerge(db, pCsr, p, aSlot[i], &p);
|
||||
for(i=0; aSlot[i]; i++){
|
||||
vdbeSorterMerge(pCsr, p, aSlot[i], &p);
|
||||
aSlot[i] = 0;
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
vdbeSorterRecordFree(db, pNext);
|
||||
break;
|
||||
}
|
||||
aSlot[i] = p;
|
||||
p = pNext;
|
||||
}
|
||||
|
||||
p = 0;
|
||||
for(i=0; i<64; i++){
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = vdbeSorterMerge(db, pCsr, p, aSlot[i], &p);
|
||||
}else{
|
||||
vdbeSorterRecordFree(db, aSlot[i]);
|
||||
}
|
||||
vdbeSorterMerge(pCsr, p, aSlot[i], &p);
|
||||
}
|
||||
pSorter->pRecord = p;
|
||||
|
||||
sqlite3_free(aSlot);
|
||||
return rc;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -577,7 +554,7 @@ static int vdbeSorterListToPMA(sqlite3 *db, VdbeCursor *pCsr){
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = vdbeSorterSort(db, pCsr);
|
||||
rc = vdbeSorterSort(pCsr);
|
||||
|
||||
/* If the first temporary PMA file has not been opened, open it now. */
|
||||
if( rc==SQLITE_OK && pSorter->pTemp1==0 ){
|
||||
@ -724,7 +701,7 @@ int sqlite3VdbeSorterRewind(sqlite3 *db, VdbeCursor *pCsr, int *pbEof){
|
||||
if( pSorter->nPMA==0 ){
|
||||
*pbEof = !pSorter->pRecord;
|
||||
assert( pSorter->aTree==0 );
|
||||
return vdbeSorterSort(db, pCsr);
|
||||
return vdbeSorterSort(pCsr);
|
||||
}
|
||||
|
||||
/* Write the current b-tree to a PMA. Close the b-tree cursor. */
|
||||
@ -894,14 +871,12 @@ int sqlite3VdbeSorterCompare(
|
||||
Mem *pVal, /* Value to compare to current sorter key */
|
||||
int *pRes /* OUT: Result of comparison */
|
||||
){
|
||||
int rc;
|
||||
VdbeSorter *pSorter = pCsr->pSorter;
|
||||
void *pKey; int nKey; /* Sorter key to compare pVal with */
|
||||
|
||||
pKey = vdbeSorterRowkey(pSorter, &nKey);
|
||||
rc = vdbeSorterCompare(pCsr, 1, pVal->z, pVal->n, pKey, nKey, pRes);
|
||||
assert( rc!=SQLITE_OK || pVal->db->mallocFailed || (*pRes)<=0 );
|
||||
return rc;
|
||||
vdbeSorterCompare(pCsr, 1, pVal->z, pVal->n, pKey, nKey, pRes);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
#endif /* #ifndef SQLITE_OMIT_MERGE_SORT */
|
||||
|
11
src/where.c
11
src/where.c
@ -467,11 +467,19 @@ static Bitmask exprListTableUsage(WhereMaskSet *pMaskSet, ExprList *pList){
|
||||
static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){
|
||||
Bitmask mask = 0;
|
||||
while( pS ){
|
||||
SrcList *pSrc = pS->pSrc;
|
||||
mask |= exprListTableUsage(pMaskSet, pS->pEList);
|
||||
mask |= exprListTableUsage(pMaskSet, pS->pGroupBy);
|
||||
mask |= exprListTableUsage(pMaskSet, pS->pOrderBy);
|
||||
mask |= exprTableUsage(pMaskSet, pS->pWhere);
|
||||
mask |= exprTableUsage(pMaskSet, pS->pHaving);
|
||||
if( ALWAYS(pSrc!=0) ){
|
||||
int i;
|
||||
for(i=0; i<pSrc->nSrc; i++){
|
||||
mask |= exprSelectTableUsage(pMaskSet, pSrc->a[i].pSelect);
|
||||
mask |= exprTableUsage(pMaskSet, pSrc->a[i].pOn);
|
||||
}
|
||||
}
|
||||
pS = pS->pPrior;
|
||||
}
|
||||
return mask;
|
||||
@ -1994,8 +2002,7 @@ static void constructAutomaticIndex(
|
||||
v = pParse->pVdbe;
|
||||
assert( v!=0 );
|
||||
regIsInit = ++pParse->nMem;
|
||||
addrInit = sqlite3VdbeAddOp1(v, OP_If, regIsInit);
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 1, regIsInit);
|
||||
addrInit = sqlite3VdbeAddOp1(v, OP_Once, regIsInit);
|
||||
|
||||
/* Count the number of columns that will be added to the index
|
||||
** and used to match WHERE clause constraints */
|
||||
|
@ -158,5 +158,23 @@ do_execsql_test 2.3 {
|
||||
SELECT docid FROM t2 WHERE t2 MATCH 'aa';
|
||||
} {3 1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that ticket [56be976859] has been fixed.
|
||||
#
|
||||
do_execsql_test 3.1 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts4(x, order=DESC);
|
||||
INSERT INTO t3(docid, x) VALUES(113382409004785664, 'aa');
|
||||
INSERT INTO t3(docid, x) VALUES(1, 'ab');
|
||||
SELECT rowid FROM t3 WHERE x MATCH 'a*' ORDER BY docid DESC;
|
||||
} {113382409004785664 1}
|
||||
do_execsql_test 3.2 {
|
||||
CREATE VIRTUAL TABLE t4 USING fts4(x);
|
||||
INSERT INTO t4(docid, x) VALUES(-113382409004785664, 'aa');
|
||||
INSERT INTO t4(docid, x) VALUES(1, 'ab');
|
||||
SELECT rowid FROM t4 WHERE x MATCH 'a*';
|
||||
} {-113382409004785664 1}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
86
test/subquery2.test
Normal file
86
test/subquery2.test
Normal file
@ -0,0 +1,86 @@
|
||||
# 2011 September 16
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#*************************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing correlated subqueries
|
||||
#
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !subquery {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_test subquery2-1.1 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
INSERT INTO t1 VALUES(3,4);
|
||||
INSERT INTO t1 VALUES(5,6);
|
||||
INSERT INTO t1 VALUES(7,8);
|
||||
CREATE TABLE t2(c,d);
|
||||
INSERT INTO t2 VALUES(1,1);
|
||||
INSERT INTO t2 VALUES(3,9);
|
||||
INSERT INTO t2 VALUES(5,25);
|
||||
INSERT INTO t2 VALUES(7,49);
|
||||
CREATE TABLE t3(e,f);
|
||||
INSERT INTO t3 VALUES(1,1);
|
||||
INSERT INTO t3 VALUES(3,27);
|
||||
INSERT INTO t3 VALUES(5,125);
|
||||
INSERT INTO t3 VALUES(7,343);
|
||||
COMMIT;
|
||||
}
|
||||
execsql {
|
||||
SELECT a FROM t1
|
||||
WHERE b IN (SELECT x+1 FROM (SELECT DISTINCT f/(a*a) AS x FROM t3));
|
||||
}
|
||||
} {1 3 5 7}
|
||||
do_test subquery2-1.2 {
|
||||
execsql {
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
SELECT a FROM t1
|
||||
WHERE b IN (SELECT x+1 FROM (SELECT DISTINCT f/(a*a) AS x FROM t3));
|
||||
}
|
||||
} {1 3 5 7}
|
||||
|
||||
do_test subquery2-1.11 {
|
||||
execsql {
|
||||
SELECT a FROM t1
|
||||
WHERE +b=(SELECT x+1 FROM (SELECT DISTINCT f/(a*a) AS x FROM t3));
|
||||
}
|
||||
} {1}
|
||||
do_test subquery2-1.12 {
|
||||
execsql {
|
||||
SELECT a FROM t1
|
||||
WHERE b=(SELECT x+1 FROM (SELECT DISTINCT f/(a*a) AS x FROM t3));
|
||||
}
|
||||
} {1}
|
||||
|
||||
do_test subquery2-1.21 {
|
||||
execsql {
|
||||
SELECT a FROM t1
|
||||
WHERE +b=(SELECT x+1 FROM
|
||||
(SELECT DISTINCT f/d AS x FROM t2 JOIN t3 ON d*a=f))
|
||||
}
|
||||
} {1 3 5 7}
|
||||
do_test subquery2-1.22 {
|
||||
execsql {
|
||||
SELECT a FROM t1
|
||||
WHERE b=(SELECT x+1 FROM
|
||||
(SELECT DISTINCT f/d AS x FROM t2 JOIN t3 ON d*a=f))
|
||||
}
|
||||
} {1 3 5 7}
|
||||
|
||||
|
||||
finish_test
|
@ -74,4 +74,105 @@ do_test tkt-31338-2.2 {
|
||||
} {111 222 222 333 888 333 444 444 555 888 333 444 444 555 999}
|
||||
|
||||
|
||||
# Ticket [2c2de252666662f5459904fc33a9f2956cbff23c]
|
||||
#
|
||||
do_test tkt-31338-3.1 {
|
||||
foreach x [db eval {SELECT name FROM sqlite_master WHERE type='table'}] {
|
||||
db eval "DROP TABLE $x"
|
||||
}
|
||||
db eval {
|
||||
CREATE TABLE t1(a,b,c,d);
|
||||
CREATE TABLE t2(e,f);
|
||||
INSERT INTO t1 VALUES(1,2,3,4);
|
||||
INSERT INTO t2 VALUES(10,-8);
|
||||
CREATE INDEX t1a ON t1(a);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
CREATE TABLE t3(g);
|
||||
INSERT INTO t3 VALUES(4);
|
||||
CREATE TABLE t4(h);
|
||||
INSERT INTO t4 VALUES(5);
|
||||
|
||||
SELECT * FROM t3 LEFT JOIN t1 ON d=g LEFT JOIN t4 ON c=h
|
||||
WHERE (a=1 AND h=4)
|
||||
OR (b IN (
|
||||
SELECT x FROM (SELECT e+f AS x, e FROM t2 ORDER BY 1 LIMIT 2)
|
||||
GROUP BY e
|
||||
));
|
||||
}
|
||||
} {4 1 2 3 4 {}}
|
||||
do_test tkt-31338-3.2 {
|
||||
db eval {
|
||||
SELECT * FROM t3 LEFT JOIN t1 ON d=g LEFT JOIN t4 ON c=h
|
||||
WHERE (a=1 AND h=4)
|
||||
OR (b=2 AND b NOT IN (
|
||||
SELECT x+1 FROM (SELECT e+f AS x, e FROM t2 ORDER BY 1 LIMIT 2)
|
||||
GROUP BY e
|
||||
));
|
||||
}
|
||||
} {4 1 2 3 4 {}}
|
||||
do_test tkt-31338-3.3 {
|
||||
db eval {
|
||||
SELECT * FROM t3 LEFT JOIN t1 ON d=g LEFT JOIN t4 ON c=h
|
||||
WHERE (+a=1 AND h=4)
|
||||
OR (b IN (
|
||||
SELECT x FROM (SELECT e+f AS x, e FROM t2 ORDER BY 1 LIMIT 2)
|
||||
GROUP BY e
|
||||
));
|
||||
}
|
||||
} {4 1 2 3 4 {}}
|
||||
do_test tkt-31338-3.4 {
|
||||
db eval {
|
||||
SELECT * FROM t3 LEFT JOIN t1 ON d=g LEFT JOIN t4 ON c=h
|
||||
WHERE (a=1 AND h=4)
|
||||
OR (+b IN (
|
||||
SELECT x FROM (SELECT e+f AS x, e FROM t2 ORDER BY 1 LIMIT 2)
|
||||
GROUP BY e
|
||||
));
|
||||
}
|
||||
} {4 1 2 3 4 {}}
|
||||
|
||||
do_test tkt-31338-3.5 {
|
||||
db eval {
|
||||
CREATE TABLE t5(a,b,c,d,e,f);
|
||||
CREATE TABLE t6(g,h);
|
||||
CREATE TRIGGER t6r AFTER INSERT ON t6 BEGIN
|
||||
INSERT INTO t5
|
||||
SELECT * FROM t3 LEFT JOIN t1 ON d=g LEFT JOIN t4 ON c=h
|
||||
WHERE (a=1 AND h=4)
|
||||
OR (b IN (
|
||||
SELECT x FROM (SELECT e+f AS x, e FROM t2 ORDER BY 1 LIMIT 2)
|
||||
GROUP BY e
|
||||
));
|
||||
END;
|
||||
INSERT INTO t6 VALUES(88,99);
|
||||
SELECT * FROM t5;
|
||||
}
|
||||
} {4 1 2 3 4 {}}
|
||||
|
||||
do_test tkt-31338-3.6 {
|
||||
db eval {
|
||||
INSERT INTO t1 VALUES(2,4,3,4);
|
||||
INSERT INTO t1 VALUES(99,101,3,4);
|
||||
INSERT INTO t1 VALUES(98,97,3,4);
|
||||
SELECT * FROM t3 LEFT JOIN t1 ON d=g LEFT JOIN t4 ON c=h
|
||||
WHERE (a=1 AND h=4)
|
||||
OR (b IN (
|
||||
SELECT x+a FROM (SELECT e+f AS x, e FROM t2 ORDER BY 1 LIMIT 2)
|
||||
GROUP BY e
|
||||
));
|
||||
}
|
||||
} {4 2 4 3 4 {} 4 99 101 3 4 {}}
|
||||
|
||||
do_test tkt-31338-3.7 {
|
||||
db eval {
|
||||
SELECT * FROM t3 LEFT JOIN t1 ON d=g LEFT JOIN t4 ON c=h
|
||||
WHERE (a=1 AND h=4)
|
||||
OR (b IN (
|
||||
SELECT x FROM (SELECT e+f+a AS x, e FROM t2 ORDER BY 1 LIMIT 2)
|
||||
GROUP BY e
|
||||
));
|
||||
}
|
||||
} {4 2 4 3 4 {} 4 99 101 3 4 {}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -4,11 +4,14 @@
|
||||
#
|
||||
|
||||
if {[catch {
|
||||
if {![info exists argv0]} {
|
||||
set argv0 [file rootname [file tail [info nameofexecutable]]]
|
||||
}
|
||||
|
||||
# Get the name of the database to analyze
|
||||
#
|
||||
#set argv $argv0
|
||||
if {[llength $argv]!=1} {
|
||||
if {![info exists argv] || [llength $argv]!=1} {
|
||||
puts stderr "Usage: $argv0 database-name"
|
||||
exit 1
|
||||
}
|
||||
@ -28,12 +31,12 @@ if {[file size $file_to_analyze]<512} {
|
||||
|
||||
# Open the database
|
||||
#
|
||||
sqlite3 db [lindex $argv 0]
|
||||
sqlite3 db $file_to_analyze
|
||||
register_dbstat_vtab db
|
||||
|
||||
set pageSize [db one {PRAGMA page_size}]
|
||||
|
||||
#set DB [btree_open [lindex $argv 0] 1000 0]
|
||||
#set DB [btree_open $file_to_analyze 1000 0]
|
||||
|
||||
# In-memory database for collecting statistics. This script loops through
|
||||
# the tables and indices in the database being analyzed, adding a row for each
|
||||
|
Loading…
x
Reference in New Issue
Block a user