]> granicus.if.org Git - postgresql/blobdiff - src/backend/nodes/print.c
Make some small planner API cleanups.
[postgresql] / src / backend / nodes / print.c
index 14f73b1860ea2d12a37b9dac644d915d7736c6d5..6d6da5299faf0b38e2ab44a72941eadc28c87f71 100644 (file)
@@ -3,12 +3,12 @@
  * print.c
  *       various print routines (used mostly for debugging)
  *
- * Portions Copyright (c) 1996-2003, 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.66 2004/05/08 21:21:18 tgl Exp $
+ *       src/backend/nodes/print.c
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
 #include "postgres.h"
 
 #include "access/printtup.h"
-#include "catalog/pg_type.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"
-#include "utils/syscache.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;
@@ -53,7 +51,7 @@ print(void *obj)
  *       pretty-print contents of Node to stdout
  */
 void
-pprint(void *obj)
+pprint(const void *obj)
 {
        char       *s;
        char       *f;
@@ -71,7 +69,7 @@ pprint(void *obj)
  *       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;
@@ -84,7 +82,7 @@ elog_node_display(int lev, const char *title, void *obj, bool pretty)
        pfree(s);
        ereport(lev,
                        (errmsg_internal("%s:", title),
-                        errdetail("%s", f)));
+                        errdetail_internal("%s", f)));
        pfree(f);
 }
 
@@ -195,17 +193,17 @@ pretty_format_node_dump(const char *dump)
                                        j = indentDist - 1;
                                        /* j will equal indentDist on next loop iteration */
                                        /* suppress whitespace just after } */
-                                       while (dump[i+1] == ' ')
+                                       while (dump[i + 1] == ' ')
                                                i++;
                                        break;
                                case ')':
                                        /* force line break after ), unless another ) follows */
-                                       if (dump[i+1] != ')')
+                                       if (dump[i + 1] != ')')
                                        {
                                                line[j + 1] = '\0';
                                                appendStringInfo(&str, "%s\n", line);
                                                j = indentDist - 1;
-                                               while (dump[i+1] == ' ')
+                                               while (dump[i + 1] == ' ')
                                                        i++;
                                        }
                                        break;
@@ -253,9 +251,9 @@ pretty_format_node_dump(const char *dump)
  *       print contents of range table
  */
 void
-print_rt(List *rtable)
+print_rt(const List *rtable)
 {
-       List       *l;
+       const ListCell *l;
        int                     i = 1;
 
        printf("resno\trefname  \trelid\tinFromCl\n");
@@ -267,23 +265,39 @@ print_rt(List *rtable)
                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_JOIN:
-                               printf("%d\t%s\t[join]",
+                       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_CTE:
+                               printf("%d\t%s\t[cte]",
                                           i, rte->eref->aliasname);
                                break;
-                       case RTE_SPECIAL:
-                               printf("%d\t%s\t[special]",
+                       case RTE_NAMEDTUPLESTORE:
+                               printf("%d\t%s\t[tuplestore]",
+                                          i, rte->eref->aliasname);
+                               break;
+                       case RTE_RESULT:
+                               printf("%d\t%s\t[result]",
                                           i, rte->eref->aliasname);
                                break;
                        default:
@@ -304,7 +318,7 @@ print_rt(List *rtable)
  *       print an expression
  */
 void
-print_expr(Node *expr, List *rtable)
+print_expr(const Node *expr, const List *rtable)
 {
        if (expr == NULL)
        {
@@ -314,26 +328,30 @@ print_expr(Node *expr, List *rtable)
 
        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;
 
                                        Assert(var->varno > 0 &&
-                                                  (int) var->varno <= length(rtable));
+                                                  (int) var->varno <= list_length(rtable));
                                        rte = rt_fetch(var->varno, rtable);
                                        relname = rte->eref->aliasname;
                                        attname = get_rte_attribute_name(rte, var->varattno);
@@ -344,10 +362,9 @@ print_expr(Node *expr, List *rtable)
        }
        else if (IsA(expr, Const))
        {
-               Const      *c = (Const *) expr;
-               HeapTuple       typeTup;
+               const Const *c = (const Const *) expr;
                Oid                     typoutput;
-               Oid                     typelem;
+               bool            typIsVarlena;
                char       *outputstr;
 
                if (c->constisnull)
@@ -356,46 +373,37 @@ print_expr(Node *expr, List *rtable)
                        return;
                }
 
-               typeTup = SearchSysCache(TYPEOID,
-                                                                ObjectIdGetDatum(c->consttype),
-                                                                0, 0, 0);
-               if (!HeapTupleIsValid(typeTup))
-                       elog(ERROR, "cache lookup failed for type %u", c->consttype);
-               typoutput = ((Form_pg_type) GETSTRUCT(typeTup))->typoutput;
-               typelem = ((Form_pg_type) GETSTRUCT(typeTup))->typelem;
-               ReleaseSysCache(typeTup);
-
-               outputstr = DatumGetCString(OidFunctionCall3(typoutput,
-                                                                                                        c->constvalue,
-                                                                                          ObjectIdGetDatum(typelem),
-                                                                                                        Int32GetDatum(-1)));
+               getTypeOutputInfo(c->consttype,
+                                                 &typoutput, &typIsVarlena);
+
+               outputstr = OidOutputFunctionCall(typoutput, c->constvalue);
                printf("%s", outputstr);
                pfree(outputstr);
        }
        else if (IsA(expr, OpExpr))
        {
-               OpExpr     *e = (OpExpr *) expr;
+               const OpExpr *e = (const OpExpr *) expr;
                char       *opname;
 
                opname = get_opname(e->opno);
-               if (length(e->args) > 1)
+               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;
-               List       *l;
+               ListCell   *l;
 
                funcname = get_func_name(e->funcid);
                printf("%s(", ((funcname != NULL) ? funcname : "(invalid function)"));
@@ -413,27 +421,36 @@ print_expr(Node *expr, List *rtable)
 
 /*
  * 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)
 {
-       List       *i,
-                          *k;
+       const ListCell *i;
 
        printf("(");
        foreach(i, pathkeys)
        {
-               List       *pathkey = 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 = 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))
@@ -447,19 +464,19 @@ print_pathkeys(List *pathkeys, List *rtable)
  *       print targetlist in a more legible way.
  */
 void
-print_tl(List *tlist, List *rtable)
+print_tl(const List *tlist, const List *rtable)
 {
-       List       *tl;
+       const ListCell *tl;
 
        printf("(\n");
        foreach(tl, tlist)
        {
-               TargetEntry *tle = lfirst(tl);
+               TargetEntry *tle = (TargetEntry *) lfirst(tl);
 
-               printf("\t%d %s\t", tle->resdom->resno,
-                          tle->resdom->resname ? tle->resdom->resname : "<null>");
-               if (tle->resdom->ressortgroupref != 0)
-                       printf("(%u):\t", tle->resdom->ressortgroupref);
+               printf("\t%d %s\t", tle->resno,
+                          tle->resname ? tle->resname : "<null>");
+               if (tle->ressortgroupref != 0)
+                       printf("(%u):\t", tle->ressortgroupref);
                else
                        printf("    :\t");
                print_expr((Node *) tle->expr, rtable);
@@ -475,145 +492,16 @@ print_tl(List *tlist, List *rtable)
 void
 print_slot(TupleTableSlot *slot)
 {
-       if (!slot->val)
+       if (TupIsNull(slot))
        {
                printf("tuple is null.\n");
                return;
        }
-       if (!slot->ttc_tupleDescriptor)
+       if (!slot->tts_tupleDescriptor)
        {
                printf("no tuple descriptor.\n");
                return;
        }
 
-       debugtup(slot->val, slot->ttc_tupleDescriptor, 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_Scan:
-                       return "SCAN";
-               case T_SeqScan:
-                       return "SEQSCAN";
-               case T_IndexScan:
-                       return "INDEXSCAN";
-               case T_TidScan:
-                       return "TIDSCAN";
-               case T_SubqueryScan:
-                       return "SUBQUERYSCAN";
-               case T_FunctionScan:
-                       return "FUNCTIONSCAN";
-               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))
-       {
-               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
-               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))
-       {
-               List       *lst;
-               int                     whichplan = 0;
-               Append     *appendplan = (Append *) p;
-
-               foreach(lst, appendplan->appendplans)
-               {
-                       Plan       *subnode = (Plan *) lfirst(lst);
-
-                       /*
-                        * I don't think we need to fiddle with the range table here,
-                        * bjm
-                        */
-                       print_plan_recursive(subnode, parsetree, indentLevel + 3, "a: ");
-
-                       whichplan++;
-               }
-       }
-}
-
-/* print_plan
-  prints just the plan node types */
-
-void
-print_plan(Plan *p, Query *parsetree)
-{
-       print_plan_recursive(p, parsetree, 0, "");
+       debugtup(slot, NULL);
 }