1
0
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:
drh
2014-04-28 18:02:21 +00:00
13 changed files with 390 additions and 72 deletions

View File

@@ -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

View File

@@ -1 +1 @@
3dca2809352c6c6d56db74447a814f77011c6220 e158812c34b01ce516d26636a489509bf61d1c27

View File

@@ -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 ){

View File

@@ -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...

View File

@@ -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*);

View File

@@ -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

View File

@@ -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], &notUsed
);
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 */

View File

@@ -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 */

View File

@@ -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

View File

@@ -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
View 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
View 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
View 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