aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_target.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2002-03-21 16:02:16 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2002-03-21 16:02:16 +0000
commit95ef6a344821655ce4d0a74999ac49dd6af6d342 (patch)
treedf484a4c9dde9827894ab707917c001a1f376749 /src/backend/parser/parse_target.c
parent8c9c8ca2b57e4edef218245ccdc9eef7c06425d8 (diff)
downloadpostgresql-95ef6a344821655ce4d0a74999ac49dd6af6d342.tar.gz
postgresql-95ef6a344821655ce4d0a74999ac49dd6af6d342.zip
First phase of SCHEMA changes, concentrating on fixing the grammar and
the parsetree representation. As yet we don't *do* anything with schema names, just drop 'em on the floor; but you can enter schema-compatible command syntax, and there's even a primitive CREATE SCHEMA command. No doc updates yet, except to note that you can now extract a field from a function-returning-row's result with (foo(...)).fieldname.
Diffstat (limited to 'src/backend/parser/parse_target.c')
-rw-r--r--src/backend/parser/parse_target.c104
1 files changed, 76 insertions, 28 deletions
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index f5791298f31..a4b78165178 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -8,13 +8,13 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.77 2002/03/12 00:51:56 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.78 2002/03/21 16:01:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
-
#include "postgres.h"
+#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "parser/parsetree.h"
#include "parser/parse_coerce.h"
@@ -56,9 +56,9 @@ transformTargetEntry(ParseState *pstate,
/* Transform the node if caller didn't do it already */
if (expr == NULL)
- expr = transformExpr(pstate, node, EXPR_COLUMN_FIRST);
+ expr = transformExpr(pstate, node);
- if (IsA(expr, Ident) &&((Ident *) expr)->isRel)
+ if (IsA(expr, RangeVar))
elog(ERROR, "You can't use relation names alone in the target list, try relation.*.");
type_id = exprType(expr);
@@ -99,11 +99,13 @@ transformTargetList(ParseState *pstate, List *targetlist)
{
ResTarget *res = (ResTarget *) lfirst(targetlist);
- if (IsA(res->val, Attr))
+ if (IsA(res->val, ColumnRef))
{
- Attr *att = (Attr *) res->val;
+ ColumnRef *cref = (ColumnRef *) res->val;
+ List *fields = cref->fields;
+ int numnames = length(fields);
- if (att->relname != NULL && strcmp(att->relname, "*") == 0)
+ if (numnames == 1 && strcmp(strVal(lfirst(fields)), "*") == 0)
{
/*
* Target item is a single '*', expand all tables (eg.
@@ -112,27 +114,59 @@ transformTargetList(ParseState *pstate, List *targetlist)
p_target = nconc(p_target,
ExpandAllTables(pstate));
}
- else if (att->attrs != NIL &&
- strcmp(strVal(lfirst(att->attrs)), "*") == 0)
+ else if (strcmp(strVal(nth(numnames-1, 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;
- rte = refnameRangeTblEntry(pstate, att->relname,
+ 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));
+
+ /*
+ * We check the catalog name and then ignore it.
+ */
+ if (strcmp(name1, DatabaseName) != 0)
+ elog(ERROR, "Cross-database references are not implemented");
+ schemaname = strVal(lsecond(fields));
+ relname = strVal(lfirst(lnext(lnext(fields))));
+ break;
+ }
+ default:
+ elog(ERROR, "Invalid qualified name syntax (too many names)");
+ schemaname = NULL; /* keep compiler quiet */
+ relname = NULL;
+ break;
+ }
+
+ /* XXX do something with schema name */
+ rte = refnameRangeTblEntry(pstate, relname,
&sublevels_up);
if (rte == NULL)
- rte = addImplicitRTE(pstate, att->relname);
+ rte = addImplicitRTE(pstate, relname);
p_target = nconc(p_target,
expandRelAttrs(pstate, rte));
}
else
{
- /* Plain Attr node, treat it as an expression */
+ /* Plain ColumnRef node, treat it as an expression */
p_target = lappend(p_target,
transformTargetEntry(pstate,
res->val,
@@ -143,7 +177,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
}
else
{
- /* Everything else but Attr */
+ /* Everything else but ColumnRef */
p_target = lappend(p_target,
transformTargetEntry(pstate,
res->val,
@@ -317,10 +351,9 @@ CoerceTargetExpr(ParseState *pstate,
/*
* checkInsertTargets -
- * generate a list of column names if not supplied or
+ * generate a list of INSERT column targets if not supplied, or
* test supplied column names to make sure they are in target table.
* Also return an integer list of the columns' attribute numbers.
- * (used exclusively for inserts)
*/
List *
checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
@@ -338,17 +371,16 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
for (i = 0; i < numcol; i++)
{
- Ident *id = makeNode(Ident);
+ ResTarget *col = makeNode(ResTarget);
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(attr[i]))
continue;
#endif /* _DROP_COLUMN_HACK__ */
- id->name = palloc(NAMEDATALEN);
- StrNCpy(id->name, NameStr(attr[i]->attname), NAMEDATALEN);
- id->indirection = NIL;
- id->isRel = false;
- cols = lappend(cols, id);
+ col->name = pstrdup(NameStr(attr[i]->attname));
+ col->indirection = NIL;
+ col->val = NULL;
+ cols = lappend(cols, col);
*attrnos = lappendi(*attrnos, i + 1);
}
}
@@ -361,7 +393,7 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
foreach(tl, cols)
{
- char *name = ((Ident *) lfirst(tl))->name;
+ char *name = ((ResTarget *) lfirst(tl))->name;
int attrno;
/* Lookup column name, elog on failure */
@@ -458,19 +490,35 @@ FigureColnameInternal(Node *node, char **name)
case T_Ident:
*name = ((Ident *) node)->name;
return 2;
- case T_Attr:
+ case T_ColumnRef:
{
- List *attrs = ((Attr *) node)->attrs;
+ List *fields = ((ColumnRef *) node)->fields;
- if (attrs)
+ while (lnext(fields) != NIL)
+ fields = lnext(fields);
+ if (strcmp(strVal(lfirst(fields)), "*") != 0)
{
- while (lnext(attrs) != NIL)
- attrs = lnext(attrs);
- *name = strVal(lfirst(attrs));
+ *name = strVal(lfirst(fields));
return 2;
}
}
break;
+ case T_ExprFieldSelect:
+ {
+ List *fields = ((ExprFieldSelect *) node)->fields;
+
+ if (fields)
+ {
+ while (lnext(fields) != NIL)
+ fields = lnext(fields);
+ if (strcmp(strVal(lfirst(fields)), "*") != 0)
+ {
+ *name = strVal(lfirst(fields));
+ return 2;
+ }
+ }
+ }
+ break;
case T_FuncCall:
*name = ((FuncCall *) node)->funcname;
return 2;