Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Query optimizer enhancement: In "FROM a,b,c left join d" allow the C table to be reordered with A and B. This used to be the case but the capability was removed by (3203) and (3052) in response to ticket #1652. This change restores the capability. (CVS 3529) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
7393c81b8cb9d4344ae744de9eabcb3a |
User & Date: | drh 2006-12-16 16:25:15.000 |
Context
2006-12-18
| ||
14:12 | Updates to the "Distinctive Features" document. (CVS 3530) (check-in: c734585e1a user: drh tags: trunk) | |
2006-12-16
| ||
16:25 | Query optimizer enhancement: In "FROM a,b,c left join d" allow the C table to be reordered with A and B. This used to be the case but the capability was removed by (3203) and (3052) in response to ticket #1652. This change restores the capability. (CVS 3529) (check-in: 7393c81b8c user: drh tags: trunk) | |
2006-12-14
| ||
01:06 | Fix a bug in lemon that leads to an assertion fault given an invalid grammar. The bug and this fix do not effect on SQLite. Ticket #2107. (CVS 3528) (check-in: f2ad230f6d user: drh tags: trunk) | |
Changes
Changes to src/build.c.
︙ | |||
18 19 20 21 22 23 24 | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | - + | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** |
︙ | |||
2936 2937 2938 2939 2940 2941 2942 | 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 | - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | if( pItem->pSelect ){ sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc); } } } } |
︙ |
Changes to src/expr.c.
︙ | |||
8 9 10 11 12 13 14 | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | - + | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** |
︙ | |||
887 888 889 890 891 892 893 | 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 | + - - - - - + + + + + - - - - - - - - - - - + + + + + + + + + + + | pExpr->iTable = pItem->iCursor; pMatch = pItem; pExpr->pSchema = pTab->pSchema; /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ pExpr->iColumn = j==pTab->iPKey ? -1 : j; pExpr->affinity = pTab->aCol[j].affinity; pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0); if( i<pSrcList->nSrc-1 ){ |
︙ |
Changes to src/parse.y.
︙ | |||
10 11 12 13 14 15 16 | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | - + | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** |
︙ | |||
440 441 442 443 444 445 446 | 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 | - + + + + - + - - - - - - - - - - + - - - - - - - - - - + | %destructor stl_prefix {sqlite3SrcListDelete($$);} %type from {SrcList*} %destructor from {sqlite3SrcListDelete($$);} // A complete FROM clause. // from(A) ::= . {A = sqliteMalloc(sizeof(*A));} |
︙ |
Changes to src/select.c.
︙ | |||
8 9 10 11 12 13 14 | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | - + | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** |
︙ | |||
297 298 299 300 301 302 303 | 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 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 | - - + + - + - - - - + + + + - - + + | Table *pRightTab = pRight->pTab; if( pLeftTab==0 || pRightTab==0 ) continue; /* When the NATURAL keyword is present, add WHERE clause terms for ** every column that the two tables have in common. */ |
︙ | |||
1305 1306 1307 1308 1309 1310 1311 | 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 | - + - + | tableSeen = 1; for(j=0; j<pTab->nCol; j++){ Expr *pExpr, *pRight; char *zName = pTab->aCol[j].zName; if( i>0 ){ struct SrcList_item *pLeft = &pTabList->a[i-1]; |
︙ | |||
2171 2172 2173 2174 2175 2176 2177 | 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 | - + - - + | ** ** If we flatten the above, we would get ** ** (t1 LEFT OUTER JOIN t2) JOIN t3 ** ** which is not at all the same thing. */ |
︙ | |||
2228 2229 2230 2231 2232 2233 2234 | 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 | - + | pSrc->a[i] = pSrc->a[i-extra]; } } for(i=0; i<nSubSrc; i++){ pSrc->a[i+iFrom] = pSubSrc->a[i]; memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); } |
︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | - + | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** |
︙ | |||
1613 1614 1615 1616 1617 1618 1619 | 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 | + + - + | void sqlite3DropTable(Parse*, SrcList*, int, int); void sqlite3DeleteTable(sqlite3*, Table*); void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int); int sqlite3ArrayAllocate(void**,int,int); IdList *sqlite3IdListAppend(IdList*, Token*); int sqlite3IdListIndex(IdList*,const char*); SrcList *sqlite3SrcListAppend(SrcList*, Token*, Token*); SrcList *sqlite3SrcListAppendFromTerm(SrcList*, Token*, Token*, Token*, Select*, Expr*, IdList*); |
︙ |
Changes to src/where.c.
︙ | |||
12 13 14 15 16 17 18 | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | - + | ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. This module is reponsible for ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** |
︙ | |||
1850 1851 1852 1853 1854 1855 1856 | 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 | - + - | int once = 0; /* True when first table is seen */ sqlite3_index_info *pIndex; /* Current virtual index */ lowestCost = SQLITE_BIG_DBL; for(j=iFrom, pTabItem=&pTabList->a[j]; j<pTabList->nSrc; j++, pTabItem++){ int doNotReorder; /* True if this table should not be reordered */ |
︙ | |||
2027 2028 2029 2030 2031 2032 2033 | 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 | - + | brk = pLevel->brk = sqlite3VdbeMakeLabel(v); cont = pLevel->cont = sqlite3VdbeMakeLabel(v); /* If this is the right table of a LEFT OUTER JOIN, allocate and ** initialize a memory cell that records if this table matches any ** row of the left table of the join. */ |
︙ |
Changes to test/where3.test.
︙ | |||
8 9 10 11 12 13 14 | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | - + | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the join reordering optimization # in cases that include a LEFT JOIN. # |
︙ | |||
73 74 75 76 77 78 79 80 81 | 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | SELECT parent1.parent1key, child1.value, child2.value FROM parent1 LEFT OUTER JOIN child1 ON child1.child1key = parent1.child1key INNER JOIN child2 ON child2.child2key = parent1.child2key; } } {1 {Value for C1.1} {Value for C2.1} 2 {} {Value for C2.2} 3 {Value for C1.3} {Value for C2.3}} # This procedure executes the SQL. Then it appends # the ::sqlite_query_plan variable. # proc queryplan {sql} { set ::sqlite_sort_count 0 set data [execsql $sql] return [concat $data $::sqlite_query_plan] } # If you have a from clause of the form: A B C left join D # then make sure the query optimizer is able to reorder the # A B C part anyway it wants. # # Following the fix to ticket #1652, there was a time when # the C table would not reorder. So the following reorderings # were possible: # # A B C left join D # B A C left join D # # But these reorders were not allowed # # C A B left join D # A C B left join D # C B A left join D # B C A left join D # # The following tests are here to verify that the latter four # reorderings are allowed again. # do_test where3-2.1 { execsql { CREATE TABLE tA(apk integer primary key, ax); CREATE TABLE tB(bpk integer primary key, bx); CREATE TABLE tC(cpk integer primary key, cx); CREATE TABLE tD(dpk integer primary key, dx); } queryplan { SELECT * FROM tA, tB, tC LEFT JOIN tD ON dpk=cx WHERE cpk=bx AND bpk=ax } } {tA {} tB * tC * tD *} do_test where3-2.2 { queryplan { SELECT * FROM tA, tB, tC LEFT JOIN tD ON dpk=cx WHERE cpk=bx AND apk=bx } } {tB {} tA * tC * tD *} do_test where3-2.3 { queryplan { SELECT * FROM tA, tB, tC LEFT JOIN tD ON dpk=cx WHERE cpk=bx AND apk=bx } } {tB {} tA * tC * tD *} do_test where3-2.4 { queryplan { SELECT * FROM tA, tB, tC LEFT JOIN tD ON dpk=cx WHERE apk=cx AND bpk=ax } } {tC {} tA * tB * tD *} do_test where3-2.5 { queryplan { SELECT * FROM tA, tB, tC LEFT JOIN tD ON dpk=cx WHERE cpk=ax AND bpk=cx } } {tA {} tC * tB * tD *} do_test where3-2.5 { queryplan { SELECT * FROM tA, tB, tC LEFT JOIN tD ON dpk=cx WHERE bpk=cx AND apk=bx } } {tC {} tB * tA * tD *} do_test where3-2.6 { queryplan { SELECT * FROM tA, tB, tC LEFT JOIN tD ON dpk=cx WHERE cpk=bx AND apk=cx } } {tB {} tC * tA * tD *} finish_test |