1
0
mirror of https://github.com/sqlite/sqlite.git synced 2026-10-28 10:57:26 +03:00

Refactor the new code on this branch.

FossilOrigin-Name: 76a03b5314bd3a48e5f8de60c47cdb6ae749a8741bf0dede0a3b599a796d76d1
This commit is contained in:
dan
2026-08-18 21:12:12 +00:00
parent 2018b9c3f6
commit bb7c3e8eac
12 changed files with 54 additions and 73 deletions

View File

@@ -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.

View File

@@ -1 +1 @@
56cdd2d432d30766e1e7e9c24766ab121230ad09608922473234f42dbefb29cd
76a03b5314bd3a48e5f8de60c47cdb6ae749a8741bf0dede0a3b599a796d76d1

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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*);

View File

@@ -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

View File

@@ -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

View File

@@ -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 ){

View File

@@ -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( iReduce<k ){

View File

@@ -212,7 +212,7 @@ static int isLikeOrGlob(
if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){
z = sqlite3_value_text(pVal);
}
sqlite3VdbeSetVarmask(pParse->pVdbe, 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);

View File

@@ -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;