Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Continue refactoring name resolution. Fix for ticket #1047. (CVS 2230) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
88d4834fec7583a9b6400a1ce5b928c1 |
User & Date: | drh 2005-01-18 14:45:48.000 |
Context
2005-01-18
| ||
16:02 | Column names coming back from a SELECT are now just the name of the source column without the "table." prefix. In other words, "PRAGMA short_column_names=ON" is now the default. This makes the names of columns behave more like other SQL engines. The old behavior can be restored by setting "PRAGMA short_column_names=OFF". (CVS 2231) (check-in: 9295050af1 user: drh tags: trunk) | |
14:45 | Continue refactoring name resolution. Fix for ticket #1047. (CVS 2230) (check-in: 88d4834fec user: drh tags: trunk) | |
04:00 | Refinements to the name resolution logic. Change the name of the keywordhash.c file to keywordhash.h. (CVS 2229) (check-in: 0142ae6f00 user: drh tags: trunk) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** | | | 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 ** ** $Id: build.c,v 1.294 2005/01/18 14:45:48 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. |
︙ | ︙ | |||
1574 1575 1576 1577 1578 1579 1580 | #ifndef SQLITE_OMIT_VIEW /* ** The Table structure pTable is really a VIEW. Fill in the names of ** the columns of the view in the pTable structure. Return the number ** of errors. If an error is seen leave an error message in pParse->zErrMsg. */ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ | | | < | > | 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 | #ifndef SQLITE_OMIT_VIEW /* ** The Table structure pTable is really a VIEW. Fill in the names of ** the columns of the view in the pTable structure. Return the number ** of errors. If an error is seen leave an error message in pParse->zErrMsg. */ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ Table *pSelTab; /* A fake table from which we get the result set */ Select *pSel; /* Copy of the SELECT that implements the view */ int nErr = 0; /* Number of errors encountered */ int n; /* Temporarily holds the number of cursors assigned */ assert( pTable ); /* A positive nCol means the columns names for this view are ** already known. */ if( pTable->nCol>0 ) return 0; |
︙ | ︙ | |||
1602 1603 1604 1605 1606 1607 1608 | */ if( pTable->nCol<0 ){ sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName); return 1; } /* If we get this far, it means we need to compute the table names. | < < < < | | < > > | | | | | < < > | < < | 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 | */ if( pTable->nCol<0 ){ sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName); return 1; } /* If we get this far, it means we need to compute the table names. ** Note that the call to sqlite3ResultSetOfSelect() will expand any ** "*" elements in the results set of the view and will assign cursors ** to the elements of the FROM clause. But we do not want these changes ** to be permanent. So the computation is done on a copy of the SELECT ** statement that defines the view. */ assert( pTable->pSelect ); pSel = sqlite3SelectDup(pTable->pSelect); n = pParse->nTab; sqlite3SrcListAssignCursors(pParse, pSel->pSrc); pTable->nCol = -1; pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel); pParse->nTab = n; if( pSelTab ){ assert( pTable->aCol==0 ); pTable->nCol = pSelTab->nCol; pTable->aCol = pSelTab->aCol; pSelTab->nCol = 0; pSelTab->aCol = 0; sqlite3DeleteTable(0, pSelTab); DbSetProperty(pParse->db, pTable->iDb, DB_UnresetViews); }else{ pTable->nCol = 0; nErr++; } sqlite3SelectDelete(pSel); return nErr; } #endif /* SQLITE_OMIT_VIEW */ #ifndef SQLITE_OMIT_VIEW /* ** Clear the column names from every VIEW in database idx. |
︙ | ︙ | |||
2580 2581 2582 2583 2584 2585 2586 | } /* ** Assign cursors to all tables in a SrcList */ void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ int i; | > | | | > > | 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 | } /* ** Assign cursors to all tables in a SrcList */ void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ int i; struct SrcList_item *pItem; for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){ if( pItem->iCursor>=0 ) break; pItem->iCursor = pParse->nTab++; if( pItem->pSelect ){ sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc); } } } /* ** Add an alias to the last identifier on the given identifier list. */ |
︙ | ︙ |
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.225 2005/01/18 14:45:48 drh Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. |
︙ | ︙ | |||
650 651 652 653 654 655 656 657 658 659 660 661 662 663 | ** The declaration type for a ROWID field is INTEGER. */ static const char *columnType(Parse *pParse, SrcList *pTabList, Expr *pExpr){ char const *zType; int j; if( pExpr==0 || pTabList==0 ) return 0; switch( pExpr->op ){ case TK_COLUMN: { Table *pTab; int iCol = pExpr->iColumn; for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable; j++){} assert( j<pTabList->nSrc ); pTab = pTabList->a[j].pTab; | > | 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 | ** The declaration type for a ROWID field is INTEGER. */ static const char *columnType(Parse *pParse, SrcList *pTabList, Expr *pExpr){ char const *zType; int j; if( pExpr==0 || pTabList==0 ) return 0; sqlite3ExprResolveNames(pParse, pTabList, 0, pExpr, 1, 0); switch( pExpr->op ){ case TK_COLUMN: { Table *pTab; int iCol = pExpr->iColumn; for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable; j++){} assert( j<pTabList->nSrc ); pTab = pTabList->a[j].pTab; |
︙ | ︙ | |||
799 800 801 802 803 804 805 | } return z; } /* ** Forward declaration */ | | | | 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 | } return z; } /* ** Forward declaration */ static int prepSelectStmt(Parse*, Select*); /* ** Given a SELECT statement, generate a Table structure that describes ** the result set of that SELECT. */ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ Table *pTab; int i, j; ExprList *pEList; Column *aCol, *pCol; if( prepSelectStmt(pParse, pSelect) ){ return 0; } pTab = sqliteMalloc( sizeof(Table) ); if( pTab==0 ){ return 0; } pTab->zName = zTabName ? sqliteStrDup(zTabName) : 0; |
︙ | ︙ | |||
866 867 868 869 870 871 872 | } } pTab->iPKey = -1; return pTab; } /* | | > > > > | | | | | > > > > > | > > | | > > | 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 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 918 919 920 921 922 923 924 925 926 927 928 929 930 | } } pTab->iPKey = -1; return pTab; } /* ** Prepare a SELECT statement for processing by doing the following ** things: ** ** (1) Make sure VDBE cursor numbers have been assigned to every ** element of the FROM clause. ** ** (2) Fill in the pTabList->a[].pTab fields in the SrcList that ** defines FROM clause. When views appear in the FROM clause, ** fill pTabList->a[].pSelect with a copy of the SELECT statement ** that implements the view. A copy is made of the view's SELECT ** statement so that we can freely modify or delete that statement ** without worrying about messing up the presistent representation ** of the view. ** ** (3) Add terms to the WHERE clause to accomodate the NATURAL keyword ** on joins and the ON and USING clause of joins. ** ** (4) Scan the list of columns in the result set (pEList) looking ** for instances of the "*" operator or the TABLE.* operator. ** If found, expand each "*" to be every column in every table ** and TABLE.* to be every column in TABLE. ** ** Return 0 on success. If there are problems, leave an error message ** in pParse and return non-zero. */ static int prepSelectStmt(Parse *pParse, Select *p){ int i, j, k, rc; SrcList *pTabList; ExprList *pEList; Table *pTab; struct SrcList_item *pFrom; if( p==0 || p->pSrc==0 ) return 1; pTabList = p->pSrc; pEList = p->pEList; /* Make sure cursor numbers have been assigned to all entries in ** the FROM clause of the SELECT statement. */ sqlite3SrcListAssignCursors(pParse, p->pSrc); /* Look up every table named in the FROM clause of the select. If ** an entry of the FROM clause is a subquery instead of a table or view, ** then create a transient table structure to describe the subquery. */ for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ if( pFrom->pTab!=0 ){ /* This statement has already been prepared. There is no need ** to go further. */ assert( i==0 ); return 0; } if( pFrom->zName==0 ){ /* A sub-query in the FROM clause of a SELECT */ assert( pFrom->pSelect!=0 ); if( pFrom->zAlias==0 ){ pFrom->zAlias = |
︙ | ︙ | |||
1121 1122 1123 1124 1125 1126 1127 | int i, j; ExprList *pEList; if( pSelect==0 || pOrderBy==0 ) return 1; if( mustComplete ){ for(i=0; i<pOrderBy->nExpr; i++){ pOrderBy->a[i].done = 0; } } | | | 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 | int i, j; ExprList *pEList; if( pSelect==0 || pOrderBy==0 ) return 1; if( mustComplete ){ for(i=0; i<pOrderBy->nExpr; i++){ pOrderBy->a[i].done = 0; } } if( prepSelectStmt(pParse, pSelect) ){ return 1; } if( pSelect->pPrior ){ if( matchOrderbyToColumn(pParse, pSelect->pPrior, pOrderBy, iTable, 0) ){ return 1; } } |
︙ | ︙ | |||
1259 1260 1261 1262 1263 1264 1265 | KeyInfo *pKeyInfo; int nColumn; sqlite3 *db = pParse->db; int i; Vdbe *v = pParse->pVdbe; int addr; | | | 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 | KeyInfo *pKeyInfo; int nColumn; sqlite3 *db = pParse->db; int i; Vdbe *v = pParse->pVdbe; int addr; if( prepSelectStmt(pParse, p) ){ return 0; } nColumn = p->pEList->nExpr; pKeyInfo = sqliteMalloc( sizeof(*pKeyInfo)+nColumn*sizeof(CollSeq*) ); if( pKeyInfo==0 ) return 0; pKeyInfo->enc = db->enc; pKeyInfo->nField = nColumn; |
︙ | ︙ | |||
2303 2304 2305 2306 2307 2308 2309 | pTabList = p->pSrc; pWhere = p->pWhere; pOrderBy = p->pOrderBy; pGroupBy = p->pGroupBy; pHaving = p->pHaving; isDistinct = p->isDistinct; | < < < < < < < < | | 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 | pTabList = p->pSrc; pWhere = p->pWhere; pOrderBy = p->pOrderBy; pGroupBy = p->pGroupBy; pHaving = p->pHaving; isDistinct = p->isDistinct; /* ** Do not even attempt to generate any code if we have already seen ** errors before this routine starts. */ if( pParse->nErr>0 ) goto select_end; if( prepSelectStmt(pParse, p) ){ goto select_end; } pWhere = p->pWhere; pEList = p->pEList; if( pEList==0 ) goto select_end; /* If writing to memory or generating a set |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 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. ** | | | 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. ** ** @(#) $Id: sqliteInt.h,v 1.356 2005/01/18 14:45:48 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** These #defines should enable >2GB file support on Posix if the ** underlying operating system supports it. If the OS lacks |
︙ | ︙ | |||
973 974 975 976 977 978 979 | ** offset). But later on, nLimit and nOffset become the memory locations ** in the VDBE that record the limit and offset counters. */ struct Select { ExprList *pEList; /* The fields of the result */ u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ u8 isDistinct; /* True if the DISTINCT keyword is present */ | < < | 973 974 975 976 977 978 979 980 981 982 983 984 985 986 | ** offset). But later on, nLimit and nOffset become the memory locations ** in the VDBE that record the limit and offset counters. */ struct Select { ExprList *pEList; /* The fields of the result */ u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ u8 isDistinct; /* True if the DISTINCT keyword is present */ SrcList *pSrc; /* The FROM clause */ Expr *pWhere; /* The WHERE clause */ ExprList *pGroupBy; /* The GROUP BY clause */ Expr *pHaving; /* The HAVING clause */ ExprList *pOrderBy; /* The ORDER BY clause */ Select *pPrior; /* Prior select in a compound select statement */ int nLimit, nOffset; /* LIMIT and OFFSET values. -1 means not used */ |
︙ | ︙ |
Changes to test/misc4.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for miscellanous features that were # left out of other test files. # | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for miscellanous features that were # left out of other test files. # # $Id: misc4.test,v 1.10 2005/01/18 14:45:49 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Prepare a statement that will create a temporary table. Then do # a rollback. Then try to execute the prepared statement. # |
︙ | ︙ | |||
94 95 96 97 98 99 100 101 102 | INSERT INTO Table2 VALUES (1, 'a'); SELECT ID, Value FROM Table1 UNION SELECT ID, max(Value) FROM Table2 GROUP BY 1,2 ORDER BY 1, 2; } } {{} {} 1 x 1 z} } ;# ifcapable compound finish_test | > > > > > > > > > > > > > > > > > > > > | 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 | INSERT INTO Table2 VALUES (1, 'a'); SELECT ID, Value FROM Table1 UNION SELECT ID, max(Value) FROM Table2 GROUP BY 1,2 ORDER BY 1, 2; } } {{} {} 1 x 1 z} } ;# ifcapable compound # Ticket #1047. Make sure column types are preserved in subqueries. # do_test misc4-4.1 { execsql { create table a(key varchar, data varchar); create table b(key varchar, period integer); insert into a values('01','data01'); insert into a values('+1','data+1'); insert into b values ('01',1); insert into b values ('01',2); insert into b values ('+1',3); insert into b values ('+1',4); select a.*, x.* from a, (select key,sum(period) from b group by key) as x where a.key=x.key; } } {01 data01 01 3.0 +1 data+1 +1 7.0} finish_test |