diff options
Diffstat (limited to 'src/backend/nodes/print.c')
-rw-r--r-- | src/backend/nodes/print.c | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c new file mode 100644 index 00000000000..0297b445b10 --- /dev/null +++ b/src/backend/nodes/print.c @@ -0,0 +1,377 @@ +/*------------------------------------------------------------------------- + * + * print.c-- + * various print routines (used mostly for debugging) + * + * Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.1.1.1 1996/07/09 06:21:33 scrappy Exp $ + * + * HISTORY + * AUTHOR DATE MAJOR EVENT + * Andrew Yu Oct 26, 1994 file creation + * + *------------------------------------------------------------------------- + */ +#include <stdio.h> +#include "postgres.h" +#include "access/printtup.h" +#include "nodes/pg_list.h" +#include "nodes/execnodes.h" +#include "nodes/parsenodes.h" + +#include "parser/parsetree.h" +#include "parser/catalog_utils.h" +#include "access/heapam.h" +#include "utils/lsyscache.h" +#include "nodes/nodes.h" +#include "nodes/plannodes.h" +#include "optimizer/clauses.h" +/* + * print-- + * print contents of Node to stdout + */ +void +print(void *obj) +{ + char *s; + + s = nodeToString(obj); + printf("%s\n", s); + fflush(stdout); + return; +} + +/* + * pretty print hack extraordinaire. -ay 10/94 + */ +void +pprint(void *obj) +{ + char *s; + int i; + char line[80]; + int indentLev; + int j; + + s = nodeToString(obj); + + indentLev = 0; + i = 0; + for(;;) { + for(j=0; j<indentLev*3; j++) { + line[j] = ' '; + } + for( ; j<75 && s[i]!='\0'; i++, j++) { + line[j] = s[i]; + switch (line[j]) { + case '}': + if (j != indentLev*3) { + line[j] = '\0'; + printf("%s\n",line); + line[indentLev*3] = '\0'; + printf("%s}\n",line); + }else { + line[j] = '\0'; + printf("%s}\n",line); + } + indentLev--; + j = indentLev*3-1; /* print the line before : and resets */ + break; + case ')': + line[j+1] = '\0'; + printf("%s\n", line); + j = indentLev*3-1; + break; + case '{': + indentLev++; + /* !!! FALLS THROUGH */ + case ':': + if (j != 0) { + line[j] = '\0'; + printf("%s\n",line); + /* print the line before : and resets */ + for(j=0; j<indentLev*3; j++) { + line[j] = ' '; + } + } + line[j] = s[i]; + break; + } + } + line[j] = '\0'; + if (s[i]=='\0') + break; + printf("%s\n", line); + } + if (j!=0) { + printf("%s\n", line); + } + fflush(stdout); + return; +} + +/* + * print_rt-- + * print contents of range table + */ +void +print_rt(List *rtable) +{ + List *l; + int i=1; + + printf("resno\trelname(refname)\trelid\tinFromCl\n"); + printf("-----\t----------------\t-----\t--------\n"); + foreach(l, rtable) { + RangeTblEntry *rte = lfirst(l); + printf("%d\t%s(%s)\t%d\t%d\t%s\n", + i,rte->relname,rte->refname,rte->relid, + rte->inFromCl, + (rte->inh?"inh":"")); + i++; + } +} + + +/* + * print_expr-- + * print an expression + */ +void +print_expr(Node *expr, List *rtable) +{ + if (expr==NULL) { + printf("nil"); + return; + } + + if (IsA(expr,Var)) { + Var *var = (Var*)expr; + RangeTblEntry *rt; + char *relname, *attname; + + switch (var->varno) { + case INNER: + relname = "INNER"; + attname = "?"; + break; + case OUTER: + relname = "OUTER"; + attname = "?"; + break; + default: + { + Relation r; + rt = rt_fetch(var->varno, rtable); + relname = rt->relname; + r = heap_openr(relname); + if (rt->refname) + relname = rt->refname; /* table renamed */ + attname = getAttrName(r, var->varattno); + heap_close(r); + } + break; + } + printf("%s.%s",relname,attname); + } else if (IsA(expr,Expr)) { + Expr *e = (Expr*)expr; + if (is_opclause(expr)) { + char *opname; + + print_expr((Node*)get_leftop(e), rtable); + opname = get_opname(((Oper*)e->oper)->opno); + printf(" %s ", opname); + print_expr((Node*)get_rightop(e), rtable); + } else { + printf("an expr"); + } + } else { + printf("not an expr"); + } +} + +/* + * print_keys - + * temporary here. where is keys list of list?? + */ +void +print_keys(List *keys, List *rtable) +{ + List *k; + + printf("("); + foreach(k, keys) { + Node *var = lfirst((List*)lfirst(k)); + print_expr(var, rtable); + if (lnext(k)) printf(", "); + } + printf(")\n"); +} + +/* + * print_tl -- + * print targetlist in a more legible way. + */ +void +print_tl(List *tlist, List *rtable) +{ + List *tl; + + printf("(\n"); + foreach(tl, tlist) { + TargetEntry *tle = lfirst(tl); + + printf("\t%d %s\t", tle->resdom->resno, tle->resdom->resname); + if (tle->resdom->reskey!=0) { + printf("(%d):\t", tle->resdom->reskey); + } else { + printf(" :\t"); + } + print_expr(tle->expr, rtable); + printf("\n"); + } + printf(")\n"); +} + +/* + * print_slot-- + * print out the tuple with the given TupleTableSlot + */ +void +print_slot(TupleTableSlot *slot) +{ + if (!slot->val) { + printf("tuple is null.\n"); + return; + } + if (!slot->ttc_tupleDescriptor) { + printf("no tuple descriptor.\n"); + return; + } + + debugtup(slot->val, slot->ttc_tupleDescriptor); +} + +char* +plannode_type (Plan* p) +{ + switch(nodeTag(p)) { + case T_Plan: + return "PLAN"; + break; + case T_Existential: + return "EXISTENTIAL"; + break; + case T_Result: + return "RESULT"; + break; + case T_Append: + return "APPEND"; + break; + case T_Scan: + return "SCAN"; + break; + case T_SeqScan: + return "SEQSCAN"; + break; + case T_IndexScan: + return "INDEXSCAN"; + break; + case T_Join: + return "JOIN"; + break; + case T_NestLoop: + return "NESTLOOP"; + break; + case T_MergeJoin: + return "MERGEJOIN"; + break; + case T_HashJoin: + return "HASHJOIN"; + break; + case T_Temp: + return "TEMP"; + break; + case T_Material: + return "MATERIAL"; + break; + case T_Sort: + return "SORT"; + break; + case T_Agg: + return "AGG"; + break; + case T_Unique: + return "UNIQUE"; + break; + case T_Hash: + return "HASH"; + break; + case T_Tee: + return "TEE"; + break; + case T_Choose: + return "CHOOSE"; + break; + case T_Group: + return "GROUP"; + break; + default: + return "UNKNOWN"; + break; + } +} +/* + prints the ascii description of the plan nodes + does this recursively by doing a depth-first traversal of the + plan tree. for SeqScan and IndexScan, the name of the table is also + printed out + +*/ +void +print_plan_recursive (Plan* p, Query *parsetree, int indentLevel, char* label) +{ + int i; + char extraInfo[100]; + + if (!p) + return; + for (i=0;i<indentLevel;i++) + printf(" "); + printf("%s%s :c=%.4f :s=%d :w=%d ",label, plannode_type(p), + p->cost, p->plan_size, p->plan_width); + if (IsA(p,Scan) || IsA(p,SeqScan)) { + RangeTblEntry *rte; + rte = rt_fetch(((Scan*)p)->scanrelid, parsetree->rtable); + strncpy(extraInfo, rte->relname, NAMEDATALEN); + extraInfo[NAMEDATALEN] = '\0'; + } else + if (IsA(p,IndexScan)) { + strncpy(extraInfo, + ((RangeTblEntry*)(nth(((IndexScan*)p)->scan.scanrelid - 1, + parsetree->rtable)))->relname, + NAMEDATALEN); + extraInfo[NAMEDATALEN] = '\0'; + } else + extraInfo[0] = '\0'; + if (extraInfo[0] != '\0') + printf(" ( %s )\n", extraInfo); + else + printf("\n"); + print_plan_recursive(p->lefttree, parsetree, indentLevel + 3, "l: "); + print_plan_recursive(p->righttree, parsetree, indentLevel + 3, "r: "); +} + +/* print_plan + prints just the plan node types */ + +void +print_plan (Plan* p, Query* parsetree) +{ + print_plan_recursive(p, parsetree, 0, ""); +} + + |