Skip to content

Commit 2cf57c8

Browse files
committed
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.
1 parent 94a3c60 commit 2cf57c8

File tree

32 files changed

+454
-336
lines changed

32 files changed

+454
-336
lines changed

src/backend/access/common/printtup.c

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.68 2003/05/05 00:44:55 tgl Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.69 2003/05/06 00:20:31 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -23,7 +23,7 @@
2323

2424

2525
static void printtup_setup(DestReceiver *self, int operation,
26-
const char *portalName, TupleDesc typeinfo);
26+
const char *portalName, TupleDesc typeinfo, List *targetlist);
2727
static void printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self);
2828
static void printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self);
2929
static void printtup_cleanup(DestReceiver *self);
@@ -78,7 +78,7 @@ printtup_create_DR(bool isBinary, bool sendDescrip)
7878

7979
static void
8080
printtup_setup(DestReceiver *self, int operation,
81-
const char *portalName, TupleDesc typeinfo)
81+
const char *portalName, TupleDesc typeinfo, List *targetlist)
8282
{
8383
DR_printtup *myState = (DR_printtup *) self;
8484

@@ -100,7 +100,7 @@ printtup_setup(DestReceiver *self, int operation,
100100
* then we send back the tuple descriptor of the tuples.
101101
*/
102102
if (operation == CMD_SELECT && myState->sendDescrip)
103-
SendRowDescriptionMessage(typeinfo);
103+
SendRowDescriptionMessage(typeinfo, targetlist);
104104

105105
/* ----------------
106106
* 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,
116116

117117
/*
118118
* SendRowDescriptionMessage --- send a RowDescription message to the frontend
119+
*
120+
* Notes: the TupleDesc has typically been manufactured by ExecTypeFromTL()
121+
* or some similar function; it does not contain a full set of fields.
122+
* The targetlist will be NIL when executing a utility function that does
123+
* not have a plan. If the targetlist isn't NIL then it is a Plan node's
124+
* targetlist; it is up to us to ignore resjunk columns in it.
119125
*/
120126
void
121-
SendRowDescriptionMessage(TupleDesc typeinfo)
127+
SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist)
122128
{
123129
Form_pg_attribute *attrs = typeinfo->attrs;
124130
int natts = typeinfo->natts;
@@ -135,9 +141,24 @@ SendRowDescriptionMessage(TupleDesc typeinfo)
135141
/* column ID info appears in protocol 3.0 and up */
136142
if (proto >= 3)
137143
{
138-
/* XXX not yet implemented, send zeroes */
139-
pq_sendint(&buf, 0, 4);
140-
pq_sendint(&buf, 0, 2);
144+
/* Do we have a non-resjunk tlist item? */
145+
while (targetlist &&
146+
((TargetEntry *) lfirst(targetlist))->resdom->resjunk)
147+
targetlist = lnext(targetlist);
148+
if (targetlist)
149+
{
150+
Resdom *res = ((TargetEntry *) lfirst(targetlist))->resdom;
151+
152+
pq_sendint(&buf, res->resorigtbl, 4);
153+
pq_sendint(&buf, res->resorigcol, 2);
154+
targetlist = lnext(targetlist);
155+
}
156+
else
157+
{
158+
/* No info available, so send zeroes */
159+
pq_sendint(&buf, 0, 4);
160+
pq_sendint(&buf, 0, 2);
161+
}
141162
}
142163
pq_sendint(&buf, (int) attrs[i]->atttypid,
143164
sizeof(attrs[i]->atttypid));
@@ -324,7 +345,7 @@ showatts(const char *name, TupleDesc tupleDesc)
324345
*/
325346
void
326347
debugSetup(DestReceiver *self, int operation,
327-
const char *portalName, TupleDesc typeinfo)
348+
const char *portalName, TupleDesc typeinfo, List *targetlist)
328349
{
329350
/*
330351
* show the return type of the tuples

src/backend/commands/explain.c

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994-5, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.106 2003/04/24 21:16:42 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.107 2003/05/06 00:20:31 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -57,8 +57,9 @@ static void show_upper_qual(List *qual, const char *qlabel,
5757
const char *outer_name, int outer_varno, Plan *outer_plan,
5858
const char *inner_name, int inner_varno, Plan *inner_plan,
5959
StringInfo str, int indent, ExplainState *es);
60-
static void show_sort_keys(List *tlist, int nkeys, const char *qlabel,
61-
StringInfo str, int indent, ExplainState *es);
60+
static void show_sort_keys(List *tlist, int nkeys, AttrNumber *keycols,
61+
const char *qlabel,
62+
StringInfo str, int indent, ExplainState *es);
6263
static Node *make_ors_ands_explicit(List *orclauses);
6364

6465
/*
@@ -193,18 +194,10 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
193194
ExplainState *es;
194195
StringInfo str;
195196

196-
/*
197-
* If we are not going to execute, suppress any SELECT INTO marker.
198-
* Without this, ExecutorStart will create the INTO target table,
199-
* which we don't want.
200-
*/
201-
if (!stmt->analyze)
202-
queryDesc->parsetree->into = NULL;
203-
204197
gettimeofday(&starttime, NULL);
205198

206199
/* call ExecutorStart to prepare the plan for execution */
207-
ExecutorStart(queryDesc);
200+
ExecutorStart(queryDesc, !stmt->analyze);
208201

209202
/* Execute the plan for statistics if asked for */
210203
if (stmt->analyze)
@@ -672,7 +665,9 @@ explain_outNode(StringInfo str,
672665
str, indent, es);
673666
break;
674667
case T_Sort:
675-
show_sort_keys(plan->targetlist, ((Sort *) plan)->keycount,
668+
show_sort_keys(plan->targetlist,
669+
((Sort *) plan)->numCols,
670+
((Sort *) plan)->sortColIdx,
676671
"Sort Key",
677672
str, indent, es);
678673
break;
@@ -937,7 +932,8 @@ show_upper_qual(List *qual, const char *qlabel,
937932
* Show the sort keys for a Sort node.
938933
*/
939934
static void
940-
show_sort_keys(List *tlist, int nkeys, const char *qlabel,
935+
show_sort_keys(List *tlist, int nkeys, AttrNumber *keycols,
936+
const char *qlabel,
941937
StringInfo str, int indent, ExplainState *es)
942938
{
943939
List *context;
@@ -985,27 +981,30 @@ show_sort_keys(List *tlist, int nkeys, const char *qlabel,
985981
}
986982
bms_free(varnos);
987983

988-
for (keyno = 1; keyno <= nkeys; keyno++)
984+
for (keyno = 0; keyno < nkeys; keyno++)
989985
{
990986
/* find key expression in tlist */
987+
AttrNumber keyresno = keycols[keyno];
988+
991989
foreach(tl, tlist)
992990
{
993991
TargetEntry *target = (TargetEntry *) lfirst(tl);
994992

995-
if (target->resdom->reskey == keyno)
993+
if (target->resdom->resno == keyresno)
996994
{
997995
/* Deparse the expression, showing any top-level cast */
998996
exprstr = deparse_expression((Node *) target->expr, context,
999997
useprefix, true);
1000998
/* And add to str */
1001-
if (keyno > 1)
999+
if (keyno > 0)
10021000
appendStringInfo(str, ", ");
10031001
appendStringInfo(str, "%s", exprstr);
10041002
break;
10051003
}
10061004
}
10071005
if (tl == NIL)
1008-
elog(ERROR, "show_sort_keys: no tlist entry for key %d", keyno);
1006+
elog(ERROR, "show_sort_keys: no tlist entry for key %d",
1007+
keyresno);
10091008
}
10101009

10111010
appendStringInfo(str, "\n");

src/backend/executor/execMain.c

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
*
2828
* IDENTIFICATION
29-
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.206 2003/05/05 17:57:47 tgl Exp $
29+
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.207 2003/05/06 00:20:31 tgl Exp $
3030
*
3131
*-------------------------------------------------------------------------
3232
*/
@@ -63,7 +63,7 @@ typedef struct evalPlanQual
6363
} evalPlanQual;
6464

6565
/* decls for local routines only used within this module */
66-
static void InitPlan(QueryDesc *queryDesc);
66+
static void InitPlan(QueryDesc *queryDesc, bool explainOnly);
6767
static void initResultRelInfo(ResultRelInfo *resultRelInfo,
6868
Index resultRelationIndex,
6969
List *rangeTable,
@@ -104,12 +104,15 @@ static void EvalPlanQualStop(evalPlanQual *epq);
104104
* field of the QueryDesc is filled in to describe the tuples that will be
105105
* returned, and the internal fields (estate and planstate) are set up.
106106
*
107+
* If explainOnly is true, we are not actually intending to run the plan,
108+
* only to set up for EXPLAIN; so skip unwanted side-effects.
109+
*
107110
* NB: the CurrentMemoryContext when this is called will become the parent
108111
* of the per-query context used for this Executor invocation.
109112
* ----------------------------------------------------------------
110113
*/
111114
void
112-
ExecutorStart(QueryDesc *queryDesc)
115+
ExecutorStart(QueryDesc *queryDesc, bool explainOnly)
113116
{
114117
EState *estate;
115118
MemoryContext oldcontext;
@@ -118,6 +121,13 @@ ExecutorStart(QueryDesc *queryDesc)
118121
Assert(queryDesc != NULL);
119122
Assert(queryDesc->estate == NULL);
120123

124+
/*
125+
* If the transaction is read-only, we need to check if any writes
126+
* are planned to non-temporary tables.
127+
*/
128+
if (!explainOnly)
129+
ExecCheckXactReadOnly(queryDesc->parsetree, queryDesc->operation);
130+
121131
/*
122132
* Build EState, switch into per-query memory context for startup.
123133
*/
@@ -149,7 +159,7 @@ ExecutorStart(QueryDesc *queryDesc)
149159
/*
150160
* Initialize the plan state tree
151161
*/
152-
InitPlan(queryDesc);
162+
InitPlan(queryDesc, explainOnly);
153163

154164
MemoryContextSwitchTo(oldcontext);
155165
}
@@ -202,23 +212,17 @@ ExecutorRun(QueryDesc *queryDesc,
202212
operation = queryDesc->operation;
203213
dest = queryDesc->dest;
204214

205-
/*
206-
* If the transaction is read-only, we need to check if any writes
207-
* are planned to non-temporary tables. This is done here at this
208-
* rather late stage so that we can handle EXPLAIN vs. EXPLAIN
209-
* ANALYZE easily.
210-
*/
211-
ExecCheckXactReadOnly(queryDesc->parsetree, operation);
212-
213215
/*
214216
* startup tuple receiver
215217
*/
216218
estate->es_processed = 0;
217219
estate->es_lastoid = InvalidOid;
218220

219221
destfunc = DestToFunction(dest);
220-
(*destfunc->setup) (destfunc, operation, queryDesc->portalName,
221-
queryDesc->tupDesc);
222+
(*destfunc->setup) (destfunc, operation,
223+
queryDesc->portalName,
224+
queryDesc->tupDesc,
225+
queryDesc->planstate->plan->targetlist);
222226

223227
/*
224228
* run plan
@@ -468,7 +472,7 @@ ExecCheckXactReadOnly(Query *parsetree, CmdType operation)
468472
* ----------------------------------------------------------------
469473
*/
470474
static void
471-
InitPlan(QueryDesc *queryDesc)
475+
InitPlan(QueryDesc *queryDesc, bool explainOnly)
472476
{
473477
CmdType operation = queryDesc->operation;
474478
Query *parseTree = queryDesc->parsetree;
@@ -751,10 +755,12 @@ InitPlan(QueryDesc *queryDesc)
751755
* If doing SELECT INTO, initialize the "into" relation. We must wait
752756
* till now so we have the "clean" result tuple type to create the
753757
* new table from.
758+
*
759+
* If EXPLAIN, skip creating the "into" relation.
754760
*/
755761
intoRelationDesc = (Relation) NULL;
756762

757-
if (do_select_into)
763+
if (do_select_into && !explainOnly)
758764
{
759765
char *intoName;
760766
Oid namespaceId;

src/backend/executor/execTuples.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.63 2002/12/13 19:45:52 tgl Exp $
18+
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.64 2003/05/06 00:20:31 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -723,7 +723,7 @@ begin_tup_output_tupdesc(CommandDest dest, TupleDesc tupdesc)
723723
tstate->destfunc = DestToFunction(dest);
724724

725725
(*tstate->destfunc->setup) (tstate->destfunc, (int) CMD_SELECT,
726-
NULL, tupdesc);
726+
NULL, tupdesc, NIL);
727727

728728
return tstate;
729729
}

src/backend/executor/functions.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.62 2002/12/15 16:17:46 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.63 2003/05/06 00:20:31 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -250,7 +250,7 @@ postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
250250

251251
/* Utility commands don't need Executor. */
252252
if (es->qd->operation != CMD_UTILITY)
253-
ExecutorStart(es->qd);
253+
ExecutorStart(es->qd, false);
254254

255255
es->status = F_EXEC_RUN;
256256
}

0 commit comments

Comments
 (0)