Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  print.c

  Sprache: C
 

/*-------------------------------------------------------------------------
 *
 * print.c
 *   various print routines (used mostly for debugging)
 *
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *   src/backend/nodes/print.c
 *
 * HISTORY
 *   AUTHOR   DATE   MAJOR EVENT
 *   Andrew Yu   Oct 26, 1994 file creation
 *
 *-------------------------------------------------------------------------
 */


#include "postgres.h"

#include "access/printtup.h"
#include "lib/stringinfo.h"
#include "nodes/nodeFuncs.h"
#include "nodes/pathnodes.h"
#include "nodes/print.h"
#include "parser/parsetree.h"
#include "utils/lsyscache.h"


/*
 * print
 *   print contents of Node to stdout
 */

void
print(const void *obj)
{
 char    *s;
 char    *f;

 s = nodeToStringWithLocations(obj);
 f = format_node_dump(s);
 pfree(s);
 printf("%s\n", f);
 fflush(stdout);
 pfree(f);
}

/*
 * pprint
 *   pretty-print contents of Node to stdout
 */

void
pprint(const void *obj)
{
 char    *s;
 char    *f;

 s = nodeToStringWithLocations(obj);
 f = pretty_format_node_dump(s);
 pfree(s);
 printf("%s\n", f);
 fflush(stdout);
 pfree(f);
}

/*
 * elog_node_display
 *   send pretty-printed contents of Node to postmaster log
 */

void
elog_node_display(int lev, const char *title, const void *obj, bool pretty)
{
 char    *s;
 char    *f;

 s = nodeToStringWithLocations(obj);
 if (pretty)
  f = pretty_format_node_dump(s);
 else
  f = format_node_dump(s);
 pfree(s);
 ereport(lev,
   (errmsg_internal("%s:", title),
    errdetail_internal("%s", f)));
 pfree(f);
}

/*
 * Format a nodeToString output for display on a terminal.
 *
 * The result is a palloc'd string.
 *
 * This version just tries to break at whitespace.
 */

char *
format_node_dump(const char *dump)
{
#define LINELEN  78
 char  line[LINELEN + 1];
 StringInfoData str;
 int   i;
 int   j;
 int   k;

 initStringInfo(&str);
 i = 0;
 for (;;)
 {
  for (j = 0; j < LINELEN && dump[i] != '\0'; i++, j++)
   line[j] = dump[i];
  if (dump[i] == '\0')
   break;
  if (dump[i] == ' ')
  {
   /* ok to break at adjacent space */
   i++;
  }
  else
  {
   for (k = j - 1; k > 0; k--)
    if (line[k] == ' ')
     break;
   if (k > 0)
   {
    /* back up; will reprint all after space */
    i -= (j - k - 1);
    j = k;
   }
  }
  line[j] = '\0';
  appendStringInfo(&str, "%s\n", line);
 }
 if (j > 0)
 {
  line[j] = '\0';
  appendStringInfo(&str, "%s\n", line);
 }
 return str.data;
#undef LINELEN
}

/*
 * Format a nodeToString output for display on a terminal.
 *
 * The result is a palloc'd string.
 *
 * This version tries to indent intelligently.
 */

char *
pretty_format_node_dump(const char *dump)
{
#define INDENTSTOP 3
#define MAXINDENT 60
#define LINELEN  78
 char  line[LINELEN + 1];
 StringInfoData str;
 int   indentLev;
 int   indentDist;
 int   i;
 int   j;

 initStringInfo(&str);
 indentLev = 0;    /* logical indent level */
 indentDist = 0;    /* physical indent distance */
 i = 0;
 for (;;)
 {
  for (j = 0; j < indentDist; j++)
   line[j] = ' ';
  for (; j < LINELEN && dump[i] != '\0'; i++, j++)
  {
   line[j] = dump[i];
   switch (line[j])
   {
    case '}':
     if (j != indentDist)
     {
      /* print data before the } */
      line[j] = '\0';
      appendStringInfo(&str, "%s\n", line);
     }
     /* print the } at indentDist */
     line[indentDist] = '}';
     line[indentDist + 1] = '\0';
     appendStringInfo(&str, "%s\n", line);
     /* outdent */
     if (indentLev > 0)
     {
      indentLev--;
      indentDist = Min(indentLev * INDENTSTOP, MAXINDENT);
     }
     j = indentDist - 1;
     /* j will equal indentDist on next loop iteration */
     /* suppress whitespace just after } */
     while (dump[i + 1] == ' ')
      i++;
     break;
    case ')':
     /* force line break after ), unless another ) follows */
     if (dump[i + 1] != ')')
     {
      line[j + 1] = '\0';
      appendStringInfo(&str, "%s\n", line);
      j = indentDist - 1;
      while (dump[i + 1] == ' ')
       i++;
     }
     break;
    case '{':
     /* force line break before { */
     if (j != indentDist)
     {
      line[j] = '\0';
      appendStringInfo(&str, "%s\n", line);
     }
     /* indent */
     indentLev++;
     indentDist = Min(indentLev * INDENTSTOP, MAXINDENT);
     for (j = 0; j < indentDist; j++)
      line[j] = ' ';
     line[j] = dump[i];
     break;
    case ':':
     /* force line break before : */
     if (j != indentDist)
     {
      line[j] = '\0';
      appendStringInfo(&str, "%s\n", line);
     }
     j = indentDist;
     line[j] = dump[i];
     break;
   }
  }
  line[j] = '\0';
  if (dump[i] == '\0')
   break;
  appendStringInfo(&str, "%s\n", line);
 }
 if (j > 0)
  appendStringInfo(&str, "%s\n", line);
 return str.data;
#undef INDENTSTOP
#undef MAXINDENT
#undef LINELEN
}

/*
 * print_rt
 *   print contents of range table
 */

void
print_rt(const List *rtable)
{
 const ListCell *l;
 int   i = 1;

 printf("resno\trefname  \trelid\tinFromCl\n");
 printf("-----\t---------\t-----\t--------\n");
 foreach(l, rtable)
 {
  RangeTblEntry *rte = lfirst(l);

  switch (rte->rtekind)
  {
   case RTE_RELATION:
    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_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_RESULT:
    printf("%d\t%s\t[result]",
        i, rte->eref->aliasname);
    break;
   case RTE_GROUP:
    printf("%d\t%s\t[group]",
        i, rte->eref->aliasname);
    break;
   default:
    printf("%d\t%s\t[unknown rtekind]",
        i, rte->eref->aliasname);
  }

  printf("\t%s\t%s\n",
      (rte->inh ? "inh" : ""),
      (rte->inFromCl ? "inFromCl" : ""));
  i++;
 }
}


/*
 * print_expr
 *   print an expression
 */

void
print_expr(const Node *expr, const List *rtable)
{
 if (expr == NULL)
 {
  printf("<>");
  return;
 }

 if (IsA(expr, Var))
 {
  const Var  *var = (const Var *) expr;
  char    *relname,
       *attname;

  switch (var->varno)
  {
   case INNER_VAR:
    relname = "INNER";
    attname = "?";
    break;
   case OUTER_VAR:
    relname = "OUTER";
    attname = "?";
    break;
   case INDEX_VAR:
    relname = "INDEX";
    attname = "?";
    break;
   default:
    {
     RangeTblEntry *rte;

     Assert(var->varno > 0 &&
         (int) var->varno <= list_length(rtable));
     rte = rt_fetch(var->varno, rtable);
     relname = rte->eref->aliasname;
     attname = get_rte_attribute_name(rte, var->varattno);
    }
    break;
  }
  printf("%s.%s", relname, attname);
 }
 else if (IsA(expr, Const))
 {
  const Const *c = (const Const *) expr;
  Oid   typoutput;
  bool  typIsVarlena;
  char    *outputstr;

  if (c->constisnull)
  {
   printf("NULL");
   return;
  }

  getTypeOutputInfo(c->consttype,
        &typoutput, &typIsVarlena);

  outputstr = OidOutputFunctionCall(typoutput, c->constvalue);
  printf("%s", outputstr);
  pfree(outputstr);
 }
 else if (IsA(expr, OpExpr))
 {
  const OpExpr *e = (const OpExpr *) expr;
  char    *opname;

  opname = get_opname(e->opno);
  if (list_length(e->args) > 1)
  {
   print_expr(get_leftop((const Expr *) e), rtable);
   printf(" %s ", ((opname != NULL) ? opname : "(invalid operator)"));
   print_expr(get_rightop((const Expr *) e), rtable);
  }
  else
  {
   printf("%s ", ((opname != NULL) ? opname : "(invalid operator)"));
   print_expr(get_leftop((const Expr *) e), rtable);
  }
 }
 else if (IsA(expr, FuncExpr))
 {
  const FuncExpr *e = (const FuncExpr *) expr;
  char    *funcname;
  ListCell   *l;

  funcname = get_func_name(e->funcid);
  printf("%s(", ((funcname != NULL) ? funcname : "(invalid function)"));
  foreach(l, e->args)
  {
   print_expr(lfirst(l), rtable);
   if (lnext(e->args, l))
    printf(",");
  }
  printf(")");
 }
 else
  printf("unknown expr");
}

/*
 * print_pathkeys -
 *   pathkeys list of PathKeys
 */

void
print_pathkeys(const List *pathkeys, const List *rtable)
{
 const ListCell *i;

 printf("(");
 foreach(i, pathkeys)
 {
  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, eclass->ec_members)
  {
   EquivalenceMember *mem = (EquivalenceMember *) lfirst(k);

   if (first)
    first = false;
   else
    printf(", ");
   print_expr((Node *) mem->em_expr, rtable);
  }
  printf(")");
  if (lnext(pathkeys, i))
   printf(", ");
 }
 printf(")\n");
}

/*
 * print_tl
 *   print targetlist in a more legible way.
 */

void
print_tl(const List *tlist, const List *rtable)
{
 const ListCell *tl;

 printf("(\n");
 foreach(tl, tlist)
 {
  TargetEntry *tle = (TargetEntry *) lfirst(tl);

  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);
  printf("\n");
 }
 printf(")\n");
}

/*
 * print_slot
 *   print out the tuple with the given TupleTableSlot
 */

void
print_slot(TupleTableSlot *slot)
{
 if (TupIsNull(slot))
 {
  printf("tuple is null.\n");
  return;
 }
 if (!slot->tts_tupleDescriptor)
 {
  printf("no tuple descriptor.\n");
  return;
 }

 debugtup(slot, NULL);
}

Messung V0.5 in Prozent
C=96 H=75 G=86

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-08-11) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=738142