mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Added the ability to say things like "SELECT rowid, * FROM table1;" (CVS 332)
FossilOrigin-Name: ffbdd43f5de62e7bf81631c83473aca29c3a6c98
This commit is contained in:
11
src/parse.y
11
src/parse.y
@ -14,7 +14,7 @@
|
||||
** the parser. Lemon will also generate a header file containing
|
||||
** numeric codes for all of the tokens.
|
||||
**
|
||||
** @(#) $Id: parse.y,v 1.38 2001/11/06 04:00:18 drh Exp $
|
||||
** @(#) $Id: parse.y,v 1.39 2001/12/16 20:05:06 drh Exp $
|
||||
*/
|
||||
%token_prefix TK_
|
||||
%token_type {Token}
|
||||
@ -198,8 +198,9 @@ distinct(A) ::= ALL. {A = 0;}
|
||||
distinct(A) ::= . {A = 0;}
|
||||
|
||||
// selcollist is a list of expressions that are to become the return
|
||||
// values of the SELECT statement. In the case of "SELECT * FROM ..."
|
||||
// the selcollist value is NULL.
|
||||
// values of the SELECT statement. The "*" in statements like
|
||||
// "SELECT * FROM ..." is encoded as a special expression with an
|
||||
// opcode of TK_ALL.
|
||||
//
|
||||
%type selcollist {ExprList*}
|
||||
%destructor selcollist {sqliteExprListDelete($$);}
|
||||
@ -207,9 +208,11 @@ distinct(A) ::= . {A = 0;}
|
||||
%destructor sclp {sqliteExprListDelete($$);}
|
||||
sclp(A) ::= selcollist(X) COMMA. {A = X;}
|
||||
sclp(A) ::= . {A = 0;}
|
||||
selcollist(A) ::= STAR. {A = 0;}
|
||||
selcollist(A) ::= sclp(P) expr(X). {A = sqliteExprListAppend(P,X,0);}
|
||||
selcollist(A) ::= sclp(P) expr(X) as ids(Y). {A = sqliteExprListAppend(P,X,&Y);}
|
||||
selcollist(A) ::= sclp(P) STAR. {
|
||||
A = sqliteExprListAppend(P, sqliteExpr(TK_ALL, 0, 0, 0), 0);
|
||||
}
|
||||
as ::= .
|
||||
as ::= AS.
|
||||
|
||||
|
70
src/select.c
70
src/select.c
@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle SELECT statements in SQLite.
|
||||
**
|
||||
** $Id: select.c,v 1.49 2001/11/07 16:48:27 drh Exp $
|
||||
** $Id: select.c,v 1.50 2001/12/16 20:05:06 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -318,7 +318,7 @@ static const char *selectOpName(int id){
|
||||
** in pParse and return non-zero.
|
||||
*/
|
||||
static int fillInColumnList(Parse *pParse, Select *p){
|
||||
int i, j;
|
||||
int i, j, k;
|
||||
IdList *pTabList;
|
||||
ExprList *pEList;
|
||||
|
||||
@ -353,34 +353,52 @@ static int fillInColumnList(Parse *pParse, Select *p){
|
||||
}
|
||||
}
|
||||
|
||||
/* If the list of columns to retrieve is "*" then replace it with
|
||||
** a list of all columns from all tables.
|
||||
/* For every "*" that occurs in the column list, insert the names of
|
||||
** all columns in all tables. The parser inserted a special expression
|
||||
** with the TK_ALL operator for each "*" that it found in the column list.
|
||||
** The following code just has to locate the TK_ALL expressions and expand
|
||||
** each one to the list of all columns in all tables.
|
||||
*/
|
||||
if( pEList==0 ){
|
||||
for(i=0; i<pTabList->nId; i++){
|
||||
Table *pTab = pTabList->a[i].pTab;
|
||||
for(j=0; j<pTab->nCol; j++){
|
||||
Expr *pExpr = sqliteExpr(TK_DOT, 0, 0, 0);
|
||||
if( pExpr==0 ) break;
|
||||
pExpr->pLeft = sqliteExpr(TK_ID, 0, 0, 0);
|
||||
if( pExpr->pLeft==0 ){ sqliteExprDelete(pExpr); break; }
|
||||
if( pTabList->a[i].zAlias && pTabList->a[i].zAlias[0] ){
|
||||
pExpr->pLeft->token.z = pTabList->a[i].zAlias;
|
||||
pExpr->pLeft->token.n = strlen(pTabList->a[i].zAlias);
|
||||
}else{
|
||||
pExpr->pLeft->token.z = pTab->zName;
|
||||
pExpr->pLeft->token.n = strlen(pTab->zName);
|
||||
for(k=0; k<pEList->nExpr; k++){
|
||||
if( pEList->a[k].pExpr->op==TK_ALL ) break;
|
||||
}
|
||||
if( k<pEList->nExpr ){
|
||||
struct ExprList_item *a = pEList->a;
|
||||
ExprList *pNew = 0;
|
||||
for(k=0; k<pEList->nExpr; k++){
|
||||
if( a[k].pExpr->op!=TK_ALL ){
|
||||
pNew = sqliteExprListAppend(pNew, a[k].pExpr, 0);
|
||||
pNew->a[pNew->nExpr-1].zName = a[k].zName;
|
||||
a[k].pExpr = 0;
|
||||
a[k].zName = 0;
|
||||
}else{
|
||||
for(i=0; i<pTabList->nId; i++){
|
||||
Table *pTab = pTabList->a[i].pTab;
|
||||
for(j=0; j<pTab->nCol; j++){
|
||||
Expr *pExpr = sqliteExpr(TK_DOT, 0, 0, 0);
|
||||
if( pExpr==0 ) break;
|
||||
pExpr->pLeft = sqliteExpr(TK_ID, 0, 0, 0);
|
||||
if( pExpr->pLeft==0 ){ sqliteExprDelete(pExpr); break; }
|
||||
if( pTabList->a[i].zAlias && pTabList->a[i].zAlias[0] ){
|
||||
pExpr->pLeft->token.z = pTabList->a[i].zAlias;
|
||||
pExpr->pLeft->token.n = strlen(pTabList->a[i].zAlias);
|
||||
}else{
|
||||
pExpr->pLeft->token.z = pTab->zName;
|
||||
pExpr->pLeft->token.n = strlen(pTab->zName);
|
||||
}
|
||||
pExpr->pRight = sqliteExpr(TK_ID, 0, 0, 0);
|
||||
if( pExpr->pRight==0 ){ sqliteExprDelete(pExpr); break; }
|
||||
pExpr->pRight->token.z = pTab->aCol[j].zName;
|
||||
pExpr->pRight->token.n = strlen(pTab->aCol[j].zName);
|
||||
pExpr->span.z = "";
|
||||
pExpr->span.n = 0;
|
||||
pNew = sqliteExprListAppend(pNew, pExpr, 0);
|
||||
}
|
||||
}
|
||||
pExpr->pRight = sqliteExpr(TK_ID, 0, 0, 0);
|
||||
if( pExpr->pRight==0 ){ sqliteExprDelete(pExpr); break; }
|
||||
pExpr->pRight->token.z = pTab->aCol[j].zName;
|
||||
pExpr->pRight->token.n = strlen(pTab->aCol[j].zName);
|
||||
pExpr->span.z = "";
|
||||
pExpr->span.n = 0;
|
||||
pEList = sqliteExprListAppend(pEList, pExpr, 0);
|
||||
}
|
||||
}
|
||||
p->pEList = pEList;
|
||||
sqliteExprListDelete(pEList);
|
||||
p->pEList = pNew;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user