4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
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
17 ** The interfaces in this file is only available when compiling
20 #include "sqliteInt.h"
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 TreeView
*sqlite3TreeViewPush(TreeView
*p
, u8 moreToFollow
){
29 p
= sqlite3_malloc64( sizeof(*p
) );
31 memset(p
, 0, sizeof(*p
));
35 assert( moreToFollow
==0 || moreToFollow
==1 );
36 if( p
->iLevel
<sizeof(p
->bLine
) ) p
->bLine
[p
->iLevel
] = moreToFollow
;
41 ** Finished with one layer of the tree
43 static void sqlite3TreeViewPop(TreeView
*p
){
46 if( p
->iLevel
<0 ) sqlite3_free(p
);
50 ** Generate a single line of output for the tree, with a prefix that contains
51 ** all the appropriate tree lines
53 static void sqlite3TreeViewLine(TreeView
*p
, const char *zFormat
, ...){
58 sqlite3StrAccumInit(&acc
, 0, zBuf
, sizeof(zBuf
), 0);
60 for(i
=0; i
<p
->iLevel
&& i
<sizeof(p
->bLine
)-1; i
++){
61 sqlite3_str_append(&acc
, p
->bLine
[i
] ? "| " : " ", 4);
63 sqlite3_str_append(&acc
, p
->bLine
[i
] ? "|-- " : "'-- ", 4);
66 va_start(ap
, zFormat
);
67 sqlite3_str_vappendf(&acc
, zFormat
, ap
);
69 assert( acc
.nChar
>0 );
70 sqlite3_str_append(&acc
, "\n", 1);
72 sqlite3StrAccumFinish(&acc
);
73 fprintf(stdout
,"%s", zBuf
);
78 ** Shorthand for starting a new tree item that consists of a single label
80 static void sqlite3TreeViewItem(TreeView
*p
, const char *zLabel
,u8 moreFollows
){
81 p
= sqlite3TreeViewPush(p
, moreFollows
);
82 sqlite3TreeViewLine(p
, "%s", zLabel
);
86 ** Generate a human-readable description of a WITH clause.
88 void sqlite3TreeViewWith(TreeView
*pView
, const With
*pWith
, u8 moreToFollow
){
90 if( pWith
==0 ) return;
91 if( pWith
->nCte
==0 ) return;
93 sqlite3TreeViewLine(pView
, "WITH (0x%p, pOuter=0x%p)",pWith
,pWith
->pOuter
);
95 sqlite3TreeViewLine(pView
, "WITH (0x%p)", pWith
);
98 pView
= sqlite3TreeViewPush(pView
, 1);
99 for(i
=0; i
<pWith
->nCte
; i
++){
102 const struct Cte
*pCte
= &pWith
->a
[i
];
103 sqlite3StrAccumInit(&x
, 0, zLine
, sizeof(zLine
), 0);
104 sqlite3_str_appendf(&x
, "%s", pCte
->zName
);
105 if( pCte
->pCols
&& pCte
->pCols
->nExpr
>0 ){
108 for(j
=0; j
<pCte
->pCols
->nExpr
; j
++){
109 sqlite3_str_appendf(&x
, "%c%s", cSep
, pCte
->pCols
->a
[j
].zName
);
112 sqlite3_str_appendf(&x
, ")");
114 sqlite3_str_appendf(&x
, " AS");
115 sqlite3StrAccumFinish(&x
);
116 sqlite3TreeViewItem(pView
, zLine
, i
<pWith
->nCte
-1);
117 sqlite3TreeViewSelect(pView
, pCte
->pSelect
, 0);
118 sqlite3TreeViewPop(pView
);
120 sqlite3TreeViewPop(pView
);
125 ** Generate a human-readable description of a SrcList object.
127 void sqlite3TreeViewSrcList(TreeView
*pView
, const SrcList
*pSrc
){
129 for(i
=0; i
<pSrc
->nSrc
; i
++){
130 const struct SrcList_item
*pItem
= &pSrc
->a
[i
];
133 sqlite3StrAccumInit(&x
, 0, zLine
, sizeof(zLine
), 0);
134 sqlite3_str_appendf(&x
, "{%d,*}", pItem
->iCursor
);
135 if( pItem
->zDatabase
){
136 sqlite3_str_appendf(&x
, " %s.%s", pItem
->zDatabase
, pItem
->zName
);
137 }else if( pItem
->zName
){
138 sqlite3_str_appendf(&x
, " %s", pItem
->zName
);
141 sqlite3_str_appendf(&x
, " tab=%Q nCol=%d ptr=%p",
142 pItem
->pTab
->zName
, pItem
->pTab
->nCol
, pItem
->pTab
);
145 sqlite3_str_appendf(&x
, " (AS %s)", pItem
->zAlias
);
147 if( pItem
->fg
.jointype
& JT_LEFT
){
148 sqlite3_str_appendf(&x
, " LEFT-JOIN");
150 sqlite3StrAccumFinish(&x
);
151 sqlite3TreeViewItem(pView
, zLine
, i
<pSrc
->nSrc
-1);
152 if( pItem
->pSelect
){
153 sqlite3TreeViewSelect(pView
, pItem
->pSelect
, 0);
155 if( pItem
->fg
.isTabFunc
){
156 sqlite3TreeViewExprList(pView
, pItem
->u1
.pFuncArg
, 0, "func-args:");
158 sqlite3TreeViewPop(pView
);
163 ** Generate a human-readable description of a Select object.
165 void sqlite3TreeViewSelect(TreeView
*pView
, const Select
*p
, u8 moreToFollow
){
169 sqlite3TreeViewLine(pView
, "nil-SELECT");
172 pView
= sqlite3TreeViewPush(pView
, moreToFollow
);
174 sqlite3TreeViewWith(pView
, p
->pWith
, 1);
176 sqlite3TreeViewPush(pView
, 1);
179 sqlite3TreeViewLine(pView
,
180 "SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d",
181 ((p
->selFlags
& SF_Distinct
) ? " DISTINCT" : ""),
182 ((p
->selFlags
& SF_Aggregate
) ? " agg_flag" : ""),
183 p
->selId
, p
, p
->selFlags
,
186 if( cnt
++ ) sqlite3TreeViewPop(pView
);
191 if( p
->pSrc
&& p
->pSrc
->nSrc
) n
++;
193 if( p
->pGroupBy
) n
++;
194 if( p
->pHaving
) n
++;
195 if( p
->pOrderBy
) n
++;
197 #ifndef SQLITE_OMIT_WINDOWFUNC
199 if( p
->pWinDefn
) n
++;
202 sqlite3TreeViewExprList(pView
, p
->pEList
, (n
--)>0, "result-set");
203 #ifndef SQLITE_OMIT_WINDOWFUNC
206 pView
= sqlite3TreeViewPush(pView
, (n
--)>0);
207 sqlite3TreeViewLine(pView
, "window-functions");
208 for(pX
=p
->pWin
; pX
; pX
=pX
->pNextWin
){
209 sqlite3TreeViewWinFunc(pView
, pX
, pX
->pNextWin
!=0);
211 sqlite3TreeViewPop(pView
);
214 if( p
->pSrc
&& p
->pSrc
->nSrc
){
215 pView
= sqlite3TreeViewPush(pView
, (n
--)>0);
216 sqlite3TreeViewLine(pView
, "FROM");
217 sqlite3TreeViewSrcList(pView
, p
->pSrc
);
218 sqlite3TreeViewPop(pView
);
221 sqlite3TreeViewItem(pView
, "WHERE", (n
--)>0);
222 sqlite3TreeViewExpr(pView
, p
->pWhere
, 0);
223 sqlite3TreeViewPop(pView
);
226 sqlite3TreeViewExprList(pView
, p
->pGroupBy
, (n
--)>0, "GROUPBY");
229 sqlite3TreeViewItem(pView
, "HAVING", (n
--)>0);
230 sqlite3TreeViewExpr(pView
, p
->pHaving
, 0);
231 sqlite3TreeViewPop(pView
);
233 #ifndef SQLITE_OMIT_WINDOWFUNC
236 sqlite3TreeViewItem(pView
, "WINDOW", (n
--)>0);
237 for(pX
=p
->pWinDefn
; pX
; pX
=pX
->pNextWin
){
238 sqlite3TreeViewWindow(pView
, pX
, pX
->pNextWin
!=0);
240 sqlite3TreeViewPop(pView
);
244 sqlite3TreeViewExprList(pView
, p
->pOrderBy
, (n
--)>0, "ORDERBY");
247 sqlite3TreeViewItem(pView
, "LIMIT", (n
--)>0);
248 sqlite3TreeViewExpr(pView
, p
->pLimit
->pLeft
, p
->pLimit
->pRight
!=0);
249 if( p
->pLimit
->pRight
){
250 sqlite3TreeViewItem(pView
, "OFFSET", (n
--)>0);
251 sqlite3TreeViewExpr(pView
, p
->pLimit
->pRight
, 0);
252 sqlite3TreeViewPop(pView
);
254 sqlite3TreeViewPop(pView
);
257 const char *zOp
= "UNION";
259 case TK_ALL
: zOp
= "UNION ALL"; break;
260 case TK_INTERSECT
: zOp
= "INTERSECT"; break;
261 case TK_EXCEPT
: zOp
= "EXCEPT"; break;
263 sqlite3TreeViewItem(pView
, zOp
, 1);
267 sqlite3TreeViewPop(pView
);
270 #ifndef SQLITE_OMIT_WINDOWFUNC
272 ** Generate a description of starting or stopping bounds
274 void sqlite3TreeViewBound(
275 TreeView
*pView
, /* View context */
276 u8 eBound
, /* UNBOUNDED, CURRENT, PRECEDING, FOLLOWING */
277 Expr
*pExpr
, /* Value for PRECEDING or FOLLOWING */
278 u8 moreToFollow
/* True if more to follow */
282 sqlite3TreeViewItem(pView
, "UNBOUNDED", moreToFollow
);
283 sqlite3TreeViewPop(pView
);
287 sqlite3TreeViewItem(pView
, "CURRENT", moreToFollow
);
288 sqlite3TreeViewPop(pView
);
292 sqlite3TreeViewItem(pView
, "PRECEDING", moreToFollow
);
293 sqlite3TreeViewExpr(pView
, pExpr
, 0);
294 sqlite3TreeViewPop(pView
);
298 sqlite3TreeViewItem(pView
, "FOLLOWING", moreToFollow
);
299 sqlite3TreeViewExpr(pView
, pExpr
, 0);
300 sqlite3TreeViewPop(pView
);
305 #endif /* SQLITE_OMIT_WINDOWFUNC */
307 #ifndef SQLITE_OMIT_WINDOWFUNC
309 ** Generate a human-readable explanation for a Window object
311 void sqlite3TreeViewWindow(TreeView
*pView
, const Window
*pWin
, u8 more
){
312 pView
= sqlite3TreeViewPush(pView
, more
);
314 sqlite3TreeViewLine(pView
, "OVER %s", pWin
->zName
);
316 sqlite3TreeViewLine(pView
, "OVER");
318 if( pWin
->pPartition
){
319 sqlite3TreeViewExprList(pView
, pWin
->pPartition
, 1, "PARTITION-BY");
321 if( pWin
->pOrderBy
){
322 sqlite3TreeViewExprList(pView
, pWin
->pOrderBy
, 1, "ORDER-BY");
325 sqlite3TreeViewItem(pView
, pWin
->eType
==TK_RANGE
? "RANGE" : "ROWS", 0);
326 sqlite3TreeViewBound(pView
, pWin
->eStart
, pWin
->pStart
, 1);
327 sqlite3TreeViewBound(pView
, pWin
->eEnd
, pWin
->pEnd
, 0);
328 sqlite3TreeViewPop(pView
);
330 sqlite3TreeViewPop(pView
);
332 #endif /* SQLITE_OMIT_WINDOWFUNC */
334 #ifndef SQLITE_OMIT_WINDOWFUNC
336 ** Generate a human-readable explanation for a Window Function object
338 void sqlite3TreeViewWinFunc(TreeView
*pView
, const Window
*pWin
, u8 more
){
339 pView
= sqlite3TreeViewPush(pView
, more
);
340 sqlite3TreeViewLine(pView
, "WINFUNC %s(%d)",
341 pWin
->pFunc
->zName
, pWin
->pFunc
->nArg
);
342 sqlite3TreeViewWindow(pView
, pWin
, 0);
343 sqlite3TreeViewPop(pView
);
345 #endif /* SQLITE_OMIT_WINDOWFUNC */
348 ** Generate a human-readable explanation of an expression tree.
350 void sqlite3TreeViewExpr(TreeView
*pView
, const Expr
*pExpr
, u8 moreToFollow
){
351 const char *zBinOp
= 0; /* Binary operator */
352 const char *zUniOp
= 0; /* Unary operator */
354 pView
= sqlite3TreeViewPush(pView
, moreToFollow
);
356 sqlite3TreeViewLine(pView
, "nil");
357 sqlite3TreeViewPop(pView
);
361 if( ExprHasProperty(pExpr
, EP_FromJoin
) ){
362 sqlite3_snprintf(sizeof(zFlgs
),zFlgs
," flags=0x%x iRJT=%d",
363 pExpr
->flags
, pExpr
->iRightJoinTable
);
365 sqlite3_snprintf(sizeof(zFlgs
),zFlgs
," flags=0x%x",pExpr
->flags
);
371 case TK_AGG_COLUMN
: {
372 sqlite3TreeViewLine(pView
, "AGG{%d:%d}%s",
373 pExpr
->iTable
, pExpr
->iColumn
, zFlgs
);
377 if( pExpr
->iTable
<0 ){
378 /* This only happens when coding check constraints */
379 sqlite3TreeViewLine(pView
, "COLUMN(%d)%s", pExpr
->iColumn
, zFlgs
);
381 sqlite3TreeViewLine(pView
, "{%d:%d}%s",
382 pExpr
->iTable
, pExpr
->iColumn
, zFlgs
);
384 if( ExprHasProperty(pExpr
, EP_FixedCol
) ){
385 sqlite3TreeViewExpr(pView
, pExpr
->pLeft
, 0);
390 if( pExpr
->flags
& EP_IntValue
){
391 sqlite3TreeViewLine(pView
, "%d", pExpr
->u
.iValue
);
393 sqlite3TreeViewLine(pView
, "%s", pExpr
->u
.zToken
);
397 #ifndef SQLITE_OMIT_FLOATING_POINT
399 sqlite3TreeViewLine(pView
,"%s", pExpr
->u
.zToken
);
404 sqlite3TreeViewLine(pView
,"%Q", pExpr
->u
.zToken
);
408 sqlite3TreeViewLine(pView
,"NULL");
412 sqlite3TreeViewLine(pView
,
413 sqlite3ExprTruthValue(pExpr
) ? "TRUE" : "FALSE");
416 #ifndef SQLITE_OMIT_BLOB_LITERAL
418 sqlite3TreeViewLine(pView
,"%s", pExpr
->u
.zToken
);
423 sqlite3TreeViewLine(pView
,"VARIABLE(%s,%d)",
424 pExpr
->u
.zToken
, pExpr
->iColumn
);
428 sqlite3TreeViewLine(pView
,"REGISTER(%d)", pExpr
->iTable
);
432 sqlite3TreeViewLine(pView
,"ID \"%w\"", pExpr
->u
.zToken
);
435 #ifndef SQLITE_OMIT_CAST
437 /* Expressions of the form: CAST(pLeft AS token) */
438 sqlite3TreeViewLine(pView
,"CAST %Q", pExpr
->u
.zToken
);
439 sqlite3TreeViewExpr(pView
, pExpr
->pLeft
, 0);
442 #endif /* SQLITE_OMIT_CAST */
443 case TK_LT
: zBinOp
= "LT"; break;
444 case TK_LE
: zBinOp
= "LE"; break;
445 case TK_GT
: zBinOp
= "GT"; break;
446 case TK_GE
: zBinOp
= "GE"; break;
447 case TK_NE
: zBinOp
= "NE"; break;
448 case TK_EQ
: zBinOp
= "EQ"; break;
449 case TK_IS
: zBinOp
= "IS"; break;
450 case TK_ISNOT
: zBinOp
= "ISNOT"; break;
451 case TK_AND
: zBinOp
= "AND"; break;
452 case TK_OR
: zBinOp
= "OR"; break;
453 case TK_PLUS
: zBinOp
= "ADD"; break;
454 case TK_STAR
: zBinOp
= "MUL"; break;
455 case TK_MINUS
: zBinOp
= "SUB"; break;
456 case TK_REM
: zBinOp
= "REM"; break;
457 case TK_BITAND
: zBinOp
= "BITAND"; break;
458 case TK_BITOR
: zBinOp
= "BITOR"; break;
459 case TK_SLASH
: zBinOp
= "DIV"; break;
460 case TK_LSHIFT
: zBinOp
= "LSHIFT"; break;
461 case TK_RSHIFT
: zBinOp
= "RSHIFT"; break;
462 case TK_CONCAT
: zBinOp
= "CONCAT"; break;
463 case TK_DOT
: zBinOp
= "DOT"; break;
465 case TK_UMINUS
: zUniOp
= "UMINUS"; break;
466 case TK_UPLUS
: zUniOp
= "UPLUS"; break;
467 case TK_BITNOT
: zUniOp
= "BITNOT"; break;
468 case TK_NOT
: zUniOp
= "NOT"; break;
469 case TK_ISNULL
: zUniOp
= "ISNULL"; break;
470 case TK_NOTNULL
: zUniOp
= "NOTNULL"; break;
474 const char *azOp
[] = {
475 "IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE"
477 assert( pExpr
->op2
==TK_IS
|| pExpr
->op2
==TK_ISNOT
);
478 assert( pExpr
->pRight
);
479 assert( pExpr
->pRight
->op
==TK_TRUEFALSE
);
480 x
= (pExpr
->op2
==TK_ISNOT
)*2 + sqlite3ExprTruthValue(pExpr
->pRight
);
486 sqlite3TreeViewLine(pView
, "SPAN %Q", pExpr
->u
.zToken
);
487 sqlite3TreeViewExpr(pView
, pExpr
->pLeft
, 0);
492 sqlite3TreeViewLine(pView
, "COLLATE %Q", pExpr
->u
.zToken
);
493 sqlite3TreeViewExpr(pView
, pExpr
->pLeft
, 0);
497 case TK_AGG_FUNCTION
:
499 ExprList
*pFarg
; /* List of function arguments */
501 if( ExprHasProperty(pExpr
, EP_TokenOnly
) ){
505 pFarg
= pExpr
->x
.pList
;
506 #ifndef SQLITE_OMIT_WINDOWFUNC
507 pWin
= pExpr
->y
.pWin
;
512 if( pExpr
->op
==TK_AGG_FUNCTION
){
513 sqlite3TreeViewLine(pView
, "AGG_FUNCTION%d %Q",
514 pExpr
->op2
, pExpr
->u
.zToken
);
516 sqlite3TreeViewLine(pView
, "FUNCTION %Q", pExpr
->u
.zToken
);
519 sqlite3TreeViewExprList(pView
, pFarg
, pWin
!=0, 0);
521 #ifndef SQLITE_OMIT_WINDOWFUNC
523 sqlite3TreeViewWindow(pView
, pWin
, 0);
528 #ifndef SQLITE_OMIT_SUBQUERY
530 sqlite3TreeViewLine(pView
, "EXISTS-expr flags=0x%x", pExpr
->flags
);
531 sqlite3TreeViewSelect(pView
, pExpr
->x
.pSelect
, 0);
535 sqlite3TreeViewLine(pView
, "SELECT-expr flags=0x%x", pExpr
->flags
);
536 sqlite3TreeViewSelect(pView
, pExpr
->x
.pSelect
, 0);
540 sqlite3TreeViewLine(pView
, "IN flags=0x%x", pExpr
->flags
);
541 sqlite3TreeViewExpr(pView
, pExpr
->pLeft
, 1);
542 if( ExprHasProperty(pExpr
, EP_xIsSelect
) ){
543 sqlite3TreeViewSelect(pView
, pExpr
->x
.pSelect
, 0);
545 sqlite3TreeViewExprList(pView
, pExpr
->x
.pList
, 0, 0);
549 #endif /* SQLITE_OMIT_SUBQUERY */
554 ** This is equivalent to
558 ** X is stored in pExpr->pLeft.
559 ** Y is stored in pExpr->pList->a[0].pExpr.
560 ** Z is stored in pExpr->pList->a[1].pExpr.
563 Expr
*pX
= pExpr
->pLeft
;
564 Expr
*pY
= pExpr
->x
.pList
->a
[0].pExpr
;
565 Expr
*pZ
= pExpr
->x
.pList
->a
[1].pExpr
;
566 sqlite3TreeViewLine(pView
, "BETWEEN");
567 sqlite3TreeViewExpr(pView
, pX
, 1);
568 sqlite3TreeViewExpr(pView
, pY
, 1);
569 sqlite3TreeViewExpr(pView
, pZ
, 0);
573 /* If the opcode is TK_TRIGGER, then the expression is a reference
574 ** to a column in the new.* or old.* pseudo-tables available to
575 ** trigger programs. In this case Expr.iTable is set to 1 for the
576 ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
577 ** is set to the column of the pseudo-table to read, or to -1 to
578 ** read the rowid field.
580 sqlite3TreeViewLine(pView
, "%s(%d)",
581 pExpr
->iTable
? "NEW" : "OLD", pExpr
->iColumn
);
585 sqlite3TreeViewLine(pView
, "CASE");
586 sqlite3TreeViewExpr(pView
, pExpr
->pLeft
, 1);
587 sqlite3TreeViewExprList(pView
, pExpr
->x
.pList
, 0, 0);
590 #ifndef SQLITE_OMIT_TRIGGER
592 const char *zType
= "unk";
593 switch( pExpr
->affinity
){
594 case OE_Rollback
: zType
= "rollback"; break;
595 case OE_Abort
: zType
= "abort"; break;
596 case OE_Fail
: zType
= "fail"; break;
597 case OE_Ignore
: zType
= "ignore"; break;
599 sqlite3TreeViewLine(pView
, "RAISE %s(%Q)", zType
, pExpr
->u
.zToken
);
604 sqlite3TreeViewLine(pView
, "MATCH {%d:%d}%s",
605 pExpr
->iTable
, pExpr
->iColumn
, zFlgs
);
606 sqlite3TreeViewExpr(pView
, pExpr
->pRight
, 0);
610 sqlite3TreeViewBareExprList(pView
, pExpr
->x
.pList
, "VECTOR");
613 case TK_SELECT_COLUMN
: {
614 sqlite3TreeViewLine(pView
, "SELECT-COLUMN %d", pExpr
->iColumn
);
615 sqlite3TreeViewSelect(pView
, pExpr
->pLeft
->x
.pSelect
, 0);
618 case TK_IF_NULL_ROW
: {
619 sqlite3TreeViewLine(pView
, "IF-NULL-ROW %d", pExpr
->iTable
);
620 sqlite3TreeViewExpr(pView
, pExpr
->pLeft
, 0);
624 sqlite3TreeViewLine(pView
, "op=%d", pExpr
->op
);
629 sqlite3TreeViewLine(pView
, "%s%s", zBinOp
, zFlgs
);
630 sqlite3TreeViewExpr(pView
, pExpr
->pLeft
, 1);
631 sqlite3TreeViewExpr(pView
, pExpr
->pRight
, 0);
633 sqlite3TreeViewLine(pView
, "%s%s", zUniOp
, zFlgs
);
634 sqlite3TreeViewExpr(pView
, pExpr
->pLeft
, 0);
636 sqlite3TreeViewPop(pView
);
641 ** Generate a human-readable explanation of an expression list.
643 void sqlite3TreeViewBareExprList(
645 const ExprList
*pList
,
648 if( zLabel
==0 || zLabel
[0]==0 ) zLabel
= "LIST";
650 sqlite3TreeViewLine(pView
, "%s (empty)", zLabel
);
653 sqlite3TreeViewLine(pView
, "%s", zLabel
);
654 for(i
=0; i
<pList
->nExpr
; i
++){
655 int j
= pList
->a
[i
].u
.x
.iOrderByCol
;
656 char *zName
= pList
->a
[i
].zName
;
657 int moreToFollow
= i
<pList
->nExpr
- 1;
659 sqlite3TreeViewPush(pView
, moreToFollow
);
661 sqlite3TreeViewLine(pView
, 0);
663 fprintf(stdout
, "AS %s ", zName
);
666 fprintf(stdout
, "iOrderByCol=%d", j
);
668 fprintf(stdout
, "\n");
671 sqlite3TreeViewExpr(pView
, pList
->a
[i
].pExpr
, moreToFollow
);
673 sqlite3TreeViewPop(pView
);
678 void sqlite3TreeViewExprList(
680 const ExprList
*pList
,
684 pView
= sqlite3TreeViewPush(pView
, moreToFollow
);
685 sqlite3TreeViewBareExprList(pView
, pList
, zLabel
);
686 sqlite3TreeViewPop(pView
);
689 #endif /* SQLITE_DEBUG */