1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-29 10:41:53 +03:00

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.
This commit is contained in:
Tom Lane
2002-03-21 16:02:16 +00:00
parent 8c9c8ca2b5
commit 95ef6a3448
52 changed files with 2039 additions and 1535 deletions

View File

@ -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;