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
);
126 ** Generate a human-readable description of a Select object.
128 void sqlite3TreeViewSelect(TreeView
*pView
, const Select
*p
, u8 moreToFollow
){
132 sqlite3TreeViewLine(pView
, "nil-SELECT");
135 pView
= sqlite3TreeViewPush(pView
, moreToFollow
);
137 sqlite3TreeViewWith(pView
, p
->pWith
, 1);
139 sqlite3TreeViewPush(pView
, 1);
142 #if SELECTTRACE_ENABLED
143 sqlite3TreeViewLine(pView
,
144 "SELECT%s%s (%s/%p) selFlags=0x%x nSelectRow=%d",
145 ((p
->selFlags
& SF_Distinct
) ? " DISTINCT" : ""),
146 ((p
->selFlags
& SF_Aggregate
) ? " agg_flag" : ""),
147 p
->zSelName
, p
, p
->selFlags
,
151 sqlite3TreeViewLine(pView
, "SELECT%s%s (0x%p) selFlags=0x%x nSelectRow=%d",
152 ((p
->selFlags
& SF_Distinct
) ? " DISTINCT" : ""),
153 ((p
->selFlags
& SF_Aggregate
) ? " agg_flag" : ""), p
, p
->selFlags
,
157 if( cnt
++ ) sqlite3TreeViewPop(pView
);
162 if( p
->pSrc
&& p
->pSrc
->nSrc
) n
++;
164 if( p
->pGroupBy
) n
++;
165 if( p
->pHaving
) n
++;
166 if( p
->pOrderBy
) n
++;
169 sqlite3TreeViewExprList(pView
, p
->pEList
, (n
--)>0, "result-set");
170 if( p
->pSrc
&& p
->pSrc
->nSrc
){
172 pView
= sqlite3TreeViewPush(pView
, (n
--)>0);
173 sqlite3TreeViewLine(pView
, "FROM");
174 for(i
=0; i
<p
->pSrc
->nSrc
; i
++){
175 struct SrcList_item
*pItem
= &p
->pSrc
->a
[i
];
178 sqlite3StrAccumInit(&x
, 0, zLine
, sizeof(zLine
), 0);
179 sqlite3_str_appendf(&x
, "{%d,*}", pItem
->iCursor
);
180 if( pItem
->zDatabase
){
181 sqlite3_str_appendf(&x
, " %s.%s", pItem
->zDatabase
, pItem
->zName
);
182 }else if( pItem
->zName
){
183 sqlite3_str_appendf(&x
, " %s", pItem
->zName
);
186 sqlite3_str_appendf(&x
, " tabname=%Q", pItem
->pTab
->zName
);
189 sqlite3_str_appendf(&x
, " (AS %s)", pItem
->zAlias
);
191 if( pItem
->fg
.jointype
& JT_LEFT
){
192 sqlite3_str_appendf(&x
, " LEFT-JOIN");
194 sqlite3StrAccumFinish(&x
);
195 sqlite3TreeViewItem(pView
, zLine
, i
<p
->pSrc
->nSrc
-1);
196 if( pItem
->pSelect
){
197 sqlite3TreeViewSelect(pView
, pItem
->pSelect
, 0);
199 if( pItem
->fg
.isTabFunc
){
200 sqlite3TreeViewExprList(pView
, pItem
->u1
.pFuncArg
, 0, "func-args:");
202 sqlite3TreeViewPop(pView
);
204 sqlite3TreeViewPop(pView
);
207 sqlite3TreeViewItem(pView
, "WHERE", (n
--)>0);
208 sqlite3TreeViewExpr(pView
, p
->pWhere
, 0);
209 sqlite3TreeViewPop(pView
);
212 sqlite3TreeViewExprList(pView
, p
->pGroupBy
, (n
--)>0, "GROUPBY");
215 sqlite3TreeViewItem(pView
, "HAVING", (n
--)>0);
216 sqlite3TreeViewExpr(pView
, p
->pHaving
, 0);
217 sqlite3TreeViewPop(pView
);
220 sqlite3TreeViewExprList(pView
, p
->pOrderBy
, (n
--)>0, "ORDERBY");
223 sqlite3TreeViewItem(pView
, "LIMIT", (n
--)>0);
224 sqlite3TreeViewExpr(pView
, p
->pLimit
->pLeft
, p
->pLimit
->pRight
!=0);
225 if( p
->pLimit
->pRight
){
226 sqlite3TreeViewItem(pView
, "OFFSET", (n
--)>0);
227 sqlite3TreeViewExpr(pView
, p
->pLimit
->pRight
, 0);
228 sqlite3TreeViewPop(pView
);
230 sqlite3TreeViewPop(pView
);
233 const char *zOp
= "UNION";
235 case TK_ALL
: zOp
= "UNION ALL"; break;
236 case TK_INTERSECT
: zOp
= "INTERSECT"; break;
237 case TK_EXCEPT
: zOp
= "EXCEPT"; break;
239 sqlite3TreeViewItem(pView
, zOp
, 1);
243 sqlite3TreeViewPop(pView
);
247 ** Generate a human-readable explanation of an expression tree.
249 void sqlite3TreeViewExpr(TreeView
*pView
, const Expr
*pExpr
, u8 moreToFollow
){
250 const char *zBinOp
= 0; /* Binary operator */
251 const char *zUniOp
= 0; /* Unary operator */
253 pView
= sqlite3TreeViewPush(pView
, moreToFollow
);
255 sqlite3TreeViewLine(pView
, "nil");
256 sqlite3TreeViewPop(pView
);
260 if( ExprHasProperty(pExpr
, EP_FromJoin
) ){
261 sqlite3_snprintf(sizeof(zFlgs
),zFlgs
," flags=0x%x iRJT=%d",
262 pExpr
->flags
, pExpr
->iRightJoinTable
);
264 sqlite3_snprintf(sizeof(zFlgs
),zFlgs
," flags=0x%x",pExpr
->flags
);
270 case TK_AGG_COLUMN
: {
271 sqlite3TreeViewLine(pView
, "AGG{%d:%d}%s",
272 pExpr
->iTable
, pExpr
->iColumn
, zFlgs
);
276 if( pExpr
->iTable
<0 ){
277 /* This only happens when coding check constraints */
278 sqlite3TreeViewLine(pView
, "COLUMN(%d)%s", pExpr
->iColumn
, zFlgs
);
280 sqlite3TreeViewLine(pView
, "{%d:%d}%s",
281 pExpr
->iTable
, pExpr
->iColumn
, zFlgs
);
286 if( pExpr
->flags
& EP_IntValue
){
287 sqlite3TreeViewLine(pView
, "%d", pExpr
->u
.iValue
);
289 sqlite3TreeViewLine(pView
, "%s", pExpr
->u
.zToken
);
293 #ifndef SQLITE_OMIT_FLOATING_POINT
295 sqlite3TreeViewLine(pView
,"%s", pExpr
->u
.zToken
);
300 sqlite3TreeViewLine(pView
,"%Q", pExpr
->u
.zToken
);
304 sqlite3TreeViewLine(pView
,"NULL");
308 sqlite3TreeViewLine(pView
,
309 sqlite3ExprTruthValue(pExpr
) ? "TRUE" : "FALSE");
312 #ifndef SQLITE_OMIT_BLOB_LITERAL
314 sqlite3TreeViewLine(pView
,"%s", pExpr
->u
.zToken
);
319 sqlite3TreeViewLine(pView
,"VARIABLE(%s,%d)",
320 pExpr
->u
.zToken
, pExpr
->iColumn
);
324 sqlite3TreeViewLine(pView
,"REGISTER(%d)", pExpr
->iTable
);
328 sqlite3TreeViewLine(pView
,"ID \"%w\"", pExpr
->u
.zToken
);
331 #ifndef SQLITE_OMIT_CAST
333 /* Expressions of the form: CAST(pLeft AS token) */
334 sqlite3TreeViewLine(pView
,"CAST %Q", pExpr
->u
.zToken
);
335 sqlite3TreeViewExpr(pView
, pExpr
->pLeft
, 0);
338 #endif /* SQLITE_OMIT_CAST */
339 case TK_LT
: zBinOp
= "LT"; break;
340 case TK_LE
: zBinOp
= "LE"; break;
341 case TK_GT
: zBinOp
= "GT"; break;
342 case TK_GE
: zBinOp
= "GE"; break;
343 case TK_NE
: zBinOp
= "NE"; break;
344 case TK_EQ
: zBinOp
= "EQ"; break;
345 case TK_IS
: zBinOp
= "IS"; break;
346 case TK_ISNOT
: zBinOp
= "ISNOT"; break;
347 case TK_AND
: zBinOp
= "AND"; break;
348 case TK_OR
: zBinOp
= "OR"; break;
349 case TK_PLUS
: zBinOp
= "ADD"; break;
350 case TK_STAR
: zBinOp
= "MUL"; break;
351 case TK_MINUS
: zBinOp
= "SUB"; break;
352 case TK_REM
: zBinOp
= "REM"; break;
353 case TK_BITAND
: zBinOp
= "BITAND"; break;
354 case TK_BITOR
: zBinOp
= "BITOR"; break;
355 case TK_SLASH
: zBinOp
= "DIV"; break;
356 case TK_LSHIFT
: zBinOp
= "LSHIFT"; break;
357 case TK_RSHIFT
: zBinOp
= "RSHIFT"; break;
358 case TK_CONCAT
: zBinOp
= "CONCAT"; break;
359 case TK_DOT
: zBinOp
= "DOT"; break;
361 case TK_UMINUS
: zUniOp
= "UMINUS"; break;
362 case TK_UPLUS
: zUniOp
= "UPLUS"; break;
363 case TK_BITNOT
: zUniOp
= "BITNOT"; break;
364 case TK_NOT
: zUniOp
= "NOT"; break;
365 case TK_ISNULL
: zUniOp
= "ISNULL"; break;
366 case TK_NOTNULL
: zUniOp
= "NOTNULL"; break;
370 const char *azOp
[] = {
371 "IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE"
373 assert( pExpr
->op2
==TK_IS
|| pExpr
->op2
==TK_ISNOT
);
374 assert( pExpr
->pRight
);
375 assert( pExpr
->pRight
->op
==TK_TRUEFALSE
);
376 x
= (pExpr
->op2
==TK_ISNOT
)*2 + sqlite3ExprTruthValue(pExpr
->pRight
);
382 sqlite3TreeViewLine(pView
, "SPAN %Q", pExpr
->u
.zToken
);
383 sqlite3TreeViewExpr(pView
, pExpr
->pLeft
, 0);
388 sqlite3TreeViewLine(pView
, "COLLATE %Q", pExpr
->u
.zToken
);
389 sqlite3TreeViewExpr(pView
, pExpr
->pLeft
, 0);
393 case TK_AGG_FUNCTION
:
395 ExprList
*pFarg
; /* List of function arguments */
396 if( ExprHasProperty(pExpr
, EP_TokenOnly
) ){
399 pFarg
= pExpr
->x
.pList
;
401 if( pExpr
->op
==TK_AGG_FUNCTION
){
402 sqlite3TreeViewLine(pView
, "AGG_FUNCTION%d %Q",
403 pExpr
->op2
, pExpr
->u
.zToken
);
405 sqlite3TreeViewLine(pView
, "FUNCTION %Q", pExpr
->u
.zToken
);
408 sqlite3TreeViewExprList(pView
, pFarg
, 0, 0);
412 #ifndef SQLITE_OMIT_SUBQUERY
414 sqlite3TreeViewLine(pView
, "EXISTS-expr flags=0x%x", pExpr
->flags
);
415 sqlite3TreeViewSelect(pView
, pExpr
->x
.pSelect
, 0);
419 sqlite3TreeViewLine(pView
, "SELECT-expr flags=0x%x", pExpr
->flags
);
420 sqlite3TreeViewSelect(pView
, pExpr
->x
.pSelect
, 0);
424 sqlite3TreeViewLine(pView
, "IN flags=0x%x", pExpr
->flags
);
425 sqlite3TreeViewExpr(pView
, pExpr
->pLeft
, 1);
426 if( ExprHasProperty(pExpr
, EP_xIsSelect
) ){
427 sqlite3TreeViewSelect(pView
, pExpr
->x
.pSelect
, 0);
429 sqlite3TreeViewExprList(pView
, pExpr
->x
.pList
, 0, 0);
433 #endif /* SQLITE_OMIT_SUBQUERY */
438 ** This is equivalent to
442 ** X is stored in pExpr->pLeft.
443 ** Y is stored in pExpr->pList->a[0].pExpr.
444 ** Z is stored in pExpr->pList->a[1].pExpr.
447 Expr
*pX
= pExpr
->pLeft
;
448 Expr
*pY
= pExpr
->x
.pList
->a
[0].pExpr
;
449 Expr
*pZ
= pExpr
->x
.pList
->a
[1].pExpr
;
450 sqlite3TreeViewLine(pView
, "BETWEEN");
451 sqlite3TreeViewExpr(pView
, pX
, 1);
452 sqlite3TreeViewExpr(pView
, pY
, 1);
453 sqlite3TreeViewExpr(pView
, pZ
, 0);
457 /* If the opcode is TK_TRIGGER, then the expression is a reference
458 ** to a column in the new.* or old.* pseudo-tables available to
459 ** trigger programs. In this case Expr.iTable is set to 1 for the
460 ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
461 ** is set to the column of the pseudo-table to read, or to -1 to
462 ** read the rowid field.
464 sqlite3TreeViewLine(pView
, "%s(%d)",
465 pExpr
->iTable
? "NEW" : "OLD", pExpr
->iColumn
);
469 sqlite3TreeViewLine(pView
, "CASE");
470 sqlite3TreeViewExpr(pView
, pExpr
->pLeft
, 1);
471 sqlite3TreeViewExprList(pView
, pExpr
->x
.pList
, 0, 0);
474 #ifndef SQLITE_OMIT_TRIGGER
476 const char *zType
= "unk";
477 switch( pExpr
->affinity
){
478 case OE_Rollback
: zType
= "rollback"; break;
479 case OE_Abort
: zType
= "abort"; break;
480 case OE_Fail
: zType
= "fail"; break;
481 case OE_Ignore
: zType
= "ignore"; break;
483 sqlite3TreeViewLine(pView
, "RAISE %s(%Q)", zType
, pExpr
->u
.zToken
);
488 sqlite3TreeViewLine(pView
, "MATCH {%d:%d}%s",
489 pExpr
->iTable
, pExpr
->iColumn
, zFlgs
);
490 sqlite3TreeViewExpr(pView
, pExpr
->pRight
, 0);
494 sqlite3TreeViewBareExprList(pView
, pExpr
->x
.pList
, "VECTOR");
497 case TK_SELECT_COLUMN
: {
498 sqlite3TreeViewLine(pView
, "SELECT-COLUMN %d", pExpr
->iColumn
);
499 sqlite3TreeViewSelect(pView
, pExpr
->pLeft
->x
.pSelect
, 0);
502 case TK_IF_NULL_ROW
: {
503 sqlite3TreeViewLine(pView
, "IF-NULL-ROW %d", pExpr
->iTable
);
504 sqlite3TreeViewExpr(pView
, pExpr
->pLeft
, 0);
508 sqlite3TreeViewLine(pView
, "op=%d", pExpr
->op
);
513 sqlite3TreeViewLine(pView
, "%s%s", zBinOp
, zFlgs
);
514 sqlite3TreeViewExpr(pView
, pExpr
->pLeft
, 1);
515 sqlite3TreeViewExpr(pView
, pExpr
->pRight
, 0);
517 sqlite3TreeViewLine(pView
, "%s%s", zUniOp
, zFlgs
);
518 sqlite3TreeViewExpr(pView
, pExpr
->pLeft
, 0);
520 sqlite3TreeViewPop(pView
);
525 ** Generate a human-readable explanation of an expression list.
527 void sqlite3TreeViewBareExprList(
529 const ExprList
*pList
,
532 if( zLabel
==0 || zLabel
[0]==0 ) zLabel
= "LIST";
534 sqlite3TreeViewLine(pView
, "%s (empty)", zLabel
);
537 sqlite3TreeViewLine(pView
, "%s", zLabel
);
538 for(i
=0; i
<pList
->nExpr
; i
++){
539 int j
= pList
->a
[i
].u
.x
.iOrderByCol
;
540 char *zName
= pList
->a
[i
].zName
;
541 int moreToFollow
= i
<pList
->nExpr
- 1;
543 sqlite3TreeViewPush(pView
, moreToFollow
);
545 sqlite3TreeViewLine(pView
, 0);
547 fprintf(stdout
, "AS %s ", zName
);
550 fprintf(stdout
, "iOrderByCol=%d", j
);
552 fprintf(stdout
, "\n");
555 sqlite3TreeViewExpr(pView
, pList
->a
[i
].pExpr
, moreToFollow
);
557 sqlite3TreeViewPop(pView
);
562 void sqlite3TreeViewExprList(
564 const ExprList
*pList
,
568 pView
= sqlite3TreeViewPush(pView
, moreToFollow
);
569 sqlite3TreeViewBareExprList(pView
, pList
, zLabel
);
570 sqlite3TreeViewPop(pView
);
573 #endif /* SQLITE_DEBUG */