mirror of
				https://github.com/sqlite/sqlite.git
				synced 2025-10-31 18:11:01 +03:00 
			
		
		
		
	Continue refactoring name resolution. Fix for ticket #1047. (CVS 2230)
FossilOrigin-Name: 88d4834fec7583a9b6400a1ce5b928c1f8a390dd
This commit is contained in:
		
							
								
								
									
										18
									
								
								manifest
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								manifest
									
									
									
									
									
								
							| @@ -1,5 +1,5 @@ | |||||||
| C Refinements\sto\sthe\sname\sresolution\slogic.\s\sChange\sthe\sname\sof\sthe\nkeywordhash.c\sfile\sto\skeywordhash.h.\s(CVS\s2229) | C Continue\srefactoring\sname\sresolution.\s\sFix\sfor\sticket\s#1047.\s(CVS\s2230) | ||||||
| D 2005-01-18T04:00:43 | D 2005-01-18T14:45:48 | ||||||
| F Makefile.in ffd81f5e926d40b457071b4de8d7c1fa18f39b5a | F Makefile.in ffd81f5e926d40b457071b4de8d7c1fa18f39b5a | ||||||
| F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 | F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 | ||||||
| F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1 | F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1 | ||||||
| @@ -31,7 +31,7 @@ F src/attach.c e49d09dad9f5f9fb10b4b0c1be5a70ae4c45e689 | |||||||
| F src/auth.c 3b81f2a42f48a62c2c9c9b0eda31a157c681edea | F src/auth.c 3b81f2a42f48a62c2c9c9b0eda31a157c681edea | ||||||
| F src/btree.c 97101cce85304edbaedafc5f39ab12e2dc78b076 | F src/btree.c 97101cce85304edbaedafc5f39ab12e2dc78b076 | ||||||
| F src/btree.h 74d19cf40ab49fd69abe9e4e12a6c321ad86c497 | F src/btree.h 74d19cf40ab49fd69abe9e4e12a6c321ad86c497 | ||||||
| F src/build.c 4b7a2c308973df3ec26ceda6e3dadc07eecf031b | F src/build.c 608ea54aab8f561da99c8a40c3ab6b26b7fc91e9 | ||||||
| F src/cursor.c f883813759742068890b1f699335872bfa8fdf41 | F src/cursor.c f883813759742068890b1f699335872bfa8fdf41 | ||||||
| F src/date.c f3d1f5cd1503dabf426a198f3ebef5afbc122a7f | F src/date.c f3d1f5cd1503dabf426a198f3ebef5afbc122a7f | ||||||
| F src/delete.c 728a02e5b5c62d294f8cdbdb21dbaa3e188983ab | F src/delete.c 728a02e5b5c62d294f8cdbdb21dbaa3e188983ab | ||||||
| @@ -57,10 +57,10 @@ F src/parse.y ceba179b9703657180963568f54b0e75f33e36e1 | |||||||
| F src/pragma.c ac594f74c90ffec043c43e49358719ffeb491eec | F src/pragma.c ac594f74c90ffec043c43e49358719ffeb491eec | ||||||
| F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357 | F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357 | ||||||
| F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 | F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 | ||||||
| F src/select.c 37b9ddb9688a98c521d092dc38c811ec72191b14 | F src/select.c 767e9d0f0652ff8d319c13cc72a8eef4098ce30e | ||||||
| F src/shell.c 591364a0e9ca4ce53873e21e0294476c0c2b4770 | F src/shell.c 591364a0e9ca4ce53873e21e0294476c0c2b4770 | ||||||
| F src/sqlite.h.in 0d5e48e506845b74a845c9470e01d3f472b59611 | F src/sqlite.h.in 0d5e48e506845b74a845c9470e01d3f472b59611 | ||||||
| F src/sqliteInt.h a208bf0f51e6d7616c083313fa7cf5313efd346a | F src/sqliteInt.h c6414179a23cab108b4b07e8665f30829ce47f2a | ||||||
| F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9 | F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9 | ||||||
| F src/tclsqlite.c fd27457b228118be96524dae285146c76efe032b | F src/tclsqlite.c fd27457b228118be96524dae285146c76efe032b | ||||||
| F src/test1.c 2e27b110ba5aa16977bad1cc2388553479d73793 | F src/test1.c 2e27b110ba5aa16977bad1cc2388553479d73793 | ||||||
| @@ -156,7 +156,7 @@ F test/minmax.test e7048476940df0af11d0f2cf687572f557cd0b29 | |||||||
| F test/misc1.test 744f60d1025fa978708b96cb222a07a1feb1524a | F test/misc1.test 744f60d1025fa978708b96cb222a07a1feb1524a | ||||||
| F test/misc2.test bc852f1622d98b610d1f3e2ceb36ed7271256050 | F test/misc2.test bc852f1622d98b610d1f3e2ceb36ed7271256050 | ||||||
| F test/misc3.test 928a2f1e1189924ed14e1ae074e34f40688bdf94 | F test/misc3.test 928a2f1e1189924ed14e1ae074e34f40688bdf94 | ||||||
| F test/misc4.test 7edc2542eadd98555c2d25c222b88a93124975ae | F test/misc4.test 33fd2ef6e9443acd73257a8f49aee0baec125888 | ||||||
| F test/misuse.test 600738a8e611989bc5f544303f5e311c5f228084 | F test/misuse.test 600738a8e611989bc5f544303f5e311c5f228084 | ||||||
| F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0 | F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0 | ||||||
| F test/null.test 5a945790ef21b24fd602fe2c7a23847b903f8687 | F test/null.test 5a945790ef21b24fd602fe2c7a23847b903f8687 | ||||||
| @@ -269,7 +269,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc | |||||||
| F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618 | F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618 | ||||||
| F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 | F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 | ||||||
| F www/whentouse.tcl c3b50d3ac31c54be2a1af9b488a89d22f1e6e746 | F www/whentouse.tcl c3b50d3ac31c54be2a1af9b488a89d22f1e6e746 | ||||||
| P 4a7534396a72ccb300303df28798bb2c50293782 | P 0142ae6f0004bf18a1c2d8e49c09d2a9a27d6369 | ||||||
| R f8f7d8c77656eb3939f3657d425a82a6 | R b2406c5f3bd45a3ced07f6eb72e28967 | ||||||
| U drh | U drh | ||||||
| Z 295a57dfb9d4d3f564ec7f21c6307f77 | Z 4a32c7e963fbc8acd621a17d2d1e7a76 | ||||||
|   | |||||||
| @@ -1 +1 @@ | |||||||
| 0142ae6f0004bf18a1c2d8e49c09d2a9a27d6369 | 88d4834fec7583a9b6400a1ce5b928c1f8a390dd | ||||||
							
								
								
									
										47
									
								
								src/build.c
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								src/build.c
									
									
									
									
									
								
							| @@ -22,7 +22,7 @@ | |||||||
| **     COMMIT | **     COMMIT | ||||||
| **     ROLLBACK | **     ROLLBACK | ||||||
| ** | ** | ||||||
| ** $Id: build.c,v 1.293 2005/01/18 04:00:44 drh Exp $ | ** $Id: build.c,v 1.294 2005/01/18 14:45:48 drh Exp $ | ||||||
| */ | */ | ||||||
| #include "sqliteInt.h" | #include "sqliteInt.h" | ||||||
| #include <ctype.h> | #include <ctype.h> | ||||||
| @@ -1578,10 +1578,10 @@ void sqlite3CreateView( | |||||||
| ** of errors.  If an error is seen leave an error message in pParse->zErrMsg. | ** of errors.  If an error is seen leave an error message in pParse->zErrMsg. | ||||||
| */ | */ | ||||||
| int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ | int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ | ||||||
|   ExprList *pEList; |   Table *pSelTab;   /* A fake table from which we get the result set */ | ||||||
|   Select *pSel; |   Select *pSel;     /* Copy of the SELECT that implements the view */ | ||||||
|   Table *pSelTab; |   int nErr = 0;     /* Number of errors encountered */ | ||||||
|   int nErr = 0; |   int n;            /* Temporarily holds the number of cursors assigned */ | ||||||
|  |  | ||||||
|   assert( pTable ); |   assert( pTable ); | ||||||
|  |  | ||||||
| @@ -1606,23 +1606,19 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* If we get this far, it means we need to compute the table names. |   /* 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 ); /* If nCol==0, then pTable must be a VIEW */ |   assert( pTable->pSelect ); | ||||||
|   pSel = pTable->pSelect; |   pSel = sqlite3SelectDup(pTable->pSelect); | ||||||
|  |   n = pParse->nTab; | ||||||
|   /* Note that the call to sqlite3ResultSetOfSelect() will expand any |   sqlite3SrcListAssignCursors(pParse, pSel->pSrc); | ||||||
|   ** "*" elements in this list.  But we will need to restore the list |  | ||||||
|   ** back to its original configuration afterwards, so we save a copy of |  | ||||||
|   ** the original in pEList. |  | ||||||
|   */ |  | ||||||
|   pEList = pSel->pEList; |  | ||||||
|   pSel->pEList = sqlite3ExprListDup(pEList); |  | ||||||
|   if( pSel->pEList==0 ){ |  | ||||||
|     pSel->pEList = pEList; |  | ||||||
|     return 1;  /* Malloc failed */ |  | ||||||
|   } |  | ||||||
|   pTable->nCol = -1; |   pTable->nCol = -1; | ||||||
|   pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel); |   pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel); | ||||||
|  |   pParse->nTab = n; | ||||||
|   if( pSelTab ){ |   if( pSelTab ){ | ||||||
|     assert( pTable->aCol==0 ); |     assert( pTable->aCol==0 ); | ||||||
|     pTable->nCol = pSelTab->nCol; |     pTable->nCol = pSelTab->nCol; | ||||||
| @@ -1635,9 +1631,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ | |||||||
|     pTable->nCol = 0; |     pTable->nCol = 0; | ||||||
|     nErr++; |     nErr++; | ||||||
|   } |   } | ||||||
|   sqlite3SelectUnbind(pSel); |   sqlite3SelectDelete(pSel); | ||||||
|   sqlite3ExprListDelete(pSel->pEList); |  | ||||||
|   pSel->pEList = pEList; |  | ||||||
|   return nErr;   |   return nErr;   | ||||||
| } | } | ||||||
| #endif /* SQLITE_OMIT_VIEW */ | #endif /* SQLITE_OMIT_VIEW */ | ||||||
| @@ -2584,9 +2578,12 @@ SrcList *sqlite3SrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){ | |||||||
| */ | */ | ||||||
| void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ | void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ | ||||||
|   int i; |   int i; | ||||||
|   for(i=0; i<pList->nSrc; i++){ |   struct SrcList_item *pItem; | ||||||
|     if( pList->a[i].iCursor<0 ){ |   for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){ | ||||||
|       pList->a[i].iCursor = pParse->nTab++; |     if( pItem->iCursor>=0 ) break; | ||||||
|  |     pItem->iCursor = pParse->nTab++; | ||||||
|  |     if( pItem->pSelect ){ | ||||||
|  |       sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										52
									
								
								src/select.c
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								src/select.c
									
									
									
									
									
								
							| @@ -12,7 +12,7 @@ | |||||||
| ** This file contains C code routines that are called by the parser | ** This file contains C code routines that are called by the parser | ||||||
| ** to handle SELECT statements in SQLite. | ** to handle SELECT statements in SQLite. | ||||||
| ** | ** | ||||||
| ** $Id: select.c,v 1.224 2005/01/18 04:00:44 drh Exp $ | ** $Id: select.c,v 1.225 2005/01/18 14:45:48 drh Exp $ | ||||||
| */ | */ | ||||||
| #include "sqliteInt.h" | #include "sqliteInt.h" | ||||||
|  |  | ||||||
| @@ -654,6 +654,7 @@ static const char *columnType(Parse *pParse, SrcList *pTabList, Expr *pExpr){ | |||||||
|   int j; |   int j; | ||||||
|   if( pExpr==0 || pTabList==0 ) return 0; |   if( pExpr==0 || pTabList==0 ) return 0; | ||||||
|  |  | ||||||
|  |   sqlite3ExprResolveNames(pParse, pTabList, 0, pExpr, 1, 0); | ||||||
|   switch( pExpr->op ){ |   switch( pExpr->op ){ | ||||||
|     case TK_COLUMN: { |     case TK_COLUMN: { | ||||||
|       Table *pTab; |       Table *pTab; | ||||||
| @@ -803,7 +804,7 @@ static const char *selectOpName(int id){ | |||||||
| /* | /* | ||||||
| ** Forward declaration | ** Forward declaration | ||||||
| */ | */ | ||||||
| static int fillInColumnList(Parse*, Select*); | static int prepSelectStmt(Parse*, Select*); | ||||||
|  |  | ||||||
| /* | /* | ||||||
| ** Given a SELECT statement, generate a Table structure that describes | ** Given a SELECT statement, generate a Table structure that describes | ||||||
| @@ -815,7 +816,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ | |||||||
|   ExprList *pEList; |   ExprList *pEList; | ||||||
|   Column *aCol, *pCol; |   Column *aCol, *pCol; | ||||||
|  |  | ||||||
|   if( fillInColumnList(pParse, pSelect) ){ |   if( prepSelectStmt(pParse, pSelect) ){ | ||||||
|     return 0; |     return 0; | ||||||
|   } |   } | ||||||
|   pTab = sqliteMalloc( sizeof(Table) ); |   pTab = sqliteMalloc( sizeof(Table) ); | ||||||
| @@ -870,20 +871,24 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ | |||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
| ** For the given SELECT statement, do three things. | ** Prepare a SELECT statement for processing by doing the following | ||||||
|  | ** things: | ||||||
| ** | ** | ||||||
| **    (1)  Fill in the pTabList->a[].pTab fields in the SrcList that  | **    (1)  Make sure VDBE cursor numbers have been assigned to every | ||||||
| **         defines the set of tables that should be scanned.  For views, | **         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 | **         fill pTabList->a[].pSelect with a copy of the SELECT statement | ||||||
| **         that implements the view.  A copy is made of the view's SELECT | **         that implements the view.  A copy is made of the view's SELECT | ||||||
| **         statement so that we can freely modify or delete that statement | **         statement so that we can freely modify or delete that statement | ||||||
| **         without worrying about messing up the presistent representation | **         without worrying about messing up the presistent representation | ||||||
| **         of the view. | **         of the view. | ||||||
| ** | ** | ||||||
| **    (2)  Add terms to the WHERE clause to accomodate the NATURAL keyword | **    (3)  Add terms to the WHERE clause to accomodate the NATURAL keyword | ||||||
| **         on joins and the ON and USING clause of joins. | **         on joins and the ON and USING clause of joins. | ||||||
| ** | ** | ||||||
| **    (3)  Scan the list of columns in the result set (pEList) looking | **    (4)  Scan the list of columns in the result set (pEList) looking | ||||||
| **         for instances of the "*" operator or the TABLE.* operator. | **         for instances of the "*" operator or the TABLE.* operator. | ||||||
| **         If found, expand each "*" to be every column in every table | **         If found, expand each "*" to be every column in every table | ||||||
| **         and TABLE.* to be every column in TABLE. | **         and TABLE.* to be every column in TABLE. | ||||||
| @@ -891,7 +896,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ | |||||||
| ** Return 0 on success.  If there are problems, leave an error message | ** Return 0 on success.  If there are problems, leave an error message | ||||||
| ** in pParse and return non-zero. | ** in pParse and return non-zero. | ||||||
| */ | */ | ||||||
| static int fillInColumnList(Parse *pParse, Select *p){ | static int prepSelectStmt(Parse *pParse, Select *p){ | ||||||
|   int i, j, k, rc; |   int i, j, k, rc; | ||||||
|   SrcList *pTabList; |   SrcList *pTabList; | ||||||
|   ExprList *pEList; |   ExprList *pEList; | ||||||
| @@ -902,11 +907,20 @@ static int fillInColumnList(Parse *pParse, Select *p){ | |||||||
|   pTabList = p->pSrc; |   pTabList = p->pSrc; | ||||||
|   pEList = p->pEList; |   pEList = p->pEList; | ||||||
|  |  | ||||||
|   /* Look up every table in the table list. |   /* 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++){ |   for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ | ||||||
|     if( pFrom->pTab ){ |     if( pFrom->pTab!=0 ){ | ||||||
|       /* This routine has run before!  No need to continue */ |       /* This statement has already been prepared.  There is no need | ||||||
|  |       ** to go further. */ | ||||||
|  |       assert( i==0 ); | ||||||
|       return 0; |       return 0; | ||||||
|     } |     } | ||||||
|     if( pFrom->zName==0 ){ |     if( pFrom->zName==0 ){ | ||||||
| @@ -1125,7 +1139,7 @@ static int matchOrderbyToColumn( | |||||||
|   if( mustComplete ){ |   if( mustComplete ){ | ||||||
|     for(i=0; i<pOrderBy->nExpr; i++){ pOrderBy->a[i].done = 0; } |     for(i=0; i<pOrderBy->nExpr; i++){ pOrderBy->a[i].done = 0; } | ||||||
|   } |   } | ||||||
|   if( fillInColumnList(pParse, pSelect) ){ |   if( prepSelectStmt(pParse, pSelect) ){ | ||||||
|     return 1; |     return 1; | ||||||
|   } |   } | ||||||
|   if( pSelect->pPrior ){ |   if( pSelect->pPrior ){ | ||||||
| @@ -1263,7 +1277,7 @@ static int openTempIndex(Parse *pParse, Select *p, int iTab, int keyAsData){ | |||||||
|   Vdbe *v = pParse->pVdbe; |   Vdbe *v = pParse->pVdbe; | ||||||
|   int addr; |   int addr; | ||||||
|  |  | ||||||
|   if( fillInColumnList(pParse, p) ){ |   if( prepSelectStmt(pParse, p) ){ | ||||||
|     return 0; |     return 0; | ||||||
|   } |   } | ||||||
|   nColumn = p->pEList->nExpr; |   nColumn = p->pEList->nExpr; | ||||||
| @@ -2307,21 +2321,13 @@ int sqlite3Select( | |||||||
|   pHaving = p->pHaving; |   pHaving = p->pHaving; | ||||||
|   isDistinct = p->isDistinct; |   isDistinct = p->isDistinct; | ||||||
|  |  | ||||||
|   /* Allocate VDBE cursors for each table in the FROM clause |  | ||||||
|   */ |  | ||||||
|   sqlite3SrcListAssignCursors(pParse, pTabList); |  | ||||||
|  |  | ||||||
|   /*  |   /*  | ||||||
|   ** Do not even attempt to generate any code if we have already seen |   ** Do not even attempt to generate any code if we have already seen | ||||||
|   ** errors before this routine starts. |   ** errors before this routine starts. | ||||||
|   */ |   */ | ||||||
|   if( pParse->nErr>0 ) goto select_end; |   if( pParse->nErr>0 ) goto select_end; | ||||||
|  |  | ||||||
|   /* Expand any "*" terms in the result set.  (For example the "*" in |   if( prepSelectStmt(pParse, p) ){ | ||||||
|   ** "SELECT * FROM t1")  The fillInColumnlist() routine also does some |  | ||||||
|   ** other housekeeping - see the header comment for details. |  | ||||||
|   */ |  | ||||||
|   if( fillInColumnList(pParse, p) ){ |  | ||||||
|     goto select_end; |     goto select_end; | ||||||
|   } |   } | ||||||
|   pWhere = p->pWhere; |   pWhere = p->pWhere; | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
| ************************************************************************* | ************************************************************************* | ||||||
| ** Internal interface definitions for SQLite. | ** Internal interface definitions for SQLite. | ||||||
| ** | ** | ||||||
| ** @(#) $Id: sqliteInt.h,v 1.355 2005/01/18 04:00:44 drh Exp $ | ** @(#) $Id: sqliteInt.h,v 1.356 2005/01/18 14:45:48 drh Exp $ | ||||||
| */ | */ | ||||||
| #ifndef _SQLITEINT_H_ | #ifndef _SQLITEINT_H_ | ||||||
| #define _SQLITEINT_H_ | #define _SQLITEINT_H_ | ||||||
| @@ -977,8 +977,6 @@ struct Select { | |||||||
|   ExprList *pEList;      /* The fields of the result */ |   ExprList *pEList;      /* The fields of the result */ | ||||||
|   u8 op;                 /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ |   u8 op;                 /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ | ||||||
|   u8 isDistinct;         /* True if the DISTINCT keyword is present */ |   u8 isDistinct;         /* True if the DISTINCT keyword is present */ | ||||||
|   u8 isAgg;              /* True if uses aggregate functions */ |  | ||||||
|   u8 namesResolved;      /* True if processed by sqlite3ExprResolve() */ |  | ||||||
|   SrcList *pSrc;         /* The FROM clause */ |   SrcList *pSrc;         /* The FROM clause */ | ||||||
|   Expr *pWhere;          /* The WHERE clause */ |   Expr *pWhere;          /* The WHERE clause */ | ||||||
|   ExprList *pGroupBy;    /* The GROUP BY clause */ |   ExprList *pGroupBy;    /* The GROUP BY clause */ | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ | |||||||
| # This file implements tests for miscellanous features that were | # This file implements tests for miscellanous features that were | ||||||
| # left out of other test files. | # left out of other test files. | ||||||
| # | # | ||||||
| # $Id: misc4.test,v 1.9 2005/01/11 15:28:33 drh Exp $ | # $Id: misc4.test,v 1.10 2005/01/18 14:45:49 drh Exp $ | ||||||
|  |  | ||||||
| set testdir [file dirname $argv0] | set testdir [file dirname $argv0] | ||||||
| source $testdir/tester.tcl | source $testdir/tester.tcl | ||||||
| @@ -99,4 +99,24 @@ do_test misc4-3.1 { | |||||||
| } {{} {} 1 x 1 z} | } {{} {} 1 x 1 z} | ||||||
| } ;# ifcapable compound | } ;# 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 | finish_test | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user