Commit 2cf57c8f authored by Tom Lane's avatar Tom Lane

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.
parent 94a3c603
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 @@ ...@@ -23,7 +23,7 @@
static void printtup_setup(DestReceiver *self, int operation, 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(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self);
static void printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self); static void printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self);
static void printtup_cleanup(DestReceiver *self); static void printtup_cleanup(DestReceiver *self);
...@@ -78,7 +78,7 @@ printtup_create_DR(bool isBinary, bool sendDescrip) ...@@ -78,7 +78,7 @@ printtup_create_DR(bool isBinary, bool sendDescrip)
static void static void
printtup_setup(DestReceiver *self, int operation, printtup_setup(DestReceiver *self, int operation,
const char *portalName, TupleDesc typeinfo) const char *portalName, TupleDesc typeinfo, List *targetlist)
{ {
DR_printtup *myState = (DR_printtup *) self; DR_printtup *myState = (DR_printtup *) self;
...@@ -100,7 +100,7 @@ printtup_setup(DestReceiver *self, int operation, ...@@ -100,7 +100,7 @@ printtup_setup(DestReceiver *self, int operation,
* then we send back the tuple descriptor of the tuples. * then we send back the tuple descriptor of the tuples.
*/ */
if (operation == CMD_SELECT && myState->sendDescrip) 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 * 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, ...@@ -116,9 +116,15 @@ printtup_setup(DestReceiver *self, int operation,
/* /*
* SendRowDescriptionMessage --- send a RowDescription message to the frontend * 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 void
SendRowDescriptionMessage(TupleDesc typeinfo) SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist)
{ {
Form_pg_attribute *attrs = typeinfo->attrs; Form_pg_attribute *attrs = typeinfo->attrs;
int natts = typeinfo->natts; int natts = typeinfo->natts;
...@@ -135,10 +141,25 @@ SendRowDescriptionMessage(TupleDesc typeinfo) ...@@ -135,10 +141,25 @@ SendRowDescriptionMessage(TupleDesc typeinfo)
/* column ID info appears in protocol 3.0 and up */ /* column ID info appears in protocol 3.0 and up */
if (proto >= 3) if (proto >= 3)
{ {
/* XXX not yet implemented, send zeroes */ /* 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, 4);
pq_sendint(&buf, 0, 2); pq_sendint(&buf, 0, 2);
} }
}
pq_sendint(&buf, (int) attrs[i]->atttypid, pq_sendint(&buf, (int) attrs[i]->atttypid,
sizeof(attrs[i]->atttypid)); sizeof(attrs[i]->atttypid));
pq_sendint(&buf, attrs[i]->attlen, pq_sendint(&buf, attrs[i]->attlen,
...@@ -324,7 +345,7 @@ showatts(const char *name, TupleDesc tupleDesc) ...@@ -324,7 +345,7 @@ showatts(const char *name, TupleDesc tupleDesc)
*/ */
void void
debugSetup(DestReceiver *self, int operation, debugSetup(DestReceiver *self, int operation,
const char *portalName, TupleDesc typeinfo) const char *portalName, TupleDesc typeinfo, List *targetlist)
{ {
/* /*
* show the return type of the tuples * show the return type of the tuples
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994-5, Regents of the University of California * Portions Copyright (c) 1994-5, Regents of the University of California
* *
* IDENTIFICATION * 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,7 +57,8 @@ static void show_upper_qual(List *qual, const char *qlabel, ...@@ -57,7 +57,8 @@ static void show_upper_qual(List *qual, const char *qlabel,
const char *outer_name, int outer_varno, Plan *outer_plan, const char *outer_name, int outer_varno, Plan *outer_plan,
const char *inner_name, int inner_varno, Plan *inner_plan, const char *inner_name, int inner_varno, Plan *inner_plan,
StringInfo str, int indent, ExplainState *es); StringInfo str, int indent, ExplainState *es);
static void show_sort_keys(List *tlist, int nkeys, const char *qlabel, static void show_sort_keys(List *tlist, int nkeys, AttrNumber *keycols,
const char *qlabel,
StringInfo str, int indent, ExplainState *es); StringInfo str, int indent, ExplainState *es);
static Node *make_ors_ands_explicit(List *orclauses); static Node *make_ors_ands_explicit(List *orclauses);
...@@ -193,18 +194,10 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt, ...@@ -193,18 +194,10 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
ExplainState *es; ExplainState *es;
StringInfo str; 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); gettimeofday(&starttime, NULL);
/* call ExecutorStart to prepare the plan for execution */ /* call ExecutorStart to prepare the plan for execution */
ExecutorStart(queryDesc); ExecutorStart(queryDesc, !stmt->analyze);
/* Execute the plan for statistics if asked for */ /* Execute the plan for statistics if asked for */
if (stmt->analyze) if (stmt->analyze)
...@@ -672,7 +665,9 @@ explain_outNode(StringInfo str, ...@@ -672,7 +665,9 @@ explain_outNode(StringInfo str,
str, indent, es); str, indent, es);
break; break;
case T_Sort: case T_Sort:
show_sort_keys(plan->targetlist, ((Sort *) plan)->keycount, show_sort_keys(plan->targetlist,
((Sort *) plan)->numCols,
((Sort *) plan)->sortColIdx,
"Sort Key", "Sort Key",
str, indent, es); str, indent, es);
break; break;
...@@ -937,7 +932,8 @@ show_upper_qual(List *qual, const char *qlabel, ...@@ -937,7 +932,8 @@ show_upper_qual(List *qual, const char *qlabel,
* Show the sort keys for a Sort node. * Show the sort keys for a Sort node.
*/ */
static void 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) StringInfo str, int indent, ExplainState *es)
{ {
List *context; List *context;
...@@ -985,27 +981,30 @@ show_sort_keys(List *tlist, int nkeys, const char *qlabel, ...@@ -985,27 +981,30 @@ show_sort_keys(List *tlist, int nkeys, const char *qlabel,
} }
bms_free(varnos); bms_free(varnos);
for (keyno = 1; keyno <= nkeys; keyno++) for (keyno = 0; keyno < nkeys; keyno++)
{ {
/* find key expression in tlist */ /* find key expression in tlist */
AttrNumber keyresno = keycols[keyno];
foreach(tl, tlist) foreach(tl, tlist)
{ {
TargetEntry *target = (TargetEntry *) lfirst(tl); TargetEntry *target = (TargetEntry *) lfirst(tl);
if (target->resdom->reskey == keyno) if (target->resdom->resno == keyresno)
{ {
/* Deparse the expression, showing any top-level cast */ /* Deparse the expression, showing any top-level cast */
exprstr = deparse_expression((Node *) target->expr, context, exprstr = deparse_expression((Node *) target->expr, context,
useprefix, true); useprefix, true);
/* And add to str */ /* And add to str */
if (keyno > 1) if (keyno > 0)
appendStringInfo(str, ", "); appendStringInfo(str, ", ");
appendStringInfo(str, "%s", exprstr); appendStringInfo(str, "%s", exprstr);
break; break;
} }
} }
if (tl == NIL) 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"); appendStringInfo(str, "\n");
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* *
* *
* IDENTIFICATION * 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 ...@@ -63,7 +63,7 @@ typedef struct evalPlanQual
} evalPlanQual; } evalPlanQual;
/* decls for local routines only used within this module */ /* 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, static void initResultRelInfo(ResultRelInfo *resultRelInfo,
Index resultRelationIndex, Index resultRelationIndex,
List *rangeTable, List *rangeTable,
...@@ -104,12 +104,15 @@ static void EvalPlanQualStop(evalPlanQual *epq); ...@@ -104,12 +104,15 @@ static void EvalPlanQualStop(evalPlanQual *epq);
* field of the QueryDesc is filled in to describe the tuples that will be * 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. * 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 * NB: the CurrentMemoryContext when this is called will become the parent
* of the per-query context used for this Executor invocation. * of the per-query context used for this Executor invocation.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecutorStart(QueryDesc *queryDesc) ExecutorStart(QueryDesc *queryDesc, bool explainOnly)
{ {
EState *estate; EState *estate;
MemoryContext oldcontext; MemoryContext oldcontext;
...@@ -118,6 +121,13 @@ ExecutorStart(QueryDesc *queryDesc) ...@@ -118,6 +121,13 @@ ExecutorStart(QueryDesc *queryDesc)
Assert(queryDesc != NULL); Assert(queryDesc != NULL);
Assert(queryDesc->estate == 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. * Build EState, switch into per-query memory context for startup.
*/ */
...@@ -149,7 +159,7 @@ ExecutorStart(QueryDesc *queryDesc) ...@@ -149,7 +159,7 @@ ExecutorStart(QueryDesc *queryDesc)
/* /*
* Initialize the plan state tree * Initialize the plan state tree
*/ */
InitPlan(queryDesc); InitPlan(queryDesc, explainOnly);
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
} }
...@@ -202,14 +212,6 @@ ExecutorRun(QueryDesc *queryDesc, ...@@ -202,14 +212,6 @@ ExecutorRun(QueryDesc *queryDesc,
operation = queryDesc->operation; operation = queryDesc->operation;
dest = queryDesc->dest; 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 * startup tuple receiver
*/ */
...@@ -217,8 +219,10 @@ ExecutorRun(QueryDesc *queryDesc, ...@@ -217,8 +219,10 @@ ExecutorRun(QueryDesc *queryDesc,
estate->es_lastoid = InvalidOid; estate->es_lastoid = InvalidOid;
destfunc = DestToFunction(dest); destfunc = DestToFunction(dest);
(*destfunc->setup) (destfunc, operation, queryDesc->portalName, (*destfunc->setup) (destfunc, operation,
queryDesc->tupDesc); queryDesc->portalName,
queryDesc->tupDesc,
queryDesc->planstate->plan->targetlist);
/* /*
* run plan * run plan
...@@ -468,7 +472,7 @@ fail: ...@@ -468,7 +472,7 @@ fail:
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static void static void
InitPlan(QueryDesc *queryDesc) InitPlan(QueryDesc *queryDesc, bool explainOnly)
{ {
CmdType operation = queryDesc->operation; CmdType operation = queryDesc->operation;
Query *parseTree = queryDesc->parsetree; Query *parseTree = queryDesc->parsetree;
...@@ -751,10 +755,12 @@ InitPlan(QueryDesc *queryDesc) ...@@ -751,10 +755,12 @@ InitPlan(QueryDesc *queryDesc)
* If doing SELECT INTO, initialize the "into" relation. We must wait * If doing SELECT INTO, initialize the "into" relation. We must wait
* till now so we have the "clean" result tuple type to create the * till now so we have the "clean" result tuple type to create the
* new table from. * new table from.
*
* If EXPLAIN, skip creating the "into" relation.
*/ */
intoRelationDesc = (Relation) NULL; intoRelationDesc = (Relation) NULL;
if (do_select_into) if (do_select_into && !explainOnly)
{ {
char *intoName; char *intoName;
Oid namespaceId; Oid namespaceId;
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -723,7 +723,7 @@ begin_tup_output_tupdesc(CommandDest dest, TupleDesc tupdesc)
tstate->destfunc = DestToFunction(dest); tstate->destfunc = DestToFunction(dest);
(*tstate->destfunc->setup) (tstate->destfunc, (int) CMD_SELECT, (*tstate->destfunc->setup) (tstate->destfunc, (int) CMD_SELECT,
NULL, tupdesc); NULL, tupdesc, NIL);
return tstate; return tstate;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -250,7 +250,7 @@ postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
/* Utility commands don't need Executor. */ /* Utility commands don't need Executor. */
if (es->qd->operation != CMD_UTILITY) if (es->qd->operation != CMD_UTILITY)
ExecutorStart(es->qd); ExecutorStart(es->qd, false);
es->status = F_EXEC_RUN; es->status = F_EXEC_RUN;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -19,59 +19,6 @@
#include "executor/nodeSort.h" #include "executor/nodeSort.h"
#include "utils/tuplesort.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 * ExecSort
...@@ -118,8 +65,6 @@ ExecSort(SortState *node) ...@@ -118,8 +65,6 @@ ExecSort(SortState *node)
Sort *plannode = (Sort *) node->ss.ps.plan; Sort *plannode = (Sort *) node->ss.ps.plan;
PlanState *outerNode; PlanState *outerNode;
TupleDesc tupDesc; TupleDesc tupDesc;
Oid *sortOperators;
AttrNumber *attNums;
SO1_printf("ExecSort: %s\n", SO1_printf("ExecSort: %s\n",
"sorting subplan"); "sorting subplan");
...@@ -139,16 +84,13 @@ ExecSort(SortState *node) ...@@ -139,16 +84,13 @@ ExecSort(SortState *node)
outerNode = outerPlanState(node); outerNode = outerPlanState(node);
tupDesc = ExecGetResultType(outerNode); tupDesc = ExecGetResultType(outerNode);
ExtractSortKeys(plannode, &sortOperators, &attNums); tuplesortstate = tuplesort_begin_heap(tupDesc,
plannode->numCols,
tuplesortstate = tuplesort_begin_heap(tupDesc, plannode->keycount, plannode->sortOperators,
sortOperators, attNums, plannode->sortColIdx,
true /* randomAccess */ ); true /* randomAccess */ );
node->tuplesortstate = (void *) tuplesortstate; node->tuplesortstate = (void *) tuplesortstate;
pfree(sortOperators);
pfree(attNums);
/* /*
* Scan the subplan and feed all the tuples to tuplesort. * Scan the subplan and feed all the tuples to tuplesort.
*/ */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -880,7 +880,7 @@ SPI_cursor_close(Portal portal)
*/ */
void void
spi_dest_setup(DestReceiver *self, int operation, spi_dest_setup(DestReceiver *self, int operation,
const char *portalName, TupleDesc typeinfo) const char *portalName, TupleDesc typeinfo, List *targetlist)
{ {
SPITupleTable *tuptable; SPITupleTable *tuptable;
MemoryContext oldcxt; MemoryContext oldcxt;
...@@ -1209,7 +1209,7 @@ _SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount) ...@@ -1209,7 +1209,7 @@ _SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount)
ResetUsage(); ResetUsage();
#endif #endif
ExecutorStart(queryDesc); ExecutorStart(queryDesc, false);
ExecutorRun(queryDesc, ForwardScanDirection, (long) tcount); ExecutorRun(queryDesc, ForwardScanDirection, (long) tcount);
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 ...@@ -40,7 +40,8 @@ typedef struct
*/ */
static void static void
tstoreSetupReceiver(DestReceiver *self, int operation, tstoreSetupReceiver(DestReceiver *self, int operation,
const char *portalname, TupleDesc typeinfo) const char *portalname,
TupleDesc typeinfo, List *targetlist)
{ {
TStoreState *myState = (TStoreState *) self; TStoreState *myState = (TStoreState *) self;
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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) ...@@ -448,7 +448,9 @@ _copySort(Sort *from)
*/ */
CopyPlanFields((Plan *) from, (Plan *) newnode); 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; return newnode;
} }
...@@ -596,8 +598,8 @@ _copyResdom(Resdom *from) ...@@ -596,8 +598,8 @@ _copyResdom(Resdom *from)
COPY_SCALAR_FIELD(restypmod); COPY_SCALAR_FIELD(restypmod);
COPY_STRING_FIELD(resname); COPY_STRING_FIELD(resname);
COPY_SCALAR_FIELD(ressortgroupref); COPY_SCALAR_FIELD(ressortgroupref);
COPY_SCALAR_FIELD(reskey); COPY_SCALAR_FIELD(resorigtbl);
COPY_SCALAR_FIELD(reskeyop); COPY_SCALAR_FIELD(resorigcol);
COPY_SCALAR_FIELD(resjunk); COPY_SCALAR_FIELD(resjunk);
return newnode; return newnode;
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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) ...@@ -104,8 +104,8 @@ _equalResdom(Resdom *a, Resdom *b)
COMPARE_SCALAR_FIELD(restypmod); COMPARE_SCALAR_FIELD(restypmod);
COMPARE_STRING_FIELD(resname); COMPARE_STRING_FIELD(resname);
COMPARE_SCALAR_FIELD(ressortgroupref); COMPARE_SCALAR_FIELD(ressortgroupref);
COMPARE_SCALAR_FIELD(reskey); COMPARE_SCALAR_FIELD(resorigtbl);
COMPARE_SCALAR_FIELD(reskeyop); COMPARE_SCALAR_FIELD(resorigcol);
COMPARE_SCALAR_FIELD(resjunk); COMPARE_SCALAR_FIELD(resjunk);
return true; return true;
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -117,16 +117,16 @@ makeResdom(AttrNumber resno,
resdom->resname = resname; resdom->resname = resname;
/* /*
* We always set the sorting/grouping fields to 0. If the caller * We always set these fields to 0. If the caller wants to change them
* wants to change them he must do so explicitly. Few if any callers * he must do so explicitly. Few callers do that, so omitting these
* should be doing that, so omitting these arguments reduces the * arguments reduces the chance of error.
* chance of error.
*/ */
resdom->ressortgroupref = 0; resdom->ressortgroupref = 0;
resdom->reskey = 0; resdom->resorigtbl = InvalidOid;
resdom->reskeyop = InvalidOid; resdom->resorigcol = 0;
resdom->resjunk = resjunk; resdom->resjunk = resjunk;
return resdom; return resdom;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* Every node type that can appear in stored rules' parsetrees *must* * Every node type that can appear in stored rules' parsetrees *must*
...@@ -420,11 +420,17 @@ _outAgg(StringInfo str, Agg *node) ...@@ -420,11 +420,17 @@ _outAgg(StringInfo str, Agg *node)
static void static void
_outGroup(StringInfo str, Group *node) _outGroup(StringInfo str, Group *node)
{ {
WRITE_NODE_TYPE("GRP"); int i;
WRITE_NODE_TYPE("GROUP");
_outPlanInfo(str, (Plan *) node); _outPlanInfo(str, (Plan *) node);
WRITE_INT_FIELD(numCols); WRITE_INT_FIELD(numCols);
appendStringInfo(str, " :grpColIdx");
for (i = 0; i < node->numCols; i++)
appendStringInfo(str, " %d", node->grpColIdx[i]);
} }
static void static void
...@@ -438,11 +444,21 @@ _outMaterial(StringInfo str, Material *node) ...@@ -438,11 +444,21 @@ _outMaterial(StringInfo str, Material *node)
static void static void
_outSort(StringInfo str, Sort *node) _outSort(StringInfo str, Sort *node)
{ {
int i;
WRITE_NODE_TYPE("SORT"); WRITE_NODE_TYPE("SORT");
_outPlanInfo(str, (Plan *) node); _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 static void
...@@ -517,8 +533,8 @@ _outResdom(StringInfo str, Resdom *node) ...@@ -517,8 +533,8 @@ _outResdom(StringInfo str, Resdom *node)
WRITE_INT_FIELD(restypmod); WRITE_INT_FIELD(restypmod);
WRITE_STRING_FIELD(resname); WRITE_STRING_FIELD(resname);
WRITE_UINT_FIELD(ressortgroupref); WRITE_UINT_FIELD(ressortgroupref);
WRITE_UINT_FIELD(reskey); WRITE_OID_FIELD(resorigtbl);
WRITE_OID_FIELD(reskeyop); WRITE_INT_FIELD(resorigcol);
WRITE_BOOL_FIELD(resjunk); WRITE_BOOL_FIELD(resjunk);
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -447,8 +447,8 @@ print_tl(List *tlist, List *rtable) ...@@ -447,8 +447,8 @@ print_tl(List *tlist, List *rtable)
TargetEntry *tle = lfirst(tl); TargetEntry *tle = lfirst(tl);
printf("\t%d %s\t", tle->resdom->resno, tle->resdom->resname); printf("\t%d %s\t", tle->resdom->resno, tle->resdom->resname);
if (tle->resdom->reskey != 0) if (tle->resdom->ressortgroupref != 0)
printf("(%d):\t", tle->resdom->reskey); printf("(%u):\t", tle->resdom->ressortgroupref);
else else
printf(" :\t"); printf(" :\t");
print_expr((Node *) tle->expr, rtable); print_expr((Node *) tle->expr, rtable);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* Path and Plan nodes do not have any readfuncs support, because we * Path and Plan nodes do not have any readfuncs support, because we
...@@ -310,8 +310,8 @@ _readResdom(void) ...@@ -310,8 +310,8 @@ _readResdom(void)
READ_INT_FIELD(restypmod); READ_INT_FIELD(restypmod);
READ_STRING_FIELD(resname); READ_STRING_FIELD(resname);
READ_UINT_FIELD(ressortgroupref); READ_UINT_FIELD(ressortgroupref);
READ_UINT_FIELD(reskey); READ_OID_FIELD(resorigtbl);
READ_OID_FIELD(reskeyop); READ_INT_FIELD(resorigcol);
READ_BOOL_FIELD(resjunk); READ_BOOL_FIELD(resjunk);
READ_DONE(); READ_DONE();
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -61,10 +61,6 @@ static void locate_grouping_columns(Query *parse,
List *tlist, List *tlist,
List *sub_tlist, List *sub_tlist,
AttrNumber *groupColIdx); 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); static List *postprocess_setop_tlist(List *new_tlist, List *orig_tlist);
...@@ -1145,7 +1141,8 @@ grouping_planner(Query *parse, double tuple_fraction) ...@@ -1145,7 +1141,8 @@ grouping_planner(Query *parse, double tuple_fraction)
{ {
if (!pathkeys_contained_in(group_pathkeys, current_pathkeys)) if (!pathkeys_contained_in(group_pathkeys, current_pathkeys))
{ {
result_plan = make_groupsortplan(parse, result_plan = (Plan *)
make_sort_from_groupcols(parse,
parse->groupClause, parse->groupClause,
groupColIdx, groupColIdx,
result_plan); result_plan);
...@@ -1193,7 +1190,8 @@ grouping_planner(Query *parse, double tuple_fraction) ...@@ -1193,7 +1190,8 @@ grouping_planner(Query *parse, double tuple_fraction)
*/ */
if (!pathkeys_contained_in(group_pathkeys, current_pathkeys)) if (!pathkeys_contained_in(group_pathkeys, current_pathkeys))
{ {
result_plan = make_groupsortplan(parse, result_plan = (Plan *)
make_sort_from_groupcols(parse,
parse->groupClause, parse->groupClause,
groupColIdx, groupColIdx,
result_plan); result_plan);
...@@ -1219,7 +1217,8 @@ grouping_planner(Query *parse, double tuple_fraction) ...@@ -1219,7 +1217,8 @@ grouping_planner(Query *parse, double tuple_fraction)
{ {
if (!pathkeys_contained_in(sort_pathkeys, current_pathkeys)) if (!pathkeys_contained_in(sort_pathkeys, current_pathkeys))
{ {
result_plan = (Plan *) make_sort_from_sortclauses(parse, result_plan = (Plan *)
make_sort_from_sortclauses(parse,
tlist, tlist,
result_plan, result_plan,
parse->sortClause); parse->sortClause);
...@@ -1471,53 +1470,6 @@ locate_grouping_columns(Query *parse, ...@@ -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 * postprocess_setop_tlist
* Fix up targetlist returned by plan_set_operations(). * Fix up targetlist returned by plan_set_operations().
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -238,7 +238,7 @@ generate_union_plan(SetOperationStmt *op, Query *parse,
{ {
List *sortList; List *sortList;
tlist = new_unsorted_tlist(tlist); tlist = copyObject(tlist);
sortList = addAllTargetsToSortList(NIL, tlist); sortList = addAllTargetsToSortList(NIL, tlist);
plan = (Plan *) make_sort_from_sortclauses(parse, tlist, plan = (Plan *) make_sort_from_sortclauses(parse, tlist,
plan, sortList); plan, sortList);
...@@ -292,7 +292,7 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse, ...@@ -292,7 +292,7 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse,
* Sort the child results, then add a SetOp plan node to generate the * Sort the child results, then add a SetOp plan node to generate the
* correct output. * correct output.
*/ */
tlist = new_unsorted_tlist(tlist); tlist = copyObject(tlist);
sortList = addAllTargetsToSortList(NIL, tlist); sortList = addAllTargetsToSortList(NIL, tlist);
plan = (Plan *) make_sort_from_sortclauses(parse, tlist, plan, sortList); plan = (Plan *) make_sort_from_sortclauses(parse, tlist, plan, sortList);
switch (op->op) switch (op->op)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -117,32 +117,6 @@ create_tl_element(Var *var, int resdomno)
* ---------- GENERAL target list routines ---------- * ---------- 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 * flatten_tlist
* Create a target list that only contains unique variables. * Create a target list that only contains unique variables.
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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) ...@@ -1747,6 +1747,9 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
if (stmt->intoColNames) if (stmt->intoColNames)
applyColumnNames(qry->targetList, stmt->intoColNames); applyColumnNames(qry->targetList, stmt->intoColNames);
/* mark column origins */
markTargetListOrigins(pstate, qry->targetList);
/* transform WHERE */ /* transform WHERE */
qual = transformWhereClause(pstate, stmt->whereClause); qual = transformWhereClause(pstate, stmt->whereClause);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -26,6 +26,7 @@
#include "utils/builtins.h" #include "utils/builtins.h"
static void markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var);
static List *ExpandAllTables(ParseState *pstate); static List *ExpandAllTables(ParseState *pstate);
static char *FigureColname(Node *node); static char *FigureColname(Node *node);
static int FigureColnameInternal(Node *node, char **name); static int FigureColnameInternal(Node *node, char **name);
...@@ -204,6 +205,94 @@ transformTargetList(ParseState *pstate, List *targetlist) ...@@ -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() * updateTargetListEntry()
* This is used in INSERT and UPDATE statements only. It prepares a * This is used in INSERT and UPDATE statements only. It prepares a
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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) ...@@ -46,7 +46,7 @@ donothingReceive(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
static void static void
donothingSetup(DestReceiver *self, int operation, donothingSetup(DestReceiver *self, int operation,
const char *portalName, TupleDesc typeinfo) const char *portalName, TupleDesc typeinfo, List *targetlist)
{ {
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* this is the "main" module of the postgres backend and * this is the "main" module of the postgres backend and
...@@ -1460,7 +1460,15 @@ exec_describe_portal_message(const char *portal_name) ...@@ -1460,7 +1460,15 @@ exec_describe_portal_message(const char *portal_name)
return; /* can't actually do anything... */ return; /* can't actually do anything... */
if (portal->tupDesc) 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 else
pq_putemptymessage('n'); /* NoData */ pq_putemptymessage('n'); /* NoData */
} }
...@@ -2335,7 +2343,7 @@ PostgresMain(int argc, char *argv[], const char *username) ...@@ -2335,7 +2343,7 @@ PostgresMain(int argc, char *argv[], const char *username)
if (!IsUnderPostmaster) if (!IsUnderPostmaster)
{ {
puts("\nPOSTGRES backend interactive interface "); 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 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -136,7 +136,7 @@ ProcessQuery(Query *parsetree,
/* /*
* Call ExecStart to prepare the plan for execution * Call ExecStart to prepare the plan for execution
*/ */
ExecutorStart(queryDesc); ExecutorStart(queryDesc, false);
/* /*
* Run the plan to completion. * Run the plan to completion.
...@@ -256,7 +256,7 @@ PortalStart(Portal portal, ParamListInfo params) ...@@ -256,7 +256,7 @@ PortalStart(Portal portal, ParamListInfo params)
/* /*
* Call ExecStart to prepare the plan for execution * Call ExecStart to prepare the plan for execution
*/ */
ExecutorStart(queryDesc); ExecutorStart(queryDesc, false);
/* /*
* This tells PortalCleanup to shut down the executor * This tells PortalCleanup to shut down the executor
*/ */
...@@ -571,10 +571,18 @@ RunFromStore(Portal portal, ScanDirection direction, long count, ...@@ -571,10 +571,18 @@ RunFromStore(Portal portal, ScanDirection direction, long count,
CommandDest dest) CommandDest dest)
{ {
DestReceiver *destfunc; DestReceiver *destfunc;
List *targetlist;
long current_tuple_count = 0; long current_tuple_count = 0;
destfunc = DestToFunction(dest); 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) if (direction == NoMovementScanDirection)
{ {
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -18,16 +18,16 @@
extern DestReceiver *printtup_create_DR(bool isBinary, bool sendDescrip); 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, 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, extern void debugtup(HeapTuple tuple, TupleDesc typeinfo,
DestReceiver *self); DestReceiver *self);
/* XXX these are really in executor/spi.c */ /* XXX these are really in executor/spi.c */
extern void spi_dest_setup(DestReceiver *self, int operation, 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, extern void spi_printtup(HeapTuple tuple, TupleDesc tupdesc,
DestReceiver *self); DestReceiver *self);
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200305011 #define CATALOG_VERSION_NO 200305051
#endif #endif
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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); ...@@ -82,7 +82,7 @@ extern HeapTuple ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot);
/* /*
* prototypes from functions in execMain.c * prototypes from functions in execMain.c
*/ */
extern void ExecutorStart(QueryDesc *queryDesc); extern void ExecutorStart(QueryDesc *queryDesc, bool explainOnly);
extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc, extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc,
ScanDirection direction, long count); ScanDirection direction, long count);
extern void ExecutorEnd(QueryDesc *queryDesc); extern void ExecutorEnd(QueryDesc *queryDesc);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 ...@@ -278,7 +278,9 @@ typedef struct Material
typedef struct Sort typedef struct Sort
{ {
Plan plan; 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; } Sort;
/* --------------- /* ---------------
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -30,7 +30,16 @@
* Resdom (Result Domain) * Resdom (Result Domain)
* *
* Notes: * 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 * GROUP BY items. Targetlist entries with ressortgroupref=0 are not
* sort/group items. If ressortgroupref>0, then this item is an ORDER BY or * 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 * GROUP BY value. No two entries in a targetlist may have the same nonzero
...@@ -39,27 +48,25 @@ ...@@ -39,27 +48,25 @@
* ressortgroupref means a more significant sort key.) The order of the * ressortgroupref means a more significant sort key.) The order of the
* associated SortClause or GroupClause lists determine the semantics. * associated SortClause or GroupClause lists determine the semantics.
* *
* reskey and reskeyop are the execution-time representation of sorting. * resorigtbl/resorigcol identify the source of the column, if it is a
* reskey must be zero in any non-sort-key item. The reskey of sort key * simple reference to a column of a base table (or view). If it is not
* targetlist items for a sort plan node is 1,2,...,n for the n sort keys. * a simple reference, these fields are zeroes.
* The reskeyop of each such targetlist item is the sort operator's OID.
* reskeyop will be zero in non-sort-key items.
* *
* Both reskey and reskeyop are typically zero during parse/plan stages. * If resjunk is true then the column is a working column (such as a sort key)
* The executor does not pay any attention to ressortgroupref. * that should be removed from the final output of the query.
*-------------------- *--------------------
*/ */
typedef struct Resdom typedef struct Resdom
{ {
NodeTag type; NodeTag type;
AttrNumber resno; /* attribute number */ AttrNumber resno; /* attribute number (1..N) */
Oid restype; /* type of the value */ Oid restype; /* type of the value */
int32 restypmod; /* type-specific modifier of the value */ int32 restypmod; /* type-specific modifier of the value */
char *resname; /* name of the resdom (could be NULL) */ char *resname; /* name of the column (could be NULL) */
Index ressortgroupref; Index ressortgroupref; /* nonzero if referenced by a
/* nonzero if referenced by a sort/group clause */ * sort/group clause */
Index reskey; /* order of key in a sort (for those > 0) */ Oid resorigtbl; /* OID of column's source table */
Oid reskeyop; /* sort operator's Oid */ AttrNumber resorigcol; /* column's number in source table */
bool resjunk; /* set to true to eliminate the attribute bool resjunk; /* set to true to eliminate the attribute
* from final target list */ * from final target list */
} Resdom; } Resdom;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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); ...@@ -30,10 +30,10 @@ extern Plan *create_plan(Query *root, Path *best_path);
extern SubqueryScan *make_subqueryscan(List *qptlist, List *qpqual, extern SubqueryScan *make_subqueryscan(List *qptlist, List *qpqual,
Index scanrelid, Plan *subplan); Index scanrelid, Plan *subplan);
extern Append *make_append(List *appendplans, bool isTarget, List *tlist); 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, extern Sort *make_sort_from_sortclauses(Query *root, List *tlist,
Plan *lefttree, List *sortcls); 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, extern Agg *make_agg(Query *root, List *tlist, List *qual,
AggStrategy aggstrategy, AggStrategy aggstrategy,
int numGroupCols, AttrNumber *grpColIdx, int numGroupCols, AttrNumber *grpColIdx,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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); ...@@ -22,7 +22,6 @@ extern Resdom *tlist_member(Node *node, List *targetlist);
extern void add_var_to_tlist(RelOptInfo *rel, Var *var); extern void add_var_to_tlist(RelOptInfo *rel, Var *var);
extern TargetEntry *create_tl_element(Var *var, int resdomno); extern TargetEntry *create_tl_element(Var *var, int resdomno);
extern List *new_unsorted_tlist(List *targetlist);
extern List *flatten_tlist(List *tlist); extern List *flatten_tlist(List *tlist);
extern List *add_to_flat_tlist(List *tlist, List *vars); extern List *add_to_flat_tlist(List *tlist, List *vars);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -18,6 +18,7 @@
extern List *transformTargetList(ParseState *pstate, List *targetlist); extern List *transformTargetList(ParseState *pstate, List *targetlist);
extern void markTargetListOrigins(ParseState *pstate, List *targetlist);
extern TargetEntry *transformTargetEntry(ParseState *pstate, extern TargetEntry *transformTargetEntry(ParseState *pstate,
Node *node, Node *expr, Node *node, Node *expr,
char *colname, bool resjunk); char *colname, bool resjunk);
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -95,7 +95,9 @@ struct _DestReceiver ...@@ -95,7 +95,9 @@ struct _DestReceiver
DestReceiver *self); DestReceiver *self);
/* Initialization and teardown: */ /* Initialization and teardown: */
void (*setup) (DestReceiver *self, int operation, void (*setup) (DestReceiver *self, int operation,
const char *portalName, TupleDesc typeinfo); const char *portalName,
TupleDesc typeinfo,
List *targetlist);
void (*cleanup) (DestReceiver *self); void (*cleanup) (DestReceiver *self);
/* Private fields might appear beyond this point... */ /* Private fields might appear beyond this point... */
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment