mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-18 10:21:03 +03:00
A list of arguments following a table name translates into equality
constraints against hidden columns in that table. FossilOrigin-Name: 40e12cfe4c29475417ba89fb637b4c763cf74016
This commit is contained in:
15
src/build.c
15
src/build.c
@@ -3797,6 +3797,21 @@ void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Add the list of function arguments to the SrcList entry for a
|
||||
** table-valued-function.
|
||||
*/
|
||||
void sqlite3SrcListFuncArgs(Parse *pParse, SrcList *p, ExprList *pList){
|
||||
if( p && ALWAYS(p->nSrc>0) ){
|
||||
struct SrcList_item *pItem = &p->a[p->nSrc-1];
|
||||
assert( pItem->fg.notIndexed==0 );
|
||||
assert( pItem->fg.isIndexedBy==0 );
|
||||
assert( pItem->fg.isTabFunc==0 );
|
||||
pItem->u1.pFuncArg = pList;
|
||||
pItem->fg.isTabFunc = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** When building up a FROM clause in the parser, the join operator
|
||||
** is initially attached to the left operand. But the code generator
|
||||
|
||||
@@ -594,6 +594,11 @@ seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) indexed_opt(I)
|
||||
A = sqlite3SrcListAppendFromTerm(pParse,X,&Y,&D,&Z,0,N,U);
|
||||
sqlite3SrcListIndexedBy(pParse, A, &I);
|
||||
}
|
||||
seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) LP exprlist(E) RP as(Z)
|
||||
on_opt(N) using_opt(U). {
|
||||
A = sqlite3SrcListAppendFromTerm(pParse,X,&Y,&D,&Z,0,N,U);
|
||||
sqlite3SrcListFuncArgs(pParse, A, E);
|
||||
}
|
||||
%ifndef SQLITE_OMIT_SUBQUERY
|
||||
seltablist(A) ::= stl_prefix(X) LP select(S) RP
|
||||
as(Z) on_opt(N) using_opt(U). {
|
||||
|
||||
@@ -1142,7 +1142,6 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
int isCompound; /* True if p is a compound select */
|
||||
int nCompound; /* Number of compound terms processed so far */
|
||||
Parse *pParse; /* Parsing context */
|
||||
ExprList *pEList; /* Result set expression list */
|
||||
int i; /* Loop counter */
|
||||
ExprList *pGroupBy; /* The GROUP BY clause */
|
||||
Select *pLeftmost; /* Left-most of SELECT of a compound */
|
||||
@@ -1237,14 +1236,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
sNC.pNext = pOuterNC;
|
||||
|
||||
/* Resolve names in the result set. */
|
||||
pEList = p->pEList;
|
||||
assert( pEList!=0 );
|
||||
for(i=0; i<pEList->nExpr; i++){
|
||||
Expr *pX = pEList->a[i].pExpr;
|
||||
if( sqlite3ResolveExprNames(&sNC, pX) ){
|
||||
return WRC_Abort;
|
||||
}
|
||||
}
|
||||
if( sqlite3ResolveExprListNames(&sNC, p->pEList) ) return WRC_Abort;
|
||||
|
||||
/* If there are no aggregate functions in the result-set, and no GROUP BY
|
||||
** expression, do not allow aggregates in any of the other expressions.
|
||||
@@ -1277,6 +1269,16 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
|
||||
if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
|
||||
|
||||
/* Resolve names in table-valued-function arguments */
|
||||
for(i=0; i<p->pSrc->nSrc; i++){
|
||||
struct SrcList_item *pItem = &p->pSrc->a[i];
|
||||
if( pItem->fg.isTabFunc
|
||||
&& sqlite3ResolveExprListNames(&sNC, pItem->u1.pFuncArg)
|
||||
){
|
||||
return WRC_Abort;
|
||||
}
|
||||
}
|
||||
|
||||
/* The ORDER BY and GROUP BY clauses may not refer to terms in
|
||||
** outer queries
|
||||
*/
|
||||
@@ -1440,6 +1442,21 @@ int sqlite3ResolveExprNames(
|
||||
return ExprHasProperty(pExpr, EP_Error);
|
||||
}
|
||||
|
||||
/*
|
||||
** Resolve all names for all expression in an expression list. This is
|
||||
** just like sqlite3ResolveExprNames() except that it works for an expression
|
||||
** list rather than a single expression.
|
||||
*/
|
||||
int sqlite3ResolveExprListNames(
|
||||
NameContext *pNC, /* Namespace to resolve expressions in. */
|
||||
ExprList *pList /* The expression list to be analyzed. */
|
||||
){
|
||||
int i;
|
||||
for(i=0; i<pList->nExpr; i++){
|
||||
if( sqlite3ResolveExprNames(pNC, pList->a[i].pExpr) ) return WRC_Abort;
|
||||
}
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
/*
|
||||
** Resolve all names in all expressions of a SELECT and in all
|
||||
|
||||
@@ -3328,6 +3328,7 @@ SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*);
|
||||
SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
|
||||
Token*, Select*, Expr*, IdList*);
|
||||
void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
|
||||
void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*);
|
||||
int sqlite3IndexedByLookup(Parse *, struct SrcList_item *);
|
||||
void sqlite3SrcListShiftJoinType(SrcList*);
|
||||
void sqlite3SrcListAssignCursors(Parse*, SrcList*);
|
||||
@@ -3619,6 +3620,7 @@ void sqlite3SelectPrep(Parse*, Select*, NameContext*);
|
||||
void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
|
||||
int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
|
||||
int sqlite3ResolveExprNames(NameContext*, Expr*);
|
||||
int sqlite3ResolveExprListNames(NameContext*, ExprList*);
|
||||
void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
|
||||
void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
|
||||
int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
|
||||
|
||||
@@ -128,6 +128,9 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
|
||||
if( pItem->pSelect ){
|
||||
sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
|
||||
}
|
||||
if( pItem->fg.isTabFunc ){
|
||||
sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
|
||||
}
|
||||
sqlite3TreeViewPop(pView);
|
||||
}
|
||||
sqlite3TreeViewPop(pView);
|
||||
|
||||
@@ -105,6 +105,11 @@ int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
|
||||
if( sqlite3WalkSelect(pWalker, pItem->pSelect) ){
|
||||
return WRC_Abort;
|
||||
}
|
||||
if( pItem->fg.isTabFunc
|
||||
&& sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg)
|
||||
){
|
||||
return WRC_Abort;
|
||||
}
|
||||
}
|
||||
}
|
||||
return WRC_Continue;
|
||||
|
||||
@@ -4030,6 +4030,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
*/
|
||||
for(ii=0; ii<pTabList->nSrc; ii++){
|
||||
createMask(pMaskSet, pTabList->a[ii].iCursor);
|
||||
sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC);
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
|
||||
@@ -475,6 +475,7 @@ void sqlite3WhereSplit(WhereClause*,Expr*,u8);
|
||||
Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*);
|
||||
Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*);
|
||||
void sqlite3WhereExprAnalyze(SrcList*, WhereClause*);
|
||||
void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1247,3 +1247,42 @@ void sqlite3WhereExprAnalyze(
|
||||
exprAnalyze(pTabList, pWC, i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** For table-valued-functions, transform the function arguments into
|
||||
** new WHERE clause terms.
|
||||
**
|
||||
** Each function argument translates into an equality constraint against
|
||||
** a HIDDEN column in the table.
|
||||
*/
|
||||
void sqlite3WhereTabFuncArgs(
|
||||
Parse *pParse, /* Parsing context */
|
||||
struct SrcList_item *pItem, /* The FROM clause term to process */
|
||||
WhereClause *pWC /* Xfer function arguments to here */
|
||||
){
|
||||
Table *pTab;
|
||||
int j, k;
|
||||
ExprList *pArgs;
|
||||
Expr *pColRef;
|
||||
Expr *pTerm;
|
||||
if( pItem->fg.isTabFunc==0 ) return;
|
||||
pTab = pItem->pTab;
|
||||
assert( pTab!=0 );
|
||||
pArgs = pItem->u1.pFuncArg;
|
||||
assert( pArgs!=0 );
|
||||
for(j=k=0; j<pArgs->nExpr; j++){
|
||||
while( k<pTab->nCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){ k++; }
|
||||
if( k>=pTab->nCol ){
|
||||
sqlite3ErrorMsg(pParse, "too many arguments on %s - max %d",
|
||||
pTab->zName, j);
|
||||
return;
|
||||
}
|
||||
pColRef = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
|
||||
if( pColRef==0 ) return;
|
||||
pColRef->iTable = pItem->iCursor;
|
||||
pColRef->iColumn = k++;
|
||||
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef,
|
||||
sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0);
|
||||
whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user