SQLite

Check-in [c948384dfd]
Login

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

Overview
Comment:Further comments on WITH-clause processing routines in select.c.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | common-table-expr
Files: files | file ages | folders
SHA1: c948384dfdd9f68a832d5a452af44f35337f66e7
User & Date: drh 2014-01-15 18:35:52.482
Context
2014-01-15
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)
18:23
Add a header comment to the searchWith() routine. (check-in: d9ae0f5d9f user: drh tags: common-table-expr)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/select.c.
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
  pNew->pOrderBy = 0;
  p->pPrior = 0;
  pNew->pLimit = 0;
  pNew->pOffset = 0;
  return WRC_Continue;
}

/* If the table identified by p is a transient table of 
** a common-table-expression (CTE) then return a pointer to the
** CTE that defines table p.  If p is not a CTE, then return NULL.
*/
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;
  }
}








|

|


















>
>
>
>
>













>
>
>

















<







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

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

Changes to src/sqliteInt.h.
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
** 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 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;
    Table *pTab;
  } 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.
*/







|
|


|

|
|
|
|
|
|







2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
** 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 on 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 */
    struct Cte *pOuterCte;          /* Next WITH clause in outer context */
    Table *pTab;                    /* Table object for this CTE */
  } 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.
*/