Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add code to handle non-recursive CTEs in the same way as SQL views. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | common-table-expr |
Files: | files | file ages | folders |
SHA1: |
a26f399ba485e8127c276c5f103ec6c5 |
User & Date: | dan 2014-01-13 15:12:23.149 |
Context
2014-01-13
| ||
16:36 | Fix some memory leaks and crashes that could follow an OOM condition during WITH clause parsing. (check-in: 8839850c44 user: dan tags: common-table-expr) | |
15:12 | Add code to handle non-recursive CTEs in the same way as SQL views. (check-in: a26f399ba4 user: dan tags: common-table-expr) | |
2014-01-11
| ||
19:19 | Update the parser so that sub-queries and CTEs may have WITH clauses. (check-in: 704d3931b8 user: dan tags: common-table-expr) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
4204 4205 4206 4207 4208 4209 4210 | ** This routine is invoked once per CTE by the parser while parsing a ** WITH clause. */ With *sqlite3WithAdd( Parse *pParse, /* Parsing context */ With *pWith, /* Existing WITH clause, or NULL */ Token *pName, /* Name of the common-table */ | | > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > > > > > | > | > > > > > > > > | 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 | ** This routine is invoked once per CTE by the parser while parsing a ** WITH clause. */ With *sqlite3WithAdd( Parse *pParse, /* Parsing context */ With *pWith, /* Existing WITH clause, or NULL */ Token *pName, /* Name of the common-table */ ExprList *pArglist, /* Optional column name list for the table */ Select *pQuery /* Query used to initialize the table */ ){ sqlite3 *db = pParse->db; With *pNew; char *zName; /* Check that the CTE name is unique within this WITH clause. If ** not, store an error in the Parse structure. */ zName = sqlite3NameFromToken(pParse->db, pName); if( zName && pWith ){ int i; for(i=0; i<pWith->nCte; i++){ if( sqlite3StrICmp(zName, pWith->a[i].zName)==0 ){ sqlite3ErrorMsg(pParse, "duplicate cte name: %s", zName); } } } if( pWith ){ int nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte); pNew = sqlite3DbRealloc(db, pWith, nByte); }else{ pNew = sqlite3DbMallocZero(db, sizeof(*pWith)); } assert( zName!=0 || pNew==0 ); if( pNew==0 ){ sqlite3WithDelete(db, pWith); sqlite3ExprListDelete(db, pArglist); sqlite3SelectDelete(db, pQuery); sqlite3DbFree(db, zName); }else{ pNew->a[pNew->nCte].pSelect = pQuery; pNew->a[pNew->nCte].pCols = pArglist; pNew->a[pNew->nCte].zName = zName; pNew->nCte++; } return pNew; } /* ** Free the contents of the With object passed as the second argument. */ void sqlite3WithDelete(sqlite3 *db, With *pWith){ if( pWith ){ int i; for(i=0; i<pWith->nCte; i++){ struct Cte *pCte = &pWith->a[i]; sqlite3ExprListDelete(db, pCte->pCols); sqlite3SelectDelete(db, pCte->pSelect); sqlite3DbFree(db, pCte->zName); } sqlite3DbFree(db, pWith); } } #endif /* !defined(SQLITE_OMIT_CTE) */ |
Changes to src/expr.c.
︙ | ︙ | |||
890 891 892 893 894 895 896 897 898 899 900 901 902 903 | } } } } return pNew; } /* ** The following group of routines make deep copies of expressions, ** expression lists, ID lists, and select statements. The copies can ** be deleted (by being passed to their respective ...Delete() routines) ** without effecting the originals. ** | > > > > > > > > > > > > > > > > > > | 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 | } } } } return pNew; } With *withDup(sqlite3 *db, With *p){ With *pRet = 0; if( p ){ int nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1); pRet = sqlite3DbMallocZero(db, nByte); if( pRet ){ int i; pRet->nCte = p->nCte; for(i=0; i<p->nCte; i++){ pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0); pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0); pRet->a[i].zName = sqlite3DbStrDup(db, p->a[i].zName); } } } return pRet; } /* ** The following group of routines make deep copies of expressions, ** expression lists, ID lists, and select statements. The copies can ** be deleted (by being passed to their respective ...Delete() routines) ** without effecting the originals. ** |
︙ | ︙ | |||
1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 | pNew->iLimit = 0; pNew->iOffset = 0; pNew->selFlags = p->selFlags & ~SF_UsesEphemeral; pNew->pRightmost = 0; pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; pNew->addrOpenEphm[2] = -1; return pNew; } #else Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ assert( p==0 ); return 0; } | > | 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 | pNew->iLimit = 0; pNew->iOffset = 0; pNew->selFlags = p->selFlags & ~SF_UsesEphemeral; pNew->pRightmost = 0; pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; pNew->addrOpenEphm[2] = -1; pNew->pWith = withDup(db, p->pWith); return pNew; } #else Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){ assert( p==0 ); return 0; } |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
663 664 665 666 667 668 669 | ** INSERT INTO <table1> SELECT * FROM <table2>; ** ** Then special optimizations can be applied that make the transfer ** very fast and which reduce fragmentation of indices. ** ** This is the 2nd template. */ | > | | 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 | ** INSERT INTO <table1> SELECT * FROM <table2>; ** ** Then special optimizations can be applied that make the transfer ** very fast and which reduce fragmentation of indices. ** ** This is the 2nd template. */ if( pColumn==0 && pParse->pWith==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){ assert( !pTrigger ); assert( pList==0 ); goto insert_end; } #endif /* SQLITE_OMIT_XFER_OPT */ /* If this is an AUTOINCREMENT table, look up the sequence number in the |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
408 409 410 411 412 413 414 | %type select {Select*} %destructor select {sqlite3SelectDelete(pParse->db, $$);} %type selectnowith {Select*} %destructor selectnowith {sqlite3SelectDelete(pParse->db, $$);} %type oneselect {Select*} %destructor oneselect {sqlite3SelectDelete(pParse->db, $$);} | | | 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 | %type select {Select*} %destructor select {sqlite3SelectDelete(pParse->db, $$);} %type selectnowith {Select*} %destructor selectnowith {sqlite3SelectDelete(pParse->db, $$);} %type oneselect {Select*} %destructor oneselect {sqlite3SelectDelete(pParse->db, $$);} select(A) ::= with(W) selectnowith(X). { if( X ) X->pWith = W; A = X; } selectnowith(A) ::= oneselect(X). {A = X;} %ifndef SQLITE_OMIT_COMPOUND_SELECT selectnowith(A) ::= selectnowith(X) multiselect_op(Y) oneselect(Z). { if( Z ){ Z->op = (u8)Y; Z->pPrior = X; |
︙ | ︙ | |||
648 649 650 651 652 653 654 | {A.pLimit = X.pExpr; A.pOffset = Y.pExpr;} limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). {A.pOffset = X.pExpr; A.pLimit = Y.pExpr;} /////////////////////////// The DELETE statement ///////////////////////////// // %ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT | | > | > | 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 | {A.pLimit = X.pExpr; A.pOffset = Y.pExpr;} limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). {A.pOffset = X.pExpr; A.pLimit = Y.pExpr;} /////////////////////////// The DELETE statement ///////////////////////////// // %ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W) orderby_opt(O) limit_opt(L). { sqlite3WithPush(pParse,C); sqlite3SrcListIndexedBy(pParse, X, &I); W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "DELETE"); sqlite3DeleteFrom(pParse,X,W); } %endif %ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W). { sqlite3WithPush(pParse,C); sqlite3SrcListIndexedBy(pParse, X, &I); sqlite3DeleteFrom(pParse,X,W); } %endif %type where_opt {Expr*} %destructor where_opt {sqlite3ExprDelete(pParse->db, $$);} |
︙ | ︙ | |||
680 681 682 683 684 685 686 | sqlite3SrcListIndexedBy(pParse, X, &I); sqlite3ExprListCheckLength(pParse,Y,"set list"); W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "UPDATE"); sqlite3Update(pParse,X,Y,W,R); } %endif %ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT | | > | > | > | > > | > | 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 | sqlite3SrcListIndexedBy(pParse, X, &I); sqlite3ExprListCheckLength(pParse,Y,"set list"); W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "UPDATE"); sqlite3Update(pParse,X,Y,W,R); } %endif %ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y) where_opt(W). { sqlite3WithPush(pParse, C); sqlite3SrcListIndexedBy(pParse, X, &I); sqlite3ExprListCheckLength(pParse,Y,"set list"); sqlite3Update(pParse,X,Y,W,R); } %endif %type setlist {ExprList*} %destructor setlist {sqlite3ExprListDelete(pParse->db, $$);} setlist(A) ::= setlist(Z) COMMA nm(X) EQ expr(Y). { A = sqlite3ExprListAppend(pParse, Z, Y.pExpr); sqlite3ExprListSetName(pParse, A, &X, 1); } setlist(A) ::= nm(X) EQ expr(Y). { A = sqlite3ExprListAppend(pParse, 0, Y.pExpr); sqlite3ExprListSetName(pParse, A, &X, 1); } ////////////////////////// The INSERT command ///////////////////////////////// // cmd ::= with(W) insert_cmd(R) INTO fullname(X) inscollist_opt(F) select(S). { sqlite3WithPush(pParse, W); sqlite3Insert(pParse, X, S, F, R); } cmd ::= with(W) insert_cmd(R) INTO fullname(X) inscollist_opt(F) DEFAULT VALUES. { sqlite3WithPush(pParse, W); sqlite3Insert(pParse, X, 0, F, R); } %type insert_cmd {u8} insert_cmd(A) ::= INSERT orconf(R). {A = R;} insert_cmd(A) ::= REPLACE. {A = OE_Replace;} %type inscollist_opt {IdList*} %destructor inscollist_opt {sqlite3IdListDelete(pParse->db, $$);} |
︙ | ︙ | |||
1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 | %endif SQLITE_OMIT_VIRTUALTABLE //////////////////////// COMMON TABLE EXPRESSIONS //////////////////////////// %type with {With*} %type wqlist {With*} %destructor with {sqlite3WithDelete(pParse->db, $$);} with(A) ::= . {A = 0;} %ifndef SQLITE_OMIT_CTE with(A) ::= WITH wqlist(W). { A = W; } with(A) ::= WITH RECURSIVE wqlist(W). { A = W; } | > | | | 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 | %endif SQLITE_OMIT_VIRTUALTABLE //////////////////////// COMMON TABLE EXPRESSIONS //////////////////////////// %type with {With*} %type wqlist {With*} %destructor with {sqlite3WithDelete(pParse->db, $$);} %destructor wqlist {sqlite3WithDelete(pParse->db, $$);} with(A) ::= . {A = 0;} %ifndef SQLITE_OMIT_CTE with(A) ::= WITH wqlist(W). { A = W; } with(A) ::= WITH RECURSIVE wqlist(W). { A = W; } wqlist(A) ::= nm(X) idxlist_opt(Y) AS LP select(Z) RP. { A = sqlite3WithAdd(pParse, 0, &X, Y, Z); } wqlist(A) ::= wqlist(W) COMMA nm(X) idxlist_opt(Y) AS LP select(Z) RP. { A = sqlite3WithAdd(pParse, W, &X, Y, Z); } %endif SQLITE_OMIT_CTE |
Changes to src/select.c.
︙ | ︙ | |||
25 26 27 28 29 30 31 32 33 34 35 36 37 38 | sqlite3ExprDelete(db, p->pWhere); sqlite3ExprListDelete(db, p->pGroupBy); sqlite3ExprDelete(db, p->pHaving); sqlite3ExprListDelete(db, p->pOrderBy); sqlite3SelectDelete(db, p->pPrior); sqlite3ExprDelete(db, p->pLimit); sqlite3ExprDelete(db, p->pOffset); } /* ** Initialize a SelectDest structure. */ void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){ pDest->eDest = (u8)eDest; | > | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | sqlite3ExprDelete(db, p->pWhere); sqlite3ExprListDelete(db, p->pGroupBy); sqlite3ExprDelete(db, p->pHaving); sqlite3ExprListDelete(db, p->pOrderBy); sqlite3SelectDelete(db, p->pPrior); sqlite3ExprDelete(db, p->pLimit); sqlite3ExprDelete(db, p->pOffset); sqlite3WithDelete(db, p->pWith); } /* ** Initialize a SelectDest structure. */ void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){ pDest->eDest = (u8)eDest; |
︙ | ︙ | |||
3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 | pNew->pHaving = 0; pNew->pOrderBy = 0; p->pPrior = 0; pNew->pLimit = 0; pNew->pOffset = 0; return WRC_Continue; } /* ** This routine is a Walker callback for "expanding" a SELECT statement. ** "Expanding" means to do the following: ** ** (1) Make sure VDBE cursor numbers have been assigned to every ** element of the FROM clause. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 | pNew->pHaving = 0; pNew->pOrderBy = 0; p->pPrior = 0; pNew->pLimit = 0; pNew->pOffset = 0; return WRC_Continue; } static struct Cte *searchWith(Parse *pParse, struct SrcList_item *p){ if( p->zDatabase==0 ){ char *zName = p->zName; With *pWith; for(pWith=pParse->pWith; pWith; pWith=pWith->pOuter){ int i; for(i=0; i<pWith->nCte; i++){ if( sqlite3StrICmp(zName, pWith->a[i].zName)==0 ){ return &pWith->a[i]; } } } } return 0; } void sqlite3WithPush(Parse *pParse, With *pWith){ if( pWith ){ pWith->pOuter = pParse->pWith; pParse->pWith = pWith; } } static void withPop(Parse *pParse, With *pWith){ if( pWith ){ assert( pParse->pWith==pWith ); pParse->pWith = pWith->pOuter; } } static int ctePush(Parse *pParse, struct Cte *pCte){ if( pCte ){ struct Cte *p; for(p=pParse->pCte; p; p=p->pOuterCte){ if( p==pCte ){ sqlite3ErrorMsg( pParse, "illegal recursive defininition in cte: %s", pCte->zName ); return SQLITE_ERROR; } } pCte->pOuterCte = pParse->pCte; pParse->pCte = pCte; } return SQLITE_OK; } static void ctePop(Parse *pParse, struct Cte *pCte){ if( pCte ){ assert( pParse->pCte==pCte ); pParse->pCte = pCte->pOuterCte; } } /* ** This routine is a Walker callback for "expanding" a SELECT statement. ** "Expanding" means to do the following: ** ** (1) Make sure VDBE cursor numbers have been assigned to every ** element of the FROM clause. |
︙ | ︙ | |||
3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 | sqlite3SrcListAssignCursors(pParse, pTabList); /* Look up every table named in the FROM clause of the select. If ** an entry of the FROM clause is a subquery instead of a table or view, ** then create a transient table structure to describe the subquery. */ for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ Table *pTab; if( pFrom->pTab!=0 ){ /* This statement has already been prepared. There is no need ** to go further. */ assert( i==0 ); return WRC_Prune; } | > > > > > > > > | > > > > > > > > | | 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 | sqlite3SrcListAssignCursors(pParse, pTabList); /* Look up every table named in the FROM clause of the select. If ** an entry of the FROM clause is a subquery instead of a table or view, ** then create a transient table structure to describe the subquery. */ for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ struct Cte *pCte = 0; Table *pTab; if( pFrom->pTab!=0 ){ /* This statement has already been prepared. There is no need ** to go further. */ assert( i==0 ); return WRC_Prune; } #ifndef SQLITE_OMIT_CTE pCte = searchWith(pParse, pFrom); if( pCte ){ pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0); if( pFrom->pSelect==0 ) return WRC_Abort; } #endif if( pFrom->zName==0 || pCte ){ #ifndef SQLITE_OMIT_SUBQUERY ExprList *pEList; Select *pSel = pFrom->pSelect; /* A sub-query in the FROM clause of a SELECT */ assert( pSel!=0 ); assert( pFrom->pTab==0 ); if( ctePush(pParse, pCte) ) return WRC_Abort; sqlite3WalkSelect(pWalker, pSel); ctePop(pParse, pCte); pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); if( pTab==0 ) return WRC_Abort; pTab->nRef = 1; pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab); while( pSel->pPrior ){ pSel = pSel->pPrior; } if( pCte && pCte->pCols ){ pEList = pCte->pCols; }else{ pEList = pSel->pEList; } selectColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol); pTab->iPKey = -1; pTab->nRowEst = 1048576; pTab->tabFlags |= TF_Ephemeral; #endif }else{ /* An ordinary table or view name in the FROM clause */ assert( pFrom->pTab==0 ); |
︙ | ︙ | |||
3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 | #if SQLITE_MAX_COLUMN if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ sqlite3ErrorMsg(pParse, "too many columns in result set"); } #endif return WRC_Continue; } /* ** No-op routine for the parse-tree walker. ** ** When this routine is the Walker.xExprCallback then expression trees ** are walked without any actions being taken at each node. Presumably, ** when this routine is used for Walker.xExprCallback then | > > > > > > > > | 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 | #if SQLITE_MAX_COLUMN if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ sqlite3ErrorMsg(pParse, "too many columns in result set"); } #endif return WRC_Continue; } static int selectExpanderWith(Walker *pWalker, Select *p){ int res; sqlite3WithPush(pWalker->pParse, p->pWith); res = selectExpander(pWalker, p); withPop(pWalker->pParse, p->pWith); return res; } /* ** No-op routine for the parse-tree walker. ** ** When this routine is the Walker.xExprCallback then expression trees ** are walked without any actions being taken at each node. Presumably, ** when this routine is used for Walker.xExprCallback then |
︙ | ︙ | |||
3711 3712 3713 3714 3715 3716 3717 | memset(&w, 0, sizeof(w)); w.xExprCallback = exprWalkNoop; w.pParse = pParse; if( pParse->hasCompound ){ w.xSelectCallback = convertCompoundSelectToSubquery; sqlite3WalkSelect(&w, pSelect); } | | | 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 | memset(&w, 0, sizeof(w)); w.xExprCallback = exprWalkNoop; w.pParse = pParse; if( pParse->hasCompound ){ w.xSelectCallback = convertCompoundSelectToSubquery; sqlite3WalkSelect(&w, pSelect); } w.xSelectCallback = selectExpanderWith; sqlite3WalkSelect(&w, pSelect); } #ifndef SQLITE_OMIT_SUBQUERY /* ** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo() |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 | Expr *pHaving; /* The HAVING clause */ ExprList *pOrderBy; /* The ORDER BY clause */ Select *pPrior; /* Prior select in a compound select statement */ Select *pNext; /* Next select to the left in a compound */ Select *pRightmost; /* Right-most select in a compound select statement */ Expr *pLimit; /* LIMIT expression. NULL means not used. */ Expr *pOffset; /* OFFSET expression. NULL means not used. */ }; /* ** Allowed values for Select.selFlags. The "SF" prefix stands for ** "Select Flag". */ #define SF_Distinct 0x0001 /* Output should be DISTINCT */ | > | 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 | Expr *pHaving; /* The HAVING clause */ ExprList *pOrderBy; /* The ORDER BY clause */ Select *pPrior; /* Prior select in a compound select statement */ Select *pNext; /* Next select to the left in a compound */ Select *pRightmost; /* Right-most select in a compound select statement */ Expr *pLimit; /* LIMIT expression. NULL means not used. */ Expr *pOffset; /* OFFSET expression. NULL means not used. */ With *pWith; /* WITH clause attached to this select. Or NULL. */ }; /* ** Allowed values for Select.selFlags. The "SF" prefix stands for ** "Select Flag". */ #define SF_Distinct 0x0001 /* Output should be DISTINCT */ |
︙ | ︙ | |||
2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 | Token sLastToken; /* The last token parsed */ #ifndef SQLITE_OMIT_VIRTUALTABLE Token sArg; /* Complete text of a module argument */ Table **apVtabLock; /* Pointer to virtual tables needing locking */ #endif Table *pZombieTab; /* List of Table objects to delete after code gen */ TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ }; /* ** Return true if currently inside an sqlite3_declare_vtab() call. */ #ifdef SQLITE_OMIT_VIRTUALTABLE #define IN_DECLARE_VTAB 0 | > > | 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 | Token sLastToken; /* The last token parsed */ #ifndef SQLITE_OMIT_VIRTUALTABLE Token sArg; /* Complete text of a module argument */ Table **apVtabLock; /* Pointer to virtual tables needing locking */ #endif Table *pZombieTab; /* List of Table objects to delete after code gen */ TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ With *pWith; /* Current WITH clause, or NULL */ struct Cte *pCte; /* Current CTE, or NULL */ }; /* ** Return true if currently inside an sqlite3_declare_vtab() call. */ #ifdef SQLITE_OMIT_VIRTUALTABLE #define IN_DECLARE_VTAB 0 |
︙ | ︙ | |||
2634 2635 2636 2637 2638 2639 2640 2641 | /* ** An instance of this structure represents a set of CTEs (common table ** expressions) created by a single WITH clause. */ struct With { int nCte; /* Number of CTEs */ struct Cte { | > | | > | 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 | /* ** An instance of this structure represents a set of CTEs (common table ** expressions) created by a single WITH clause. */ struct With { int nCte; /* Number of CTEs */ With *pOuter; /* Containing WITH clause, or NULL */ struct Cte { char *zName; /* Name of this CTE */ ExprList *pCols; /* List of explicit column names, or NULL */ Select *pSelect; /* The contents of the CTE */ struct Cte *pOuterCte; } a[1]; }; /* ** Assuming zIn points to the first byte of a UTF-8 character, ** advance zIn to point to the first byte of the next UTF-8 character. */ |
︙ | ︙ | |||
3340 3341 3342 3343 3344 3345 3346 | int sqlite3TempInMemory(const sqlite3*); const char *sqlite3JournalModename(int); #ifndef SQLITE_OMIT_WAL int sqlite3Checkpoint(sqlite3*, int, int, int*, int*); int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int); #endif #ifndef SQLITE_OMIT_CTE | | > > > | 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 | int sqlite3TempInMemory(const sqlite3*); const char *sqlite3JournalModename(int); #ifndef SQLITE_OMIT_WAL int sqlite3Checkpoint(sqlite3*, int, int, int*, int*); int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int); #endif #ifndef SQLITE_OMIT_CTE With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*); void sqlite3WithDelete(sqlite3*,With*); void sqlite3WithPush(Parse*, With*); #else #define sqlite3WithPush(x,y) #endif /* Declarations for functions in fkey.c. All of these are replaced by ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign ** key functionality is available. If OMIT_TRIGGER is defined but ** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In ** this case foreign keys are parsed, but no other functionality is |
︙ | ︙ |
Changes to src/tokenize.c.
︙ | ︙ | |||
490 491 492 493 494 495 496 497 498 499 500 501 502 503 | /* If the pParse->declareVtab flag is set, do not delete any table ** structure built up in pParse->pNewTable. The calling code (see vtab.c) ** will take responsibility for freeing the Table structure. */ sqlite3DeleteTable(db, pParse->pNewTable); } sqlite3DeleteTrigger(db, pParse->pNewTrigger); for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]); sqlite3DbFree(db, pParse->azVar); while( pParse->pAinc ){ AutoincInfo *p = pParse->pAinc; pParse->pAinc = p->pNext; sqlite3DbFree(db, p); | > > | 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 | /* If the pParse->declareVtab flag is set, do not delete any table ** structure built up in pParse->pNewTable. The calling code (see vtab.c) ** will take responsibility for freeing the Table structure. */ sqlite3DeleteTable(db, pParse->pNewTable); } assert( pParse->pWith==0 || pParse->pWith->pOuter==0 ); sqlite3WithDelete(db, pParse->pWith); sqlite3DeleteTrigger(db, pParse->pNewTrigger); for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]); sqlite3DbFree(db, pParse->azVar); while( pParse->pAinc ){ AutoincInfo *p = pParse->pAinc; pParse->pAinc = p->pNext; sqlite3DbFree(db, p); |
︙ | ︙ |
Changes to test/pagerfault.test.
︙ | ︙ | |||
59 60 61 62 63 64 65 66 67 68 69 70 71 72 | } -test { faultsim_test_result {0 4} faultsim_integrity_check if {[db one { SELECT count(*) FROM t1 }] != 4} { error "Database content appears incorrect" } } #------------------------------------------------------------------------- # Test fault-injection while rolling back a hot-journal file with a # page-size different from the current value stored on page 1 of the # database file. # do_test pagerfault-2-pre1 { | > | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | } -test { faultsim_test_result {0 4} faultsim_integrity_check if {[db one { SELECT count(*) FROM t1 }] != 4} { error "Database content appears incorrect" } } finish_test #------------------------------------------------------------------------- # Test fault-injection while rolling back a hot-journal file with a # page-size different from the current value stored on page 1 of the # database file. # do_test pagerfault-2-pre1 { |
︙ | ︙ |
Changes to test/with1.test.
︙ | ︙ | |||
33 34 35 36 37 38 39 40 | WITH x(a) AS ( SELECT * FROM t1) DELETE FROM t1; } {} do_execsql_test 1.4 { WITH x(a) AS ( SELECT * FROM t1) UPDATE t1 SET x = y; } {} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | WITH x(a) AS ( SELECT * FROM t1) DELETE FROM t1; } {} do_execsql_test 1.4 { WITH x(a) AS ( SELECT * FROM t1) UPDATE t1 SET x = y; } {} #-------------------------------------------------------------------------- do_execsql_test 2.1 { DROP TABLE IF EXISTS t1; CREATE TABLE t1(x); INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(2); WITH tmp AS ( SELECT * FROM t1 ) SELECT x FROM tmp; } {1 2} do_execsql_test 2.2 { WITH tmp(a) AS ( SELECT * FROM t1 ) SELECT a FROM tmp; } {1 2} do_execsql_test 2.3 { SELECT * FROM ( WITH tmp(a) AS ( SELECT * FROM t1 ) SELECT a FROM tmp ); } {1 2} do_execsql_test 2.4 { WITH tmp1(a) AS ( SELECT * FROM t1 ), tmp2(x) AS ( SELECT * FROM tmp1) SELECT * FROM tmp2; } {1 2} do_execsql_test 2.5 { WITH tmp2(x) AS ( SELECT * FROM tmp1), tmp1(a) AS ( SELECT * FROM t1 ) SELECT * FROM tmp2; } {1 2} #------------------------------------------------------------------------- do_catchsql_test 3.1 { WITH tmp2(x) AS ( SELECT * FROM tmp1), tmp1(a) AS ( SELECT * FROM tmp2 ) SELECT * FROM tmp1; } {1 {illegal recursive defininition in cte: tmp1}} do_catchsql_test 3.2 { CREATE TABLE t2(x INTEGER); WITH tmp(a) AS (SELECT * FROM t1), tmp(a) AS (SELECT * FROM t1) SELECT * FROM tmp; } {1 {duplicate cte name: tmp}} do_execsql_test 3.3 { CREATE TABLE t3(x); CREATE TABLE t4(x); INSERT INTO t3 VALUES('T3'); INSERT INTO t4 VALUES('T4'); WITH t3(a) AS (SELECT * FROM t4) SELECT * FROM t3; } {T4} do_execsql_test 3.4 { WITH tmp AS ( SELECT * FROM t3 ), tmp2 AS ( WITH tmp AS ( SELECT * FROM t4 ) SELECT * FROM tmp ) SELECT * FROM tmp2; } {T4} do_execsql_test 3.5 { WITH tmp AS ( SELECT * FROM t3 ), tmp2 AS ( WITH xxxx AS ( SELECT * FROM t4 ) SELECT * FROM tmp ) SELECT * FROM tmp2; } {T3} do_catchsql_test 3.6 { WITH tmp AS ( SELECT * FROM t3 ), SELECT * FROM tmp; } {1 {near "SELECT": syntax error}} #------------------------------------------------------------------------- do_execsql_test 4.1 { DROP TABLE IF EXISTS t1; CREATE TABLE t1(x); INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(2); INSERT INTO t1 VALUES(3); INSERT INTO t1 VALUES(4); WITH dset AS ( SELECT 2 UNION ALL SELECT 4 ) DELETE FROM t1 WHERE x IN dset; SELECT * FROM t1; } {1 3} do_execsql_test 4.2 { WITH iset AS ( SELECT 2 UNION ALL SELECT 4 ) INSERT INTO t1 SELECT * FROM iset; SELECT * FROM t1; } {1 3 2 4} do_execsql_test 4.3 { WITH uset(a, b) AS ( SELECT 2, 8 UNION ALL SELECT 4, 9 ) UPDATE t1 SET x = COALESCE( (SELECT b FROM uset WHERE a=x), x ); SELECT * FROM t1; } {1 3 8 9} finish_test |
Added test/withM.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | # 2014 January 11 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the WITH clause. # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl set ::testprefix withM do_execsql_test 1.0 { CREATE TABLE t1(x INTEGER, y INTEGER); INSERT INTO t1 VALUES(123, 456); } do_faultsim_test withM-1 -prep { sqlite3 db test.db } -body { execsql { WITH tmp AS ( SELECT * FROM t1 ) SELECT * FROM tmp; } } -test { faultsim_test_result {0 {123 456}} db close } finish_test |