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