SQLite

Changes On Branch with-generated-as
Login

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

Changes In Branch with-generated-as Excluding Merge-Ins

This is equivalent to a diff from 27d41179 to 78dcddd9

2021-02-16
20:43
Add experimental implementation of ALTER TABLE DROP COLUMN. Only some cases work so far. (check-in: f0217937 user: dan tags: alter-table-drop-column)
20:01
New SELECTTRACE macros more clearly deliniate when the query planner is invoked in the middle of PRAGMA vdbe_addoptrace output. (check-in: 7c03ce49 user: drh tags: trunk)
16:32
Trying to get the new AS MATERIALIZE syntax of CTEs to work. There are still performance and memory management issues. This is a WIP check-in. (check-in: bf0fd9b2 user: drh tags: as-materialize)
00:48
Change the syntax from "GENERATED AS" to "AS MATERIALIZED" so as to match the syntax of PostgreSQL 12+. (Closed-Leaf check-in: 78dcddd9 user: drh tags: with-generated-as)
2021-02-15
17:51
Merge the LIKE operator fix from trunk. (check-in: 8c861878 user: drh tags: with-generated-as)
17:02
Fix an issue with the LIKE operator when it includes the "ESCAPE '_'" clause. Ticket [c0aeea67d58ae0fd]. (check-in: 27d41179 user: drh tags: trunk)
14:32
Add tests for sqlite3_column_count(). (check-in: 7cc65ae5 user: dan tags: trunk)

Changes to src/build.c.

5200
5201
5202
5203
5204
5205
5206











































5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221





5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
      pKey = 0;
    }
  }
  return pKey;
}

#ifndef SQLITE_OMIT_CTE











































/* 
** 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 WITH table name: %s", zName);
      }
    }
  }

  if( pWith ){
    sqlite3_int64 nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte);
    pNew = sqlite3DbRealloc(db, pWith, nByte);
  }else{
    pNew = sqlite3DbMallocZero(db, sizeof(*pWith));
  }
  assert( (pNew!=0 && zName!=0) || db->mallocFailed );

  if( db->mallocFailed ){
    sqlite3ExprListDelete(db, pArglist);
    sqlite3SelectDelete(db, pQuery);
    sqlite3DbFree(db, zName);
    pNew = pWith;
  }else{
    pNew->a[pNew->nCte].pSelect = pQuery;
    pNew->a[pNew->nCte].pCols = pArglist;
    pNew->a[pNew->nCte].zName = zName;
    pNew->a[pNew->nCte].zCteErr = 0;
    pNew->nCte++;
  }

  return pNew;
}

/*
** Free the contents of the With object passed as the second argument.
*/
void sqlite3WithDelete(sqlite3 *db, With *pWith){







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







|
<
<





>
>
>
>
>


|















<


<
|
<


<
<
|
|


<







5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257


5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285

5286
5287

5288

5289
5290


5291
5292
5293
5294

5295
5296
5297
5298
5299
5300
5301
      pKey = 0;
    }
  }
  return pKey;
}

#ifndef SQLITE_OMIT_CTE
/*
** Create a new CTE object
*/
Cte *sqlite3CteNew(
  Parse *pParse,          /* Parsing context */
  Token *pName,           /* Name of the common-table */
  ExprList *pArglist,     /* Optional column name list for the table */
  Select *pQuery,         /* Query used to initialize the table */
  int eMaterialized       /* Force or prohibit materialization */
){
  Cte *pNew;
  sqlite3 *db = pParse->db;

  assert( eMaterialized==MAT_NotSpec || eMaterialized==MAT_Yes
            || eMaterialized==MAT_No );
  pNew = sqlite3DbMallocZero(db, sizeof(*pNew));
  assert( pNew!=0 || db->mallocFailed );

  if( db->mallocFailed ){
    sqlite3ExprListDelete(db, pArglist);
    sqlite3SelectDelete(db, pQuery);
  }else{
    pNew->pSelect = pQuery;
    pNew->pCols = pArglist;
    pNew->zName = sqlite3NameFromToken(pParse->db, pName);
    pNew->zCteErr = 0;
    pNew->eMaterialized = (u8)eMaterialized;
  }
  return pNew;
}

/*
** Free the contents of the CTE object passed as the second argument.
*/
void sqlite3CteDelete(sqlite3 *db, Cte *pCte){
  if( pCte ){
    sqlite3ExprListDelete(db, pCte->pCols);
    sqlite3SelectDelete(db, pCte->pSelect);
    sqlite3DbFree(db, pCte->zName);
    sqlite3DbFree(db, pCte);
  }
}

/* 
** 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 */
  Cte *pCte               /* The CTE to add to the WITH clause */


){
  sqlite3 *db = pParse->db;
  With *pNew;
  char *zName;


  if( pCte==0 ){
    return pWith;
  }

  /* Check that the CTE name is unique within this WITH clause. If
  ** not, store an error in the Parse structure. */
  zName = pCte->zName;
  if( zName && pWith ){
    int i;
    for(i=0; i<pWith->nCte; i++){
      if( sqlite3StrICmp(zName, pWith->a[i].zName)==0 ){
        sqlite3ErrorMsg(pParse, "duplicate WITH table name: %s", zName);
      }
    }
  }

  if( pWith ){
    sqlite3_int64 nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte);
    pNew = sqlite3DbRealloc(db, pWith, nByte);
  }else{
    pNew = sqlite3DbMallocZero(db, sizeof(*pWith));
  }


  if( db->mallocFailed ){

    sqlite3CteDelete(db, pCte);

    pNew = pWith;
  }else{


    pNew->a[pNew->nCte] = *pCte;
    sqlite3DbFree(db, pCte);
    pNew->nCte++;
  }

  return pNew;
}

/*
** Free the contents of the With object passed as the second argument.
*/
void sqlite3WithDelete(sqlite3 *db, With *pWith){

Changes to src/parse.y.

245
246
247
248
249
250
251



252
253
254
255
256
257
258
%endif SQLITE_OMIT_COMPOUND_SELECT
%ifndef SQLITE_OMIT_WINDOWFUNC
  CURRENT FOLLOWING PARTITION PRECEDING RANGE UNBOUNDED
  EXCLUDE GROUPS OTHERS TIES
%endif SQLITE_OMIT_WINDOWFUNC
%ifndef SQLITE_OMIT_GENERATED_COLUMNS
  GENERATED ALWAYS



%endif
  REINDEX RENAME CTIME_KW IF
  .
%wildcard ANY.

// Define operator precedence early so that this is the first occurrence
// of the operator tokens in the grammer.  Keeping the operators together







>
>
>







245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
%endif SQLITE_OMIT_COMPOUND_SELECT
%ifndef SQLITE_OMIT_WINDOWFUNC
  CURRENT FOLLOWING PARTITION PRECEDING RANGE UNBOUNDED
  EXCLUDE GROUPS OTHERS TIES
%endif SQLITE_OMIT_WINDOWFUNC
%ifndef SQLITE_OMIT_GENERATED_COLUMNS
  GENERATED ALWAYS
%endif
%ifndef SQLITE_OMIT_CTE
  MATERIALIZED
%endif
  REINDEX RENAME CTIME_KW IF
  .
%wildcard ANY.

// Define operator precedence early so that this is the first occurrence
// of the operator tokens in the grammer.  Keeping the operators together
1654
1655
1656
1657
1658
1659
1660



1661
1662
1663
1664
1665
1666






1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
anylist ::= anylist ANY.
%endif  SQLITE_OMIT_VIRTUALTABLE


//////////////////////// COMMON TABLE EXPRESSIONS ////////////////////////////
%type wqlist {With*}
%destructor wqlist {sqlite3WithDelete(pParse->db, $$);}




with ::= .
%ifndef SQLITE_OMIT_CTE
with ::= WITH wqlist(W).              { sqlite3WithPush(pParse, W, 1); }
with ::= WITH RECURSIVE wqlist(W).    { sqlite3WithPush(pParse, W, 1); }







wqlist(A) ::= nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
  A = sqlite3WithAdd(pParse, 0, &X, Y, Z); /*A-overwrites-X*/
}
wqlist(A) ::= wqlist(A) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
  A = sqlite3WithAdd(pParse, A, &X, Y, Z);
}
%endif  SQLITE_OMIT_CTE

//////////////////////// WINDOW FUNCTION EXPRESSIONS /////////////////////////
// These must be at the end of this file. Specifically, the rules that
// introduce tokens WINDOW, OVER and FILTER must appear last. This causes 
// the integer values assigned to these tokens to be larger than all other 







>
>
>






>
>
>
>
>
>
|
|

|
|







1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
anylist ::= anylist ANY.
%endif  SQLITE_OMIT_VIRTUALTABLE


//////////////////////// COMMON TABLE EXPRESSIONS ////////////////////////////
%type wqlist {With*}
%destructor wqlist {sqlite3WithDelete(pParse->db, $$);}
%type wqitem {Cte*}
%destructor wqitem {sqlite3CteDelete(pParse->db, $$);}
%type wqas {int}

with ::= .
%ifndef SQLITE_OMIT_CTE
with ::= WITH wqlist(W).              { sqlite3WithPush(pParse, W, 1); }
with ::= WITH RECURSIVE wqlist(W).    { sqlite3WithPush(pParse, W, 1); }

wqas(A)   ::= AS.                   {A=MAT_NotSpec;}
wqas(A)   ::= AS MATERIALIZED.      {A=MAT_Yes;}
//wqas(A) ::= AS NOT MATERIALIZED.  {A=MAT_No;}
wqitem(A) ::= nm(X) eidlist_opt(Y) wqas(F) LP select(Z) RP. {
  A = sqlite3CteNew(pParse, &X, Y, Z, F); /*A-overwrites-X*/
}
wqlist(A) ::= wqitem(X). {
  A = sqlite3WithAdd(pParse, 0, X); /*A-overwrites-X*/
}
wqlist(A) ::= wqlist(A) COMMA wqitem(X). {
  A = sqlite3WithAdd(pParse, A, X);
}
%endif  SQLITE_OMIT_CTE

//////////////////////// WINDOW FUNCTION EXPRESSIONS /////////////////////////
// These must be at the end of this file. Specifically, the rules that
// introduce tokens WINDOW, OVER and FILTER must appear last. This causes 
// the integer values assigned to these tokens to be larger than all other 

Changes to src/select.c.

4934
4935
4936
4937
4938
4939
4940



4941
4942
4943
4944
4945
4946
4947
    pTab->zName = sqlite3DbStrDup(db, pCte->zName);
    pTab->iPKey = -1;
    pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
    pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
    pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
    if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
    assert( pFrom->pSelect );




    /* Check if this is a recursive CTE. */
    pRecTerm = pSel = pFrom->pSelect;
    bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION );
    while( bMayRecursive && pRecTerm->op==pSel->op ){
      int i;
      SrcList *pSrc = pRecTerm->pSrc;







>
>
>







4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
    pTab->zName = sqlite3DbStrDup(db, pCte->zName);
    pTab->iPKey = -1;
    pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
    pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
    pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
    if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
    assert( pFrom->pSelect );
    if( pCte->eMaterialized==MAT_Yes ){
      pFrom->pSelect->selFlags |= SF_OptBarrier;
    }

    /* Check if this is a recursive CTE. */
    pRecTerm = pSel = pFrom->pSelect;
    bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION );
    while( bMayRecursive && pRecTerm->op==pSel->op ){
      int i;
      SrcList *pSrc = pRecTerm->pSrc;
6066
6067
6068
6069
6070
6071
6072



6073
6074
6075
6076
6077
6078
6079
     && (p->selFlags & SF_ComplexResult)!=0
     && (pTabList->nSrc==1
         || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0)
    ){
      continue;
    }




    if( flattenSubquery(pParse, p, i, isAgg) ){
      if( pParse->nErr ) goto select_end;
      /* This subquery can be absorbed into its parent. */
      i = -1;
    }
    pTabList = p->pSrc;
    if( db->mallocFailed ) goto select_end;







>
>
>







6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
     && (p->selFlags & SF_ComplexResult)!=0
     && (pTabList->nSrc==1
         || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0)
    ){
      continue;
    }

    /* Do not flatten across an optimization barrier */
    if( pSub->selFlags & SF_OptBarrier ) continue;

    if( flattenSubquery(pParse, p, i, isAgg) ){
      if( pParse->nErr ) goto select_end;
      /* This subquery can be absorbed into its parent. */
      i = -1;
    }
    pTabList = p->pSrc;
    if( db->mallocFailed ) goto select_end;
6190
6191
6192
6193
6194
6195
6196

6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219

6220
6221
6222




6223
6224
6225
6226

6227
6228
6229
6230
6231
6232
6233
    */
    pParse->nHeight += sqlite3SelectExprHeight(p);

    /* 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( OptimizationEnabled(db, SQLITE_PushDown)

     && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor,
                           (pItem->fg.jointype & JT_OUTER)!=0)
    ){
#if SELECTTRACE_ENABLED
      if( sqlite3SelectTrace & 0x100 ){
        SELECTTRACE(0x100,pParse,p,
            ("After WHERE-clause push-down into subquery %d:\n", pSub->selId));
        sqlite3TreeViewSelect(0, p, 0);
      }
#endif
      assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
    }else{
      SELECTTRACE(0x100,pParse,p,("Push-down not possible\n"));
    }

    zSavedAuthContext = pParse->zAuthContext;
    pParse->zAuthContext = pItem->zName;

    /* Generate code to implement the subquery
    **
    ** The subquery is implemented as a co-routine if the subquery is
    ** guaranteed to be the outer loop (so that it does not need to be
    ** computed more than once)

    **
    ** TODO: Are there other reasons beside (1) to use a co-routine
    ** implementation?




    */
    if( i==0
     && (pTabList->nSrc==1
            || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0)  /* (1) */

    ){
      /* Implement a co-routine that will return a single row of the result
      ** set on each invocation.
      */
      int addrTop = sqlite3VdbeCurrentAddr(v)+1;
     
      pItem->regReturn = ++pParse->nMem;







>




















|

|
>

|

>
>
>
>




>







6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
    */
    pParse->nHeight += sqlite3SelectExprHeight(p);

    /* 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( OptimizationEnabled(db, SQLITE_PushDown)
     && (pSub->selFlags & SF_OptBarrier)==0
     && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor,
                           (pItem->fg.jointype & JT_OUTER)!=0)
    ){
#if SELECTTRACE_ENABLED
      if( sqlite3SelectTrace & 0x100 ){
        SELECTTRACE(0x100,pParse,p,
            ("After WHERE-clause push-down into subquery %d:\n", pSub->selId));
        sqlite3TreeViewSelect(0, p, 0);
      }
#endif
      assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
    }else{
      SELECTTRACE(0x100,pParse,p,("Push-down not possible\n"));
    }

    zSavedAuthContext = pParse->zAuthContext;
    pParse->zAuthContext = pItem->zName;

    /* Generate code to implement the subquery
    **
    ** The subquery is implemented as a co-routine if (1) the subquery is
    ** guaranteed to be the outer loop (so that it does not need to be
    ** computed more than once) and if (2) the subquery is not optimization
    ** barrier.
    **
    ** TODO: Are there other reasons beside (1) and (2) to use a co-routine
    ** implementation?
    **
    ** TODO: We might should allow a subquery that is an optimization barrier
    ** to be implemented as a co-routine as long as we know that it is the
    ** only use of the subquery.
    */
    if( i==0
     && (pTabList->nSrc==1
            || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0)  /* (1) */
     && (pSub->selFlags & SF_OptBarrier)==0                         /* (2) */
    ){
      /* Implement a co-routine that will return a single row of the result
      ** set on each invocation.
      */
      int addrTop = sqlite3VdbeCurrentAddr(v)+1;
     
      pItem->regReturn = ++pParse->nMem;

Changes to src/sqliteInt.h.

1132
1133
1134
1135
1136
1137
1138

1139
1140
1141
1142
1143
1144
1145
*/
typedef struct AggInfo AggInfo;
typedef struct AuthContext AuthContext;
typedef struct AutoincInfo AutoincInfo;
typedef struct Bitvec Bitvec;
typedef struct CollSeq CollSeq;
typedef struct Column Column;

typedef struct Db Db;
typedef struct DbFixer DbFixer;
typedef struct Schema Schema;
typedef struct Expr Expr;
typedef struct ExprList ExprList;
typedef struct FKey FKey;
typedef struct FuncDestructor FuncDestructor;







>







1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
*/
typedef struct AggInfo AggInfo;
typedef struct AuthContext AuthContext;
typedef struct AutoincInfo AutoincInfo;
typedef struct Bitvec Bitvec;
typedef struct CollSeq CollSeq;
typedef struct Column Column;
typedef struct Cte Cte;
typedef struct Db Db;
typedef struct DbFixer DbFixer;
typedef struct Schema Schema;
typedef struct Expr Expr;
typedef struct ExprList ExprList;
typedef struct FKey FKey;
typedef struct FuncDestructor FuncDestructor;
3181
3182
3183
3184
3185
3186
3187

3188
3189
3190
3191
3192
3193
3194
#define SF_ComplexResult 0x0040000 /* Result contains subquery or function */
#define SF_WhereBegin    0x0080000 /* Really a WhereBegin() call.  Debug Only */
#define SF_WinRewrite    0x0100000 /* Window function rewrite accomplished */
#define SF_View          0x0200000 /* SELECT statement is a view */
#define SF_NoopOrderBy   0x0400000 /* ORDER BY is ignored for this query */
#define SF_UpdateFrom    0x0800000 /* Statement is an UPDATE...FROM */
#define SF_PushDown      0x1000000 /* SELECT has be modified by push-down opt */


/*
** The results of a SELECT can be distributed in several ways, as defined
** by one of the following macros.  The "SRT" prefix means "SELECT Result
** Type".
**
**     SRT_Union       Store results as a key in a temporary index







>







3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
#define SF_ComplexResult 0x0040000 /* Result contains subquery or function */
#define SF_WhereBegin    0x0080000 /* Really a WhereBegin() call.  Debug Only */
#define SF_WinRewrite    0x0100000 /* Window function rewrite accomplished */
#define SF_View          0x0200000 /* SELECT statement is a view */
#define SF_NoopOrderBy   0x0400000 /* ORDER BY is ignored for this query */
#define SF_UpdateFrom    0x0800000 /* Statement is an UPDATE...FROM */
#define SF_PushDown      0x1000000 /* SELECT has be modified by push-down opt */
#define SF_OptBarrier    0x2000000 /* SELECT is an optimization barrier */

/*
** The results of a SELECT can be distributed in several ways, as defined
** by one of the following macros.  The "SRT" prefix means "SELECT Result
** Type".
**
**     SRT_Union       Store results as a key in a temporary index
3863
3864
3865
3866
3867
3868
3869







3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881

3882




3883
3884
3885
3886
3887
3888
3889
** Return code from the parse-tree walking primitives and their
** callbacks.
*/
#define WRC_Continue    0   /* Continue down into children */
#define WRC_Prune       1   /* Omit children but continue walking siblings */
#define WRC_Abort       2   /* Abandon the tree walk */








/*
** An instance of this structure represents a set of one or more CTEs
** (common table expressions) created by a single WITH clause.
*/
struct With {
  int nCte;                       /* Number of CTEs in the WITH clause */
  With *pOuter;                   /* Containing WITH clause, or NULL */
  struct Cte {                    /* For each CTE in the WITH clause.... */
    char *zName;                    /* Name of this CTE */
    ExprList *pCols;                /* List of explicit column names, or NULL */
    Select *pSelect;                /* The definition of this CTE */
    const char *zCteErr;            /* Error message for circular references */

  } a[1];




};

#ifdef SQLITE_DEBUG
/*
** An instance of the TreeView object is used for printing the content of
** data structures on sqlite3DebugPrintf() using a tree-like view.
*/







>
>
>
>
>
>
>




|
<
<
<
|
|
|
|
>
|
>
>
>
>







3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883



3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
** Return code from the parse-tree walking primitives and their
** callbacks.
*/
#define WRC_Continue    0   /* Continue down into children */
#define WRC_Prune       1   /* Omit children but continue walking siblings */
#define WRC_Abort       2   /* Abandon the tree walk */

/*
** Allowed values for Cte.eMAterialized
*/
#define MAT_NotSpec     0   /* Not specified */
#define MAT_Yes         1   /* AS MATERIALIZED ... */
#define MAT_No          2   /* AS NOT MATERIALIZED.  Not currently used */

/*
** An instance of this structure represents a set of one or more CTEs
** (common table expressions) created by a single WITH clause.
*/
struct Cte {



  char *zName;                  /* Name of this CTE */
  ExprList *pCols;              /* List of explicit column names, or NULL */
  Select *pSelect;              /* The definition of this CTE */
  const char *zCteErr;          /* Error message for circular references */
  u8 eMaterialized;             /* One of the MAT_* values */
};
struct With {
  int nCte;                     /* Number of CTEs in the WITH clause */
  With *pOuter;                 /* Containing WITH clause, or NULL */
  Cte a[1];                     /* The CTEs of this WITH clause */
};

#ifdef SQLITE_DEBUG
/*
** An instance of the TreeView object is used for printing the content of
** data structures on sqlite3DebugPrintf() using a tree-like view.
*/
4879
4880
4881
4882
4883
4884
4885

4886

4887
4888
4889
4890
4891
4892
4893
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*, u8);
#else
#define sqlite3WithPush(x,y,z)
#define sqlite3WithDelete(x,y)
#endif
#ifndef SQLITE_OMIT_UPSERT







>
|
>







4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
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
  Cte *sqlite3CteNew(Parse*,Token*,ExprList*,Select*,int);
  With *sqlite3WithAdd(Parse*,With*,Cte*);
  void sqlite3CteDelete(sqlite3*,Cte*);
  void sqlite3WithDelete(sqlite3*,With*);
  void sqlite3WithPush(Parse*, With*, u8);
#else
#define sqlite3WithPush(x,y,z)
#define sqlite3WithDelete(x,y)
#endif
#ifndef SQLITE_OMIT_UPSERT

Changes to tool/mkkeywordhash.c.

225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
  { "FILTER",           "TK_FILTER",       WINDOWFUNC,       4      },
  { "FIRST",            "TK_FIRST",        ALWAYS,           4      },
  { "FOLLOWING",        "TK_FOLLOWING",    WINDOWFUNC,       4      },
  { "FOR",              "TK_FOR",          TRIGGER,          2      },
  { "FOREIGN",          "TK_FOREIGN",      FKEY,             1      },
  { "FROM",             "TK_FROM",         ALWAYS,           10     },
  { "FULL",             "TK_JOIN_KW",      ALWAYS,           3      },
  { "GENERATED",        "TK_GENERATED",    GENCOL,           1      },
  { "GLOB",             "TK_LIKE_KW",      ALWAYS,           3      },
  { "GROUP",            "TK_GROUP",        ALWAYS,           5      },
  { "GROUPS",           "TK_GROUPS",       WINDOWFUNC,       2      },
  { "HAVING",           "TK_HAVING",       ALWAYS,           5      },
  { "IF",               "TK_IF",           ALWAYS,           2      },
  { "IGNORE",           "TK_IGNORE",       CONFLICT|TRIGGER, 1      },
  { "IMMEDIATE",        "TK_IMMEDIATE",    ALWAYS,           1      },







|







225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
  { "FILTER",           "TK_FILTER",       WINDOWFUNC,       4      },
  { "FIRST",            "TK_FIRST",        ALWAYS,           4      },
  { "FOLLOWING",        "TK_FOLLOWING",    WINDOWFUNC,       4      },
  { "FOR",              "TK_FOR",          TRIGGER,          2      },
  { "FOREIGN",          "TK_FOREIGN",      FKEY,             1      },
  { "FROM",             "TK_FROM",         ALWAYS,           10     },
  { "FULL",             "TK_JOIN_KW",      ALWAYS,           3      },
  { "GENERATED",        "TK_GENERATED",    ALWAYS,           1      },
  { "GLOB",             "TK_LIKE_KW",      ALWAYS,           3      },
  { "GROUP",            "TK_GROUP",        ALWAYS,           5      },
  { "GROUPS",           "TK_GROUPS",       WINDOWFUNC,       2      },
  { "HAVING",           "TK_HAVING",       ALWAYS,           5      },
  { "IF",               "TK_IF",           ALWAYS,           2      },
  { "IGNORE",           "TK_IGNORE",       CONFLICT|TRIGGER, 1      },
  { "IMMEDIATE",        "TK_IMMEDIATE",    ALWAYS,           1      },
251
252
253
254
255
256
257

258
259
260
261
262
263
264
  { "JOIN",             "TK_JOIN",         ALWAYS,           5      },
  { "KEY",              "TK_KEY",          ALWAYS,           1      },
  { "LAST",             "TK_LAST",         ALWAYS,           4      },
  { "LEFT",             "TK_JOIN_KW",      ALWAYS,           5      },
  { "LIKE",             "TK_LIKE_KW",      ALWAYS,           5      },
  { "LIMIT",            "TK_LIMIT",        ALWAYS,           3      },
  { "MATCH",            "TK_MATCH",        ALWAYS,           2      },

  { "NATURAL",          "TK_JOIN_KW",      ALWAYS,           3      },
  { "NO",               "TK_NO",           FKEY|WINDOWFUNC,  2      },
  { "NOT",              "TK_NOT",          ALWAYS,           10     },
  { "NOTHING",          "TK_NOTHING",      UPSERT,           1      },
  { "NOTNULL",          "TK_NOTNULL",      ALWAYS,           3      },
  { "NULL",             "TK_NULL",         ALWAYS,           10     },
  { "NULLS",            "TK_NULLS",        ALWAYS,           3      },







>







251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
  { "JOIN",             "TK_JOIN",         ALWAYS,           5      },
  { "KEY",              "TK_KEY",          ALWAYS,           1      },
  { "LAST",             "TK_LAST",         ALWAYS,           4      },
  { "LEFT",             "TK_JOIN_KW",      ALWAYS,           5      },
  { "LIKE",             "TK_LIKE_KW",      ALWAYS,           5      },
  { "LIMIT",            "TK_LIMIT",        ALWAYS,           3      },
  { "MATCH",            "TK_MATCH",        ALWAYS,           2      },
  { "MATERIALIZED",     "TK_MATERIALIZED", CTE,              12     },
  { "NATURAL",          "TK_JOIN_KW",      ALWAYS,           3      },
  { "NO",               "TK_NO",           FKEY|WINDOWFUNC,  2      },
  { "NOT",              "TK_NOT",          ALWAYS,           10     },
  { "NOTHING",          "TK_NOTHING",      UPSERT,           1      },
  { "NOTNULL",          "TK_NOTNULL",      ALWAYS,           3      },
  { "NULL",             "TK_NULL",         ALWAYS,           10     },
  { "NULLS",            "TK_NULLS",        ALWAYS,           3      },