From: drh Date: Sat, 26 May 2018 18:03:48 +0000 (+0000) Subject: Experimental change that allows overloaded functions to be analyzed by X-Git-Tag: version-3.25.0~60^2~9^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Fvtab-func-constraint;p=thirdparty%2Fsqlite.git Experimental change that allows overloaded functions to be analyzed by the xBestIndex method and used by the xFilter method of a virtual table. FossilOrigin-Name: a353b1d7ee6c5989ba1b98a3990c9a4c2ff39ae66572fd1200606e8ef585e5fa --- diff --git a/manifest b/manifest index 1867640d1d..b86958ab3e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Store\sapplication-defined\sfunction\snames\sas\slower-case\sto\savoid\sthe\sneed\nfor\scase\sconversions\sbefore\scalling\sxFindFunction\son\svirtual\stables.\nAvoid\susing\slookaside\sto\sstore\sthe\sdestructors\sfor\sapplication\sdefined\nfunctions,\sas\slookaside\sshould\sbe\sreserved\sfor\stransient\sallocations. -D 2018-05-26T16:00:26.368 +C Experimental\schange\sthat\sallows\soverloaded\sfunctions\sto\sbe\sanalyzed\sby\nthe\sxBestIndex\smethod\sand\sused\sby\sthe\sxFilter\smethod\sof\sa\svirtual\stable. +D 2018-05-26T18:03:48.120 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -446,7 +446,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 F src/delete.c 4c8c7604277a2041647f96b78f4b9a47858e9217e4fb333d35e7b5ab32c5b57f -F src/expr.c af4a81a385277510bfc56df87c25d76fc365f98c33bc8797c4a8d84b88e31013 +F src/expr.c 81b3925fb84e226d230eb59d8ef8d680b22a121410934545ba026027d5fe03df F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 F src/func.c e2e3c02621a528a472933fd4733a5da635676f1461be73293f6e9f62f18d4eaa @@ -496,7 +496,7 @@ F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c a35d462ee7a3c0856ad7a9d9c8921fbf3d91d911a8f39ad9d61302eb43b24a71 F src/shell.c.in 51c100206f4b7f86cd9affd80b764825e0edc36ca0190c442e4ca7994611bfe2 -F src/sqlite.h.in db327b5de56909e060da241ff89cc3726eadf98e9eb17386fc831bbce80e0820 +F src/sqlite.h.in 9823d4fee4b4d56d210a2f603c255af3c984c3cacb14a841d35c5bb27707055b F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 F src/sqliteInt.h d2bd297dba08f2390a91c31ff775e0964e9663df5b2910a569fe6f830b8b2beb @@ -581,7 +581,7 @@ F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f F src/where.c 60ec752fcbe9f9e0271ac60548d159a540a1ee47a4f9fedc85e88a3d0e392dd1 F src/whereInt.h cbae2bcd37cfebdb7812a8b188cdb19634ced2b9346470d1c270556b0c33ea53 F src/wherecode.c 728c7f70731430ccdac807a79969873e1af6968bf1c4745dff3f9dd35f636cc8 -F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a +F src/whereexpr.c a6994e3a616f33e885becc2d6a4377ce5aea92b6e2dff96de3a8dd986ed3113f F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d @@ -1729,7 +1729,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 27b4fa5dd0defc6ddaf5d8cde6a1e1162b70d99bfdc69c1d2290621a6d23ed91 -R d728fa434c4672bbeedeb70c9aae9549 +P 777189ce88799f93f393fd14fd716111c85bcdcb23690fd561f78ea2bd2ce5da +R 287ad6e657f697576be6591ee557b37e +T *branch * vtab-func-constraint +T *sym-vtab-func-constraint * +T -sym-trunk * U drh -Z 593bd01a2c2330ddb0f8d8891bce9a51 +Z 1dcaa168f6b87a9c36f55e4d22ec80f8 diff --git a/manifest.uuid b/manifest.uuid index 2496e83258..bf9a43fb0d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -777189ce88799f93f393fd14fd716111c85bcdcb23690fd561f78ea2bd2ce5da \ No newline at end of file +a353b1d7ee6c5989ba1b98a3990c9a4c2ff39ae66572fd1200606e8ef585e5fa \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 6aff83a256..a45f38f9c7 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3903,7 +3903,7 @@ expr_code_doover: ** "glob(B,A). We want to use the A in "A glob B" to test ** for function overloading. But we use the B term in "glob(B,A)". */ - if( nFarg>=2 && (pExpr->flags & EP_InfixFunc) ){ + if( nFarg>=2 && ExprHasProperty(pExpr, EP_InfixFunc) ){ pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr); }else if( nFarg>0 ){ pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 64e929a89e..979b974699 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -6323,6 +6323,7 @@ struct sqlite3_index_info { #define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 #define SQLITE_INDEX_CONSTRAINT_ISNULL 71 #define SQLITE_INDEX_CONSTRAINT_IS 72 +#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150 /* ** CAPI3REF: Register A Virtual Table Implementation diff --git a/src/whereexpr.c b/src/whereexpr.c index 29750080a1..b177a7d995 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -338,6 +338,7 @@ static int isLikeOrGlob( ** If the expression matches none of the patterns above, return 0. */ static int isAuxiliaryVtabOperator( + sqlite3 *db, /* Parsing context */ Expr *pExpr, /* Test this expression */ unsigned char *peOp2, /* OUT: 0 for MATCH, or else an op2 value */ Expr **ppLeft, /* Column expression to left of MATCH/op2 */ @@ -361,16 +362,54 @@ static int isAuxiliaryVtabOperator( if( pList==0 || pList->nExpr!=2 ){ return 0; } + + /* Built-in operators MATCH, GLOB, LIKE, and REGEXP attach to a + ** virtual table on their second argument, which is the same as + ** the left-hand side operand in their in-fix form. + ** + ** vtab_column MATCH expression + ** MATCH(expression,vtab_column) + */ pCol = pList->a[1].pExpr; - if( pCol->op!=TK_COLUMN || !IsVirtual(pCol->pTab) ){ - return 0; + if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){ + for(i=0; iu.zToken, aOp[i].zOp)==0 ){ + *peOp2 = aOp[i].eOp2; + *ppRight = pList->a[0].pExpr; + *ppLeft = pCol; + return 1; + } + } } - for(i=0; iu.zToken, aOp[i].zOp)==0 ){ - *peOp2 = aOp[i].eOp2; - *ppRight = pList->a[0].pExpr; - *ppLeft = pCol; - return 1; + + /* We can also match against the first column of overloaded + ** functions where xFindFunction returns a value of at least + ** SQLITE_INDEX_CONSTRAINT_FUNCTION. + ** + ** OVERLOADED(vtab_column,expression) + ** + ** Historically, xFindFunction expected to see lower-case function + ** names. But for this use case, xFindFunction is expected to deal + ** with function names in an arbitrary case. + */ + pCol = pList->a[0].pExpr; + if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){ + sqlite3_vtab *pVtab; + sqlite3_module *pMod; + void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); + void *pNotUsed; + pVtab = sqlite3GetVTable(db, pCol->pTab)->pVtab; + assert( pVtab!=0 ); + assert( pVtab->pModule!=0 ); + pMod = (sqlite3_module *)pVtab->pModule; + if( pMod->xFindFunction!=0 ){ + i = pMod->xFindFunction(pVtab,2, pExpr->u.zToken, &xNotUsed, &pNotUsed); + if( i>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){ + *peOp2 = i; + *ppRight = pList->a[1].pExpr; + *ppLeft = pCol; + return 1; + } } } }else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){ @@ -1230,7 +1269,7 @@ static void exprAnalyze( */ if( pWC->op==TK_AND ){ Expr *pRight = 0, *pLeft = 0; - int res = isAuxiliaryVtabOperator(pExpr, &eOp2, &pLeft, &pRight); + int res = isAuxiliaryVtabOperator(db, pExpr, &eOp2, &pLeft, &pRight); while( res-- > 0 ){ int idxNew; WhereTerm *pNewTerm;