From: drh Date: Wed, 19 Aug 2015 17:11:37 +0000 (+0000) Subject: A list of arguments following a table name translates into equality X-Git-Tag: version-3.9.0~215^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=01d230ce057ac505b064cdffcc01075eb387967c;p=thirdparty%2Fsqlite.git A list of arguments following a table name translates into equality constraints against hidden columns in that table. FossilOrigin-Name: 40e12cfe4c29475417ba89fb637b4c763cf74016 --- diff --git a/manifest b/manifest index 97f862e1e2..758e6c154c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\srefactor\sof\sthe\sSrcList\sobject\sso\sthat\sit\sis\sable\sto\shold\sthe\sargument\nlist\sto\sa\stable-valued-function\sin\sthe\sFROM\sclause. -D 2015-08-19T15:20:00.817 +C A\slist\sof\sarguments\sfollowing\sa\stable\sname\stranslates\sinto\sequality\nconstraints\sagainst\shidden\scolumns\sin\sthat\stable. +D 2015-08-19T17:11:37.512 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 4f663b6b4954b9b1eb0e6f08387688a93b57542d F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -281,7 +281,7 @@ F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 F src/btree.c f48b3ef91676c06a90a8832987ecef6b94c931ee F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1 F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0 -F src/build.c 909416959d8948a436d86461ffacdb3b19ec8286 +F src/build.c 16051071cd855c23e47b087b49ac99c65b1d8c39 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b @@ -325,7 +325,7 @@ F src/os_win.c 40b3af7a47eb1107d0d69e592bec345a3b7b798a F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c aa916ca28606ccf4b6877dfc2b643ccbca86589f F src/pager.h 6d435f563b3f7fcae4b84433b76a6ac2730036e2 -F src/parse.y 2ed6efe32ec400c765fec5f3253c650ffdfeb65b +F src/parse.y ad9af8552f6f340bd646577ca63356a6f82b6a7e F src/pcache.c cde06aa50962595e412d497e22fd2e07878ba1f0 F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9 F src/pcache1.c d08939800abf3031bd0affd5a13fbc4d7ba3fb68 @@ -334,14 +334,14 @@ F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1 F src/printf.c 2bc439ff20a4aad0e0ad50a37a67b5eae7d20edc F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 -F src/resolve.c cd1c44c853c3560b3fa85637f732a9b7fc0e9295 +F src/resolve.c bbb4874decae6e60eee0395a31205d3b55cd2c00 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c c46de38c1b66355f02a839bb72eb13f277e6d19c F src/shell.c b1f91e60918df3a68efad1e3a11696b9a7e23d23 F src/sqlite.h.in 447ead0a6b3293206f04a0896553955d07cfb4b9 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h a0b948ebc89bac13941254641326a6aa248c2cc4 -F src/sqliteInt.h 9fae37f6bcc2f9ed71fe0362972c263642326914 +F src/sqliteInt.h 89e68539d645db597366a91411468b51e73c21a0 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179 F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -393,7 +393,7 @@ F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481 F src/tokenize.c 57cb3720f53f84d811def2069c2b169b6be539a5 -F src/treeview.c fda5cfc4635d4a436214c4593f3032d07688a0e2 +F src/treeview.c c15df00728034549ff92d78ae851b44952736d3b F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f F src/update.c 487747b328b7216bb7f6af0695d6937d5c9e605f F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c @@ -412,11 +412,11 @@ F src/vtab.c 1e3405f78e9f248bdee6ef7a8903fadaa7222f9c F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb F src/wal.c 6fb6b68969e4692593c2552c4e7bff5882de2cb8 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 -F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804 -F src/where.c a572b23993febb7bb72ee997c55da3b03d870be8 -F src/whereInt.h 5f87e3c4b0551747d119730dfebddd3c54f04047 +F src/walker.c 2e14d17f592d176b6dc879c33fbdec4fbccaa2ba +F src/where.c 66518a14a1238611aa0744d6980b6b7f544f4816 +F src/whereInt.h 880a8599226ac1c00203490d934f3ed79b292572 F src/wherecode.c 69f19535a6de0cceb10e16b31a3a03463e31bc24 -F src/whereexpr.c 9ce1c9cfedbf80c93c7d899497025ec8256ce652 +F src/whereexpr.c 6332ade8f72beebb6438734e92757da4631176e0 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -1031,7 +1031,7 @@ F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2 F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85 F test/syscall.test d2fdaad713f103ac611fe7ef9b724c7b69f8149c F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6 -F test/tabfunc01.test 0c1fb6ee8eba49c13b8a4c35b8f0726397debb33 +F test/tabfunc01.test ca013d7012764f85185d0d1b77f158a7b1b3ad6d F test/table.test 33bf0d1fd07f304582695184b8e6feb017303816 F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 @@ -1376,7 +1376,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c58426dbd5ea8b8440ebcc1214f79fa63d658216 -R 8f19410a9a93222f2a2f5ce9faa04ea9 +P b919376147597c4b73421abe5788f893baf1560b +R 03d0a3c413d15fc0179aae3fc23d1837 U drh -Z 28752308589cee1f3c6d24275593910d +Z 86fabb010e68498602162c53cf0d6cc5 diff --git a/manifest.uuid b/manifest.uuid index d399910325..26e06bc1f6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b919376147597c4b73421abe5788f893baf1560b \ No newline at end of file +40e12cfe4c29475417ba89fb637b4c763cf74016 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 3ff49d12b5..96dc03a825 100644 --- a/src/build.c +++ b/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 diff --git a/src/parse.y b/src/parse.y index 9174abf7f9..3d186b28aa 100644 --- a/src/parse.y +++ b/src/parse.y @@ -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). { diff --git a/src/resolve.c b/src/resolve.c index ecba89162a..72d5f319c1 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -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; inExpr; 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; ipSrc->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; inExpr; 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 diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 739678998d..96a7700210 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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*); diff --git a/src/treeview.c b/src/treeview.c index 77a654477d..fbe8fd46d5 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -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); diff --git a/src/walker.c b/src/walker.c index e30bb60b5a..81e0f2cd60 100644 --- a/src/walker.c +++ b/src/walker.c @@ -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; diff --git a/src/where.c b/src/where.c index 2a84a5952a..bdcfeaa9aa 100644 --- a/src/where.c +++ b/src/where.c @@ -4030,6 +4030,7 @@ WhereInfo *sqlite3WhereBegin( */ for(ii=0; iinSrc; ii++){ createMask(pMaskSet, pTabList->a[ii].iCursor); + sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC); } #ifndef NDEBUG { diff --git a/src/whereInt.h b/src/whereInt.h index 8929d8c4be..76b665d971 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -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*); diff --git a/src/whereexpr.c b/src/whereexpr.c index 3607ef5352..a0f7c822af 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -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; jnExpr; j++){ + while( knCol && (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); + } +} diff --git a/test/tabfunc01.test b/test/tabfunc01.test index f657958440..7393238b94 100644 --- a/test/tabfunc01.test +++ b/test/tabfunc01.test @@ -32,5 +32,24 @@ do_execsql_test tabfunc01-1.2 { do_catchsql_test tabfunc01-1.3 { CREATE VIRTUAL TABLE t1 USING generate_series; } {1 {no such module: generate_series}} +do_execsql_test tabfunc01-1.4 { + SELECT * FROM generate_series(1,9,2); +} {1 3 5 7 9} +do_execsql_test tabfunc01-1.5 { + SELECT * FROM generate_series(1,9); +} {1 2 3 4 5 6 7 8 9} +do_execsql_test tabfunc01-1.6 { + SELECT * FROM generate_series(1,10) WHERE step=3; +} {1 4 7 10} +do_catchsql_test tabfunc01-1.7 { + SELECT * FROM generate_series(1,9,2,11); +} {1 {too many arguments on generate_series - max 3}} + +do_execsql_test tabfunc01-2.1 { + CREATE TABLE t1(x); + INSERT INTO t1(x) VALUES(2),(3); + SELECT *, '|' FROM t1, generate_series(1,x) ORDER BY 1, 2 + +} {2 1 | 2 2 | 3 1 | 3 2 | 3 3 |} finish_test