1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-12 13:01:09 +03:00

Enhanced detection logic for preventing the use of static schema expressions

by code generating routines.

FossilOrigin-Name: 5f60b527b938c0778e8f725c635ce0dc5ed7a4e01fd6252aa2cdb64da2f625bc
This commit is contained in:
drh
2020-03-10 19:24:38 +00:00
parent 5cf1b611a2
commit e7375bfa72
7 changed files with 102 additions and 43 deletions

View File

@@ -1,5 +1,5 @@
C Further\schanges\sto\sensure\sthat\sexpressions\sheld\sin\stable\sand\sindex\sdefinitions\ndo\snot\sget\spassed\sdown\sinto\scode\sgenerator\slogic\swhere\sthey\smight\sbe\smodified. C Enhanced\sdetection\slogic\sfor\spreventing\sthe\suse\sof\sstatic\sschema\sexpressions\nby\scode\sgenerating\sroutines.
D 2020-03-10T18:55:41.227 D 2020-03-10T19:24:38.960
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -475,7 +475,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c 7271a120a66dfd12edcee942443fcd7b3860514a5621cb26a374781af1462117 F src/btree.c 7271a120a66dfd12edcee942443fcd7b3860514a5621cb26a374781af1462117
F src/btree.h 6111552f19ed7a40f029cf4b33badc6fef9880314fffd80a945f0b7f43ab7471 F src/btree.h 6111552f19ed7a40f029cf4b33badc6fef9880314fffd80a945f0b7f43ab7471
F src/btreeInt.h dee1a1d0c621524e006bb260bd6b66d5d1867da6fe38cba9ad7b6a9bb9c0c175 F src/btreeInt.h dee1a1d0c621524e006bb260bd6b66d5d1867da6fe38cba9ad7b6a9bb9c0c175
F src/build.c 2394d2c853088106dfc1cf485d609f20e6421d7c84892b795824e454f78e50ad F src/build.c 406645db37154920075d90a4ea3c47f33d5f5b6e0769010a54ea8247ee433c1a
F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 6a77ec9e0eb87aea929e002c816298907e337094a7b556898ae2d1e6be209f90 F src/ctime.c 6a77ec9e0eb87aea929e002c816298907e337094a7b556898ae2d1e6be209f90
@@ -483,7 +483,7 @@ F src/date.c 6c408fdd2e9ddf6e8431aba76315a2d061bea2cec8fbb75e25d7c1ba08274712
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
F src/dbstat.c 0f55297469d4244ab7df395849e1af98eb5e95816af7c661e7d2d8402dea23da F src/dbstat.c 0f55297469d4244ab7df395849e1af98eb5e95816af7c661e7d2d8402dea23da
F src/delete.c 11000121c4281c0bce4e41db29addfaea0038eaa127ece02557c9207bc3e541d F src/delete.c 11000121c4281c0bce4e41db29addfaea0038eaa127ece02557c9207bc3e541d
F src/expr.c 6454893aab3ed99aff11d36a22735a83225759e85ca781b9568f4f620f958b10 F src/expr.c 117997508b41b1d02b4c376bdca16da04e813c0f36d0811e3ea13d1c786f53f4
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 4b575423b0a5d4898b1a7868ce985cf1a8ad91c741c9abbb108ff02536d20f41 F src/fkey.c 4b575423b0a5d4898b1a7868ce985cf1a8ad91c741c9abbb108ff02536d20f41
F src/func.c 108577cebe8a50c86d849a93b99493a54e348dd0b846f00d13b52ca973d5baf4 F src/func.c 108577cebe8a50c86d849a93b99493a54e348dd0b846f00d13b52ca973d5baf4
@@ -520,7 +520,7 @@ F src/os_win.c 035a813cbd17f355bdcad7ab894af214a9c13a1db8aeac902365350b98cd45a7
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c a71ffd145f55e28cbdc1bdabb5e6bef063da428a6c0de3c3a36e9a0c41d4c8c0 F src/pager.c a71ffd145f55e28cbdc1bdabb5e6bef063da428a6c0de3c3a36e9a0c41d4c8c0
F src/pager.h 3b33619a90180e0874c7eca31d6f6ceb464d9322c6fb4e9a7bbb318c8a17bdb3 F src/pager.h 3b33619a90180e0874c7eca31d6f6ceb464d9322c6fb4e9a7bbb318c8a17bdb3
F src/parse.y 61ae75b1764c86f56fdfe384d736e4ba9b0d54015a5ca61925d8cb6b94943d4c F src/parse.y 8575183809cf30f8c9d1fbea65ca34d1de78b659792bc7c42681e01fc596b520
F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177 F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a
@@ -536,7 +536,7 @@ F src/shell.c.in f76590931c0cbbfef347f44f81ade6b335f80c46bc6e59b8b6114383a8df30e
F src/sqlite.h.in 802957feeb249ede54f8dfe99b72aa19e70a0b7737969c46e625dc2f9f2d42b0 F src/sqlite.h.in 802957feeb249ede54f8dfe99b72aa19e70a0b7737969c46e625dc2f9f2d42b0
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 9c5269260409eb3275324ccace6a13a96f4ad330c708415f70ca6097901ff4ee F src/sqlite3ext.h 9c5269260409eb3275324ccace6a13a96f4ad330c708415f70ca6097901ff4ee
F src/sqliteInt.h 37511a5bd13dab6c61242b8d6525c7efdea7a90a7fd00e5ca8e809fa292efe7c F src/sqliteInt.h ed6885bb0ec82db2503c931fd96c795fc7a4b474dc075c3442a45c3a8523c797
F src/sqliteLimit.h 95cb8479ca459496d9c1c6a9f76b38aee12203a56ce1092fe13e50ae2454c032 F src/sqliteLimit.h 95cb8479ca459496d9c1c6a9f76b38aee12203a56ce1092fe13e50ae2454c032
F src/status.c 9ff2210207c6c3b4d9631a8241a7d45ab1b26a0e9c84cb07a9b5ce2de9a3b278 F src/status.c 9ff2210207c6c3b4d9631a8241a7d45ab1b26a0e9c84cb07a9b5ce2de9a3b278
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -596,7 +596,7 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 7b17f6e2f20f6cbcb0b215025a86b7457c38451fc7622f705e553d7a488c572d F src/tokenize.c 7b17f6e2f20f6cbcb0b215025a86b7457c38451fc7622f705e553d7a488c572d
F src/treeview.c 438c1000587b33faba35e87596bebcf7f40638d98f33781cdd9e04711b18b09c F src/treeview.c f78cd9cd79a889e70cd98bd6edd4a464c421452da833e65e987d97d8c41f71fe
F src/trigger.c a40d50e88bd3355f1d2a73f0a3b2d6b42eae26ca4219001b82ef0d064439badc F src/trigger.c a40d50e88bd3355f1d2a73f0a3b2d6b42eae26ca4219001b82ef0d064439badc
F src/update.c 3eb778c42155d944377a4ee5e440b04520f07094804ed6ce63d2528f619614d9 F src/update.c 3eb778c42155d944377a4ee5e440b04520f07094804ed6ce63d2528f619614d9
F src/upsert.c 2920de71b20f04fe25eb00b655d086f0ba60ea133c59d7fa3325c49838818e78 F src/upsert.c 2920de71b20f04fe25eb00b655d086f0ba60ea133c59d7fa3325c49838818e78
@@ -1860,7 +1860,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 03d201c041c17579e791c73fe6babd60b9f892a84ffd1470851f8eb2857d3990 P f45f5de000834da5b23cdcf12c3f0e3073287756afe06bdb77b95fb65b250258
R 15f3f41fa383817c4f7bc848e5f606e0 R f078265eb0d8f8487aa3c2a1c341660a
U drh U drh
Z aac525d59390e43f110256e9523cebc2 Z 1d0ba7c8bbe7247314d90dba25e45a8e

View File

@@ -1 +1 @@
f45f5de000834da5b23cdcf12c3f0e3073287756afe06bdb77b95fb65b250258 5f60b527b938c0778e8f725c635ce0dc5ed7a4e01fd6252aa2cdb64da2f625bc

View File

@@ -2157,6 +2157,32 @@ int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
} }
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
#ifdef SQLITE_DEBUG
/*
** Mark all nodes of an expression as EP_Immutable, indicating that
** they should not be changed. Expressions attached to a table or
** index definition are tagged this way to help ensure that we do
** not pass them into code generator routines by mistake.
*/
static int markImmutableExprStep(Walker *pWalker, Expr *pExpr){
ExprSetVVAProperty(pExpr, EP_Immutable);
return WRC_Continue;
}
static void markExprListImmutable(ExprList *pList){
if( pList ){
Walker w;
memset(&w, 0, sizeof(w));
w.xExprCallback = markImmutableExprStep;
w.xSelectCallback = sqlite3SelectWalkNoop;
w.xSelectCallback2 = 0;
sqlite3WalkExprList(&w, pList);
}
}
#else
#define markExprListImmutable(X) /* no-op */
#endif /* SQLITE_DEBUG */
/* /*
** This routine is called to report the final ")" that terminates ** This routine is called to report the final ")" that terminates
** a CREATE TABLE statement. ** a CREATE TABLE statement.
@@ -2249,6 +2275,8 @@ void sqlite3EndTable(
** actually be used if PRAGMA writable_schema=ON is set. */ ** actually be used if PRAGMA writable_schema=ON is set. */
sqlite3ExprListDelete(db, p->pCheck); sqlite3ExprListDelete(db, p->pCheck);
p->pCheck = 0; p->pCheck = 0;
}else{
markExprListImmutable(p->pCheck);
} }
} }
#endif /* !defined(SQLITE_OMIT_CHECK) */ #endif /* !defined(SQLITE_OMIT_CHECK) */

View File

@@ -42,7 +42,7 @@ char sqlite3TableColumnAffinity(Table *pTab, int iCol){
** SELECT a AS b FROM t1 WHERE b; ** SELECT a AS b FROM t1 WHERE b;
** SELECT * FROM t1 WHERE (select a from t1); ** SELECT * FROM t1 WHERE (select a from t1);
*/ */
char sqlite3ExprAffinity(Expr *pExpr){ char sqlite3ExprAffinity(const Expr *pExpr){
int op; int op;
while( ExprHasProperty(pExpr, EP_Skip) ){ while( ExprHasProperty(pExpr, EP_Skip) ){
assert( pExpr->op==TK_COLLATE ); assert( pExpr->op==TK_COLLATE );
@@ -152,10 +152,10 @@ Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
** COLLATE operators take first precedence. Left operands take ** COLLATE operators take first precedence. Left operands take
** precedence over right operands. ** precedence over right operands.
*/ */
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){
sqlite3 *db = pParse->db; sqlite3 *db = pParse->db;
CollSeq *pColl = 0; CollSeq *pColl = 0;
Expr *p = pExpr; const Expr *p = pExpr;
while( p ){ while( p ){
int op = p->op; int op = p->op;
if( op==TK_REGISTER ) op = p->op2; if( op==TK_REGISTER ) op = p->op2;
@@ -224,7 +224,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
** The sqlite3ExprCollSeq() routine works the same except that it ** The sqlite3ExprCollSeq() routine works the same except that it
** returns NULL if there is no defined collation. ** returns NULL if there is no defined collation.
*/ */
CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr){ CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, const Expr *pExpr){
CollSeq *p = sqlite3ExprCollSeq(pParse, pExpr); CollSeq *p = sqlite3ExprCollSeq(pParse, pExpr);
if( p==0 ) p = pParse->db->pDfltColl; if( p==0 ) p = pParse->db->pDfltColl;
assert( p!=0 ); assert( p!=0 );
@@ -234,7 +234,7 @@ CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr){
/* /*
** Return TRUE if the two expressions have equivalent collating sequences. ** Return TRUE if the two expressions have equivalent collating sequences.
*/ */
int sqlite3ExprCollSeqMatch(Parse *pParse, Expr *pE1, Expr *pE2){ int sqlite3ExprCollSeqMatch(Parse *pParse, const Expr *pE1, const Expr *pE2){
CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pE1); CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pE1);
CollSeq *pColl2 = sqlite3ExprNNCollSeq(pParse, pE2); CollSeq *pColl2 = sqlite3ExprNNCollSeq(pParse, pE2);
return sqlite3StrICmp(pColl1->zName, pColl2->zName)==0; return sqlite3StrICmp(pColl1->zName, pColl2->zName)==0;
@@ -245,7 +245,7 @@ int sqlite3ExprCollSeqMatch(Parse *pParse, Expr *pE1, Expr *pE2){
** type affinity of the other operand. This routine returns the ** type affinity of the other operand. This routine returns the
** type affinity that should be used for the comparison operator. ** type affinity that should be used for the comparison operator.
*/ */
char sqlite3CompareAffinity(Expr *pExpr, char aff2){ char sqlite3CompareAffinity(const Expr *pExpr, char aff2){
char aff1 = sqlite3ExprAffinity(pExpr); char aff1 = sqlite3ExprAffinity(pExpr);
if( aff1>SQLITE_AFF_NONE && aff2>SQLITE_AFF_NONE ){ if( aff1>SQLITE_AFF_NONE && aff2>SQLITE_AFF_NONE ){
/* Both sides of the comparison are columns. If one has numeric /* Both sides of the comparison are columns. If one has numeric
@@ -267,7 +267,7 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2){
** pExpr is a comparison operator. Return the type affinity that should ** pExpr is a comparison operator. Return the type affinity that should
** be applied to both operands prior to doing the comparison. ** be applied to both operands prior to doing the comparison.
*/ */
static char comparisonAffinity(Expr *pExpr){ static char comparisonAffinity(const Expr *pExpr){
char aff; char aff;
assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT || assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT ||
pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE || pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE ||
@@ -290,7 +290,7 @@ static char comparisonAffinity(Expr *pExpr){
** if the index with affinity idx_affinity may be used to implement ** if the index with affinity idx_affinity may be used to implement
** the comparison in pExpr. ** the comparison in pExpr.
*/ */
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ int sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity){
char aff = comparisonAffinity(pExpr); char aff = comparisonAffinity(pExpr);
if( aff<SQLITE_AFF_TEXT ){ if( aff<SQLITE_AFF_TEXT ){
return 1; return 1;
@@ -305,7 +305,11 @@ int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){
** Return the P5 value that should be used for a binary comparison ** Return the P5 value that should be used for a binary comparison
** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2. ** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2.
*/ */
static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){ static u8 binaryCompareP5(
const Expr *pExpr1, /* Left operand */
const Expr *pExpr2, /* Right operand */
int jumpIfNull /* Extra flags added to P5 */
){
u8 aff = (char)sqlite3ExprAffinity(pExpr2); u8 aff = (char)sqlite3ExprAffinity(pExpr2);
aff = (u8)sqlite3CompareAffinity(pExpr1, aff) | (u8)jumpIfNull; aff = (u8)sqlite3CompareAffinity(pExpr1, aff) | (u8)jumpIfNull;
return aff; return aff;
@@ -325,8 +329,8 @@ static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
*/ */
CollSeq *sqlite3BinaryCompareCollSeq( CollSeq *sqlite3BinaryCompareCollSeq(
Parse *pParse, Parse *pParse,
Expr *pLeft, const Expr *pLeft,
Expr *pRight const Expr *pRight
){ ){
CollSeq *pColl; CollSeq *pColl;
assert( pLeft ); assert( pLeft );
@@ -351,7 +355,7 @@ CollSeq *sqlite3BinaryCompareCollSeq(
** is reversed in the sqlite3BinaryCompareCollSeq() call so that the ** is reversed in the sqlite3BinaryCompareCollSeq() call so that the
** correct collating sequence is found. ** correct collating sequence is found.
*/ */
CollSeq *sqlite3ExprCompareCollSeq(Parse *pParse, Expr *p){ CollSeq *sqlite3ExprCompareCollSeq(Parse *pParse, const Expr *p){
if( ExprHasProperty(p, EP_Commuted) ){ if( ExprHasProperty(p, EP_Commuted) ){
return sqlite3BinaryCompareCollSeq(pParse, p->pRight, p->pLeft); return sqlite3BinaryCompareCollSeq(pParse, p->pRight, p->pLeft);
}else{ }else{
@@ -594,6 +598,7 @@ static void codeVectorCompare(
int addrDone = sqlite3VdbeMakeLabel(pParse); int addrDone = sqlite3VdbeMakeLabel(pParse);
int isCommuted = ExprHasProperty(pExpr,EP_Commuted); int isCommuted = ExprHasProperty(pExpr,EP_Commuted);
assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
if( pParse->nErr ) return; if( pParse->nErr ) return;
if( nLeft!=sqlite3ExprVectorSize(pRight) ){ if( nLeft!=sqlite3ExprVectorSize(pRight) ){
sqlite3ErrorMsg(pParse, "row value misused"); sqlite3ErrorMsg(pParse, "row value misused");
@@ -1206,7 +1211,7 @@ static int dupedExprStructSize(Expr *p, int flags){
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasProperty(p, EP_FromJoin) ); assert( !ExprHasProperty(p, EP_FromJoin) );
assert( !ExprHasProperty(p, EP_MemToken) ); assert( !ExprHasProperty(p, EP_MemToken) );
assert( !ExprHasProperty(p, EP_NoReduce) ); assert( !ExprHasVVAProperty(p, EP_NoReduce) );
if( p->pLeft || p->x.pList ){ if( p->pLeft || p->x.pList ){
nSize = EXPR_REDUCEDSIZE | EP_Reduced; nSize = EXPR_REDUCEDSIZE | EP_Reduced;
}else{ }else{
@@ -1311,6 +1316,10 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken); pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken);
pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly); pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
pNew->flags |= staticFlag; pNew->flags |= staticFlag;
ExprClearVVAProperties(pNew);
if( dupFlags ){
ExprSetVVAProperty(pNew, EP_Immutable);
}
/* Copy the p->u.zToken string, if any. */ /* Copy the p->u.zToken string, if any. */
if( nToken ){ if( nToken ){
@@ -3171,6 +3180,7 @@ static void sqlite3ExprCodeIN(
int addrTop; /* Top of the step-6 loop */ int addrTop; /* Top of the step-6 loop */
int iTab = 0; /* Index to use */ int iTab = 0; /* Index to use */
assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
pLeft = pExpr->pLeft; pLeft = pExpr->pLeft;
if( sqlite3ExprCheckIN(pParse, pExpr) ) return; if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
zAff = exprINAffinity(pParse, pExpr); zAff = exprINAffinity(pParse, pExpr);
@@ -3781,6 +3791,7 @@ expr_code_doover:
if( pExpr==0 ){ if( pExpr==0 ){
op = TK_NULL; op = TK_NULL;
}else{ }else{
assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
op = pExpr->op; op = pExpr->op;
} }
switch( op ){ switch( op ){
@@ -4039,6 +4050,7 @@ expr_code_doover:
tempX.op = TK_INTEGER; tempX.op = TK_INTEGER;
tempX.flags = EP_IntValue|EP_TokenOnly; tempX.flags = EP_IntValue|EP_TokenOnly;
tempX.u.iValue = 0; tempX.u.iValue = 0;
ExprClearVVAProperties(&tempX);
r1 = sqlite3ExprCodeTemp(pParse, &tempX, &regFree1); r1 = sqlite3ExprCodeTemp(pParse, &tempX, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree2); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree2);
sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target); sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target);
@@ -4115,11 +4127,8 @@ expr_code_doover:
return sqlite3ExprCodeAtInit(pParse, pExpr, -1); return sqlite3ExprCodeAtInit(pParse, pExpr, -1);
} }
assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
if( ExprHasProperty(pExpr, EP_TokenOnly) ){ assert( !ExprHasProperty(pExpr, EP_TokenOnly) );
pFarg = 0; pFarg = pExpr->x.pList;
}else{
pFarg = pExpr->x.pList;
}
nFarg = pFarg ? pFarg->nExpr : 0; nFarg = pFarg ? pFarg->nExpr : 0;
assert( !ExprHasProperty(pExpr, EP_IntValue) ); assert( !ExprHasProperty(pExpr, EP_IntValue) );
zId = pExpr->u.zToken; zId = pExpr->u.zToken;
@@ -4573,6 +4582,7 @@ int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
int inReg; int inReg;
assert( pExpr==0 || !ExprHasVVAProperty(pExpr,EP_Immutable) );
assert( target>0 && target<=pParse->nMem ); assert( target>0 && target<=pParse->nMem );
inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
assert( pParse->pVdbe!=0 || pParse->db->mallocFailed ); assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
@@ -4790,6 +4800,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */ if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
if( NEVER(pExpr==0) ) return; /* No way this can happen */ if( NEVER(pExpr==0) ) return; /* No way this can happen */
assert( !ExprHasVVAProperty(pExpr, EP_Immutable) );
op = pExpr->op; op = pExpr->op;
switch( op ){ switch( op ){
case TK_AND: case TK_AND:
@@ -4931,6 +4942,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */ if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
if( pExpr==0 ) return; if( pExpr==0 ) return;
assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
/* The value of pExpr->op and op are related as follows: /* The value of pExpr->op and op are related as follows:
** **
@@ -5214,7 +5226,7 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
} }
if( (pA->flags & (EP_Distinct|EP_Commuted)) if( (pA->flags & (EP_Distinct|EP_Commuted))
!= (pB->flags & (EP_Distinct|EP_Commuted)) ) return 2; != (pB->flags & (EP_Distinct|EP_Commuted)) ) return 2;
if( (combinedFlags & EP_TokenOnly)==0 ){ if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
if( combinedFlags & EP_xIsSelect ) return 2; if( combinedFlags & EP_xIsSelect ) return 2;
if( (combinedFlags & EP_FixedCol)==0 if( (combinedFlags & EP_FixedCol)==0
&& sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2; && sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
@@ -5222,7 +5234,7 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
if( pA->op!=TK_STRING if( pA->op!=TK_STRING
&& pA->op!=TK_TRUEFALSE && pA->op!=TK_TRUEFALSE
&& (combinedFlags & EP_Reduced)==0 && ALWAYS((combinedFlags & EP_Reduced)==0)
){ ){
if( pA->iColumn!=pB->iColumn ) return 2; if( pA->iColumn!=pB->iColumn ) return 2;
if( pA->op2!=pB->op2 ){ if( pA->op2!=pB->op2 ){

View File

@@ -965,6 +965,7 @@ idlist(A) ::= nm(Y).
p->op = (u8)op; p->op = (u8)op;
p->affExpr = 0; p->affExpr = 0;
p->flags = EP_Leaf; p->flags = EP_Leaf;
ExprClearVVAProperties(p);
p->iAgg = -1; p->iAgg = -1;
p->pLeft = p->pRight = 0; p->pLeft = p->pRight = 0;
p->x.pList = 0; p->x.pList = 0;

View File

@@ -2594,6 +2594,9 @@ struct Expr {
** TK_COLUMN: the value of p5 for OP_Column ** TK_COLUMN: the value of p5 for OP_Column
** TK_AGG_FUNCTION: nesting depth ** TK_AGG_FUNCTION: nesting depth
** TK_FUNCTION: NC_SelfRef flag if needs OP_PureFunc */ ** TK_FUNCTION: NC_SelfRef flag if needs OP_PureFunc */
#ifdef SQLITE_DEBUG
u8 vvaFlags; /* Verification flags. */
#endif
u32 flags; /* Various flags. EP_* See below */ u32 flags; /* Various flags. EP_* See below */
union { union {
char *zToken; /* Token value. Zero terminated and dequoted */ char *zToken; /* Token value. Zero terminated and dequoted */
@@ -2668,7 +2671,7 @@ struct Expr {
#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */ #define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
#define EP_Win 0x008000 /* Contains window functions */ #define EP_Win 0x008000 /* Contains window functions */
#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ #define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ /* 0x020000 // available for reuse */
#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG 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_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
@@ -2682,6 +2685,7 @@ struct Expr {
#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */ #define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */ #define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
#define EP_FromDDL 0x40000000 /* Originates from sqlite_master */ #define EP_FromDDL 0x40000000 /* Originates from sqlite_master */
/* 0x80000000 // Available */
/* /*
** The EP_Propagate mask is a set of properties that automatically propagate ** The EP_Propagate mask is a set of properties that automatically propagate
@@ -2700,14 +2704,24 @@ struct Expr {
#define ExprAlwaysTrue(E) (((E)->flags&(EP_FromJoin|EP_IsTrue))==EP_IsTrue) #define ExprAlwaysTrue(E) (((E)->flags&(EP_FromJoin|EP_IsTrue))==EP_IsTrue)
#define ExprAlwaysFalse(E) (((E)->flags&(EP_FromJoin|EP_IsFalse))==EP_IsFalse) #define ExprAlwaysFalse(E) (((E)->flags&(EP_FromJoin|EP_IsFalse))==EP_IsFalse)
/* Flags for use with Expr.vvaFlags
*/
#define EP_NoReduce 0x01 /* Cannot EXPRDUP_REDUCE this Expr */
#define EP_Immutable 0x02 /* Do not change this Expr node */
/* The ExprSetVVAProperty() macro is used for Verification, Validation, /* The ExprSetVVAProperty() macro is used for Verification, Validation,
** and Accreditation only. It works like ExprSetProperty() during VVA ** and Accreditation only. It works like ExprSetProperty() during VVA
** processes but is a no-op for delivery. ** processes but is a no-op for delivery.
*/ */
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
# define ExprSetVVAProperty(E,P) (E)->flags|=(P) # define ExprSetVVAProperty(E,P) (E)->vvaFlags|=(P)
# define ExprHasVVAProperty(E,P) (((E)->vvaFlags&(P))!=0)
# define ExprClearVVAProperties(E) (E)->vvaFlags = 0
#else #else
# define ExprSetVVAProperty(E,P) # define ExprSetVVAProperty(E,P)
# define ExprHasVVAProperty(E,P) 0
# define ExprClearVVAProperties(E)
#endif #endif
/* /*
@@ -4439,10 +4453,10 @@ int sqlite3VarintLen(u64 v);
const char *sqlite3IndexAffinityStr(sqlite3*, Index*); const char *sqlite3IndexAffinityStr(sqlite3*, Index*);
void sqlite3TableAffinity(Vdbe*, Table*, int); void sqlite3TableAffinity(Vdbe*, Table*, int);
char sqlite3CompareAffinity(Expr *pExpr, char aff2); char sqlite3CompareAffinity(const Expr *pExpr, char aff2);
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity); int sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity);
char sqlite3TableColumnAffinity(Table*,int); char sqlite3TableColumnAffinity(Table*,int);
char sqlite3ExprAffinity(Expr *pExpr); char sqlite3ExprAffinity(const Expr *pExpr);
int sqlite3Atoi64(const char*, i64*, int, u8); int sqlite3Atoi64(const char*, i64*, int, u8);
int sqlite3DecOrHexToI64(const char*, i64*); int sqlite3DecOrHexToI64(const char*, i64*);
void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...); void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
@@ -4466,9 +4480,9 @@ CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
int sqlite3IsBinary(const CollSeq*); int sqlite3IsBinary(const CollSeq*);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
void sqlite3SetTextEncoding(sqlite3 *db, u8); void sqlite3SetTextEncoding(sqlite3 *db, u8);
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr);
CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr); CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, const Expr *pExpr);
int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*); int sqlite3ExprCollSeqMatch(Parse*,const Expr*,const Expr*);
Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int); Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
Expr *sqlite3ExprSkipCollate(Expr*); Expr *sqlite3ExprSkipCollate(Expr*);
@@ -4699,8 +4713,8 @@ char *sqlite3Normalize(Vdbe*, const char*);
#endif #endif
int sqlite3Reprepare(Vdbe*); int sqlite3Reprepare(Vdbe*);
void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
CollSeq *sqlite3ExprCompareCollSeq(Parse*,Expr*); CollSeq *sqlite3ExprCompareCollSeq(Parse*,const Expr*);
CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); CollSeq *sqlite3BinaryCompareCollSeq(Parse *, const Expr*, const Expr*);
int sqlite3TempInMemory(const sqlite3*); int sqlite3TempInMemory(const sqlite3*);
const char *sqlite3JournalModename(int); const char *sqlite3JournalModename(int);
#ifndef SQLITE_OMIT_WAL #ifndef SQLITE_OMIT_WAL

View File

@@ -398,14 +398,14 @@ void sqlite3TreeViewWinFunc(TreeView *pView, const Window *pWin, u8 more){
void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
const char *zBinOp = 0; /* Binary operator */ const char *zBinOp = 0; /* Binary operator */
const char *zUniOp = 0; /* Unary operator */ const char *zUniOp = 0; /* Unary operator */
char zFlgs[60]; char zFlgs[200];
pView = sqlite3TreeViewPush(pView, moreToFollow); pView = sqlite3TreeViewPush(pView, moreToFollow);
if( pExpr==0 ){ if( pExpr==0 ){
sqlite3TreeViewLine(pView, "nil"); sqlite3TreeViewLine(pView, "nil");
sqlite3TreeViewPop(pView); sqlite3TreeViewPop(pView);
return; return;
} }
if( pExpr->flags || pExpr->affExpr ){ if( pExpr->flags || pExpr->affExpr || pExpr->vvaFlags ){
StrAccum x; StrAccum x;
sqlite3StrAccumInit(&x, 0, zFlgs, sizeof(zFlgs), 0); sqlite3StrAccumInit(&x, 0, zFlgs, sizeof(zFlgs), 0);
sqlite3_str_appendf(&x, " fg.af=%x.%c", sqlite3_str_appendf(&x, " fg.af=%x.%c",
@@ -416,6 +416,9 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
if( ExprHasProperty(pExpr, EP_FromDDL) ){ if( ExprHasProperty(pExpr, EP_FromDDL) ){
sqlite3_str_appendf(&x, " DDL"); sqlite3_str_appendf(&x, " DDL");
} }
if( ExprHasVVAProperty(pExpr, EP_Immutable) ){
sqlite3_str_appendf(&x, " IMMUTABLE");
}
sqlite3StrAccumFinish(&x); sqlite3StrAccumFinish(&x);
}else{ }else{
zFlgs[0] = 0; zFlgs[0] = 0;
@@ -522,6 +525,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
case TK_RSHIFT: zBinOp = "RSHIFT"; break; case TK_RSHIFT: zBinOp = "RSHIFT"; break;
case TK_CONCAT: zBinOp = "CONCAT"; break; case TK_CONCAT: zBinOp = "CONCAT"; break;
case TK_DOT: zBinOp = "DOT"; break; case TK_DOT: zBinOp = "DOT"; break;
case TK_LIMIT: zBinOp = "LIMIT"; break;
case TK_UMINUS: zUniOp = "UMINUS"; break; case TK_UMINUS: zUniOp = "UMINUS"; break;
case TK_UPLUS: zUniOp = "UPLUS"; break; case TK_UPLUS: zUniOp = "UPLUS"; break;