From: drh Date: Wed, 1 Jan 2020 13:55:08 +0000 (+0000) Subject: Factor out code generation for in-line SQL functions into a separate routine X-Git-Tag: version-3.31.0~103 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=25c4296bd97072f7b5a13f4eda021bd2782bcc45;p=thirdparty%2Fsqlite.git Factor out code generation for in-line SQL functions into a separate routine inside of expr.c. FossilOrigin-Name: 586a65a28fc6cac77309612abc32a2e1017c65e0387f9f438f5d8ac8406da8eb --- diff --git a/manifest b/manifest index f74d206ba8..1899d7f3fb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Issue\sOP_ReleaseReg\sopcodes\sagainst\sthe\sarray\sof\sregisters\sused\sto\scompute\nindex\srecords\safter\sthe\sindex\srecord\shas\sbeen\scomputed. -D 2020-01-01T01:26:05.547 +C Factor\sout\scode\sgeneration\sfor\sin-line\sSQL\sfunctions\sinto\sa\sseparate\sroutine\ninside\sof\sexpr.c. +D 2020-01-01T13:55:08.668 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -480,10 +480,10 @@ F src/date.c e1d8ac7102f3f283e63e13867acb0efa33861cf34f0faf4cdbaf9fa7a1eb7041 F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7 F src/dbstat.c 6c407e549406c10fde9ac3987f6d734459205239ad370369bc5fcd683084a4fa F src/delete.c a5c59b9c0251cf7682bc52af0d64f09b1aefc6781a63592c8f1136f7b73c66e4 -F src/expr.c 3584e19c222f94cd0bb9070318ad270c3ca0d4fe235a6f70a198f16d8faf976f +F src/expr.c afde0ea1060266338820277d210edc0ed383416c59e5f3472a253f121b5a9de3 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 92a248ec0fa4ed8ab60c98d9b188ce173aaf218f32e7737ba77deb2a684f9847 -F src/func.c 511204091c82bd0f351a64f05359b1b0444f0953de92fa1d37b129e544ed5126 +F src/func.c de2641a4763c78b872099649c12adedc638a83df0c41dcb0cb99efc6ceb5f69b F src/global.c a1a8d698762ddd9a1543aac26c1e0029b20fcc3fcb56bfa41ec8cea2368f2798 F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38 @@ -533,7 +533,7 @@ F src/shell.c.in 4a3a9e1c11847b1904f2b01d087af1c052f660902755abab457cab1756817de F src/sqlite.h.in 51f69c62ba3e980aca1e39badcaf9ad13f008774fe1bb8e7f57e3e456c656670 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 72af51aa4e912e14cd495fb6e7fac65f0940db80ed950d90911aff292cc47ce2 -F src/sqliteInt.h e526421d44d88f17c397647371e460841c961b27ccf69301177b63d18ebbeead +F src/sqliteInt.h a7d75ef422e07c85eaeb12309b071f3342497d960bf0a353dca8665be6ceb576 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -1853,7 +1853,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 eca7ec9cda4606c4104bcb8da315070b615713db9f3444579c6a3e96b0aad02f -R 831eba5ca2213a1142c1d3fcf8abb412 +P e3330861b4deab7c7cc09ad8b936d633c600b9fb4e274801efeaaf94e5c860b4 +R cfe1bf37072aa553a15293de91196bb1 U drh -Z d9905a9f70d8f738c4685ad63b39c0a5 +Z 1739d48acd97cb5e3553660f1568a9b2 diff --git a/manifest.uuid b/manifest.uuid index 6ac57e8761..82209644bd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e3330861b4deab7c7cc09ad8b936d633c600b9fb4e274801efeaaf94e5c860b4 \ No newline at end of file +586a65a28fc6cac77309612abc32a2e1017c65e0387f9f438f5d8ac8406da8eb \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index e0a03d956f..629768f3a2 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3573,6 +3573,69 @@ static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){ return iResult; } +/* +** Generate code to implement special SQL functions that are implemented +** in-line rather than by using the usual callbacks. +*/ +static int exprCodeInlineFunction( + Parse *pParse, /* Parsing context */ + ExprList *pFarg, /* List of function arguments */ + int iFuncId, /* Function ID. One of the INTFUNC_... values */ + int target /* Store function result in this register */ +){ + int nFarg; + Vdbe *v = pParse->pVdbe; + assert( v!=0 ); + assert( pFarg!=0 ); + nFarg = pFarg->nExpr; + assert( nFarg>0 ); /* All in-line functions have at least one argument */ + switch( iFuncId ){ + case INLINEFUNC_coalesce: { + /* Attempt a direct implementation of the built-in COALESCE() and + ** IFNULL() functions. This avoids unnecessary evaluation of + ** arguments past the first non-NULL argument. + */ + int endCoalesce = sqlite3VdbeMakeLabel(pParse); + int i; + assert( nFarg>=2 ); + sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); + for(i=1; ia[i].pExpr, target); + } + sqlite3VdbeResolveLabel(v, endCoalesce); + break; + } + + case INLINEFUNC_unlikely: { + /* The UNLIKELY() function is a no-op. The result is the value + ** of the first argument. + */ + assert( nFarg>=1 ); + target = sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target); + break; + } + +#ifdef SQLITE_DEBUG + case INLINEFUNC_affinity: { + /* The AFFINITY() function evaluates to a string that describes + ** the type affinity of the argument. This is used for testing of + ** the SQLite type logic. + */ + const char *azAff[] = { "blob", "text", "numeric", "integer", "real" }; + char aff; + assert( nFarg==1 ); + aff = sqlite3ExprAffinity(pFarg->a[0].pExpr); + sqlite3VdbeLoadString(v, target, + (aff<=SQLITE_AFF_NONE) ? "none" : azAff[aff-SQLITE_AFF_BLOB]); + break; + } +#endif + } + return target; +} + /* ** Generate code into the current Vdbe to evaluate the given @@ -3953,48 +4016,11 @@ expr_code_doover: sqlite3ErrorMsg(pParse, "unknown function: %s()", zId); break; } - - /* Attempt a direct implementation of the built-in COALESCE() and - ** IFNULL() functions. This avoids unnecessary evaluation of - ** arguments past the first non-NULL argument. - */ - if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){ - int endCoalesce = sqlite3VdbeMakeLabel(pParse); - assert( nFarg>=2 ); - sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); - for(i=1; ia[i].pExpr, target); - } - sqlite3VdbeResolveLabel(v, endCoalesce); - break; + if( pDef->funcFlags & SQLITE_FUNC_INLINE ){ + return exprCodeInlineFunction(pParse, pFarg, + SQLITE_PTR_TO_INT(pDef->pUserData), target); } - /* The UNLIKELY() function is a no-op. The result is the value - ** of the first argument. - */ - if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){ - assert( nFarg>=1 ); - return sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target); - } - -#ifdef SQLITE_DEBUG - /* The AFFINITY() function evaluates to a string that describes - ** the type affinity of the argument. This is used for testing of - ** the SQLite type logic. - */ - if( pDef->funcFlags & SQLITE_FUNC_AFFINITY ){ - const char *azAff[] = { "blob", "text", "numeric", "integer", "real" }; - char aff; - assert( nFarg==1 ); - aff = sqlite3ExprAffinity(pFarg->a[0].pExpr); - sqlite3VdbeLoadString(v, target, - (aff<=SQLITE_AFF_NONE) ? "none" : azAff[aff-SQLITE_AFF_BLOB]); - return target; - } -#endif - for(i=0; ia[i].pExpr) ){ testcase( i==31 ); diff --git a/src/func.c b/src/func.c index d4c6936b10..31b548ff93 100644 --- a/src/func.c +++ b/src/func.c @@ -1921,11 +1921,11 @@ void sqlite3RegisterBuiltinFunctions(void){ DFUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ), DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ), #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ - FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), - FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), - FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY), + INLINE_FUNC(unlikely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY), + INLINE_FUNC(likelihood, 2, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY), + INLINE_FUNC(likely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY), #ifdef SQLITE_DEBUG - FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY), + TEST_FUNC(affinity, 1, INLINEFUNC_affinity, 0), #endif #ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC FUNCTION2(sqlite_offset, 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET| @@ -1959,7 +1959,7 @@ void sqlite3RegisterBuiltinFunctions(void){ FUNCTION(upper, 1, 0, 0, upperFunc ), FUNCTION(lower, 1, 0, 0, lowerFunc ), FUNCTION(hex, 1, 0, 0, hexFunc ), - FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE), + INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, SQLITE_FUNC_COALESCE), VFUNCTION(random, 0, 0, 0, randomFunc ), VFUNCTION(randomblob, 1, 0, 0, randomBlob ), FUNCTION(nullif, 2, 0, 1, nullifFunc ), @@ -1999,7 +1999,7 @@ void sqlite3RegisterBuiltinFunctions(void){ #endif FUNCTION(coalesce, 1, 0, 0, 0 ), FUNCTION(coalesce, 0, 0, 0, 0 ), - FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE), + INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, SQLITE_FUNC_COALESCE), }; #ifndef SQLITE_OMIT_ALTERTABLE sqlite3AlterFunctions(); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 0dcb103532..d696ffd3a0 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1712,12 +1712,18 @@ struct FuncDestructor { #define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */ #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a ** single query - might change over time */ -#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ +#define SQLITE_FUNC_TEST 0x4000 /* Built-in testing functions */ #define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ #define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ #define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ #define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */ #define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */ +#define SQLITE_FUNC_INLINE 0x00200000 /* Functions implemented in-line */ + +/* Identifier numbers for each in-line function */ +#define INLINEFUNC_unlikely 0 /* unlikely(EXPR) and friends */ +#define INLINEFUNC_coalesce 1 /* coalesce(EXPR,...) */ +#define INLINEFUNC_affinity 2 /* affinity(EXPR) */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are @@ -1737,6 +1743,18 @@ struct FuncDestructor { ** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and ** adds the SQLITE_DIRECTONLY flag. ** +** INLINE_FUNC(zName, nArg, iFuncId, mFlags) +** zName is the name of a function that is implemented by in-line +** byte code rather than by the usual callbacks. The iFuncId +** parameter determines the function id. The mFlags parameter is +** optional SQLITE_FUNC_ flags for this function. +** +** TEST_FUNC(zName, nArg, iFuncId, mFlags) +** zName is the name of a test-only function implemented by in-line +** byte code rather than by the usual callbacks. The iFuncId +** parameter determines the function id. The mFlags parameter is +** optional SQLITE_FUNC_ flags for this function. +** ** DFUNCTION(zName, nArg, iArg, bNC, xFunc) ** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and ** adds the SQLITE_FUNC_SLOCHNG flag. Used for date & time functions @@ -1779,6 +1797,13 @@ struct FuncDestructor { #define SFUNCTION(zName, nArg, iArg, bNC, xFunc) \ {nArg, SQLITE_UTF8|SQLITE_DIRECTONLY, \ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } +#define INLINE_FUNC(zName, nArg, iArg, mFlags) \ + {nArg, SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \ + SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} } +#define TEST_FUNC(zName, nArg, iArg, mFlags) \ + {nArg, SQLITE_UTF8|SQLITE_FUNC_INTERNAL|SQLITE_FUNC_TEST| \ + SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \ + SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} } #define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \ {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \ 0, 0, xFunc, 0, 0, 0, #zName, {0} }