1 /*-------------------------------------------------------------------------
4 * various print routines (used mostly for debugging)
6 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.45 2000/10/26 21:35:48 tgl Exp $
14 * AUTHOR DATE MAJOR EVENT
15 * Andrew Yu Oct 26, 1994 file creation
17 *-------------------------------------------------------------------------
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"
28 static char *plannode_type(Plan *p);
32 * print contents of Node to stdout
39 s = nodeToString(obj);
45 * pretty print hack extraordinaire. -ay 10/94
56 s = nodeToString(obj);
62 for (j = 0; j < indentLev * 3; j++)
64 for (; j < 75 && s[i] != '\0'; i++, j++)
70 if (j != indentLev * 3)
74 line[indentLev * 3] = '\0';
75 printf("%s}\n", line);
80 printf("%s}\n", line);
83 j = indentLev * 3 - 1; /* print the line before :
89 j = indentLev * 3 - 1;
93 /* !!! FALLS THROUGH */
99 /* print the line before : and resets */
100 for (j = 0; j < indentLev * 3; j++)
110 printf("%s\n", line);
113 printf("%s\n", line);
120 * print contents of range table
123 print_rt(List *rtable)
128 printf("resno\trelname(refname)\trelid\tinFromCl\n");
129 printf("-----\t----------------\t-----\t--------\n");
132 RangeTblEntry *rte = lfirst(l);
135 printf("%d\t%s (%s)\t%u",
136 i, rte->relname, rte->eref->relname, rte->relid);
138 printf("%d\t[subquery] (%s)\t",
139 i, rte->eref->relname);
141 (rte->inh ? "inh" : ""),
142 (rte->inFromCl ? "inFromCl" : ""));
150 * print an expression
153 print_expr(Node *expr, List *rtable)
163 Var *var = (Var *) expr;
181 Assert(var->varno > 0 &&
182 (int) var->varno <= length(rtable));
183 rte = rt_fetch(var->varno, rtable);
184 relname = rte->eref->relname;
185 attname = get_rte_attribute_name(rte, var->varattno);
189 printf("%s.%s", relname, attname);
191 else if (IsA(expr, Expr))
193 Expr *e = (Expr *) expr;
195 if (is_opclause(expr))
199 print_expr((Node *) get_leftop(e), rtable);
200 opname = get_opname(((Oper *) e->oper)->opno);
201 printf(" %s ", ((opname != NULL) ? opname : "(invalid operator)"));
202 print_expr((Node *) get_rightop(e), rtable);
208 printf("not an expr");
213 * pathkeys list of list of PathKeyItems
216 print_pathkeys(List *pathkeys, List *rtable)
224 List *pathkey = lfirst(i);
229 PathKeyItem *item = lfirst(k);
231 print_expr(item->key, rtable);
244 * print targetlist in a more legible way.
247 print_tl(List *tlist, List *rtable)
254 TargetEntry *tle = lfirst(tl);
256 printf("\t%d %s\t", tle->resdom->resno, tle->resdom->resname);
257 if (tle->resdom->reskey != 0)
258 printf("(%d):\t", tle->resdom->reskey);
261 print_expr(tle->expr, rtable);
269 * print out the tuple with the given TupleTableSlot
272 print_slot(TupleTableSlot *slot)
276 printf("tuple is null.\n");
279 if (!slot->ttc_tupleDescriptor)
281 printf("no tuple descriptor.\n");
285 debugtup(slot->val, slot->ttc_tupleDescriptor, NULL);
289 plannode_type(Plan *p)
308 return "SUBQUERYSCAN";
339 prints the ascii description of the plan nodes
340 does this recursively by doing a depth-first traversal of the
341 plan tree. for SeqScan and IndexScan, the name of the table is also
346 print_plan_recursive(Plan *p, Query *parsetree, int indentLevel, char *label)
353 for (i = 0; i < indentLevel; i++)
355 printf("%s%s :c=%.2f..%.2f :r=%.0f :w=%d ", label, plannode_type(p),
356 p->startup_cost, p->total_cost,
357 p->plan_rows, p->plan_width);
358 if (IsA(p, Scan) ||IsA(p, SeqScan))
362 rte = rt_fetch(((Scan *) p)->scanrelid, parsetree->rtable);
363 StrNCpy(extraInfo, rte->relname, NAMEDATALEN);
365 else if (IsA(p, IndexScan))
369 rte = rt_fetch(((IndexScan *) p)->scan.scanrelid, parsetree->rtable);
370 StrNCpy(extraInfo, rte->relname, NAMEDATALEN);
374 if (extraInfo[0] != '\0')
375 printf(" ( %s )\n", extraInfo);
378 print_plan_recursive(p->lefttree, parsetree, indentLevel + 3, "l: ");
379 print_plan_recursive(p->righttree, parsetree, indentLevel + 3, "r: ");
385 Append *appendplan = (Append *) p;
387 foreach(lst, appendplan->appendplans)
389 Plan *subnode = (Plan *) lfirst(lst);
392 * I don't think we need to fiddle with the range table here,
395 print_plan_recursive(subnode, parsetree, indentLevel + 3, "a: ");
403 prints just the plan node types */
406 print_plan(Plan *p, Query *parsetree)
408 print_plan_recursive(p, parsetree, 0, "");