Replaces use of deprecated WINAPI_FAMILY_APP macro with WINAPI_FAMILY_PC_APP
[sqlcipher.git] / src / treeview.c
blobfa9eac61425419c4cb8b8e0ba7aa470fe3b1f250
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.
11 *************************************************************************
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.
17 ** The interfaces in this file is only available when compiling
18 ** with SQLITE_DEBUG.
20 #include "sqliteInt.h"
21 #ifdef SQLITE_DEBUG
24 ** Add a new subitem to the tree. The moreToFollow flag indicates that this
25 ** is not the last item in the tree.
27 static 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++;
36 assert( moreToFollow==0 || moreToFollow==1 );
37 if( p->iLevel<(int)sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
41 ** Finished with one layer of the tree
43 static 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;
54 ** Generate a single line of output for the tree, with a prefix that contains
55 ** all the appropriate tree lines
57 void 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);
67 sqlite3_str_append(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
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);
76 sqlite3StrAccumFinish(&acc);
77 fprintf(stdout,"%s", zBuf);
78 fflush(stdout);
82 ** Shorthand for starting a new tree item that consists of a single label
84 static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){
85 sqlite3TreeViewPush(&p, moreFollows);
86 sqlite3TreeViewLine(p, "%s", zLabel);
90 ** Show a list of Column objects in tree format.
92 void sqlite3TreeViewColumnList(
93 TreeView *pView,
94 const Column *aCol,
95 int nCol,
96 u8 moreToFollow
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;
123 if( flg & COLFLAG_PRIMKEY ) printf(" PRIMARY KEY");
124 if( flg & COLFLAG_HIDDEN ) printf(" HIDDEN");
125 #ifdef COLFLAG_NOEXPAND
126 if( flg & COLFLAG_NOEXPAND ) printf(" NO-EXPAND");
127 #endif
128 if( flg ) printf(" flags=%04x", flg);
129 printf("\n");
130 fflush(stdout);
131 sqlite3TreeViewPop(&pView);
133 sqlite3TreeViewPop(&pView);
137 ** Generate a human-readable description of a WITH clause.
139 void 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);
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 = ',';
163 sqlite3_str_appendf(&x, ")");
165 if( pCte->eM10d!=M10d_Any ){
166 sqlite3_str_appendf(&x, " %sMATERIALIZED",
167 pCte->eM10d==M10d_No ? "NOT " : "");
169 if( pCte->pUse ){
170 sqlite3_str_appendf(&x, " (pUse=0x%p, nUse=%d)", pCte->pUse,
171 pCte->pUse->nUse);
173 sqlite3StrAccumFinish(&x);
174 sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1);
175 sqlite3TreeViewSelect(pView, pCte->pSelect, 0);
176 sqlite3TreeViewPop(&pView);
178 sqlite3TreeViewPop(&pView);
183 ** Generate a human-readable description of a SrcList object.
185 void 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->pTab ){
197 sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx%s",
198 pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab,
199 pItem->colUsed,
200 pItem->fg.rowidUsed ? "+rowid" : "");
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");
211 if( pItem->fg.jointype & JT_LTORJ ){
212 sqlite3_str_appendf(&x, " LTORJ");
214 if( pItem->fg.fromDDL ){
215 sqlite3_str_appendf(&x, " DDL");
217 if( pItem->fg.isCte ){
218 sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse);
220 if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){
221 sqlite3_str_appendf(&x, " ON");
223 if( pItem->fg.isTabFunc ) sqlite3_str_appendf(&x, " isTabFunc");
224 if( pItem->fg.isCorrelated ) sqlite3_str_appendf(&x, " isCorrelated");
225 if( pItem->fg.isMaterialized ) sqlite3_str_appendf(&x, " isMaterialized");
226 if( pItem->fg.viaCoroutine ) sqlite3_str_appendf(&x, " viaCoroutine");
227 if( pItem->fg.notCte ) sqlite3_str_appendf(&x, " notCte");
228 if( pItem->fg.isNestedFrom ) sqlite3_str_appendf(&x, " isNestedFrom");
230 sqlite3StrAccumFinish(&x);
231 sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1);
232 n = 0;
233 if( pItem->pSelect ) n++;
234 if( pItem->fg.isTabFunc ) n++;
235 if( pItem->fg.isUsing ) n++;
236 if( pItem->fg.isUsing ){
237 sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
239 if( pItem->pSelect ){
240 sqlite3TreeViewPush(&pView, i+1<pSrc->nSrc);
241 if( pItem->pTab ){
242 Table *pTab = pItem->pTab;
243 sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
245 assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
246 sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0);
247 sqlite3TreeViewPop(&pView);
249 if( pItem->fg.isTabFunc ){
250 sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
252 sqlite3TreeViewPop(&pView);
257 ** Generate a human-readable description of a Select object.
259 void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
260 int n = 0;
261 int cnt = 0;
262 if( p==0 ){
263 sqlite3TreeViewLine(pView, "nil-SELECT");
264 return;
266 sqlite3TreeViewPush(&pView, moreToFollow);
267 if( p->pWith ){
268 sqlite3TreeViewWith(pView, p->pWith, 1);
269 cnt = 1;
270 sqlite3TreeViewPush(&pView, 1);
273 if( p->selFlags & SF_WhereBegin ){
274 sqlite3TreeViewLine(pView, "sqlite3WhereBegin()");
275 }else{
276 sqlite3TreeViewLine(pView,
277 "SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d",
278 ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
279 ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""),
280 p->selId, p, p->selFlags,
281 (int)p->nSelectRow
284 if( cnt++ ) sqlite3TreeViewPop(&pView);
285 if( p->pPrior ){
286 n = 1000;
287 }else{
288 n = 0;
289 if( p->pSrc && p->pSrc->nSrc ) n++;
290 if( p->pWhere ) n++;
291 if( p->pGroupBy ) n++;
292 if( p->pHaving ) n++;
293 if( p->pOrderBy ) n++;
294 if( p->pLimit ) n++;
295 #ifndef SQLITE_OMIT_WINDOWFUNC
296 if( p->pWin ) n++;
297 if( p->pWinDefn ) n++;
298 #endif
300 if( p->pEList ){
301 sqlite3TreeViewExprList(pView, p->pEList, n>0, "result-set");
303 n--;
304 #ifndef SQLITE_OMIT_WINDOWFUNC
305 if( p->pWin ){
306 Window *pX;
307 sqlite3TreeViewPush(&pView, (n--)>0);
308 sqlite3TreeViewLine(pView, "window-functions");
309 for(pX=p->pWin; pX; pX=pX->pNextWin){
310 sqlite3TreeViewWinFunc(pView, pX, pX->pNextWin!=0);
312 sqlite3TreeViewPop(&pView);
314 #endif
315 if( p->pSrc && p->pSrc->nSrc ){
316 sqlite3TreeViewPush(&pView, (n--)>0);
317 sqlite3TreeViewLine(pView, "FROM");
318 sqlite3TreeViewSrcList(pView, p->pSrc);
319 sqlite3TreeViewPop(&pView);
321 if( p->pWhere ){
322 sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
323 sqlite3TreeViewExpr(pView, p->pWhere, 0);
324 sqlite3TreeViewPop(&pView);
326 if( p->pGroupBy ){
327 sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
329 if( p->pHaving ){
330 sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
331 sqlite3TreeViewExpr(pView, p->pHaving, 0);
332 sqlite3TreeViewPop(&pView);
334 #ifndef SQLITE_OMIT_WINDOWFUNC
335 if( p->pWinDefn ){
336 Window *pX;
337 sqlite3TreeViewItem(pView, "WINDOW", (n--)>0);
338 for(pX=p->pWinDefn; pX; pX=pX->pNextWin){
339 sqlite3TreeViewWindow(pView, pX, pX->pNextWin!=0);
341 sqlite3TreeViewPop(&pView);
343 #endif
344 if( p->pOrderBy ){
345 sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");
347 if( p->pLimit ){
348 sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
349 sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
350 if( p->pLimit->pRight ){
351 sqlite3TreeViewItem(pView, "OFFSET", 0);
352 sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
353 sqlite3TreeViewPop(&pView);
355 sqlite3TreeViewPop(&pView);
357 if( p->pPrior ){
358 const char *zOp = "UNION";
359 switch( p->op ){
360 case TK_ALL: zOp = "UNION ALL"; break;
361 case TK_INTERSECT: zOp = "INTERSECT"; break;
362 case TK_EXCEPT: zOp = "EXCEPT"; break;
364 sqlite3TreeViewItem(pView, zOp, 1);
366 p = p->pPrior;
367 }while( p!=0 );
368 sqlite3TreeViewPop(&pView);
371 #ifndef SQLITE_OMIT_WINDOWFUNC
373 ** Generate a description of starting or stopping bounds
375 void sqlite3TreeViewBound(
376 TreeView *pView, /* View context */
377 u8 eBound, /* UNBOUNDED, CURRENT, PRECEDING, FOLLOWING */
378 Expr *pExpr, /* Value for PRECEDING or FOLLOWING */
379 u8 moreToFollow /* True if more to follow */
381 switch( eBound ){
382 case TK_UNBOUNDED: {
383 sqlite3TreeViewItem(pView, "UNBOUNDED", moreToFollow);
384 sqlite3TreeViewPop(&pView);
385 break;
387 case TK_CURRENT: {
388 sqlite3TreeViewItem(pView, "CURRENT", moreToFollow);
389 sqlite3TreeViewPop(&pView);
390 break;
392 case TK_PRECEDING: {
393 sqlite3TreeViewItem(pView, "PRECEDING", moreToFollow);
394 sqlite3TreeViewExpr(pView, pExpr, 0);
395 sqlite3TreeViewPop(&pView);
396 break;
398 case TK_FOLLOWING: {
399 sqlite3TreeViewItem(pView, "FOLLOWING", moreToFollow);
400 sqlite3TreeViewExpr(pView, pExpr, 0);
401 sqlite3TreeViewPop(&pView);
402 break;
406 #endif /* SQLITE_OMIT_WINDOWFUNC */
408 #ifndef SQLITE_OMIT_WINDOWFUNC
410 ** Generate a human-readable explanation for a Window object
412 void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u8 more){
413 int nElement = 0;
414 if( pWin==0 ) return;
415 if( pWin->pFilter ){
416 sqlite3TreeViewItem(pView, "FILTER", 1);
417 sqlite3TreeViewExpr(pView, pWin->pFilter, 0);
418 sqlite3TreeViewPop(&pView);
419 if( pWin->eFrmType==TK_FILTER ) return;
421 sqlite3TreeViewPush(&pView, more);
422 if( pWin->zName ){
423 sqlite3TreeViewLine(pView, "OVER %s (%p)", pWin->zName, pWin);
424 }else{
425 sqlite3TreeViewLine(pView, "OVER (%p)", pWin);
427 if( pWin->zBase ) nElement++;
428 if( pWin->pOrderBy ) nElement++;
429 if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ) nElement++;
430 if( pWin->eExclude ) nElement++;
431 if( pWin->zBase ){
432 sqlite3TreeViewPush(&pView, (--nElement)>0);
433 sqlite3TreeViewLine(pView, "window: %s", pWin->zBase);
434 sqlite3TreeViewPop(&pView);
436 if( pWin->pPartition ){
437 sqlite3TreeViewExprList(pView, pWin->pPartition, nElement>0,"PARTITION-BY");
439 if( pWin->pOrderBy ){
440 sqlite3TreeViewExprList(pView, pWin->pOrderBy, (--nElement)>0, "ORDER-BY");
442 if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ){
443 char zBuf[30];
444 const char *zFrmType = "ROWS";
445 if( pWin->eFrmType==TK_RANGE ) zFrmType = "RANGE";
446 if( pWin->eFrmType==TK_GROUPS ) zFrmType = "GROUPS";
447 sqlite3_snprintf(sizeof(zBuf),zBuf,"%s%s",zFrmType,
448 pWin->bImplicitFrame ? " (implied)" : "");
449 sqlite3TreeViewItem(pView, zBuf, (--nElement)>0);
450 sqlite3TreeViewBound(pView, pWin->eStart, pWin->pStart, 1);
451 sqlite3TreeViewBound(pView, pWin->eEnd, pWin->pEnd, 0);
452 sqlite3TreeViewPop(&pView);
454 if( pWin->eExclude ){
455 char zBuf[30];
456 const char *zExclude;
457 switch( pWin->eExclude ){
458 case TK_NO: zExclude = "NO OTHERS"; break;
459 case TK_CURRENT: zExclude = "CURRENT ROW"; break;
460 case TK_GROUP: zExclude = "GROUP"; break;
461 case TK_TIES: zExclude = "TIES"; break;
462 default:
463 sqlite3_snprintf(sizeof(zBuf),zBuf,"invalid(%d)", pWin->eExclude);
464 zExclude = zBuf;
465 break;
467 sqlite3TreeViewPush(&pView, 0);
468 sqlite3TreeViewLine(pView, "EXCLUDE %s", zExclude);
469 sqlite3TreeViewPop(&pView);
471 sqlite3TreeViewPop(&pView);
473 #endif /* SQLITE_OMIT_WINDOWFUNC */
475 #ifndef SQLITE_OMIT_WINDOWFUNC
477 ** Generate a human-readable explanation for a Window Function object
479 void sqlite3TreeViewWinFunc(TreeView *pView, const Window *pWin, u8 more){
480 if( pWin==0 ) return;
481 sqlite3TreeViewPush(&pView, more);
482 sqlite3TreeViewLine(pView, "WINFUNC %s(%d)",
483 pWin->pWFunc->zName, pWin->pWFunc->nArg);
484 sqlite3TreeViewWindow(pView, pWin, 0);
485 sqlite3TreeViewPop(&pView);
487 #endif /* SQLITE_OMIT_WINDOWFUNC */
490 ** Generate a human-readable explanation of an expression tree.
492 void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
493 const char *zBinOp = 0; /* Binary operator */
494 const char *zUniOp = 0; /* Unary operator */
495 char zFlgs[200];
496 sqlite3TreeViewPush(&pView, moreToFollow);
497 if( pExpr==0 ){
498 sqlite3TreeViewLine(pView, "nil");
499 sqlite3TreeViewPop(&pView);
500 return;
502 if( pExpr->flags || pExpr->affExpr || pExpr->vvaFlags || pExpr->pAggInfo ){
503 StrAccum x;
504 sqlite3StrAccumInit(&x, 0, zFlgs, sizeof(zFlgs), 0);
505 sqlite3_str_appendf(&x, " fg.af=%x.%c",
506 pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n');
507 if( ExprHasProperty(pExpr, EP_OuterON) ){
508 sqlite3_str_appendf(&x, " outer.iJoin=%d", pExpr->w.iJoin);
510 if( ExprHasProperty(pExpr, EP_InnerON) ){
511 sqlite3_str_appendf(&x, " inner.iJoin=%d", pExpr->w.iJoin);
513 if( ExprHasProperty(pExpr, EP_FromDDL) ){
514 sqlite3_str_appendf(&x, " DDL");
516 if( ExprHasVVAProperty(pExpr, EP_Immutable) ){
517 sqlite3_str_appendf(&x, " IMMUTABLE");
519 if( pExpr->pAggInfo!=0 ){
520 sqlite3_str_appendf(&x, " agg-column[%d]", pExpr->iAgg);
522 sqlite3StrAccumFinish(&x);
523 }else{
524 zFlgs[0] = 0;
526 switch( pExpr->op ){
527 case TK_AGG_COLUMN: {
528 sqlite3TreeViewLine(pView, "AGG{%d:%d}%s",
529 pExpr->iTable, pExpr->iColumn, zFlgs);
530 break;
532 case TK_COLUMN: {
533 if( pExpr->iTable<0 ){
534 /* This only happens when coding check constraints */
535 char zOp2[16];
536 if( pExpr->op2 ){
537 sqlite3_snprintf(sizeof(zOp2),zOp2," op2=0x%02x",pExpr->op2);
538 }else{
539 zOp2[0] = 0;
541 sqlite3TreeViewLine(pView, "COLUMN(%d)%s%s",
542 pExpr->iColumn, zFlgs, zOp2);
543 }else{
544 assert( ExprUseYTab(pExpr) );
545 sqlite3TreeViewLine(pView, "{%d:%d} pTab=%p%s",
546 pExpr->iTable, pExpr->iColumn,
547 pExpr->y.pTab, zFlgs);
549 if( ExprHasProperty(pExpr, EP_FixedCol) ){
550 sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
552 break;
554 case TK_INTEGER: {
555 if( pExpr->flags & EP_IntValue ){
556 sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);
557 }else{
558 sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);
560 break;
562 #ifndef SQLITE_OMIT_FLOATING_POINT
563 case TK_FLOAT: {
564 assert( !ExprHasProperty(pExpr, EP_IntValue) );
565 sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
566 break;
568 #endif
569 case TK_STRING: {
570 assert( !ExprHasProperty(pExpr, EP_IntValue) );
571 sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
572 break;
574 case TK_NULL: {
575 sqlite3TreeViewLine(pView,"NULL");
576 break;
578 case TK_TRUEFALSE: {
579 sqlite3TreeViewLine(pView,"%s%s",
580 sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE", zFlgs);
581 break;
583 #ifndef SQLITE_OMIT_BLOB_LITERAL
584 case TK_BLOB: {
585 assert( !ExprHasProperty(pExpr, EP_IntValue) );
586 sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
587 break;
589 #endif
590 case TK_VARIABLE: {
591 assert( !ExprHasProperty(pExpr, EP_IntValue) );
592 sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
593 pExpr->u.zToken, pExpr->iColumn);
594 break;
596 case TK_REGISTER: {
597 sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
598 break;
600 case TK_ID: {
601 assert( !ExprHasProperty(pExpr, EP_IntValue) );
602 sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
603 break;
605 #ifndef SQLITE_OMIT_CAST
606 case TK_CAST: {
607 /* Expressions of the form: CAST(pLeft AS token) */
608 assert( !ExprHasProperty(pExpr, EP_IntValue) );
609 sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
610 sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
611 break;
613 #endif /* SQLITE_OMIT_CAST */
614 case TK_LT: zBinOp = "LT"; break;
615 case TK_LE: zBinOp = "LE"; break;
616 case TK_GT: zBinOp = "GT"; break;
617 case TK_GE: zBinOp = "GE"; break;
618 case TK_NE: zBinOp = "NE"; break;
619 case TK_EQ: zBinOp = "EQ"; break;
620 case TK_IS: zBinOp = "IS"; break;
621 case TK_ISNOT: zBinOp = "ISNOT"; break;
622 case TK_AND: zBinOp = "AND"; break;
623 case TK_OR: zBinOp = "OR"; break;
624 case TK_PLUS: zBinOp = "ADD"; break;
625 case TK_STAR: zBinOp = "MUL"; break;
626 case TK_MINUS: zBinOp = "SUB"; break;
627 case TK_REM: zBinOp = "REM"; break;
628 case TK_BITAND: zBinOp = "BITAND"; break;
629 case TK_BITOR: zBinOp = "BITOR"; break;
630 case TK_SLASH: zBinOp = "DIV"; break;
631 case TK_LSHIFT: zBinOp = "LSHIFT"; break;
632 case TK_RSHIFT: zBinOp = "RSHIFT"; break;
633 case TK_CONCAT: zBinOp = "CONCAT"; break;
634 case TK_DOT: zBinOp = "DOT"; break;
635 case TK_LIMIT: zBinOp = "LIMIT"; break;
637 case TK_UMINUS: zUniOp = "UMINUS"; break;
638 case TK_UPLUS: zUniOp = "UPLUS"; break;
639 case TK_BITNOT: zUniOp = "BITNOT"; break;
640 case TK_NOT: zUniOp = "NOT"; break;
641 case TK_ISNULL: zUniOp = "ISNULL"; break;
642 case TK_NOTNULL: zUniOp = "NOTNULL"; break;
644 case TK_TRUTH: {
645 int x;
646 const char *azOp[] = {
647 "IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE"
649 assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT );
650 assert( pExpr->pRight );
651 assert( sqlite3ExprSkipCollateAndLikely(pExpr->pRight)->op
652 == TK_TRUEFALSE );
653 x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight);
654 zUniOp = azOp[x];
655 break;
658 case TK_SPAN: {
659 assert( !ExprHasProperty(pExpr, EP_IntValue) );
660 sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken);
661 sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
662 break;
665 case TK_COLLATE: {
666 /* COLLATE operators without the EP_Collate flag are intended to
667 ** emulate collation associated with a table column. These show
668 ** up in the treeview output as "SOFT-COLLATE". Explicit COLLATE
669 ** operators that appear in the original SQL always have the
670 ** EP_Collate bit set and appear in treeview output as just "COLLATE" */
671 assert( !ExprHasProperty(pExpr, EP_IntValue) );
672 sqlite3TreeViewLine(pView, "%sCOLLATE %Q%s",
673 !ExprHasProperty(pExpr, EP_Collate) ? "SOFT-" : "",
674 pExpr->u.zToken, zFlgs);
675 sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
676 break;
679 case TK_AGG_FUNCTION:
680 case TK_FUNCTION: {
681 ExprList *pFarg; /* List of function arguments */
682 Window *pWin;
683 if( ExprHasProperty(pExpr, EP_TokenOnly) ){
684 pFarg = 0;
685 pWin = 0;
686 }else{
687 assert( ExprUseXList(pExpr) );
688 pFarg = pExpr->x.pList;
689 #ifndef SQLITE_OMIT_WINDOWFUNC
690 pWin = IsWindowFunc(pExpr) ? pExpr->y.pWin : 0;
691 #else
692 pWin = 0;
693 #endif
695 assert( !ExprHasProperty(pExpr, EP_IntValue) );
696 if( pExpr->op==TK_AGG_FUNCTION ){
697 sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s agg=%d[%d]/%p",
698 pExpr->op2, pExpr->u.zToken, zFlgs,
699 pExpr->pAggInfo ? pExpr->pAggInfo->selId : 0,
700 pExpr->iAgg, pExpr->pAggInfo);
701 }else if( pExpr->op2!=0 ){
702 const char *zOp2;
703 char zBuf[8];
704 sqlite3_snprintf(sizeof(zBuf),zBuf,"0x%02x",pExpr->op2);
705 zOp2 = zBuf;
706 if( pExpr->op2==NC_IsCheck ) zOp2 = "NC_IsCheck";
707 if( pExpr->op2==NC_IdxExpr ) zOp2 = "NC_IdxExpr";
708 if( pExpr->op2==NC_PartIdx ) zOp2 = "NC_PartIdx";
709 if( pExpr->op2==NC_GenCol ) zOp2 = "NC_GenCol";
710 sqlite3TreeViewLine(pView, "FUNCTION %Q%s op2=%s",
711 pExpr->u.zToken, zFlgs, zOp2);
712 }else{
713 sqlite3TreeViewLine(pView, "FUNCTION %Q%s", pExpr->u.zToken, zFlgs);
715 if( pFarg ){
716 sqlite3TreeViewExprList(pView, pFarg, pWin!=0 || pExpr->pLeft, 0);
717 if( pExpr->pLeft ){
718 Expr *pOB = pExpr->pLeft;
719 assert( pOB->op==TK_ORDER );
720 assert( ExprUseXList(pOB) );
721 sqlite3TreeViewExprList(pView, pOB->x.pList, pWin!=0, "ORDERBY");
724 #ifndef SQLITE_OMIT_WINDOWFUNC
725 if( pWin ){
726 sqlite3TreeViewWindow(pView, pWin, 0);
728 #endif
729 break;
731 case TK_ORDER: {
732 sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, "ORDERBY");
733 break;
735 #ifndef SQLITE_OMIT_SUBQUERY
736 case TK_EXISTS: {
737 assert( ExprUseXSelect(pExpr) );
738 sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags);
739 sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
740 break;
742 case TK_SELECT: {
743 assert( ExprUseXSelect(pExpr) );
744 sqlite3TreeViewLine(pView, "subquery-expr flags=0x%x", pExpr->flags);
745 sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
746 break;
748 case TK_IN: {
749 sqlite3_str *pStr = sqlite3_str_new(0);
750 char *z;
751 sqlite3_str_appendf(pStr, "IN flags=0x%x", pExpr->flags);
752 if( pExpr->iTable ) sqlite3_str_appendf(pStr, " iTable=%d",pExpr->iTable);
753 if( ExprHasProperty(pExpr, EP_Subrtn) ){
754 sqlite3_str_appendf(pStr, " subrtn(%d,%d)",
755 pExpr->y.sub.regReturn, pExpr->y.sub.iAddr);
757 z = sqlite3_str_finish(pStr);
758 sqlite3TreeViewLine(pView, z);
759 sqlite3_free(z);
760 sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
761 if( ExprUseXSelect(pExpr) ){
762 sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
763 }else{
764 sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
766 break;
768 #endif /* SQLITE_OMIT_SUBQUERY */
771 ** x BETWEEN y AND z
773 ** This is equivalent to
775 ** x>=y AND x<=z
777 ** X is stored in pExpr->pLeft.
778 ** Y is stored in pExpr->pList->a[0].pExpr.
779 ** Z is stored in pExpr->pList->a[1].pExpr.
781 case TK_BETWEEN: {
782 const Expr *pX, *pY, *pZ;
783 pX = pExpr->pLeft;
784 assert( ExprUseXList(pExpr) );
785 assert( pExpr->x.pList->nExpr==2 );
786 pY = pExpr->x.pList->a[0].pExpr;
787 pZ = pExpr->x.pList->a[1].pExpr;
788 sqlite3TreeViewLine(pView, "BETWEEN%s", zFlgs);
789 sqlite3TreeViewExpr(pView, pX, 1);
790 sqlite3TreeViewExpr(pView, pY, 1);
791 sqlite3TreeViewExpr(pView, pZ, 0);
792 break;
794 case TK_TRIGGER: {
795 /* If the opcode is TK_TRIGGER, then the expression is a reference
796 ** to a column in the new.* or old.* pseudo-tables available to
797 ** trigger programs. In this case Expr.iTable is set to 1 for the
798 ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
799 ** is set to the column of the pseudo-table to read, or to -1 to
800 ** read the rowid field.
802 sqlite3TreeViewLine(pView, "%s(%d)",
803 pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
804 break;
806 case TK_CASE: {
807 sqlite3TreeViewLine(pView, "CASE");
808 sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
809 assert( ExprUseXList(pExpr) );
810 sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
811 break;
813 #ifndef SQLITE_OMIT_TRIGGER
814 case TK_RAISE: {
815 const char *zType = "unk";
816 switch( pExpr->affExpr ){
817 case OE_Rollback: zType = "rollback"; break;
818 case OE_Abort: zType = "abort"; break;
819 case OE_Fail: zType = "fail"; break;
820 case OE_Ignore: zType = "ignore"; break;
822 assert( !ExprHasProperty(pExpr, EP_IntValue) );
823 sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
824 break;
826 #endif
827 case TK_MATCH: {
828 sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s",
829 pExpr->iTable, pExpr->iColumn, zFlgs);
830 sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
831 break;
833 case TK_VECTOR: {
834 char *z = sqlite3_mprintf("VECTOR%s",zFlgs);
835 assert( ExprUseXList(pExpr) );
836 sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z);
837 sqlite3_free(z);
838 break;
840 case TK_SELECT_COLUMN: {
841 sqlite3TreeViewLine(pView, "SELECT-COLUMN %d of [0..%d]%s",
842 pExpr->iColumn, pExpr->iTable-1,
843 pExpr->pRight==pExpr->pLeft ? " (SELECT-owner)" : "");
844 assert( ExprUseXSelect(pExpr->pLeft) );
845 sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
846 break;
848 case TK_IF_NULL_ROW: {
849 sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable);
850 sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
851 break;
853 case TK_ERROR: {
854 Expr tmp;
855 sqlite3TreeViewLine(pView, "ERROR");
856 tmp = *pExpr;
857 tmp.op = pExpr->op2;
858 sqlite3TreeViewExpr(pView, &tmp, 0);
859 break;
861 case TK_ROW: {
862 if( pExpr->iColumn<=0 ){
863 sqlite3TreeViewLine(pView, "First FROM table rowid");
864 }else{
865 sqlite3TreeViewLine(pView, "First FROM table column %d",
866 pExpr->iColumn-1);
868 break;
870 default: {
871 sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
872 break;
875 if( zBinOp ){
876 sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs);
877 sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
878 sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
879 }else if( zUniOp ){
880 sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs);
881 sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
883 sqlite3TreeViewPop(&pView);
888 ** Generate a human-readable explanation of an expression list.
890 void sqlite3TreeViewBareExprList(
891 TreeView *pView,
892 const ExprList *pList,
893 const char *zLabel
895 if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
896 if( pList==0 ){
897 sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
898 }else{
899 int i;
900 sqlite3TreeViewLine(pView, "%s", zLabel);
901 for(i=0; i<pList->nExpr; i++){
902 int j = pList->a[i].u.x.iOrderByCol;
903 char *zName = pList->a[i].zEName;
904 int moreToFollow = i<pList->nExpr - 1;
905 if( j || zName ){
906 sqlite3TreeViewPush(&pView, moreToFollow);
907 moreToFollow = 0;
908 sqlite3TreeViewLine(pView, 0);
909 if( zName ){
910 switch( pList->a[i].fg.eEName ){
911 default:
912 fprintf(stdout, "AS %s ", zName);
913 break;
914 case ENAME_TAB:
915 fprintf(stdout, "TABLE-ALIAS-NAME(\"%s\") ", zName);
916 if( pList->a[i].fg.bUsed ) fprintf(stdout, "(used) ");
917 if( pList->a[i].fg.bUsingTerm ) fprintf(stdout, "(USING-term) ");
918 if( pList->a[i].fg.bNoExpand ) fprintf(stdout, "(NoExpand) ");
919 break;
920 case ENAME_SPAN:
921 fprintf(stdout, "SPAN(\"%s\") ", zName);
922 break;
925 if( j ){
926 fprintf(stdout, "iOrderByCol=%d", j);
928 fprintf(stdout, "\n");
929 fflush(stdout);
931 sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow);
932 if( j || zName ){
933 sqlite3TreeViewPop(&pView);
938 void sqlite3TreeViewExprList(
939 TreeView *pView,
940 const ExprList *pList,
941 u8 moreToFollow,
942 const char *zLabel
944 sqlite3TreeViewPush(&pView, moreToFollow);
945 sqlite3TreeViewBareExprList(pView, pList, zLabel);
946 sqlite3TreeViewPop(&pView);
950 ** Generate a human-readable explanation of an id-list.
952 void sqlite3TreeViewBareIdList(
953 TreeView *pView,
954 const IdList *pList,
955 const char *zLabel
957 if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
958 if( pList==0 ){
959 sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
960 }else{
961 int i;
962 sqlite3TreeViewLine(pView, "%s", zLabel);
963 for(i=0; i<pList->nId; i++){
964 char *zName = pList->a[i].zName;
965 int moreToFollow = i<pList->nId - 1;
966 if( zName==0 ) zName = "(null)";
967 sqlite3TreeViewPush(&pView, moreToFollow);
968 sqlite3TreeViewLine(pView, 0);
969 if( pList->eU4==EU4_NONE ){
970 fprintf(stdout, "%s\n", zName);
971 }else if( pList->eU4==EU4_IDX ){
972 fprintf(stdout, "%s (%d)\n", zName, pList->a[i].u4.idx);
973 }else{
974 assert( pList->eU4==EU4_EXPR );
975 if( pList->a[i].u4.pExpr==0 ){
976 fprintf(stdout, "%s (pExpr=NULL)\n", zName);
977 }else{
978 fprintf(stdout, "%s\n", zName);
979 sqlite3TreeViewPush(&pView, i<pList->nId-1);
980 sqlite3TreeViewExpr(pView, pList->a[i].u4.pExpr, 0);
981 sqlite3TreeViewPop(&pView);
984 sqlite3TreeViewPop(&pView);
988 void sqlite3TreeViewIdList(
989 TreeView *pView,
990 const IdList *pList,
991 u8 moreToFollow,
992 const char *zLabel
994 sqlite3TreeViewPush(&pView, moreToFollow);
995 sqlite3TreeViewBareIdList(pView, pList, zLabel);
996 sqlite3TreeViewPop(&pView);
1000 ** Generate a human-readable explanation of a list of Upsert objects
1002 void sqlite3TreeViewUpsert(
1003 TreeView *pView,
1004 const Upsert *pUpsert,
1005 u8 moreToFollow
1007 if( pUpsert==0 ) return;
1008 sqlite3TreeViewPush(&pView, moreToFollow);
1009 while( pUpsert ){
1010 int n;
1011 sqlite3TreeViewPush(&pView, pUpsert->pNextUpsert!=0 || moreToFollow);
1012 sqlite3TreeViewLine(pView, "ON CONFLICT DO %s",
1013 pUpsert->isDoUpdate ? "UPDATE" : "NOTHING");
1014 n = (pUpsert->pUpsertSet!=0) + (pUpsert->pUpsertWhere!=0);
1015 sqlite3TreeViewExprList(pView, pUpsert->pUpsertTarget, (n--)>0, "TARGET");
1016 sqlite3TreeViewExprList(pView, pUpsert->pUpsertSet, (n--)>0, "SET");
1017 if( pUpsert->pUpsertWhere ){
1018 sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
1019 sqlite3TreeViewExpr(pView, pUpsert->pUpsertWhere, 0);
1020 sqlite3TreeViewPop(&pView);
1022 sqlite3TreeViewPop(&pView);
1023 pUpsert = pUpsert->pNextUpsert;
1025 sqlite3TreeViewPop(&pView);
1028 #if TREETRACE_ENABLED
1030 ** Generate a human-readable diagram of the data structure that go
1031 ** into generating an DELETE statement.
1033 void sqlite3TreeViewDelete(
1034 const With *pWith,
1035 const SrcList *pTabList,
1036 const Expr *pWhere,
1037 const ExprList *pOrderBy,
1038 const Expr *pLimit,
1039 const Trigger *pTrigger
1041 int n = 0;
1042 TreeView *pView = 0;
1043 sqlite3TreeViewPush(&pView, 0);
1044 sqlite3TreeViewLine(pView, "DELETE");
1045 if( pWith ) n++;
1046 if( pTabList ) n++;
1047 if( pWhere ) n++;
1048 if( pOrderBy ) n++;
1049 if( pLimit ) n++;
1050 if( pTrigger ) n++;
1051 if( pWith ){
1052 sqlite3TreeViewPush(&pView, (--n)>0);
1053 sqlite3TreeViewWith(pView, pWith, 0);
1054 sqlite3TreeViewPop(&pView);
1056 if( pTabList ){
1057 sqlite3TreeViewPush(&pView, (--n)>0);
1058 sqlite3TreeViewLine(pView, "FROM");
1059 sqlite3TreeViewSrcList(pView, pTabList);
1060 sqlite3TreeViewPop(&pView);
1062 if( pWhere ){
1063 sqlite3TreeViewPush(&pView, (--n)>0);
1064 sqlite3TreeViewLine(pView, "WHERE");
1065 sqlite3TreeViewExpr(pView, pWhere, 0);
1066 sqlite3TreeViewPop(&pView);
1068 if( pOrderBy ){
1069 sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY");
1071 if( pLimit ){
1072 sqlite3TreeViewPush(&pView, (--n)>0);
1073 sqlite3TreeViewLine(pView, "LIMIT");
1074 sqlite3TreeViewExpr(pView, pLimit, 0);
1075 sqlite3TreeViewPop(&pView);
1077 if( pTrigger ){
1078 sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
1080 sqlite3TreeViewPop(&pView);
1082 #endif /* TREETRACE_ENABLED */
1084 #if TREETRACE_ENABLED
1086 ** Generate a human-readable diagram of the data structure that go
1087 ** into generating an INSERT statement.
1089 void sqlite3TreeViewInsert(
1090 const With *pWith,
1091 const SrcList *pTabList,
1092 const IdList *pColumnList,
1093 const Select *pSelect,
1094 const ExprList *pExprList,
1095 int onError,
1096 const Upsert *pUpsert,
1097 const Trigger *pTrigger
1099 TreeView *pView = 0;
1100 int n = 0;
1101 const char *zLabel = "INSERT";
1102 switch( onError ){
1103 case OE_Replace: zLabel = "REPLACE"; break;
1104 case OE_Ignore: zLabel = "INSERT OR IGNORE"; break;
1105 case OE_Rollback: zLabel = "INSERT OR ROLLBACK"; break;
1106 case OE_Abort: zLabel = "INSERT OR ABORT"; break;
1107 case OE_Fail: zLabel = "INSERT OR FAIL"; break;
1109 sqlite3TreeViewPush(&pView, 0);
1110 sqlite3TreeViewLine(pView, zLabel);
1111 if( pWith ) n++;
1112 if( pTabList ) n++;
1113 if( pColumnList ) n++;
1114 if( pSelect ) n++;
1115 if( pExprList ) n++;
1116 if( pUpsert ) n++;
1117 if( pTrigger ) n++;
1118 if( pWith ){
1119 sqlite3TreeViewPush(&pView, (--n)>0);
1120 sqlite3TreeViewWith(pView, pWith, 0);
1121 sqlite3TreeViewPop(&pView);
1123 if( pTabList ){
1124 sqlite3TreeViewPush(&pView, (--n)>0);
1125 sqlite3TreeViewLine(pView, "INTO");
1126 sqlite3TreeViewSrcList(pView, pTabList);
1127 sqlite3TreeViewPop(&pView);
1129 if( pColumnList ){
1130 sqlite3TreeViewIdList(pView, pColumnList, (--n)>0, "COLUMNS");
1132 if( pSelect ){
1133 sqlite3TreeViewPush(&pView, (--n)>0);
1134 sqlite3TreeViewLine(pView, "DATA-SOURCE");
1135 sqlite3TreeViewSelect(pView, pSelect, 0);
1136 sqlite3TreeViewPop(&pView);
1138 if( pExprList ){
1139 sqlite3TreeViewExprList(pView, pExprList, (--n)>0, "VALUES");
1141 if( pUpsert ){
1142 sqlite3TreeViewPush(&pView, (--n)>0);
1143 sqlite3TreeViewLine(pView, "UPSERT");
1144 sqlite3TreeViewUpsert(pView, pUpsert, 0);
1145 sqlite3TreeViewPop(&pView);
1147 if( pTrigger ){
1148 sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
1150 sqlite3TreeViewPop(&pView);
1152 #endif /* TREETRACE_ENABLED */
1154 #if TREETRACE_ENABLED
1156 ** Generate a human-readable diagram of the data structure that go
1157 ** into generating an UPDATE statement.
1159 void sqlite3TreeViewUpdate(
1160 const With *pWith,
1161 const SrcList *pTabList,
1162 const ExprList *pChanges,
1163 const Expr *pWhere,
1164 int onError,
1165 const ExprList *pOrderBy,
1166 const Expr *pLimit,
1167 const Upsert *pUpsert,
1168 const Trigger *pTrigger
1170 int n = 0;
1171 TreeView *pView = 0;
1172 const char *zLabel = "UPDATE";
1173 switch( onError ){
1174 case OE_Replace: zLabel = "UPDATE OR REPLACE"; break;
1175 case OE_Ignore: zLabel = "UPDATE OR IGNORE"; break;
1176 case OE_Rollback: zLabel = "UPDATE OR ROLLBACK"; break;
1177 case OE_Abort: zLabel = "UPDATE OR ABORT"; break;
1178 case OE_Fail: zLabel = "UPDATE OR FAIL"; break;
1180 sqlite3TreeViewPush(&pView, 0);
1181 sqlite3TreeViewLine(pView, zLabel);
1182 if( pWith ) n++;
1183 if( pTabList ) n++;
1184 if( pChanges ) n++;
1185 if( pWhere ) n++;
1186 if( pOrderBy ) n++;
1187 if( pLimit ) n++;
1188 if( pUpsert ) n++;
1189 if( pTrigger ) n++;
1190 if( pWith ){
1191 sqlite3TreeViewPush(&pView, (--n)>0);
1192 sqlite3TreeViewWith(pView, pWith, 0);
1193 sqlite3TreeViewPop(&pView);
1195 if( pTabList ){
1196 sqlite3TreeViewPush(&pView, (--n)>0);
1197 sqlite3TreeViewLine(pView, "FROM");
1198 sqlite3TreeViewSrcList(pView, pTabList);
1199 sqlite3TreeViewPop(&pView);
1201 if( pChanges ){
1202 sqlite3TreeViewExprList(pView, pChanges, (--n)>0, "SET");
1204 if( pWhere ){
1205 sqlite3TreeViewPush(&pView, (--n)>0);
1206 sqlite3TreeViewLine(pView, "WHERE");
1207 sqlite3TreeViewExpr(pView, pWhere, 0);
1208 sqlite3TreeViewPop(&pView);
1210 if( pOrderBy ){
1211 sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY");
1213 if( pLimit ){
1214 sqlite3TreeViewPush(&pView, (--n)>0);
1215 sqlite3TreeViewLine(pView, "LIMIT");
1216 sqlite3TreeViewExpr(pView, pLimit, 0);
1217 sqlite3TreeViewPop(&pView);
1219 if( pUpsert ){
1220 sqlite3TreeViewPush(&pView, (--n)>0);
1221 sqlite3TreeViewLine(pView, "UPSERT");
1222 sqlite3TreeViewUpsert(pView, pUpsert, 0);
1223 sqlite3TreeViewPop(&pView);
1225 if( pTrigger ){
1226 sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
1228 sqlite3TreeViewPop(&pView);
1230 #endif /* TREETRACE_ENABLED */
1232 #ifndef SQLITE_OMIT_TRIGGER
1234 ** Show a human-readable graph of a TriggerStep
1236 void sqlite3TreeViewTriggerStep(
1237 TreeView *pView,
1238 const TriggerStep *pStep,
1239 u8 moreToFollow,
1240 u8 showFullList
1242 int cnt = 0;
1243 if( pStep==0 ) return;
1244 sqlite3TreeViewPush(&pView,
1245 moreToFollow || (showFullList && pStep->pNext!=0));
1247 if( cnt++ && pStep->pNext==0 ){
1248 sqlite3TreeViewPop(&pView);
1249 sqlite3TreeViewPush(&pView, 0);
1251 sqlite3TreeViewLine(pView, "%s", pStep->zSpan ? pStep->zSpan : "RETURNING");
1252 }while( showFullList && (pStep = pStep->pNext)!=0 );
1253 sqlite3TreeViewPop(&pView);
1257 ** Show a human-readable graph of a Trigger
1259 void sqlite3TreeViewTrigger(
1260 TreeView *pView,
1261 const Trigger *pTrigger,
1262 u8 moreToFollow,
1263 u8 showFullList
1265 int cnt = 0;
1266 if( pTrigger==0 ) return;
1267 sqlite3TreeViewPush(&pView,
1268 moreToFollow || (showFullList && pTrigger->pNext!=0));
1270 if( cnt++ && pTrigger->pNext==0 ){
1271 sqlite3TreeViewPop(&pView);
1272 sqlite3TreeViewPush(&pView, 0);
1274 sqlite3TreeViewLine(pView, "TRIGGER %s", pTrigger->zName);
1275 sqlite3TreeViewPush(&pView, 0);
1276 sqlite3TreeViewTriggerStep(pView, pTrigger->step_list, 0, 1);
1277 sqlite3TreeViewPop(&pView);
1278 }while( showFullList && (pTrigger = pTrigger->pNext)!=0 );
1279 sqlite3TreeViewPop(&pView);
1281 #endif /* SQLITE_OMIT_TRIGGER */
1285 ** These simplified versions of the tree-view routines omit unnecessary
1286 ** parameters. These variants are intended to be used from a symbolic
1287 ** debugger, such as "gdb", during interactive debugging sessions.
1289 ** This routines are given external linkage so that they will always be
1290 ** accessible to the debugging, and to avoid warnings about unused
1291 ** functions. But these routines only exist in debugging builds, so they
1292 ** do not contaminate the interface.
1294 void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); }
1295 void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);}
1296 void sqlite3ShowIdList(const IdList *p){ sqlite3TreeViewIdList(0,p,0,0); }
1297 void sqlite3ShowSrcList(const SrcList *p){ sqlite3TreeViewSrcList(0,p); }
1298 void sqlite3ShowSelect(const Select *p){ sqlite3TreeViewSelect(0,p,0); }
1299 void sqlite3ShowWith(const With *p){ sqlite3TreeViewWith(0,p,0); }
1300 void sqlite3ShowUpsert(const Upsert *p){ sqlite3TreeViewUpsert(0,p,0); }
1301 #ifndef SQLITE_OMIT_TRIGGER
1302 void sqlite3ShowTriggerStep(const TriggerStep *p){
1303 sqlite3TreeViewTriggerStep(0,p,0,0);
1305 void sqlite3ShowTriggerStepList(const TriggerStep *p){
1306 sqlite3TreeViewTriggerStep(0,p,0,1);
1308 void sqlite3ShowTrigger(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,0); }
1309 void sqlite3ShowTriggerList(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,1);}
1310 #endif
1311 #ifndef SQLITE_OMIT_WINDOWFUNC
1312 void sqlite3ShowWindow(const Window *p){ sqlite3TreeViewWindow(0,p,0); }
1313 void sqlite3ShowWinFunc(const Window *p){ sqlite3TreeViewWinFunc(0,p,0); }
1314 #endif
1316 #endif /* SQLITE_DEBUG */