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:
Tom Lane 2003-05-06 00:20:33 +00:00
parent 94a3c60324
commit 2cf57c8f8d
32 changed files with 454 additions and 336 deletions

View File

@ -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

View File

@ -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");

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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.
*/

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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();

View File

@ -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 *

View File

@ -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().

View File

@ -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)

View File

@ -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.

View File

@ -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);

View File

@ -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

View File

@ -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)
{
}

View File

@ -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");
}
/*

View File

@ -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)
{

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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;
/* ---------------

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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... */
};