Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix some problems with virtual tables and joins in where.c. (CVS 3277) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
3e19a7d8eabcd2fa71ced3f76c5f9bc1 |
User & Date: | danielk1977 2006-06-20 13:07:27.000 |
Context
2006-06-21
| ||
07:02 | Fix a problem with virtual tables and joins. (CVS 3278) (check-in: 643e63e588 user: danielk1977 tags: trunk) | |
2006-06-20
| ||
13:07 | Fix some problems with virtual tables and joins in where.c. (CVS 3277) (check-in: 3e19a7d8ea user: danielk1977 tags: trunk) | |
11:01 | Modifications so that compilation and testing with the various OMIT macros defined works. (CVS 3276) (check-in: c6ea353bd9 user: danielk1977 tags: trunk) | |
Changes
Changes to src/select.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** 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. ** | | | 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. ** ** $Id: select.c,v 1.317 2006/06/20 13:07:27 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** Delete all the content of a Select structure but do not deallocate ** the select structure itself. |
︙ | ︙ | |||
1209 1210 1211 1212 1213 1214 1215 | assert( pFrom->pTab==0 ); pFrom->pTab = pTab = sqlite3LocateTable(pParse,pFrom->zName,pFrom->zDatabase); if( pTab==0 ){ return 1; } pTab->nRef++; | | | | 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 | assert( pFrom->pTab==0 ); pFrom->pTab = pTab = sqlite3LocateTable(pParse,pFrom->zName,pFrom->zDatabase); if( pTab==0 ){ return 1; } pTab->nRef++; #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) if( pTab->pSelect || IsVirtual(pTab) ){ /* We reach here if the named table is a really a view */ if( sqlite3ViewGetColumnNames(pParse, pTab) ){ return 1; } /* If pFrom->pSelect!=0 it means we are dealing with a ** view within a view. The SELECT structure has already been ** copied by the outer view so we can skip the copy step here |
︙ | ︙ |
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.221 2006/06/20 13:07:28 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** The number of bits in a Bitmask. "BMS" means "BitMask Size". */ #define BMS (sizeof(Bitmask)*8) |
︙ | ︙ | |||
1114 1115 1116 1117 1118 1119 1120 | if( pIdxInfo->needToFreeIdxStr ){ sqlite3_free(pIdxInfo->idxStr); } pIdxInfo->idxStr = 0; pIdxInfo->idxNum = 0; pIdxInfo->needToFreeIdxStr = 0; pIdxInfo->orderByConsumed = 0; | | | 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 | if( pIdxInfo->needToFreeIdxStr ){ sqlite3_free(pIdxInfo->idxStr); } pIdxInfo->idxStr = 0; pIdxInfo->idxNum = 0; pIdxInfo->needToFreeIdxStr = 0; pIdxInfo->orderByConsumed = 0; pIdxInfo->estimatedCost = SQLITE_BIG_DBL / 2.0; nOrderBy = pIdxInfo->nOrderBy; if( pIdxInfo->nOrderBy && !orderByUsable ){ *(int*)&pIdxInfo->nOrderBy = 0; } sqlite3SafetyOff(pParse->db); pTab->pVtab->pModule->xBestIndex(pTab->pVtab, pIdxInfo); |
︙ | ︙ | |||
1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 | Index *pBest = 0; /* The best index seen so far */ int bestFlags = 0; /* Flags associated with pBest */ int bestNEq = 0; /* nEq associated with pBest */ double lowestCost; /* Cost of the pBest */ int bestJ = 0; /* The value of j */ Bitmask m; /* Bitmask value for j or bestJ */ int once = 0; /* True when first table is seen */ 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 */ doNotReorder = (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0 || (j>0 && (pTabItem[-1].jointype & (JT_LEFT|JT_CROSS))!=0); if( once && doNotReorder ) break; m = getMask(&maskSet, pTabItem->iCursor); if( (m & notReady)==0 ){ if( j==iFrom ) iFrom++; continue; } assert( pTabItem->pTab ); #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTabItem->pTab) ){ cost = bestVirtualIndex(pParse, &wc, pTabItem, notReady, ppOrderBy ? *ppOrderBy : 0, i==0, | > > | | > > > > > > > > > | 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 | Index *pBest = 0; /* The best index seen so far */ int bestFlags = 0; /* Flags associated with pBest */ int bestNEq = 0; /* nEq associated with pBest */ double lowestCost; /* Cost of the pBest */ int bestJ = 0; /* The value of j */ Bitmask m; /* Bitmask value for j or bestJ */ int once = 0; /* True when first table is seen */ sqlite3_index_info *pBestIndex = 0; sqlite3_index_info *pIndex = 0; 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 */ doNotReorder = (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0 || (j>0 && (pTabItem[-1].jointype & (JT_LEFT|JT_CROSS))!=0); if( once && doNotReorder ) break; m = getMask(&maskSet, pTabItem->iCursor); if( (m & notReady)==0 ){ if( j==iFrom ) iFrom++; continue; } assert( pTabItem->pTab ); #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pTabItem->pTab) ){ cost = bestVirtualIndex(pParse, &wc, pTabItem, notReady, ppOrderBy ? *ppOrderBy : 0, i==0, &pIndex); flags = WHERE_VIRTUALTABLE; if( pIndex && pIndex->orderByConsumed ){ flags = WHERE_VIRTUALTABLE | WHERE_ORDERBY; } pIdx = 0; nEq = 0; }else #endif { cost = bestIndex(pParse, &wc, pTabItem, notReady, (i==0 && ppOrderBy) ? *ppOrderBy : 0, &pIdx, &flags, &nEq); } if( cost<lowestCost ){ once = 1; lowestCost = cost; pBest = pIdx; bestFlags = flags; bestNEq = nEq; bestJ = j; #ifndef SQLITE_OMIT_VIRTUALTABLE sqliteFree(pBestIndex); pBestIndex = pIndex; pIndex = 0; }else{ sqliteFree(pIndex); pIndex = 0; #endif } if( doNotReorder ) break; } TRACE(("*** Optimizer choose table %d for loop %d\n", bestJ, pLevel-pWInfo->a)); if( (bestFlags & WHERE_ORDERBY)!=0 ){ *ppOrderBy = 0; } andFlags &= bestFlags; pLevel->flags = bestFlags; pLevel->pIdx = pBest; pLevel->nEq = bestNEq; pLevel->aInLoop = 0; pLevel->nIn = 0; pLevel->pIdxInfo = pBestIndex; if( pBest ){ pLevel->iIdxCur = pParse->nTab++; }else{ pLevel->iIdxCur = -1; } notReady &= ~getMask(&maskSet, pTabList->a[bestJ].iCursor); pLevel->iFrom = bestJ; |
︙ | ︙ | |||
1895 1896 1897 1898 1899 1900 1901 | #endif /* SQLITE_OMIT_EXPLAIN */ pTabItem = &pTabList->a[pLevel->iFrom]; pTab = pTabItem->pTab; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); if( pTab->isEphem || pTab->pSelect ) continue; #ifndef SQLITE_OMIT_VIRTUALTABLE if( pLevel->pIdxInfo ){ | > | | 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 | #endif /* SQLITE_OMIT_EXPLAIN */ pTabItem = &pTabList->a[pLevel->iFrom]; pTab = pTabItem->pTab; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); if( pTab->isEphem || pTab->pSelect ) continue; #ifndef SQLITE_OMIT_VIRTUALTABLE if( pLevel->pIdxInfo ){ int iCur = pTabItem->iCursor; sqlite3VdbeOp3(v, OP_VOpen, iCur, 0, (const char*)pTab->pVtab, P3_VTAB); }else #endif if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){ sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, OP_OpenRead); if( pTab->nCol<(sizeof(Bitmask)*8) ){ Bitmask b = pTabItem->colUsed; int n = 0; |
︙ | ︙ | |||
1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 | } #ifndef SQLITE_OMIT_VIRTUALTABLE if( pLevel->pIdxInfo ){ /* Case 0: The table is a virtual-table. Use the VFilter and VNext ** to access the data. */ sqlite3_index_info *pIdxInfo = pLevel->pIdxInfo; int nConstraint = pIdxInfo->nConstraint; struct sqlite3_index_constraint_usage *aUsage = pIdxInfo->aConstraintUsage; const struct sqlite3_index_constraint *aConstraint = pIdxInfo->aConstraint; | > | | | | | | | 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 | } #ifndef SQLITE_OMIT_VIRTUALTABLE if( pLevel->pIdxInfo ){ /* Case 0: The table is a virtual-table. Use the VFilter and VNext ** to access the data. */ int ii; sqlite3_index_info *pIdxInfo = pLevel->pIdxInfo; int nConstraint = pIdxInfo->nConstraint; struct sqlite3_index_constraint_usage *aUsage = pIdxInfo->aConstraintUsage; const struct sqlite3_index_constraint *aConstraint = pIdxInfo->aConstraint; for(ii=1; ii<=nConstraint; ii++){ int j; for(j=0; j<nConstraint; j++){ if( aUsage[j].argvIndex==ii ){ int k = aConstraint[j].iTermOffset; sqlite3ExprCode(pParse, wc.a[k].pExpr->pRight); break; } } if( j==nConstraint ) break; } sqlite3VdbeAddOp(v, OP_Integer, ii-1, 0); sqlite3VdbeAddOp(v, OP_Integer, pIdxInfo->idxNum, 0); sqlite3VdbeOp3(v, OP_VFilter, iCur, brk, pIdxInfo->idxStr, pIdxInfo->needToFreeIdxStr ? P3_MPRINTF : P3_STATIC); pIdxInfo->needToFreeIdxStr = 0; for(ii=0; ii<pIdxInfo->nConstraint; ii++){ if( pIdxInfo->aConstraintUsage[ii].omit ){ disableTerm(pLevel, &wc.a[ii]); } } pLevel->op = OP_VNext; pLevel->p1 = iCur; pLevel->p2 = sqlite3VdbeCurrentAddr(v); }else #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
︙ | ︙ |
Changes to test/vtab1.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2006 June 10 # # 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 implements regression tests for SQLite library. The # focus of this file is creating and dropping virtual tables. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2006 June 10 # # 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 implements regression tests for SQLite library. The # focus of this file is creating and dropping virtual tables. # # $Id: vtab1.test,v 1.24 2006/06/20 13:07:28 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !vtab||!schema_pragmas { finish_test return |
︙ | ︙ | |||
200 201 202 203 204 205 206 | do_test vtab1-2.5 { set echo_module "" execsql { DROP TABLE t1; } set echo_module } {xDestroy} | < | 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | do_test vtab1-2.5 { set echo_module "" execsql { DROP TABLE t1; } set echo_module } {xDestroy} do_test vtab1-2.6 { execsql { PRAGMA table_info(t1); } } {} do_test vtab1-2.7 { |
︙ | ︙ | |||
409 410 411 412 413 414 415 416 417 418 419 420 421 422 | } [list xBestIndex {SELECT rowid, * FROM 'treal'} \ xFilter {SELECT rowid, * FROM 'treal'} ] execsql { DROP TABLE t1; DROP TABLE treal; } #---------------------------------------------------------------------- # Test cases vtab1-6 test INSERT, UPDATE and DELETE operations # on virtual tables. do_test vtab1-6-1 { execsql { SELECT sql FROM sqlite_master } } {} | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 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 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 | } [list xBestIndex {SELECT rowid, * FROM 'treal'} \ xFilter {SELECT rowid, * FROM 'treal'} ] execsql { DROP TABLE t1; DROP TABLE treal; } #---------------------------------------------------------------------- # Test cases vtab1-5 test SELECT queries that include joins on virtual # tables. proc filter {log} { set out [list] for {set ii 0} {$ii < [llength $log]} {incr ii} { if {[lindex $log $ii] eq "xFilter"} { lappend out xFilter lappend out [lindex $log [expr $ii+1]] } } return $out } do_test vtab1-5-1 { execsql { CREATE TABLE t1(a, b, c); CREATE TABLE t2(d, e, f); INSERT INTO t1 VALUES(1, 'red', 'green'); INSERT INTO t1 VALUES(2, 'blue', 'black'); INSERT INTO t2 VALUES(1, 'spades', 'clubs'); INSERT INTO t2 VALUES(2, 'hearts', 'diamonds'); CREATE VIRTUAL TABLE et1 USING echo(t1); CREATE VIRTUAL TABLE et2 USING echo(t2); } } {} do_test vtab1-5-2 { set echo_module "" execsql { SELECT * FROM et1, et2; } } [list \ 1 red green 1 spades clubs \ 1 red green 2 hearts diamonds \ 2 blue black 1 spades clubs \ 2 blue black 2 hearts diamonds \ ] do_test vtab1-5-3 { filter $echo_module } [list \ xFilter {SELECT rowid, * FROM 't1'} \ xFilter {SELECT rowid, * FROM 't2'} \ xFilter {SELECT rowid, * FROM 't2'} \ ] do_test vtab1-5-4 { set echo_module "" execsql { SELECT * FROM et1, et2 WHERE et2.d = 2; } } [list \ 1 red green 2 hearts diamonds \ 2 blue black 2 hearts diamonds \ ] do_test vtab1-5-5 { filter $echo_module } [list \ xFilter {SELECT rowid, * FROM 't1'} \ xFilter {SELECT rowid, * FROM 't2'} \ xFilter {SELECT rowid, * FROM 't2'} \ ] do_test vtab1-5-6 { execsql { CREATE INDEX i1 ON t2(d); } db close sqlite3 db test.db register_echo_module [sqlite3_connection_pointer db] set echo_module "" execsql { SELECT * FROM et1, et2 WHERE et2.d = 2; } } [list \ 1 red green 2 hearts diamonds \ 2 blue black 2 hearts diamonds \ ] do_test vtab1-5-7 { filter $echo_module } [list \ xFilter {SELECT rowid, * FROM 't2' WHERE d = ?} \ xFilter {SELECT rowid, * FROM 't1'} \ ] execsql { DROP TABLE t1; DROP TABLE t2; DROP TABLE et1; DROP TABLE et2; } #---------------------------------------------------------------------- # Test cases vtab1-6 test INSERT, UPDATE and DELETE operations # on virtual tables. do_test vtab1-6-1 { execsql { SELECT sql FROM sqlite_master } } {} |
︙ | ︙ |