*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.129 2005/04/28 21:47:13 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.130 2005/06/04 19:19:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
bool *differentTypes);
static bool qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
bool *differentTypes);
-static void subquery_push_qual(Query *subquery, List *rtable,
- Index rti, Node *qual);
+static void subquery_push_qual(Query *subquery,
+ RangeTblEntry *rte, Index rti, Node *qual);
static void recurse_push_qual(Node *setOp, Query *topquery,
- List *rtable, Index rti, Node *qual);
+ RangeTblEntry *rte, Index rti, Node *qual);
/*
if (qual_is_pushdown_safe(subquery, rti, clause, differentTypes))
{
/* Push it down */
- subquery_push_qual(subquery, root->rtable, rti, clause);
+ subquery_push_qual(subquery, rte, rti, clause);
}
else
{
* subquery_push_qual - push down a qual that we have determined is safe
*/
static void
-subquery_push_qual(Query *subquery, List *rtable, Index rti, Node *qual)
+subquery_push_qual(Query *subquery, RangeTblEntry *rte, Index rti, Node *qual)
{
if (subquery->setOperations != NULL)
{
/* Recurse to push it separately to each component query */
recurse_push_qual(subquery->setOperations, subquery,
- rtable, rti, qual);
+ rte, rti, qual);
}
else
{
* This step also ensures that when we are pushing into a setop tree,
* each component query gets its own copy of the qual.
*/
- qual = ResolveNew(qual, rti, 0, rtable,
+ qual = ResolveNew(qual, rti, 0, rte,
subquery->targetList,
CMD_SELECT, 0);
*/
static void
recurse_push_qual(Node *setOp, Query *topquery,
- List *rtable, Index rti, Node *qual)
+ RangeTblEntry *rte, Index rti, Node *qual)
{
if (IsA(setOp, RangeTblRef))
{
Query *subquery = subrte->subquery;
Assert(subquery != NULL);
- subquery_push_qual(subquery, rtable, rti, qual);
+ subquery_push_qual(subquery, rte, rti, qual);
}
else if (IsA(setOp, SetOperationStmt))
{
SetOperationStmt *op = (SetOperationStmt *) setOp;
- recurse_push_qual(op->larg, topquery, rtable, rti, qual);
- recurse_push_qual(op->rarg, topquery, rtable, rti, qual);
+ recurse_push_qual(op->larg, topquery, rte, rti, qual);
+ recurse_push_qual(op->rarg, topquery, rte, rti, qual);
}
else
{
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.27 2005/04/28 21:47:14 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.28 2005/06/04 19:19:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
static bool is_simple_subquery(Query *subquery);
static bool has_nullable_targetlist(Query *subquery);
static void resolvenew_in_jointree(Node *jtnode, int varno,
- List *rtable, List *subtlist);
+ RangeTblEntry *rte, List *subtlist);
static reduce_outer_joins_state *reduce_outer_joins_pass1(Node *jtnode);
static void reduce_outer_joins_pass2(Node *jtnode,
reduce_outer_joins_state *state,
subtlist = subquery->targetList;
parse->targetList = (List *)
ResolveNew((Node *) parse->targetList,
- varno, 0, parse->rtable,
+ varno, 0, rte,
subtlist, CMD_SELECT, 0);
resolvenew_in_jointree((Node *) parse->jointree, varno,
- parse->rtable, subtlist);
+ rte, subtlist);
Assert(parse->setOperations == NULL);
parse->havingQual =
ResolveNew(parse->havingQual,
- varno, 0, parse->rtable,
+ varno, 0, rte,
subtlist, CMD_SELECT, 0);
parse->in_info_list = (List *)
ResolveNew((Node *) parse->in_info_list,
- varno, 0, parse->rtable,
+ varno, 0, rte,
subtlist, CMD_SELECT, 0);
foreach(rt, parse->rtable)
if (otherrte->rtekind == RTE_JOIN)
otherrte->joinaliasvars = (List *)
ResolveNew((Node *) otherrte->joinaliasvars,
- varno, 0, parse->rtable,
+ varno, 0, rte,
subtlist, CMD_SELECT, 0);
}
*/
static void
resolvenew_in_jointree(Node *jtnode, int varno,
- List *rtable, List *subtlist)
+ RangeTblEntry *rte, List *subtlist)
{
if (jtnode == NULL)
return;
ListCell *l;
foreach(l, f->fromlist)
- resolvenew_in_jointree(lfirst(l), varno, rtable, subtlist);
+ resolvenew_in_jointree(lfirst(l), varno, rte, subtlist);
f->quals = ResolveNew(f->quals,
- varno, 0, rtable,
+ varno, 0, rte,
subtlist, CMD_SELECT, 0);
}
else if (IsA(jtnode, JoinExpr))
{
JoinExpr *j = (JoinExpr *) jtnode;
- resolvenew_in_jointree(j->larg, varno, rtable, subtlist);
- resolvenew_in_jointree(j->rarg, varno, rtable, subtlist);
+ resolvenew_in_jointree(j->larg, varno, rte, subtlist);
+ resolvenew_in_jointree(j->rarg, varno, rte, subtlist);
j->quals = ResolveNew(j->quals,
- varno, 0, rtable,
+ varno, 0, rte,
subtlist, CMD_SELECT, 0);
/*
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.109 2005/05/30 18:55:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.110 2005/06/04 19:19:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
break;
case RTE_FUNCTION:
- expandRTE(root->rtable, varno, 0, true /* include dropped */,
+ expandRTE(rte, varno, 0, true /* include dropped */,
NULL, &colvars);
foreach(l, colvars)
{
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.140 2005/04/13 16:50:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.141 2005/06/04 19:19:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(j->larg));
leftrti = 0; /* keep compiler quiet */
}
- expandRTE(pstate->p_rtable, leftrti, 0, false,
+ rte = rt_fetch(leftrti, pstate->p_rtable);
+ expandRTE(rte, leftrti, 0, false,
&l_colnames, &l_colvars);
if (IsA(j->rarg, RangeTblRef))
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(j->rarg));
rightrti = 0; /* keep compiler quiet */
}
- expandRTE(pstate->p_rtable, rightrti, 0, false,
+ rte = rt_fetch(rightrti, pstate->p_rtable);
+ expandRTE(rte, rightrti, 0, false,
&r_colnames, &r_colvars);
/*
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.130 2005/05/30 01:20:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.131 2005/06/04 19:19:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
int rtindex = ((Var *) node)->varno;
int sublevels_up = ((Var *) node)->varlevelsup;
- List *rtable;
+ RangeTblEntry *rte;
- rtable = GetLevelNRangeTable(pstate, sublevels_up);
- expandRTE(rtable, rtindex, sublevels_up, false, NULL, &args);
+ rte = GetRTEByRangeTablePosn(pstate, rtindex, sublevels_up);
+ expandRTE(rte, rtindex, sublevels_up, false,
+ NULL, &args);
}
else
ereport(ERROR,
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.109 2005/06/03 23:05:28 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.110 2005/06/04 19:19:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
return rt_fetch(varno, pstate->p_rtable);
}
-/*
- * GetLevelNRangeTable
- * Get the rangetable list for the N'th query level up from current.
- */
-List *
-GetLevelNRangeTable(ParseState *pstate, int sublevels_up)
-{
- int index = 0;
-
- while (pstate != NULL)
- {
- if (index == sublevels_up)
- return pstate->p_rtable;
- index++;
- pstate = pstate->parentParseState;
- }
-
- elog(ERROR, "rangetable not found (internal error)");
- return NIL; /* keep compiler quiet */
-}
-
/*
* scanRTEForColumn
* Search the column names of a single RTE for the given name.
* results. If include_dropped is TRUE then empty strings and NULL constants
* (not Vars!) are returned for dropped columns.
*
- * The target RTE is the rtindex'th entry of rtable.
- * sublevels_up is the varlevelsup value to use in the created Vars.
+ * rtindex and sublevels_up are the varno and varlevelsup values to use
+ * in the created Vars. Ordinarily rtindex should match the actual position
+ * of the RTE in its rangetable.
*
* The output lists go into *colnames and *colvars.
* If only one of the two kinds of output list is needed, pass NULL for the
* output pointer for the unwanted one.
*/
void
-expandRTE(List *rtable, int rtindex, int sublevels_up,
+expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
bool include_dropped,
List **colnames, List **colvars)
{
- RangeTblEntry *rte = rt_fetch(rtindex, rtable);
int varattno;
if (colnames)
* expandRelAttrs -
* Workhorse for "*" expansion: produce a list of targetentries
* for the attributes of the rte
+ *
+ * As with expandRTE, rtindex/sublevels_up determine the varno/varlevelsup
+ * fields of the Vars produced. pstate->p_next_resno determines the resnos
+ * assigned to the TLEs.
*/
List *
-expandRelAttrs(ParseState *pstate, List *rtable, int rtindex, int sublevels_up)
+expandRelAttrs(ParseState *pstate, RangeTblEntry *rte,
+ int rtindex, int sublevels_up)
{
List *names,
*vars;
*var;
List *te_list = NIL;
- expandRTE(rtable, rtindex, sublevels_up, false, &names, &vars);
+ expandRTE(rte, rtindex, sublevels_up, false,
+ &names, &vars);
forboth(name, names, var, vars)
{
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.134 2005/05/31 01:03:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.135 2005/06/04 19:19:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
RangeTblEntry *rte;
int sublevels_up;
int rtindex;
- List *rtable;
switch (numnames)
{
relname));
rtindex = RTERangeTablePosn(pstate, rte, &sublevels_up);
- rtable = GetLevelNRangeTable(pstate, sublevels_up);
- return expandRelAttrs(pstate, rtable, rtindex, sublevels_up);
+ return expandRelAttrs(pstate, rte, rtindex, sublevels_up);
}
}
found_table = true;
target = list_concat(target,
- expandRelAttrs(pstate, pstate->p_rtable,
- rtindex, 0));
+ expandRelAttrs(pstate, rte, rtindex, 0));
}
/* Check for SELECT *; */
*lvar;
int i;
- expandRTE(GetLevelNRangeTable(pstate, netlevelsup),
- var->varno, 0, false, &names, &vars);
+ expandRTE(rte, var->varno, 0, false,
+ &names, &vars);
tupleDesc = CreateTemplateTupleDesc(list_length(vars), false);
i = 1;
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.153 2005/06/03 23:05:28 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.154 2005/06/04 19:19:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Relation rel;
LOCKMODE lockmode;
List *newaliasvars;
+ Index curinputvarno;
+ RangeTblEntry *curinputrte;
ListCell *ll;
++rt_index;
* Scan the join's alias var list to see if any columns
* have been dropped, and if so replace those Vars with
* NULL Consts.
+ *
+ * Since a join has only two inputs, we can expect to
+ * see multiple references to the same input RTE; optimize
+ * away multiple fetches.
*/
newaliasvars = NIL;
+ curinputvarno = 0;
+ curinputrte = NULL;
foreach(ll, rte->joinaliasvars)
{
Var *aliasvar = (Var *) lfirst(ll);
* but it's OK to assume here.)
*/
Assert(aliasvar->varlevelsup == 0);
- if (aliasvar->varno >= rt_index)
- elog(ERROR, "unexpected varno %d in JOIN RTE %d",
- aliasvar->varno, rt_index);
- if (get_rte_attribute_is_dropped(
- rt_fetch(aliasvar->varno, parsetree->rtable),
- aliasvar->varattno))
+ if (aliasvar->varno != curinputvarno)
+ {
+ curinputvarno = aliasvar->varno;
+ if (curinputvarno >= rt_index)
+ elog(ERROR, "unexpected varno %d in JOIN RTE %d",
+ curinputvarno, rt_index);
+ curinputrte = rt_fetch(curinputvarno,
+ parsetree->rtable);
+ }
+ if (get_rte_attribute_is_dropped(curinputrte,
+ aliasvar->varattno))
{
/*
* can't use vartype here, since that might be a
sub_action = (Query *) ResolveNew((Node *) sub_action,
new_varno,
0,
- sub_action->rtable,
+ rt_fetch(new_varno,
+ sub_action->rtable),
parsetree->targetList,
event,
current_varno);
new_qual = ResolveNew(new_qual,
PRS2_NEW_VARNO,
0,
- parsetree->rtable,
+ rt_fetch(rt_index, parsetree->rtable),
parsetree->targetList,
event,
rt_index);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.90 2005/03/10 23:21:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.91 2005/06/04 19:19:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* If not, we either change the unmatched Var's varno to update_varno
* (when event == CMD_UPDATE) or replace it with a constant NULL.
*
- * The caller must also provide target_rtable, the rangetable containing
- * the target relation (which must be described by the target_varno'th
- * RTE in that list). This is needed to handle whole-row Vars referencing
- * the target. We expand such Vars into RowExpr constructs.
+ * The caller must also provide target_rte, the RTE describing the target
+ * relation. This is needed to handle whole-row Vars referencing the target.
+ * We expand such Vars into RowExpr constructs.
*
* Note: the business with inserted_sublink is needed to update hasSubLinks
* in subqueries when the replacement adds a subquery inside a subquery.
{
int target_varno;
int sublevels_up;
- List *target_rtable;
+ RangeTblEntry *target_rte;
List *targetlist;
int event;
int update_varno;
* include dummy items for dropped columns. If the var is
* RECORD (ie, this is a JOIN), then omit dropped columns.
*/
- expandRTE(context->target_rtable, this_varno, this_varlevelsup,
+ expandRTE(context->target_rte,
+ this_varno, this_varlevelsup,
(var->vartype != RECORDOID),
NULL, &fields);
/* Adjust the generated per-field Vars... */
Node *
ResolveNew(Node *node, int target_varno, int sublevels_up,
- List *target_rtable,
+ RangeTblEntry *target_rte,
List *targetlist, int event, int update_varno)
{
ResolveNew_context context;
context.target_varno = target_varno;
context.sublevels_up = sublevels_up;
- context.target_rtable = target_rtable;
+ context.target_rte = target_rte;
context.targetlist = targetlist;
context.event = event;
context.update_varno = update_varno;
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.49 2005/04/13 16:50:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.50 2005/06/04 19:19:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern RangeTblEntry *GetRTEByRangeTablePosn(ParseState *pstate,
int varno,
int sublevels_up);
-extern List *GetLevelNRangeTable(ParseState *pstate, int sublevels_up);
extern Node *scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte,
char *colname);
extern Node *colNameToVar(ParseState *pstate, char *colname, bool localonly);
extern void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte,
bool addToJoinList, bool addToNameSpace);
extern RangeTblEntry *addImplicitRTE(ParseState *pstate, RangeVar *relation);
-extern void expandRTE(List *rtable, int rtindex, int sublevels_up,
+extern void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
bool include_dropped,
List **colnames, List **colvars);
-extern List *expandRelAttrs(ParseState *pstate, List *rtable,
+extern List *expandRelAttrs(ParseState *pstate, RangeTblEntry *rte,
int rtindex, int sublevels_up);
extern int attnameAttNum(Relation rd, const char *attname, bool sysColOK);
extern Name attnumAttName(Relation rd, int attid);
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/rewrite/rewriteManip.h,v 1.40 2005/03/10 23:21:25 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/rewrite/rewriteManip.h,v 1.41 2005/06/04 19:19:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern bool checkExprHasSubLink(Node *node);
extern Node *ResolveNew(Node *node, int target_varno, int sublevels_up,
- List *target_rtable,
+ RangeTblEntry *target_rte,
List *targetlist, int event, int update_varno);
#endif /* REWRITEMANIP_H */