/ Check-in [3908e2ea]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fixes so that SQLITE_OMIT_CTE builds work.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | common-table-expr
Files: files | file ages | folders
SHA1: 3908e2ea2e7e5f466cbbbffdc27e0fe8dc9751ac
User & Date: dan 2014-01-15 19:42:23
Context
2014-01-15
20:10
Remove an ALWAYS() that is no longer always true. check-in: c95823cd user: drh tags: common-table-expr
19:42
Fixes so that SQLITE_OMIT_CTE builds work. check-in: 3908e2ea user: dan tags: common-table-expr
18:35
Further comments on WITH-clause processing routines in select.c. check-in: c948384d user: drh tags: common-table-expr
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

896
897
898
899
900
901
902

903
904
905
906
907
908
909
...
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->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
...
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->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
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
....
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
....
1860
1861
1862
1863
1864
1865
1866






1867
1868
1869
1870
1871
1872
1873
....
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
....
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
....
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
....
3619
3620
3621
3622
3623
3624
3625

3626
3627
3628
3629
3630
3631
3632
....
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693

3694
3695
3696
3697
3698
3699
3700
....
3913
3914
3915
3916
3917
3918
3919









3920

3921
3922
3923
3924




3925
3926



3927
3928
3929
3930
3931
3932
3933
      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;
  }

  /* Compound SELECTs that have an ORDER BY clause are handled separately.
  */
  if( p->pOrderBy ){
    return multiSelectOrderBy(pParse, p, pDest);
  }

#ifndef SQLITE_OMIT_CTE
  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 */
................................................................................
      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 teturn 
    ** 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);
................................................................................
    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;
................................................................................
  pNew->pOrderBy = 0;
  p->pPrior = 0;
  pNew->pLimit = 0;
  pNew->pOffset = 0;
  return WRC_Continue;
}

/* If the table identified by FROM clause element p is really



** a common-table-expression (CTE) then return a pointer to the
** CTE definition for that table.

*/
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;
  }
}

/* Push or pull a CTE on the stack of all CTEs currently being
** coded.
*/
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
................................................................................
    }
    
    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;
  }
}
















static int withExpand(
  Walker *pWalker, 
  struct SrcList_item *pFrom,
  struct Cte *pCte
){
  Table *pTab;
  Parse *pParse = pWalker->pParse;
  sqlite3 *db = pParse->db;


  assert( pFrom->pSelect==0 );
  assert( pFrom->pTab==0 );




  if( pCte==pParse->pCte && (pTab = pCte->pTab) ){
    /* This is the recursive part of a recursive CTE */
    assert( pFrom->pTab==0 && pFrom->isRecursive==0 );
    pFrom->pTab = pTab;
    pFrom->isRecursive = 1;
    pTab->nRef++;
  }else{
    ExprList *pEList;
    Select *pSel;
    Select *pLeft;                /* Left-most SELECT statement */
................................................................................
    }

    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.
................................................................................
  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 ){
      if( withExpand(pWalker, pFrom, pCte) ) return WRC_Abort;
    }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 );
................................................................................
  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 







>










<
<
<
<
<
<
<







 







|







 







>
>
>
>
>
>







 







|
>
>
>
|
|
>

|
|
|
|
<
<
>

|
|
|







 







|
|
|
|
|
|
|
|
|
|







 







>
>
>
>
>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|
<




>

<


>
>
>
|

|







 







>







 







<








<
<
|
<
>







 







>
>
>
>
>
>
>
>
>

>

|

<
>
>
>
>


>
>
>







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
....
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
....
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
....
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
....
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
....
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
....
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
....
3700
3701
3702
3703
3704
3705
3706

3707
3708
3709
3710
3711
3712
3713
3714


3715

3716
3717
3718
3719
3720
3721
3722
3723
....
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
      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 */
................................................................................
      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);
................................................................................
    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;
................................................................................
  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;
}

................................................................................
*/
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
................................................................................
    }
    
    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 */
................................................................................
    }

    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.
................................................................................
  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 );
................................................................................
  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
....
3411
3412
3413
3414
3415
3416
3417

3418
3419
3420
3421
3422
3423
3424
      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: {
................................................................................
  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.
*/







>







 







>







3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
....
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
      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: {
................................................................................
  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 {