Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
treeview.c1323 linesDownload Raw Back to src
1/*2** 2015-06-083**4** The author disclaims copyright to this source code.  In place of5** 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 and15** analysis. 16**17** The interfaces in this file is only available when compiling18** with SQLITE_DEBUG.19*/20#include "sqliteInt.h"21#ifdef SQLITE_DEBUG22 23/*24** Add a new subitem to the tree.  The moreToFollow flag indicates that this25** is not the last item in the tree.26*/27static void sqlite3TreeViewPush(TreeView **pp, u8 moreToFollow){28  TreeView *p = *pp;29  if( p==0 ){30    *pp = p = sqlite3_malloc64( sizeof(*p) );31    if( p==0 ) return;32    memset(p, 0, sizeof(*p));33  }else{34    p->iLevel++;35  }36  assert( moreToFollow==0 || moreToFollow==1 );37  if( p->iLevel<(int)sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;38}39 40/*41** Finished with one layer of the tree42*/43static void sqlite3TreeViewPop(TreeView **pp){44  TreeView *p = *pp;45  if( p==0 ) return;46  p->iLevel--;47  if( p->iLevel<0 ){48    sqlite3_free(p);49    *pp = 0;50  }51}52 53/*54** Generate a single line of output for the tree, with a prefix that contains55** all the appropriate tree lines56*/57void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){58  va_list ap;59  int i;60  StrAccum acc;61  char zBuf[1000];62  sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);63  if( p ){64    for(i=0; i<p->iLevel && i<(int)sizeof(p->bLine)-1; i++){65      sqlite3_str_append(&acc, p->bLine[i] ? "|   " : "    ", 4);66    }67    sqlite3_str_append(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);68  }69  if( zFormat!=0 ){70    va_start(ap, zFormat);71    sqlite3_str_vappendf(&acc, zFormat, ap);72    va_end(ap);73    assert( acc.nChar>0 || acc.accError );74    sqlite3_str_append(&acc, "\n", 1);75  }76  sqlite3StrAccumFinish(&acc);77  fprintf(stdout,"%s", zBuf);78  fflush(stdout);79}80 81/*82** Shorthand for starting a new tree item that consists of a single label83*/84static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){85  sqlite3TreeViewPush(&p, moreFollows);86  sqlite3TreeViewLine(p, "%s", zLabel);87}88 89/*90** Show a list of Column objects in tree format.91*/92void sqlite3TreeViewColumnList(93  TreeView *pView,94  const Column *aCol,95  int nCol,96  u8 moreToFollow97){98  int i;99  sqlite3TreeViewPush(&pView, moreToFollow);100  sqlite3TreeViewLine(pView, "COLUMNS");101  for(i=0; i<nCol; i++){102    u16 flg = aCol[i].colFlags;103    int colMoreToFollow = i<(nCol - 1);104    sqlite3TreeViewPush(&pView, colMoreToFollow);105    sqlite3TreeViewLine(pView, 0);106    printf(" %s", aCol[i].zCnName);107    switch( aCol[i].eCType ){108      case COLTYPE_ANY:      printf(" ANY");        break;109      case COLTYPE_BLOB:     printf(" BLOB");       break;110      case COLTYPE_INT:      printf(" INT");        break;111      case COLTYPE_INTEGER:  printf(" INTEGER");    break;112      case COLTYPE_REAL:     printf(" REAL");       break;113      case COLTYPE_TEXT:     printf(" TEXT");       break;114      case COLTYPE_CUSTOM: {115        if( flg & COLFLAG_HASTYPE ){116          const char *z = aCol[i].zCnName;117          z += strlen(z)+1;118          printf(" X-%s", z);119          break;120        }121      }122    }123    if( flg & COLFLAG_PRIMKEY ) printf(" PRIMARY KEY");124    if( flg & COLFLAG_HIDDEN ) printf(" HIDDEN");125#ifdef COLFLAG_NOEXPAND126    if( flg & COLFLAG_NOEXPAND ) printf(" NO-EXPAND");127#endif128    if( flg ) printf(" flags=%04x", flg);129    printf("\n");      130    fflush(stdout);131    sqlite3TreeViewPop(&pView);132  }133  sqlite3TreeViewPop(&pView);134}135 136/*137** Generate a human-readable description of a WITH clause.138*/139void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){140  int i;141  if( pWith==0 ) return;142  if( pWith->nCte==0 ) return;143  if( pWith->pOuter ){144    sqlite3TreeViewLine(pView, "WITH (0x%p, pOuter=0x%p)",pWith,pWith->pOuter);145  }else{146    sqlite3TreeViewLine(pView, "WITH (0x%p)", pWith);147  }148  if( pWith->nCte>0 ){149    sqlite3TreeViewPush(&pView, moreToFollow);150    for(i=0; i<pWith->nCte; i++){151      StrAccum x;152      char zLine[1000];153      const struct Cte *pCte = &pWith->a[i];154      sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);155      sqlite3_str_appendf(&x, "%s", pCte->zName);156      if( pCte->pCols && pCte->pCols->nExpr>0 ){157        char cSep = '(';158        int j;159        for(j=0; j<pCte->pCols->nExpr; j++){160          sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zEName);161          cSep = ',';162        }163        sqlite3_str_appendf(&x, ")");164      }165      if( pCte->eM10d!=M10d_Any ){166        sqlite3_str_appendf(&x, " %sMATERIALIZED", 167           pCte->eM10d==M10d_No ? "NOT " : "");168      }169      if( pCte->pUse ){170        sqlite3_str_appendf(&x, " (pUse=0x%p, nUse=%d)", pCte->pUse,171                 pCte->pUse->nUse);172      }173      sqlite3StrAccumFinish(&x);174      sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1);175      sqlite3TreeViewSelect(pView, pCte->pSelect, 0);176      sqlite3TreeViewPop(&pView);177    }178    sqlite3TreeViewPop(&pView);179  }180}181 182/*183** Generate a human-readable description of a SrcList object.184*/185void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){186  int i;187  if( pSrc==0 ) return;188  for(i=0; i<pSrc->nSrc; i++){189    const SrcItem *pItem = &pSrc->a[i];190    StrAccum x;191    int n = 0;192    char zLine[1000];193    sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);194    x.printfFlags |= SQLITE_PRINTF_INTERNAL;195    sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);196    if( pItem->pSTab ){197      sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx%s",198           pItem->pSTab->zName, pItem->pSTab->nCol, pItem->pSTab, 199           pItem->colUsed,200           pItem->fg.rowidUsed ? "+rowid" : "");201    }202    if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){203      sqlite3_str_appendf(&x, " FULL-OUTER-JOIN");204    }else if( pItem->fg.jointype & JT_LEFT ){205      sqlite3_str_appendf(&x, " LEFT-JOIN");206    }else if( pItem->fg.jointype & JT_RIGHT ){207      sqlite3_str_appendf(&x, " RIGHT-JOIN");208    }else if( pItem->fg.jointype & JT_CROSS ){209      sqlite3_str_appendf(&x, " CROSS-JOIN");210    }211    if( pItem->fg.jointype & JT_LTORJ ){212      sqlite3_str_appendf(&x, " LTORJ");213    }214    if( pItem->fg.fromDDL ){215      sqlite3_str_appendf(&x, " DDL");216    }217    if( pItem->fg.isCte ){218      static const char *aMat[] = {",MAT", "", ",NO-MAT"};219      sqlite3_str_appendf(&x, " CteUse=%d%s",220                          pItem->u2.pCteUse->nUse,221                          aMat[pItem->u2.pCteUse->eM10d]);222    }223    if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){224      sqlite3_str_appendf(&x, " isOn");225    }226    if( pItem->fg.isTabFunc )      sqlite3_str_appendf(&x, " isTabFunc");227    if( pItem->fg.isCorrelated )   sqlite3_str_appendf(&x, " isCorrelated");228    if( pItem->fg.isMaterialized ) sqlite3_str_appendf(&x, " isMaterialized");229    if( pItem->fg.viaCoroutine )   sqlite3_str_appendf(&x, " viaCoroutine");230    if( pItem->fg.notCte )         sqlite3_str_appendf(&x, " notCte");231    if( pItem->fg.isNestedFrom )   sqlite3_str_appendf(&x, " isNestedFrom");232    if( pItem->fg.fixedSchema )    sqlite3_str_appendf(&x, " fixedSchema");233    if( pItem->fg.hadSchema )      sqlite3_str_appendf(&x, " hadSchema");234    if( pItem->fg.isSubquery )     sqlite3_str_appendf(&x, " isSubquery");235 236    sqlite3StrAccumFinish(&x);237    sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1);238    n = 0;239    if( pItem->fg.isSubquery ) n++;240    if( pItem->fg.isTabFunc ) n++;241    if( pItem->fg.isUsing || pItem->u3.pOn!=0 ) n++;242    if( pItem->fg.isUsing ){243      sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");244    }else if( pItem->u3.pOn!=0 ){245      sqlite3TreeViewItem(pView, "ON", (--n)>0);246      sqlite3TreeViewExpr(pView, pItem->u3.pOn, 0);247      sqlite3TreeViewPop(&pView);248    }249    if( pItem->fg.isSubquery ){250      assert( n==1 );251      if( pItem->pSTab ){252        Table *pTab = pItem->pSTab;253        sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);254      }255      assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem) );256      sqlite3TreeViewSelect(pView, pItem->u4.pSubq->pSelect, 0);257    }258    if( pItem->fg.isTabFunc ){259      sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");260    }261    sqlite3TreeViewPop(&pView);262  }263}264 265/*266** Generate a human-readable description of a Select object.267*/268void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){269  int n = 0;270  int cnt = 0;271  if( p==0 ){272    sqlite3TreeViewLine(pView, "nil-SELECT");273    return;274  } 275  sqlite3TreeViewPush(&pView, moreToFollow);276  if( p->pWith ){277    sqlite3TreeViewWith(pView, p->pWith, 1);278    cnt = 1;279    sqlite3TreeViewPush(&pView, 1);280  }281  do{282    if( p->selFlags & SF_WhereBegin ){283      sqlite3TreeViewLine(pView, "sqlite3WhereBegin()");284    }else{285      sqlite3TreeViewLine(pView,286        "SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d",287        ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),288        ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""),289        p->selId, p, p->selFlags,290        (int)p->nSelectRow291      );292    }293    if( cnt++ ) sqlite3TreeViewPop(&pView);294    if( p->pPrior ){295      n = 1000;296    }else{297      n = 0;298      if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ) n++;299      if( p->pWhere ) n++;300      if( p->pGroupBy ) n++;301      if( p->pHaving ) n++;302      if( p->pOrderBy ) n++;303      if( p->pLimit ) n++;304#ifndef SQLITE_OMIT_WINDOWFUNC305      if( p->pWin ) n++;306      if( p->pWinDefn ) n++;307#endif308    }309    if( p->pEList ){310      sqlite3TreeViewExprList(pView, p->pEList, n>0, "result-set");311    }312    n--;313#ifndef SQLITE_OMIT_WINDOWFUNC314    if( p->pWin ){315      Window *pX;316      sqlite3TreeViewPush(&pView, (n--)>0);317      sqlite3TreeViewLine(pView, "window-functions");318      for(pX=p->pWin; pX; pX=pX->pNextWin){319        sqlite3TreeViewWinFunc(pView, pX, pX->pNextWin!=0);320      }321      sqlite3TreeViewPop(&pView);322    }323#endif324    if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ){325      sqlite3TreeViewPush(&pView, (n--)>0);326      sqlite3TreeViewLine(pView, "FROM");327      sqlite3TreeViewSrcList(pView, p->pSrc);328      sqlite3TreeViewPop(&pView);329    }330    if( p->pWhere ){331      sqlite3TreeViewItem(pView, "WHERE", (n--)>0);332      sqlite3TreeViewExpr(pView, p->pWhere, 0);333      sqlite3TreeViewPop(&pView);334    }335    if( p->pGroupBy ){336      sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");337    }338    if( p->pHaving ){339      sqlite3TreeViewItem(pView, "HAVING", (n--)>0);340      sqlite3TreeViewExpr(pView, p->pHaving, 0);341      sqlite3TreeViewPop(&pView);342    }343#ifndef SQLITE_OMIT_WINDOWFUNC344    if( p->pWinDefn ){345      Window *pX;346      sqlite3TreeViewItem(pView, "WINDOW", (n--)>0);347      for(pX=p->pWinDefn; pX; pX=pX->pNextWin){348        sqlite3TreeViewWindow(pView, pX, pX->pNextWin!=0);349      }350      sqlite3TreeViewPop(&pView);351    }352#endif353    if( p->pOrderBy ){354      sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");355    }356    if( p->pLimit ){357      sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);358      sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);359      if( p->pLimit->pRight ){360        sqlite3TreeViewItem(pView, "OFFSET", 0);361        sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);362        sqlite3TreeViewPop(&pView);363      }364      sqlite3TreeViewPop(&pView);365    }366    if( p->pPrior ){367      const char *zOp = "UNION";368      switch( p->op ){369        case TK_ALL:         zOp = "UNION ALL";  break;370        case TK_INTERSECT:   zOp = "INTERSECT";  break;371        case TK_EXCEPT:      zOp = "EXCEPT";     break;372      }373      sqlite3TreeViewItem(pView, zOp, 1);374    }375    p = p->pPrior;376  }while( p!=0 );377  sqlite3TreeViewPop(&pView);378}379 380#ifndef SQLITE_OMIT_WINDOWFUNC381/*382** Generate a description of starting or stopping bounds383*/384void sqlite3TreeViewBound(385  TreeView *pView,        /* View context */386  u8 eBound,              /* UNBOUNDED, CURRENT, PRECEDING, FOLLOWING */387  Expr *pExpr,            /* Value for PRECEDING or FOLLOWING */388  u8 moreToFollow         /* True if more to follow */389){390  switch( eBound ){391    case TK_UNBOUNDED: {392      sqlite3TreeViewItem(pView, "UNBOUNDED", moreToFollow);393      sqlite3TreeViewPop(&pView);394      break;395    }396    case TK_CURRENT: {397      sqlite3TreeViewItem(pView, "CURRENT", moreToFollow);398      sqlite3TreeViewPop(&pView);399      break;400    }401    case TK_PRECEDING: {402      sqlite3TreeViewItem(pView, "PRECEDING", moreToFollow);403      sqlite3TreeViewExpr(pView, pExpr, 0);404      sqlite3TreeViewPop(&pView);405      break;406    }407    case TK_FOLLOWING: {408      sqlite3TreeViewItem(pView, "FOLLOWING", moreToFollow);409      sqlite3TreeViewExpr(pView, pExpr, 0);410      sqlite3TreeViewPop(&pView);411      break;412    }413  }414}415#endif /* SQLITE_OMIT_WINDOWFUNC */416 417#ifndef SQLITE_OMIT_WINDOWFUNC418/*419** Generate a human-readable explanation for a Window object420*/421void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u8 more){422  int nElement = 0;423  if( pWin==0 ) return;424  if( pWin->pFilter ){425    sqlite3TreeViewItem(pView, "FILTER", 1);426    sqlite3TreeViewExpr(pView, pWin->pFilter, 0);427    sqlite3TreeViewPop(&pView);428    if( pWin->eFrmType==TK_FILTER ) return;429  }430  sqlite3TreeViewPush(&pView, more);431  if( pWin->zName ){432    sqlite3TreeViewLine(pView, "OVER %s (%p)", pWin->zName, pWin);433  }else{434    sqlite3TreeViewLine(pView, "OVER (%p)", pWin);435  }436  if( pWin->zBase )    nElement++;437  if( pWin->pOrderBy ) nElement++;438  if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ) nElement++;439  if( pWin->eExclude ) nElement++;440  if( pWin->zBase ){441    sqlite3TreeViewPush(&pView, (--nElement)>0);442    sqlite3TreeViewLine(pView, "window: %s", pWin->zBase);443    sqlite3TreeViewPop(&pView);444  }445  if( pWin->pPartition ){446    sqlite3TreeViewExprList(pView, pWin->pPartition, nElement>0,"PARTITION-BY");447  }448  if( pWin->pOrderBy ){449    sqlite3TreeViewExprList(pView, pWin->pOrderBy, (--nElement)>0, "ORDER-BY");450  }451  if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ){452    char zBuf[30];453    const char *zFrmType = "ROWS";454    if( pWin->eFrmType==TK_RANGE ) zFrmType = "RANGE";455    if( pWin->eFrmType==TK_GROUPS ) zFrmType = "GROUPS";456    sqlite3_snprintf(sizeof(zBuf),zBuf,"%s%s",zFrmType,457        pWin->bImplicitFrame ? " (implied)" : "");458    sqlite3TreeViewItem(pView, zBuf, (--nElement)>0);459    sqlite3TreeViewBound(pView, pWin->eStart, pWin->pStart, 1);460    sqlite3TreeViewBound(pView, pWin->eEnd, pWin->pEnd, 0);461    sqlite3TreeViewPop(&pView);462  }463  if( pWin->eExclude ){464    char zBuf[30];465    const char *zExclude;466    switch( pWin->eExclude ){467      case TK_NO:      zExclude = "NO OTHERS";   break;468      case TK_CURRENT: zExclude = "CURRENT ROW"; break;469      case TK_GROUP:   zExclude = "GROUP";       break;470      case TK_TIES:    zExclude = "TIES";        break;471      default:472        sqlite3_snprintf(sizeof(zBuf),zBuf,"invalid(%d)", pWin->eExclude);473        zExclude = zBuf;474        break;475    }476    sqlite3TreeViewPush(&pView, 0);477    sqlite3TreeViewLine(pView, "EXCLUDE %s", zExclude);478    sqlite3TreeViewPop(&pView);479  }480  sqlite3TreeViewPop(&pView);481}482#endif /* SQLITE_OMIT_WINDOWFUNC */483 484#ifndef SQLITE_OMIT_WINDOWFUNC485/*486** Generate a human-readable explanation for a Window Function object487*/488void sqlite3TreeViewWinFunc(TreeView *pView, const Window *pWin, u8 more){489  if( pWin==0 ) return;490  sqlite3TreeViewPush(&pView, more);491  sqlite3TreeViewLine(pView, "WINFUNC %s(%d)",492                       pWin->pWFunc->zName, pWin->pWFunc->nArg);493  sqlite3TreeViewWindow(pView, pWin, 0);494  sqlite3TreeViewPop(&pView);495}496#endif /* SQLITE_OMIT_WINDOWFUNC */497 498/*499** Generate a human-readable explanation of an expression tree.500*/501void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){502  const char *zBinOp = 0;   /* Binary operator */503  const char *zUniOp = 0;   /* Unary operator */504  char zFlgs[200];505  sqlite3TreeViewPush(&pView, moreToFollow);506  if( pExpr==0 ){507    sqlite3TreeViewLine(pView, "nil");508    sqlite3TreeViewPop(&pView);509    return;510  }511  if( pExpr->flags || pExpr->affExpr || pExpr->vvaFlags || pExpr->pAggInfo ){512    StrAccum x;513    sqlite3StrAccumInit(&x, 0, zFlgs, sizeof(zFlgs), 0);514    sqlite3_str_appendf(&x, " fg.af=%x.%c",515      pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n');516    if( ExprHasProperty(pExpr, EP_OuterON) ){517      sqlite3_str_appendf(&x, " outer.iJoin=%d", pExpr->w.iJoin);518    }519    if( ExprHasProperty(pExpr, EP_InnerON) ){520      sqlite3_str_appendf(&x, " inner.iJoin=%d", pExpr->w.iJoin);521    }522    if( ExprHasProperty(pExpr, EP_FromDDL) ){523      sqlite3_str_appendf(&x, " DDL");524    }525    if( ExprHasVVAProperty(pExpr, EP_Immutable) ){526      sqlite3_str_appendf(&x, " IMMUTABLE");527    }528    if( pExpr->pAggInfo!=0 ){529      sqlite3_str_appendf(&x, " agg-column[%d]", pExpr->iAgg);530    }531    sqlite3StrAccumFinish(&x);532  }else{533    zFlgs[0] = 0;534  }535  switch( pExpr->op ){536    case TK_AGG_COLUMN: {537      sqlite3TreeViewLine(pView, "AGG{%d:%d}%s",538            pExpr->iTable, pExpr->iColumn, zFlgs);539      break;540    }541    case TK_COLUMN: {542      if( pExpr->iTable<0 ){543        /* This only happens when coding check constraints */544        char zOp2[16];545        if( pExpr->op2 ){546          sqlite3_snprintf(sizeof(zOp2),zOp2," op2=0x%02x",pExpr->op2);547        }else{548          zOp2[0] = 0;549        }550        sqlite3TreeViewLine(pView, "COLUMN(%d)%s%s",551                                    pExpr->iColumn, zFlgs, zOp2);552      }else{553        assert( ExprUseYTab(pExpr) );554        sqlite3TreeViewLine(pView, "{%d:%d} pTab=%p%s",555                        pExpr->iTable, pExpr->iColumn,556                        pExpr->y.pTab, zFlgs);557      }558      if( ExprHasProperty(pExpr, EP_FixedCol) ){559        sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);560      }561      break;562    }563    case TK_INTEGER: {564      if( pExpr->flags & EP_IntValue ){565        sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);566      }else{567        sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);568      }569      break;570    }571#ifndef SQLITE_OMIT_FLOATING_POINT572    case TK_FLOAT: {573      assert( !ExprHasProperty(pExpr, EP_IntValue) );574      sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);575      break;576    }577#endif578    case TK_STRING: {579      assert( !ExprHasProperty(pExpr, EP_IntValue) );580      sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);581      break;582    }583    case TK_NULL: {584      sqlite3TreeViewLine(pView,"NULL");585      break;586    }587    case TK_TRUEFALSE: {588      sqlite3TreeViewLine(pView,"%s%s",589         sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE", zFlgs);590      break;591    }592#ifndef SQLITE_OMIT_BLOB_LITERAL593    case TK_BLOB: {594      assert( !ExprHasProperty(pExpr, EP_IntValue) );595      sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);596      break;597    }598#endif599    case TK_VARIABLE: {600      assert( !ExprHasProperty(pExpr, EP_IntValue) );601      sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",602                          pExpr->u.zToken, pExpr->iColumn);603      break;604    }605    case TK_REGISTER: {606      sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);607      break;608    }609    case TK_ID: {610      assert( !ExprHasProperty(pExpr, EP_IntValue) );611      sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);612      break;613    }614#ifndef SQLITE_OMIT_CAST615    case TK_CAST: {616      /* Expressions of the form:   CAST(pLeft AS token) */617      assert( !ExprHasProperty(pExpr, EP_IntValue) );618      sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);619      sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);620      break;621    }622#endif /* SQLITE_OMIT_CAST */623    case TK_LT:      zBinOp = "LT";     break;624    case TK_LE:      zBinOp = "LE";     break;625    case TK_GT:      zBinOp = "GT";     break;626    case TK_GE:      zBinOp = "GE";     break;627    case TK_NE:      zBinOp = "NE";     break;628    case TK_EQ:      zBinOp = "EQ";     break;629    case TK_IS:      zBinOp = "IS";     break;630    case TK_ISNOT:   zBinOp = "ISNOT";  break;631    case TK_AND:     zBinOp = "AND";    break;632    case TK_OR:      zBinOp = "OR";     break;633    case TK_PLUS:    zBinOp = "ADD";    break;634    case TK_STAR:    zBinOp = "MUL";    break;635    case TK_MINUS:   zBinOp = "SUB";    break;636    case TK_REM:     zBinOp = "REM";    break;637    case TK_BITAND:  zBinOp = "BITAND"; break;638    case TK_BITOR:   zBinOp = "BITOR";  break;639    case TK_SLASH:   zBinOp = "DIV";    break;640    case TK_LSHIFT:  zBinOp = "LSHIFT"; break;641    case TK_RSHIFT:  zBinOp = "RSHIFT"; break;642    case TK_CONCAT:  zBinOp = "CONCAT"; break;643    case TK_DOT:     zBinOp = "DOT";    break;644    case TK_LIMIT:   zBinOp = "LIMIT";  break;645 646    case TK_UMINUS:  zUniOp = "UMINUS"; break;647    case TK_UPLUS:   zUniOp = "UPLUS";  break;648    case TK_BITNOT:  zUniOp = "BITNOT"; break;649    case TK_NOT:     zUniOp = "NOT";    break;650    case TK_ISNULL:  zUniOp = "ISNULL"; break;651    case TK_NOTNULL: zUniOp = "NOTNULL"; break;652 653    case TK_TRUTH: {654      int x;655      const char *azOp[] = {656         "IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE"657      };658      assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT );659      assert( pExpr->pRight );660      assert( sqlite3ExprSkipCollateAndLikely(pExpr->pRight)->op661                  == TK_TRUEFALSE );662      x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight);663      zUniOp = azOp[x];664      break;665    }666 667    case TK_SPAN: {668      assert( !ExprHasProperty(pExpr, EP_IntValue) );669      sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken);670      sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);671      break;672    }673 674    case TK_COLLATE: {675      /* COLLATE operators without the EP_Collate flag are intended to676      ** emulate collation associated with a table column.  These show677      ** up in the treeview output as "SOFT-COLLATE".  Explicit COLLATE678      ** operators that appear in the original SQL always have the679      ** EP_Collate bit set and appear in treeview output as just "COLLATE" */680      assert( !ExprHasProperty(pExpr, EP_IntValue) );681      sqlite3TreeViewLine(pView, "%sCOLLATE %Q%s",682        !ExprHasProperty(pExpr, EP_Collate) ? "SOFT-" : "",683        pExpr->u.zToken, zFlgs);684      sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);685      break;686    }687 688    case TK_AGG_FUNCTION:689    case TK_FUNCTION: {690      ExprList *pFarg;       /* List of function arguments */691      Window *pWin;692      if( ExprHasProperty(pExpr, EP_TokenOnly) ){693        pFarg = 0;694        pWin = 0;695      }else{696        assert( ExprUseXList(pExpr) );697        pFarg = pExpr->x.pList;698#ifndef SQLITE_OMIT_WINDOWFUNC699        pWin = IsWindowFunc(pExpr) ? pExpr->y.pWin : 0;700#else701        pWin = 0;702#endif 703      }704      assert( !ExprHasProperty(pExpr, EP_IntValue) );705      if( pExpr->op==TK_AGG_FUNCTION ){706        sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s agg=%d[%d]/%p",707                             pExpr->op2, pExpr->u.zToken, zFlgs,708                             pExpr->pAggInfo ? pExpr->pAggInfo->selId : 0,709                             pExpr->iAgg, pExpr->pAggInfo);710      }else if( pExpr->op2!=0 ){711        const char *zOp2;712        char zBuf[8];713        sqlite3_snprintf(sizeof(zBuf),zBuf,"0x%02x",pExpr->op2);714        zOp2 = zBuf;715        if( pExpr->op2==NC_IsCheck ) zOp2 = "NC_IsCheck";716        if( pExpr->op2==NC_IdxExpr ) zOp2 = "NC_IdxExpr";717        if( pExpr->op2==NC_PartIdx ) zOp2 = "NC_PartIdx";718        if( pExpr->op2==NC_GenCol ) zOp2 = "NC_GenCol";719        sqlite3TreeViewLine(pView, "FUNCTION %Q%s op2=%s",720                            pExpr->u.zToken, zFlgs, zOp2);721      }else{722        sqlite3TreeViewLine(pView, "FUNCTION %Q%s", pExpr->u.zToken, zFlgs);723      }724      if( pFarg ){725        sqlite3TreeViewExprList(pView, pFarg, pWin!=0 || pExpr->pLeft, 0);726        if( pExpr->pLeft ){727          Expr *pOB = pExpr->pLeft;728          assert( pOB->op==TK_ORDER );729          assert( ExprUseXList(pOB) );730          sqlite3TreeViewExprList(pView, pOB->x.pList, pWin!=0, "ORDERBY");731        }732      }733#ifndef SQLITE_OMIT_WINDOWFUNC734      if( pWin ){735        sqlite3TreeViewWindow(pView, pWin, 0);736      }737#endif738      break;739    }740    case TK_ORDER: {741      sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, "ORDERBY");742      break;743    }744#ifndef SQLITE_OMIT_SUBQUERY745    case TK_EXISTS: {746      assert( ExprUseXSelect(pExpr) );747      sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags);748      sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);749      break;750    }751    case TK_SELECT: {752      assert( ExprUseXSelect(pExpr) );753      sqlite3TreeViewLine(pView, "subquery-expr flags=0x%x", pExpr->flags);754      sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);755      break;756    }757    case TK_IN: {758      sqlite3_str *pStr = sqlite3_str_new(0);759      char *z;760      sqlite3_str_appendf(pStr, "IN flags=0x%x", pExpr->flags);761      if( pExpr->iTable ) sqlite3_str_appendf(pStr, " iTable=%d",pExpr->iTable);762      if( ExprHasProperty(pExpr, EP_Subrtn) ){763        sqlite3_str_appendf(pStr, " subrtn(%d,%d)",764            pExpr->y.sub.regReturn, pExpr->y.sub.iAddr);765      }766      z = sqlite3_str_finish(pStr);767      sqlite3TreeViewLine(pView, z);768      sqlite3_free(z);769      sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);770      if( ExprUseXSelect(pExpr) ){771        sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);772      }else{773        sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);774      }775      break;776    }777#endif /* SQLITE_OMIT_SUBQUERY */778 779    /*780    **    x BETWEEN y AND z781    **782    ** This is equivalent to783    **784    **    x>=y AND x<=z785    **786    ** X is stored in pExpr->pLeft.787    ** Y is stored in pExpr->pList->a[0].pExpr.788    ** Z is stored in pExpr->pList->a[1].pExpr.789    */790    case TK_BETWEEN: {791      const Expr *pX, *pY, *pZ;792      pX = pExpr->pLeft;793      assert( ExprUseXList(pExpr) );794      assert( pExpr->x.pList->nExpr==2 );795      pY = pExpr->x.pList->a[0].pExpr;796      pZ = pExpr->x.pList->a[1].pExpr;797      sqlite3TreeViewLine(pView, "BETWEEN%s", zFlgs);798      sqlite3TreeViewExpr(pView, pX, 1);799      sqlite3TreeViewExpr(pView, pY, 1);800      sqlite3TreeViewExpr(pView, pZ, 0);801      break;802    }803    case TK_TRIGGER: {804      /* If the opcode is TK_TRIGGER, then the expression is a reference805      ** to a column in the new.* or old.* pseudo-tables available to806      ** trigger programs. In this case Expr.iTable is set to 1 for the807      ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn808      ** is set to the column of the pseudo-table to read, or to -1 to809      ** read the rowid field.810      */811      sqlite3TreeViewLine(pView, "%s(%d)", 812          pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);813      break;814    }815    case TK_CASE: {816      sqlite3TreeViewLine(pView, "CASE");817      sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);818      assert( ExprUseXList(pExpr) );819      sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);820      break;821    }822#ifndef SQLITE_OMIT_TRIGGER823    case TK_RAISE: {824      const char *zType = "unk";825      switch( pExpr->affExpr ){826        case OE_Rollback:   zType = "rollback";  break;827        case OE_Abort:      zType = "abort";     break;828        case OE_Fail:       zType = "fail";      break;829        case OE_Ignore:     zType = "ignore";    break;830      }831      assert( !ExprHasProperty(pExpr, EP_IntValue) );832      sqlite3TreeViewLine(pView, "RAISE %s", zType);833      sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);834      break;835    }836#endif837    case TK_MATCH: {838      sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s",839                          pExpr->iTable, pExpr->iColumn, zFlgs);840      sqlite3TreeViewExpr(pView, pExpr->pRight, 0);841      break;842    }843    case TK_VECTOR: {844      char *z = sqlite3_mprintf("VECTOR%s",zFlgs);845      assert( ExprUseXList(pExpr) );846      sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z);847      sqlite3_free(z);848      break;849    }850    case TK_SELECT_COLUMN: {851      sqlite3TreeViewLine(pView, "SELECT-COLUMN %d of [0..%d]%s",852              pExpr->iColumn, pExpr->iTable-1,853              pExpr->pRight==pExpr->pLeft ? " (SELECT-owner)" : "");854      assert( ExprUseXSelect(pExpr->pLeft) );855      sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);856      break;857    }858    case TK_IF_NULL_ROW: {859      sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable);860      sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);861      break;862    }863    case TK_ERROR: {864      Expr tmp;865      sqlite3TreeViewLine(pView, "ERROR");866      tmp = *pExpr;867      tmp.op = pExpr->op2;868      sqlite3TreeViewExpr(pView, &tmp, 0);869      break;870    }871    case TK_ROW: {872      if( pExpr->iColumn<=0 ){873        sqlite3TreeViewLine(pView, "First FROM table rowid");874      }else{875        sqlite3TreeViewLine(pView, "First FROM table column %d",876            pExpr->iColumn-1);877      }878      break;879    }880    default: {881      sqlite3TreeViewLine(pView, "op=%d", pExpr->op);882      break;883    }884  }885  if( zBinOp ){886    sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs);887    sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);888    sqlite3TreeViewExpr(pView, pExpr->pRight, 0);889  }else if( zUniOp ){890    sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs);891   sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);892  }893  sqlite3TreeViewPop(&pView);894}895 896 897/*898** Generate a human-readable explanation of an expression list.899*/900void sqlite3TreeViewBareExprList(901  TreeView *pView,902  const ExprList *pList,903  const char *zLabel904){905  if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";906  if( pList==0 ){907    sqlite3TreeViewLine(pView, "%s (empty)", zLabel);908  }else{909    int i;910    sqlite3TreeViewLine(pView, "%s", zLabel);911    for(i=0; i<pList->nExpr; i++){912      int j = pList->a[i].u.x.iOrderByCol;913      u8 sortFlags = pList->a[i].fg.sortFlags;914      char *zName = pList->a[i].zEName;915      int moreToFollow = i<pList->nExpr - 1;916      if( j || zName || sortFlags ){917        sqlite3TreeViewPush(&pView, moreToFollow);918        moreToFollow = 0;919        sqlite3TreeViewLine(pView, 0);920        if( zName ){921          switch( pList->a[i].fg.eEName ){922            default:923              fprintf(stdout, "AS %s ", zName);924              break;925            case ENAME_TAB:926              fprintf(stdout, "TABLE-ALIAS-NAME(\"%s\") ", zName);927              if( pList->a[i].fg.bUsed ) fprintf(stdout, "(used) ");928              if( pList->a[i].fg.bUsingTerm ) fprintf(stdout, "(USING-term) ");929              if( pList->a[i].fg.bNoExpand ) fprintf(stdout, "(NoExpand) ");930              break;931            case ENAME_SPAN:932              fprintf(stdout, "SPAN(\"%s\") ", zName);933              break;934          }935        }936        if( j ){937          fprintf(stdout, "iOrderByCol=%d ", j);938        }939        if( sortFlags & KEYINFO_ORDER_DESC ){940          fprintf(stdout, "DESC ");941        }else if( sortFlags & KEYINFO_ORDER_BIGNULL ){942          fprintf(stdout, "NULLS-LAST");943        }944        fprintf(stdout, "\n");945        fflush(stdout);946      }947      sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow);948      if( j || zName || sortFlags ){949        sqlite3TreeViewPop(&pView);950      }951    }952  }953}954void sqlite3TreeViewExprList(955  TreeView *pView,956  const ExprList *pList,957  u8 moreToFollow,958  const char *zLabel959){960  sqlite3TreeViewPush(&pView, moreToFollow);961  sqlite3TreeViewBareExprList(pView, pList, zLabel);962  sqlite3TreeViewPop(&pView);963}964 965/*966** Generate a human-readable explanation of an id-list.967*/968void sqlite3TreeViewBareIdList(969  TreeView *pView,970  const IdList *pList,971  const char *zLabel972){973  if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";974  if( pList==0 ){975    sqlite3TreeViewLine(pView, "%s (empty)", zLabel);976  }else{977    int i;978    sqlite3TreeViewLine(pView, "%s", zLabel);979    for(i=0; i<pList->nId; i++){980      char *zName = pList->a[i].zName;981      int moreToFollow = i<pList->nId - 1;982      if( zName==0 ) zName = "(null)";983      sqlite3TreeViewPush(&pView, moreToFollow);984      sqlite3TreeViewLine(pView, 0);985      fprintf(stdout, "%s\n", zName);986      sqlite3TreeViewPop(&pView);987    }988  }989}990void sqlite3TreeViewIdList(991  TreeView *pView,992  const IdList *pList,993  u8 moreToFollow,994  const char *zLabel995){996  sqlite3TreeViewPush(&pView, moreToFollow);997  sqlite3TreeViewBareIdList(pView, pList, zLabel);998  sqlite3TreeViewPop(&pView);999}1000 1001/*1002** Generate a human-readable explanation of a list of Upsert objects1003*/1004void sqlite3TreeViewUpsert(1005  TreeView *pView,1006  const Upsert *pUpsert,1007  u8 moreToFollow1008){1009  if( pUpsert==0 ) return;1010  sqlite3TreeViewPush(&pView, moreToFollow);1011  while( pUpsert ){1012    int n;1013    sqlite3TreeViewPush(&pView, pUpsert->pNextUpsert!=0 || moreToFollow);1014    sqlite3TreeViewLine(pView, "ON CONFLICT DO %s", 1015         pUpsert->isDoUpdate ? "UPDATE" : "NOTHING");1016    n = (pUpsert->pUpsertSet!=0) + (pUpsert->pUpsertWhere!=0);1017    sqlite3TreeViewExprList(pView, pUpsert->pUpsertTarget, (n--)>0, "TARGET");1018    sqlite3TreeViewExprList(pView, pUpsert->pUpsertSet, (n--)>0, "SET");1019    if( pUpsert->pUpsertWhere ){1020      sqlite3TreeViewItem(pView, "WHERE", (n--)>0);1021      sqlite3TreeViewExpr(pView, pUpsert->pUpsertWhere, 0);1022      sqlite3TreeViewPop(&pView);1023    }1024    sqlite3TreeViewPop(&pView);1025    pUpsert = pUpsert->pNextUpsert;1026  }1027  sqlite3TreeViewPop(&pView);1028}1029 1030#if TREETRACE_ENABLED1031/*1032** Generate a human-readable diagram of the data structure that go1033** into generating an DELETE statement.1034*/1035void sqlite3TreeViewDelete(1036  const With *pWith,1037  const SrcList *pTabList,1038  const Expr *pWhere,1039  const ExprList *pOrderBy,1040  const Expr *pLimit,1041  const Trigger *pTrigger1042){1043  int n = 0;1044  TreeView *pView = 0;1045  sqlite3TreeViewPush(&pView, 0);1046  sqlite3TreeViewLine(pView, "DELETE");1047  if( pWith ) n++;1048  if( pTabList ) n++;1049  if( pWhere ) n++;1050  if( pOrderBy ) n++;1051  if( pLimit ) n++;1052  if( pTrigger ) n++;1053  if( pWith ){1054    sqlite3TreeViewPush(&pView, (--n)>0);1055    sqlite3TreeViewWith(pView, pWith, 0);1056    sqlite3TreeViewPop(&pView);1057  }1058  if( pTabList ){1059    sqlite3TreeViewPush(&pView, (--n)>0);1060    sqlite3TreeViewLine(pView, "FROM");1061    sqlite3TreeViewSrcList(pView, pTabList);1062    sqlite3TreeViewPop(&pView);1063  }1064  if( pWhere ){1065    sqlite3TreeViewPush(&pView, (--n)>0);1066    sqlite3TreeViewLine(pView, "WHERE");1067    sqlite3TreeViewExpr(pView, pWhere, 0);1068    sqlite3TreeViewPop(&pView);1069  }1070  if( pOrderBy ){1071    sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY");1072  }1073  if( pLimit ){1074    sqlite3TreeViewPush(&pView, (--n)>0);1075    sqlite3TreeViewLine(pView, "LIMIT");1076    sqlite3TreeViewExpr(pView, pLimit, 0);1077    sqlite3TreeViewPop(&pView);1078  }1079  if( pTrigger ){1080    sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);1081  }1082  sqlite3TreeViewPop(&pView);1083}1084#endif /* TREETRACE_ENABLED */1085 1086#if TREETRACE_ENABLED1087/*1088** Generate a human-readable diagram of the data structure that go1089** into generating an INSERT statement.1090*/1091void sqlite3TreeViewInsert(1092  const With *pWith,1093  const SrcList *pTabList,1094  const IdList *pColumnList,1095  const Select *pSelect,1096  const ExprList *pExprList,1097  int onError,1098  const Upsert *pUpsert,1099  const Trigger *pTrigger1100){1101  TreeView *pView = 0;1102  int n = 0;1103  const char *zLabel = "INSERT";1104  switch( onError ){1105    case OE_Replace:  zLabel = "REPLACE";             break;1106    case OE_Ignore:   zLabel = "INSERT OR IGNORE";    break;1107    case OE_Rollback: zLabel = "INSERT OR ROLLBACK";  break;1108    case OE_Abort:    zLabel = "INSERT OR ABORT";     break;1109    case OE_Fail:     zLabel = "INSERT OR FAIL";      break;1110  }1111  sqlite3TreeViewPush(&pView, 0);1112  sqlite3TreeViewLine(pView, zLabel);1113  if( pWith ) n++;1114  if( pTabList ) n++;1115  if( pColumnList ) n++;1116  if( pSelect ) n++;1117  if( pExprList ) n++;1118  if( pUpsert ) n++;1119  if( pTrigger ) n++;1120  if( pWith ){1121    sqlite3TreeViewPush(&pView, (--n)>0);1122    sqlite3TreeViewWith(pView, pWith, 0);1123    sqlite3TreeViewPop(&pView);1124  }1125  if( pTabList ){1126    sqlite3TreeViewPush(&pView, (--n)>0);1127    sqlite3TreeViewLine(pView, "INTO");1128    sqlite3TreeViewSrcList(pView, pTabList);1129    sqlite3TreeViewPop(&pView);1130  }1131  if( pColumnList ){1132    sqlite3TreeViewIdList(pView, pColumnList, (--n)>0, "COLUMNS");1133  }1134  if( pSelect ){1135    sqlite3TreeViewPush(&pView, (--n)>0);1136    sqlite3TreeViewLine(pView, "DATA-SOURCE");1137    sqlite3TreeViewSelect(pView, pSelect, 0);1138    sqlite3TreeViewPop(&pView);1139  }1140  if( pExprList ){1141    sqlite3TreeViewExprList(pView, pExprList, (--n)>0, "VALUES");1142  }1143  if( pUpsert ){1144    sqlite3TreeViewPush(&pView, (--n)>0);1145    sqlite3TreeViewLine(pView, "UPSERT");1146    sqlite3TreeViewUpsert(pView, pUpsert, 0);1147    sqlite3TreeViewPop(&pView);1148  }1149  if( pTrigger ){1150    sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);1151  }1152  sqlite3TreeViewPop(&pView);1153}1154#endif /* TREETRACE_ENABLED */1155 1156#if TREETRACE_ENABLED1157/*1158** Generate a human-readable diagram of the data structure that go1159** into generating an UPDATE statement.1160*/1161void sqlite3TreeViewUpdate(1162  const With *pWith,1163  const SrcList *pTabList,1164  const ExprList *pChanges,1165  const Expr *pWhere,1166  int onError,1167  const ExprList *pOrderBy,1168  const Expr *pLimit,1169  const Upsert *pUpsert,1170  const Trigger *pTrigger1171){1172  int n = 0;1173  TreeView *pView = 0;1174  const char *zLabel = "UPDATE";1175  switch( onError ){1176    case OE_Replace:  zLabel = "UPDATE OR REPLACE";   break;1177    case OE_Ignore:   zLabel = "UPDATE OR IGNORE";    break;1178    case OE_Rollback: zLabel = "UPDATE OR ROLLBACK";  break;1179    case OE_Abort:    zLabel = "UPDATE OR ABORT";     break;1180    case OE_Fail:     zLabel = "UPDATE OR FAIL";      break;1181  }1182  sqlite3TreeViewPush(&pView, 0);1183  sqlite3TreeViewLine(pView, zLabel);1184  if( pWith ) n++;1185  if( pTabList ) n++;1186  if( pChanges ) n++;1187  if( pWhere ) n++;1188  if( pOrderBy ) n++;1189  if( pLimit ) n++;1190  if( pUpsert ) n++;1191  if( pTrigger ) n++;1192  if( pWith ){1193    sqlite3TreeViewPush(&pView, (--n)>0);1194    sqlite3TreeViewWith(pView, pWith, 0);1195    sqlite3TreeViewPop(&pView);1196  }1197  if( pTabList ){1198    sqlite3TreeViewPush(&pView, (--n)>0);1199    sqlite3TreeViewLine(pView, "FROM");1200    sqlite3TreeViewSrcList(pView, pTabList);

Showing the first 1,200 of 1323 lines. Download the file for the rest.