diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2005-06-05 00:38:11 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2005-06-05 00:38:11 +0000 |
commit | a4996a895399a4b0363c7dace71fc6ce8acbc196 (patch) | |
tree | 9fe26cb35badc6a7b0c86a9db1eaf2e7ca95b142 /src/backend/parser/analyze.c | |
parent | efe0d0808b055fb2f651dd3732bd770290eb2659 (diff) | |
download | postgresql-a4996a895399a4b0363c7dace71fc6ce8acbc196.tar.gz |
Replace the parser's namespace tree (which formerly had the same
representation as the jointree) with two lists of RTEs, one showing
the RTEs accessible by qualified names, and the other showing the RTEs
accessible by unqualified names. I think this is conceptually simpler
than what we did before, and it's sure a whole lot easier to search.
This seems to eliminate the parse-time bottleneck for deeply nested
JOIN structures that was exhibited by phil@vodafone.
Diffstat (limited to 'src/backend/parser/analyze.c')
-rw-r--r-- | src/backend/parser/analyze.c | 82 |
1 files changed, 43 insertions, 39 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index ee6bfe6ae9..1c8fe6cf77 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.321 2005/04/28 21:47:14 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.322 2005/06/05 00:38:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -512,7 +512,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt, Query *qry = makeNode(Query); Query *selectQuery = NULL; List *sub_rtable; - List *sub_namespace; + List *sub_relnamespace; + List *sub_varnamespace; List *icolumns; List *attrnos; ListCell *icols; @@ -528,20 +529,23 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt, * SELECT. This can only happen if we are inside a CREATE RULE, and * in that case we want the rule's OLD and NEW rtable entries to * appear as part of the SELECT's rtable, not as outer references for - * it. (Kluge!) The SELECT's joinlist is not affected however. We + * it. (Kluge!) The SELECT's joinlist is not affected however. We * must do this before adding the target table to the INSERT's rtable. */ if (stmt->selectStmt) { sub_rtable = pstate->p_rtable; pstate->p_rtable = NIL; - sub_namespace = pstate->p_namespace; - pstate->p_namespace = NIL; + sub_relnamespace = pstate->p_relnamespace; + pstate->p_relnamespace = NIL; + sub_varnamespace = pstate->p_varnamespace; + pstate->p_varnamespace = NIL; } else { sub_rtable = NIL; /* not used, but keep compiler quiet */ - sub_namespace = NIL; + sub_relnamespace = NIL; + sub_varnamespace = NIL; } /* @@ -578,7 +582,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt, * through 6.5 had bugs of just that nature...) */ sub_pstate->p_rtable = sub_rtable; - sub_pstate->p_namespace = sub_namespace; + sub_pstate->p_relnamespace = sub_relnamespace; + sub_pstate->p_varnamespace = sub_varnamespace; /* * Note: we are not expecting that extras_before and extras_after @@ -605,7 +610,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt, rte = addRangeTableEntryForSubquery(pstate, selectQuery, makeAlias("*SELECT*", NIL), - true); + false); rtr = makeNode(RangeTblRef); /* assume new rte is at end */ rtr->rtindex = list_length(pstate->p_rtable); @@ -1481,8 +1486,8 @@ transformIndexStmt(ParseState *pstate, IndexStmt *stmt) */ rte = addRangeTableEntry(pstate, stmt->relation, NULL, false, true); - /* no to join list, yes to namespace */ - addRTEtoQuery(pstate, rte, false, true); + /* no to join list, yes to namespaces */ + addRTEtoQuery(pstate, rte, false, true, true); stmt->whereClause = transformWhereClause(pstate, stmt->whereClause, "WHERE"); @@ -1500,8 +1505,8 @@ transformIndexStmt(ParseState *pstate, IndexStmt *stmt) { rte = addRangeTableEntry(pstate, stmt->relation, NULL, false, true); - /* no to join list, yes to namespace */ - addRTEtoQuery(pstate, rte, false, true); + /* no to join list, yes to namespaces */ + addRTEtoQuery(pstate, rte, false, true, true); } ielem->expr = transformExpr(pstate, ielem->expr); @@ -1559,10 +1564,10 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt, Assert(pstate->p_rtable == NIL); oldrte = addRangeTableEntryForRelation(pstate, rel, makeAlias("*OLD*", NIL), - false, true); + false, false); newrte = addRangeTableEntryForRelation(pstate, rel, makeAlias("*NEW*", NIL), - false, true); + false, false); /* Must override addRangeTableEntry's default access-check flags */ oldrte->requiredPerms = 0; newrte->requiredPerms = 0; @@ -1572,24 +1577,22 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt, * the one(s) that are relevant for the current kind of rule. In an * UPDATE rule, quals must refer to OLD.field or NEW.field to be * unambiguous, but there's no need to be so picky for INSERT & - * DELETE. (Note we marked the RTEs "inFromCl = true" above to allow - * unqualified references to their fields.) We do not add them to the - * joinlist. + * DELETE. We do not add them to the joinlist. */ switch (stmt->event) { case CMD_SELECT: - addRTEtoQuery(pstate, oldrte, false, true); + addRTEtoQuery(pstate, oldrte, false, true, true); break; case CMD_UPDATE: - addRTEtoQuery(pstate, oldrte, false, true); - addRTEtoQuery(pstate, newrte, false, true); + addRTEtoQuery(pstate, oldrte, false, true, true); + addRTEtoQuery(pstate, newrte, false, true, true); break; case CMD_INSERT: - addRTEtoQuery(pstate, newrte, false, true); + addRTEtoQuery(pstate, newrte, false, true, true); break; case CMD_DELETE: - addRTEtoQuery(pstate, oldrte, false, true); + addRTEtoQuery(pstate, oldrte, false, true, true); break; default: elog(ERROR, "unrecognized event type: %d", @@ -1651,10 +1654,9 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt, /* * Set up OLD/NEW in the rtable for this statement. The - * entries are marked not inFromCl because we don't want them - * to be referred to by unqualified field names nor "*" in the - * rule actions. We must add them to the namespace, however, - * or they won't be accessible at all. We decide later + * entries are added only to relnamespace, not varnamespace, + * because we don't want them to be referred to by unqualified + * field names nor "*" in the rule actions. We decide later * whether to put them in the joinlist. */ oldrte = addRangeTableEntryForRelation(sub_pstate, rel, @@ -1665,8 +1667,8 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt, false, false); oldrte->requiredPerms = 0; newrte->requiredPerms = 0; - addRTEtoQuery(sub_pstate, oldrte, false, true); - addRTEtoQuery(sub_pstate, newrte, false, true); + addRTEtoQuery(sub_pstate, oldrte, false, true, false); + addRTEtoQuery(sub_pstate, newrte, false, true, false); /* Transform the rule action statement */ top_subqry = transformStmt(sub_pstate, action, @@ -1776,7 +1778,7 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt, /* hack so we can use addRTEtoQuery() */ sub_pstate->p_rtable = sub_qry->rtable; sub_pstate->p_joinlist = sub_qry->jointree->fromlist; - addRTEtoQuery(sub_pstate, oldrte, true, false); + addRTEtoQuery(sub_pstate, oldrte, true, false, false); sub_qry->jointree->fromlist = sub_pstate->p_joinlist; } @@ -1906,10 +1908,10 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) *dtlist; List *targetvars, *targetnames, - *sv_namespace, + *sv_relnamespace, + *sv_varnamespace, *sv_rtable; RangeTblEntry *jrte; - RangeTblRef *jrtr; int tllen; qry->commandType = CMD_SELECT; @@ -2027,7 +2029,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) /* * As a first step towards supporting sort clauses that are - * expressions using the output columns, generate a namespace entry + * expressions using the output columns, generate a varnamespace entry * that makes the output columns visible. A Join RTE node is handy * for this, since we can easily control the Vars generated upon * matches. @@ -2041,15 +2043,16 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) JOIN_INNER, targetvars, NULL, - true); - jrtr = makeNode(RangeTblRef); - jrtr->rtindex = 1; /* only entry in dummy rtable */ + false); sv_rtable = pstate->p_rtable; pstate->p_rtable = list_make1(jrte); - sv_namespace = pstate->p_namespace; - pstate->p_namespace = list_make1(jrtr); + sv_relnamespace = pstate->p_relnamespace; + pstate->p_relnamespace = NIL; /* no qualified names allowed */ + + sv_varnamespace = pstate->p_varnamespace; + pstate->p_varnamespace = list_make1(jrte); /* * For now, we don't support resjunk sort clauses on the output of a @@ -2064,8 +2067,9 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) &qry->targetList, false /* no unknowns expected */ ); - pstate->p_namespace = sv_namespace; pstate->p_rtable = sv_rtable; + pstate->p_relnamespace = sv_relnamespace; + pstate->p_varnamespace = sv_varnamespace; if (tllen != list_length(qry->targetList)) ereport(ERROR, @@ -2164,7 +2168,7 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt) * happen because the namespace will be empty, but it could happen * if we are inside a rule. */ - if (pstate->p_namespace) + if (pstate->p_relnamespace || pstate->p_varnamespace) { if (contain_vars_of_level((Node *) selectQuery, 1)) ereport(ERROR, |