Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix for the problem identified in forum post 0cd8e058bf: When evaluating an multi-index OR, do not push down auxiliary WHERE clause terms that involve subqueries into the OR-subqueries. Otherwise, the covering-index optimizer might convert table-references into index-references for the particular OR index that is active for the branch in which the subquery subroutine is coded, and those index-references will not work if the subquery subroutine is invoked from a different OR branch that uses a different index. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
61a1c6dbd089979cbeb8b0c0c5ee1ab1 |
User & Date: | drh 2022-03-03 15:59:22 |
Context
2022-03-05
| ||
19:39 | Cherry-pick all bug fix changes since the 3.38.0 release. (check-in: 45a5d5ac user: drh tags: branch-3.38) | |
2022-03-03
| ||
16:48 | Make sure the xParseCell and xCellSize methods of the MemPage object are initialized consistently even if the page is detected as being corrupt. dbsqlfuzz fd21f341f3b4f582401d2feb2a1c0c4cc2c26caa. (check-in: 725a0643 user: drh tags: trunk) | |
15:59 | Fix for the problem identified in forum post 0cd8e058bf: When evaluating an multi-index OR, do not push down auxiliary WHERE clause terms that involve subqueries into the OR-subqueries. Otherwise, the covering-index optimizer might convert table-references into index-references for the particular OR index that is active for the branch in which the subquery subroutine is coded, and those index-references will not work if the subquery subroutine is invoked from a different OR branch that uses a different index. (check-in: 61a1c6db user: drh tags: trunk) | |
15:00 | Add the new OP_BeginSubrtn opcode (which is really an alias for OP_Integer) and make other changes so that the span of a subroutine that implements a subquery is more readily apparent in bytecode listings. (check-in: b8226748 user: drh tags: trunk) | |
Changes
Changes to src/wherecode.c.
︙ | ︙ | |||
2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 | ** See ticket http://www.sqlite.org/src/info/f2369304e4 ** ** 2022-02-04: Do not push down slices of a row-value comparison. ** In other words, "w" or "y" may not be a slice of a vector. Otherwise, ** the initialization of the right-hand operand of the vector comparison ** might not occur, or might occur only in an OR branch that is not ** taken. dbsqlfuzz 80a9fade844b4fb43564efc972bcb2c68270f5d1. */ if( pWC->nTerm>1 ){ int iTerm; for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ Expr *pExpr = pWC->a[iTerm].pExpr; if( &pWC->a[iTerm] == pTerm ) continue; testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); testcase( pWC->a[iTerm].wtFlags & TERM_CODED ); testcase( pWC->a[iTerm].wtFlags & TERM_SLICE ); if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED|TERM_SLICE))!=0 ){ continue; } | > > > > > > > > | | | 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 | ** See ticket http://www.sqlite.org/src/info/f2369304e4 ** ** 2022-02-04: Do not push down slices of a row-value comparison. ** In other words, "w" or "y" may not be a slice of a vector. Otherwise, ** the initialization of the right-hand operand of the vector comparison ** might not occur, or might occur only in an OR branch that is not ** taken. dbsqlfuzz 80a9fade844b4fb43564efc972bcb2c68270f5d1. ** ** 2022-03-03: Do not push down expressions that involve subqueries. ** The subquery might get coded as a subroutine. Any table-references ** in the subquery might be resolved to index-references for the index on ** the OR branch in which the subroutine is coded. But if the subroutine ** is invoked from a different OR branch that uses a different index, such ** index-references will not work. tag-20220303a ** https://sqlite.org/forum/forumpost/36937b197273d403 */ if( pWC->nTerm>1 ){ int iTerm; for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ Expr *pExpr = pWC->a[iTerm].pExpr; if( &pWC->a[iTerm] == pTerm ) continue; testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); testcase( pWC->a[iTerm].wtFlags & TERM_CODED ); testcase( pWC->a[iTerm].wtFlags & TERM_SLICE ); if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED|TERM_SLICE))!=0 ){ continue; } if( (pWC->a[iTerm].eOperator & WO_SINGLE)==0 ) continue; if( ExprHasProperty(pExpr, EP_Subquery) ) continue; /* tag-20220303a */ pExpr = sqlite3ExprDup(db, pExpr, 0); pAndExpr = sqlite3ExprAnd(pParse, pAndExpr, pExpr); } if( pAndExpr ){ /* The extra 0x10000 bit on the opcode is masked off and does not ** become part of the new Expr.op. However, it does make the ** op==TK_AND comparison inside of sqlite3PExpr() false, and this |
︙ | ︙ |
Changes to test/where7.test.
︙ | ︙ | |||
23356 23357 23358 23359 23360 23361 23362 23363 23364 | | |--INDEX 1 | | `--SEARCH t301 USING COVERING INDEX t301_c4 (c4=?) | `--INDEX 2 | `--SEARCH t301 USING INTEGER PRIMARY KEY (rowid=?) |--SEARCH t302 USING INDEX t302_c8_c3 (c8=? AND c3>?) `--USE TEMP B-TREE FOR ORDER BY } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > | 23356 23357 23358 23359 23360 23361 23362 23363 23364 23365 23366 23367 23368 23369 23370 23371 23372 23373 23374 23375 23376 23377 23378 23379 23380 23381 23382 23383 23384 23385 23386 23387 23388 | | |--INDEX 1 | | `--SEARCH t301 USING COVERING INDEX t301_c4 (c4=?) | `--INDEX 2 | `--SEARCH t301 USING INTEGER PRIMARY KEY (rowid=?) |--SEARCH t302 USING INDEX t302_c8_c3 (c8=? AND c3>?) `--USE TEMP B-TREE FOR ORDER BY } # 2022-03-03 https://sqlite.org/forum/forumpost/36937b197273d403 # # In the multi-index OR, if there is an auxiliary WHERE clause term # that includes a subquery and that subquery is pushed down into the # OR-clause subqueries, WHERE subquery might get coded as a subroutine. # In that case, the covering-index optimizer will attempt to change # table-references into index-references. But it will do so for the # index of the OR branch in which the subquery is coded. If the # subquery subroutine is called from a different OR branch, the # index might be different and the index-reference will no longer # work. tag-20220303a # reset_db do_execsql_test 4.1 { CREATE TABLE t0(w); INSERT INTO t0(w) VALUES(1); CREATE TABLE t1(x INT, y INT PRIMARY KEY, z); INSERT INTO t1 VALUES(0,111,222); CREATE INDEX t1zxy ON t1(z,x,y); SELECT y FROM t1 WHERE (z=222 OR y=111) AND (false OR EXISTS(SELECT 1 FROM t0 WHERE t1.y)); } {111} finish_test |