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