Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fixes so that SQLITE_OMIT_CTE builds work. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | common-table-expr |
Files: | files | file ages | folders |
SHA1: |
3908e2ea2e7e5f466cbbbffdc27e0fe8 |
User & Date: | dan 2014-01-15 19:42:23.894 |
Context
2014-01-15
| ||
20:10 | Remove an ALWAYS() that is no longer always true. (check-in: c95823cd45 user: drh tags: common-table-expr) | |
19:42 | Fixes so that SQLITE_OMIT_CTE builds work. (check-in: 3908e2ea2e user: dan tags: common-table-expr) | |
18:35 | Further comments on WITH-clause processing routines in select.c. (check-in: c948384dfd user: drh tags: common-table-expr) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
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 922 923 924 925 926 | } /* ** Create and return a deep copy of the object passed as the second ** argument. If an OOM condition is encountered, NULL is returned ** and the db->mallocFailed flag set. */ static 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. ** | > > > > | 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 922 923 924 925 926 927 928 929 930 | } /* ** Create and return a deep copy of the object passed as the second ** argument. If an OOM condition is encountered, NULL is returned ** and the db->mallocFailed flag set. */ #ifndef SQLITE_OMIT_CTE static 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; } #else # define withDup(x,y) 0 #endif /* ** 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. ** |
︙ | ︙ |
Changes to src/resolve.c.
︙ | ︙ | |||
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 | lookupname_end: if( cnt==1 ){ assert( pNC!=0 ); if( pExpr->op!=TK_AS ){ sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList); } /* If this expression reads a column value from a recursive CTE ** reference, then this is equivalent to reading from the outermost ** available name-context. */ if( pMatch && pMatch->isRecursive ){ while( pNC->pNext ) pNC = pNC->pNext; } /* Increment the nRef value on all name contexts from TopNC up to ** the point where the name matched. */ for(;;){ assert( pTopNC!=0 ); pTopNC->nRef++; if( pTopNC==pNC ) break; | > > | 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 | lookupname_end: if( cnt==1 ){ assert( pNC!=0 ); if( pExpr->op!=TK_AS ){ sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList); } #ifndef SQLITE_OMIT_CTE /* If this expression reads a column value from a recursive CTE ** reference, then this is equivalent to reading from the outermost ** available name-context. */ if( pMatch && pMatch->isRecursive ){ while( pNC->pNext ) pNC = pNC->pNext; } #endif /* Increment the nRef value on all name contexts from TopNC up to ** the point where the name matched. */ for(;;){ assert( pTopNC!=0 ); pTopNC->nRef++; if( pTopNC==pNC ) break; |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 | sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" " do not have the same number of result columns", selectOpName(p->op)); } rc = 1; goto multi_select_end; } /* If this is a recursive query, check that there is no ORDER BY or ** LIMIT clause. Neither of these are supported. */ assert( p->pOffset==0 || p->pLimit ); if( p->pRecurse && (p->pOrderBy || p->pLimit) ){ sqlite3ErrorMsg(pParse, "%s in a recursive query is not allowed", p->pOrderBy ? "ORDER BY" : "LIMIT" ); goto multi_select_end; } | > < < < < < < < | 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 | sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" " do not have the same number of result columns", selectOpName(p->op)); } rc = 1; goto multi_select_end; } #ifndef SQLITE_OMIT_CTE /* If this is a recursive query, check that there is no ORDER BY or ** LIMIT clause. Neither of these are supported. */ assert( p->pOffset==0 || p->pLimit ); if( p->pRecurse && (p->pOrderBy || p->pLimit) ){ sqlite3ErrorMsg(pParse, "%s in a recursive query is not allowed", p->pOrderBy ? "ORDER BY" : "LIMIT" ); goto multi_select_end; } if( p->pRecurse ){ int nCol = p->pEList->nExpr; int addrNext; int addrSwap; int iCont, iBreak; int tmp1, tmp2; /* Cursors used to access temporary tables */ int tmp3 = 0; /* To ensure unique results if UNION */ |
︙ | ︙ | |||
1834 1835 1836 1837 1838 1839 1840 | p->selFlags |= SF_UsesEphemeral; } /* Store the results of the initial SELECT in tmp2. */ rc = sqlite3Select(pParse, pPrior, &tmp2dest); if( rc ) goto multi_select_end; | | | 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 | p->selFlags |= SF_UsesEphemeral; } /* Store the results of the initial SELECT in tmp2. */ rc = sqlite3Select(pParse, pPrior, &tmp2dest); if( rc ) goto multi_select_end; /* Clear tmp1. Then switch the contents of tmp1 and tmp2. Then return ** the contents of tmp1 to the caller. Or, if tmp1 is empty at this ** point, the recursive query has finished - jump to address iBreak. */ addrSwap = sqlite3VdbeAddOp2(v, OP_SwapCursors, tmp1, tmp2); sqlite3VdbeAddOp2(v, OP_Rewind, tmp1, iBreak); addrNext = sqlite3VdbeCurrentAddr(v); selectInnerLoop(pParse, p, p->pEList, tmp1, p->pEList->nExpr, 0, 0, &dest, iCont, iBreak); |
︙ | ︙ | |||
1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 | p->pPrior = pPrior; if( rc ) goto multi_select_end; sqlite3VdbeAddOp2(v, OP_Goto, 0, addrSwap); sqlite3VdbeResolveLabel(v, iBreak); }else #endif /* Generate code for the left and right SELECT statements. */ switch( p->op ){ case TK_ALL: { int addr = 0; int nLimit; | > > > > > > | 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 | p->pPrior = pPrior; if( rc ) goto multi_select_end; sqlite3VdbeAddOp2(v, OP_Goto, 0, addrSwap); sqlite3VdbeResolveLabel(v, iBreak); }else #endif /* Compound SELECTs that have an ORDER BY clause are handled separately. */ if( p->pOrderBy ){ return multiSelectOrderBy(pParse, p, pDest); }else /* Generate code for the left and right SELECT statements. */ switch( p->op ){ case TK_ALL: { int addr = 0; int nLimit; |
︙ | ︙ | |||
3478 3479 3480 3481 3482 3483 3484 | pNew->pOrderBy = 0; p->pPrior = 0; pNew->pLimit = 0; pNew->pOffset = 0; return WRC_Continue; } | > > > | | | > | | | | | < | | | < < < < | < | > | > > | > > | > > > > > > > > > > > > > > > > > > > > | < > < > > > | | | 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 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 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 | pNew->pOrderBy = 0; p->pPrior = 0; pNew->pLimit = 0; pNew->pOffset = 0; return WRC_Continue; } #ifndef SQLITE_OMIT_CTE /* ** Argument pWith (which may be NULL) points to a linked list of nested ** WITH contexts, from inner to outermost. If the table identified by ** FROM clause element pItem is really a common-table-expression (CTE) ** then return a pointer to the CTE definition for that table. Otherwise ** return NULL. */ static struct Cte *searchWith(With *pWith, struct SrcList_item *pItem){ if( pItem->zDatabase==0 ){ const char *zName = pItem->zName; With *p; for(p=pWith; p; p=p->pOuter){ int i; for(i=0; i<p->nCte; i++){ if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){ return &p->a[i]; } } } } return 0; } /* The code generator maintains a stack of active WITH clauses ** with the inner-most WITH clause being at the top of the stack. ** ** These routines push and pull WITH clauses on the stack. */ void sqlite3WithPush(Parse *pParse, With *pWith){ if( pWith ){ pWith->pOuter = pParse->pWith; pParse->pWith = pWith; } } /* ** If argument pCte is not NULL, check if it is already a part of the ** stack of CTEs stored by the parser. If so, this indicates an illegal ** recursive reference in a CTE, set of mutually recursive CTEs. Store ** an error in the parser and return SQLITE_ERROR if this is the case. ** ** Otherwise, if pCte is not already part of the stack of CTEs stored ** in the parser, push it onto the stop of that stack. */ 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; } /* ** If argument pCte is not NULL, it must be a pointer to the CTE currently ** on top of the stack of CTEs stored in the parser. Remove it from that ** stack. */ static void ctePop(Parse *pParse, struct Cte *pCte){ if( pCte ){ assert( pParse->pCte==pCte ); pParse->pCte = pCte->pOuterCte; } } /* ** This function checks if argument pFrom refers to a CTE declared by ** a WITH clause on the stack currently maintained by the parser. And, ** if currently processing a CTE expression, if it is a recursive ** reference to the current CTE. ** ** If pFrom falls into either of the two categories above, pFrom->pTab ** and other fields are populated accordingly. The caller should check ** (pFrom->pTab!=0) to determine whether or not a successful match ** was found. ** ** Whether or not a match is found, SQLITE_OK is returned if no error ** occurs. If an error does occur, an error message is stored in the ** parser and some error code other than SQLITE_OK returned. */ static int withExpand( Walker *pWalker, struct SrcList_item *pFrom ){ Table *pTab; Parse *pParse = pWalker->pParse; sqlite3 *db = pParse->db; struct Cte *pCte; assert( pFrom->pTab==0 ); pCte = searchWith(pParse->pWith, pFrom); if( pCte==0 ){ /* no-op */ }else if( pCte==pParse->pCte && (pTab = pCte->pTab) ){ /* This is the recursive part of a recursive CTE */ assert( pFrom->pTab==0 && pFrom->isRecursive==0 && pFrom->pSelect==0 ); pFrom->pTab = pTab; pFrom->isRecursive = 1; pTab->nRef++; }else{ ExprList *pEList; Select *pSel; Select *pLeft; /* Left-most SELECT statement */ |
︙ | ︙ | |||
3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 | } ctePop(pParse, pCte); } return SQLITE_OK; } /* ** 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. | > | 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 | } ctePop(pParse, pCte); } return SQLITE_OK; } #endif /* ** 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. |
︙ | ︙ | |||
3674 3675 3676 3677 3678 3679 3680 | 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++){ | < < < | | | 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 | 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; } #ifndef SQLITE_OMIT_CTE if( withExpand(pWalker, pFrom) ) return WRC_Abort; if( pFrom->pTab ) {} else #endif if( pFrom->zName==0 ){ #ifndef SQLITE_OMIT_SUBQUERY Select *pSel = pFrom->pSelect; /* A sub-query in the FROM clause of a SELECT */ assert( pSel!=0 ); assert( pFrom->pTab==0 ); |
︙ | ︙ | |||
3913 3914 3915 3916 3917 3918 3919 3920 3921 | 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; | > > > > > > > > > > | | > > > > > > | 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 | if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ sqlite3ErrorMsg(pParse, "too many columns in result set"); } #endif return WRC_Continue; } /* ** Function (or macro) selectExpanderWith is used as the SELECT callback ** by sqlite3SelectExpand(). In builds that do not support CTEs, this ** is equivalent to the selectExpander() function. In CTE-enabled builds, ** any WITH clause associated with the SELECT statement needs to be ** pushed onto the stack before calling selectExpander(), and popped ** off again afterwards. */ #ifndef SQLITE_OMIT_CTE static int selectExpanderWith(Walker *pWalker, Select *p){ Parse *pParse = pWalker->pParse; int res; sqlite3WithPush(pParse, p->pWith); res = selectExpander(pWalker, p); if( p->pWith ){ assert( pParse->pWith==p->pWith ); pParse->pWith = p->pWith->pOuter; } return res; } #else #define selectExpanderWith selectExpander #endif /* ** 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 |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 | #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 | > | 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 | #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) #define sqlite3WithDelete(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/test_config.c.
︙ | ︙ | |||
220 221 222 223 224 225 226 227 228 229 230 231 232 233 | #endif #ifdef SQLITE_OMIT_CHECK Tcl_SetVar2(interp, "sqlite_options", "check", "0", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "check", "1", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_ENABLE_COLUMN_METADATA Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "0", TCL_GLOBAL_ONLY); #endif | > > > > > > | 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | #endif #ifdef SQLITE_OMIT_CHECK Tcl_SetVar2(interp, "sqlite_options", "check", "0", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "check", "1", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_OMIT_CTE Tcl_SetVar2(interp, "sqlite_options", "cte", "0", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "cte", "1", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_ENABLE_COLUMN_METADATA Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "0", TCL_GLOBAL_ONLY); #endif |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 | pCx->isTable = 1; } } pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); break; } /* Opcode: OpenEphreader P1 P2 * * * ** ** P2 is a cursor opened by the OpenEphemeral opcode. This opcode opens ** a new read-only cursor named P1 that accesses the same epheremal table ** as P2. */ case OP_OpenEphreader: { | > | 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 | pCx->isTable = 1; } } pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); break; } #ifndef SQLITE_OMIT_CTE /* Opcode: OpenEphreader P1 P2 * * * ** ** P2 is a cursor opened by the OpenEphemeral opcode. This opcode opens ** a new read-only cursor named P1 that accesses the same epheremal table ** as P2. */ case OP_OpenEphreader: { |
︙ | ︙ | |||
3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 | pTmp = p->apCsr[pOp->p1]; p->apCsr[pOp->p1] = p->apCsr[pOp->p2]; p->apCsr[pOp->p2] = pTmp; rc = sqlite3BtreeClearTable(pTmp->pBt, MASTER_ROOT + !pTmp->isTable, 0); break; } /* Opcode: SorterOpen P1 * * P4 * ** ** This opcode works like OP_OpenEphemeral except that it opens ** a transient index that is specifically designed to sort large ** tables using an external merge-sort algorithm. */ | > | 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 | pTmp = p->apCsr[pOp->p1]; p->apCsr[pOp->p1] = p->apCsr[pOp->p2]; p->apCsr[pOp->p2] = pTmp; rc = sqlite3BtreeClearTable(pTmp->pBt, MASTER_ROOT + !pTmp->isTable, 0); break; } #endif /* ifndef SQLITE_OMIT_CTE */ /* Opcode: SorterOpen P1 * * P4 * ** ** This opcode works like OP_OpenEphemeral except that it opens ** a transient index that is specifically designed to sort large ** tables using an external merge-sort algorithm. */ |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 | struct SrcList_item *pTabItem; pTabItem = &pTabList->a[pLevel->iFrom]; pTab = pTabItem->pTab; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); pLoop = pLevel->pWLoop; if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){ if( pTab->tabFlags & TF_Recursive ){ int iCur = pTabItem->iCursor; sqlite3VdbeAddOp2(v, OP_OpenEphreader, iCur, pTab->tnum); } /* Otherwise do nothing */ }else #ifndef SQLITE_OMIT_VIRTUALTABLE if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){ const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); int iCur = pTabItem->iCursor; sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB); | > > | 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 | struct SrcList_item *pTabItem; pTabItem = &pTabList->a[pLevel->iFrom]; pTab = pTabItem->pTab; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); pLoop = pLevel->pWLoop; if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){ #ifndef SQLITE_OMIT_CTE if( pTab->tabFlags & TF_Recursive ){ int iCur = pTabItem->iCursor; sqlite3VdbeAddOp2(v, OP_OpenEphreader, iCur, pTab->tnum); } #endif /* Otherwise do nothing */ }else #ifndef SQLITE_OMIT_VIRTUALTABLE if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){ const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); int iCur = pTabItem->iCursor; sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB); |
︙ | ︙ |
Changes to test/with1.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # 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 set ::testprefix with1 do_execsql_test 1.0 { CREATE TABLE t1(x INTEGER, y INTEGER); WITH x(a) AS ( SELECT * FROM t1) SELECT 10 } {10} do_execsql_test 1.1 { | > > > > > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # 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 set ::testprefix with1 ifcapable {!cte} { finish_test return } do_execsql_test 1.0 { CREATE TABLE t1(x INTEGER, y INTEGER); WITH x(a) AS ( SELECT * FROM t1) SELECT 10 } {10} do_execsql_test 1.1 { |
︙ | ︙ |
Changes to test/withM.test.
︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # 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.1 -prep { | > > > > > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # 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 ifcapable {!cte} { finish_test return } do_execsql_test 1.0 { CREATE TABLE t1(x INTEGER, y INTEGER); INSERT INTO t1 VALUES(123, 456); } do_faultsim_test withM-1.1 -prep { |
︙ | ︙ |