AryaWu/sqlite
0
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);