Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Immediately purge entries from the column cache when the associated register undergoes an affinity change. Ticket [eb5548a849]. Enhance the SQLITE_TESTCTRL_OPTIMIZATIONS setting of sqlite3_test_control so that it can disable the column cache for testing purposes, in an effort to prevent future problems of a similar nature to this one. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
ea4e57e1c1b6663ceb12872e31a8503f |
User & Date: | drh 2009-12-24 16:00:29.000 |
References
2009-12-24
| ||
16:01 | • Fixed ticket [eb5548a849]: CAST in WHERE clause causes inconsistent query results plus 3 other changes (artifact: 5ad1607e97 user: drh) | |
Context
2009-12-29
| ||
10:32 | Fix a bug triggered by optimizing an FTS3 table when there are no segments on disk but pending terms in the hash table. (check-in: a3b50e4f80 user: dan tags: trunk) | |
2009-12-24
| ||
16:00 | Immediately purge entries from the column cache when the associated register undergoes an affinity change. Ticket [eb5548a849]. Enhance the SQLITE_TESTCTRL_OPTIMIZATIONS setting of sqlite3_test_control so that it can disable the column cache for testing purposes, in an effort to prevent future problems of a similar nature to this one. (check-in: ea4e57e1c1 user: drh tags: trunk) | |
2009-12-22
| ||
23:52 | Move the query flattener turn-off from a pragma to an sqlite3_test_control() call. Make provisions (not yet implemented) to turn off other optimizers using the same call. (check-in: 4a97c623f4 user: drh tags: trunk) | |
Changes
Changes to src/delete.c.
︙ | ︙ | |||
360 361 362 363 364 365 366 | int regRowid; /* Actual register containing rowids */ /* Collect rowids of every row to be deleted. */ sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK); if( pWInfo==0 ) goto delete_from_cleanup; | | | 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 | int regRowid; /* Actual register containing rowids */ /* Collect rowids of every row to be deleted. */ sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,WHERE_DUPLICATES_OK); if( pWInfo==0 ) goto delete_from_cleanup; regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid); sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid); if( db->flags & SQLITE_CountRows ){ sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); } sqlite3WhereEnd(pWInfo); /* Delete every item whose key was written to the list during the |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
223 224 225 226 227 228 229 | if( !pColl ){ pColl = sqlite3ExprCollSeq(pParse, pRight); } } return pColl; } | < < < < < < < < < < < < < < < < < < < < < < < < | 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | if( !pColl ){ pColl = sqlite3ExprCollSeq(pParse, pRight); } } return pColl; } /* ** Generate code for a comparison operator. */ static int codeCompare( Parse *pParse, /* The parsing (and code generating) context */ Expr *pLeft, /* The left operand */ Expr *pRight, /* The right operand */ |
︙ | ︙ | |||
1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 | int minLru; int idxLru; struct yColCache *p; assert( iReg>0 ); /* Register numbers are always positive */ assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */ /* First replace any existing entry */ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ if( p->iReg && p->iTable==iTab && p->iColumn==iCol ){ cacheEntryClear(pParse, p); p->iLevel = pParse->iCacheLevel; p->iReg = iReg; | > > > > > > < < | 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 | int minLru; int idxLru; struct yColCache *p; assert( iReg>0 ); /* Register numbers are always positive */ assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */ /* The SQLITE_ColumnCache flag disables the column cache. This is used ** for testing only - to verify that SQLite always gets the same answer ** with and without the column cache. */ if( pParse->db->flags & SQLITE_ColumnCache ) return; /* First replace any existing entry */ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ if( p->iReg && p->iTable==iTab && p->iColumn==iCol ){ cacheEntryClear(pParse, p); p->iLevel = pParse->iCacheLevel; p->iReg = iReg; p->lru = pParse->iCacheCnt++; return; } } /* Find an empty slot and replace it */ for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ if( p->iReg==0 ){ p->iLevel = pParse->iCacheLevel; p->iTable = iTab; p->iColumn = iCol; p->iReg = iReg; p->tempReg = 0; p->lru = pParse->iCacheCnt++; return; } } /* Replace the last recently used */ |
︙ | ︙ | |||
2019 2020 2021 2022 2023 2024 2025 | } if( ALWAYS(idxLru>=0) ){ p = &pParse->aColCache[idxLru]; p->iLevel = pParse->iCacheLevel; p->iTable = iTab; p->iColumn = iCol; p->iReg = iReg; | < | 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 | } if( ALWAYS(idxLru>=0) ){ p = &pParse->aColCache[idxLru]; p->iLevel = pParse->iCacheLevel; p->iTable = iTab; p->iColumn = iCol; p->iReg = iReg; p->tempReg = 0; p->lru = pParse->iCacheCnt++; return; } } /* |
︙ | ︙ | |||
2105 2106 2107 2108 2109 2110 2111 | ** used if allowAffChng is true. */ int sqlite3ExprCodeGetColumn( Parse *pParse, /* Parsing and code generating context */ Table *pTab, /* Description of the table we are reading from */ int iColumn, /* Index of the table column */ int iTable, /* The cursor pointing to the table */ | | < | < | 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 | ** used if allowAffChng is true. */ int sqlite3ExprCodeGetColumn( Parse *pParse, /* Parsing and code generating context */ Table *pTab, /* Description of the table we are reading from */ int iColumn, /* Index of the table column */ int iTable, /* The cursor pointing to the table */ int iReg /* Store results here */ ){ Vdbe *v = pParse->pVdbe; int i; struct yColCache *p; for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn ){ p->lru = pParse->iCacheCnt++; sqlite3ExprCachePinRegister(pParse, p->iReg); return p->iReg; } } assert( v!=0 ); if( iColumn<0 ){ |
︙ | ︙ | |||
2158 2159 2160 2161 2162 2163 2164 | void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){ int iEnd = iStart + iCount - 1; int i; struct yColCache *p; for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ int r = p->iReg; if( r>=iStart && r<=iEnd ){ | > | | 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 | void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){ int iEnd = iStart + iCount - 1; int i; struct yColCache *p; for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){ int r = p->iReg; if( r>=iStart && r<=iEnd ){ cacheEntryClear(pParse, p); p->iReg = 0; } } } /* ** Generate code to move content from registers iFrom...iFrom+nReg-1 ** over to iTo..iTo+nReg-1. Keep the column cache up-to-date. |
︙ | ︙ | |||
2325 2326 2327 2328 2329 2330 2331 | } case TK_COLUMN: { if( pExpr->iTable<0 ){ /* This only happens when coding check constraints */ assert( pParse->ckBase>0 ); inReg = pExpr->iColumn + pParse->ckBase; }else{ | < | < | 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 | } case TK_COLUMN: { if( pExpr->iTable<0 ){ /* This only happens when coding check constraints */ assert( pParse->ckBase>0 ); inReg = pExpr->iColumn + pParse->ckBase; }else{ inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, pExpr->iColumn, pExpr->iTable, target); } break; } case TK_INTEGER: { codeInteger(v, pExpr, 0, target); break; } |
︙ | ︙ | |||
2445 2446 2447 2448 2449 2450 2451 | assert( TK_NE==OP_Ne ); testcase( op==TK_LT ); testcase( op==TK_LE ); testcase( op==TK_GT ); testcase( op==TK_GE ); testcase( op==TK_EQ ); testcase( op==TK_NE ); | | | | | | 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 | assert( TK_NE==OP_Ne ); testcase( op==TK_LT ); testcase( op==TK_LE ); testcase( op==TK_GT ); testcase( op==TK_GE ); testcase( op==TK_EQ ); testcase( op==TK_NE ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, inReg, SQLITE_STOREP2); testcase( regFree1==0 ); testcase( regFree2==0 ); break; } case TK_IS: case TK_ISNOT: { testcase( op==TK_IS ); testcase( op==TK_ISNOT ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); op = (op==TK_IS) ? TK_EQ : TK_NE; codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ); testcase( regFree1==0 ); testcase( regFree2==0 ); break; } |
︙ | ︙ | |||
2698 2699 2700 2701 2702 2703 2704 | ** Z is stored in pExpr->pList->a[1].pExpr. */ case TK_BETWEEN: { Expr *pLeft = pExpr->pLeft; struct ExprList_item *pLItem = pExpr->x.pList->a; Expr *pRight = pLItem->pExpr; | | | | 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 | ** Z is stored in pExpr->pList->a[1].pExpr. */ case TK_BETWEEN: { Expr *pLeft = pExpr->pLeft; struct ExprList_item *pLItem = pExpr->x.pList->a; Expr *pRight = pLItem->pExpr; r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2); testcase( regFree1==0 ); testcase( regFree2==0 ); r3 = sqlite3GetTempReg(pParse); r4 = sqlite3GetTempReg(pParse); codeCompare(pParse, pLeft, pRight, OP_Ge, r1, r2, r3, SQLITE_STOREP2); pLItem++; |
︙ | ︙ | |||
3234 3235 3236 3237 3238 3239 3240 | testcase( op==TK_LT ); testcase( op==TK_LE ); testcase( op==TK_GT ); testcase( op==TK_GE ); testcase( op==TK_EQ ); testcase( op==TK_NE ); testcase( jumpIfNull==0 ); | | | | | | 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 | testcase( op==TK_LT ); testcase( op==TK_LE ); testcase( op==TK_GT ); testcase( op==TK_GE ); testcase( op==TK_EQ ); testcase( op==TK_NE ); testcase( jumpIfNull==0 ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, dest, jumpIfNull); testcase( regFree1==0 ); testcase( regFree2==0 ); break; } case TK_IS: case TK_ISNOT: { testcase( op==TK_IS ); testcase( op==TK_ISNOT ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); op = (op==TK_IS) ? TK_EQ : TK_NE; codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, dest, SQLITE_NULLEQ); testcase( regFree1==0 ); testcase( regFree2==0 ); break; } |
︙ | ︙ | |||
3377 3378 3379 3380 3381 3382 3383 | testcase( op==TK_LT ); testcase( op==TK_LE ); testcase( op==TK_GT ); testcase( op==TK_GE ); testcase( op==TK_EQ ); testcase( op==TK_NE ); testcase( jumpIfNull==0 ); | | | | | | 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 | testcase( op==TK_LT ); testcase( op==TK_LE ); testcase( op==TK_GT ); testcase( op==TK_GE ); testcase( op==TK_EQ ); testcase( op==TK_NE ); testcase( jumpIfNull==0 ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, dest, jumpIfNull); testcase( regFree1==0 ); testcase( regFree2==0 ); break; } case TK_IS: case TK_ISNOT: { testcase( pExpr->op==TK_IS ); testcase( pExpr->op==TK_ISNOT ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ; codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, r1, r2, dest, SQLITE_NULLEQ); testcase( regFree1==0 ); testcase( regFree2==0 ); break; } |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
3913 3914 3915 3916 3917 3918 3919 | for(i=0; i<sAggInfo.nColumn; i++){ struct AggInfo_col *pCol = &sAggInfo.aCol[i]; if( pCol->iSorterColumn>=j ){ int r1 = j + regBase; int r2; r2 = sqlite3ExprCodeGetColumn(pParse, | | | 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 | for(i=0; i<sAggInfo.nColumn; i++){ struct AggInfo_col *pCol = &sAggInfo.aCol[i]; if( pCol->iSorterColumn>=j ){ int r1 = j + regBase; int r2; r2 = sqlite3ExprCodeGetColumn(pParse, pCol->pTab, pCol->iColumn, pCol->iTable, r1); if( r1!=r2 ){ sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1); } j++; } } regRecord = sqlite3GetTempReg(pParse); |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
926 927 928 929 930 931 932 | /* ** Bits of the sqlite3.flags field that are used by the ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface. ** These must be the low-order bits of the flags field. */ #define SQLITE_QueryFlattener 0x01 /* Disable query flattening */ | | | | | | 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 | /* ** Bits of the sqlite3.flags field that are used by the ** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface. ** These must be the low-order bits of the flags field. */ #define SQLITE_QueryFlattener 0x01 /* Disable query flattening */ #define SQLITE_ColumnCache 0x02 /* Disable the column cache */ #define SQLITE_IndexSort 0x04 /* Disable indexes for sorting */ #define SQLITE_IndexSearch 0x08 /* Disable indexes for searching */ #define SQLITE_IndexCover 0x10 /* Disable index covering table */ #define SQLITE_OptMask 0x1f /* Mask of all disablable opts */ /* ** Possible values for the sqlite.magic field. ** The numbers are obtained at random and have no special meaning, other ** than being distinct from one another. */ |
︙ | ︙ | |||
1644 1645 1646 1647 1648 1649 1650 | #define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */ #define EP_Error 0x0008 /* Expression contains one or more errors */ #define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */ #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ #define EP_DblQuoted 0x0040 /* token.z was originally in "..." */ #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ #define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */ | < | | | | | | | 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 | #define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */ #define EP_Error 0x0008 /* Expression contains one or more errors */ #define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */ #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ #define EP_DblQuoted 0x0040 /* token.z was originally in "..." */ #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ #define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */ #define EP_FixedDest 0x0200 /* Result needed in a specific register */ #define EP_IntValue 0x0400 /* Integer value contained in u.iValue */ #define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */ #define EP_Reduced 0x1000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */ #define EP_TokenOnly 0x2000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */ #define EP_Static 0x4000 /* Held in memory not obtained from malloc() */ /* ** The following are the meanings of bits in the Expr.flags2 field. */ #define EP2_MallocedToken 0x0001 /* Need to sqlite3DbFree() Expr.zToken */ #define EP2_Irreducible 0x0002 /* Cannot EXPRDUP_REDUCE this Expr */ |
︙ | ︙ | |||
2129 2130 2131 2132 2133 2134 2135 | int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */ int iCacheCnt; /* Counter used to generate aColCache[].lru values */ u8 nColCache; /* Number of entries in the column cache */ u8 iColCache; /* Next entry of the cache to replace */ struct yColCache { int iTable; /* Table cursor number */ int iColumn; /* Table column number */ | < | 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 | int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */ int iCacheCnt; /* Counter used to generate aColCache[].lru values */ u8 nColCache; /* Number of entries in the column cache */ u8 iColCache; /* Next entry of the cache to replace */ struct yColCache { int iTable; /* Table cursor number */ int iColumn; /* Table column number */ u8 tempReg; /* iReg is a temp register that needs to be freed */ int iLevel; /* Nesting level */ int iReg; /* Reg with value of this column. 0 means none. */ int lru; /* Least recently used entry has the smallest value */ } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */ u32 writeMask; /* Start a write transaction on these databases */ u32 cookieMask; /* Bitmask of schema verified databases */ |
︙ | ︙ | |||
2648 2649 2650 2651 2652 2653 2654 | #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *); #endif void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u16); void sqlite3WhereEnd(WhereInfo*); | | | 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 | #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *); #endif void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u16); void sqlite3WhereEnd(WhereInfo*); int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int); void sqlite3ExprCodeMove(Parse*, int, int, int); void sqlite3ExprCodeCopy(Parse*, int, int, int); void sqlite3ExprCacheStore(Parse*, int, int, int); void sqlite3ExprCachePush(Parse*); void sqlite3ExprCachePop(Parse*, int); void sqlite3ExprCacheRemove(Parse*, int); void sqlite3ExprCacheClear(Parse*); |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
3332 3333 3334 3335 3336 3337 3338 | WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE | WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY); if( pSubWInfo ){ if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); int r; r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur, | | | 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 | WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE | WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY); if( pSubWInfo ){ if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); int r; r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur, regRowid); sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, sqlite3VdbeCurrentAddr(v)+2, r, iSet); } sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody); /* The pSubWInfo->untestedTerms flag means that this OR term ** contained one or more AND term from a notReady table. The |
︙ | ︙ |