summaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_relation.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parse_relation.c')
-rw-r--r--src/backend/parser/parse_relation.c115
1 files changed, 74 insertions, 41 deletions
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 5009b0326b..f4078c9dfa 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.7 1998/01/20 05:04:24 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.8 1998/01/20 22:12:01 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -67,35 +67,57 @@ static char *attnum_type[SPECIALS] = {
/* given refname, return a pointer to the range table entry */
RangeTblEntry *
-refnameRangeTableEntry(List *rtable, char *refname)
+refnameRangeTableEntry(ParseState *pstate, char *refname)
{
List *temp;
- foreach(temp, rtable)
+ while (pstate != NULL)
{
- RangeTblEntry *rte = lfirst(temp);
-
- if (!strcmp(rte->refname, refname))
- return rte;
+ foreach(temp, pstate->p_rtable)
+ {
+ RangeTblEntry *rte = lfirst(temp);
+
+ if (!strcmp(rte->refname, refname))
+ return rte;
+ }
+ /* only allow correlated columns in WHERE clause */
+ if (pstate->p_in_where_clause)
+ pstate = pstate->parentParseState;
+ else break;
}
return NULL;
}
/* given refname, return id of variable; position starts with 1 */
int
-refnameRangeTablePosn(List *rtable, char *refname)
+refnameRangeTablePosn(ParseState *pstate, char *refname, int *sublevels_up)
{
int index;
List *temp;
- index = 1;
- foreach(temp, rtable)
- {
- RangeTblEntry *rte = lfirst(temp);
+
+ if (sublevels_up)
+ *sublevels_up = 0;
- if (!strcmp(rte->refname, refname))
- return index;
- index++;
+ while (pstate != NULL)
+ {
+ index = 1;
+ foreach(temp, pstate->p_rtable)
+ {
+ RangeTblEntry *rte = lfirst(temp);
+
+ if (!strcmp(rte->refname, refname))
+ return index;
+ index++;
+ }
+ /* only allow correlated columns in WHERE clause */
+ if (pstate->p_in_where_clause)
+ {
+ pstate = pstate->parentParseState;
+ if (sublevels_up)
+ (*sublevels_up)++;
+ }
+ else break;
}
return 0;
}
@@ -110,31 +132,38 @@ colnameRangeTableEntry(ParseState *pstate, char *colname)
List *rtable;
RangeTblEntry *rte_result;
- if (pstate->p_is_rule)
- rtable = lnext(lnext(pstate->p_rtable));
- else
- rtable = pstate->p_rtable;
-
rte_result = NULL;
- foreach(et, rtable)
+ while (pstate != NULL)
{
- RangeTblEntry *rte = lfirst(et);
-
- /* only entries on outer(non-function?) scope */
- if (!rte->inFromCl && rte != pstate->p_target_rangetblentry)
- continue;
+ if (pstate->p_is_rule)
+ rtable = lnext(lnext(pstate->p_rtable));
+ else
+ rtable = pstate->p_rtable;
- if (get_attnum(rte->relid, colname) != InvalidAttrNumber)
+ foreach(et, rtable)
{
- if (rte_result != NULL)
+ RangeTblEntry *rte = lfirst(et);
+
+ /* only entries on outer(non-function?) scope */
+ if (!rte->inFromCl && rte != pstate->p_target_rangetblentry)
+ continue;
+
+ if (get_attnum(rte->relid, colname) != InvalidAttrNumber)
{
- if (!pstate->p_is_insert ||
- rte != pstate->p_target_rangetblentry)
- elog(ERROR, "Column %s is ambiguous", colname);
+ if (rte_result != NULL)
+ {
+ if (!pstate->p_is_insert ||
+ rte != pstate->p_target_rangetblentry)
+ elog(ERROR, "Column %s is ambiguous", colname);
+ }
+ else
+ rte_result = rte;
}
- else
- rte_result = rte;
}
+ /* only allow correlated columns in WHERE clause */
+ if (pstate->p_in_where_clause && rte_result == NULL)
+ pstate = pstate->parentParseState;
+ else break;
}
return rte_result;
}
@@ -152,11 +181,15 @@ addRangeTableEntry(ParseState *pstate,
{
Relation relation;
RangeTblEntry *rte = makeNode(RangeTblEntry);
+ int sublevels_up;
- if (pstate != NULL &&
- refnameRangeTableEntry(pstate->p_rtable, refname) != NULL)
- elog(ERROR, "Table name %s specified more than once", refname);
-
+ if (pstate != NULL)
+ {
+ if (refnameRangeTablePosn(pstate, refname, &sublevels_up) != 0 &&
+ (!inFromCl || sublevels_up == 0))
+ elog(ERROR, "Table name %s specified more than once", refname);
+ }
+
rte->relname = pstrdup(relname);
rte->refname = pstrdup(refname);
@@ -191,7 +224,6 @@ addRangeTableEntry(ParseState *pstate,
/*
* expandAll -
* makes a list of attributes
- * assumes reldesc caching works
*/
List *
expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
@@ -206,7 +238,7 @@ expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
int type_len;
RangeTblEntry *rte;
- rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+ rte = refnameRangeTableEntry(pstate, refname);
if (rte == NULL)
rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE);
@@ -225,7 +257,8 @@ expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
TargetEntry *te = makeNode(TargetEntry);
attrname = pstrdup((rdesc->rd_att->attrs[varattno]->attname).data);
- varnode = (Var *) make_var(pstate, refname, attrname, &type_id);
+ varnode = (Var *) make_var(pstate, rte->relid, refname,
+ attrname, &type_id);
type_len = (int) typeLen(typeidType(type_id));
handleTargetColname(pstate, &resname, refname, attrname);
@@ -381,7 +414,7 @@ checkTargetTypes(ParseState *pstate, char *target_colname,
return;
if (refname != NULL)
- rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+ rte = refnameRangeTableEntry(pstate, refname);
else
{
rte = colnameRangeTableEntry(pstate, colname);