Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Omit the "x IN (y)" to "x==y" optimization of check-in [e68b427afbc82e20] (and ticket [e39d032577df6942]) as it causes difficult affinity problems as demonstrated by ticket [dbaf8a6820be1ece] and the original assertion fault is no longer a factor due to countless other changes of the previous 5 years. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
7f5168a76a400fc2e1e40c6950470b1b |
User & Date: | drh 2019-08-27 17:01:07 |
Context
2019-08-27
| ||
17:28 | Add ALWAYS() to an always true conditional that results from the previous check-in. Add a test case for ticket [dbaf8a6820be1ece] to supplement those already checked into TH3. (check-in: aff20980 user: drh tags: trunk) | |
17:01 | Omit the "x IN (y)" to "x==y" optimization of check-in [e68b427afbc82e20] (and ticket [e39d032577df6942]) as it causes difficult affinity problems as demonstrated by ticket [dbaf8a6820be1ece] and the original assertion fault is no longer a factor due to countless other changes of the previous 5 years. (check-in: 7f5168a7 user: drh tags: trunk) | |
10:05 | If a TEMP TRIGGER references an auxiliary schema, and that auxiliary schema is detached, move the trigger to reference the TEMP schema before completing the detach, so that the trigger does not hold a dangling schema pointer. Ticket [ac8dd4a32ba4322f] (check-in: 069c2f4c user: drh tags: trunk) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
40 41 42 43 44 45 46 | ** CREATE TABLE t1(a); ** SELECT * FROM t1 WHERE a; ** SELECT a AS b FROM t1 WHERE b; ** SELECT * FROM t1 WHERE (select a from t1); */ char sqlite3ExprAffinity(Expr *pExpr){ int op; | < | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** CREATE TABLE t1(a); ** SELECT * FROM t1 WHERE a; ** SELECT a AS b FROM t1 WHERE b; ** SELECT * FROM t1 WHERE (select a from t1); */ char sqlite3ExprAffinity(Expr *pExpr){ int op; while( ExprHasProperty(pExpr, EP_Skip) ){ assert( pExpr->op==TK_COLLATE ); pExpr = pExpr->pLeft; assert( pExpr!=0 ); } op = pExpr->op; if( op==TK_SELECT ){ |
︙ | ︙ | |||
152 153 154 155 156 157 158 | */ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ sqlite3 *db = pParse->db; CollSeq *pColl = 0; Expr *p = pExpr; while( p ){ int op = p->op; | < | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | */ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ sqlite3 *db = pParse->db; CollSeq *pColl = 0; Expr *p = pExpr; while( p ){ int op = p->op; if( op==TK_REGISTER ) op = p->op2; if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER) && p->y.pTab!=0 ){ /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally ** a TK_COLUMN but was previously evaluated and cached in a register */ int j = p->iColumn; |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
1172 1173 1174 1175 1176 1177 1178 | ** expr1 NOT IN () ** ** simplify to constants 0 (false) and 1 (true), respectively, ** regardless of the value of expr1. */ sqlite3ExprUnmapAndDelete(pParse, A); A = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[N],1); | < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 | ** expr1 NOT IN () ** ** simplify to constants 0 (false) and 1 (true), respectively, ** regardless of the value of expr1. */ sqlite3ExprUnmapAndDelete(pParse, A); A = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[N],1); }else{ A = sqlite3PExpr(pParse, TK_IN, A, 0); if( A ){ A->x.pList = Y; sqlite3ExprSetHeightAndFlags(pParse, A); }else{ sqlite3ExprListDelete(pParse->db, Y); |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
3472 3473 3474 3475 3476 3477 3478 | if( pNew && pSubst->isLeftJoin ){ ExprSetProperty(pNew, EP_CanBeNull); } if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){ pNew->iRightJoinTable = pExpr->iRightJoinTable; ExprSetProperty(pNew, EP_FromJoin); } | < < < | 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 | if( pNew && pSubst->isLeftJoin ){ ExprSetProperty(pNew, EP_CanBeNull); } if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){ pNew->iRightJoinTable = pExpr->iRightJoinTable; ExprSetProperty(pNew, EP_FromJoin); } sqlite3ExprDelete(db, pExpr); pExpr = pNew; } } }else{ if( pExpr->op==TK_IF_NULL_ROW && pExpr->iTable==pSubst->iTable ){ pExpr->iTable = pSubst->iNewTable; |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
2504 2505 2506 2507 2508 2509 2510 | #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 */ | | | 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 | #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 */ /* 0x000200 Available for reuse */ #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 */ |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
5440 5441 5442 5443 5444 5445 5446 | assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext ); assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious ); /* The Next opcode is only used after SeekGT, SeekGE, Rewind, and Found. ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */ assert( pOp->opcode!=OP_Next || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE | | | > | | 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 | assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext ); assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious ); /* The Next opcode is only used after SeekGT, SeekGE, Rewind, and Found. ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */ assert( pOp->opcode!=OP_Next || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found || pC->seekOp==OP_NullRow|| pC->seekOp==OP_SeekRowid || pC->seekOp==OP_IfNoHope); assert( pOp->opcode!=OP_Prev || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE || pC->seekOp==OP_Last || pC->seekOp==OP_IfNoHope || pC->seekOp==OP_NullRow); rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3); next_tail: pC->cacheStatus = CACHE_STALE; VdbeBranchTaken(rc==SQLITE_OK,2); if( rc==SQLITE_OK ){ |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
2513 2514 2515 2516 2517 2518 2519 | ** first such term in use, and sets nIn back to 0 if it is not. */ for(i=0; i<pNew->nLTerm-1; i++){ if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0; } }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ /* "x IN (value, value, ...)" */ nIn = sqlite3LogEst(pExpr->x.pList->nExpr); | < < | 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 | ** first such term in use, and sets nIn back to 0 if it is not. */ for(i=0; i<pNew->nLTerm-1; i++){ if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0; } }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ /* "x IN (value, value, ...)" */ nIn = sqlite3LogEst(pExpr->x.pList->nExpr); } if( pProbe->hasStat1 ){ LogEst M, logK, safetyMargin; /* Let: ** N = the total number of rows in the table ** K = the number of entries on the RHS of the IN operator ** M = the number of rows in the table that match terms to the |
︙ | ︙ |
Changes to test/in4.test.
︙ | ︙ | |||
222 223 224 225 226 227 228 | do_execsql_test in4-3.42 { EXPLAIN SELECT * FROM t3 WHERE x IN (10,11); } {/OpenEphemeral/} do_execsql_test in4-3.43 { SELECT * FROM t3 WHERE x IN (10); } {10 10 10} | > > > | | | | | 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 | do_execsql_test in4-3.42 { EXPLAIN SELECT * FROM t3 WHERE x IN (10,11); } {/OpenEphemeral/} do_execsql_test in4-3.43 { SELECT * FROM t3 WHERE x IN (10); } {10 10 10} # This test would verify that the "X IN (Y)" -> "X==Y" optimization # was working. But we have now taken that optimization out. #do_execsql_test in4-3.44 { # EXPLAIN # SELECT * FROM t3 WHERE x IN (10); #} {~/OpenEphemeral/} do_execsql_test in4-3.45 { SELECT * FROM t3 WHERE x NOT IN (10,11,99999); } {1 1 1} do_execsql_test in4-3.46 { EXPLAIN SELECT * FROM t3 WHERE x NOT IN (10,11,99999); } {/OpenEphemeral/} |
︙ | ︙ | |||
322 323 324 325 326 327 328 | INSERT INTO t6b VALUES(4,44),(5,55),(6,66); SELECT * FROM t6a, t6b WHERE a=3 AND b IN (c); } {3 4 4 44} do_execsql_test in4-6.1-eqp { EXPLAIN QUERY PLAN SELECT * FROM t6a, t6b WHERE a=3 AND b IN (c); | | | 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 | INSERT INTO t6b VALUES(4,44),(5,55),(6,66); SELECT * FROM t6a, t6b WHERE a=3 AND b IN (c); } {3 4 4 44} do_execsql_test in4-6.1-eqp { EXPLAIN QUERY PLAN SELECT * FROM t6a, t6b WHERE a=3 AND b IN (c); } {~/SCAN TABLE t6a/} do_execsql_test in4-6.2 { SELECT * FROM t6a, t6b WHERE a=3 AND c IN (b); } {3 4 4 44} do_execsql_test in4-6.2-eqp { EXPLAIN QUERY PLAN SELECT * FROM t6a, t6b WHERE a=3 AND c IN (b); } {~/SCAN/} finish_test |