diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 1 | ||||
-rw-r--r-- | src/resolve.c | 1 | ||||
-rw-r--r-- | src/select.c | 46 | ||||
-rw-r--r-- | src/sqliteInt.h | 6 | ||||
-rw-r--r-- | src/treeview.c | 3 |
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); |