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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy