Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | In the query optimizer, make sure table dependencies from all terms of a compound SELECT statement are recognized so that subqueries in a WHERE clause are not evaluated too early. Fix for ticket #2640. (CVS 4422) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
9c9c2a1da2b6235b3b0541d1f55a02a1 |
User & Date: | drh 2007-09-12 15:41:01.000 |
Context
2007-09-12
| ||
17:01 | Fixes for compilation/testing when the various OMIT macros are defined. (CVS 4423) (check-in: c8405b15c0 user: danielk1977 tags: trunk) | |
15:41 | In the query optimizer, make sure table dependencies from all terms of a compound SELECT statement are recognized so that subqueries in a WHERE clause are not evaluated too early. Fix for ticket #2640. (CVS 4422) (check-in: 9c9c2a1da2 user: drh tags: trunk) | |
14:09 | Add a missing semi-colon to os_win.c. Ticket #2642. (CVS 4421) (check-in: c6ee5929e7 user: danielk1977 tags: trunk) | |
Changes
Changes to src/where.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** 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". ** | | | 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". ** ** $Id: where.c,v 1.260 2007/09/12 15:41:01 drh Exp $ */ #include "sqliteInt.h" /* ** The number of bits in a Bitmask. "BMS" means "BitMask Size". */ #define BMS (sizeof(Bitmask)*8) |
︙ | ︙ | |||
346 347 348 349 350 351 352 | for(i=0; i<pList->nExpr; i++){ mask |= exprTableUsage(pMaskSet, pList->a[i].pExpr); } } return mask; } static Bitmask exprSelectTableUsage(ExprMaskSet *pMaskSet, Select *pS){ | | | < < | > | 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 | for(i=0; i<pList->nExpr; i++){ mask |= exprTableUsage(pMaskSet, pList->a[i].pExpr); } } return mask; } static Bitmask exprSelectTableUsage(ExprMaskSet *pMaskSet, Select *pS){ Bitmask mask = 0; while( pS ){ mask |= exprListTableUsage(pMaskSet, pS->pEList); mask |= exprListTableUsage(pMaskSet, pS->pGroupBy); mask |= exprListTableUsage(pMaskSet, pS->pOrderBy); mask |= exprTableUsage(pMaskSet, pS->pWhere); mask |= exprTableUsage(pMaskSet, pS->pHaving); pS = pS->pPrior; } return mask; } /* ** Return TRUE if the given operator is one of the operators that is ** allowed for an indexable WHERE clause term. The allowed operators are |
︙ | ︙ |
Added test/tkt2640.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 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 | # 2007 Sep 12 # # 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. # #*********************************************************************** # # This file is to test that ticket #2640 has been fixed. # # $Id: tkt2640.test,v 1.1 2007/09/12 15:41:01 drh Exp $ # # The problem in ticket #2640 was that the query optimizer was # not recognizing all uses of tables within subqueries in the # WHERE clause. If the subquery contained a compound SELECT, # then tables that were used by terms of the compound other than # the last term would not be recognized as dependencies. # So if one of the SELECT statements within a compound made # use of a table that occurs later in a join, the query # optimizer would not recognize this and would try to evaluate # the subquery too early, before that tables value had been # established. set testdir [file dirname $argv0] source $testdir/tester.tcl do_test tkt2640-1.1 { execsql { CREATE TABLE persons(person_id, name); INSERT INTO persons VALUES(1,'fred'); INSERT INTO persons VALUES(2,'barney'); INSERT INTO persons VALUES(3,'wilma'); INSERT INTO persons VALUES(4,'pebbles'); INSERT INTO persons VALUES(5,'bambam'); CREATE TABLE directors(person_id); INSERT INTO directors VALUES(5); INSERT INTO directors VALUES(3); CREATE TABLE writers(person_id); INSERT INTO writers VALUES(2); INSERT INTO writers VALUES(3); INSERT INTO writers VALUES(4); SELECT DISTINCT p.name FROM persons p, directors d WHERE d.person_id=p.person_id AND NOT EXISTS ( SELECT person_id FROM directors d1 WHERE d1.person_id=p.person_id EXCEPT SELECT person_id FROM writers w ); } } {wilma} do_test tkt2640-1.2 { execsql { SELECT DISTINCT p.name FROM persons p CROSS JOIN directors d WHERE d.person_id=p.person_id AND NOT EXISTS ( SELECT person_id FROM directors d1 WHERE d1.person_id=p.person_id EXCEPT SELECT person_id FROM writers w ); } } {wilma} do_test tkt2640-1.3 { execsql { SELECT DISTINCT p.name FROM directors d CROSS JOIN persons p WHERE d.person_id=p.person_id AND NOT EXISTS ( SELECT person_id FROM directors d1 WHERE d1.person_id=p.person_id EXCEPT SELECT person_id FROM writers w ); } } {wilma} do_test tkt2640-1.4 { execsql { SELECT DISTINCT p.name FROM persons p, directors d WHERE d.person_id=p.person_id AND NOT EXISTS ( SELECT person_id FROM directors d1 WHERE d1.person_id=d.person_id EXCEPT SELECT person_id FROM writers w ); } } {wilma} do_test tkt2640-1.5 { execsql { SELECT DISTINCT p.name FROM persons p CROSS JOIN directors d WHERE d.person_id=p.person_id AND NOT EXISTS ( SELECT person_id FROM directors d1 WHERE d1.person_id=d.person_id EXCEPT SELECT person_id FROM writers w ); } } {wilma} do_test tkt2640-1.6 { execsql { SELECT DISTINCT p.name FROM directors d CROSS JOIN persons p WHERE d.person_id=p.person_id AND NOT EXISTS ( SELECT person_id FROM directors d1 WHERE d1.person_id=d.person_id EXCEPT SELECT person_id FROM writers w ); } } {wilma} finish_test |