Minor refactor of the SrcList object so that it is able to hold the argument
list to a table-valued-function in the FROM clause. FossilOrigin-Name: b919376147597c4b73421abe5788f893baf1560b
This commit is contained in:
parent
398f872d1f
commit
8a48b9c0b1
30
manifest
30
manifest
@ -1,5 +1,5 @@
|
||||
C Virtual\stable\smodules\swith\sa\snull\sxCreate\smethod\sact\sas\seponymous-only\smodules\s-\nthey\scannot\sbe\sused\sin\sa\sCREATE\sVIRTUAL\sTABLE\sstatement.\s\sAdd\sthe\sseries.c\nextension\sthat\simplements\sa\spostgres-like\sgenerate_series\svirtual\stable\sto\ndemonstrate\sthis\scapability.
|
||||
D 2015-08-19T13:54:20.227
|
||||
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
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 4f663b6b4954b9b1eb0e6f08387688a93b57542d
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -281,14 +281,14 @@ F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
|
||||
F src/btree.c f48b3ef91676c06a90a8832987ecef6b94c931ee
|
||||
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
|
||||
F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0
|
||||
F src/build.c 77a9683d9202c091349d8d0bb40922c8dcc4784d
|
||||
F src/build.c 909416959d8948a436d86461ffacdb3b19ec8286
|
||||
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
|
||||
F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f
|
||||
F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
|
||||
F src/date.c 8ec787fed4929d8ccdf6b1bc360fccc3e1d2ca58
|
||||
F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a
|
||||
F src/delete.c 8857a6f27560718f65d43bdbec86c967ae1f8dfa
|
||||
F src/expr.c c5c58e4d01c7ceb2266791d8d877f1b23a88e316
|
||||
F src/expr.c 9b9fa7f825290dee945007edc9fe8fdd9b8ce49e
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c c9b63a217d86582c22121699a47f22f524608869
|
||||
F src/func.c 824bea430d3a2b7dbc62806ad54da8fdb8ed9e3f
|
||||
@ -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 6d60dda8f8d418b6dc034f1fbccd816c459983a8
|
||||
F src/parse.y 2ed6efe32ec400c765fec5f3253c650ffdfeb65b
|
||||
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 2d47554370de8de6dd5be060cef9559eec315005
|
||||
F src/resolve.c cd1c44c853c3560b3fa85637f732a9b7fc0e9295
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c 57ef3d98c4400b93eea318813be41b2af2da2217
|
||||
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 683b48027374e20bea20e36180984be07bb03031
|
||||
F src/sqliteInt.h 9fae37f6bcc2f9ed71fe0362972c263642326914
|
||||
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 c84b1a8ebc7f1d00cd76ce4958eeb3ae1021beed
|
||||
F src/treeview.c fda5cfc4635d4a436214c4593f3032d07688a0e2
|
||||
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
|
||||
F src/update.c 487747b328b7216bb7f6af0695d6937d5c9e605f
|
||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||
@ -413,9 +413,9 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
|
||||
F src/wal.c 6fb6b68969e4692593c2552c4e7bff5882de2cb8
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
|
||||
F src/where.c c745d3aa78ad1aa8982febb99f2f17ee5cbac069
|
||||
F src/where.c a572b23993febb7bb72ee997c55da3b03d870be8
|
||||
F src/whereInt.h 5f87e3c4b0551747d119730dfebddd3c54f04047
|
||||
F src/wherecode.c 5da5049224f12db314931ae7e0919b4914a2a0b1
|
||||
F src/wherecode.c 69f19535a6de0cceb10e16b31a3a03463e31bc24
|
||||
F src/whereexpr.c 9ce1c9cfedbf80c93c7d899497025ec8256ce652
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
@ -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 239e336a556c92c6f81431f4f144f16311184880
|
||||
F test/tabfunc01.test 0c1fb6ee8eba49c13b8a4c35b8f0726397debb33
|
||||
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 dddd792dedf0c73ebe74b4ff8d303e6216c16b6a
|
||||
R 5f16282689e1192bf9396f5e61d5d753
|
||||
P c58426dbd5ea8b8440ebcc1214f79fa63d658216
|
||||
R 8f19410a9a93222f2a2f5ce9faa04ea9
|
||||
U drh
|
||||
Z 970ed95f4f43231f807975375b2847aa
|
||||
Z 28752308589cee1f3c6d24275593910d
|
||||
|
@ -1 +1 @@
|
||||
c58426dbd5ea8b8440ebcc1214f79fa63d658216
|
||||
b919376147597c4b73421abe5788f893baf1560b
|
16
src/build.c
16
src/build.c
@ -3709,7 +3709,8 @@ void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
|
||||
sqlite3DbFree(db, pItem->zDatabase);
|
||||
sqlite3DbFree(db, pItem->zName);
|
||||
sqlite3DbFree(db, pItem->zAlias);
|
||||
sqlite3DbFree(db, pItem->zIndexedBy);
|
||||
if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy);
|
||||
if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
|
||||
sqlite3DeleteTable(db, pItem->pTab);
|
||||
sqlite3SelectDelete(db, pItem->pSelect);
|
||||
sqlite3ExprDelete(db, pItem->pOn);
|
||||
@ -3782,13 +3783,16 @@ void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
|
||||
assert( pIndexedBy!=0 );
|
||||
if( p && ALWAYS(p->nSrc>0) ){
|
||||
struct SrcList_item *pItem = &p->a[p->nSrc-1];
|
||||
assert( pItem->notIndexed==0 && pItem->zIndexedBy==0 );
|
||||
assert( pItem->fg.notIndexed==0 );
|
||||
assert( pItem->fg.isIndexedBy==0 );
|
||||
assert( pItem->fg.isTabFunc==0 );
|
||||
if( pIndexedBy->n==1 && !pIndexedBy->z ){
|
||||
/* A "NOT INDEXED" clause was supplied. See parse.y
|
||||
** construct "indexed_opt" for details. */
|
||||
pItem->notIndexed = 1;
|
||||
pItem->fg.notIndexed = 1;
|
||||
}else{
|
||||
pItem->zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy);
|
||||
pItem->u1.zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy);
|
||||
pItem->fg.isIndexedBy = (pItem->u1.zIndexedBy!=0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3812,9 +3816,9 @@ void sqlite3SrcListShiftJoinType(SrcList *p){
|
||||
if( p ){
|
||||
int i;
|
||||
for(i=p->nSrc-1; i>0; i--){
|
||||
p->a[i].jointype = p->a[i-1].jointype;
|
||||
p->a[i].fg.jointype = p->a[i-1].fg.jointype;
|
||||
}
|
||||
p->a[0].jointype = 0;
|
||||
p->a[0].fg.jointype = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
16
src/expr.c
16
src/expr.c
@ -1034,16 +1034,18 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
|
||||
pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
|
||||
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
|
||||
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
|
||||
pNewItem->jointype = pOldItem->jointype;
|
||||
pNewItem->fg = pOldItem->fg;
|
||||
pNewItem->iCursor = pOldItem->iCursor;
|
||||
pNewItem->addrFillSub = pOldItem->addrFillSub;
|
||||
pNewItem->regReturn = pOldItem->regReturn;
|
||||
pNewItem->isCorrelated = pOldItem->isCorrelated;
|
||||
pNewItem->viaCoroutine = pOldItem->viaCoroutine;
|
||||
pNewItem->isRecursive = pOldItem->isRecursive;
|
||||
pNewItem->zIndexedBy = sqlite3DbStrDup(db, pOldItem->zIndexedBy);
|
||||
pNewItem->notIndexed = pOldItem->notIndexed;
|
||||
pNewItem->pIndex = pOldItem->pIndex;
|
||||
if( pNewItem->fg.isIndexedBy ){
|
||||
pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy);
|
||||
}
|
||||
pNewItem->pIBIndex = pOldItem->pIBIndex;
|
||||
if( pNewItem->fg.isTabFunc ){
|
||||
pNewItem->u1.pFuncArg =
|
||||
sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
|
||||
}
|
||||
pTab = pNewItem->pTab = pOldItem->pTab;
|
||||
if( pTab ){
|
||||
pTab->nRef++;
|
||||
|
@ -586,7 +586,7 @@ from(A) ::= FROM seltablist(X). {
|
||||
//
|
||||
stl_prefix(A) ::= seltablist(X) joinop(Y). {
|
||||
A = X;
|
||||
if( ALWAYS(A && A->nSrc>0) ) A->a[A->nSrc-1].jointype = (u8)Y;
|
||||
if( ALWAYS(A && A->nSrc>0) ) A->a[A->nSrc-1].fg.jointype = (u8)Y;
|
||||
}
|
||||
stl_prefix(A) ::= . {A = 0;}
|
||||
seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) indexed_opt(I)
|
||||
|
@ -306,7 +306,7 @@ static int lookupName(
|
||||
** USING clause, then skip this match.
|
||||
*/
|
||||
if( cnt==1 ){
|
||||
if( pItem->jointype & JT_NATURAL ) continue;
|
||||
if( pItem->fg.jointype & JT_NATURAL ) continue;
|
||||
if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
|
||||
}
|
||||
cnt++;
|
||||
@ -321,8 +321,8 @@ static int lookupName(
|
||||
pExpr->iTable = pMatch->iCursor;
|
||||
pExpr->pTab = pMatch->pTab;
|
||||
/* RIGHT JOIN not (yet) supported */
|
||||
assert( (pMatch->jointype & JT_RIGHT)==0 );
|
||||
if( (pMatch->jointype & JT_LEFT)!=0 ){
|
||||
assert( (pMatch->fg.jointype & JT_RIGHT)==0 );
|
||||
if( (pMatch->fg.jointype & JT_LEFT)!=0 ){
|
||||
ExprSetProperty(pExpr, EP_CanBeNull);
|
||||
}
|
||||
pSchema = pExpr->pTab->pSchema;
|
||||
@ -1215,7 +1215,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
** parent contexts. After resolving references to expressions in
|
||||
** pItem->pSelect, check if this value has changed. If so, then
|
||||
** SELECT statement pItem->pSelect must be correlated. Set the
|
||||
** pItem->isCorrelated flag if this is the case. */
|
||||
** pItem->fg.isCorrelated flag if this is the case. */
|
||||
for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef;
|
||||
|
||||
if( pItem->zName ) pParse->zAuthContext = pItem->zName;
|
||||
@ -1224,8 +1224,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
|
||||
|
||||
for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
|
||||
assert( pItem->isCorrelated==0 && nRef<=0 );
|
||||
pItem->isCorrelated = (nRef!=0);
|
||||
assert( pItem->fg.isCorrelated==0 && nRef<=0 );
|
||||
pItem->fg.isCorrelated = (nRef!=0);
|
||||
}
|
||||
}
|
||||
|
||||
|
36
src/select.c
36
src/select.c
@ -406,12 +406,12 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
|
||||
int isOuter;
|
||||
|
||||
if( NEVER(pLeftTab==0 || pRightTab==0) ) continue;
|
||||
isOuter = (pRight->jointype & JT_OUTER)!=0;
|
||||
isOuter = (pRight->fg.jointype & JT_OUTER)!=0;
|
||||
|
||||
/* When the NATURAL keyword is present, add WHERE clause terms for
|
||||
** every column that the two tables have in common.
|
||||
*/
|
||||
if( pRight->jointype & JT_NATURAL ){
|
||||
if( pRight->fg.jointype & JT_NATURAL ){
|
||||
if( pRight->pOn || pRight->pUsing ){
|
||||
sqlite3ErrorMsg(pParse, "a NATURAL join may not have "
|
||||
"an ON or USING clause", 0);
|
||||
@ -1933,7 +1933,7 @@ static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
|
||||
**
|
||||
**
|
||||
** There is exactly one reference to the recursive-table in the FROM clause
|
||||
** of recursive-query, marked with the SrcList->a[].isRecursive flag.
|
||||
** of recursive-query, marked with the SrcList->a[].fg.isRecursive flag.
|
||||
**
|
||||
** The setup-query runs once to generate an initial set of rows that go
|
||||
** into a Queue table. Rows are extracted from the Queue table one by
|
||||
@ -1998,7 +1998,7 @@ static void generateWithRecursiveQuery(
|
||||
|
||||
/* Locate the cursor number of the Current table */
|
||||
for(i=0; ALWAYS(i<pSrc->nSrc); i++){
|
||||
if( pSrc->a[i].isRecursive ){
|
||||
if( pSrc->a[i].fg.isRecursive ){
|
||||
iCurrent = pSrc->a[i].iCursor;
|
||||
break;
|
||||
}
|
||||
@ -3413,7 +3413,7 @@ static int flattenSubquery(
|
||||
** is fraught with danger. Best to avoid the whole thing. If the
|
||||
** subquery is the right term of a LEFT JOIN, then do not flatten.
|
||||
*/
|
||||
if( (pSubitem->jointype & JT_OUTER)!=0 ){
|
||||
if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3584,7 +3584,7 @@ static int flattenSubquery(
|
||||
|
||||
if( pSrc ){
|
||||
assert( pParent==p ); /* First time through the loop */
|
||||
jointype = pSubitem->jointype;
|
||||
jointype = pSubitem->fg.jointype;
|
||||
}else{
|
||||
assert( pParent!=p ); /* 2nd and subsequent times through the loop */
|
||||
pSrc = pParent->pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
|
||||
@ -3624,7 +3624,7 @@ static int flattenSubquery(
|
||||
pSrc->a[i+iFrom] = pSubSrc->a[i];
|
||||
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
|
||||
}
|
||||
pSrc->a[iFrom].jointype = jointype;
|
||||
pSrc->a[iFrom].fg.jointype = jointype;
|
||||
|
||||
/* Now begin substituting subquery result set expressions for
|
||||
** references to the iParent in the outer query.
|
||||
@ -3875,9 +3875,9 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
|
||||
** pFrom->pIndex and return SQLITE_OK.
|
||||
*/
|
||||
int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){
|
||||
if( pFrom->pTab && pFrom->zIndexedBy ){
|
||||
if( pFrom->pTab && pFrom->fg.isIndexedBy ){
|
||||
Table *pTab = pFrom->pTab;
|
||||
char *zIndexedBy = pFrom->zIndexedBy;
|
||||
char *zIndexedBy = pFrom->u1.zIndexedBy;
|
||||
Index *pIdx;
|
||||
for(pIdx=pTab->pIndex;
|
||||
pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy);
|
||||
@ -3888,7 +3888,7 @@ int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){
|
||||
pParse->checkSchema = 1;
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
pFrom->pIndex = pIdx;
|
||||
pFrom->pIBIndex = pIdx;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@ -4083,7 +4083,7 @@ static int withExpand(
|
||||
&& 0==sqlite3StrICmp(pItem->zName, pCte->zName)
|
||||
){
|
||||
pItem->pTab = pTab;
|
||||
pItem->isRecursive = 1;
|
||||
pItem->fg.isRecursive = 1;
|
||||
pTab->nRef++;
|
||||
pSel->selFlags |= SF_Recursive;
|
||||
}
|
||||
@ -4213,8 +4213,8 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
*/
|
||||
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
|
||||
Table *pTab;
|
||||
assert( pFrom->isRecursive==0 || pFrom->pTab );
|
||||
if( pFrom->isRecursive ) continue;
|
||||
assert( pFrom->fg.isRecursive==0 || pFrom->pTab );
|
||||
if( pFrom->fg.isRecursive ) continue;
|
||||
if( pFrom->pTab!=0 ){
|
||||
/* This statement has already been prepared. There is no need
|
||||
** to go further. */
|
||||
@ -4377,7 +4377,7 @@ static int selectExpander(Walker *pWalker, Select *p){
|
||||
tableSeen = 1;
|
||||
|
||||
if( i>0 && zTName==0 ){
|
||||
if( (pFrom->jointype & JT_NATURAL)!=0
|
||||
if( (pFrom->fg.jointype & JT_NATURAL)!=0
|
||||
&& tableAndColumnIndex(pTabList, i, zName, 0, 0)
|
||||
){
|
||||
/* In a NATURAL join, omit the join columns from the
|
||||
@ -4904,7 +4904,7 @@ int sqlite3Select(
|
||||
** is sufficient, though the subroutine to manifest the view does need
|
||||
** to be invoked again. */
|
||||
if( pItem->addrFillSub ){
|
||||
if( pItem->viaCoroutine==0 ){
|
||||
if( pItem->fg.viaCoroutine==0 ){
|
||||
sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
|
||||
}
|
||||
continue;
|
||||
@ -4922,7 +4922,7 @@ int sqlite3Select(
|
||||
/* Make copies of constant WHERE-clause terms in the outer query down
|
||||
** inside the subquery. This can help the subquery to run more efficiently.
|
||||
*/
|
||||
if( (pItem->jointype & JT_OUTER)==0
|
||||
if( (pItem->fg.jointype & JT_OUTER)==0
|
||||
&& pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor)
|
||||
){
|
||||
#if SELECTTRACE_ENABLED
|
||||
@ -4951,7 +4951,7 @@ int sqlite3Select(
|
||||
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
|
||||
sqlite3Select(pParse, pSub, &dest);
|
||||
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
|
||||
pItem->viaCoroutine = 1;
|
||||
pItem->fg.viaCoroutine = 1;
|
||||
pItem->regResult = dest.iSdst;
|
||||
sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn);
|
||||
sqlite3VdbeJumpHere(v, addrTop-1);
|
||||
@ -4969,7 +4969,7 @@ int sqlite3Select(
|
||||
pItem->regReturn = ++pParse->nMem;
|
||||
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
|
||||
pItem->addrFillSub = topAddr+1;
|
||||
if( pItem->isCorrelated==0 ){
|
||||
if( pItem->fg.isCorrelated==0 ){
|
||||
/* If the subquery is not correlated and if we are not inside of
|
||||
** a trigger, then we only need to compute the value of the subquery
|
||||
** once. */
|
||||
|
@ -1650,7 +1650,7 @@ struct Table {
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
int nModuleArg; /* Number of arguments to the module */
|
||||
char **azModuleArg; /* Text of all module args. [0] is module name */
|
||||
char **azModuleArg; /* 0: module 1: schema 2: vtab name 3...: args */
|
||||
VTable *pVTable; /* List of VTable objects. */
|
||||
#endif
|
||||
Trigger *pTrigger; /* List of triggers stored in pSchema */
|
||||
@ -2285,11 +2285,15 @@ struct SrcList {
|
||||
int addrFillSub; /* Address of subroutine to manifest a subquery */
|
||||
int regReturn; /* Register holding return address of addrFillSub */
|
||||
int regResult; /* Registers holding results of a co-routine */
|
||||
u8 jointype; /* Type of join between this able and the previous */
|
||||
unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
|
||||
unsigned isCorrelated :1; /* True if sub-query is correlated */
|
||||
unsigned viaCoroutine :1; /* Implemented as a co-routine */
|
||||
unsigned isRecursive :1; /* True for recursive reference in WITH */
|
||||
struct {
|
||||
u8 jointype; /* Type of join between this able and the previous */
|
||||
unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
|
||||
unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
|
||||
unsigned isTabFunc :1; /* True if table-valued-function syntax */
|
||||
unsigned isCorrelated :1; /* True if sub-query is correlated */
|
||||
unsigned viaCoroutine :1; /* Implemented as a co-routine */
|
||||
unsigned isRecursive :1; /* True for recursive reference in WITH */
|
||||
} fg;
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */
|
||||
#endif
|
||||
@ -2297,8 +2301,11 @@ struct SrcList {
|
||||
Expr *pOn; /* The ON clause of a join */
|
||||
IdList *pUsing; /* The USING clause of a join */
|
||||
Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */
|
||||
char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
|
||||
Index *pIndex; /* Index structure corresponding to zIndex, if any */
|
||||
union {
|
||||
char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
|
||||
ExprList *pFuncArg; /* Arguments to table-valued-function */
|
||||
} u1;
|
||||
Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
|
||||
} a[1]; /* One entry for each identifier on the list */
|
||||
};
|
||||
|
||||
|
@ -120,7 +120,7 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
|
||||
if( pItem->zAlias ){
|
||||
sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias);
|
||||
}
|
||||
if( pItem->jointype & JT_LEFT ){
|
||||
if( pItem->fg.jointype & JT_LEFT ){
|
||||
sqlite3XPrintf(&x, 0, " LEFT-JOIN");
|
||||
}
|
||||
sqlite3StrAccumFinish(&x);
|
||||
|
40
src/where.c
40
src/where.c
@ -709,7 +709,7 @@ static void constructAutomaticIndex(
|
||||
/* Fill the automatic index with content */
|
||||
sqlite3ExprCachePush(pParse);
|
||||
pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom];
|
||||
if( pTabItem->viaCoroutine ){
|
||||
if( pTabItem->fg.viaCoroutine ){
|
||||
int regYield = pTabItem->regReturn;
|
||||
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
|
||||
addrTop = sqlite3VdbeAddOp1(v, OP_Yield, regYield);
|
||||
@ -728,10 +728,10 @@ static void constructAutomaticIndex(
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
|
||||
if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue);
|
||||
if( pTabItem->viaCoroutine ){
|
||||
if( pTabItem->fg.viaCoroutine ){
|
||||
translateColumnToCopy(v, addrTop, pLevel->iTabCur, pTabItem->regResult);
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop);
|
||||
pTabItem->viaCoroutine = 0;
|
||||
pTabItem->fg.viaCoroutine = 0;
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v);
|
||||
}
|
||||
@ -2128,7 +2128,7 @@ static int whereLoopAddBtreeIndex(
|
||||
assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
|
||||
if( pNew->wsFlags & WHERE_BTM_LIMIT ){
|
||||
opMask = WO_LT|WO_LE;
|
||||
}else if( /*pProbe->tnum<=0 ||*/ (pSrc->jointype & JT_LEFT)!=0 ){
|
||||
}else if( /*pProbe->tnum<=0 ||*/ (pSrc->fg.jointype & JT_LEFT)!=0 ){
|
||||
opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE;
|
||||
}else{
|
||||
opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS;
|
||||
@ -2502,9 +2502,9 @@ static int whereLoopAddBtree(
|
||||
pWC = pBuilder->pWC;
|
||||
assert( !IsVirtual(pSrc->pTab) );
|
||||
|
||||
if( pSrc->pIndex ){
|
||||
if( pSrc->pIBIndex ){
|
||||
/* An INDEXED BY clause specifies a particular index to use */
|
||||
pProbe = pSrc->pIndex;
|
||||
pProbe = pSrc->pIBIndex;
|
||||
}else if( !HasRowid(pTab) ){
|
||||
pProbe = pTab->pIndex;
|
||||
}else{
|
||||
@ -2524,7 +2524,7 @@ static int whereLoopAddBtree(
|
||||
aiRowEstPk[0] = pTab->nRowLogEst;
|
||||
aiRowEstPk[1] = 0;
|
||||
pFirst = pSrc->pTab->pIndex;
|
||||
if( pSrc->notIndexed==0 ){
|
||||
if( pSrc->fg.notIndexed==0 ){
|
||||
/* The real indices of the table are only considered if the
|
||||
** NOT INDEXED qualifier is omitted from the FROM clause */
|
||||
sPk.pNext = pFirst;
|
||||
@ -2536,14 +2536,14 @@ static int whereLoopAddBtree(
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
|
||||
/* Automatic indexes */
|
||||
if( !pBuilder->pOrSet /* Not part of an OR optimization */
|
||||
if( !pBuilder->pOrSet /* Not part of an OR optimization */
|
||||
&& (pWInfo->wctrlFlags & WHERE_NO_AUTOINDEX)==0
|
||||
&& (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
|
||||
&& pSrc->pIndex==0 /* Has no INDEXED BY clause */
|
||||
&& !pSrc->notIndexed /* Has no NOT INDEXED clause */
|
||||
&& HasRowid(pTab) /* Is not a WITHOUT ROWID table. (FIXME: Why not?) */
|
||||
&& !pSrc->isCorrelated /* Not a correlated subquery */
|
||||
&& !pSrc->isRecursive /* Not a recursive common table expression. */
|
||||
&& pSrc->pIBIndex==0 /* Has no INDEXED BY clause */
|
||||
&& !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */
|
||||
&& HasRowid(pTab) /* Is not a WITHOUT ROWID table. (FIXME: Why not?) */
|
||||
&& !pSrc->fg.isCorrelated /* Not a correlated subquery */
|
||||
&& !pSrc->fg.isRecursive /* Not a recursive common table expression. */
|
||||
){
|
||||
/* Generate auto-index WhereLoops */
|
||||
WhereTerm *pTerm;
|
||||
@ -2664,7 +2664,7 @@ static int whereLoopAddBtree(
|
||||
|
||||
/* If there was an INDEXED BY clause, then only that one index is
|
||||
** considered. */
|
||||
if( pSrc->pIndex ) break;
|
||||
if( pSrc->pIBIndex ) break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@ -3010,16 +3010,16 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
|
||||
Bitmask mUnusable = 0;
|
||||
pNew->iTab = iTab;
|
||||
pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor);
|
||||
if( ((pItem->jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){
|
||||
if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){
|
||||
/* This condition is true when pItem is the FROM clause term on the
|
||||
** right-hand-side of a LEFT or CROSS JOIN. */
|
||||
mExtra = mPrior;
|
||||
}
|
||||
priorJointype = pItem->jointype;
|
||||
priorJointype = pItem->fg.jointype;
|
||||
if( IsVirtual(pItem->pTab) ){
|
||||
struct SrcList_item *p;
|
||||
for(p=&pItem[1]; p<pEnd; p++){
|
||||
if( mUnusable || (p->jointype & (JT_LEFT|JT_CROSS)) ){
|
||||
if( mUnusable || (p->fg.jointype & (JT_LEFT|JT_CROSS)) ){
|
||||
mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor);
|
||||
}
|
||||
}
|
||||
@ -3749,7 +3749,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
|
||||
pItem = pWInfo->pTabList->a;
|
||||
pTab = pItem->pTab;
|
||||
if( IsVirtual(pTab) ) return 0;
|
||||
if( pItem->zIndexedBy ) return 0;
|
||||
if( pItem->fg.isIndexedBy ) return 0;
|
||||
iCur = pItem->iCursor;
|
||||
pWC = &pWInfo->sWC;
|
||||
pLoop = pBuilder->pNew;
|
||||
@ -4136,7 +4136,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
while( pWInfo->nLevel>=2 ){
|
||||
WhereTerm *pTerm, *pEnd;
|
||||
pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop;
|
||||
if( (pWInfo->pTabList->a[pLoop->iTab].jointype & JT_LEFT)==0 ) break;
|
||||
if( (pWInfo->pTabList->a[pLoop->iTab].fg.jointype & JT_LEFT)==0 ) break;
|
||||
if( (wctrlFlags & WHERE_WANT_DISTINCT)==0
|
||||
&& (pLoop->wsFlags & WHERE_ONEROW)==0
|
||||
){
|
||||
@ -4429,7 +4429,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
** the co-routine into OP_Copy of result contained in a register.
|
||||
** OP_Rowid becomes OP_Null.
|
||||
*/
|
||||
if( pTabItem->viaCoroutine && !db->mallocFailed ){
|
||||
if( pTabItem->fg.viaCoroutine && !db->mallocFailed ){
|
||||
translateColumnToCopy(v, pLevel->addrBody, pLevel->iTabCur,
|
||||
pTabItem->regResult);
|
||||
continue;
|
||||
|
@ -646,14 +646,14 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
** initialize a memory cell that records if this table matches any
|
||||
** row of the left table of the join.
|
||||
*/
|
||||
if( pLevel->iFrom>0 && (pTabItem[0].jointype & JT_LEFT)!=0 ){
|
||||
if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){
|
||||
pLevel->iLeftJoin = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin);
|
||||
VdbeComment((v, "init LEFT JOIN no-match flag"));
|
||||
}
|
||||
|
||||
/* Special case of a FROM clause subquery implemented as a co-routine */
|
||||
if( pTabItem->viaCoroutine ){
|
||||
if( pTabItem->fg.viaCoroutine ){
|
||||
int regYield = pTabItem->regReturn;
|
||||
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
|
||||
pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk);
|
||||
@ -1395,7 +1395,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
static const u8 aStep[] = { OP_Next, OP_Prev };
|
||||
static const u8 aStart[] = { OP_Rewind, OP_Last };
|
||||
assert( bRev==0 || bRev==1 );
|
||||
if( pTabItem->isRecursive ){
|
||||
if( pTabItem->fg.isRecursive ){
|
||||
/* Tables marked isRecursive have only a single row that is stored in
|
||||
** a pseudo-cursor. No need to Rewind or Next such cursors. */
|
||||
pLevel->op = OP_Noop;
|
||||
|
@ -31,6 +31,6 @@ do_execsql_test tabfunc01-1.2 {
|
||||
} {0 | 1 | 2 | 3 | 4 |}
|
||||
do_catchsql_test tabfunc01-1.3 {
|
||||
CREATE VIRTUAL TABLE t1 USING generate_series;
|
||||
} {}
|
||||
} {1 {no such module: generate_series}}
|
||||
|
||||
finish_test
|
||||
|
Loading…
Reference in New Issue
Block a user