mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Merge all recent trunk enhancements and fixes into the sessions branch.
FossilOrigin-Name: e158812c34b01ce516d26636a489509bf61d1c27
This commit is contained in:
30
manifest
30
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Add\sthe\ssqlite3_rtree_query_callback()\sAPI\sto\sthe\sRTree\svirtual\stable.
|
C Merge\sall\srecent\strunk\senhancements\sand\sfixes\sinto\sthe\ssessions\sbranch.
|
||||||
D 2014-04-28T17:51:12.403
|
D 2014-04-28T18:02:21.241
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a
|
F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -196,7 +196,7 @@ F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486
|
|||||||
F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd
|
F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd
|
||||||
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
||||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||||
F src/insert.c e1ebd5d798da6b8dc180841c34e3c91b4d1fb798
|
F src/insert.c 2396a980907782f959362c2aef8e1596bb57c5ac
|
||||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||||
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
||||||
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
||||||
@@ -232,12 +232,12 @@ F src/printf.c e5a0005f8b3de21f85da6a709d2fbee76775bf4b
|
|||||||
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
||||||
F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66
|
F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66
|
||||||
F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be
|
F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be
|
||||||
F src/select.c 269c3e31a450fce642a10569221a49180348c88e
|
F src/select.c bc7feff0fb4c4a1b9d655b717bef166846b48e33
|
||||||
F src/shell.c 2afe7a7154e97be0c74c5feacf09626bda8493be
|
F src/shell.c 2afe7a7154e97be0c74c5feacf09626bda8493be
|
||||||
F src/sqlite.h.in 6e6d3e092ca968abb3e65fbe22ec9220a3b616b6
|
F src/sqlite.h.in 6e6d3e092ca968abb3e65fbe22ec9220a3b616b6
|
||||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||||
F src/sqliteInt.h 8697c8e82d4d2ccbfe7fd2f582081e600c9dc7fc
|
F src/sqliteInt.h 76b4d4f0b9200e58b0a2d5339e2d46b4c7c7c691
|
||||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||||
@@ -293,7 +293,7 @@ F src/update.c 7bb549d61efc6853f5cc708c1de6931179f8a12d
|
|||||||
F src/utf.c 6dc9ec9f1b3db43ae8ba0365377f11df1ee4c01c
|
F src/utf.c 6dc9ec9f1b3db43ae8ba0365377f11df1ee4c01c
|
||||||
F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf
|
F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf
|
||||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||||
F src/vdbe.c 9d883d5c91c5e7636cd56e952a0ff567e2d5c119
|
F src/vdbe.c d6038559beb49c57f73a79412821d7143fc276ee
|
||||||
F src/vdbe.h d03fcf47890ae1c79a335ca994cb878b302697ca
|
F src/vdbe.h d03fcf47890ae1c79a335ca994cb878b302697ca
|
||||||
F src/vdbeInt.h c05d4572211384c560b7579e7a299248cf31d6bd
|
F src/vdbeInt.h c05d4572211384c560b7579e7a299248cf31d6bd
|
||||||
F src/vdbeapi.c d3c662762b62e330a03f29de8e2ac7098ef78030
|
F src/vdbeapi.c d3c662762b62e330a03f29de8e2ac7098ef78030
|
||||||
@@ -306,8 +306,8 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
|
|||||||
F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
|
F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
|
||||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||||
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
|
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
|
||||||
F src/where.c 7614c4383d8b6143558dc349da286d0325704d35
|
F src/where.c 6ae02f1e8b1b29744d9e8cd9b95eac4c5232736d
|
||||||
F src/whereInt.h 2564055b440e44ebec8b47f237bbccae6719b7af
|
F src/whereInt.h 929c1349b5355fd44f22cee5c14d72b3329c58a6
|
||||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
||||||
@@ -448,12 +448,12 @@ F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
|
|||||||
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
|
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
|
||||||
F test/distinct.test 086e70c765f172e8974e9f83b9ac5ca03c154e77
|
F test/distinct.test 086e70c765f172e8974e9f83b9ac5ca03c154e77
|
||||||
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
|
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
|
||||||
F test/e_createtable.test ee95d48664503d40f6cc9ef4a7d03216188e2ada
|
F test/e_createtable.test ed82efcedc4b3656b27a5fcd12335cdb7e20eeee
|
||||||
F test/e_delete.test d5186e2f5478b659f16a2c8b66c09892823e542a
|
F test/e_delete.test d5186e2f5478b659f16a2c8b66c09892823e542a
|
||||||
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
|
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
|
||||||
F test/e_dropview.test 0c9f7f60989164a70a67a9d9c26d1083bc808306
|
F test/e_dropview.test 0c9f7f60989164a70a67a9d9c26d1083bc808306
|
||||||
F test/e_expr.test 5c71d183fbf519a4769fd2e2124afdc70b5b1f42
|
F test/e_expr.test 5c71d183fbf519a4769fd2e2124afdc70b5b1f42
|
||||||
F test/e_fkey.test 630597377549af579d34faaf64c6959a5a68ef76
|
F test/e_fkey.test a1783fe1f759e1990e6a11adfcf0702dac4d0707
|
||||||
F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
|
F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
|
||||||
F test/e_insert.test 1e44f84d2abe44d66e4fbf198be4b20e3cc724a0
|
F test/e_insert.test 1e44f84d2abe44d66e4fbf198be4b20e3cc724a0
|
||||||
F test/e_reindex.test 396b7b4f0a66863b4e95116a67d93b227193e589
|
F test/e_reindex.test 396b7b4f0a66863b4e95116a67d93b227193e589
|
||||||
@@ -739,6 +739,7 @@ F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
|
|||||||
F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
|
F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
|
||||||
F test/orderby5.test 2490183fef54417209d1df253633a605d46bd350
|
F test/orderby5.test 2490183fef54417209d1df253633a605d46bd350
|
||||||
F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
|
F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
|
||||||
|
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
|
||||||
F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
|
F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
|
||||||
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
|
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
|
||||||
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
|
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
|
||||||
@@ -913,6 +914,7 @@ F test/tkt-a8a0d2996a.test eb597379dbcefa24765763d7f682c00cb5924fa9
|
|||||||
F test/tkt-b1d3a2e531.test 8f7576e41ca179289ee1a8fee28386fd8e4b0550
|
F test/tkt-b1d3a2e531.test 8f7576e41ca179289ee1a8fee28386fd8e4b0550
|
||||||
F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0
|
F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0
|
||||||
F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3
|
F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3
|
||||||
|
F test/tkt-b75a9ca6b0.test 97cc2d5eeaf82799eb42138c0a1ff64370238ce4
|
||||||
F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898
|
F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898
|
||||||
F test/tkt-bdc6bbbb38.test fc38bb09bdd440e3513a1f5f98fc60a075182d7d
|
F test/tkt-bdc6bbbb38.test fc38bb09bdd440e3513a1f5f98fc60a075182d7d
|
||||||
F test/tkt-c48d99d690.test ba61977d62ab612fc515b3c488a6fbd6464a2447
|
F test/tkt-c48d99d690.test ba61977d62ab612fc515b3c488a6fbd6464a2447
|
||||||
@@ -921,6 +923,7 @@ F test/tkt-d11f09d36e.test d999b548fef885d1d1afa49a0e8544ecf436869d
|
|||||||
F test/tkt-d635236375.test 9d37e988b47d87505bc9445be0ca447002df5d09
|
F test/tkt-d635236375.test 9d37e988b47d87505bc9445be0ca447002df5d09
|
||||||
F test/tkt-d82e3f3721.test bcc0dfba658d15bab30fd4a9320c9e35d214ce30
|
F test/tkt-d82e3f3721.test bcc0dfba658d15bab30fd4a9320c9e35d214ce30
|
||||||
F test/tkt-f3e5abed55.test d5a0126118142d13e27f6ce9f4c47096e9321c00
|
F test/tkt-f3e5abed55.test d5a0126118142d13e27f6ce9f4c47096e9321c00
|
||||||
|
F test/tkt-f67b41381a.test a23bc124c981662db712167bacd0ed8ad11abac9
|
||||||
F test/tkt-f777251dc7a.test af6531446c64bfd268416f07b4df7be7f9c749d2
|
F test/tkt-f777251dc7a.test af6531446c64bfd268416f07b4df7be7f9c749d2
|
||||||
F test/tkt-f7b4edec.test d998a08ff2b18b7f62edce8e3044317c45efe6c7
|
F test/tkt-f7b4edec.test d998a08ff2b18b7f62edce8e3044317c45efe6c7
|
||||||
F test/tkt-f973c7ac31.test 28ef85c7f015477916795246d8286aeda39d4ead
|
F test/tkt-f973c7ac31.test 28ef85c7f015477916795246d8286aeda39d4ead
|
||||||
@@ -1177,8 +1180,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||||
P 95e77efe076ab421bd246119c47dba5dacf9d087 f7dad408dd46a1e3612b6142a3afb1d0d4fcda00
|
P 3dca2809352c6c6d56db74447a814f77011c6220 af2cbe64adab5f9e3b0f3da00d06428088589d7f
|
||||||
R dc0ef589b047e789a0dc76337788157a
|
R 9172deb3091895924031286a7ef97633
|
||||||
T +closed f7dad408dd46a1e3612b6142a3afb1d0d4fcda00
|
|
||||||
U drh
|
U drh
|
||||||
Z d1607abc9a994a369c35e1f132aa6989
|
Z dedb5680561bda872be1d3df9c89cc1d
|
||||||
|
@@ -1 +1 @@
|
|||||||
3dca2809352c6c6d56db74447a814f77011c6220
|
e158812c34b01ce516d26636a489509bf61d1c27
|
15
src/insert.c
15
src/insert.c
@@ -1877,15 +1877,24 @@ static int xferOptimization(
|
|||||||
return 0; /* Both tables must have the same INTEGER PRIMARY KEY */
|
return 0; /* Both tables must have the same INTEGER PRIMARY KEY */
|
||||||
}
|
}
|
||||||
for(i=0; i<pDest->nCol; i++){
|
for(i=0; i<pDest->nCol; i++){
|
||||||
if( pDest->aCol[i].affinity!=pSrc->aCol[i].affinity ){
|
Column *pDestCol = &pDest->aCol[i];
|
||||||
|
Column *pSrcCol = &pSrc->aCol[i];
|
||||||
|
if( pDestCol->affinity!=pSrcCol->affinity ){
|
||||||
return 0; /* Affinity must be the same on all columns */
|
return 0; /* Affinity must be the same on all columns */
|
||||||
}
|
}
|
||||||
if( !xferCompatibleCollation(pDest->aCol[i].zColl, pSrc->aCol[i].zColl) ){
|
if( !xferCompatibleCollation(pDestCol->zColl, pSrcCol->zColl) ){
|
||||||
return 0; /* Collating sequence must be the same on all columns */
|
return 0; /* Collating sequence must be the same on all columns */
|
||||||
}
|
}
|
||||||
if( pDest->aCol[i].notNull && !pSrc->aCol[i].notNull ){
|
if( pDestCol->notNull && !pSrcCol->notNull ){
|
||||||
return 0; /* tab2 must be NOT NULL if tab1 is */
|
return 0; /* tab2 must be NOT NULL if tab1 is */
|
||||||
}
|
}
|
||||||
|
/* Default values for second and subsequent columns need to match. */
|
||||||
|
if( i>0
|
||||||
|
&& ((pDestCol->zDflt==0)!=(pSrcCol->zDflt==0)
|
||||||
|
|| (pDestCol->zDflt && strcmp(pDestCol->zDflt, pSrcCol->zDflt)!=0))
|
||||||
|
){
|
||||||
|
return 0; /* Default values must be the same for all columns */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
|
for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
|
||||||
if( pDestIdx->onError!=OE_None ){
|
if( pDestIdx->onError!=OE_None ){
|
||||||
|
43
src/select.c
43
src/select.c
@@ -4719,18 +4719,6 @@ int sqlite3Select(
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If there is both a GROUP BY and an ORDER BY clause and they are
|
|
||||||
** identical, then disable the ORDER BY clause since the GROUP BY
|
|
||||||
** will cause elements to come out in the correct order. This is
|
|
||||||
** an optimization - the correct answer should result regardless.
|
|
||||||
** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
|
|
||||||
** to disable this optimization for testing purposes.
|
|
||||||
*/
|
|
||||||
if( sqlite3ExprListCompare(p->pGroupBy, sSort.pOrderBy, -1)==0
|
|
||||||
&& OptimizationEnabled(db, SQLITE_GroupByOrder) ){
|
|
||||||
sSort.pOrderBy = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
|
/* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
|
||||||
** if the select-list is the same as the ORDER BY list, then this query
|
** if the select-list is the same as the ORDER BY list, then this query
|
||||||
** can be rewritten as a GROUP BY. In other words, this:
|
** can be rewritten as a GROUP BY. In other words, this:
|
||||||
@@ -4859,6 +4847,7 @@ int sqlite3Select(
|
|||||||
int addrEnd; /* End of processing for this SELECT */
|
int addrEnd; /* End of processing for this SELECT */
|
||||||
int sortPTab = 0; /* Pseudotable used to decode sorting results */
|
int sortPTab = 0; /* Pseudotable used to decode sorting results */
|
||||||
int sortOut = 0; /* Output register from the sorter */
|
int sortOut = 0; /* Output register from the sorter */
|
||||||
|
int orderByGrp = 0; /* True if the GROUP BY and ORDER BY are the same */
|
||||||
|
|
||||||
/* Remove any and all aliases between the result set and the
|
/* Remove any and all aliases between the result set and the
|
||||||
** GROUP BY clause.
|
** GROUP BY clause.
|
||||||
@@ -4878,6 +4867,18 @@ int sqlite3Select(
|
|||||||
p->nSelectRow = 1;
|
p->nSelectRow = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* If there is both a GROUP BY and an ORDER BY clause and they are
|
||||||
|
** identical, then it may be possible to disable the ORDER BY clause
|
||||||
|
** on the grounds that the GROUP BY will cause elements to come out
|
||||||
|
** in the correct order. It also may not - the GROUP BY may use a
|
||||||
|
** database index that causes rows to be grouped together as required
|
||||||
|
** but not actually sorted. Either way, record the fact that the
|
||||||
|
** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
|
||||||
|
** variable. */
|
||||||
|
if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
|
||||||
|
orderByGrp = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a label to jump to when we want to abort the query */
|
/* Create a label to jump to when we want to abort the query */
|
||||||
addrEnd = sqlite3VdbeMakeLabel(v);
|
addrEnd = sqlite3VdbeMakeLabel(v);
|
||||||
@@ -4958,7 +4959,8 @@ int sqlite3Select(
|
|||||||
*/
|
*/
|
||||||
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
|
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
|
||||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
|
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
|
||||||
WHERE_GROUPBY, 0);
|
WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0
|
||||||
|
);
|
||||||
if( pWInfo==0 ) goto select_end;
|
if( pWInfo==0 ) goto select_end;
|
||||||
if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){
|
if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){
|
||||||
/* The optimizer is able to deliver rows in group by order so
|
/* The optimizer is able to deliver rows in group by order so
|
||||||
@@ -5023,6 +5025,21 @@ int sqlite3Select(
|
|||||||
VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v);
|
VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v);
|
||||||
sAggInfo.useSortingIdx = 1;
|
sAggInfo.useSortingIdx = 1;
|
||||||
sqlite3ExprCacheClear(pParse);
|
sqlite3ExprCacheClear(pParse);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the index or temporary table used by the GROUP BY sort
|
||||||
|
** will naturally deliver rows in the order required by the ORDER BY
|
||||||
|
** clause, cancel the ephemeral table open coded earlier.
|
||||||
|
**
|
||||||
|
** This is an optimization - the correct answer should result regardless.
|
||||||
|
** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER to
|
||||||
|
** disable this optimization for testing purposes. */
|
||||||
|
if( orderByGrp && OptimizationEnabled(db, SQLITE_GroupByOrder)
|
||||||
|
&& (groupBySort || sqlite3WhereIsSorted(pWInfo))
|
||||||
|
){
|
||||||
|
sSort.pOrderBy = 0;
|
||||||
|
sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Evaluate the current GROUP BY terms and store in b0, b1, b2...
|
/* Evaluate the current GROUP BY terms and store in b0, b1, b2...
|
||||||
|
@@ -2133,6 +2133,7 @@ struct SrcList {
|
|||||||
#define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
|
#define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
|
||||||
#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
|
#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
|
||||||
#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
|
#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
|
||||||
|
#define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */
|
||||||
|
|
||||||
/* Allowed return values from sqlite3WhereIsDistinct()
|
/* Allowed return values from sqlite3WhereIsDistinct()
|
||||||
*/
|
*/
|
||||||
@@ -3104,6 +3105,7 @@ void sqlite3WhereEnd(WhereInfo*);
|
|||||||
u64 sqlite3WhereOutputRowCount(WhereInfo*);
|
u64 sqlite3WhereOutputRowCount(WhereInfo*);
|
||||||
int sqlite3WhereIsDistinct(WhereInfo*);
|
int sqlite3WhereIsDistinct(WhereInfo*);
|
||||||
int sqlite3WhereIsOrdered(WhereInfo*);
|
int sqlite3WhereIsOrdered(WhereInfo*);
|
||||||
|
int sqlite3WhereIsSorted(WhereInfo*);
|
||||||
int sqlite3WhereContinueLabel(WhereInfo*);
|
int sqlite3WhereContinueLabel(WhereInfo*);
|
||||||
int sqlite3WhereBreakLabel(WhereInfo*);
|
int sqlite3WhereBreakLabel(WhereInfo*);
|
||||||
int sqlite3WhereOkOnePass(WhereInfo*, int*);
|
int sqlite3WhereOkOnePass(WhereInfo*, int*);
|
||||||
|
@@ -6384,8 +6384,8 @@ default: { /* This is really OP_Noop and OP_Explain */
|
|||||||
|
|
||||||
#ifdef VDBE_PROFILE
|
#ifdef VDBE_PROFILE
|
||||||
{
|
{
|
||||||
u64 elapsed = sqlite3Hwtime() - start;
|
u64 endTime = sqlite3Hwtime();
|
||||||
pOp->cycles += elapsed;
|
if( endTime>start ) pOp->cycles += endTime - start;
|
||||||
pOp->cnt++;
|
pOp->cnt++;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
113
src/where.c
113
src/where.c
@@ -3712,18 +3712,36 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Return TRUE if the set of WHERE clause terms used by pA is a proper
|
** Return TRUE if both of the following are true:
|
||||||
** subset of the WHERE clause terms used by pB.
|
**
|
||||||
|
** (1) X has the same or lower cost that Y
|
||||||
|
** (2) X is a proper subset of Y
|
||||||
|
**
|
||||||
|
** By "proper subset" we mean that X uses fewer WHERE clause terms
|
||||||
|
** than Y and that every WHERE clause term used by X is also used
|
||||||
|
** by Y.
|
||||||
|
**
|
||||||
|
** If X is a proper subset of Y then Y is a better choice and ought
|
||||||
|
** to have a lower cost. This routine returns TRUE when that cost
|
||||||
|
** relationship is inverted and needs to be adjusted.
|
||||||
*/
|
*/
|
||||||
static int whereLoopProperSubset(const WhereLoop *pA, const WhereLoop *pB){
|
static int whereLoopCheaperProperSubset(
|
||||||
|
const WhereLoop *pX, /* First WhereLoop to compare */
|
||||||
|
const WhereLoop *pY /* Compare against this WhereLoop */
|
||||||
|
){
|
||||||
int i, j;
|
int i, j;
|
||||||
assert( pA->nLTerm<pB->nLTerm ); /* Checked by calling function */
|
if( pX->nLTerm >= pY->nLTerm ) return 0; /* X is not a subset of Y */
|
||||||
for(j=0, i=pA->nLTerm-1; i>=0 && j>=0; i--){
|
if( pX->rRun >= pY->rRun ){
|
||||||
for(j=pB->nLTerm-1; j>=0; j--){
|
if( pX->rRun > pY->rRun ) return 0; /* X costs more than Y */
|
||||||
if( pB->aLTerm[j]==pA->aLTerm[i] ) break;
|
if( pX->nOut > pY->nOut ) return 0; /* X costs more than Y */
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return j>=0;
|
for(j=0, i=pX->nLTerm-1; i>=0; i--){
|
||||||
|
for(j=pY->nLTerm-1; j>=0; j--){
|
||||||
|
if( pY->aLTerm[j]==pX->aLTerm[i] ) break;
|
||||||
|
}
|
||||||
|
if( j<0 ) return 0; /* X not a subset of Y since term X[i] not used by Y */
|
||||||
|
}
|
||||||
|
return 1; /* All conditions meet */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3745,19 +3763,14 @@ static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){
|
|||||||
for(; p; p=p->pNextLoop){
|
for(; p; p=p->pNextLoop){
|
||||||
if( p->iTab!=pTemplate->iTab ) continue;
|
if( p->iTab!=pTemplate->iTab ) continue;
|
||||||
if( (p->wsFlags & WHERE_INDEXED)==0 ) continue;
|
if( (p->wsFlags & WHERE_INDEXED)==0 ) continue;
|
||||||
if( p->nLTerm<pTemplate->nLTerm
|
if( whereLoopCheaperProperSubset(p, pTemplate) ){
|
||||||
&& (p->rRun<pTemplate->rRun || (p->rRun==pTemplate->rRun &&
|
/* Adjust pTemplate cost downward so that it is cheaper than its
|
||||||
p->nOut<=pTemplate->nOut))
|
** subset p */
|
||||||
&& whereLoopProperSubset(p, pTemplate)
|
|
||||||
){
|
|
||||||
pTemplate->rRun = p->rRun;
|
pTemplate->rRun = p->rRun;
|
||||||
pTemplate->nOut = p->nOut - 1;
|
pTemplate->nOut = p->nOut - 1;
|
||||||
}else
|
}else if( whereLoopCheaperProperSubset(pTemplate, p) ){
|
||||||
if( p->nLTerm>pTemplate->nLTerm
|
/* Adjust pTemplate cost upward so that it is costlier than p since
|
||||||
&& (p->rRun>pTemplate->rRun || (p->rRun==pTemplate->rRun &&
|
** pTemplate is a proper subset of p */
|
||||||
p->nOut>=pTemplate->nOut))
|
|
||||||
&& whereLoopProperSubset(pTemplate, p)
|
|
||||||
){
|
|
||||||
pTemplate->rRun = p->rRun;
|
pTemplate->rRun = p->rRun;
|
||||||
pTemplate->nOut = p->nOut + 1;
|
pTemplate->nOut = p->nOut + 1;
|
||||||
}
|
}
|
||||||
@@ -4783,7 +4796,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
|
|||||||
** Note that processing for WHERE_GROUPBY and WHERE_DISTINCTBY is not as
|
** Note that processing for WHERE_GROUPBY and WHERE_DISTINCTBY is not as
|
||||||
** strict. With GROUP BY and DISTINCT the only requirement is that
|
** strict. With GROUP BY and DISTINCT the only requirement is that
|
||||||
** equivalent rows appear immediately adjacent to one another. GROUP BY
|
** equivalent rows appear immediately adjacent to one another. GROUP BY
|
||||||
** and DISTINT do not require rows to appear in any particular order as long
|
** and DISTINCT do not require rows to appear in any particular order as long
|
||||||
** as equivelent rows are grouped together. Thus for GROUP BY and DISTINCT
|
** as equivelent rows are grouped together. Thus for GROUP BY and DISTINCT
|
||||||
** the pOrderBy terms can be matched in any order. With ORDER BY, the
|
** the pOrderBy terms can be matched in any order. With ORDER BY, the
|
||||||
** pOrderBy terms must be matched in strict left-to-right order.
|
** pOrderBy terms must be matched in strict left-to-right order.
|
||||||
@@ -4844,14 +4857,6 @@ static i8 wherePathSatisfiesOrderBy(
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
assert( pOrderBy!=0 );
|
assert( pOrderBy!=0 );
|
||||||
|
|
||||||
/* Sortability of virtual tables is determined by the xBestIndex method
|
|
||||||
** of the virtual table itself */
|
|
||||||
if( pLast->wsFlags & WHERE_VIRTUALTABLE ){
|
|
||||||
testcase( nLoop>0 ); /* True when outer loops are one-row and match
|
|
||||||
** no ORDER BY terms */
|
|
||||||
return pLast->u.vtab.isOrdered;
|
|
||||||
}
|
|
||||||
if( nLoop && OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ) return 0;
|
if( nLoop && OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ) return 0;
|
||||||
|
|
||||||
nOrderBy = pOrderBy->nExpr;
|
nOrderBy = pOrderBy->nExpr;
|
||||||
@@ -4864,7 +4869,10 @@ static i8 wherePathSatisfiesOrderBy(
|
|||||||
for(iLoop=0; isOrderDistinct && obSat<obDone && iLoop<=nLoop; iLoop++){
|
for(iLoop=0; isOrderDistinct && obSat<obDone && iLoop<=nLoop; iLoop++){
|
||||||
if( iLoop>0 ) ready |= pLoop->maskSelf;
|
if( iLoop>0 ) ready |= pLoop->maskSelf;
|
||||||
pLoop = iLoop<nLoop ? pPath->aLoop[iLoop] : pLast;
|
pLoop = iLoop<nLoop ? pPath->aLoop[iLoop] : pLast;
|
||||||
assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 );
|
if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
|
||||||
|
if( pLoop->u.vtab.isOrdered ) obSat = obDone;
|
||||||
|
break;
|
||||||
|
}
|
||||||
iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;
|
iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;
|
||||||
|
|
||||||
/* Mark off any ORDER BY term X that is a column in the table of
|
/* Mark off any ORDER BY term X that is a column in the table of
|
||||||
@@ -4952,7 +4960,7 @@ static i8 wherePathSatisfiesOrderBy(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Find the ORDER BY term that corresponds to the j-th column
|
/* Find the ORDER BY term that corresponds to the j-th column
|
||||||
** of the index and and mark that ORDER BY term off
|
** of the index and mark that ORDER BY term off
|
||||||
*/
|
*/
|
||||||
bOnce = 1;
|
bOnce = 1;
|
||||||
isMatch = 0;
|
isMatch = 0;
|
||||||
@@ -5032,6 +5040,36 @@ static i8 wherePathSatisfiesOrderBy(
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** If the WHERE_GROUPBY flag is set in the mask passed to sqlite3WhereBegin(),
|
||||||
|
** the planner assumes that the specified pOrderBy list is actually a GROUP
|
||||||
|
** BY clause - and so any order that groups rows as required satisfies the
|
||||||
|
** request.
|
||||||
|
**
|
||||||
|
** Normally, in this case it is not possible for the caller to determine
|
||||||
|
** whether or not the rows are really being delivered in sorted order, or
|
||||||
|
** just in some other order that provides the required grouping. However,
|
||||||
|
** if the WHERE_SORTBYGROUP flag is also passed to sqlite3WhereBegin(), then
|
||||||
|
** this function may be called on the returned WhereInfo object. It returns
|
||||||
|
** true if the rows really will be sorted in the specified order, or false
|
||||||
|
** otherwise.
|
||||||
|
**
|
||||||
|
** For example, assuming:
|
||||||
|
**
|
||||||
|
** CREATE INDEX i1 ON t1(x, Y);
|
||||||
|
**
|
||||||
|
** then
|
||||||
|
**
|
||||||
|
** SELECT * FROM t1 GROUP BY x,y ORDER BY x,y; -- IsSorted()==1
|
||||||
|
** SELECT * FROM t1 GROUP BY y,x ORDER BY y,x; -- IsSorted()==0
|
||||||
|
*/
|
||||||
|
int sqlite3WhereIsSorted(WhereInfo *pWInfo){
|
||||||
|
assert( pWInfo->wctrlFlags & WHERE_GROUPBY );
|
||||||
|
assert( pWInfo->wctrlFlags & WHERE_SORTBYGROUP );
|
||||||
|
return pWInfo->sorted;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WHERETRACE_ENABLED
|
#ifdef WHERETRACE_ENABLED
|
||||||
/* For debugging use only: */
|
/* For debugging use only: */
|
||||||
static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){
|
static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){
|
||||||
@@ -5044,7 +5082,6 @@ static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
|
** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
|
||||||
** attempts to find the lowest cost path that visits each WhereLoop
|
** attempts to find the lowest cost path that visits each WhereLoop
|
||||||
@@ -5325,7 +5362,19 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||||||
if( pWInfo->nOBSat<0 ) pWInfo->nOBSat = 0;
|
if( pWInfo->nOBSat<0 ) pWInfo->nOBSat = 0;
|
||||||
pWInfo->revMask = pFrom->revLoop;
|
pWInfo->revMask = pFrom->revLoop;
|
||||||
}
|
}
|
||||||
|
if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)
|
||||||
|
&& pWInfo->nOBSat==pWInfo->pOrderBy->nExpr
|
||||||
|
){
|
||||||
|
Bitmask notUsed = 0;
|
||||||
|
int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy,
|
||||||
|
pFrom, 0, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used
|
||||||
|
);
|
||||||
|
assert( pWInfo->sorted==0 );
|
||||||
|
pWInfo->sorted = (nOrder==pWInfo->pOrderBy->nExpr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pWInfo->nRowOut = pFrom->nRow;
|
pWInfo->nRowOut = pFrom->nRow;
|
||||||
|
|
||||||
/* Free temporary memory and return success */
|
/* Free temporary memory and return success */
|
||||||
|
@@ -398,6 +398,7 @@ struct WhereInfo {
|
|||||||
LogEst nRowOut; /* Estimated number of output rows */
|
LogEst nRowOut; /* Estimated number of output rows */
|
||||||
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
|
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
|
||||||
i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */
|
i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */
|
||||||
|
u8 sorted; /* True if really sorted (not just grouped) */
|
||||||
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
|
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
|
||||||
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
|
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
|
||||||
u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
|
u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
|
||||||
|
@@ -884,9 +884,10 @@ do_execsql_test e_createtable-3.3.1 {
|
|||||||
);
|
);
|
||||||
} {}
|
} {}
|
||||||
|
|
||||||
# EVIDENCE-OF: R-10288-43169 For the purposes of the DEFAULT clause, an
|
# EVIDENCE-OF: R-36381-62919 For the purposes of the DEFAULT clause, an
|
||||||
# expression is considered constant provided that it does not contain
|
# expression is considered constant provided that it does not contain
|
||||||
# any sub-queries or string constants enclosed in double quotes.
|
# any sub-queries, column or table references, or string literals
|
||||||
|
# enclosed in double-quotes instead of single-quotes.
|
||||||
#
|
#
|
||||||
do_createtable_tests 3.4.1 -error {
|
do_createtable_tests 3.4.1 -error {
|
||||||
default value of column [x] is not constant
|
default value of column [x] is not constant
|
||||||
|
@@ -135,9 +135,9 @@ reset_db
|
|||||||
#
|
#
|
||||||
# This also tests that foreign key constraints are disabled by default.
|
# This also tests that foreign key constraints are disabled by default.
|
||||||
#
|
#
|
||||||
# EVIDENCE-OF: R-59578-04990 Foreign key constraints are disabled by
|
# EVIDENCE-OF: R-44261-39702 Foreign key constraints are disabled by
|
||||||
# default (for backwards compatibility), so must be enabled separately
|
# default (for backwards compatibility), so must be enabled separately
|
||||||
# for each database connection separately.
|
# for each database connection.
|
||||||
#
|
#
|
||||||
drop_all_tables
|
drop_all_tables
|
||||||
do_test e_fkey-4.1 {
|
do_test e_fkey-4.1 {
|
||||||
@@ -163,9 +163,10 @@ do_test e_fkey-4.2 {
|
|||||||
} {world}
|
} {world}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# EVIDENCE-OF: R-15278-54456 The application can can also use a PRAGMA
|
# EVIDENCE-OF: R-08013-37737 The application can also use a PRAGMA
|
||||||
# foreign_keys statement to determine if foreign keys are currently
|
# foreign_keys statement to determine if foreign keys are currently
|
||||||
# enabled.
|
# enabled.
|
||||||
|
|
||||||
#
|
#
|
||||||
# This also tests the example code in section 2 of foreignkeys.in.
|
# This also tests the example code in section 2 of foreignkeys.in.
|
||||||
#
|
#
|
||||||
@@ -2990,8 +2991,8 @@ if {[clang_sanitize_address]==0} {
|
|||||||
# The setting of the recursive_triggers pragma does not affect foreign
|
# The setting of the recursive_triggers pragma does not affect foreign
|
||||||
# key actions.
|
# key actions.
|
||||||
#
|
#
|
||||||
# EVIDENCE-OF: R-51769-32730 The PRAGMA recursive_triggers setting does
|
# EVIDENCE-OF: R-44355-00270 The PRAGMA recursive_triggers setting does
|
||||||
# not not affect the operation of foreign key actions.
|
# not affect the operation of foreign key actions.
|
||||||
#
|
#
|
||||||
foreach recursive_triggers_setting [list 0 1 ON OFF] {
|
foreach recursive_triggers_setting [list 0 1 ON OFF] {
|
||||||
drop_all_tables
|
drop_all_tables
|
||||||
|
106
test/orderby7.test
Normal file
106
test/orderby7.test
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
# 2014-04-25
|
||||||
|
#
|
||||||
|
# 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 file is testing ORDER BY optimizations on joins
|
||||||
|
# that involve virtual tables.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
set testdir [file dirname $argv0]
|
||||||
|
source $testdir/tester.tcl
|
||||||
|
set ::testprefix orderby7
|
||||||
|
|
||||||
|
ifcapable !fts3 {
|
||||||
|
finish_test
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test 1.0 {
|
||||||
|
CREATE VIRTUAL TABLE fts USING fts3(content TEXT);
|
||||||
|
INSERT INTO fts(rowid,content)
|
||||||
|
VALUES(1,'this is a test of the fts3 virtual'),
|
||||||
|
(2,'table used as part of a join together'),
|
||||||
|
(3,'with the DISTINCT keyword. There was'),
|
||||||
|
(4,'a bug at one time (2013-06 through 2014-04)'),
|
||||||
|
(5,'that prevented this from working correctly.'),
|
||||||
|
(11,'a row that occurs twice'),
|
||||||
|
(12,'a row that occurs twice');
|
||||||
|
|
||||||
|
CREATE TABLE t1(x TEXT PRIMARY KEY, y);
|
||||||
|
INSERT OR IGNORE INTO t1 SELECT content, rowid+100 FROM fts;
|
||||||
|
} {}
|
||||||
|
do_execsql_test 1.1 {
|
||||||
|
SELECT DISTINCT fts.rowid, t1.y
|
||||||
|
FROM fts, t1
|
||||||
|
WHERE fts MATCH 'that twice'
|
||||||
|
AND content=x
|
||||||
|
ORDER BY y;
|
||||||
|
} {11 111 12 111}
|
||||||
|
do_execsql_test 1.2 {
|
||||||
|
SELECT DISTINCT fts.rowid, t1.x
|
||||||
|
FROM fts, t1
|
||||||
|
WHERE fts MATCH 'that twice'
|
||||||
|
AND content=x
|
||||||
|
ORDER BY 1;
|
||||||
|
} {11 {a row that occurs twice} 12 {a row that occurs twice}}
|
||||||
|
do_execsql_test 1.3 {
|
||||||
|
SELECT DISTINCT t1.x
|
||||||
|
FROM fts, t1
|
||||||
|
WHERE fts MATCH 'that twice'
|
||||||
|
AND content=x
|
||||||
|
ORDER BY 1;
|
||||||
|
} {{a row that occurs twice}}
|
||||||
|
do_execsql_test 1.4 {
|
||||||
|
SELECT t1.x
|
||||||
|
FROM fts, t1
|
||||||
|
WHERE fts MATCH 'that twice'
|
||||||
|
AND content=x
|
||||||
|
ORDER BY 1;
|
||||||
|
} {{a row that occurs twice} {a row that occurs twice}}
|
||||||
|
do_execsql_test 1.5 {
|
||||||
|
SELECT DISTINCT t1.x
|
||||||
|
FROM fts, t1
|
||||||
|
WHERE fts MATCH 'that twice'
|
||||||
|
AND content=x;
|
||||||
|
} {{a row that occurs twice}}
|
||||||
|
do_execsql_test 1.6 {
|
||||||
|
SELECT t1.x
|
||||||
|
FROM fts, t1
|
||||||
|
WHERE fts MATCH 'that twice'
|
||||||
|
AND content=x;
|
||||||
|
} {{a row that occurs twice} {a row that occurs twice}}
|
||||||
|
|
||||||
|
do_execsql_test 2.1 {
|
||||||
|
SELECT DISTINCT t1.x
|
||||||
|
FROM fts, t1
|
||||||
|
WHERE fts.rowid=11
|
||||||
|
AND content=x
|
||||||
|
ORDER BY fts.rowid;
|
||||||
|
} {{a row that occurs twice}}
|
||||||
|
do_execsql_test 2.2 {
|
||||||
|
SELECT DISTINCT t1.*
|
||||||
|
FROM fts, t1
|
||||||
|
WHERE fts.rowid=11
|
||||||
|
AND content=x
|
||||||
|
ORDER BY fts.rowid;
|
||||||
|
} {{a row that occurs twice} 111}
|
||||||
|
do_execsql_test 2.3 {
|
||||||
|
SELECT DISTINCT t1.*
|
||||||
|
FROM fts, t1
|
||||||
|
WHERE fts.rowid=11
|
||||||
|
AND content=x
|
||||||
|
ORDER BY t1.y
|
||||||
|
} {{a row that occurs twice} 111}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
finish_test
|
77
test/tkt-b75a9ca6b0.test
Normal file
77
test/tkt-b75a9ca6b0.test
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# 2014-04-21
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
#*************************************************************************
|
||||||
|
#
|
||||||
|
# Test that ticket [b75a9ca6b0] has been fixed.
|
||||||
|
#
|
||||||
|
# Ticket [b75a9ca6b0] concerns queries that have both a GROUP BY
|
||||||
|
# and an ORDER BY. This code verifies that SQLite is able to
|
||||||
|
# optimize out the ORDER BY in some circumstances, but retains the
|
||||||
|
# ORDER BY when necessary.
|
||||||
|
#
|
||||||
|
|
||||||
|
set testdir [file dirname $argv0]
|
||||||
|
source $testdir/tester.tcl
|
||||||
|
set testprefix tkt-b75a9ca6b0
|
||||||
|
|
||||||
|
do_execsql_test 1 {
|
||||||
|
CREATE TABLE t1 (x, y);
|
||||||
|
INSERT INTO t1 VALUES (1, 3);
|
||||||
|
INSERT INTO t1 VALUES (2, 2);
|
||||||
|
INSERT INTO t1 VALUES (3, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test 1.1 {
|
||||||
|
CREATE INDEX i1 ON t1(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
set idxscan {0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}}
|
||||||
|
set tblscan {0 0 0 {SCAN TABLE t1}}
|
||||||
|
set grpsort {0 0 0 {USE TEMP B-TREE FOR GROUP BY}}
|
||||||
|
set sort {0 0 0 {USE TEMP B-TREE FOR ORDER BY}}
|
||||||
|
|
||||||
|
foreach {tn q res eqp} [subst -nocommands {
|
||||||
|
1 "SELECT * FROM t1 GROUP BY x, y ORDER BY x,y"
|
||||||
|
{1 3 2 2 3 1} {$idxscan}
|
||||||
|
|
||||||
|
2 "SELECT * FROM t1 GROUP BY x, y ORDER BY x"
|
||||||
|
{1 3 2 2 3 1} {$idxscan $sort}
|
||||||
|
|
||||||
|
3 "SELECT * FROM t1 GROUP BY y, x ORDER BY y, x"
|
||||||
|
{3 1 2 2 1 3} {$idxscan $sort}
|
||||||
|
|
||||||
|
4 "SELECT * FROM t1 GROUP BY x ORDER BY x"
|
||||||
|
{1 3 2 2 3 1} {$idxscan}
|
||||||
|
|
||||||
|
5 "SELECT * FROM t1 GROUP BY y ORDER BY y"
|
||||||
|
{3 1 2 2 1 3} {$tblscan $grpsort}
|
||||||
|
|
||||||
|
6 "SELECT * FROM t1 GROUP BY y ORDER BY x"
|
||||||
|
{1 3 2 2 3 1} {$tblscan $grpsort $sort}
|
||||||
|
|
||||||
|
7 "SELECT * FROM t1 GROUP BY x, y ORDER BY x, y DESC"
|
||||||
|
{1 3 2 2 3 1} {$idxscan $sort}
|
||||||
|
|
||||||
|
8 "SELECT * FROM t1 GROUP BY x, y ORDER BY x DESC, y DESC"
|
||||||
|
{3 1 2 2 1 3} {$idxscan $sort}
|
||||||
|
|
||||||
|
9 "SELECT * FROM t1 GROUP BY x, y ORDER BY x ASC, y ASC"
|
||||||
|
{1 3 2 2 3 1} {$idxscan}
|
||||||
|
|
||||||
|
10 "SELECT * FROM t1 GROUP BY x, y ORDER BY x COLLATE nocase, y"
|
||||||
|
{1 3 2 2 3 1} {$idxscan $sort}
|
||||||
|
|
||||||
|
}] {
|
||||||
|
do_execsql_test 1.$tn.1 $q $res
|
||||||
|
do_eqp_test 1.$tn.2 $q $eqp
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
finish_test
|
53
test/tkt-f67b41381a.test
Normal file
53
test/tkt-f67b41381a.test
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# 2014 April 26
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
#***********************************************************************
|
||||||
|
# Test that ticket f67b41381a has been resolved.
|
||||||
|
#
|
||||||
|
|
||||||
|
set testdir [file dirname $argv0]
|
||||||
|
source $testdir/tester.tcl
|
||||||
|
set testprefix tkt-f67b41381a
|
||||||
|
|
||||||
|
do_execsql_test 1.0 {
|
||||||
|
CREATE TABLE t1(a);
|
||||||
|
INSERT INTO t1 VALUES(1);
|
||||||
|
ALTER TABLE t1 ADD COLUMN b DEFAULT 2;
|
||||||
|
CREATE TABLE t2(a, b);
|
||||||
|
INSERT INTO t2 SELECT * FROM t1;
|
||||||
|
SELECT * FROM t2;
|
||||||
|
} {1 2}
|
||||||
|
|
||||||
|
db cache size 0
|
||||||
|
foreach {tn tbls xfer} {
|
||||||
|
1 { CREATE TABLE t1(a, b); CREATE TABLE t2(a, b) } 1
|
||||||
|
2 { CREATE TABLE t1(a, b DEFAULT 'x'); CREATE TABLE t2(a, b) } 0
|
||||||
|
3 { CREATE TABLE t1(a, b DEFAULT 'x'); CREATE TABLE t2(a, b DEFAULT 'x') } 1
|
||||||
|
4 { CREATE TABLE t1(a, b DEFAULT NULL); CREATE TABLE t2(a, b) } 0
|
||||||
|
5 { CREATE TABLE t1(a DEFAULT 2, b); CREATE TABLE t2(a DEFAULT 1, b) } 1
|
||||||
|
6 { CREATE TABLE t1(a DEFAULT 1, b); CREATE TABLE t2(a DEFAULT 1, b) } 1
|
||||||
|
7 { CREATE TABLE t1(a DEFAULT 1, b DEFAULT 1);
|
||||||
|
CREATE TABLE t2(a DEFAULT 3, b DEFAULT 1) } 1
|
||||||
|
8 { CREATE TABLE t1(a DEFAULT 1, b DEFAULT 1);
|
||||||
|
CREATE TABLE t2(a DEFAULT 3, b DEFAULT 3) } 0
|
||||||
|
|
||||||
|
} {
|
||||||
|
|
||||||
|
execsql { DROP TABLE t1; DROP TABLE t2 }
|
||||||
|
execsql $tbls
|
||||||
|
|
||||||
|
set res 1
|
||||||
|
db eval { EXPLAIN INSERT INTO t1 SELECT * FROM t2 } {
|
||||||
|
if {$opcode == "Column"} { set res 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
do_test 2.$tn [list set res] $xfer
|
||||||
|
}
|
||||||
|
|
||||||
|
finish_test
|
Reference in New Issue
Block a user