]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Provide the SQLITE_DIRECTONLY flag for app-defined functions that prohibits directonly
authordrh <drh@noemail.net>
Thu, 15 Aug 2019 20:04:09 +0000 (20:04 +0000)
committerdrh <drh@noemail.net>
Thu, 15 Aug 2019 20:04:09 +0000 (20:04 +0000)
the use of those functions within triggers or views.

FossilOrigin-Name: fc745845d8d76adc165575e2192f4176e3c28e614c72571d56f4011560499fe1

manifest
manifest.uuid
src/attach.c
src/main.c
src/resolve.c
src/sqlite.h.in
src/sqliteInt.h
src/tclsqlite.c
src/treeview.c
test/func.test
test/tclsqlite.test

index 7d4def8408d1c26ff5fe79be99a4e313482593cf..9b54e4ca099b2618eeea013a67a112009df2bf50 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Ensure\sthat\sthe\soptional\s"sz=N"\sparameter\sthat\scan\sbe\smanually\sadded\sto\sthe\nend\sof\san\ssqlite_stat1\sentry\sdoes\snot\shave\san\sN\svalue\sthat\sis\stoo\ssmall.\nTicket\s[e4598ecbdd18bd82]
-D 2019-08-15T14:35:45.987
+C Provide\sthe\sSQLITE_DIRECTONLY\sflag\sfor\sapp-defined\sfunctions\sthat\sprohibits\nthe\suse\sof\sthose\sfunctions\swithin\striggers\sor\sviews.
+D 2019-08-15T20:04:09.316
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -459,7 +459,7 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
 F src/alter.c 5c3031e45e80f79d7d54c2d32dd3c44926544d4f6a478858bfe4ee3191570190
 F src/analyze.c a3f4ea45cdb4e9df78d4ea7beb87ec8a7a46f494173b641cd28512a40a97bff2
-F src/attach.c 78e986baee90cb7b83fb9eafa79c22581a8ada14030fd633b0683c95cf11213c
+F src/attach.c a6f108eb7922fad920e8aba0cda56fb56d89d136d519be5177cd3bd3559f2566
 F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06
 F src/backup.c f70077d40c08b7787bfe934e4d1da8030cb0cc57d46b345fba2294b7d1be23ab
 F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
@@ -487,7 +487,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
 F src/insert.c c2194dd2886337b870226fcb31c13e7df8c4b5e0ea85140e510a6f1daf1ad65b
 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
 F src/loadext.c 22afc33c3a61b4fd80a60a54f1882688371e6bc64685df2696b008fce65a999c
-F src/main.c 3add6433e077635dac5579edaf7b3942e3ff3dda5588c49c0edd7abea2096482
+F src/main.c ff418603f9435914e8bd2febd1d5dbfcbf2ece3a4e853481a81a50fc27b321ab
 F src/malloc.c 0f9da2a66b230a5785af94b9672126845099b57b70a32c987d04ac28c69da990
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -521,18 +521,18 @@ F src/pragma.h 4a9fabff14db4487a734dfeeb4be984ce662bfdccfae16145b9c732327735e13
 F src/prepare.c 132484635a30f873ee7eccd47f93ed1932503863b93b28423b42332d81adffaf
 F src/printf.c 9be6945837c839ba57837b4bc3af349eba630920fa5532aa518816defe42a7d4
 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
-F src/resolve.c 14ae3326af3d8b94bd64a29e0369986f3125cf4c0dcb8f8dc1b8be2cd1bcdbaa
+F src/resolve.c b2733d39a22f5023ab489b8535ca6854b51ff8667ca975815d004bb7388b0e41
 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
 F src/select.c 11087458ec2af5c4b377559ea0462c2ab842e02badd35b21a8d67257c4e0b117
 F src/shell.c.in 66cd8289adbcd159ca67872c242990ca6bed29fe80be7ebf9c6a1c068249a41e
-F src/sqlite.h.in 1fe019ae55182040e6ea10c89ddbb8d24c1b1015c423da53e55205398a65a906
+F src/sqlite.h.in dfbb64c0b8e4b3de2958d8372208437509acdc523aed8ae90a164f3a5d9a5739
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 9ecc93b8493bd20c0c07d52e2ac0ed8bab9b549c7f7955b59869597b650dd8b5
-F src/sqliteInt.h 4875fb443102c9d92ed1cb23b7fb6e2d97714591f02725d595576ef316596b94
+F src/sqliteInt.h 12e8af40a561a3006b6996938c88cce1e24efe690955e193824571d20c3ef352
 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
 F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
-F src/tclsqlite.c cfe7f93daf9d8787f65e099efb67d7cdfc2c35236dec5d3f6758520bd3519424
+F src/tclsqlite.c a65eb317f8b83f7ae546f88db56600f9a39550688d70501b8eb0cc3a4b4960c9
 F src/test1.c 87059457fb90b73a74044b379fe2cb0aefbb53c010c646ecaff23179a423638c
 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
@@ -588,7 +588,7 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
 F src/tokenize.c d3615f0cbe4db5949503bf5916f3cd4fa5de855d5b4ef560f3b6dd5629423a1e
-F src/treeview.c 06e65db6ffa14dd583f90403192190dfe3855c0e3acfcbac0e82109a46e2b16c
+F src/treeview.c fc8c6c0a8a26afb3a97e3f844d65403dd27cf1450baf4415034fa4ccf00c4d7e
 F src/trigger.c 2305271878e95addc1c01361e5e8e342e87cba5efefdd7d3032687e5d67e05d1
 F src/update.c 3cb9150d2cf661d938e2f1b1749945f3faa767f88febdb739ab1793bbf895ff2
 F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
@@ -990,7 +990,7 @@ F test/fts4rename.test 15fd9985c2bce6dea20da2245b22029ec89bd4710ed317c4c53abbe3c
 F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f757380429
 F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95
 F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
-F test/func.test e4313baba80bf933e58eb89a7c617bec0f0c348c862b096ec4387f36e05ad0a6
+F test/func.test 0889128141b99b38aa9ce78445acfc4c1f9fbe9aa4f51d4c6aff88ae43cf125b
 F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
 F test/func3.test 2bb0f31ab7baaed690b962a88544d7be6b34fa389364bc36a44e441ed3e3f1e6
 F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f
@@ -1388,7 +1388,7 @@ F test/tabfunc01.test 20e98ffe55f35d8d33fd834ca8bf9d4b637e560af8fcd00464b4154d90
 F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132
 F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
-F test/tclsqlite.test 5a06962d8f18edf4703931f6b7dacd83678d02fa5c8ced9a7958c007ad58626a
+F test/tclsqlite.test 6c7368554f15ea6df3852173c0f1d6353f824afb1896f6fc17fb21b057c0685a
 F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
 F test/tempdb2.test 353864e96fd3ae2f70773d0ffbf8b1fe48589b02c2ec05013b540879410c3440
 F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
@@ -1836,7 +1836,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 4f5b2d938194fab7627486e2ced633def2c90d9d3328e3700612feb9dbfa3d9a
-R e211e009e748f2e64e3d39bc31b03be2
+P 98357d8c1263920b33a3648ef9214a63c99728bafa7a8d3dd6a1241b2303fd42
+R ad310bbebd66791c892628fc8eec172c
+T *branch * directonly
+T *sym-directonly *
+T -sym-trunk *
 U drh
-Z bec392cb43d1df3c3b62ac4b05f24424
+Z 950f463a47bf34120eda446765855ee2
index 7672348cd3d6cc3f8db993ccffa8493a865bba14..bd2dbbdbb6b10de924cdd9283aeda18f5dfd78d4 100644 (file)
@@ -1 +1 @@
-98357d8c1263920b33a3648ef9214a63c99728bafa7a8d3dd6a1241b2303fd42
\ No newline at end of file
+fc745845d8d76adc165575e2192f4176e3c28e614c72571d56f4011560499fe1
\ No newline at end of file
index 55e0eb53634a3c822e3d94fe9b28c3927981b295..61f169ed76c4e1a9b91c6752758d185d690c7ac5 100644 (file)
@@ -560,6 +560,7 @@ int sqlite3FixExpr(
   Expr *pExpr        /* The expression to be fixed to one database */
 ){
   while( pExpr ){
+    ExprSetProperty(pExpr, EP_Indirect);
     if( pExpr->op==TK_VARIABLE ){
       if( pFix->pParse->db->init.busy ){
         pExpr->op = TK_NULL;
index 06a55eca0201a2bf5061ed5e42b51c7a947e4d1f..969bd570c4ccce599ff93645a92935c511b93d70 100644 (file)
@@ -1720,7 +1720,8 @@ int sqlite3CreateFunc(
   }
 
   assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
-  extraFlags = enc &  SQLITE_DETERMINISTIC;
+  assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY );
+  extraFlags = enc &  (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY);
   enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY);
   
 #ifndef SQLITE_OMIT_UTF16
@@ -1783,6 +1784,7 @@ int sqlite3CreateFunc(
   p->u.pDestructor = pDestructor;
   p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags;
   testcase( p->funcFlags & SQLITE_DETERMINISTIC );
+  testcase( p->funcFlags & SQLITE_DIRECTONLY );
   p->xSFunc = xSFunc ? xSFunc : xStep;
   p->xFinalize = xFinal;
   p->xValue = xValue;
index 31600382fb5eb73470a0fcd9ae2aa42ba5fbce34..ab226640953ddc3430d569b4a2e2a1e70cfc4723 100644 (file)
@@ -823,6 +823,15 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
           ** SQL is being compiled using sqlite3NestedParse() */
           no_such_func = 1;
           pDef = 0;
+        }else
+        if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0
+         && ExprHasProperty(pExpr, EP_Indirect)
+         && !IN_RENAME_OBJECT
+        ){
+          /* Functions tagged with SQLITE_DIRECTONLY may not be used
+          ** inside of triggers and views */
+          sqlite3ErrorMsg(pParse, "%s() prohibited in triggers and views",
+                          pDef->zName);
         }
       }
 
index d68cef2490e06d974d4dab1ff5352d7fbe2284f7..d50f44e6cc3f929ed221b94c31d52883a18d1622 100644 (file)
@@ -4848,6 +4848,9 @@ int sqlite3_reset(sqlite3_stmt *pStmt);
 ** function that is not deterministic.  The SQLite query planner is able to
 ** perform additional optimizations on deterministic functions, so use
 ** of the [SQLITE_DETERMINISTIC] flag is recommended where possible.
+** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY]
+** flag, which if present prevents the function from being invoked from
+** within VIEWs or TRIGGERs.
 **
 ** ^(The fifth parameter is an arbitrary pointer.  The implementation of the
 ** function can gain access to this pointer using [sqlite3_user_data()].)^
@@ -4965,8 +4968,16 @@ int sqlite3_create_window_function(
 ** [SQLITE_UTF8 | preferred text encoding] as the fourth argument
 ** to [sqlite3_create_function()], [sqlite3_create_function16()], or
 ** [sqlite3_create_function_v2()].
+**
+** The SQLITE_DETERMINISTIC flag means that the new function will always
+** maps the same inputs into the same output.  The abs() function is
+** deterministic, for example, but randomblob() is not.
+**
+** The SQLITE_DIRECTONLY flag means that the function may only be invoked
+** from top-level SQL, and cannot be used in VIEWs or TRIGGERs.
 */
-#define SQLITE_DETERMINISTIC    0x800
+#define SQLITE_DETERMINISTIC    0x000000800
+#define SQLITE_DIRECTONLY       0x000080000
 
 /*
 ** CAPI3REF: Deprecated Functions
index d6746aadca5ab2ce36dbddc43891c8e333a5b2e4..47b4e749da5482f835fe88e63ed84ff13c8714f1 100644 (file)
@@ -1663,6 +1663,7 @@ struct FuncDestructor {
 **     SQLITE_FUNC_LENGTH    ==  OPFLAG_LENGTHARG
 **     SQLITE_FUNC_TYPEOF    ==  OPFLAG_TYPEOFARG
 **     SQLITE_FUNC_CONSTANT  ==  SQLITE_DETERMINISTIC from the API
+**     SQLITE_FUNC_DIRECT    ==  SQLITE_DIRECTONLY from the API
 **     SQLITE_FUNC_ENCMASK   depends on SQLITE_UTF* macros in the API
 */
 #define SQLITE_FUNC_ENCMASK  0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
@@ -1683,6 +1684,7 @@ struct FuncDestructor {
 #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 */
 
 /*
 ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -2494,36 +2496,37 @@ struct Expr {
 **          EP_Agg == NC_HasAgg == SF_HasAgg
 **          EP_Win == NC_HasWin
 */
-#define EP_FromJoin  0x000001 /* Originates in ON/USING clause of outer join */
-#define EP_Distinct  0x000002 /* Aggregate function with DISTINCT keyword */
-#define EP_HasFunc   0x000004 /* Contains one or more functions of any kind */
-#define EP_FixedCol  0x000008 /* TK_Column with a known fixed value */
-#define EP_Agg       0x000010 /* Contains one or more aggregate functions */
-#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
-#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
-#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
-#define EP_Collate   0x000100 /* Tree contains a TK_COLLATE operator */
-#define EP_Generic   0x000200 /* Ignore COLLATE or affinity on this tree */
-#define EP_IntValue  0x000400 /* Integer value contained in u.iValue */
-#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
-#define EP_Skip      0x001000 /* Operator does not contribute to affinity */
-#define EP_Reduced   0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
-#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
-#define EP_Win       0x008000 /* Contains window functions */
-#define EP_MemToken  0x010000 /* Need to sqlite3DbFree() Expr.zToken */
-#define EP_NoReduce  0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
-#define EP_Unlikely  0x040000 /* unlikely() or likelihood() function */
-#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
-#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
-#define EP_Subquery  0x200000 /* Tree contains a TK_SELECT operator */
-#define EP_Alias     0x400000 /* Is an alias for a result set column */
-#define EP_Leaf      0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
-#define EP_WinFunc  0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
-#define EP_Subrtn   0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */
-#define EP_Quoted   0x4000000 /* TK_ID was originally quoted */
-#define EP_Static   0x8000000 /* Held in memory not obtained from malloc() */
-#define EP_IsTrue  0x10000000 /* Always has boolean value of TRUE */
-#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
+#define EP_FromJoin   0x000001 /* Originates in ON/USING clause of outer join */
+#define EP_Distinct   0x000002 /* Aggregate function with DISTINCT keyword */
+#define EP_HasFunc    0x000004 /* Contains one or more functions of any kind */
+#define EP_FixedCol   0x000008 /* TK_Column with a known fixed value */
+#define EP_Agg        0x000010 /* Contains one or more aggregate functions */
+#define EP_VarSelect  0x000020 /* pSelect is correlated, not constant */
+#define EP_DblQuoted  0x000040 /* token.z was originally in "..." */
+#define EP_InfixFunc  0x000080 /* True for an infix function: LIKE, GLOB, etc */
+#define EP_Collate    0x000100 /* Tree contains a TK_COLLATE operator */
+#define EP_Generic    0x000200 /* Ignore COLLATE or affinity on this tree */
+#define EP_IntValue   0x000400 /* Integer value contained in u.iValue */
+#define EP_xIsSelect  0x000800 /* x.pSelect is valid (otherwise x.pList is) */
+#define EP_Skip       0x001000 /* Operator does not contribute to affinity */
+#define EP_Reduced    0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
+#define EP_TokenOnly  0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
+#define EP_Win        0x008000 /* Contains window functions */
+#define EP_MemToken   0x010000 /* Need to sqlite3DbFree() Expr.zToken */
+#define EP_NoReduce   0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
+#define EP_Unlikely   0x040000 /* unlikely() or likelihood() function */
+#define EP_ConstFunc  0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
+#define EP_CanBeNull  0x100000 /* Can be null despite NOT NULL constraint */
+#define EP_Subquery   0x200000 /* Tree contains a TK_SELECT operator */
+#define EP_Alias      0x400000 /* Is an alias for a result set column */
+#define EP_Leaf       0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
+#define EP_WinFunc   0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
+#define EP_Subrtn    0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */
+#define EP_Quoted    0x4000000 /* TK_ID was originally quoted */
+#define EP_Static    0x8000000 /* Held in memory not obtained from malloc() */
+#define EP_IsTrue   0x10000000 /* Always has boolean value of TRUE */
+#define EP_IsFalse  0x20000000 /* Always has boolean value of FALSE */
+#define EP_Indirect 0x40000000 /* Contained within a TRIGGER or a VIEW */
 
 /*
 ** The EP_Propagate mask is a set of properties that automatically propagate
index a78d5676c738b3ddc2ba2c7857c181fd70fac8ce..511a9c8a66c3eeb30134f9720638138d4da1eb03 100644 (file)
@@ -2741,10 +2741,16 @@ deserialize_error:
   }
 
   /*
-  **     $db function NAME [-argcount N] [-deterministic] SCRIPT
+  **     $db function NAME [OPTIONS] SCRIPT
   **
   ** Create a new SQL function called NAME.  Whenever that function is
   ** called, invoke SCRIPT to evaluate the function.
+  **
+  ** Options:
+  **         --argcount N           Function has exactly N arguments
+  **         --deterministic        The function is pure
+  **         --directonly           Prohibit use inside triggers and views
+  **         --returntype TYPE      Specify the return type of the function
   */
   case DB_FUNCTION: {
     int flags = SQLITE_UTF8;
@@ -2777,6 +2783,9 @@ deserialize_error:
       if( n>1 && strncmp(z, "-deterministic",n)==0 ){
         flags |= SQLITE_DETERMINISTIC;
       }else
+      if( n>1 && strncmp(z, "-directonly",n)==0 ){
+        flags |= SQLITE_DIRECTONLY;
+      }else
       if( n>1 && strncmp(z, "-returntype", n)==0 ){
         const char *azType[] = {"integer", "real", "text", "blob", "any", 0};
         assert( SQLITE_INTEGER==1 && SQLITE_FLOAT==2 && SQLITE_TEXT==3 );
@@ -2792,7 +2801,8 @@ deserialize_error:
         eType++;
       }else{
         Tcl_AppendResult(interp, "bad option \"", z,
-            "\": must be -argcount, -deterministic or -returntype", (char*)0
+            "\": must be -argcount, -deterministic, -directonly,"
+            " or -returntype", (char*)0
         );
         return TCL_ERROR;
       }
index 753f2148996fd0d1f48ed6d806275a5fe2afb9eb..6dfdccd7ee0bbeefabbdf2088ddab27e37acce9b 100644 (file)
@@ -557,10 +557,10 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
 #endif 
       }
       if( pExpr->op==TK_AGG_FUNCTION ){
-        sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q",
-                             pExpr->op2, pExpr->u.zToken);
+        sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s",
+                             pExpr->op2, pExpr->u.zToken, zFlgs);
       }else{
-        sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken);
+        sqlite3TreeViewLine(pView, "FUNCTION %Q%s", pExpr->u.zToken, zFlgs);
       }
       if( pFarg ){
         sqlite3TreeViewExprList(pView, pFarg, pWin!=0, 0);
index 579bad8e44f9cbc6483d082bcd0c60af61580df4..7315af322ab17a92421a36cc56e234fff82d9d04 100644 (file)
@@ -1419,7 +1419,45 @@ do_execsql_test func-32.150 {
   SELECT test_frombind(x.a,y.b,x.c,:123,y.e,x.f,$xyz+y.f) FROM t1 x, t1 y;
 } {8}
 
-
+# 2019-08-15
+# Direct-only functions.
+#
+proc testdirectonly {x} {return [expr {$x*2}]}
+do_test func-33.1 {
+  db func testdirectonly -directonly testdirectonly
+  db eval {SELECT testdirectonly(15)}
+} {30}
+do_catchsql_test func-33.2 {
+  CREATE VIEW v33(y) AS SELECT testdirectonly(15);
+  SELECT * FROM v33;
+} {1 {testdirectonly() prohibited in triggers and views}}
+do_execsql_test func-33.3 {
+  SELECT * FROM (SELECT testdirectonly(15)) AS v33;
+} {30}
+do_execsql_test func-33.4 {
+  WITH c(x) AS (SELECT testdirectonly(15))
+  SELECT * FROM c;
+} {30}
+do_catchsql_test func-33.5 {
+  WITH c(x) AS (SELECT * FROM v33)
+  SELECT * FROM c;
+} {1 {testdirectonly() prohibited in triggers and views}}
+do_execsql_test func-33.10 {
+  CREATE TABLE t33a(a,b);
+  CREATE TABLE t33b(x,y);
+  CREATE TRIGGER r1 AFTER INSERT ON t33a BEGIN
+    INSERT INTO t33b(x,y) VALUES(testdirectonly(new.a),new.b);
+  END;
+} {}
+do_catchsql_test func-33.11 {
+  INSERT INTO t33a VALUES(1,2);
+} {1 {testdirectonly() prohibited in triggers and views}}
+do_execsql_test func-33.20 {
+  ALTER TABLE t33a RENAME COLUMN a TO aaa;
+  SELECT sql FROM sqlite_master WHERE name='r1';
+} {{CREATE TRIGGER r1 AFTER INSERT ON t33a BEGIN
+    INSERT INTO t33b(x,y) VALUES(testdirectonly(new.aaa),new.b);
+  END}}
 
 
 finish_test
index 319737426f9f224538169f12e3324086f471a6a3..ec0312254cc6cb1dadf58c563705da4508148ff2 100644 (file)
@@ -789,7 +789,7 @@ do_test 17.6.2 {
 
 do_test 17.6.3 {
   list [catch { db function xyz -n object ret } msg] $msg
-} {1 {bad option "-n": must be -argcount, -deterministic or -returntype}}
+} {1 {bad option "-n": must be -argcount, -deterministic, -directonly, or -returntype}}
 
 # 2019-02-28: The "bind_fallback" command.
 #