Skip to content

Commit b4a09ea

Browse files
committed
This patch will allow arbitrary levels of analyze / rewriting
by making the static variables extra_before and extra_after automatic so we can use recursion. It gets much easier to generate extra commands now, and one can rest assured that the extra commands will be properly analyzed/rewritten. Without this patch, if a command produced by transformation tries to use these static lists their first contents would be lost with unpredictable results. I know I could fix this by just using nconc() instead of assignments, but the resulting order of the commands would not be exactly what one could expect. -- Fernando Nasser
1 parent d6198ee commit b4a09ea

File tree

1 file changed

+53
-37
lines changed

1 file changed

+53
-37
lines changed

src/backend/parser/analyze.c

Lines changed: 53 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.213 2002/01/03 23:21:31 tgl Exp $
9+
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.214 2002/02/25 04:21:55 momjian Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -64,17 +64,22 @@ typedef struct
6464
} CreateStmtContext;
6565

6666

67-
static Query *transformStmt(ParseState *pstate, Node *stmt);
67+
static Query *transformStmt(ParseState *pstate, Node *stmt,
68+
List **extras_before, List **extras_after);
6869
static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
69-
static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
70+
static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
71+
List **extras_before, List **extras_after);
7072
static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
71-
static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
73+
static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt,
74+
List **extras_before, List **extras_after);
7275
static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt);
7376
static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt);
7477
static Node *transformSetOperationTree(ParseState *pstate, SelectStmt *stmt);
7578
static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
76-
static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt);
77-
static Query *transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt);
79+
static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt,
80+
List **extras_before, List **extras_after);
81+
static Query *transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
82+
List **extras_before, List **extras_after);
7883
static void transformColumnDefinition(ParseState *pstate,
7984
CreateStmtContext *cxt,
8085
ColumnDef *column);
@@ -101,9 +106,6 @@ static Oid transformFkeyGetColType(CreateStmtContext *cxt, char *colname);
101106
static void release_pstate_resources(ParseState *pstate);
102107
static FromExpr *makeFromExpr(List *fromlist, Node *quals);
103108

104-
/* kluge to return extra info from transformCreateStmt() */
105-
static List *extras_before;
106-
static List *extras_after;
107109

108110

109111
/*
@@ -121,27 +123,24 @@ parse_analyze(Node *parseTree, ParseState *parentParseState)
121123
List *result = NIL;
122124
ParseState *pstate = make_parsestate(parentParseState);
123125
Query *query;
126+
/* Lists to return extra commands from transformation */
127+
List *extras_before = NIL;
128+
List *extras_after = NIL;
124129

125-
extras_before = extras_after = NIL;
126-
127-
query = transformStmt(pstate, parseTree);
130+
query = transformStmt(pstate, parseTree, &extras_before, &extras_after);
128131
release_pstate_resources(pstate);
129132

130133
while (extras_before != NIL)
131134
{
132-
result = lappend(result,
133-
transformStmt(pstate, lfirst(extras_before)));
134-
release_pstate_resources(pstate);
135+
result = nconc(result, parse_analyze(lfirst(extras_before), pstate));
135136
extras_before = lnext(extras_before);
136137
}
137138

138139
result = lappend(result, query);
139140

140141
while (extras_after != NIL)
141142
{
142-
result = lappend(result,
143-
transformStmt(pstate, lfirst(extras_after)));
144-
release_pstate_resources(pstate);
143+
result = nconc(result, parse_analyze(lfirst(extras_after), pstate));
145144
extras_after = lnext(extras_after);
146145
}
147146

@@ -164,7 +163,8 @@ release_pstate_resources(ParseState *pstate)
164163
* transform a Parse tree into a Query tree.
165164
*/
166165
static Query *
167-
transformStmt(ParseState *pstate, Node *parseTree)
166+
transformStmt(ParseState *pstate, Node *parseTree,
167+
List **extras_before, List **extras_after)
168168
{
169169
Query *result = NULL;
170170

@@ -174,22 +174,25 @@ transformStmt(ParseState *pstate, Node *parseTree)
174174
* Non-optimizable statements
175175
*/
176176
case T_CreateStmt:
177-
result = transformCreateStmt(pstate, (CreateStmt *) parseTree);
177+
result = transformCreateStmt(pstate, (CreateStmt *) parseTree,
178+
extras_before, extras_after);
178179
break;
179180

180181
case T_IndexStmt:
181182
result = transformIndexStmt(pstate, (IndexStmt *) parseTree);
182183
break;
183184

184185
case T_RuleStmt:
185-
result = transformRuleStmt(pstate, (RuleStmt *) parseTree);
186+
result = transformRuleStmt(pstate, (RuleStmt *) parseTree,
187+
extras_before, extras_after);
186188
break;
187189

188190
case T_ViewStmt:
189191
{
190192
ViewStmt *n = (ViewStmt *) parseTree;
191193

192-
n->query = transformStmt(pstate, (Node *) n->query);
194+
n->query = transformStmt(pstate, (Node *) n->query,
195+
extras_before, extras_after);
193196

194197
/*
195198
* If a list of column names was given, run through and
@@ -239,20 +242,23 @@ transformStmt(ParseState *pstate, Node *parseTree)
239242

240243
result = makeNode(Query);
241244
result->commandType = CMD_UTILITY;
242-
n->query = transformStmt(pstate, (Node *) n->query);
245+
n->query = transformStmt(pstate, (Node *) n->query,
246+
extras_before, extras_after);
243247
result->utilityStmt = (Node *) parseTree;
244248
}
245249
break;
246250

247251
case T_AlterTableStmt:
248-
result = transformAlterTableStmt(pstate, (AlterTableStmt *) parseTree);
252+
result = transformAlterTableStmt(pstate, (AlterTableStmt *) parseTree,
253+
extras_before, extras_after);
249254
break;
250255

251256
/*
252257
* Optimizable statements
253258
*/
254259
case T_InsertStmt:
255-
result = transformInsertStmt(pstate, (InsertStmt *) parseTree);
260+
result = transformInsertStmt(pstate, (InsertStmt *) parseTree,
261+
extras_before, extras_after);
256262
break;
257263

258264
case T_DeleteStmt:
@@ -337,7 +343,8 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
337343
* transform an Insert Statement
338344
*/
339345
static Query *
340-
transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
346+
transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
347+
List **extras_before, List **extras_after)
341348
{
342349
Query *qry = makeNode(Query);
343350
List *sub_rtable;
@@ -402,7 +409,12 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
402409
sub_pstate->p_rtable = sub_rtable;
403410
sub_pstate->p_namespace = sub_namespace;
404411

405-
selectQuery = transformStmt(sub_pstate, stmt->selectStmt);
412+
/*
413+
* Note: we are not expecting that extras_before and extras_after
414+
* are going to be used by the transformation of the SELECT statement.
415+
*/
416+
selectQuery = transformStmt(sub_pstate, stmt->selectStmt,
417+
extras_before, extras_after);
406418

407419
release_pstate_resources(sub_pstate);
408420
pfree(sub_pstate);
@@ -658,7 +670,8 @@ CreateIndexName(char *table_name, char *column_name,
658670
* - thomas 1997-12-02
659671
*/
660672
static Query *
661-
transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
673+
transformCreateStmt(ParseState *pstate, CreateStmt *stmt,
674+
List **extras_before, List **extras_after)
662675
{
663676
CreateStmtContext cxt;
664677
Query *q;
@@ -728,8 +741,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
728741
q->utilityStmt = (Node *) stmt;
729742
stmt->tableElts = cxt.columns;
730743
stmt->constraints = cxt.ckconstraints;
731-
extras_before = cxt.blist;
732-
extras_after = cxt.alist;
744+
*extras_before = nconc (*extras_before, cxt.blist);
745+
*extras_after = nconc (cxt.alist, *extras_after);
733746

734747
return q;
735748
}
@@ -1668,7 +1681,8 @@ transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
16681681
* trees which is transformed into a list of query trees.
16691682
*/
16701683
static Query *
1671-
transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
1684+
transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
1685+
List **extras_before, List **extras_after)
16721686
{
16731687
Query *qry;
16741688
RangeTblEntry *oldrte;
@@ -1797,7 +1811,8 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt)
17971811
addRTEtoQuery(sub_pstate, newrte, false, true);
17981812

17991813
/* Transform the rule action statement */
1800-
top_subqry = transformStmt(sub_pstate, action);
1814+
top_subqry = transformStmt(sub_pstate, action,
1815+
extras_before, extras_after);
18011816

18021817
/*
18031818
* We cannot support utility-statement actions (eg NOTIFY)
@@ -2494,7 +2509,8 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
24942509
* transform an Alter Table Statement
24952510
*/
24962511
static Query *
2497-
transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt)
2512+
transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
2513+
List **extras_before, List **extras_after)
24982514
{
24992515
CreateStmtContext cxt;
25002516
Query *qry;
@@ -2534,8 +2550,8 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt)
25342550
transformFKConstraints(pstate, &cxt);
25352551

25362552
((ColumnDef *) stmt->def)->constraints = cxt.ckconstraints;
2537-
extras_before = cxt.blist;
2538-
extras_after = cxt.alist;
2553+
*extras_before = nconc(*extras_before, cxt.blist);
2554+
*extras_after = nconc(cxt.alist, *extras_after);
25392555
break;
25402556

25412557
case 'C':
@@ -2571,8 +2587,8 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt)
25712587

25722588
Assert(cxt.columns == NIL);
25732589
stmt->def = (Node *) nconc(cxt.ckconstraints, cxt.fkconstraints);
2574-
extras_before = cxt.blist;
2575-
extras_after = cxt.alist;
2590+
*extras_before = nconc(*extras_before, cxt.blist);
2591+
*extras_after = nconc(cxt.alist, *extras_after);
25762592
break;
25772593

25782594
default:

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