mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
OK, folks, here is the pgindent output.
This commit is contained in:
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.24 1998/07/27 19:37:54 vadim Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.25 1998/09/01 04:28:13 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -54,8 +54,7 @@
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/heap.h"
|
||||
|
||||
static Pointer
|
||||
ExecBeginScan(Relation relation, int nkeys, ScanKey skeys,
|
||||
static Pointer ExecBeginScan(Relation relation, int nkeys, ScanKey skeys,
|
||||
bool isindex, ScanDirection dir, Snapshot snapshot);
|
||||
static Relation ExecOpenR(Oid relationOid, bool isindex);
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/Attic/execFlatten.c,v 1.6 1998/09/01 03:22:11 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/Attic/execFlatten.c,v 1.7 1998/09/01 04:28:14 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -33,8 +33,7 @@
|
||||
#include "executor/execFlatten.h"
|
||||
|
||||
#ifdef SETS_FIXED
|
||||
static bool
|
||||
FjoinBumpOuterNodes(TargetEntry *tlist, ExprContext *econtext,
|
||||
static bool FjoinBumpOuterNodes(TargetEntry *tlist, ExprContext *econtext,
|
||||
DatumPtr results, char *nulls);
|
||||
|
||||
#endif
|
||||
|
@ -26,7 +26,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.54 1998/09/01 03:22:14 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.55 1998/09/01 04:28:16 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -54,31 +54,25 @@
|
||||
#include "catalog/heap.h"
|
||||
#include "commands/trigger.h"
|
||||
|
||||
void
|
||||
ExecCheckPerms(CmdType operation, int resultRelation, List *rangeTable,
|
||||
void ExecCheckPerms(CmdType operation, int resultRelation, List *rangeTable,
|
||||
Query *parseTree);
|
||||
|
||||
|
||||
/* decls for local routines only used within this module */
|
||||
static TupleDesc
|
||||
InitPlan(CmdType operation, Query *parseTree,
|
||||
static TupleDesc InitPlan(CmdType operation, Query *parseTree,
|
||||
Plan *plan, EState *estate);
|
||||
static void EndPlan(Plan *plan, EState *estate);
|
||||
static TupleTableSlot *
|
||||
ExecutePlan(EState *estate, Plan *plan,
|
||||
static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan,
|
||||
Query *parseTree, CmdType operation,
|
||||
int numberTuples, ScanDirection direction,
|
||||
void (*printfunc) ());
|
||||
static void ExecRetrieve(TupleTableSlot *slot, void (*printfunc) (),
|
||||
EState *estate);
|
||||
static void
|
||||
ExecAppend(TupleTableSlot *slot, ItemPointer tupleid,
|
||||
static void ExecAppend(TupleTableSlot *slot, ItemPointer tupleid,
|
||||
EState *estate);
|
||||
static void
|
||||
ExecDelete(TupleTableSlot *slot, ItemPointer tupleid,
|
||||
static void ExecDelete(TupleTableSlot *slot, ItemPointer tupleid,
|
||||
EState *estate);
|
||||
static void
|
||||
ExecReplace(TupleTableSlot *slot, ItemPointer tupleid,
|
||||
static void ExecReplace(TupleTableSlot *slot, ItemPointer tupleid,
|
||||
EState *estate, Query *parseTree);
|
||||
|
||||
/* end of local decls */
|
||||
@ -124,7 +118,7 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate)
|
||||
palloc(queryDesc->plantree->nParamExec * sizeof(ParamExecData));
|
||||
memset(estate->es_param_exec_vals, 0, queryDesc->plantree->nParamExec * sizeof(ParamExecData));
|
||||
}
|
||||
|
||||
|
||||
estate->es_snapshot = SnapshotNow;
|
||||
|
||||
result = InitPlan(queryDesc->operation,
|
||||
@ -315,8 +309,8 @@ ExecCheckPerms(CmdType operation,
|
||||
|
||||
relid = rte->relid;
|
||||
htup = SearchSysCacheTuple(RELOID,
|
||||
ObjectIdGetDatum(relid),
|
||||
0, 0, 0);
|
||||
ObjectIdGetDatum(relid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(htup))
|
||||
elog(ERROR, "ExecCheckPerms: bogus RT relid: %d",
|
||||
relid);
|
||||
@ -521,19 +515,19 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
|
||||
* NOTE: in the future we might want to initialize the junk
|
||||
* filter for all queries.
|
||||
* ----------------
|
||||
* SELECT added by daveh@insightdist.com 5/20/98 to allow
|
||||
* ORDER/GROUP BY have an identifier missing from the target.
|
||||
* SELECT added by daveh@insightdist.com 5/20/98 to allow
|
||||
* ORDER/GROUP BY have an identifier missing from the target.
|
||||
*/
|
||||
{
|
||||
bool junk_filter_needed = false;
|
||||
List *tlist;
|
||||
|
||||
bool junk_filter_needed = false;
|
||||
List *tlist;
|
||||
|
||||
if (operation == CMD_SELECT)
|
||||
{
|
||||
foreach(tlist, targetList)
|
||||
{
|
||||
TargetEntry *tle = lfirst(tlist);
|
||||
|
||||
TargetEntry *tle = lfirst(tlist);
|
||||
|
||||
if (tle->resdom->resjunk)
|
||||
{
|
||||
junk_filter_needed = true;
|
||||
@ -547,6 +541,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
|
||||
(operation == CMD_SELECT && junk_filter_needed))
|
||||
{
|
||||
JunkFilter *j = (JunkFilter *) ExecInitJunkFilter(targetList);
|
||||
|
||||
estate->es_junkFilter = j;
|
||||
|
||||
if (operation == CMD_SELECT)
|
||||
@ -555,7 +550,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
|
||||
else
|
||||
estate->es_junkFilter = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------
|
||||
* initialize the "into" relation
|
||||
* ----------------
|
||||
@ -588,7 +583,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
|
||||
tupdesc = CreateTupleDescCopy(tupType);
|
||||
|
||||
intoRelationId = heap_create_with_catalog(intoName,
|
||||
tupdesc, RELKIND_RELATION);
|
||||
tupdesc, RELKIND_RELATION);
|
||||
|
||||
FreeTupleDesc(tupdesc);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.35 1998/09/01 03:22:18 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.36 1998/09/01 04:28:18 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -68,24 +68,19 @@ int execConstLen;
|
||||
|
||||
/* static functions decls */
|
||||
static Datum ExecEvalAggreg(Aggreg *agg, ExprContext *econtext, bool *isNull);
|
||||
static Datum
|
||||
ExecEvalArrayRef(ArrayRef *arrayRef, ExprContext *econtext,
|
||||
static Datum ExecEvalArrayRef(ArrayRef *arrayRef, ExprContext *econtext,
|
||||
bool *isNull, bool *isDone);
|
||||
static Datum ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull);
|
||||
static Datum
|
||||
ExecEvalFunc(Expr *funcClause, ExprContext *econtext,
|
||||
static Datum ExecEvalFunc(Expr *funcClause, ExprContext *econtext,
|
||||
bool *isNull, bool *isDone);
|
||||
static void
|
||||
ExecEvalFuncArgs(FunctionCachePtr fcache, ExprContext *econtext,
|
||||
static void ExecEvalFuncArgs(FunctionCachePtr fcache, ExprContext *econtext,
|
||||
List *argList, Datum argV[], bool *argIsDone);
|
||||
static Datum ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull);
|
||||
static Datum
|
||||
ExecEvalOper(Expr *opClause, ExprContext *econtext,
|
||||
static Datum ExecEvalOper(Expr *opClause, ExprContext *econtext,
|
||||
bool *isNull);
|
||||
static Datum ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull);
|
||||
static Datum ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull);
|
||||
static Datum
|
||||
ExecMakeFunctionResult(Node *node, List *arguments,
|
||||
static Datum ExecMakeFunctionResult(Node *node, List *arguments,
|
||||
ExprContext *econtext, bool *isNull, bool *isDone);
|
||||
static bool ExecQualClause(Node *clause, ExprContext *econtext);
|
||||
|
||||
@ -200,7 +195,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
|
||||
static Datum
|
||||
ExecEvalAggreg(Aggreg *agg, ExprContext *econtext, bool *isNull)
|
||||
{
|
||||
*isNull = econtext->ecxt_nulls[agg->aggno];
|
||||
*isNull = econtext->ecxt_nulls[agg->aggno];
|
||||
return econtext->ecxt_values[agg->aggno];
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execScan.c,v 1.7 1998/02/26 12:13:09 vadim Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execScan.c,v 1.8 1998/09/01 04:28:20 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -106,9 +106,9 @@ ExecScan(Scan *node,
|
||||
* NULL, then it means there is nothing more to scan
|
||||
* so we just return the empty slot...
|
||||
*
|
||||
* ... with invalid TupleDesc (not the same as in
|
||||
* projInfo->pi_slot) and break upper MergeJoin node.
|
||||
* New code below do what ExecProject() does. - vadim 02/26/98
|
||||
* ... with invalid TupleDesc (not the same as in
|
||||
* projInfo->pi_slot) and break upper MergeJoin node.
|
||||
* New code below do what ExecProject() does. - vadim 02/26/98
|
||||
* ----------------
|
||||
*/
|
||||
if (TupIsNull(slot))
|
||||
@ -116,10 +116,10 @@ ExecScan(Scan *node,
|
||||
scanstate->cstate.cs_TupFromTlist = false;
|
||||
resultSlot = scanstate->cstate.cs_ProjInfo->pi_slot;
|
||||
return (TupleTableSlot *)
|
||||
ExecStoreTuple (NULL,
|
||||
resultSlot,
|
||||
InvalidBuffer,
|
||||
true);
|
||||
ExecStoreTuple(NULL,
|
||||
resultSlot,
|
||||
InvalidBuffer,
|
||||
true);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.37 1998/09/01 03:22:21 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.38 1998/09/01 04:28:22 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -57,8 +57,7 @@
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/mcxt.h"
|
||||
|
||||
static void
|
||||
ExecGetIndexKeyInfo(Form_pg_index indexTuple, int *numAttsOutP,
|
||||
static void ExecGetIndexKeyInfo(Form_pg_index indexTuple, int *numAttsOutP,
|
||||
AttrNumber **attsOutP, FuncIndexInfoPtr fInfoP);
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
@ -750,7 +749,7 @@ ExecOpenIndices(Oid resultRelationOid,
|
||||
*/
|
||||
indexSd = heap_beginscan(indexRd, /* scan desc */
|
||||
false, /* scan backward flag */
|
||||
SnapshotNow, /* NOW snapshot */
|
||||
SnapshotNow, /* NOW snapshot */
|
||||
1, /* number scan keys */
|
||||
&key); /* scan keys */
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.19 1998/09/01 03:22:22 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.20 1998/09/01 04:28:23 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -57,16 +57,13 @@ typedef struct local_es
|
||||
|
||||
/* non-export function prototypes */
|
||||
static TupleDesc postquel_start(execution_state *es);
|
||||
static execution_state *
|
||||
init_execution_state(FunctionCachePtr fcache,
|
||||
static execution_state *init_execution_state(FunctionCachePtr fcache,
|
||||
char *args[]);
|
||||
static TupleTableSlot *postquel_getnext(execution_state *es);
|
||||
static void postquel_end(execution_state *es);
|
||||
static void
|
||||
postquel_sub_params(execution_state *es, int nargs,
|
||||
static void postquel_sub_params(execution_state *es, int nargs,
|
||||
char *args[], bool *nullV);
|
||||
static Datum
|
||||
postquel_execute(execution_state *es, FunctionCachePtr fcache,
|
||||
static Datum postquel_execute(execution_state *es, FunctionCachePtr fcache,
|
||||
List *fTlist, char **args, bool *isNull);
|
||||
|
||||
|
||||
|
@ -109,388 +109,397 @@ ExecAgg(Agg *node)
|
||||
bool isNull = FALSE,
|
||||
isNull1 = FALSE,
|
||||
isNull2 = FALSE;
|
||||
bool qual_result;
|
||||
|
||||
bool qual_result;
|
||||
|
||||
|
||||
/* ---------------------
|
||||
* get state info from node
|
||||
* ---------------------
|
||||
*/
|
||||
|
||||
/* We loop retrieving groups until we find one matching node->plan.qual */
|
||||
do {
|
||||
|
||||
aggstate = node->aggstate;
|
||||
if (aggstate->agg_done)
|
||||
return NULL;
|
||||
|
||||
estate = node->plan.state;
|
||||
econtext = aggstate->csstate.cstate.cs_ExprContext;
|
||||
|
||||
nagg = length(node->aggs);
|
||||
|
||||
aggregates = (Aggreg **) palloc(sizeof(Aggreg *) * nagg);
|
||||
|
||||
/* take List* and make it an array that can be quickly indexed */
|
||||
alist = node->aggs;
|
||||
for (i = 0; i < nagg; i++)
|
||||
{
|
||||
aggregates[i] = lfirst(alist);
|
||||
aggregates[i]->aggno = i;
|
||||
alist = lnext(alist);
|
||||
}
|
||||
|
||||
value1 = node->aggstate->csstate.cstate.cs_ExprContext->ecxt_values;
|
||||
nulls = node->aggstate->csstate.cstate.cs_ExprContext->ecxt_nulls;
|
||||
|
||||
value2 = (Datum *) palloc(sizeof(Datum) * nagg);
|
||||
MemSet(value2, 0, sizeof(Datum) * nagg);
|
||||
|
||||
aggFuncInfo = (AggFuncInfo *) palloc(sizeof(AggFuncInfo) * nagg);
|
||||
MemSet(aggFuncInfo, 0, sizeof(AggFuncInfo) * nagg);
|
||||
|
||||
noInitValue = (int *) palloc(sizeof(int) * nagg);
|
||||
MemSet(noInitValue, 0, sizeof(noInitValue) * nagg);
|
||||
|
||||
outerPlan = outerPlan(node);
|
||||
oneTuple = NULL;
|
||||
|
||||
projInfo = aggstate->csstate.cstate.cs_ProjInfo;
|
||||
|
||||
for (i = 0; i < nagg; i++)
|
||||
{
|
||||
Aggreg *agg;
|
||||
char *aggname;
|
||||
HeapTuple aggTuple;
|
||||
Form_pg_aggregate aggp;
|
||||
Oid xfn1_oid,
|
||||
xfn2_oid,
|
||||
finalfn_oid;
|
||||
|
||||
agg = aggregates[i];
|
||||
|
||||
/* ---------------------
|
||||
* find transfer functions of all the aggregates and initialize
|
||||
* their initial values
|
||||
* ---------------------
|
||||
*/
|
||||
aggname = agg->aggname;
|
||||
aggTuple = SearchSysCacheTuple(AGGNAME,
|
||||
PointerGetDatum(aggname),
|
||||
ObjectIdGetDatum(agg->basetype),
|
||||
0, 0);
|
||||
if (!HeapTupleIsValid(aggTuple))
|
||||
elog(ERROR, "ExecAgg: cache lookup failed for aggregate \"%s\"(%s)",
|
||||
aggname,
|
||||
typeidTypeName(agg->basetype));
|
||||
aggp = (Form_pg_aggregate) GETSTRUCT(aggTuple);
|
||||
|
||||
xfn1_oid = aggp->aggtransfn1;
|
||||
xfn2_oid = aggp->aggtransfn2;
|
||||
finalfn_oid = aggp->aggfinalfn;
|
||||
|
||||
if (OidIsValid(finalfn_oid))
|
||||
{
|
||||
fmgr_info(finalfn_oid, &aggFuncInfo[i].finalfn);
|
||||
aggFuncInfo[i].finalfn_oid = finalfn_oid;
|
||||
}
|
||||
|
||||
if (OidIsValid(xfn2_oid))
|
||||
{
|
||||
fmgr_info(xfn2_oid, &aggFuncInfo[i].xfn2);
|
||||
aggFuncInfo[i].xfn2_oid = xfn2_oid;
|
||||
value2[i] = (Datum) AggNameGetInitVal((char *) aggname,
|
||||
aggp->aggbasetype,
|
||||
2,
|
||||
&isNull2);
|
||||
/* ------------------------------------------
|
||||
* If there is a second transition function, its initial
|
||||
* value must exist -- as it does not depend on data values,
|
||||
* we have no other way of determining an initial value.
|
||||
* ------------------------------------------
|
||||
*/
|
||||
if (isNull2)
|
||||
elog(ERROR, "ExecAgg: agginitval2 is null");
|
||||
}
|
||||
|
||||
if (OidIsValid(xfn1_oid))
|
||||
{
|
||||
fmgr_info(xfn1_oid, &aggFuncInfo[i].xfn1);
|
||||
aggFuncInfo[i].xfn1_oid = xfn1_oid;
|
||||
value1[i] = (Datum) AggNameGetInitVal((char *) aggname,
|
||||
aggp->aggbasetype,
|
||||
1,
|
||||
&isNull1);
|
||||
|
||||
/* ------------------------------------------
|
||||
* If the initial value for the first transition function
|
||||
* doesn't exist in the pg_aggregate table then we let
|
||||
* the first value returned from the outer procNode become
|
||||
* the initial value. (This is useful for aggregates like
|
||||
* max{} and min{}.)
|
||||
* ------------------------------------------
|
||||
*/
|
||||
if (isNull1)
|
||||
{
|
||||
noInitValue[i] = 1;
|
||||
nulls[i] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* for each tuple from the the outer plan, apply all the aggregates
|
||||
* ----------------
|
||||
/*
|
||||
* We loop retrieving groups until we find one matching
|
||||
* node->plan.qual
|
||||
*/
|
||||
for (;;)
|
||||
do
|
||||
{
|
||||
HeapTuple outerTuple = NULL;
|
||||
TupleTableSlot *outerslot;
|
||||
|
||||
isNull = isNull1 = isNull2 = 0;
|
||||
outerslot = ExecProcNode(outerPlan, (Plan *) node);
|
||||
if (outerslot)
|
||||
outerTuple = outerslot->val;
|
||||
if (!HeapTupleIsValid(outerTuple))
|
||||
aggstate = node->aggstate;
|
||||
if (aggstate->agg_done)
|
||||
return NULL;
|
||||
|
||||
estate = node->plan.state;
|
||||
econtext = aggstate->csstate.cstate.cs_ExprContext;
|
||||
|
||||
nagg = length(node->aggs);
|
||||
|
||||
aggregates = (Aggreg **) palloc(sizeof(Aggreg *) * nagg);
|
||||
|
||||
/* take List* and make it an array that can be quickly indexed */
|
||||
alist = node->aggs;
|
||||
for (i = 0; i < nagg; i++)
|
||||
{
|
||||
|
||||
/*
|
||||
* when the outerplan doesn't return a single tuple, create a
|
||||
* dummy heaptuple anyway because we still need to return a
|
||||
* valid aggregate value. The value returned will be the
|
||||
* initial values of the transition functions
|
||||
*/
|
||||
if (nTuplesAgged == 0)
|
||||
{
|
||||
TupleDesc tupType;
|
||||
Datum *tupValue;
|
||||
char *null_array;
|
||||
|
||||
tupType = aggstate->csstate.css_ScanTupleSlot->ttc_tupleDescriptor;
|
||||
tupValue = projInfo->pi_tupValue;
|
||||
|
||||
/* initially, set all the values to NULL */
|
||||
null_array = palloc(tupType->natts);
|
||||
for (i = 0; i < tupType->natts; i++)
|
||||
null_array[i] = 'n';
|
||||
oneTuple = heap_formtuple(tupType, tupValue, null_array);
|
||||
pfree(null_array);
|
||||
}
|
||||
break;
|
||||
aggregates[i] = lfirst(alist);
|
||||
aggregates[i]->aggno = i;
|
||||
alist = lnext(alist);
|
||||
}
|
||||
|
||||
value1 = node->aggstate->csstate.cstate.cs_ExprContext->ecxt_values;
|
||||
nulls = node->aggstate->csstate.cstate.cs_ExprContext->ecxt_nulls;
|
||||
|
||||
value2 = (Datum *) palloc(sizeof(Datum) * nagg);
|
||||
MemSet(value2, 0, sizeof(Datum) * nagg);
|
||||
|
||||
aggFuncInfo = (AggFuncInfo *) palloc(sizeof(AggFuncInfo) * nagg);
|
||||
MemSet(aggFuncInfo, 0, sizeof(AggFuncInfo) * nagg);
|
||||
|
||||
noInitValue = (int *) palloc(sizeof(int) * nagg);
|
||||
MemSet(noInitValue, 0, sizeof(noInitValue) * nagg);
|
||||
|
||||
outerPlan = outerPlan(node);
|
||||
oneTuple = NULL;
|
||||
|
||||
projInfo = aggstate->csstate.cstate.cs_ProjInfo;
|
||||
|
||||
for (i = 0; i < nagg; i++)
|
||||
{
|
||||
AttrNumber attnum;
|
||||
int2 attlen = 0;
|
||||
Datum newVal = (Datum) NULL;
|
||||
AggFuncInfo *aggfns = &aggFuncInfo[i];
|
||||
Datum args[2];
|
||||
Node *tagnode = NULL;
|
||||
Aggreg *agg;
|
||||
char *aggname;
|
||||
HeapTuple aggTuple;
|
||||
Form_pg_aggregate aggp;
|
||||
Oid xfn1_oid,
|
||||
xfn2_oid,
|
||||
finalfn_oid;
|
||||
|
||||
switch (nodeTag(aggregates[i]->target))
|
||||
agg = aggregates[i];
|
||||
|
||||
/* ---------------------
|
||||
* find transfer functions of all the aggregates and initialize
|
||||
* their initial values
|
||||
* ---------------------
|
||||
*/
|
||||
aggname = agg->aggname;
|
||||
aggTuple = SearchSysCacheTuple(AGGNAME,
|
||||
PointerGetDatum(aggname),
|
||||
ObjectIdGetDatum(agg->basetype),
|
||||
0, 0);
|
||||
if (!HeapTupleIsValid(aggTuple))
|
||||
elog(ERROR, "ExecAgg: cache lookup failed for aggregate \"%s\"(%s)",
|
||||
aggname,
|
||||
typeidTypeName(agg->basetype));
|
||||
aggp = (Form_pg_aggregate) GETSTRUCT(aggTuple);
|
||||
|
||||
xfn1_oid = aggp->aggtransfn1;
|
||||
xfn2_oid = aggp->aggtransfn2;
|
||||
finalfn_oid = aggp->aggfinalfn;
|
||||
|
||||
if (OidIsValid(finalfn_oid))
|
||||
{
|
||||
case T_Var:
|
||||
tagnode = NULL;
|
||||
newVal = aggGetAttr(outerslot,
|
||||
aggregates[i],
|
||||
&isNull);
|
||||
break;
|
||||
case T_Expr:
|
||||
tagnode = ((Expr *) aggregates[i]->target)->oper;
|
||||
econtext->ecxt_scantuple = outerslot;
|
||||
newVal = ExecEvalExpr(aggregates[i]->target, econtext,
|
||||
&isNull, &isDone);
|
||||
break;
|
||||
case T_Const:
|
||||
tagnode = NULL;
|
||||
econtext->ecxt_scantuple = outerslot;
|
||||
newVal = ExecEvalExpr(aggregates[i]->target, econtext,
|
||||
&isNull, &isDone);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "ExecAgg: Bad Agg->Target for Agg %d", i);
|
||||
fmgr_info(finalfn_oid, &aggFuncInfo[i].finalfn);
|
||||
aggFuncInfo[i].finalfn_oid = finalfn_oid;
|
||||
}
|
||||
|
||||
if (isNull && !aggregates[i]->usenulls)
|
||||
continue; /* ignore this tuple for this agg */
|
||||
|
||||
if (aggfns->xfn1.fn_addr != NULL)
|
||||
if (OidIsValid(xfn2_oid))
|
||||
{
|
||||
if (noInitValue[i])
|
||||
fmgr_info(xfn2_oid, &aggFuncInfo[i].xfn2);
|
||||
aggFuncInfo[i].xfn2_oid = xfn2_oid;
|
||||
value2[i] = (Datum) AggNameGetInitVal((char *) aggname,
|
||||
aggp->aggbasetype,
|
||||
2,
|
||||
&isNull2);
|
||||
/* ------------------------------------------
|
||||
* If there is a second transition function, its initial
|
||||
* value must exist -- as it does not depend on data values,
|
||||
* we have no other way of determining an initial value.
|
||||
* ------------------------------------------
|
||||
*/
|
||||
if (isNull2)
|
||||
elog(ERROR, "ExecAgg: agginitval2 is null");
|
||||
}
|
||||
|
||||
if (OidIsValid(xfn1_oid))
|
||||
{
|
||||
fmgr_info(xfn1_oid, &aggFuncInfo[i].xfn1);
|
||||
aggFuncInfo[i].xfn1_oid = xfn1_oid;
|
||||
value1[i] = (Datum) AggNameGetInitVal((char *) aggname,
|
||||
aggp->aggbasetype,
|
||||
1,
|
||||
&isNull1);
|
||||
|
||||
/* ------------------------------------------
|
||||
* If the initial value for the first transition function
|
||||
* doesn't exist in the pg_aggregate table then we let
|
||||
* the first value returned from the outer procNode become
|
||||
* the initial value. (This is useful for aggregates like
|
||||
* max{} and min{}.)
|
||||
* ------------------------------------------
|
||||
*/
|
||||
if (isNull1)
|
||||
{
|
||||
int byVal = 0;
|
||||
noInitValue[i] = 1;
|
||||
nulls[i] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* value1 and value2 has not been initialized. This is
|
||||
* the first non-NULL value. We use it as the initial
|
||||
* value.
|
||||
*/
|
||||
/* ----------------
|
||||
* for each tuple from the the outer plan, apply all the aggregates
|
||||
* ----------------
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
HeapTuple outerTuple = NULL;
|
||||
TupleTableSlot *outerslot;
|
||||
|
||||
/*
|
||||
* but we can't just use it straight, we have to make
|
||||
* a copy of it since the tuple from which it came
|
||||
* will be freed on the next iteration of the scan
|
||||
*/
|
||||
switch (nodeTag(aggregates[i]->target))
|
||||
isNull = isNull1 = isNull2 = 0;
|
||||
outerslot = ExecProcNode(outerPlan, (Plan *) node);
|
||||
if (outerslot)
|
||||
outerTuple = outerslot->val;
|
||||
if (!HeapTupleIsValid(outerTuple))
|
||||
{
|
||||
|
||||
/*
|
||||
* when the outerplan doesn't return a single tuple,
|
||||
* create a dummy heaptuple anyway because we still need
|
||||
* to return a valid aggregate value. The value returned
|
||||
* will be the initial values of the transition functions
|
||||
*/
|
||||
if (nTuplesAgged == 0)
|
||||
{
|
||||
TupleDesc tupType;
|
||||
Datum *tupValue;
|
||||
char *null_array;
|
||||
|
||||
tupType = aggstate->csstate.css_ScanTupleSlot->ttc_tupleDescriptor;
|
||||
tupValue = projInfo->pi_tupValue;
|
||||
|
||||
/* initially, set all the values to NULL */
|
||||
null_array = palloc(tupType->natts);
|
||||
for (i = 0; i < tupType->natts; i++)
|
||||
null_array[i] = 'n';
|
||||
oneTuple = heap_formtuple(tupType, tupValue, null_array);
|
||||
pfree(null_array);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < nagg; i++)
|
||||
{
|
||||
AttrNumber attnum;
|
||||
int2 attlen = 0;
|
||||
Datum newVal = (Datum) NULL;
|
||||
AggFuncInfo *aggfns = &aggFuncInfo[i];
|
||||
Datum args[2];
|
||||
Node *tagnode = NULL;
|
||||
|
||||
switch (nodeTag(aggregates[i]->target))
|
||||
{
|
||||
case T_Var:
|
||||
tagnode = NULL;
|
||||
newVal = aggGetAttr(outerslot,
|
||||
aggregates[i],
|
||||
&isNull);
|
||||
break;
|
||||
case T_Expr:
|
||||
tagnode = ((Expr *) aggregates[i]->target)->oper;
|
||||
econtext->ecxt_scantuple = outerslot;
|
||||
newVal = ExecEvalExpr(aggregates[i]->target, econtext,
|
||||
&isNull, &isDone);
|
||||
break;
|
||||
case T_Const:
|
||||
tagnode = NULL;
|
||||
econtext->ecxt_scantuple = outerslot;
|
||||
newVal = ExecEvalExpr(aggregates[i]->target, econtext,
|
||||
&isNull, &isDone);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "ExecAgg: Bad Agg->Target for Agg %d", i);
|
||||
}
|
||||
|
||||
if (isNull && !aggregates[i]->usenulls)
|
||||
continue; /* ignore this tuple for this agg */
|
||||
|
||||
if (aggfns->xfn1.fn_addr != NULL)
|
||||
{
|
||||
if (noInitValue[i])
|
||||
{
|
||||
case T_Var:
|
||||
attnum = ((Var *) aggregates[i]->target)->varattno;
|
||||
attlen = outerslot->ttc_tupleDescriptor->attrs[attnum - 1]->attlen;
|
||||
byVal = outerslot->ttc_tupleDescriptor->attrs[attnum - 1]->attbyval;
|
||||
int byVal = 0;
|
||||
|
||||
break;
|
||||
case T_Expr:
|
||||
{
|
||||
FunctionCachePtr fcache_ptr;
|
||||
/*
|
||||
* value1 and value2 has not been initialized.
|
||||
* This is the first non-NULL value. We use it as
|
||||
* the initial value.
|
||||
*/
|
||||
|
||||
if (nodeTag(tagnode) == T_Func)
|
||||
fcache_ptr = ((Func *) tagnode)->func_fcache;
|
||||
else
|
||||
fcache_ptr = ((Oper *) tagnode)->op_fcache;
|
||||
attlen = fcache_ptr->typlen;
|
||||
byVal = fcache_ptr->typbyval;
|
||||
/*
|
||||
* but we can't just use it straight, we have to
|
||||
* make a copy of it since the tuple from which it
|
||||
* came will be freed on the next iteration of the
|
||||
* scan
|
||||
*/
|
||||
switch (nodeTag(aggregates[i]->target))
|
||||
{
|
||||
case T_Var:
|
||||
attnum = ((Var *) aggregates[i]->target)->varattno;
|
||||
attlen = outerslot->ttc_tupleDescriptor->attrs[attnum - 1]->attlen;
|
||||
byVal = outerslot->ttc_tupleDescriptor->attrs[attnum - 1]->attbyval;
|
||||
|
||||
break;
|
||||
}
|
||||
case T_Const:
|
||||
attlen = ((Const *) aggregates[i]->target)->constlen;
|
||||
byVal = ((Const *) aggregates[i]->target)->constbyval;
|
||||
case T_Expr:
|
||||
{
|
||||
FunctionCachePtr fcache_ptr;
|
||||
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "ExecAgg: Bad Agg->Target for Agg %d", i);
|
||||
if (nodeTag(tagnode) == T_Func)
|
||||
fcache_ptr = ((Func *) tagnode)->func_fcache;
|
||||
else
|
||||
fcache_ptr = ((Oper *) tagnode)->op_fcache;
|
||||
attlen = fcache_ptr->typlen;
|
||||
byVal = fcache_ptr->typbyval;
|
||||
|
||||
break;
|
||||
}
|
||||
case T_Const:
|
||||
attlen = ((Const *) aggregates[i]->target)->constlen;
|
||||
byVal = ((Const *) aggregates[i]->target)->constbyval;
|
||||
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "ExecAgg: Bad Agg->Target for Agg %d", i);
|
||||
}
|
||||
if (attlen == -1)
|
||||
{
|
||||
/* variable length */
|
||||
attlen = VARSIZE((struct varlena *) newVal);
|
||||
}
|
||||
value1[i] = (Datum) palloc(attlen);
|
||||
if (byVal)
|
||||
value1[i] = newVal;
|
||||
else
|
||||
memmove((char *) (value1[i]), (char *) newVal, attlen);
|
||||
noInitValue[i] = 0;
|
||||
nulls[i] = 0;
|
||||
}
|
||||
if (attlen == -1)
|
||||
{
|
||||
/* variable length */
|
||||
attlen = VARSIZE((struct varlena *) newVal);
|
||||
}
|
||||
value1[i] = (Datum) palloc(attlen);
|
||||
if (byVal)
|
||||
value1[i] = newVal;
|
||||
else
|
||||
memmove((char *) (value1[i]), (char *) newVal, attlen);
|
||||
noInitValue[i] = 0;
|
||||
nulls[i] = 0;
|
||||
{
|
||||
|
||||
/*
|
||||
* apply the transition functions.
|
||||
*/
|
||||
args[0] = value1[i];
|
||||
args[1] = newVal;
|
||||
value1[i] =
|
||||
(Datum) fmgr_c(&aggfns->xfn1,
|
||||
(FmgrValues *) args,
|
||||
&isNull1);
|
||||
Assert(!isNull1);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (aggfns->xfn2.fn_addr != NULL)
|
||||
{
|
||||
Datum xfn2_val = value2[i];
|
||||
|
||||
/*
|
||||
* apply the transition functions.
|
||||
*/
|
||||
args[0] = value1[i];
|
||||
args[1] = newVal;
|
||||
value1[i] =
|
||||
(Datum) fmgr_c(&aggfns->xfn1,
|
||||
(FmgrValues *) args,
|
||||
&isNull1);
|
||||
Assert(!isNull1);
|
||||
value2[i] =
|
||||
(Datum) fmgr_c(&aggfns->xfn2,
|
||||
(FmgrValues *) &xfn2_val, &isNull2);
|
||||
Assert(!isNull2);
|
||||
}
|
||||
}
|
||||
|
||||
if (aggfns->xfn2.fn_addr != NULL)
|
||||
{
|
||||
Datum xfn2_val = value2[i];
|
||||
/*
|
||||
* keep this for the projection (we only need one of these -
|
||||
* all the tuples we aggregate over share the same group
|
||||
* column)
|
||||
*/
|
||||
if (!oneTuple)
|
||||
oneTuple = heap_copytuple(outerslot->val);
|
||||
|
||||
value2[i] =
|
||||
(Datum) fmgr_c(&aggfns->xfn2,
|
||||
(FmgrValues *) &xfn2_val, &isNull2);
|
||||
Assert(!isNull2);
|
||||
nTuplesAgged++;
|
||||
}
|
||||
|
||||
/* --------------
|
||||
* finalize the aggregate (if necessary), and get the resultant value
|
||||
* --------------
|
||||
*/
|
||||
for (i = 0; i < nagg; i++)
|
||||
{
|
||||
char *args[2];
|
||||
AggFuncInfo *aggfns = &aggFuncInfo[i];
|
||||
|
||||
if (noInitValue[i])
|
||||
{
|
||||
|
||||
/*
|
||||
* No values found for this agg; return current state.
|
||||
* This seems to fix behavior for avg() aggregate. -tgl
|
||||
* 12/96
|
||||
*/
|
||||
}
|
||||
else if (aggfns->finalfn.fn_addr != NULL && nTuplesAgged > 0)
|
||||
{
|
||||
if (aggfns->finalfn.fn_nargs > 1)
|
||||
{
|
||||
args[0] = (char *) value1[i];
|
||||
args[1] = (char *) value2[i];
|
||||
}
|
||||
else if (aggfns->xfn1.fn_addr != NULL)
|
||||
args[0] = (char *) value1[i];
|
||||
else if (aggfns->xfn2.fn_addr != NULL)
|
||||
args[0] = (char *) value2[i];
|
||||
else
|
||||
elog(NOTICE, "ExecAgg: no valid transition functions??");
|
||||
value1[i] = (Datum) fmgr_c(&aggfns->finalfn,
|
||||
(FmgrValues *) args, &(nulls[i]));
|
||||
}
|
||||
else if (aggfns->xfn1.fn_addr != NULL)
|
||||
{
|
||||
|
||||
/*
|
||||
* value in the right place, ignore. (If you remove this
|
||||
* case, fix the else part. -ay 2/95)
|
||||
*/
|
||||
}
|
||||
else if (aggfns->xfn2.fn_addr != NULL)
|
||||
value1[i] = value2[i];
|
||||
else
|
||||
elog(ERROR, "ExecAgg: no valid transition functions??");
|
||||
}
|
||||
|
||||
/*
|
||||
* keep this for the projection (we only need one of these - all
|
||||
* the tuples we aggregate over share the same group column)
|
||||
* whether the aggregation is done depends on whether we are doing
|
||||
* aggregation over groups or the entire table
|
||||
*/
|
||||
if (!oneTuple)
|
||||
oneTuple = heap_copytuple(outerslot->val);
|
||||
|
||||
nTuplesAgged++;
|
||||
}
|
||||
|
||||
/* --------------
|
||||
* finalize the aggregate (if necessary), and get the resultant value
|
||||
* --------------
|
||||
*/
|
||||
for (i = 0; i < nagg; i++)
|
||||
{
|
||||
char *args[2];
|
||||
AggFuncInfo *aggfns = &aggFuncInfo[i];
|
||||
|
||||
if (noInitValue[i])
|
||||
if (nodeTag(outerPlan) == T_Group)
|
||||
{
|
||||
|
||||
/*
|
||||
* No values found for this agg; return current state. This
|
||||
* seems to fix behavior for avg() aggregate. -tgl 12/96
|
||||
*/
|
||||
/* aggregation over groups */
|
||||
aggstate->agg_done = ((Group *) outerPlan)->grpstate->grp_done;
|
||||
}
|
||||
else if (aggfns->finalfn.fn_addr != NULL && nTuplesAgged > 0)
|
||||
{
|
||||
if (aggfns->finalfn.fn_nargs > 1)
|
||||
{
|
||||
args[0] = (char *) value1[i];
|
||||
args[1] = (char *) value2[i];
|
||||
}
|
||||
else if (aggfns->xfn1.fn_addr != NULL)
|
||||
args[0] = (char *) value1[i];
|
||||
else if (aggfns->xfn2.fn_addr != NULL)
|
||||
args[0] = (char *) value2[i];
|
||||
else
|
||||
elog(NOTICE, "ExecAgg: no valid transition functions??");
|
||||
value1[i] = (Datum) fmgr_c(&aggfns->finalfn,
|
||||
(FmgrValues *) args, &(nulls[i]));
|
||||
}
|
||||
else if (aggfns->xfn1.fn_addr != NULL)
|
||||
{
|
||||
|
||||
/*
|
||||
* value in the right place, ignore. (If you remove this case,
|
||||
* fix the else part. -ay 2/95)
|
||||
*/
|
||||
}
|
||||
else if (aggfns->xfn2.fn_addr != NULL)
|
||||
value1[i] = value2[i];
|
||||
else
|
||||
elog(ERROR, "ExecAgg: no valid transition functions??");
|
||||
aggstate->agg_done = TRUE;
|
||||
|
||||
/* ----------------
|
||||
* form a projection tuple, store it in the result tuple
|
||||
* slot and return it.
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
ExecStoreTuple(oneTuple,
|
||||
aggstate->csstate.css_ScanTupleSlot,
|
||||
InvalidBuffer,
|
||||
false);
|
||||
econtext->ecxt_scantuple = aggstate->csstate.css_ScanTupleSlot;
|
||||
|
||||
resultSlot = ExecProject(projInfo, &isDone);
|
||||
|
||||
/*
|
||||
* As long as the retrieved group does not match the
|
||||
* qualifications it is ignored and the next group is fetched
|
||||
*/
|
||||
qual_result = ExecQual(fix_opids(node->plan.qual), econtext);
|
||||
if (oneTuple)
|
||||
pfree(oneTuple);
|
||||
}
|
||||
|
||||
/*
|
||||
* whether the aggregation is done depends on whether we are doing
|
||||
* aggregation over groups or the entire table
|
||||
*/
|
||||
if (nodeTag(outerPlan) == T_Group)
|
||||
{
|
||||
/* aggregation over groups */
|
||||
aggstate->agg_done = ((Group *) outerPlan)->grpstate->grp_done;
|
||||
}
|
||||
else
|
||||
aggstate->agg_done = TRUE;
|
||||
|
||||
/* ----------------
|
||||
* form a projection tuple, store it in the result tuple
|
||||
* slot and return it.
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
ExecStoreTuple(oneTuple,
|
||||
aggstate->csstate.css_ScanTupleSlot,
|
||||
InvalidBuffer,
|
||||
false);
|
||||
econtext->ecxt_scantuple = aggstate->csstate.css_ScanTupleSlot;
|
||||
|
||||
resultSlot = ExecProject(projInfo, &isDone);
|
||||
|
||||
/* As long as the retrieved group does not match the qualifications it is ignored and
|
||||
* the next group is fetched */
|
||||
qual_result=ExecQual(fix_opids(node->plan.qual),econtext);
|
||||
if (oneTuple)
|
||||
pfree(oneTuple);
|
||||
}
|
||||
while((node->plan.qual!=NULL) && (qual_result!=true));
|
||||
while ((node->plan.qual != NULL) && (qual_result != true));
|
||||
|
||||
return resultSlot;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.14 1998/07/15 22:16:18 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.15 1998/09/01 04:28:26 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -158,7 +158,7 @@ exec_append_initialize_next(Append *node)
|
||||
{
|
||||
estate->es_result_relation_info =
|
||||
(RelationInfo *) nth(whichplan,
|
||||
appendstate->as_result_relation_info_list);
|
||||
appendstate->as_result_relation_info_list);
|
||||
}
|
||||
result_slot->ttc_whichplan = whichplan;
|
||||
|
||||
@ -505,8 +505,8 @@ void
|
||||
ExecReScanAppend(Append *node, ExprContext *exprCtxt, Plan *parent)
|
||||
{
|
||||
AppendState *appendstate = node->appendstate;
|
||||
int nplans = length(node->appendplans);
|
||||
int i;
|
||||
int nplans = length(node->appendplans);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nplans; i++)
|
||||
{
|
||||
@ -517,7 +517,7 @@ ExecReScanAppend(Append *node, ExprContext *exprCtxt, Plan *parent)
|
||||
if (rescanNode->chgParam == NULL)
|
||||
{
|
||||
exec_append_initialize_next(node);
|
||||
ExecReScan((Plan *)rescanNode, exprCtxt, (Plan *) node);
|
||||
ExecReScan((Plan *) rescanNode, exprCtxt, (Plan *) node);
|
||||
}
|
||||
}
|
||||
appendstate->as_whichplan = 0;
|
||||
|
@ -13,7 +13,7 @@
|
||||
* columns. (ie. tuples from the same group are consecutive)
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.21 1998/07/16 02:58:09 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.22 1998/09/01 04:28:28 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -30,8 +30,7 @@
|
||||
|
||||
static TupleTableSlot *ExecGroupEveryTuple(Group *node);
|
||||
static TupleTableSlot *ExecGroupOneTuple(Group *node);
|
||||
static bool
|
||||
sameGroup(HeapTuple oldslot, HeapTuple newslot,
|
||||
static bool sameGroup(HeapTuple oldslot, HeapTuple newslot,
|
||||
int numCols, AttrNumber *grpColIdx, TupleDesc tupdesc);
|
||||
|
||||
/* ---------------------------------------
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeHash.c,v 1.22 1998/09/01 03:22:23 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeHash.c,v 1.23 1998/09/01 04:28:29 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -45,8 +45,7 @@ static void mk_hj_temp(char *tempname);
|
||||
static int hashFunc(char *key, int len);
|
||||
static int ExecHashPartition(Hash *node);
|
||||
static RelativeAddr hashTableAlloc(int size, HashJoinTable hashtable);
|
||||
static void
|
||||
ExecHashOverflowInsert(HashJoinTable hashtable,
|
||||
static void ExecHashOverflowInsert(HashJoinTable hashtable,
|
||||
HashBucket bucket,
|
||||
HeapTuple heapTuple);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.12 1998/09/01 03:22:25 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.13 1998/09/01 04:28:31 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -28,12 +28,10 @@
|
||||
static TupleTableSlot *
|
||||
ExecHashJoinOuterGetTuple(Plan *node, Plan *parent, HashJoinState *hjstate);
|
||||
|
||||
static TupleTableSlot *
|
||||
ExecHashJoinGetSavedTuple(HashJoinState *hjstate, char *buffer,
|
||||
static TupleTableSlot *ExecHashJoinGetSavedTuple(HashJoinState *hjstate, char *buffer,
|
||||
File file, TupleTableSlot *tupleSlot, int *block, char **position);
|
||||
|
||||
static int
|
||||
ExecHashJoinGetBatch(int bucketno, HashJoinTable hashtable,
|
||||
static int ExecHashJoinGetBatch(int bucketno, HashJoinTable hashtable,
|
||||
int nbatch);
|
||||
|
||||
static int ExecHashJoinNewBatch(HashJoinState *hjstate);
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.26 1998/09/01 03:22:26 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.27 1998/09/01 04:28:32 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -85,8 +85,8 @@ IndexNext(IndexScan *node)
|
||||
EState *estate;
|
||||
CommonScanState *scanstate;
|
||||
IndexScanState *indexstate;
|
||||
ScanDirection direction;
|
||||
Snapshot snapshot;
|
||||
ScanDirection direction;
|
||||
Snapshot snapshot;
|
||||
IndexScanDescPtr scanDescs;
|
||||
IndexScanDesc scandesc;
|
||||
Relation heapRelation;
|
||||
@ -95,7 +95,7 @@ IndexNext(IndexScan *node)
|
||||
TupleTableSlot *slot;
|
||||
Buffer buffer = InvalidBuffer;
|
||||
int numIndices;
|
||||
|
||||
|
||||
/* ----------------
|
||||
* extract necessary information from index scan node
|
||||
* ----------------
|
||||
@ -122,39 +122,40 @@ IndexNext(IndexScan *node)
|
||||
while ((result = index_getnext(scandesc, direction)) != NULL)
|
||||
{
|
||||
tuple = heap_fetch(heapRelation, snapshot,
|
||||
&result->heap_iptr, &buffer);
|
||||
&result->heap_iptr, &buffer);
|
||||
pfree(result);
|
||||
|
||||
if (tuple != NULL)
|
||||
{
|
||||
bool prev_matches = false;
|
||||
int prev_index;
|
||||
|
||||
|
||||
/* ----------------
|
||||
* store the scanned tuple in the scan tuple slot of
|
||||
* the scan state. Eventually we will only do this and not
|
||||
* return a tuple. Note: we pass 'false' because tuples
|
||||
* returned by amgetnext are pointers onto disk pages and
|
||||
* were not created with palloc() and so should not be pfree()'d.
|
||||
* ----------------
|
||||
*/
|
||||
ExecStoreTuple(tuple, /* tuple to store */
|
||||
slot, /* slot to store in */
|
||||
buffer, /* buffer associated with tuple */
|
||||
false); /* don't pfree */
|
||||
* store the scanned tuple in the scan tuple slot of
|
||||
* the scan state. Eventually we will only do this and not
|
||||
* return a tuple. Note: we pass 'false' because tuples
|
||||
* returned by amgetnext are pointers onto disk pages and
|
||||
* were not created with palloc() and so should not be pfree()'d.
|
||||
* ----------------
|
||||
*/
|
||||
ExecStoreTuple(tuple, /* tuple to store */
|
||||
slot, /* slot to store in */
|
||||
buffer, /* buffer associated with tuple */
|
||||
false); /* don't pfree */
|
||||
|
||||
/*
|
||||
* We must check to see if the current tuple would have been
|
||||
* matched by an earlier index, so we don't double report it.
|
||||
* We do this by passing the tuple through ExecQual and look
|
||||
* for failure with all previous qualifications.
|
||||
* We must check to see if the current tuple would have
|
||||
* been matched by an earlier index, so we don't double
|
||||
* report it. We do this by passing the tuple through
|
||||
* ExecQual and look for failure with all previous
|
||||
* qualifications.
|
||||
*/
|
||||
for (prev_index = 0; prev_index < indexstate->iss_IndexPtr;
|
||||
prev_index++)
|
||||
prev_index++)
|
||||
{
|
||||
scanstate->cstate.cs_ExprContext->ecxt_scantuple = slot;
|
||||
if (ExecQual(nth(prev_index, node->indxqual),
|
||||
scanstate->cstate.cs_ExprContext))
|
||||
scanstate->cstate.cs_ExprContext))
|
||||
{
|
||||
prev_matches = true;
|
||||
break;
|
||||
@ -259,17 +260,16 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
|
||||
indxqual = node->indxqual;
|
||||
numScanKeys = indexstate->iss_NumScanKeys;
|
||||
indexstate->iss_IndexPtr = 0;
|
||||
|
||||
|
||||
/* it's possible in subselects */
|
||||
if (exprCtxt == NULL)
|
||||
exprCtxt = node->scan.scanstate->cstate.cs_ExprContext;
|
||||
|
||||
node->scan.scanstate->cstate.cs_ExprContext->ecxt_outertuple =
|
||||
exprCtxt->ecxt_outertuple;
|
||||
|
||||
|
||||
/*
|
||||
* get the index qualifications and recalculate the appropriate
|
||||
* values
|
||||
* get the index qualifications and recalculate the appropriate values
|
||||
*/
|
||||
for (i = 0; i < numIndices; i++)
|
||||
{
|
||||
@ -282,17 +282,19 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
|
||||
run_keys = (int *) runtimeKeyInfo[i];
|
||||
for (j = 0; j < n_keys; j++)
|
||||
{
|
||||
|
||||
/*
|
||||
* If we have a run-time key, then extract the run-time
|
||||
* expression and evaluate it with respect to the current
|
||||
* outer tuple. We then stick the result into the scan key.
|
||||
* outer tuple. We then stick the result into the scan
|
||||
* key.
|
||||
*/
|
||||
if (run_keys[j] != NO_OP)
|
||||
{
|
||||
clause = nth(j, qual);
|
||||
scanexpr = (run_keys[j] == RIGHT_OP) ?
|
||||
(Node *) get_rightop(clause) : (Node *) get_leftop(clause);
|
||||
|
||||
|
||||
/*
|
||||
* pass in isDone but ignore it. We don't iterate in
|
||||
* quals
|
||||
@ -333,7 +335,7 @@ ExecEndIndexScan(IndexScan *node)
|
||||
IndexScanState *indexstate;
|
||||
Pointer *runtimeKeyInfo;
|
||||
ScanKey *scanKeys;
|
||||
List *indxqual;
|
||||
List *indxqual;
|
||||
int *numScanKeys;
|
||||
int numIndices;
|
||||
int i;
|
||||
@ -342,7 +344,7 @@ ExecEndIndexScan(IndexScan *node)
|
||||
indexstate = node->indxstate;
|
||||
indxqual = node->indxqual;
|
||||
runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
|
||||
|
||||
|
||||
/* ----------------
|
||||
* extract information from the node
|
||||
* ----------------
|
||||
@ -381,7 +383,7 @@ ExecEndIndexScan(IndexScan *node)
|
||||
pfree(numScanKeys);
|
||||
|
||||
if (runtimeKeyInfo)
|
||||
{
|
||||
{
|
||||
for (i = 0; i < numIndices; i++)
|
||||
{
|
||||
List *qual;
|
||||
@ -394,7 +396,7 @@ ExecEndIndexScan(IndexScan *node)
|
||||
}
|
||||
pfree(runtimeKeyInfo);
|
||||
}
|
||||
|
||||
|
||||
/* ----------------
|
||||
* clear out tuple table slots
|
||||
* ----------------
|
||||
@ -428,7 +430,7 @@ ExecIndexMarkPos(IndexScan *node)
|
||||
#if 0
|
||||
IndexScanMarkPosition(scanDesc);
|
||||
#endif
|
||||
index_markpos (scanDesc);
|
||||
index_markpos(scanDesc);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
@ -457,7 +459,7 @@ ExecIndexRestrPos(IndexScan *node)
|
||||
#if 0
|
||||
IndexScanRestorePosition(scanDesc);
|
||||
#endif
|
||||
index_restrpos (scanDesc);
|
||||
index_restrpos(scanDesc);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
@ -504,7 +506,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
HeapScanDesc currentScanDesc;
|
||||
ScanDirection direction;
|
||||
int baseid;
|
||||
|
||||
|
||||
List *execParam = NULL;
|
||||
|
||||
/* ----------------
|
||||
@ -727,22 +729,22 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
* it identifies the value to place in our scan key.
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
|
||||
/* Life was so easy before ... subselects */
|
||||
if ( ((Param *) leftop)->paramkind == PARAM_EXEC )
|
||||
if (((Param *) leftop)->paramkind == PARAM_EXEC)
|
||||
{
|
||||
have_runtime_keys = true;
|
||||
run_keys[j] = LEFT_OP;
|
||||
execParam = lappendi (execParam, ((Param*) leftop)->paramid);
|
||||
execParam = lappendi(execParam, ((Param *) leftop)->paramid);
|
||||
}
|
||||
else
|
||||
{
|
||||
scanvalue = ExecEvalParam((Param *) leftop,
|
||||
scanstate->cstate.cs_ExprContext,
|
||||
scanstate->cstate.cs_ExprContext,
|
||||
&isnull);
|
||||
if (isnull)
|
||||
flags |= SK_ISNULL;
|
||||
|
||||
|
||||
run_keys[j] = NO_OP;
|
||||
}
|
||||
}
|
||||
@ -820,22 +822,22 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
* it identifies the value to place in our scan key.
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
|
||||
/* Life was so easy before ... subselects */
|
||||
if ( ((Param *) rightop)->paramkind == PARAM_EXEC )
|
||||
if (((Param *) rightop)->paramkind == PARAM_EXEC)
|
||||
{
|
||||
have_runtime_keys = true;
|
||||
run_keys[j] = RIGHT_OP;
|
||||
execParam = lappendi (execParam, ((Param*) rightop)->paramid);
|
||||
execParam = lappendi(execParam, ((Param *) rightop)->paramid);
|
||||
}
|
||||
else
|
||||
{
|
||||
scanvalue = ExecEvalParam((Param *) rightop,
|
||||
scanstate->cstate.cs_ExprContext,
|
||||
scanstate->cstate.cs_ExprContext,
|
||||
&isnull);
|
||||
if (isnull)
|
||||
flags |= SK_ISNULL;
|
||||
|
||||
|
||||
run_keys[j] = NO_OP;
|
||||
}
|
||||
}
|
||||
@ -992,13 +994,13 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
indexstate->iss_ScanDescs = scanDescs;
|
||||
|
||||
indexstate->cstate.cs_TupFromTlist = false;
|
||||
|
||||
/*
|
||||
* if there are some PARAM_EXEC in skankeys then
|
||||
* force index rescan on first scan.
|
||||
|
||||
/*
|
||||
* if there are some PARAM_EXEC in skankeys then force index rescan on
|
||||
* first scan.
|
||||
*/
|
||||
((Plan*) node)->chgParam = execParam;
|
||||
|
||||
((Plan *) node)->chgParam = execParam;
|
||||
|
||||
/* ----------------
|
||||
* all done.
|
||||
* ----------------
|
||||
@ -1010,5 +1012,5 @@ int
|
||||
ExecCountSlotsIndexScan(IndexScan *node)
|
||||
{
|
||||
return ExecCountSlotsNode(outerPlan((Plan *) node)) +
|
||||
ExecCountSlotsNode(innerPlan((Plan *) node)) + INDEXSCAN_NSLOTS;
|
||||
ExecCountSlotsNode(innerPlan((Plan *) node)) + INDEXSCAN_NSLOTS;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.16 1998/09/01 03:22:27 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.17 1998/09/01 04:28:34 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -173,7 +173,7 @@ ExecMaterial(Material *node)
|
||||
|
||||
return ExecStoreTuple(heapTuple, /* tuple to store */
|
||||
slot, /* slot to store in */
|
||||
currentScanDesc->rs_cbuf, /* buffer for this tuple */
|
||||
currentScanDesc->rs_cbuf, /* buffer for this tuple */
|
||||
false); /* don't pfree this pointer */
|
||||
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.18 1998/07/19 10:05:19 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.19 1998/09/01 04:28:35 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -480,8 +480,8 @@ ExecMergeJoin(MergeJoin *node)
|
||||
* means that this is the first time ExecMergeJoin() has
|
||||
* been called and so we have to initialize the inner,
|
||||
* outer and marked tuples as well as various stuff in the
|
||||
* expression context.
|
||||
* ********************************
|
||||
* expression context. ********************************
|
||||
*
|
||||
*/
|
||||
case EXEC_MJ_INITIALIZE:
|
||||
MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE\n");
|
||||
@ -514,7 +514,7 @@ ExecMergeJoin(MergeJoin *node)
|
||||
|
||||
mergestate->mj_MarkedTupleSlot->ttc_tupleDescriptor =
|
||||
innerTupleSlot->ttc_tupleDescriptor;
|
||||
|
||||
|
||||
/* ----------------
|
||||
* initialize merge join state to skip inner tuples.
|
||||
* ----------------
|
||||
@ -526,8 +526,8 @@ ExecMergeJoin(MergeJoin *node)
|
||||
* ******************************** EXEC_MJ_JOINMARK means
|
||||
* we have just found a new outer tuple and a possible
|
||||
* matching inner tuple. This is the case after the
|
||||
* INITIALIZE, SKIPOUTER or SKIPINNER states.
|
||||
* ********************************
|
||||
* INITIALIZE, SKIPOUTER or SKIPINNER states. ********************************
|
||||
*
|
||||
*/
|
||||
case EXEC_MJ_JOINMARK:
|
||||
MJ_printf("ExecMergeJoin: EXEC_MJ_JOINMARK\n");
|
||||
@ -655,8 +655,8 @@ ExecMergeJoin(MergeJoin *node)
|
||||
break;
|
||||
|
||||
/*
|
||||
* ******************************** EXEC_MJ_TESTOUTER
|
||||
* If the new outer tuple and the marked tuple satisify the
|
||||
* ******************************** EXEC_MJ_TESTOUTER If
|
||||
* the new outer tuple and the marked tuple satisify the
|
||||
* merge clause then we know we have duplicates in the
|
||||
* outer scan so we have to restore the inner scan to the
|
||||
* marked tuple and proceed to join the new outer tuples
|
||||
@ -680,7 +680,9 @@ ExecMergeJoin(MergeJoin *node)
|
||||
*
|
||||
* new outer tuple > marked tuple
|
||||
*
|
||||
* ****************************
|
||||
***************************
|
||||
*
|
||||
*
|
||||
*/
|
||||
case EXEC_MJ_TESTOUTER:
|
||||
MJ_printf("ExecMergeJoin: EXEC_MJ_TESTOUTER\n");
|
||||
@ -698,13 +700,14 @@ ExecMergeJoin(MergeJoin *node)
|
||||
|
||||
if (qualResult)
|
||||
{
|
||||
/*
|
||||
* the merge clause matched so now we juggle the slots
|
||||
* back the way they were and proceed to JOINTEST.
|
||||
|
||||
/*
|
||||
* the merge clause matched so now we juggle the slots
|
||||
* back the way they were and proceed to JOINTEST.
|
||||
*
|
||||
* I can't understand why we have to go to JOINTEST
|
||||
* and compare outer tuple with the same inner one
|
||||
* again -> go to JOINTUPLES... - vadim 02/27/98
|
||||
* I can't understand why we have to go to JOINTEST and
|
||||
* compare outer tuple with the same inner one again
|
||||
* -> go to JOINTUPLES... - vadim 02/27/98
|
||||
*/
|
||||
|
||||
ExecRestrPos(innerPlan);
|
||||
@ -738,7 +741,7 @@ ExecMergeJoin(MergeJoin *node)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* continue on to skip outer tuples */
|
||||
/* continue on to skip outer tuples */
|
||||
mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER;
|
||||
}
|
||||
break;
|
||||
@ -756,7 +759,9 @@ ExecMergeJoin(MergeJoin *node)
|
||||
* we have to advance the outer scan until we find the outer
|
||||
* 8.
|
||||
*
|
||||
****************************
|
||||
**************************
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
@ -856,7 +861,9 @@ ExecMergeJoin(MergeJoin *node)
|
||||
* we have to advance the inner scan until we find the inner
|
||||
* 12.
|
||||
*
|
||||
****************************
|
||||
**************************
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
@ -988,10 +995,10 @@ bool
|
||||
ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
|
||||
{
|
||||
MergeJoinState *mergestate;
|
||||
List *joinclauses;
|
||||
RegProcedure rightsortop;
|
||||
RegProcedure leftsortop;
|
||||
RegProcedure sortop;
|
||||
List *joinclauses;
|
||||
RegProcedure rightsortop;
|
||||
RegProcedure leftsortop;
|
||||
RegProcedure sortop;
|
||||
TupleTableSlot *mjSlot;
|
||||
|
||||
List *OSortopI;
|
||||
@ -1042,7 +1049,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
|
||||
mjSlot->ttc_whichplan = -1;
|
||||
mjSlot->ttc_descIsNew = true;
|
||||
mergestate->mj_MarkedTupleSlot = mjSlot;
|
||||
|
||||
|
||||
/* ----------------
|
||||
* get merge sort operators.
|
||||
*
|
||||
@ -1166,9 +1173,9 @@ ExecEndMergeJoin(MergeJoin *node)
|
||||
*/
|
||||
ExecClearTuple(mergestate->jstate.cs_ResultTupleSlot);
|
||||
ExecClearTuple(mergestate->mj_MarkedTupleSlot);
|
||||
pfree (mergestate->mj_MarkedTupleSlot);
|
||||
pfree(mergestate->mj_MarkedTupleSlot);
|
||||
mergestate->mj_MarkedTupleSlot = NULL;
|
||||
|
||||
|
||||
MJ1_printf("ExecEndMergeJoin: %s\n",
|
||||
"node processing ended");
|
||||
}
|
||||
@ -1185,12 +1192,12 @@ ExecReScanMergeJoin(MergeJoin *node, ExprContext *exprCtxt, Plan *parent)
|
||||
mjSlot->ttc_tupleDescriptor = NULL;
|
||||
mjSlot->ttc_whichplan = -1;
|
||||
mjSlot->ttc_descIsNew = true;
|
||||
|
||||
|
||||
mergestate->mj_JoinState = EXEC_MJ_INITIALIZE;
|
||||
|
||||
/*
|
||||
* if chgParam of subnodes is not null then plans will be re-scanned by
|
||||
* first ExecProcNode.
|
||||
* if chgParam of subnodes is not null then plans will be re-scanned
|
||||
* by first ExecProcNode.
|
||||
*/
|
||||
if (((Plan *) node)->lefttree->chgParam == NULL)
|
||||
ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.13 1998/09/01 03:22:28 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.14 1998/09/01 04:28:37 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -30,8 +30,7 @@
|
||||
#include "access/heapam.h"
|
||||
#include "parser/parsetree.h"
|
||||
|
||||
static Oid
|
||||
InitScanRelation(SeqScan *node, EState *estate,
|
||||
static Oid InitScanRelation(SeqScan *node, EState *estate,
|
||||
CommonScanState *scanstate, Plan *outerPlan);
|
||||
|
||||
static TupleTableSlot *SeqNext(SeqScan *node);
|
||||
@ -83,7 +82,8 @@ SeqNext(SeqScan *node)
|
||||
|
||||
slot = ExecStoreTuple(tuple,/* tuple to store */
|
||||
slot, /* slot to store in */
|
||||
scandesc->rs_cbuf,/* buffer associated with this tuple */
|
||||
scandesc->rs_cbuf, /* buffer associated with
|
||||
* this tuple */
|
||||
false); /* don't pfree this pointer */
|
||||
|
||||
/* ----------------
|
||||
|
@ -112,8 +112,8 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent)
|
||||
{
|
||||
EState *sp_estate = CreateExecutorState();
|
||||
|
||||
ExecCheckPerms (CMD_SELECT, 0, node->rtable, (Query*) NULL);
|
||||
|
||||
ExecCheckPerms(CMD_SELECT, 0, node->rtable, (Query *) NULL);
|
||||
|
||||
sp_estate->es_range_table = node->rtable;
|
||||
sp_estate->es_param_list_info = estate->es_param_list_info;
|
||||
sp_estate->es_param_exec_vals = estate->es_param_exec_vals;
|
||||
|
@ -15,7 +15,7 @@
|
||||
* ExecEndTee
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/Attic/nodeTee.c,v 1.22 1998/09/01 03:22:32 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/Attic/nodeTee.c,v 1.23 1998/09/01 04:28:40 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -168,8 +168,8 @@ ExecInitTee(Tee *node, EState *currentEstate, Plan *parent)
|
||||
bufferRel = heap_openr(teeState->tee_bufferRelname);
|
||||
else
|
||||
bufferRel = heap_open(
|
||||
heap_create_with_catalog(teeState->tee_bufferRelname,
|
||||
tupType, RELKIND_RELATION));
|
||||
heap_create_with_catalog(teeState->tee_bufferRelname,
|
||||
tupType, RELKIND_RELATION));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -178,8 +178,8 @@ ExecInitTee(Tee *node, EState *currentEstate, Plan *parent)
|
||||
newoid());
|
||||
/* bufferRel = ExecCreatR(len, tupType, _TEMP_RELATION_ID); */
|
||||
bufferRel = heap_open(
|
||||
heap_create_with_catalog(teeState->tee_bufferRelname,
|
||||
tupType, RELKIND_RELATION));
|
||||
heap_create_with_catalog(teeState->tee_bufferRelname,
|
||||
tupType, RELKIND_RELATION));
|
||||
}
|
||||
|
||||
teeState->tee_bufferRel = bufferRel;
|
||||
@ -228,11 +228,11 @@ ExecCountSlotsTee(Tee *node)
|
||||
static void
|
||||
initTeeScanDescs(Tee *node)
|
||||
{
|
||||
TeeState *teeState;
|
||||
Relation bufferRel;
|
||||
ScanDirection dir;
|
||||
Snapshot snapshot;
|
||||
MemoryContext orig;
|
||||
TeeState *teeState;
|
||||
Relation bufferRel;
|
||||
ScanDirection dir;
|
||||
Snapshot snapshot;
|
||||
MemoryContext orig;
|
||||
|
||||
teeState = node->teestate;
|
||||
if (teeState->tee_leftScanDesc && teeState->tee_rightScanDesc)
|
||||
@ -250,18 +250,18 @@ initTeeScanDescs(Tee *node)
|
||||
{
|
||||
teeState->tee_leftScanDesc = heap_beginscan(bufferRel,
|
||||
ScanDirectionIsBackward(dir),
|
||||
snapshot,
|
||||
0, /* num scan keys */
|
||||
NULL /* scan keys */
|
||||
snapshot,
|
||||
0, /* num scan keys */
|
||||
NULL /* scan keys */
|
||||
);
|
||||
}
|
||||
if (teeState->tee_rightScanDesc == NULL)
|
||||
{
|
||||
teeState->tee_rightScanDesc = heap_beginscan(bufferRel,
|
||||
ScanDirectionIsBackward(dir),
|
||||
snapshot,
|
||||
0, /* num scan keys */
|
||||
NULL /* scan keys */
|
||||
snapshot,
|
||||
0, /* num scan keys */
|
||||
NULL /* scan keys */
|
||||
);
|
||||
}
|
||||
|
||||
@ -365,7 +365,7 @@ ExecTee(Tee *node, Plan *parent)
|
||||
HeapTuple throwAway;
|
||||
|
||||
/* Buffer buffer; */
|
||||
throwAway = heap_getnext(scanDesc,ScanDirectionIsBackward(dir));
|
||||
throwAway = heap_getnext(scanDesc, ScanDirectionIsBackward(dir));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -406,7 +406,7 @@ ExecTee(Tee *node, Plan *parent)
|
||||
|
||||
result = ExecStoreTuple(heapTuple, /* tuple to store */
|
||||
slot, /* slot to store in */
|
||||
scanDesc->rs_cbuf, /* this tuple's buffer */
|
||||
scanDesc->rs_cbuf, /* this tuple's buffer */
|
||||
false); /* don't free stuff from
|
||||
* heap_getnext */
|
||||
|
||||
|
@ -47,8 +47,7 @@ static int _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount);
|
||||
static void _SPI_fetch(FetchStmt *stmt);
|
||||
|
||||
#endif
|
||||
static int
|
||||
_SPI_execute_plan(_SPI_plan *plan,
|
||||
static int _SPI_execute_plan(_SPI_plan *plan,
|
||||
Datum *Values, char *Nulls, int tcount);
|
||||
|
||||
#define _SPI_CPLAN_CURCXT 0
|
||||
@ -466,7 +465,7 @@ SPI_gettype(TupleDesc tupdesc, int fnumber)
|
||||
}
|
||||
|
||||
typeTuple = SearchSysCacheTuple(TYPOID,
|
||||
ObjectIdGetDatum(tupdesc->attrs[fnumber - 1]->atttypid),
|
||||
ObjectIdGetDatum(tupdesc->attrs[fnumber - 1]->atttypid),
|
||||
0, 0, 0);
|
||||
|
||||
if (!HeapTupleIsValid(typeTuple))
|
||||
|
Reference in New Issue
Block a user