]> granicus.if.org Git - postgresql/blob - src/backend/nodes/print.c
Another SELECT speedup: extract OIDs of column print functions
[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.19 1999/01/27 00:36:28 tgl 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%d\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_keys -
216  *        temporary here. where is keys list of list??
217  */
218 void
219 print_keys(List *keys, List *rtable)
220 {
221         List       *k;
222
223         printf("(");
224         foreach(k, keys)
225         {
226                 Node       *var = lfirst((List *) lfirst(k));
227
228                 print_expr(var, rtable);
229                 if (lnext(k))
230                         printf(", ");
231         }
232         printf(")\n");
233 }
234
235 /*
236  * print_tl --
237  *        print targetlist in a more legible way.
238  */
239 void
240 print_tl(List *tlist, List *rtable)
241 {
242         List       *tl;
243
244         printf("(\n");
245         foreach(tl, tlist)
246         {
247                 TargetEntry *tle = lfirst(tl);
248
249                 printf("\t%d %s\t", tle->resdom->resno, tle->resdom->resname);
250                 if (tle->resdom->reskey != 0)
251                         printf("(%d):\t", tle->resdom->reskey);
252                 else
253                         printf("    :\t");
254                 print_expr(tle->expr, rtable);
255                 printf("\n");
256         }
257         printf(")\n");
258 }
259
260 /*
261  * print_slot--
262  *        print out the tuple with the given TupleTableSlot
263  */
264 void
265 print_slot(TupleTableSlot *slot)
266 {
267         if (!slot->val)
268         {
269                 printf("tuple is null.\n");
270                 return;
271         }
272         if (!slot->ttc_tupleDescriptor)
273         {
274                 printf("no tuple descriptor.\n");
275                 return;
276         }
277
278         debugtup(slot->val, slot->ttc_tupleDescriptor, NULL);
279 }
280
281 static char *
282 plannode_type(Plan *p)
283 {
284         switch (nodeTag(p))
285         {
286                         case T_Plan:
287                         return "PLAN";
288                         break;
289                 case T_Result:
290                         return "RESULT";
291                         break;
292                 case T_Append:
293                         return "APPEND";
294                         break;
295                 case T_Scan:
296                         return "SCAN";
297                         break;
298                 case T_SeqScan:
299                         return "SEQSCAN";
300                         break;
301                 case T_IndexScan:
302                         return "INDEXSCAN";
303                         break;
304                 case T_Join:
305                         return "JOIN";
306                         break;
307                 case T_NestLoop:
308                         return "NESTLOOP";
309                         break;
310                 case T_MergeJoin:
311                         return "MERGEJOIN";
312                         break;
313                 case T_HashJoin:
314                         return "HASHJOIN";
315                         break;
316                 case T_Temp:
317                         return "TEMP";
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_Tee:
335                         return "TEE";
336                         break;
337                 case T_Choose:
338                         return "CHOOSE";
339                         break;
340                 case T_Group:
341                         return "GROUP";
342                         break;
343                 default:
344                         return "UNKNOWN";
345                         break;
346         }
347 }
348
349 /*
350    prints the ascii description of the plan nodes
351    does this recursively by doing a depth-first traversal of the
352    plan tree.  for SeqScan and IndexScan, the name of the table is also
353    printed out
354
355 */
356 void
357 print_plan_recursive(Plan *p, Query *parsetree, int indentLevel, char *label)
358 {
359         int                     i;
360         char            extraInfo[100];
361
362         if (!p)
363                 return;
364         for (i = 0; i < indentLevel; i++)
365                 printf(" ");
366         printf("%s%s :c=%.4f :s=%d :w=%d ", label, plannode_type(p),
367                    p->cost, p->plan_size, p->plan_width);
368         if (IsA(p, Scan) ||IsA(p, SeqScan))
369         {
370                 RangeTblEntry *rte;
371
372                 rte = rt_fetch(((Scan *) p)->scanrelid, parsetree->rtable);
373                 StrNCpy(extraInfo, rte->relname, NAMEDATALEN);
374         }
375         else if (IsA(p, IndexScan))
376         {
377                 StrNCpy(extraInfo,
378                    ((RangeTblEntry *) (nth(((IndexScan *) p)->scan.scanrelid - 1,
379                                                                    parsetree->rtable)))->relname,
380                                 NAMEDATALEN);
381         }
382         else
383                 extraInfo[0] = '\0';
384         if (extraInfo[0] != '\0')
385                 printf(" ( %s )\n", extraInfo);
386         else
387                 printf("\n");
388         print_plan_recursive(p->lefttree, parsetree, indentLevel + 3, "l: ");
389         print_plan_recursive(p->righttree, parsetree, indentLevel + 3, "r: ");
390
391         if (nodeTag(p) == T_Append)
392         {
393                 List       *lst;
394                 int                     whichplan = 0;
395                 Append     *appendplan = (Append *) p;
396
397                 foreach(lst, appendplan->appendplans)
398                 {
399                         Plan       *subnode = (Plan *) lfirst(lst);
400
401                         /*
402                          * I don't think we need to fiddle with the range table here,
403                          * bjm
404                          */
405                         print_plan_recursive(subnode, parsetree, indentLevel + 3, "a: ");
406
407                         whichplan++;
408                 }
409         }
410 }
411
412 /* print_plan
413   prints just the plan node types */
414
415 void
416 print_plan(Plan *p, Query *parsetree)
417 {
418         print_plan_recursive(p, parsetree, 0, "");
419 }