diff options
Diffstat (limited to 'src/backend/parser/parse_relation.c')
-rw-r--r-- | src/backend/parser/parse_relation.c | 115 |
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); |