aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/expr.c1
-rw-r--r--src/resolve.c1
-rw-r--r--src/select.c46
-rw-r--r--src/sqliteInt.h6
-rw-r--r--src/treeview.c3
5 files changed, 47 insertions, 10 deletions
diff --git a/src/expr.c b/src/expr.c
index 8e47578cc..77b5e0ad6 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1633,6 +1633,7 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, const ExprList *p, int flags){
pItem->done = 0;
pItem->bNulls = pOldItem->bNulls;
pItem->bUsed = pOldItem->bUsed;
+ pItem->bUsingTerm = pOldItem->bUsingTerm;
pItem->bSorterRef = pOldItem->bSorterRef;
pItem->u = pOldItem->u;
}
diff --git a/src/resolve.c b/src/resolve.c
index e9cfe9d9f..7f99152cb 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -361,6 +361,7 @@ static int lookupName(
pExpr->iColumn = j;
pEList->a[j].bUsed = 1;
hit = 1;
+ if( pEList->a[j].bUsingTerm ) break;
}
if( hit || zTab==0 ) continue;
}
diff --git a/src/select.c b/src/select.c
index e0f93a101..ed0fc6e4c 100644
--- a/src/select.c
+++ b/src/select.c
@@ -2180,6 +2180,7 @@ int sqlite3ColumnsFromExprList(
for(i=0, pCol=aCol; i<nCol && !db->mallocFailed; i++, pCol++){
struct ExprList_item *pX = &pEList->a[i];
+ struct ExprList_item *pCollide;
/* Get an appropriate name for the column
*/
if( (zName = pX->zEName)!=0 && pX->eEName==ENAME_NAME ){
@@ -2216,7 +2217,10 @@ int sqlite3ColumnsFromExprList(
** append an integer to the name so that it becomes unique.
*/
cnt = 0;
- while( zName && sqlite3HashFind(&ht, zName)!=0 ){
+ while( zName && (pCollide = sqlite3HashFind(&ht, zName))!=0 ){
+ if( pCollide->bUsingTerm ){
+ pCol->colFlags |= COLFLAG_NOEXPAND;
+ }
nName = sqlite3Strlen30(zName);
if( nName>0 ){
for(j=nName-1; j>0 && sqlite3Isdigit(zName[j]); j--){}
@@ -2228,7 +2232,7 @@ int sqlite3ColumnsFromExprList(
pCol->zCnName = zName;
pCol->hName = sqlite3StrIHash(zName);
sqlite3ColumnPropertiesFromName(0, pCol);
- if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){
+ if( zName && sqlite3HashInsert(&ht, zName, pX)==pX ){
sqlite3OomFault(db);
}
}
@@ -5837,6 +5841,25 @@ static int selectExpander(Walker *pWalker, Select *p){
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*";
}
+ if( i+1<pTabList->nSrc
+ && pFrom[1].fg.isUsing
+ && (selFlags & SF_NestedFrom)!=0
+ ){
+ int ii;
+ IdList *pUsing = pFrom[1].u3.pUsing;
+ for(ii=0; ii<pUsing->nId; ii++){
+ const char *zUName = pUsing->a[ii].zName;
+ pRight = sqlite3Expr(db, TK_ID, zUName);
+ pNew = sqlite3ExprListAppend(pParse, pNew, pRight);
+ if( pNew ){
+ struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
+ assert( pX->zEName==0 );
+ pX->zEName = sqlite3MPrintf(db,"..%s", zUName);
+ pX->eEName = ENAME_TAB;
+ pX->bUsingTerm = 1;
+ }
+ }
+ }
for(j=0; j<pTab->nCol; j++){
char *zName = pTab->aCol[j].zCnName;
struct ExprList_item *pX; /* Newly added ExprList term */
@@ -5853,14 +5876,22 @@ static int selectExpander(Walker *pWalker, Select *p){
** result-set list unless the SELECT has the SF_IncludeHidden
** bit set.
*/
- if( (p->selFlags & SF_IncludeHidden)==0
- && IsHiddenColumn(&pTab->aCol[j])
- ){
- continue;
+ if( pTab->aCol[j].colFlags & (COLFLAG_HIDDEN|COLFLAG_NOEXPAND) ){
+ if( IsHiddenColumn(&pTab->aCol[j])
+ && (selFlags & (SF_IncludeHidden|SF_NestedFrom))==0
+ ){
+ continue;
+ }
+ if( (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)!=0
+ && zTName==0
+ && (selFlags & (SF_NestedFrom))==0
+ ){
+ continue;
+ }
}
tableSeen = 1;
- if( i>0 && zTName==0 ){
+ if( i>0 && zTName==0 && (selFlags & SF_NestedFrom)==0 ){
if( pFrom->fg.isUsing
&& sqlite3IdListIndex(pFrom->u3.pUsing, zName)>=0
){
@@ -5872,6 +5903,7 @@ static int selectExpander(Walker *pWalker, Select *p){
pRight = sqlite3Expr(db, TK_ID, zName);
if( (pTabList->nSrc>1
&& ( (pFrom->fg.jointype & JT_LTORJ)==0
+ || (selFlags & SF_NestedFrom)!=0
|| !inAnyUsingClause(zName,pFrom,pTabList->nSrc-i-1)
)
)
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index e9f0af544..0715cae3c 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -2126,6 +2126,7 @@ struct Column {
#define COLFLAG_NOTAVAIL 0x0080 /* STORED column not yet calculated */
#define COLFLAG_BUSY 0x0100 /* Blocks recursion on GENERATED columns */
#define COLFLAG_HASCOLL 0x0200 /* Has collating sequence name in zCnName */
+#define COLFLAG_NOEXPAND 0x0400 /* Omit this column when expanding "*" */
#define COLFLAG_GENERATED 0x0060 /* Combo: _STORED, _VIRTUAL */
#define COLFLAG_NOINSERT 0x0062 /* Combo: _HIDDEN, _STORED, _VIRTUAL */
@@ -3004,8 +3005,9 @@ struct ExprList {
unsigned done :1; /* A flag to indicate when processing is finished */
unsigned reusable :1; /* Constant expression is reusable */
unsigned bSorterRef :1; /* Defer evaluation until after sorting */
- unsigned bNulls: 1; /* True if explicit "NULLS FIRST/LAST" */
- unsigned bUsed: 1; /* This column used in a SF_NestedFrom subquery */
+ unsigned bNulls :1; /* True if explicit "NULLS FIRST/LAST" */
+ unsigned bUsed :1; /* This column used in a SF_NestedFrom subquery */
+ unsigned bUsingTerm:1; /* Term from the USING clause of a NestedFrom */
union {
struct { /* Used by any ExprList other than Parse.pConsExpr */
u16 iOrderByCol; /* For ORDER BY, column number in result set */
diff --git a/src/treeview.c b/src/treeview.c
index 3d5bd7175..b498692ba 100644
--- a/src/treeview.c
+++ b/src/treeview.c
@@ -880,7 +880,8 @@ void sqlite3TreeViewBareExprList(
break;
case ENAME_TAB:
fprintf(stdout, "TABLE-ALIAS-NAME(\"%s\") ", zName);
- if( pList->a[i].bUsed==0 ) fprintf(stdout, "(unused) ");
+ if( pList->a[i].bUsed ) fprintf(stdout, "(used) ");
+ if( pList->a[i].bUsingTerm ) fprintf(stdout, "(USING-term) ");
break;
case ENAME_SPAN:
fprintf(stdout, "SPAN(\"%s\") ", zName);