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