Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Just because a CTE is used more than once, does not mean it should be tagged with M10d_Yes and thereby prohibited from participating in the query flattening optimization. See forum thread 1d571c02963. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
66f29c403d28630bfaea9124bd63ee4a |
User & Date: | drh 2023-02-01 15:41:07 |
Context
2023-02-01
| ||
20:45 | New assert() statements to verify that sqlite3DeleteIndexSamples() is always called with non-NULL parameters. (check-in: 92c71fdd user: drh tags: trunk) | |
20:14 | Update testrunner.tcl to use a separate process for each test script. And to run some extra tests too. (check-in: d090948a user: dan tags: testrunner) | |
15:41 | Just because a CTE is used more than once, does not mean it should be tagged with M10d_Yes and thereby prohibited from participating in the query flattening optimization. See forum thread 1d571c02963. (check-in: 66f29c40 user: drh tags: trunk) | |
14:17 | Fix a comment related to PENDING locks in os_unix.c. No code changes. (check-in: 6b3546c8 user: dan tags: trunk) | |
Changes
Changes to src/select.c.
︙ | ︙ | |||
5622 5623 5624 5625 5626 5627 5628 | if( pFrom->fg.isIndexedBy ){ sqlite3ErrorMsg(pParse, "no such index: \"%s\"", pFrom->u1.zIndexedBy); return 2; } pFrom->fg.isCte = 1; pFrom->u2.pCteUse = pCteUse; pCteUse->nUse++; | < < < | 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 | if( pFrom->fg.isIndexedBy ){ sqlite3ErrorMsg(pParse, "no such index: \"%s\"", pFrom->u1.zIndexedBy); return 2; } pFrom->fg.isCte = 1; pFrom->u2.pCteUse = pCteUse; pCteUse->nUse++; /* Check if this is a recursive CTE. */ pRecTerm = pSel = pFrom->pSelect; bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION ); while( bMayRecursive && pRecTerm->op==pSel->op ){ int i; SrcList *pSrc = pRecTerm->pSrc; |
︙ | ︙ | |||
6907 6908 6909 6910 6911 6912 6913 | ** requires it to be the outer loop ** (c) All of the following are true: ** (i) The subquery is the left-most subquery in the FROM clause ** (ii) There is nothing that would prevent the subquery from ** being used as the outer loop if the sqlite3WhereBegin() ** routine nominates it to that position. ** (iii) The query is not a UPDATE ... FROM | | | > > | > > > > | | | 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 | ** requires it to be the outer loop ** (c) All of the following are true: ** (i) The subquery is the left-most subquery in the FROM clause ** (ii) There is nothing that would prevent the subquery from ** being used as the outer loop if the sqlite3WhereBegin() ** routine nominates it to that position. ** (iii) The query is not a UPDATE ... FROM ** (2) The subquery is not a CTE that should be materialized because ** (a) the AS MATERIALIZED keyword is used, or ** (b) the CTE is used multiple times and does not have the ** NOT MATERIALIZED keyword ** (3) The subquery is not part of a left operand for a RIGHT JOIN ** (4) The SQLITE_Coroutine optimization disable flag is not set ** (5) The subquery is not self-joined */ static int fromClauseTermCanBeCoroutine( Parse *pParse, /* Parsing context */ SrcList *pTabList, /* FROM clause */ int i, /* Which term of the FROM clause holds the subquery */ int selFlags /* Flags on the SELECT statement */ ){ SrcItem *pItem = &pTabList->a[i]; if( pItem->fg.isCte ){ const CteUse *pCteUse = pItem->u2.pCteUse; if( pCteUse->eM10d==M10d_Yes ) return 0; /* (2a) */ if( pCteUse->nUse>=2 && pCteUse->eM10d!=M10d_No ) return 0; /* (2b) */ } if( pTabList->a[0].fg.jointype & JT_LTORJ ) return 0; /* (3) */ if( OptimizationDisabled(pParse->db, SQLITE_Coroutines) ) return 0; /* (4) */ if( isSelfJoinView(pTabList, pItem, i+1, pTabList->nSrc)!=0 ){ return 0; /* (5) */ } if( i==0 ){ if( pTabList->nSrc==1 ) return 1; /* (1a) */ if( pTabList->a[1].fg.jointype & JT_CROSS ) return 1; /* (1b) */ if( selFlags & SF_UpdateFrom ) return 0; /* (1c-iii) */ |
︙ | ︙ |
Changes to test/with6.test.
︙ | ︙ | |||
313 314 315 316 317 318 319 320 321 322 | } { QUERY PLAN |--SCAN t2 |--SCAN t3 LEFT-JOIN `--RIGHT-JOIN t3 `--SCAN t3 } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 | } { QUERY PLAN |--SCAN t2 |--SCAN t3 LEFT-JOIN `--RIGHT-JOIN t3 `--SCAN t3 } # 2023-02-01 # https://sqlite.org/forum/forumpost/1d571c02963355ed # # Just because a CTE is used more than once, does not mean it should be # marked with M10d_Yes and hence prohibited from participating in the # query flattening optimization. # reset_db db eval { CREATE TABLE raw(country,date,total,delta, UNIQUE(country,date)); } do_eqp_test 400 { with recursive init(country, date, fin) AS (SELECT country, min(date), max(date) FROM raw WHERE total > 0 GROUP BY country), src(country, date) AS (SELECT raw.country, raw.date FROM raw JOIN init i on raw.country = i.country AND raw.date > i.date ORDER BY raw.country, raw.date), vals(country, date, x, y) AS (SELECT src.country, src.date, julianday(raw.date) - julianday(src.date), log(delta+1) FROM src JOIN raw on raw.country = src.country AND raw.date > date(src.date,'-7 days') AND raw.date <= src.date AND delta >= 0), sums(country, date, x2, x, n, xy, y) AS (SELECT country, date, sum(x*x*1.0), sum(x*1.0), sum(1.0), sum(x*y*1.0), sum(y*1.0) FROM vals GROUP BY 1, 2), mult(country, date, m) AS (SELECT country, date, 1.0/(x2 * n - x * x) FROM sums), inv(country, date, a,b,c,d) AS (SELECT mult.country, mult.date, n * m, -x * m, -x * m, x2 * m FROM mult JOIN sums on sums.country=mult.country AND mult.date=sums.date), fit(country, date, a, b) AS (SELECT inv.country, inv.date, a * xy + b * y, c * xy + d * y FROM inv JOIN mult on mult.country = inv.country AND mult.date = inv.date JOIN sums on sums.country = mult.country AND sums.date = mult.date ) SELECT *, nFin/nPrev - 1 AS growth, log(2)/log(nFin/nPrev) AS doubling FROM (SELECT f.*, exp(b) - 1 AS nFin, exp(a* (-1) + b) - 1 AS nPrev FROM fit f JOIN init i on i.country = f.country AND f.date <= date(i.fin,'-3 days')) WHERE nPrev > 0 AND nFin > 0; } { QUERY PLAN |--MATERIALIZE sums | |--MATERIALIZE src | | |--MATERIALIZE init | | | `--SCAN raw USING INDEX sqlite_autoindex_raw_1 | | |--SCAN i | | |--SEARCH raw USING COVERING INDEX sqlite_autoindex_raw_1 (country=? AND date>?) | | `--USE TEMP B-TREE FOR ORDER BY | |--SCAN src | |--SEARCH raw USING INDEX sqlite_autoindex_raw_1 (country=? AND date>? AND date<?) | `--USE TEMP B-TREE FOR GROUP BY |--SCAN sums |--SEARCH sums USING AUTOMATIC COVERING INDEX (country=? AND date=?) |--SEARCH sums USING AUTOMATIC COVERING INDEX (country=? AND date=?) |--SEARCH sums USING AUTOMATIC COVERING INDEX (country=? AND date=?) `--SEARCH i USING AUTOMATIC COVERING INDEX (country=?) } finish_test |