/ Changes On Branch ast-trace-demo
Login

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

Changes In Branch ast-trace-demo Excluding Merge-Ins

This is equivalent to a diff from 08665a9e to 2a75e631

2018-05-01
18:39
The SQLITE_ALLOW_SQLITE_MASTER_INDEX compile-time option allows a CREATE INDEX statement against the sqlite_master table. Once created, the index works, and is usable by legacy instances of SQLite. check-in: 853f3163 user: drh tags: trunk
01:18
The ".selecttrace 0x4000" command causes the AST to be output to stdout as a table with four columns. Leaf check-in: 2a75e631 user: drh tags: ast-trace-demo
2018-04-30
19:32
Defer loading result column values into registers on an ORDER BY LIMIT until we know that the LIMIT does not exclude the current row. Closed-Leaf check-in: ce4ef460 user: drh tags: faster-order-by-limit
2018-04-28
19:08
Test cases added for SQLITE_DBCONFIG_RESET_DATABASE. check-in: 08665a9e user: drh tags: trunk
18:20
Fix an RBU problem causing spurious SQLITE_CONSTRAINT errors when restarting an RBU update in which more than one source table writes to a single target database table. check-in: 564ae829 user: dan tags: trunk

Changes to src/select.c.

  5490   5490     if( p->pPrior ){
  5491   5491       rc = multiSelect(pParse, p, pDest);
  5492   5492   #if SELECTTRACE_ENABLED
  5493   5493       SELECTTRACE(0x1,pParse,p,("end compound-select processing\n"));
  5494   5494       if( pParse->iSelectId==0 && (sqlite3SelectTrace & 0x2000)!=0 ){
  5495   5495         sqlite3TreeViewSelect(0, p, 0);
  5496   5496       }
         5497  +    if( pParse->iSelectId==0 && (sqlite3SelectTrace & 0x4000)!=0 ){
         5498  +      int iNodeId = 0;
         5499  +      sqlite3AstSelect(p, &iNodeId, 0);
         5500  +    }
  5497   5501   #endif
  5498   5502       explainSetInteger(pParse->iSelectId, iRestoreSelectId);
  5499   5503       return rc;
  5500   5504     }
  5501   5505   #endif
  5502   5506   
  5503   5507     /* For each term in the FROM clause, do two things:
................................................................................
  6283   6287     sqlite3ExprListDelete(db, pMinMaxOrderBy);
  6284   6288     sqlite3DbFree(db, sAggInfo.aCol);
  6285   6289     sqlite3DbFree(db, sAggInfo.aFunc);
  6286   6290   #if SELECTTRACE_ENABLED
  6287   6291     SELECTTRACE(0x1,pParse,p,("end processing\n"));
  6288   6292     if( pParse->iSelectId==0 && (sqlite3SelectTrace & 0x2000)!=0 ){
  6289   6293       sqlite3TreeViewSelect(0, p, 0);
         6294  +  }
         6295  +  if( pParse->iSelectId==0 && (sqlite3SelectTrace & 0x4000)!=0 ){
         6296  +    int iNodeId = 0;
         6297  +    sqlite3AstSelect(p, &iNodeId, 0);
  6290   6298     }
  6291   6299   #endif
  6292   6300     explainSetInteger(pParse->iSelectId, iRestoreSelectId);
  6293   6301     return rc;
  6294   6302   }

Changes to src/sqliteInt.h.

  3674   3674   
  3675   3675   #if defined(SQLITE_DEBUG)
  3676   3676     void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
  3677   3677     void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*);
  3678   3678     void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
  3679   3679     void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
  3680   3680     void sqlite3TreeViewWith(TreeView*, const With*, u8);
         3681  +
         3682  +  void sqlite3AstExpr(const Expr*,int*,int);
         3683  +  void sqlite3AstExprList(const ExprList*,int*,int,int);
         3684  +  void sqlite3AstSelect(const Select*,int*,int);
         3685  +  void sqlite3AstWith(const With*,int*,int);
  3681   3686   #endif
  3682   3687   
  3683   3688   
  3684   3689   void sqlite3SetString(char **, sqlite3*, const char*);
  3685   3690   void sqlite3ErrorMsg(Parse*, const char*, ...);
  3686   3691   void sqlite3Dequote(char*);
  3687   3692   void sqlite3TokenInit(Token*,char*);

Changes to src/treeview.c.

   565    565     u8 moreToFollow,
   566    566     const char *zLabel
   567    567   ){
   568    568     pView = sqlite3TreeViewPush(pView, moreToFollow);
   569    569     sqlite3TreeViewBareExprList(pView, pList, zLabel);
   570    570     sqlite3TreeViewPop(pView);
   571    571   }
          572  +
          573  +/****************************************************************************
          574  +** Experimental (demonstration-only) routines for printing a AST as a
          575  +** relation:
          576  +**
          577  +**     CREATE TABLE AstNode(
          578  +**        nodeId INTEGER PRIMARY KEY,
          579  +**        parentId INTEGER REFERENCES AstNode,
          580  +**        name TEXT,
          581  +**        value ANY
          582  +**     );
          583  +*/
          584  +
          585  +#define ASTVT_NULL   0
          586  +#define ASTVT_TEXT   1
          587  +#define ASTVT_INT    2
          588  +
          589  +/*
          590  +** Output a single row of the AstNode relation
          591  +*/
          592  +static int sqlite3AstOneRow(
          593  +  int *pNodeCnt,
          594  +  int parentId,
          595  +  const char *zName,
          596  +  int eValtype,
          597  +  int iValue,
          598  +  const char *zValue
          599  +){
          600  +  int nodeId = ++(*pNodeCnt);
          601  +  printf("%d,", nodeId);
          602  +  if( parentId ){
          603  +    printf("%d,", parentId);
          604  +  }else{
          605  +    printf("NULL,");
          606  +  }
          607  +  printf("'%s',", zName);
          608  +  switch( eValtype ){
          609  +    case ASTVT_INT:  printf("%d\n", iValue);   break;
          610  +    case ASTVT_TEXT: printf("'%s'\n", zValue); break;
          611  +    default:         printf("NULL\n");         break;
          612  +  }
          613  +  return nodeId;
          614  +}
          615  +static int sqlite3AstOneRowInt(
          616  +  int *pNodeCnt,
          617  +  int parentId,
          618  +  const char *zName,
          619  +  int iValue
          620  +){
          621  +  return sqlite3AstOneRow(pNodeCnt,parentId,zName,ASTVT_INT,iValue,0);
          622  +}
          623  +static int sqlite3AstOneRowText(
          624  +  int *pNodeCnt,
          625  +  int parentId,
          626  +  const char *zName,
          627  +  const char *zValue
          628  +){
          629  +  return sqlite3AstOneRow(pNodeCnt,parentId,zName,ASTVT_TEXT,0,zValue);
          630  +}
          631  +static int sqlite3AstOneRowNull(
          632  +  int *pNodeCnt,
          633  +  int parentId,
          634  +  const char *zName
          635  +){
          636  +  return sqlite3AstOneRow(pNodeCnt,parentId,zName,ASTVT_NULL,0,0);
          637  +}
          638  +static int sqlite3AstOneRowOp(
          639  +  int *pNodeCnt,
          640  +  int parentId,
          641  +  const char *zName,
          642  +  const Expr *pExpr
          643  +){
          644  +  char zFlg[30];
          645  +  sqlite3_snprintf(sizeof(zFlg),zFlg,"0x%6x",pExpr->flags);
          646  +  return sqlite3AstOneRow(pNodeCnt,parentId,zName,ASTVT_TEXT,0,zFlg);
          647  +}
          648  +
          649  +
          650  +void sqlite3AstExpr(const Expr *pExpr, int *pNodeCnt, int iParentId){
          651  +  int iNodeId;
          652  +  const char *zBinOp = 0;
          653  +  const char *zUniOp = 0;
          654  +
          655  +  if( pExpr==0 ) return;
          656  +  switch( pExpr->op ){
          657  +    case TK_AGG_COLUMN: {
          658  +      iNodeId = sqlite3AstOneRowOp(pNodeCnt, iParentId, "agg_column", pExpr);
          659  +      sqlite3AstOneRowInt(pNodeCnt, iNodeId, "table", pExpr->iTable);
          660  +      sqlite3AstOneRowInt(pNodeCnt, iNodeId, "column", pExpr->iColumn);
          661  +      break;
          662  +    }
          663  +    case TK_COLUMN: {
          664  +      iNodeId = sqlite3AstOneRowOp(pNodeCnt, iParentId, "column", pExpr);
          665  +      if( pExpr->iTable>=0 ){
          666  +        sqlite3AstOneRowInt(pNodeCnt, iNodeId, "table", pExpr->iTable);
          667  +      }
          668  +      sqlite3AstOneRowInt(pNodeCnt, iNodeId, "column", pExpr->iColumn);
          669  +      break;
          670  +    }
          671  +    case TK_INTEGER: {
          672  +      if( pExpr->flags & EP_IntValue ){
          673  +        iNodeId = sqlite3AstOneRowInt(pNodeCnt, iParentId,
          674  +                                      "integer", pExpr->u.iValue);
          675  +      }else{
          676  +        iNodeId = sqlite3AstOneRowText(pNodeCnt, iParentId,
          677  +                                       "integer", pExpr->u.zToken);
          678  +      }
          679  +      break;
          680  +    }
          681  +#ifndef SQLITE_OMIT_FLOATING_POINT
          682  +    case TK_FLOAT: {
          683  +      iNodeId = sqlite3AstOneRowText(pNodeCnt, iParentId,
          684  +                                     "float", pExpr->u.zToken);
          685  +      break;
          686  +    }
          687  +#endif
          688  +    case TK_STRING: {
          689  +      iNodeId = sqlite3AstOneRowText(pNodeCnt, iParentId,
          690  +                                     "string", pExpr->u.zToken);
          691  +      break;
          692  +    }
          693  +    case TK_NULL: {
          694  +      iNodeId = sqlite3AstOneRowNull(pNodeCnt, iParentId, "null");
          695  +      break;
          696  +    }
          697  +    case TK_TRUEFALSE: {
          698  +      iNodeId = sqlite3AstOneRowNull(pNodeCnt, iParentId,
          699  +           sqlite3ExprTruthValue(pExpr) ? "true" : "false");
          700  +      break;
          701  +    }
          702  +#ifndef SQLITE_OMIT_BLOB_LITERAL
          703  +    case TK_BLOB: {
          704  +      iNodeId = sqlite3AstOneRowText(pNodeCnt, iParentId, "blob",
          705  +                                     pExpr->u.zToken);
          706  +      break;
          707  +    }
          708  +#endif
          709  +    case TK_VARIABLE: {
          710  +      iNodeId = sqlite3AstOneRowOp(pNodeCnt, iParentId, "variable", pExpr);
          711  +      sqlite3AstOneRowText(pNodeCnt, iNodeId, "name", pExpr->u.zToken);
          712  +      sqlite3AstOneRowInt(pNodeCnt, iNodeId, "column", pExpr->iColumn);
          713  +      break;
          714  +    }
          715  +    case TK_REGISTER: {
          716  +      iNodeId = sqlite3AstOneRowOp(pNodeCnt, iParentId, "register", pExpr);
          717  +      sqlite3AstOneRowInt(pNodeCnt, iNodeId, "registerNumber", 
          718  +                           pExpr->iTable);
          719  +      break;
          720  +    }
          721  +    case TK_ID: {
          722  +      iNodeId = sqlite3AstOneRowOp(pNodeCnt, iParentId, "id", pExpr);
          723  +      sqlite3AstOneRowText(pNodeCnt, iNodeId, "Name", pExpr->u.zToken);
          724  +      break;
          725  +    }
          726  +    case TK_LT:      zBinOp = "LT";     break;
          727  +    case TK_LE:      zBinOp = "LE";     break;
          728  +    case TK_GT:      zBinOp = "GT";     break;
          729  +    case TK_GE:      zBinOp = "GE";     break;
          730  +    case TK_NE:      zBinOp = "NE";     break;
          731  +    case TK_EQ:      zBinOp = "EQ";     break;
          732  +    case TK_IS:      zBinOp = "IS";     break;
          733  +    case TK_ISNOT:   zBinOp = "ISNOT";  break;
          734  +    case TK_AND:     zBinOp = "AND";    break;
          735  +    case TK_OR:      zBinOp = "OR";     break;
          736  +    case TK_PLUS:    zBinOp = "ADD";    break;
          737  +    case TK_STAR:    zBinOp = "MUL";    break;
          738  +    case TK_MINUS:   zBinOp = "SUB";    break;
          739  +    case TK_REM:     zBinOp = "REM";    break;
          740  +    case TK_BITAND:  zBinOp = "BITAND"; break;
          741  +    case TK_BITOR:   zBinOp = "BITOR";  break;
          742  +    case TK_SLASH:   zBinOp = "DIV";    break;
          743  +    case TK_LSHIFT:  zBinOp = "LSHIFT"; break;
          744  +    case TK_RSHIFT:  zBinOp = "RSHIFT"; break;
          745  +    case TK_CONCAT:  zBinOp = "CONCAT"; break;
          746  +    case TK_DOT:     zBinOp = "DOT";    break;
          747  +
          748  +    case TK_CAST:    zUniOp = "CAST";   break;
          749  +    case TK_UMINUS:  zUniOp = "UMINUS"; break;
          750  +    case TK_UPLUS:   zUniOp = "UPLUS";  break;
          751  +    case TK_BITNOT:  zUniOp = "BITNOT"; break;
          752  +    case TK_NOT:     zUniOp = "NOT";    break;
          753  +    case TK_ISNULL:  zUniOp = "ISNULL"; break;
          754  +    case TK_NOTNULL: zUniOp = "NOTNULL"; break;
          755  +    case TK_IF_NULL_ROW: zUniOp = "IFNULLROW"; break;
          756  +
          757  +    case TK_TRUTH: {
          758  +      int x;
          759  +      const char *azOp[] = {
          760  +         "IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE"
          761  +      };
          762  +      assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT );
          763  +      assert( pExpr->pRight );
          764  +      assert( pExpr->pRight->op==TK_TRUEFALSE );
          765  +      x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight);
          766  +      zUniOp = azOp[x];
          767  +      break;
          768  +    }
          769  +
          770  +    case TK_SPAN: {
          771  +      iNodeId = sqlite3AstOneRowText(pNodeCnt, iParentId, "span", 
          772  +                                     pExpr->u.zToken);
          773  +      sqlite3AstExpr(pExpr->pLeft, pNodeCnt, iNodeId);
          774  +      break;
          775  +    }
          776  +
          777  +    case TK_COLLATE: {
          778  +      iNodeId = sqlite3AstOneRowText(pNodeCnt, iParentId, "collate", 
          779  +                                     pExpr->u.zToken);
          780  +      sqlite3AstExpr(pExpr->pLeft, pNodeCnt, iNodeId);
          781  +      break;
          782  +    }
          783  +
          784  +    case TK_AGG_FUNCTION:
          785  +    case TK_FUNCTION: {
          786  +      ExprList *pFarg;       /* List of function arguments */
          787  +      if( ExprHasProperty(pExpr, EP_TokenOnly) ){
          788  +        pFarg = 0;
          789  +      }else{
          790  +        pFarg = pExpr->x.pList;
          791  +      }
          792  +      if( pExpr->op==TK_AGG_FUNCTION ){
          793  +        char zId[20];
          794  +        sqlite3_snprintf(sizeof(zId),zId,"agg_function%d", pExpr->op2);
          795  +        iNodeId = sqlite3AstOneRowText(pNodeCnt, iParentId, zId, 
          796  +                                       pExpr->u.zToken);
          797  +      }else{
          798  +        iNodeId = sqlite3AstOneRowText(pNodeCnt, iParentId, "function", 
          799  +                                       pExpr->u.zToken);
          800  +      }
          801  +      if( pFarg ){
          802  +        sqlite3AstExprList(pFarg, pNodeCnt, iNodeId, 0);
          803  +      }
          804  +      break;
          805  +    }
          806  +#ifndef SQLITE_OMIT_SUBQUERY
          807  +    case TK_EXISTS: {
          808  +      iNodeId = sqlite3AstOneRowOp(pNodeCnt, iParentId, "exists-expr", pExpr);
          809  +      sqlite3AstSelect(pExpr->x.pSelect, pNodeCnt, iNodeId);
          810  +      break;
          811  +    }
          812  +    case TK_SELECT: {
          813  +      iNodeId = sqlite3AstOneRowOp(pNodeCnt, iParentId, "select-expr", pExpr);
          814  +      sqlite3AstSelect(pExpr->x.pSelect, pNodeCnt, iNodeId);
          815  +      break;
          816  +    }
          817  +    case TK_IN: {
          818  +      int id;
          819  +      iNodeId = sqlite3AstOneRowOp(pNodeCnt, iParentId, "in", pExpr);
          820  +      id = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "left");
          821  +      sqlite3AstExpr(pExpr->pLeft, pNodeCnt, id);
          822  +      id = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "right");
          823  +      if( ExprHasProperty(pExpr, EP_xIsSelect) ){
          824  +        sqlite3AstSelect(pExpr->x.pSelect, pNodeCnt, id);
          825  +      }else{
          826  +        sqlite3AstExprList(pExpr->x.pList, pNodeCnt, id, 0);
          827  +      }
          828  +      break;
          829  +    }
          830  +#endif /* SQLITE_OMIT_SUBQUERY */
          831  +
          832  +    /*
          833  +    **    x BETWEEN y AND z
          834  +    **
          835  +    ** This is equivalent to
          836  +    **
          837  +    **    x>=y AND x<=z
          838  +    **
          839  +    ** X is stored in pExpr->pLeft.
          840  +    ** Y is stored in pExpr->pList->a[0].pExpr.
          841  +    ** Z is stored in pExpr->pList->a[1].pExpr.
          842  +    */
          843  +    case TK_BETWEEN: {
          844  +      int id;
          845  +      Expr *pX = pExpr->pLeft;
          846  +      Expr *pY = pExpr->x.pList->a[0].pExpr;
          847  +      Expr *pZ = pExpr->x.pList->a[1].pExpr;
          848  +      iNodeId = sqlite3AstOneRowOp(pNodeCnt, iParentId, "between", pExpr);
          849  +      id = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "left");
          850  +      sqlite3AstExpr(pX, pNodeCnt, id);
          851  +      id = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "lower");
          852  +      sqlite3AstExpr(pY, pNodeCnt, id);
          853  +      id = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "upper");
          854  +      sqlite3AstExpr(pZ, pNodeCnt, id);
          855  +      break;
          856  +    }
          857  +    case TK_TRIGGER: {
          858  +      /* If the opcode is TK_TRIGGER, then the expression is a reference
          859  +      ** to a column in the new.* or old.* pseudo-tables available to
          860  +      ** trigger programs. In this case Expr.iTable is set to 1 for the
          861  +      ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
          862  +      ** is set to the column of the pseudo-table to read, or to -1 to
          863  +      ** read the rowid field.
          864  +      */
          865  +      iNodeId = sqlite3AstOneRowOp(pNodeCnt, iParentId, 
          866  +          pExpr->iTable ? "new-column" : "old-column", pExpr);
          867  +      sqlite3AstOneRowInt(pNodeCnt, iNodeId, "column", pExpr->iColumn);
          868  +      break;
          869  +    }
          870  +    case TK_CASE: {
          871  +      int id;
          872  +      iNodeId = sqlite3AstOneRowOp(pNodeCnt, iParentId, "case", pExpr);
          873  +      id = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "left");
          874  +      sqlite3AstExpr(pExpr->pLeft, pNodeCnt, id);
          875  +      id = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "list");
          876  +      sqlite3AstExprList(pExpr->x.pList, pNodeCnt, id, 0);
          877  +      break;
          878  +    }
          879  +    case TK_RAISE: {
          880  +      const char *zType = "unk";
          881  +      switch( pExpr->affinity ){
          882  +        case OE_Rollback:   zType = "rollback";  break;
          883  +        case OE_Abort:      zType = "abort";     break;
          884  +        case OE_Fail:       zType = "fail";      break;
          885  +        case OE_Ignore:     zType = "ignore";    break;
          886  +      }
          887  +      iNodeId = sqlite3AstOneRowOp(pNodeCnt, iParentId, "raise", pExpr);
          888  +      sqlite3AstOneRowText(pNodeCnt, iNodeId, "type", zType);
          889  +      sqlite3AstOneRowText(pNodeCnt, iNodeId, "arg", pExpr->u.zToken);
          890  +      break;
          891  +    }
          892  +    case TK_MATCH: {
          893  +      iNodeId = sqlite3AstOneRowOp(pNodeCnt, iParentId, "match", pExpr);
          894  +      sqlite3AstOneRowInt(pNodeCnt, iNodeId, "table", pExpr->iTable);
          895  +      sqlite3AstOneRowInt(pNodeCnt, iNodeId, "column", pExpr->iColumn);
          896  +      break;
          897  +    }
          898  +    case TK_VECTOR: {
          899  +      iNodeId = sqlite3AstOneRowOp(pNodeCnt, iParentId, "vector", pExpr);
          900  +      sqlite3AstExprList(pExpr->x.pList, pNodeCnt, iNodeId, 0);
          901  +      break;
          902  +    }
          903  +    case TK_SELECT_COLUMN: {
          904  +      iNodeId = sqlite3AstOneRowInt(pNodeCnt, iParentId, "select-column",
          905  +                                    pExpr->iColumn);
          906  +      sqlite3AstSelect(pExpr->pLeft->x.pSelect, pNodeCnt, iNodeId);
          907  +      break;
          908  +    }
          909  +    default: {
          910  +      sqlite3AstOneRowInt(pNodeCnt, iParentId, "unknown", pExpr->op);
          911  +      break;
          912  +    }
          913  +  }
          914  +  if( zBinOp ){
          915  +    iNodeId = sqlite3AstOneRowOp(pNodeCnt, iParentId, zBinOp, pExpr);
          916  +    if( pExpr->pLeft ){
          917  +      int id = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "left");
          918  +      sqlite3AstExpr(pExpr->pLeft, pNodeCnt, id);
          919  +    }
          920  +    if( pExpr->pRight ){
          921  +      int id = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "right");
          922  +      sqlite3AstExpr(pExpr->pRight, pNodeCnt, id);
          923  +    }
          924  +  }
          925  +  if( zUniOp ){
          926  +    iNodeId = sqlite3AstOneRowOp(pNodeCnt, iParentId, zUniOp, pExpr);
          927  +    if( pExpr->pLeft ){
          928  +      sqlite3AstExpr(pExpr->pLeft, pNodeCnt, iNodeId);
          929  +    }
          930  +  }
          931  +}
          932  +
          933  +void sqlite3AstExprList(
          934  +  const ExprList *pList,
          935  +  int *pNodeCnt,
          936  +  int iParentId,
          937  +  int showSortOrder
          938  +){
          939  +  int i;
          940  +  if( pList==0 ) return;
          941  +  for(i=0; i<pList->nExpr; i++){
          942  +    const struct ExprList_item *pItem = pList->a + i;
          943  +    int id = sqlite3AstOneRowNull(pNodeCnt, iParentId, "listitem");
          944  +    if( pItem->zName && pItem->zName[0] ){
          945  +      sqlite3AstOneRowText(pNodeCnt, id, "name", pItem->zName);
          946  +    }
          947  +    if( showSortOrder && pItem->sortOrder ){
          948  +      sqlite3AstOneRowInt(pNodeCnt, id, "desc", 1);
          949  +    }
          950  +    sqlite3AstExpr(pList->a[i].pExpr, pNodeCnt, id);
          951  +  }
          952  +}
          953  +
          954  +
          955  +/*
          956  +** Generate a human-readable description of a WITH clause.
          957  +*/
          958  +void sqlite3AstWith(const With *pWith, int *pNodeCnt, int iParentId){
          959  +  int i;
          960  +  if( pWith==0 ) return;
          961  +  if( pWith->nCte==0 ) return;
          962  +  if( pWith && pWith->nCte>0 ){
          963  +    int iNodeId = sqlite3AstOneRowNull(pNodeCnt, iParentId, "WITH");
          964  +    for(i=0; i<pWith->nCte; i++){
          965  +      const struct Cte *pCte = &pWith->a[i];
          966  +      int id = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "with-cte");
          967  +      sqlite3AstOneRowText(pNodeCnt, id, "name", pCte->zName);
          968  +      if( pCte->pCols && pCte->pCols->nExpr>0 ){
          969  +        int x = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "column-list");
          970  +        sqlite3AstExprList(pCte->pCols, pNodeCnt, x, 0);
          971  +      }
          972  +      sqlite3AstSelect(pCte->pSelect, pNodeCnt, iNodeId);
          973  +    }
          974  +  }
          975  +}
          976  +
          977  +
          978  +/*
          979  +** Generate a human-readable description of a Select object.
          980  +*/
          981  +void sqlite3AstSelect(const Select *p, int *pNodeCnt, int iParentId){
          982  +  if( p==0 ) return;
          983  +  if( p->pWith ){
          984  +    sqlite3AstWith(p->pWith, pNodeCnt, iParentId);
          985  +  }
          986  +  do{
          987  +    int iNodeId = sqlite3AstOneRowNull(pNodeCnt, iParentId, "SELECT");
          988  +    int id = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "result-set");
          989  +    sqlite3AstExprList(p->pEList, pNodeCnt, id, 0);
          990  +    if( p->pSrc && p->pSrc->nSrc ){
          991  +      int i;
          992  +      for(i=0; i<p->pSrc->nSrc; i++){
          993  +        struct SrcList_item *pItem = &p->pSrc->a[i];
          994  +        int iFrom = sqlite3AstOneRowInt(pNodeCnt, iNodeId,
          995  +                                        "from-item", pItem->iCursor);
          996  +        if( pItem->zDatabase ){
          997  +          sqlite3AstOneRowText(pNodeCnt, iFrom, "database", pItem->zDatabase);
          998  +        }
          999  +        if( pItem->zName ){
         1000  +          sqlite3AstOneRowText(pNodeCnt, iFrom, "name", pItem->zName);
         1001  +        }
         1002  +        if( pItem->pTab ){
         1003  +          sqlite3AstOneRowText(pNodeCnt, iFrom, "tabname", pItem->pTab->zName);
         1004  +        }
         1005  +        if( pItem->zAlias ){
         1006  +          sqlite3AstOneRowText(pNodeCnt, iFrom, "as", pItem->zAlias);
         1007  +        }
         1008  +        if( pItem->fg.jointype & JT_LEFT ){
         1009  +          sqlite3AstOneRowInt(pNodeCnt, iFrom, "left-join", 1);
         1010  +        }
         1011  +        if( pItem->pSelect ){
         1012  +          sqlite3AstSelect(pItem->pSelect, pNodeCnt, iFrom);
         1013  +        }
         1014  +        if( pItem->fg.isTabFunc ){
         1015  +          int x = sqlite3AstOneRowNull(pNodeCnt, iFrom, "func-args");
         1016  +          sqlite3AstExprList(pItem->u1.pFuncArg, pNodeCnt, x, 0);
         1017  +        }
         1018  +      }
         1019  +    }
         1020  +    if( p->pWhere ){
         1021  +      id = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "where");
         1022  +      sqlite3AstExpr(p->pWhere, pNodeCnt, id);
         1023  +    }
         1024  +    if( p->pGroupBy ){
         1025  +      id = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "groupby");
         1026  +      sqlite3AstExprList(p->pGroupBy, pNodeCnt, id, 0);
         1027  +    }
         1028  +    if( p->pHaving ){
         1029  +      id = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "having");
         1030  +      sqlite3AstExpr(p->pHaving, pNodeCnt, id);
         1031  +    }
         1032  +    if( p->pOrderBy ){
         1033  +      id = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "orderby");
         1034  +      sqlite3AstExprList(p->pOrderBy, pNodeCnt, id, 1);
         1035  +    }
         1036  +    if( p->pLimit ){
         1037  +      id = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "limit");
         1038  +      sqlite3AstExpr(p->pLimit->pLeft, pNodeCnt, id);
         1039  +      if( p->pLimit->pRight ){
         1040  +        id = sqlite3AstOneRowNull(pNodeCnt, iNodeId, "offset");
         1041  +        sqlite3AstExpr(p->pLimit->pRight, pNodeCnt, id);
         1042  +      }
         1043  +    }
         1044  +    if( p->pPrior ){
         1045  +      const char *zOp = "UNION";
         1046  +      switch( p->op ){
         1047  +        case TK_ALL:         zOp = "UNION ALL";  break;
         1048  +        case TK_INTERSECT:   zOp = "INTERSECT";  break;
         1049  +        case TK_EXCEPT:      zOp = "EXCEPT";     break;
         1050  +      }
         1051  +      iParentId = sqlite3AstOneRowNull(pNodeCnt, iNodeId, zOp);
         1052  +    }
         1053  +    p = p->pPrior;
         1054  +  }while( p!=0 );
         1055  +}
   572   1056   
   573   1057   #endif /* SQLITE_DEBUG */