aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/parse_relation.c48
-rw-r--r--src/backend/parser/parse_target.c158
2 files changed, 109 insertions, 97 deletions
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index f9c3a8ba039..b8c2d8c8e36 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.87 2003/08/04 02:40:02 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.88 2003/08/11 20:46:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1599,21 +1599,14 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
case RTE_SUBQUERY:
{
/* Subselect RTE --- get type info from subselect's tlist */
- List *tlistitem;
-
- foreach(tlistitem, rte->subquery->targetList)
- {
- TargetEntry *te = (TargetEntry *) lfirst(tlistitem);
-
- if (te->resdom->resjunk || te->resdom->resno != attnum)
- continue;
- *vartype = te->resdom->restype;
- *vartypmod = te->resdom->restypmod;
- return;
- }
- /* falling off end of list shouldn't happen... */
- elog(ERROR, "subquery %s does not have attribute %d",
- rte->eref->aliasname, attnum);
+ TargetEntry *te = get_tle_by_resno(rte->subquery->targetList,
+ attnum);
+
+ if (te == NULL || te->resdom->resjunk)
+ elog(ERROR, "subquery %s does not have attribute %d",
+ rte->eref->aliasname, attnum);
+ *vartype = te->resdom->restype;
+ *vartypmod = te->resdom->restypmod;
}
break;
case RTE_FUNCTION:
@@ -1778,6 +1771,29 @@ get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
}
/*
+ * Given a targetlist and a resno, return the matching TargetEntry
+ *
+ * Returns NULL if resno is not present in list.
+ *
+ * Note: we need to search, rather than just indexing with nth(), because
+ * not all tlists are sorted by resno.
+ */
+TargetEntry *
+get_tle_by_resno(List *tlist, AttrNumber resno)
+{
+ List *i;
+
+ foreach(i, tlist)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(i);
+
+ if (tle->resdom->resno == resno)
+ return tle;
+ }
+ return NULL;
+}
+
+/*
* given relation and att name, return id of variable
*
* This should only be used if the relation is already
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 2f1233da7ca..a525e8795f0 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.110 2003/08/04 02:40:02 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.111 2003/08/11 20:46:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -100,49 +100,55 @@ transformTargetEntry(ParseState *pstate,
List *
transformTargetList(ParseState *pstate, List *targetlist)
{
- List *p_target = NIL;
+ FastList p_target;
+ List *o_target;
- while (targetlist != NIL)
+ FastListInit(&p_target);
+
+ foreach(o_target, targetlist)
{
- ResTarget *res = (ResTarget *) lfirst(targetlist);
+ ResTarget *res = (ResTarget *) lfirst(o_target);
if (IsA(res->val, ColumnRef))
{
ColumnRef *cref = (ColumnRef *) res->val;
List *fields = cref->fields;
- int numnames = length(fields);
- if (numnames == 1 && strcmp(strVal(lfirst(fields)), "*") == 0)
- {
- /*
- * Target item is a single '*', expand all tables (eg.
- * SELECT * FROM emp)
- */
- p_target = nconc(p_target,
- ExpandAllTables(pstate));
- }
- else if (strcmp(strVal(nth(numnames - 1, fields)), "*") == 0)
+ if (strcmp(strVal(llast(fields)), "*") == 0)
{
- /*
- * Target item is relation.*, expand that table (eg.
- * SELECT emp.*, dname FROM emp, dept)
- */
- char *schemaname;
- char *relname;
- RangeTblEntry *rte;
- int sublevels_up;
-
- switch (numnames)
+ int numnames = length(fields);
+
+ if (numnames == 1)
{
- case 2:
- schemaname = NULL;
- relname = strVal(lfirst(fields));
- break;
- case 3:
- schemaname = strVal(lfirst(fields));
- relname = strVal(lsecond(fields));
- break;
- case 4:
+ /*
+ * Target item is a single '*', expand all tables
+ * (e.g., SELECT * FROM emp)
+ */
+ FastConc(&p_target,
+ ExpandAllTables(pstate));
+ }
+ else
+ {
+ /*
+ * Target item is relation.*, expand that table
+ * (e.g., SELECT emp.*, dname FROM emp, dept)
+ */
+ char *schemaname;
+ char *relname;
+ RangeTblEntry *rte;
+ int sublevels_up;
+
+ switch (numnames)
+ {
+ case 2:
+ schemaname = NULL;
+ relname = strVal(lfirst(fields));
+ break;
+ case 3:
+ schemaname = strVal(lfirst(fields));
+ relname = strVal(lsecond(fields));
+ break;
+ case 4:
{
char *name1 = strVal(lfirst(fields));
@@ -152,57 +158,56 @@ transformTargetList(ParseState *pstate, List *targetlist)
*/
if (strcmp(name1, get_database_name(MyDatabaseId)) != 0)
ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("cross-database references are not implemented")));
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cross-database references are not implemented")));
schemaname = strVal(lsecond(fields));
relname = strVal(lthird(fields));
break;
}
- default:
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("improper qualified name (too many dotted names): %s",
- NameListToString(fields))));
- schemaname = NULL; /* keep compiler quiet */
- relname = NULL;
- break;
- }
+ default:
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("improper qualified name (too many dotted names): %s",
+ NameListToString(fields))));
+ schemaname = NULL; /* keep compiler quiet */
+ relname = NULL;
+ break;
+ }
- rte = refnameRangeTblEntry(pstate, schemaname, relname,
- &sublevels_up);
- if (rte == NULL)
- rte = addImplicitRTE(pstate, makeRangeVar(schemaname,
- relname));
+ rte = refnameRangeTblEntry(pstate, schemaname, relname,
+ &sublevels_up);
+ if (rte == NULL)
+ rte = addImplicitRTE(pstate, makeRangeVar(schemaname,
+ relname));
- p_target = nconc(p_target,
- expandRelAttrs(pstate, rte));
+ FastConc(&p_target,
+ expandRelAttrs(pstate, rte));
+ }
}
else
{
/* Plain ColumnRef node, treat it as an expression */
- p_target = lappend(p_target,
- transformTargetEntry(pstate,
- res->val,
- NULL,
- res->name,
- false));
+ FastAppend(&p_target,
+ transformTargetEntry(pstate,
+ res->val,
+ NULL,
+ res->name,
+ false));
}
}
else
{
/* Everything else but ColumnRef */
- p_target = lappend(p_target,
- transformTargetEntry(pstate,
- res->val,
- NULL,
- res->name,
- false));
+ FastAppend(&p_target,
+ transformTargetEntry(pstate,
+ res->val,
+ NULL,
+ res->name,
+ false));
}
-
- targetlist = lnext(targetlist);
}
- return p_target;
+ return FastListValue(&p_target);
}
@@ -264,23 +269,14 @@ markTargetListOrigin(ParseState *pstate, Resdom *res, Var *var)
case RTE_SUBQUERY:
{
/* Subselect-in-FROM: copy up from the subselect */
- List *subtl;
+ TargetEntry *te = get_tle_by_resno(rte->subquery->targetList,
+ attnum);
- foreach(subtl, rte->subquery->targetList)
- {
- TargetEntry *subte = (TargetEntry *) lfirst(subtl);
-
- if (subte->resdom->resjunk ||
- subte->resdom->resno != attnum)
- continue;
- res->resorigtbl = subte->resdom->resorigtbl;
- res->resorigcol = subte->resdom->resorigcol;
- break;
- }
- /* falling off end of list shouldn't happen... */
- if (subtl == NIL)
+ if (te == NULL || te->resdom->resjunk)
elog(ERROR, "subquery %s does not have attribute %d",
rte->eref->aliasname, attnum);
+ res->resorigtbl = te->resdom->resorigtbl;
+ res->resorigcol = te->resdom->resorigcol;
}
break;
case RTE_JOIN: