]> granicus.if.org Git - postgresql/blob - src/backend/nodes/print.c
Parser cleanup.
[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.14 1998/01/20 05:03:54 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                 {
73                         line[j] = ' ';
74                 }
75                 for (; j < 75 && s[i] != '\0'; i++, j++)
76                 {
77                         line[j] = s[i];
78                         switch (line[j])
79                         {
80                                 case '}':
81                                         if (j != indentLev * 3)
82                                         {
83                                                 line[j] = '\0';
84                                                 printf("%s\n", line);
85                                                 line[indentLev * 3] = '\0';
86                                                 printf("%s}\n", line);
87                                         }
88                                         else
89                                         {
90                                                 line[j] = '\0';
91                                                 printf("%s}\n", line);
92                                         }
93                                         indentLev--;
94                                         j = indentLev * 3 - 1;          /* print the line before :
95                                                                                                  * and resets */
96                                         break;
97                                 case ')':
98                                         line[j + 1] = '\0';
99                                         printf("%s\n", line);
100                                         j = indentLev * 3 - 1;
101                                         break;
102                                 case '{':
103                                         indentLev++;
104                                         /* !!! FALLS THROUGH */
105                                 case ':':
106                                         if (j != 0)
107                                         {
108                                                 line[j] = '\0';
109                                                 printf("%s\n", line);
110                                                 /* print the line before : and resets */
111                                                 for (j = 0; j < indentLev * 3; j++)
112                                                 {
113                                                         line[j] = ' ';
114                                                 }
115                                         }
116                                         line[j] = s[i];
117                                         break;
118                         }
119                 }
120                 line[j] = '\0';
121                 if (s[i] == '\0')
122                         break;
123                 printf("%s\n", line);
124         }
125         if (j != 0)
126         {
127                 printf("%s\n", line);
128         }
129         fflush(stdout);
130         return;
131 }
132
133 /*
134  * print_rt--
135  *        print contents of range table
136  */
137 void
138 print_rt(List *rtable)
139 {
140         List       *l;
141         int                     i = 1;
142
143         printf("resno\trelname(refname)\trelid\tinFromCl\n");
144         printf("-----\t----------------\t-----\t--------\n");
145         foreach(l, rtable)
146         {
147                 RangeTblEntry *rte = lfirst(l);
148
149                 printf("%d\t%s(%s)\t%d\t%d\t%s\n",
150                            i, rte->relname, rte->refname, rte->relid,
151                            rte->inFromCl,
152                            (rte->inh ? "inh" : ""));
153                 i++;
154         }
155 }
156
157
158 /*
159  * print_expr--
160  *        print an expression
161  */
162 void
163 print_expr(Node *expr, List *rtable)
164 {
165         if (expr == NULL)
166         {
167                 printf("<>");
168                 return;
169         }
170
171         if (IsA(expr, Var))
172         {
173                 Var                *var = (Var *) expr;
174                 RangeTblEntry *rt;
175                 char       *relname,
176                                    *attname;
177
178                 switch (var->varno)
179                 {
180                         case INNER:
181                                 relname = "INNER";
182                                 attname = "?";
183                                 break;
184                         case OUTER:
185                                 relname = "OUTER";
186                                 attname = "?";
187                                 break;
188                         default:
189                                 {
190                                         rt = rt_fetch(var->varno, rtable);
191                                         relname = rt->relname;
192                                         if (rt->refname)
193                                                 relname = rt->refname;  /* table renamed */
194                                         attname = get_attname(rt->relid, var->varattno);
195                                 }
196                                 break;
197                 }
198                 printf("%s.%s", relname, attname);
199         }
200         else if (IsA(expr, Expr))
201         {
202                 Expr       *e = (Expr *) expr;
203
204                 if (is_opclause(expr))
205                 {
206                         char       *opname;
207
208                         print_expr((Node *) get_leftop(e), rtable);
209                         opname = get_opname(((Oper *) e->oper)->opno);
210                         printf(" %s ", opname);
211                         print_expr((Node *) get_rightop(e), rtable);
212                 }
213                 else
214                 {
215                         printf("an expr");
216                 }
217         }
218         else
219         {
220                 printf("not an expr");
221         }
222 }
223
224 /*
225  * print_keys -
226  *        temporary here. where is keys list of list??
227  */
228 void
229 print_keys(List *keys, List *rtable)
230 {
231         List       *k;
232
233         printf("(");
234         foreach(k, keys)
235         {
236                 Node       *var = lfirst((List *) lfirst(k));
237
238                 print_expr(var, rtable);
239                 if (lnext(k))
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                 {
262                         printf("(%d):\t", tle->resdom->reskey);
263                 }
264                 else
265                 {
266                         printf("    :\t");
267                 }
268                 print_expr(tle->expr, rtable);
269                 printf("\n");
270         }
271         printf(")\n");
272 }
273
274 /*
275  * print_slot--
276  *        print out the tuple with the given TupleTableSlot
277  */
278 void
279 print_slot(TupleTableSlot *slot)
280 {
281         if (!slot->val)
282         {
283                 printf("tuple is null.\n");
284                 return;
285         }
286         if (!slot->ttc_tupleDescriptor)
287         {
288                 printf("no tuple descriptor.\n");
289                 return;
290         }
291
292         debugtup(slot->val, slot->ttc_tupleDescriptor);
293 }
294
295 static char *
296 plannode_type(Plan *p)
297 {
298         switch (nodeTag(p))
299         {
300                         case T_Plan:
301                         return "PLAN";
302                         break;
303                 case T_Result:
304                         return "RESULT";
305                         break;
306                 case T_Append:
307                         return "APPEND";
308                         break;
309                 case T_Scan:
310                         return "SCAN";
311                         break;
312                 case T_SeqScan:
313                         return "SEQSCAN";
314                         break;
315                 case T_IndexScan:
316                         return "INDEXSCAN";
317                         break;
318                 case T_Join:
319                         return "JOIN";
320                         break;
321                 case T_NestLoop:
322                         return "NESTLOOP";
323                         break;
324                 case T_MergeJoin:
325                         return "MERGEJOIN";
326                         break;
327                 case T_HashJoin:
328                         return "HASHJOIN";
329                         break;
330                 case T_Temp:
331                         return "TEMP";
332                         break;
333                 case T_Material:
334                         return "MATERIAL";
335                         break;
336                 case T_Sort:
337                         return "SORT";
338                         break;
339                 case T_Agg:
340                         return "AGG";
341                         break;
342                 case T_Unique:
343                         return "UNIQUE";
344                         break;
345                 case T_Hash:
346                         return "HASH";
347                         break;
348                 case T_Tee:
349                         return "TEE";
350                         break;
351                 case T_Choose:
352                         return "CHOOSE";
353                         break;
354                 case T_Group:
355                         return "GROUP";
356                         break;
357                 default:
358                         return "UNKNOWN";
359                         break;
360         }
361 }
362
363 /*
364    prints the ascii description of the plan nodes
365    does this recursively by doing a depth-first traversal of the
366    plan tree.  for SeqScan and IndexScan, the name of the table is also
367    printed out
368
369 */
370 void
371 print_plan_recursive(Plan *p, Query *parsetree, int indentLevel, char *label)
372 {
373         int                     i;
374         char            extraInfo[100];
375
376         if (!p)
377                 return;
378         for (i = 0; i < indentLevel; i++)
379                 printf(" ");
380         printf("%s%s :c=%.4f :s=%d :w=%d ", label, plannode_type(p),
381                    p->cost, p->plan_size, p->plan_width);
382         if (IsA(p, Scan) ||IsA(p, SeqScan))
383         {
384                 RangeTblEntry *rte;
385
386                 rte = rt_fetch(((Scan *) p)->scanrelid, parsetree->rtable);
387                 StrNCpy(extraInfo, rte->relname, NAMEDATALEN);
388         }
389         else if (IsA(p, IndexScan))
390         {
391                 StrNCpy(extraInfo,
392                    ((RangeTblEntry *) (nth(((IndexScan *) p)->scan.scanrelid - 1,
393                                                                    parsetree->rtable)))->relname,
394                                 NAMEDATALEN);
395         }
396         else
397                 extraInfo[0] = '\0';
398         if (extraInfo[0] != '\0')
399                 printf(" ( %s )\n", extraInfo);
400         else
401                 printf("\n");
402         print_plan_recursive(p->lefttree, parsetree, indentLevel + 3, "l: ");
403         print_plan_recursive(p->righttree, parsetree, indentLevel + 3, "r: ");
404 }
405
406 /* print_plan
407   prints just the plan node types */
408
409 void
410 print_plan(Plan *p, Query *parsetree)
411 {
412         print_plan_recursive(p, parsetree, 0, "");
413 }