Re: Allow arbitrary levels of analyze/rewriting
От | Bruce Momjian |
---|---|
Тема | Re: Allow arbitrary levels of analyze/rewriting |
Дата | |
Msg-id | 200202220440.g1M4eTe18137@candle.pha.pa.us обсуждение исходный текст |
Ответ на | Allow arbitrary levels of analyze/rewriting (Fernando Nasser <fnasser@redhat.com>) |
Список | pgsql-patches |
This has been saved for the 7.3 release: http://candle.pha.pa.us/cgi-bin/pgpatches2 --------------------------------------------------------------------------- Fernando Nasser wrote: > Hi, > > 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 > Red Hat Canada Ltd. E-Mail: fnasser@redhat.com > 2323 Yonge Street, Suite #300 > Toronto, Ontario M4P 2C9 > Index: src/backend/parser/analyze.c > =================================================================== > RCS file: /projects/cvsroot/pgsql/src/backend/parser/analyze.c,v > retrieving revision 1.213 > diff -c -p -r1.213 analyze.c > *** src/backend/parser/analyze.c 2002/01/03 23:21:31 1.213 > --- src/backend/parser/analyze.c 2002/02/12 15:35:58 > *************** typedef struct > *** 64,80 **** > } CreateStmtContext; > > > ! static Query *transformStmt(ParseState *pstate, Node *stmt); > static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt); > ! static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt); > static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt); > ! static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt); > static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt); > static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt); > static Node *transformSetOperationTree(ParseState *pstate, SelectStmt *stmt); > static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt); > ! static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt); > ! static Query *transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt); > static void transformColumnDefinition(ParseState *pstate, > CreateStmtContext *cxt, > ColumnDef *column); > --- 64,85 ---- > } CreateStmtContext; > > > ! static Query *transformStmt(ParseState *pstate, Node *stmt, > ! List **extras_before, List **extras_after); > static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt); > ! static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt, > ! List **extras_before, List **extras_after); > static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt); > ! static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt, > ! List **extras_before, List **extras_after); > static Query *transformSelectStmt(ParseState *pstate, SelectStmt *stmt); > static Query *transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt); > static Node *transformSetOperationTree(ParseState *pstate, SelectStmt *stmt); > static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt); > ! static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt, > ! List **extras_before, List **extras_after); > ! static Query *transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt, > ! List **extras_before, List **extras_after); > static void transformColumnDefinition(ParseState *pstate, > CreateStmtContext *cxt, > ColumnDef *column); > *************** static Oid transformFkeyGetColType(Creat > *** 101,109 **** > static void release_pstate_resources(ParseState *pstate); > static FromExpr *makeFromExpr(List *fromlist, Node *quals); > > - /* kluge to return extra info from transformCreateStmt() */ > - static List *extras_before; > - static List *extras_after; > > > /* > --- 106,111 ---- > *************** parse_analyze(Node *parseTree, ParseStat > *** 121,137 **** > List *result = NIL; > ParseState *pstate = make_parsestate(parentParseState); > Query *query; > > ! extras_before = extras_after = NIL; > ! > ! query = transformStmt(pstate, parseTree); > release_pstate_resources(pstate); > > while (extras_before != NIL) > { > ! result = lappend(result, > ! transformStmt(pstate, lfirst(extras_before))); > ! release_pstate_resources(pstate); > extras_before = lnext(extras_before); > } > > --- 123,138 ---- > List *result = NIL; > ParseState *pstate = make_parsestate(parentParseState); > Query *query; > + /* Lists to return extra commands from transformation */ > + List *extras_before = NIL; > + List *extras_after = NIL; > > ! query = transformStmt(pstate, parseTree, &extras_before, &extras_after); > release_pstate_resources(pstate); > > while (extras_before != NIL) > { > ! result = nconc(result, parse_analyze(lfirst(extras_before), pstate)); > extras_before = lnext(extras_before); > } > > *************** parse_analyze(Node *parseTree, ParseStat > *** 139,147 **** > > while (extras_after != NIL) > { > ! result = lappend(result, > ! transformStmt(pstate, lfirst(extras_after))); > ! release_pstate_resources(pstate); > extras_after = lnext(extras_after); > } > > --- 140,146 ---- > > while (extras_after != NIL) > { > ! result = nconc(result, parse_analyze(lfirst(extras_after), pstate)); > extras_after = lnext(extras_after); > } > > *************** release_pstate_resources(ParseState *pst > *** 164,170 **** > * transform a Parse tree into a Query tree. > */ > static Query * > ! transformStmt(ParseState *pstate, Node *parseTree) > { > Query *result = NULL; > > --- 163,170 ---- > * transform a Parse tree into a Query tree. > */ > static Query * > ! transformStmt(ParseState *pstate, Node *parseTree, > ! List **extras_before, List **extras_after) > { > Query *result = NULL; > > *************** transformStmt(ParseState *pstate, Node * > *** 174,180 **** > * Non-optimizable statements > */ > case T_CreateStmt: > ! result = transformCreateStmt(pstate, (CreateStmt *) parseTree); > break; > > case T_IndexStmt: > --- 174,181 ---- > * Non-optimizable statements > */ > case T_CreateStmt: > ! result = transformCreateStmt(pstate, (CreateStmt *) parseTree, > ! extras_before, extras_after); > break; > > case T_IndexStmt: > *************** transformStmt(ParseState *pstate, Node * > *** 182,195 **** > break; > > case T_RuleStmt: > ! result = transformRuleStmt(pstate, (RuleStmt *) parseTree); > break; > > case T_ViewStmt: > { > ViewStmt *n = (ViewStmt *) parseTree; > > ! n->query = transformStmt(pstate, (Node *) n->query); > > /* > * If a list of column names was given, run through and > --- 183,198 ---- > break; > > case T_RuleStmt: > ! result = transformRuleStmt(pstate, (RuleStmt *) parseTree, > ! extras_before, extras_after); > break; > > case T_ViewStmt: > { > ViewStmt *n = (ViewStmt *) parseTree; > > ! n->query = transformStmt(pstate, (Node *) n->query, > ! extras_before, extras_after); > > /* > * If a list of column names was given, run through and > *************** transformStmt(ParseState *pstate, Node * > *** 239,258 **** > > result = makeNode(Query); > result->commandType = CMD_UTILITY; > ! n->query = transformStmt(pstate, (Node *) n->query); > result->utilityStmt = (Node *) parseTree; > } > break; > > case T_AlterTableStmt: > ! result = transformAlterTableStmt(pstate, (AlterTableStmt *) parseTree); > break; > > /* > * Optimizable statements > */ > case T_InsertStmt: > ! result = transformInsertStmt(pstate, (InsertStmt *) parseTree); > break; > > case T_DeleteStmt: > --- 242,264 ---- > > result = makeNode(Query); > result->commandType = CMD_UTILITY; > ! n->query = transformStmt(pstate, (Node *) n->query, > ! extras_before, extras_after); > result->utilityStmt = (Node *) parseTree; > } > break; > > case T_AlterTableStmt: > ! result = transformAlterTableStmt(pstate, (AlterTableStmt *) parseTree, > ! extras_before, extras_after); > break; > > /* > * Optimizable statements > */ > case T_InsertStmt: > ! result = transformInsertStmt(pstate, (InsertStmt *) parseTree, > ! extras_before, extras_after); > break; > > case T_DeleteStmt: > *************** transformDeleteStmt(ParseState *pstate, > *** 337,343 **** > * transform an Insert Statement > */ > static Query * > ! transformInsertStmt(ParseState *pstate, InsertStmt *stmt) > { > Query *qry = makeNode(Query); > List *sub_rtable; > --- 343,350 ---- > * transform an Insert Statement > */ > static Query * > ! transformInsertStmt(ParseState *pstate, InsertStmt *stmt, > ! List **extras_before, List **extras_after) > { > Query *qry = makeNode(Query); > List *sub_rtable; > *************** transformInsertStmt(ParseState *pstate, > *** 402,408 **** > sub_pstate->p_rtable = sub_rtable; > sub_pstate->p_namespace = sub_namespace; > > ! selectQuery = transformStmt(sub_pstate, stmt->selectStmt); > > release_pstate_resources(sub_pstate); > pfree(sub_pstate); > --- 409,420 ---- > sub_pstate->p_rtable = sub_rtable; > sub_pstate->p_namespace = sub_namespace; > > ! /* > ! * Note: we are not expecting that extras_before and extras_after > ! * are going to be used by the transformation of the SELECT statement. > ! */ > ! selectQuery = transformStmt(sub_pstate, stmt->selectStmt, > ! extras_before, extras_after); > > release_pstate_resources(sub_pstate); > pfree(sub_pstate); > *************** CreateIndexName(char *table_name, char * > *** 658,664 **** > * - thomas 1997-12-02 > */ > static Query * > ! transformCreateStmt(ParseState *pstate, CreateStmt *stmt) > { > CreateStmtContext cxt; > Query *q; > --- 670,677 ---- > * - thomas 1997-12-02 > */ > static Query * > ! transformCreateStmt(ParseState *pstate, CreateStmt *stmt, > ! List **extras_before, List **extras_after) > { > CreateStmtContext cxt; > Query *q; > *************** transformCreateStmt(ParseState *pstate, > *** 728,735 **** > q->utilityStmt = (Node *) stmt; > stmt->tableElts = cxt.columns; > stmt->constraints = cxt.ckconstraints; > ! extras_before = cxt.blist; > ! extras_after = cxt.alist; > > return q; > } > --- 741,748 ---- > q->utilityStmt = (Node *) stmt; > stmt->tableElts = cxt.columns; > stmt->constraints = cxt.ckconstraints; > ! *extras_before = nconc (*extras_before, cxt.blist); > ! *extras_after = nconc (cxt.alist, *extras_after); > > return q; > } > *************** transformIndexStmt(ParseState *pstate, I > *** 1668,1674 **** > * trees which is transformed into a list of query trees. > */ > static Query * > ! transformRuleStmt(ParseState *pstate, RuleStmt *stmt) > { > Query *qry; > RangeTblEntry *oldrte; > --- 1681,1688 ---- > * trees which is transformed into a list of query trees. > */ > static Query * > ! transformRuleStmt(ParseState *pstate, RuleStmt *stmt, > ! List **extras_before, List **extras_after) > { > Query *qry; > RangeTblEntry *oldrte; > *************** transformRuleStmt(ParseState *pstate, Ru > *** 1797,1803 **** > addRTEtoQuery(sub_pstate, newrte, false, true); > > /* Transform the rule action statement */ > ! top_subqry = transformStmt(sub_pstate, action); > > /* > * We cannot support utility-statement actions (eg NOTIFY) > --- 1811,1818 ---- > addRTEtoQuery(sub_pstate, newrte, false, true); > > /* Transform the rule action statement */ > ! top_subqry = transformStmt(sub_pstate, action, > ! extras_before, extras_after); > > /* > * We cannot support utility-statement actions (eg NOTIFY) > *************** transformUpdateStmt(ParseState *pstate, > *** 2494,2500 **** > * transform an Alter Table Statement > */ > static Query * > ! transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt) > { > CreateStmtContext cxt; > Query *qry; > --- 2509,2516 ---- > * transform an Alter Table Statement > */ > static Query * > ! transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt, > ! List **extras_before, List **extras_after) > { > CreateStmtContext cxt; > Query *qry; > *************** transformAlterTableStmt(ParseState *psta > *** 2534,2541 **** > transformFKConstraints(pstate, &cxt); > > ((ColumnDef *) stmt->def)->constraints = cxt.ckconstraints; > ! extras_before = cxt.blist; > ! extras_after = cxt.alist; > break; > > case 'C': > --- 2550,2557 ---- > transformFKConstraints(pstate, &cxt); > > ((ColumnDef *) stmt->def)->constraints = cxt.ckconstraints; > ! *extras_before = nconc(*extras_before, cxt.blist); > ! *extras_after = nconc(cxt.alist, *extras_after); > break; > > case 'C': > *************** transformAlterTableStmt(ParseState *psta > *** 2571,2578 **** > > Assert(cxt.columns == NIL); > stmt->def = (Node *) nconc(cxt.ckconstraints, cxt.fkconstraints); > ! extras_before = cxt.blist; > ! extras_after = cxt.alist; > break; > > default: > --- 2587,2594 ---- > > Assert(cxt.columns == NIL); > stmt->def = (Node *) nconc(cxt.ckconstraints, cxt.fkconstraints); > ! *extras_before = nconc(*extras_before, cxt.blist); > ! *extras_after = nconc(cxt.alist, *extras_after); > break; > > default: > > ---------------------------(end of broadcast)--------------------------- > TIP 5: Have you checked our extensive FAQ? > > http://www.postgresql.org/users-lounge/docs/faq.html -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 853-3000 + If your life is a hard drive, | 830 Blythe Avenue + Christ can be your backup. | Drexel Hill, Pennsylvania 19026
В списке pgsql-patches по дате отправления: