* print.c
* various print routines (used mostly for debugging)
*
- * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/print.c,v 1.81 2006/08/02 01:59:45 joe Exp $
+ * src/backend/nodes/print.c
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
#include "postgres.h"
#include "access/printtup.h"
+#include "lib/stringinfo.h"
+#include "nodes/nodeFuncs.h"
#include "nodes/print.h"
-#include "optimizer/clauses.h"
+#include "nodes/relation.h"
#include "parser/parsetree.h"
#include "utils/lsyscache.h"
-static char *plannode_type(Plan *p);
/*
* print
* print contents of Node to stdout
*/
void
-print(void *obj)
+print(const void *obj)
{
char *s;
char *f;
* pretty-print contents of Node to stdout
*/
void
-pprint(void *obj)
+pprint(const void *obj)
{
char *s;
char *f;
* send pretty-printed contents of Node to postmaster log
*/
void
-elog_node_display(int lev, const char *title, void *obj, bool pretty)
+elog_node_display(int lev, const char *title, const void *obj, bool pretty)
{
char *s;
char *f;
pfree(s);
ereport(lev,
(errmsg_internal("%s:", title),
- errdetail("%s", f)));
+ errdetail_internal("%s", f)));
pfree(f);
}
* print contents of range table
*/
void
-print_rt(List *rtable)
+print_rt(const List *rtable)
{
- ListCell *l;
+ const ListCell *l;
int i = 1;
printf("resno\trefname \trelid\tinFromCl\n");
switch (rte->rtekind)
{
case RTE_RELATION:
- printf("%d\t%s\t%u",
- i, rte->eref->aliasname, rte->relid);
+ printf("%d\t%s\t%u\t%c",
+ i, rte->eref->aliasname, rte->relid, rte->relkind);
break;
case RTE_SUBQUERY:
printf("%d\t%s\t[subquery]",
i, rte->eref->aliasname);
break;
+ case RTE_JOIN:
+ printf("%d\t%s\t[join]",
+ i, rte->eref->aliasname);
+ break;
case RTE_FUNCTION:
printf("%d\t%s\t[rangefunction]",
i, rte->eref->aliasname);
break;
+ case RTE_TABLEFUNC:
+ printf("%d\t%s\t[table function]",
+ i, rte->eref->aliasname);
+ break;
case RTE_VALUES:
printf("%d\t%s\t[values list]",
i, rte->eref->aliasname);
break;
- case RTE_JOIN:
- printf("%d\t%s\t[join]",
+ case RTE_CTE:
+ printf("%d\t%s\t[cte]",
+ i, rte->eref->aliasname);
+ break;
+ case RTE_NAMEDTUPLESTORE:
+ printf("%d\t%s\t[tuplestore]",
i, rte->eref->aliasname);
break;
- case RTE_SPECIAL:
- printf("%d\t%s\t[special]",
+ case RTE_RESULT:
+ printf("%d\t%s\t[result]",
i, rte->eref->aliasname);
break;
default:
* print an expression
*/
void
-print_expr(Node *expr, List *rtable)
+print_expr(const Node *expr, const List *rtable)
{
if (expr == NULL)
{
if (IsA(expr, Var))
{
- Var *var = (Var *) expr;
+ const Var *var = (const Var *) expr;
char *relname,
*attname;
switch (var->varno)
{
- case INNER:
+ case INNER_VAR:
relname = "INNER";
attname = "?";
break;
- case OUTER:
+ case OUTER_VAR:
relname = "OUTER";
attname = "?";
break;
+ case INDEX_VAR:
+ relname = "INDEX";
+ attname = "?";
+ break;
default:
{
RangeTblEntry *rte;
}
else if (IsA(expr, Const))
{
- Const *c = (Const *) expr;
+ const Const *c = (const Const *) expr;
Oid typoutput;
bool typIsVarlena;
char *outputstr;
}
else if (IsA(expr, OpExpr))
{
- OpExpr *e = (OpExpr *) expr;
+ const OpExpr *e = (const OpExpr *) expr;
char *opname;
opname = get_opname(e->opno);
if (list_length(e->args) > 1)
{
- print_expr(get_leftop((Expr *) e), rtable);
+ print_expr(get_leftop((const Expr *) e), rtable);
printf(" %s ", ((opname != NULL) ? opname : "(invalid operator)"));
- print_expr(get_rightop((Expr *) e), rtable);
+ print_expr(get_rightop((const Expr *) e), rtable);
}
else
{
/* we print prefix and postfix ops the same... */
printf("%s ", ((opname != NULL) ? opname : "(invalid operator)"));
- print_expr(get_leftop((Expr *) e), rtable);
+ print_expr(get_leftop((const Expr *) e), rtable);
}
}
else if (IsA(expr, FuncExpr))
{
- FuncExpr *e = (FuncExpr *) expr;
+ const FuncExpr *e = (const FuncExpr *) expr;
char *funcname;
ListCell *l;
/*
* print_pathkeys -
- * pathkeys list of list of PathKeyItems
+ * pathkeys list of PathKeys
*/
void
-print_pathkeys(List *pathkeys, List *rtable)
+print_pathkeys(const List *pathkeys, const List *rtable)
{
- ListCell *i;
+ const ListCell *i;
printf("(");
foreach(i, pathkeys)
{
- List *pathkey = (List *) lfirst(i);
+ PathKey *pathkey = (PathKey *) lfirst(i);
+ EquivalenceClass *eclass;
ListCell *k;
+ bool first = true;
+
+ eclass = pathkey->pk_eclass;
+ /* chase up, in case pathkey is non-canonical */
+ while (eclass->ec_merged)
+ eclass = eclass->ec_merged;
printf("(");
- foreach(k, pathkey)
+ foreach(k, eclass->ec_members)
{
- PathKeyItem *item = (PathKeyItem *) lfirst(k);
+ EquivalenceMember *mem = (EquivalenceMember *) lfirst(k);
- print_expr(item->key, rtable);
- if (lnext(k))
+ if (first)
+ first = false;
+ else
printf(", ");
+ print_expr((Node *) mem->em_expr, rtable);
}
printf(")");
if (lnext(i))
* print targetlist in a more legible way.
*/
void
-print_tl(List *tlist, List *rtable)
+print_tl(const List *tlist, const List *rtable)
{
- ListCell *tl;
+ const ListCell *tl;
printf("(\n");
foreach(tl, tlist)
debugtup(slot, NULL);
}
-
-static char *
-plannode_type(Plan *p)
-{
- switch (nodeTag(p))
- {
- case T_Plan:
- return "PLAN";
- case T_Result:
- return "RESULT";
- case T_Append:
- return "APPEND";
- case T_BitmapAnd:
- return "BITMAPAND";
- case T_BitmapOr:
- return "BITMAPOR";
- case T_Scan:
- return "SCAN";
- case T_SeqScan:
- return "SEQSCAN";
- case T_IndexScan:
- return "INDEXSCAN";
- case T_BitmapIndexScan:
- return "BITMAPINDEXSCAN";
- case T_BitmapHeapScan:
- return "BITMAPHEAPSCAN";
- case T_TidScan:
- return "TIDSCAN";
- case T_SubqueryScan:
- return "SUBQUERYSCAN";
- case T_FunctionScan:
- return "FUNCTIONSCAN";
- case T_ValuesScan:
- return "VALUESSCAN";
- case T_Join:
- return "JOIN";
- case T_NestLoop:
- return "NESTLOOP";
- case T_MergeJoin:
- return "MERGEJOIN";
- case T_HashJoin:
- return "HASHJOIN";
- case T_Material:
- return "MATERIAL";
- case T_Sort:
- return "SORT";
- case T_Agg:
- return "AGG";
- case T_Unique:
- return "UNIQUE";
- case T_SetOp:
- return "SETOP";
- case T_Limit:
- return "LIMIT";
- case T_Hash:
- return "HASH";
- case T_Group:
- return "GROUP";
- default:
- return "UNKNOWN";
- }
-}
-
-/*
- * Recursively prints a simple text description of the plan tree
- */
-void
-print_plan_recursive(Plan *p, Query *parsetree, int indentLevel, char *label)
-{
- int i;
- char extraInfo[NAMEDATALEN + 100];
-
- if (!p)
- return;
- for (i = 0; i < indentLevel; i++)
- printf(" ");
- printf("%s%s :c=%.2f..%.2f :r=%.0f :w=%d ", label, plannode_type(p),
- p->startup_cost, p->total_cost,
- p->plan_rows, p->plan_width);
- if (IsA(p, Scan) ||
- IsA(p, SeqScan) ||
- IsA(p, BitmapHeapScan))
- {
- RangeTblEntry *rte;
-
- rte = rt_fetch(((Scan *) p)->scanrelid, parsetree->rtable);
- StrNCpy(extraInfo, rte->eref->aliasname, NAMEDATALEN);
- }
- else if (IsA(p, IndexScan))
- {
- RangeTblEntry *rte;
-
- rte = rt_fetch(((IndexScan *) p)->scan.scanrelid, parsetree->rtable);
- StrNCpy(extraInfo, rte->eref->aliasname, NAMEDATALEN);
- }
- else if (IsA(p, FunctionScan))
- {
- RangeTblEntry *rte;
-
- rte = rt_fetch(((FunctionScan *) p)->scan.scanrelid, parsetree->rtable);
- StrNCpy(extraInfo, rte->eref->aliasname, NAMEDATALEN);
- }
- else if (IsA(p, ValuesScan))
- {
- RangeTblEntry *rte;
-
- rte = rt_fetch(((ValuesScan *) p)->scan.scanrelid, parsetree->rtable);
- StrNCpy(extraInfo, rte->eref->aliasname, NAMEDATALEN);
- }
- 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: ");
-
- if (IsA(p, Append))
- {
- ListCell *l;
- Append *appendplan = (Append *) p;
-
- foreach(l, appendplan->appendplans)
- {
- Plan *subnode = (Plan *) lfirst(l);
-
- print_plan_recursive(subnode, parsetree, indentLevel + 3, "a: ");
- }
- }
-
- if (IsA(p, BitmapAnd))
- {
- ListCell *l;
- BitmapAnd *bitmapandplan = (BitmapAnd *) p;
-
- foreach(l, bitmapandplan->bitmapplans)
- {
- Plan *subnode = (Plan *) lfirst(l);
-
- print_plan_recursive(subnode, parsetree, indentLevel + 3, "a: ");
- }
- }
-
- if (IsA(p, BitmapOr))
- {
- ListCell *l;
- BitmapOr *bitmaporplan = (BitmapOr *) p;
-
- foreach(l, bitmaporplan->bitmapplans)
- {
- Plan *subnode = (Plan *) lfirst(l);
-
- print_plan_recursive(subnode, parsetree, indentLevel + 3, "a: ");
- }
- }
-}
-
-/*
- * print_plan
- *
- * prints just the plan node types
- */
-void
-print_plan(Plan *p, Query *parsetree)
-{
- print_plan_recursive(p, parsetree, 0, "");
-}