提交 bbd6eb5b 编写于 作者: T Tom Lane

Repair some issues with column aliases and RowExpr construction in the

presence of dropped columns.  Document the already-presumed fact that
eref aliases in relation RTEs are supposed to have entries for dropped
columns; cause the user alias structs to have such entries too, so that
there's always a one-to-one mapping to the underlying physical attnums.
Adjust expandRTE() and related code to handle the case where a column
that is part of a JOIN has been dropped.  Generalize expandRTE()'s API
so that it can be used in a couple of places that formerly rolled their
own implementation of the same logic.  Fix ruleutils.c to suppress
display of aliases for columns that were dropped since the rule was made.
上级 040450be
......@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.36 2004/05/26 04:41:06 neilc Exp $
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.37 2004/08/19 20:57:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -970,10 +970,15 @@ find_expr_references_walker(Node *node,
if (var->varno <= 0 || var->varno > list_length(rtable))
elog(ERROR, "invalid varno %d", var->varno);
rte = rt_fetch(var->varno, rtable);
/*
* A whole-row Var references no specific columns, so adds no new
* dependency.
*/
if (var->varattno == InvalidAttrNumber)
return false;
if (rte->rtekind == RTE_RELATION)
{
/* If it's a plain relation, reference this column */
/* NB: this code works for whole-row Var with attno 0, too */
add_object_address(OCLASS_CLASS, rte->relid, var->varattno,
&context->addrs);
}
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.118 2004/06/05 01:55:04 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.119 2004/08/19 20:57:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -57,10 +57,10 @@ static void compare_tlist_datatypes(List *tlist, List *colTypes,
bool *differentTypes);
static bool qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
bool *differentTypes);
static void subquery_push_qual(Query *subquery,
RangeTblEntry *rte, Index rti, Node *qual);
static void subquery_push_qual(Query *subquery, List *rtable,
Index rti, Node *qual);
static void recurse_push_qual(Node *setOp, Query *topquery,
RangeTblEntry *rte, Index rti, Node *qual);
List *rtable, Index rti, Node *qual);
/*
......@@ -376,7 +376,7 @@ set_subquery_pathlist(Query *root, RelOptInfo *rel,
if (qual_is_pushdown_safe(subquery, rti, clause, differentTypes))
{
/* Push it down */
subquery_push_qual(subquery, rte, rti, clause);
subquery_push_qual(subquery, root->rtable, rti, clause);
}
else
{
......@@ -780,12 +780,13 @@ qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
* subquery_push_qual - push down a qual that we have determined is safe
*/
static void
subquery_push_qual(Query *subquery, RangeTblEntry *rte, Index rti, Node *qual)
subquery_push_qual(Query *subquery, List *rtable, Index rti, Node *qual)
{
if (subquery->setOperations != NULL)
{
/* Recurse to push it separately to each component query */
recurse_push_qual(subquery->setOperations, subquery, rte, rti, qual);
recurse_push_qual(subquery->setOperations, subquery,
rtable, rti, qual);
}
else
{
......@@ -799,7 +800,7 @@ subquery_push_qual(Query *subquery, RangeTblEntry *rte, Index rti, Node *qual)
* 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, rte,
qual = ResolveNew(qual, rti, 0, rtable,
subquery->targetList,
CMD_SELECT, 0);
subquery->havingQual = make_and_qual(subquery->havingQual,
......@@ -818,7 +819,7 @@ subquery_push_qual(Query *subquery, RangeTblEntry *rte, Index rti, Node *qual)
*/
static void
recurse_push_qual(Node *setOp, Query *topquery,
RangeTblEntry *rte, Index rti, Node *qual)
List *rtable, Index rti, Node *qual)
{
if (IsA(setOp, RangeTblRef))
{
......@@ -827,14 +828,14 @@ recurse_push_qual(Node *setOp, Query *topquery,
Query *subquery = subrte->subquery;
Assert(subquery != NULL);
subquery_push_qual(subquery, rte, rti, qual);
subquery_push_qual(subquery, rtable, rti, qual);
}
else if (IsA(setOp, SetOperationStmt))
{
SetOperationStmt *op = (SetOperationStmt *) setOp;
recurse_push_qual(op->larg, topquery, rte, rti, qual);
recurse_push_qual(op->rarg, topquery, rte, rti, qual);
recurse_push_qual(op->larg, topquery, rtable, rti, qual);
recurse_push_qual(op->rarg, topquery, rtable, rti, qual);
}
else
{
......
......@@ -16,7 +16,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.20 2004/05/30 23:40:29 neilc Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.21 2004/08/19 20:57:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -46,7 +46,7 @@ typedef struct reduce_outer_joins_state
static bool is_simple_subquery(Query *subquery);
static bool has_nullable_targetlist(Query *subquery);
static void resolvenew_in_jointree(Node *jtnode, int varno,
RangeTblEntry *rte, List *subtlist);
List *rtable, 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,
......@@ -243,16 +243,19 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join)
subtlist = subquery->targetList;
parse->targetList = (List *)
ResolveNew((Node *) parse->targetList,
varno, 0, rte, subtlist, CMD_SELECT, 0);
varno, 0, parse->rtable,
subtlist, CMD_SELECT, 0);
resolvenew_in_jointree((Node *) parse->jointree, varno,
rte, subtlist);
parse->rtable, subtlist);
Assert(parse->setOperations == NULL);
parse->havingQual =
ResolveNew(parse->havingQual,
varno, 0, rte, subtlist, CMD_SELECT, 0);
varno, 0, parse->rtable,
subtlist, CMD_SELECT, 0);
parse->in_info_list = (List *)
ResolveNew((Node *) parse->in_info_list,
varno, 0, rte, subtlist, CMD_SELECT, 0);
varno, 0, parse->rtable,
subtlist, CMD_SELECT, 0);
foreach(rt, parse->rtable)
{
......@@ -261,7 +264,8 @@ pull_up_subqueries(Query *parse, Node *jtnode, bool below_outer_join)
if (otherrte->rtekind == RTE_JOIN)
otherrte->joinaliasvars = (List *)
ResolveNew((Node *) otherrte->joinaliasvars,
varno, 0, rte, subtlist, CMD_SELECT, 0);
varno, 0, parse->rtable,
subtlist, CMD_SELECT, 0);
}
/*
......@@ -477,7 +481,7 @@ has_nullable_targetlist(Query *subquery)
*/
static void
resolvenew_in_jointree(Node *jtnode, int varno,
RangeTblEntry *rte, List *subtlist)
List *rtable, List *subtlist)
{
if (jtnode == NULL)
return;
......@@ -491,18 +495,20 @@ resolvenew_in_jointree(Node *jtnode, int varno,
ListCell *l;
foreach(l, f->fromlist)
resolvenew_in_jointree(lfirst(l), varno, rte, subtlist);
resolvenew_in_jointree(lfirst(l), varno, rtable, subtlist);
f->quals = ResolveNew(f->quals,
varno, 0, rte, subtlist, CMD_SELECT, 0);
varno, 0, rtable,
subtlist, CMD_SELECT, 0);
}
else if (IsA(jtnode, JoinExpr))
{
JoinExpr *j = (JoinExpr *) jtnode;
resolvenew_in_jointree(j->larg, varno, rte, subtlist);
resolvenew_in_jointree(j->rarg, varno, rte, subtlist);
resolvenew_in_jointree(j->larg, varno, rtable, subtlist);
resolvenew_in_jointree(j->rarg, varno, rtable, subtlist);
j->quals = ResolveNew(j->quals,
varno, 0, rte, subtlist, CMD_SELECT, 0);
varno, 0, rtable,
subtlist, CMD_SELECT, 0);
/*
* We don't bother to update the colvars list, since it won't be
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.59 2004/06/01 04:47:46 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.60 2004/08/19 20:57:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -515,11 +515,19 @@ flatten_join_alias_vars_mutator(Node *node,
/* Must expand whole-row reference */
RowExpr *rowexpr;
List *fields = NIL;
AttrNumber attnum;
ListCell *l;
attnum = 0;
foreach(l, rte->joinaliasvars)
{
newvar = (Node *) lfirst(l);
attnum++;
/* Ignore dropped columns */
if (get_rte_attribute_is_dropped(context->root->rtable,
var->varno,
attnum))
continue;
/*
* If we are expanding an alias carried down from an upper
* query, must adjust its varlevelsup fields.
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.133 2004/06/16 01:26:44 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.134 2004/08/19 20:57:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -655,8 +655,8 @@ transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels)
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(j->larg));
leftrti = 0; /* keep compiler quiet */
}
rte = rt_fetch(leftrti, pstate->p_rtable);
expandRTE(pstate, rte, &l_colnames, &l_colvars);
expandRTE(pstate->p_rtable, leftrti, 0, false,
&l_colnames, &l_colvars);
if (IsA(j->rarg, RangeTblRef))
rightrti = ((RangeTblRef *) j->rarg)->rtindex;
......@@ -667,8 +667,8 @@ transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels)
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(j->rarg));
rightrti = 0; /* keep compiler quiet */
}
rte = rt_fetch(rightrti, pstate->p_rtable);
expandRTE(pstate, rte, &r_colnames, &r_colvars);
expandRTE(pstate->p_rtable, rightrti, 0, false,
&r_colnames, &r_colvars);
/*
* Natural join does not explicitly specify columns; must generate
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.120 2004/08/17 18:47:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.121 2004/08/19 20:57:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -662,29 +662,12 @@ coerce_record_to_complex(ParseState *pstate, Node *node,
else if (node && IsA(node, Var) &&
((Var *) node)->varattno == InvalidAttrNumber)
{
RangeTblEntry *rte;
AttrNumber nfields;
AttrNumber nf;
rte = GetRTEByRangeTablePosn(pstate,
((Var *) node)->varno,
((Var *) node)->varlevelsup);
nfields = list_length(rte->eref->colnames);
for (nf = 1; nf <= nfields; nf++)
{
Oid vartype;
int32 vartypmod;
int rtindex = ((Var *) node)->varno;
int sublevels_up = ((Var *) node)->varlevelsup;
List *rtable;
if (get_rte_attribute_is_dropped(rte, nf))
continue;
get_rte_attribute_type(rte, nf, &vartype, &vartypmod);
args = lappend(args,
makeVar(((Var *) node)->varno,
nf,
vartype,
vartypmod,
((Var *) node)->varlevelsup));
}
rtable = GetLevelNRangeTable(pstate, sublevels_up);
expandRTE(rtable, rtindex, sublevels_up, false, NULL, &args);
}
else
ereport(ERROR,
......
此差异已折叠。
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.122 2004/06/19 18:19:55 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.123 2004/08/19 20:57:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -699,6 +699,8 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref)
char *relname;
RangeTblEntry *rte;
int sublevels_up;
int rtindex;
List *rtable;
switch (numnames)
{
......@@ -743,7 +745,10 @@ ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref)
rte = addImplicitRTE(pstate, makeRangeVar(schemaname,
relname));
return expandRelAttrs(pstate, rte);
rtindex = RTERangeTablePosn(pstate, rte, &sublevels_up);
rtable = GetLevelNRangeTable(pstate, sublevels_up);
return expandRelAttrs(pstate, rtable, rtindex, sublevels_up);
}
}
......@@ -765,29 +770,31 @@ ExpandAllTables(ParseState *pstate)
foreach(ns, pstate->p_namespace)
{
Node *n = (Node *) lfirst(ns);
int rtindex;
RangeTblEntry *rte;
if (IsA(n, RangeTblRef))
rte = rt_fetch(((RangeTblRef *) n)->rtindex,
pstate->p_rtable);
rtindex = ((RangeTblRef *) n)->rtindex;
else if (IsA(n, JoinExpr))
rte = rt_fetch(((JoinExpr *) n)->rtindex,
pstate->p_rtable);
rtindex = ((JoinExpr *) n)->rtindex;
else
{
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(n));
rte = NULL; /* keep compiler quiet */
rtindex = 0; /* keep compiler quiet */
}
/*
* Ignore added-on relations that were not listed in the FROM
* clause.
*/
rte = rt_fetch(rtindex, pstate->p_rtable);
if (!rte->inFromCl)
continue;
found_table = true;
target = list_concat(target, expandRelAttrs(pstate, rte));
target = list_concat(target,
expandRelAttrs(pstate, pstate->p_rtable,
rtindex, 0));
}
/* Check for SELECT *; */
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.141 2004/08/07 17:40:49 tgl Exp $
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.142 2004/08/19 20:57:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -214,8 +214,7 @@ rewriteRuleAction(Query *parsetree,
sub_action = (Query *) ResolveNew((Node *) sub_action,
new_varno,
0,
rt_fetch(new_varno,
sub_action->rtable),
sub_action->rtable,
parsetree->targetList,
event,
current_varno);
......@@ -1040,7 +1039,7 @@ CopyAndAddInvertedQual(Query *parsetree,
new_qual = ResolveNew(new_qual,
PRS2_NEW_VARNO,
0,
rt_fetch(rt_index, parsetree->rtable),
parsetree->rtable,
parsetree->targetList,
event,
rt_index);
......
......@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.85 2004/08/17 18:47:09 tgl Exp $
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.86 2004/08/19 20:57:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -18,7 +18,7 @@
#include "optimizer/clauses.h"
#include "optimizer/tlist.h"
#include "parser/parsetree.h"
#include "parser/parse_clause.h"
#include "parser/parse_relation.h"
#include "rewrite/rewriteManip.h"
#include "utils/lsyscache.h"
......@@ -853,9 +853,10 @@ AddInvertedQual(Query *parsetree, Node *qual)
* 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_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.
* 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.
*
* Note: the business with inserted_sublink is needed to update hasSubLinks
* in subqueries when the replacement adds a subquery inside a subquery.
......@@ -868,7 +869,7 @@ typedef struct
{
int target_varno;
int sublevels_up;
RangeTblEntry *target_rte;
List *target_rtable;
List *targetlist;
int event;
int update_varno;
......@@ -931,40 +932,21 @@ ResolveNew_mutator(Node *node, ResolveNew_context *context)
if (var->varattno == InvalidAttrNumber)
{
/* Must expand whole-tuple reference into RowExpr */
RangeTblEntry *rte = context->target_rte;
RowExpr *rowexpr;
List *fields = NIL;
AttrNumber nfields = list_length(rte->eref->colnames);
AttrNumber nf;
for (nf = 1; nf <= nfields; nf++)
{
if (get_rte_attribute_is_dropped(rte, nf))
{
/*
* can't determine att type here, but it doesn't
* really matter what type the Const claims to be.
*/
fields = lappend(fields,
makeNullConst(INT4OID));
}
else
{
Oid vartype;
int32 vartypmod;
Var *newvar;
get_rte_attribute_type(rte, nf, &vartype, &vartypmod);
newvar = makeVar(this_varno,
nf,
vartype,
vartypmod,
this_varlevelsup);
fields = lappend(fields,
resolve_one_var(newvar, context));
}
}
List *fields;
/*
* If generating an expansion for a var of a named rowtype
* (ie, this is a plain relation RTE), then we must 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,
(var->vartype != RECORDOID),
NULL, &fields);
/* Adjust the generated per-field Vars... */
fields = (List *) ResolveNew_mutator((Node *) fields,
context);
rowexpr = makeNode(RowExpr);
rowexpr->args = fields;
rowexpr->row_typeid = var->vartype;
......@@ -1003,14 +985,14 @@ ResolveNew_mutator(Node *node, ResolveNew_context *context)
Node *
ResolveNew(Node *node, int target_varno, int sublevels_up,
RangeTblEntry *target_rte,
List *target_rtable,
List *targetlist, int event, int update_varno)
{
ResolveNew_context context;
context.target_varno = target_varno;
context.sublevels_up = sublevels_up;
context.target_rte = target_rte;
context.target_rtable = target_rtable;
context.targetlist = targetlist;
context.event = event;
context.update_varno = update_varno;
......
......@@ -3,7 +3,7 @@
* back to source text
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.177 2004/08/17 18:47:09 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.178 2004/08/19 20:57:41 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
......@@ -203,6 +203,8 @@ static void get_sublink_expr(SubLink *sublink, deparse_context *context);
static void get_from_clause(Query *query, deparse_context *context);
static void get_from_clause_item(Node *jtnode, Query *query,
deparse_context *context);
static void get_from_clause_alias(Alias *alias, int varno,
Query *query, deparse_context *context);
static void get_from_clause_coldeflist(List *coldeflist,
deparse_context *context);
static void get_opclass_name(Oid opclass, Oid actual_datatype,
......@@ -3962,20 +3964,8 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
appendStringInfo(buf, " %s",
quote_identifier(rte->alias->aliasname));
gavealias = true;
if (rte->alias->colnames != NIL && coldeflist == NIL)
{
ListCell *col;
appendStringInfoChar(buf, '(');
foreach(col, rte->alias->colnames)
{
if (col != list_head(rte->alias->colnames))
appendStringInfo(buf, ", ");
appendStringInfoString(buf,
quote_identifier(strVal(lfirst(col))));
}
appendStringInfoChar(buf, ')');
}
if (coldeflist == NIL)
get_from_clause_alias(rte->alias, varno, query, context);
}
else if (rte->rtekind == RTE_RELATION &&
strcmp(rte->eref->aliasname, get_rel_name(rte->relid)) != 0)
......@@ -4128,20 +4118,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
{
appendStringInfo(buf, " %s",
quote_identifier(j->alias->aliasname));
if (j->alias->colnames != NIL)
{
ListCell *col;
appendStringInfoChar(buf, '(');
foreach(col, j->alias->colnames)
{
if (col != list_head(j->alias->colnames))
appendStringInfo(buf, ", ");
appendStringInfoString(buf,
quote_identifier(strVal(lfirst(col))));
}
appendStringInfoChar(buf, ')');
}
get_from_clause_alias(j->alias, j->rtindex, query, context);
}
}
else
......@@ -4149,6 +4126,43 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
(int) nodeTag(jtnode));
}
/*
* get_from_clause_alias - reproduce column alias list
*
* This is tricky because we must ignore dropped columns.
*/
static void
get_from_clause_alias(Alias *alias, int varno,
Query *query, deparse_context *context)
{
StringInfo buf = context->buf;
ListCell *col;
AttrNumber attnum;
bool first = true;
if (alias == NULL || alias->colnames == NIL)
return; /* definitely nothing to do */
attnum = 0;
foreach(col, alias->colnames)
{
attnum++;
if (get_rte_attribute_is_dropped(query->rtable, varno, attnum))
continue;
if (first)
{
appendStringInfoChar(buf, '(');
first = false;
}
else
appendStringInfo(buf, ", ");
appendStringInfoString(buf,
quote_identifier(strVal(lfirst(col))));
}
if (!first)
appendStringInfoChar(buf, ')');
}
/*
* get_from_clause_coldeflist - reproduce FROM clause coldeflist
*
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.265 2004/08/04 21:34:24 tgl Exp $
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.266 2004/08/19 20:57:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -447,6 +447,22 @@ typedef struct DefElem
* eref->aliasname is required to be present, and should generally be used
* to identify the RTE for error messages etc.
*
* In RELATION RTEs, the colnames in both alias and eref are indexed by
* physical attribute number; this means there must be colname entries for
* dropped columns. When building an RTE we insert empty strings ("") for
* dropped columns. Note however that a stored rule may have nonempty
* colnames for columns dropped since the rule was created (and for that
* matter the colnames might be out of date due to column renamings).
* The same comments apply to FUNCTION RTEs when the function's return type
* is a named composite type.
*
* In JOIN RTEs, the colnames in both alias and eref are one-to-one with
* joinaliasvars entries. A JOIN RTE will omit columns of its inputs when
* those columns are known to be dropped at parse time. Again, however,
* a stored rule might contain entries for columns dropped since the rule
* was created. (This is only possible for columns not actually referenced
* in the rule.)
*
* inh is TRUE for relation references that should be expanded to include
* inheritance children, if the rel has any. This *must* be FALSE for
* RTEs other than RTE_RELATION entries.
......
......@@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.101 2004/08/17 18:47:09 tgl Exp $
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.102 2004/08/19 20:57:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -98,9 +98,9 @@ typedef struct Resdom
* specifies an alias for a range variable; the alias might also
* specify renaming of columns within the table.
*
* Note: colnames is a list of Value nodes (always strings). In an RTE's
* eref Alias, the colnames list includes dropped columns, so that the
* colname list position matches the physical attribute number.
* Note: colnames is a list of Value nodes (always strings). In Alias structs
* associated with RTEs, there may be entries corresponding to dropped
* columns; these are normally empty strings (""). See parsenodes.h for info.
*/
typedef struct Alias
{
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.44 2004/04/18 18:12:58 tgl Exp $
* $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.45 2004/08/19 20:57:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -30,6 +30,7 @@ extern int RTERangeTablePosn(ParseState *pstate,
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);
......@@ -66,9 +67,11 @@ extern RangeTblEntry *addRangeTableEntryForJoin(ParseState *pstate,
extern void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte,
bool addToJoinList, bool addToNameSpace);
extern RangeTblEntry *addImplicitRTE(ParseState *pstate, RangeVar *relation);
extern void expandRTE(ParseState *pstate, RangeTblEntry *rte,
List **colnames, List **colvars);
extern List *expandRelAttrs(ParseState *pstate, RangeTblEntry *rte);
extern void expandRTE(List *rtable, int rtindex, int sublevels_up,
bool include_dropped,
List **colnames, List **colvars);
extern List *expandRelAttrs(ParseState *pstate, List *rtable,
int rtindex, int sublevels_up);
extern int attnameAttNum(Relation rd, const char *attname, bool sysColOK);
extern Name attnumAttName(Relation rd, int attid);
extern Oid attnumTypeId(Relation rd, int attid);
......
......@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/parser/parsetree.h,v 1.25 2004/08/17 18:47:09 tgl Exp $
* $PostgreSQL: pgsql/src/include/parser/parsetree.h,v 1.26 2004/08/19 20:57:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -59,7 +59,7 @@ extern void get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
* Check whether an attribute of an RTE has been dropped (note that
* get_rte_attribute_type will fail on such an attr)
*/
extern bool get_rte_attribute_is_dropped(RangeTblEntry *rte,
extern bool get_rte_attribute_is_dropped(List *rtable, int rtindex,
AttrNumber attnum);
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/rewrite/rewriteManip.h,v 1.35 2004/05/10 22:44:49 tgl Exp $
* $PostgreSQL: pgsql/src/include/rewrite/rewriteManip.h,v 1.36 2004/08/19 20:57:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -38,7 +38,7 @@ extern bool checkExprHasAggs(Node *node);
extern bool checkExprHasSubLink(Node *node);
extern Node *ResolveNew(Node *node, int target_varno, int sublevels_up,
RangeTblEntry *target_rte,
List *target_rtable,
List *targetlist, int event, int update_varno);
#endif /* REWRITEMANIP_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册