1998-12-14 09:11:17 +01:00
|
|
|
/*
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* outfuncs.c
|
1997-09-07 07:04:48 +02:00
|
|
|
* routines to convert a node to ascii representation
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
1999-02-18 01:49:48 +01:00
|
|
|
* $Id: outfuncs.c,v 1.75 1999/02/18 00:49:14 momjian Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* NOTES
|
1997-09-07 07:04:48 +02:00
|
|
|
* Every (plan) node in POSTGRES has an associated "out" routine which
|
|
|
|
* knows how to create its ascii representation. These functions are
|
|
|
|
* useful for debugging as well as for storing plans in the system
|
|
|
|
* catalogs (eg. indexes). This is also the plan string sent out in
|
|
|
|
* Mariposa.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* These functions update the in/out argument of type StringInfo
|
|
|
|
* passed to them. This argument contains the string holding the ASCII
|
|
|
|
* representation plus some other information (string length, etc.)
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
#include "access/heapam.h"
|
|
|
|
#include "access/htup.h"
|
|
|
|
#include "utils/syscache.h"
|
|
|
|
#include "utils/lsyscache.h"
|
|
|
|
#include "fmgr.h"
|
|
|
|
#include "utils/elog.h"
|
|
|
|
#include "utils/datum.h"
|
|
|
|
#include "utils/palloc.h"
|
|
|
|
|
|
|
|
#include "nodes/nodes.h"
|
|
|
|
#include "nodes/execnodes.h"
|
|
|
|
#include "nodes/pg_list.h"
|
|
|
|
#include "nodes/plannodes.h"
|
|
|
|
#include "nodes/parsenodes.h"
|
|
|
|
#include "nodes/primnodes.h"
|
|
|
|
#include "nodes/relation.h"
|
|
|
|
|
|
|
|
#include "catalog/pg_type.h"
|
|
|
|
#include "lib/stringinfo.h"
|
|
|
|
|
1998-05-10 01:46:35 +02:00
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
#include "../parse.h"
|
|
|
|
#endif
|
|
|
|
|
1997-09-08 04:41:22 +02:00
|
|
|
static void _outDatum(StringInfo str, Datum value, Oid type);
|
|
|
|
static void _outNode(StringInfo str, void *obj);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* _outIntList -
|
1997-09-07 07:04:48 +02:00
|
|
|
* converts a List of integers
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1996-11-10 04:06:38 +01:00
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outIntList(StringInfo str, List *list)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-14 09:11:17 +01:00
|
|
|
List *l;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
appendStringInfo(str, "(");
|
|
|
|
foreach(l, list)
|
|
|
|
{
|
1999-02-18 01:49:48 +01:00
|
|
|
appendStringInfo(str, " %d ", lfirsti(l));
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
appendStringInfo(str, ")");
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1997-12-05 00:20:32 +01:00
|
|
|
static void
|
|
|
|
_outCreateStmt(StringInfo str, CreateStmt *node)
|
|
|
|
{
|
1999-02-02 04:45:56 +01:00
|
|
|
appendStringInfo(str, " CREATE :relname %s ",
|
1998-12-18 15:45:09 +01:00
|
|
|
stringStringInfo(node->relname));
|
1999-02-02 04:45:56 +01:00
|
|
|
|
|
|
|
appendStringInfo(str, " :istemp %s ",
|
|
|
|
node->istemp ? "true" : "false");
|
|
|
|
|
|
|
|
appendStringInfo(str, " :columns ");
|
1997-12-05 00:20:32 +01:00
|
|
|
_outNode(str, node->tableElts);
|
1998-12-20 08:13:36 +01:00
|
|
|
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " :inhRelnames ");
|
1998-01-06 19:53:02 +01:00
|
|
|
_outNode(str, node->inhRelnames);
|
1998-12-20 08:13:36 +01:00
|
|
|
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " :constraints ");
|
1998-01-06 19:53:02 +01:00
|
|
|
_outNode(str, node->constraints);
|
1998-01-07 00:19:49 +01:00
|
|
|
}
|
1997-12-05 00:20:32 +01:00
|
|
|
|
|
|
|
static void
|
|
|
|
_outIndexStmt(StringInfo str, IndexStmt *node)
|
|
|
|
{
|
1998-12-14 09:11:17 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" INDEX :idxname %s :relname %s :accessMethod %s :indexParams ",
|
1998-12-18 15:45:09 +01:00
|
|
|
stringStringInfo(node->idxname),
|
|
|
|
stringStringInfo(node->relname),
|
|
|
|
stringStringInfo(node->accessMethod));
|
1997-12-05 00:20:32 +01:00
|
|
|
_outNode(str, node->indexParams);
|
1998-12-20 08:13:36 +01:00
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :withClause ");
|
|
|
|
_outNode(str, node->withClause);
|
1998-12-20 08:13:36 +01:00
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :whereClause ");
|
|
|
|
_outNode(str, node->whereClause);
|
1998-12-20 08:13:36 +01:00
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :rangetable ");
|
|
|
|
_outNode(str, node->rangetable);
|
1998-12-14 09:11:17 +01:00
|
|
|
|
|
|
|
appendStringInfo(str, " :lossy %s :unique %s ",
|
|
|
|
node->lossy ? "true" : "false",
|
|
|
|
node->unique ? "true" : "false");
|
1998-01-07 00:19:49 +01:00
|
|
|
}
|
1997-12-05 00:20:32 +01:00
|
|
|
|
1998-05-10 01:46:35 +02:00
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
static void
|
|
|
|
_outSelectStmt(StringInfo str, SelectStmt *node)
|
|
|
|
{
|
1998-12-14 09:11:17 +01:00
|
|
|
appendStringInfo(str, "SELECT :where ");
|
1998-05-10 01:46:35 +02:00
|
|
|
_outNode(str, node->whereClause);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_outFuncCall(StringInfo str, FuncCall *node)
|
|
|
|
{
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, "FUNCTION %s :args ", stringStringInfo(node->funcname));
|
1998-05-10 01:46:35 +02:00
|
|
|
_outNode(str, node->args);
|
|
|
|
}
|
1998-09-01 06:40:42 +02:00
|
|
|
|
1998-05-10 01:46:35 +02:00
|
|
|
#endif
|
|
|
|
|
1997-12-05 00:20:32 +01:00
|
|
|
static void
|
|
|
|
_outColumnDef(StringInfo str, ColumnDef *node)
|
|
|
|
{
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, " COLUMNDEF :colname %s :typename ",
|
|
|
|
stringStringInfo(node->colname));
|
1997-12-05 00:20:32 +01:00
|
|
|
_outNode(str, node->typename);
|
1998-12-14 09:11:17 +01:00
|
|
|
|
|
|
|
appendStringInfo(str, " :is_not_null %s :defval %s :constraints ",
|
1998-12-18 15:45:09 +01:00
|
|
|
node->is_not_null ? "true" : "false",
|
|
|
|
stringStringInfo(node->defval));
|
1998-01-06 19:53:02 +01:00
|
|
|
_outNode(str, node->constraints);
|
1998-01-07 00:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_outTypeName(StringInfo str, TypeName *node)
|
|
|
|
{
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" TYPENAME :name %s :timezone %s :setof %s typmod %d :arrayBounds ",
|
1998-12-18 15:45:09 +01:00
|
|
|
stringStringInfo(node->name),
|
1998-12-15 03:32:57 +01:00
|
|
|
node->timezone ? "true" : "false",
|
1998-12-15 03:24:15 +01:00
|
|
|
node->setof ? "true" : "false",
|
1998-12-15 03:32:57 +01:00
|
|
|
node->typmod);
|
1998-01-07 00:19:49 +01:00
|
|
|
|
|
|
|
appendStringInfo(str, " :arrayBounds ");
|
|
|
|
_outNode(str, node->arrayBounds);
|
|
|
|
}
|
1997-12-05 00:20:32 +01:00
|
|
|
|
|
|
|
static void
|
|
|
|
_outIndexElem(StringInfo str, IndexElem *node)
|
|
|
|
{
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, " INDEXELEM :name %s :args ",
|
|
|
|
stringStringInfo(node->name));
|
1998-01-06 19:53:02 +01:00
|
|
|
_outNode(str, node->args);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, " :class %s :typename ", stringStringInfo(node->class));
|
1998-08-26 07:22:58 +02:00
|
|
|
_outNode(str, node->typename);
|
1998-01-07 00:19:49 +01:00
|
|
|
}
|
1997-12-05 00:20:32 +01:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outQuery(StringInfo str, Query *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1999-01-21 17:08:55 +01:00
|
|
|
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str, " QUERY :command %d ", node->commandType);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1997-12-05 00:20:32 +01:00
|
|
|
if (node->utilityStmt)
|
|
|
|
{
|
|
|
|
switch (nodeTag(node->utilityStmt))
|
|
|
|
{
|
|
|
|
case T_CreateStmt:
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str, " :create %s ",
|
1998-12-18 15:45:09 +01:00
|
|
|
stringStringInfo(((CreateStmt *) (node->utilityStmt))->relname));
|
1997-12-05 00:20:32 +01:00
|
|
|
_outNode(str, node->utilityStmt);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_IndexStmt:
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str, " :index %s on %s ",
|
1998-12-18 15:45:09 +01:00
|
|
|
stringStringInfo(((IndexStmt *) (node->utilityStmt))->idxname),
|
|
|
|
stringStringInfo(((IndexStmt *) (node->utilityStmt))->relname));
|
1997-12-05 00:20:32 +01:00
|
|
|
_outNode(str, node->utilityStmt);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_NotifyStmt:
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str, " :utility %s ",
|
1998-12-18 15:45:09 +01:00
|
|
|
stringStringInfo(((NotifyStmt *) (node->utilityStmt))->relname));
|
1997-12-05 00:20:32 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :utility ? ");
|
1997-12-05 00:20:32 +01:00
|
|
|
}
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
else
|
1997-12-05 00:20:32 +01:00
|
|
|
{
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, " :utility <>");
|
1997-12-05 00:20:32 +01:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str,
|
1999-02-02 04:45:56 +01:00
|
|
|
" :resultRelation %d :into %s :isPortal %s :isBinary %s :isTemp %s :unionall %s ",
|
1998-12-15 03:24:15 +01:00
|
|
|
node->resultRelation,
|
1998-12-18 15:45:09 +01:00
|
|
|
stringStringInfo(node->into),
|
1998-12-15 03:24:15 +01:00
|
|
|
node->isPortal ? "true" : "false",
|
|
|
|
node->isBinary ? "true" : "false",
|
1999-02-02 04:45:56 +01:00
|
|
|
node->isTemp ? "true" : "false",
|
1998-12-15 03:24:15 +01:00
|
|
|
node->unionall ? "true" : "false");
|
|
|
|
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, " :unique %s :sortClause ",
|
|
|
|
stringStringInfo(node->uniqueFlag));
|
1998-01-06 19:53:02 +01:00
|
|
|
_outNode(str, node->sortClause);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :rtable ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->rtable);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :targetlist ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->targetList);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :qual ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->qual);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :groupClause ");
|
|
|
|
_outNode(str, node->groupClause);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :havingQual ");
|
1998-02-26 05:46:47 +01:00
|
|
|
_outNode(str, node->havingQual);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
|
|
|
appendStringInfo(str, " :hasAggs %s :hasSubLinks %s :unionClause ",
|
|
|
|
node->hasAggs ? "true" : "false",
|
|
|
|
node->hasSubLinks ? "true" : "false");
|
1998-02-26 05:46:47 +01:00
|
|
|
_outNode(str, node->unionClause);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
Hi!
INTERSECT and EXCEPT is available for postgresql-v6.4!
The patch against v6.4 is included at the end of the current text
(in uuencoded form!)
I also included the text of my Master's Thesis. (a postscript
version). I hope that you find something of it useful and would be
happy if parts of it find their way into the PostgreSQL documentation
project (If so, tell me, then I send the sources of the document!)
The contents of the document are:
-) The first chapter might be of less interest as it gives only an
overview on SQL.
-) The second chapter gives a description on much of PostgreSQL's
features (like user defined types etc. and how to use these features)
-) The third chapter starts with an overview of PostgreSQL's internal
structure with focus on the stages a query has to pass (i.e. parser,
planner/optimizer, executor). Then a detailed description of the
implementation of the Having clause and the Intersect/Except logic is
given.
Originally I worked on v6.3.2 but never found time enough to prepare
and post a patch. Now I applied the changes to v6.4 to get Intersect
and Except working with the new version. Chapter 3 of my documentation
deals with the changes against v6.3.2, so keep that in mind when
comparing the parts of the code printed there with the patched sources
of v6.4.
Here are some remarks on the patch. There are some things that have
still to be done but at the moment I don't have time to do them
myself. (I'm doing my military service at the moment) Sorry for that
:-(
-) I used a rewrite technique for the implementation of the Except/Intersect
logic which rewrites the query to a semantically equivalent query before
it is handed to the rewrite system (for views, rules etc.), planner,
executor etc.
-) In v6.3.2 the types of the attributes of two select statements
connected by the UNION keyword had to match 100%. In v6.4 the types
only need to be familiar (i.e. int and float can be mixed). Since this
feature did not exist when I worked on Intersect/Except it
does not work correctly for Except/Intersect queries WHEN USED IN
COMBINATION WITH UNIONS! (i.e. sometimes the wrong type is used for the
resulting table. This is because until now the types of the attributes of
the first select statement have been used for the resulting table.
When Intersects and/or Excepts are used in combination with Unions it
might happen, that the first select statement of the original query
appears at another position in the query which will be executed. The reason
for this is the technique used for the implementation of
Except/Intersect which does a query rewrite!)
NOTE: It is NOT broken for pure UNION queries and pure INTERSECT/EXCEPT
queries!!!
-) I had to add the field intersect_clause to some data structures
but did not find time to implement printfuncs for the new field.
This does NOT break the debug modes but when an Except/Intersect
is used the query debug output will be the already rewritten query.
-) Massive changes to the grammar rules for SELECT and INSERT statements
have been necessary (see comments in gram.y and documentation for
deatails) in order to be able to use mixed queries like
(SELECT ... UNION (SELECT ... EXCEPT SELECT)) INTERSECT SELECT...;
-) When using UNION/EXCEPT/INTERSECT you will get:
NOTICE: equal: "Don't know if nodes of type xxx are equal".
I did not have time to add comparsion support for all the needed nodes,
but the default behaviour of the function equal met my requirements.
I did not dare to supress this message!
That's the reason why the regression test for union will fail: These
messages are also included in the union.out file!
-) Somebody of you changed the union_planner() function for v6.4
(I copied the targetlist to new_tlist and that was removed and
replaced by a cleanup of the original targetlist). These chnages
violated some having queries executed against views so I changed
it back again. I did not have time to examine the differences between the
two versions but now it works :-)
If you want to find out, try the file queries/view_having.sql on
both versions and compare the results . Two queries won't produce a
correct result with your version.
regards
Stefan
1999-01-18 01:10:17 +01:00
|
|
|
appendStringInfo(str, " :intersectClause ");
|
|
|
|
_outNode(str, node->intersectClause);
|
|
|
|
|
1998-10-22 15:52:24 +02:00
|
|
|
appendStringInfo(str, " :limitOffset ");
|
|
|
|
_outNode(str, node->limitOffset);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
1998-10-22 15:52:24 +02:00
|
|
|
appendStringInfo(str, " :limitCount ");
|
|
|
|
_outNode(str, node->limitCount);
|
1999-01-21 17:08:55 +01:00
|
|
|
|
|
|
|
appendStringInfo(str, " :rowMark ");
|
|
|
|
_outNode(str, node->rowMark);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-01-07 00:19:49 +01:00
|
|
|
_outSortClause(StringInfo str, SortClause *node)
|
1998-01-06 19:53:02 +01:00
|
|
|
{
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str, " SORTCLAUSE :resdom ");
|
1998-01-07 00:19:49 +01:00
|
|
|
_outNode(str, node->resdom);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
|
|
|
appendStringInfo(str, " :opoid %u ", node->opoid);
|
1998-01-07 00:19:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_outGroupClause(StringInfo str, GroupClause *node)
|
|
|
|
{
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str, " GROUPCLAUSE :entry ");
|
1998-01-07 00:19:49 +01:00
|
|
|
_outNode(str, node->entry);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
|
|
|
appendStringInfo(str, " :grpOpoid %u ", node->grpOpoid);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* print the basic stuff of all nodes that inherit from Plan
|
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outPlanInfo(StringInfo str, Plan *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
":cost %g :size %d :width %d :state %s :qptargetlist ",
|
|
|
|
node->cost,
|
|
|
|
node->plan_size,
|
|
|
|
node->plan_width,
|
|
|
|
node->state ? "not-NULL" : "<>");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->targetlist);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :qpqual ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->qual);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :lefttree ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->lefttree);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :righttree ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->righttree);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
1998-02-13 04:27:47 +01:00
|
|
|
appendStringInfo(str, " :extprm ");
|
|
|
|
_outIntList(str, node->extParam);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
1998-02-13 04:27:47 +01:00
|
|
|
appendStringInfo(str, " :locprm ");
|
|
|
|
_outIntList(str, node->locParam);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
1998-02-13 04:27:47 +01:00
|
|
|
appendStringInfo(str, " :initplan ");
|
|
|
|
_outNode(str, node->initPlan);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
1998-12-15 03:32:57 +01:00
|
|
|
appendStringInfo(str, " :nprm %d ", node->nParamExec);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Stuff from plannodes.h
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outPlan(StringInfo str, Plan *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " PLAN ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outPlanInfo(str, (Plan *) node);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outResult(StringInfo str, Result *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " RESULT ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outPlanInfo(str, (Plan *) node);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :resconstantqual ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->resconstantqual);
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Append is a subclass of Plan.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 22:59:27 +02:00
|
|
|
_outAppend(StringInfo str, Append *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " APPEND ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outPlanInfo(str, (Plan *) node);
|
|
|
|
|
1998-07-15 16:54:39 +02:00
|
|
|
appendStringInfo(str, " :appendplans ");
|
|
|
|
_outNode(str, node->appendplans);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-07-15 16:54:39 +02:00
|
|
|
appendStringInfo(str, " :unionrtables ");
|
|
|
|
_outNode(str, node->unionrtables);
|
1998-01-06 19:53:02 +01:00
|
|
|
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" :inheritrelid %d :inheritrtable ",
|
|
|
|
node->inheritrelid);
|
1998-07-15 16:54:39 +02:00
|
|
|
_outNode(str, node->inheritrtable);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Join is a subclass of Plan
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outJoin(StringInfo str, Join *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " JOIN ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outPlanInfo(str, (Plan *) node);
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* NestLoop is a subclass of Join
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outNestLoop(StringInfo str, NestLoop *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " NESTLOOP ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outPlanInfo(str, (Plan *) node);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* MergeJoin is a subclass of Join
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outMergeJoin(StringInfo str, MergeJoin *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " MERGEJOIN ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outPlanInfo(str, (Plan *) node);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :mergeclauses ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->mergeclauses);
|
|
|
|
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" :mergejoinop %u :mergerightorder %u :mergeleftorder %u ",
|
|
|
|
node->mergejoinop,
|
|
|
|
node->mergerightorder,
|
|
|
|
node->mergeleftorder);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* HashJoin is a subclass of Join.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outHashJoin(StringInfo str, HashJoin *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " HASHJOIN ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outPlanInfo(str, (Plan *) node);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :hashclauses ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->hashclauses);
|
|
|
|
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" :hashjoinop %u :hashjointable 0x%x :hashjointablekey %d ",
|
|
|
|
node->hashjoinop,
|
|
|
|
(int) node->hashjointable,
|
|
|
|
node->hashjointablekey);
|
|
|
|
|
|
|
|
appendStringInfo(str,
|
|
|
|
" :hashjointablesize %d :hashdone %d ",
|
|
|
|
node->hashjointablesize,
|
|
|
|
node->hashdone);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1998-02-13 04:27:47 +01:00
|
|
|
static void
|
|
|
|
_outSubPlan(StringInfo str, SubPlan *node)
|
|
|
|
{
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str, " SUBPLAN :plan ");
|
1998-02-13 04:27:47 +01:00
|
|
|
_outNode(str, node->plan);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
|
|
|
appendStringInfo(str, " :planid %u :rtable ", node->plan_id);
|
1998-02-13 04:27:47 +01:00
|
|
|
_outNode(str, node->rtable);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
1998-02-13 04:27:47 +01:00
|
|
|
appendStringInfo(str, " :setprm ");
|
1998-02-26 05:46:47 +01:00
|
|
|
_outIntList(str, node->setParam);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
1998-02-13 04:27:47 +01:00
|
|
|
appendStringInfo(str, " :parprm ");
|
1998-02-26 05:46:47 +01:00
|
|
|
_outIntList(str, node->parParam);
|
1998-12-15 03:24:15 +01:00
|
|
|
|
1998-02-13 04:27:47 +01:00
|
|
|
appendStringInfo(str, " :slink ");
|
|
|
|
_outNode(str, node->sublink);
|
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Scan is a subclass of Node
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outScan(StringInfo str, Scan *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " SCAN ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outPlanInfo(str, (Plan *) node);
|
|
|
|
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str, " :scanrelid %d ", node->scanrelid);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* SeqScan is a subclass of Scan
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outSeqScan(StringInfo str, SeqScan *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " SEQSCAN ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outPlanInfo(str, (Plan *) node);
|
|
|
|
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str, " :scanrelid %d ", node->scanrelid);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* IndexScan is a subclass of Scan
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outIndexScan(StringInfo str, IndexScan *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " INDEXSCAN ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outPlanInfo(str, (Plan *) node);
|
|
|
|
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str, " :scanrelid %d :indxid ", node->scan.scanrelid);
|
1997-09-07 07:04:48 +02:00
|
|
|
_outIntList(str, node->indxid);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :indxqual ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->indxqual);
|
|
|
|
|
1998-11-22 11:48:45 +01:00
|
|
|
appendStringInfo(str, " :indxqualorig ");
|
|
|
|
_outNode(str, node->indxqualorig);
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1999-02-09 18:03:14 +01:00
|
|
|
* Noname is a subclass of Plan
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1999-02-09 18:03:14 +01:00
|
|
|
_outNoname(StringInfo str, Noname *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1999-02-09 18:03:14 +01:00
|
|
|
appendStringInfo(str, " NONAME ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outPlanInfo(str, (Plan *) node);
|
|
|
|
|
1999-02-09 18:03:14 +01:00
|
|
|
appendStringInfo(str, " :nonameid %u :keycount %d ",
|
|
|
|
node->nonameid,
|
1998-12-15 03:24:15 +01:00
|
|
|
node->keycount);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1999-02-09 18:03:14 +01:00
|
|
|
* Sort is a subclass of Noname
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outSort(StringInfo str, Sort *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " SORT ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outPlanInfo(str, (Plan *) node);
|
|
|
|
|
1999-02-09 18:03:14 +01:00
|
|
|
appendStringInfo(str, " :nonameid %u :keycount %d ",
|
|
|
|
node->nonameid,
|
1998-12-15 03:24:15 +01:00
|
|
|
node->keycount);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1997-09-08 22:59:27 +02:00
|
|
|
_outAgg(StringInfo str, Agg *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " AGG ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outPlanInfo(str, (Plan *) node);
|
|
|
|
|
1998-01-15 20:00:16 +01:00
|
|
|
appendStringInfo(str, " :aggs ");
|
|
|
|
_outNode(str, node->aggs);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outGroup(StringInfo str, Group *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " GRP ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outPlanInfo(str, (Plan *) node);
|
|
|
|
|
|
|
|
/* the actual Group fields */
|
1998-12-15 03:32:57 +01:00
|
|
|
appendStringInfo(str, " :numCols %d :tuplePerGroup %s ",
|
1998-12-15 03:24:15 +01:00
|
|
|
node->numCols,
|
|
|
|
node->tuplePerGroup ? "true" : "false");
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
1999-02-09 18:03:14 +01:00
|
|
|
* For some reason, unique is a subclass of Noname.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outUnique(StringInfo str, Unique *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " UNIQUE ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outPlanInfo(str, (Plan *) node);
|
|
|
|
|
1999-02-09 18:03:14 +01:00
|
|
|
appendStringInfo(str, " :nonameid %u :keycount %d ",
|
|
|
|
node->nonameid,
|
1998-12-15 03:24:15 +01:00
|
|
|
node->keycount);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
1999-02-09 18:03:14 +01:00
|
|
|
* Hash is a subclass of Noname
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outHash(StringInfo str, Hash *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " HASH ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outPlanInfo(str, (Plan *) node);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :hashkey ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->hashkey);
|
|
|
|
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str, " :hashtable 0x%x :hashtablekey %d :hashtablesize %d ",
|
|
|
|
(int) node->hashtable,
|
|
|
|
node->hashtablekey,
|
|
|
|
node->hashtablesize);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outTee(StringInfo str, Tee *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-04-27 04:58:07 +02:00
|
|
|
appendStringInfo(str, " TEE ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outPlanInfo(str, (Plan *) node);
|
|
|
|
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str, " :leftParent %X :rightParent %X ",
|
|
|
|
(int) node->leftParent,
|
|
|
|
(int) node->rightParent);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :rtentries ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->rtentries);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Stuff from primnodes.h.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Resdom is a subclass of Node
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outResdom(StringInfo str, Resdom *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str, " RESDOM :resno %d :restype %u :restypmod %d ",
|
|
|
|
node->resno,
|
|
|
|
node->restype,
|
|
|
|
node->restypmod);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str, " :resname \"%s\" :reskey %d :reskeyop %u :resjunk %d",
|
1998-12-18 15:45:09 +01:00
|
|
|
stringStringInfo(node->resname),
|
1998-12-15 03:24:15 +01:00
|
|
|
node->reskey,
|
|
|
|
node->reskeyop,
|
|
|
|
node->resjunk);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outFjoin(StringInfo str, Fjoin *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int i;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str, " FJOIN :initialized %s :nNodes %d ",
|
|
|
|
node->fj_initialized ? "true" : "false",
|
|
|
|
node->fj_nNodes);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
appendStringInfo(str, " :innerNode ");
|
|
|
|
_outNode(str, node->fj_innerNode);
|
|
|
|
|
1998-12-15 03:24:15 +01:00
|
|
|
appendStringInfo(str, " :results @ 0x%x :alwaysdone",
|
|
|
|
(int) node->fj_results);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
for (i = 0; i < node->fj_nNodes; i++)
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, (node->fj_alwaysDone[i]) ? "true" : "false");
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Expr is a subclass of Node
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outExpr(StringInfo str, Expr *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
char *opstr = NULL;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str, " EXPR :typeOid %u ",
|
|
|
|
node->typeOid);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
switch (node->opType)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
case OP_EXPR:
|
|
|
|
opstr = "op";
|
|
|
|
break;
|
|
|
|
case FUNC_EXPR:
|
|
|
|
opstr = "func";
|
|
|
|
break;
|
|
|
|
case OR_EXPR:
|
|
|
|
opstr = "or";
|
|
|
|
break;
|
|
|
|
case AND_EXPR:
|
|
|
|
opstr = "and";
|
|
|
|
break;
|
|
|
|
case NOT_EXPR:
|
|
|
|
opstr = "not";
|
|
|
|
break;
|
1998-02-13 04:27:47 +01:00
|
|
|
case SUBPLAN_EXPR:
|
|
|
|
opstr = "subp";
|
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, " :opType %s :oper ", stringStringInfo(opstr));
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->oper);
|
1998-12-15 05:00:46 +01:00
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :args ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->args);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Var is a subclass of Expr
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outVar(StringInfo str, Var *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
1998-12-17 14:09:52 +01:00
|
|
|
" VAR :varno %d :varattno %d :vartype %u :vartypmod %d ",
|
1998-12-15 05:00:46 +01:00
|
|
|
node->varno,
|
|
|
|
node->varattno,
|
|
|
|
node->vartype,
|
|
|
|
node->vartypmod);
|
|
|
|
|
|
|
|
appendStringInfo(str, " :varlevelsup %u :varnoold %d :varoattno %d" ,
|
|
|
|
node->varlevelsup,
|
|
|
|
node->varnoold,
|
|
|
|
node->varoattno);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Const is a subclass of Expr
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outConst(StringInfo str, Const *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" CONST :consttype %u :constlen %d :constisnull %s :constvalue ",
|
|
|
|
node->consttype,
|
|
|
|
node->constlen,
|
|
|
|
node->constisnull ? "true" : "false");
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
if (node->constisnull)
|
1998-01-07 16:32:47 +01:00
|
|
|
appendStringInfo(str, "<>");
|
1997-09-07 07:04:48 +02:00
|
|
|
else
|
|
|
|
_outDatum(str, node->constvalue, node->consttype);
|
1998-12-15 05:00:46 +01:00
|
|
|
|
|
|
|
appendStringInfo(str, " :constbyval %s ",
|
|
|
|
node->constbyval ? "true" : "false");
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1999-01-24 01:28:37 +01:00
|
|
|
* Aggref
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1999-01-24 01:28:37 +01:00
|
|
|
_outAggref(StringInfo str, Aggref *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" AGGREG :aggname %s :basetype %u :aggtype %u :target ",
|
1998-12-18 15:45:09 +01:00
|
|
|
stringStringInfo(node->aggname),
|
1998-12-15 05:00:46 +01:00
|
|
|
node->basetype,
|
|
|
|
node->aggtype);
|
1998-01-06 19:53:02 +01:00
|
|
|
_outNode(str, node->target);
|
1998-12-15 05:00:46 +01:00
|
|
|
|
|
|
|
appendStringInfo(str, ":aggno %d :usenulls %s",
|
|
|
|
node->aggno,
|
|
|
|
node->usenulls ? "true" : "false");
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1998-01-17 05:53:46 +01:00
|
|
|
/*
|
|
|
|
* SubLink
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
_outSubLink(StringInfo str, SubLink *node)
|
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" SUBLINK :subLinkType %d :useor %s :lefthand ",
|
|
|
|
node->subLinkType,
|
|
|
|
node->useor ? "true" : "false");
|
1998-01-17 05:53:46 +01:00
|
|
|
_outNode(str, node->lefthand);
|
1998-12-15 05:00:46 +01:00
|
|
|
|
1998-01-17 05:53:46 +01:00
|
|
|
appendStringInfo(str, " :oper ");
|
1998-01-20 06:05:08 +01:00
|
|
|
_outNode(str, node->oper);
|
1998-12-15 05:00:46 +01:00
|
|
|
|
1998-01-17 05:53:46 +01:00
|
|
|
appendStringInfo(str, " :subselect ");
|
|
|
|
_outNode(str, node->subselect);
|
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Array is a subclass of Expr
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 22:59:27 +02:00
|
|
|
_outArray(StringInfo str, Array *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int i;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" ARRAY :arrayelemtype %u :arrayelemlength %d :arrayelembyval %c ",
|
|
|
|
node->arrayelemtype,
|
|
|
|
node->arrayelemlength,
|
|
|
|
node->arrayelembyval ? 't' : 'f');
|
|
|
|
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, " :arrayndim %d :arraylow ", node->arrayndim);
|
1997-09-07 07:04:48 +02:00
|
|
|
for (i = 0; i < node->arrayndim; i++)
|
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str, " %d ", node->arraylow.indx[i]);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :arrayhigh ");
|
1997-09-07 07:04:48 +02:00
|
|
|
for (i = 0; i < node->arrayndim; i++)
|
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str, " %d ", node->arrayhigh.indx[i]);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str, " :arraylen %d ", node->arraylen);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* ArrayRef is a subclass of Expr
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 22:59:27 +02:00
|
|
|
_outArrayRef(StringInfo str, ArrayRef *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" ARRAYREF :refelemtype %u :refattrlength $d :refelemlength %d ",
|
|
|
|
node->refelemtype,
|
|
|
|
node->refattrlength,
|
|
|
|
node->refelemlength);
|
|
|
|
|
|
|
|
appendStringInfo(str, " :refelembyval %c :refupperindex ",
|
|
|
|
node->refelembyval ? 't' : 'f');
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->refupperindexpr);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :reflowerindex ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->reflowerindexpr);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :refexpr ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->refexpr);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :refassgnexpr ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->refassgnexpr);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Func is a subclass of Expr
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outFunc(StringInfo str, Func *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" FUNC :funcid %u :functype %u :funcisindex %s :funcsize %d ",
|
|
|
|
node->funcid,
|
|
|
|
node->functype,
|
|
|
|
node->funcisindex ? "true" : "false",
|
|
|
|
node->funcsize);
|
|
|
|
|
|
|
|
appendStringInfo(str, " :func_fcache @ 0x%x :func_tlist ",
|
|
|
|
(int) node->func_fcache);
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->func_tlist);
|
|
|
|
|
|
|
|
appendStringInfo(str, " :func_planlist ");
|
|
|
|
_outNode(str, node->func_planlist);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Oper is a subclass of Expr
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outOper(StringInfo str, Oper *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" OPER :opno %u :opid %u :opresulttype %u ",
|
|
|
|
node->opno,
|
|
|
|
node->opid,
|
|
|
|
node->opresulttype);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Param is a subclass of Expr
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outParam(StringInfo str, Param *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" PARAM :paramkind %d :paramid %d :paramname %s :paramtype %u ",
|
|
|
|
node->paramkind,
|
|
|
|
node->paramid,
|
1998-12-18 15:45:09 +01:00
|
|
|
stringStringInfo(node->paramname),
|
1998-12-15 05:00:46 +01:00
|
|
|
node->paramtype);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
appendStringInfo(str, " :param_tlist ");
|
|
|
|
_outNode(str, node->param_tlist);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Stuff from execnodes.h
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* EState is a subclass of Node.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outEState(StringInfo str, EState *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" ESTATE :direction %d :range_table ",
|
|
|
|
node->es_direction);
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->es_range_table);
|
|
|
|
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str, " :result_relation_info @ 0x%x ",
|
1997-09-07 07:04:48 +02:00
|
|
|
(int) (node->es_result_relation_info));
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Stuff from relation.h
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1999-02-09 04:51:42 +01:00
|
|
|
_outRelOptInfo(StringInfo str, RelOptInfo *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str, " RELOPTINFO :relids ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outIntList(str, node->relids);
|
|
|
|
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" :indexed %s :pages %u :tuples %u :size %u :width %u :targetlist ",
|
|
|
|
node->indexed ? "true" : "false",
|
|
|
|
node->pages,
|
|
|
|
node->tuples,
|
|
|
|
node->size,
|
|
|
|
node->width);
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->targetlist);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :pathlist ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->pathlist);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Not sure if these are nodes or not. They're declared as struct
|
|
|
|
* Path *. Since i don't know, i'll just print the addresses for now.
|
|
|
|
* This can be changed later, if necessary.
|
|
|
|
*/
|
|
|
|
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
1999-02-12 06:57:08 +01:00
|
|
|
" :cheapestpath @ 0x%x :pruneable %s :restrictinfo ",
|
1998-12-15 05:00:46 +01:00
|
|
|
(int) node->cheapestpath,
|
|
|
|
node->pruneable ? "true" : "false");
|
1999-02-03 21:15:53 +01:00
|
|
|
_outNode(str, node->restrictinfo);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :joininfo ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->joininfo);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :innerjoin ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->innerjoin);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* TargetEntry is a subclass of Node.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outTargetEntry(StringInfo str, TargetEntry *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str, " TARGETENTRY :resdom ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->resdom);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :expr ");
|
|
|
|
_outNode(str, node->expr);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outRangeTblEntry(StringInfo str, RangeTblEntry *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" RTE :relname %s :refname %s :relid %u :inh %s :inFromCl %s :skipAcl %s",
|
1998-12-18 15:45:09 +01:00
|
|
|
stringStringInfo(node->relname),
|
|
|
|
stringStringInfo(node->refname),
|
1998-12-15 05:00:46 +01:00
|
|
|
node->relid,
|
|
|
|
node->inh ? "true" : "false",
|
|
|
|
node->inFromCl ? "true" : "false",
|
|
|
|
node->skipAcl ? "true" : "false");
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1999-01-21 17:08:55 +01:00
|
|
|
static void
|
|
|
|
_outRowMark(StringInfo str, RowMark *node)
|
|
|
|
{
|
|
|
|
appendStringInfo(str, " ROWMARK :rti %u :info %u", node->rti, node->info);
|
|
|
|
}
|
|
|
|
|
1999-02-09 04:51:42 +01:00
|
|
|
/*
|
|
|
|
* Path is a subclass of Node.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
_outPathOrder(StringInfo str, PathOrder *node)
|
|
|
|
{
|
|
|
|
appendStringInfo(str, " PATHORDER :ordtype %d ",
|
|
|
|
node->ordtype);
|
|
|
|
if (node->ordtype == SORTOP_ORDER)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
appendStringInfo(str, " :sortop ");
|
|
|
|
if (node->ord.sortop == NULL)
|
|
|
|
appendStringInfo(str, "<>");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i=0; node->ord.sortop[i] != 0; i++)
|
|
|
|
appendStringInfo(str, " %d ", node->ord.sortop[i]);
|
|
|
|
appendStringInfo(str, " %d ", 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
appendStringInfo(str, " :merge ");
|
|
|
|
_outNode(str,node->ord.merge);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Path is a subclass of Node.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outPath(StringInfo str, Path *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1999-02-10 04:52:54 +01:00
|
|
|
appendStringInfo(str, " PATH :pathtype %d :cost %f :pathkeys ",
|
1998-12-15 05:00:46 +01:00
|
|
|
node->pathtype,
|
|
|
|
node->path_cost);
|
1999-02-10 04:52:54 +01:00
|
|
|
_outNode(str, node->pathkeys);
|
1999-02-09 04:51:42 +01:00
|
|
|
|
1999-02-11 15:59:09 +01:00
|
|
|
appendStringInfo(str, " :pathorder ");
|
|
|
|
_outNode(str, node->pathorder);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* IndexPath is a subclass of Path.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outIndexPath(StringInfo str, IndexPath *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
1999-02-10 04:52:54 +01:00
|
|
|
" INDEXPATH :pathtype %d :cost %f :pathkeys ",
|
1998-12-15 05:00:46 +01:00
|
|
|
node->path.pathtype,
|
|
|
|
node->path.path_cost);
|
1999-02-10 04:52:54 +01:00
|
|
|
_outNode(str, node->path.pathkeys);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-02-11 15:59:09 +01:00
|
|
|
appendStringInfo(str, " :pathorder ");
|
|
|
|
_outNode(str, node->path.pathorder);
|
1999-02-09 04:51:42 +01:00
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :indexid ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outIntList(str, node->indexid);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :indexqual ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->indexqual);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1999-02-12 07:43:53 +01:00
|
|
|
* NestPath is a subclass of Path
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1999-02-12 07:43:53 +01:00
|
|
|
_outNestPath(StringInfo str, NestPath *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
1999-02-12 07:43:53 +01:00
|
|
|
" NESTPATH :pathtype %d :cost %f :pathkeys ",
|
1998-12-15 05:00:46 +01:00
|
|
|
node->path.pathtype,
|
|
|
|
node->path.path_cost);
|
1999-02-10 04:52:54 +01:00
|
|
|
_outNode(str, node->path.pathkeys);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-02-11 15:59:09 +01:00
|
|
|
appendStringInfo(str, " :pathorder ");
|
|
|
|
_outNode(str, node->path.pathorder);
|
1999-02-09 04:51:42 +01:00
|
|
|
|
1999-02-03 21:15:53 +01:00
|
|
|
appendStringInfo(str, " :pathinfo ");
|
|
|
|
_outNode(str, node->pathinfo);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Not sure if these are nodes; they're declared as "struct path *".
|
|
|
|
* For now, i'll just print the addresses.
|
|
|
|
*/
|
|
|
|
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x :outjoincost %f :joinid ",
|
|
|
|
(int) node->outerjoinpath,
|
|
|
|
(int) node->innerjoinpath,
|
|
|
|
node->path.outerjoincost);
|
1997-09-07 07:04:48 +02:00
|
|
|
_outIntList(str, node->path.joinid);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1999-02-12 07:43:53 +01:00
|
|
|
* MergePath is a subclass of NestPath.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outMergePath(StringInfo str, MergePath *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
1999-02-10 04:52:54 +01:00
|
|
|
" MERGEPATH :pathtype %d :cost %f :pathkeys ",
|
1998-12-15 05:00:46 +01:00
|
|
|
node->jpath.path.pathtype,
|
|
|
|
node->jpath.path.path_cost);
|
1999-02-10 04:52:54 +01:00
|
|
|
_outNode(str, node->jpath.path.pathkeys);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-02-11 15:59:09 +01:00
|
|
|
appendStringInfo(str, " :pathorder ");
|
|
|
|
_outNode(str, node->jpath.path.pathorder);
|
1999-02-09 04:51:42 +01:00
|
|
|
|
1999-02-03 21:15:53 +01:00
|
|
|
appendStringInfo(str, " :pathinfo ");
|
|
|
|
_outNode(str, node->jpath.pathinfo);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Not sure if these are nodes; they're declared as "struct path *".
|
|
|
|
* For now, i'll just print the addresses.
|
|
|
|
*/
|
|
|
|
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x :outerjoincost %f :joinid ",
|
|
|
|
(int) node->jpath.outerjoinpath,
|
|
|
|
(int) node->jpath.innerjoinpath,
|
|
|
|
(int) node->jpath.path.outerjoincost);
|
1997-09-07 07:04:48 +02:00
|
|
|
_outIntList(str, node->jpath.path.joinid);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :path_mergeclauses ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->path_mergeclauses);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :outersortkeys ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->outersortkeys);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :innersortkeys ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->innersortkeys);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1999-02-12 07:43:53 +01:00
|
|
|
* HashPath is a subclass of NestPath.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outHashPath(StringInfo str, HashPath *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
1999-02-10 04:52:54 +01:00
|
|
|
" HASHPATH :pathtype %d :cost %f :pathkeys ",
|
1998-12-15 05:00:46 +01:00
|
|
|
node->jpath.path.pathtype,
|
|
|
|
node->jpath.path.path_cost);
|
1999-02-10 04:52:54 +01:00
|
|
|
_outNode(str, node->jpath.path.pathkeys);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-02-11 15:59:09 +01:00
|
|
|
appendStringInfo(str, " :pathorder ");
|
|
|
|
_outNode(str, node->jpath.path.pathorder);
|
1999-02-09 04:51:42 +01:00
|
|
|
|
1999-02-03 21:15:53 +01:00
|
|
|
appendStringInfo(str, " :pathinfo ");
|
|
|
|
_outNode(str, node->jpath.pathinfo);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Not sure if these are nodes; they're declared as "struct path *".
|
|
|
|
* For now, i'll just print the addresses.
|
|
|
|
*/
|
|
|
|
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" :outerjoinpath @ 0x%x :innerjoinpath @ 0x%x :outerjoincost %f :joinid ",
|
|
|
|
(int) node->jpath.outerjoinpath,
|
|
|
|
(int) node->jpath.innerjoinpath,
|
|
|
|
node->jpath.path.outerjoincost);
|
1997-09-07 07:04:48 +02:00
|
|
|
_outIntList(str, node->jpath.path.joinid);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :path_hashclauses ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->path_hashclauses);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :outerhashkeys ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->outerhashkeys);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :innerhashkeys ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->innerhashkeys);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* OrderKey is a subclass of Node.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outOrderKey(StringInfo str, OrderKey *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-15 05:00:46 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" ORDERKEY :attribute_number %d :array_index %d ",
|
|
|
|
node->attribute_number,
|
|
|
|
node->array_index);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* JoinKey is a subclass of Node.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outJoinKey(StringInfo str, JoinKey *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, " JOINKEY :outer ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->outer);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :inner ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->inner);
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* MergeOrder is a subclass of Node.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outMergeOrder(StringInfo str, MergeOrder *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" MERGEORDER :join_operator %d :left_operator %d :right_operator %d ",
|
|
|
|
node->join_operator,
|
|
|
|
node->left_operator,
|
|
|
|
node->right_operator);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" :left_type %d :right_type %d ",
|
|
|
|
node->left_type,
|
|
|
|
node->right_type);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1999-02-03 21:15:53 +01:00
|
|
|
* RestrictInfo is a subclass of Node.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1999-02-14 00:22:53 +01:00
|
|
|
_outRestrictInfo(StringInfo str, RestrictInfo *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1999-02-05 20:59:31 +01:00
|
|
|
appendStringInfo(str, " RESTRICTINFO :clause ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->clause);
|
|
|
|
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" :selectivity %f :notclause %s :indexids ",
|
|
|
|
node->selectivity,
|
|
|
|
node->notclause ? "true" : "false");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->indexids);
|
|
|
|
|
1998-08-04 18:44:31 +02:00
|
|
|
appendStringInfo(str, " :mergejoinorder ");
|
|
|
|
_outNode(str, node->mergejoinorder);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, " :hashjoinoperator %u ", node->hashjoinoperator);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* JoinMethod is a subclass of Node.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outJoinMethod(StringInfo str, JoinMethod *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, " JOINMETHOD :jmkeys ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->jmkeys);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :clauses ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->clauses);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1999-02-04 02:47:02 +01:00
|
|
|
* HashInfo is a subclass of JoinMethod.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1999-02-04 02:47:02 +01:00
|
|
|
_outHashInfo(StringInfo str, HashInfo *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, " HASHINFO :hashop %u :jmkeys ", node->hashop);
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->jmethod.jmkeys);
|
|
|
|
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, " :clauses ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->jmethod.clauses);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1998-09-01 05:29:17 +02:00
|
|
|
* JoinInfo is a subclass of Node.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
1999-02-15 04:22:37 +01:00
|
|
|
_outJoinInfo(StringInfo str, JoinInfo *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1999-02-18 01:49:48 +01:00
|
|
|
appendStringInfo(str, " JINFO :unjoined_relids ");
|
|
|
|
_outIntList(str, node->unjoined_relids);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-02-03 21:15:53 +01:00
|
|
|
appendStringInfo(str, " :jinfo_restrictinfo ");
|
|
|
|
_outNode(str, node->jinfo_restrictinfo);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, " :mergejoinable %s :hashjoinable %s ",
|
|
|
|
node->mergejoinable ? "true" : "false",
|
|
|
|
node->hashjoinable ? "true" : "false");
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Print the value of a Datum given its type.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
_outDatum(StringInfo str, Datum value, Oid type)
|
|
|
|
{
|
1998-12-20 08:13:36 +01:00
|
|
|
char *s;
|
1997-09-08 04:41:22 +02:00
|
|
|
Size length,
|
1998-12-20 08:13:36 +01:00
|
|
|
typeLength;
|
1997-09-08 04:41:22 +02:00
|
|
|
bool byValue;
|
|
|
|
int i;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* find some information about the type and the "real" length of the
|
|
|
|
* datum.
|
|
|
|
*/
|
|
|
|
byValue = get_typbyval(type);
|
|
|
|
typeLength = get_typlen(type);
|
|
|
|
length = datumGetSize(value, type, byValue, typeLength);
|
|
|
|
|
|
|
|
if (byValue)
|
|
|
|
{
|
|
|
|
s = (char *) (&value);
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, " %d [ ", length);
|
1997-09-07 07:04:48 +02:00
|
|
|
for (i = 0; i < sizeof(Datum); i++)
|
|
|
|
{
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, " %d ", (int) (s[i]));
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, "] ");
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
else
|
|
|
|
{ /* !byValue */
|
|
|
|
s = (char *) DatumGetPointer(value);
|
|
|
|
if (!PointerIsValid(s))
|
|
|
|
{
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, " 0 [ ] ");
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* length is unsigned - very bad to do < comparison to -1
|
|
|
|
* without casting it to int first!! -mer 8 Jan 1991
|
|
|
|
*/
|
|
|
|
if (((int) length) <= -1)
|
|
|
|
length = VARSIZE(s);
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, " %d [ ", length);
|
1997-09-07 07:04:48 +02:00
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
{
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, " %d ", (int) (s[i]));
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, "] ");
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outIter(StringInfo str, Iter *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, " ITER :iterexpr ");
|
1997-09-07 07:04:48 +02:00
|
|
|
_outNode(str, node->iterexpr);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outStream(StringInfo str, Stream *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" STREAM :pathptr @ 0x%x :cinfo @ 0x%x :clausetype %d :upstream @ 0x%x ",
|
|
|
|
(int) node->pathptr,
|
|
|
|
(int) node->cinfo,
|
|
|
|
(int) node->clausetype,
|
|
|
|
(int) node->upstream);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str,
|
|
|
|
" :downstream @ 0x%x :groupup %d :groupcost %f :groupsel %f ",
|
|
|
|
(int) node->downstream,
|
|
|
|
node->groupup,
|
|
|
|
node->groupcost,
|
|
|
|
node->groupsel);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-12-23 20:50:54 +01:00
|
|
|
static void
|
|
|
|
_outAExpr(StringInfo str, A_Expr *node)
|
|
|
|
{
|
1998-01-06 19:53:02 +01:00
|
|
|
appendStringInfo(str, "EXPR ");
|
1998-05-10 01:46:35 +02:00
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
switch (node->oper)
|
|
|
|
{
|
|
|
|
case AND:
|
|
|
|
appendStringInfo(str, "AND");
|
|
|
|
break;
|
|
|
|
case OR:
|
|
|
|
appendStringInfo(str, "OR");
|
|
|
|
break;
|
|
|
|
case NOT:
|
|
|
|
appendStringInfo(str, "NOT");
|
|
|
|
break;
|
|
|
|
case ISNULL:
|
|
|
|
appendStringInfo(str, "ISNULL");
|
|
|
|
break;
|
|
|
|
case NOTNULL:
|
|
|
|
appendStringInfo(str, "NOTNULL");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
#endif
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, stringStringInfo(node->opname));
|
1998-05-10 01:46:35 +02:00
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
1997-12-23 20:50:54 +01:00
|
|
|
_outNode(str, node->lexpr);
|
|
|
|
_outNode(str, node->rexpr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
static void
|
1997-09-08 23:56:23 +02:00
|
|
|
_outValue(StringInfo str, Value *value)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-07 07:04:48 +02:00
|
|
|
switch (value->type)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
case T_String:
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, " \"%s\" ", stringStringInfo(value->val.str));
|
1997-09-08 04:41:22 +02:00
|
|
|
break;
|
|
|
|
case T_Integer:
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, " %ld ", value->val.ival);
|
1997-09-08 04:41:22 +02:00
|
|
|
break;
|
|
|
|
case T_Float:
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, " %f ", value->val.dval);
|
1997-09-08 04:41:22 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
return;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1997-12-23 20:50:54 +01:00
|
|
|
static void
|
|
|
|
_outIdent(StringInfo str, Ident *node)
|
|
|
|
{
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, " IDENT \"%s\" ", stringStringInfo(node->name));
|
1997-12-23 20:50:54 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_outAConst(StringInfo str, A_Const *node)
|
|
|
|
{
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, "CONST ");
|
1997-12-23 20:50:54 +01:00
|
|
|
_outValue(str, &(node->val));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1998-12-04 16:34:49 +01:00
|
|
|
static void
|
|
|
|
_outConstraint(StringInfo str, Constraint *node)
|
|
|
|
{
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str," %s :type", stringStringInfo(node->name));
|
1998-12-04 16:34:49 +01:00
|
|
|
|
|
|
|
switch (node->contype)
|
|
|
|
{
|
|
|
|
case CONSTR_PRIMARY:
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, " PRIMARY KEY ");
|
1998-12-04 16:34:49 +01:00
|
|
|
_outNode(str, node->keys);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONSTR_CHECK:
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, " CHECK %s", stringStringInfo(node->def));
|
1998-12-04 16:34:49 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CONSTR_DEFAULT:
|
1998-12-20 08:13:36 +01:00
|
|
|
appendStringInfo(str, " DEFAULT %s", stringStringInfo(node->def));
|
1998-12-04 16:34:49 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CONSTR_NOTNULL:
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, " NOT NULL ");
|
1998-12-04 16:34:49 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CONSTR_UNIQUE:
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, " UNIQUE ");
|
1998-12-04 16:34:49 +01:00
|
|
|
_outNode(str, node->keys);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, "<unrecognized constraint>");
|
1998-12-04 16:34:49 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_outCaseExpr(StringInfo str, CaseExpr *node)
|
|
|
|
{
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, "CASE ");
|
1998-12-04 16:34:49 +01:00
|
|
|
_outNode(str, node->args);
|
1998-12-20 08:13:36 +01:00
|
|
|
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, " :default ");
|
1998-12-04 16:34:49 +01:00
|
|
|
_outNode(str, node->defresult);
|
1998-12-20 08:13:36 +01:00
|
|
|
|
1998-12-04 16:34:49 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_outCaseWhen(StringInfo str, CaseWhen *node)
|
|
|
|
{
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, " WHEN ");
|
1998-12-04 16:34:49 +01:00
|
|
|
_outNode(str, node->expr);
|
1998-12-20 08:13:36 +01:00
|
|
|
|
1998-12-18 15:45:09 +01:00
|
|
|
appendStringInfo(str, " :then ");
|
1998-12-04 16:34:49 +01:00
|
|
|
_outNode(str, node->result);
|
1998-12-20 08:13:36 +01:00
|
|
|
|
1998-12-04 16:34:49 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
|
|
|
* _outNode -
|
1997-09-07 07:04:48 +02:00
|
|
|
* converts a Node into ascii string and append it to 'str'
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
_outNode(StringInfo str, void *obj)
|
|
|
|
{
|
1997-09-07 07:04:48 +02:00
|
|
|
if (obj == NULL)
|
|
|
|
{
|
1998-01-07 16:32:47 +01:00
|
|
|
appendStringInfo(str, "<>");
|
1997-09-07 07:04:48 +02:00
|
|
|
return;
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
if (nodeTag(obj) == T_List)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
List *l;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
appendStringInfo(str, "(");
|
|
|
|
foreach(l, (List *) obj)
|
|
|
|
{
|
|
|
|
_outNode(str, lfirst(l));
|
|
|
|
if (lnext(l))
|
|
|
|
appendStringInfo(str, " ");
|
|
|
|
}
|
|
|
|
appendStringInfo(str, ")");
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
appendStringInfo(str, "{");
|
|
|
|
switch (nodeTag(obj))
|
|
|
|
{
|
1997-12-05 00:20:32 +01:00
|
|
|
case T_CreateStmt:
|
|
|
|
_outCreateStmt(str, obj);
|
|
|
|
break;
|
|
|
|
case T_IndexStmt:
|
|
|
|
_outIndexStmt(str, obj);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_ColumnDef:
|
|
|
|
_outColumnDef(str, obj);
|
|
|
|
break;
|
1998-01-07 00:19:49 +01:00
|
|
|
case T_TypeName:
|
|
|
|
_outTypeName(str, obj);
|
|
|
|
break;
|
1997-12-05 00:20:32 +01:00
|
|
|
case T_IndexElem:
|
|
|
|
_outIndexElem(str, obj);
|
|
|
|
break;
|
|
|
|
|
1998-05-10 01:46:35 +02:00
|
|
|
#ifdef PARSEDEBUG
|
|
|
|
case T_VariableSetStmt:
|
|
|
|
break;
|
|
|
|
case T_SelectStmt:
|
|
|
|
_outSelectStmt(str, obj);
|
|
|
|
break;
|
|
|
|
case T_FuncCall:
|
|
|
|
_outFuncCall(str, obj);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
1997-09-08 04:41:22 +02:00
|
|
|
case T_Query:
|
|
|
|
_outQuery(str, obj);
|
|
|
|
break;
|
1998-01-07 00:19:49 +01:00
|
|
|
case T_SortClause:
|
|
|
|
_outSortClause(str, obj);
|
|
|
|
break;
|
|
|
|
case T_GroupClause:
|
|
|
|
_outGroupClause(str, obj);
|
1998-01-06 19:53:02 +01:00
|
|
|
break;
|
1997-09-08 04:41:22 +02:00
|
|
|
case T_Plan:
|
|
|
|
_outPlan(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Result:
|
|
|
|
_outResult(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Append:
|
|
|
|
_outAppend(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Join:
|
|
|
|
_outJoin(str, obj);
|
|
|
|
break;
|
|
|
|
case T_NestLoop:
|
|
|
|
_outNestLoop(str, obj);
|
|
|
|
break;
|
|
|
|
case T_MergeJoin:
|
|
|
|
_outMergeJoin(str, obj);
|
|
|
|
break;
|
|
|
|
case T_HashJoin:
|
|
|
|
_outHashJoin(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Scan:
|
|
|
|
_outScan(str, obj);
|
|
|
|
break;
|
|
|
|
case T_SeqScan:
|
|
|
|
_outSeqScan(str, obj);
|
|
|
|
break;
|
|
|
|
case T_IndexScan:
|
|
|
|
_outIndexScan(str, obj);
|
|
|
|
break;
|
1999-02-09 18:03:14 +01:00
|
|
|
case T_Noname:
|
|
|
|
_outNoname(str, obj);
|
1997-09-08 04:41:22 +02:00
|
|
|
break;
|
|
|
|
case T_Sort:
|
|
|
|
_outSort(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Agg:
|
|
|
|
_outAgg(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Group:
|
|
|
|
_outGroup(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Unique:
|
|
|
|
_outUnique(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Hash:
|
|
|
|
_outHash(str, obj);
|
|
|
|
break;
|
1998-02-13 04:27:47 +01:00
|
|
|
case T_SubPlan:
|
|
|
|
_outSubPlan(str, obj);
|
|
|
|
break;
|
1997-09-08 04:41:22 +02:00
|
|
|
case T_Tee:
|
|
|
|
_outTee(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Resdom:
|
|
|
|
_outResdom(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Fjoin:
|
|
|
|
_outFjoin(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Expr:
|
|
|
|
_outExpr(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Var:
|
|
|
|
_outVar(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Const:
|
|
|
|
_outConst(str, obj);
|
|
|
|
break;
|
1999-01-24 01:28:37 +01:00
|
|
|
case T_Aggref:
|
|
|
|
_outAggref(str, obj);
|
1997-09-08 04:41:22 +02:00
|
|
|
break;
|
1998-01-17 05:53:46 +01:00
|
|
|
case T_SubLink:
|
|
|
|
_outSubLink(str, obj);
|
|
|
|
break;
|
1997-09-08 04:41:22 +02:00
|
|
|
case T_Array:
|
|
|
|
_outArray(str, obj);
|
|
|
|
break;
|
|
|
|
case T_ArrayRef:
|
|
|
|
_outArrayRef(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Func:
|
|
|
|
_outFunc(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Oper:
|
|
|
|
_outOper(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Param:
|
|
|
|
_outParam(str, obj);
|
|
|
|
break;
|
|
|
|
case T_EState:
|
|
|
|
_outEState(str, obj);
|
|
|
|
break;
|
1998-07-18 06:22:52 +02:00
|
|
|
case T_RelOptInfo:
|
1998-08-02 00:12:13 +02:00
|
|
|
_outRelOptInfo(str, obj);
|
1997-09-08 04:41:22 +02:00
|
|
|
break;
|
|
|
|
case T_TargetEntry:
|
|
|
|
_outTargetEntry(str, obj);
|
|
|
|
break;
|
|
|
|
case T_RangeTblEntry:
|
|
|
|
_outRangeTblEntry(str, obj);
|
|
|
|
break;
|
1999-01-21 17:08:55 +01:00
|
|
|
case T_RowMark:
|
|
|
|
_outRowMark(str, obj);
|
|
|
|
break;
|
1999-02-09 04:51:42 +01:00
|
|
|
case T_PathOrder:
|
|
|
|
_outPathOrder(str, obj);
|
|
|
|
break;
|
1997-09-08 04:41:22 +02:00
|
|
|
case T_Path:
|
|
|
|
_outPath(str, obj);
|
|
|
|
break;
|
|
|
|
case T_IndexPath:
|
|
|
|
_outIndexPath(str, obj);
|
|
|
|
break;
|
1999-02-12 07:43:53 +01:00
|
|
|
case T_NestPath:
|
|
|
|
_outNestPath(str, obj);
|
1997-09-08 04:41:22 +02:00
|
|
|
break;
|
|
|
|
case T_MergePath:
|
|
|
|
_outMergePath(str, obj);
|
|
|
|
break;
|
|
|
|
case T_HashPath:
|
|
|
|
_outHashPath(str, obj);
|
|
|
|
break;
|
|
|
|
case T_OrderKey:
|
|
|
|
_outOrderKey(str, obj);
|
|
|
|
break;
|
|
|
|
case T_JoinKey:
|
|
|
|
_outJoinKey(str, obj);
|
|
|
|
break;
|
|
|
|
case T_MergeOrder:
|
|
|
|
_outMergeOrder(str, obj);
|
|
|
|
break;
|
1999-02-03 21:15:53 +01:00
|
|
|
case T_RestrictInfo:
|
|
|
|
_outRestrictInfo(str, obj);
|
1997-09-08 04:41:22 +02:00
|
|
|
break;
|
|
|
|
case T_JoinMethod:
|
|
|
|
_outJoinMethod(str, obj);
|
|
|
|
break;
|
1999-02-04 02:47:02 +01:00
|
|
|
case T_HashInfo:
|
|
|
|
_outHashInfo(str, obj);
|
1997-09-08 04:41:22 +02:00
|
|
|
break;
|
1998-09-01 05:29:17 +02:00
|
|
|
case T_JoinInfo:
|
|
|
|
_outJoinInfo(str, obj);
|
1997-09-08 04:41:22 +02:00
|
|
|
break;
|
|
|
|
case T_Iter:
|
|
|
|
_outIter(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Stream:
|
|
|
|
_outStream(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Integer:
|
|
|
|
case T_String:
|
|
|
|
case T_Float:
|
|
|
|
_outValue(str, obj);
|
|
|
|
break;
|
1997-12-23 20:50:54 +01:00
|
|
|
case T_A_Expr:
|
|
|
|
_outAExpr(str, obj);
|
|
|
|
break;
|
|
|
|
case T_Ident:
|
|
|
|
_outIdent(str, obj);
|
|
|
|
break;
|
|
|
|
case T_A_Const:
|
|
|
|
_outAConst(str, obj);
|
|
|
|
break;
|
1998-12-04 16:34:49 +01:00
|
|
|
case T_Constraint:
|
|
|
|
_outConstraint(str, obj);
|
|
|
|
break;
|
|
|
|
case T_CaseExpr:
|
|
|
|
_outCaseExpr(str, obj);
|
|
|
|
break;
|
|
|
|
case T_CaseWhen:
|
|
|
|
_outCaseWhen(str, obj);
|
|
|
|
break;
|
1997-09-08 04:41:22 +02:00
|
|
|
default:
|
1998-01-07 06:42:47 +01:00
|
|
|
elog(NOTICE, "_outNode: don't know how to print type %d ",
|
1997-09-08 04:41:22 +02:00
|
|
|
nodeTag(obj));
|
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
appendStringInfo(str, "}");
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
return;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* nodeToString -
|
1997-09-07 07:04:48 +02:00
|
|
|
* returns the ascii representation of the Node
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1998-02-26 05:46:47 +01:00
|
|
|
char *
|
1996-07-09 08:22:35 +02:00
|
|
|
nodeToString(void *obj)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
StringInfo str;
|
|
|
|
char *s;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
if (obj == NULL)
|
|
|
|
return "";
|
|
|
|
Assert(obj != NULL);
|
|
|
|
str = makeStringInfo();
|
|
|
|
_outNode(str, obj);
|
|
|
|
s = str->data;
|
|
|
|
pfree(str);
|
|
|
|
|
|
|
|
return s;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|