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