mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-24 18:55:04 +08:00
Implement feature of new FE/BE protocol whereby RowDescription identifies
the column by table OID and column number, if it's a simple column reference. Along the way, get rid of reskey/reskeyop fields in Resdoms. Turns out that representation was not convenient for either the planner or the executor; we can make the planner deliver exactly what the executor wants with no more effort. initdb forced due to change in stored rule representation.
This commit is contained in:
parent
94a3c60324
commit
2cf57c8f8d
@ -9,7 +9,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.68 2003/05/05 00:44:55 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.69 2003/05/06 00:20:31 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
|
||||
static void printtup_setup(DestReceiver *self, int operation,
|
||||
const char *portalName, TupleDesc typeinfo);
|
||||
const char *portalName, TupleDesc typeinfo, List *targetlist);
|
||||
static void printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self);
|
||||
static void printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self);
|
||||
static void printtup_cleanup(DestReceiver *self);
|
||||
@ -78,7 +78,7 @@ printtup_create_DR(bool isBinary, bool sendDescrip)
|
||||
|
||||
static void
|
||||
printtup_setup(DestReceiver *self, int operation,
|
||||
const char *portalName, TupleDesc typeinfo)
|
||||
const char *portalName, TupleDesc typeinfo, List *targetlist)
|
||||
{
|
||||
DR_printtup *myState = (DR_printtup *) self;
|
||||
|
||||
@ -100,7 +100,7 @@ printtup_setup(DestReceiver *self, int operation,
|
||||
* then we send back the tuple descriptor of the tuples.
|
||||
*/
|
||||
if (operation == CMD_SELECT && myState->sendDescrip)
|
||||
SendRowDescriptionMessage(typeinfo);
|
||||
SendRowDescriptionMessage(typeinfo, targetlist);
|
||||
|
||||
/* ----------------
|
||||
* We could set up the derived attr info at this time, but we postpone it
|
||||
@ -116,9 +116,15 @@ printtup_setup(DestReceiver *self, int operation,
|
||||
|
||||
/*
|
||||
* SendRowDescriptionMessage --- send a RowDescription message to the frontend
|
||||
*
|
||||
* Notes: the TupleDesc has typically been manufactured by ExecTypeFromTL()
|
||||
* or some similar function; it does not contain a full set of fields.
|
||||
* The targetlist will be NIL when executing a utility function that does
|
||||
* not have a plan. If the targetlist isn't NIL then it is a Plan node's
|
||||
* targetlist; it is up to us to ignore resjunk columns in it.
|
||||
*/
|
||||
void
|
||||
SendRowDescriptionMessage(TupleDesc typeinfo)
|
||||
SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist)
|
||||
{
|
||||
Form_pg_attribute *attrs = typeinfo->attrs;
|
||||
int natts = typeinfo->natts;
|
||||
@ -135,9 +141,24 @@ SendRowDescriptionMessage(TupleDesc typeinfo)
|
||||
/* column ID info appears in protocol 3.0 and up */
|
||||
if (proto >= 3)
|
||||
{
|
||||
/* XXX not yet implemented, send zeroes */
|
||||
pq_sendint(&buf, 0, 4);
|
||||
pq_sendint(&buf, 0, 2);
|
||||
/* Do we have a non-resjunk tlist item? */
|
||||
while (targetlist &&
|
||||
((TargetEntry *) lfirst(targetlist))->resdom->resjunk)
|
||||
targetlist = lnext(targetlist);
|
||||
if (targetlist)
|
||||
{
|
||||
Resdom *res = ((TargetEntry *) lfirst(targetlist))->resdom;
|
||||
|
||||
pq_sendint(&buf, res->resorigtbl, 4);
|
||||
pq_sendint(&buf, res->resorigcol, 2);
|
||||
targetlist = lnext(targetlist);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No info available, so send zeroes */
|
||||
pq_sendint(&buf, 0, 4);
|
||||
pq_sendint(&buf, 0, 2);
|
||||
}
|
||||
}
|
||||
pq_sendint(&buf, (int) attrs[i]->atttypid,
|
||||
sizeof(attrs[i]->atttypid));
|
||||
@ -324,7 +345,7 @@ showatts(const char *name, TupleDesc tupleDesc)
|
||||
*/
|
||||
void
|
||||
debugSetup(DestReceiver *self, int operation,
|
||||
const char *portalName, TupleDesc typeinfo)
|
||||
const char *portalName, TupleDesc typeinfo, List *targetlist)
|
||||
{
|
||||
/*
|
||||
* show the return type of the tuples
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994-5, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.106 2003/04/24 21:16:42 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.107 2003/05/06 00:20:31 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -57,8 +57,9 @@ static void show_upper_qual(List *qual, const char *qlabel,
|
||||
const char *outer_name, int outer_varno, Plan *outer_plan,
|
||||
const char *inner_name, int inner_varno, Plan *inner_plan,
|
||||
StringInfo str, int indent, ExplainState *es);
|
||||
static void show_sort_keys(List *tlist, int nkeys, const char *qlabel,
|
||||
StringInfo str, int indent, ExplainState *es);
|
||||
static void show_sort_keys(List *tlist, int nkeys, AttrNumber *keycols,
|
||||
const char *qlabel,
|
||||
StringInfo str, int indent, ExplainState *es);
|
||||
static Node *make_ors_ands_explicit(List *orclauses);
|
||||
|
||||
/*
|
||||
@ -193,18 +194,10 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
|
||||
ExplainState *es;
|
||||
StringInfo str;
|
||||
|
||||
/*
|
||||
* If we are not going to execute, suppress any SELECT INTO marker.
|
||||
* Without this, ExecutorStart will create the INTO target table,
|
||||
* which we don't want.
|
||||
*/
|
||||
if (!stmt->analyze)
|
||||
queryDesc->parsetree->into = NULL;
|
||||
|
||||
gettimeofday(&starttime, NULL);
|
||||
|
||||
/* call ExecutorStart to prepare the plan for execution */
|
||||
ExecutorStart(queryDesc);
|
||||
ExecutorStart(queryDesc, !stmt->analyze);
|
||||
|
||||
/* Execute the plan for statistics if asked for */
|
||||
if (stmt->analyze)
|
||||
@ -672,7 +665,9 @@ explain_outNode(StringInfo str,
|
||||
str, indent, es);
|
||||
break;
|
||||
case T_Sort:
|
||||
show_sort_keys(plan->targetlist, ((Sort *) plan)->keycount,
|
||||
show_sort_keys(plan->targetlist,
|
||||
((Sort *) plan)->numCols,
|
||||
((Sort *) plan)->sortColIdx,
|
||||
"Sort Key",
|
||||
str, indent, es);
|
||||
break;
|
||||
@ -937,7 +932,8 @@ show_upper_qual(List *qual, const char *qlabel,
|
||||
* Show the sort keys for a Sort node.
|
||||
*/
|
||||
static void
|
||||
show_sort_keys(List *tlist, int nkeys, const char *qlabel,
|
||||
show_sort_keys(List *tlist, int nkeys, AttrNumber *keycols,
|
||||
const char *qlabel,
|
||||
StringInfo str, int indent, ExplainState *es)
|
||||
{
|
||||
List *context;
|
||||
@ -985,27 +981,30 @@ show_sort_keys(List *tlist, int nkeys, const char *qlabel,
|
||||
}
|
||||
bms_free(varnos);
|
||||
|
||||
for (keyno = 1; keyno <= nkeys; keyno++)
|
||||
for (keyno = 0; keyno < nkeys; keyno++)
|
||||
{
|
||||
/* find key expression in tlist */
|
||||
AttrNumber keyresno = keycols[keyno];
|
||||
|
||||
foreach(tl, tlist)
|
||||
{
|
||||
TargetEntry *target = (TargetEntry *) lfirst(tl);
|
||||
|
||||
if (target->resdom->reskey == keyno)
|
||||
if (target->resdom->resno == keyresno)
|
||||
{
|
||||
/* Deparse the expression, showing any top-level cast */
|
||||
exprstr = deparse_expression((Node *) target->expr, context,
|
||||
useprefix, true);
|
||||
/* And add to str */
|
||||
if (keyno > 1)
|
||||
if (keyno > 0)
|
||||
appendStringInfo(str, ", ");
|
||||
appendStringInfo(str, "%s", exprstr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tl == NIL)
|
||||
elog(ERROR, "show_sort_keys: no tlist entry for key %d", keyno);
|
||||
elog(ERROR, "show_sort_keys: no tlist entry for key %d",
|
||||
keyresno);
|
||||
}
|
||||
|
||||
appendStringInfo(str, "\n");
|
||||
|
@ -26,7 +26,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.206 2003/05/05 17:57:47 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.207 2003/05/06 00:20:31 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -63,7 +63,7 @@ typedef struct evalPlanQual
|
||||
} evalPlanQual;
|
||||
|
||||
/* decls for local routines only used within this module */
|
||||
static void InitPlan(QueryDesc *queryDesc);
|
||||
static void InitPlan(QueryDesc *queryDesc, bool explainOnly);
|
||||
static void initResultRelInfo(ResultRelInfo *resultRelInfo,
|
||||
Index resultRelationIndex,
|
||||
List *rangeTable,
|
||||
@ -104,12 +104,15 @@ static void EvalPlanQualStop(evalPlanQual *epq);
|
||||
* field of the QueryDesc is filled in to describe the tuples that will be
|
||||
* returned, and the internal fields (estate and planstate) are set up.
|
||||
*
|
||||
* If explainOnly is true, we are not actually intending to run the plan,
|
||||
* only to set up for EXPLAIN; so skip unwanted side-effects.
|
||||
*
|
||||
* NB: the CurrentMemoryContext when this is called will become the parent
|
||||
* of the per-query context used for this Executor invocation.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
ExecutorStart(QueryDesc *queryDesc)
|
||||
ExecutorStart(QueryDesc *queryDesc, bool explainOnly)
|
||||
{
|
||||
EState *estate;
|
||||
MemoryContext oldcontext;
|
||||
@ -118,6 +121,13 @@ ExecutorStart(QueryDesc *queryDesc)
|
||||
Assert(queryDesc != NULL);
|
||||
Assert(queryDesc->estate == NULL);
|
||||
|
||||
/*
|
||||
* If the transaction is read-only, we need to check if any writes
|
||||
* are planned to non-temporary tables.
|
||||
*/
|
||||
if (!explainOnly)
|
||||
ExecCheckXactReadOnly(queryDesc->parsetree, queryDesc->operation);
|
||||
|
||||
/*
|
||||
* Build EState, switch into per-query memory context for startup.
|
||||
*/
|
||||
@ -149,7 +159,7 @@ ExecutorStart(QueryDesc *queryDesc)
|
||||
/*
|
||||
* Initialize the plan state tree
|
||||
*/
|
||||
InitPlan(queryDesc);
|
||||
InitPlan(queryDesc, explainOnly);
|
||||
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
}
|
||||
@ -202,14 +212,6 @@ ExecutorRun(QueryDesc *queryDesc,
|
||||
operation = queryDesc->operation;
|
||||
dest = queryDesc->dest;
|
||||
|
||||
/*
|
||||
* If the transaction is read-only, we need to check if any writes
|
||||
* are planned to non-temporary tables. This is done here at this
|
||||
* rather late stage so that we can handle EXPLAIN vs. EXPLAIN
|
||||
* ANALYZE easily.
|
||||
*/
|
||||
ExecCheckXactReadOnly(queryDesc->parsetree, operation);
|
||||
|
||||
/*
|
||||
* startup tuple receiver
|
||||
*/
|
||||
@ -217,8 +219,10 @@ ExecutorRun(QueryDesc *queryDesc,
|
||||
estate->es_lastoid = InvalidOid;
|
||||
|
||||
destfunc = DestToFunction(dest);
|
||||
(*destfunc->setup) (destfunc, operation, queryDesc->portalName,
|
||||
queryDesc->tupDesc);
|
||||
(*destfunc->setup) (destfunc, operation,
|
||||
queryDesc->portalName,
|
||||
queryDesc->tupDesc,
|
||||
queryDesc->planstate->plan->targetlist);
|
||||
|
||||
/*
|
||||
* run plan
|
||||
@ -468,7 +472,7 @@ fail:
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
static void
|
||||
InitPlan(QueryDesc *queryDesc)
|
||||
InitPlan(QueryDesc *queryDesc, bool explainOnly)
|
||||
{
|
||||
CmdType operation = queryDesc->operation;
|
||||
Query *parseTree = queryDesc->parsetree;
|
||||
@ -751,10 +755,12 @@ InitPlan(QueryDesc *queryDesc)
|
||||
* If doing SELECT INTO, initialize the "into" relation. We must wait
|
||||
* till now so we have the "clean" result tuple type to create the
|
||||
* new table from.
|
||||
*
|
||||
* If EXPLAIN, skip creating the "into" relation.
|
||||
*/
|
||||
intoRelationDesc = (Relation) NULL;
|
||||
|
||||
if (do_select_into)
|
||||
if (do_select_into && !explainOnly)
|
||||
{
|
||||
char *intoName;
|
||||
Oid namespaceId;
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.63 2002/12/13 19:45:52 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.64 2003/05/06 00:20:31 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -723,7 +723,7 @@ begin_tup_output_tupdesc(CommandDest dest, TupleDesc tupdesc)
|
||||
tstate->destfunc = DestToFunction(dest);
|
||||
|
||||
(*tstate->destfunc->setup) (tstate->destfunc, (int) CMD_SELECT,
|
||||
NULL, tupdesc);
|
||||
NULL, tupdesc, NIL);
|
||||
|
||||
return tstate;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.62 2002/12/15 16:17:46 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.63 2003/05/06 00:20:31 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -250,7 +250,7 @@ postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
|
||||
|
||||
/* Utility commands don't need Executor. */
|
||||
if (es->qd->operation != CMD_UTILITY)
|
||||
ExecutorStart(es->qd);
|
||||
ExecutorStart(es->qd, false);
|
||||
|
||||
es->status = F_EXEC_RUN;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSort.c,v 1.43 2003/05/05 17:57:47 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSort.c,v 1.44 2003/05/06 00:20:31 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -19,59 +19,6 @@
|
||||
#include "executor/nodeSort.h"
|
||||
#include "utils/tuplesort.h"
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExtractSortKeys
|
||||
*
|
||||
* Extract the sorting key information from the plan node.
|
||||
*
|
||||
* Returns two palloc'd arrays, one of sort operator OIDs and
|
||||
* one of attribute numbers.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
static void
|
||||
ExtractSortKeys(Sort *sortnode,
|
||||
Oid **sortOperators,
|
||||
AttrNumber **attNums)
|
||||
{
|
||||
List *targetList;
|
||||
int keycount;
|
||||
Oid *sortOps;
|
||||
AttrNumber *attNos;
|
||||
List *tl;
|
||||
|
||||
/*
|
||||
* get information from the node
|
||||
*/
|
||||
targetList = sortnode->plan.targetlist;
|
||||
keycount = sortnode->keycount;
|
||||
|
||||
/*
|
||||
* first allocate space for results
|
||||
*/
|
||||
if (keycount <= 0)
|
||||
elog(ERROR, "ExtractSortKeys: keycount <= 0");
|
||||
sortOps = (Oid *) palloc0(keycount * sizeof(Oid));
|
||||
*sortOperators = sortOps;
|
||||
attNos = (AttrNumber *) palloc0(keycount * sizeof(AttrNumber));
|
||||
*attNums = attNos;
|
||||
|
||||
/*
|
||||
* extract info from the resdom nodes in the target list
|
||||
*/
|
||||
foreach(tl, targetList)
|
||||
{
|
||||
TargetEntry *target = (TargetEntry *) lfirst(tl);
|
||||
Resdom *resdom = target->resdom;
|
||||
Index reskey = resdom->reskey;
|
||||
|
||||
if (reskey > 0) /* ignore TLEs that are not sort keys */
|
||||
{
|
||||
Assert(reskey <= keycount);
|
||||
sortOps[reskey - 1] = resdom->reskeyop;
|
||||
attNos[reskey - 1] = resdom->resno;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecSort
|
||||
@ -118,8 +65,6 @@ ExecSort(SortState *node)
|
||||
Sort *plannode = (Sort *) node->ss.ps.plan;
|
||||
PlanState *outerNode;
|
||||
TupleDesc tupDesc;
|
||||
Oid *sortOperators;
|
||||
AttrNumber *attNums;
|
||||
|
||||
SO1_printf("ExecSort: %s\n",
|
||||
"sorting subplan");
|
||||
@ -139,16 +84,13 @@ ExecSort(SortState *node)
|
||||
outerNode = outerPlanState(node);
|
||||
tupDesc = ExecGetResultType(outerNode);
|
||||
|
||||
ExtractSortKeys(plannode, &sortOperators, &attNums);
|
||||
|
||||
tuplesortstate = tuplesort_begin_heap(tupDesc, plannode->keycount,
|
||||
sortOperators, attNums,
|
||||
tuplesortstate = tuplesort_begin_heap(tupDesc,
|
||||
plannode->numCols,
|
||||
plannode->sortOperators,
|
||||
plannode->sortColIdx,
|
||||
true /* randomAccess */ );
|
||||
node->tuplesortstate = (void *) tuplesortstate;
|
||||
|
||||
pfree(sortOperators);
|
||||
pfree(attNums);
|
||||
|
||||
/*
|
||||
* Scan the subplan and feed all the tuples to tuplesort.
|
||||
*/
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.94 2003/05/02 20:54:34 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.95 2003/05/06 00:20:31 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -880,7 +880,7 @@ SPI_cursor_close(Portal portal)
|
||||
*/
|
||||
void
|
||||
spi_dest_setup(DestReceiver *self, int operation,
|
||||
const char *portalName, TupleDesc typeinfo)
|
||||
const char *portalName, TupleDesc typeinfo, List *targetlist)
|
||||
{
|
||||
SPITupleTable *tuptable;
|
||||
MemoryContext oldcxt;
|
||||
@ -1209,7 +1209,7 @@ _SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount)
|
||||
ResetUsage();
|
||||
#endif
|
||||
|
||||
ExecutorStart(queryDesc);
|
||||
ExecutorStart(queryDesc, false);
|
||||
|
||||
ExecutorRun(queryDesc, ForwardScanDirection, (long) tcount);
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/tstoreReceiver.c,v 1.3 2003/05/02 20:54:34 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/tstoreReceiver.c,v 1.4 2003/05/06 00:20:31 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -40,7 +40,8 @@ typedef struct
|
||||
*/
|
||||
static void
|
||||
tstoreSetupReceiver(DestReceiver *self, int operation,
|
||||
const char *portalname, TupleDesc typeinfo)
|
||||
const char *portalname,
|
||||
TupleDesc typeinfo, List *targetlist)
|
||||
{
|
||||
TStoreState *myState = (TStoreState *) self;
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.249 2003/05/02 20:54:34 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.250 2003/05/06 00:20:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -448,7 +448,9 @@ _copySort(Sort *from)
|
||||
*/
|
||||
CopyPlanFields((Plan *) from, (Plan *) newnode);
|
||||
|
||||
COPY_SCALAR_FIELD(keycount);
|
||||
COPY_SCALAR_FIELD(numCols);
|
||||
COPY_POINTER_FIELD(sortColIdx, from->numCols * sizeof(AttrNumber));
|
||||
COPY_POINTER_FIELD(sortOperators, from->numCols * sizeof(Oid));
|
||||
|
||||
return newnode;
|
||||
}
|
||||
@ -596,8 +598,8 @@ _copyResdom(Resdom *from)
|
||||
COPY_SCALAR_FIELD(restypmod);
|
||||
COPY_STRING_FIELD(resname);
|
||||
COPY_SCALAR_FIELD(ressortgroupref);
|
||||
COPY_SCALAR_FIELD(reskey);
|
||||
COPY_SCALAR_FIELD(reskeyop);
|
||||
COPY_SCALAR_FIELD(resorigtbl);
|
||||
COPY_SCALAR_FIELD(resorigcol);
|
||||
COPY_SCALAR_FIELD(resjunk);
|
||||
|
||||
return newnode;
|
||||
|
@ -18,7 +18,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.192 2003/05/02 20:54:34 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.193 2003/05/06 00:20:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -104,8 +104,8 @@ _equalResdom(Resdom *a, Resdom *b)
|
||||
COMPARE_SCALAR_FIELD(restypmod);
|
||||
COMPARE_STRING_FIELD(resname);
|
||||
COMPARE_SCALAR_FIELD(ressortgroupref);
|
||||
COMPARE_SCALAR_FIELD(reskey);
|
||||
COMPARE_SCALAR_FIELD(reskeyop);
|
||||
COMPARE_SCALAR_FIELD(resorigtbl);
|
||||
COMPARE_SCALAR_FIELD(resorigcol);
|
||||
COMPARE_SCALAR_FIELD(resjunk);
|
||||
|
||||
return true;
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.38 2003/02/10 04:44:45 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.39 2003/05/06 00:20:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -117,16 +117,16 @@ makeResdom(AttrNumber resno,
|
||||
resdom->resname = resname;
|
||||
|
||||
/*
|
||||
* We always set the sorting/grouping fields to 0. If the caller
|
||||
* wants to change them he must do so explicitly. Few if any callers
|
||||
* should be doing that, so omitting these arguments reduces the
|
||||
* chance of error.
|
||||
* We always set these fields to 0. If the caller wants to change them
|
||||
* he must do so explicitly. Few callers do that, so omitting these
|
||||
* arguments reduces the chance of error.
|
||||
*/
|
||||
resdom->ressortgroupref = 0;
|
||||
resdom->reskey = 0;
|
||||
resdom->reskeyop = InvalidOid;
|
||||
resdom->resorigtbl = InvalidOid;
|
||||
resdom->resorigcol = 0;
|
||||
|
||||
resdom->resjunk = resjunk;
|
||||
|
||||
return resdom;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.204 2003/05/02 20:54:34 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.205 2003/05/06 00:20:32 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Every node type that can appear in stored rules' parsetrees *must*
|
||||
@ -420,11 +420,17 @@ _outAgg(StringInfo str, Agg *node)
|
||||
static void
|
||||
_outGroup(StringInfo str, Group *node)
|
||||
{
|
||||
WRITE_NODE_TYPE("GRP");
|
||||
int i;
|
||||
|
||||
WRITE_NODE_TYPE("GROUP");
|
||||
|
||||
_outPlanInfo(str, (Plan *) node);
|
||||
|
||||
WRITE_INT_FIELD(numCols);
|
||||
|
||||
appendStringInfo(str, " :grpColIdx");
|
||||
for (i = 0; i < node->numCols; i++)
|
||||
appendStringInfo(str, " %d", node->grpColIdx[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -438,11 +444,21 @@ _outMaterial(StringInfo str, Material *node)
|
||||
static void
|
||||
_outSort(StringInfo str, Sort *node)
|
||||
{
|
||||
int i;
|
||||
|
||||
WRITE_NODE_TYPE("SORT");
|
||||
|
||||
_outPlanInfo(str, (Plan *) node);
|
||||
|
||||
WRITE_INT_FIELD(keycount);
|
||||
WRITE_INT_FIELD(numCols);
|
||||
|
||||
appendStringInfo(str, " :sortColIdx");
|
||||
for (i = 0; i < node->numCols; i++)
|
||||
appendStringInfo(str, " %d", node->sortColIdx[i]);
|
||||
|
||||
appendStringInfo(str, " :sortOperators");
|
||||
for (i = 0; i < node->numCols; i++)
|
||||
appendStringInfo(str, " %u", node->sortOperators[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -517,8 +533,8 @@ _outResdom(StringInfo str, Resdom *node)
|
||||
WRITE_INT_FIELD(restypmod);
|
||||
WRITE_STRING_FIELD(resname);
|
||||
WRITE_UINT_FIELD(ressortgroupref);
|
||||
WRITE_UINT_FIELD(reskey);
|
||||
WRITE_OID_FIELD(reskeyop);
|
||||
WRITE_OID_FIELD(resorigtbl);
|
||||
WRITE_INT_FIELD(resorigcol);
|
||||
WRITE_BOOL_FIELD(resjunk);
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.60 2003/01/22 19:26:35 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.61 2003/05/06 00:20:32 tgl Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@ -447,8 +447,8 @@ print_tl(List *tlist, List *rtable)
|
||||
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);
|
||||
if (tle->resdom->ressortgroupref != 0)
|
||||
printf("(%u):\t", tle->resdom->ressortgroupref);
|
||||
else
|
||||
printf(" :\t");
|
||||
print_expr((Node *) tle->expr, rtable);
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.152 2003/05/02 20:54:34 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.153 2003/05/06 00:20:32 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Path and Plan nodes do not have any readfuncs support, because we
|
||||
@ -310,8 +310,8 @@ _readResdom(void)
|
||||
READ_INT_FIELD(restypmod);
|
||||
READ_STRING_FIELD(resname);
|
||||
READ_UINT_FIELD(ressortgroupref);
|
||||
READ_UINT_FIELD(reskey);
|
||||
READ_OID_FIELD(reskeyop);
|
||||
READ_OID_FIELD(resorigtbl);
|
||||
READ_INT_FIELD(resorigcol);
|
||||
READ_BOOL_FIELD(resjunk);
|
||||
|
||||
READ_DONE();
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.138 2003/03/10 03:53:50 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.139 2003/05/06 00:20:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -101,6 +101,8 @@ static MergeJoin *make_mergejoin(List *tlist,
|
||||
List *mergeclauses,
|
||||
Plan *lefttree, Plan *righttree,
|
||||
JoinType jointype);
|
||||
static Sort *make_sort(Query *root, List *tlist, Plan *lefttree, int numCols,
|
||||
AttrNumber *sortColIdx, Oid *sortOperators);
|
||||
static Sort *make_sort_from_pathkeys(Query *root, Plan *lefttree,
|
||||
Relids relids, List *pathkeys);
|
||||
|
||||
@ -576,7 +578,7 @@ create_unique_plan(Query *root, UniquePath *best_path)
|
||||
subplan->targetlist = newtlist;
|
||||
}
|
||||
|
||||
my_tlist = new_unsorted_tlist(subplan->targetlist);
|
||||
my_tlist = copyObject(subplan->targetlist);
|
||||
|
||||
if (best_path->use_hash)
|
||||
{
|
||||
@ -1614,13 +1616,13 @@ make_mergejoin(List *tlist,
|
||||
}
|
||||
|
||||
/*
|
||||
* To use make_sort directly, you must already have marked the tlist
|
||||
* with reskey and reskeyop information. The keys had better be
|
||||
* non-redundant, too (ie, there had better be tlist items marked with
|
||||
* each key number from 1 to keycount), or the executor will get confused!
|
||||
* make_sort --- basic routine to build a Sort plan node
|
||||
*
|
||||
* Caller must have built the sortColIdx and sortOperators arrays already.
|
||||
*/
|
||||
Sort *
|
||||
make_sort(Query *root, List *tlist, Plan *lefttree, int keycount)
|
||||
static Sort *
|
||||
make_sort(Query *root, List *tlist, Plan *lefttree, int numCols,
|
||||
AttrNumber *sortColIdx, Oid *sortOperators)
|
||||
{
|
||||
Sort *node = makeNode(Sort);
|
||||
Plan *plan = &node->plan;
|
||||
@ -1637,11 +1639,43 @@ make_sort(Query *root, List *tlist, Plan *lefttree, int keycount)
|
||||
plan->qual = NIL;
|
||||
plan->lefttree = lefttree;
|
||||
plan->righttree = NULL;
|
||||
node->keycount = keycount;
|
||||
node->numCols = numCols;
|
||||
node->sortColIdx = sortColIdx;
|
||||
node->sortOperators = sortOperators;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_sort_column --- utility subroutine for building sort info arrays
|
||||
*
|
||||
* We need this routine because the same column might be selected more than
|
||||
* once as a sort key column; if so, the extra mentions are redundant.
|
||||
*
|
||||
* Caller is assumed to have allocated the arrays large enough for the
|
||||
* max possible number of columns. Return value is the new column count.
|
||||
*/
|
||||
static int
|
||||
add_sort_column(AttrNumber colIdx, Oid sortOp,
|
||||
int numCols, AttrNumber *sortColIdx, Oid *sortOperators)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < numCols; i++)
|
||||
{
|
||||
if (sortColIdx[i] == colIdx)
|
||||
{
|
||||
/* Already sorting by this col, so extra sort key is useless */
|
||||
return numCols;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the column */
|
||||
sortColIdx[numCols] = colIdx;
|
||||
sortOperators[numCols] = sortOp;
|
||||
return numCols + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* make_sort_from_pathkeys
|
||||
* Create sort plan to sort according to given pathkeys
|
||||
@ -1650,8 +1684,8 @@ make_sort(Query *root, List *tlist, Plan *lefttree, int keycount)
|
||||
* 'relids' is the set of relids represented by the input node
|
||||
* 'pathkeys' is the list of pathkeys by which the result is to be sorted
|
||||
*
|
||||
* We must convert the pathkey information into reskey and reskeyop fields
|
||||
* of resdom nodes in the sort plan's target list.
|
||||
* We must convert the pathkey information into arrays of sort key column
|
||||
* numbers and sort operator OIDs.
|
||||
*
|
||||
* If the pathkeys include expressions that aren't simple Vars, we will
|
||||
* usually need to add resjunk items to the input plan's targetlist to
|
||||
@ -1666,10 +1700,16 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree,
|
||||
List *tlist = lefttree->targetlist;
|
||||
List *sort_tlist;
|
||||
List *i;
|
||||
int numsortkeys = 0;
|
||||
int numsortkeys;
|
||||
AttrNumber *sortColIdx;
|
||||
Oid *sortOperators;
|
||||
|
||||
/* Create a new target list for the sort, with sort keys set. */
|
||||
sort_tlist = new_unsorted_tlist(tlist);
|
||||
/* We will need at most length(pathkeys) sort columns; possibly less */
|
||||
numsortkeys = length(pathkeys);
|
||||
sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
|
||||
sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
|
||||
|
||||
numsortkeys = 0;
|
||||
|
||||
foreach(i, pathkeys)
|
||||
{
|
||||
@ -1681,7 +1721,7 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree,
|
||||
/*
|
||||
* We can sort by any one of the sort key items listed in this
|
||||
* sublist. For now, we take the first one that corresponds to an
|
||||
* available Var in the sort_tlist. If there isn't any, use the
|
||||
* available Var in the tlist. If there isn't any, use the
|
||||
* first one that is an expression in the input's vars.
|
||||
*
|
||||
* XXX if we have a choice, is there any way of figuring out which
|
||||
@ -1694,7 +1734,7 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree,
|
||||
{
|
||||
pathkey = lfirst(j);
|
||||
Assert(IsA(pathkey, PathKeyItem));
|
||||
resdom = tlist_member(pathkey->key, sort_tlist);
|
||||
resdom = tlist_member(pathkey->key, tlist);
|
||||
if (resdom)
|
||||
break;
|
||||
}
|
||||
@ -1717,7 +1757,7 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree,
|
||||
*/
|
||||
if (IsA(lefttree, Append))
|
||||
{
|
||||
tlist = new_unsorted_tlist(tlist);
|
||||
tlist = copyObject(tlist);
|
||||
lefttree = (Plan *) make_result(tlist, NULL, lefttree);
|
||||
}
|
||||
/*
|
||||
@ -1732,38 +1772,24 @@ make_sort_from_pathkeys(Query *root, Plan *lefttree,
|
||||
makeTargetEntry(resdom,
|
||||
(Expr *) pathkey->key));
|
||||
lefttree->targetlist = tlist; /* just in case NIL before */
|
||||
/*
|
||||
* Add one to sort node's tlist too. This will be identical
|
||||
* except we are going to set the sort key info in it.
|
||||
*/
|
||||
resdom = makeResdom(length(sort_tlist) + 1,
|
||||
exprType(pathkey->key),
|
||||
exprTypmod(pathkey->key),
|
||||
NULL,
|
||||
true);
|
||||
sort_tlist = lappend(sort_tlist,
|
||||
makeTargetEntry(resdom,
|
||||
(Expr *) pathkey->key));
|
||||
}
|
||||
/*
|
||||
* The resdom might be already marked as a sort key, if the
|
||||
* The column might already be selected as a sort key, if the
|
||||
* pathkeys contain duplicate entries. (This can happen in
|
||||
* scenarios where multiple mergejoinable clauses mention the same
|
||||
* var, for example.) In that case the current pathkey is
|
||||
* essentially a no-op, because only one value can be seen within
|
||||
* any subgroup where it would be consulted. We can ignore it.
|
||||
* var, for example.) So enter it only once in the sort arrays.
|
||||
*/
|
||||
if (resdom->reskey == 0)
|
||||
{
|
||||
/* OK, mark it as a sort key and set the sort operator */
|
||||
resdom->reskey = ++numsortkeys;
|
||||
resdom->reskeyop = pathkey->sortop;
|
||||
}
|
||||
numsortkeys = add_sort_column(resdom->resno, pathkey->sortop,
|
||||
numsortkeys, sortColIdx, sortOperators);
|
||||
}
|
||||
|
||||
Assert(numsortkeys > 0);
|
||||
|
||||
return make_sort(root, sort_tlist, lefttree, numsortkeys);
|
||||
/* Give Sort node its own copy of the tlist (still necessary?) */
|
||||
sort_tlist = copyObject(tlist);
|
||||
|
||||
return make_sort(root, sort_tlist, lefttree, numsortkeys,
|
||||
sortColIdx, sortOperators);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1780,36 +1806,96 @@ make_sort_from_sortclauses(Query *root, List *tlist,
|
||||
{
|
||||
List *sort_tlist;
|
||||
List *i;
|
||||
int keyno = 0;
|
||||
int numsortkeys;
|
||||
AttrNumber *sortColIdx;
|
||||
Oid *sortOperators;
|
||||
|
||||
/*
|
||||
* First make a copy of the tlist so that we don't corrupt the
|
||||
* original.
|
||||
*/
|
||||
sort_tlist = new_unsorted_tlist(tlist);
|
||||
/* We will need at most length(sortcls) sort columns; possibly less */
|
||||
numsortkeys = length(sortcls);
|
||||
sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
|
||||
sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
|
||||
|
||||
numsortkeys = 0;
|
||||
|
||||
foreach(i, sortcls)
|
||||
{
|
||||
SortClause *sortcl = (SortClause *) lfirst(i);
|
||||
TargetEntry *tle = get_sortgroupclause_tle(sortcl, sort_tlist);
|
||||
TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist);
|
||||
Resdom *resdom = tle->resdom;
|
||||
|
||||
/*
|
||||
* Check for the possibility of duplicate order-by clauses --- the
|
||||
* parser should have removed 'em, but the executor will get
|
||||
* terribly confused if any get through!
|
||||
* parser should have removed 'em, but no point in sorting redundantly.
|
||||
*/
|
||||
if (resdom->reskey == 0)
|
||||
{
|
||||
/* OK, insert the ordering info needed by the executor. */
|
||||
resdom->reskey = ++keyno;
|
||||
resdom->reskeyop = sortcl->sortop;
|
||||
}
|
||||
numsortkeys = add_sort_column(resdom->resno, sortcl->sortop,
|
||||
numsortkeys, sortColIdx, sortOperators);
|
||||
}
|
||||
|
||||
Assert(keyno > 0);
|
||||
Assert(numsortkeys > 0);
|
||||
|
||||
return make_sort(root, sort_tlist, lefttree, keyno);
|
||||
/* Give Sort node its own copy of the tlist (still necessary?) */
|
||||
sort_tlist = copyObject(tlist);
|
||||
|
||||
return make_sort(root, sort_tlist, lefttree, numsortkeys,
|
||||
sortColIdx, sortOperators);
|
||||
}
|
||||
|
||||
/*
|
||||
* make_sort_from_groupcols
|
||||
* Create sort plan to sort based on grouping columns
|
||||
*
|
||||
* 'groupcls' is the list of GroupClauses
|
||||
* 'grpColIdx' gives the column numbers to use
|
||||
*
|
||||
* This might look like it could be merged with make_sort_from_sortclauses,
|
||||
* but presently we *must* use the grpColIdx[] array to locate sort columns,
|
||||
* because the child plan's tlist is not marked with ressortgroupref info
|
||||
* appropriate to the grouping node. So, only the sortop is used from the
|
||||
* GroupClause entries.
|
||||
*/
|
||||
Sort *
|
||||
make_sort_from_groupcols(Query *root,
|
||||
List *groupcls,
|
||||
AttrNumber *grpColIdx,
|
||||
Plan *lefttree)
|
||||
{
|
||||
List *sub_tlist = lefttree->targetlist;
|
||||
List *sort_tlist;
|
||||
int grpno = 0;
|
||||
List *i;
|
||||
int numsortkeys;
|
||||
AttrNumber *sortColIdx;
|
||||
Oid *sortOperators;
|
||||
|
||||
/* We will need at most length(groupcls) sort columns; possibly less */
|
||||
numsortkeys = length(groupcls);
|
||||
sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
|
||||
sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
|
||||
|
||||
numsortkeys = 0;
|
||||
|
||||
foreach(i, groupcls)
|
||||
{
|
||||
GroupClause *grpcl = (GroupClause *) lfirst(i);
|
||||
TargetEntry *tle = nth(grpColIdx[grpno] - 1, sub_tlist);
|
||||
Resdom *resdom = tle->resdom;
|
||||
|
||||
/*
|
||||
* Check for the possibility of duplicate group-by clauses --- the
|
||||
* parser should have removed 'em, but no point in sorting redundantly.
|
||||
*/
|
||||
numsortkeys = add_sort_column(resdom->resno, grpcl->sortop,
|
||||
numsortkeys, sortColIdx, sortOperators);
|
||||
grpno++;
|
||||
}
|
||||
|
||||
Assert(numsortkeys > 0);
|
||||
|
||||
/* Give Sort node its own copy of the tlist (still necessary?) */
|
||||
sort_tlist = copyObject(sub_tlist);
|
||||
|
||||
return make_sort(root, sort_tlist, lefttree, numsortkeys,
|
||||
sortColIdx, sortOperators);
|
||||
}
|
||||
|
||||
Material *
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.152 2003/03/13 16:58:35 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.153 2003/05/06 00:20:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -61,10 +61,6 @@ static void locate_grouping_columns(Query *parse,
|
||||
List *tlist,
|
||||
List *sub_tlist,
|
||||
AttrNumber *groupColIdx);
|
||||
static Plan *make_groupsortplan(Query *parse,
|
||||
List *groupClause,
|
||||
AttrNumber *grpColIdx,
|
||||
Plan *subplan);
|
||||
static List *postprocess_setop_tlist(List *new_tlist, List *orig_tlist);
|
||||
|
||||
|
||||
@ -1145,10 +1141,11 @@ grouping_planner(Query *parse, double tuple_fraction)
|
||||
{
|
||||
if (!pathkeys_contained_in(group_pathkeys, current_pathkeys))
|
||||
{
|
||||
result_plan = make_groupsortplan(parse,
|
||||
parse->groupClause,
|
||||
groupColIdx,
|
||||
result_plan);
|
||||
result_plan = (Plan *)
|
||||
make_sort_from_groupcols(parse,
|
||||
parse->groupClause,
|
||||
groupColIdx,
|
||||
result_plan);
|
||||
current_pathkeys = group_pathkeys;
|
||||
}
|
||||
aggstrategy = AGG_SORTED;
|
||||
@ -1193,10 +1190,11 @@ grouping_planner(Query *parse, double tuple_fraction)
|
||||
*/
|
||||
if (!pathkeys_contained_in(group_pathkeys, current_pathkeys))
|
||||
{
|
||||
result_plan = make_groupsortplan(parse,
|
||||
parse->groupClause,
|
||||
groupColIdx,
|
||||
result_plan);
|
||||
result_plan = (Plan *)
|
||||
make_sort_from_groupcols(parse,
|
||||
parse->groupClause,
|
||||
groupColIdx,
|
||||
result_plan);
|
||||
current_pathkeys = group_pathkeys;
|
||||
}
|
||||
|
||||
@ -1219,10 +1217,11 @@ grouping_planner(Query *parse, double tuple_fraction)
|
||||
{
|
||||
if (!pathkeys_contained_in(sort_pathkeys, current_pathkeys))
|
||||
{
|
||||
result_plan = (Plan *) make_sort_from_sortclauses(parse,
|
||||
tlist,
|
||||
result_plan,
|
||||
parse->sortClause);
|
||||
result_plan = (Plan *)
|
||||
make_sort_from_sortclauses(parse,
|
||||
tlist,
|
||||
result_plan,
|
||||
parse->sortClause);
|
||||
current_pathkeys = sort_pathkeys;
|
||||
}
|
||||
}
|
||||
@ -1471,53 +1470,6 @@ locate_grouping_columns(Query *parse,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* make_groupsortplan
|
||||
* Add a Sort node to explicitly sort according to the GROUP BY clause.
|
||||
*
|
||||
* Note: the Sort node always just takes a copy of the subplan's tlist
|
||||
* plus ordering information. (This might seem inefficient if the
|
||||
* subplan contains complex GROUP BY expressions, but in fact Sort
|
||||
* does not evaluate its targetlist --- it only outputs the same
|
||||
* tuples in a new order. So the expressions we might be copying
|
||||
* are just dummies with no extra execution cost.)
|
||||
*/
|
||||
static Plan *
|
||||
make_groupsortplan(Query *parse,
|
||||
List *groupClause,
|
||||
AttrNumber *grpColIdx,
|
||||
Plan *subplan)
|
||||
{
|
||||
List *sort_tlist = new_unsorted_tlist(subplan->targetlist);
|
||||
int grpno = 0;
|
||||
int keyno = 0;
|
||||
List *gl;
|
||||
|
||||
foreach(gl, groupClause)
|
||||
{
|
||||
GroupClause *grpcl = (GroupClause *) lfirst(gl);
|
||||
TargetEntry *te = nth(grpColIdx[grpno] - 1, sort_tlist);
|
||||
Resdom *resdom = te->resdom;
|
||||
|
||||
/*
|
||||
* Check for the possibility of duplicate group-by clauses ---
|
||||
* the parser should have removed 'em, but the Sort executor
|
||||
* will get terribly confused if any get through!
|
||||
*/
|
||||
if (resdom->reskey == 0)
|
||||
{
|
||||
/* OK, insert the ordering info needed by the executor. */
|
||||
resdom->reskey = ++keyno;
|
||||
resdom->reskeyop = grpcl->sortop;
|
||||
}
|
||||
grpno++;
|
||||
}
|
||||
|
||||
Assert(keyno > 0);
|
||||
|
||||
return (Plan *) make_sort(parse, sort_tlist, subplan, keyno);
|
||||
}
|
||||
|
||||
/*
|
||||
* postprocess_setop_tlist
|
||||
* Fix up targetlist returned by plan_set_operations().
|
||||
|
@ -14,7 +14,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.94 2003/04/29 22:13:09 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.95 2003/05/06 00:20:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -238,7 +238,7 @@ generate_union_plan(SetOperationStmt *op, Query *parse,
|
||||
{
|
||||
List *sortList;
|
||||
|
||||
tlist = new_unsorted_tlist(tlist);
|
||||
tlist = copyObject(tlist);
|
||||
sortList = addAllTargetsToSortList(NIL, tlist);
|
||||
plan = (Plan *) make_sort_from_sortclauses(parse, tlist,
|
||||
plan, sortList);
|
||||
@ -292,7 +292,7 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse,
|
||||
* Sort the child results, then add a SetOp plan node to generate the
|
||||
* correct output.
|
||||
*/
|
||||
tlist = new_unsorted_tlist(tlist);
|
||||
tlist = copyObject(tlist);
|
||||
sortList = addAllTargetsToSortList(NIL, tlist);
|
||||
plan = (Plan *) make_sort_from_sortclauses(parse, tlist, plan, sortList);
|
||||
switch (op->op)
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.55 2003/02/15 20:12:40 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.56 2003/05/06 00:20:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -117,32 +117,6 @@ create_tl_element(Var *var, int resdomno)
|
||||
* ---------- GENERAL target list routines ----------
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* new_unsorted_tlist
|
||||
* Creates a copy of a target list by creating new resdom nodes
|
||||
* without sort information.
|
||||
*
|
||||
* 'targetlist' is the target list to be copied.
|
||||
*
|
||||
* Returns the resulting target list.
|
||||
*
|
||||
*/
|
||||
List *
|
||||
new_unsorted_tlist(List *targetlist)
|
||||
{
|
||||
List *new_targetlist = (List *) copyObject((Node *) targetlist);
|
||||
List *x;
|
||||
|
||||
foreach(x, new_targetlist)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(x);
|
||||
|
||||
tle->resdom->reskey = 0;
|
||||
tle->resdom->reskeyop = (Oid) 0;
|
||||
}
|
||||
return new_targetlist;
|
||||
}
|
||||
|
||||
/*
|
||||
* flatten_tlist
|
||||
* Create a target list that only contains unique variables.
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.270 2003/05/05 00:44:55 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.271 2003/05/06 00:20:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1747,6 +1747,9 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
if (stmt->intoColNames)
|
||||
applyColumnNames(qry->targetList, stmt->intoColNames);
|
||||
|
||||
/* mark column origins */
|
||||
markTargetListOrigins(pstate, qry->targetList);
|
||||
|
||||
/* transform WHERE */
|
||||
qual = transformWhereClause(pstate, stmt->whereClause);
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.100 2003/04/29 22:13:10 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.101 2003/05/06 00:20:32 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -26,6 +26,7 @@
|
||||
#include "utils/builtins.h"
|
||||
|
||||
|
||||
static void markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var);
|
||||
static List *ExpandAllTables(ParseState *pstate);
|
||||
static char *FigureColname(Node *node);
|
||||
static int FigureColnameInternal(Node *node, char **name);
|
||||
@ -204,6 +205,94 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* markTargetListOrigins()
|
||||
* Mark targetlist columns that are simple Vars with the source
|
||||
* table's OID and column number.
|
||||
*
|
||||
* Currently, this is done only for SELECT targetlists, since we only
|
||||
* need the info if we are going to send it to the frontend.
|
||||
*/
|
||||
void
|
||||
markTargetListOrigins(ParseState *pstate, List *targetlist)
|
||||
{
|
||||
List *l;
|
||||
|
||||
foreach(l, targetlist)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
||||
|
||||
markTargetListOrigin(pstate, tle->resdom, (Var *) tle->expr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* markTargetListOrigin()
|
||||
* If 'var' is a Var of a plain relation, mark 'res' with its origin
|
||||
*
|
||||
* This is split out so it can recurse for join references. Note that we
|
||||
* do not drill down into views, but report the view as the column owner.
|
||||
*/
|
||||
static void
|
||||
markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var)
|
||||
{
|
||||
RangeTblEntry *rte;
|
||||
AttrNumber attnum;
|
||||
|
||||
if (var == NULL || !IsA(var, Var))
|
||||
return;
|
||||
Assert(var->varno > 0 &&
|
||||
(int) var->varno <= length(pstate->p_rtable));
|
||||
rte = rt_fetch(var->varno, pstate->p_rtable);
|
||||
attnum = var->varattno;
|
||||
|
||||
switch (rte->rtekind)
|
||||
{
|
||||
case RTE_RELATION:
|
||||
/* It's a table or view, report it */
|
||||
res->resorigtbl = rte->relid;
|
||||
res->resorigcol = attnum;
|
||||
break;
|
||||
case RTE_SUBQUERY:
|
||||
{
|
||||
/* Subselect-in-FROM: copy up from the subselect */
|
||||
List *subtl;
|
||||
|
||||
foreach(subtl, rte->subquery->targetList)
|
||||
{
|
||||
TargetEntry *subte = (TargetEntry *) lfirst(subtl);
|
||||
|
||||
if (subte->resdom->resjunk ||
|
||||
subte->resdom->resno != attnum)
|
||||
continue;
|
||||
res->resorigtbl = subte->resdom->resorigtbl;
|
||||
res->resorigcol = subte->resdom->resorigcol;
|
||||
break;
|
||||
}
|
||||
/* falling off end of list shouldn't happen... */
|
||||
if (subtl == NIL)
|
||||
elog(ERROR, "Subquery %s does not have attribute %d",
|
||||
rte->eref->aliasname, attnum);
|
||||
}
|
||||
break;
|
||||
case RTE_JOIN:
|
||||
{
|
||||
/* Join RTE --- recursively inspect the alias variable */
|
||||
Var *aliasvar;
|
||||
|
||||
Assert(attnum > 0 && attnum <= length(rte->joinaliasvars));
|
||||
aliasvar = (Var *) nth(attnum - 1, rte->joinaliasvars);
|
||||
markTargetListOrigin(pstate, res, aliasvar);
|
||||
}
|
||||
break;
|
||||
case RTE_SPECIAL:
|
||||
case RTE_FUNCTION:
|
||||
/* not a simple relation, leave it unmarked */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* updateTargetListEntry()
|
||||
* This is used in INSERT and UPDATE statements only. It prepares a
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/dest.c,v 1.55 2003/05/05 00:44:56 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/dest.c,v 1.56 2003/05/06 00:20:33 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -46,7 +46,7 @@ donothingReceive(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
|
||||
|
||||
static void
|
||||
donothingSetup(DestReceiver *self, int operation,
|
||||
const char *portalName, TupleDesc typeinfo)
|
||||
const char *portalName, TupleDesc typeinfo, List *targetlist)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.332 2003/05/05 00:44:56 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.333 2003/05/06 00:20:33 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* this is the "main" module of the postgres backend and
|
||||
@ -1460,7 +1460,15 @@ exec_describe_portal_message(const char *portal_name)
|
||||
return; /* can't actually do anything... */
|
||||
|
||||
if (portal->tupDesc)
|
||||
SendRowDescriptionMessage(portal->tupDesc);
|
||||
{
|
||||
List *targetlist;
|
||||
|
||||
if (portal->strategy == PORTAL_ONE_SELECT)
|
||||
targetlist = ((Plan *) lfirst(portal->planTrees))->targetlist;
|
||||
else
|
||||
targetlist = NIL;
|
||||
SendRowDescriptionMessage(portal->tupDesc, targetlist);
|
||||
}
|
||||
else
|
||||
pq_putemptymessage('n'); /* NoData */
|
||||
}
|
||||
@ -2335,7 +2343,7 @@ PostgresMain(int argc, char *argv[], const char *username)
|
||||
if (!IsUnderPostmaster)
|
||||
{
|
||||
puts("\nPOSTGRES backend interactive interface ");
|
||||
puts("$Revision: 1.332 $ $Date: 2003/05/05 00:44:56 $\n");
|
||||
puts("$Revision: 1.333 $ $Date: 2003/05/06 00:20:33 $\n");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.60 2003/05/02 20:54:35 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.61 2003/05/06 00:20:33 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -136,7 +136,7 @@ ProcessQuery(Query *parsetree,
|
||||
/*
|
||||
* Call ExecStart to prepare the plan for execution
|
||||
*/
|
||||
ExecutorStart(queryDesc);
|
||||
ExecutorStart(queryDesc, false);
|
||||
|
||||
/*
|
||||
* Run the plan to completion.
|
||||
@ -256,7 +256,7 @@ PortalStart(Portal portal, ParamListInfo params)
|
||||
/*
|
||||
* Call ExecStart to prepare the plan for execution
|
||||
*/
|
||||
ExecutorStart(queryDesc);
|
||||
ExecutorStart(queryDesc, false);
|
||||
/*
|
||||
* This tells PortalCleanup to shut down the executor
|
||||
*/
|
||||
@ -571,10 +571,18 @@ RunFromStore(Portal portal, ScanDirection direction, long count,
|
||||
CommandDest dest)
|
||||
{
|
||||
DestReceiver *destfunc;
|
||||
List *targetlist;
|
||||
long current_tuple_count = 0;
|
||||
|
||||
destfunc = DestToFunction(dest);
|
||||
(*destfunc->setup) (destfunc, CMD_SELECT, portal->name, portal->tupDesc);
|
||||
|
||||
if (portal->strategy == PORTAL_ONE_SELECT)
|
||||
targetlist = ((Plan *) lfirst(portal->planTrees))->targetlist;
|
||||
else
|
||||
targetlist = NIL;
|
||||
|
||||
(*destfunc->setup) (destfunc, CMD_SELECT, portal->name, portal->tupDesc,
|
||||
targetlist);
|
||||
|
||||
if (direction == NoMovementScanDirection)
|
||||
{
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: printtup.h,v 1.24 2003/05/05 00:44:56 tgl Exp $
|
||||
* $Id: printtup.h,v 1.25 2003/05/06 00:20:33 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -18,16 +18,16 @@
|
||||
|
||||
extern DestReceiver *printtup_create_DR(bool isBinary, bool sendDescrip);
|
||||
|
||||
extern void SendRowDescriptionMessage(TupleDesc typeinfo);
|
||||
extern void SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist);
|
||||
|
||||
extern void debugSetup(DestReceiver *self, int operation,
|
||||
const char *portalName, TupleDesc typeinfo);
|
||||
const char *portalName, TupleDesc typeinfo, List *targetlist);
|
||||
extern void debugtup(HeapTuple tuple, TupleDesc typeinfo,
|
||||
DestReceiver *self);
|
||||
|
||||
/* XXX these are really in executor/spi.c */
|
||||
extern void spi_dest_setup(DestReceiver *self, int operation,
|
||||
const char *portalName, TupleDesc typeinfo);
|
||||
const char *portalName, TupleDesc typeinfo, List *targetlist);
|
||||
extern void spi_printtup(HeapTuple tuple, TupleDesc tupdesc,
|
||||
DestReceiver *self);
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: catversion.h,v 1.185 2003/05/02 20:54:35 tgl Exp $
|
||||
* $Id: catversion.h,v 1.186 2003/05/06 00:20:33 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -53,6 +53,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 200305011
|
||||
#define CATALOG_VERSION_NO 200305051
|
||||
|
||||
#endif
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: executor.h,v 1.92 2003/05/05 17:57:47 tgl Exp $
|
||||
* $Id: executor.h,v 1.93 2003/05/06 00:20:33 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -82,7 +82,7 @@ extern HeapTuple ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot);
|
||||
/*
|
||||
* prototypes from functions in execMain.c
|
||||
*/
|
||||
extern void ExecutorStart(QueryDesc *queryDesc);
|
||||
extern void ExecutorStart(QueryDesc *queryDesc, bool explainOnly);
|
||||
extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc,
|
||||
ScanDirection direction, long count);
|
||||
extern void ExecutorEnd(QueryDesc *queryDesc);
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: plannodes.h,v 1.64 2003/02/09 00:30:40 tgl Exp $
|
||||
* $Id: plannodes.h,v 1.65 2003/05/06 00:20:33 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -278,7 +278,9 @@ typedef struct Material
|
||||
typedef struct Sort
|
||||
{
|
||||
Plan plan;
|
||||
int keycount;
|
||||
int numCols; /* number of sort-key columns */
|
||||
AttrNumber *sortColIdx; /* their indexes in the target list */
|
||||
Oid *sortOperators; /* OIDs of operators to sort them by */
|
||||
} Sort;
|
||||
|
||||
/* ---------------
|
||||
|
@ -10,7 +10,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: primnodes.h,v 1.81 2003/04/08 23:20:04 tgl Exp $
|
||||
* $Id: primnodes.h,v 1.82 2003/05/06 00:20:33 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -30,7 +30,16 @@
|
||||
* Resdom (Result Domain)
|
||||
*
|
||||
* Notes:
|
||||
* ressortgroupref is the parse/plan-time representation of ORDER BY and
|
||||
*
|
||||
* resno will normally be equal to the item's position in a targetlist,
|
||||
* but the code generally tries to avoid relying on that (eg, we avoid
|
||||
* using "nth()" rather than a search to find an item by resno).
|
||||
*
|
||||
* resname will be null if no name can easily be assigned to the column.
|
||||
* But it should never be null for user-visible columns (i.e., non-junk
|
||||
* columns in a toplevel targetlist).
|
||||
*
|
||||
* ressortgroupref is used in the representation of ORDER BY and
|
||||
* GROUP BY items. Targetlist entries with ressortgroupref=0 are not
|
||||
* sort/group items. If ressortgroupref>0, then this item is an ORDER BY or
|
||||
* GROUP BY value. No two entries in a targetlist may have the same nonzero
|
||||
@ -39,27 +48,25 @@
|
||||
* ressortgroupref means a more significant sort key.) The order of the
|
||||
* associated SortClause or GroupClause lists determine the semantics.
|
||||
*
|
||||
* reskey and reskeyop are the execution-time representation of sorting.
|
||||
* reskey must be zero in any non-sort-key item. The reskey of sort key
|
||||
* targetlist items for a sort plan node is 1,2,...,n for the n sort keys.
|
||||
* The reskeyop of each such targetlist item is the sort operator's OID.
|
||||
* reskeyop will be zero in non-sort-key items.
|
||||
* resorigtbl/resorigcol identify the source of the column, if it is a
|
||||
* simple reference to a column of a base table (or view). If it is not
|
||||
* a simple reference, these fields are zeroes.
|
||||
*
|
||||
* Both reskey and reskeyop are typically zero during parse/plan stages.
|
||||
* The executor does not pay any attention to ressortgroupref.
|
||||
* If resjunk is true then the column is a working column (such as a sort key)
|
||||
* that should be removed from the final output of the query.
|
||||
*--------------------
|
||||
*/
|
||||
typedef struct Resdom
|
||||
{
|
||||
NodeTag type;
|
||||
AttrNumber resno; /* attribute number */
|
||||
AttrNumber resno; /* attribute number (1..N) */
|
||||
Oid restype; /* type of the value */
|
||||
int32 restypmod; /* type-specific modifier of the value */
|
||||
char *resname; /* name of the resdom (could be NULL) */
|
||||
Index ressortgroupref;
|
||||
/* nonzero if referenced by a sort/group clause */
|
||||
Index reskey; /* order of key in a sort (for those > 0) */
|
||||
Oid reskeyop; /* sort operator's Oid */
|
||||
char *resname; /* name of the column (could be NULL) */
|
||||
Index ressortgroupref; /* nonzero if referenced by a
|
||||
* sort/group clause */
|
||||
Oid resorigtbl; /* OID of column's source table */
|
||||
AttrNumber resorigcol; /* column's number in source table */
|
||||
bool resjunk; /* set to true to eliminate the attribute
|
||||
* from final target list */
|
||||
} Resdom;
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: planmain.h,v 1.69 2003/03/10 03:53:52 tgl Exp $
|
||||
* $Id: planmain.h,v 1.70 2003/05/06 00:20:33 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -30,10 +30,10 @@ extern Plan *create_plan(Query *root, Path *best_path);
|
||||
extern SubqueryScan *make_subqueryscan(List *qptlist, List *qpqual,
|
||||
Index scanrelid, Plan *subplan);
|
||||
extern Append *make_append(List *appendplans, bool isTarget, List *tlist);
|
||||
extern Sort *make_sort(Query *root, List *tlist,
|
||||
Plan *lefttree, int keycount);
|
||||
extern Sort *make_sort_from_sortclauses(Query *root, List *tlist,
|
||||
Plan *lefttree, List *sortcls);
|
||||
extern Sort *make_sort_from_groupcols(Query *root, List *groupcls,
|
||||
AttrNumber *grpColIdx, Plan *lefttree);
|
||||
extern Agg *make_agg(Query *root, List *tlist, List *qual,
|
||||
AggStrategy aggstrategy,
|
||||
int numGroupCols, AttrNumber *grpColIdx,
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: tlist.h,v 1.34 2003/02/15 20:12:41 tgl Exp $
|
||||
* $Id: tlist.h,v 1.35 2003/05/06 00:20:33 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -22,7 +22,6 @@ extern Resdom *tlist_member(Node *node, List *targetlist);
|
||||
extern void add_var_to_tlist(RelOptInfo *rel, Var *var);
|
||||
extern TargetEntry *create_tl_element(Var *var, int resdomno);
|
||||
|
||||
extern List *new_unsorted_tlist(List *targetlist);
|
||||
extern List *flatten_tlist(List *tlist);
|
||||
extern List *add_to_flat_tlist(List *tlist, List *vars);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: parse_target.h,v 1.29 2003/02/13 05:53:46 momjian Exp $
|
||||
* $Id: parse_target.h,v 1.30 2003/05/06 00:20:33 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -18,6 +18,7 @@
|
||||
|
||||
|
||||
extern List *transformTargetList(ParseState *pstate, List *targetlist);
|
||||
extern void markTargetListOrigins(ParseState *pstate, List *targetlist);
|
||||
extern TargetEntry *transformTargetEntry(ParseState *pstate,
|
||||
Node *node, Node *expr,
|
||||
char *colname, bool resjunk);
|
||||
|
@ -44,7 +44,7 @@
|
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: dest.h,v 1.35 2003/05/05 00:44:56 tgl Exp $
|
||||
* $Id: dest.h,v 1.36 2003/05/06 00:20:33 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -92,10 +92,12 @@ struct _DestReceiver
|
||||
{
|
||||
/* Called for each tuple to be output: */
|
||||
void (*receiveTuple) (HeapTuple tuple, TupleDesc typeinfo,
|
||||
DestReceiver *self);
|
||||
DestReceiver *self);
|
||||
/* Initialization and teardown: */
|
||||
void (*setup) (DestReceiver *self, int operation,
|
||||
const char *portalName, TupleDesc typeinfo);
|
||||
const char *portalName,
|
||||
TupleDesc typeinfo,
|
||||
List *targetlist);
|
||||
void (*cleanup) (DestReceiver *self);
|
||||
/* Private fields might appear beyond this point... */
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user