aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_target.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-09-12 21:07:18 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-09-12 21:07:18 +0000
commited5003c58401e5727fcdd970505972394c95febb (patch)
tree53c25d5c65d6f7275f110503f51ab370e55af6ea /src/backend/parser/parse_target.c
parentb5c0ab278bc67bc7f363da7d828a08ce7c4d28c2 (diff)
downloadpostgresql-ed5003c58401e5727fcdd970505972394c95febb.tar.gz
postgresql-ed5003c58401e5727fcdd970505972394c95febb.zip
First cut at full support for OUTER JOINs. There are still a few loose
ends to clean up (see my message of same date to pghackers), but mostly it works. INITDB REQUIRED!
Diffstat (limited to 'src/backend/parser/parse_target.c')
-rw-r--r--src/backend/parser/parse_target.c142
1 files changed, 66 insertions, 76 deletions
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 1564f976b04..b8e1570985f 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -8,13 +8,14 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.61 2000/08/08 15:42:04 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.62 2000/09/12 21:07:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "nodes/makefuncs.h"
+#include "parser/parsetree.h"
#include "parser/parse_coerce.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
@@ -104,36 +105,8 @@ transformTargetList(ParseState *pstate, List *targetlist)
* Target item is a single '*', expand all tables (eg.
* SELECT * FROM emp)
*/
- if (pstate->p_shape != NULL)
- {
- List *s,
- *a;
- int i;
-
- Assert(length(pstate->p_shape) == length(pstate->p_alias));
-
- s = pstate->p_shape;
- a = pstate->p_alias;
- for (i = 0; i < length(pstate->p_shape); i++)
- {
- TargetEntry *te;
- char *colname;
- Attr *shape = lfirst(s);
- Attr *alias = lfirst(a);
-
- Assert(IsA(shape, Attr) &&IsA(alias, Attr));
-
- colname = strVal(lfirst(alias->attrs));
- te = transformTargetEntry(pstate, (Node *) shape,
- NULL, colname, false);
- p_target = lappend(p_target, te);
- s = lnext(s);
- a = lnext(a);
- }
- }
- else
- p_target = nconc(p_target,
- ExpandAllTables(pstate));
+ p_target = nconc(p_target,
+ ExpandAllTables(pstate));
}
else if (att->attrs != NIL &&
strcmp(strVal(lfirst(att->attrs)), "*") == 0)
@@ -143,10 +116,30 @@ transformTargetList(ParseState *pstate, List *targetlist)
* Target item is relation.*, expand that table (eg.
* SELECT emp.*, dname FROM emp, dept)
*/
- p_target = nconc(p_target,
- expandAll(pstate, att->relname,
- makeAttr(att->relname, NULL),
- &pstate->p_last_resno));
+ Node *rteorjoin;
+ int sublevels_up;
+
+ rteorjoin = refnameRangeOrJoinEntry(pstate, att->relname,
+ &sublevels_up);
+
+ if (rteorjoin == NULL)
+ {
+ rteorjoin = (Node *) addImplicitRTE(pstate, att->relname);
+ sublevels_up = 0;
+ }
+
+ if (IsA(rteorjoin, RangeTblEntry))
+ p_target = nconc(p_target,
+ expandRelAttrs(pstate,
+ (RangeTblEntry *) rteorjoin));
+ else if (IsA(rteorjoin, JoinExpr))
+ p_target = nconc(p_target,
+ expandJoinAttrs(pstate,
+ (JoinExpr *) rteorjoin,
+ sublevels_up));
+ else
+ elog(ERROR, "transformTargetList: unexpected node type %d",
+ nodeTag(rteorjoin));
}
else
{
@@ -219,23 +212,12 @@ updateTargetListEntry(ParseState *pstate,
*/
if (indirection)
{
-#ifndef DISABLE_JOIN_SYNTAX
- Attr *att = makeAttr(pstrdup(RelationGetRelationName(rd)), colname);
-
-#else
- Attr *att = makeNode(Attr);
-
-#endif
+ Attr *att = makeAttr(pstrdup(RelationGetRelationName(rd)),
+ colname);
Node *arrayBase;
ArrayRef *aref;
-#ifdef DISABLE_JOIN_SYNTAX
- att->relname = pstrdup(RelationGetRelationName(rd));
- att->attrs = lcons(makeString(colname), NIL);
-#endif
- arrayBase = ParseNestedFuncOrColumn(pstate, att,
- &pstate->p_last_resno,
- EXPR_COLUMN_FIRST);
+ arrayBase = ParseNestedFuncOrColumn(pstate, att, EXPR_COLUMN_FIRST);
aref = transformArraySubscripts(pstate, arrayBase,
indirection,
pstate->p_is_insert,
@@ -401,46 +383,54 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
}
/* ExpandAllTables()
- * Turns '*' (in the target list) into a list of attributes
- * (of all relations in the range table)
+ * Turns '*' (in the target list) into a list of targetlist entries.
+ *
+ * tlist entries are generated for each relation appearing in the FROM list,
+ * which by now has been expanded into a join tree.
*/
static List *
ExpandAllTables(ParseState *pstate)
{
List *target = NIL;
- List *rt,
- *rtable;
-
- rtable = pstate->p_rtable;
- if (pstate->p_is_rule)
- {
-
- /*
- * skip first two entries, "*new*" and "*current*"
- */
- rtable = lnext(lnext(rtable));
- }
+ List *jt;
/* SELECT *; */
- if (rtable == NIL)
+ if (pstate->p_jointree == NIL)
elog(ERROR, "Wildcard with no tables specified not allowed");
- foreach(rt, rtable)
+ foreach(jt, pstate->p_jointree)
{
- RangeTblEntry *rte = lfirst(rt);
+ Node *n = (Node *) lfirst(jt);
- /*
- * we only expand those listed in the from clause. (This will also
- * prevent us from using the wrong table in inserts: eg. tenk2 in
- * "insert into tenk2 select * from tenk1;")
- */
- if (!rte->inFromCl)
- continue;
+ if (IsA(n, RangeTblRef))
+ {
+ RangeTblEntry *rte;
- target = nconc(target,
- expandAll(pstate, rte->eref->relname, rte->eref,
- &pstate->p_last_resno));
+ rte = rt_fetch(((RangeTblRef *) n)->rtindex,
+ pstate->p_rtable);
+
+ /*
+ * Ignore added-on relations that were not listed in the FROM
+ * clause.
+ */
+ if (!rte->inFromCl)
+ continue;
+
+ target = nconc(target, expandRelAttrs(pstate, rte));
+ }
+ else if (IsA(n, JoinExpr))
+ {
+ /* A newfangled join expression */
+ JoinExpr *j = (JoinExpr *) n;
+
+ /* Currently, a join expr could only have come from FROM. */
+ target = nconc(target, expandJoinAttrs(pstate, j, 0));
+ }
+ else
+ elog(ERROR, "ExpandAllTables: unexpected node (internal error)"
+ "\n\t%s", nodeToString(n));
}
+
return target;
}