/*------------------------------------------------------------------------- * * 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.6 1997/08/19 21:31:43 momjian Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT * Andrew Yu Oct 26, 1994 file creation * *------------------------------------------------------------------------- */ #include #include #include "postgres.h" #include "access/printtup.h" #include "nodes/pg_list.h" #include "nodes/execnodes.h" #include "nodes/parsenodes.h" #include "nodes/print.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" static char *plannode_type (Plan* p); /* * 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; jrelname,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); } static 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;icost, 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-1); } else if (IsA(p,IndexScan)) { strNcpy(extraInfo, ((RangeTblEntry*)(nth(((IndexScan*)p)->scan.scanrelid - 1, parsetree->rtable)))->relname, NAMEDATALEN-1); } 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, ""); }