]> granicus.if.org Git - postgresql/blob - src/backend/nodes/print.c
pgindent run over code.
[postgresql] / src / backend / nodes / print.c
1 /*-------------------------------------------------------------------------
2  *
3  * print.c
4  *        various print routines (used mostly for debugging)
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.28 1999/05/25 16:09:10 momjian Exp $
11  *
12  * HISTORY
13  *        AUTHOR                        DATE                    MAJOR EVENT
14  *        Andrew Yu                     Oct 26, 1994    file creation
15  *
16  *-------------------------------------------------------------------------
17  */
18 #include <stdio.h>
19 #include <string.h>
20
21 #include "postgres.h"
22
23 #include "access/printtup.h"
24 #include "nodes/pg_list.h"
25 #include "nodes/execnodes.h"
26 #include "nodes/parsenodes.h"
27 #include "nodes/print.h"
28 #include "parser/parsetree.h"
29 #include "access/heapam.h"
30 #include "utils/lsyscache.h"
31 #include "nodes/nodes.h"
32 #include "nodes/plannodes.h"
33 #include "parser/parse_relation.h"
34 #include "optimizer/clauses.h"
35
36 static char *plannode_type(Plan *p);
37
38 /*
39  * print
40  *        print contents of Node to stdout
41  */
42 void
43 print(void *obj)
44 {
45         char       *s;
46
47         s = nodeToString(obj);
48         printf("%s\n", s);
49         fflush(stdout);
50         return;
51 }
52
53 /*
54  * pretty print hack extraordinaire.  -ay 10/94
55  */
56 void
57 pprint(void *obj)
58 {
59         char       *s;
60         int                     i;
61         char            line[80];
62         int                     indentLev;
63         int                     j;
64
65         s = nodeToString(obj);
66
67         indentLev = 0;
68         i = 0;
69         for (;;)
70         {
71                 for (j = 0; j < indentLev * 3; j++)
72                         line[j] = ' ';
73                 for (; j < 75 && s[i] != '\0'; i++, j++)
74                 {
75                         line[j] = s[i];
76                         switch (line[j])
77                         {
78                                 case '}':
79                                         if (j != indentLev * 3)
80                                         {
81                                                 line[j] = '\0';
82                                                 printf("%s\n", line);
83                                                 line[indentLev * 3] = '\0';
84                                                 printf("%s}\n", line);
85                                         }
86                                         else
87                                         {
88                                                 line[j] = '\0';
89                                                 printf("%s}\n", line);
90                                         }
91                                         indentLev--;
92                                         j = indentLev * 3 - 1;          /* print the line before :
93                                                                                                  * and resets */
94                                         break;
95                                 case ')':
96                                         line[j + 1] = '\0';
97                                         printf("%s\n", line);
98                                         j = indentLev * 3 - 1;
99                                         break;
100                                 case '{':
101                                         indentLev++;
102                                         /* !!! FALLS THROUGH */
103                                 case ':':
104                                         if (j != 0)
105                                         {
106                                                 line[j] = '\0';
107                                                 printf("%s\n", line);
108                                                 /* print the line before : and resets */
109                                                 for (j = 0; j < indentLev * 3; j++)
110                                                         line[j] = ' ';
111                                         }
112                                         line[j] = s[i];
113                                         break;
114                         }
115                 }
116                 line[j] = '\0';
117                 if (s[i] == '\0')
118                         break;
119                 printf("%s\n", line);
120         }
121         if (j != 0)
122                 printf("%s\n", line);
123         fflush(stdout);
124         return;
125 }
126
127 /*
128  * print_rt
129  *        print contents of range table
130  */
131 void
132 print_rt(List *rtable)
133 {
134         List       *l;
135         int                     i = 1;
136
137         printf("resno\trelname(refname)\trelid\tinFromCl\n");
138         printf("-----\t----------------\t-----\t--------\n");
139         foreach(l, rtable)
140         {
141                 RangeTblEntry *rte = lfirst(l);
142
143                 printf("%d\t%s(%s)\t%u\t%d\t%s\n",
144                            i, rte->relname, rte->refname, rte->relid,
145                            rte->inFromCl,
146                            (rte->inh ? "inh" : ""));
147                 i++;
148         }
149 }
150
151
152 /*
153  * print_expr
154  *        print an expression
155  */
156 void
157 print_expr(Node *expr, List *rtable)
158 {
159         if (expr == NULL)
160         {
161                 printf("<>");
162                 return;
163         }
164
165         if (IsA(expr, Var))
166         {
167                 Var                *var = (Var *) expr;
168                 RangeTblEntry *rt;
169                 char       *relname,
170                                    *attname;
171
172                 switch (var->varno)
173                 {
174                         case INNER:
175                                 relname = "INNER";
176                                 attname = "?";
177                                 break;
178                         case OUTER:
179                                 relname = "OUTER";
180                                 attname = "?";
181                                 break;
182                         default:
183                                 {
184                                         rt = rt_fetch(var->varno, rtable);
185                                         relname = rt->relname;
186                                         if (rt->refname)
187                                                 relname = rt->refname;  /* table renamed */
188                                         attname = get_attname(rt->relid, var->varattno);
189                                 }
190                                 break;
191                 }
192                 printf("%s.%s", relname, attname);
193         }
194         else if (IsA(expr, Expr))
195         {
196                 Expr       *e = (Expr *) expr;
197
198                 if (is_opclause(expr))
199                 {
200                         char       *opname;
201
202                         print_expr((Node *) get_leftop(e), rtable);
203                         opname = get_opname(((Oper *) e->oper)->opno);
204                         printf(" %s ", ((opname != NULL) ? opname : "(invalid operator)"));
205                         print_expr((Node *) get_rightop(e), rtable);
206                 }
207                 else
208                         printf("an expr");
209         }
210         else
211                 printf("not an expr");
212 }
213
214 /*
215  * print_pathkeys -
216  *        pathkeys list of list of Var's
217  */
218 void
219 print_pathkeys(List *pathkeys, List *rtable)
220 {
221         List       *i,
222                            *k;
223
224         printf("(");
225         foreach(i, pathkeys)
226         {
227                 List       *pathkey = lfirst(i);
228
229                 printf("(");
230                 foreach(k, pathkey)
231                 {
232                         Node       *var = lfirst(k);
233
234                         print_expr(var, rtable);
235                         if (lnext(k))
236                                 printf(", ");
237                 }
238                 printf(") ");
239                 if (lnext(i))
240                         printf(", ");
241         }
242         printf(")\n");
243 }
244
245 /*
246  * print_tl
247  *        print targetlist in a more legible way.
248  */
249 void
250 print_tl(List *tlist, List *rtable)
251 {
252         List       *tl;
253
254         printf("(\n");
255         foreach(tl, tlist)
256         {
257                 TargetEntry *tle = lfirst(tl);
258
259                 printf("\t%d %s\t", tle->resdom->resno, tle->resdom->resname);
260                 if (tle->resdom->reskey != 0)
261                         printf("(%d):\t", tle->resdom->reskey);
262                 else
263                         printf("    :\t");
264                 print_expr(tle->expr, rtable);
265                 printf("\n");
266         }
267         printf(")\n");
268 }
269
270 /*
271  * print_slot
272  *        print out the tuple with the given TupleTableSlot
273  */
274 void
275 print_slot(TupleTableSlot *slot)
276 {
277         if (!slot->val)
278         {
279                 printf("tuple is null.\n");
280                 return;
281         }
282         if (!slot->ttc_tupleDescriptor)
283         {
284                 printf("no tuple descriptor.\n");
285                 return;
286         }
287
288         debugtup(slot->val, slot->ttc_tupleDescriptor, NULL);
289 }
290
291 static char *
292 plannode_type(Plan *p)
293 {
294         switch (nodeTag(p))
295         {
296                         case T_Plan:
297                         return "PLAN";
298                         break;
299                 case T_Result:
300                         return "RESULT";
301                         break;
302                 case T_Append:
303                         return "APPEND";
304                         break;
305                 case T_Scan:
306                         return "SCAN";
307                         break;
308                 case T_SeqScan:
309                         return "SEQSCAN";
310                         break;
311                 case T_IndexScan:
312                         return "INDEXSCAN";
313                         break;
314                 case T_Join:
315                         return "JOIN";
316                         break;
317                 case T_NestLoop:
318                         return "NESTLOOP";
319                         break;
320                 case T_MergeJoin:
321                         return "MERGEJOIN";
322                         break;
323                 case T_HashJoin:
324                         return "HASHJOIN";
325                         break;
326                 case T_Noname:
327                         return "NONAME";
328                         break;
329                 case T_Material:
330                         return "MATERIAL";
331                         break;
332                 case T_Sort:
333                         return "SORT";
334                         break;
335                 case T_Agg:
336                         return "AGG";
337                         break;
338                 case T_Unique:
339                         return "UNIQUE";
340                         break;
341                 case T_Hash:
342                         return "HASH";
343                         break;
344                 case T_Choose:
345                         return "CHOOSE";
346                         break;
347                 case T_Group:
348                         return "GROUP";
349                         break;
350                 default:
351                         return "UNKNOWN";
352                         break;
353         }
354 }
355
356 /*
357    prints the ascii description of the plan nodes
358    does this recursively by doing a depth-first traversal of the
359    plan tree.  for SeqScan and IndexScan, the name of the table is also
360    printed out
361
362 */
363 void
364 print_plan_recursive(Plan *p, Query *parsetree, int indentLevel, char *label)
365 {
366         int                     i;
367         char            extraInfo[100];
368
369         if (!p)
370                 return;
371         for (i = 0; i < indentLevel; i++)
372                 printf(" ");
373         printf("%s%s :c=%.4f :s=%d :w=%d ", label, plannode_type(p),
374                    p->cost, p->plan_size, p->plan_width);
375         if (IsA(p, Scan) ||IsA(p, SeqScan))
376         {
377                 RangeTblEntry *rte;
378
379                 rte = rt_fetch(((Scan *) p)->scanrelid, parsetree->rtable);
380                 StrNCpy(extraInfo, rte->relname, NAMEDATALEN);
381         }
382         else if (IsA(p, IndexScan))
383         {
384                 StrNCpy(extraInfo,
385                    ((RangeTblEntry *) (nth(((IndexScan *) p)->scan.scanrelid - 1,
386                                                                    parsetree->rtable)))->relname,
387                                 NAMEDATALEN);
388         }
389         else
390                 extraInfo[0] = '\0';
391         if (extraInfo[0] != '\0')
392                 printf(" ( %s )\n", extraInfo);
393         else
394                 printf("\n");
395         print_plan_recursive(p->lefttree, parsetree, indentLevel + 3, "l: ");
396         print_plan_recursive(p->righttree, parsetree, indentLevel + 3, "r: ");
397
398         if (nodeTag(p) == T_Append)
399         {
400                 List       *lst;
401                 int                     whichplan = 0;
402                 Append     *appendplan = (Append *) p;
403
404                 foreach(lst, appendplan->appendplans)
405                 {
406                         Plan       *subnode = (Plan *) lfirst(lst);
407
408                         /*
409                          * I don't think we need to fiddle with the range table here,
410                          * bjm
411                          */
412                         print_plan_recursive(subnode, parsetree, indentLevel + 3, "a: ");
413
414                         whichplan++;
415                 }
416         }
417 }
418
419 /* print_plan
420   prints just the plan node types */
421
422 void
423 print_plan(Plan *p, Query *parsetree)
424 {
425         print_plan_recursive(p, parsetree, 0, "");
426 }