blob: 0a3f942677616a51c69b87f711ff4b256f3c2a2a [file] [log] [blame]
drh38b41492015-06-08 15:08:15 +00001/*
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.
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 and
15** analysis.
16**
17** The interfaces in this file is only available when compiling
18** with SQLITE_DEBUG.
19*/
20#include "sqliteInt.h"
21#ifdef SQLITE_DEBUG
22
23/*
24** Add a new subitem to the tree. The moreToFollow flag indicates that this
25** is not the last item in the tree.
26*/
drh2a7dcbf2022-04-06 15:41:53 +000027static void sqlite3TreeViewPush(TreeView **pp, u8 moreToFollow){
28 TreeView *p = *pp;
drh38b41492015-06-08 15:08:15 +000029 if( p==0 ){
drh2a7dcbf2022-04-06 15:41:53 +000030 *pp = p = sqlite3_malloc64( sizeof(*p) );
31 if( p==0 ) return;
drh38b41492015-06-08 15:08:15 +000032 memset(p, 0, sizeof(*p));
33 }else{
34 p->iLevel++;
35 }
36 assert( moreToFollow==0 || moreToFollow==1 );
drhe684ac62022-03-08 13:59:46 +000037 if( p->iLevel<(int)sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
drh38b41492015-06-08 15:08:15 +000038}
39
40/*
41** Finished with one layer of the tree
42*/
drh2a7dcbf2022-04-06 15:41:53 +000043static void sqlite3TreeViewPop(TreeView **pp){
44 TreeView *p = *pp;
drh38b41492015-06-08 15:08:15 +000045 if( p==0 ) return;
46 p->iLevel--;
drh2a7dcbf2022-04-06 15:41:53 +000047 if( p->iLevel<0 ){
48 sqlite3_free(p);
49 *pp = 0;
50 }
drh38b41492015-06-08 15:08:15 +000051}
52
53/*
54** Generate a single line of output for the tree, with a prefix that contains
55** all the appropriate tree lines
56*/
drh2a7dcbf2022-04-06 15:41:53 +000057void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
drh38b41492015-06-08 15:08:15 +000058 va_list ap;
59 int i;
60 StrAccum acc;
61 char zBuf[500];
62 sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
63 if( p ){
drhe684ac62022-03-08 13:59:46 +000064 for(i=0; i<p->iLevel && i<(int)sizeof(p->bLine)-1; i++){
drh0cdbe1a2018-05-09 13:46:26 +000065 sqlite3_str_append(&acc, p->bLine[i] ? "| " : " ", 4);
drh38b41492015-06-08 15:08:15 +000066 }
drh0cdbe1a2018-05-09 13:46:26 +000067 sqlite3_str_append(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
drh38b41492015-06-08 15:08:15 +000068 }
drhfbe07532018-04-23 20:04:38 +000069 if( zFormat!=0 ){
70 va_start(ap, zFormat);
drh0cdbe1a2018-05-09 13:46:26 +000071 sqlite3_str_vappendf(&acc, zFormat, ap);
drhfbe07532018-04-23 20:04:38 +000072 va_end(ap);
drh10c0e712019-04-25 18:15:38 +000073 assert( acc.nChar>0 || acc.accError );
drh0cdbe1a2018-05-09 13:46:26 +000074 sqlite3_str_append(&acc, "\n", 1);
drhfbe07532018-04-23 20:04:38 +000075 }
drh38b41492015-06-08 15:08:15 +000076 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 label
83*/
84static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){
drh2a7dcbf2022-04-06 15:41:53 +000085 sqlite3TreeViewPush(&p, moreFollows);
drh38b41492015-06-08 15:08:15 +000086 sqlite3TreeViewLine(p, "%s", zLabel);
87}
88
drh2476a6f2015-11-07 15:19:59 +000089/*
90** Generate a human-readable description of a WITH clause.
91*/
92void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){
93 int i;
94 if( pWith==0 ) return;
95 if( pWith->nCte==0 ) return;
96 if( pWith->pOuter ){
97 sqlite3TreeViewLine(pView, "WITH (0x%p, pOuter=0x%p)",pWith,pWith->pOuter);
98 }else{
99 sqlite3TreeViewLine(pView, "WITH (0x%p)", pWith);
100 }
101 if( pWith->nCte>0 ){
drh2a7dcbf2022-04-06 15:41:53 +0000102 sqlite3TreeViewPush(&pView, moreToFollow);
drh2476a6f2015-11-07 15:19:59 +0000103 for(i=0; i<pWith->nCte; i++){
104 StrAccum x;
105 char zLine[1000];
106 const struct Cte *pCte = &pWith->a[i];
107 sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
drh0cdbe1a2018-05-09 13:46:26 +0000108 sqlite3_str_appendf(&x, "%s", pCte->zName);
drh2476a6f2015-11-07 15:19:59 +0000109 if( pCte->pCols && pCte->pCols->nExpr>0 ){
110 char cSep = '(';
111 int j;
112 for(j=0; j<pCte->pCols->nExpr; j++){
drh41cee662019-12-12 20:22:34 +0000113 sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zEName);
drh2476a6f2015-11-07 15:19:59 +0000114 cSep = ',';
115 }
drh0cdbe1a2018-05-09 13:46:26 +0000116 sqlite3_str_appendf(&x, ")");
drh2476a6f2015-11-07 15:19:59 +0000117 }
drha79e2a22021-02-21 23:44:14 +0000118 if( pCte->pUse ){
119 sqlite3_str_appendf(&x, " (pUse=0x%p, nUse=%d)", pCte->pUse,
120 pCte->pUse->nUse);
121 }
drh2476a6f2015-11-07 15:19:59 +0000122 sqlite3StrAccumFinish(&x);
123 sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1);
124 sqlite3TreeViewSelect(pView, pCte->pSelect, 0);
drh2a7dcbf2022-04-06 15:41:53 +0000125 sqlite3TreeViewPop(&pView);
drh2476a6f2015-11-07 15:19:59 +0000126 }
drh2a7dcbf2022-04-06 15:41:53 +0000127 sqlite3TreeViewPop(&pView);
drh2476a6f2015-11-07 15:19:59 +0000128 }
129}
130
drh145d0a32018-11-08 22:53:06 +0000131/*
132** Generate a human-readable description of a SrcList object.
133*/
134void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
135 int i;
drhb60d1fb2022-04-13 18:32:04 +0000136 if( pSrc==0 ) return;
drh145d0a32018-11-08 22:53:06 +0000137 for(i=0; i<pSrc->nSrc; i++){
drh76012942021-02-21 21:04:54 +0000138 const SrcItem *pItem = &pSrc->a[i];
drh145d0a32018-11-08 22:53:06 +0000139 StrAccum x;
140 char zLine[100];
141 sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
drhff374912021-04-12 12:58:55 +0000142 x.printfFlags |= SQLITE_PRINTF_INTERNAL;
drh6610e6a2021-03-19 19:44:56 +0000143 sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
drh145d0a32018-11-08 22:53:06 +0000144 if( pItem->pTab ){
drhf7f6dbf2020-03-21 22:03:32 +0000145 sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
146 pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
drh145d0a32018-11-08 22:53:06 +0000147 }
drha76ac882022-04-08 19:20:12 +0000148 if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){
149 sqlite3_str_appendf(&x, " FULL-OUTER-JOIN");
150 }else if( pItem->fg.jointype & JT_LEFT ){
drh145d0a32018-11-08 22:53:06 +0000151 sqlite3_str_appendf(&x, " LEFT-JOIN");
drha76ac882022-04-08 19:20:12 +0000152 }else if( pItem->fg.jointype & JT_RIGHT ){
153 sqlite3_str_appendf(&x, " RIGHT-JOIN");
drh9b9f2352021-06-23 11:39:00 +0000154 }else if( pItem->fg.jointype & JT_CROSS ){
155 sqlite3_str_appendf(&x, " CROSS-JOIN");
drh145d0a32018-11-08 22:53:06 +0000156 }
drh8a28ce72022-04-11 00:54:30 +0000157 if( pItem->fg.jointype & JT_LTORJ ){
158 sqlite3_str_appendf(&x, " LTORJ");
159 }
drhb7e51992020-01-08 14:39:57 +0000160 if( pItem->fg.fromDDL ){
161 sqlite3_str_appendf(&x, " DDL");
162 }
drha79e2a22021-02-21 23:44:14 +0000163 if( pItem->fg.isCte ){
164 sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse);
165 }
drh145d0a32018-11-08 22:53:06 +0000166 sqlite3StrAccumFinish(&x);
167 sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1);
168 if( pItem->pSelect ){
169 sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
170 }
171 if( pItem->fg.isTabFunc ){
172 sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
173 }
drh2a7dcbf2022-04-06 15:41:53 +0000174 sqlite3TreeViewPop(&pView);
drh145d0a32018-11-08 22:53:06 +0000175 }
176}
drh38b41492015-06-08 15:08:15 +0000177
178/*
drh2e5c5052016-08-27 20:21:51 +0000179** Generate a human-readable description of a Select object.
drh38b41492015-06-08 15:08:15 +0000180*/
181void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
182 int n = 0;
drh1c4505d2015-08-26 11:34:31 +0000183 int cnt = 0;
drh510b7ff2017-03-13 17:37:13 +0000184 if( p==0 ){
185 sqlite3TreeViewLine(pView, "nil-SELECT");
186 return;
187 }
drh2a7dcbf2022-04-06 15:41:53 +0000188 sqlite3TreeViewPush(&pView, moreToFollow);
drh2476a6f2015-11-07 15:19:59 +0000189 if( p->pWith ){
190 sqlite3TreeViewWith(pView, p->pWith, 1);
191 cnt = 1;
drh2a7dcbf2022-04-06 15:41:53 +0000192 sqlite3TreeViewPush(&pView, 1);
drh2476a6f2015-11-07 15:19:59 +0000193 }
drh1c4505d2015-08-26 11:34:31 +0000194 do{
drh55b4c822019-08-03 16:17:46 +0000195 if( p->selFlags & SF_WhereBegin ){
196 sqlite3TreeViewLine(pView, "sqlite3WhereBegin()");
197 }else{
198 sqlite3TreeViewLine(pView,
199 "SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d",
200 ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
201 ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""),
202 p->selId, p, p->selFlags,
203 (int)p->nSelectRow
204 );
205 }
drh2a7dcbf2022-04-06 15:41:53 +0000206 if( cnt++ ) sqlite3TreeViewPop(&pView);
drh1c4505d2015-08-26 11:34:31 +0000207 if( p->pPrior ){
208 n = 1000;
209 }else{
210 n = 0;
211 if( p->pSrc && p->pSrc->nSrc ) n++;
212 if( p->pWhere ) n++;
213 if( p->pGroupBy ) n++;
214 if( p->pHaving ) n++;
215 if( p->pOrderBy ) n++;
216 if( p->pLimit ) n++;
drha1fd4b52018-07-10 06:32:53 +0000217#ifndef SQLITE_OMIT_WINDOWFUNC
218 if( p->pWin ) n++;
219 if( p->pWinDefn ) n++;
220#endif
drh1c4505d2015-08-26 11:34:31 +0000221 }
drh55b4c822019-08-03 16:17:46 +0000222 if( p->pEList ){
223 sqlite3TreeViewExprList(pView, p->pEList, n>0, "result-set");
224 }
225 n--;
drha1fd4b52018-07-10 06:32:53 +0000226#ifndef SQLITE_OMIT_WINDOWFUNC
227 if( p->pWin ){
228 Window *pX;
drh2a7dcbf2022-04-06 15:41:53 +0000229 sqlite3TreeViewPush(&pView, (n--)>0);
drha1fd4b52018-07-10 06:32:53 +0000230 sqlite3TreeViewLine(pView, "window-functions");
231 for(pX=p->pWin; pX; pX=pX->pNextWin){
232 sqlite3TreeViewWinFunc(pView, pX, pX->pNextWin!=0);
233 }
drh2a7dcbf2022-04-06 15:41:53 +0000234 sqlite3TreeViewPop(&pView);
drha1fd4b52018-07-10 06:32:53 +0000235 }
236#endif
drh1c4505d2015-08-26 11:34:31 +0000237 if( p->pSrc && p->pSrc->nSrc ){
drh2a7dcbf2022-04-06 15:41:53 +0000238 sqlite3TreeViewPush(&pView, (n--)>0);
drh1c4505d2015-08-26 11:34:31 +0000239 sqlite3TreeViewLine(pView, "FROM");
drh145d0a32018-11-08 22:53:06 +0000240 sqlite3TreeViewSrcList(pView, p->pSrc);
drh2a7dcbf2022-04-06 15:41:53 +0000241 sqlite3TreeViewPop(&pView);
drh38b41492015-06-08 15:08:15 +0000242 }
drh1c4505d2015-08-26 11:34:31 +0000243 if( p->pWhere ){
244 sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
245 sqlite3TreeViewExpr(pView, p->pWhere, 0);
drh2a7dcbf2022-04-06 15:41:53 +0000246 sqlite3TreeViewPop(&pView);
drh38b41492015-06-08 15:08:15 +0000247 }
drh1c4505d2015-08-26 11:34:31 +0000248 if( p->pGroupBy ){
249 sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
250 }
251 if( p->pHaving ){
252 sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
253 sqlite3TreeViewExpr(pView, p->pHaving, 0);
drh2a7dcbf2022-04-06 15:41:53 +0000254 sqlite3TreeViewPop(&pView);
drh1c4505d2015-08-26 11:34:31 +0000255 }
drha1fd4b52018-07-10 06:32:53 +0000256#ifndef SQLITE_OMIT_WINDOWFUNC
257 if( p->pWinDefn ){
258 Window *pX;
259 sqlite3TreeViewItem(pView, "WINDOW", (n--)>0);
260 for(pX=p->pWinDefn; pX; pX=pX->pNextWin){
261 sqlite3TreeViewWindow(pView, pX, pX->pNextWin!=0);
262 }
drh2a7dcbf2022-04-06 15:41:53 +0000263 sqlite3TreeViewPop(&pView);
drha1fd4b52018-07-10 06:32:53 +0000264 }
265#endif
drh1c4505d2015-08-26 11:34:31 +0000266 if( p->pOrderBy ){
267 sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");
268 }
269 if( p->pLimit ){
270 sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
drh8c0833f2017-11-14 23:48:23 +0000271 sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
272 if( p->pLimit->pRight ){
273 sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
274 sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
drh2a7dcbf2022-04-06 15:41:53 +0000275 sqlite3TreeViewPop(&pView);
drh8c0833f2017-11-14 23:48:23 +0000276 }
drh2a7dcbf2022-04-06 15:41:53 +0000277 sqlite3TreeViewPop(&pView);
drh1c4505d2015-08-26 11:34:31 +0000278 }
279 if( p->pPrior ){
280 const char *zOp = "UNION";
281 switch( p->op ){
282 case TK_ALL: zOp = "UNION ALL"; break;
283 case TK_INTERSECT: zOp = "INTERSECT"; break;
284 case TK_EXCEPT: zOp = "EXCEPT"; break;
285 }
286 sqlite3TreeViewItem(pView, zOp, 1);
287 }
288 p = p->pPrior;
289 }while( p!=0 );
drh2a7dcbf2022-04-06 15:41:53 +0000290 sqlite3TreeViewPop(&pView);
drh38b41492015-06-08 15:08:15 +0000291}
292
drha1fd4b52018-07-10 06:32:53 +0000293#ifndef SQLITE_OMIT_WINDOWFUNC
294/*
295** Generate a description of starting or stopping bounds
296*/
297void sqlite3TreeViewBound(
298 TreeView *pView, /* View context */
299 u8 eBound, /* UNBOUNDED, CURRENT, PRECEDING, FOLLOWING */
300 Expr *pExpr, /* Value for PRECEDING or FOLLOWING */
301 u8 moreToFollow /* True if more to follow */
302){
303 switch( eBound ){
304 case TK_UNBOUNDED: {
305 sqlite3TreeViewItem(pView, "UNBOUNDED", moreToFollow);
drh2a7dcbf2022-04-06 15:41:53 +0000306 sqlite3TreeViewPop(&pView);
drha1fd4b52018-07-10 06:32:53 +0000307 break;
308 }
309 case TK_CURRENT: {
310 sqlite3TreeViewItem(pView, "CURRENT", moreToFollow);
drh2a7dcbf2022-04-06 15:41:53 +0000311 sqlite3TreeViewPop(&pView);
drha1fd4b52018-07-10 06:32:53 +0000312 break;
313 }
314 case TK_PRECEDING: {
315 sqlite3TreeViewItem(pView, "PRECEDING", moreToFollow);
316 sqlite3TreeViewExpr(pView, pExpr, 0);
drh2a7dcbf2022-04-06 15:41:53 +0000317 sqlite3TreeViewPop(&pView);
drha1fd4b52018-07-10 06:32:53 +0000318 break;
319 }
320 case TK_FOLLOWING: {
321 sqlite3TreeViewItem(pView, "FOLLOWING", moreToFollow);
322 sqlite3TreeViewExpr(pView, pExpr, 0);
drh2a7dcbf2022-04-06 15:41:53 +0000323 sqlite3TreeViewPop(&pView);
drha1fd4b52018-07-10 06:32:53 +0000324 break;
325 }
326 }
327}
328#endif /* SQLITE_OMIT_WINDOWFUNC */
329
330#ifndef SQLITE_OMIT_WINDOWFUNC
331/*
332** Generate a human-readable explanation for a Window object
333*/
334void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u8 more){
drhfc15f4c2019-03-28 13:03:41 +0000335 int nElement = 0;
drh0dc0e9c2019-03-28 13:35:28 +0000336 if( pWin->pFilter ){
337 sqlite3TreeViewItem(pView, "FILTER", 1);
338 sqlite3TreeViewExpr(pView, pWin->pFilter, 0);
drh2a7dcbf2022-04-06 15:41:53 +0000339 sqlite3TreeViewPop(&pView);
drh0dc0e9c2019-03-28 13:35:28 +0000340 }
drh2a7dcbf2022-04-06 15:41:53 +0000341 sqlite3TreeViewPush(&pView, more);
drha1fd4b52018-07-10 06:32:53 +0000342 if( pWin->zName ){
drh6f1644c2019-03-28 13:53:12 +0000343 sqlite3TreeViewLine(pView, "OVER %s (%p)", pWin->zName, pWin);
drha1fd4b52018-07-10 06:32:53 +0000344 }else{
drh6f1644c2019-03-28 13:53:12 +0000345 sqlite3TreeViewLine(pView, "OVER (%p)", pWin);
drha1fd4b52018-07-10 06:32:53 +0000346 }
drhfc15f4c2019-03-28 13:03:41 +0000347 if( pWin->zBase ) nElement++;
348 if( pWin->pOrderBy ) nElement++;
349 if( pWin->eFrmType ) nElement++;
350 if( pWin->eExclude ) nElement++;
drhfc15f4c2019-03-28 13:03:41 +0000351 if( pWin->zBase ){
drh2a7dcbf2022-04-06 15:41:53 +0000352 sqlite3TreeViewPush(&pView, (--nElement)>0);
drhfc15f4c2019-03-28 13:03:41 +0000353 sqlite3TreeViewLine(pView, "window: %s", pWin->zBase);
drh2a7dcbf2022-04-06 15:41:53 +0000354 sqlite3TreeViewPop(&pView);
drhfc15f4c2019-03-28 13:03:41 +0000355 }
drha1fd4b52018-07-10 06:32:53 +0000356 if( pWin->pPartition ){
drhfc15f4c2019-03-28 13:03:41 +0000357 sqlite3TreeViewExprList(pView, pWin->pPartition, nElement>0,"PARTITION-BY");
drha1fd4b52018-07-10 06:32:53 +0000358 }
359 if( pWin->pOrderBy ){
drhfc15f4c2019-03-28 13:03:41 +0000360 sqlite3TreeViewExprList(pView, pWin->pOrderBy, (--nElement)>0, "ORDER-BY");
drha1fd4b52018-07-10 06:32:53 +0000361 }
drhfc15f4c2019-03-28 13:03:41 +0000362 if( pWin->eFrmType ){
drh0dc0e9c2019-03-28 13:35:28 +0000363 char zBuf[30];
drhfc15f4c2019-03-28 13:03:41 +0000364 const char *zFrmType = "ROWS";
365 if( pWin->eFrmType==TK_RANGE ) zFrmType = "RANGE";
366 if( pWin->eFrmType==TK_GROUPS ) zFrmType = "GROUPS";
drh0dc0e9c2019-03-28 13:35:28 +0000367 sqlite3_snprintf(sizeof(zBuf),zBuf,"%s%s",zFrmType,
368 pWin->bImplicitFrame ? " (implied)" : "");
369 sqlite3TreeViewItem(pView, zBuf, (--nElement)>0);
drha1fd4b52018-07-10 06:32:53 +0000370 sqlite3TreeViewBound(pView, pWin->eStart, pWin->pStart, 1);
371 sqlite3TreeViewBound(pView, pWin->eEnd, pWin->pEnd, 0);
drh2a7dcbf2022-04-06 15:41:53 +0000372 sqlite3TreeViewPop(&pView);
drha1fd4b52018-07-10 06:32:53 +0000373 }
drhfc15f4c2019-03-28 13:03:41 +0000374 if( pWin->eExclude ){
375 char zBuf[30];
376 const char *zExclude;
377 switch( pWin->eExclude ){
378 case TK_NO: zExclude = "NO OTHERS"; break;
379 case TK_CURRENT: zExclude = "CURRENT ROW"; break;
380 case TK_GROUP: zExclude = "GROUP"; break;
381 case TK_TIES: zExclude = "TIES"; break;
382 default:
383 sqlite3_snprintf(sizeof(zBuf),zBuf,"invalid(%d)", pWin->eExclude);
384 zExclude = zBuf;
385 break;
386 }
drh2a7dcbf2022-04-06 15:41:53 +0000387 sqlite3TreeViewPush(&pView, 0);
drhfc15f4c2019-03-28 13:03:41 +0000388 sqlite3TreeViewLine(pView, "EXCLUDE %s", zExclude);
drh2a7dcbf2022-04-06 15:41:53 +0000389 sqlite3TreeViewPop(&pView);
drhfc15f4c2019-03-28 13:03:41 +0000390 }
drh2a7dcbf2022-04-06 15:41:53 +0000391 sqlite3TreeViewPop(&pView);
drha1fd4b52018-07-10 06:32:53 +0000392}
393#endif /* SQLITE_OMIT_WINDOWFUNC */
394
395#ifndef SQLITE_OMIT_WINDOWFUNC
396/*
397** Generate a human-readable explanation for a Window Function object
398*/
399void sqlite3TreeViewWinFunc(TreeView *pView, const Window *pWin, u8 more){
drh2a7dcbf2022-04-06 15:41:53 +0000400 sqlite3TreeViewPush(&pView, more);
drha1fd4b52018-07-10 06:32:53 +0000401 sqlite3TreeViewLine(pView, "WINFUNC %s(%d)",
drh105dcaa2022-03-10 16:01:14 +0000402 pWin->pWFunc->zName, pWin->pWFunc->nArg);
drha1fd4b52018-07-10 06:32:53 +0000403 sqlite3TreeViewWindow(pView, pWin, 0);
drh2a7dcbf2022-04-06 15:41:53 +0000404 sqlite3TreeViewPop(&pView);
drha1fd4b52018-07-10 06:32:53 +0000405}
406#endif /* SQLITE_OMIT_WINDOWFUNC */
407
drh38b41492015-06-08 15:08:15 +0000408/*
409** Generate a human-readable explanation of an expression tree.
410*/
411void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
412 const char *zBinOp = 0; /* Binary operator */
413 const char *zUniOp = 0; /* Unary operator */
drhe7375bf2020-03-10 19:24:38 +0000414 char zFlgs[200];
drh2a7dcbf2022-04-06 15:41:53 +0000415 sqlite3TreeViewPush(&pView, moreToFollow);
drh38b41492015-06-08 15:08:15 +0000416 if( pExpr==0 ){
417 sqlite3TreeViewLine(pView, "nil");
drh2a7dcbf2022-04-06 15:41:53 +0000418 sqlite3TreeViewPop(&pView);
drh38b41492015-06-08 15:08:15 +0000419 return;
420 }
drhe7375bf2020-03-10 19:24:38 +0000421 if( pExpr->flags || pExpr->affExpr || pExpr->vvaFlags ){
drhb7e51992020-01-08 14:39:57 +0000422 StrAccum x;
423 sqlite3StrAccumInit(&x, 0, zFlgs, sizeof(zFlgs), 0);
424 sqlite3_str_appendf(&x, " fg.af=%x.%c",
425 pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n');
drhd97cda42017-04-14 14:02:14 +0000426 if( ExprHasProperty(pExpr, EP_FromJoin) ){
drhd1985262022-04-11 11:25:28 +0000427 sqlite3_str_appendf(&x, " iJoin=%d", pExpr->w.iJoin);
drhd97cda42017-04-14 14:02:14 +0000428 }
drhb7e51992020-01-08 14:39:57 +0000429 if( ExprHasProperty(pExpr, EP_FromDDL) ){
430 sqlite3_str_appendf(&x, " DDL");
431 }
drhe7375bf2020-03-10 19:24:38 +0000432 if( ExprHasVVAProperty(pExpr, EP_Immutable) ){
433 sqlite3_str_appendf(&x, " IMMUTABLE");
434 }
drhb7e51992020-01-08 14:39:57 +0000435 sqlite3StrAccumFinish(&x);
drhb3d903e2015-06-18 14:09:13 +0000436 }else{
437 zFlgs[0] = 0;
438 }
drh38b41492015-06-08 15:08:15 +0000439 switch( pExpr->op ){
440 case TK_AGG_COLUMN: {
drhb3d903e2015-06-18 14:09:13 +0000441 sqlite3TreeViewLine(pView, "AGG{%d:%d}%s",
442 pExpr->iTable, pExpr->iColumn, zFlgs);
drh38b41492015-06-08 15:08:15 +0000443 break;
444 }
445 case TK_COLUMN: {
446 if( pExpr->iTable<0 ){
447 /* This only happens when coding check constraints */
drhd4933532019-10-31 12:30:38 +0000448 char zOp2[16];
449 if( pExpr->op2 ){
450 sqlite3_snprintf(sizeof(zOp2),zOp2," op2=0x%02x",pExpr->op2);
451 }else{
452 zOp2[0] = 0;
453 }
454 sqlite3TreeViewLine(pView, "COLUMN(%d)%s%s",
455 pExpr->iColumn, zFlgs, zOp2);
drh38b41492015-06-08 15:08:15 +0000456 }else{
drh477572b2021-10-07 20:46:29 +0000457 assert( ExprUseYTab(pExpr) );
drha513e592019-12-20 20:08:56 +0000458 sqlite3TreeViewLine(pView, "{%d:%d} pTab=%p%s",
459 pExpr->iTable, pExpr->iColumn,
460 pExpr->y.pTab, zFlgs);
drh38b41492015-06-08 15:08:15 +0000461 }
drhefad2e22018-07-27 16:57:11 +0000462 if( ExprHasProperty(pExpr, EP_FixedCol) ){
463 sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
464 }
drh38b41492015-06-08 15:08:15 +0000465 break;
466 }
467 case TK_INTEGER: {
468 if( pExpr->flags & EP_IntValue ){
469 sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);
470 }else{
471 sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);
472 }
473 break;
474 }
475#ifndef SQLITE_OMIT_FLOATING_POINT
476 case TK_FLOAT: {
drhf9751072021-10-07 13:40:29 +0000477 assert( !ExprHasProperty(pExpr, EP_IntValue) );
drh38b41492015-06-08 15:08:15 +0000478 sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
479 break;
480 }
481#endif
482 case TK_STRING: {
drhf9751072021-10-07 13:40:29 +0000483 assert( !ExprHasProperty(pExpr, EP_IntValue) );
drh38b41492015-06-08 15:08:15 +0000484 sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
485 break;
486 }
487 case TK_NULL: {
488 sqlite3TreeViewLine(pView,"NULL");
489 break;
490 }
drh34328212018-02-26 19:03:25 +0000491 case TK_TRUEFALSE: {
drh348e0022021-07-22 16:07:01 +0000492 sqlite3TreeViewLine(pView,"%s%s",
493 sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE", zFlgs);
drh34328212018-02-26 19:03:25 +0000494 break;
495 }
drh38b41492015-06-08 15:08:15 +0000496#ifndef SQLITE_OMIT_BLOB_LITERAL
497 case TK_BLOB: {
drhf9751072021-10-07 13:40:29 +0000498 assert( !ExprHasProperty(pExpr, EP_IntValue) );
drh38b41492015-06-08 15:08:15 +0000499 sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
500 break;
501 }
502#endif
503 case TK_VARIABLE: {
drhf9751072021-10-07 13:40:29 +0000504 assert( !ExprHasProperty(pExpr, EP_IntValue) );
drh38b41492015-06-08 15:08:15 +0000505 sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
506 pExpr->u.zToken, pExpr->iColumn);
507 break;
508 }
509 case TK_REGISTER: {
510 sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
511 break;
512 }
drh38b41492015-06-08 15:08:15 +0000513 case TK_ID: {
drhf9751072021-10-07 13:40:29 +0000514 assert( !ExprHasProperty(pExpr, EP_IntValue) );
drh38b41492015-06-08 15:08:15 +0000515 sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
516 break;
517 }
518#ifndef SQLITE_OMIT_CAST
519 case TK_CAST: {
520 /* Expressions of the form: CAST(pLeft AS token) */
drhf9751072021-10-07 13:40:29 +0000521 assert( !ExprHasProperty(pExpr, EP_IntValue) );
drh38b41492015-06-08 15:08:15 +0000522 sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
523 sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
524 break;
525 }
526#endif /* SQLITE_OMIT_CAST */
527 case TK_LT: zBinOp = "LT"; break;
528 case TK_LE: zBinOp = "LE"; break;
529 case TK_GT: zBinOp = "GT"; break;
530 case TK_GE: zBinOp = "GE"; break;
531 case TK_NE: zBinOp = "NE"; break;
532 case TK_EQ: zBinOp = "EQ"; break;
533 case TK_IS: zBinOp = "IS"; break;
534 case TK_ISNOT: zBinOp = "ISNOT"; break;
535 case TK_AND: zBinOp = "AND"; break;
536 case TK_OR: zBinOp = "OR"; break;
537 case TK_PLUS: zBinOp = "ADD"; break;
538 case TK_STAR: zBinOp = "MUL"; break;
539 case TK_MINUS: zBinOp = "SUB"; break;
540 case TK_REM: zBinOp = "REM"; break;
541 case TK_BITAND: zBinOp = "BITAND"; break;
542 case TK_BITOR: zBinOp = "BITOR"; break;
543 case TK_SLASH: zBinOp = "DIV"; break;
544 case TK_LSHIFT: zBinOp = "LSHIFT"; break;
545 case TK_RSHIFT: zBinOp = "RSHIFT"; break;
546 case TK_CONCAT: zBinOp = "CONCAT"; break;
547 case TK_DOT: zBinOp = "DOT"; break;
drhe7375bf2020-03-10 19:24:38 +0000548 case TK_LIMIT: zBinOp = "LIMIT"; break;
drh38b41492015-06-08 15:08:15 +0000549
550 case TK_UMINUS: zUniOp = "UMINUS"; break;
551 case TK_UPLUS: zUniOp = "UPLUS"; break;
552 case TK_BITNOT: zUniOp = "BITNOT"; break;
553 case TK_NOT: zUniOp = "NOT"; break;
554 case TK_ISNULL: zUniOp = "ISNULL"; break;
555 case TK_NOTNULL: zUniOp = "NOTNULL"; break;
556
drh34328212018-02-26 19:03:25 +0000557 case TK_TRUTH: {
drh43c4ac82018-02-26 21:26:27 +0000558 int x;
559 const char *azOp[] = {
560 "IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE"
561 };
drh34328212018-02-26 19:03:25 +0000562 assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT );
563 assert( pExpr->pRight );
dan6ece3532019-06-12 13:49:32 +0000564 assert( sqlite3ExprSkipCollate(pExpr->pRight)->op==TK_TRUEFALSE );
drh96acafb2018-02-27 14:49:25 +0000565 x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight);
drh43c4ac82018-02-26 21:26:27 +0000566 zUniOp = azOp[x];
drh34328212018-02-26 19:03:25 +0000567 break;
568 }
569
drh94fa9c42016-02-27 21:16:04 +0000570 case TK_SPAN: {
drhf9751072021-10-07 13:40:29 +0000571 assert( !ExprHasProperty(pExpr, EP_IntValue) );
drh94fa9c42016-02-27 21:16:04 +0000572 sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken);
573 sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
574 break;
575 }
576
drh38b41492015-06-08 15:08:15 +0000577 case TK_COLLATE: {
drhc204d812019-09-10 17:51:27 +0000578 /* COLLATE operators without the EP_Collate flag are intended to
drh018dbb12019-09-28 16:14:55 +0000579 ** emulate collation associated with a table column. These show
580 ** up in the treeview output as "SOFT-COLLATE". Explicit COLLATE
581 ** operators that appear in the original SQL always have the
582 ** EP_Collate bit set and appear in treeview output as just "COLLATE" */
drhf9751072021-10-07 13:40:29 +0000583 assert( !ExprHasProperty(pExpr, EP_IntValue) );
drhc204d812019-09-10 17:51:27 +0000584 sqlite3TreeViewLine(pView, "%sCOLLATE %Q%s",
585 !ExprHasProperty(pExpr, EP_Collate) ? "SOFT-" : "",
586 pExpr->u.zToken, zFlgs);
drh38b41492015-06-08 15:08:15 +0000587 sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
588 break;
589 }
590
591 case TK_AGG_FUNCTION:
592 case TK_FUNCTION: {
593 ExprList *pFarg; /* List of function arguments */
drha1fd4b52018-07-10 06:32:53 +0000594 Window *pWin;
drh38b41492015-06-08 15:08:15 +0000595 if( ExprHasProperty(pExpr, EP_TokenOnly) ){
596 pFarg = 0;
drha1fd4b52018-07-10 06:32:53 +0000597 pWin = 0;
drh38b41492015-06-08 15:08:15 +0000598 }else{
drha4eeccd2021-10-07 17:43:30 +0000599 assert( ExprUseXList(pExpr) );
drh38b41492015-06-08 15:08:15 +0000600 pFarg = pExpr->x.pList;
drha1fd4b52018-07-10 06:32:53 +0000601#ifndef SQLITE_OMIT_WINDOWFUNC
drh014fff22020-01-08 22:22:36 +0000602 pWin = ExprHasProperty(pExpr, EP_WinFunc) ? pExpr->y.pWin : 0;
drha1fd4b52018-07-10 06:32:53 +0000603#else
604 pWin = 0;
605#endif
drh38b41492015-06-08 15:08:15 +0000606 }
drhf9751072021-10-07 13:40:29 +0000607 assert( !ExprHasProperty(pExpr, EP_IntValue) );
drh38b41492015-06-08 15:08:15 +0000608 if( pExpr->op==TK_AGG_FUNCTION ){
drhe26d4282020-06-09 11:59:15 +0000609 sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s agg=%d[%d]/%p",
drhca74fbf2020-05-24 02:05:04 +0000610 pExpr->op2, pExpr->u.zToken, zFlgs,
drhe26d4282020-06-09 11:59:15 +0000611 pExpr->pAggInfo ? pExpr->pAggInfo->selId : 0,
drhca74fbf2020-05-24 02:05:04 +0000612 pExpr->iAgg, pExpr->pAggInfo);
drhd4933532019-10-31 12:30:38 +0000613 }else if( pExpr->op2!=0 ){
614 const char *zOp2;
615 char zBuf[8];
616 sqlite3_snprintf(sizeof(zBuf),zBuf,"0x%02x",pExpr->op2);
617 zOp2 = zBuf;
618 if( pExpr->op2==NC_IsCheck ) zOp2 = "NC_IsCheck";
619 if( pExpr->op2==NC_IdxExpr ) zOp2 = "NC_IdxExpr";
620 if( pExpr->op2==NC_PartIdx ) zOp2 = "NC_PartIdx";
621 if( pExpr->op2==NC_GenCol ) zOp2 = "NC_GenCol";
622 sqlite3TreeViewLine(pView, "FUNCTION %Q%s op2=%s",
623 pExpr->u.zToken, zFlgs, zOp2);
drh38b41492015-06-08 15:08:15 +0000624 }else{
drh42d2fce2019-08-15 20:04:09 +0000625 sqlite3TreeViewLine(pView, "FUNCTION %Q%s", pExpr->u.zToken, zFlgs);
drh38b41492015-06-08 15:08:15 +0000626 }
627 if( pFarg ){
drha1fd4b52018-07-10 06:32:53 +0000628 sqlite3TreeViewExprList(pView, pFarg, pWin!=0, 0);
drh38b41492015-06-08 15:08:15 +0000629 }
mistachkin14897852018-07-23 18:53:49 +0000630#ifndef SQLITE_OMIT_WINDOWFUNC
drha1fd4b52018-07-10 06:32:53 +0000631 if( pWin ){
632 sqlite3TreeViewWindow(pView, pWin, 0);
633 }
634#endif
drh38b41492015-06-08 15:08:15 +0000635 break;
636 }
637#ifndef SQLITE_OMIT_SUBQUERY
638 case TK_EXISTS: {
drha4eeccd2021-10-07 17:43:30 +0000639 assert( ExprUseXSelect(pExpr) );
drh9f6e14c2017-07-10 13:24:58 +0000640 sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags);
drh38b41492015-06-08 15:08:15 +0000641 sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
642 break;
643 }
644 case TK_SELECT: {
drha4eeccd2021-10-07 17:43:30 +0000645 assert( ExprUseXSelect(pExpr) );
drha0365c42020-06-05 04:01:50 +0000646 sqlite3TreeViewLine(pView, "subquery-expr flags=0x%x", pExpr->flags);
drh38b41492015-06-08 15:08:15 +0000647 sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
648 break;
649 }
650 case TK_IN: {
drh9f6e14c2017-07-10 13:24:58 +0000651 sqlite3TreeViewLine(pView, "IN flags=0x%x", pExpr->flags);
drh38b41492015-06-08 15:08:15 +0000652 sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
drha4eeccd2021-10-07 17:43:30 +0000653 if( ExprUseXSelect(pExpr) ){
drh38b41492015-06-08 15:08:15 +0000654 sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
655 }else{
656 sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
657 }
658 break;
659 }
660#endif /* SQLITE_OMIT_SUBQUERY */
661
662 /*
663 ** x BETWEEN y AND z
664 **
665 ** This is equivalent to
666 **
667 ** x>=y AND x<=z
668 **
669 ** X is stored in pExpr->pLeft.
670 ** Y is stored in pExpr->pList->a[0].pExpr.
671 ** Z is stored in pExpr->pList->a[1].pExpr.
672 */
673 case TK_BETWEEN: {
drha4eeccd2021-10-07 17:43:30 +0000674 const Expr *pX, *pY, *pZ;
675 pX = pExpr->pLeft;
676 assert( ExprUseXList(pExpr) );
677 assert( pExpr->x.pList->nExpr==2 );
678 pY = pExpr->x.pList->a[0].pExpr;
679 pZ = pExpr->x.pList->a[1].pExpr;
drh38b41492015-06-08 15:08:15 +0000680 sqlite3TreeViewLine(pView, "BETWEEN");
681 sqlite3TreeViewExpr(pView, pX, 1);
682 sqlite3TreeViewExpr(pView, pY, 1);
683 sqlite3TreeViewExpr(pView, pZ, 0);
684 break;
685 }
686 case TK_TRIGGER: {
687 /* If the opcode is TK_TRIGGER, then the expression is a reference
688 ** to a column in the new.* or old.* pseudo-tables available to
689 ** trigger programs. In this case Expr.iTable is set to 1 for the
690 ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
691 ** is set to the column of the pseudo-table to read, or to -1 to
692 ** read the rowid field.
693 */
694 sqlite3TreeViewLine(pView, "%s(%d)",
695 pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
696 break;
697 }
698 case TK_CASE: {
699 sqlite3TreeViewLine(pView, "CASE");
700 sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
drha4eeccd2021-10-07 17:43:30 +0000701 assert( ExprUseXList(pExpr) );
drh38b41492015-06-08 15:08:15 +0000702 sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
703 break;
704 }
705#ifndef SQLITE_OMIT_TRIGGER
706 case TK_RAISE: {
707 const char *zType = "unk";
drh11949042019-08-05 18:01:42 +0000708 switch( pExpr->affExpr ){
drh38b41492015-06-08 15:08:15 +0000709 case OE_Rollback: zType = "rollback"; break;
710 case OE_Abort: zType = "abort"; break;
711 case OE_Fail: zType = "fail"; break;
712 case OE_Ignore: zType = "ignore"; break;
713 }
drhf9751072021-10-07 13:40:29 +0000714 assert( !ExprHasProperty(pExpr, EP_IntValue) );
drh38b41492015-06-08 15:08:15 +0000715 sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
716 break;
717 }
718#endif
drhc84a4022016-05-27 12:30:20 +0000719 case TK_MATCH: {
720 sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s",
721 pExpr->iTable, pExpr->iColumn, zFlgs);
722 sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
723 break;
724 }
drhdb97e562016-08-18 17:55:57 +0000725 case TK_VECTOR: {
drh269d3222019-10-23 18:09:39 +0000726 char *z = sqlite3_mprintf("VECTOR%s",zFlgs);
drha4eeccd2021-10-07 17:43:30 +0000727 assert( ExprUseXList(pExpr) );
drh269d3222019-10-23 18:09:39 +0000728 sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z);
729 sqlite3_free(z);
drhdb97e562016-08-18 17:55:57 +0000730 break;
731 }
drh48cb3a72016-08-18 18:09:10 +0000732 case TK_SELECT_COLUMN: {
drhe46292a2021-07-05 02:40:29 +0000733 sqlite3TreeViewLine(pView, "SELECT-COLUMN %d of [0..%d]%s",
734 pExpr->iColumn, pExpr->iTable-1,
735 pExpr->pRight==pExpr->pLeft ? " (SELECT-owner)" : "");
drha4eeccd2021-10-07 17:43:30 +0000736 assert( ExprUseXSelect(pExpr->pLeft) );
drh48cb3a72016-08-18 18:09:10 +0000737 sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
738 break;
739 }
drh31d6fd52017-04-14 19:03:10 +0000740 case TK_IF_NULL_ROW: {
741 sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable);
742 sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
743 break;
744 }
drhbf7f3a02021-05-24 11:35:16 +0000745 case TK_ERROR: {
746 Expr tmp;
747 sqlite3TreeViewLine(pView, "ERROR");
748 tmp = *pExpr;
749 tmp.op = pExpr->op2;
750 sqlite3TreeViewExpr(pView, &tmp, 0);
751 break;
752 }
drh4a4e02b2021-07-04 22:33:08 +0000753 case TK_ROW: {
754 if( pExpr->iColumn<=0 ){
755 sqlite3TreeViewLine(pView, "First FROM table rowid");
756 }else{
757 sqlite3TreeViewLine(pView, "First FROM table column %d",
758 pExpr->iColumn-1);
759 }
760 break;
761 }
drh38b41492015-06-08 15:08:15 +0000762 default: {
763 sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
764 break;
765 }
766 }
767 if( zBinOp ){
drhb3d903e2015-06-18 14:09:13 +0000768 sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs);
drh38b41492015-06-08 15:08:15 +0000769 sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
770 sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
771 }else if( zUniOp ){
drhb3d903e2015-06-18 14:09:13 +0000772 sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs);
drh11949042019-08-05 18:01:42 +0000773 sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
drh38b41492015-06-08 15:08:15 +0000774 }
drh2a7dcbf2022-04-06 15:41:53 +0000775 sqlite3TreeViewPop(&pView);
drh38b41492015-06-08 15:08:15 +0000776}
777
drhdb97e562016-08-18 17:55:57 +0000778
drh38b41492015-06-08 15:08:15 +0000779/*
780** Generate a human-readable explanation of an expression list.
781*/
drhdb97e562016-08-18 17:55:57 +0000782void sqlite3TreeViewBareExprList(
drh38b41492015-06-08 15:08:15 +0000783 TreeView *pView,
784 const ExprList *pList,
drh38b41492015-06-08 15:08:15 +0000785 const char *zLabel
786){
drh38b41492015-06-08 15:08:15 +0000787 if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
788 if( pList==0 ){
789 sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
790 }else{
drhdb97e562016-08-18 17:55:57 +0000791 int i;
drh38b41492015-06-08 15:08:15 +0000792 sqlite3TreeViewLine(pView, "%s", zLabel);
793 for(i=0; i<pList->nExpr; i++){
drh5579d592015-08-26 14:01:41 +0000794 int j = pList->a[i].u.x.iOrderByCol;
drh41cee662019-12-12 20:22:34 +0000795 char *zName = pList->a[i].zEName;
drhfbe07532018-04-23 20:04:38 +0000796 int moreToFollow = i<pList->nExpr - 1;
drhe1f49b82020-01-03 00:28:14 +0000797 if( pList->a[i].eEName!=ENAME_NAME ) zName = 0;
drh5a699a02017-12-22 19:53:02 +0000798 if( j || zName ){
drh2a7dcbf2022-04-06 15:41:53 +0000799 sqlite3TreeViewPush(&pView, moreToFollow);
drhfbe07532018-04-23 20:04:38 +0000800 moreToFollow = 0;
801 sqlite3TreeViewLine(pView, 0);
802 if( zName ){
803 fprintf(stdout, "AS %s ", zName);
804 }
805 if( j ){
806 fprintf(stdout, "iOrderByCol=%d", j);
807 }
808 fprintf(stdout, "\n");
809 fflush(stdout);
drh5a699a02017-12-22 19:53:02 +0000810 }
drhfbe07532018-04-23 20:04:38 +0000811 sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow);
drh5a699a02017-12-22 19:53:02 +0000812 if( j || zName ){
drh2a7dcbf2022-04-06 15:41:53 +0000813 sqlite3TreeViewPop(&pView);
drh5a699a02017-12-22 19:53:02 +0000814 }
drh38b41492015-06-08 15:08:15 +0000815 }
816 }
drhdb97e562016-08-18 17:55:57 +0000817}
818void sqlite3TreeViewExprList(
819 TreeView *pView,
820 const ExprList *pList,
821 u8 moreToFollow,
822 const char *zLabel
823){
drh2a7dcbf2022-04-06 15:41:53 +0000824 sqlite3TreeViewPush(&pView, moreToFollow);
drhdb97e562016-08-18 17:55:57 +0000825 sqlite3TreeViewBareExprList(pView, pList, zLabel);
drh2a7dcbf2022-04-06 15:41:53 +0000826 sqlite3TreeViewPop(&pView);
drh38b41492015-06-08 15:08:15 +0000827}
828
drh7d2c1d22022-04-06 00:29:21 +0000829/*
830** Generate a human-readable explanation of an id-list.
831*/
832void sqlite3TreeViewBareIdList(
833 TreeView *pView,
834 const IdList *pList,
835 const char *zLabel
836){
837 if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
838 if( pList==0 ){
839 sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
840 }else{
841 int i;
842 sqlite3TreeViewLine(pView, "%s", zLabel);
843 for(i=0; i<pList->nId; i++){
844 char *zName = pList->a[i].zName;
845 int moreToFollow = i<pList->nId - 1;
846 if( zName==0 ) zName = "(null)";
drh2a7dcbf2022-04-06 15:41:53 +0000847 sqlite3TreeViewPush(&pView, moreToFollow);
drh7d2c1d22022-04-06 00:29:21 +0000848 sqlite3TreeViewLine(pView, 0);
849 fprintf(stdout, "%s (%d)\n", zName, pList->a[i].idx);
drh2a7dcbf2022-04-06 15:41:53 +0000850 sqlite3TreeViewPop(&pView);
drh7d2c1d22022-04-06 00:29:21 +0000851 }
852 }
853}
854void sqlite3TreeViewIdList(
855 TreeView *pView,
856 const IdList *pList,
857 u8 moreToFollow,
858 const char *zLabel
859){
drh2a7dcbf2022-04-06 15:41:53 +0000860 sqlite3TreeViewPush(&pView, moreToFollow);
drh7d2c1d22022-04-06 00:29:21 +0000861 sqlite3TreeViewBareIdList(pView, pList, zLabel);
drh2a7dcbf2022-04-06 15:41:53 +0000862 sqlite3TreeViewPop(&pView);
drh7d2c1d22022-04-06 00:29:21 +0000863}
864
865/*
866** Generate a human-readable explanation of a list of Upsert objects
867*/
868void sqlite3TreeViewUpsert(
869 TreeView *pView,
870 const Upsert *pUpsert,
871 u8 moreToFollow
872){
873 if( pUpsert==0 ) return;
drh2a7dcbf2022-04-06 15:41:53 +0000874 sqlite3TreeViewPush(&pView, moreToFollow);
drh7d2c1d22022-04-06 00:29:21 +0000875 while( pUpsert ){
876 int n;
drh2a7dcbf2022-04-06 15:41:53 +0000877 sqlite3TreeViewPush(&pView, pUpsert->pNextUpsert!=0 || moreToFollow);
drh7d2c1d22022-04-06 00:29:21 +0000878 sqlite3TreeViewLine(pView, "ON CONFLICT DO %s",
879 pUpsert->isDoUpdate ? "UPDATE" : "NOTHING");
880 n = (pUpsert->pUpsertSet!=0) + (pUpsert->pUpsertWhere!=0);
881 sqlite3TreeViewExprList(pView, pUpsert->pUpsertTarget, (n--)>0, "TARGET");
882 sqlite3TreeViewExprList(pView, pUpsert->pUpsertSet, (n--)>0, "SET");
883 if( pUpsert->pUpsertWhere ){
884 sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
885 sqlite3TreeViewExpr(pView, pUpsert->pUpsertWhere, 0);
drh2a7dcbf2022-04-06 15:41:53 +0000886 sqlite3TreeViewPop(&pView);
drh7d2c1d22022-04-06 00:29:21 +0000887 }
drh2a7dcbf2022-04-06 15:41:53 +0000888 sqlite3TreeViewPop(&pView);
drh7d2c1d22022-04-06 00:29:21 +0000889 pUpsert = pUpsert->pNextUpsert;
890 }
drh2a7dcbf2022-04-06 15:41:53 +0000891 sqlite3TreeViewPop(&pView);
drh7d2c1d22022-04-06 00:29:21 +0000892}
893
894/*
895** Generate a human-readable diagram of the data structure that go
drhf8ef2db2022-04-06 10:37:44 +0000896** into generating an DELETE statement.
897*/
898void sqlite3TreeViewDelete(
drhf8ef2db2022-04-06 10:37:44 +0000899 const With *pWith,
900 const SrcList *pTabList,
901 const Expr *pWhere,
902 const ExprList *pOrderBy,
drh2a7dcbf2022-04-06 15:41:53 +0000903 const Expr *pLimit,
904 const Trigger *pTrigger
drhf8ef2db2022-04-06 10:37:44 +0000905){
906 int n = 0;
drh2a7dcbf2022-04-06 15:41:53 +0000907 TreeView *pView = 0;
908 sqlite3TreeViewPush(&pView, 0);
drhf8ef2db2022-04-06 10:37:44 +0000909 sqlite3TreeViewLine(pView, "DELETE");
drhf8ef2db2022-04-06 10:37:44 +0000910 if( pWith ) n++;
911 if( pTabList ) n++;
912 if( pWhere ) n++;
913 if( pOrderBy ) n++;
914 if( pLimit ) n++;
drh2a7dcbf2022-04-06 15:41:53 +0000915 if( pTrigger ) n++;
drhf8ef2db2022-04-06 10:37:44 +0000916 if( pWith ){
drh2a7dcbf2022-04-06 15:41:53 +0000917 sqlite3TreeViewPush(&pView, (--n)>0);
drhf8ef2db2022-04-06 10:37:44 +0000918 sqlite3TreeViewWith(pView, pWith, 0);
drh2a7dcbf2022-04-06 15:41:53 +0000919 sqlite3TreeViewPop(&pView);
drhf8ef2db2022-04-06 10:37:44 +0000920 }
921 if( pTabList ){
drh2a7dcbf2022-04-06 15:41:53 +0000922 sqlite3TreeViewPush(&pView, (--n)>0);
drhf8ef2db2022-04-06 10:37:44 +0000923 sqlite3TreeViewLine(pView, "FROM");
924 sqlite3TreeViewSrcList(pView, pTabList);
drh2a7dcbf2022-04-06 15:41:53 +0000925 sqlite3TreeViewPop(&pView);
drhf8ef2db2022-04-06 10:37:44 +0000926 }
927 if( pWhere ){
drh2a7dcbf2022-04-06 15:41:53 +0000928 sqlite3TreeViewPush(&pView, (--n)>0);
drhf8ef2db2022-04-06 10:37:44 +0000929 sqlite3TreeViewLine(pView, "WHERE");
930 sqlite3TreeViewExpr(pView, pWhere, 0);
drh2a7dcbf2022-04-06 15:41:53 +0000931 sqlite3TreeViewPop(&pView);
drhf8ef2db2022-04-06 10:37:44 +0000932 }
933 if( pOrderBy ){
934 sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY");
935 }
936 if( pLimit ){
drh2a7dcbf2022-04-06 15:41:53 +0000937 sqlite3TreeViewPush(&pView, (--n)>0);
drhf8ef2db2022-04-06 10:37:44 +0000938 sqlite3TreeViewLine(pView, "LIMIT");
939 sqlite3TreeViewExpr(pView, pLimit, 0);
drh2a7dcbf2022-04-06 15:41:53 +0000940 sqlite3TreeViewPop(&pView);
drhf8ef2db2022-04-06 10:37:44 +0000941 }
drh2a7dcbf2022-04-06 15:41:53 +0000942 if( pTrigger ){
943 sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
944 }
945 sqlite3TreeViewPop(&pView);
drhf8ef2db2022-04-06 10:37:44 +0000946}
947
948/*
949** Generate a human-readable diagram of the data structure that go
drh7d2c1d22022-04-06 00:29:21 +0000950** into generating an INSERT statement.
951*/
952void sqlite3TreeViewInsert(
drh7d2c1d22022-04-06 00:29:21 +0000953 const With *pWith,
954 const SrcList *pTabList,
955 const IdList *pColumnList,
956 const Select *pSelect,
drhc2d0df92022-04-06 18:30:17 +0000957 const ExprList *pExprList,
drh7d2c1d22022-04-06 00:29:21 +0000958 int onError,
drh2a7dcbf2022-04-06 15:41:53 +0000959 const Upsert *pUpsert,
960 const Trigger *pTrigger
drh7d2c1d22022-04-06 00:29:21 +0000961){
drh2a7dcbf2022-04-06 15:41:53 +0000962 TreeView *pView = 0;
drh7d2c1d22022-04-06 00:29:21 +0000963 int n = 0;
964 const char *zLabel = "INSERT";
965 switch( onError ){
966 case OE_Replace: zLabel = "REPLACE"; break;
967 case OE_Ignore: zLabel = "INSERT OR IGNORE"; break;
968 case OE_Rollback: zLabel = "INSERT OR ROLLBACK"; break;
969 case OE_Abort: zLabel = "INSERT OR ABORT"; break;
970 case OE_Fail: zLabel = "INSERT OR FAIL"; break;
971 }
drh2a7dcbf2022-04-06 15:41:53 +0000972 sqlite3TreeViewPush(&pView, 0);
drh7d2c1d22022-04-06 00:29:21 +0000973 sqlite3TreeViewLine(pView, zLabel);
drh7d2c1d22022-04-06 00:29:21 +0000974 if( pWith ) n++;
975 if( pTabList ) n++;
976 if( pColumnList ) n++;
977 if( pSelect ) n++;
drhc2d0df92022-04-06 18:30:17 +0000978 if( pExprList ) n++;
drh7d2c1d22022-04-06 00:29:21 +0000979 if( pUpsert ) n++;
drh2a7dcbf2022-04-06 15:41:53 +0000980 if( pTrigger ) n++;
drh7d2c1d22022-04-06 00:29:21 +0000981 if( pWith ){
drh2a7dcbf2022-04-06 15:41:53 +0000982 sqlite3TreeViewPush(&pView, (--n)>0);
drh7d2c1d22022-04-06 00:29:21 +0000983 sqlite3TreeViewWith(pView, pWith, 0);
drh2a7dcbf2022-04-06 15:41:53 +0000984 sqlite3TreeViewPop(&pView);
drh7d2c1d22022-04-06 00:29:21 +0000985 }
986 if( pTabList ){
drh2a7dcbf2022-04-06 15:41:53 +0000987 sqlite3TreeViewPush(&pView, (--n)>0);
drh7d2c1d22022-04-06 00:29:21 +0000988 sqlite3TreeViewLine(pView, "INTO");
989 sqlite3TreeViewSrcList(pView, pTabList);
drh2a7dcbf2022-04-06 15:41:53 +0000990 sqlite3TreeViewPop(&pView);
drh7d2c1d22022-04-06 00:29:21 +0000991 }
992 if( pColumnList ){
993 sqlite3TreeViewIdList(pView, pColumnList, (--n)>0, "COLUMNS");
994 }
995 if( pSelect ){
drh2a7dcbf2022-04-06 15:41:53 +0000996 sqlite3TreeViewPush(&pView, (--n)>0);
drh7d2c1d22022-04-06 00:29:21 +0000997 sqlite3TreeViewLine(pView, "DATA-SOURCE");
998 sqlite3TreeViewSelect(pView, pSelect, 0);
drh2a7dcbf2022-04-06 15:41:53 +0000999 sqlite3TreeViewPop(&pView);
drh7d2c1d22022-04-06 00:29:21 +00001000 }
drhc2d0df92022-04-06 18:30:17 +00001001 if( pExprList ){
1002 sqlite3TreeViewExprList(pView, pExprList, (--n)>0, "VALUES");
1003 }
drh7d2c1d22022-04-06 00:29:21 +00001004 if( pUpsert ){
drh2a7dcbf2022-04-06 15:41:53 +00001005 sqlite3TreeViewPush(&pView, (--n)>0);
drh7d2c1d22022-04-06 00:29:21 +00001006 sqlite3TreeViewLine(pView, "UPSERT");
1007 sqlite3TreeViewUpsert(pView, pUpsert, 0);
drh2a7dcbf2022-04-06 15:41:53 +00001008 sqlite3TreeViewPop(&pView);
drh7d2c1d22022-04-06 00:29:21 +00001009 }
drh2a7dcbf2022-04-06 15:41:53 +00001010 if( pTrigger ){
1011 sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
1012 }
1013 sqlite3TreeViewPop(&pView);
drh7d2c1d22022-04-06 00:29:21 +00001014}
1015
drhf8ef2db2022-04-06 10:37:44 +00001016/*
1017** Generate a human-readable diagram of the data structure that go
1018** into generating an UPDATE statement.
1019*/
1020void sqlite3TreeViewUpdate(
drhf8ef2db2022-04-06 10:37:44 +00001021 const With *pWith,
1022 const SrcList *pTabList,
1023 const ExprList *pChanges,
1024 const Expr *pWhere,
1025 int onError,
1026 const ExprList *pOrderBy,
1027 const Expr *pLimit,
drh2a7dcbf2022-04-06 15:41:53 +00001028 const Upsert *pUpsert,
1029 const Trigger *pTrigger
drhf8ef2db2022-04-06 10:37:44 +00001030){
1031 int n = 0;
drh2a7dcbf2022-04-06 15:41:53 +00001032 TreeView *pView = 0;
drhf8ef2db2022-04-06 10:37:44 +00001033 const char *zLabel = "UPDATE";
1034 switch( onError ){
1035 case OE_Replace: zLabel = "UPDATE OR REPLACE"; break;
1036 case OE_Ignore: zLabel = "UPDATE OR IGNORE"; break;
1037 case OE_Rollback: zLabel = "UPDATE OR ROLLBACK"; break;
1038 case OE_Abort: zLabel = "UPDATE OR ABORT"; break;
1039 case OE_Fail: zLabel = "UPDATE OR FAIL"; break;
1040 }
drh2a7dcbf2022-04-06 15:41:53 +00001041 sqlite3TreeViewPush(&pView, 0);
drhf8ef2db2022-04-06 10:37:44 +00001042 sqlite3TreeViewLine(pView, zLabel);
drhf8ef2db2022-04-06 10:37:44 +00001043 if( pWith ) n++;
1044 if( pTabList ) n++;
1045 if( pChanges ) n++;
1046 if( pWhere ) n++;
1047 if( pOrderBy ) n++;
1048 if( pLimit ) n++;
1049 if( pUpsert ) n++;
drh2a7dcbf2022-04-06 15:41:53 +00001050 if( pTrigger ) n++;
drhf8ef2db2022-04-06 10:37:44 +00001051 if( pWith ){
drh2a7dcbf2022-04-06 15:41:53 +00001052 sqlite3TreeViewPush(&pView, (--n)>0);
drhf8ef2db2022-04-06 10:37:44 +00001053 sqlite3TreeViewWith(pView, pWith, 0);
drh2a7dcbf2022-04-06 15:41:53 +00001054 sqlite3TreeViewPop(&pView);
drhf8ef2db2022-04-06 10:37:44 +00001055 }
1056 if( pTabList ){
drh2a7dcbf2022-04-06 15:41:53 +00001057 sqlite3TreeViewPush(&pView, (--n)>0);
drhf8ef2db2022-04-06 10:37:44 +00001058 sqlite3TreeViewLine(pView, "FROM");
1059 sqlite3TreeViewSrcList(pView, pTabList);
drh2a7dcbf2022-04-06 15:41:53 +00001060 sqlite3TreeViewPop(&pView);
drhf8ef2db2022-04-06 10:37:44 +00001061 }
1062 if( pChanges ){
1063 sqlite3TreeViewExprList(pView, pChanges, (--n)>0, "SET");
1064 }
1065 if( pWhere ){
drh2a7dcbf2022-04-06 15:41:53 +00001066 sqlite3TreeViewPush(&pView, (--n)>0);
drhf8ef2db2022-04-06 10:37:44 +00001067 sqlite3TreeViewLine(pView, "WHERE");
1068 sqlite3TreeViewExpr(pView, pWhere, 0);
drh2a7dcbf2022-04-06 15:41:53 +00001069 sqlite3TreeViewPop(&pView);
drhf8ef2db2022-04-06 10:37:44 +00001070 }
1071 if( pOrderBy ){
1072 sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY");
1073 }
1074 if( pLimit ){
drh2a7dcbf2022-04-06 15:41:53 +00001075 sqlite3TreeViewPush(&pView, (--n)>0);
drhf8ef2db2022-04-06 10:37:44 +00001076 sqlite3TreeViewLine(pView, "LIMIT");
1077 sqlite3TreeViewExpr(pView, pLimit, 0);
drh2a7dcbf2022-04-06 15:41:53 +00001078 sqlite3TreeViewPop(&pView);
drhf8ef2db2022-04-06 10:37:44 +00001079 }
1080 if( pUpsert ){
drh2a7dcbf2022-04-06 15:41:53 +00001081 sqlite3TreeViewPush(&pView, (--n)>0);
drhf8ef2db2022-04-06 10:37:44 +00001082 sqlite3TreeViewLine(pView, "UPSERT");
1083 sqlite3TreeViewUpsert(pView, pUpsert, 0);
drh2a7dcbf2022-04-06 15:41:53 +00001084 sqlite3TreeViewPop(&pView);
drhf8ef2db2022-04-06 10:37:44 +00001085 }
drh2a7dcbf2022-04-06 15:41:53 +00001086 if( pTrigger ){
1087 sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
1088 }
1089 sqlite3TreeViewPop(&pView);
drhf8ef2db2022-04-06 10:37:44 +00001090}
1091
drh2a7dcbf2022-04-06 15:41:53 +00001092#ifndef SQLITE_OMIT_TRIGGER
1093/*
1094** Show a human-readable graph of a TriggerStep
1095*/
1096void sqlite3TreeViewTriggerStep(
1097 TreeView *pView,
1098 const TriggerStep *pStep,
1099 u8 moreToFollow,
1100 u8 showFullList
1101){
1102 int cnt = 0;
1103 if( pStep==0 ) return;
1104 sqlite3TreeViewPush(&pView,
1105 moreToFollow || (showFullList && pStep->pNext!=0));
1106 do{
1107 if( cnt++ && pStep->pNext==0 ){
1108 sqlite3TreeViewPop(&pView);
1109 sqlite3TreeViewPush(&pView, 0);
1110 }
1111 sqlite3TreeViewLine(pView, "%s", pStep->zSpan ? pStep->zSpan : "RETURNING");
1112 }while( showFullList && (pStep = pStep->pNext)!=0 );
1113 sqlite3TreeViewPop(&pView);
1114}
1115
1116/*
1117** Show a human-readable graph of a Trigger
1118*/
1119void sqlite3TreeViewTrigger(
1120 TreeView *pView,
1121 const Trigger *pTrigger,
1122 u8 moreToFollow,
1123 u8 showFullList
1124){
1125 int cnt = 0;
1126 if( pTrigger==0 ) return;
1127 sqlite3TreeViewPush(&pView,
1128 moreToFollow || (showFullList && pTrigger->pNext!=0));
1129 do{
1130 if( cnt++ && pTrigger->pNext==0 ){
1131 sqlite3TreeViewPop(&pView);
1132 sqlite3TreeViewPush(&pView, 0);
1133 }
1134 sqlite3TreeViewLine(pView, "TRIGGER %s", pTrigger->zName);
1135 sqlite3TreeViewPush(&pView, 0);
1136 sqlite3TreeViewTriggerStep(pView, pTrigger->step_list, 0, 1);
1137 sqlite3TreeViewPop(&pView);
1138 }while( showFullList && (pTrigger = pTrigger->pNext)!=0 );
1139 sqlite3TreeViewPop(&pView);
1140}
1141#endif /* SQLITE_OMIT_TRIGGER */
1142
1143
drh8f1eb6f2022-04-06 12:25:04 +00001144/*
1145** These simplified versions of the tree-view routines omit unnecessary
1146** parameters. These variants are intended to be used from a symbolic
1147** debugger, such as "gdb", during interactive debugging sessions.
1148**
1149** This routines are given external linkage so that they will always be
1150** accessible to the debugging, and to avoid warnings about unused
1151** functions. But these routines only exist in debugging builds, so they
1152** do not contaminate the interface.
1153*/
1154void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); }
1155void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);}
1156void sqlite3ShowIdList(const IdList *p){ sqlite3TreeViewIdList(0,p,0,0); }
1157void sqlite3ShowSrcList(const SrcList *p){ sqlite3TreeViewSrcList(0,p); }
1158void sqlite3ShowSelect(const Select *p){ sqlite3TreeViewSelect(0,p,0); }
1159void sqlite3ShowWith(const With *p){ sqlite3TreeViewWith(0,p,0); }
1160void sqlite3ShowUpsert(const Upsert *p){ sqlite3TreeViewUpsert(0,p,0); }
drh2a7dcbf2022-04-06 15:41:53 +00001161#ifndef SQLITE_OMIT_TRIGGER
1162void sqlite3ShowTriggerStep(const TriggerStep *p){
1163 sqlite3TreeViewTriggerStep(0,p,0,0);
1164}
1165void sqlite3ShowTriggerStepList(const TriggerStep *p){
1166 sqlite3TreeViewTriggerStep(0,p,0,1);
1167}
1168void sqlite3ShowTrigger(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,0); }
1169void sqlite3ShowTriggerList(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,1);}
1170#endif
drh8f1eb6f2022-04-06 12:25:04 +00001171#ifndef SQLITE_OMIT_WINDOWFUNC
1172void sqlite3ShowWindow(const Window *p){ sqlite3TreeViewWindow(0,p,0); }
1173void sqlite3ShowWinFunc(const Window *p){ sqlite3TreeViewWinFunc(0,p,0); }
1174#endif
1175
drh38b41492015-06-08 15:08:15 +00001176#endif /* SQLITE_DEBUG */