mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Postgres95 1.01 Distribution - Virgin Sources
This commit is contained in:
33
src/backend/nodes/Makefile.inc
Normal file
33
src/backend/nodes/Makefile.inc
Normal file
@ -0,0 +1,33 @@
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Makefile.inc--
|
||||
# Makefile for the nodes module
|
||||
#
|
||||
# Copyright (c) 1994, Regents of the University of California
|
||||
#
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $Header: /cvsroot/pgsql/src/backend/nodes/Attic/Makefile.inc,v 1.1.1.1 1996/07/09 06:21:32 scrappy Exp $
|
||||
#
|
||||
# NOTES
|
||||
# Originally, the nodes module is a home-brew, C++ like inheritance
|
||||
# system. However, the automatically generated tags, accessor functions
|
||||
# and the header files themselves are difficult to maintain. We need
|
||||
# real language support. Emulation doesn't quite do it...
|
||||
#
|
||||
# See nodes/README for an explanation of the new no-frills nodes
|
||||
# structures.
|
||||
# - ay 11/5/94
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
VPATH:= $(VPATH):$(CURDIR)/nodes
|
||||
|
||||
|
||||
SRCS_NODES= nodeFuncs.c nodes.c list.c \
|
||||
copyfuncs.c equalfuncs.c makefuncs.c outfuncs.c readfuncs.c \
|
||||
print.c read.c
|
||||
|
||||
HEADERS+= execnodes.h makefuncs.h memnodes.h nodeFuncs.h nodes.h \
|
||||
params.h parsenodes.h pg_list.h plannodes.h primnodes.h relation.h
|
||||
|
65
src/backend/nodes/README
Normal file
65
src/backend/nodes/README
Normal file
@ -0,0 +1,65 @@
|
||||
*******************************************************************************
|
||||
* *
|
||||
* EXPLANATION OF THE NODE STRUCTURES *
|
||||
* - Andrew Yu (11/94) *
|
||||
* *
|
||||
* Copyright (c) 1994, Regents of the University of California *
|
||||
* *
|
||||
* $Id: README,v 1.1.1.1 1996/07/09 06:21:32 scrappy Exp $
|
||||
* *
|
||||
*******************************************************************************
|
||||
|
||||
INTRODUCTION
|
||||
|
||||
The current node structures are plain old C structures. "Inheritance" is
|
||||
achieved by convention. No additional functions will be generated. Functions
|
||||
that manipulate node structures reside in this directory.
|
||||
|
||||
|
||||
FILES IN THIS DIRECTORY
|
||||
|
||||
Node manipulation functions:
|
||||
copyfuncs.c - copying a node
|
||||
equalfuncs.c - comparing a node
|
||||
outfuncs.c - convert a node to ascii representation
|
||||
readfuncs.c - convert ascii representation back to a node
|
||||
makefuncs.c - creator functions for primitive nodes
|
||||
|
||||
Node definitions:
|
||||
nodes.h - define node tags (NodeTag)
|
||||
pg_list.h - generic list
|
||||
primnodes.h - primitive nodes
|
||||
parsenodes.h - parse tree nodes
|
||||
plannodes.h - plan tree nodes
|
||||
relation.h - inner plan tree nodes
|
||||
execnodes.h - executor nodes
|
||||
memnodes.h - memory nodes
|
||||
|
||||
|
||||
STEPS TO ADD A NODE
|
||||
|
||||
Suppose you wana define a node Foo:
|
||||
|
||||
1. add a tag (T_Foo) to the enum NodeTag in nodes.h (You may have to
|
||||
recompile the whole tree after doing this.)
|
||||
2. add the structure definition to the appropriate ???nodes.h file. If you
|
||||
intend to inherit from, say a Plan node, put Plan as the first field of
|
||||
you definition.
|
||||
3. if you intend to use copyObject, equal, nodeToString or stringToNode,
|
||||
add an appropriate function to copyfuncs.c, equalfuncs.c, outfuncs.c
|
||||
and readfuncs.c accordingly. (Except for frequently used nodes, don't
|
||||
bother writing a creator function in makefuncs.c)
|
||||
|
||||
|
||||
HISTORICAL NOTE
|
||||
|
||||
Prior to the current simple C structure definitions, the Node structures
|
||||
uses a pseudo-inheritance system which automatically generates creator and
|
||||
accessor functions. Since every node inherits from LispValue, the whole thing
|
||||
is a mess. Here's a little anecdote:
|
||||
|
||||
LispValue definition -- class used to support lisp structures
|
||||
in C. This is here because we did not want to totally rewrite
|
||||
planner and executor code which depended on lisp structures when
|
||||
we ported postgres V1 from lisp to C. -cim 4/23/90
|
||||
|
1675
src/backend/nodes/copyfuncs.c
Normal file
1675
src/backend/nodes/copyfuncs.c
Normal file
File diff suppressed because it is too large
Load Diff
703
src/backend/nodes/equalfuncs.c
Normal file
703
src/backend/nodes/equalfuncs.c
Normal file
@ -0,0 +1,703 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* equalfuncs.c--
|
||||
* equal functions to compare the nodes
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.1.1.1 1996/07/09 06:21:32 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "nodes/nodes.h"
|
||||
#include "nodes/primnodes.h"
|
||||
#include "nodes/relation.h"
|
||||
#include "nodes/execnodes.h"
|
||||
#include "nodes/plannodes.h"
|
||||
|
||||
#include "utils/builtins.h" /* for namestrcmp() */
|
||||
#include "utils/datum.h"
|
||||
#include "utils/elog.h"
|
||||
#include "storage/itemptr.h"
|
||||
|
||||
/*
|
||||
* Stuff from primnodes.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* Resdom is a subclass of Node.
|
||||
*/
|
||||
static bool
|
||||
_equalResdom(Resdom *a, Resdom *b)
|
||||
{
|
||||
if (a->resno != b->resno)
|
||||
return (false);
|
||||
if (a->restype != b->restype)
|
||||
return (false);
|
||||
if (a->reslen != b->reslen)
|
||||
return (false);
|
||||
if (strcmp(a->resname, b->resname) != 0)
|
||||
return (false);
|
||||
if (a->reskey != b->reskey)
|
||||
return (false);
|
||||
if (a->reskeyop != b->reskeyop)
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalFjoin(Fjoin *a, Fjoin *b)
|
||||
{
|
||||
int nNodes;
|
||||
|
||||
if (a->fj_initialized != b->fj_initialized)
|
||||
return (false);
|
||||
if (a->fj_nNodes != b->fj_nNodes)
|
||||
return (false);
|
||||
if (!equal(a->fj_innerNode, b->fj_innerNode))
|
||||
return (false);
|
||||
|
||||
nNodes = a->fj_nNodes;
|
||||
if (memcmp(a->fj_results, b->fj_results, nNodes*sizeof(Datum)) != 0)
|
||||
return (false);
|
||||
if (memcmp(a->fj_alwaysDone, b->fj_alwaysDone, nNodes*sizeof(bool)) != 0)
|
||||
return (false);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Expr is a subclass of Node.
|
||||
*/
|
||||
static bool
|
||||
_equalExpr(Expr *a, Expr *b)
|
||||
{
|
||||
if (a->opType != b->opType)
|
||||
return (false);
|
||||
if (!equal(a->oper, b->oper))
|
||||
return (false);
|
||||
if (!equal(a->args, b->args))
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool _equalIter(Iter *a, Iter *b)
|
||||
{
|
||||
return (equal(a->iterexpr, b->iterexpr));
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalStream(Stream *a, Stream *b)
|
||||
{
|
||||
if (a->clausetype != b->clausetype)
|
||||
return(false);
|
||||
if (a->groupup != b->groupup)
|
||||
return(false);
|
||||
if (a->groupcost != b->groupcost)
|
||||
return(false);
|
||||
if (a->groupsel != b->groupsel)
|
||||
return(false);
|
||||
if (!equal(a->pathptr, b->pathptr))
|
||||
return(false);
|
||||
if (!equal(a->cinfo, b->cinfo))
|
||||
return(false);
|
||||
if (!equal(a->upstream, b->upstream))
|
||||
return(false);
|
||||
return(equal(a->downstream, b->downstream));
|
||||
}
|
||||
|
||||
/*
|
||||
* Var is a subclass of Expr.
|
||||
*/
|
||||
static bool
|
||||
_equalVar(Var *a, Var *b)
|
||||
{
|
||||
if (a->varno != b->varno)
|
||||
return (false);
|
||||
if (a->varattno != b->varattno)
|
||||
return (false);
|
||||
if (a->vartype != b->vartype)
|
||||
return (false);
|
||||
if (a->varnoold != b->varnoold)
|
||||
return (false);
|
||||
if (a->varoattno != b->varoattno)
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalArray(Array *a, Array *b)
|
||||
{
|
||||
if (a->arrayelemtype != b->arrayelemtype)
|
||||
return (false);
|
||||
if (a->arrayndim != b->arrayndim)
|
||||
return (false);
|
||||
if (a->arraylow.indx[0] != b->arraylow.indx[0])
|
||||
return (false);
|
||||
if (a->arrayhigh.indx[0] != b->arrayhigh.indx[0])
|
||||
return (false);
|
||||
if (a->arraylen != b->arraylen)
|
||||
return (false);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalArrayRef(ArrayRef *a, ArrayRef *b)
|
||||
{
|
||||
if (a->refelemtype != b->refelemtype)
|
||||
return (false);
|
||||
if (a->refattrlength != b->refattrlength)
|
||||
return (false);
|
||||
if (a->refelemlength != b->refelemlength)
|
||||
return (false);
|
||||
if (a->refelembyval != b->refelembyval)
|
||||
return (false);
|
||||
if (!equal(a->refupperindexpr, b->refupperindexpr))
|
||||
return (false);
|
||||
if (!equal(a->reflowerindexpr, b->reflowerindexpr))
|
||||
return (false);
|
||||
if (!equal(a->refexpr, b->refexpr))
|
||||
return (false);
|
||||
return (equal(a->refassgnexpr, b->refassgnexpr));
|
||||
}
|
||||
|
||||
/*
|
||||
* Oper is a subclass of Expr.
|
||||
*/
|
||||
static bool
|
||||
_equalOper(Oper *a, Oper *b)
|
||||
{
|
||||
if (a->opno != b->opno)
|
||||
return (false);
|
||||
if (a->opresulttype != b->opresulttype)
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Const is a subclass of Expr.
|
||||
*/
|
||||
static bool
|
||||
_equalConst(Const *a, Const *b)
|
||||
{
|
||||
/*
|
||||
** this function used to do a pointer compare on a and b. That's
|
||||
** ridiculous. -- JMH, 7/11/92
|
||||
*/
|
||||
if (a->consttype != b->consttype)
|
||||
return(false);
|
||||
if (a->constlen != b->constlen)
|
||||
return(false);
|
||||
if (a->constisnull != b->constisnull)
|
||||
return(false);
|
||||
if (a->constbyval != b->constbyval)
|
||||
return(false);
|
||||
return(datumIsEqual(a->constvalue, b->constvalue,
|
||||
a->consttype, a->constbyval, a->constlen));
|
||||
}
|
||||
|
||||
/*
|
||||
* Param is a subclass of Expr.
|
||||
*/
|
||||
static bool
|
||||
_equalParam(Param *a, Param *b)
|
||||
{
|
||||
if (a->paramkind != b->paramkind)
|
||||
return (false);
|
||||
if (a->paramtype != b->paramtype)
|
||||
return (false);
|
||||
if (!equal(a->param_tlist, b->param_tlist))
|
||||
return (false);
|
||||
|
||||
switch (a->paramkind) {
|
||||
case PARAM_NAMED:
|
||||
case PARAM_NEW:
|
||||
case PARAM_OLD:
|
||||
if (strcmp(a->paramname, b->paramname) != 0)
|
||||
return (false);
|
||||
break;
|
||||
case PARAM_NUM:
|
||||
if (a->paramid != b->paramid)
|
||||
return (false);
|
||||
break;
|
||||
case PARAM_INVALID:
|
||||
/*
|
||||
* XXX: Hmmm... What are we supposed to return
|
||||
* in this case ??
|
||||
*/
|
||||
return(true);
|
||||
break;
|
||||
default:
|
||||
elog(WARN, "_equalParam: Invalid paramkind value: %d",
|
||||
a->paramkind);
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Func is a subclass of Expr.
|
||||
*/
|
||||
static bool
|
||||
_equalFunc(Func *a, Func *b)
|
||||
{
|
||||
if (a->funcid != b->funcid)
|
||||
return (false);
|
||||
if (a->functype != b->functype)
|
||||
return (false);
|
||||
if (a->funcisindex != b->funcisindex)
|
||||
return (false);
|
||||
if (a->funcsize != b->funcsize)
|
||||
return (false);
|
||||
if (!equal(a->func_tlist, b->func_tlist))
|
||||
return (false);
|
||||
if (!equal(a->func_planlist, b->func_planlist))
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* CInfo is a subclass of Node.
|
||||
*/
|
||||
static bool
|
||||
_equalCInfo(CInfo *a, CInfo *b)
|
||||
{
|
||||
Assert(IsA(a,CInfo));
|
||||
Assert(IsA(b,CInfo));
|
||||
|
||||
if (!equal(a->clause, b->clause))
|
||||
return(false);
|
||||
if (a->selectivity != b->selectivity)
|
||||
return(false);
|
||||
if (a->notclause != b->notclause)
|
||||
return(false);
|
||||
#ifdef EqualMergeOrderExists
|
||||
if (!EqualMergeOrder(a->mergesortorder,b->mergesortorder))
|
||||
return(false);
|
||||
#endif
|
||||
if(a->hashjoinoperator != b->hashjoinoperator)
|
||||
return(false);
|
||||
return(equal((a->indexids),
|
||||
(b->indexids)));
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalJoinMethod(JoinMethod *a, JoinMethod *b)
|
||||
{
|
||||
Assert(IsA(a,JoinMethod));
|
||||
Assert(IsA(b,JoinMethod));
|
||||
|
||||
if (!equal((a->jmkeys),
|
||||
(b->jmkeys)))
|
||||
return(false);
|
||||
if (!equal((a->clauses),
|
||||
(b->clauses)))
|
||||
return(false);
|
||||
return(true);
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalPath(Path *a, Path *b)
|
||||
{
|
||||
if (a->pathtype != b->pathtype)
|
||||
return(false);
|
||||
if (a->parent != b->parent)
|
||||
return(false);
|
||||
/*
|
||||
if (a->path_cost != b->path_cost)
|
||||
return(false);
|
||||
*/
|
||||
if (a->p_ordering.ordtype == SORTOP_ORDER) {
|
||||
int i = 0;
|
||||
if (a->p_ordering.ord.sortop==NULL ||
|
||||
b->p_ordering.ord.sortop==NULL) {
|
||||
|
||||
if (a->p_ordering.ord.sortop != b->p_ordering.ord.sortop)
|
||||
return false;
|
||||
} else {
|
||||
while(a->p_ordering.ord.sortop[i]!=0 &&
|
||||
b->p_ordering.ord.sortop[i]!=0) {
|
||||
if (a->p_ordering.ord.sortop[i] != b->p_ordering.ord.sortop[i])
|
||||
return false;
|
||||
i++;
|
||||
}
|
||||
if (a->p_ordering.ord.sortop[i]!=0 ||
|
||||
b->p_ordering.ord.sortop[i]!=0)
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!equal((a->p_ordering.ord.merge),
|
||||
(b->p_ordering.ord.merge)))
|
||||
return(false);
|
||||
}
|
||||
if (!equal((a->keys),
|
||||
(b->keys)))
|
||||
return(false);
|
||||
/*
|
||||
if (a->outerjoincost != b->outerjoincost)
|
||||
return(false);
|
||||
*/
|
||||
if (!equali((a->joinid),
|
||||
(b->joinid)))
|
||||
return(false);
|
||||
return(true);
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalIndexPath(IndexPath *a, IndexPath *b)
|
||||
{
|
||||
if (!_equalPath((Path*)a,(Path*)b))
|
||||
return(false);
|
||||
if (!equali((a->indexid), (b->indexid)))
|
||||
return(false);
|
||||
if (!equal((a->indexqual), (b->indexqual)))
|
||||
return(false);
|
||||
return(true);
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalJoinPath(JoinPath *a,JoinPath *b)
|
||||
{
|
||||
Assert(IsA_JoinPath(a));
|
||||
Assert(IsA_JoinPath(b));
|
||||
|
||||
if (!_equalPath((Path*)a,(Path*)b))
|
||||
return(false);
|
||||
if (!equal((a->pathclauseinfo), (b->pathclauseinfo)))
|
||||
return(false);
|
||||
if (!equal((a->outerjoinpath), (b->outerjoinpath)))
|
||||
return(false);
|
||||
if (!equal((a->innerjoinpath), (b->innerjoinpath)))
|
||||
return(false);
|
||||
return(true);
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalMergePath(MergePath *a, MergePath *b)
|
||||
{
|
||||
Assert(IsA(a,MergePath));
|
||||
Assert(IsA(b,MergePath));
|
||||
|
||||
if (!_equalJoinPath((JoinPath*)a,(JoinPath*)b))
|
||||
return(false);
|
||||
if (!equal((a->path_mergeclauses), (b->path_mergeclauses)))
|
||||
return(false);
|
||||
if (!equal((a->outersortkeys), (b->outersortkeys)))
|
||||
return(false);
|
||||
if (!equal((a->innersortkeys), (b->innersortkeys)))
|
||||
return(false);
|
||||
return(true);
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalHashPath(HashPath *a, HashPath *b)
|
||||
{
|
||||
Assert(IsA(a,HashPath));
|
||||
Assert(IsA(b,HashPath));
|
||||
|
||||
if (!_equalJoinPath((JoinPath*)a,(JoinPath*)b))
|
||||
return(false);
|
||||
if (!equal((a->path_hashclauses), (b->path_hashclauses)))
|
||||
return(false);
|
||||
if (!equal((a->outerhashkeys), (b->outerhashkeys)))
|
||||
return(false);
|
||||
if (!equal((a->innerhashkeys), (b->innerhashkeys)))
|
||||
return(false);
|
||||
return(true);
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalJoinKey(JoinKey *a, JoinKey *b)
|
||||
{
|
||||
Assert(IsA(a,JoinKey));
|
||||
Assert(IsA(b,JoinKey));
|
||||
|
||||
if (!equal((a->outer),(b->outer)))
|
||||
return(false);
|
||||
if (!equal((a->inner),(b->inner)))
|
||||
return(false);
|
||||
return(true);
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalMergeOrder(MergeOrder *a, MergeOrder *b)
|
||||
{
|
||||
if (a == (MergeOrder*)NULL && b == (MergeOrder*)NULL)
|
||||
return(true);
|
||||
Assert(IsA(a,MergeOrder));
|
||||
Assert(IsA(b,MergeOrder));
|
||||
|
||||
if (a->join_operator != b->join_operator)
|
||||
return(false);
|
||||
if (a->left_operator != b->left_operator)
|
||||
return(false);
|
||||
if (a->right_operator != b->right_operator)
|
||||
return(false);
|
||||
if (a->left_type != b->left_type)
|
||||
return(false);
|
||||
if (a->right_type != b->right_type)
|
||||
return(false);
|
||||
return(true);
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalHInfo(HInfo *a, HInfo *b)
|
||||
{
|
||||
Assert(IsA(a,HInfo));
|
||||
Assert(IsA(b,HInfo));
|
||||
|
||||
if (a->hashop != b->hashop)
|
||||
return(false);
|
||||
return(true);
|
||||
}
|
||||
|
||||
/* XXX This equality function is a quick hack, should be
|
||||
* fixed to compare all fields.
|
||||
*/
|
||||
static bool
|
||||
_equalIndexScan(IndexScan *a, IndexScan *b)
|
||||
{
|
||||
Assert(IsA(a,IndexScan));
|
||||
Assert(IsA(b,IndexScan));
|
||||
|
||||
/*
|
||||
if(a->scan.plan.cost != b->scan.plan.cost)
|
||||
return(false);
|
||||
*/
|
||||
|
||||
if (!equal((a->indxqual),(b->indxqual)))
|
||||
return(false);
|
||||
|
||||
if (a->scan.scanrelid != b->scan.scanrelid)
|
||||
return(false);
|
||||
|
||||
if (!equali((a->indxid),(b->indxid)))
|
||||
return(false);
|
||||
return(true);
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalJInfo(JInfo *a, JInfo *b)
|
||||
{
|
||||
Assert(IsA(a,JInfo));
|
||||
Assert(IsA(b,JInfo));
|
||||
if (!equal((a->otherrels),(b->otherrels)))
|
||||
return(false);
|
||||
if (!equal((a->jinfoclauseinfo),(b->jinfoclauseinfo)))
|
||||
return(false);
|
||||
if (a->mergesortable != b->mergesortable)
|
||||
return(false);
|
||||
if (a->hashjoinable != b->hashjoinable)
|
||||
return(false);
|
||||
return(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stuff from execnodes.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* EState is a subclass of Node.
|
||||
*/
|
||||
static bool
|
||||
_equalEState(EState *a, EState *b)
|
||||
{
|
||||
if (a->es_direction != b->es_direction)
|
||||
return (false);
|
||||
|
||||
if (!equal(a->es_range_table, b->es_range_table))
|
||||
return (false);
|
||||
|
||||
if (a->es_result_relation_info != b->es_result_relation_info)
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* equal -- are two lists equal?
|
||||
*
|
||||
* This is a comparison by value. It would be simpler to write it
|
||||
* to be recursive, but it should run faster if we iterate.
|
||||
*/
|
||||
static bool
|
||||
_equalValue(Value *a, Value *b)
|
||||
{
|
||||
if (a->type != b->type)
|
||||
return (false);
|
||||
|
||||
switch(a->type) {
|
||||
case T_String:
|
||||
return strcmp(a->val.str, b->val.str);
|
||||
case T_Integer:
|
||||
return (a->val.ival==b->val.ival);
|
||||
case T_Float:
|
||||
return (a->val.dval==b->val.dval);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
/*
|
||||
* equal--
|
||||
* returns whether two nodes are equal
|
||||
*/
|
||||
bool
|
||||
equal(void *a, void *b)
|
||||
{
|
||||
bool retval;
|
||||
|
||||
if (a == b)
|
||||
return(true);
|
||||
/*
|
||||
* note that a!=b, so only one of them can be NULL
|
||||
*/
|
||||
if (a==NULL || b==NULL)
|
||||
return (false);
|
||||
/*
|
||||
* are they the same type of nodes?
|
||||
*/
|
||||
if (nodeTag(a)!=nodeTag(b))
|
||||
return (false);
|
||||
|
||||
switch(nodeTag(a)) {
|
||||
case T_Resdom:
|
||||
retval = _equalResdom(a, b);
|
||||
break;
|
||||
case T_Fjoin:
|
||||
retval = _equalFjoin(a, b);
|
||||
break;
|
||||
case T_Expr:
|
||||
retval = _equalExpr(a, b);
|
||||
break;
|
||||
case T_Iter:
|
||||
retval = _equalIter(a, b);
|
||||
break;
|
||||
case T_Stream:
|
||||
retval = _equalStream(a, b);
|
||||
break;
|
||||
case T_Var:
|
||||
retval = _equalVar(a, b);
|
||||
break;
|
||||
case T_Array:
|
||||
retval = _equalArray(a, b);
|
||||
break;
|
||||
case T_ArrayRef:
|
||||
retval = _equalArrayRef(a, b);
|
||||
break;
|
||||
case T_Oper:
|
||||
retval = _equalOper(a, b);
|
||||
break;
|
||||
case T_Const:
|
||||
retval = _equalConst(a, b);
|
||||
break;
|
||||
case T_Param:
|
||||
retval = _equalParam(a, b);
|
||||
break;
|
||||
case T_Func:
|
||||
retval = _equalFunc(a, b);
|
||||
break;
|
||||
case T_CInfo:
|
||||
retval = _equalCInfo(a, b);
|
||||
break;
|
||||
case T_JoinMethod:
|
||||
retval = _equalJoinMethod(a, b);
|
||||
break;
|
||||
case T_Path:
|
||||
retval = _equalPath(a, b);
|
||||
break;
|
||||
case T_IndexPath:
|
||||
retval = _equalIndexPath(a, b);
|
||||
break;
|
||||
case T_JoinPath:
|
||||
retval = _equalJoinPath(a, b);
|
||||
break;
|
||||
case T_MergePath:
|
||||
retval = _equalMergePath(a, b);
|
||||
break;
|
||||
case T_HashPath:
|
||||
retval = _equalHashPath(a, b);
|
||||
break;
|
||||
case T_JoinKey:
|
||||
retval = _equalJoinKey(a, b);
|
||||
break;
|
||||
case T_MergeOrder:
|
||||
retval = _equalMergeOrder(a, b);
|
||||
break;
|
||||
case T_HInfo:
|
||||
retval = _equalHInfo(a, b);
|
||||
break;
|
||||
case T_IndexScan:
|
||||
retval = _equalIndexScan(a, b);
|
||||
break;
|
||||
case T_JInfo:
|
||||
retval = _equalJInfo(a, b);
|
||||
break;
|
||||
case T_EState:
|
||||
retval = _equalEState(a, b);
|
||||
break;
|
||||
case T_Integer: case T_String: case T_Float:
|
||||
retval = _equalValue(a, b);
|
||||
break;
|
||||
case T_List:
|
||||
{
|
||||
List *la = (List*)a;
|
||||
List *lb = (List*)b;
|
||||
List *l;
|
||||
|
||||
if (a==NULL && b==NULL)
|
||||
return (true);
|
||||
if (length(a)!=length(b))
|
||||
return (false);
|
||||
foreach(l, la) {
|
||||
if (!equal(lfirst(l), lfirst(lb)))
|
||||
return (false);
|
||||
lb = lnext(lb);
|
||||
}
|
||||
retval = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
elog(NOTICE, "equal: don't know whether nodes of type %d are equal",
|
||||
nodeTag(a));
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* equali--
|
||||
* compares two lists of integers
|
||||
*
|
||||
* XXX temp hack. needs something like T_IntList
|
||||
*/
|
||||
bool equali(List *a, List *b)
|
||||
{
|
||||
List *la = (List*)a;
|
||||
List *lb = (List*)b;
|
||||
List *l;
|
||||
|
||||
if (a==NULL && b==NULL)
|
||||
return (true);
|
||||
if (length(a)!=length(b))
|
||||
return (false);
|
||||
foreach(l, la) {
|
||||
if (lfirsti(l) != lfirsti(lb))
|
||||
return (false);
|
||||
lb = lnext(lb);
|
||||
}
|
||||
return true;
|
||||
}
|
689
src/backend/nodes/execnodes.h
Normal file
689
src/backend/nodes/execnodes.h
Normal file
@ -0,0 +1,689 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* execnodes.h--
|
||||
* definitions for executor state nodes
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: execnodes.h,v 1.1.1.1 1996/07/09 06:21:32 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef EXECNODES_H
|
||||
#define EXECNODES_H
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "nodes/nodes.h"
|
||||
#include "nodes/primnodes.h"
|
||||
#include "nodes/pg_list.h"
|
||||
|
||||
#include "nodes/memnodes.h"
|
||||
|
||||
#include "storage/item.h"
|
||||
#include "access/sdir.h"
|
||||
#include "access/htup.h"
|
||||
#include "access/tupdesc.h"
|
||||
#include "access/funcindex.h"
|
||||
#include "utils/rel.h"
|
||||
#include "access/relscan.h"
|
||||
#include "executor/hashjoin.h"
|
||||
#include "executor/tuptable.h"
|
||||
|
||||
/* ----------------
|
||||
* IndexInfo information
|
||||
*
|
||||
* this class holds the information saying what attributes
|
||||
* are the key attributes for this index. -cim 10/15/89
|
||||
*
|
||||
* NumKeyAttributes number of key attributes for this index
|
||||
* KeyAttributeNumbers array of attribute numbers used as keys
|
||||
* Predicate partial-index predicate for this index
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct IndexInfo {
|
||||
NodeTag type;
|
||||
int ii_NumKeyAttributes;
|
||||
AttrNumber *ii_KeyAttributeNumbers;
|
||||
FuncIndexInfoPtr ii_FuncIndexInfo;
|
||||
Node *ii_Predicate;
|
||||
} IndexInfo;
|
||||
|
||||
/* ----------------
|
||||
* RelationInfo information
|
||||
*
|
||||
* whenever we update an existing relation, we have to
|
||||
* update indices on the relation. The RelationInfo class
|
||||
* is used to hold all the information on result relations,
|
||||
* including indices.. -cim 10/15/89
|
||||
*
|
||||
* RangeTableIndex result relation's range table index
|
||||
* RelationDesc relation descriptor for result relation
|
||||
* NumIndices number indices existing on result relation
|
||||
* IndexRelationDescs array of relation descriptors for indices
|
||||
* IndexRelationInfo array of key/attr info for indices
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct RelationInfo {
|
||||
NodeTag type;
|
||||
Index ri_RangeTableIndex;
|
||||
Relation ri_RelationDesc;
|
||||
int ri_NumIndices;
|
||||
RelationPtr ri_IndexRelationDescs;
|
||||
IndexInfo **ri_IndexRelationInfo;
|
||||
} RelationInfo;
|
||||
|
||||
/* ----------------
|
||||
* ExprContext
|
||||
*
|
||||
* This class holds the "current context" information
|
||||
* needed to evaluate expressions for doing tuple qualifications
|
||||
* and tuple projections. For example, if an expression refers
|
||||
* to an attribute in the current inner tuple then we need to know
|
||||
* what the current inner tuple is and so we look at the expression
|
||||
* context.
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct ExprContext {
|
||||
NodeTag type;
|
||||
TupleTableSlot *ecxt_scantuple;
|
||||
TupleTableSlot *ecxt_innertuple;
|
||||
TupleTableSlot *ecxt_outertuple;
|
||||
Relation ecxt_relation;
|
||||
Index ecxt_relid;
|
||||
ParamListInfo ecxt_param_list_info;
|
||||
List *ecxt_range_table;
|
||||
Datum *ecxt_values; /* precomputed values for aggreg */
|
||||
char *ecxt_nulls; /* null flags for aggreg values */
|
||||
} ExprContext;
|
||||
|
||||
/* ----------------
|
||||
* ProjectionInfo node information
|
||||
*
|
||||
* This is all the information needed to preform projections
|
||||
* on a tuple. Nodes which need to do projections create one
|
||||
* of these. In theory, when a node wants to preform a projection
|
||||
* it should just update this information as necessary and then
|
||||
* call ExecProject(). -cim 6/3/91
|
||||
*
|
||||
* targetlist target list for projection
|
||||
* len length of target list
|
||||
* tupValue array of pointers to projection results
|
||||
* exprContext expression context for ExecTargetList
|
||||
* slot slot to place projection result in
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct ProjectionInfo {
|
||||
NodeTag type;
|
||||
List *pi_targetlist;
|
||||
int pi_len;
|
||||
Datum *pi_tupValue;
|
||||
ExprContext *pi_exprContext;
|
||||
TupleTableSlot *pi_slot;
|
||||
} ProjectionInfo;
|
||||
|
||||
/* ----------------
|
||||
* JunkFilter
|
||||
*
|
||||
* this class is used to store information regarding junk attributes.
|
||||
* A junk attribute is an attribute in a tuple that is needed only for
|
||||
* storing intermediate information in the executor, and does not belong
|
||||
* in the tuple proper. For example, when we do a delete or replace
|
||||
* query, the planner adds an entry to the targetlist so that the tuples
|
||||
* returned to ExecutePlan() contain an extra attribute: the t_ctid of
|
||||
* the tuple to be deleted/replaced. This is needed for amdelete() and
|
||||
* amreplace(). In doing a delete this does not make much of a
|
||||
* difference, but in doing a replace we have to make sure we disgard
|
||||
* all the junk in a tuple before calling amreplace(). Otherwise the
|
||||
* inserted tuple will not have the correct schema. This solves a
|
||||
* problem with hash-join and merge-sort replace plans. -cim 10/10/90
|
||||
*
|
||||
* targetList: the original target list (including junk attributes).
|
||||
* length: the length of 'targetList'.
|
||||
* tupType: the tuple descriptor for the "original" tuple
|
||||
* (including the junk attributes).
|
||||
* cleanTargetList: the "clean" target list (junk attributes removed).
|
||||
* cleanLength: the length of 'cleanTargetList'
|
||||
* cleanTupTyp: the tuple descriptor of the "clean" tuple (with
|
||||
* junk attributes removed).
|
||||
* cleanMap: A map with the correspondance between the non junk
|
||||
* attributes of the "original" tuple and the
|
||||
* attributes of the "clean" tuple.
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct JunkFilter {
|
||||
NodeTag type;
|
||||
List *jf_targetList;
|
||||
int jf_length;
|
||||
TupleDesc jf_tupType;
|
||||
List *jf_cleanTargetList;
|
||||
int jf_cleanLength;
|
||||
TupleDesc jf_cleanTupType;
|
||||
AttrNumber *jf_cleanMap;
|
||||
} JunkFilter;
|
||||
|
||||
/* ----------------
|
||||
* EState information
|
||||
*
|
||||
* direction direction of the scan
|
||||
*
|
||||
* range_table array of scan relation information
|
||||
*
|
||||
* result_relation_information for update queries
|
||||
*
|
||||
* into_relation_descriptor relation being retrieved "into"
|
||||
*
|
||||
* param_list_info information needed to transform
|
||||
* Param nodes into Const nodes
|
||||
*
|
||||
* BaseId during InitPlan(), each node is
|
||||
* given a number. this is the next
|
||||
* number to be assigned.
|
||||
*
|
||||
* tupleTable this is a pointer to an array
|
||||
* of pointers to tuples used by
|
||||
* the executor at any given moment.
|
||||
*
|
||||
* junkFilter contains information used to
|
||||
* extract junk attributes from a tuple.
|
||||
* (see JunkFilter above)
|
||||
*
|
||||
* refcount local buffer refcounts used in
|
||||
* an ExecMain cycle. this is introduced
|
||||
* to avoid ExecStart's unpinning each
|
||||
* other's buffers when called recursively
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct EState {
|
||||
NodeTag type;
|
||||
ScanDirection es_direction;
|
||||
List *es_range_table;
|
||||
RelationInfo *es_result_relation_info;
|
||||
Relation es_into_relation_descriptor;
|
||||
ParamListInfo es_param_list_info;
|
||||
int es_BaseId;
|
||||
TupleTable es_tupleTable;
|
||||
JunkFilter *es_junkFilter;
|
||||
int *es_refcount;
|
||||
} EState;
|
||||
|
||||
/* ----------------
|
||||
* Executor Type information needed by plannodes.h
|
||||
*
|
||||
*| Note: the bogus classes CommonState and CommonScanState exist only
|
||||
*| because our inheritance system only allows single inheritance
|
||||
*| and we have to have unique slot names. Hence two or more
|
||||
*| classes which want to have a common slot must ALL inherit
|
||||
*| the slot from some other class. (This is a big hack to
|
||||
*| allow our classes to share slot names..)
|
||||
*|
|
||||
*| Example:
|
||||
*| the class Result and the class NestLoop nodes both want
|
||||
*| a slot called "OuterTuple" so they both have to inherit
|
||||
*| it from some other class. In this case they inherit
|
||||
*| it from CommonState. "CommonState" and "CommonScanState" are
|
||||
*| the best names I could come up with for this sort of
|
||||
*| stuff.
|
||||
*|
|
||||
*| As a result, many classes have extra slots which they
|
||||
*| don't use. These slots are denoted (unused) in the
|
||||
*| comment preceeding the class definition. If you
|
||||
*| comes up with a better idea of a way of doing things
|
||||
*| along these lines, then feel free to make your idea
|
||||
*| known to me.. -cim 10/15/89
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* Common Executor State Information
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* BaseNode removed -- base_id moved into CommonState - jolly */
|
||||
|
||||
/* ----------------
|
||||
* CommonState information
|
||||
*
|
||||
*| this is a bogus class used to hold slots so other
|
||||
*| nodes can inherit them...
|
||||
*
|
||||
* OuterTupleSlot pointer to slot containing current "outer" tuple
|
||||
* ResultTupleSlot pointer to slot in tuple table for projected tuple
|
||||
* ExprContext node's current expression context
|
||||
* ProjInfo info this node uses to form tuple projections
|
||||
* NumScanAttributes size of ScanAttributes array
|
||||
* ScanAttributes attribute numbers of interest in this tuple
|
||||
*
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct CommonState {
|
||||
NodeTag type; /* its first field is NodeTag */
|
||||
int cs_base_id;
|
||||
TupleTableSlot *cs_OuterTupleSlot;
|
||||
TupleTableSlot *cs_ResultTupleSlot;
|
||||
ExprContext *cs_ExprContext;
|
||||
ProjectionInfo *cs_ProjInfo;
|
||||
bool cs_TupFromTlist;
|
||||
} CommonState;
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* Control Node State Information
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ----------------
|
||||
* ResultState information
|
||||
*
|
||||
* done flag which tells us to quit when we
|
||||
* have already returned a constant tuple.
|
||||
*
|
||||
* CommonState information
|
||||
*
|
||||
* OuterTupleSlot pointer to slot containing current "outer" tuple
|
||||
* ResultTupleSlot pointer to slot in tuple table for projected tuple
|
||||
* ExprContext node's current expression context
|
||||
* ProjInfo info this node uses to form tuple projections
|
||||
* NumScanAttributes size of ScanAttributes array
|
||||
* ScanAttributes attribute numbers of interest in this tuple
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct ResultState {
|
||||
CommonState cstate; /* its first field is NodeTag */
|
||||
int rs_done;
|
||||
} ResultState;
|
||||
|
||||
/* ----------------
|
||||
* AppendState information
|
||||
*
|
||||
* append nodes have this field "unionplans" which is this
|
||||
* list of plans to execute in sequence.. these variables
|
||||
* keep track of things..
|
||||
*
|
||||
* whichplan which plan is being executed
|
||||
* nplans how many plans are in the list
|
||||
* initialized array of ExecInitNode() results
|
||||
* rtentries range table for the current plan
|
||||
* result_relation_info_list array of each subplan's result relation info
|
||||
* junkFilter_list array of each subplan's junk filter
|
||||
*
|
||||
* CommonState information
|
||||
*
|
||||
* OuterTupleSlot pointer to slot containing current "outer" tuple
|
||||
* ResultTupleSlot pointer to slot in tuple table for projected tuple
|
||||
* ExprContext node's current expression context
|
||||
* ProjInfo info this node uses to form tuple projections
|
||||
* NumScanAttributes size of ScanAttributes array
|
||||
* ScanAttributes attribute numbers of interest in this tuple
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct AppendState {
|
||||
CommonState cstate; /* its first field is NodeTag */
|
||||
int as_whichplan;
|
||||
int as_nplans;
|
||||
bool *as_initialized;
|
||||
List *as_rtentries;
|
||||
List *as_result_relation_info_list;
|
||||
List *as_junkFilter_list;
|
||||
} AppendState;
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* Scan State Information
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ----------------
|
||||
* CommonScanState information
|
||||
*
|
||||
* CommonScanState is a class like CommonState, but is used more
|
||||
* by the nodes like SeqScan and Sort which want to
|
||||
* keep track of an underlying relation.
|
||||
*
|
||||
* currentRelation relation being scanned
|
||||
* currentScanDesc current scan descriptor for scan
|
||||
* ScanTupleSlot pointer to slot in tuple table holding scan tuple
|
||||
*
|
||||
* CommonState information
|
||||
*
|
||||
* OuterTupleSlot pointer to slot containing current "outer" tuple
|
||||
* ResultTupleSlot pointer to slot in tuple table for projected tuple
|
||||
* ExprContext node's current expression context
|
||||
* ProjInfo info this node uses to form tuple projections
|
||||
* NumScanAttributes size of ScanAttributes array
|
||||
* ScanAttributes attribute numbers of interest in this tuple
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct CommonScanState {
|
||||
CommonState cstate; /* its first field is NodeTag */
|
||||
Relation css_currentRelation;
|
||||
HeapScanDesc css_currentScanDesc;
|
||||
TupleTableSlot *css_ScanTupleSlot;
|
||||
} CommonScanState;
|
||||
|
||||
/* ----------------
|
||||
* IndexScanState information
|
||||
*
|
||||
*| index scans don't use CommonScanState because
|
||||
*| the underlying AM abstractions for heap scans and
|
||||
*| index scans are too different.. It would be nice
|
||||
*| if the current abstraction was more useful but ... -cim 10/15/89
|
||||
*
|
||||
* IndexPtr current index in use
|
||||
* NumIndices number of indices in this scan
|
||||
* ScanKeys Skey structures to scan index rels
|
||||
* NumScanKeys array of no of keys in each Skey struct
|
||||
* RuntimeKeyInfo array of array of flags for Skeys evaled at runtime
|
||||
* RelationDescs ptr to array of relation descriptors
|
||||
* ScanDescs ptr to array of scan descriptors
|
||||
*
|
||||
* CommonState information
|
||||
*
|
||||
* OuterTupleSlot pointer to slot containing current "outer" tuple
|
||||
* ResultTupleSlot pointer to slot in tuple table for projected tuple
|
||||
* ExprContext node's current expression context
|
||||
* ProjInfo info this node uses to form tuple projections
|
||||
* NumScanAttributes size of ScanAttributes array
|
||||
* ScanAttributes attribute numbers of interest in this tuple
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct IndexScanState {
|
||||
CommonState cstate; /* its first field is NodeTag */
|
||||
int iss_NumIndices;
|
||||
int iss_IndexPtr;
|
||||
ScanKey *iss_ScanKeys;
|
||||
int *iss_NumScanKeys;
|
||||
Pointer iss_RuntimeKeyInfo;
|
||||
RelationPtr iss_RelationDescs;
|
||||
IndexScanDescPtr iss_ScanDescs;
|
||||
} IndexScanState;
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* Join State Information
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ----------------
|
||||
* JoinState information
|
||||
*
|
||||
* CommonState information
|
||||
*
|
||||
* OuterTupleSlot pointer to slot containing current "outer" tuple
|
||||
* ResultTupleSlot pointer to slot in tuple table for projected tuple
|
||||
* ExprContext node's current expression context
|
||||
* ProjInfo info this node uses to form tuple projections
|
||||
* NumScanAttributes size of ScanAttributes array
|
||||
* ScanAttributes attribute numbers of interest in this tuple
|
||||
* ----------------
|
||||
*/
|
||||
typedef CommonState JoinState;
|
||||
|
||||
/* ----------------
|
||||
* NestLoopState information
|
||||
*
|
||||
* PortalFlag Set to enable portals to work.
|
||||
*
|
||||
* JoinState information
|
||||
*
|
||||
* CommonState information
|
||||
*
|
||||
* OuterTupleSlot pointer to slot containing current "outer" tuple
|
||||
* ResultTupleSlot pointer to slot in tuple table for projected tuple
|
||||
* ExprContext node's current expression context
|
||||
* ProjInfo info this node uses to form tuple projections
|
||||
* NumScanAttributes size of ScanAttributes array
|
||||
* ScanAttributes attribute numbers of interest in this tuple
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct NestLoopState {
|
||||
JoinState jstate; /* its first field is NodeTag */
|
||||
bool nl_PortalFlag;
|
||||
} NestLoopState;
|
||||
|
||||
/* ----------------
|
||||
* MergeJoinState information
|
||||
*
|
||||
* OSortopI outerKey1 sortOp innerKey1 ...
|
||||
* ISortopO innerkey1 sortOp outerkey1 ...
|
||||
* JoinState current "state" of join. see executor.h
|
||||
* MarkedTupleSlot pointer to slot in tuple table for marked tuple
|
||||
*
|
||||
* JoinState information
|
||||
*
|
||||
* CommonState information
|
||||
*
|
||||
* OuterTupleSlot pointer to slot containing current "outer" tuple
|
||||
* ResultTupleSlot pointer to slot in tuple table for projected tuple
|
||||
* ExprContext node's current expression context
|
||||
* ProjInfo info this node uses to form tuple projections
|
||||
* NumScanAttributes size of ScanAttributes array
|
||||
* ScanAttributes attribute numbers of interest in this tuple
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct MergeJoinState {
|
||||
JoinState jstate; /* its first field is NodeTag */
|
||||
List *mj_OSortopI;
|
||||
List *mj_ISortopO;
|
||||
int mj_JoinState;
|
||||
TupleTableSlot *mj_MarkedTupleSlot;
|
||||
} MergeJoinState;
|
||||
|
||||
/* ----------------
|
||||
* HashJoinState information
|
||||
*
|
||||
* hj_HashTable address of the hash table for the hashjoin
|
||||
* hj_HashTableShmId shared memory id of hash table
|
||||
* hj_CurBucket the current hash bucket that we are searching
|
||||
* for matches of the current outer tuple
|
||||
* hj_CurTuple the current matching inner tuple in the
|
||||
* current hash bucket
|
||||
* hj_CurOTuple the current matching inner tuple in the
|
||||
* current hash overflow chain
|
||||
* hj_InnerHashKey the inner hash key in the hashjoin condition
|
||||
* hj_OuterBatches file descriptors for outer batches
|
||||
* hj_InnerBatches file descriptors for inner batches
|
||||
* hj_OuterReadPos current read position of outer batch
|
||||
* hj_OuterReadBlk current read block of outer batch
|
||||
* hj_OuterTupleSlot tuple slot for outer tuples
|
||||
* hj_HashTupleSlot tuple slot for hashed tuples
|
||||
*
|
||||
*
|
||||
*
|
||||
* JoinState information
|
||||
*
|
||||
* CommonState information
|
||||
*
|
||||
* OuterTupleSlot pointer to slot containing current "outer" tuple
|
||||
* ResultTupleSlot pointer to slot in tuple table for projected tuple
|
||||
* ExprContext node's current expression context
|
||||
* ProjInfo info this node uses to form tuple projections
|
||||
* NumScanAttributes size of ScanAttributes array
|
||||
* ScanAttributes attribute numbers of interest in this tuple
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct HashJoinState {
|
||||
JoinState jstate; /* its first field is NodeTag */
|
||||
HashJoinTable hj_HashTable;
|
||||
IpcMemoryId hj_HashTableShmId;
|
||||
HashBucket hj_CurBucket;
|
||||
HeapTuple hj_CurTuple;
|
||||
OverflowTuple hj_CurOTuple;
|
||||
Var *hj_InnerHashKey;
|
||||
File *hj_OuterBatches;
|
||||
File *hj_InnerBatches;
|
||||
char *hj_OuterReadPos;
|
||||
int hj_OuterReadBlk;
|
||||
TupleTableSlot *hj_OuterTupleSlot;
|
||||
TupleTableSlot *hj_HashTupleSlot;
|
||||
} HashJoinState;
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* Materialization State Information
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ----------------
|
||||
* MaterialState information
|
||||
*
|
||||
* materialize nodes are used to materialize the results
|
||||
* of a subplan into a temporary relation.
|
||||
*
|
||||
* Flag indicated whether subplan has been materialized
|
||||
* TempRelation temporary relation containing result of executing
|
||||
* the subplan.
|
||||
*
|
||||
* CommonScanState information
|
||||
*
|
||||
* currentRelation relation descriptor of sorted relation
|
||||
* currentScanDesc current scan descriptor for scan
|
||||
* ScanTupleSlot pointer to slot in tuple table holding scan tuple
|
||||
*
|
||||
* CommonState information
|
||||
*
|
||||
* OuterTupleSlot pointer to slot containing current "outer" tuple
|
||||
* ResultTupleSlot pointer to slot in tuple table for projected tuple
|
||||
* ExprContext node's current expression context
|
||||
* ProjInfo info this node uses to form tuple projections
|
||||
* NumScanAttributes size of ScanAttributes array
|
||||
* ScanAttributes attribute numbers of interest in this tuple
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct MaterialState {
|
||||
CommonScanState csstate; /* its first field is NodeTag */
|
||||
bool mat_Flag;
|
||||
Relation mat_TempRelation;
|
||||
} MaterialState;
|
||||
|
||||
/* ---------------------
|
||||
* AggregateState information
|
||||
*
|
||||
* done indicated whether aggregate has been materialized
|
||||
* -------------------------
|
||||
*/
|
||||
typedef struct AggState {
|
||||
CommonScanState csstate; /* its first field is NodeTag */
|
||||
bool agg_done;
|
||||
} AggState;
|
||||
|
||||
/* ---------------------
|
||||
* GroupState information
|
||||
*
|
||||
* -------------------------
|
||||
*/
|
||||
typedef struct GroupState {
|
||||
CommonScanState csstate; /* its first field is NodeTag */
|
||||
bool grp_useLastTuple; /* last tuple not processed yet */
|
||||
bool grp_done;
|
||||
TupleTableSlot *grp_lastSlot;
|
||||
} GroupState;
|
||||
|
||||
/* ----------------
|
||||
* SortState information
|
||||
*
|
||||
*| sort nodes are really just a kind of a scan since
|
||||
*| we implement sorts by retrieveing the entire subplan
|
||||
*| into a temp relation, sorting the temp relation into
|
||||
*| another sorted relation, and then preforming a simple
|
||||
*| unqualified sequential scan on the sorted relation..
|
||||
*| -cim 10/15/89
|
||||
*
|
||||
* Flag indicated whether relation has been sorted
|
||||
* Keys scan key structures used to keep info on sort keys
|
||||
* TempRelation temporary relation containing result of executing
|
||||
* the subplan.
|
||||
*
|
||||
* CommonScanState information
|
||||
*
|
||||
* currentRelation relation descriptor of sorted relation
|
||||
* currentScanDesc current scan descriptor for scan
|
||||
* ScanTupleSlot pointer to slot in tuple table holding scan tuple
|
||||
*
|
||||
* CommonState information
|
||||
*
|
||||
* OuterTupleSlot pointer to slot containing current "outer" tuple
|
||||
* ResultTupleSlot pointer to slot in tuple table for projected tuple
|
||||
* ExprContext node's current expression context
|
||||
* ProjInfo info this node uses to form tuple projections
|
||||
* NumScanAttributes size of ScanAttributes array
|
||||
* ScanAttributes attribute numbers of interest in this tuple
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct SortState {
|
||||
CommonScanState csstate; /* its first field is NodeTag */
|
||||
bool sort_Flag;
|
||||
ScanKey sort_Keys;
|
||||
Relation sort_TempRelation;
|
||||
} SortState;
|
||||
|
||||
/* ----------------
|
||||
* UniqueState information
|
||||
*
|
||||
* Unique nodes are used "on top of" sort nodes to discard
|
||||
* duplicate tuples returned from the sort phase. Basically
|
||||
* all it does is compare the current tuple from the subplan
|
||||
* with the previously fetched tuple stored in OuterTuple and
|
||||
* if the two are identical, then we just fetch another tuple
|
||||
* from the sort and try again.
|
||||
*
|
||||
* CommonState information
|
||||
*
|
||||
* OuterTupleSlot pointer to slot containing current "outer" tuple
|
||||
* ResultTupleSlot pointer to slot in tuple table for projected tuple
|
||||
* ExprContext node's current expression context
|
||||
* ProjInfo info this node uses to form tuple projections
|
||||
* NumScanAttributes size of ScanAttributes array
|
||||
* ScanAttributes attribute numbers of interest in this tuple
|
||||
* ----------------
|
||||
*/
|
||||
typedef CommonState UniqueState;
|
||||
|
||||
|
||||
/* ----------------
|
||||
* HashState information
|
||||
*
|
||||
* hashBatches file descriptors for the batches
|
||||
*
|
||||
* CommonState information
|
||||
*
|
||||
* OuterTupleSlot pointer to slot containing current "outer" tuple
|
||||
* ResultTupleSlot pointer to slot in tuple table for projected tuple
|
||||
* ExprContext node's current expression context
|
||||
* ProjInfo info this node uses to form tuple projections
|
||||
* NumScanAttributes size of ScanAttributes array
|
||||
* ScanAttributes attribute numbers of interest in this tuple
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct HashState {
|
||||
CommonState cstate; /* its first field is NodeTag */
|
||||
File *hashBatches;
|
||||
} HashState;
|
||||
|
||||
/* -----------------------
|
||||
* TeeState information
|
||||
* leftPlace : next item in the queue unseen by the left parent
|
||||
* rightPlace : next item in the queue unseen by the right parent
|
||||
* lastPlace : last item in the queue
|
||||
* bufferRelname : name of the relation used as the buffer queue
|
||||
* bufferRel : the relation used as the buffer queue
|
||||
* mcxt : for now, tee's have their own memory context
|
||||
* may be cleaned up later if portals are cleaned up
|
||||
*
|
||||
* initially, a Tee starts with [left/right]Place variables set to -1.
|
||||
* on cleanup, queue is free'd when both leftPlace and rightPlace = -1
|
||||
* -------------------------
|
||||
*/
|
||||
typedef struct TeeState {
|
||||
CommonState cstate; /* its first field is NodeTag */
|
||||
int tee_leftPlace;
|
||||
int tee_rightPlace;
|
||||
int tee_lastPlace;
|
||||
char *tee_bufferRelname;
|
||||
Relation tee_bufferRel;
|
||||
MemoryContext tee_mcxt;
|
||||
HeapScanDesc tee_leftScanDesc;
|
||||
HeapScanDesc tee_rightScanDesc;
|
||||
} TeeState;
|
||||
|
||||
#endif /* EXECNODES_H */
|
438
src/backend/nodes/list.c
Normal file
438
src/backend/nodes/list.c
Normal file
@ -0,0 +1,438 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* list.c--
|
||||
* various list handling routines
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.1.1.1 1996/07/09 06:21:32 scrappy Exp $
|
||||
*
|
||||
* NOTES
|
||||
* XXX a few of the following functions are duplicated to handle
|
||||
* List of pointers and List of integers separately. Some day,
|
||||
* someone should unify them. - ay 11/2/94
|
||||
* This file needs cleanup.
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
* Andrew Yu Oct, 1994 file creation
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include "postgres.h"
|
||||
#include "nodes/pg_list.h"
|
||||
#include "nodes/parsenodes.h"
|
||||
#include "utils/builtins.h" /* for namecpy */
|
||||
#include "utils/elog.h"
|
||||
#include "utils/palloc.h"
|
||||
|
||||
List *
|
||||
makeList(void *elem, ...)
|
||||
{
|
||||
va_list args;
|
||||
List *retval = NIL;
|
||||
List *temp = NIL;
|
||||
List *tempcons = NIL;
|
||||
|
||||
va_start(args, elem);
|
||||
|
||||
temp = elem;
|
||||
while (temp != (void *) -1) {
|
||||
temp = lcons(temp, NIL);
|
||||
if (tempcons == NIL)
|
||||
retval = temp;
|
||||
else
|
||||
lnext(tempcons) = temp;
|
||||
tempcons = temp;
|
||||
|
||||
temp = va_arg(args, void *);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
List *
|
||||
lcons(void *datum, List *list)
|
||||
{
|
||||
List *l = makeNode(List);
|
||||
lfirst(l) = datum;
|
||||
lnext(l) = list;
|
||||
return l;
|
||||
}
|
||||
|
||||
List *
|
||||
lappend(List *list, void *obj)
|
||||
{
|
||||
return nconc(list, lcons(obj, NIL));
|
||||
}
|
||||
|
||||
Value *
|
||||
makeInteger(long i)
|
||||
{
|
||||
Value *v = makeNode(Value);
|
||||
v->type = T_Integer;
|
||||
v->val.ival = i;
|
||||
return v;
|
||||
}
|
||||
|
||||
Value *
|
||||
makeFloat(double d)
|
||||
{
|
||||
Value *v = makeNode(Value);
|
||||
v->type = T_Float;
|
||||
v->val.dval = d;
|
||||
return v;
|
||||
}
|
||||
|
||||
Value *
|
||||
makeString(char *str)
|
||||
{
|
||||
Value *v = makeNode(Value);
|
||||
v->type = T_String;
|
||||
v->val.str = str;
|
||||
return v;
|
||||
}
|
||||
|
||||
/* n starts with 0 */
|
||||
void *
|
||||
nth(int n, List *l)
|
||||
{
|
||||
/* XXX assume list is long enough */
|
||||
while(n > 0) {
|
||||
l = lnext(l);
|
||||
n--;
|
||||
}
|
||||
return lfirst(l);
|
||||
}
|
||||
|
||||
/* this is here solely for rt_store. Get rid of me some day! */
|
||||
void
|
||||
set_nth(List *l, int n, void *elem)
|
||||
{
|
||||
/* XXX assume list is long enough */
|
||||
while(n > 0) {
|
||||
l = lnext(l);
|
||||
n--;
|
||||
}
|
||||
lfirst(l) = elem;
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
length(List *l)
|
||||
{
|
||||
int i=0;
|
||||
while(l!=NIL) {
|
||||
l = lnext(l);
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void
|
||||
freeList(List *list)
|
||||
{
|
||||
while(list!=NIL) {
|
||||
List *l = list;
|
||||
list = lnext(list);
|
||||
pfree(l);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* below are for backwards compatibility
|
||||
*/
|
||||
List *
|
||||
append(List *l1, List *l2)
|
||||
{
|
||||
List *newlist, *newlist2, *p;
|
||||
|
||||
if (l1==NIL)
|
||||
return copyObject(l2);
|
||||
|
||||
newlist = copyObject(l1);
|
||||
newlist2 = copyObject(l2);
|
||||
|
||||
for (p=newlist; lnext(p)!=NIL; p=lnext(p))
|
||||
;
|
||||
lnext(p) = newlist2;
|
||||
return newlist;
|
||||
}
|
||||
|
||||
/*
|
||||
* below are for backwards compatibility
|
||||
*/
|
||||
List *
|
||||
intAppend(List *l1, List *l2)
|
||||
{
|
||||
List *newlist, *newlist2, *p;
|
||||
|
||||
if (l1==NIL)
|
||||
return listCopy(l2);
|
||||
|
||||
newlist = listCopy(l1);
|
||||
newlist2 = listCopy(l2);
|
||||
|
||||
for (p=newlist; lnext(p)!=NIL; p=lnext(p))
|
||||
;
|
||||
lnext(p) = newlist2;
|
||||
return newlist;
|
||||
}
|
||||
|
||||
List *
|
||||
nconc(List *l1, List *l2)
|
||||
{
|
||||
List *temp;
|
||||
|
||||
if (l1 == NIL)
|
||||
return l2;
|
||||
if (l2 == NIL)
|
||||
return l1;
|
||||
if (l1 == l2)
|
||||
elog(WARN, "tryout to nconc a list to itself");
|
||||
|
||||
for (temp = l1; lnext(temp)!=NULL; temp = lnext(temp))
|
||||
;
|
||||
|
||||
lnext(temp) = l2;
|
||||
return(l1); /* list1 is now list1[]list2 */
|
||||
}
|
||||
|
||||
|
||||
List *
|
||||
nreverse(List *list)
|
||||
{
|
||||
List *rlist = NIL;
|
||||
List *p = NIL;
|
||||
|
||||
if(list==NULL)
|
||||
return(NIL);
|
||||
|
||||
if (length(list) == 1)
|
||||
return(list);
|
||||
|
||||
for (p = list; p!=NULL; p = lnext(p)) {
|
||||
rlist = lcons(lfirst(p),rlist);
|
||||
}
|
||||
|
||||
lfirst(list) = lfirst(rlist);
|
||||
lnext(list) = lnext(rlist);
|
||||
return(list);
|
||||
}
|
||||
|
||||
/*
|
||||
* same
|
||||
*
|
||||
* Returns t if two lists contain the same elements.
|
||||
* now defined in lispdep.c
|
||||
*
|
||||
* XXX only good for IntList -ay
|
||||
*/
|
||||
bool
|
||||
same(List *foo, List *bar)
|
||||
{
|
||||
List *temp = NIL;
|
||||
|
||||
if (foo == NULL)
|
||||
return (bar==NULL);
|
||||
if (bar == NULL)
|
||||
return (foo==NULL);
|
||||
if (length(foo) == length(bar)) {
|
||||
foreach (temp,foo) {
|
||||
if (!intMember((int)lfirst(temp),bar))
|
||||
return(false);
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
return(false);
|
||||
|
||||
}
|
||||
|
||||
List *
|
||||
LispUnion(List *foo, List *bar)
|
||||
{
|
||||
List *retval = NIL;
|
||||
List *i = NIL;
|
||||
List *j = NIL;
|
||||
|
||||
if (foo==NIL)
|
||||
return(bar); /* XXX - should be copy of bar */
|
||||
|
||||
if (bar==NIL)
|
||||
return(foo); /* XXX - should be copy of foo */
|
||||
|
||||
foreach (i,foo) {
|
||||
foreach (j,bar) {
|
||||
if (! equal(lfirst(i), lfirst(j))) {
|
||||
retval = lappend(retval,lfirst(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach(i,bar) {
|
||||
retval = lappend(retval,lfirst(i));
|
||||
}
|
||||
|
||||
return(retval);
|
||||
}
|
||||
|
||||
List *
|
||||
LispUnioni(List *foo, List *bar)
|
||||
{
|
||||
List *retval = NIL;
|
||||
List *i = NIL;
|
||||
List *j = NIL;
|
||||
|
||||
if (foo==NIL)
|
||||
return(bar); /* XXX - should be copy of bar */
|
||||
|
||||
if (bar==NIL)
|
||||
return(foo); /* XXX - should be copy of foo */
|
||||
|
||||
foreach (i,foo) {
|
||||
foreach (j,bar) {
|
||||
if (lfirsti(i) != lfirsti(j)) {
|
||||
retval = lappendi(retval,lfirst(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach(i,bar) {
|
||||
retval = lappendi(retval, lfirsti(i));
|
||||
}
|
||||
|
||||
return(retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* member()
|
||||
* - nondestructive, returns t iff foo is a member of the list
|
||||
* bar
|
||||
*/
|
||||
bool
|
||||
member(void *foo, List *bar)
|
||||
{
|
||||
List *i;
|
||||
foreach (i,bar)
|
||||
if (equal((Node*)(lfirst(i)),(Node*)foo))
|
||||
return(true);
|
||||
return(false);
|
||||
}
|
||||
|
||||
bool
|
||||
intMember(int foo, List *bar)
|
||||
{
|
||||
List *i;
|
||||
foreach (i,bar)
|
||||
if (foo == (int)lfirst(i))
|
||||
return(true);
|
||||
return(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* lremove -
|
||||
* only does pointer comparisons. Removes 'elem' from the the linked list.
|
||||
*/
|
||||
List *
|
||||
lremove(void *elem, List *list)
|
||||
{
|
||||
List *l;
|
||||
List *prev = NIL;
|
||||
List *result = list;
|
||||
|
||||
foreach(l, list) {
|
||||
if (elem == lfirst(l))
|
||||
break;
|
||||
prev = l;
|
||||
}
|
||||
if (l!=NULL) {
|
||||
if (prev == NIL) {
|
||||
result = lnext(list);
|
||||
} else {
|
||||
lnext(prev) = lnext(l);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
List *
|
||||
LispRemove(void *elem, List *list)
|
||||
{
|
||||
List *temp = NIL;
|
||||
List *prev = NIL;
|
||||
|
||||
if (equal(elem, lfirst(list)))
|
||||
return lnext(list);
|
||||
|
||||
temp = lnext(list);
|
||||
prev = list;
|
||||
while(temp!=NIL) {
|
||||
if (equal(elem, lfirst(temp))) {
|
||||
lnext(prev) = lnext(temp);
|
||||
break;
|
||||
}
|
||||
temp = lnext(temp);
|
||||
prev = lnext(prev);
|
||||
}
|
||||
return(list);
|
||||
}
|
||||
|
||||
List *
|
||||
intLispRemove(int elem, List *list)
|
||||
{
|
||||
List *temp = NIL;
|
||||
List *prev = NIL;
|
||||
|
||||
if (elem == (int)lfirst(list))
|
||||
return lnext(list);
|
||||
|
||||
temp = lnext(list);
|
||||
prev = list;
|
||||
while(temp!=NIL) {
|
||||
if (elem == (int)lfirst(temp)) {
|
||||
lnext(prev) = lnext(temp);
|
||||
break;
|
||||
}
|
||||
temp = lnext(temp);
|
||||
prev = lnext(prev);
|
||||
}
|
||||
return(list);
|
||||
}
|
||||
|
||||
List *
|
||||
set_difference(List *list1, List *list2)
|
||||
{
|
||||
List *temp1 = NIL;
|
||||
List *result = NIL;
|
||||
|
||||
if (list2==NIL)
|
||||
return(list1);
|
||||
|
||||
foreach (temp1, list1) {
|
||||
if (!member(lfirst(temp1), list2))
|
||||
result = lappend(result, lfirst(temp1));
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
List *
|
||||
set_differencei(List *list1, List *list2)
|
||||
{
|
||||
List *temp1 = NIL;
|
||||
List *result = NIL;
|
||||
|
||||
if (list2==NIL)
|
||||
return(list1);
|
||||
|
||||
foreach (temp1, list1) {
|
||||
if (!intMember(lfirsti(temp1), list2))
|
||||
result = lappendi(result, lfirst(temp1));
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
117
src/backend/nodes/makefuncs.c
Normal file
117
src/backend/nodes/makefuncs.c
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* makefuncs.c--
|
||||
* creator functions for primitive nodes. The functions here are for
|
||||
* the most frequently created nodes.
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.1.1.1 1996/07/09 06:21:32 scrappy Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Creator functions in POSTGRES 4.2 are generated automatically. Most of
|
||||
* them are rarely used. Now we don't generate them any more. If you want
|
||||
* one, you have to write it yourself.
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
* Andrew Yu Oct 20, 1994 file creation
|
||||
*/
|
||||
#include "postgres.h"
|
||||
#include "nodes/pg_list.h"
|
||||
#include "nodes/primnodes.h"
|
||||
#include "nodes/makefuncs.h"
|
||||
|
||||
/*
|
||||
* makeOper -
|
||||
* creates an Oper node
|
||||
*/
|
||||
Oper *
|
||||
makeOper(Oid opno,
|
||||
Oid opid,
|
||||
Oid opresulttype,
|
||||
int opsize,
|
||||
FunctionCachePtr op_fcache)
|
||||
{
|
||||
Oper *oper = makeNode(Oper);
|
||||
|
||||
oper->opno = opno;
|
||||
oper->opid = opid;
|
||||
oper->opresulttype = opresulttype;
|
||||
oper->opsize = opsize;
|
||||
oper->op_fcache = op_fcache;
|
||||
return oper;
|
||||
}
|
||||
|
||||
/*
|
||||
* makeVar -
|
||||
* creates a Var node
|
||||
*
|
||||
*/
|
||||
Var *
|
||||
makeVar(Index varno,
|
||||
AttrNumber varattno,
|
||||
Oid vartype,
|
||||
Index varnoold,
|
||||
AttrNumber varoattno)
|
||||
{
|
||||
Var *var = makeNode(Var);
|
||||
|
||||
var->varno = varno;
|
||||
var->varattno = varattno;
|
||||
var->vartype = vartype;
|
||||
var->varnoold = varnoold;
|
||||
var->varoattno = varoattno;
|
||||
|
||||
return var;
|
||||
}
|
||||
|
||||
/*
|
||||
* makeResdom -
|
||||
* creates a Resdom (Result Domain) node
|
||||
*/
|
||||
Resdom *
|
||||
makeResdom(AttrNumber resno,
|
||||
Oid restype,
|
||||
int reslen,
|
||||
char *resname,
|
||||
Index reskey,
|
||||
Oid reskeyop,
|
||||
int resjunk)
|
||||
{
|
||||
Resdom *resdom = makeNode(Resdom);
|
||||
|
||||
resdom->resno = resno;
|
||||
resdom->restype = restype;
|
||||
resdom->reslen = reslen;
|
||||
resdom->resname = resname;
|
||||
resdom->reskey = reskey;
|
||||
resdom->reskeyop = reskeyop;
|
||||
resdom->resjunk = resjunk;
|
||||
return resdom;
|
||||
}
|
||||
|
||||
/*
|
||||
* makeConst -
|
||||
* creates a Const node
|
||||
*/
|
||||
Const *
|
||||
makeConst(Oid consttype,
|
||||
Size constlen,
|
||||
Datum constvalue,
|
||||
bool constisnull,
|
||||
bool constbyval,
|
||||
bool constisset)
|
||||
{
|
||||
Const *cnst = makeNode(Const);
|
||||
|
||||
cnst->consttype = consttype;
|
||||
cnst->constlen = constlen;
|
||||
cnst->constvalue = constvalue;
|
||||
cnst->constisnull = constisnull;
|
||||
cnst->constbyval = constbyval;
|
||||
cnst->constisset = constisset;
|
||||
return cnst;
|
||||
}
|
||||
|
48
src/backend/nodes/makefuncs.h
Normal file
48
src/backend/nodes/makefuncs.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* makefuncs.h--
|
||||
* prototypes for the creator functions (for primitive nodes)
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: makefuncs.h,v 1.1.1.1 1996/07/09 06:21:32 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef MAKEFUNC_H
|
||||
#define MAKEFUNC_H
|
||||
|
||||
#include "access/attnum.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "utils/fcache.h"
|
||||
#include "nodes/primnodes.h"
|
||||
|
||||
extern Oper *makeOper(Oid opno,
|
||||
Oid opid,
|
||||
Oid opresulttype,
|
||||
int opsize,
|
||||
FunctionCachePtr op_fcache);
|
||||
|
||||
extern Var *makeVar(Index varno,
|
||||
AttrNumber varattno,
|
||||
Oid vartype,
|
||||
Index varnoold,
|
||||
AttrNumber varoattno);
|
||||
|
||||
extern Resdom *makeResdom(AttrNumber resno,
|
||||
Oid restype,
|
||||
int reslen,
|
||||
char *resname,
|
||||
Index reskey,
|
||||
Oid reskeyop,
|
||||
int resjunk);
|
||||
|
||||
extern Const *makeConst(Oid consttype,
|
||||
Size constlen,
|
||||
Datum constvalue,
|
||||
bool constisnull,
|
||||
bool constbyval,
|
||||
bool constisset);
|
||||
|
||||
#endif /* MAKEFUNC_H */
|
101
src/backend/nodes/memnodes.h
Normal file
101
src/backend/nodes/memnodes.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* memnodes.h--
|
||||
* POSTGRES memory context node definitions.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: memnodes.h,v 1.1.1.1 1996/07/09 06:21:32 scrappy Exp $
|
||||
*
|
||||
* XXX the typedefs in this file are different from the other ???nodes.h;
|
||||
* they are pointers to structures instead of the structures themselves.
|
||||
* If you're wondering, this is plain laziness. I don't want to touch
|
||||
* the memory context code which should be revamped altogether some day.
|
||||
* - ay 10/94
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef MEMNODES_H
|
||||
#define MEMNODES_H
|
||||
|
||||
#include "c.h"
|
||||
|
||||
#include "utils/memutils.h"
|
||||
#include "lib/fstack.h"
|
||||
|
||||
#include "nodes/nodes.h"
|
||||
|
||||
/*
|
||||
* MemoryContext --
|
||||
* A logical context in which memory allocations occur.
|
||||
*
|
||||
* The types of memory contexts can be thought of as members of the
|
||||
* following inheritance hierarchy with properties summarized below.
|
||||
*
|
||||
* Node
|
||||
* |
|
||||
* MemoryContext___
|
||||
* / \
|
||||
* GlobalMemory PortalMemoryContext
|
||||
* / \
|
||||
* PortalVariableMemory PortalHeapMemory
|
||||
*
|
||||
* Flushed at Flushed at Checkpoints
|
||||
* Transaction Portal
|
||||
* Commit Close
|
||||
*
|
||||
* GlobalMemory n n n
|
||||
* PortalVariableMemory n y n
|
||||
* PortalHeapMemory y y y
|
||||
*/
|
||||
|
||||
typedef struct MemoryContextMethodsData {
|
||||
Pointer (*alloc)();
|
||||
void (*free_p)(); /* need to use free as a #define,
|
||||
so can't use free */
|
||||
Pointer (*realloc)();
|
||||
char* (*getName)();
|
||||
void (*dump)();
|
||||
} *MemoryContextMethods;
|
||||
|
||||
typedef struct MemoryContext {
|
||||
NodeTag type;
|
||||
MemoryContextMethods method;
|
||||
} *MemoryContext;
|
||||
|
||||
/* think about doing this right some time but we'll have explicit fields
|
||||
for now -ay 10/94 */
|
||||
typedef struct GlobalMemory {
|
||||
NodeTag type;
|
||||
MemoryContextMethods method;
|
||||
AllocSetData setData;
|
||||
char *name;
|
||||
OrderedElemData elemData;
|
||||
} *GlobalMemory;
|
||||
|
||||
typedef MemoryContext *PortalMemoryContext;
|
||||
|
||||
typedef struct PortalVariableMemory {
|
||||
NodeTag type;
|
||||
MemoryContextMethods method;
|
||||
AllocSetData setData;
|
||||
} *PortalVariableMemory;
|
||||
|
||||
typedef struct PortalHeapMemory {
|
||||
NodeTag type;
|
||||
MemoryContextMethods method;
|
||||
Pointer block;
|
||||
FixedStackData stackData;
|
||||
} *PortalHeapMemory;
|
||||
|
||||
/*
|
||||
* MemoryContextIsValid --
|
||||
* True iff memory context is valid.
|
||||
*/
|
||||
#define MemoryContextIsValid(context) \
|
||||
(IsA(context,MemoryContext) || IsA(context,GlobalMemory) || \
|
||||
IsA(context,PortalVariableMemory) || IsA(context,PortalHeapMemory))
|
||||
|
||||
#endif /* MEMNODES_H */
|
||||
|
||||
|
116
src/backend/nodes/nodeFuncs.c
Normal file
116
src/backend/nodes/nodeFuncs.c
Normal file
@ -0,0 +1,116 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* nodeFuncs.c--
|
||||
* All node routines more complicated than simple access/modification
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/nodeFuncs.c,v 1.1.1.1 1996/07/09 06:21:32 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "c.h"
|
||||
|
||||
#include "nodes/primnodes.h"
|
||||
#include "nodes/plannodes.h"
|
||||
#include "nodes/pg_list.h"
|
||||
#include "nodes/relation.h"
|
||||
#include "nodes/nodeFuncs.h"
|
||||
#include "utils/lsyscache.h"
|
||||
|
||||
/*
|
||||
* single_node -
|
||||
* Returns t if node corresponds to a single-noded expression
|
||||
*/
|
||||
bool
|
||||
single_node(Node *node)
|
||||
{
|
||||
if(IsA(node,Ident) || IsA(node,Const) || IsA(node,Var) || IsA(node,Param))
|
||||
return(true);
|
||||
else
|
||||
return(false);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* VAR nodes
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* var_is_outer
|
||||
* var_is_inner
|
||||
* var_is_mat
|
||||
* var_is_rel
|
||||
*
|
||||
* Returns t iff the var node corresponds to (respectively):
|
||||
* the outer relation in a join
|
||||
* the inner relation of a join
|
||||
* a materialized relation
|
||||
* a base relation (i.e., not an attribute reference, a variable from
|
||||
* some lower join level, or a sort result)
|
||||
* var node is an array reference
|
||||
*
|
||||
*/
|
||||
bool
|
||||
var_is_outer (Var *var)
|
||||
{
|
||||
return((bool)(var->varno == OUTER));
|
||||
}
|
||||
|
||||
bool
|
||||
var_is_inner (Var *var)
|
||||
{
|
||||
return ( (bool) (var->varno == INNER));
|
||||
}
|
||||
|
||||
bool
|
||||
var_is_rel (Var *var)
|
||||
{
|
||||
return (bool)
|
||||
! (var_is_inner (var) || var_is_outer (var));
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* OPER nodes
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* replace_opid -
|
||||
*
|
||||
* Given a oper node, resets the opfid field with the
|
||||
* procedure OID (regproc id).
|
||||
*
|
||||
* Returns the modified oper node.
|
||||
*
|
||||
*/
|
||||
Oper *
|
||||
replace_opid (Oper *oper)
|
||||
{
|
||||
oper->opid = get_opcode(oper->opno);
|
||||
oper->op_fcache = NULL;
|
||||
return(oper);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* constant (CONST, PARAM) nodes
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* non_null -
|
||||
* Returns t if the node is a non-null constant, e.g., if the node has a
|
||||
* valid `constvalue' field.
|
||||
*
|
||||
*/
|
||||
bool
|
||||
non_null (Expr *c)
|
||||
{
|
||||
|
||||
if ( IsA(c,Const) && ! ((Const*)c)->constisnull )
|
||||
return(true);
|
||||
else
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
|
23
src/backend/nodes/nodeFuncs.h
Normal file
23
src/backend/nodes/nodeFuncs.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* nodeFuncs.h--
|
||||
*
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: nodeFuncs.h,v 1.1.1.1 1996/07/09 06:21:32 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef NODEFUNCS_H
|
||||
#define NODEFUNCS_H
|
||||
|
||||
extern bool single_node(Node *node);
|
||||
extern bool var_is_outer(Var *var);
|
||||
extern bool var_is_inner(Var *var);
|
||||
extern bool var_is_rel(Var *var);
|
||||
extern Oper *replace_opid(Oper *oper);
|
||||
extern bool non_null(Expr *c);
|
||||
|
||||
#endif /* NODEFUNCS_H */
|
45
src/backend/nodes/nodes.c
Normal file
45
src/backend/nodes/nodes.c
Normal file
@ -0,0 +1,45 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* nodes.c--
|
||||
* support code for nodes (now that we get rid of the home-brew
|
||||
* inheritance system, our support code for nodes get much simpler)
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/nodes.c,v 1.1.1.1 1996/07/09 06:21:33 scrappy Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* Andrew Yu Oct 20, 1994 file creation
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "postgres.h"
|
||||
#include "utils/palloc.h"
|
||||
#include "utils/elog.h"
|
||||
#include "nodes/nodes.h" /* where func declarations of this file goes */
|
||||
|
||||
/*
|
||||
* newNode -
|
||||
* create a new node of the specified size and tag the node with the
|
||||
* specified tag.
|
||||
*
|
||||
* !WARNING!: Avoid using newNode directly. You should be using the
|
||||
* macro makeNode. eg. to create a Resdom node, use makeNode(Resdom)
|
||||
*
|
||||
*/
|
||||
Node *
|
||||
newNode(Size size, NodeTag tag)
|
||||
{
|
||||
Node *newNode;
|
||||
|
||||
Assert(size >= 4); /* need the tag, at least */
|
||||
|
||||
newNode = (Node *)palloc(size);
|
||||
memset((char *)newNode, 0, size);
|
||||
newNode->type = tag;
|
||||
return(newNode);
|
||||
}
|
||||
|
299
src/backend/nodes/nodes.h
Normal file
299
src/backend/nodes/nodes.h
Normal file
@ -0,0 +1,299 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* nodes.h--
|
||||
* Definitions for tagged nodes.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: nodes.h,v 1.1.1.1 1996/07/09 06:21:33 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef NODES_H
|
||||
#define NODES_H
|
||||
|
||||
#include "c.h"
|
||||
|
||||
/*
|
||||
* The first field of every node is NodeTag. Each node created (with makeNode)
|
||||
* will have one of the following tags as the value of its first field.
|
||||
*
|
||||
* Note that the number of the node tags are not contiguous. We left holes
|
||||
* here so that we can add more tags without changing the existing enum's.
|
||||
*/
|
||||
typedef enum NodeTag {
|
||||
T_Invalid = 0,
|
||||
|
||||
/*---------------------
|
||||
* TAGS FOR PLAN NODES (plannodes.h)
|
||||
*---------------------
|
||||
*/
|
||||
T_Plan = 10,
|
||||
T_Existential,
|
||||
T_Result,
|
||||
T_Append,
|
||||
T_Scan,
|
||||
T_SeqScan,
|
||||
T_IndexScan,
|
||||
T_Join,
|
||||
T_NestLoop,
|
||||
T_MergeJoin,
|
||||
T_HashJoin,
|
||||
T_Temp,
|
||||
T_Material,
|
||||
T_Sort,
|
||||
T_Agg,
|
||||
T_Unique,
|
||||
T_Hash,
|
||||
T_Choose,
|
||||
T_Tee,
|
||||
T_Group,
|
||||
|
||||
/*---------------------
|
||||
* TAGS FOR PRIMITIVE NODES (primnodes.h)
|
||||
*---------------------
|
||||
*/
|
||||
T_Resdom = 100,
|
||||
T_Fjoin,
|
||||
T_Expr,
|
||||
T_Var,
|
||||
T_Oper,
|
||||
T_Const,
|
||||
T_Param,
|
||||
T_Aggreg,
|
||||
T_Func,
|
||||
T_Array,
|
||||
T_ArrayRef,
|
||||
|
||||
/*---------------------
|
||||
* TAGS FOR INNER PLAN NODES (relation.h)
|
||||
*---------------------
|
||||
*/
|
||||
T_Rel = 200,
|
||||
T_Path,
|
||||
T_IndexPath,
|
||||
T_JoinPath,
|
||||
T_MergePath,
|
||||
T_HashPath,
|
||||
T_OrderKey,
|
||||
T_JoinKey,
|
||||
T_MergeOrder,
|
||||
T_CInfo,
|
||||
T_JoinMethod,
|
||||
T_HInfo,
|
||||
T_MInfo,
|
||||
T_JInfo,
|
||||
T_Iter,
|
||||
T_Stream,
|
||||
|
||||
/*---------------------
|
||||
* TAGS FOR EXECUTOR NODES (execnodes.h)
|
||||
*---------------------
|
||||
*/
|
||||
T_IndexInfo = 300,
|
||||
T_RelationInfo,
|
||||
T_TupleCount,
|
||||
T_TupleTableSlot,
|
||||
T_ExprContext,
|
||||
T_ProjectionInfo,
|
||||
T_JunkFilter,
|
||||
T_EState,
|
||||
T_BaseNode,
|
||||
T_CommonState,
|
||||
T_ResultState,
|
||||
T_AppendState,
|
||||
T_CommonScanState,
|
||||
T_ScanState,
|
||||
T_IndexScanState,
|
||||
T_JoinState,
|
||||
T_NestLoopState,
|
||||
T_MergeJoinState,
|
||||
T_HashJoinState,
|
||||
T_MaterialState,
|
||||
T_AggState,
|
||||
T_GroupState,
|
||||
T_SortState,
|
||||
T_UniqueState,
|
||||
T_HashState,
|
||||
T_TeeState,
|
||||
|
||||
/*---------------------
|
||||
* TAGS FOR MEMORY NODES (memnodes.h)
|
||||
*---------------------
|
||||
*/
|
||||
T_MemoryContext = 400,
|
||||
T_GlobalMemory,
|
||||
T_PortalMemoryContext,
|
||||
T_PortalVariableMemory,
|
||||
T_PortalHeapMemory,
|
||||
|
||||
/*---------------------
|
||||
* TAGS FOR VALUE NODES (pg_list.h)
|
||||
*---------------------
|
||||
*/
|
||||
T_Value = 500,
|
||||
T_List,
|
||||
T_Integer,
|
||||
T_Float,
|
||||
T_String,
|
||||
T_Null,
|
||||
|
||||
/*---------------------
|
||||
* TAGS FOR PARSE TREE NODES (parsenode.h)
|
||||
*---------------------
|
||||
*/
|
||||
T_Query = 600,
|
||||
T_AppendStmt,
|
||||
T_DeleteStmt,
|
||||
T_ReplaceStmt,
|
||||
T_CursorStmt,
|
||||
T_RetrieveStmt,
|
||||
T_AddAttrStmt,
|
||||
T_AggregateStmt,
|
||||
T_ChangeACLStmt,
|
||||
T_ClosePortalStmt,
|
||||
T_ClusterStmt,
|
||||
T_CopyStmt,
|
||||
T_CreateStmt,
|
||||
T_VersionStmt,
|
||||
T_DefineStmt,
|
||||
T_DestroyStmt,
|
||||
T_ExtendStmt,
|
||||
T_FetchStmt,
|
||||
T_IndexStmt,
|
||||
T_MoveStmt,
|
||||
T_ProcedureStmt,
|
||||
T_PurgeStmt,
|
||||
T_RecipeStmt,
|
||||
T_RemoveFuncStmt,
|
||||
T_RemoveOperStmt,
|
||||
T_RemoveStmt,
|
||||
T_RenameStmt,
|
||||
T_RuleStmt,
|
||||
T_NotifyStmt,
|
||||
T_ListenStmt,
|
||||
T_TransactionStmt,
|
||||
T_ViewStmt,
|
||||
T_LoadStmt,
|
||||
T_CreatedbStmt,
|
||||
T_DestroydbStmt,
|
||||
T_VacuumStmt,
|
||||
T_ExplainStmt,
|
||||
|
||||
T_A_Expr = 700,
|
||||
T_Attr,
|
||||
T_A_Const,
|
||||
T_ParamNo,
|
||||
T_Ident,
|
||||
T_FuncCall,
|
||||
T_A_Indices,
|
||||
T_ResTarget,
|
||||
T_ParamString,
|
||||
T_TimeRange,
|
||||
T_RelExpr,
|
||||
T_SortBy,
|
||||
T_RangeVar,
|
||||
T_TypeName,
|
||||
T_IndexElem,
|
||||
T_ColumnDef,
|
||||
T_DefElem,
|
||||
T_TargetEntry,
|
||||
T_RangeTblEntry,
|
||||
T_SortClause,
|
||||
T_GroupClause
|
||||
} NodeTag;
|
||||
|
||||
/*
|
||||
* The first field of a node of any type is gauranteed to be the NodeTag.
|
||||
* Hence the type of any node can be gotten by casting it to Node. Declaring
|
||||
* a variable to be of Node * (instead of void *) can also facilitate
|
||||
* debugging.
|
||||
*/
|
||||
typedef struct Node {
|
||||
NodeTag type;
|
||||
} Node;
|
||||
|
||||
#define nodeTag(_node_) ((Node*)_node_)->type
|
||||
|
||||
#define makeNode(_node_) (_node_*)newNode(sizeof(_node_),T_##_node_)
|
||||
#define NodeSetTag(n, t) ((Node *)n)->type = t
|
||||
|
||||
#define IsA(_node_,_tag_) (nodeTag(_node_) == T_##_tag_)
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* IsA functions (no inheritence any more)
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
#define IsA_JoinPath(jp) \
|
||||
(nodeTag(jp)==T_JoinPath || nodeTag(jp)==T_MergePath || \
|
||||
nodeTag(jp)==T_HashPath)
|
||||
|
||||
#define IsA_Join(j) \
|
||||
(nodeTag(j)==T_Join || nodeTag(j)==T_NestLoop || \
|
||||
nodeTag(j)==T_MergeJoin || nodeTag(j)==T_HashJoin)
|
||||
|
||||
#define IsA_Temp(t) \
|
||||
(nodeTag(t)==T_Temp || nodeTag(t)==T_Material || nodeTag(t)==T_Sort || \
|
||||
nodeTag(t)==T_Unique)
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* extern declarations follow
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* nodes/nodes.c
|
||||
*/
|
||||
extern Node *newNode(Size size, NodeTag tag);
|
||||
|
||||
/*
|
||||
* nodes/{outfuncs.c,print.c}
|
||||
*/
|
||||
#define nodeDisplay print
|
||||
|
||||
extern char *nodeToString(void *obj);
|
||||
extern void print(void *obj);
|
||||
|
||||
/*
|
||||
* nodes/{readfuncs.c,read.c}
|
||||
*/
|
||||
extern void *stringToNode(char *str);
|
||||
|
||||
/*
|
||||
* nodes/copyfuncs.c
|
||||
*/
|
||||
extern void *copyObject(void *obj);
|
||||
|
||||
/*
|
||||
* nodes/equalfuncs.c
|
||||
*/
|
||||
extern bool equal(void *a, void *b);
|
||||
|
||||
|
||||
/* ----------------
|
||||
* I don't know why this is here. Most likely a hack..
|
||||
* -cim 6/3/90
|
||||
* ----------------
|
||||
*/
|
||||
typedef float Cost;
|
||||
|
||||
/*
|
||||
* CmdType -
|
||||
* enums for type of operation to aid debugging
|
||||
*
|
||||
* ??? could have put this in parsenodes.h but many files not in the
|
||||
* optimizer also need this...
|
||||
*/
|
||||
typedef enum CmdType {
|
||||
CMD_UNKNOWN,
|
||||
CMD_SELECT, /* select stmt (formerly retrieve) */
|
||||
CMD_UPDATE, /* update stmt (formerly replace) */
|
||||
CMD_INSERT, /* insert stmt (formerly append) */
|
||||
CMD_DELETE,
|
||||
CMD_NOTIFY,
|
||||
CMD_UTILITY /* cmds like create, destroy, copy, vacuum, etc. */
|
||||
} CmdType;
|
||||
|
||||
|
||||
#endif /* NODES_H */
|
1670
src/backend/nodes/outfuncs.c
Normal file
1670
src/backend/nodes/outfuncs.c
Normal file
File diff suppressed because it is too large
Load Diff
90
src/backend/nodes/params.h
Normal file
90
src/backend/nodes/params.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* params.h--
|
||||
* Declarations/definitions of stuff needed to handle parameterized plans.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: params.h,v 1.1.1.1 1996/07/09 06:21:33 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef PARAMS_H
|
||||
#define PARAMS_H
|
||||
|
||||
#include "postgres.h"
|
||||
#include "access/attnum.h"
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
*
|
||||
* The following are the possible values for the 'paramkind'
|
||||
* field of a Param node.
|
||||
*
|
||||
* PARAM_NAMED: The parameter has a name, i.e. something
|
||||
* like `$.salary' or `$.foobar'.
|
||||
* In this case field `paramname' must be a valid Name.
|
||||
* and field `paramid' must be == 0.
|
||||
*
|
||||
* PARAM_NUM: The parameter has only a numeric identifier,
|
||||
* i.e. something like `$1', `$2' etc.
|
||||
* The number is contained in the `parmid' field.
|
||||
*
|
||||
* PARAM_NEW: Used in PRS2 rule, similar to PARAM_NAMED.
|
||||
* The `paramname' & `paramid' refer to the "NEW" tuple
|
||||
* `paramname' is the attribute name and `paramid' its
|
||||
* attribute number.
|
||||
*
|
||||
* PARAM_OLD: Same as PARAM_NEW, but in this case we refer to
|
||||
* the "OLD" tuple.
|
||||
*/
|
||||
|
||||
#define PARAM_NAMED 11
|
||||
#define PARAM_NUM 12
|
||||
#define PARAM_NEW 13
|
||||
#define PARAM_OLD 14
|
||||
#define PARAM_INVALID 100
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ParamListInfo
|
||||
*
|
||||
* Information needed in order for the executor to handle
|
||||
* parameterized plans (you know, $.salary, $.name etc. stuff...).
|
||||
*
|
||||
* ParamListInfoData contains information needed when substituting a
|
||||
* Param node with a Const node.
|
||||
*
|
||||
* kind : the kind of parameter.
|
||||
* name : the parameter name (valid if kind == PARAM_NAMED,
|
||||
* PARAM_NEW or PARAM_OLD)
|
||||
* id : the parameter id (valid if kind == PARAM_NUM)
|
||||
* or the attrno (if kind == PARAM_NEW or PARAM_OLD)
|
||||
* type : PG_TYPE OID of the value
|
||||
* length : length in bytes of the value
|
||||
* isnull : true if & only if the value is null (if true then
|
||||
* the fields 'length' and 'value' are undefined).
|
||||
* value : the value that has to be substituted in the place
|
||||
* of the parameter.
|
||||
*
|
||||
* ParamListInfo is to be used as an array of ParamListInfoData
|
||||
* records. An 'InvalidName' in the name field of such a record
|
||||
* indicates that this is the last record in the array.
|
||||
*
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
typedef struct ParamListInfoData {
|
||||
int kind;
|
||||
char *name;
|
||||
AttrNumber id;
|
||||
Oid type;
|
||||
Size length;
|
||||
bool isnull;
|
||||
bool byval;
|
||||
Datum value;
|
||||
} ParamListInfoData;
|
||||
|
||||
typedef ParamListInfoData *ParamListInfo;
|
||||
|
||||
#endif /* PARAMS_H */
|
731
src/backend/nodes/parsenodes.h
Normal file
731
src/backend/nodes/parsenodes.h
Normal file
@ -0,0 +1,731 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* parsenodes.h--
|
||||
* definitions for parse tree nodes
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: parsenodes.h,v 1.1.1.1 1996/07/09 06:21:33 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef PARSENODES_H
|
||||
#define PARSENODES_H
|
||||
|
||||
#include "nodes/nodes.h"
|
||||
#include "nodes/pg_list.h"
|
||||
#include "nodes/primnodes.h"
|
||||
#include "utils/tqual.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Query Tree
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Query -
|
||||
* all statments are turned into a Query tree (via transformStmt)
|
||||
* for further processing by the optimizer
|
||||
* utility statements (i.e. non-optimizable statements)
|
||||
* have the *utilityStmt field set.
|
||||
*
|
||||
* we need the isPortal flag because portal names can be null too; can
|
||||
* get rid of it if we support CURSOR as a commandType.
|
||||
*
|
||||
*/
|
||||
typedef struct Query {
|
||||
NodeTag type;
|
||||
|
||||
CmdType commandType; /* select|insert|update|delete|utility */
|
||||
|
||||
Node *utilityStmt; /* non-null if this is a non-optimizable
|
||||
statement */
|
||||
|
||||
int resultRelation; /* target relation (index to rtable) */
|
||||
char *into; /* portal (cursor) name */
|
||||
bool isPortal; /* is this a retrieve into portal? */
|
||||
bool isBinary; /* binary portal? */
|
||||
|
||||
char *uniqueFlag; /* NULL, '*', or Unique attribute name */
|
||||
List *sortClause; /* a list of SortClause's */
|
||||
|
||||
List *rtable; /* list of range table entries */
|
||||
List *targetList; /* target list (of TargetEntry) */
|
||||
Node *qual; /* qualifications */
|
||||
|
||||
List *groupClause; /* list of columns to specified in GROUP BY */
|
||||
Node *havingQual; /* qualification of each group */
|
||||
|
||||
int qry_numAgg; /* number of aggregates in the target list */
|
||||
Aggreg **qry_aggs; /* the aggregates */
|
||||
|
||||
/* internal to planner */
|
||||
List *base_relation_list_; /* base relation list */
|
||||
List *join_relation_list_; /* list of relations generated by joins */
|
||||
bool query_is_archival_; /* archival query flag */
|
||||
} Query;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Other Statements (no optimizations required)
|
||||
*
|
||||
* Some of them require a little bit of transformation (which is also
|
||||
* done by transformStmt). The whole structure is then passed on to
|
||||
* ProcessUtility (by-passing the optimization step) as the utilityStmt
|
||||
* field in Query.
|
||||
*****************************************************************************/
|
||||
|
||||
/* ----------------------
|
||||
* Add Column Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct AddAttrStmt {
|
||||
NodeTag type;
|
||||
char *relname; /* the relation to add attr */
|
||||
bool inh; /* add recursively to children? */
|
||||
struct ColumnDef *colDef; /* the attribute definition */
|
||||
} AddAttrStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Change ACL Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct ChangeACLStmt {
|
||||
NodeTag type;
|
||||
struct AclItem *aclitem;
|
||||
unsigned modechg;
|
||||
List *relNames;
|
||||
} ChangeACLStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Close Portal Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct ClosePortalStmt {
|
||||
NodeTag type;
|
||||
char *portalname; /* name of the portal (cursor) */
|
||||
} ClosePortalStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Copy Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct CopyStmt {
|
||||
NodeTag type;
|
||||
bool binary; /* is a binary copy? */
|
||||
char *relname; /* the relation to copy */
|
||||
int direction; /* TO or FROM */
|
||||
char *filename; /* if NULL, use stdin/stdout */
|
||||
char *delimiter; /* delimiter character, \t by default*/
|
||||
} CopyStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Create Table Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef enum ArchType {
|
||||
ARCH_NONE, ARCH_LIGHT, ARCH_HEAVY /* archive mode */
|
||||
} ArchType;
|
||||
|
||||
typedef struct CreateStmt {
|
||||
NodeTag type;
|
||||
char *relname; /* the relation to create */
|
||||
List *tableElts; /* column definitions
|
||||
list of ColumnDef */
|
||||
List *inhRelnames; /* relations to inherit from
|
||||
list of Value (string) */
|
||||
ArchType archiveType; /* archive mode (ARCH_NONE if none */
|
||||
int location; /* smgrid (-1 if none) */
|
||||
int archiveLoc; /* smgrid (-1 if none) */
|
||||
} CreateStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Create Version Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct VersionStmt {
|
||||
NodeTag type;
|
||||
char *relname; /* the new relation */
|
||||
int direction; /* FORWARD | BACKWARD */
|
||||
char *fromRelname; /* relation to create a version */
|
||||
char *date; /* date of the snapshot */
|
||||
} VersionStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Create {Operator|Type|Aggregate} Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct DefineStmt {
|
||||
NodeTag type;
|
||||
int defType; /* OPERATOR|P_TYPE|AGGREGATE*/
|
||||
char *defname;
|
||||
List *definition; /* a list of DefElem */
|
||||
} DefineStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Drop Table Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct DestroyStmt {
|
||||
NodeTag type;
|
||||
List *relNames; /* relations to be dropped */
|
||||
} DestroyStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Extend Index Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct ExtendStmt {
|
||||
NodeTag type;
|
||||
char *idxname; /* name of the index */
|
||||
Node *whereClause; /* qualifications */
|
||||
List *rangetable; /* range table, filled in
|
||||
by transformStmt() */
|
||||
} ExtendStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Begin Recipe Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct RecipeStmt {
|
||||
NodeTag type;
|
||||
char *recipeName; /* name of the recipe*/
|
||||
} RecipeStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Fetch Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct FetchStmt {
|
||||
NodeTag type;
|
||||
int direction; /* FORWARD or BACKWARD */
|
||||
int howMany; /* amount to fetch ("ALL" --> 0) */
|
||||
char *portalname; /* name of portal (cursor) */
|
||||
} FetchStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Create Index Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct IndexStmt {
|
||||
NodeTag type;
|
||||
char *idxname; /* name of the index */
|
||||
char *relname; /* name of relation to index on */
|
||||
char *accessMethod; /* name of acess methood (eg. btree) */
|
||||
List *indexParams; /* a list of IndexElem */
|
||||
List *withClause; /* a list of ParamString */
|
||||
Node *whereClause; /* qualifications */
|
||||
List *rangetable; /* range table, filled in
|
||||
by transformStmt() */
|
||||
} IndexStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Move Statement (Not implemented)
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct MoveStmt {
|
||||
NodeTag type;
|
||||
int direction; /* FORWARD or BACKWARD */
|
||||
bool to;
|
||||
int where;
|
||||
char *portalname;
|
||||
} MoveStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Create Function Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct ProcedureStmt {
|
||||
NodeTag type;
|
||||
char *funcname; /* name of function to create */
|
||||
List *defArgs; /* list of definitions
|
||||
a list of strings (as Value *) */
|
||||
Node *returnType; /* the return type (as a string or
|
||||
a TypeName (ie.setof) */
|
||||
List *withClause; /* a list of ParamString */
|
||||
char *as; /* the SQL statement or filename */
|
||||
char *language; /* C or SQL */
|
||||
} ProcedureStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Purge Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct PurgeStmt {
|
||||
NodeTag type;
|
||||
char *relname; /* relation to purge */
|
||||
char *beforeDate; /* purge before this date */
|
||||
char *afterDate; /* purge after this date */
|
||||
} PurgeStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Drop Function Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct RemoveFuncStmt {
|
||||
NodeTag type;
|
||||
char *funcname; /* function to drop */
|
||||
List *args; /* types of the arguments */
|
||||
} RemoveFuncStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Drop Operator Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct RemoveOperStmt {
|
||||
NodeTag type;
|
||||
char *opname; /* operator to drop */
|
||||
List *args; /* types of the arguments */
|
||||
} RemoveOperStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Drop {Aggregate|Type|Index|Rule|View} Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct RemoveStmt {
|
||||
NodeTag type;
|
||||
int removeType; /* AGGREGATE|P_TYPE|INDEX|RULE|VIEW */
|
||||
char *name; /* name to drop */
|
||||
} RemoveStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Alter Table Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct RenameStmt {
|
||||
NodeTag type;
|
||||
char *relname; /* relation to be altered */
|
||||
bool inh; /* recursively alter children? */
|
||||
char *column; /* if NULL, rename the relation name
|
||||
to the new name. Otherwise, rename
|
||||
this column name. */
|
||||
char *newname; /* the new name */
|
||||
} RenameStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Create Rule Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct RuleStmt {
|
||||
NodeTag type;
|
||||
char *rulename; /* name of the rule */
|
||||
Node *whereClause; /* qualifications */
|
||||
CmdType event; /* RETRIEVE */
|
||||
struct Attr *object; /* object affected */
|
||||
bool instead; /* is a 'do instead'? */
|
||||
List *actions; /* the action statements */
|
||||
} RuleStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Notify Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct NotifyStmt {
|
||||
NodeTag type;
|
||||
char *relname; /* relation to notify */
|
||||
} NotifyStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Listen Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct ListenStmt {
|
||||
NodeTag type;
|
||||
char *relname; /* relation to listen on */
|
||||
} ListenStmt;
|
||||
|
||||
/* ----------------------
|
||||
* {Begin|Abort|End} Transaction Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct TransactionStmt {
|
||||
NodeTag type;
|
||||
int command; /* BEGIN|END|ABORT */
|
||||
} TransactionStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Create View Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct ViewStmt {
|
||||
NodeTag type;
|
||||
char *viewname; /* name of the view */
|
||||
Query *query; /* the SQL statement */
|
||||
} ViewStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Load Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct LoadStmt {
|
||||
NodeTag type;
|
||||
char *filename; /* file to load */
|
||||
} LoadStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Createdb Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct CreatedbStmt {
|
||||
NodeTag type;
|
||||
char *dbname; /* database to create */
|
||||
} CreatedbStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Destroydb Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct DestroydbStmt {
|
||||
NodeTag type;
|
||||
char *dbname; /* database to drop */
|
||||
} DestroydbStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Cluster Statement (support pbrown's cluster index implementation)
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct ClusterStmt {
|
||||
NodeTag type;
|
||||
char *relname; /* relation being indexed */
|
||||
char *indexname; /* original index defined */
|
||||
} ClusterStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Vacuum Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct VacuumStmt {
|
||||
NodeTag type;
|
||||
char *vacrel; /* table to vacuum */
|
||||
} VacuumStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Explain Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct ExplainStmt {
|
||||
NodeTag type;
|
||||
Query *query; /* the query */
|
||||
List *options;
|
||||
} ExplainStmt;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Optimizable Statements
|
||||
*****************************************************************************/
|
||||
|
||||
/* ----------------------
|
||||
* Insert Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct AppendStmt {
|
||||
NodeTag type;
|
||||
char *relname; /* relation to insert into */
|
||||
List *cols; /* names of the columns */
|
||||
List *exprs; /* the expressions (same order as
|
||||
the columns) */
|
||||
List *fromClause; /* the from clause */
|
||||
Node *whereClause; /* qualifications */
|
||||
} AppendStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Delete Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct DeleteStmt {
|
||||
NodeTag type;
|
||||
char *relname; /* relation to delete from */
|
||||
Node *whereClause; /* qualifications */
|
||||
} DeleteStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Update Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct ReplaceStmt {
|
||||
NodeTag type;
|
||||
char *relname; /* relation to update */
|
||||
List *targetList; /* the target list (of ResTarget) */
|
||||
Node *whereClause; /* qualifications */
|
||||
List *fromClause; /* the from clause */
|
||||
} ReplaceStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Create Cursor Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct CursorStmt {
|
||||
NodeTag type;
|
||||
char *portalname; /* the portal (cursor) to create */
|
||||
bool binary; /* a binary (internal) portal? */
|
||||
char *unique; /* NULL, "*", or unique attribute name */
|
||||
List *targetList; /* the target list (of ResTarget) */
|
||||
List *fromClause; /* the from clause */
|
||||
Node *whereClause; /* qualifications */
|
||||
List *orderClause; /* sort clause (a list of SortBy's) */
|
||||
} CursorStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Select Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct RetrieveStmt {
|
||||
NodeTag type;
|
||||
char *unique; /* NULL, '*', or unique attribute name */
|
||||
char *into; /* name of table (for select into
|
||||
table) */
|
||||
List *targetList; /* the target list (of ResTarget) */
|
||||
List *fromClause; /* the from clause */
|
||||
Node *whereClause; /* qualifications */
|
||||
List *groupClause; /* group by clause */
|
||||
Node *havingClause; /* having conditional-expression */
|
||||
List *orderClause; /* sort clause (a list of SortBy's) */
|
||||
} RetrieveStmt;
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Supporting data structures for Parse Trees
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* TypeName - specifies a type in definitions
|
||||
*/
|
||||
typedef struct TypeName {
|
||||
NodeTag type;
|
||||
char *name; /* name of the type */
|
||||
bool setof; /* is a set? */
|
||||
List *arrayBounds; /* array bounds */
|
||||
int typlen; /* length for char() and varchar() */
|
||||
} TypeName;
|
||||
|
||||
/*
|
||||
* ParamNo - specifies a parameter reference
|
||||
*/
|
||||
typedef struct ParamNo {
|
||||
NodeTag type;
|
||||
int number; /* the number of the parameter */
|
||||
TypeName *typename; /* the typecast */
|
||||
} ParamNo;
|
||||
|
||||
/*
|
||||
* A_Expr - binary expressions
|
||||
*/
|
||||
typedef struct A_Expr {
|
||||
NodeTag type;
|
||||
int oper; /* type of operation
|
||||
{OP,OR,AND,NOT,ISNULL,NOTNULL} */
|
||||
char *opname; /* name of operator/function */
|
||||
Node *lexpr; /* left argument */
|
||||
Node *rexpr; /* right argument */
|
||||
} A_Expr;
|
||||
|
||||
/*
|
||||
* Attr -
|
||||
* specifies an Attribute (ie. a Column); could have nested dots or
|
||||
* array references.
|
||||
*
|
||||
*/
|
||||
typedef struct Attr {
|
||||
NodeTag type;
|
||||
char *relname; /* name of relation (can be "*") */
|
||||
ParamNo *paramNo; /* or a parameter */
|
||||
List *attrs; /* attributes (possibly nested);
|
||||
list of Values (strings) */
|
||||
List *indirection; /* array refs (list of A_Indices') */
|
||||
} Attr;
|
||||
|
||||
/*
|
||||
* A_Const - a constant expression
|
||||
*/
|
||||
typedef struct A_Const {
|
||||
NodeTag type;
|
||||
Value val; /* the value (with the tag) */
|
||||
TypeName *typename; /* typecast */
|
||||
} A_Const;
|
||||
|
||||
/*
|
||||
* ColumnDef - column definition (used in various creates)
|
||||
*/
|
||||
typedef struct ColumnDef {
|
||||
NodeTag type;
|
||||
char *colname; /* name of column */
|
||||
TypeName *typename; /* type of column */
|
||||
} ColumnDef;
|
||||
|
||||
/*
|
||||
* Ident -
|
||||
* an identifier (could be an attribute or a relation name). Depending
|
||||
* on the context at transformStmt time, the identifier is treated as
|
||||
* either a relation name (in which case, isRel will be set) or an
|
||||
* attribute (in which case, it will be transformed into an Attr).
|
||||
*/
|
||||
typedef struct Ident {
|
||||
NodeTag type;
|
||||
char *name; /* its name */
|
||||
List *indirection; /* array references */
|
||||
bool isRel; /* is a relation - filled in by
|
||||
transformExpr() */
|
||||
} Ident;
|
||||
|
||||
/*
|
||||
* FuncCall - a function/aggregate invocation
|
||||
*/
|
||||
typedef struct FuncCall {
|
||||
NodeTag type;
|
||||
char *funcname; /* name of function */
|
||||
List *args; /* the arguments (list of exprs) */
|
||||
} FuncCall;
|
||||
|
||||
/*
|
||||
* A_Indices - array reference or bounds ([lidx:uidx] or [uidx])
|
||||
*/
|
||||
typedef struct A_Indices {
|
||||
NodeTag type;
|
||||
Node *lidx; /* could be NULL */
|
||||
Node *uidx;
|
||||
} A_Indices;
|
||||
|
||||
/*
|
||||
* ResTarget -
|
||||
* result target (used in target list of pre-transformed Parse trees)
|
||||
*/
|
||||
typedef struct ResTarget {
|
||||
NodeTag type;
|
||||
char *name; /* name of the result column */
|
||||
List *indirection; /* array references */
|
||||
Node *val; /* the value of the result
|
||||
(A_Expr or Attr) */
|
||||
} ResTarget;
|
||||
|
||||
/*
|
||||
* ParamString - used in with clauses
|
||||
*/
|
||||
typedef struct ParamString {
|
||||
NodeTag type;
|
||||
char *name;
|
||||
char *val;
|
||||
} ParamString;
|
||||
|
||||
/*
|
||||
* TimeRange - specifies a time range
|
||||
*/
|
||||
typedef struct TimeRange {
|
||||
NodeTag type;
|
||||
char *startDate;
|
||||
char *endDate; /* snapshot if NULL */
|
||||
} TimeRange;
|
||||
|
||||
/*
|
||||
* RelExpr - relation expressions
|
||||
*/
|
||||
typedef struct RelExpr {
|
||||
NodeTag type;
|
||||
char *relname; /* the relation name */
|
||||
bool inh; /* inheritance query */
|
||||
TimeRange *timeRange; /* the time range */
|
||||
} RelExpr;
|
||||
|
||||
/*
|
||||
* Sortby - for order by clause
|
||||
*/
|
||||
typedef struct SortBy {
|
||||
NodeTag type;
|
||||
char *name; /* name of column to sort on */
|
||||
char *useOp; /* operator to use */
|
||||
} SortBy;
|
||||
|
||||
/*
|
||||
* RangeVar - range variable, used in from clauses
|
||||
*/
|
||||
typedef struct RangeVar {
|
||||
NodeTag type;
|
||||
RelExpr *relExpr; /* the relation expression */
|
||||
char *name; /* the name to be referenced
|
||||
(optional) */
|
||||
} RangeVar;
|
||||
|
||||
/*
|
||||
* IndexElem - index parameters (used in create index)
|
||||
*/
|
||||
typedef struct IndexElem {
|
||||
NodeTag type;
|
||||
char *name; /* name of index */
|
||||
List *args; /* if not NULL, function index */
|
||||
char *class;
|
||||
} IndexElem;
|
||||
|
||||
/*
|
||||
* DefElem -
|
||||
* a definition (used in definition lists in the form of defname = arg)
|
||||
*/
|
||||
typedef struct DefElem {
|
||||
NodeTag type;
|
||||
char *defname;
|
||||
Node *arg; /* a (Value *) or a (TypeName *) */
|
||||
} DefElem;
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Nodes for a Query tree
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* TargetEntry -
|
||||
* a target entry (used in the transformed target list)
|
||||
*
|
||||
* one of resdom or fjoin is not NULL. a target list is
|
||||
* ((<resdom | fjoin> expr) (<resdom | fjoin> expr) ...)
|
||||
*/
|
||||
typedef struct TargetEntry {
|
||||
NodeTag type;
|
||||
Resdom *resdom; /* fjoin overload this to be a list??*/
|
||||
Fjoin *fjoin;
|
||||
Node *expr; /* can be a list too */
|
||||
} TargetEntry;
|
||||
|
||||
/*
|
||||
* RangeTblEntry -
|
||||
* used in range tables. Some of the following are only used in one of
|
||||
* the parsing, optimizing, execution stages.
|
||||
*
|
||||
* inFromCl marks those range variables that are listed in the from clause.
|
||||
* In SQL, the targetlist can only refer to range variables listed in the
|
||||
* from clause but POSTQUEL allows you to refer to tables not specified, in
|
||||
* which case a range table entry will be generated. We use POSTQUEL
|
||||
* semantics which is more powerful. However, we need SQL semantics in
|
||||
* some cases (eg. when expanding a '*')
|
||||
*/
|
||||
typedef struct RangeTblEntry {
|
||||
NodeTag type;
|
||||
char *relname; /* real name of the relation */
|
||||
TimeRange *timeRange; /* time range */
|
||||
char *refname; /* the reference name (specified in
|
||||
the from clause) */
|
||||
Oid relid;
|
||||
bool inh; /* inheritance? */
|
||||
bool archive; /* filled in by plan_archive */
|
||||
bool inFromCl; /* comes from From Clause */
|
||||
TimeQual timeQual; /* filled in by pg_plan */
|
||||
} RangeTblEntry;
|
||||
|
||||
/*
|
||||
* SortClause -
|
||||
* used in the sort clause for retrieves and cursors
|
||||
*/
|
||||
typedef struct SortClause {
|
||||
NodeTag type;
|
||||
Resdom *resdom; /* attributes in tlist to be sorted */
|
||||
Oid opoid; /* sort operators */
|
||||
} SortClause;
|
||||
|
||||
/*
|
||||
* GroupClause -
|
||||
* used in the GROUP BY clause
|
||||
*/
|
||||
typedef struct GroupClause {
|
||||
NodeTag type;
|
||||
Var *grpAttr; /* attributes to group on */
|
||||
Oid grpOpoid; /* the sort operator to use */
|
||||
} GroupClause;
|
||||
|
||||
#endif /* PARSENODES_H */
|
112
src/backend/nodes/pg_list.h
Normal file
112
src/backend/nodes/pg_list.h
Normal file
@ -0,0 +1,112 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pg_list.h--
|
||||
* POSTGRES generic list package
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: pg_list.h,v 1.1.1.1 1996/07/09 06:21:33 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef PG_LIST_H
|
||||
#define PG_LIST_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "c.h"
|
||||
#include "nodes/nodes.h"
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* node definitions
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*----------------------
|
||||
* Value node
|
||||
*----------------------
|
||||
*/
|
||||
typedef struct Value {
|
||||
NodeTag type; /* tag appropriately (eg. T_String) */
|
||||
union ValUnion {
|
||||
char *str; /* string */
|
||||
long ival;
|
||||
double dval;
|
||||
} val;
|
||||
} Value;
|
||||
|
||||
#define intVal(v) (((Value *)v)->val.ival)
|
||||
#define floatVal(v) (((Value *)v)->val.dval)
|
||||
#define strVal(v) (((Value *)v)->val.str)
|
||||
|
||||
|
||||
/*----------------------
|
||||
* List node
|
||||
*----------------------
|
||||
*/
|
||||
typedef struct List {
|
||||
NodeTag type;
|
||||
void *elem;
|
||||
struct List *next;
|
||||
} List;
|
||||
|
||||
#define NIL ((List *) NULL)
|
||||
|
||||
/* ----------------
|
||||
* accessor macros
|
||||
* ----------------
|
||||
*/
|
||||
#define lfirst(l) ((l)->elem)
|
||||
#define lnext(l) ((l)->next)
|
||||
#define lsecond(l) (lfirst(lnext(l)))
|
||||
|
||||
/*
|
||||
* foreach -
|
||||
* a convenience macro which loops through the list
|
||||
*/
|
||||
#define foreach(_elt_,_list_) \
|
||||
for(_elt_=_list_; _elt_!=NIL;_elt_=lnext(_elt_))
|
||||
|
||||
|
||||
/*
|
||||
* function prototypes in nodes/list.c
|
||||
*/
|
||||
extern int length(List *list);
|
||||
extern List *append(List *list1, List *list2);
|
||||
extern List *nconc(List *list1, List *list2);
|
||||
extern List *lcons(void *datum, List *list);
|
||||
extern bool member(void *foo, List *bar);
|
||||
extern Value *makeInteger(long i);
|
||||
extern Value *makeFloat(double d);
|
||||
extern Value *makeString(char *str);
|
||||
extern List *makeList(void *elem, ...);
|
||||
extern List *lappend(List *list, void *obj);
|
||||
extern List *lremove(void *elem, List *list);
|
||||
extern void freeList(List *list);
|
||||
|
||||
extern void *nth(int n, List *l);
|
||||
extern void set_nth(List *l, int n, void *elem);
|
||||
|
||||
/* hack for now */
|
||||
#define lconsi(i,l) lcons((void*)i,l)
|
||||
#define lfirsti(l) ((int)lfirst(l))
|
||||
#define lappendi(l,i) lappend(l,(void*)i)
|
||||
extern bool intMember(int, List *);
|
||||
extern List *intAppend(List *list1, List *list2);
|
||||
|
||||
extern List *nreverse(List *);
|
||||
extern List *set_difference(List *, List *);
|
||||
extern List *set_differencei(List *, List *);
|
||||
extern List *LispRemove(void *, List *);
|
||||
extern List *intLispRemove(int, List *);
|
||||
extern List *LispUnion(List *foo, List *bar);
|
||||
extern List *LispUnioni(List *foo, List *bar);
|
||||
extern bool same(List *foo, List *bar);
|
||||
|
||||
/* should be in nodes.h but needs List */
|
||||
extern bool equali(List *a, List *b);
|
||||
|
||||
/* in copyfuncs.c */
|
||||
extern List *listCopy(List *);
|
||||
|
||||
#endif /* PG_LIST_H */
|
330
src/backend/nodes/plannodes.h
Normal file
330
src/backend/nodes/plannodes.h
Normal file
@ -0,0 +1,330 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* plannodes.h--
|
||||
* definitions for query plan nodes
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: plannodes.h,v 1.1.1.1 1996/07/09 06:21:33 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef PLANNODES_H
|
||||
#define PLANNODES_H
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "nodes/nodes.h"
|
||||
#include "nodes/pg_list.h"
|
||||
#include "nodes/primnodes.h"
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* Executor State types are used in the plannode structures
|
||||
* so we have to include their definitions too.
|
||||
*
|
||||
* Node Type node information used by executor
|
||||
*
|
||||
* control nodes
|
||||
*
|
||||
* Existential ExistentialState exstate;
|
||||
* Result ResultState resstate;
|
||||
* Append AppendState unionstate;
|
||||
*
|
||||
* scan nodes
|
||||
*
|
||||
* Scan *** CommonScanState scanstate;
|
||||
* IndexScan IndexScanState indxstate;
|
||||
*
|
||||
* (*** nodes which inherit Scan also inherit scanstate)
|
||||
*
|
||||
* join nodes
|
||||
*
|
||||
* NestLoop NestLoopState nlstate;
|
||||
* MergeJoin MergeJoinState mergestate;
|
||||
* HashJoin HashJoinState hashjoinstate;
|
||||
*
|
||||
* materialize nodes
|
||||
*
|
||||
* Material MaterialState matstate;
|
||||
* Sort SortState sortstate;
|
||||
* Unique UniqueState uniquestate;
|
||||
* Hash HashState hashstate;
|
||||
*
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
#include "nodes/execnodes.h" /* XXX move executor types elsewhere */
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* node definitions
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ----------------
|
||||
* Plan node
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
typedef struct Plan {
|
||||
NodeTag type;
|
||||
Cost cost;
|
||||
int plan_size;
|
||||
int plan_width;
|
||||
int plan_tupperpage;
|
||||
EState *state; /* at execution time, state's of individual
|
||||
nodes point to one EState for the
|
||||
whole top-level plan */
|
||||
List *targetlist;
|
||||
List *qual; /* Node* or List* ?? */
|
||||
struct Plan *lefttree;
|
||||
struct Plan *righttree;
|
||||
} Plan;
|
||||
|
||||
/* ----------------
|
||||
* these are are defined to avoid confusion problems with "left"
|
||||
* and "right" and "inner" and "outer". The convention is that
|
||||
* the "left" plan is the "outer" plan and the "right" plan is
|
||||
* the inner plan, but these make the code more readable.
|
||||
* ----------------
|
||||
*/
|
||||
#define innerPlan(node) (((Plan *)(node))->righttree)
|
||||
#define outerPlan(node) (((Plan *)(node))->lefttree)
|
||||
|
||||
|
||||
/*
|
||||
* ===============
|
||||
* Top-level nodes
|
||||
* ===============
|
||||
*/
|
||||
|
||||
/* all plan nodes "derive" from the Plan structure by having the
|
||||
Plan structure as the first field. This ensures that everything works
|
||||
when nodes are cast to Plan's. (node pointers are frequently cast to Plan*
|
||||
when passed around generically in the executor */
|
||||
|
||||
|
||||
/* ----------------
|
||||
* existential node
|
||||
* ----------------
|
||||
*/
|
||||
typedef Plan Existential;
|
||||
|
||||
/* ----------------
|
||||
* result node -
|
||||
* returns tuples from outer plan that satisfy the qualifications
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct Result {
|
||||
Plan plan;
|
||||
Node *resconstantqual;
|
||||
ResultState *resstate;
|
||||
} Result;
|
||||
|
||||
/* ----------------
|
||||
* append node
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct Append {
|
||||
Plan plan;
|
||||
List *unionplans;
|
||||
Index unionrelid;
|
||||
List *unionrtentries;
|
||||
AppendState *unionstate;
|
||||
} Append;
|
||||
|
||||
/*
|
||||
* ==========
|
||||
* Scan nodes
|
||||
* ==========
|
||||
*/
|
||||
typedef struct Scan {
|
||||
Plan plan;
|
||||
Index scanrelid; /* relid is index into the range table */
|
||||
CommonScanState *scanstate;
|
||||
} Scan;
|
||||
|
||||
/* ----------------
|
||||
* sequential scan node
|
||||
* ----------------
|
||||
*/
|
||||
typedef Scan SeqScan;
|
||||
|
||||
/* ----------------
|
||||
* index scan node
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct IndexScan {
|
||||
Scan scan;
|
||||
List *indxid;
|
||||
List *indxqual;
|
||||
IndexScanState *indxstate;
|
||||
} IndexScan;
|
||||
|
||||
/*
|
||||
* ==========
|
||||
* Join nodes
|
||||
* ==========
|
||||
*/
|
||||
|
||||
/* ----------------
|
||||
* Join node
|
||||
* ----------------
|
||||
*/
|
||||
typedef Plan Join;
|
||||
|
||||
/* ----------------
|
||||
* nest loop join node
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct NestLoop {
|
||||
Join join;
|
||||
NestLoopState *nlstate;
|
||||
} NestLoop;
|
||||
|
||||
/* ----------------
|
||||
* merge join node
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct MergeJoin {
|
||||
Join join;
|
||||
List *mergeclauses;
|
||||
Oid mergesortop;
|
||||
Oid *mergerightorder; /* inner sort operator */
|
||||
Oid *mergeleftorder; /* outer sort operator */
|
||||
MergeJoinState *mergestate;
|
||||
} MergeJoin;
|
||||
|
||||
/* ----------------
|
||||
* hash join (probe) node
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct HashJoin {
|
||||
Join join;
|
||||
List *hashclauses;
|
||||
Oid hashjoinop;
|
||||
HashJoinState *hashjoinstate;
|
||||
HashJoinTable hashjointable;
|
||||
IpcMemoryKey hashjointablekey;
|
||||
int hashjointablesize;
|
||||
bool hashdone;
|
||||
} HashJoin;
|
||||
|
||||
/* ---------------
|
||||
* aggregate node
|
||||
* ---------------
|
||||
*/
|
||||
typedef struct Agg {
|
||||
Plan plan;
|
||||
int numAgg;
|
||||
Aggreg **aggs;
|
||||
AggState *aggstate;
|
||||
} Agg;
|
||||
|
||||
/* ---------------
|
||||
* group node -
|
||||
* use for queries with GROUP BY specified.
|
||||
*
|
||||
* If tuplePerGroup is true, one tuple (with group columns only) is
|
||||
* returned for each group and NULL is returned when there are no more
|
||||
* groups. Otherwise, all the tuples of a group are returned with a
|
||||
* NULL returned at the end of each group. (see nodeGroup.c for details)
|
||||
* ---------------
|
||||
*/
|
||||
typedef struct Group {
|
||||
Plan plan;
|
||||
bool tuplePerGroup; /* what tuples to return (see above) */
|
||||
int numCols; /* number of group columns */
|
||||
AttrNumber *grpColIdx; /* index into the target list */
|
||||
GroupState *grpstate;
|
||||
} Group;
|
||||
|
||||
/*
|
||||
* ==========
|
||||
* Temp nodes
|
||||
* ==========
|
||||
*/
|
||||
typedef struct Temp {
|
||||
Plan plan;
|
||||
Oid tempid;
|
||||
int keycount;
|
||||
} Temp;
|
||||
|
||||
/* ----------------
|
||||
* materialization node
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct Material {
|
||||
Plan plan; /* temp node flattened out */
|
||||
Oid tempid;
|
||||
int keycount;
|
||||
MaterialState *matstate;
|
||||
} Material;
|
||||
|
||||
/* ----------------
|
||||
* sort node
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct Sort {
|
||||
Plan plan; /* temp node flattened out */
|
||||
Oid tempid;
|
||||
int keycount;
|
||||
SortState *sortstate;
|
||||
} Sort;
|
||||
|
||||
/* ----------------
|
||||
* unique node
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct Unique {
|
||||
Plan plan; /* temp node flattened out */
|
||||
Oid tempid;
|
||||
int keycount;
|
||||
char *uniqueAttr; /* NULL if all attrs,
|
||||
or unique attribute name */
|
||||
AttrNumber uniqueAttrNum; /* attribute number of attribute
|
||||
to select distinct on */
|
||||
UniqueState *uniquestate;
|
||||
} Unique;
|
||||
|
||||
/* ----------------
|
||||
* hash build node
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct Hash {
|
||||
Plan plan;
|
||||
Var *hashkey;
|
||||
HashState *hashstate;
|
||||
HashJoinTable hashtable;
|
||||
IpcMemoryKey hashtablekey;
|
||||
int hashtablesize;
|
||||
} Hash;
|
||||
|
||||
/* ---------------------
|
||||
* choose node
|
||||
* ---------------------
|
||||
*/
|
||||
typedef struct Choose {
|
||||
Plan plan;
|
||||
List *chooseplanlist;
|
||||
} Choose;
|
||||
|
||||
/* -------------------
|
||||
* Tee node information
|
||||
*
|
||||
* leftParent : the left parent of this node
|
||||
* rightParent: the right parent of this node
|
||||
* -------------------
|
||||
*/
|
||||
typedef struct Tee {
|
||||
Plan plan;
|
||||
Plan* leftParent;
|
||||
Plan* rightParent;
|
||||
TeeState *teestate;
|
||||
char *teeTableName; /* the name of the table to materialize
|
||||
the tee into */
|
||||
List *rtentries; /* the range table for the plan below the Tee
|
||||
may be different than the parent plans */
|
||||
} Tee;
|
||||
|
||||
#endif /* PLANNODES_H */
|
318
src/backend/nodes/primnodes.h
Normal file
318
src/backend/nodes/primnodes.h
Normal file
@ -0,0 +1,318 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* primnodes.h--
|
||||
* Definitions for parse tree/query tree ("primitive") nodes.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: primnodes.h,v 1.1.1.1 1996/07/09 06:21:33 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef PRIMNODES_H
|
||||
#define PRIMNODES_H
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/attnum.h"
|
||||
#include "storage/buf.h"
|
||||
#include "utils/rel.h"
|
||||
#include "utils/fcache.h"
|
||||
#include "nodes/params.h"
|
||||
|
||||
#include "nodes/nodes.h"
|
||||
#include "nodes/pg_list.h"
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* node definitions
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ----------------
|
||||
* Resdom (Result Domain)
|
||||
* resno - attribute number
|
||||
* restype - type of the resdom
|
||||
* reslen - length (in bytes) of the result
|
||||
* resname - name of the resdom (could be NULL)
|
||||
* reskey - order of key in a sort (for those > 0)
|
||||
* reskeyop - sort operator Oid
|
||||
* resjunk - set to nonzero to eliminate the attribute
|
||||
* from final target list e.g., ctid for replace
|
||||
* and delete
|
||||
*
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct Resdom {
|
||||
NodeTag type;
|
||||
AttrNumber resno;
|
||||
Oid restype;
|
||||
int reslen;
|
||||
char *resname;
|
||||
Index reskey;
|
||||
Oid reskeyop;
|
||||
int resjunk;
|
||||
} Resdom;
|
||||
|
||||
/* -------------
|
||||
* Fjoin
|
||||
* initialized - true if the Fjoin has already been initialized for
|
||||
* the current target list evaluation
|
||||
* nNodes - The number of Iter nodes returning sets that the
|
||||
* node will flatten
|
||||
* outerList - 1 or more Iter nodes
|
||||
* inner - exactly one Iter node. We eval every node in the
|
||||
* outerList once then eval the inner node to completion
|
||||
* pair the outerList result vector with each inner
|
||||
* result to form the full result. When the inner has
|
||||
* been exhausted, we get the next outer result vector
|
||||
* and reset the inner.
|
||||
* results - The complete (flattened) result vector
|
||||
* alwaysNull - a null vector to indicate sets with a cardinality of
|
||||
* 0, we treat them as the set {NULL}.
|
||||
*/
|
||||
typedef struct Fjoin {
|
||||
NodeTag type;
|
||||
bool fj_initialized;
|
||||
int fj_nNodes;
|
||||
List *fj_innerNode;
|
||||
DatumPtr fj_results;
|
||||
BoolPtr fj_alwaysDone;
|
||||
} Fjoin;
|
||||
|
||||
/* ----------------
|
||||
* Expr
|
||||
* typeOid - oid of the type of this expression
|
||||
* opType - type of this expression
|
||||
* oper - the Oper node if it is an OPER_EXPR or the
|
||||
* Func node if it is a FUNC_EXPR
|
||||
* args - arguments to this expression
|
||||
* ----------------
|
||||
*/
|
||||
typedef enum OpType {
|
||||
OP_EXPR, FUNC_EXPR, OR_EXPR, AND_EXPR, NOT_EXPR
|
||||
} OpType;
|
||||
|
||||
typedef struct Expr {
|
||||
NodeTag type;
|
||||
Oid typeOid; /* oid of the type of this expr */
|
||||
OpType opType; /* type of the op */
|
||||
Node *oper; /* could be Oper or Func */
|
||||
List *args; /* list of argument nodes */
|
||||
} Expr;
|
||||
|
||||
/* ----------------
|
||||
* Var
|
||||
* varno - index of this var's relation in the range table
|
||||
* (could be INNER or OUTER)
|
||||
* varattno - attribute number of this var
|
||||
* vartype - pg_type tuple oid for the type of this var
|
||||
* varnoold - keep varno around in case it got changed to INNER/
|
||||
* OUTER (see match_varid)
|
||||
* varoattno - attribute number of this var
|
||||
* [ '(varnoold varoattno) was varid -ay 2/95]
|
||||
* ----------------
|
||||
*/
|
||||
#define INNER 65000
|
||||
#define OUTER 65001
|
||||
|
||||
#define PRS2_CURRENT_VARNO 1
|
||||
#define PRS2_NEW_VARNO 2
|
||||
|
||||
typedef struct Var {
|
||||
NodeTag type;
|
||||
Index varno;
|
||||
AttrNumber varattno;
|
||||
Oid vartype;
|
||||
Index varnoold; /* only used by optimizer */
|
||||
AttrNumber varoattno; /* only used by optimizer */
|
||||
} Var;
|
||||
|
||||
/* ----------------
|
||||
* Oper
|
||||
* opno - PG_OPERATOR OID of the operator
|
||||
* opid - PG_PROC OID for the operator
|
||||
* opresulttype - PG_TYPE OID of the operator's return value
|
||||
* opsize - size of return result (cached by executor)
|
||||
* op_fcache - XXX comment me.
|
||||
*
|
||||
* ----
|
||||
* NOTE: in the good old days 'opno' used to be both (or either, or
|
||||
* neither) the pg_operator oid, and/or the pg_proc oid depending
|
||||
* on the postgres module in question (parser->pg_operator,
|
||||
* executor->pg_proc, planner->both), the mood of the programmer,
|
||||
* and the phase of the moon (rumors that it was also depending on the day
|
||||
* of the week are probably false). To make things even more postgres-like
|
||||
* (i.e. a mess) some comments were referring to 'opno' using the name
|
||||
* 'opid'. Anyway, now we have two separate fields, and of course that
|
||||
* immediately removes all bugs from the code... [ sp :-) ].
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct Oper {
|
||||
NodeTag type;
|
||||
Oid opno;
|
||||
Oid opid;
|
||||
Oid opresulttype;
|
||||
int opsize;
|
||||
FunctionCachePtr op_fcache;
|
||||
} Oper;
|
||||
|
||||
|
||||
/* ----------------
|
||||
* Const
|
||||
* consttype - PG_TYPE OID of the constant's value
|
||||
* constlen - length in bytes of the constant's value
|
||||
* constvalue - the constant's value
|
||||
* constisnull - whether the constant is null
|
||||
* (if true, the other fields are undefined)
|
||||
* constbyval - whether the information in constvalue
|
||||
* if passed by value. If true, then all the information
|
||||
* is stored in the datum. If false, then the datum
|
||||
* contains a pointer to the information.
|
||||
* constisset - whether the const represents a set. The const
|
||||
* value corresponding will be the query that defines
|
||||
* the set.
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct Const {
|
||||
NodeTag type;
|
||||
Oid consttype;
|
||||
Size constlen;
|
||||
Datum constvalue;
|
||||
bool constisnull;
|
||||
bool constbyval;
|
||||
bool constisset;
|
||||
} Const;
|
||||
|
||||
/* ----------------
|
||||
* Param
|
||||
* paramkind - specifies the kind of parameter. The possible values
|
||||
* for this field are specified in "params.h", and they are:
|
||||
*
|
||||
* PARAM_NAMED: The parameter has a name, i.e. something
|
||||
* like `$.salary' or `$.foobar'.
|
||||
* In this case field `paramname' must be a valid Name.
|
||||
*
|
||||
* PARAM_NUM: The parameter has only a numeric identifier,
|
||||
* i.e. something like `$1', `$2' etc.
|
||||
* The number is contained in the `paramid' field.
|
||||
*
|
||||
* PARAM_NEW: Used in PRS2 rule, similar to PARAM_NAMED.
|
||||
* The `paramname' and `paramid' refer to the "NEW" tuple
|
||||
* The `pramname' is the attribute name and `paramid'
|
||||
* is the attribute number.
|
||||
*
|
||||
* PARAM_OLD: Same as PARAM_NEW, but in this case we refer to
|
||||
* the "OLD" tuple.
|
||||
*
|
||||
* paramid - numeric identifier for literal-constant parameters ("$1")
|
||||
* paramname - attribute name for tuple-substitution parameters ("$.foo")
|
||||
* paramtype - PG_TYPE OID of the parameter's value
|
||||
* param_tlist - allows for projection in a param node.
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct Param {
|
||||
NodeTag type;
|
||||
int paramkind;
|
||||
AttrNumber paramid;
|
||||
char *paramname;
|
||||
Oid paramtype;
|
||||
List *param_tlist;
|
||||
} Param;
|
||||
|
||||
|
||||
/* ----------------
|
||||
* Func
|
||||
* funcid - PG_FUNCTION OID of the function
|
||||
* functype - PG_TYPE OID of the function's return value
|
||||
* funcisindex - the function can be evaluated by scanning an index
|
||||
* (set during query optimization)
|
||||
* funcsize - size of return result (cached by executor)
|
||||
* func_fcache - runtime state while running this function. Where
|
||||
* we are in the execution of the function if it
|
||||
* returns more than one value, etc.
|
||||
* See utils/fcache.h
|
||||
* func_tlist - projection of functions returning tuples
|
||||
* func_planlist - result of planning this func, if it's a PQ func
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct Func {
|
||||
NodeTag type;
|
||||
Oid funcid;
|
||||
Oid functype;
|
||||
bool funcisindex;
|
||||
int funcsize;
|
||||
FunctionCachePtr func_fcache;
|
||||
List *func_tlist;
|
||||
List *func_planlist;
|
||||
} Func;
|
||||
|
||||
/* ----------------
|
||||
* Aggreg
|
||||
* aggname - name of the aggregate
|
||||
* basetype - base type Oid of the aggregate
|
||||
* aggtype - type Oid of final result of the aggregate
|
||||
* query - XXX comment me
|
||||
* target - XXX comment me
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct Aggreg {
|
||||
NodeTag type;
|
||||
char *aggname;
|
||||
Oid basetype; /* base type of the aggregate */
|
||||
Oid aggtype; /* type of final result */
|
||||
Node *target; /* attribute to aggreg on */
|
||||
int aggno; /* index to ecxt_values */
|
||||
} Aggreg;
|
||||
|
||||
/* ----------------
|
||||
* Array
|
||||
* arrayelemtype - base type of the array's elements (homogenous!)
|
||||
* arrayelemlength - length of that type
|
||||
* arrayelembyval - can you pass this element by value?
|
||||
* arrayndim - number of dimensions of the array
|
||||
* arraylow - base for array indexing
|
||||
* arrayhigh - limit for array indexing
|
||||
* arraylen -
|
||||
* ----------------
|
||||
*
|
||||
* memo from mao: the array support we inherited from 3.1 is just
|
||||
* wrong. when time exists, we should redesign this stuff to get
|
||||
* around a bunch of unfortunate implementation decisions made there.
|
||||
*/
|
||||
typedef struct Array {
|
||||
NodeTag type;
|
||||
Oid arrayelemtype;
|
||||
int arrayelemlength;
|
||||
bool arrayelembyval;
|
||||
int arrayndim;
|
||||
IntArray arraylow;
|
||||
IntArray arrayhigh;
|
||||
int arraylen;
|
||||
} Array;
|
||||
|
||||
/* ----------------
|
||||
* ArrayRef:
|
||||
* refelemtype - type of the element referenced here
|
||||
* refelemlength - length of that type
|
||||
* refelembyval - can you pass this element type by value?
|
||||
* refupperindexpr - expressions that evaluate to upper array index
|
||||
* reflowerexpr- the expressions that evaluate to a lower array index
|
||||
* refexpr - the expression that evaluates to an array
|
||||
* refassignexpr- the expression that evaluates to the new value
|
||||
* to be assigned to the array in case of replace.
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct ArrayRef {
|
||||
NodeTag type;
|
||||
int refattrlength;
|
||||
int refelemlength;
|
||||
Oid refelemtype;
|
||||
bool refelembyval;
|
||||
List *refupperindexpr;
|
||||
List *reflowerindexpr;
|
||||
Node *refexpr;
|
||||
Node *refassgnexpr;
|
||||
} ArrayRef;
|
||||
|
||||
#endif /* PRIMNODES_H */
|
377
src/backend/nodes/print.c
Normal file
377
src/backend/nodes/print.c
Normal file
@ -0,0 +1,377 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* print.c--
|
||||
* various print routines (used mostly for debugging)
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.1.1.1 1996/07/09 06:21:33 scrappy Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
* Andrew Yu Oct 26, 1994 file creation
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "postgres.h"
|
||||
#include "access/printtup.h"
|
||||
#include "nodes/pg_list.h"
|
||||
#include "nodes/execnodes.h"
|
||||
#include "nodes/parsenodes.h"
|
||||
|
||||
#include "parser/parsetree.h"
|
||||
#include "parser/catalog_utils.h"
|
||||
#include "access/heapam.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "nodes/nodes.h"
|
||||
#include "nodes/plannodes.h"
|
||||
#include "optimizer/clauses.h"
|
||||
/*
|
||||
* print--
|
||||
* print contents of Node to stdout
|
||||
*/
|
||||
void
|
||||
print(void *obj)
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = nodeToString(obj);
|
||||
printf("%s\n", s);
|
||||
fflush(stdout);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* pretty print hack extraordinaire. -ay 10/94
|
||||
*/
|
||||
void
|
||||
pprint(void *obj)
|
||||
{
|
||||
char *s;
|
||||
int i;
|
||||
char line[80];
|
||||
int indentLev;
|
||||
int j;
|
||||
|
||||
s = nodeToString(obj);
|
||||
|
||||
indentLev = 0;
|
||||
i = 0;
|
||||
for(;;) {
|
||||
for(j=0; j<indentLev*3; j++) {
|
||||
line[j] = ' ';
|
||||
}
|
||||
for( ; j<75 && s[i]!='\0'; i++, j++) {
|
||||
line[j] = s[i];
|
||||
switch (line[j]) {
|
||||
case '}':
|
||||
if (j != indentLev*3) {
|
||||
line[j] = '\0';
|
||||
printf("%s\n",line);
|
||||
line[indentLev*3] = '\0';
|
||||
printf("%s}\n",line);
|
||||
}else {
|
||||
line[j] = '\0';
|
||||
printf("%s}\n",line);
|
||||
}
|
||||
indentLev--;
|
||||
j = indentLev*3-1; /* print the line before : and resets */
|
||||
break;
|
||||
case ')':
|
||||
line[j+1] = '\0';
|
||||
printf("%s\n", line);
|
||||
j = indentLev*3-1;
|
||||
break;
|
||||
case '{':
|
||||
indentLev++;
|
||||
/* !!! FALLS THROUGH */
|
||||
case ':':
|
||||
if (j != 0) {
|
||||
line[j] = '\0';
|
||||
printf("%s\n",line);
|
||||
/* print the line before : and resets */
|
||||
for(j=0; j<indentLev*3; j++) {
|
||||
line[j] = ' ';
|
||||
}
|
||||
}
|
||||
line[j] = s[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
line[j] = '\0';
|
||||
if (s[i]=='\0')
|
||||
break;
|
||||
printf("%s\n", line);
|
||||
}
|
||||
if (j!=0) {
|
||||
printf("%s\n", line);
|
||||
}
|
||||
fflush(stdout);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* print_rt--
|
||||
* print contents of range table
|
||||
*/
|
||||
void
|
||||
print_rt(List *rtable)
|
||||
{
|
||||
List *l;
|
||||
int i=1;
|
||||
|
||||
printf("resno\trelname(refname)\trelid\tinFromCl\n");
|
||||
printf("-----\t----------------\t-----\t--------\n");
|
||||
foreach(l, rtable) {
|
||||
RangeTblEntry *rte = lfirst(l);
|
||||
printf("%d\t%s(%s)\t%d\t%d\t%s\n",
|
||||
i,rte->relname,rte->refname,rte->relid,
|
||||
rte->inFromCl,
|
||||
(rte->inh?"inh":""));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* print_expr--
|
||||
* print an expression
|
||||
*/
|
||||
void
|
||||
print_expr(Node *expr, List *rtable)
|
||||
{
|
||||
if (expr==NULL) {
|
||||
printf("nil");
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsA(expr,Var)) {
|
||||
Var *var = (Var*)expr;
|
||||
RangeTblEntry *rt;
|
||||
char *relname, *attname;
|
||||
|
||||
switch (var->varno) {
|
||||
case INNER:
|
||||
relname = "INNER";
|
||||
attname = "?";
|
||||
break;
|
||||
case OUTER:
|
||||
relname = "OUTER";
|
||||
attname = "?";
|
||||
break;
|
||||
default:
|
||||
{
|
||||
Relation r;
|
||||
rt = rt_fetch(var->varno, rtable);
|
||||
relname = rt->relname;
|
||||
r = heap_openr(relname);
|
||||
if (rt->refname)
|
||||
relname = rt->refname; /* table renamed */
|
||||
attname = getAttrName(r, var->varattno);
|
||||
heap_close(r);
|
||||
}
|
||||
break;
|
||||
}
|
||||
printf("%s.%s",relname,attname);
|
||||
} else if (IsA(expr,Expr)) {
|
||||
Expr *e = (Expr*)expr;
|
||||
if (is_opclause(expr)) {
|
||||
char *opname;
|
||||
|
||||
print_expr((Node*)get_leftop(e), rtable);
|
||||
opname = get_opname(((Oper*)e->oper)->opno);
|
||||
printf(" %s ", opname);
|
||||
print_expr((Node*)get_rightop(e), rtable);
|
||||
} else {
|
||||
printf("an expr");
|
||||
}
|
||||
} else {
|
||||
printf("not an expr");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* print_keys -
|
||||
* temporary here. where is keys list of list??
|
||||
*/
|
||||
void
|
||||
print_keys(List *keys, List *rtable)
|
||||
{
|
||||
List *k;
|
||||
|
||||
printf("(");
|
||||
foreach(k, keys) {
|
||||
Node *var = lfirst((List*)lfirst(k));
|
||||
print_expr(var, rtable);
|
||||
if (lnext(k)) printf(", ");
|
||||
}
|
||||
printf(")\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* print_tl --
|
||||
* print targetlist in a more legible way.
|
||||
*/
|
||||
void
|
||||
print_tl(List *tlist, List *rtable)
|
||||
{
|
||||
List *tl;
|
||||
|
||||
printf("(\n");
|
||||
foreach(tl, tlist) {
|
||||
TargetEntry *tle = lfirst(tl);
|
||||
|
||||
printf("\t%d %s\t", tle->resdom->resno, tle->resdom->resname);
|
||||
if (tle->resdom->reskey!=0) {
|
||||
printf("(%d):\t", tle->resdom->reskey);
|
||||
} else {
|
||||
printf(" :\t");
|
||||
}
|
||||
print_expr(tle->expr, rtable);
|
||||
printf("\n");
|
||||
}
|
||||
printf(")\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* print_slot--
|
||||
* print out the tuple with the given TupleTableSlot
|
||||
*/
|
||||
void
|
||||
print_slot(TupleTableSlot *slot)
|
||||
{
|
||||
if (!slot->val) {
|
||||
printf("tuple is null.\n");
|
||||
return;
|
||||
}
|
||||
if (!slot->ttc_tupleDescriptor) {
|
||||
printf("no tuple descriptor.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
debugtup(slot->val, slot->ttc_tupleDescriptor);
|
||||
}
|
||||
|
||||
char*
|
||||
plannode_type (Plan* p)
|
||||
{
|
||||
switch(nodeTag(p)) {
|
||||
case T_Plan:
|
||||
return "PLAN";
|
||||
break;
|
||||
case T_Existential:
|
||||
return "EXISTENTIAL";
|
||||
break;
|
||||
case T_Result:
|
||||
return "RESULT";
|
||||
break;
|
||||
case T_Append:
|
||||
return "APPEND";
|
||||
break;
|
||||
case T_Scan:
|
||||
return "SCAN";
|
||||
break;
|
||||
case T_SeqScan:
|
||||
return "SEQSCAN";
|
||||
break;
|
||||
case T_IndexScan:
|
||||
return "INDEXSCAN";
|
||||
break;
|
||||
case T_Join:
|
||||
return "JOIN";
|
||||
break;
|
||||
case T_NestLoop:
|
||||
return "NESTLOOP";
|
||||
break;
|
||||
case T_MergeJoin:
|
||||
return "MERGEJOIN";
|
||||
break;
|
||||
case T_HashJoin:
|
||||
return "HASHJOIN";
|
||||
break;
|
||||
case T_Temp:
|
||||
return "TEMP";
|
||||
break;
|
||||
case T_Material:
|
||||
return "MATERIAL";
|
||||
break;
|
||||
case T_Sort:
|
||||
return "SORT";
|
||||
break;
|
||||
case T_Agg:
|
||||
return "AGG";
|
||||
break;
|
||||
case T_Unique:
|
||||
return "UNIQUE";
|
||||
break;
|
||||
case T_Hash:
|
||||
return "HASH";
|
||||
break;
|
||||
case T_Tee:
|
||||
return "TEE";
|
||||
break;
|
||||
case T_Choose:
|
||||
return "CHOOSE";
|
||||
break;
|
||||
case T_Group:
|
||||
return "GROUP";
|
||||
break;
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
prints the ascii description of the plan nodes
|
||||
does this recursively by doing a depth-first traversal of the
|
||||
plan tree. for SeqScan and IndexScan, the name of the table is also
|
||||
printed out
|
||||
|
||||
*/
|
||||
void
|
||||
print_plan_recursive (Plan* p, Query *parsetree, int indentLevel, char* label)
|
||||
{
|
||||
int i;
|
||||
char extraInfo[100];
|
||||
|
||||
if (!p)
|
||||
return;
|
||||
for (i=0;i<indentLevel;i++)
|
||||
printf(" ");
|
||||
printf("%s%s :c=%.4f :s=%d :w=%d ",label, plannode_type(p),
|
||||
p->cost, p->plan_size, p->plan_width);
|
||||
if (IsA(p,Scan) || IsA(p,SeqScan)) {
|
||||
RangeTblEntry *rte;
|
||||
rte = rt_fetch(((Scan*)p)->scanrelid, parsetree->rtable);
|
||||
strncpy(extraInfo, rte->relname, NAMEDATALEN);
|
||||
extraInfo[NAMEDATALEN] = '\0';
|
||||
} else
|
||||
if (IsA(p,IndexScan)) {
|
||||
strncpy(extraInfo,
|
||||
((RangeTblEntry*)(nth(((IndexScan*)p)->scan.scanrelid - 1,
|
||||
parsetree->rtable)))->relname,
|
||||
NAMEDATALEN);
|
||||
extraInfo[NAMEDATALEN] = '\0';
|
||||
} else
|
||||
extraInfo[0] = '\0';
|
||||
if (extraInfo[0] != '\0')
|
||||
printf(" ( %s )\n", extraInfo);
|
||||
else
|
||||
printf("\n");
|
||||
print_plan_recursive(p->lefttree, parsetree, indentLevel + 3, "l: ");
|
||||
print_plan_recursive(p->righttree, parsetree, indentLevel + 3, "r: ");
|
||||
}
|
||||
|
||||
/* print_plan
|
||||
prints just the plan node types */
|
||||
|
||||
void
|
||||
print_plan (Plan* p, Query* parsetree)
|
||||
{
|
||||
print_plan_recursive(p, parsetree, 0, "");
|
||||
}
|
||||
|
||||
|
270
src/backend/nodes/read.c
Normal file
270
src/backend/nodes/read.c
Normal file
@ -0,0 +1,270 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* read.c--
|
||||
* routines to convert a string (legal ascii representation of node) back
|
||||
* to nodes
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/read.c,v 1.1.1.1 1996/07/09 06:21:33 scrappy Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
* Andrew Yu Nov 2, 1994 file creation
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "postgres.h"
|
||||
#include "nodes/pg_list.h"
|
||||
#include "nodes/readfuncs.h"
|
||||
#include "utils/elog.h"
|
||||
|
||||
/*
|
||||
* stringToNode -
|
||||
* returns a Node with a given legal ascii representation
|
||||
*/
|
||||
void *
|
||||
stringToNode(char *str)
|
||||
{
|
||||
void *retval;
|
||||
|
||||
(void) lsptok(str, NULL); /* set the string used in lsptok */
|
||||
retval = nodeRead(true); /* start reading */
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* the lisp token parser
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define RIGHT_PAREN (1000000 + 1)
|
||||
#define LEFT_PAREN (1000000 + 2)
|
||||
#define PLAN_SYM (1000000 + 3)
|
||||
#define AT_SYMBOL (1000000 + 4)
|
||||
#define ATOM_TOKEN (1000000 + 5)
|
||||
|
||||
/*
|
||||
* nodeTokenType -
|
||||
* returns the type of the node token contained in token.
|
||||
* It returns one of the following valid NodeTags:
|
||||
* T_Integer, T_Float, T_String
|
||||
* and some of its own:
|
||||
* RIGHT_PAREN, LEFT_PAREN, PLAN_SYM, AT_SYMBOL, ATOM_TOKEN
|
||||
*
|
||||
* Assumption: the ascii representation is legal
|
||||
*/
|
||||
static NodeTag
|
||||
nodeTokenType(char *token, int length)
|
||||
{
|
||||
NodeTag retval;
|
||||
|
||||
/*
|
||||
* Check if the token is a number (decimal or integer,
|
||||
* positive or negative
|
||||
*/
|
||||
if (isdigit(*token) ||
|
||||
(length>=2 && *token=='-' && isdigit(*(token+1)) ))
|
||||
{
|
||||
/*
|
||||
* skip the optional '-' (i.e. negative number)
|
||||
*/
|
||||
if (*token == '-') {
|
||||
token++;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if there is a decimal point
|
||||
*/
|
||||
|
||||
for (; length && *token != '.'; token++, length--);
|
||||
|
||||
/*
|
||||
* if there isn't, token's an int, otherwise it's a float.
|
||||
*/
|
||||
|
||||
retval = (*token != '.') ? T_Integer : T_Float;
|
||||
}
|
||||
else if (isalpha(*token))
|
||||
retval = ATOM_TOKEN;
|
||||
else if (*token == '(')
|
||||
retval = LEFT_PAREN;
|
||||
else if (*token == ')')
|
||||
retval = RIGHT_PAREN;
|
||||
else if (*token == '@')
|
||||
retval = AT_SYMBOL;
|
||||
else if (*token == '\"')
|
||||
retval = T_String;
|
||||
else if (*token == '{')
|
||||
retval = PLAN_SYM;
|
||||
return(retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Works kinda like strtok, except it doesn't put nulls into string.
|
||||
*
|
||||
* Returns the length in length instead. The string can be set without
|
||||
* returning a token by calling lsptok with length == NULL.
|
||||
*
|
||||
*/
|
||||
char *
|
||||
lsptok(char *string, int *length)
|
||||
{
|
||||
static char *local_str;
|
||||
char *ret_string;
|
||||
|
||||
if (string != NULL) {
|
||||
local_str = string;
|
||||
if (length == NULL) {
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
for (; *local_str == ' '
|
||||
|| *local_str == '\n'
|
||||
|| *local_str == '\t'; local_str++);
|
||||
|
||||
/*
|
||||
* Now pointing at next token.
|
||||
*/
|
||||
ret_string = local_str;
|
||||
if (*local_str == '\0') return(NULL);
|
||||
*length = 1;
|
||||
|
||||
if (*local_str == '\"') {
|
||||
for (local_str++; *local_str != '\"'; (*length)++, local_str++);
|
||||
(*length)++; local_str++;
|
||||
}else if (*local_str == ')' || *local_str == '(' ||
|
||||
*local_str == '}' || *local_str == '{') {
|
||||
local_str++;
|
||||
}else {
|
||||
for (; *local_str != ' '
|
||||
&& *local_str != '\n'
|
||||
&& *local_str != '\t'
|
||||
&& *local_str != '{'
|
||||
&& *local_str != '}'
|
||||
&& *local_str != '('
|
||||
&& *local_str != ')'; local_str++, (*length)++);
|
||||
(*length)--;
|
||||
}
|
||||
return(ret_string);
|
||||
}
|
||||
|
||||
/*
|
||||
* This guy does all the reading.
|
||||
*
|
||||
* Secrets: He assumes that lsptok already has the string (see below).
|
||||
* Any callers should set read_car_only to true.
|
||||
*/
|
||||
void *
|
||||
nodeRead(bool read_car_only)
|
||||
{
|
||||
char *token;
|
||||
NodeTag type;
|
||||
Node *this_value, *return_value;
|
||||
int tok_len;
|
||||
char tmp;
|
||||
bool make_dotted_pair_cell = false;
|
||||
|
||||
token = lsptok(NULL, &tok_len);
|
||||
|
||||
if (token == NULL) return(NULL);
|
||||
|
||||
type = nodeTokenType(token, tok_len);
|
||||
|
||||
switch(type) {
|
||||
case PLAN_SYM:
|
||||
this_value = parsePlanString();
|
||||
token = lsptok(NULL, &tok_len);
|
||||
if (token[0] != '}') return(NULL);
|
||||
|
||||
if (!read_car_only)
|
||||
make_dotted_pair_cell = true;
|
||||
else
|
||||
make_dotted_pair_cell = false;
|
||||
break;
|
||||
case LEFT_PAREN:
|
||||
if (!read_car_only) {
|
||||
List *l = makeNode(List);
|
||||
|
||||
lfirst(l) = nodeRead(false);
|
||||
lnext(l) = nodeRead(false);
|
||||
this_value = (Node*)l;
|
||||
}else {
|
||||
this_value = nodeRead(false);
|
||||
}
|
||||
break;
|
||||
case RIGHT_PAREN:
|
||||
this_value = NULL;
|
||||
break;
|
||||
case AT_SYMBOL:
|
||||
break;
|
||||
case ATOM_TOKEN:
|
||||
if (!strncmp(token, "nil", 3)) {
|
||||
this_value = NULL;
|
||||
/*
|
||||
* It might be "nil" but it is an atom!
|
||||
*/
|
||||
if (read_car_only) {
|
||||
make_dotted_pair_cell = false;
|
||||
} else {
|
||||
make_dotted_pair_cell = true;
|
||||
}
|
||||
}else {
|
||||
tmp = token[tok_len];
|
||||
token[tok_len] = '\0';
|
||||
this_value = (Node*)pstrdup(token); /* !attention! not a Node.
|
||||
use with caution */
|
||||
token[tok_len] = tmp;
|
||||
make_dotted_pair_cell = true;
|
||||
}
|
||||
break;
|
||||
case T_Float:
|
||||
tmp = token[tok_len];
|
||||
token[tok_len] = '\0';
|
||||
this_value = (Node*)makeFloat(atof(token));
|
||||
token[tok_len] = tmp;
|
||||
make_dotted_pair_cell = true;
|
||||
break;
|
||||
case T_Integer:
|
||||
tmp = token[tok_len];
|
||||
token[tok_len] = '\0';
|
||||
this_value = (Node*)makeInteger(atoi(token));
|
||||
token[tok_len] = tmp;
|
||||
make_dotted_pair_cell = true;
|
||||
break;
|
||||
case T_String:
|
||||
tmp = token[tok_len - 1];
|
||||
token[tok_len - 1] = '\0';
|
||||
token++;
|
||||
this_value = (Node*)makeString(token); /* !! not strdup'd */
|
||||
token[tok_len - 2] = tmp;
|
||||
make_dotted_pair_cell = true;
|
||||
break;
|
||||
default:
|
||||
elog(WARN, "nodeRead: Bad type %d", type);
|
||||
break;
|
||||
}
|
||||
if (make_dotted_pair_cell) {
|
||||
List *l = makeNode(List);
|
||||
|
||||
lfirst(l) = this_value;
|
||||
if (!read_car_only) {
|
||||
lnext(l) = nodeRead(false);
|
||||
}else {
|
||||
lnext(l) = NULL;
|
||||
}
|
||||
return_value = (Node*)l;
|
||||
}else {
|
||||
return_value = this_value;
|
||||
}
|
||||
return(return_value);
|
||||
}
|
||||
|
1948
src/backend/nodes/readfuncs.c
Normal file
1948
src/backend/nodes/readfuncs.c
Normal file
File diff suppressed because it is too large
Load Diff
27
src/backend/nodes/readfuncs.h
Normal file
27
src/backend/nodes/readfuncs.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* readfuncs.h--
|
||||
* header file for read.c and readfuncs.c. These functions are internal
|
||||
* to the stringToNode interface and should not be used by anyone else.
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: readfuncs.h,v 1.1.1.1 1996/07/09 06:21:33 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef READFUNCS_H
|
||||
#define READFUNCS_H
|
||||
|
||||
/*
|
||||
* prototypes for functions in read.c (the lisp token parser)
|
||||
*/
|
||||
extern char *lsptok(char *string, int *length);
|
||||
extern void *nodeRead(bool read_car_only);
|
||||
|
||||
/*
|
||||
* prototypes for functions in readfuncs.c
|
||||
*/
|
||||
extern Node *parsePlanString();
|
||||
|
||||
#endif /* READFUNCS_H */
|
279
src/backend/nodes/relation.h
Normal file
279
src/backend/nodes/relation.h
Normal file
@ -0,0 +1,279 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* relation.h--
|
||||
* Definitions for internal planner nodes.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: relation.h,v 1.1.1.1 1996/07/09 06:21:33 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef RELATION_H
|
||||
#define RELATION_H
|
||||
|
||||
#include "c.h"
|
||||
#include "nodes/pg_list.h"
|
||||
#include "nodes/primnodes.h"
|
||||
#include "nodes/parsenodes.h"
|
||||
#include "nodes/nodes.h"
|
||||
|
||||
/*
|
||||
* Relid
|
||||
* List of relation identifiers (indexes into the rangetable).
|
||||
*/
|
||||
|
||||
typedef List *Relid;
|
||||
|
||||
/*
|
||||
* Rel
|
||||
* Per-base-relation information
|
||||
*
|
||||
* Parts of this data structure are specific to various scan and join
|
||||
* mechanisms. It didn't seem worth creating new node types for them.
|
||||
*
|
||||
* relids - List of relation indentifiers
|
||||
* indexed - true if the relation has secondary indices
|
||||
* pages - number of pages in the relation
|
||||
* tuples - number of tuples in the relation
|
||||
* size - number of tuples in the relation after restrictions clauses
|
||||
* have been applied
|
||||
* width - number of bytes per tuple in the relation after the
|
||||
* appropriate projections have been done
|
||||
* targetlist - List of TargetList nodes
|
||||
* pathlist - List of Path nodes, one for each possible method of
|
||||
* generating the relation
|
||||
* unorderedpath - a Path node generating this relation whose resulting
|
||||
* tuples are unordered (this isn't necessarily a
|
||||
* sequential scan path, e.g., scanning with a hash index
|
||||
* leaves the tuples unordered)
|
||||
* cheapestpath - least expensive Path (regardless of final order)
|
||||
* pruneable - flag to let the planner know whether it can prune the plan
|
||||
* space of this Rel or not. -- JMH, 11/11/92
|
||||
*
|
||||
* * If the relation is a (secondary) index it will have the following
|
||||
* three fields:
|
||||
*
|
||||
* classlist - List of PG_AMOPCLASS OIDs for the index
|
||||
* indexkeys - List of base-relation attribute numbers that are index keys
|
||||
* ordering - List of PG_OPERATOR OIDs which order the indexscan result
|
||||
* relam - the OID of the pg_am of the index
|
||||
*
|
||||
* * The presence of the remaining fields depends on the restrictions
|
||||
* and joins which the relation participates in:
|
||||
*
|
||||
* clauseinfo - List of ClauseInfo nodes, containing info about each
|
||||
* qualification clause in which this relation participates
|
||||
* joininfo - List of JoinInfo nodes, containing info about each join
|
||||
* clause in which this relation participates
|
||||
* innerjoin - List of Path nodes that represent indices that may be used
|
||||
* as inner paths of nestloop joins
|
||||
*
|
||||
* NB. the last element of the arrays classlist, indexkeys and ordering
|
||||
* is always 0. 2/95 - ay
|
||||
*/
|
||||
|
||||
typedef struct Rel {
|
||||
NodeTag type;
|
||||
|
||||
/* all relations: */
|
||||
Relid relids;
|
||||
|
||||
/* catalog statistics information */
|
||||
bool indexed;
|
||||
int pages;
|
||||
int tuples;
|
||||
int size;
|
||||
int width;
|
||||
|
||||
/* materialization information */
|
||||
List *targetlist;
|
||||
List *pathlist;
|
||||
struct Path *unorderedpath;
|
||||
struct Path *cheapestpath;
|
||||
bool pruneable;
|
||||
|
||||
/* used solely by indices: */
|
||||
Oid *classlist; /* classes of AM operators */
|
||||
int *indexkeys; /* keys over which we're indexing */
|
||||
Oid relam; /* OID of the access method (in pg_am) */
|
||||
|
||||
Oid indproc;
|
||||
List *indpred;
|
||||
|
||||
/* used by various scans and joins: */
|
||||
Oid *ordering; /* OID of operators in sort order */
|
||||
List *clauseinfo; /* restriction clauses */
|
||||
List *joininfo; /* join clauses */
|
||||
List *innerjoin;
|
||||
List *superrels;
|
||||
} Rel;
|
||||
|
||||
extern Var *get_expr(TargetEntry *foo);
|
||||
|
||||
typedef struct MergeOrder {
|
||||
NodeTag type;
|
||||
Oid join_operator;
|
||||
Oid left_operator;
|
||||
Oid right_operator;
|
||||
Oid left_type;
|
||||
Oid right_type;
|
||||
} MergeOrder;
|
||||
|
||||
typedef enum OrderType {
|
||||
MERGE_ORDER, SORTOP_ORDER
|
||||
} OrderType;
|
||||
|
||||
typedef struct PathOrder {
|
||||
OrderType ordtype;
|
||||
union {
|
||||
Oid *sortop;
|
||||
MergeOrder *merge;
|
||||
} ord;
|
||||
} PathOrder;
|
||||
|
||||
typedef struct Path {
|
||||
NodeTag type;
|
||||
|
||||
Rel *parent;
|
||||
Cost path_cost;
|
||||
|
||||
NodeTag pathtype;
|
||||
|
||||
PathOrder p_ordering;
|
||||
|
||||
List *keys;
|
||||
Cost outerjoincost;
|
||||
Relid joinid;
|
||||
List *locclauseinfo;
|
||||
} Path;
|
||||
|
||||
typedef struct IndexPath {
|
||||
Path path;
|
||||
List *indexid;
|
||||
List *indexqual;
|
||||
} IndexPath;
|
||||
|
||||
typedef struct JoinPath {
|
||||
Path path;
|
||||
List *pathclauseinfo;
|
||||
Path *outerjoinpath;
|
||||
Path *innerjoinpath;
|
||||
} JoinPath;
|
||||
|
||||
typedef struct MergePath {
|
||||
JoinPath jpath;
|
||||
List *path_mergeclauses;
|
||||
List *outersortkeys;
|
||||
List *innersortkeys;
|
||||
} MergePath;
|
||||
|
||||
typedef struct HashPath {
|
||||
JoinPath jpath;
|
||||
List *path_hashclauses;
|
||||
List *outerhashkeys;
|
||||
List *innerhashkeys;
|
||||
} HashPath;
|
||||
|
||||
/******
|
||||
* Keys
|
||||
******/
|
||||
|
||||
typedef struct OrderKey {
|
||||
NodeTag type;
|
||||
int attribute_number;
|
||||
Index array_index;
|
||||
} OrderKey;
|
||||
|
||||
typedef struct JoinKey {
|
||||
NodeTag type;
|
||||
Var *outer;
|
||||
Var *inner;
|
||||
} JoinKey;
|
||||
|
||||
/*******
|
||||
* clause info
|
||||
*******/
|
||||
|
||||
typedef struct CInfo {
|
||||
NodeTag type;
|
||||
Expr *clause; /* should be an OP clause */
|
||||
Cost selectivity;
|
||||
bool notclause;
|
||||
List *indexids;
|
||||
|
||||
/* mergesort only */
|
||||
MergeOrder *mergesortorder;
|
||||
|
||||
/* hashjoin only */
|
||||
Oid hashjoinoperator;
|
||||
Relid cinfojoinid;
|
||||
} CInfo;
|
||||
|
||||
typedef struct JoinMethod {
|
||||
NodeTag type;
|
||||
List *jmkeys;
|
||||
List *clauses;
|
||||
} JoinMethod;
|
||||
|
||||
typedef struct HInfo {
|
||||
JoinMethod jmethod;
|
||||
Oid hashop;
|
||||
} HInfo;
|
||||
|
||||
typedef struct MInfo {
|
||||
JoinMethod jmethod;
|
||||
MergeOrder *m_ordering;
|
||||
} MInfo;
|
||||
|
||||
typedef struct JInfo {
|
||||
NodeTag type;
|
||||
List *otherrels;
|
||||
List *jinfoclauseinfo;
|
||||
bool mergesortable;
|
||||
bool hashjoinable;
|
||||
bool inactive;
|
||||
} JInfo;
|
||||
|
||||
typedef struct Iter {
|
||||
NodeTag type;
|
||||
Node *iterexpr;
|
||||
Oid itertype; /* type of the iter expr (use for type
|
||||
checking) */
|
||||
} Iter;
|
||||
|
||||
/*
|
||||
** Stream:
|
||||
** A stream represents a root-to-leaf path in a plan tree (i.e. a tree of
|
||||
** JoinPaths and Paths). The stream includes pointers to all Path nodes,
|
||||
** as well as to any clauses that reside above Path nodes. This structure
|
||||
** is used to make Path nodes and clauses look similar, so that Predicate
|
||||
** Migration can run.
|
||||
**
|
||||
** pathptr -- pointer to the current path node
|
||||
** cinfo -- if NULL, this stream node referes to the path node.
|
||||
** Otherwise this is a pointer to the current clause.
|
||||
** clausetype -- whether cinfo is in locclauseinfo or pathclauseinfo in the
|
||||
** path node
|
||||
** upstream -- linked list pointer upwards
|
||||
** downstream -- ditto, downwards
|
||||
** groupup -- whether or not this node is in a group with the node upstream
|
||||
** groupcost -- total cost of the group that node is in
|
||||
** groupsel -- total selectivity of the group that node is in
|
||||
*/
|
||||
typedef struct Stream *StreamPtr;
|
||||
|
||||
typedef struct Stream {
|
||||
NodeTag type;
|
||||
Path *pathptr;
|
||||
CInfo *cinfo;
|
||||
int *clausetype;
|
||||
struct Stream *upstream;
|
||||
struct Stream *downstream;
|
||||
bool groupup;
|
||||
Cost groupcost;
|
||||
Cost groupsel;
|
||||
} Stream;
|
||||
|
||||
#endif /* RELATION_H */
|
Reference in New Issue
Block a user