Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Do not generate subroutines for non-static SELECT and EXISTS expressions. Fix up some test cases to account for the minor changes in EXPLAIN QUERY PLAN output. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | reuse-subqueries |
Files: | files | file ages | folders |
SHA3-256: |
06de44ec9e173992ca9afb89dd2b4e40 |
User & Date: | drh 2018-12-24 12:09:47.593 |
Context
2018-12-24
| ||
14:30 | Restore a line of code that was previously commented out for debugging. (check-in: e53781f5bd user: drh tags: reuse-subqueries) | |
12:09 | Do not generate subroutines for non-static SELECT and EXISTS expressions. Fix up some test cases to account for the minor changes in EXPLAIN QUERY PLAN output. (check-in: 06de44ec9e user: drh tags: reuse-subqueries) | |
11:55 | Prevent the use of subroutines to implement the RHS of IN operators within CHECK constraints. (check-in: 6b24d3fb94 user: drh tags: reuse-subqueries) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
2861 2862 2863 2864 2865 2866 2867 | SelectDest dest; /* How to deal with SELECT result */ int nReg; /* Registers to allocate */ Expr *pLimit; /* New limit expression */ Vdbe *v = pParse->pVdbe; assert( v!=0 ); | < < < < < < < < < < < < < | > > > > > > > > > > > > > > > | 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 | SelectDest dest; /* How to deal with SELECT result */ int nReg; /* Registers to allocate */ Expr *pLimit; /* New limit expression */ Vdbe *v = pParse->pVdbe; assert( v!=0 ); /* The evaluation of the EXISTS/SELECT must be repeated every time it ** is encountered if any of the following is true: ** ** * The right-hand side is a correlated subquery ** * The right-hand side is an expression list containing variables ** * We are inside a trigger ** ** If all of the above are false, then we can run this code just once ** save the results, and reuse the same result on subsequent invocations. */ if( !ExprHasProperty(pExpr, EP_VarSelect) ){ /* If this routine has already been coded, then invoke it as a ** subroutine. */ if( ExprHasProperty(pExpr, EP_Subrtn) ){ sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn, pExpr->y.sub.iAddr); return pExpr->iTable; } /* Begin coding the subroutine */ ExprSetProperty(pExpr, EP_Subrtn); pExpr->y.sub.regReturn = ++pParse->nMem; pExpr->y.sub.iAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pExpr->y.sub.regReturn) + 1; VdbeComment((v, "return address")); addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } /* For a SELECT, generate code to put the values for all columns of ** the first row into an array of registers and return the index of ** the first register. ** |
︙ | ︙ | |||
2935 2936 2937 2938 2939 2940 2941 | if( sqlite3Select(pParse, pSel, &dest) ){ return 0; } pExpr->iTable = rReg = dest.iSDParm; ExprSetVVAProperty(pExpr, EP_NoReduce); if( addrOnce ){ sqlite3VdbeJumpHere(v, addrOnce); | | < | | | | > | 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 | if( sqlite3Select(pParse, pSel, &dest) ){ return 0; } pExpr->iTable = rReg = dest.iSDParm; ExprSetVVAProperty(pExpr, EP_NoReduce); if( addrOnce ){ sqlite3VdbeJumpHere(v, addrOnce); /* Subroutine return */ sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn); sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1); } return rReg; } #endif /* SQLITE_OMIT_SUBQUERY */ #ifndef SQLITE_OMIT_SUBQUERY /* ** Expr pIn is an IN(...) expression. This function checks that the |
︙ | ︙ |
Changes to test/autoindex1.test.
︙ | ︙ | |||
180 181 182 183 184 185 186 | } do_eqp_test autoindex1-500.1 { SELECT b FROM t501 WHERE t501.a IN (SELECT x FROM t502 WHERE y=?); } { QUERY PLAN |--SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?) | | | | | 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | } do_eqp_test autoindex1-500.1 { SELECT b FROM t501 WHERE t501.a IN (SELECT x FROM t502 WHERE y=?); } { QUERY PLAN |--SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?) `--LIST SUBQUERY xxxxxx `--SCAN TABLE t502 } do_eqp_test autoindex1-501 { SELECT b FROM t501 WHERE t501.a IN (SELECT x FROM t502 WHERE y=t501.b); } { QUERY PLAN |--SCAN TABLE t501 `--CORRELATED LIST SUBQUERY xxxxxx `--SEARCH TABLE t502 USING AUTOMATIC COVERING INDEX (y=?) } do_eqp_test autoindex1-502 { SELECT b FROM t501 WHERE t501.a=123 AND t501.a IN (SELECT x FROM t502 WHERE y=t501.b); } { QUERY PLAN |--SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?) `--CORRELATED LIST SUBQUERY xxxxxx `--SCAN TABLE t502 } # The following code checks a performance regression reported on the # mailing list on 2010-10-19. The problem is that the nRowEst field # of ephermeral tables was not being initialized correctly and so no # automatic index was being created for the emphemeral table when it was |
︙ | ︙ |
Changes to test/eqp.test.
︙ | ︙ | |||
282 283 284 285 286 287 288 | } det 3.3.1 { SELECT * FROM t1 WHERE y IN (SELECT y FROM t2) } { QUERY PLAN |--SCAN TABLE t1 | | | | 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 | } det 3.3.1 { SELECT * FROM t1 WHERE y IN (SELECT y FROM t2) } { QUERY PLAN |--SCAN TABLE t1 `--LIST SUBQUERY xxxxxx `--SCAN TABLE t2 } det 3.3.2 { SELECT * FROM t1 WHERE y IN (SELECT y FROM t2 WHERE t1.x!=t2.x) } { QUERY PLAN |--SCAN TABLE t1 `--CORRELATED LIST SUBQUERY xxxxxx `--SCAN TABLE t2 } det 3.3.3 { SELECT * FROM t1 WHERE EXISTS (SELECT y FROM t2 WHERE t1.x!=t2.x) } { QUERY PLAN |--SCAN TABLE t1 |
︙ | ︙ |
Changes to test/rowvalue4.test.
︙ | ︙ | |||
231 232 233 234 235 236 237 | do_eqp_test 5.1 { SELECT * FROM d2 WHERE (a, b) IN (SELECT x, y FROM d1) AND (c) IN (SELECT y FROM d1) } { QUERY PLAN |--SEARCH TABLE d2 USING INDEX d2ab (a=? AND b=?) | | | | 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | do_eqp_test 5.1 { SELECT * FROM d2 WHERE (a, b) IN (SELECT x, y FROM d1) AND (c) IN (SELECT y FROM d1) } { QUERY PLAN |--SEARCH TABLE d2 USING INDEX d2ab (a=? AND b=?) |--LIST SUBQUERY xxxxxx | `--SCAN TABLE d1 `--LIST SUBQUERY xxxxxx `--SCAN TABLE d1 } do_execsql_test 6.0 { CREATE TABLE e1(a, b, c, d, e); CREATE INDEX e1ab ON e1(a, b); CREATE INDEX e1cde ON e1(c, d, e); |
︙ | ︙ |