modernc.org/cc@v1.0.1/v2/testdata/_sqlite/src/treeview.c (about)

     1  /*
     2  ** 2015-06-08
     3  **
     4  ** The author disclaims copyright to this source code.  In place of
     5  ** a legal notice, here is a blessing:
     6  **
     7  **    May you do good and not evil.
     8  **    May you find forgiveness for yourself and forgive others.
     9  **    May you share freely, never taking more than you give.
    10  **
    11  *************************************************************************
    12  **
    13  ** This file contains C code to implement the TreeView debugging routines.
    14  ** These routines print a parse tree to standard output for debugging and
    15  ** analysis. 
    16  **
    17  ** The interfaces in this file is only available when compiling
    18  ** with SQLITE_DEBUG.
    19  */
    20  #include "sqliteInt.h"
    21  #ifdef SQLITE_DEBUG
    22  
    23  /*
    24  ** Add a new subitem to the tree.  The moreToFollow flag indicates that this
    25  ** is not the last item in the tree.
    26  */
    27  static TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){
    28    if( p==0 ){
    29      p = sqlite3_malloc64( sizeof(*p) );
    30      if( p==0 ) return 0;
    31      memset(p, 0, sizeof(*p));
    32    }else{
    33      p->iLevel++;
    34    }
    35    assert( moreToFollow==0 || moreToFollow==1 );
    36    if( p->iLevel<sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
    37    return p;
    38  }
    39  
    40  /*
    41  ** Finished with one layer of the tree
    42  */
    43  static void sqlite3TreeViewPop(TreeView *p){
    44    if( p==0 ) return;
    45    p->iLevel--;
    46    if( p->iLevel<0 ) sqlite3_free(p);
    47  }
    48  
    49  /*
    50  ** Generate a single line of output for the tree, with a prefix that contains
    51  ** all the appropriate tree lines
    52  */
    53  static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
    54    va_list ap;
    55    int i;
    56    StrAccum acc;
    57    char zBuf[500];
    58    sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
    59    if( p ){
    60      for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){
    61        sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|   " : "    ", 4);
    62      }
    63      sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
    64    }
    65    va_start(ap, zFormat);
    66    sqlite3VXPrintf(&acc, zFormat, ap);
    67    va_end(ap);
    68    assert( acc.nChar>0 );
    69    if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1);
    70    sqlite3StrAccumFinish(&acc);
    71    fprintf(stdout,"%s", zBuf);
    72    fflush(stdout);
    73  }
    74  
    75  /*
    76  ** Shorthand for starting a new tree item that consists of a single label
    77  */
    78  static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){
    79    p = sqlite3TreeViewPush(p, moreFollows);
    80    sqlite3TreeViewLine(p, "%s", zLabel);
    81  }
    82  
    83  /*
    84  ** Generate a human-readable description of a WITH clause.
    85  */
    86  void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){
    87    int i;
    88    if( pWith==0 ) return;
    89    if( pWith->nCte==0 ) return;
    90    if( pWith->pOuter ){
    91      sqlite3TreeViewLine(pView, "WITH (0x%p, pOuter=0x%p)",pWith,pWith->pOuter);
    92    }else{
    93      sqlite3TreeViewLine(pView, "WITH (0x%p)", pWith);
    94    }
    95    if( pWith->nCte>0 ){
    96      pView = sqlite3TreeViewPush(pView, 1);
    97      for(i=0; i<pWith->nCte; i++){
    98        StrAccum x;
    99        char zLine[1000];
   100        const struct Cte *pCte = &pWith->a[i];
   101        sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
   102        sqlite3XPrintf(&x, "%s", pCte->zName);
   103        if( pCte->pCols && pCte->pCols->nExpr>0 ){
   104          char cSep = '(';
   105          int j;
   106          for(j=0; j<pCte->pCols->nExpr; j++){
   107            sqlite3XPrintf(&x, "%c%s", cSep, pCte->pCols->a[j].zName);
   108            cSep = ',';
   109          }
   110          sqlite3XPrintf(&x, ")");
   111        }
   112        sqlite3XPrintf(&x, " AS");
   113        sqlite3StrAccumFinish(&x);
   114        sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1);
   115        sqlite3TreeViewSelect(pView, pCte->pSelect, 0);
   116        sqlite3TreeViewPop(pView);
   117      }
   118      sqlite3TreeViewPop(pView);
   119    }
   120  }
   121  
   122  
   123  /*
   124  ** Generate a human-readable description of a Select object.
   125  */
   126  void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
   127    int n = 0;
   128    int cnt = 0;
   129    if( p==0 ){
   130      sqlite3TreeViewLine(pView, "nil-SELECT");
   131      return;
   132    } 
   133    pView = sqlite3TreeViewPush(pView, moreToFollow);
   134    if( p->pWith ){
   135      sqlite3TreeViewWith(pView, p->pWith, 1);
   136      cnt = 1;
   137      sqlite3TreeViewPush(pView, 1);
   138    }
   139    do{
   140      sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x nSelectRow=%d",
   141        ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
   142        ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags,
   143        (int)p->nSelectRow
   144      );
   145      if( cnt++ ) sqlite3TreeViewPop(pView);
   146      if( p->pPrior ){
   147        n = 1000;
   148      }else{
   149        n = 0;
   150        if( p->pSrc && p->pSrc->nSrc ) n++;
   151        if( p->pWhere ) n++;
   152        if( p->pGroupBy ) n++;
   153        if( p->pHaving ) n++;
   154        if( p->pOrderBy ) n++;
   155        if( p->pLimit ) n++;
   156        if( p->pOffset ) n++;
   157      }
   158      sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
   159      if( p->pSrc && p->pSrc->nSrc ){
   160        int i;
   161        pView = sqlite3TreeViewPush(pView, (n--)>0);
   162        sqlite3TreeViewLine(pView, "FROM");
   163        for(i=0; i<p->pSrc->nSrc; i++){
   164          struct SrcList_item *pItem = &p->pSrc->a[i];
   165          StrAccum x;
   166          char zLine[100];
   167          sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
   168          sqlite3XPrintf(&x, "{%d,*}", pItem->iCursor);
   169          if( pItem->zDatabase ){
   170            sqlite3XPrintf(&x, " %s.%s", pItem->zDatabase, pItem->zName);
   171          }else if( pItem->zName ){
   172            sqlite3XPrintf(&x, " %s", pItem->zName);
   173          }
   174          if( pItem->pTab ){
   175            sqlite3XPrintf(&x, " tabname=%Q", pItem->pTab->zName);
   176          }
   177          if( pItem->zAlias ){
   178            sqlite3XPrintf(&x, " (AS %s)", pItem->zAlias);
   179          }
   180          if( pItem->fg.jointype & JT_LEFT ){
   181            sqlite3XPrintf(&x, " LEFT-JOIN");
   182          }
   183          sqlite3StrAccumFinish(&x);
   184          sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1); 
   185          if( pItem->pSelect ){
   186            sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
   187          }
   188          if( pItem->fg.isTabFunc ){
   189            sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
   190          }
   191          sqlite3TreeViewPop(pView);
   192        }
   193        sqlite3TreeViewPop(pView);
   194      }
   195      if( p->pWhere ){
   196        sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
   197        sqlite3TreeViewExpr(pView, p->pWhere, 0);
   198        sqlite3TreeViewPop(pView);
   199      }
   200      if( p->pGroupBy ){
   201        sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
   202      }
   203      if( p->pHaving ){
   204        sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
   205        sqlite3TreeViewExpr(pView, p->pHaving, 0);
   206        sqlite3TreeViewPop(pView);
   207      }
   208      if( p->pOrderBy ){
   209        sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");
   210      }
   211      if( p->pLimit ){
   212        sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
   213        sqlite3TreeViewExpr(pView, p->pLimit, 0);
   214        sqlite3TreeViewPop(pView);
   215      }
   216      if( p->pOffset ){
   217        sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
   218        sqlite3TreeViewExpr(pView, p->pOffset, 0);
   219        sqlite3TreeViewPop(pView);
   220      }
   221      if( p->pPrior ){
   222        const char *zOp = "UNION";
   223        switch( p->op ){
   224          case TK_ALL:         zOp = "UNION ALL";  break;
   225          case TK_INTERSECT:   zOp = "INTERSECT";  break;
   226          case TK_EXCEPT:      zOp = "EXCEPT";     break;
   227        }
   228        sqlite3TreeViewItem(pView, zOp, 1);
   229      }
   230      p = p->pPrior;
   231    }while( p!=0 );
   232    sqlite3TreeViewPop(pView);
   233  }
   234  
   235  /*
   236  ** Generate a human-readable explanation of an expression tree.
   237  */
   238  void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
   239    const char *zBinOp = 0;   /* Binary operator */
   240    const char *zUniOp = 0;   /* Unary operator */
   241    char zFlgs[60];
   242    pView = sqlite3TreeViewPush(pView, moreToFollow);
   243    if( pExpr==0 ){
   244      sqlite3TreeViewLine(pView, "nil");
   245      sqlite3TreeViewPop(pView);
   246      return;
   247    }
   248    if( pExpr->flags ){
   249      if( ExprHasProperty(pExpr, EP_FromJoin) ){
   250        sqlite3_snprintf(sizeof(zFlgs),zFlgs,"  flags=0x%x iRJT=%d",
   251                         pExpr->flags, pExpr->iRightJoinTable);
   252      }else{
   253        sqlite3_snprintf(sizeof(zFlgs),zFlgs,"  flags=0x%x",pExpr->flags);
   254      }
   255    }else{
   256      zFlgs[0] = 0;
   257    }
   258    switch( pExpr->op ){
   259      case TK_AGG_COLUMN: {
   260        sqlite3TreeViewLine(pView, "AGG{%d:%d}%s",
   261              pExpr->iTable, pExpr->iColumn, zFlgs);
   262        break;
   263      }
   264      case TK_COLUMN: {
   265        if( pExpr->iTable<0 ){
   266          /* This only happens when coding check constraints */
   267          sqlite3TreeViewLine(pView, "COLUMN(%d)%s", pExpr->iColumn, zFlgs);
   268        }else{
   269          sqlite3TreeViewLine(pView, "{%d:%d}%s",
   270                               pExpr->iTable, pExpr->iColumn, zFlgs);
   271        }
   272        break;
   273      }
   274      case TK_INTEGER: {
   275        if( pExpr->flags & EP_IntValue ){
   276          sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);
   277        }else{
   278          sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);
   279        }
   280        break;
   281      }
   282  #ifndef SQLITE_OMIT_FLOATING_POINT
   283      case TK_FLOAT: {
   284        sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
   285        break;
   286      }
   287  #endif
   288      case TK_STRING: {
   289        sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
   290        break;
   291      }
   292      case TK_NULL: {
   293        sqlite3TreeViewLine(pView,"NULL");
   294        break;
   295      }
   296  #ifndef SQLITE_OMIT_BLOB_LITERAL
   297      case TK_BLOB: {
   298        sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
   299        break;
   300      }
   301  #endif
   302      case TK_VARIABLE: {
   303        sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
   304                            pExpr->u.zToken, pExpr->iColumn);
   305        break;
   306      }
   307      case TK_REGISTER: {
   308        sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
   309        break;
   310      }
   311      case TK_ID: {
   312        sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
   313        break;
   314      }
   315  #ifndef SQLITE_OMIT_CAST
   316      case TK_CAST: {
   317        /* Expressions of the form:   CAST(pLeft AS token) */
   318        sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
   319        sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
   320        break;
   321      }
   322  #endif /* SQLITE_OMIT_CAST */
   323      case TK_LT:      zBinOp = "LT";     break;
   324      case TK_LE:      zBinOp = "LE";     break;
   325      case TK_GT:      zBinOp = "GT";     break;
   326      case TK_GE:      zBinOp = "GE";     break;
   327      case TK_NE:      zBinOp = "NE";     break;
   328      case TK_EQ:      zBinOp = "EQ";     break;
   329      case TK_IS:      zBinOp = "IS";     break;
   330      case TK_ISNOT:   zBinOp = "ISNOT";  break;
   331      case TK_AND:     zBinOp = "AND";    break;
   332      case TK_OR:      zBinOp = "OR";     break;
   333      case TK_PLUS:    zBinOp = "ADD";    break;
   334      case TK_STAR:    zBinOp = "MUL";    break;
   335      case TK_MINUS:   zBinOp = "SUB";    break;
   336      case TK_REM:     zBinOp = "REM";    break;
   337      case TK_BITAND:  zBinOp = "BITAND"; break;
   338      case TK_BITOR:   zBinOp = "BITOR";  break;
   339      case TK_SLASH:   zBinOp = "DIV";    break;
   340      case TK_LSHIFT:  zBinOp = "LSHIFT"; break;
   341      case TK_RSHIFT:  zBinOp = "RSHIFT"; break;
   342      case TK_CONCAT:  zBinOp = "CONCAT"; break;
   343      case TK_DOT:     zBinOp = "DOT";    break;
   344  
   345      case TK_UMINUS:  zUniOp = "UMINUS"; break;
   346      case TK_UPLUS:   zUniOp = "UPLUS";  break;
   347      case TK_BITNOT:  zUniOp = "BITNOT"; break;
   348      case TK_NOT:     zUniOp = "NOT";    break;
   349      case TK_ISNULL:  zUniOp = "ISNULL"; break;
   350      case TK_NOTNULL: zUniOp = "NOTNULL"; break;
   351  
   352      case TK_SPAN: {
   353        sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken);
   354        sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
   355        break;
   356      }
   357  
   358      case TK_COLLATE: {
   359        sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken);
   360        sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
   361        break;
   362      }
   363  
   364      case TK_AGG_FUNCTION:
   365      case TK_FUNCTION: {
   366        ExprList *pFarg;       /* List of function arguments */
   367        if( ExprHasProperty(pExpr, EP_TokenOnly) ){
   368          pFarg = 0;
   369        }else{
   370          pFarg = pExpr->x.pList;
   371        }
   372        if( pExpr->op==TK_AGG_FUNCTION ){
   373          sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q",
   374                               pExpr->op2, pExpr->u.zToken);
   375        }else{
   376          sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken);
   377        }
   378        if( pFarg ){
   379          sqlite3TreeViewExprList(pView, pFarg, 0, 0);
   380        }
   381        break;
   382      }
   383  #ifndef SQLITE_OMIT_SUBQUERY
   384      case TK_EXISTS: {
   385        sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags);
   386        sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
   387        break;
   388      }
   389      case TK_SELECT: {
   390        sqlite3TreeViewLine(pView, "SELECT-expr flags=0x%x", pExpr->flags);
   391        sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
   392        break;
   393      }
   394      case TK_IN: {
   395        sqlite3TreeViewLine(pView, "IN flags=0x%x", pExpr->flags);
   396        sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
   397        if( ExprHasProperty(pExpr, EP_xIsSelect) ){
   398          sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
   399        }else{
   400          sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
   401        }
   402        break;
   403      }
   404  #endif /* SQLITE_OMIT_SUBQUERY */
   405  
   406      /*
   407      **    x BETWEEN y AND z
   408      **
   409      ** This is equivalent to
   410      **
   411      **    x>=y AND x<=z
   412      **
   413      ** X is stored in pExpr->pLeft.
   414      ** Y is stored in pExpr->pList->a[0].pExpr.
   415      ** Z is stored in pExpr->pList->a[1].pExpr.
   416      */
   417      case TK_BETWEEN: {
   418        Expr *pX = pExpr->pLeft;
   419        Expr *pY = pExpr->x.pList->a[0].pExpr;
   420        Expr *pZ = pExpr->x.pList->a[1].pExpr;
   421        sqlite3TreeViewLine(pView, "BETWEEN");
   422        sqlite3TreeViewExpr(pView, pX, 1);
   423        sqlite3TreeViewExpr(pView, pY, 1);
   424        sqlite3TreeViewExpr(pView, pZ, 0);
   425        break;
   426      }
   427      case TK_TRIGGER: {
   428        /* If the opcode is TK_TRIGGER, then the expression is a reference
   429        ** to a column in the new.* or old.* pseudo-tables available to
   430        ** trigger programs. In this case Expr.iTable is set to 1 for the
   431        ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
   432        ** is set to the column of the pseudo-table to read, or to -1 to
   433        ** read the rowid field.
   434        */
   435        sqlite3TreeViewLine(pView, "%s(%d)", 
   436            pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
   437        break;
   438      }
   439      case TK_CASE: {
   440        sqlite3TreeViewLine(pView, "CASE");
   441        sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
   442        sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
   443        break;
   444      }
   445  #ifndef SQLITE_OMIT_TRIGGER
   446      case TK_RAISE: {
   447        const char *zType = "unk";
   448        switch( pExpr->affinity ){
   449          case OE_Rollback:   zType = "rollback";  break;
   450          case OE_Abort:      zType = "abort";     break;
   451          case OE_Fail:       zType = "fail";      break;
   452          case OE_Ignore:     zType = "ignore";    break;
   453        }
   454        sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
   455        break;
   456      }
   457  #endif
   458      case TK_MATCH: {
   459        sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s",
   460                            pExpr->iTable, pExpr->iColumn, zFlgs);
   461        sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
   462        break;
   463      }
   464      case TK_VECTOR: {
   465        sqlite3TreeViewBareExprList(pView, pExpr->x.pList, "VECTOR");
   466        break;
   467      }
   468      case TK_SELECT_COLUMN: {
   469        sqlite3TreeViewLine(pView, "SELECT-COLUMN %d", pExpr->iColumn);
   470        sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
   471        break;
   472      }
   473      case TK_IF_NULL_ROW: {
   474        sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable);
   475        sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
   476        break;
   477      }
   478      default: {
   479        sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
   480        break;
   481      }
   482    }
   483    if( zBinOp ){
   484      sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs);
   485      sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
   486      sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
   487    }else if( zUniOp ){
   488      sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs);
   489      sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
   490    }
   491    sqlite3TreeViewPop(pView);
   492  }
   493  
   494  
   495  /*
   496  ** Generate a human-readable explanation of an expression list.
   497  */
   498  void sqlite3TreeViewBareExprList(
   499    TreeView *pView,
   500    const ExprList *pList,
   501    const char *zLabel
   502  ){
   503    if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
   504    if( pList==0 ){
   505      sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
   506    }else{
   507      int i;
   508      sqlite3TreeViewLine(pView, "%s", zLabel);
   509      for(i=0; i<pList->nExpr; i++){
   510        int j = pList->a[i].u.x.iOrderByCol;
   511        if( j ){
   512          sqlite3TreeViewPush(pView, 0);
   513          sqlite3TreeViewLine(pView, "iOrderByCol=%d", j);
   514        }
   515        sqlite3TreeViewExpr(pView, pList->a[i].pExpr, i<pList->nExpr-1);
   516        if( j ) sqlite3TreeViewPop(pView);
   517      }
   518    }
   519  }
   520  void sqlite3TreeViewExprList(
   521    TreeView *pView,
   522    const ExprList *pList,
   523    u8 moreToFollow,
   524    const char *zLabel
   525  ){
   526    pView = sqlite3TreeViewPush(pView, moreToFollow);
   527    sqlite3TreeViewBareExprList(pView, pList, zLabel);
   528    sqlite3TreeViewPop(pView);
   529  }
   530  
   531  #endif /* SQLITE_DEBUG */