From bb7c3e8eacefb826d371ccc7fb2f4dba5371475a Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 18 Aug 2026 21:12:12 +0000 Subject: [PATCH] Refactor the new code on this branch. FossilOrigin-Name: 76a03b5314bd3a48e5f8de60c47cdb6ae749a8741bf0dede0a3b599a796d76d1 --- manifest | 30 +++++++++++++++--------------- manifest.uuid | 2 +- src/expr.c | 22 ++++++++++++++++------ src/resolve.c | 6 +++--- src/select.c | 4 ++-- src/sqliteInt.h | 2 +- src/vdbe.h | 4 +--- src/vdbeaux.c | 43 +++++++++---------------------------------- src/vdbemem.c | 2 +- src/where.c | 4 +--- src/whereexpr.c | 6 +++--- src/window.c | 2 +- 12 files changed, 54 insertions(+), 73 deletions(-) diff --git a/manifest b/manifest index 45ac9e44d5..d050eb9388 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Ensure\sthat\sVdbe.smimask\sis\scorrectly\sset\safter\sa\sreprepare. -D 2026-08-18T20:22:37.721 +C Refactor\sthe\snew\scode\son\sthis\sbranch. +D 2026-08-18T21:12:12.638 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -694,7 +694,7 @@ F src/date.c e1a002a4199bfa85e8778c0f72182c679580b131147d8e46d9221cfceffb8500 F src/dbpage.c ec8590c5e7a564cef28ca3c6156521316a4d26cb572a34841b0bcb26b67b3f97 F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c F src/delete.c 59eeca3fb88c29329afc41bb803ee568b120d9dd7470b5f38ab55cc38390b451 -F src/expr.c 1cb8c6b1005854b760f5b74999e98da381a84e7fa510bcfc3c1e2dae64d6d559 +F src/expr.c 28838c41596a82d7e4193e2dbff48a1fe0e7a4a4134d5e78a170a0c124d3cf25 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 931f74cec1dc8038a0217ef340c91ce147dd1bbed08dc40c47ee0ec6edfffb08 F src/func.c d833ab92ed95e84af60247e7d752cda33234d8979173442079d54d96e9853dd9 @@ -741,14 +741,14 @@ F src/pragma.c a3ffc8473689240121084fdd87d462164de0aa04c306df377074d8c9eb331725 F src/prepare.c 8954bb69defe377cd6a926f8c61d8215ea4f1974838d3ec6f22681a2c0a2939f F src/printf.c b480176bd0aaed9d64e804cfa3ca27fc585f65a73e7c7ca2fe9b9016db2cf6d5 F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c -F src/resolve.c 7145e41ad75e04a811b326aa5faf83c2e071480fabd9fc825055a6b889e6cb86 +F src/resolve.c 0e0990f60c93db38c735d85e5d1741130e72dd0670aec204b5a39118b53c8044 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 -F src/select.c 7720e5e4ffcdf630691a2208e284a5b4eb507f51a06a380487b10ef5f6a9c8dc +F src/select.c f9da7b070c559f249d6cb7911f8467b6cb8fcb1c785c8d4bf3aaecccdd472789 F src/shell.c.in 7ba51656c54cb0d3ecaa70c35e20ae67c25778431d1d9355d5f6486b54c86c12 F src/sqlite.h.in efc3f7aa00a2bb01c087435e6fa5f86103e310e6c3ea072b12cc110cf2715a75 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 0efd4723bad9124ea1f581d9f1ea0254ac1c6f3e5fb29e4f3dcf36c72485a456 -F src/sqliteInt.h 2d84c44f38e5691bea62cf2512cba068f5370b0bb607dd8e1fc193f4b30ee909 +F src/sqliteInt.h ee9af58ede6c294ae3a0939174661df59d1d689216cd855c6efd22bd9e220042 F src/sqliteLimit.h c433b3fdb5e52f4226bf78d7e8081dff8fd8fbb0ce0cb1a5fee282aaa8976813 F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -811,12 +811,12 @@ F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165 F src/util.c cfdf9c6e5323af886d5ce766709da607ba1d14193ad3a15f4f462a45420e8211 F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82 F src/vdbe.c 37ffba7c3fe3ed2c90dd8b889b0e1b957c337bf5ecdca49dac769e579b96ec9f -F src/vdbe.h 772a672b9f7dc3446b1233cf08016fa02b4e57736e21de1b625f924ee5743de3 +F src/vdbe.h 4fe01be4413203c157280be3caa28705ea1118fcfb54589da5aae3d1cda4917c F src/vdbeInt.h 2ab0984d970c9aa9dc5f861f4938e627137bf0122c61cd19e0a8e2c3b2704105 F src/vdbeapi.c f413302be2dfe6fd9b7397c5ef269ed34d51a47e48d8da406a618bbd99dbf6d2 -F src/vdbeaux.c 4845fe5b5b8a1d13881c1cd045970bcd35d723cdd6c35de3a4f2422c46b0ae5b +F src/vdbeaux.c ca2bbb7df121cc58c6cc55547c4ca78393741f1b2a7afaf63c825bfc4ff80200 F src/vdbeblob.c b3f0640db9642fbdc88bd6ebcc83d6009514cafc98f062f675f2c8d505d82692 -F src/vdbemem.c 6e7ad67507c9a8e625b46256a9c003929331d6a27b99bbe139b8f0dab636e1f2 +F src/vdbemem.c 025fcbeebd9a285afbed4bd3c751248c25da3a0515e0e76c9957d5d2a4226ff8 F src/vdbesort.c a72ad2a629df2901fde4aa588e38590d0aa27b7d5bc3b2a416e5f295de839cc1 F src/vdbetrace.c 49e689f751505839742f4a243a1a566e57d5c9eaf0d33bbaa26e2de3febf7b41 F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3 @@ -825,11 +825,11 @@ F src/vxworks.h 9d18819c5235b49c2340a8a4d48195ec5d5afb637b152406de95a9436beeaeab F src/wal.c cb28ab3a71cb73ea422a2fcc26283b65a1e5a2a65c44de86951c7d6a186381ac F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452 F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014 -F src/where.c 1e688d7ca06f48104fa217d61f7864a471d400dd7c161cc0928ea4a23e1662c9 +F src/where.c 4d764d3173e299ad4a15226529334764f190fc8de989f9a42f893f64702f374c F src/whereInt.h f039ad303bc2913de673e431821ef8db3b619d249e6e5548d90072a684e72285 F src/wherecode.c aa733a45b550c65aae0641335ddd6179a24c6bf0889bf0dda44a8dddc74d6bb0 -F src/whereexpr.c cd88bd3e1a421fb987eb5991ecf7a9a3d5dad1abb02a8baa070336b6dfa70b59 -F src/window.c 0d7dacdf2e84c6ee8ff498d5cc881dd245fcb2f14f6c5976e97e112ce96e90dc +F src/whereexpr.c 76f72a95c5cf0e8a8edb679ca4fb7afa17ba45ff4effe73c414266510109e701 +F src/window.c de9948416a216c7ef970337d8eb5228fcb3c6e67c9989a1d21c49201d8aa0242 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d F test/affinity3.test 9b7d1133e11d5edd7805573c4ab6f3ba73b0b74a1f280d5b130d4bf3506a93ff @@ -2219,8 +2219,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 1cfdde74f1c68589d722b876c20317c2a70cec2d915546a2200035190d3fb082 -R c75aca9a0572272070413ed32f5fd21e +P 56cdd2d432d30766e1e7e9c24766ab121230ad09608922473234f42dbefb29cd +R a4b809d648090c3ef003a9b909b9f2fb U dan -Z bb889800e9827ba37f88cf9367828b9c +Z d1e10f85d7f814acdbf202ed30e288e5 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 17d9f4c803..c479196c7e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -56cdd2d432d30766e1e7e9c24766ab121230ad09608922473234f42dbefb29cd +76a03b5314bd3a48e5f8de60c47cdb6ae749a8741bf0dede0a3b599a796d76d1 diff --git a/src/expr.c b/src/expr.c index acc6f57c86..f3399a81b4 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2937,8 +2937,16 @@ int sqlite3ExprContainsSubquery(Expr *p){ ** If the pParse pointer is provided, then allow the expression p to be ** a parameter (TK_VARIABLE) that is bound to an integer. ** But if pParse is NULL, then p must be a pure integer literal. +** +** If pParse is not NULL and expression p is a variable, then the variable +** is marked so as to cause the statement to be reprepared each time a new +** value is bound to it. Except, if parameter bRSI is true, then the statement +** will only be reprepared if either the new value bound to the variable +** is integer value 0 or 1, or if the value being replaced is integer value +** 0 or 1. RSI -> Reprepare Small Integers. +** */ -int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse){ +int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse, int bRSI){ int rc = 0; if( NEVER(p==0) ) return 0; /* Used to only happen following on OOM */ @@ -2953,12 +2961,12 @@ int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse){ } switch( p->op ){ case TK_UPLUS: { - rc = sqlite3ExprIsInteger(p->pLeft, pValue, 0); + rc = sqlite3ExprIsInteger(p->pLeft, pValue, 0, bRSI); break; } case TK_UMINUS: { int v = 0; - if( sqlite3ExprIsInteger(p->pLeft, &v, 0) ){ + if( sqlite3ExprIsInteger(p->pLeft, &v, 0, bRSI) ){ assert( ((unsigned int)v)!=0x80000000 ); *pValue = -v; rc = 1; @@ -2966,11 +2974,11 @@ int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse){ break; } case TK_VARIABLE: { + int bReprepareSmallint = bRSI; sqlite3_value *pVal; if( pParse==0 ) break; if( NEVER(pParse->pVdbe==0) ) break; if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) break; - sqlite3VdbeSetVarmask(pParse->pVdbe, p->iColumn); pVal = sqlite3VdbeGetBoundValue(pParse->pReprepare, p->iColumn, SQLITE_AFF_BLOB); if( pVal ){ @@ -2979,10 +2987,12 @@ int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse){ if( vv == (vv & 0x7fffffff) ){ /* non-negative numbers only */ *pValue = (int)vv; rc = 1; + if( vv==0 || vv==1 ) bReprepareSmallint = 0; } } sqlite3ValueFree(pVal); } + sqlite3VdbeReprepareOnBind(pParse->pVdbe, p->iColumn, bReprepareSmallint); break; } default: break; @@ -6587,7 +6597,7 @@ static SQLITE_NOINLINE int exprCompareVariable( sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB, &pR); if( pR ){ iVar = pVar->iColumn; - sqlite3VdbeSetVarmask(pParse->pVdbe, iVar); + sqlite3VdbeReprepareOnBind(pParse->pVdbe, iVar, 0); pL = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, SQLITE_AFF_BLOB); if( pL ){ if( sqlite3_value_type(pL)==SQLITE_TEXT ){ @@ -6843,7 +6853,7 @@ static int sqlite3ExprIsNotTrue(Expr *pExpr){ if( pExpr->op==TK_NULL ) return 1; if( pExpr->op==TK_TRUEFALSE && sqlite3ExprTruthValue(pExpr)==0 ) return 1; v = 1; - if( sqlite3ExprIsInteger(pExpr, &v, 0) && v==0 ) return 1; + if( sqlite3ExprIsInteger(pExpr, &v, 0, 0) && v==0 ) return 1; return 0; } diff --git a/src/resolve.c b/src/resolve.c index 9417578be9..c949d3a9ba 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -1571,7 +1571,7 @@ static int resolveOrderByTermToExprList( int rc; /* Return code from subprocedures */ u8 savedSuppErr; /* Saved value of db->suppressErr */ - assert( sqlite3ExprIsInteger(pE, &i, 0)==0 ); + assert( sqlite3ExprIsInteger(pE, &i, 0, 0)==0 ); pEList = pSelect->pEList; /* Resolve all names in the ORDER BY term expression @@ -1670,7 +1670,7 @@ static int resolveCompoundOrderBy( if( pItem->fg.done ) continue; pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr); if( NEVER(pE==0) ) continue; - if( sqlite3ExprIsInteger(pE, &iCol, 0) ){ + if( sqlite3ExprIsInteger(pE, &iCol, 0, 0) ){ if( iCol<=0 || iCol>pEList->nExpr ){ resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE); return 1; @@ -1853,7 +1853,7 @@ static int resolveOrderGroupBy( continue; } } - if( sqlite3ExprIsInteger(pE2, &iCol, 0) ){ + if( sqlite3ExprIsInteger(pE2, &iCol, 0, 0) ){ /* The ORDER BY term is an integer constant. Again, set the column ** number so that sqlite3ResolveOrderGroupBy() will convert the ** order-by term to a copy of the result-set expression */ diff --git a/src/select.c b/src/select.c index 4acbe1fa12..cdd712b8a3 100644 --- a/src/select.c +++ b/src/select.c @@ -2578,7 +2578,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ p->iLimit = iLimit = ++pParse->nMem; v = sqlite3GetVdbe(pParse); assert( v!=0 ); - if( sqlite3ExprIsInteger(pLimit->pLeft, &n, pParse) ){ + if( sqlite3ExprIsInteger(pLimit->pLeft, &n, pParse, 0) ){ sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit); VdbeComment((v, "LIMIT counter")); if( n==0 ){ @@ -3086,7 +3086,7 @@ static int multiSelect( p->pPrior = pPrior; p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow); if( p->pLimit - && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse) + && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse, 0) && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit) ){ p->nSelectRow = sqlite3LogEst((u64)nLimit); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index c2b56464d2..a657f18d65 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -5274,7 +5274,7 @@ int sqlite3ExprListIsConstant(Parse *pParse, ExprList *pList, int bNoIs); #ifdef SQLITE_ENABLE_CURSOR_HINTS int sqlite3ExprContainsSubquery(Expr*); #endif -int sqlite3ExprIsInteger(const Expr*, int*, Parse*); +int sqlite3ExprIsInteger(const Expr*, int*, Parse*, int); int sqlite3ExprCanBeNull(const Expr*); int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); int sqlite3ExprIsLikeOperator(const Expr*); diff --git a/src/vdbe.h b/src/vdbe.h index 2c476db3b1..b66176d2f9 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -296,9 +296,7 @@ int sqlite3VdbeUsesDoubleQuotedString(Vdbe*,const char*); void sqlite3VdbeSwap(Vdbe*,Vdbe*); VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*); sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8); -void sqlite3VdbeSetVarmask(Vdbe*, int); -u32 sqlite3VdbeGetVarmask(Vdbe *v); -void sqlite3VdbeSetSmallint(Vdbe*, u32); +void sqlite3VdbeReprepareOnBind(Vdbe*, int, int); #ifndef SQLITE_OMIT_TRACE char *sqlite3VdbeExpandSql(Vdbe*, const char*); #endif diff --git a/src/vdbeaux.c b/src/vdbeaux.c index b3169d04d2..f974d85578 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -5330,48 +5330,23 @@ sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){ /* ** Configure SQL variable iVar so that binding a new value to it signals ** to sqlite3_reoptimize() that re-preparing the statement may result -** in a better query plan. +** in a better query plan. If parameter bSmallint is true, then the +* *statement is only re-prepared if the new value is integer value 0 or 1. */ -void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){ +void sqlite3VdbeReprepareOnBind(Vdbe *v, int iVar, int bSmallint){ + u32 m; assert( iVar>0 ); assert( (v->db->flags & SQLITE_EnableQPSG)==0 || (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 ); - if( iVar>=32 ){ - v->expmask |= 0x80000000; + + m = (iVar>=32) ? 0x80000000 : ((u32)1 << (iVar-1)); + if( bSmallint ){ + v->smimask |= m; }else{ - v->expmask |= ((u32)1 << (iVar-1)); + v->expmask |= m; } } -/* -** Return the current value of expmask - the mask of variables for which -** binding a new value forces repreparation of the statement. -*/ -u32 sqlite3VdbeGetVarmask(Vdbe *v){ - return v->expmask; -} - -/* -** This is called to configure an SQL variable so that the statement is -** reprepared if a small integer value (0 or 1) is bound to it. -** -** To use this function, the current value of expmask is obtained via -** sqlite3VdbeGetVarmask(). This value should be passed as the second -** parameter to this function. Then some sub-routine is called that may -** make a call to sqlite3VdbeSetVarmask(). Finally, this routine is called. -** If sqlite3VdbeSetVarmask was called, then the variable that it marked -** as causing repreparation is modified to that it only causes a reprepare -** if a small integer value is bound to it. -** -** u32 mask = sqlite3VdbeGetVarmask(); -** sqlite3VdbeSetVarmask(v, iVar); // mark iVar as causing repreparation -** sqlite3VdbeSetSmallint(v, mask); // but only for small integer values -*/ -void sqlite3VdbeSetSmallint(Vdbe *v, u32 expmask){ - v->smimask |= (v->expmask ^ expmask); - v->expmask = expmask; -} - /* ** Helper function for vdbeIsMatchingIndexKey(). Return true if column ** iCol should be ignored when comparing a record with a record from diff --git a/src/vdbemem.c b/src/vdbemem.c index cf88cf4698..923d3e7951 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -2027,7 +2027,7 @@ static int stat4ValueFromExpr( }else if( pExpr->op==TK_VARIABLE && (db->flags & SQLITE_EnableQPSG)==0 ){ Vdbe *v; int iBindVar = pExpr->iColumn; - sqlite3VdbeSetVarmask(pParse->pVdbe, iBindVar); + sqlite3VdbeReprepareOnBind(pParse->pVdbe, iBindVar, 0); if( (v = pParse->pReprepare)!=0 ){ pVal = valueNew(db, pAlloc); if( pVal ){ diff --git a/src/where.c b/src/where.c index 792fc890ab..a80553603d 100644 --- a/src/where.c +++ b/src/where.c @@ -3095,12 +3095,10 @@ static void whereLoopOutputAdjust( Expr *pRight = pOpExpr->pRight; Parse *pParse = pWC->pWInfo->pParse; int k = 0; - u32 expmask = sqlite3VdbeGetVarmask(pParse->pVdbe); testcase( pOpExpr->op==TK_IS ); - if( sqlite3ExprIsInteger(pRight, &k, pParse) && k>=(-1) && k<=1 ){ + if( sqlite3ExprIsInteger(pRight, &k, pParse, 1) && k>=(-1) && k<=1 ){ k = 10; }else{ - sqlite3VdbeSetSmallint(pParse->pVdbe, expmask); k = 20; } if( iReducepVdbe, iCol); + sqlite3VdbeReprepareOnBind(pParse->pVdbe, iCol, 0); assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER ); }else if( op==TK_STRING ){ assert( !ExprHasProperty(pRight, EP_IntValue) ); @@ -317,7 +317,7 @@ static int isLikeOrGlob( ** reprepare the statement when that parameter is rebound */ if( op==TK_VARIABLE ){ Vdbe *v = pParse->pVdbe; - sqlite3VdbeSetVarmask(v, pRight->iColumn); + sqlite3VdbeReprepareOnBind(v, pRight->iColumn, 0); assert( !ExprHasProperty(pRight, EP_IntValue) ); if( *pisComplete && pRight->u.zToken[1] ){ /* If the rhs of the LIKE expression is a variable, and the current @@ -1668,7 +1668,7 @@ static void whereAddLimitExpr( Expr *pNew; int iVal = 0; - if( sqlite3ExprIsInteger(pExpr, &iVal, pParse) && iVal>=0 ){ + if( sqlite3ExprIsInteger(pExpr, &iVal, pParse, 0) && iVal>=0 ){ Expr *pVal = sqlite3ExprInt32(db, iVal); if( pVal==0 ) return; pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal); diff --git a/src/window.c b/src/window.c index f38930c488..40892c4737 100644 --- a/src/window.c +++ b/src/window.c @@ -909,7 +909,7 @@ static ExprList *exprListAppendList( int iDummy; Expr *pSub; pSub = sqlite3ExprSkipCollateAndLikely(pDup); - if( sqlite3ExprIsInteger(pSub, &iDummy, 0) ){ + if( sqlite3ExprIsInteger(pSub, &iDummy, 0, 0) ){ pSub->op = TK_NULL; pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse); pSub->u.zToken = 0;