Add some support for OR terms to sqlite3_whereinfo_hook().

FossilOrigin-Name: 5cd070000da1d9e399090677b4db75dc5639c33211385d6eb84f14a4d0b617cd
This commit is contained in:
dan 2017-04-04 17:50:31 +00:00
parent e86573fa51
commit 53761f4d52
5 changed files with 138 additions and 18 deletions

View File

@ -1,5 +1,5 @@
C Add\sthe\ssqlite3_whereinfo_hook()\sAPI\s-\san\sexperimental\sAPI\sreplacing\sthe\nDBCONFIG_WHEREINFO\shack\son\sthis\sbranch.
D 2017-04-04T04:23:06.108
C Add\ssome\ssupport\sfor\sOR\sterms\sto\ssqlite3_whereinfo_hook().
D 2017-04-04T17:50:31.913
F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc a4c0613a18663bda56d8cf76079ab6590a7c3602e54befb4bbdef76bcaa38b6a
@ -403,7 +403,7 @@ F src/resolve.c 3e518b962d932a997fae373366880fc028c75706
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c 2496d0cc6368dabe7ad2e4c7f5ed3ad9aa3b4d11cd90f33fa1d1ef72493f43aa
F src/shell.c e524688c2544167f835ba43e24309f8707ca60c8ab6eb5c263a12c8618a233b8
F src/shell_indexes.c 12cc58b62492bddc88f879086b4cd1045dbfd4e52040ecb6c39b971a6aac80ba
F src/shell_indexes.c d40ea0a81112df7bdccd7232238bee0bbb39699085ea78cc08fd863bf052a63b
F src/sqlite.h.in ae5c9cbf2e77492c319fca08769575d9695e64718a16d32324944d24e291bcf7
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 58fd0676d3111d02e62e5a35992a7d3da5d3f88753acc174f2d37b774fbbdd28
@ -483,7 +483,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344
F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
F src/walker.c b71a992b413b3a022572eccf29ef4b4890223791
F src/where.c cbd1e8562fa37de359963749e1dc3d0dd1a42a894d10a62928bffc709490fde6
F src/where.c be352441558b55e21964ff53f0483776594789d0ede12dd9c58b022873c858f8
F src/whereInt.h 2d50c2b74a33be44cb68fdecee30b4d93552f1f4
F src/wherecode.c 677e95413c472c0b413023b6b69a47f40fce1b04
F src/whereexpr.c 130cdd1a43af71b19755270fb1224874cf55158c
@ -1120,7 +1120,7 @@ F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
F test/shell3.test 9b95ba643eaa228376f06a898fb410ee9b6e57c1
F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
F test/shell5.test 50a732c1c2158b1cd62cf53975ce1ea7ce6b9dc9
F test/shell6.test 05c2488ff2bb11ac300b9170e8f5b6e03d58982c77035cdca5dbf036f0d3c5b7
F test/shell6.test 081067c1afcb38da50134ffd5ccc0a59ede14f41959486f733ffbba689c0ccfa
F test/shell7.test 07751911b294698e0c5df67bcbd29e7d2f0f2907
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
@ -1571,7 +1571,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P cb721d0b36268a7b0ef493fa4d7f6bcbaa9ead8b1990e3c3fae015fa1d545226
R 061e66f6528edc67cfbe5cb82be7b02d
P a54aef35da11f7508a8888a159372036a362fc52afa1df752dc835db334c4330
R 51e547bc1c25ea79dd375d8f020224f3
U dan
Z d08fd2524fbe07ca7104a150ba1edcbe
Z fe378068686ea107c39185021a17b4ae

View File

@ -1 +1 @@
a54aef35da11f7508a8888a159372036a362fc52afa1df752dc835db334c4330
5cd070000da1d9e399090677b4db75dc5639c33211385d6eb84f14a4d0b617cd

View File

@ -175,9 +175,6 @@ static void idxWhereInfo(
eOp==SQLITE_WHEREINFO_EQUALS ? "EQUALS" :
eOp==SQLITE_WHEREINFO_RANGE ? "RANGE" :
eOp==SQLITE_WHEREINFO_ORDERBY ? "ORDERBY" :
eOp==SQLITE_WHEREINFO_NEXTOR ? "NEXTOR" :
eOp==SQLITE_WHEREINFO_ENDOR ? "ENDOR" :
eOp==SQLITE_WHEREINFO_BEGINOR ? "BEGINOR" :
"!error!";
printf("op=%s zVal=%s iVal=%d mask=%llx\n", zOp, zVal, iVal, mask);
#endif
@ -630,7 +627,9 @@ static int idxCreateFromCons(
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_exec(dbm, zIdx, 0, 0, pCtx->pzErrmsg);
/* printf("%s\n", zIdx); */
#if 0
printf("CANDIDATE: %s\n", zIdx);
#endif
}
}
if( rc==SQLITE_OK && pCtx->iIdxRowid==0 ){

View File

@ -4278,6 +4278,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
}
#ifdef SQLITE_ENABLE_WHEREINFO_HOOK
static void whereTraceWC(
Parse *pParse,
struct SrcList_item *pItem,
@ -4285,7 +4286,7 @@ static void whereTraceWC(
){
sqlite3 *db = pParse->db;
Table *pTab = pItem->pTab;
void (*x)(void*, int, const char*, int, i64) = db->xWhereInfo;
void (*x)(void*, int, const char*, int, u64) = db->xWhereInfo;
void *pCtx = db->pWhereInfoCtx;
int ii;
@ -4311,6 +4312,109 @@ static void whereTraceWC(
}
}
/*
** If there are any OR terms in WHERE clause pWC, make the associated
** where-info hook callbacks.
*/
static void whereTraceOR(
Parse *pParse,
struct SrcList_item *pItem,
WhereClause *pWC
){
sqlite3 *db = pParse->db;
WhereClause tempWC;
struct TermAndIdx {
WhereTerm *pTerm;
int iIdx;
} aOr[4];
int nOr = 0;
Table *pTab = pItem->pTab;
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
int ii;
memset(aOr, 0, sizeof(aOr));
/* Iterate through OR nodes */
for(ii=0; ii<pWC->nTerm; ii++){
WhereTerm *pTerm = &pWC->a[ii];
if( pTerm->eOperator & WO_OR ){
/* Check that each branch of this OR term contains at least
** one reference to the table currently being processed. If that
** is not the case, this term can be ignored. */
WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
WhereTerm *pOrTerm;
WhereClause *pTermWC;
WhereScan scan;
for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
int iCol;
if( (pOrTerm->eOperator & WO_AND)!=0 ){
pTermWC = &pOrTerm->u.pAndInfo->wc;
}else{
tempWC.pWInfo = pWC->pWInfo;
tempWC.pOuter = pWC;
tempWC.op = TK_AND;
tempWC.nTerm = 1;
tempWC.a = pOrTerm;
pTermWC = &tempWC;
}
for(iCol=0; iCol<pTab->nCol; iCol++){
int iCsr = pItem->iCursor;
if( !whereScanInit(&scan, pTermWC, iCsr, iCol, WO_SINGLE, 0) ){
break;
}
}
if( iCol==pTab->nCol ) break;
}
if( pOrTerm==pOrWCEnd ){
aOr[nOr].pTerm = pTerm;
aOr[nOr].iIdx = pOrWC->nTerm;
nOr++;
if( nOr==ArraySize(aOr) ) break;
}
}
}
while( 1 ){
for(ii=0; ii<nOr; ii++){
if( aOr[ii].iIdx==0 ){
aOr[ii].iIdx = aOr[ii].pTerm->u.pOrInfo->wc.nTerm;
}else{
aOr[ii].iIdx--;
break;
}
}
if( ii==nOr ) break;
/* Table name callback */
db->xWhereInfo(db->pWhereInfoCtx,
SQLITE_WHEREINFO_TABLE, pTab->zName, iDb, pItem->colUsed
);
/* whereTraceWC(pParse, pItem, pWC); */
for(ii=0; ii<nOr; ii++){
WhereClause * const pOrWC = &aOr[ii].pTerm->u.pOrInfo->wc;
if( aOr[ii].iIdx<pOrWC->nTerm ){
WhereClause *pTermWC;
WhereTerm *pOrTerm = &pOrWC->a[aOr[ii].iIdx];
if( (pOrTerm->eOperator & WO_AND)!=0 ){
pTermWC = &pOrTerm->u.pAndInfo->wc;
}else{
tempWC.pWInfo = pWC->pWInfo;
tempWC.pOuter = pWC;
tempWC.op = TK_AND;
tempWC.nTerm = 1;
tempWC.a = pOrTerm;
pTermWC = &tempWC;
}
whereTraceWC(pParse, pItem, pTermWC);
}
}
}
}
/*
** If there is a where-info hook attached to the database handle, issue all
** required callbacks for the current sqlite3WhereBegin() call.
@ -4321,16 +4425,16 @@ static void whereTraceBuilder(
){
sqlite3 *db = pParse->db;
if( db->xWhereInfo && db->init.busy==0 ){
void (*x)(void*, int, const char*, int, i64) = db->xWhereInfo;
void (*x)(void*, int, const char*, int, u64) = db->xWhereInfo;
void *pCtx = db->pWhereInfoCtx;
int ii;
int nTab = p->pWInfo->pTabList->nSrc;
SrcList *pTabList = p->pWInfo->pTabList;
/* Loop through each element of the FROM clause. Ignore any sub-selects
** or views. Invoke the xWhereInfo() callback multiple times for each
** real table. */
for(ii=0; ii<p->pWInfo->pTabList->nSrc; ii++){
struct SrcList_item *pItem = &p->pWInfo->pTabList->a[ii];
for(ii=0; ii<pTabList->nSrc; ii++){
struct SrcList_item *pItem = &pTabList->a[ii];
if( pItem->pSelect==0 ){
Table *pTab = pItem->pTab;
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@ -4357,6 +4461,9 @@ static void whereTraceBuilder(
/* WHERE callbacks */
whereTraceWC(pParse, pItem, p->pWC);
/* OR-clause processing */
whereTraceOR(pParse, pItem, p->pWC);
}
}
}

View File

@ -188,4 +188,18 @@ do_setup_rec_test 10.1 {
0|1|0|SEARCH TABLE t5 USING COVERING INDEX t5_idx_000123a7 (a=? AND b=?)
}
# OR terms.
#
do_setup_rec_test 11.1 {
CREATE TABLE t7(a, b);
} {
SELECT * FROM t7 WHERE a=? OR b=?
} {
CREATE INDEX t7_idx_00000061 ON t7(a)
CREATE INDEX t7_idx_00000062 ON t7(b)
0|0|0|SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?)
0|0|0|SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
}
finish_test