1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-16 06:01:02 +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

@ -1,5 +1,5 @@
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.49 2002/03/11 05:03:52 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.50 2002/03/21 16:00:28 tgl Exp $
--> -->
<chapter id="xfunc"> <chapter id="xfunc">
@ -306,7 +306,8 @@ CREATE FUNCTION new_emp() RETURNS EMP AS '
<para> <para>
The target list order must be exactly the same as The target list order must be exactly the same as
that in which the columns appear in the table associated that in which the columns appear in the table associated
with the composite type. with the composite type. (Naming the columns, as we did above,
is irrelevant to the system.)
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
@ -328,10 +329,35 @@ ERROR: function declared to return emp returns varchar instead of text at colum
there are some unpleasant restrictions on how functions returning there are some unpleasant restrictions on how functions returning
composite types can be used. Briefly, when calling a function that composite types can be used. Briefly, when calling a function that
returns a row, we cannot retrieve the entire row. We must either returns a row, we cannot retrieve the entire row. We must either
project a single attribute out of the row or pass the entire row into extract a single attribute out of the row or pass the entire row into
another function. (Trying to display the entire row value will yield another function. (Trying to display the entire row value will yield
a meaningless number.) For example, a meaningless number.) For example,
<programlisting>
SELECT (new_emp()).name;
</programlisting>
<screen>
name
------
None
</screen>
We need the extra parentheses to keep the parser from getting confused:
<screen>
SELECT new_emp().name;
ERROR: parser: parse error at or near "."
</screen>
</para>
<para>
Another approach is to use
functional notation for extracting attributes. The simple way
to explain this is that we can use the
notations <literal>attribute(table)</> and <literal>table.attribute</>
interchangeably:
<programlisting> <programlisting>
SELECT name(new_emp()); SELECT name(new_emp());
</programlisting> </programlisting>
@ -343,13 +369,6 @@ SELECT name(new_emp());
</screen> </screen>
</para> </para>
<para>
This example makes use of the
function notation for projecting attributes. The simple way
to explain this is that we can usually use the
notations <literal>attribute(table)</> and <literal>table.attribute</>
interchangeably:
<programlisting> <programlisting>
-- --
-- this is the same as: -- this is the same as:
@ -367,19 +386,6 @@ SELECT name(EMP) AS youngster
</screen> </screen>
</para> </para>
<para>
The reason why, in general, we must use the function
syntax for projecting attributes of function return
values is that the parser just doesn't understand
the dot syntax for projection when combined
with function calls.
<screen>
SELECT new_emp().name AS nobody;
ERROR: parser: parse error at or near "."
</screen>
</para>
<para> <para>
Another way to use a function returning a row result is to declare a Another way to use a function returning a row result is to declare a
second function accepting a row type parameter, and pass the function second function accepting a row type parameter, and pass the function

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.56 2002/03/06 06:09:24 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.57 2002/03/21 16:00:29 tgl Exp $
* *
* NOTES * NOTES
* See acl.h. * See acl.h.
@ -200,7 +200,7 @@ ExecuteGrantStmt_Table(GrantStmt *stmt)
foreach(i, stmt->objects) foreach(i, stmt->objects)
{ {
char *relname = strVal(lfirst(i)); char *relname = ((RangeVar *) lfirst(i))->relname;
Relation relation; Relation relation;
HeapTuple tuple; HeapTuple tuple;
Form_pg_class pg_class_tuple; Form_pg_class pg_class_tuple;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.189 2002/03/20 19:43:34 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.190 2002/03/21 16:00:29 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
@ -1728,7 +1728,7 @@ AddRelationRawConstraints(Relation rel,
/* /*
* Transform raw parsetree to executable expression. * Transform raw parsetree to executable expression.
*/ */
expr = transformExpr(pstate, cdef->raw_expr, EXPR_COLUMN_FIRST); expr = transformExpr(pstate, cdef->raw_expr);
/* /*
* Make sure it yields a boolean result. * Make sure it yields a boolean result.
@ -1863,7 +1863,7 @@ cookDefault(ParseState *pstate,
/* /*
* Transform raw parsetree to executable expression. * Transform raw parsetree to executable expression.
*/ */
expr = transformExpr(pstate, raw_default, EXPR_COLUMN_FIRST); expr = transformExpr(pstate, raw_default);
/* /*
* Make sure default expr does not refer to any vars. * Make sure default expr does not refer to any vars.

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.161 2002/03/14 22:44:50 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.162 2002/03/21 16:00:31 tgl Exp $
* *
* NOTES * NOTES
* The PerformAddAttribute() code, like most of the relation * The PerformAddAttribute() code, like most of the relation
@ -33,7 +33,7 @@
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "commands/command.h" #include "commands/command.h"
#include "commands/trigger.h" #include "commands/trigger.h"
#include "commands/defrem.h" /* For add constraint unique, primary */ #include "commands/defrem.h"
#include "executor/execdefs.h" #include "executor/execdefs.h"
#include "executor/executor.h" #include "executor/executor.h"
#include "miscadmin.h" #include "miscadmin.h"
@ -44,7 +44,8 @@
#include "parser/parse_expr.h" #include "parser/parse_expr.h"
#include "parser/parse_oper.h" #include "parser/parse_oper.h"
#include "parser/parse_relation.h" #include "parser/parse_relation.h"
#include "parser/analyze.h" /* For add constraint unique, primary */ #include "parser/analyze.h"
#include "tcop/utility.h"
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h" #include "utils/fmgroids.h"
@ -1279,8 +1280,7 @@ AlterTableAddConstraint(char *relationName,
* Convert the A_EXPR in raw_expr into an * Convert the A_EXPR in raw_expr into an
* EXPR * EXPR
*/ */
expr = transformExpr(pstate, constr->raw_expr, expr = transformExpr(pstate, constr->raw_expr);
EXPR_COLUMN_FIRST);
/* /*
* Make sure it yields a boolean result. * Make sure it yields a boolean result.
@ -1366,7 +1366,7 @@ AlterTableAddConstraint(char *relationName,
List *list; List *list;
int count; int count;
if (is_temp_rel_name(fkconstraint->pktable_name) && if (is_temp_rel_name(fkconstraint->pktable->relname) &&
!is_temp_rel_name(relationName)) !is_temp_rel_name(relationName))
elog(ERROR, "ALTER TABLE / ADD CONSTRAINT: Unable to reference temporary table from permanent table constraint."); elog(ERROR, "ALTER TABLE / ADD CONSTRAINT: Unable to reference temporary table from permanent table constraint.");
@ -1375,10 +1375,10 @@ AlterTableAddConstraint(char *relationName,
* someone doesn't delete rows out from under us. * someone doesn't delete rows out from under us.
*/ */
pkrel = heap_openr(fkconstraint->pktable_name, AccessExclusiveLock); pkrel = heap_openr(fkconstraint->pktable->relname, AccessExclusiveLock);
if (pkrel->rd_rel->relkind != RELKIND_RELATION) if (pkrel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "referenced table \"%s\" not a relation", elog(ERROR, "referenced table \"%s\" not a relation",
fkconstraint->pktable_name); fkconstraint->pktable->relname);
heap_close(pkrel, NoLock); heap_close(pkrel, NoLock);
/* /*
@ -1417,7 +1417,7 @@ AlterTableAddConstraint(char *relationName,
else else
trig.tgargs[0] = "<unknown>"; trig.tgargs[0] = "<unknown>";
trig.tgargs[1] = (char *) relationName; trig.tgargs[1] = (char *) relationName;
trig.tgargs[2] = fkconstraint->pktable_name; trig.tgargs[2] = fkconstraint->pktable->relname;
trig.tgargs[3] = fkconstraint->match_type; trig.tgargs[3] = fkconstraint->match_type;
count = 4; count = 4;
foreach(list, fkconstraint->fk_attrs) foreach(list, fkconstraint->fk_attrs)
@ -1936,9 +1936,10 @@ LockTableCommand(LockStmt *lockstmt)
* at a time * at a time
*/ */
foreach(p, lockstmt->rellist) foreach(p, lockstmt->relations)
{ {
char *relname = strVal(lfirst(p)); RangeVar *relation = lfirst(p);
char *relname = relation->relname;
int aclresult; int aclresult;
Relation rel; Relation rel;
@ -1962,3 +1963,94 @@ LockTableCommand(LockStmt *lockstmt)
relation_close(rel, NoLock); /* close rel, keep lock */ relation_close(rel, NoLock); /* close rel, keep lock */
} }
} }
/*
* CREATE SCHEMA
*/
void
CreateSchemaCommand(CreateSchemaStmt *stmt)
{
const char *schemaName = stmt->schemaname;
const char *authId = stmt->authid;
List *parsetree_list;
List *parsetree_item;
const char *owner_name;
Oid owner_userid;
Oid saved_userid;
saved_userid = GetUserId();
if (!authId)
{
owner_userid = saved_userid;
owner_name = GetUserName(owner_userid);
}
else if (superuser())
{
owner_name = authId;
/* The following will error out if user does not exist */
owner_userid = get_usesysid(owner_name);
/*
* Set the current user to the requested authorization so
* that objects created in the statement have the requested
* owner. (This will revert to session user on error or at
* the end of this routine.)
*/
SetUserId(owner_userid);
}
else /* not superuser */
{
owner_userid = saved_userid;
owner_name = GetUserName(owner_userid);
if (strcmp(authId, owner_name) != 0)
elog(ERROR, "CREATE SCHEMA: permission denied"
"\n\t\"%s\" is not a superuser, so cannot create a schema for \"%s\"",
owner_name, authId);
}
/* FIXME FENN: Create the schema here */
(void) schemaName; /* suppress compiler warning for now... */
/*
* Let commands in the schema-element-list know about the schema
*/
CommandCounterIncrement();
/*
* Examine the list of commands embedded in the CREATE SCHEMA command,
* and reorganize them into a sequentially executable order with no
* forward references. Note that the result is still a list of raw
* parsetrees in need of parse analysis --- we cannot, in general,
* run analyze.c on one statement until we have actually executed the
* prior ones.
*/
parsetree_list = analyzeCreateSchemaStmt(stmt);
/*
* Analyze and execute each command contained in the CREATE SCHEMA
*/
foreach(parsetree_item, parsetree_list)
{
Node *parsetree = (Node *) lfirst(parsetree_item);
List *querytree_list,
*querytree_item;
querytree_list = parse_analyze(parsetree, NULL);
foreach(querytree_item, querytree_list)
{
Query *querytree = (Query *) lfirst(querytree_item);
/* schemas should contain only utility stmts */
Assert(querytree->commandType == CMD_UTILITY);
/* do this step */
ProcessUtility(querytree->utilityStmt, None, NULL);
/* make sure later steps can see the object created here */
CommandCounterIncrement();
}
}
/* Reset current user */
SetUserId(saved_userid);
}

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.88 2002/03/20 19:43:42 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.89 2002/03/21 16:00:31 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -69,7 +69,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
* Truncate relname to appropriate length (probably a waste of time, * Truncate relname to appropriate length (probably a waste of time,
* as parser should have done this already). * as parser should have done this already).
*/ */
StrNCpy(relname, stmt->relname, NAMEDATALEN); StrNCpy(relname, (stmt->relation)->relname, NAMEDATALEN);
/* /*
* Merge domain attributes into the known columns before processing table * Merge domain attributes into the known columns before processing table
@ -82,7 +82,8 @@ DefineRelation(CreateStmt *stmt, char relkind)
* Look up inheritance ancestors and generate relation schema, * Look up inheritance ancestors and generate relation schema,
* including inherited attributes. * including inherited attributes.
*/ */
schema = MergeAttributes(schema, stmt->inhRelnames, stmt->istemp, schema = MergeAttributes(schema, stmt->inhRelations,
stmt->relation->istemp,
&inheritOids, &old_constraints, &parentHasOids); &inheritOids, &old_constraints, &parentHasOids);
numberOfAttributes = length(schema); numberOfAttributes = length(schema);
@ -147,7 +148,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
relationId = heap_create_with_catalog(relname, descriptor, relationId = heap_create_with_catalog(relname, descriptor,
relkind, relkind,
stmt->hasoids || parentHasOids, stmt->hasoids || parentHasOids,
stmt->istemp, stmt->relation->istemp,
allowSystemTableMods); allowSystemTableMods);
StoreCatalogInheritance(relationId, inheritOids); StoreCatalogInheritance(relationId, inheritOids);
@ -414,6 +415,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
/* /*
* Reject duplicate names in the list of parents, too. * Reject duplicate names in the list of parents, too.
*
* XXX needs to be smarter about schema-qualified table names.
*/ */
foreach(entry, supers) foreach(entry, supers)
{ {
@ -421,9 +424,10 @@ MergeAttributes(List *schema, List *supers, bool istemp,
foreach(rest, lnext(entry)) foreach(rest, lnext(entry))
{ {
if (strcmp(strVal(lfirst(entry)), strVal(lfirst(rest))) == 0) if (strcmp(((RangeVar *) lfirst(entry))->relname,
((RangeVar *) lfirst(rest))->relname) == 0)
elog(ERROR, "CREATE TABLE: inherited relation \"%s\" duplicated", elog(ERROR, "CREATE TABLE: inherited relation \"%s\" duplicated",
strVal(lfirst(entry))); ((RangeVar *) lfirst(entry))->relname);
} }
} }
@ -435,7 +439,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
child_attno = 0; child_attno = 0;
foreach(entry, supers) foreach(entry, supers)
{ {
char *name = strVal(lfirst(entry)); char *name = ((RangeVar *) lfirst(entry))->relname;
Relation relation; Relation relation;
TupleDesc tupleDesc; TupleDesc tupleDesc;
TupleConstr *constr; TupleConstr *constr;

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California * Portions Copyright (c) 1994-5, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.71 2002/03/12 00:51:35 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.72 2002/03/21 16:00:32 tgl Exp $
* *
*/ */
@ -310,9 +310,9 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es)
appendStringInfo(str, " on %s", appendStringInfo(str, " on %s",
stringStringInfo(rte->relname)); stringStringInfo(rte->relname));
if (strcmp(rte->eref->relname, rte->relname) != 0) if (strcmp(rte->eref->aliasname, rte->relname) != 0)
appendStringInfo(str, " %s", appendStringInfo(str, " %s",
stringStringInfo(rte->eref->relname)); stringStringInfo(rte->eref->aliasname));
} }
break; break;
case T_SubqueryScan: case T_SubqueryScan:
@ -322,7 +322,7 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es)
es->rtable); es->rtable);
appendStringInfo(str, " %s", appendStringInfo(str, " %s",
stringStringInfo(rte->eref->relname)); stringStringInfo(rte->eref->aliasname));
} }
break; break;
default: default:

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.71 2002/03/15 19:20:35 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.72 2002/03/21 16:00:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -123,7 +123,7 @@ DefineSequence(CreateSeqStmt *seq)
case SEQ_COL_NAME: case SEQ_COL_NAME:
typnam->name = "name"; typnam->name = "name";
coldef->colname = "sequence_name"; coldef->colname = "sequence_name";
namestrcpy(&name, seq->seqname); namestrcpy(&name, seq->sequence->relname);
value[i - 1] = NameGetDatum(&name); value[i - 1] = NameGetDatum(&name);
break; break;
case SEQ_COL_LASTVAL: case SEQ_COL_LASTVAL:
@ -170,15 +170,14 @@ DefineSequence(CreateSeqStmt *seq)
stmt->tableElts = lappend(stmt->tableElts, coldef); stmt->tableElts = lappend(stmt->tableElts, coldef);
} }
stmt->relname = seq->seqname; stmt->relation = seq->sequence;
stmt->inhRelnames = NIL; stmt->inhRelations = NIL;
stmt->constraints = NIL; stmt->constraints = NIL;
stmt->istemp = seq->istemp;
stmt->hasoids = false; stmt->hasoids = false;
DefineRelation(stmt, RELKIND_SEQUENCE); DefineRelation(stmt, RELKIND_SEQUENCE);
rel = heap_openr(seq->seqname, AccessExclusiveLock); rel = heap_openr(seq->sequence->relname, AccessExclusiveLock);
tupDesc = RelationGetDescr(rel); tupDesc = RelationGetDescr(rel);
/* Initialize first page of relation with special magic number */ /* Initialize first page of relation with special magic number */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.105 2002/03/08 04:37:14 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.106 2002/03/21 16:00:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -71,10 +71,11 @@ CreateTrigger(CreateTrigStmt *stmt)
char *constrname = ""; char *constrname = "";
Oid constrrelid = InvalidOid; Oid constrrelid = InvalidOid;
if (!allowSystemTableMods && IsSystemRelationName(stmt->relname)) if (!allowSystemTableMods && IsSystemRelationName(stmt->relation->relname))
elog(ERROR, "CreateTrigger: can't create trigger for system relation %s", stmt->relname); elog(ERROR, "CreateTrigger: can't create trigger for system relation %s",
stmt->relation->relname);
if (pg_aclcheck(stmt->relname, GetUserId(), if (pg_aclcheck(stmt->relation->relname, GetUserId(),
stmt->isconstraint ? ACL_REFERENCES : ACL_TRIGGER) stmt->isconstraint ? ACL_REFERENCES : ACL_TRIGGER)
!= ACLCHECK_OK) != ACLCHECK_OK)
elog(ERROR, "permission denied"); elog(ERROR, "permission denied");
@ -89,7 +90,7 @@ CreateTrigger(CreateTrigStmt *stmt)
stmt->trigname = constrtrigname; stmt->trigname = constrtrigname;
sprintf(constrtrigname, "RI_ConstraintTrigger_%u", newoid()); sprintf(constrtrigname, "RI_ConstraintTrigger_%u", newoid());
if (strcmp(stmt->constrrelname, "") == 0) if (stmt->constrrel == NULL)
constrrelid = InvalidOid; constrrelid = InvalidOid;
else else
{ {
@ -97,17 +98,17 @@ CreateTrigger(CreateTrigStmt *stmt)
* NoLock is probably sufficient here, since we're only * NoLock is probably sufficient here, since we're only
* interested in getting the relation's OID... * interested in getting the relation's OID...
*/ */
rel = heap_openr(stmt->constrrelname, NoLock); rel = heap_openr(stmt->constrrel->relname, NoLock);
constrrelid = rel->rd_id; constrrelid = rel->rd_id;
heap_close(rel, NoLock); heap_close(rel, NoLock);
} }
} }
rel = heap_openr(stmt->relname, AccessExclusiveLock); rel = heap_openr(stmt->relation->relname, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION) if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "CreateTrigger: relation \"%s\" is not a table", elog(ERROR, "CreateTrigger: relation \"%s\" is not a table",
stmt->relname); stmt->relation->relname);
TRIGGER_CLEAR_TYPE(tgtype); TRIGGER_CLEAR_TYPE(tgtype);
if (stmt->before) if (stmt->before)
@ -159,7 +160,7 @@ CreateTrigger(CreateTrigStmt *stmt)
if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0) if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0)
elog(ERROR, "CreateTrigger: trigger %s already defined on relation %s", elog(ERROR, "CreateTrigger: trigger %s already defined on relation %s",
stmt->trigname, stmt->relname); stmt->trigname, stmt->relation->relname);
found++; found++;
} }
systable_endscan(tgscan); systable_endscan(tgscan);
@ -283,11 +284,11 @@ CreateTrigger(CreateTrigStmt *stmt)
*/ */
pgrel = heap_openr(RelationRelationName, RowExclusiveLock); pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheCopy(RELNAME, tuple = SearchSysCacheCopy(RELNAME,
PointerGetDatum(stmt->relname), PointerGetDatum(stmt->relation->relname),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
elog(ERROR, "CreateTrigger: relation %s not found in pg_class", elog(ERROR, "CreateTrigger: relation %s not found in pg_class",
stmt->relname); stmt->relation->relname);
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1; ((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;
simple_heap_update(pgrel, &tuple->t_self, tuple); simple_heap_update(pgrel, &tuple->t_self, tuple);
@ -320,19 +321,19 @@ DropTrigger(DropTrigStmt *stmt)
int found = 0; int found = 0;
int tgfound = 0; int tgfound = 0;
if (!allowSystemTableMods && IsSystemRelationName(stmt->relname)) if (!allowSystemTableMods && IsSystemRelationName(stmt->relation->relname))
elog(ERROR, "DropTrigger: can't drop trigger for system relation %s", elog(ERROR, "DropTrigger: can't drop trigger for system relation %s",
stmt->relname); stmt->relation->relname);
if (!pg_ownercheck(GetUserId(), stmt->relname, RELNAME)) if (!pg_ownercheck(GetUserId(), stmt->relation->relname, RELNAME))
elog(ERROR, "%s: %s", stmt->relname, elog(ERROR, "%s: %s", stmt->relation->relname,
aclcheck_error_strings[ACLCHECK_NOT_OWNER]); aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
rel = heap_openr(stmt->relname, AccessExclusiveLock); rel = heap_openr(stmt->relation->relname, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION) if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "DropTrigger: relation \"%s\" is not a table", elog(ERROR, "DropTrigger: relation \"%s\" is not a table",
stmt->relname); stmt->relation->relname);
/* /*
* Search pg_trigger, delete target trigger, count remaining triggers * Search pg_trigger, delete target trigger, count remaining triggers
@ -366,10 +367,10 @@ DropTrigger(DropTrigStmt *stmt)
if (tgfound == 0) if (tgfound == 0)
elog(ERROR, "DropTrigger: there is no trigger %s on relation %s", elog(ERROR, "DropTrigger: there is no trigger %s on relation %s",
stmt->trigname, stmt->relname); stmt->trigname, stmt->relation->relname);
if (tgfound > 1) if (tgfound > 1)
elog(NOTICE, "DropTrigger: found (and deleted) %d triggers %s on relation %s", elog(NOTICE, "DropTrigger: found (and deleted) %d triggers %s on relation %s",
tgfound, stmt->trigname, stmt->relname); tgfound, stmt->trigname, stmt->relation->relname);
/* /*
* Update relation's pg_class entry. Crucial side-effect: other * Update relation's pg_class entry. Crucial side-effect: other
@ -378,11 +379,11 @@ DropTrigger(DropTrigStmt *stmt)
*/ */
pgrel = heap_openr(RelationRelationName, RowExclusiveLock); pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheCopy(RELNAME, tuple = SearchSysCacheCopy(RELNAME,
PointerGetDatum(stmt->relname), PointerGetDatum(stmt->relation->relname),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
elog(ERROR, "DropTrigger: relation %s not found in pg_class", elog(ERROR, "DropTrigger: relation %s not found in pg_class",
stmt->relname); stmt->relation->relname);
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found; ((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found;
simple_heap_update(pgrel, &tuple->t_self, tuple); simple_heap_update(pgrel, &tuple->t_self, tuple);
@ -478,20 +479,23 @@ RelationRemoveTriggers(Relation rel)
{ {
Form_pg_trigger pg_trigger; Form_pg_trigger pg_trigger;
Relation refrel; Relation refrel;
DropTrigStmt stmt; DropTrigStmt *stmt = makeNode(DropTrigStmt);
pg_trigger = (Form_pg_trigger) GETSTRUCT(tup); pg_trigger = (Form_pg_trigger) GETSTRUCT(tup);
stmt.trigname = pstrdup(NameStr(pg_trigger->tgname)); stmt->trigname = pstrdup(NameStr(pg_trigger->tgname));
/* May as well grab AccessExclusiveLock, since DropTrigger will. */ /* May as well grab AccessExclusiveLock, since DropTrigger will. */
refrel = heap_open(pg_trigger->tgrelid, AccessExclusiveLock); refrel = heap_open(pg_trigger->tgrelid, AccessExclusiveLock);
stmt.relname = pstrdup(RelationGetRelationName(refrel)); stmt->relation = makeNode(RangeVar);
/* XXX bogus: what about schema? */
stmt->relation->relname = pstrdup(RelationGetRelationName(refrel));
heap_close(refrel, NoLock); heap_close(refrel, NoLock);
elog(NOTICE, "DROP TABLE implicitly drops referential integrity trigger from table \"%s\"", stmt.relname); elog(NOTICE, "DROP TABLE implicitly drops referential integrity trigger from table \"%s\"",
stmt->relation->relname);
DropTrigger(&stmt); DropTrigger(stmt);
/* /*
* Need to do a command counter increment here to show up new * Need to do a command counter increment here to show up new
@ -500,9 +504,6 @@ RelationRemoveTriggers(Relation rel)
* FK table defined on the PK table). * FK table defined on the PK table).
*/ */
CommandCounterIncrement(); CommandCounterIncrement();
pfree(stmt.relname);
pfree(stmt.trigname);
} }
systable_endscan(tgscan); systable_endscan(tgscan);

View File

@ -13,7 +13,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.217 2002/03/06 06:09:38 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.218 2002/03/21 16:00:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -209,10 +209,10 @@ vacuum(VacuumStmt *vacstmt)
ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE); ALLOCSET_DEFAULT_MAXSIZE);
/* Convert vacrel, which is just a string, to a Name */ /* Convert relname, which is just a string, to a Name */
if (vacstmt->vacrel) if (vacstmt->relation)
{ {
namestrcpy(&VacRel, vacstmt->vacrel); namestrcpy(&VacRel, vacstmt->relation->relname);
VacRelName = &VacRel; VacRelName = &VacRel;
} }
else else
@ -268,7 +268,7 @@ vacuum(VacuumStmt *vacstmt)
static void static void
vacuum_init(VacuumStmt *vacstmt) vacuum_init(VacuumStmt *vacstmt)
{ {
if (vacstmt->vacuum && vacstmt->vacrel == NULL) if (vacstmt->vacuum && vacstmt->relation == NULL)
{ {
/* /*
* Compute the initially applicable OldestXmin and FreezeLimit * Compute the initially applicable OldestXmin and FreezeLimit
@ -308,7 +308,7 @@ vacuum_shutdown(VacuumStmt *vacstmt)
* row with info about the transaction IDs used, and try to truncate * row with info about the transaction IDs used, and try to truncate
* pg_clog. * pg_clog.
*/ */
if (vacstmt->vacuum && vacstmt->vacrel == NULL) if (vacstmt->vacuum && vacstmt->relation == NULL)
{ {
vac_update_dbstats(MyDatabaseId, vac_update_dbstats(MyDatabaseId,
initialOldestXmin, initialFreezeLimit); initialOldestXmin, initialFreezeLimit);

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: view.c,v 1.58 2001/10/25 05:49:26 momjian Exp $ * $Id: view.c,v 1.59 2002/03/21 16:00:36 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -41,6 +41,7 @@ static void
DefineVirtualRelation(char *relname, List *tlist) DefineVirtualRelation(char *relname, List *tlist)
{ {
CreateStmt *createStmt = makeNode(CreateStmt); CreateStmt *createStmt = makeNode(CreateStmt);
RangeVar *rel = makeNode(RangeVar);
List *attrList, List *attrList,
*t; *t;
@ -83,11 +84,13 @@ DefineVirtualRelation(char *relname, List *tlist)
* now create the parameters for keys/inheritance etc. All of them are * now create the parameters for keys/inheritance etc. All of them are
* nil... * nil...
*/ */
createStmt->relname = relname; rel->relname = relname;
rel->schemaname = NULL; /* XXX wrong */
rel->istemp = false;
createStmt->relation = rel;
createStmt->tableElts = attrList; createStmt->tableElts = attrList;
createStmt->inhRelnames = NIL; createStmt->inhRelations = NIL;
createStmt->constraints = NIL; createStmt->constraints = NIL;
createStmt->istemp = false;
createStmt->hasoids = false; createStmt->hasoids = false;
/* /*
@ -101,21 +104,24 @@ FormViewRetrieveRule(char *viewName, Query *viewParse)
{ {
RuleStmt *rule; RuleStmt *rule;
char *rname; char *rname;
Attr *attr; RangeVar *rel;
/* /*
* Create a RuleStmt that corresponds to the suitable rewrite rule * Create a RuleStmt that corresponds to the suitable rewrite rule
* args for DefineQueryRewrite(); * args for DefineQueryRewrite();
*/ */
rule = makeNode(RuleStmt);
rname = MakeRetrieveViewRuleName(viewName); rname = MakeRetrieveViewRuleName(viewName);
attr = makeNode(Attr); rel = makeNode(RangeVar);
attr->relname = pstrdup(viewName); rel->relname = pstrdup(viewName);
rel->inhOpt = INH_NO;
rel->alias = NULL;
rule = makeNode(RuleStmt);
rule->relation = rel;
rule->rulename = pstrdup(rname); rule->rulename = pstrdup(rname);
rule->whereClause = NULL; rule->whereClause = NULL;
rule->event = CMD_SELECT; rule->event = CMD_SELECT;
rule->object = attr;
rule->instead = true; rule->instead = true;
rule->actions = makeList1(viewParse); rule->actions = makeList1(viewParse);
@ -191,10 +197,10 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
* table... OLD first, then NEW.... * table... OLD first, then NEW....
*/ */
rt_entry1 = addRangeTableEntry(NULL, viewName, rt_entry1 = addRangeTableEntry(NULL, viewName,
makeAttr("*OLD*", NULL), makeAlias("*OLD*", NIL),
false, false); false, false);
rt_entry2 = addRangeTableEntry(NULL, viewName, rt_entry2 = addRangeTableEntry(NULL, viewName,
makeAttr("*NEW*", NULL), makeAlias("*NEW*", NIL),
false, false); false, false);
/* Must override addRangeTableEntry's default access-check flags */ /* Must override addRangeTableEntry's default access-check flags */
rt_entry1->checkForRead = false; rt_entry1->checkForRead = false;

View File

@ -27,7 +27,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.152 2002/03/06 06:09:42 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.153 2002/03/21 16:00:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -707,7 +707,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
/* /*
* create the "into" relation * create the "into" relation
*/ */
intoName = parseTree->into; intoName = parseTree->into->relname;
/* /*
* have to copy tupType to get rid of constraints * have to copy tupType to get rid of constraints
@ -718,7 +718,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
heap_create_with_catalog(intoName, heap_create_with_catalog(intoName,
tupdesc, tupdesc,
RELKIND_RELATION, true, RELKIND_RELATION, true,
parseTree->isTemp, parseTree->into->istemp,
allowSystemTableMods); allowSystemTableMods);
FreeTupleDesc(tupdesc); FreeTupleDesc(tupdesc);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.67 2002/02/27 19:34:59 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.68 2002/03/21 16:00:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -775,7 +775,8 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls)
/* Modify the parsetree to be a cursor */ /* Modify the parsetree to be a cursor */
queryTree->isPortal = true; queryTree->isPortal = true;
queryTree->into = pstrdup(name); queryTree->into = makeNode(RangeVar);
queryTree->into->relname = pstrdup(name);
queryTree->isBinary = false; queryTree->isBinary = false;
/* Create the QueryDesc object and the executor state */ /* Create the QueryDesc object and the executor state */
@ -1145,7 +1146,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
if (parseTree->isPortal) if (parseTree->isPortal)
{ {
isRetrieveIntoPortal = true; isRetrieveIntoPortal = true;
intoName = parseTree->into; intoName = parseTree->into->relname;
parseTree->isBinary = false; /* */ parseTree->isBinary = false; /* */
return SPI_ERROR_CURSOR; return SPI_ERROR_CURSOR;

View File

@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.171 2002/03/20 19:43:58 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.172 2002/03/21 16:00:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -733,18 +733,6 @@ _copyVar(Var *from)
return newnode; return newnode;
} }
static Attr *
_copyAttr(Attr *from)
{
Attr *newnode = makeNode(Attr);
if (from->relname)
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, attrs);
return newnode;
}
/* ---------------- /* ----------------
* _copyOper * _copyOper
* ---------------- * ----------------
@ -1515,8 +1503,7 @@ _copyFkConstraint(FkConstraint *from)
if (from->constr_name) if (from->constr_name)
newnode->constr_name = pstrdup(from->constr_name); newnode->constr_name = pstrdup(from->constr_name);
if (from->pktable_name) Node_Copy(from, newnode, pktable);
newnode->pktable_name = pstrdup(from->pktable_name);
Node_Copy(from, newnode, fk_attrs); Node_Copy(from, newnode, fk_attrs);
Node_Copy(from, newnode, pk_attrs); Node_Copy(from, newnode, pk_attrs);
if (from->match_type) if (from->match_type)
@ -1553,6 +1540,29 @@ _copyAExpr(A_Expr *from)
return newnode; return newnode;
} }
static ColumnRef *
_copyColumnRef(ColumnRef *from)
{
ColumnRef *newnode = makeNode(ColumnRef);
Node_Copy(from, newnode, fields);
Node_Copy(from, newnode, indirection);
return newnode;
}
static ParamRef *
_copyParamRef(ParamRef *from)
{
ParamRef *newnode = makeNode(ParamRef);
newnode->number = from->number;
Node_Copy(from, newnode, fields);
Node_Copy(from, newnode, indirection);
return newnode;
}
static A_Const * static A_Const *
_copyAConst(A_Const *from) _copyAConst(A_Const *from)
{ {
@ -1564,27 +1574,12 @@ _copyAConst(A_Const *from)
return newnode; return newnode;
} }
static ParamNo *
_copyParamNo(ParamNo *from)
{
ParamNo *newnode = makeNode(ParamNo);
newnode->number = from->number;
Node_Copy(from, newnode, typename);
Node_Copy(from, newnode, indirection);
return newnode;
}
static Ident * static Ident *
_copyIdent(Ident *from) _copyIdent(Ident *from)
{ {
Ident *newnode = makeNode(Ident); Ident *newnode = makeNode(Ident);
if (from->name)
newnode->name = pstrdup(from->name); newnode->name = pstrdup(from->name);
Node_Copy(from, newnode, indirection);
newnode->isRel = from->isRel;
return newnode; return newnode;
} }
@ -1614,6 +1609,18 @@ _copyAIndices(A_Indices *from)
return newnode; return newnode;
} }
static ExprFieldSelect *
_copyExprFieldSelect(ExprFieldSelect *from)
{
ExprFieldSelect *newnode = makeNode(ExprFieldSelect);
Node_Copy(from, newnode, arg);
Node_Copy(from, newnode, fields);
Node_Copy(from, newnode, indirection);
return newnode;
}
static ResTarget * static ResTarget *
_copyResTarget(ResTarget *from) _copyResTarget(ResTarget *from)
{ {
@ -1654,15 +1661,32 @@ _copySortGroupBy(SortGroupBy *from)
return newnode; return newnode;
} }
static Alias *
_copyAlias(Alias *from)
{
Alias *newnode = makeNode(Alias);
if (from->aliasname)
newnode->aliasname = pstrdup(from->aliasname);
Node_Copy(from, newnode, colnames);
return newnode;
}
static RangeVar * static RangeVar *
_copyRangeVar(RangeVar *from) _copyRangeVar(RangeVar *from)
{ {
RangeVar *newnode = makeNode(RangeVar); RangeVar *newnode = makeNode(RangeVar);
if (from->catalogname)
newnode->catalogname = pstrdup(from->catalogname);
if (from->schemaname)
newnode->schemaname = pstrdup(from->schemaname);
if (from->relname) if (from->relname)
newnode->relname = pstrdup(from->relname); newnode->relname = pstrdup(from->relname);
newnode->inhOpt = from->inhOpt; newnode->inhOpt = from->inhOpt;
Node_Copy(from, newnode, name); newnode->istemp = from->istemp;
Node_Copy(from, newnode, alias);
return newnode; return newnode;
} }
@ -1673,7 +1697,7 @@ _copyRangeSubselect(RangeSubselect *from)
RangeSubselect *newnode = makeNode(RangeSubselect); RangeSubselect *newnode = makeNode(RangeSubselect);
Node_Copy(from, newnode, subquery); Node_Copy(from, newnode, subquery);
Node_Copy(from, newnode, name); Node_Copy(from, newnode, alias);
return newnode; return newnode;
} }
@ -1756,11 +1780,9 @@ _copyQuery(Query *from)
newnode->commandType = from->commandType; newnode->commandType = from->commandType;
Node_Copy(from, newnode, utilityStmt); Node_Copy(from, newnode, utilityStmt);
newnode->resultRelation = from->resultRelation; newnode->resultRelation = from->resultRelation;
if (from->into) Node_Copy(from, newnode, into);
newnode->into = pstrdup(from->into);
newnode->isPortal = from->isPortal; newnode->isPortal = from->isPortal;
newnode->isBinary = from->isBinary; newnode->isBinary = from->isBinary;
newnode->isTemp = from->isTemp;
newnode->hasAggs = from->hasAggs; newnode->hasAggs = from->hasAggs;
newnode->hasSubLinks = from->hasSubLinks; newnode->hasSubLinks = from->hasSubLinks;
newnode->originalQuery = from->originalQuery; newnode->originalQuery = from->originalQuery;
@ -1798,8 +1820,7 @@ _copyInsertStmt(InsertStmt *from)
{ {
InsertStmt *newnode = makeNode(InsertStmt); InsertStmt *newnode = makeNode(InsertStmt);
if (from->relname) Node_Copy(from, newnode, relation);
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, cols); Node_Copy(from, newnode, cols);
Node_Copy(from, newnode, targetList); Node_Copy(from, newnode, targetList);
Node_Copy(from, newnode, selectStmt); Node_Copy(from, newnode, selectStmt);
@ -1812,10 +1833,8 @@ _copyDeleteStmt(DeleteStmt *from)
{ {
DeleteStmt *newnode = makeNode(DeleteStmt); DeleteStmt *newnode = makeNode(DeleteStmt);
if (from->relname) Node_Copy(from, newnode, relation);
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, whereClause); Node_Copy(from, newnode, whereClause);
newnode->inhOpt = from->inhOpt;
return newnode; return newnode;
} }
@ -1825,12 +1844,10 @@ _copyUpdateStmt(UpdateStmt *from)
{ {
UpdateStmt *newnode = makeNode(UpdateStmt); UpdateStmt *newnode = makeNode(UpdateStmt);
if (from->relname) Node_Copy(from, newnode, relation);
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, targetList); Node_Copy(from, newnode, targetList);
Node_Copy(from, newnode, whereClause); Node_Copy(from, newnode, whereClause);
Node_Copy(from, newnode, fromClause); Node_Copy(from, newnode, fromClause);
newnode->inhOpt = from->inhOpt;
return newnode; return newnode;
} }
@ -1841,9 +1858,7 @@ _copySelectStmt(SelectStmt *from)
SelectStmt *newnode = makeNode(SelectStmt); SelectStmt *newnode = makeNode(SelectStmt);
Node_Copy(from, newnode, distinctClause); Node_Copy(from, newnode, distinctClause);
if (from->into) Node_Copy(from, newnode, into);
newnode->into = pstrdup(from->into);
newnode->istemp = from->istemp;
Node_Copy(from, newnode, intoColNames); Node_Copy(from, newnode, intoColNames);
Node_Copy(from, newnode, targetList); Node_Copy(from, newnode, targetList);
Node_Copy(from, newnode, fromClause); Node_Copy(from, newnode, fromClause);
@ -1885,9 +1900,7 @@ _copyAlterTableStmt(AlterTableStmt *from)
AlterTableStmt *newnode = makeNode(AlterTableStmt); AlterTableStmt *newnode = makeNode(AlterTableStmt);
newnode->subtype = from->subtype; newnode->subtype = from->subtype;
if (from->relname) Node_Copy(from, newnode, relation);
newnode->relname = pstrdup(from->relname);
newnode->inhOpt = from->inhOpt;
if (from->name) if (from->name)
newnode->name = pstrdup(from->name); newnode->name = pstrdup(from->name);
Node_Copy(from, newnode, def); Node_Copy(from, newnode, def);
@ -1951,8 +1964,7 @@ _copyClusterStmt(ClusterStmt *from)
{ {
ClusterStmt *newnode = makeNode(ClusterStmt); ClusterStmt *newnode = makeNode(ClusterStmt);
if (from->relname) Node_Copy(from, newnode, relation);
newnode->relname = pstrdup(from->relname);
if (from->indexname) if (from->indexname)
newnode->indexname = pstrdup(from->indexname); newnode->indexname = pstrdup(from->indexname);
@ -1965,8 +1977,7 @@ _copyCopyStmt(CopyStmt *from)
CopyStmt *newnode = makeNode(CopyStmt); CopyStmt *newnode = makeNode(CopyStmt);
newnode->binary = from->binary; newnode->binary = from->binary;
if (from->relname) Node_Copy(from, newnode, relation);
newnode->relname = pstrdup(from->relname);
newnode->oids = from->oids; newnode->oids = from->oids;
newnode->direction = from->direction; newnode->direction = from->direction;
if (from->filename) if (from->filename)
@ -1984,11 +1995,10 @@ _copyCreateStmt(CreateStmt *from)
{ {
CreateStmt *newnode = makeNode(CreateStmt); CreateStmt *newnode = makeNode(CreateStmt);
newnode->relname = pstrdup(from->relname); Node_Copy(from, newnode, relation);
Node_Copy(from, newnode, tableElts); Node_Copy(from, newnode, tableElts);
Node_Copy(from, newnode, inhRelnames); Node_Copy(from, newnode, inhRelations);
Node_Copy(from, newnode, constraints); Node_Copy(from, newnode, constraints);
newnode->istemp = from->istemp;
newnode->hasoids = from->hasoids; newnode->hasoids = from->hasoids;
return newnode; return newnode;
@ -2024,7 +2034,7 @@ _copyDropStmt(DropStmt *from)
{ {
DropStmt *newnode = makeNode(DropStmt); DropStmt *newnode = makeNode(DropStmt);
Node_Copy(from, newnode, names); Node_Copy(from, newnode, objects);
newnode->removeType = from->removeType; newnode->removeType = from->removeType;
newnode->behavior = from->behavior; newnode->behavior = from->behavior;
@ -2036,7 +2046,7 @@ _copyTruncateStmt(TruncateStmt *from)
{ {
TruncateStmt *newnode = makeNode(TruncateStmt); TruncateStmt *newnode = makeNode(TruncateStmt);
newnode->relName = pstrdup(from->relName); Node_Copy(from, newnode, relation);
return newnode; return newnode;
} }
@ -2047,6 +2057,8 @@ _copyCommentStmt(CommentStmt *from)
CommentStmt *newnode = makeNode(CommentStmt); CommentStmt *newnode = makeNode(CommentStmt);
newnode->objtype = from->objtype; newnode->objtype = from->objtype;
if (from->objschema)
newnode->objschema = pstrdup(from->objschema);
newnode->objname = pstrdup(from->objname); newnode->objname = pstrdup(from->objname);
if (from->objproperty) if (from->objproperty)
newnode->objproperty = pstrdup(from->objproperty); newnode->objproperty = pstrdup(from->objproperty);
@ -2075,7 +2087,7 @@ _copyIndexStmt(IndexStmt *from)
IndexStmt *newnode = makeNode(IndexStmt); IndexStmt *newnode = makeNode(IndexStmt);
newnode->idxname = pstrdup(from->idxname); newnode->idxname = pstrdup(from->idxname);
newnode->relname = pstrdup(from->relname); Node_Copy(from, newnode, relation);
newnode->accessMethod = pstrdup(from->accessMethod); newnode->accessMethod = pstrdup(from->accessMethod);
Node_Copy(from, newnode, indexParams); Node_Copy(from, newnode, indexParams);
Node_Copy(from, newnode, whereClause); Node_Copy(from, newnode, whereClause);
@ -2140,8 +2152,7 @@ _copyRenameStmt(RenameStmt *from)
{ {
RenameStmt *newnode = makeNode(RenameStmt); RenameStmt *newnode = makeNode(RenameStmt);
newnode->relname = pstrdup(from->relname); Node_Copy(from, newnode, relation);
newnode->inhOpt = from->inhOpt;
if (from->column) if (from->column)
newnode->column = pstrdup(from->column); newnode->column = pstrdup(from->column);
if (from->newname) if (from->newname)
@ -2155,10 +2166,10 @@ _copyRuleStmt(RuleStmt *from)
{ {
RuleStmt *newnode = makeNode(RuleStmt); RuleStmt *newnode = makeNode(RuleStmt);
Node_Copy(from, newnode, relation);
newnode->rulename = pstrdup(from->rulename); newnode->rulename = pstrdup(from->rulename);
Node_Copy(from, newnode, whereClause); Node_Copy(from, newnode, whereClause);
newnode->event = from->event; newnode->event = from->event;
Node_Copy(from, newnode, object);
newnode->instead = from->instead; newnode->instead = from->instead;
Node_Copy(from, newnode, actions); Node_Copy(from, newnode, actions);
@ -2170,8 +2181,7 @@ _copyNotifyStmt(NotifyStmt *from)
{ {
NotifyStmt *newnode = makeNode(NotifyStmt); NotifyStmt *newnode = makeNode(NotifyStmt);
if (from->relname) Node_Copy(from, newnode, relation);
newnode->relname = pstrdup(from->relname);
return newnode; return newnode;
} }
@ -2181,8 +2191,7 @@ _copyListenStmt(ListenStmt *from)
{ {
ListenStmt *newnode = makeNode(ListenStmt); ListenStmt *newnode = makeNode(ListenStmt);
if (from->relname) Node_Copy(from, newnode, relation);
newnode->relname = pstrdup(from->relname);
return newnode; return newnode;
} }
@ -2192,8 +2201,7 @@ _copyUnlistenStmt(UnlistenStmt *from)
{ {
UnlistenStmt *newnode = makeNode(UnlistenStmt); UnlistenStmt *newnode = makeNode(UnlistenStmt);
if (from->relname) Node_Copy(from, newnode, relation);
newnode->relname = pstrdup(from->relname);
return newnode; return newnode;
} }
@ -2213,8 +2221,7 @@ _copyViewStmt(ViewStmt *from)
{ {
ViewStmt *newnode = makeNode(ViewStmt); ViewStmt *newnode = makeNode(ViewStmt);
if (from->viewname) Node_Copy(from, newnode, view);
newnode->viewname = pstrdup(from->viewname);
Node_Copy(from, newnode, aliases); Node_Copy(from, newnode, aliases);
Node_Copy(from, newnode, query); Node_Copy(from, newnode, query);
@ -2298,8 +2305,7 @@ _copyVacuumStmt(VacuumStmt *from)
newnode->analyze = from->analyze; newnode->analyze = from->analyze;
newnode->freeze = from->freeze; newnode->freeze = from->freeze;
newnode->verbose = from->verbose; newnode->verbose = from->verbose;
if (from->vacrel) Node_Copy(from, newnode, relation);
newnode->vacrel = pstrdup(from->vacrel);
Node_Copy(from, newnode, va_cols); Node_Copy(from, newnode, va_cols);
return newnode; return newnode;
@ -2322,8 +2328,7 @@ _copyCreateSeqStmt(CreateSeqStmt *from)
{ {
CreateSeqStmt *newnode = makeNode(CreateSeqStmt); CreateSeqStmt *newnode = makeNode(CreateSeqStmt);
if (from->seqname) Node_Copy(from, newnode, sequence);
newnode->seqname = pstrdup(from->seqname);
Node_Copy(from, newnode, options); Node_Copy(from, newnode, options);
return newnode; return newnode;
@ -2370,8 +2375,7 @@ _copyCreateTrigStmt(CreateTrigStmt *from)
if (from->trigname) if (from->trigname)
newnode->trigname = pstrdup(from->trigname); newnode->trigname = pstrdup(from->trigname);
if (from->relname) Node_Copy(from, newnode, relation);
newnode->relname = pstrdup(from->relname);
if (from->funcname) if (from->funcname)
newnode->funcname = pstrdup(from->funcname); newnode->funcname = pstrdup(from->funcname);
Node_Copy(from, newnode, args); Node_Copy(from, newnode, args);
@ -2389,8 +2393,7 @@ _copyCreateTrigStmt(CreateTrigStmt *from)
newnode->isconstraint = from->isconstraint; newnode->isconstraint = from->isconstraint;
newnode->deferrable = from->deferrable; newnode->deferrable = from->deferrable;
newnode->initdeferred = from->initdeferred; newnode->initdeferred = from->initdeferred;
if (from->constrrelname) Node_Copy(from, newnode, constrrel);
newnode->constrrelname = pstrdup(from->constrrelname);
return newnode; return newnode;
} }
@ -2402,8 +2405,7 @@ _copyDropTrigStmt(DropTrigStmt *from)
if (from->trigname) if (from->trigname)
newnode->trigname = pstrdup(from->trigname); newnode->trigname = pstrdup(from->trigname);
if (from->relname) Node_Copy(from, newnode, relation);
newnode->relname = pstrdup(from->relname);
return newnode; return newnode;
} }
@ -2488,7 +2490,7 @@ _copyLockStmt(LockStmt *from)
{ {
LockStmt *newnode = makeNode(LockStmt); LockStmt *newnode = makeNode(LockStmt);
Node_Copy(from, newnode, rellist); Node_Copy(from, newnode, relations);
newnode->mode = from->mode; newnode->mode = from->mode;
@ -2548,6 +2550,7 @@ _copyReindexStmt(ReindexStmt *from)
ReindexStmt *newnode = makeNode(ReindexStmt); ReindexStmt *newnode = makeNode(ReindexStmt);
newnode->reindexType = from->reindexType; newnode->reindexType = from->reindexType;
Node_Copy(from, newnode, relation);
if (from->name) if (from->name)
newnode->name = pstrdup(from->name); newnode->name = pstrdup(from->name);
newnode->force = from->force; newnode->force = from->force;
@ -2556,6 +2559,19 @@ _copyReindexStmt(ReindexStmt *from)
return newnode; return newnode;
} }
static CreateSchemaStmt *
_copyCreateSchemaStmt(CreateSchemaStmt *from)
{
CreateSchemaStmt *newnode = makeNode(CreateSchemaStmt);
newnode->schemaname = pstrdup(from->schemaname);
if (from->authid)
newnode->authid = pstrdup(from->authid);
Node_Copy(from, newnode, schemaElts);
return newnode;
}
/* **************************************************************** /* ****************************************************************
* pg_list.h copy functions * pg_list.h copy functions
@ -2888,6 +2904,9 @@ copyObject(void *from)
case T_LoadStmt: case T_LoadStmt:
retval = _copyLoadStmt(from); retval = _copyLoadStmt(from);
break; break;
case T_CreateDomainStmt:
retval = _copyCreateDomainStmt(from);
break;
case T_CreatedbStmt: case T_CreatedbStmt:
retval = _copyCreatedbStmt(from); retval = _copyCreatedbStmt(from);
break; break;
@ -2960,19 +2979,22 @@ copyObject(void *from)
case T_CheckPointStmt: case T_CheckPointStmt:
retval = (void *) makeNode(CheckPointStmt); retval = (void *) makeNode(CheckPointStmt);
break; break;
case T_CreateSchemaStmt:
retval = _copyCreateSchemaStmt(from);
break;
case T_A_Expr: case T_A_Expr:
retval = _copyAExpr(from); retval = _copyAExpr(from);
break; break;
case T_Attr: case T_ColumnRef:
retval = _copyAttr(from); retval = _copyColumnRef(from);
break;
case T_ParamRef:
retval = _copyParamRef(from);
break; break;
case T_A_Const: case T_A_Const:
retval = _copyAConst(from); retval = _copyAConst(from);
break; break;
case T_ParamNo:
retval = _copyParamNo(from);
break;
case T_Ident: case T_Ident:
retval = _copyIdent(from); retval = _copyIdent(from);
break; break;
@ -2982,6 +3004,9 @@ copyObject(void *from)
case T_A_Indices: case T_A_Indices:
retval = _copyAIndices(from); retval = _copyAIndices(from);
break; break;
case T_ExprFieldSelect:
retval = _copyExprFieldSelect(from);
break;
case T_ResTarget: case T_ResTarget:
retval = _copyResTarget(from); retval = _copyResTarget(from);
break; break;
@ -2991,6 +3016,9 @@ copyObject(void *from)
case T_SortGroupBy: case T_SortGroupBy:
retval = _copySortGroupBy(from); retval = _copySortGroupBy(from);
break; break;
case T_Alias:
retval = _copyAlias(from);
break;
case T_RangeVar: case T_RangeVar:
retval = _copyRangeVar(from); retval = _copyRangeVar(from);
break; break;
@ -3045,9 +3073,6 @@ copyObject(void *from)
case T_FuncWithArgs: case T_FuncWithArgs:
retval = _copyFuncWithArgs(from); retval = _copyFuncWithArgs(from);
break; break;
case T_CreateDomainStmt:
retval = _copyCreateDomainStmt(from);
break;
default: default:
elog(ERROR, "copyObject: don't know how to copy node type %d", elog(ERROR, "copyObject: don't know how to copy node type %d",

View File

@ -20,7 +20,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.119 2002/03/20 19:44:01 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.120 2002/03/21 16:00:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -579,14 +579,12 @@ _equalQuery(Query *a, Query *b)
return false; return false;
if (a->resultRelation != b->resultRelation) if (a->resultRelation != b->resultRelation)
return false; return false;
if (!equalstr(a->into, b->into)) if (!equal(a->into, b->into))
return false; return false;
if (a->isPortal != b->isPortal) if (a->isPortal != b->isPortal)
return false; return false;
if (a->isBinary != b->isBinary) if (a->isBinary != b->isBinary)
return false; return false;
if (a->isTemp != b->isTemp)
return false;
if (a->hasAggs != b->hasAggs) if (a->hasAggs != b->hasAggs)
return false; return false;
if (a->hasSubLinks != b->hasSubLinks) if (a->hasSubLinks != b->hasSubLinks)
@ -629,7 +627,7 @@ _equalQuery(Query *a, Query *b)
static bool static bool
_equalInsertStmt(InsertStmt *a, InsertStmt *b) _equalInsertStmt(InsertStmt *a, InsertStmt *b)
{ {
if (!equalstr(a->relname, b->relname)) if (!equal(a->relation, b->relation))
return false; return false;
if (!equal(a->cols, b->cols)) if (!equal(a->cols, b->cols))
return false; return false;
@ -644,12 +642,10 @@ _equalInsertStmt(InsertStmt *a, InsertStmt *b)
static bool static bool
_equalDeleteStmt(DeleteStmt *a, DeleteStmt *b) _equalDeleteStmt(DeleteStmt *a, DeleteStmt *b)
{ {
if (!equalstr(a->relname, b->relname)) if (!equal(a->relation, b->relation))
return false; return false;
if (!equal(a->whereClause, b->whereClause)) if (!equal(a->whereClause, b->whereClause))
return false; return false;
if (a->inhOpt != b->inhOpt)
return false;
return true; return true;
} }
@ -657,7 +653,7 @@ _equalDeleteStmt(DeleteStmt *a, DeleteStmt *b)
static bool static bool
_equalUpdateStmt(UpdateStmt *a, UpdateStmt *b) _equalUpdateStmt(UpdateStmt *a, UpdateStmt *b)
{ {
if (!equalstr(a->relname, b->relname)) if (!equal(a->relation, b->relation))
return false; return false;
if (!equal(a->targetList, b->targetList)) if (!equal(a->targetList, b->targetList))
return false; return false;
@ -665,8 +661,6 @@ _equalUpdateStmt(UpdateStmt *a, UpdateStmt *b)
return false; return false;
if (!equal(a->fromClause, b->fromClause)) if (!equal(a->fromClause, b->fromClause))
return false; return false;
if (a->inhOpt != b->inhOpt)
return false;
return true; return true;
} }
@ -676,9 +670,7 @@ _equalSelectStmt(SelectStmt *a, SelectStmt *b)
{ {
if (!equal(a->distinctClause, b->distinctClause)) if (!equal(a->distinctClause, b->distinctClause))
return false; return false;
if (!equalstr(a->into, b->into)) if (!equal(a->into, b->into))
return false;
if (a->istemp != b->istemp)
return false; return false;
if (!equal(a->intoColNames, b->intoColNames)) if (!equal(a->intoColNames, b->intoColNames))
return false; return false;
@ -738,9 +730,7 @@ _equalAlterTableStmt(AlterTableStmt *a, AlterTableStmt *b)
{ {
if (a->subtype != b->subtype) if (a->subtype != b->subtype)
return false; return false;
if (!equalstr(a->relname, b->relname)) if (!equal(a->relation, b->relation))
return false;
if (a->inhOpt != b->inhOpt)
return false; return false;
if (!equalstr(a->name, b->name)) if (!equalstr(a->name, b->name))
return false; return false;
@ -795,7 +785,7 @@ _equalClosePortalStmt(ClosePortalStmt *a, ClosePortalStmt *b)
static bool static bool
_equalClusterStmt(ClusterStmt *a, ClusterStmt *b) _equalClusterStmt(ClusterStmt *a, ClusterStmt *b)
{ {
if (!equalstr(a->relname, b->relname)) if (!equal(a->relation, b->relation))
return false; return false;
if (!equalstr(a->indexname, b->indexname)) if (!equalstr(a->indexname, b->indexname))
return false; return false;
@ -808,7 +798,7 @@ _equalCopyStmt(CopyStmt *a, CopyStmt *b)
{ {
if (a->binary != b->binary) if (a->binary != b->binary)
return false; return false;
if (!equalstr(a->relname, b->relname)) if (!equal(a->relation, b->relation))
return false; return false;
if (a->oids != b->oids) if (a->oids != b->oids)
return false; return false;
@ -827,16 +817,14 @@ _equalCopyStmt(CopyStmt *a, CopyStmt *b)
static bool static bool
_equalCreateStmt(CreateStmt *a, CreateStmt *b) _equalCreateStmt(CreateStmt *a, CreateStmt *b)
{ {
if (!equalstr(a->relname, b->relname)) if (!equal(a->relation, b->relation))
return false; return false;
if (!equal(a->tableElts, b->tableElts)) if (!equal(a->tableElts, b->tableElts))
return false; return false;
if (!equal(a->inhRelnames, b->inhRelnames)) if (!equal(a->inhRelations, b->inhRelations))
return false; return false;
if (!equal(a->constraints, b->constraints)) if (!equal(a->constraints, b->constraints))
return false; return false;
if (a->istemp != b->istemp)
return false;
if (a->hasoids != b->hasoids) if (a->hasoids != b->hasoids)
return false; return false;
@ -874,7 +862,7 @@ _equalDefineStmt(DefineStmt *a, DefineStmt *b)
static bool static bool
_equalDropStmt(DropStmt *a, DropStmt *b) _equalDropStmt(DropStmt *a, DropStmt *b)
{ {
if (!equal(a->names, b->names)) if (!equal(a->objects, b->objects))
return false; return false;
if (a->removeType != b->removeType) if (a->removeType != b->removeType)
return false; return false;
@ -887,7 +875,7 @@ _equalDropStmt(DropStmt *a, DropStmt *b)
static bool static bool
_equalTruncateStmt(TruncateStmt *a, TruncateStmt *b) _equalTruncateStmt(TruncateStmt *a, TruncateStmt *b)
{ {
if (!equalstr(a->relName, b->relName)) if (!equal(a->relation, b->relation))
return false; return false;
return true; return true;
@ -900,6 +888,8 @@ _equalCommentStmt(CommentStmt *a, CommentStmt *b)
return false; return false;
if (!equalstr(a->objname, b->objname)) if (!equalstr(a->objname, b->objname))
return false; return false;
if (!equalstr(a->objschema, b->objschema))
return false;
if (!equalstr(a->objproperty, b->objproperty)) if (!equalstr(a->objproperty, b->objproperty))
return false; return false;
if (!equal(a->objlist, b->objlist)) if (!equal(a->objlist, b->objlist))
@ -930,7 +920,7 @@ _equalIndexStmt(IndexStmt *a, IndexStmt *b)
{ {
if (!equalstr(a->idxname, b->idxname)) if (!equalstr(a->idxname, b->idxname))
return false; return false;
if (!equalstr(a->relname, b->relname)) if (!equal(a->relation, b->relation))
return false; return false;
if (!equalstr(a->accessMethod, b->accessMethod)) if (!equalstr(a->accessMethod, b->accessMethod))
return false; return false;
@ -1006,9 +996,7 @@ _equalRemoveOperStmt(RemoveOperStmt *a, RemoveOperStmt *b)
static bool static bool
_equalRenameStmt(RenameStmt *a, RenameStmt *b) _equalRenameStmt(RenameStmt *a, RenameStmt *b)
{ {
if (!equalstr(a->relname, b->relname)) if (!equal(a->relation, b->relation))
return false;
if (a->inhOpt != b->inhOpt)
return false; return false;
if (!equalstr(a->column, b->column)) if (!equalstr(a->column, b->column))
return false; return false;
@ -1021,14 +1009,14 @@ _equalRenameStmt(RenameStmt *a, RenameStmt *b)
static bool static bool
_equalRuleStmt(RuleStmt *a, RuleStmt *b) _equalRuleStmt(RuleStmt *a, RuleStmt *b)
{ {
if (!equal(a->relation, b->relation))
return false;
if (!equalstr(a->rulename, b->rulename)) if (!equalstr(a->rulename, b->rulename))
return false; return false;
if (!equal(a->whereClause, b->whereClause)) if (!equal(a->whereClause, b->whereClause))
return false; return false;
if (a->event != b->event) if (a->event != b->event)
return false; return false;
if (!equal(a->object, b->object))
return false;
if (a->instead != b->instead) if (a->instead != b->instead)
return false; return false;
if (!equal(a->actions, b->actions)) if (!equal(a->actions, b->actions))
@ -1040,7 +1028,7 @@ _equalRuleStmt(RuleStmt *a, RuleStmt *b)
static bool static bool
_equalNotifyStmt(NotifyStmt *a, NotifyStmt *b) _equalNotifyStmt(NotifyStmt *a, NotifyStmt *b)
{ {
if (!equalstr(a->relname, b->relname)) if (!equal(a->relation, b->relation))
return false; return false;
return true; return true;
@ -1049,7 +1037,7 @@ _equalNotifyStmt(NotifyStmt *a, NotifyStmt *b)
static bool static bool
_equalListenStmt(ListenStmt *a, ListenStmt *b) _equalListenStmt(ListenStmt *a, ListenStmt *b)
{ {
if (!equalstr(a->relname, b->relname)) if (!equal(a->relation, b->relation))
return false; return false;
return true; return true;
@ -1058,7 +1046,7 @@ _equalListenStmt(ListenStmt *a, ListenStmt *b)
static bool static bool
_equalUnlistenStmt(UnlistenStmt *a, UnlistenStmt *b) _equalUnlistenStmt(UnlistenStmt *a, UnlistenStmt *b)
{ {
if (!equalstr(a->relname, b->relname)) if (!equal(a->relation, b->relation))
return false; return false;
return true; return true;
@ -1076,7 +1064,7 @@ _equalTransactionStmt(TransactionStmt *a, TransactionStmt *b)
static bool static bool
_equalViewStmt(ViewStmt *a, ViewStmt *b) _equalViewStmt(ViewStmt *a, ViewStmt *b)
{ {
if (!equalstr(a->viewname, b->viewname)) if (!equal(a->view, b->view))
return false; return false;
if (!equal(a->aliases, b->aliases)) if (!equal(a->aliases, b->aliases))
return false; return false;
@ -1160,7 +1148,7 @@ _equalVacuumStmt(VacuumStmt *a, VacuumStmt *b)
return false; return false;
if (a->verbose != b->verbose) if (a->verbose != b->verbose)
return false; return false;
if (!equalstr(a->vacrel, b->vacrel)) if (!equal(a->relation, b->relation))
return false; return false;
if (!equal(a->va_cols, b->va_cols)) if (!equal(a->va_cols, b->va_cols))
return false; return false;
@ -1184,7 +1172,7 @@ _equalExplainStmt(ExplainStmt *a, ExplainStmt *b)
static bool static bool
_equalCreateSeqStmt(CreateSeqStmt *a, CreateSeqStmt *b) _equalCreateSeqStmt(CreateSeqStmt *a, CreateSeqStmt *b)
{ {
if (!equalstr(a->seqname, b->seqname)) if (!equal(a->sequence, b->sequence))
return false; return false;
if (!equal(a->options, b->options)) if (!equal(a->options, b->options))
return false; return false;
@ -1226,7 +1214,7 @@ _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b)
{ {
if (!equalstr(a->trigname, b->trigname)) if (!equalstr(a->trigname, b->trigname))
return false; return false;
if (!equalstr(a->relname, b->relname)) if (!equal(a->relation, b->relation))
return false; return false;
if (!equalstr(a->funcname, b->funcname)) if (!equalstr(a->funcname, b->funcname))
return false; return false;
@ -1252,7 +1240,7 @@ _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b)
return false; return false;
if (a->initdeferred != b->initdeferred) if (a->initdeferred != b->initdeferred)
return false; return false;
if (!equalstr(a->constrrelname, b->constrrelname)) if (!equal(a->constrrel, b->constrrel))
return false; return false;
return true; return true;
@ -1263,7 +1251,7 @@ _equalDropTrigStmt(DropTrigStmt *a, DropTrigStmt *b)
{ {
if (!equalstr(a->trigname, b->trigname)) if (!equalstr(a->trigname, b->trigname))
return false; return false;
if (!equalstr(a->relname, b->relname)) if (!equal(a->relation, b->relation))
return false; return false;
return true; return true;
@ -1340,7 +1328,7 @@ _equalDropUserStmt(DropUserStmt *a, DropUserStmt *b)
static bool static bool
_equalLockStmt(LockStmt *a, LockStmt *b) _equalLockStmt(LockStmt *a, LockStmt *b)
{ {
if (!equal(a->rellist, b->rellist)) if (!equal(a->relations, b->relations))
return false; return false;
if (a->mode != b->mode) if (a->mode != b->mode)
return false; return false;
@ -1397,6 +1385,8 @@ _equalReindexStmt(ReindexStmt *a, ReindexStmt *b)
{ {
if (a->reindexType != b->reindexType) if (a->reindexType != b->reindexType)
return false; return false;
if (!equal(a->relation, b->relation))
return false;
if (!equalstr(a->name, b->name)) if (!equalstr(a->name, b->name))
return false; return false;
if (a->force != b->force) if (a->force != b->force)
@ -1407,6 +1397,19 @@ _equalReindexStmt(ReindexStmt *a, ReindexStmt *b)
return true; return true;
} }
static bool
_equalCreateSchemaStmt(CreateSchemaStmt *a, CreateSchemaStmt *b)
{
if (!equalstr(a->schemaname, b->schemaname))
return false;
if (!equalstr(a->authid, b->authid))
return false;
if (!equal(a->schemaElts, b->schemaElts))
return false;
return true;
}
static bool static bool
_equalAExpr(A_Expr *a, A_Expr *b) _equalAExpr(A_Expr *a, A_Expr *b)
{ {
@ -1423,13 +1426,22 @@ _equalAExpr(A_Expr *a, A_Expr *b)
} }
static bool static bool
_equalAttr(Attr *a, Attr *b) _equalColumnRef(ColumnRef *a, ColumnRef *b)
{ {
if (strcmp(a->relname, b->relname) != 0) if (!equal(a->fields, b->fields))
return false; return false;
if (!equal(a->paramNo, b->paramNo)) if (!equal(a->indirection, b->indirection))
return false; return false;
if (!equal(a->attrs, b->attrs))
return true;
}
static bool
_equalParamRef(ParamRef *a, ParamRef *b)
{
if (a->number != b->number)
return false;
if (!equal(a->fields, b->fields))
return false; return false;
if (!equal(a->indirection, b->indirection)) if (!equal(a->indirection, b->indirection))
return false; return false;
@ -1448,28 +1460,11 @@ _equalAConst(A_Const *a, A_Const *b)
return true; return true;
} }
static bool
_equalParamNo(ParamNo *a, ParamNo *b)
{
if (a->number != b->number)
return false;
if (!equal(a->typename, b->typename))
return false;
if (!equal(a->indirection, b->indirection))
return false;
return true;
}
static bool static bool
_equalIdent(Ident *a, Ident *b) _equalIdent(Ident *a, Ident *b)
{ {
if (!equalstr(a->name, b->name)) if (!equalstr(a->name, b->name))
return false; return false;
if (!equal(a->indirection, b->indirection))
return false;
if (a->isRel != b->isRel)
return false;
return true; return true;
} }
@ -1500,6 +1495,19 @@ _equalAIndices(A_Indices *a, A_Indices *b)
return true; return true;
} }
static bool
_equalExprFieldSelect(ExprFieldSelect *a, ExprFieldSelect *b)
{
if (!equal(a->arg, b->arg))
return false;
if (!equal(a->fields, b->fields))
return false;
if (!equal(a->indirection, b->indirection))
return false;
return true;
}
static bool static bool
_equalResTarget(ResTarget *a, ResTarget *b) _equalResTarget(ResTarget *a, ResTarget *b)
{ {
@ -1535,14 +1543,31 @@ _equalSortGroupBy(SortGroupBy *a, SortGroupBy *b)
return true; return true;
} }
static bool
_equalAlias(Alias *a, Alias *b)
{
if (!equalstr(a->aliasname, b->aliasname))
return false;
if (!equal(a->colnames, b->colnames))
return false;
return true;
}
static bool static bool
_equalRangeVar(RangeVar *a, RangeVar *b) _equalRangeVar(RangeVar *a, RangeVar *b)
{ {
if (!equalstr(a->catalogname, b->catalogname))
return false;
if (!equalstr(a->schemaname, b->schemaname))
return false;
if (!equalstr(a->relname, b->relname)) if (!equalstr(a->relname, b->relname))
return false; return false;
if (a->inhOpt != b->inhOpt) if (a->inhOpt != b->inhOpt)
return false; return false;
if (!equal(a->name, b->name)) if (a->istemp != b->istemp)
return false;
if (!equal(a->alias, b->alias))
return false; return false;
return true; return true;
@ -1553,7 +1578,7 @@ _equalRangeSubselect(RangeSubselect *a, RangeSubselect *b)
{ {
if (!equal(a->subquery, b->subquery)) if (!equal(a->subquery, b->subquery))
return false; return false;
if (!equal(a->name, b->name)) if (!equal(a->alias, b->alias))
return false; return false;
return true; return true;
@ -1704,7 +1729,7 @@ _equalFkConstraint(FkConstraint *a, FkConstraint *b)
{ {
if (!equalstr(a->constr_name, b->constr_name)) if (!equalstr(a->constr_name, b->constr_name))
return false; return false;
if (!equalstr(a->pktable_name, b->pktable_name)) if (!equal(a->pktable, b->pktable))
return false; return false;
if (!equal(a->fk_attrs, b->fk_attrs)) if (!equal(a->fk_attrs, b->fk_attrs))
return false; return false;
@ -2111,19 +2136,22 @@ equal(void *a, void *b)
case T_CheckPointStmt: case T_CheckPointStmt:
retval = true; retval = true;
break; break;
case T_CreateSchemaStmt:
retval = _equalCreateSchemaStmt(a, b);
break;
case T_A_Expr: case T_A_Expr:
retval = _equalAExpr(a, b); retval = _equalAExpr(a, b);
break; break;
case T_Attr: case T_ColumnRef:
retval = _equalAttr(a, b); retval = _equalColumnRef(a, b);
break;
case T_ParamRef:
retval = _equalParamRef(a, b);
break; break;
case T_A_Const: case T_A_Const:
retval = _equalAConst(a, b); retval = _equalAConst(a, b);
break; break;
case T_ParamNo:
retval = _equalParamNo(a, b);
break;
case T_Ident: case T_Ident:
retval = _equalIdent(a, b); retval = _equalIdent(a, b);
break; break;
@ -2133,6 +2161,9 @@ equal(void *a, void *b)
case T_A_Indices: case T_A_Indices:
retval = _equalAIndices(a, b); retval = _equalAIndices(a, b);
break; break;
case T_ExprFieldSelect:
retval = _equalExprFieldSelect(a, b);
break;
case T_ResTarget: case T_ResTarget:
retval = _equalResTarget(a, b); retval = _equalResTarget(a, b);
break; break;
@ -2142,6 +2173,9 @@ equal(void *a, void *b)
case T_SortGroupBy: case T_SortGroupBy:
retval = _equalSortGroupBy(a, b); retval = _equalSortGroupBy(a, b);
break; break;
case T_Alias:
retval = _equalAlias(a, b);
break;
case T_RangeVar: case T_RangeVar:
retval = _equalRangeVar(a, b); retval = _equalRangeVar(a, b);
break; break;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.27 2002/03/20 19:44:04 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.28 2002/03/21 16:00:40 tgl Exp $
*/ */
#include "postgres.h" #include "postgres.h"
@ -159,19 +159,18 @@ makeNullConst(Oid consttype)
} }
/* /*
* makeAttr - * makeAlias -
* creates an Attr node * creates an Alias node
*
* NOTE: the given name is copied, but the colnames list (if any) isn't.
*/ */
Attr * Alias *
makeAttr(char *relname, char *attname) makeAlias(const char *aliasname, List *colnames)
{ {
Attr *a = makeNode(Attr); Alias *a = makeNode(Alias);
a->relname = pstrdup(relname); a->aliasname = pstrdup(aliasname);
a->paramNo = NULL; a->colnames = colnames;
if (attname != NULL)
a->attrs = makeList1(makeString(pstrdup(attname)));
a->indirection = NULL;
return a; return a;
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/nodeFuncs.c,v 1.16 2001/10/28 06:25:44 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/nodeFuncs.c,v 1.17 2002/03/21 16:00:40 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -29,7 +29,9 @@ static bool var_is_inner(Var *var);
bool bool
single_node(Node *node) single_node(Node *node)
{ {
if (IsA(node, Ident) ||IsA(node, Const) ||IsA(node, Var) ||IsA(node, Param)) if (IsA(node, Const) ||
IsA(node, Var) ||
IsA(node, Param))
return true; return true;
else else
return false; return false;
@ -103,13 +105,13 @@ replace_opid(Oper *oper)
* non_null - * non_null -
* Returns t if the node is a non-null constant, e.g., if the node has a * Returns t if the node is a non-null constant, e.g., if the node has a
* valid `constvalue' field. * valid `constvalue' field.
*
*/ */
bool bool
non_null(Expr *c) non_null(Expr *c)
{ {
if (IsA(c, Const) &&!((Const *) c)->constisnull) if (IsA(c, Const) &&
!((Const *) c)->constisnull)
return true; return true;
else else
return false; return false;

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.149 2002/03/12 00:51:39 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.150 2002/03/21 16:00:40 tgl Exp $
* *
* NOTES * NOTES
* Every (plan) node in POSTGRES has an associated "out" routine which * Every (plan) node in POSTGRES has an associated "out" routine which
@ -105,20 +105,19 @@ _outOidList(StringInfo str, List *list)
static void static void
_outCreateStmt(StringInfo str, CreateStmt *node) _outCreateStmt(StringInfo str, CreateStmt *node)
{ {
appendStringInfo(str, " CREATE :relname "); appendStringInfo(str, " CREATE :relation ");
_outToken(str, node->relname); _outNode(str, node->relation);
appendStringInfo(str, " :columns "); appendStringInfo(str, " :tableElts ");
_outNode(str, node->tableElts); _outNode(str, node->tableElts);
appendStringInfo(str, " :inhRelnames "); appendStringInfo(str, " :inhRelations ");
_outNode(str, node->inhRelnames); _outNode(str, node->inhRelations);
appendStringInfo(str, " :constraints "); appendStringInfo(str, " :constraints ");
_outNode(str, node->constraints); _outNode(str, node->constraints);
appendStringInfo(str, " :istemp %s :hasoids %s ", appendStringInfo(str, " :hasoids %s ",
booltostr(node->istemp),
booltostr(node->hasoids)); booltostr(node->hasoids));
} }
@ -127,8 +126,8 @@ _outIndexStmt(StringInfo str, IndexStmt *node)
{ {
appendStringInfo(str, " INDEX :idxname "); appendStringInfo(str, " INDEX :idxname ");
_outToken(str, node->idxname); _outToken(str, node->idxname);
appendStringInfo(str, " :relname "); appendStringInfo(str, " :relation ");
_outToken(str, node->relname); _outNode(str, node->relation);
appendStringInfo(str, " :accessMethod "); appendStringInfo(str, " :accessMethod ");
_outToken(str, node->accessMethod); _outToken(str, node->accessMethod);
appendStringInfo(str, " :indexParams "); appendStringInfo(str, " :indexParams ");
@ -142,6 +141,13 @@ _outIndexStmt(StringInfo str, IndexStmt *node)
booltostr(node->primary)); booltostr(node->primary));
} }
static void
_outNotifyStmt(StringInfo str, NotifyStmt *node)
{
appendStringInfo(str, "NOTIFY :relation ");
_outNode(str, node->relation);
}
static void static void
_outSelectStmt(StringInfo str, SelectStmt *node) _outSelectStmt(StringInfo str, SelectStmt *node)
{ {
@ -213,53 +219,40 @@ _outIndexElem(StringInfo str, IndexElem *node)
static void static void
_outQuery(StringInfo str, Query *node) _outQuery(StringInfo str, Query *node)
{ {
appendStringInfo(str, " QUERY :command %d :utility ", node->commandType);
appendStringInfo(str, " QUERY :command %d ", node->commandType); /*
* Hack to work around missing outfuncs routines for a lot of the
* utility-statement node types. (The only one we actually *need*
* for rules support is NotifyStmt.) Someday we ought to support
* 'em all, but for the meantime do this to avoid getting lots of
* warnings when running with debug_print_parse on.
*/
if (node->utilityStmt) if (node->utilityStmt)
{ {
/*
* Hack to make up for lack of outfuncs for utility-stmt nodes
*/
switch (nodeTag(node->utilityStmt)) switch (nodeTag(node->utilityStmt))
{ {
case T_CreateStmt: case T_CreateStmt:
appendStringInfo(str, " :create ");
_outToken(str, ((CreateStmt *) (node->utilityStmt))->relname);
appendStringInfo(str, " ");
_outNode(str, node->utilityStmt);
break;
case T_IndexStmt: case T_IndexStmt:
appendStringInfo(str, " :index "); case T_NotifyStmt:
_outToken(str, ((IndexStmt *) (node->utilityStmt))->idxname);
appendStringInfo(str, " on ");
_outToken(str, ((IndexStmt *) (node->utilityStmt))->relname);
appendStringInfo(str, " ");
_outNode(str, node->utilityStmt); _outNode(str, node->utilityStmt);
break; break;
case T_NotifyStmt:
appendStringInfo(str, " :notify ");
_outToken(str, ((NotifyStmt *) (node->utilityStmt))->relname);
break;
default: default:
appendStringInfo(str, " :utility ? "); appendStringInfo(str, "?");
break;
} }
} }
else else
appendStringInfo(str, " :utility <>"); appendStringInfo(str, "<>");
appendStringInfo(str, " :resultRelation %d :into ", appendStringInfo(str, " :resultRelation %d :into ",
node->resultRelation); node->resultRelation);
_outToken(str, node->into); _outNode(str, node->into);
appendStringInfo(str, " :isPortal %s :isBinary %s :isTemp %s" appendStringInfo(str, " :isPortal %s :isBinary %s"
" :hasAggs %s :hasSubLinks %s :rtable ", " :hasAggs %s :hasSubLinks %s :rtable ",
booltostr(node->isPortal), booltostr(node->isPortal),
booltostr(node->isBinary), booltostr(node->isBinary),
booltostr(node->isTemp),
booltostr(node->hasAggs), booltostr(node->hasAggs),
booltostr(node->hasSubLinks)); booltostr(node->hasSubLinks));
_outNode(str, node->rtable); _outNode(str, node->rtable);
@ -963,6 +956,15 @@ _outTargetEntry(StringInfo str, TargetEntry *node)
_outNode(str, node->expr); _outNode(str, node->expr);
} }
static void
_outAlias(StringInfo str, Alias *node)
{
appendStringInfo(str, " ALIAS :aliasname ");
_outToken(str, node->aliasname);
appendStringInfo(str, " :colnames ");
_outNode(str, node->colnames);
}
static void static void
_outRangeTblEntry(StringInfo str, RangeTblEntry *node) _outRangeTblEntry(StringInfo str, RangeTblEntry *node)
{ {
@ -1311,6 +1313,42 @@ _outValue(StringInfo str, Value *value)
} }
} }
static void
_outRangeVar(StringInfo str, RangeVar *node)
{
appendStringInfo(str, " RANGEVAR :relation ");
/*
* we deliberately ignore catalogname here, since it is presently not
* semantically meaningful
*/
_outToken(str, node->schemaname);
appendStringInfo(str, " . ");
_outToken(str, node->relname);
appendStringInfo(str, " :inhopt %d :istemp %s",
(int) node->inhOpt,
booltostr(node->istemp));
appendStringInfo(str, " :alias ");
_outNode(str, node->alias);
}
static void
_outColumnRef(StringInfo str, ColumnRef *node)
{
appendStringInfo(str, " COLUMNREF :fields ");
_outNode(str, node->fields);
appendStringInfo(str, " :indirection ");
_outNode(str, node->indirection);
}
static void
_outParamRef(StringInfo str, ParamRef *node)
{
appendStringInfo(str, " PARAMREF :number %d :fields ", node->number);
_outNode(str, node->fields);
appendStringInfo(str, " :indirection ");
_outNode(str, node->indirection);
}
static void static void
_outIdent(StringInfo str, Ident *node) _outIdent(StringInfo str, Ident *node)
{ {
@ -1318,15 +1356,6 @@ _outIdent(StringInfo str, Ident *node)
_outToken(str, node->name); _outToken(str, node->name);
} }
static void
_outAttr(StringInfo str, Attr *node)
{
appendStringInfo(str, " ATTR :relname ");
_outToken(str, node->relname);
appendStringInfo(str, " :attrs ");
_outNode(str, node->attrs);
}
static void static void
_outAConst(StringInfo str, A_Const *node) _outAConst(StringInfo str, A_Const *node)
{ {
@ -1336,6 +1365,17 @@ _outAConst(StringInfo str, A_Const *node)
_outNode(str, node->typename); _outNode(str, node->typename);
} }
static void
_outExprFieldSelect(StringInfo str, ExprFieldSelect *node)
{
appendStringInfo(str, " EXPRFIELDSELECT :arg ");
_outNode(str, node->arg);
appendStringInfo(str, " :fields ");
_outNode(str, node->fields);
appendStringInfo(str, " :indirection ");
_outNode(str, node->indirection);
}
static void static void
_outConstraint(StringInfo str, Constraint *node) _outConstraint(StringInfo str, Constraint *node)
{ {
@ -1384,8 +1424,8 @@ _outFkConstraint(StringInfo str, FkConstraint *node)
{ {
appendStringInfo(str, " FKCONSTRAINT :constr_name "); appendStringInfo(str, " FKCONSTRAINT :constr_name ");
_outToken(str, node->constr_name); _outToken(str, node->constr_name);
appendStringInfo(str, " :pktable_name "); appendStringInfo(str, " :pktable ");
_outToken(str, node->pktable_name); _outNode(str, node->pktable);
appendStringInfo(str, " :fk_attrs "); appendStringInfo(str, " :fk_attrs ");
_outNode(str, node->fk_attrs); _outNode(str, node->fk_attrs);
appendStringInfo(str, " :pk_attrs "); appendStringInfo(str, " :pk_attrs ");
@ -1490,6 +1530,12 @@ _outNode(StringInfo str, void *obj)
case T_IndexStmt: case T_IndexStmt:
_outIndexStmt(str, obj); _outIndexStmt(str, obj);
break; break;
case T_NotifyStmt:
_outNotifyStmt(str, obj);
break;
case T_SelectStmt:
_outSelectStmt(str, obj);
break;
case T_ColumnDef: case T_ColumnDef:
_outColumnDef(str, obj); _outColumnDef(str, obj);
break; break;
@ -1628,6 +1674,9 @@ _outNode(StringInfo str, void *obj)
case T_TargetEntry: case T_TargetEntry:
_outTargetEntry(str, obj); _outTargetEntry(str, obj);
break; break;
case T_Alias:
_outAlias(str, obj);
break;
case T_RangeTblEntry: case T_RangeTblEntry:
_outRangeTblEntry(str, obj); _outRangeTblEntry(str, obj);
break; break;
@ -1670,12 +1719,24 @@ _outNode(StringInfo str, void *obj)
case T_A_Expr: case T_A_Expr:
_outAExpr(str, obj); _outAExpr(str, obj);
break; break;
case T_RangeVar:
_outRangeVar(str, obj);
break;
case T_ColumnRef:
_outColumnRef(str, obj);
break;
case T_ParamRef:
_outParamRef(str, obj);
break;
case T_Ident: case T_Ident:
_outIdent(str, obj); _outIdent(str, obj);
break; break;
case T_A_Const: case T_A_Const:
_outAConst(str, obj); _outAConst(str, obj);
break; break;
case T_ExprFieldSelect:
_outExprFieldSelect(str, obj);
break;
case T_Constraint: case T_Constraint:
_outConstraint(str, obj); _outConstraint(str, obj);
break; break;
@ -1694,17 +1755,9 @@ _outNode(StringInfo str, void *obj)
case T_BooleanTest: case T_BooleanTest:
_outBooleanTest(str, obj); _outBooleanTest(str, obj);
break; break;
case T_VariableSetStmt:
break;
case T_SelectStmt:
_outSelectStmt(str, obj);
break;
case T_FuncCall: case T_FuncCall:
_outFuncCall(str, obj); _outFuncCall(str, obj);
break; break;
case T_Attr:
_outAttr(str, obj);
break;
default: default:
elog(WARNING, "_outNode: don't know how to print type %d ", elog(WARNING, "_outNode: don't know how to print type %d ",

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.51 2001/12/20 02:39:26 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.52 2002/03/21 16:00:41 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
@ -154,10 +154,10 @@ print_rt(List *rtable)
if (rte->relname) if (rte->relname)
printf("%d\t%s (%s)\t%u", printf("%d\t%s (%s)\t%u",
i, rte->relname, rte->eref->relname, rte->relid); i, rte->relname, rte->eref->aliasname, rte->relid);
else else
printf("%d\t[subquery] (%s)\t", printf("%d\t[subquery] (%s)\t",
i, rte->eref->relname); i, rte->eref->aliasname);
printf("\t%s\t%s\n", printf("\t%s\t%s\n",
(rte->inh ? "inh" : ""), (rte->inh ? "inh" : ""),
(rte->inFromCl ? "inFromCl" : "")); (rte->inFromCl ? "inFromCl" : ""));
@ -202,7 +202,7 @@ print_expr(Node *expr, List *rtable)
Assert(var->varno > 0 && Assert(var->varno > 0 &&
(int) var->varno <= length(rtable)); (int) var->varno <= length(rtable));
rte = rt_fetch(var->varno, rtable); rte = rt_fetch(var->varno, rtable);
relname = rte->eref->relname; relname = rte->eref->aliasname;
attname = get_rte_attribute_name(rte, var->varattno); attname = get_rte_attribute_name(rte, var->varattno);
} }
break; break;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.116 2002/03/12 00:51:39 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.117 2002/03/21 16:00:42 tgl Exp $
* *
* NOTES * NOTES
* Most of the read functions for plan nodes are tested. (In fact, they * Most of the read functions for plan nodes are tested. (In fact, they
@ -119,34 +119,19 @@ _readQuery(void)
local_node = makeNode(Query); local_node = makeNode(Query);
token = pg_strtok(&length); /* skip the :command */ token = pg_strtok(&length); /* skip :command */
token = pg_strtok(&length); /* get the commandType */ token = pg_strtok(&length); /* get commandType */
local_node->commandType = atoi(token); local_node->commandType = atoi(token);
token = pg_strtok(&length); /* skip :utility */ token = pg_strtok(&length); /* skip :utility */
token = pg_strtok(&length); local_node->utilityStmt = nodeRead(true);
if (length == 0)
local_node->utilityStmt = NULL;
else
{
/*
* Hack to make up for lack of readfuncs for utility-stmt nodes
*
* we can't get create or index here, can we?
*/
NotifyStmt *n = makeNode(NotifyStmt);
n->relname = debackslash(token, length); token = pg_strtok(&length); /* skip :resultRelation */
local_node->utilityStmt = (Node *) n;
}
token = pg_strtok(&length); /* skip the :resultRelation */
token = pg_strtok(&length); /* get the resultRelation */ token = pg_strtok(&length); /* get the resultRelation */
local_node->resultRelation = atoi(token); local_node->resultRelation = atoi(token);
token = pg_strtok(&length); /* skip :into */ token = pg_strtok(&length); /* skip :into */
token = pg_strtok(&length); /* get into */ local_node->into = nodeRead(true);
local_node->into = nullable_string(token, length);
token = pg_strtok(&length); /* skip :isPortal */ token = pg_strtok(&length); /* skip :isPortal */
token = pg_strtok(&length); /* get isPortal */ token = pg_strtok(&length); /* get isPortal */
@ -156,10 +141,6 @@ _readQuery(void)
token = pg_strtok(&length); /* get isBinary */ token = pg_strtok(&length); /* get isBinary */
local_node->isBinary = strtobool(token); local_node->isBinary = strtobool(token);
token = pg_strtok(&length); /* skip :isTemp */
token = pg_strtok(&length); /* get isTemp */
local_node->isTemp = strtobool(token);
token = pg_strtok(&length); /* skip the :hasAggs */ token = pg_strtok(&length); /* skip the :hasAggs */
token = pg_strtok(&length); /* get hasAggs */ token = pg_strtok(&length); /* get hasAggs */
local_node->hasAggs = strtobool(token); local_node->hasAggs = strtobool(token);
@ -210,6 +191,25 @@ _readQuery(void)
return local_node; return local_node;
} }
/* ----------------
* _readNotifyStmt
* ----------------
*/
static NotifyStmt *
_readNotifyStmt(void)
{
NotifyStmt *local_node;
char *token;
int length;
local_node = makeNode(NotifyStmt);
token = pg_strtok(&length); /* skip :relation */
local_node->relation = nodeRead(true);
return local_node;
}
/* ---------------- /* ----------------
* _readSortClause * _readSortClause
* ---------------- * ----------------
@ -1394,21 +1394,93 @@ _readTargetEntry(void)
return local_node; return local_node;
} }
static Attr * static RangeVar *
_readAttr(void) _readRangeVar(void)
{ {
Attr *local_node; RangeVar *local_node;
char *token; char *token;
int length; int length;
local_node = makeNode(Attr); local_node = makeNode(RangeVar);
token = pg_strtok(&length); /* eat :relname */ local_node->catalogname = NULL; /* not currently saved in output format */
token = pg_strtok(&length); /* eat :relation */
token = pg_strtok(&length); /* get schemaname */
local_node->schemaname = nullable_string(token, length);
token = pg_strtok(&length); /* eat "." */
token = pg_strtok(&length); /* get relname */ token = pg_strtok(&length); /* get relname */
local_node->relname = debackslash(token, length); local_node->relname = nullable_string(token, length);
token = pg_strtok(&length); /* eat :attrs */ token = pg_strtok(&length); /* eat :inhopt */
local_node->attrs = nodeRead(true); /* now read it */ token = pg_strtok(&length); /* get inhopt */
local_node->inhOpt = (InhOption) atoi(token);
token = pg_strtok(&length); /* eat :istemp */
token = pg_strtok(&length); /* get istemp */
local_node->istemp = strtobool(token);
token = pg_strtok(&length); /* eat :alias */
local_node->alias = nodeRead(true); /* now read it */
return local_node;
}
static ColumnRef *
_readColumnRef(void)
{
ColumnRef *local_node;
char *token;
int length;
local_node = makeNode(ColumnRef);
token = pg_strtok(&length); /* eat :fields */
local_node->fields = nodeRead(true); /* now read it */
token = pg_strtok(&length); /* eat :indirection */
local_node->indirection = nodeRead(true); /* now read it */
return local_node;
}
static ExprFieldSelect *
_readExprFieldSelect(void)
{
ExprFieldSelect *local_node;
char *token;
int length;
local_node = makeNode(ExprFieldSelect);
token = pg_strtok(&length); /* eat :arg */
local_node->arg = nodeRead(true); /* now read it */
token = pg_strtok(&length); /* eat :fields */
local_node->fields = nodeRead(true); /* now read it */
token = pg_strtok(&length); /* eat :indirection */
local_node->indirection = nodeRead(true); /* now read it */
return local_node;
}
static Alias *
_readAlias(void)
{
Alias *local_node;
char *token;
int length;
local_node = makeNode(Alias);
token = pg_strtok(&length); /* eat :aliasname */
token = pg_strtok(&length); /* get aliasname */
local_node->aliasname = debackslash(token, length);
token = pg_strtok(&length); /* eat :colnames */
local_node->colnames = nodeRead(true); /* now read it */
return local_node; return local_node;
} }
@ -1994,8 +2066,6 @@ parsePlanString(void)
return_value = _readArrayRef(); return_value = _readArrayRef();
else if (length == 3 && strncmp(token, "VAR", length) == 0) else if (length == 3 && strncmp(token, "VAR", length) == 0)
return_value = _readVar(); return_value = _readVar();
else if (length == 4 && strncmp(token, "ATTR", length) == 0)
return_value = _readAttr();
else if (length == 5 && strncmp(token, "CONST", length) == 0) else if (length == 5 && strncmp(token, "CONST", length) == 0)
return_value = _readConst(); return_value = _readConst();
else if (length == 4 && strncmp(token, "FUNC", length) == 0) else if (length == 4 && strncmp(token, "FUNC", length) == 0)
@ -2006,6 +2076,14 @@ parsePlanString(void)
return_value = _readParam(); return_value = _readParam();
else if (length == 11 && strncmp(token, "TARGETENTRY", length) == 0) else if (length == 11 && strncmp(token, "TARGETENTRY", length) == 0)
return_value = _readTargetEntry(); return_value = _readTargetEntry();
else if (length == 8 && strncmp(token, "RANGEVAR", length) == 0)
return_value = _readRangeVar();
else if (length == 9 && strncmp(token, "COLUMNREF", length) == 0)
return_value = _readColumnRef();
else if (length == 15 && strncmp(token, "EXPRFIELDSELECT", length) == 0)
return_value = _readExprFieldSelect();
else if (length == 5 && strncmp(token, "ALIAS", length) == 0)
return_value = _readAlias();
else if (length == 3 && strncmp(token, "RTE", length) == 0) else if (length == 3 && strncmp(token, "RTE", length) == 0)
return_value = _readRangeTblEntry(); return_value = _readRangeTblEntry();
else if (length == 4 && strncmp(token, "PATH", length) == 0) else if (length == 4 && strncmp(token, "PATH", length) == 0)
@ -2032,6 +2110,8 @@ parsePlanString(void)
return_value = _readIter(); return_value = _readIter();
else if (length == 5 && strncmp(token, "QUERY", length) == 0) else if (length == 5 && strncmp(token, "QUERY", length) == 0)
return_value = _readQuery(); return_value = _readQuery();
else if (length == 6 && strncmp(token, "NOTIFY", length) == 0)
return_value = _readNotifyStmt();
else if (length == 10 && strncmp(token, "SORTCLAUSE", length) == 0) else if (length == 10 && strncmp(token, "SORTCLAUSE", length) == 0)
return_value = _readSortClause(); return_value = _readSortClause();
else if (length == 11 && strncmp(token, "GROUPCLAUSE", length) == 0) else if (length == 11 && strncmp(token, "GROUPCLAUSE", length) == 0)

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.94 2002/03/12 00:51:50 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.95 2002/03/21 16:00:44 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
@ -687,7 +687,7 @@ check_subplans_for_ungrouped_vars_walker(Node *node,
rte = rt_fetch(var->varno, context->query->rtable); rte = rt_fetch(var->varno, context->query->rtable);
attname = get_rte_attribute_name(rte, var->varattno); attname = get_rte_attribute_name(rte, var->varattno);
elog(ERROR, "Sub-SELECT uses un-GROUPed attribute %s.%s from outer query", elog(ERROR, "Sub-SELECT uses un-GROUPed attribute %s.%s from outer query",
rte->eref->relname, attname); rte->eref->aliasname, attname);
} }
} }
} }
@ -1670,7 +1670,6 @@ expression_tree_walker(Node *node,
return false; return false;
switch (nodeTag(node)) switch (nodeTag(node))
{ {
case T_Ident:
case T_Const: case T_Const:
case T_Var: case T_Var:
case T_Param: case T_Param:
@ -1963,7 +1962,6 @@ expression_tree_mutator(Node *node,
return NULL; return NULL;
switch (nodeTag(node)) switch (nodeTag(node))
{ {
case T_Ident:
case T_Const: case T_Const:
case T_Var: case T_Var:
case T_Param: case T_Param:

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.220 2002/03/12 00:51:52 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.221 2002/03/21 16:00:48 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -43,13 +43,30 @@
#endif #endif
/* State shared by transformCreateSchemaStmt and its subroutines */
typedef struct
{
const char *stmtType; /* "CREATE TABLE" or "ALTER TABLE" */
char *schemaname; /* name of schema */
char *authid; /* owner of schema */
List *tables; /* CREATE TABLE items */
List *views; /* CREATE VIEW items */
List *grants; /* GRANT items */
List *fwconstraints; /* Forward referencing FOREIGN KEY constraints */
List *alters; /* Generated ALTER items (from the above) */
List *ixconstraints; /* index-creating constraints */
List *blist; /* "before list" of things to do before
* creating the schema */
List *alist; /* "after list" of things to do after
* creating the schema */
} CreateSchemaStmtContext;
/* State shared by transformCreateStmt and its subroutines */ /* State shared by transformCreateStmt and its subroutines */
typedef struct typedef struct
{ {
const char *stmtType; /* "CREATE TABLE" or "ALTER TABLE" */ const char *stmtType; /* "CREATE TABLE" or "ALTER TABLE" */
char *relname; /* name of relation */ RangeVar *relation; /* relation to create */
List *inhRelnames; /* names of relations to inherit from */ List *inhRelations; /* relations to inherit from */
bool istemp; /* is it to be a temp relation? */
bool hasoids; /* does relation have an OID column? */ bool hasoids; /* does relation have an OID column? */
Oid relOid; /* OID of table, if ALTER TABLE case */ Oid relOid; /* OID of table, if ALTER TABLE case */
List *columns; /* ColumnDef items */ List *columns; /* ColumnDef items */
@ -330,8 +347,8 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
qry->commandType = CMD_DELETE; qry->commandType = CMD_DELETE;
/* set up range table with just the result rel */ /* set up range table with just the result rel */
qry->resultRelation = setTargetTable(pstate, stmt->relname, qry->resultRelation = setTargetTable(pstate, stmt->relation->relname,
interpretInhOption(stmt->inhOpt), interpretInhOption(stmt->relation->inhOpt),
true); true);
qry->distinctClause = NIL; qry->distinctClause = NIL;
@ -398,7 +415,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
* table is also mentioned in the SELECT part. Note that the target * table is also mentioned in the SELECT part. Note that the target
* table is not added to the joinlist or namespace. * table is not added to the joinlist or namespace.
*/ */
qry->resultRelation = setTargetTable(pstate, stmt->relname, qry->resultRelation = setTargetTable(pstate, stmt->relation->relname,
false, false); false, false);
/* /*
@ -443,7 +460,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
*/ */
rte = addRangeTableEntryForSubquery(pstate, rte = addRangeTableEntryForSubquery(pstate,
selectQuery, selectQuery,
makeAttr("*SELECT*", NULL), makeAlias("*SELECT*", NIL),
true); true);
rtr = makeNode(RangeTblRef); rtr = makeNode(RangeTblRef);
/* assume new rte is at end */ /* assume new rte is at end */
@ -515,14 +532,15 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
foreach(tl, qry->targetList) foreach(tl, qry->targetList)
{ {
TargetEntry *tle = (TargetEntry *) lfirst(tl); TargetEntry *tle = (TargetEntry *) lfirst(tl);
Ident *id; ResTarget *col;
Assert(!tle->resdom->resjunk); Assert(!tle->resdom->resjunk);
if (icolumns == NIL || attnos == NIL) if (icolumns == NIL || attnos == NIL)
elog(ERROR, "INSERT has more expressions than target columns"); elog(ERROR, "INSERT has more expressions than target columns");
id = (Ident *) lfirst(icolumns); col = (ResTarget *) lfirst(icolumns);
updateTargetListEntry(pstate, tle, id->name, lfirsti(attnos), Assert(IsA(col, ResTarget));
id->indirection); updateTargetListEntry(pstate, tle, col->name, lfirsti(attnos),
col->indirection);
icolumns = lnext(icolumns); icolumns = lnext(icolumns);
attnos = lnext(attnos); attnos = lnext(attnos);
} }
@ -691,9 +709,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt,
List *elements; List *elements;
cxt.stmtType = "CREATE TABLE"; cxt.stmtType = "CREATE TABLE";
cxt.relname = stmt->relname; cxt.relation = stmt->relation;
cxt.inhRelnames = stmt->inhRelnames; cxt.inhRelations = stmt->inhRelations;
cxt.istemp = stmt->istemp;
cxt.hasoids = stmt->hasoids; cxt.hasoids = stmt->hasoids;
cxt.relOid = InvalidOid; cxt.relOid = InvalidOid;
cxt.columns = NIL; cxt.columns = NIL;
@ -805,7 +822,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
* conflicting constraints the user wrote (like a different * conflicting constraints the user wrote (like a different
* DEFAULT). * DEFAULT).
*/ */
sname = makeObjectName(cxt->relname, column->colname, "seq"); sname = makeObjectName((cxt->relation)->relname, column->colname, "seq");
/* /*
* Create an expression tree representing the function call * Create an expression tree representing the function call
@ -845,12 +862,12 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
* CREATE/ALTER TABLE. * CREATE/ALTER TABLE.
*/ */
sequence = makeNode(CreateSeqStmt); sequence = makeNode(CreateSeqStmt);
sequence->seqname = pstrdup(sname); sequence->sequence = copyObject(cxt->relation);
sequence->istemp = cxt->istemp; sequence->sequence->relname = pstrdup(sname);
sequence->options = NIL; sequence->options = NIL;
elog(NOTICE, "%s will create implicit sequence '%s' for SERIAL column '%s.%s'", elog(NOTICE, "%s will create implicit sequence '%s' for SERIAL column '%s.%s'",
cxt->stmtType, sequence->seqname, cxt->relname, column->colname); cxt->stmtType, sequence->sequence->relname, (cxt->relation)->relname, column->colname);
cxt->blist = lappend(cxt->blist, sequence); cxt->blist = lappend(cxt->blist, sequence);
} }
@ -875,9 +892,6 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
Ident *id = makeNode(Ident); Ident *id = makeNode(Ident);
id->name = column->colname; id->name = column->colname;
id->indirection = NIL;
id->isRel = false;
fkconstraint->fk_attrs = makeList1(id); fkconstraint->fk_attrs = makeList1(id);
cxt->fkconstraints = lappend(cxt->fkconstraints, fkconstraint); cxt->fkconstraints = lappend(cxt->fkconstraints, fkconstraint);
@ -891,7 +905,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
case CONSTR_NULL: case CONSTR_NULL:
if (saw_nullable && column->is_not_null) if (saw_nullable && column->is_not_null)
elog(ERROR, "%s/(NOT) NULL conflicting declaration for '%s.%s'", elog(ERROR, "%s/(NOT) NULL conflicting declaration for '%s.%s'",
cxt->stmtType, cxt->relname, column->colname); cxt->stmtType, (cxt->relation)->relname, column->colname);
column->is_not_null = FALSE; column->is_not_null = FALSE;
saw_nullable = true; saw_nullable = true;
break; break;
@ -899,7 +913,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
case CONSTR_NOTNULL: case CONSTR_NOTNULL:
if (saw_nullable && !column->is_not_null) if (saw_nullable && !column->is_not_null)
elog(ERROR, "%s/(NOT) NULL conflicting declaration for '%s.%s'", elog(ERROR, "%s/(NOT) NULL conflicting declaration for '%s.%s'",
cxt->stmtType, cxt->relname, column->colname); cxt->stmtType, (cxt->relation)->relname, column->colname);
column->is_not_null = TRUE; column->is_not_null = TRUE;
saw_nullable = true; saw_nullable = true;
break; break;
@ -907,14 +921,14 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
case CONSTR_DEFAULT: case CONSTR_DEFAULT:
if (column->raw_default != NULL) if (column->raw_default != NULL)
elog(ERROR, "%s/DEFAULT multiple values specified for '%s.%s'", elog(ERROR, "%s/DEFAULT multiple values specified for '%s.%s'",
cxt->stmtType, cxt->relname, column->colname); cxt->stmtType, (cxt->relation)->relname, column->colname);
column->raw_default = constraint->raw_expr; column->raw_default = constraint->raw_expr;
Assert(constraint->cooked_expr == NULL); Assert(constraint->cooked_expr == NULL);
break; break;
case CONSTR_PRIMARY: case CONSTR_PRIMARY:
if (constraint->name == NULL) if (constraint->name == NULL)
constraint->name = makeObjectName(cxt->relname, constraint->name = makeObjectName((cxt->relation)->relname,
NULL, NULL,
"pkey"); "pkey");
if (constraint->keys == NIL) if (constraint->keys == NIL)
@ -928,7 +942,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
case CONSTR_UNIQUE: case CONSTR_UNIQUE:
if (constraint->name == NULL) if (constraint->name == NULL)
constraint->name = makeObjectName(cxt->relname, constraint->name = makeObjectName((cxt->relation)->relname,
column->colname, column->colname,
"key"); "key");
if (constraint->keys == NIL) if (constraint->keys == NIL)
@ -942,7 +956,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
case CONSTR_CHECK: case CONSTR_CHECK:
if (constraint->name == NULL) if (constraint->name == NULL)
constraint->name = makeObjectName(cxt->relname, constraint->name = makeObjectName((cxt->relation)->relname,
column->colname, column->colname,
NULL); NULL);
cxt->ckconstraints = lappend(cxt->ckconstraints, constraint); cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
@ -970,7 +984,7 @@ transformTableConstraint(ParseState *pstate, CreateStmtContext *cxt,
{ {
case CONSTR_PRIMARY: case CONSTR_PRIMARY:
if (constraint->name == NULL) if (constraint->name == NULL)
constraint->name = makeObjectName(cxt->relname, constraint->name = makeObjectName((cxt->relation)->relname,
NULL, NULL,
"pkey"); "pkey");
cxt->ixconstraints = lappend(cxt->ixconstraints, constraint); cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);
@ -1034,21 +1048,21 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
/* In ALTER TABLE case, a primary index might already exist */ /* In ALTER TABLE case, a primary index might already exist */
if (cxt->pkey != NULL || if (cxt->pkey != NULL ||
(OidIsValid(cxt->relOid) && (OidIsValid(cxt->relOid) &&
relationHasPrimaryKey(cxt->relname))) relationHasPrimaryKey((cxt->relation)->relname)))
elog(ERROR, "%s / PRIMARY KEY multiple primary keys" elog(ERROR, "%s / PRIMARY KEY multiple primary keys"
" for table '%s' are not allowed", " for table '%s' are not allowed",
cxt->stmtType, cxt->relname); cxt->stmtType, (cxt->relation)->relname);
cxt->pkey = index; cxt->pkey = index;
} }
if (constraint->name != NULL) if (constraint->name != NULL)
index->idxname = pstrdup(constraint->name); index->idxname = pstrdup(constraint->name);
else if (constraint->contype == CONSTR_PRIMARY) else if (constraint->contype == CONSTR_PRIMARY)
index->idxname = makeObjectName(cxt->relname, NULL, "pkey"); index->idxname = makeObjectName((cxt->relation)->relname, NULL, "pkey");
else else
index->idxname = NULL; /* will set it later */ index->idxname = NULL; /* will set it later */
index->relname = cxt->relname; index->relation = cxt->relation;
index->accessMethod = DEFAULT_INDEX_TYPE; index->accessMethod = DEFAULT_INDEX_TYPE;
index->indexParams = NIL; index->indexParams = NIL;
index->whereClause = NULL; index->whereClause = NULL;
@ -1089,19 +1103,19 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
*/ */
found = true; found = true;
} }
else if (cxt->inhRelnames) else if (cxt->inhRelations)
{ {
/* try inherited tables */ /* try inherited tables */
List *inher; List *inher;
foreach(inher, cxt->inhRelnames) foreach(inher, cxt->inhRelations)
{ {
Value *inh = lfirst(inher); RangeVar *inh = lfirst(inher);
Relation rel; Relation rel;
int count; int count;
Assert(IsA(inh, String)); Assert(IsA(inh, RangeVar));
rel = heap_openr(strVal(inh), AccessShareLock); rel = heap_openr(inh->relname, AccessShareLock);
if (rel->rd_rel->relkind != RELKIND_RELATION) if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "inherited table \"%s\" is not a relation", elog(ERROR, "inherited table \"%s\" is not a relation",
strVal(inh)); strVal(inh));
@ -1257,7 +1271,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
if (index->idxname == NULL && index->indexParams != NIL) if (index->idxname == NULL && index->indexParams != NIL)
{ {
iparam = lfirst(index->indexParams); iparam = lfirst(index->indexParams);
index->idxname = CreateIndexName(cxt->relname, iparam->name, index->idxname = CreateIndexName((cxt->relation)->relname, iparam->name,
"key", cxt->alist); "key", cxt->alist);
} }
if (index->idxname == NULL) /* should not happen */ if (index->idxname == NULL) /* should not happen */
@ -1268,7 +1282,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
cxt->stmtType, cxt->stmtType,
(strcmp(cxt->stmtType, "ALTER TABLE") == 0) ? "ADD " : "", (strcmp(cxt->stmtType, "ALTER TABLE") == 0) ? "ADD " : "",
(index->primary ? "PRIMARY KEY" : "UNIQUE"), (index->primary ? "PRIMARY KEY" : "UNIQUE"),
index->idxname, cxt->relname); index->idxname, (cxt->relation)->relname);
} }
} }
@ -1328,7 +1342,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
*/ */
if (fkconstraint->pk_attrs == NIL) if (fkconstraint->pk_attrs == NIL)
{ {
if (strcmp(fkconstraint->pktable_name, cxt->relname) != 0) if (strcmp(fkconstraint->pktable->relname, (cxt->relation)->relname) != 0)
transformFkeyGetPrimaryKey(fkconstraint, pktypoid); transformFkeyGetPrimaryKey(fkconstraint, pktypoid);
else if (cxt->pkey != NULL) else if (cxt->pkey != NULL)
{ {
@ -1342,8 +1356,6 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
Ident *pkattr = (Ident *) makeNode(Ident); Ident *pkattr = (Ident *) makeNode(Ident);
pkattr->name = pstrdup(ielem->name); pkattr->name = pstrdup(ielem->name);
pkattr->indirection = NIL;
pkattr->isRel = false;
fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs,
pkattr); pkattr);
if (attnum >= INDEX_MAX_KEYS) if (attnum >= INDEX_MAX_KEYS)
@ -1360,13 +1372,13 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
transformFkeyGetPrimaryKey(fkconstraint, pktypoid); transformFkeyGetPrimaryKey(fkconstraint, pktypoid);
else else
elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found", elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found",
fkconstraint->pktable_name); fkconstraint->pktable->relname);
} }
} }
else else
{ {
/* Validate the specified referenced key list */ /* Validate the specified referenced key list */
if (strcmp(fkconstraint->pktable_name, cxt->relname) != 0) if (strcmp(fkconstraint->pktable->relname, (cxt->relation)->relname) != 0)
transformFkeyCheckAttrs(fkconstraint, pktypoid); transformFkeyCheckAttrs(fkconstraint, pktypoid);
else else
{ {
@ -1422,7 +1434,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
transformFkeyCheckAttrs(fkconstraint, pktypoid); transformFkeyCheckAttrs(fkconstraint, pktypoid);
else else
elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found", elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found",
fkconstraint->pktable_name); fkconstraint->pktable->relname);
} }
} }
} }
@ -1447,7 +1459,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
*/ */
fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt); fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
fk_trigger->trigname = fkconstraint->constr_name; fk_trigger->trigname = fkconstraint->constr_name;
fk_trigger->relname = cxt->relname; fk_trigger->relation = cxt->relation;
fk_trigger->funcname = "RI_FKey_check_ins"; fk_trigger->funcname = "RI_FKey_check_ins";
fk_trigger->before = false; fk_trigger->before = false;
fk_trigger->row = true; fk_trigger->row = true;
@ -1462,15 +1474,15 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
fk_trigger->isconstraint = true; fk_trigger->isconstraint = true;
fk_trigger->deferrable = fkconstraint->deferrable; fk_trigger->deferrable = fkconstraint->deferrable;
fk_trigger->initdeferred = fkconstraint->initdeferred; fk_trigger->initdeferred = fkconstraint->initdeferred;
fk_trigger->constrrelname = fkconstraint->pktable_name; fk_trigger->constrrel = fkconstraint->pktable;
fk_trigger->args = NIL; fk_trigger->args = NIL;
fk_trigger->args = lappend(fk_trigger->args, fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->constr_name)); makeString(fkconstraint->constr_name));
fk_trigger->args = lappend(fk_trigger->args, fk_trigger->args = lappend(fk_trigger->args,
makeString(cxt->relname)); makeString((cxt->relation)->relname));
fk_trigger->args = lappend(fk_trigger->args, fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->pktable_name)); makeString(fkconstraint->pktable->relname));
fk_trigger->args = lappend(fk_trigger->args, fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->match_type)); makeString(fkconstraint->match_type));
fk_attr = fkconstraint->fk_attrs; fk_attr = fkconstraint->fk_attrs;
@ -1478,7 +1490,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
if (length(fk_attr) != length(pk_attr)) if (length(fk_attr) != length(pk_attr))
elog(ERROR, "number of key attributes in referenced table must be equal to foreign key" elog(ERROR, "number of key attributes in referenced table must be equal to foreign key"
"\n\tIllegal FOREIGN KEY definition references \"%s\"", "\n\tIllegal FOREIGN KEY definition references \"%s\"",
fkconstraint->pktable_name); fkconstraint->pktable->relname);
while (fk_attr != NIL) while (fk_attr != NIL)
{ {
@ -1502,7 +1514,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
*/ */
fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt); fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
fk_trigger->trigname = fkconstraint->constr_name; fk_trigger->trigname = fkconstraint->constr_name;
fk_trigger->relname = fkconstraint->pktable_name; fk_trigger->relation = fkconstraint->pktable;
fk_trigger->before = false; fk_trigger->before = false;
fk_trigger->row = true; fk_trigger->row = true;
fk_trigger->actions[0] = 'd'; fk_trigger->actions[0] = 'd';
@ -1515,7 +1527,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
fk_trigger->isconstraint = true; fk_trigger->isconstraint = true;
fk_trigger->deferrable = fkconstraint->deferrable; fk_trigger->deferrable = fkconstraint->deferrable;
fk_trigger->initdeferred = fkconstraint->initdeferred; fk_trigger->initdeferred = fkconstraint->initdeferred;
fk_trigger->constrrelname = cxt->relname; fk_trigger->constrrel = cxt->relation;
switch ((fkconstraint->actions & FKCONSTR_ON_DELETE_MASK) switch ((fkconstraint->actions & FKCONSTR_ON_DELETE_MASK)
>> FKCONSTR_ON_DELETE_SHIFT) >> FKCONSTR_ON_DELETE_SHIFT)
{ {
@ -1545,9 +1557,9 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
fk_trigger->args = lappend(fk_trigger->args, fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->constr_name)); makeString(fkconstraint->constr_name));
fk_trigger->args = lappend(fk_trigger->args, fk_trigger->args = lappend(fk_trigger->args,
makeString(cxt->relname)); makeString((cxt->relation)->relname));
fk_trigger->args = lappend(fk_trigger->args, fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->pktable_name)); makeString(fkconstraint->pktable->relname));
fk_trigger->args = lappend(fk_trigger->args, fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->match_type)); makeString(fkconstraint->match_type));
fk_attr = fkconstraint->fk_attrs; fk_attr = fkconstraint->fk_attrs;
@ -1574,7 +1586,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
*/ */
fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt); fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
fk_trigger->trigname = fkconstraint->constr_name; fk_trigger->trigname = fkconstraint->constr_name;
fk_trigger->relname = fkconstraint->pktable_name; fk_trigger->relation = fkconstraint->pktable;
fk_trigger->before = false; fk_trigger->before = false;
fk_trigger->row = true; fk_trigger->row = true;
fk_trigger->actions[0] = 'u'; fk_trigger->actions[0] = 'u';
@ -1587,7 +1599,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
fk_trigger->isconstraint = true; fk_trigger->isconstraint = true;
fk_trigger->deferrable = fkconstraint->deferrable; fk_trigger->deferrable = fkconstraint->deferrable;
fk_trigger->initdeferred = fkconstraint->initdeferred; fk_trigger->initdeferred = fkconstraint->initdeferred;
fk_trigger->constrrelname = cxt->relname; fk_trigger->constrrel = cxt->relation;
switch ((fkconstraint->actions & FKCONSTR_ON_UPDATE_MASK) switch ((fkconstraint->actions & FKCONSTR_ON_UPDATE_MASK)
>> FKCONSTR_ON_UPDATE_SHIFT) >> FKCONSTR_ON_UPDATE_SHIFT)
{ {
@ -1617,9 +1629,9 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
fk_trigger->args = lappend(fk_trigger->args, fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->constr_name)); makeString(fkconstraint->constr_name));
fk_trigger->args = lappend(fk_trigger->args, fk_trigger->args = lappend(fk_trigger->args,
makeString(cxt->relname)); makeString((cxt->relation)->relname));
fk_trigger->args = lappend(fk_trigger->args, fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->pktable_name)); makeString(fkconstraint->pktable->relname));
fk_trigger->args = lappend(fk_trigger->args, fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->match_type)); makeString(fkconstraint->match_type));
fk_attr = fkconstraint->fk_attrs; fk_attr = fkconstraint->fk_attrs;
@ -1672,7 +1684,7 @@ transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
* easily support predicates on indexes created implicitly by * easily support predicates on indexes created implicitly by
* CREATE TABLE. Fortunately, that's not necessary. * CREATE TABLE. Fortunately, that's not necessary.
*/ */
rte = addRangeTableEntry(pstate, stmt->relname, NULL, false, true); rte = addRangeTableEntry(pstate, stmt->relation->relname, NULL, false, true);
/* no to join list, yes to namespace */ /* no to join list, yes to namespace */
addRTEtoQuery(pstate, rte, false, true); addRTEtoQuery(pstate, rte, false, true);
@ -1712,7 +1724,7 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
* beforehand. We don't need to hold a refcount on the relcache * beforehand. We don't need to hold a refcount on the relcache
* entry, however. * entry, however.
*/ */
heap_close(heap_openr(stmt->object->relname, AccessExclusiveLock), heap_close(heap_openr(stmt->relation->relname, AccessExclusiveLock),
NoLock); NoLock);
/* /*
@ -1721,11 +1733,11 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
* rule qualification. * rule qualification.
*/ */
Assert(pstate->p_rtable == NIL); Assert(pstate->p_rtable == NIL);
oldrte = addRangeTableEntry(pstate, stmt->object->relname, oldrte = addRangeTableEntry(pstate, stmt->relation->relname,
makeAttr("*OLD*", NULL), makeAlias("*OLD*", NIL),
false, true); false, true);
newrte = addRangeTableEntry(pstate, stmt->object->relname, newrte = addRangeTableEntry(pstate, stmt->relation->relname,
makeAttr("*NEW*", NULL), makeAlias("*NEW*", NIL),
false, true); false, true);
/* Must override addRangeTableEntry's default access-check flags */ /* Must override addRangeTableEntry's default access-check flags */
oldrte->checkForRead = false; oldrte->checkForRead = false;
@ -1812,11 +1824,11 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
* or they won't be accessible at all. We decide later * or they won't be accessible at all. We decide later
* whether to put them in the joinlist. * whether to put them in the joinlist.
*/ */
oldrte = addRangeTableEntry(sub_pstate, stmt->object->relname, oldrte = addRangeTableEntry(sub_pstate, stmt->relation->relname,
makeAttr("*OLD*", NULL), makeAlias("*OLD*", NIL),
false, false); false, false);
newrte = addRangeTableEntry(sub_pstate, stmt->object->relname, newrte = addRangeTableEntry(sub_pstate, stmt->relation->relname,
makeAttr("*NEW*", NULL), makeAlias("*NEW*", NIL),
false, false); false, false);
oldrte->checkForRead = false; oldrte->checkForRead = false;
newrte->checkForRead = false; newrte->checkForRead = false;
@ -1950,8 +1962,8 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
if (!IsTransactionBlock()) if (!IsTransactionBlock())
elog(ERROR, "DECLARE CURSOR may only be used in begin/end transaction blocks"); elog(ERROR, "DECLARE CURSOR may only be used in begin/end transaction blocks");
qry->into = stmt->portalname; qry->into = makeNode(RangeVar);
qry->isTemp = stmt->istemp; qry->into->relname = stmt->portalname;
qry->isPortal = TRUE; qry->isPortal = TRUE;
qry->isBinary = stmt->binary; /* internal portal */ qry->isBinary = stmt->binary; /* internal portal */
} }
@ -1959,7 +1971,6 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
{ {
/* SELECT */ /* SELECT */
qry->into = stmt->into; qry->into = stmt->into;
qry->isTemp = stmt->istemp;
qry->isPortal = FALSE; qry->isPortal = FALSE;
qry->isBinary = FALSE; qry->isBinary = FALSE;
} }
@ -2033,8 +2044,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
int leftmostRTI; int leftmostRTI;
Query *leftmostQuery; Query *leftmostQuery;
SetOperationStmt *sostmt; SetOperationStmt *sostmt;
char *into; RangeVar *into;
bool istemp;
List *intoColNames; List *intoColNames;
char *portalname; char *portalname;
bool binary; bool binary;
@ -2065,14 +2075,12 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
Assert(leftmostSelect && IsA(leftmostSelect, SelectStmt) && Assert(leftmostSelect && IsA(leftmostSelect, SelectStmt) &&
leftmostSelect->larg == NULL); leftmostSelect->larg == NULL);
into = leftmostSelect->into; into = leftmostSelect->into;
istemp = leftmostSelect->istemp;
intoColNames = leftmostSelect->intoColNames; intoColNames = leftmostSelect->intoColNames;
portalname = stmt->portalname; portalname = stmt->portalname;
binary = stmt->binary; binary = stmt->binary;
/* clear them to prevent complaints in transformSetOperationTree() */ /* clear them to prevent complaints in transformSetOperationTree() */
leftmostSelect->into = NULL; leftmostSelect->into = NULL;
leftmostSelect->istemp = false;
leftmostSelect->intoColNames = NIL; leftmostSelect->intoColNames = NIL;
stmt->portalname = NULL; stmt->portalname = NULL;
stmt->binary = false; stmt->binary = false;
@ -2174,8 +2182,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
if (!IsTransactionBlock()) if (!IsTransactionBlock())
elog(ERROR, "DECLARE CURSOR may only be used in begin/end transaction blocks"); elog(ERROR, "DECLARE CURSOR may only be used in begin/end transaction blocks");
qry->into = portalname; qry->into = makeNode(RangeVar);
qry->isTemp = istemp; qry->into->relname = portalname;
qry->isPortal = TRUE; qry->isPortal = TRUE;
qry->isBinary = binary; /* internal portal */ qry->isBinary = binary; /* internal portal */
} }
@ -2183,7 +2191,6 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
{ {
/* SELECT */ /* SELECT */
qry->into = into; qry->into = into;
qry->isTemp = istemp;
qry->isPortal = FALSE; qry->isPortal = FALSE;
qry->isBinary = FALSE; qry->isBinary = FALSE;
} }
@ -2325,8 +2332,7 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
sprintf(selectName, "*SELECT* %d", length(pstate->p_rtable) + 1); sprintf(selectName, "*SELECT* %d", length(pstate->p_rtable) + 1);
rte = addRangeTableEntryForSubquery(pstate, rte = addRangeTableEntryForSubquery(pstate,
selectQuery, selectQuery,
makeAttr(pstrdup(selectName), makeAlias(selectName, NIL),
NULL),
false); false);
/* /*
@ -2468,8 +2474,8 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
qry->commandType = CMD_UPDATE; qry->commandType = CMD_UPDATE;
pstate->p_is_update = true; pstate->p_is_update = true;
qry->resultRelation = setTargetTable(pstate, stmt->relname, qry->resultRelation = setTargetTable(pstate, stmt->relation->relname,
interpretInhOption(stmt->inhOpt), interpretInhOption(stmt->relation->inhOpt),
true); true);
/* /*
@ -2553,11 +2559,11 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
{ {
case 'A': case 'A':
cxt.stmtType = "ALTER TABLE"; cxt.stmtType = "ALTER TABLE";
cxt.relname = stmt->relname; cxt.relation = stmt->relation;
cxt.inhRelnames = NIL; cxt.inhRelations = NIL;
cxt.istemp = is_temp_rel_name(stmt->relname); cxt.relation->istemp = is_temp_rel_name(stmt->relation->relname);
cxt.relOid = GetSysCacheOid(RELNAME, cxt.relOid = GetSysCacheOid(RELNAME,
PointerGetDatum(stmt->relname), PointerGetDatum((stmt->relation)->relname),
0, 0, 0); 0, 0, 0);
cxt.hasoids = SearchSysCacheExists(ATTNUM, cxt.hasoids = SearchSysCacheExists(ATTNUM,
ObjectIdGetDatum(cxt.relOid), ObjectIdGetDatum(cxt.relOid),
@ -2585,11 +2591,11 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
case 'C': case 'C':
cxt.stmtType = "ALTER TABLE"; cxt.stmtType = "ALTER TABLE";
cxt.relname = stmt->relname; cxt.relation = stmt->relation;
cxt.inhRelnames = NIL; cxt.inhRelations = NIL;
cxt.istemp = is_temp_rel_name(stmt->relname); cxt.relation->istemp = is_temp_rel_name(stmt->relation->relname);
cxt.relOid = GetSysCacheOid(RELNAME, cxt.relOid = GetSysCacheOid(RELNAME,
PointerGetDatum(stmt->relname), PointerGetDatum((stmt->relation)->relname),
0, 0, 0); 0, 0, 0);
cxt.hasoids = SearchSysCacheExists(ATTNUM, cxt.hasoids = SearchSysCacheExists(ATTNUM,
ObjectIdGetDatum(cxt.relOid), ObjectIdGetDatum(cxt.relOid),
@ -2713,15 +2719,18 @@ transformTypeRefsList(ParseState *pstate, List *l)
static void static void
transformTypeRef(ParseState *pstate, TypeName *tn) transformTypeRef(ParseState *pstate, TypeName *tn)
{ {
Attr *att; ColumnRef *cref;
Node *n; Node *n;
Var *v; Var *v;
char *tyn; char *tyn;
if (tn->attrname == NULL) if (tn->attrname == NULL)
return; return;
att = makeAttr(tn->name, tn->attrname); /* XXX this needs work; can't type name be qualified? */
n = transformExpr(pstate, (Node *) att, EXPR_COLUMN_FIRST); cref = makeNode(ColumnRef);
cref->fields = makeList2(makeString(tn->name), makeString(tn->attrname));
cref->indirection = NIL;
n = transformExpr(pstate, (Node *) cref);
if (!IsA(n, Var)) if (!IsA(n, Var))
elog(ERROR, "unsupported expression in %%TYPE"); elog(ERROR, "unsupported expression in %%TYPE");
v = (Var *) n; v = (Var *) n;
@ -2791,7 +2800,7 @@ transformForUpdate(Query *qry, List *forUpdate)
RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt); RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
++i; ++i;
if (strcmp(rte->eref->relname, relname) == 0) if (strcmp(rte->eref->aliasname, relname) == 0)
{ {
if (rte->subquery) if (rte->subquery)
{ {
@ -2835,11 +2844,11 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid)
/* /*
* Open the referenced table * Open the referenced table
*/ */
pkrel = heap_openr(fkconstraint->pktable_name, AccessShareLock); pkrel = heap_openr(fkconstraint->pktable->relname, AccessShareLock);
if (pkrel->rd_rel->relkind != RELKIND_RELATION) if (pkrel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "Referenced relation \"%s\" is not a table", elog(ERROR, "Referenced relation \"%s\" is not a table",
fkconstraint->pktable_name); fkconstraint->pktable->relname);
/* /*
* Get the list of index OIDs for the table from the relcache, and * Get the list of index OIDs for the table from the relcache, and
@ -2901,7 +2910,7 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid)
} }
if (!found) if (!found)
elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found", elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found",
fkconstraint->pktable_name); fkconstraint->pktable->relname);
freeList(indexoidlist); freeList(indexoidlist);
heap_close(pkrel, AccessShareLock); heap_close(pkrel, AccessShareLock);
@ -2928,11 +2937,11 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
/* /*
* Open the referenced table * Open the referenced table
*/ */
pkrel = heap_openr(fkconstraint->pktable_name, AccessShareLock); pkrel = heap_openr(fkconstraint->pktable->relname, AccessShareLock);
if (pkrel->rd_rel->relkind != RELKIND_RELATION) if (pkrel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "Referenced relation \"%s\" is not a table", elog(ERROR, "Referenced relation \"%s\" is not a table",
fkconstraint->pktable_name); fkconstraint->pktable->relname);
/* /*
* Get the list of index OIDs for the table from the relcache, and * Get the list of index OIDs for the table from the relcache, and
@ -2965,7 +2974,7 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
*/ */
if (indexStruct == NULL) if (indexStruct == NULL)
elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found", elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found",
fkconstraint->pktable_name); fkconstraint->pktable->relname);
/* /*
* Now build the list of PK attributes from the indkey definition * Now build the list of PK attributes from the indkey definition
@ -2977,8 +2986,6 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
Ident *pkattr = makeNode(Ident); Ident *pkattr = makeNode(Ident);
pkattr->name = pstrdup(NameStr(*attnumAttName(pkrel, pkattno))); pkattr->name = pstrdup(NameStr(*attnumAttName(pkrel, pkattno)));
pkattr->indirection = NIL;
pkattr->isRel = false;
pktypoid[attnum++] = attnumTypeId(pkrel, pkattno); pktypoid[attnum++] = attnumTypeId(pkrel, pkattno);
fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr); fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr);
@ -3070,14 +3077,14 @@ transformFkeyGetColType(CreateStmtContext *cxt, char *colname)
if (sysatt) if (sysatt)
return sysatt->atttypid; return sysatt->atttypid;
/* Look for column among inherited columns (if CREATE TABLE case) */ /* Look for column among inherited columns (if CREATE TABLE case) */
foreach(inher, cxt->inhRelnames) foreach(inher, cxt->inhRelations)
{ {
Value *inh = lfirst(inher); RangeVar *inh = lfirst(inher);
Relation rel; Relation rel;
int count; int count;
Assert(IsA(inh, String)); Assert(IsA(inh, RangeVar));
rel = heap_openr(strVal(inh), AccessShareLock); rel = heap_openr(inh->relname, AccessShareLock);
if (rel->rd_rel->relkind != RELKIND_RELATION) if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "inherited table \"%s\" is not a relation", elog(ERROR, "inherited table \"%s\" is not a relation",
strVal(inh)); strVal(inh));
@ -3248,3 +3255,104 @@ transformColumnType(ParseState *pstate, ColumnDef *column)
ReleaseSysCache(ctype); ReleaseSysCache(ctype);
} }
/*
* analyzeCreateSchemaStmt -
* analyzes the "create schema" statement
*
* Split the schema element list into individual commands and place
* them in the result list in an order such that there are no
* forward references (e.g. GRANT to a table created later in the list).
*
* SQL92 also allows constraints to make forward references, so thumb through
* the table columns and move forward references to a posterior alter-table
* command.
*
* The result is a list of parse nodes that still need to be analyzed ---
* but we can't analyze the later commands until we've executed the earlier
* ones, because of possible inter-object references.
*
* Note: Called from commands/command.c
*/
List *
analyzeCreateSchemaStmt(CreateSchemaStmt *stmt)
{
CreateSchemaStmtContext cxt;
List *result;
List *elements;
cxt.stmtType = "CREATE SCHEMA";
cxt.schemaname = stmt->schemaname;
cxt.authid = stmt->authid;
cxt.tables = NIL;
cxt.views = NIL;
cxt.grants = NIL;
cxt.fwconstraints = NIL;
cxt.alters = NIL;
cxt.blist = NIL;
cxt.alist = NIL;
/*
* Run through each schema element in the schema element list.
* Separate statements by type, and do preliminary analysis.
*/
foreach(elements, stmt->schemaElts)
{
Node *element = lfirst(elements);
switch (nodeTag(element))
{
case T_CreateStmt:
{
CreateStmt *elp = (CreateStmt *) element;
if (elp->relation->schemaname == NULL)
elp->relation->schemaname = cxt.schemaname;
else if (strcmp(cxt.schemaname, elp->relation->schemaname))
elog(ERROR, "New table refers to a schema (%s)"
" different from the one being created (%s)",
elp->relation->schemaname, cxt.schemaname);
/*
* XXX todo: deal with constraints
*/
cxt.tables = lappend(cxt.tables, element);
}
break;
case T_ViewStmt:
{
ViewStmt *elp = (ViewStmt *) element;
if (elp->view->schemaname == NULL)
elp->view->schemaname = cxt.schemaname;
else if (strcmp(cxt.schemaname, elp->view->schemaname))
elog(ERROR, "New view refers to a schema (%s)"
" different from the one being created (%s)",
elp->view->schemaname, cxt.schemaname);
/*
* XXX todo: deal with references between views
*/
cxt.views = lappend(cxt.views, element);
}
break;
case T_GrantStmt:
cxt.grants = lappend(cxt.grants, element);
break;
default:
elog(ERROR, "parser: unsupported schema node (internal error)");
}
}
result = NIL;
result = nconc(result, cxt.tables);
result = nconc(result, cxt.views);
result = nconc(result, cxt.grants);
return result;
}

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.46 2001/10/25 05:49:36 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.47 2002/03/21 16:00:58 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -116,7 +116,7 @@ check_ungrouped_columns_walker(Node *node,
rte = rt_fetch(var->varno, context->pstate->p_rtable); rte = rt_fetch(var->varno, context->pstate->p_rtable);
attname = get_rte_attribute_name(rte, var->varattno); attname = get_rte_attribute_name(rte, var->varattno);
elog(ERROR, "Attribute %s.%s must be GROUPed or used in an aggregate function", elog(ERROR, "Attribute %s.%s must be GROUPed or used in an aggregate function",
rte->eref->relname, attname); rte->eref->aliasname, attname);
} }
/* Otherwise, recurse. */ /* Otherwise, recurse. */
return expression_tree_walker(node, check_ungrouped_columns_walker, return expression_tree_walker(node, check_ungrouped_columns_walker,
@ -188,8 +188,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry, Node *qual)
Aggref * Aggref *
ParseAgg(ParseState *pstate, char *aggname, Oid basetype, ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
List *args, bool agg_star, bool agg_distinct, List *args, bool agg_star, bool agg_distinct)
int precedence)
{ {
HeapTuple aggtuple; HeapTuple aggtuple;
Form_pg_aggregate aggform; Form_pg_aggregate aggform;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.84 2002/03/12 00:51:54 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.85 2002/03/21 16:00:59 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -285,7 +285,7 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars)
* transformJoinOnClause() does. Just invoke transformExpr() to fix * transformJoinOnClause() does. Just invoke transformExpr() to fix
* up the operators, and we're done. * up the operators, and we're done.
*/ */
result = transformExpr(pstate, result, EXPR_COLUMN_FIRST); result = transformExpr(pstate, result);
/* /*
* We expect the result to yield bool directly, otherwise complain. We * We expect the result to yield bool directly, otherwise complain. We
@ -326,7 +326,7 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j,
pstate->p_namespace = makeList2(j->larg, j->rarg); pstate->p_namespace = makeList2(j->larg, j->rarg);
/* This part is just like transformWhereClause() */ /* This part is just like transformWhereClause() */
result = transformExpr(pstate, j->quals, EXPR_COLUMN_FIRST); result = transformExpr(pstate, j->quals);
if (!coerce_to_boolean(pstate, &result)) if (!coerce_to_boolean(pstate, &result))
elog(ERROR, "JOIN/ON clause must return type boolean, not type %s", elog(ERROR, "JOIN/ON clause must return type boolean, not type %s",
@ -350,7 +350,7 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j,
if (!intMember(varno, containedRels)) if (!intMember(varno, containedRels))
{ {
elog(ERROR, "JOIN/ON clause refers to \"%s\", which is not part of JOIN", elog(ERROR, "JOIN/ON clause refers to \"%s\", which is not part of JOIN",
rt_fetch(varno, pstate->p_rtable)->eref->relname); rt_fetch(varno, pstate->p_rtable)->eref->aliasname);
} }
} }
freeList(clause_varnos); freeList(clause_varnos);
@ -375,7 +375,7 @@ transformTableEntry(ParseState *pstate, RangeVar *r)
* automatically generate the range variable if not specified. However * automatically generate the range variable if not specified. However
* there are times we need to know whether the entries are legitimate. * there are times we need to know whether the entries are legitimate.
*/ */
rte = addRangeTableEntry(pstate, relname, r->name, rte = addRangeTableEntry(pstate, relname, r->alias,
interpretInhOption(r->inhOpt), true); interpretInhOption(r->inhOpt), true);
/* /*
@ -408,7 +408,7 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
* relax this, we'd have to be prepared to gin up a unique alias for * relax this, we'd have to be prepared to gin up a unique alias for
* an unlabeled subselect. * an unlabeled subselect.
*/ */
if (r->name == NULL) if (r->alias == NULL)
elog(ERROR, "sub-select in FROM must have an alias"); elog(ERROR, "sub-select in FROM must have an alias");
/* /*
@ -444,7 +444,7 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
/* /*
* OK, build an RTE for the subquery. * OK, build an RTE for the subquery.
*/ */
rte = addRangeTableEntryForSubquery(pstate, query, r->name, true); rte = addRangeTableEntryForSubquery(pstate, query, r->alias, true);
/* /*
* We create a RangeTblRef, but we do not add it to the joinlist or * We create a RangeTblRef, but we do not add it to the joinlist or
@ -748,11 +748,11 @@ transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels)
*/ */
if (j->alias) if (j->alias)
{ {
if (j->alias->attrs != NIL) if (j->alias->colnames != NIL)
{ {
if (length(j->alias->attrs) > length(res_colnames)) if (length(j->alias->colnames) > length(res_colnames))
elog(ERROR, "Column alias list for \"%s\" has too many entries", elog(ERROR, "Column alias list for \"%s\" has too many entries",
j->alias->relname); j->alias->aliasname);
} }
} }
@ -791,7 +791,7 @@ transformWhereClause(ParseState *pstate, Node *clause)
if (clause == NULL) if (clause == NULL)
return NULL; return NULL;
qual = transformExpr(pstate, clause, EXPR_COLUMN_FIRST); qual = transformExpr(pstate, clause);
if (!coerce_to_boolean(pstate, &qual)) if (!coerce_to_boolean(pstate, &qual))
elog(ERROR, "WHERE clause must return type boolean, not type %s", elog(ERROR, "WHERE clause must return type boolean, not type %s",
@ -858,9 +858,11 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
* an expression. * an expression.
*---------- *----------
*/ */
if (IsA(node, Ident) &&((Ident *) node)->indirection == NIL) if (IsA(node, ColumnRef) &&
length(((ColumnRef *) node)->fields) == 1 &&
((ColumnRef *) node)->indirection == NIL)
{ {
char *name = ((Ident *) node)->name; char *name = strVal(lfirst(((ColumnRef *) node)->fields));
if (clause == GROUP_CLAUSE) if (clause == GROUP_CLAUSE)
{ {
@ -934,7 +936,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
* willing to match a resjunk target here, though the above cases must * willing to match a resjunk target here, though the above cases must
* ignore resjunk targets. * ignore resjunk targets.
*/ */
expr = transformExpr(pstate, node, EXPR_COLUMN_FIRST); expr = transformExpr(pstate, node);
foreach(tl, tlist) foreach(tl, tlist)
{ {

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.110 2002/03/20 19:44:25 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.111 2002/03/21 16:01:03 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -17,6 +17,7 @@
#include "catalog/pg_operator.h" #include "catalog/pg_operator.h"
#include "catalog/pg_proc.h" #include "catalog/pg_proc.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h" #include "nodes/makefuncs.h"
#include "nodes/params.h" #include "nodes/params.h"
#include "parser/analyze.h" #include "parser/analyze.h"
@ -41,8 +42,7 @@ bool Transform_null_equals = false;
static Node *parser_typecast_constant(Value *expr, TypeName *typename); static Node *parser_typecast_constant(Value *expr, TypeName *typename);
static Node *parser_typecast_expression(ParseState *pstate, static Node *parser_typecast_expression(ParseState *pstate,
Node *expr, TypeName *typename); Node *expr, TypeName *typename);
static Node *transformAttr(ParseState *pstate, Attr *att, int precedence); static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
static Node *transformIdent(ParseState *pstate, Ident *ident, int precedence);
static Node *transformIndirection(ParseState *pstate, Node *basenode, static Node *transformIndirection(ParseState *pstate, Node *basenode,
List *indirection); List *indirection);
@ -85,7 +85,7 @@ parse_expr_init(void)
* input and output of transformExpr; see SubLink for example. * input and output of transformExpr; see SubLink for example.
*/ */
Node * Node *
transformExpr(ParseState *pstate, Node *expr, int precedence) transformExpr(ParseState *pstate, Node *expr)
{ {
Node *result = NULL; Node *result = NULL;
@ -105,9 +105,37 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
switch (nodeTag(expr)) switch (nodeTag(expr))
{ {
case T_Attr: case T_ColumnRef:
{ {
result = transformAttr(pstate, (Attr *) expr, precedence); result = transformColumnRef(pstate, (ColumnRef *) expr);
break;
}
case T_ParamRef:
{
ParamRef *pref = (ParamRef *) expr;
int paramno = pref->number;
Oid paramtyp = param_type(paramno);
Param *param;
List *fields;
if (!OidIsValid(paramtyp))
elog(ERROR, "Parameter '$%d' is out of range", paramno);
param = makeNode(Param);
param->paramkind = PARAM_NUM;
param->paramid = (AttrNumber) paramno;
param->paramname = "<unnamed>";
param->paramtype = paramtyp;
result = (Node *) param;
/* handle qualification, if any */
foreach(fields, pref->fields)
{
result = ParseFuncOrColumn(pstate, strVal(lfirst(fields)),
makeList1(result),
false, false, true);
}
/* handle subscripts, if any */
result = transformIndirection(pstate, result,
pref->indirection);
break; break;
} }
case T_A_Const: case T_A_Const:
@ -121,31 +149,28 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
result = (Node *) make_const(val); result = (Node *) make_const(val);
break; break;
} }
case T_ParamNo: case T_ExprFieldSelect:
{ {
ParamNo *pno = (ParamNo *) expr; ExprFieldSelect *efs = (ExprFieldSelect *) expr;
int paramno = pno->number; List *fields;
Oid toid = param_type(paramno);
Param *param = makeNode(Param);
if (!OidIsValid(toid)) result = transformExpr(pstate, efs->arg);
elog(ERROR, "Parameter '$%d' is out of range", paramno); /* handle qualification, if any */
param->paramkind = PARAM_NUM; foreach(fields, efs->fields)
param->paramid = (AttrNumber) paramno; {
param->paramname = "<unnamed>"; result = ParseFuncOrColumn(pstate, strVal(lfirst(fields)),
param->paramtype = toid; makeList1(result),
result = transformIndirection(pstate, (Node *) param, false, false, true);
pno->indirection); }
/* cope with typecast applied to param */ /* handle subscripts, if any */
if (pno->typename != NULL) result = transformIndirection(pstate, result,
result = parser_typecast_expression(pstate, result, efs->indirection);
pno->typename);
break; break;
} }
case T_TypeCast: case T_TypeCast:
{ {
TypeCast *tc = (TypeCast *) expr; TypeCast *tc = (TypeCast *) expr;
Node *arg = transformExpr(pstate, tc->arg, precedence); Node *arg = transformExpr(pstate, tc->arg);
result = parser_typecast_expression(pstate, arg, tc->typename); result = parser_typecast_expression(pstate, arg, tc->typename);
break; break;
@ -179,17 +204,14 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
n->arg = a->lexpr; n->arg = a->lexpr;
result = transformExpr(pstate, result = transformExpr(pstate,
(Node *) n, (Node *) n);
precedence);
} }
else else
{ {
Node *lexpr = transformExpr(pstate, Node *lexpr = transformExpr(pstate,
a->lexpr, a->lexpr);
precedence);
Node *rexpr = transformExpr(pstate, Node *rexpr = transformExpr(pstate,
a->rexpr, a->rexpr);
precedence);
result = (Node *) make_op(a->opname, result = (Node *) make_op(a->opname,
lexpr, lexpr,
@ -200,11 +222,9 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
case AND: case AND:
{ {
Node *lexpr = transformExpr(pstate, Node *lexpr = transformExpr(pstate,
a->lexpr, a->lexpr);
precedence);
Node *rexpr = transformExpr(pstate, Node *rexpr = transformExpr(pstate,
a->rexpr, a->rexpr);
precedence);
Expr *expr = makeNode(Expr); Expr *expr = makeNode(Expr);
if (!coerce_to_boolean(pstate, &lexpr)) if (!coerce_to_boolean(pstate, &lexpr))
@ -226,11 +246,9 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
case OR: case OR:
{ {
Node *lexpr = transformExpr(pstate, Node *lexpr = transformExpr(pstate,
a->lexpr, a->lexpr);
precedence);
Node *rexpr = transformExpr(pstate, Node *rexpr = transformExpr(pstate,
a->rexpr, a->rexpr);
precedence);
Expr *expr = makeNode(Expr); Expr *expr = makeNode(Expr);
if (!coerce_to_boolean(pstate, &lexpr)) if (!coerce_to_boolean(pstate, &lexpr))
@ -252,8 +270,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
case NOT: case NOT:
{ {
Node *rexpr = transformExpr(pstate, Node *rexpr = transformExpr(pstate,
a->rexpr, a->rexpr);
precedence);
Expr *expr = makeNode(Expr); Expr *expr = makeNode(Expr);
if (!coerce_to_boolean(pstate, &rexpr)) if (!coerce_to_boolean(pstate, &rexpr))
@ -270,11 +287,6 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
} }
break; break;
} }
case T_Ident:
{
result = transformIdent(pstate, (Ident *) expr, precedence);
break;
}
case T_FuncCall: case T_FuncCall:
{ {
FuncCall *fn = (FuncCall *) expr; FuncCall *fn = (FuncCall *) expr;
@ -283,14 +295,13 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
/* transform the list of arguments */ /* transform the list of arguments */
foreach(args, fn->args) foreach(args, fn->args)
lfirst(args) = transformExpr(pstate, lfirst(args) = transformExpr(pstate,
(Node *) lfirst(args), (Node *) lfirst(args));
precedence);
result = ParseFuncOrColumn(pstate, result = ParseFuncOrColumn(pstate,
fn->funcname, fn->funcname,
fn->args, fn->args,
fn->agg_star, fn->agg_star,
fn->agg_distinct, fn->agg_distinct,
precedence); false);
break; break;
} }
case T_SubLink: case T_SubLink:
@ -357,8 +368,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
List *elist; List *elist;
foreach(elist, left_list) foreach(elist, left_list)
lfirst(elist) = transformExpr(pstate, lfirst(elist), lfirst(elist) = transformExpr(pstate, lfirst(elist));
precedence);
Assert(IsA(sublink->oper, A_Expr)); Assert(IsA(sublink->oper, A_Expr));
op = ((A_Expr *) sublink->oper)->opname; op = ((A_Expr *) sublink->oper)->opname;
@ -455,7 +465,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
a->rexpr = warg; a->rexpr = warg;
warg = (Node *) a; warg = (Node *) a;
} }
neww->expr = transformExpr(pstate, warg, precedence); neww->expr = transformExpr(pstate, warg);
if (!coerce_to_boolean(pstate, &neww->expr)) if (!coerce_to_boolean(pstate, &neww->expr))
elog(ERROR, "WHEN clause must have a boolean result"); elog(ERROR, "WHEN clause must have a boolean result");
@ -472,7 +482,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
n->val.type = T_Null; n->val.type = T_Null;
warg = (Node *) n; warg = (Node *) n;
} }
neww->result = transformExpr(pstate, warg, precedence); neww->result = transformExpr(pstate, warg);
newargs = lappend(newargs, neww); newargs = lappend(newargs, neww);
typeids = lappendi(typeids, exprType(neww->result)); typeids = lappendi(typeids, exprType(neww->result));
@ -496,7 +506,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
n->val.type = T_Null; n->val.type = T_Null;
defresult = (Node *) n; defresult = (Node *) n;
} }
newc->defresult = transformExpr(pstate, defresult, precedence); newc->defresult = transformExpr(pstate, defresult);
/* /*
* Note: default result is considered the most significant * Note: default result is considered the most significant
@ -534,7 +544,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
{ {
NullTest *n = (NullTest *) expr; NullTest *n = (NullTest *) expr;
n->arg = transformExpr(pstate, n->arg, precedence); n->arg = transformExpr(pstate, n->arg);
/* the argument can be any type, so don't coerce it */ /* the argument can be any type, so don't coerce it */
result = expr; result = expr;
break; break;
@ -544,7 +554,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
{ {
BooleanTest *b = (BooleanTest *) expr; BooleanTest *b = (BooleanTest *) expr;
b->arg = transformExpr(pstate, b->arg, precedence); b->arg = transformExpr(pstate, b->arg);
if (!coerce_to_boolean(pstate, &b->arg)) if (!coerce_to_boolean(pstate, &b->arg))
{ {
@ -627,47 +637,183 @@ transformIndirection(ParseState *pstate, Node *basenode, List *indirection)
} }
static Node * static Node *
transformAttr(ParseState *pstate, Attr *att, int precedence) transformColumnRef(ParseState *pstate, ColumnRef *cref)
{ {
Node *basenode; int numnames = length(cref->fields);
Node *node;
RangeVar *rv;
basenode = ParseNestedFuncOrColumn(pstate, att, precedence); /*----------
return transformIndirection(pstate, basenode, att->indirection); * The allowed syntaxes are:
} *
* A First try to resolve as unqualified column name;
* if no luck, try to resolve as unqual. table name (A.*).
* A.B A is an unqual. table name; B is either a
* column or function name (trying column name first).
* A.B.C schema A, table B, col or func name C.
* A.B.C.D catalog A, schema B, table C, col or func D.
* A.* A is an unqual. table name; means whole-row value.
* A.B.* whole-row value of table B in schema A.
* A.B.C.* whole-row value of table C in schema B in catalog A.
*
* We do not need to cope with bare "*"; that will only be accepted by
* the grammar at the top level of a SELECT list, and transformTargetList
* will take care of it before it ever gets here.
*
* Currently, if a catalog name is given then it must equal the current
* database name; we check it here and then discard it.
*
* For whole-row references, the result is an untransformed RangeVar,
* which will work as the argument to a function call, but not in any
* other context at present. (We could instead coerce to a whole-row Var,
* but that will fail for subselect and join RTEs, because there is no
* pg_type entry for their rowtypes.)
*----------
*/
switch (numnames)
{
case 1:
{
char *name = strVal(lfirst(cref->fields));
static Node * /* Try to identify as an unqualified column */
transformIdent(ParseState *pstate, Ident *ident, int precedence) node = colnameToVar(pstate, name);
{ if (node == NULL)
Node *result = NULL; {
int sublevels_up; /*
* Not known as a column of any range-table entry, so
* try to find the name as a relation ... but not if
* subscripts appear. Note also that only relations
* already entered into the rangetable will be recognized.
*/
int levels_up;
if (cref->indirection == NIL &&
refnameRangeTblEntry(pstate, name, &levels_up) != NULL)
{
rv = makeNode(RangeVar);
rv->relname = name;
rv->inhOpt = INH_DEFAULT;
node = (Node *) rv;
}
else
elog(ERROR, "Attribute \"%s\" not found", name);
}
break;
}
case 2:
{
char *name1 = strVal(lfirst(cref->fields));
char *name2 = strVal(lsecond(cref->fields));
/* Whole-row reference? */
if (strcmp(name2, "*") == 0)
{
rv = makeNode(RangeVar);
rv->relname = name1;
rv->inhOpt = INH_DEFAULT;
node = (Node *) rv;
break;
}
/* Try to identify as a once-qualified column */
node = qualifiedNameToVar(pstate, name1, name2, true);
if (node == NULL)
{
/*
* Not known as a column of any range-table entry, so
* try it as a function call. Here, we will create an
* implicit RTE for tables not already entered.
*/
rv = makeNode(RangeVar);
rv->relname = name1;
rv->inhOpt = INH_DEFAULT;
node = ParseFuncOrColumn(pstate, name2,
makeList1(rv),
false, false, true);
}
break;
}
case 3:
{
char *name1 = strVal(lfirst(cref->fields));
char *name2 = strVal(lsecond(cref->fields));
char *name3 = strVal(lfirst(lnext(lnext(cref->fields))));
/* Whole-row reference? */
if (strcmp(name3, "*") == 0)
{
rv = makeNode(RangeVar);
rv->schemaname = name1;
rv->relname = name2;
rv->inhOpt = INH_DEFAULT;
node = (Node *) rv;
break;
}
/* Try to identify as a twice-qualified column */
/* XXX do something with schema name here */
node = qualifiedNameToVar(pstate, name2, name3, true);
if (node == NULL)
{
/* Try it as a function call */
rv = makeNode(RangeVar);
rv->schemaname = name1;
rv->relname = name2;
rv->inhOpt = INH_DEFAULT;
node = ParseFuncOrColumn(pstate, name3,
makeList1(rv),
false, false, true);
}
break;
}
case 4:
{
char *name1 = strVal(lfirst(cref->fields));
char *name2 = strVal(lsecond(cref->fields));
char *name3 = strVal(lfirst(lnext(lnext(cref->fields))));
char *name4 = strVal(lfirst(lnext(lnext(lnext(cref->fields)))));
/* /*
* try to find the ident as a relation ... but not if subscripts * We check the catalog name and then ignore it.
* appear
*/ */
if (ident->indirection == NIL && if (strcmp(name1, DatabaseName) != 0)
refnameRangeTblEntry(pstate, ident->name, &sublevels_up) != NULL) elog(ERROR, "Cross-database references are not implemented");
/* Whole-row reference? */
if (strcmp(name4, "*") == 0)
{ {
ident->isRel = TRUE; rv = makeNode(RangeVar);
result = (Node *) ident; rv->schemaname = name2;
rv->relname = name3;
rv->inhOpt = INH_DEFAULT;
node = (Node *) rv;
break;
} }
if (result == NULL || precedence == EXPR_COLUMN_FIRST) /* Try to identify as a twice-qualified column */
/* XXX do something with schema name here */
node = qualifiedNameToVar(pstate, name3, name4, true);
if (node == NULL)
{ {
/* try to find the ident as a column */ /* Try it as a function call */
Node *var = colnameToVar(pstate, ident->name); rv = makeNode(RangeVar);
rv->schemaname = name2;
if (var != NULL) rv->relname = name3;
{ rv->inhOpt = INH_DEFAULT;
ident->isRel = FALSE; node = ParseFuncOrColumn(pstate, name4,
result = transformIndirection(pstate, var, ident->indirection); makeList1(rv),
false, false, true);
} }
break;
}
default:
elog(ERROR, "Invalid qualified name syntax (too many names)");
node = NULL; /* keep compiler quiet */
break;
} }
if (result == NULL) return transformIndirection(pstate, node, cref->indirection);
elog(ERROR, "Attribute '%s' not found", ident->name);
return result;
} }
/* /*
@ -748,10 +894,6 @@ exprType(Node *expr)
case T_BooleanTest: case T_BooleanTest:
type = BOOLOID; type = BOOLOID;
break; break;
case T_Ident:
/* XXX is this right? */
type = UNKNOWNOID;
break;
default: default:
elog(ERROR, "Do not know how to get type for %d node", elog(ERROR, "Do not know how to get type for %d node",
nodeTag(expr)); nodeTag(expr));

View File

@ -8,11 +8,10 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.118 2002/03/20 19:44:29 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.119 2002/03/21 16:01:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h" #include "postgres.h"
#include "access/genam.h" #include "access/genam.h"
@ -36,8 +35,7 @@
static Node *ParseComplexProjection(ParseState *pstate, static Node *ParseComplexProjection(ParseState *pstate,
char *funcname, char *funcname,
Node *first_arg, Node *first_arg);
bool *attisset);
static Oid **argtype_inherit(int nargs, Oid *argtypes); static Oid **argtype_inherit(int nargs, Oid *argtypes);
static int find_inheritors(Oid relid, Oid **supervec); static int find_inheritors(Oid relid, Oid **supervec);
@ -60,75 +58,31 @@ static Oid agg_select_candidate(Oid typeid, CandidateList candidates);
/* /*
** ParseNestedFuncOrColumn * Parse a function call
** Given a nested dot expression (i.e. (relation func ... attr), build up
** a tree with of Iter and Func nodes.
*/
Node *
ParseNestedFuncOrColumn(ParseState *pstate, Attr *attr, int precedence)
{
List *mutator_iter;
Node *retval = NULL;
if (attr->paramNo != NULL)
{
Param *param = (Param *) transformExpr(pstate,
(Node *) attr->paramNo,
EXPR_RELATION_FIRST);
retval = ParseFuncOrColumn(pstate, strVal(lfirst(attr->attrs)),
makeList1(param),
false, false,
precedence);
}
else
{
Ident *ident = makeNode(Ident);
ident->name = attr->relname;
ident->isRel = TRUE;
retval = ParseFuncOrColumn(pstate, strVal(lfirst(attr->attrs)),
makeList1(ident),
false, false,
precedence);
}
/* Do more attributes follow this one? */
foreach(mutator_iter, lnext(attr->attrs))
{
retval = ParseFuncOrColumn(pstate, strVal(lfirst(mutator_iter)),
makeList1(retval),
false, false,
precedence);
}
return retval;
}
/*
* parse function
* *
* This code is confusing because the database can accept * For historical reasons, Postgres tries to treat the notations tab.col
* relation.column, column.function, or relation.column.function. * and col(tab) as equivalent: if a single-argument function call has an
* In these cases, funcname is the last parameter, and fargs are * argument of complex type and the function name matches any attribute
* the rest. * of the type, we take it as a column projection.
* *
* It can also be called as func(col) or func(col,col). * Hence, both cases come through here. The is_column parameter tells us
* In this case, Funcname is the part before parens, and fargs * which syntactic construct is actually being dealt with, but this is
* are the part in parens. * intended to be used only to deliver an appropriate error message,
* * not to affect the semantics. When is_column is true, we should have
* FYI, projection is choosing column from a table. * a single argument (the putative table), function name equal to the
* column name, and no aggregate decoration.
* *
* In the function-call case, the argument expressions have been transformed
* already. In the column case, we may get either a transformed expression
* or a RangeVar node as argument.
*/ */
Node * Node *
ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
bool agg_star, bool agg_distinct, bool agg_star, bool agg_distinct, bool is_column)
int precedence)
{ {
Oid rettype = InvalidOid; Oid rettype;
Oid argrelid = InvalidOid; Oid funcid;
Oid funcid = InvalidOid; List *i;
List *i = NIL;
Node *first_arg = NULL; Node *first_arg = NULL;
char *refname; char *refname;
int nargs = length(fargs); int nargs = length(fargs);
@ -140,9 +94,8 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
bool retset; bool retset;
bool must_be_agg = agg_star || agg_distinct; bool must_be_agg = agg_star || agg_distinct;
bool could_be_agg; bool could_be_agg;
bool attisset = false;
Oid toid = InvalidOid;
Expr *expr; Expr *expr;
FuncDetailCode fdresult;
/* /*
* Most of the rest of the parser just assumes that functions do not * Most of the rest of the parser just assumes that functions do not
@ -157,33 +110,26 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
if (fargs) if (fargs)
{ {
first_arg = lfirst(fargs); first_arg = lfirst(fargs);
if (first_arg == NULL) if (first_arg == NULL) /* should not happen */
elog(ERROR, "Function '%s' does not allow NULL input", funcname); elog(ERROR, "Function '%s' does not allow NULL input", funcname);
} }
/* /*
* test for relation.column * check for column projection: if function has one argument, and that
* * argument is of complex type, then the function could be a projection.
* check for projection methods: if function takes one argument, and that
* argument is a relation, param, or PQ function returning a complex *
* type, then the function could be a projection.
*/ */
/* We only have one parameter, and it's not got aggregate decoration */ /* We only have one parameter, and it's not got aggregate decoration */
if (nargs == 1 && !must_be_agg) if (nargs == 1 && !must_be_agg)
{ {
/* Is it a plain Relation name from the parser? */ /* Is it a not-yet-transformed RangeVar node? */
if (IsA(first_arg, Ident) &&((Ident *) first_arg)->isRel) if (IsA(first_arg, RangeVar))
{ {
Ident *ident = (Ident *) first_arg;
/* First arg is a relation. This could be a projection. */ /* First arg is a relation. This could be a projection. */
refname = ident->name; refname = ((RangeVar *) first_arg)->relname;
retval = qualifiedNameToVar(pstate, refname, funcname, true); retval = qualifiedNameToVar(pstate, refname, funcname, true);
if (retval) if (retval)
return retval; return retval;
/* else drop through - attr is a set or function */
} }
else if (ISCOMPLEX(exprType(first_arg))) else if (ISCOMPLEX(exprType(first_arg)))
{ {
@ -194,24 +140,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
*/ */
retval = ParseComplexProjection(pstate, retval = ParseComplexProjection(pstate,
funcname, funcname,
first_arg, first_arg);
&attisset);
if (attisset)
{
toid = exprType(first_arg);
argrelid = typeidTypeRelid(toid);
if (argrelid == InvalidOid)
elog(ERROR, "Type '%s' is not a relation type",
typeidTypeName(toid));
/*
* A projection must match an attribute name of the rel.
*/
if (get_attnum(argrelid, funcname) == InvalidAttrNumber)
elog(ERROR, "No such attribute or function '%s'",
funcname);
}
if (retval) if (retval)
return retval; return retval;
} }
@ -226,15 +155,14 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
if (nargs != 1) if (nargs != 1)
elog(ERROR, "Aggregate functions may only have one parameter"); elog(ERROR, "Aggregate functions may only have one parameter");
/* Agg's argument can't be a relation name, either */ /* Agg's argument can't be a relation name, either */
if (IsA(first_arg, Ident) &&((Ident *) first_arg)->isRel) if (IsA(first_arg, RangeVar))
elog(ERROR, "Aggregate functions cannot be applied to relation names"); elog(ERROR, "Aggregate functions cannot be applied to relation names");
could_be_agg = true; could_be_agg = true;
} }
else else
{ {
/* Try to parse as an aggregate if above-mentioned checks are OK */ /* Try to parse as an aggregate if above-mentioned checks are OK */
could_be_agg = (nargs == 1) && could_be_agg = (nargs == 1) && !(IsA(first_arg, RangeVar));
!(IsA(first_arg, Ident) &&((Ident *) first_arg)->isRel);
} }
if (could_be_agg) if (could_be_agg)
@ -249,8 +177,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
ObjectIdGetDatum(basetype), ObjectIdGetDatum(basetype),
0, 0)) 0, 0))
return (Node *) ParseAgg(pstate, funcname, basetype, return (Node *) ParseAgg(pstate, funcname, basetype,
fargs, agg_star, agg_distinct, fargs, agg_star, agg_distinct);
precedence);
/* check for aggregate-that-accepts-any-type (eg, COUNT) */ /* check for aggregate-that-accepts-any-type (eg, COUNT) */
if (SearchSysCacheExists(AGGNAME, if (SearchSysCacheExists(AGGNAME,
@ -258,8 +185,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
ObjectIdGetDatum(0), ObjectIdGetDatum(0),
0, 0)) 0, 0))
return (Node *) ParseAgg(pstate, funcname, 0, return (Node *) ParseAgg(pstate, funcname, 0,
fargs, agg_star, agg_distinct, fargs, agg_star, agg_distinct);
precedence);
/* /*
* No exact match yet, so see if there is another entry in the * No exact match yet, so see if there is another entry in the
@ -277,8 +203,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
basetype, type, -1); basetype, type, -1);
basetype = type; basetype = type;
return (Node *) ParseAgg(pstate, funcname, basetype, return (Node *) ParseAgg(pstate, funcname, basetype,
fargs, agg_star, agg_distinct, fargs, agg_star, agg_distinct);
precedence);
} }
else else
{ {
@ -300,10 +225,9 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
} }
/* /*
* If we dropped through to here it's really a function (or a set, * Okay, it's not a column projection, so it must really be a function.
* which is implemented as a function). Extract arg type info and * Extract arg type info and transform RangeVar arguments into varnodes
* transform relation name arguments into varnodes of the appropriate * of the appropriate form.
* form.
*/ */
MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid)); MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
@ -311,8 +235,9 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
foreach(i, fargs) foreach(i, fargs)
{ {
Node *arg = lfirst(i); Node *arg = lfirst(i);
Oid toid;
if (IsA(arg, Ident) &&((Ident *) arg)->isRel) if (IsA(arg, RangeVar))
{ {
RangeTblEntry *rte; RangeTblEntry *rte;
int vnum; int vnum;
@ -321,7 +246,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
/* /*
* a relation * a relation
*/ */
refname = ((Ident *) arg)->name; refname = ((RangeVar *) arg)->relname;
rte = refnameRangeTblEntry(pstate, refname, rte = refnameRangeTblEntry(pstate, refname,
&sublevels_up); &sublevels_up);
@ -346,16 +271,9 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
* RTE is a join or subselect; must fail for lack of a * RTE is a join or subselect; must fail for lack of a
* named tuple type * named tuple type
*/ */
if (nargs == 1) if (is_column)
{ elog(ERROR, "No such attribute %s.%s",
/*
* Here, we probably have an unrecognized attribute of
* a sub-select; again can't tell if it was x.f or
* f(x)
*/
elog(ERROR, "No such attribute or function %s.%s",
refname, funcname); refname, funcname);
}
else else
{ {
elog(ERROR, "Cannot pass result of sub-select or join %s to a function", elog(ERROR, "Cannot pass result of sub-select or join %s to a function",
@ -365,48 +283,19 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
toid = typenameTypeId(rte->relname); toid = typenameTypeId(rte->relname);
/* replace it in the arg list */ /* replace RangeVar in the arg list */
lfirst(i) = makeVar(vnum, lfirst(i) = makeVar(vnum,
InvalidAttrNumber, InvalidAttrNumber,
toid, toid,
sizeof(Pointer), sizeof(Pointer),
sublevels_up); sublevels_up);
} }
else if (!attisset)
toid = exprType(arg);
else else
{ toid = exprType(arg);
/* if attisset is true, we already set toid for the single arg */
}
oid_array[argn++] = toid; oid_array[argn++] = toid;
} }
/*
* Is it a set, or a function?
*/
if (attisset)
{ /* we know all of these fields already */
/*
* We create a funcnode with a placeholder function seteval(). At
* runtime, seteval() will execute the function identified by the
* funcid it receives as parameter.
*
* Example: retrieve (emp.mgr.name). The plan for this will scan the
* emp relation, projecting out the mgr attribute, which is a
* funcid. This function is then called (via seteval()) and "name"
* is projected from its result.
*/
funcid = F_SETEVAL;
rettype = toid;
retset = true;
true_oid_array = oid_array;
}
else
{
FuncDetailCode fdresult;
/* /*
* func_get_detail looks up the function in the catalogs, does * func_get_detail looks up the function in the catalogs, does
* disambiguation for polymorphic functions, handles inheritance, * disambiguation for polymorphic functions, handles inheritance,
@ -431,28 +320,17 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
/* /*
* Oops. Time to die. * Oops. Time to die.
* *
* If there is a single argument of complex type, we might be * If we are dealing with the attribute notation rel.function,
* dealing with the PostQuel notation rel.function instead of * give an error message that is appropriate for that case.
* the more usual function(rel). Give a nonspecific error
* message that will cover both cases.
*/ */
if (nargs == 1) if (is_column)
{ elog(ERROR, "Attribute \"%s\" not found", funcname);
Type tp = typeidType(oid_array[0]);
if (typeTypeFlag(tp) == 'c')
elog(ERROR, "No such attribute or function '%s'",
funcname);
ReleaseSysCache(tp);
}
/* Else generate a detailed complaint */ /* Else generate a detailed complaint */
func_error(NULL, funcname, nargs, oid_array, func_error(NULL, funcname, nargs, oid_array,
"Unable to identify a function that satisfies the " "Unable to identify a function that satisfies the "
"given argument types" "given argument types"
"\n\tYou may need to add explicit typecasts"); "\n\tYou may need to add explicit typecasts");
} }
}
/* got it */ /* got it */
funcnode = makeNode(Func); funcnode = makeNode(Func);
@ -470,26 +348,12 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
expr->args = fargs; expr->args = fargs;
retval = (Node *) expr; retval = (Node *) expr;
/*
* For sets, we want to project out the desired attribute of the
* tuples.
*/
if (attisset)
{
FieldSelect *fselect;
fselect = setup_field_select(retval, funcname, argrelid);
rettype = fselect->resulttype;
retval = (Node *) fselect;
}
/* /*
* if the function returns a set of values, then we need to iterate * if the function returns a set of values, then we need to iterate
* over all the returned values in the executor, so we stick an iter * over all the returned values in the executor, so we stick an iter
* node here. if it returns a singleton, then we don't need the iter * node here. if it returns a singleton, then we don't need the iter
* node. * node.
*/ */
if (retset) if (retset)
{ {
Iter *iter = makeNode(Iter); Iter *iter = makeNode(Iter);
@ -1497,10 +1361,10 @@ make_arguments(ParseState *pstate,
} }
/* /*
** setup_field_select * setup_field_select
** Build a FieldSelect node that says which attribute to project to. * Build a FieldSelect node that says which attribute to project to.
** This routine is called by ParseFuncOrColumn() when we have found * This routine is called by ParseFuncOrColumn() when we have found
** a projection on a function result or parameter. * a projection on a function result or parameter.
*/ */
static FieldSelect * static FieldSelect *
setup_field_select(Node *input, char *attname, Oid relid) setup_field_select(Node *input, char *attname, Oid relid)
@ -1521,18 +1385,31 @@ setup_field_select(Node *input, char *attname, Oid relid)
/* /*
* ParseComplexProjection - * ParseComplexProjection -
* handles function calls with a single argument that is of complex type. * handles function calls with a single argument that is of complex type.
* This routine returns NULL if it can't handle the projection (eg. sets). * If the function call is actually a column projection, return a suitably
* transformed expression tree. If not, return NULL.
*
* NB: argument is expected to be transformed already, ie, not a RangeVar.
*/ */
static Node * static Node *
ParseComplexProjection(ParseState *pstate, ParseComplexProjection(ParseState *pstate,
char *funcname, char *funcname,
Node *first_arg, Node *first_arg)
bool *attisset)
{ {
Oid argtype; Oid argtype = exprType(first_arg);
Oid argrelid; Oid argrelid;
AttrNumber attnum;
FieldSelect *fselect; FieldSelect *fselect;
argrelid = typeidTypeRelid(argtype);
if (!argrelid)
return NULL; /* probably should not happen */
attnum = get_attnum(argrelid, funcname);
if (attnum == InvalidAttrNumber)
return NULL; /* funcname does not match any column */
/*
* Check for special cases where we don't want to return a FieldSelect.
*/
switch (nodeTag(first_arg)) switch (nodeTag(first_arg))
{ {
case T_Iter: case T_Iter:
@ -1540,75 +1417,42 @@ ParseComplexProjection(ParseState *pstate,
Iter *iter = (Iter *) first_arg; Iter *iter = (Iter *) first_arg;
/* /*
* If the argument of the Iter returns a tuple, funcname * If it's an Iter, we stick the FieldSelect
* may be a projection. If so, we stick the FieldSelect
* *inside* the Iter --- this is klugy, but necessary * *inside* the Iter --- this is klugy, but necessary
* because ExecTargetList() currently does the right thing * because ExecTargetList() currently does the right thing
* only when the Iter node is at the top level of a * only when the Iter node is at the top level of a
* targetlist item. * targetlist item.
*
* XXX Iter should go away altogether...
*/ */
argtype = iter->itertype;
argrelid = typeidTypeRelid(argtype);
if (argrelid &&
get_attnum(argrelid, funcname) != InvalidAttrNumber)
{
fselect = setup_field_select(iter->iterexpr, fselect = setup_field_select(iter->iterexpr,
funcname, argrelid); funcname, argrelid);
iter->iterexpr = (Node *) fselect; iter->iterexpr = (Node *) fselect;
iter->itertype = fselect->resulttype; iter->itertype = fselect->resulttype;
return (Node *) iter; return (Node *) iter;
}
break; break;
} }
case T_Var: case T_Var:
{ {
/* Var *var = (Var *) first_arg;
* The argument is a set, so this is either a projection
* or a function call on this set.
*/
*attisset = true;
break;
}
case T_Expr:
{
Expr *expr = (Expr *) first_arg;
Func *funcnode;
if (expr->opType != FUNC_EXPR)
break;
/* /*
* If the argument is a function returning a tuple, * If the Var is a whole-row tuple, we can just replace it
* funcname may be a projection * with a simple Var reference.
*/ */
funcnode = (Func *) expr->oper; if (var->varattno == InvalidAttrNumber)
argtype = funcnode->functype;
argrelid = typeidTypeRelid(argtype);
if (argrelid &&
get_attnum(argrelid, funcname) != InvalidAttrNumber)
{ {
fselect = setup_field_select((Node *) expr, Oid vartype;
funcname, argrelid); int32 vartypmod;
return (Node *) fselect;
}
break;
}
case T_Param:
{
Param *param = (Param *) first_arg;
/* get_atttypetypmod(argrelid, attnum,
* If the Param is a complex type, this could be a &vartype, &vartypmod);
* projection
*/ return (Node *) makeVar(var->varno,
argtype = param->paramtype; attnum,
argrelid = typeidTypeRelid(argtype); vartype,
if (argrelid && vartypmod,
get_attnum(argrelid, funcname) != InvalidAttrNumber) var->varlevelsup);
{
fselect = setup_field_select((Node *) param,
funcname, argrelid);
return (Node *) fselect;
} }
break; break;
} }
@ -1616,7 +1460,9 @@ ParseComplexProjection(ParseState *pstate,
break; break;
} }
return NULL; /* Else generate a FieldSelect expression */
fselect = setup_field_select(first_arg, funcname, argrelid);
return (Node *) fselect;
} }
/* /*

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.59 2002/03/12 00:51:55 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.60 2002/03/21 16:01:07 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -285,7 +285,7 @@ transformArraySubscripts(ParseState *pstate,
{ {
if (ai->lidx) if (ai->lidx)
{ {
subexpr = transformExpr(pstate, ai->lidx, EXPR_COLUMN_FIRST); subexpr = transformExpr(pstate, ai->lidx);
/* If it's not int4 already, try to coerce */ /* If it's not int4 already, try to coerce */
subexpr = CoerceTargetExpr(pstate, subexpr, exprType(subexpr), subexpr = CoerceTargetExpr(pstate, subexpr, exprType(subexpr),
INT4OID, -1); INT4OID, -1);
@ -305,7 +305,7 @@ transformArraySubscripts(ParseState *pstate,
} }
lowerIndexpr = lappend(lowerIndexpr, subexpr); lowerIndexpr = lappend(lowerIndexpr, subexpr);
} }
subexpr = transformExpr(pstate, ai->uidx, EXPR_COLUMN_FIRST); subexpr = transformExpr(pstate, ai->uidx);
/* If it's not int4 already, try to coerce */ /* If it's not int4 already, try to coerce */
subexpr = CoerceTargetExpr(pstate, subexpr, exprType(subexpr), subexpr = CoerceTargetExpr(pstate, subexpr, exprType(subexpr),
INT4OID, -1); INT4OID, -1);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.63 2002/03/12 00:51:56 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.64 2002/03/21 16:01:09 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -104,7 +104,7 @@ scanNameSpaceForRefname(ParseState *pstate, Node *nsnode,
int varno = ((RangeTblRef *) nsnode)->rtindex; int varno = ((RangeTblRef *) nsnode)->rtindex;
RangeTblEntry *rte = rt_fetch(varno, pstate->p_rtable); RangeTblEntry *rte = rt_fetch(varno, pstate->p_rtable);
if (strcmp(rte->eref->relname, refname) == 0) if (strcmp(rte->eref->aliasname, refname) == 0)
result = (Node *) rte; result = (Node *) rte;
} }
else if (IsA(nsnode, JoinExpr)) else if (IsA(nsnode, JoinExpr))
@ -113,7 +113,7 @@ scanNameSpaceForRefname(ParseState *pstate, Node *nsnode,
if (j->alias) if (j->alias)
{ {
if (strcmp(j->alias->relname, refname) == 0) if (strcmp(j->alias->aliasname, refname) == 0)
return (Node *) j; /* matched a join alias */ return (Node *) j; /* matched a join alias */
/* /*
@ -175,7 +175,7 @@ checkNameSpaceConflicts(ParseState *pstate, Node *namespace1,
int varno = ((RangeTblRef *) namespace1)->rtindex; int varno = ((RangeTblRef *) namespace1)->rtindex;
RangeTblEntry *rte = rt_fetch(varno, pstate->p_rtable); RangeTblEntry *rte = rt_fetch(varno, pstate->p_rtable);
scanNameSpaceForConflict(pstate, namespace2, rte->eref->relname); scanNameSpaceForConflict(pstate, namespace2, rte->eref->aliasname);
} }
else if (IsA(namespace1, JoinExpr)) else if (IsA(namespace1, JoinExpr))
{ {
@ -183,7 +183,7 @@ checkNameSpaceConflicts(ParseState *pstate, Node *namespace1,
if (j->alias) if (j->alias)
{ {
scanNameSpaceForConflict(pstate, namespace2, j->alias->relname); scanNameSpaceForConflict(pstate, namespace2, j->alias->aliasname);
/* /*
* Tables within an aliased join are invisible from outside * Tables within an aliased join are invisible from outside
@ -268,7 +268,7 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname)
* Scan the user column names (or aliases) for a match. Complain if * Scan the user column names (or aliases) for a match. Complain if
* multiple matches. * multiple matches.
*/ */
foreach(c, rte->eref->attrs) foreach(c, rte->eref->colnames)
{ {
attnum++; attnum++;
if (strcmp(strVal(lfirst(c)), colname) == 0) if (strcmp(strVal(lfirst(c)), colname) == 0)
@ -420,15 +420,15 @@ qualifiedNameToVar(ParseState *pstate, char *refname, char *colname,
RangeTblEntry * RangeTblEntry *
addRangeTableEntry(ParseState *pstate, addRangeTableEntry(ParseState *pstate,
char *relname, char *relname,
Attr *alias, Alias *alias,
bool inh, bool inh,
bool inFromCl) bool inFromCl)
{ {
RangeTblEntry *rte = makeNode(RangeTblEntry); RangeTblEntry *rte = makeNode(RangeTblEntry);
char *refname = alias ? alias->relname : relname; char *refname = alias ? alias->aliasname : relname;
LOCKMODE lockmode; LOCKMODE lockmode;
Relation rel; Relation rel;
Attr *eref; Alias *eref;
int maxattrs; int maxattrs;
int numaliases; int numaliases;
int varattno; int varattno;
@ -447,8 +447,8 @@ addRangeTableEntry(ParseState *pstate,
rel = heap_openr(relname, lockmode); rel = heap_openr(relname, lockmode);
rte->relid = RelationGetRelid(rel); rte->relid = RelationGetRelid(rel);
eref = alias ? (Attr *) copyObject(alias) : makeAttr(refname, NULL); eref = alias ? (Alias *) copyObject(alias) : makeAlias(refname, NIL);
numaliases = length(eref->attrs); numaliases = length(eref->colnames);
/* /*
* Since the rel is open anyway, let's check that the number of column * Since the rel is open anyway, let's check that the number of column
@ -459,13 +459,13 @@ addRangeTableEntry(ParseState *pstate,
elog(ERROR, "Table \"%s\" has %d columns available but %d columns specified", elog(ERROR, "Table \"%s\" has %d columns available but %d columns specified",
refname, maxattrs, numaliases); refname, maxattrs, numaliases);
/* fill in any unspecified alias columns */ /* fill in any unspecified alias columns using actual column names */
for (varattno = numaliases; varattno < maxattrs; varattno++) for (varattno = numaliases; varattno < maxattrs; varattno++)
{ {
char *attrname; char *attrname;
attrname = pstrdup(NameStr(rel->rd_att->attrs[varattno]->attname)); attrname = pstrdup(NameStr(rel->rd_att->attrs[varattno]->attname));
eref->attrs = lappend(eref->attrs, makeString(attrname)); eref->colnames = lappend(eref->colnames, makeString(attrname));
} }
rte->eref = eref; rte->eref = eref;
@ -512,12 +512,12 @@ addRangeTableEntry(ParseState *pstate,
RangeTblEntry * RangeTblEntry *
addRangeTableEntryForSubquery(ParseState *pstate, addRangeTableEntryForSubquery(ParseState *pstate,
Query *subquery, Query *subquery,
Attr *alias, Alias *alias,
bool inFromCl) bool inFromCl)
{ {
RangeTblEntry *rte = makeNode(RangeTblEntry); RangeTblEntry *rte = makeNode(RangeTblEntry);
char *refname = alias->relname; char *refname = alias->aliasname;
Attr *eref; Alias *eref;
int numaliases; int numaliases;
int varattno; int varattno;
List *tlistitem; List *tlistitem;
@ -529,7 +529,7 @@ addRangeTableEntryForSubquery(ParseState *pstate,
rte->alias = alias; rte->alias = alias;
eref = copyObject(alias); eref = copyObject(alias);
numaliases = length(eref->attrs); numaliases = length(eref->colnames);
/* fill in any unspecified alias columns */ /* fill in any unspecified alias columns */
varattno = 0; varattno = 0;
@ -546,7 +546,7 @@ addRangeTableEntryForSubquery(ParseState *pstate,
char *attrname; char *attrname;
attrname = pstrdup(te->resdom->resname); attrname = pstrdup(te->resdom->resname);
eref->attrs = lappend(eref->attrs, makeString(attrname)); eref->colnames = lappend(eref->colnames, makeString(attrname));
} }
} }
if (varattno < numaliases) if (varattno < numaliases)
@ -594,11 +594,11 @@ addRangeTableEntryForJoin(ParseState *pstate,
List *coltypmods, List *coltypmods,
List *leftcols, List *leftcols,
List *rightcols, List *rightcols,
Attr *alias, Alias *alias,
bool inFromCl) bool inFromCl)
{ {
RangeTblEntry *rte = makeNode(RangeTblEntry); RangeTblEntry *rte = makeNode(RangeTblEntry);
Attr *eref; Alias *eref;
int numaliases; int numaliases;
rte->rtekind = RTE_JOIN; rte->rtekind = RTE_JOIN;
@ -612,15 +612,15 @@ addRangeTableEntryForJoin(ParseState *pstate,
rte->joinrightcols = rightcols; rte->joinrightcols = rightcols;
rte->alias = alias; rte->alias = alias;
eref = alias ? (Attr *) copyObject(alias) : makeAttr("unnamed_join", NULL); eref = alias ? (Alias *) copyObject(alias) : makeAlias("unnamed_join", NIL);
numaliases = length(eref->attrs); numaliases = length(eref->colnames);
/* fill in any unspecified alias columns */ /* fill in any unspecified alias columns */
if (numaliases < length(colnames)) if (numaliases < length(colnames))
{ {
while (numaliases-- > 0) while (numaliases-- > 0)
colnames = lnext(colnames); colnames = lnext(colnames);
eref->attrs = nconc(eref->attrs, colnames); eref->colnames = nconc(eref->colnames, colnames);
} }
rte->eref = eref; rte->eref = eref;
@ -759,7 +759,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
rel = heap_openr(rte->relname, AccessShareLock); rel = heap_openr(rte->relname, AccessShareLock);
maxattrs = RelationGetNumberOfAttributes(rel); maxattrs = RelationGetNumberOfAttributes(rel);
numaliases = length(rte->eref->attrs); numaliases = length(rte->eref->colnames);
for (varattno = 0; varattno < maxattrs; varattno++) for (varattno = 0; varattno < maxattrs; varattno++)
{ {
@ -775,7 +775,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
char *label; char *label;
if (varattno < numaliases) if (varattno < numaliases)
label = strVal(nth(varattno, rte->eref->attrs)); label = strVal(nth(varattno, rte->eref->colnames));
else else
label = NameStr(attr->attname); label = NameStr(attr->attname);
*colnames = lappend(*colnames, makeString(pstrdup(label))); *colnames = lappend(*colnames, makeString(pstrdup(label)));
@ -798,7 +798,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
else if (rte->rtekind == RTE_SUBQUERY) else if (rte->rtekind == RTE_SUBQUERY)
{ {
/* Subquery RTE */ /* Subquery RTE */
List *aliasp = rte->eref->attrs; List *aliasp = rte->eref->colnames;
List *tlistitem; List *tlistitem;
varattno = 0; varattno = 0;
@ -836,7 +836,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
else if (rte->rtekind == RTE_JOIN) else if (rte->rtekind == RTE_JOIN)
{ {
/* Join RTE */ /* Join RTE */
List *aliasp = rte->eref->attrs; List *aliasp = rte->eref->colnames;
List *coltypes = rte->joincoltypes; List *coltypes = rte->joincoltypes;
List *coltypmods = rte->joincoltypmods; List *coltypmods = rte->joincoltypmods;
@ -936,8 +936,8 @@ get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
* If there is an alias, use it. (This path should always be taken * If there is an alias, use it. (This path should always be taken
* for non-relation RTEs.) * for non-relation RTEs.)
*/ */
if (attnum > 0 && attnum <= length(rte->eref->attrs)) if (attnum > 0 && attnum <= length(rte->eref->colnames))
return strVal(nth(attnum - 1, rte->eref->attrs)); return strVal(nth(attnum - 1, rte->eref->colnames));
/* /*
* Can get here for a system attribute (which never has an alias), or * Can get here for a system attribute (which never has an alias), or
@ -946,7 +946,7 @@ get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
*/ */
if (rte->rtekind != RTE_RELATION) if (rte->rtekind != RTE_RELATION)
elog(ERROR, "Invalid attnum %d for rangetable entry %s", elog(ERROR, "Invalid attnum %d for rangetable entry %s",
attnum, rte->eref->relname); attnum, rte->eref->aliasname);
/* /*
* Use the real name of the table's column * Use the real name of the table's column
@ -1002,7 +1002,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
} }
/* falling off end of list shouldn't happen... */ /* falling off end of list shouldn't happen... */
elog(ERROR, "Subquery %s does not have attribute %d", elog(ERROR, "Subquery %s does not have attribute %d",
rte->eref->relname, attnum); rte->eref->aliasname, attnum);
} }
else if (rte->rtekind == RTE_JOIN) else if (rte->rtekind == RTE_JOIN)
{ {

View File

@ -8,13 +8,13 @@
* *
* *
* IDENTIFICATION * 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 "postgres.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h" #include "nodes/makefuncs.h"
#include "parser/parsetree.h" #include "parser/parsetree.h"
#include "parser/parse_coerce.h" #include "parser/parse_coerce.h"
@ -56,9 +56,9 @@ transformTargetEntry(ParseState *pstate,
/* Transform the node if caller didn't do it already */ /* Transform the node if caller didn't do it already */
if (expr == NULL) 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.*."); elog(ERROR, "You can't use relation names alone in the target list, try relation.*.");
type_id = exprType(expr); type_id = exprType(expr);
@ -99,11 +99,13 @@ transformTargetList(ParseState *pstate, List *targetlist)
{ {
ResTarget *res = (ResTarget *) lfirst(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. * Target item is a single '*', expand all tables (eg.
@ -112,27 +114,59 @@ transformTargetList(ParseState *pstate, List *targetlist)
p_target = nconc(p_target, p_target = nconc(p_target,
ExpandAllTables(pstate)); ExpandAllTables(pstate));
} }
else if (att->attrs != NIL && else if (strcmp(strVal(nth(numnames-1, fields)), "*") == 0)
strcmp(strVal(lfirst(att->attrs)), "*") == 0)
{ {
/* /*
* Target item is relation.*, expand that table (eg. * Target item is relation.*, expand that table (eg.
* SELECT emp.*, dname FROM emp, dept) * SELECT emp.*, dname FROM emp, dept)
*/ */
char *schemaname;
char *relname;
RangeTblEntry *rte; RangeTblEntry *rte;
int sublevels_up; 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); &sublevels_up);
if (rte == NULL) if (rte == NULL)
rte = addImplicitRTE(pstate, att->relname); rte = addImplicitRTE(pstate, relname);
p_target = nconc(p_target, p_target = nconc(p_target,
expandRelAttrs(pstate, rte)); expandRelAttrs(pstate, rte));
} }
else else
{ {
/* Plain Attr node, treat it as an expression */ /* Plain ColumnRef node, treat it as an expression */
p_target = lappend(p_target, p_target = lappend(p_target,
transformTargetEntry(pstate, transformTargetEntry(pstate,
res->val, res->val,
@ -143,7 +177,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
} }
else else
{ {
/* Everything else but Attr */ /* Everything else but ColumnRef */
p_target = lappend(p_target, p_target = lappend(p_target,
transformTargetEntry(pstate, transformTargetEntry(pstate,
res->val, res->val,
@ -317,10 +351,9 @@ CoerceTargetExpr(ParseState *pstate,
/* /*
* checkInsertTargets - * 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. * test supplied column names to make sure they are in target table.
* Also return an integer list of the columns' attribute numbers. * Also return an integer list of the columns' attribute numbers.
* (used exclusively for inserts)
*/ */
List * List *
checkInsertTargets(ParseState *pstate, List *cols, List **attrnos) checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
@ -338,17 +371,16 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
for (i = 0; i < numcol; i++) for (i = 0; i < numcol; i++)
{ {
Ident *id = makeNode(Ident); ResTarget *col = makeNode(ResTarget);
#ifdef _DROP_COLUMN_HACK__ #ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(attr[i])) if (COLUMN_IS_DROPPED(attr[i]))
continue; continue;
#endif /* _DROP_COLUMN_HACK__ */ #endif /* _DROP_COLUMN_HACK__ */
id->name = palloc(NAMEDATALEN); col->name = pstrdup(NameStr(attr[i]->attname));
StrNCpy(id->name, NameStr(attr[i]->attname), NAMEDATALEN); col->indirection = NIL;
id->indirection = NIL; col->val = NULL;
id->isRel = false; cols = lappend(cols, col);
cols = lappend(cols, id);
*attrnos = lappendi(*attrnos, i + 1); *attrnos = lappendi(*attrnos, i + 1);
} }
} }
@ -361,7 +393,7 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
foreach(tl, cols) foreach(tl, cols)
{ {
char *name = ((Ident *) lfirst(tl))->name; char *name = ((ResTarget *) lfirst(tl))->name;
int attrno; int attrno;
/* Lookup column name, elog on failure */ /* Lookup column name, elog on failure */
@ -458,19 +490,35 @@ FigureColnameInternal(Node *node, char **name)
case T_Ident: case T_Ident:
*name = ((Ident *) node)->name; *name = ((Ident *) node)->name;
return 2; 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) *name = strVal(lfirst(fields));
attrs = lnext(attrs);
*name = strVal(lfirst(attrs));
return 2; return 2;
} }
} }
break; 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: case T_FuncCall:
*name = ((FuncCall *) node)->funcname; *name = ((FuncCall *) node)->funcname;
return 2; return 2;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.63 2001/08/12 21:35:18 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.64 2002/03/21 16:01:16 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -110,63 +110,17 @@ InsertRule(char *rulname,
return rewriteObjectId; return rewriteObjectId;
} }
/*
* for now, event_object must be a single attribute
*/
static void
ValidateRule(int event_type,
char *eobj_string,
char *eslot_string,
Node *event_qual,
List **action,
int is_instead,
Oid event_attype)
{
if (((event_type == CMD_INSERT) || (event_type == CMD_DELETE)) &&
eslot_string)
{
elog(ERROR,
"rules not allowed for insert or delete events to an attribute");
}
#ifdef NOT_USED
/*---------
* on retrieve to class.attribute do instead nothing is converted to
* 'on retrieve to class.attribute do instead:
*
* retrieve (attribute = NULL)'
*
* this is also a terrible hack that works well -- glass
*---------
*/
if (is_instead && !*action && eslot_string && event_type == CMD_SELECT)
{
char *temp_buffer = (char *) palloc(strlen(template) + 80);
sprintf(temp_buffer, template, event_attype,
get_typlen(event_attype), eslot_string,
event_attype);
*action = (List *) stringToNode(temp_buffer);
pfree(temp_buffer);
}
#endif
}
void void
DefineQueryRewrite(RuleStmt *stmt) DefineQueryRewrite(RuleStmt *stmt)
{ {
CmdType event_type = stmt->event; RangeVar *event_obj = stmt->relation;
Attr *event_obj = stmt->object;
Node *event_qual = stmt->whereClause; Node *event_qual = stmt->whereClause;
CmdType event_type = stmt->event;
bool is_instead = stmt->instead; bool is_instead = stmt->instead;
List *action = stmt->actions; List *action = stmt->actions;
Relation event_relation; Relation event_relation;
Oid ev_relid; Oid ev_relid;
Oid ruleId; Oid ruleId;
char *eslot_string = NULL;
int event_attno; int event_attno;
Oid event_attype; Oid event_attype;
char *actionP, char *actionP,
@ -186,23 +140,6 @@ DefineQueryRewrite(RuleStmt *stmt)
event_relation = heap_openr(event_obj->relname, AccessExclusiveLock); event_relation = heap_openr(event_obj->relname, AccessExclusiveLock);
ev_relid = RelationGetRelid(event_relation); ev_relid = RelationGetRelid(event_relation);
/*
* The current rewrite handler is known to work on relation level
* rules only. And for SELECT events, it expects one non-nothing
* action that is instead and returns exactly a tuple of the rewritten
* relation. This restricts SELECT rules to views.
*
* Jan
*/
if (event_obj->attrs)
elog(ERROR, "attribute level rules currently not supported");
/*
* eslot_string = strVal(lfirst(event_obj->attrs));
*/
else
eslot_string = NULL;
/* /*
* No rule actions that modify OLD or NEW * No rule actions that modify OLD or NEW
*/ */
@ -358,21 +295,8 @@ DefineQueryRewrite(RuleStmt *stmt)
/* /*
* This rule is allowed - prepare to install it. * This rule is allowed - prepare to install it.
*/ */
if (eslot_string == NULL)
{
event_attno = -1; event_attno = -1;
event_attype = InvalidOid; event_attype = InvalidOid;
}
else
{
event_attno = attnameAttNum(event_relation, eslot_string);
event_attype = attnumTypeId(event_relation, event_attno);
}
/* fix bug about instead nothing */
ValidateRule(event_type, event_obj->relname,
eslot_string, event_qual, &action,
is_instead, event_attype);
/* /*
* We want the rule's table references to be checked as though by the * We want the rule's table references to be checked as though by the

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.62 2002/03/12 00:51:58 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.63 2002/03/21 16:01:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -573,9 +573,9 @@ getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr)
* they've been pushed down to the SELECT. * they've been pushed down to the SELECT.
*/ */
if (length(parsetree->rtable) >= 2 && if (length(parsetree->rtable) >= 2 &&
strcmp(rt_fetch(PRS2_OLD_VARNO, parsetree->rtable)->eref->relname, strcmp(rt_fetch(PRS2_OLD_VARNO, parsetree->rtable)->eref->aliasname,
"*OLD*") == 0 && "*OLD*") == 0 &&
strcmp(rt_fetch(PRS2_NEW_VARNO, parsetree->rtable)->eref->relname, strcmp(rt_fetch(PRS2_NEW_VARNO, parsetree->rtable)->eref->aliasname,
"*NEW*") == 0) "*NEW*") == 0)
return parsetree; return parsetree;
Assert(parsetree->jointree && IsA(parsetree->jointree, FromExpr)); Assert(parsetree->jointree && IsA(parsetree->jointree, FromExpr));
@ -589,9 +589,9 @@ getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr)
selectquery->commandType == CMD_SELECT)) selectquery->commandType == CMD_SELECT))
elog(ERROR, "getInsertSelectQuery: expected to find SELECT subquery"); elog(ERROR, "getInsertSelectQuery: expected to find SELECT subquery");
if (length(selectquery->rtable) >= 2 && if (length(selectquery->rtable) >= 2 &&
strcmp(rt_fetch(PRS2_OLD_VARNO, selectquery->rtable)->eref->relname, strcmp(rt_fetch(PRS2_OLD_VARNO, selectquery->rtable)->eref->aliasname,
"*OLD*") == 0 && "*OLD*") == 0 &&
strcmp(rt_fetch(PRS2_NEW_VARNO, selectquery->rtable)->eref->relname, strcmp(rt_fetch(PRS2_NEW_VARNO, selectquery->rtable)->eref->aliasname,
"*NEW*") == 0) "*NEW*") == 0)
{ {
if (subquery_ptr) if (subquery_ptr)

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.257 2002/03/19 16:10:48 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.258 2002/03/21 16:01:25 tgl Exp $
* *
* NOTES * NOTES
* this is the "main" module of the postgres backend and * this is the "main" module of the postgres backend and
@ -1722,7 +1722,7 @@ PostgresMain(int argc, char *argv[], const char *username)
if (!IsUnderPostmaster) if (!IsUnderPostmaster)
{ {
puts("\nPOSTGRES backend interactive interface "); puts("\nPOSTGRES backend interactive interface ");
puts("$Revision: 1.257 $ $Date: 2002/03/19 16:10:48 $\n"); puts("$Revision: 1.258 $ $Date: 2002/03/21 16:01:25 $\n");
} }
/* /*
@ -2216,6 +2216,10 @@ CreateCommandTag(Node *parsetree)
tag = "CREATE DOMAIN"; tag = "CREATE DOMAIN";
break; break;
case T_CreateSchemaStmt:
tag = "CREATE";
break;
case T_CreateStmt: case T_CreateStmt:
tag = "CREATE"; tag = "CREATE";
break; break;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.50 2002/03/06 06:10:10 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.51 2002/03/21 16:01:27 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -181,12 +181,12 @@ ProcessQuery(Query *parsetree,
*/ */
if (isRetrieveIntoPortal) if (isRetrieveIntoPortal)
{ {
intoName = parsetree->into; intoName = parsetree->into->relname;
portal = PreparePortal(intoName); portal = PreparePortal(intoName);
oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
parsetree = copyObject(parsetree); parsetree = copyObject(parsetree);
plan = copyObject(plan); plan = copyObject(plan);
intoName = parsetree->into; /* use copied name in QueryDesc */ intoName = parsetree->into->relname; /* use copied name in QueryDesc */
/* /*
* We stay in portal's memory context for now, so that query desc, * We stay in portal's memory context for now, so that query desc,

View File

@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.135 2002/03/20 19:44:35 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.136 2002/03/21 16:01:30 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -218,6 +218,14 @@ ProcessUtility(Node *parsetree,
/* /*
* relation and attribute manipulation * relation and attribute manipulation
*/ */
case T_CreateSchemaStmt:
{
CreateSchemaStmt *stmt = (CreateSchemaStmt *) parsetree;
CreateSchemaCommand(stmt);
}
break;
case T_CreateStmt: case T_CreateStmt:
DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION); DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION);
@ -226,19 +234,19 @@ ProcessUtility(Node *parsetree,
* secondary relation too. * secondary relation too.
*/ */
CommandCounterIncrement(); CommandCounterIncrement();
AlterTableCreateToastTable(((CreateStmt *) parsetree)->relname, AlterTableCreateToastTable(((CreateStmt *) parsetree)->relation->relname,
true); true);
break; break;
case T_DropStmt: case T_DropStmt:
{ {
DropStmt *stmt = (DropStmt *) parsetree; DropStmt *stmt = (DropStmt *) parsetree;
List *args = stmt->names; List *args = stmt->objects;
List *arg; List *arg;
foreach(arg, args) foreach(arg, args)
{ {
relname = strVal(lfirst(arg)); relname = ((RangeVar *) lfirst(arg))->relname;
switch (stmt->removeType) switch (stmt->removeType)
{ {
@ -299,7 +307,8 @@ ProcessUtility(Node *parsetree,
case T_TruncateStmt: case T_TruncateStmt:
{ {
TruncateRelation(((TruncateStmt *) parsetree)->relName); relname = ((TruncateStmt *) parsetree)->relation->relname;
TruncateRelation(relname);
} }
break; break;
@ -322,7 +331,7 @@ ProcessUtility(Node *parsetree,
if (stmt->direction != FROM) if (stmt->direction != FROM)
SetQuerySnapshot(); SetQuerySnapshot();
DoCopy(stmt->relname, DoCopy(stmt->relation->relname,
stmt->binary, stmt->binary,
stmt->oids, stmt->oids,
(bool) (stmt->direction == FROM), (bool) (stmt->direction == FROM),
@ -345,7 +354,7 @@ ProcessUtility(Node *parsetree,
{ {
RenameStmt *stmt = (RenameStmt *) parsetree; RenameStmt *stmt = (RenameStmt *) parsetree;
relname = stmt->relname; relname = stmt->relation->relname;
if (!allowSystemTableMods && IsSystemRelationName(relname)) if (!allowSystemTableMods && IsSystemRelationName(relname))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog", elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relname); relname);
@ -380,7 +389,7 @@ ProcessUtility(Node *parsetree,
renameatt(relname, /* relname */ renameatt(relname, /* relname */
stmt->column, /* old att name */ stmt->column, /* old att name */
stmt->newname, /* new att name */ stmt->newname, /* new att name */
interpretInhOption(stmt->inhOpt)); /* recursive? */ interpretInhOption(stmt->relation->inhOpt)); /* recursive? */
} }
} }
break; break;
@ -398,47 +407,47 @@ ProcessUtility(Node *parsetree,
switch (stmt->subtype) switch (stmt->subtype)
{ {
case 'A': /* ADD COLUMN */ case 'A': /* ADD COLUMN */
AlterTableAddColumn(stmt->relname, AlterTableAddColumn(stmt->relation->relname,
interpretInhOption(stmt->inhOpt), interpretInhOption((stmt->relation)->inhOpt),
(ColumnDef *) stmt->def); (ColumnDef *) stmt->def);
break; break;
case 'T': /* ALTER COLUMN DEFAULT */ case 'T': /* ALTER COLUMN DEFAULT */
AlterTableAlterColumnDefault(stmt->relname, AlterTableAlterColumnDefault(stmt->relation->relname,
interpretInhOption(stmt->inhOpt), interpretInhOption((stmt->relation)->inhOpt),
stmt->name, stmt->name,
stmt->def); stmt->def);
break; break;
case 'S': /* ALTER COLUMN STATISTICS */ case 'S': /* ALTER COLUMN STATISTICS */
case 'M': /* ALTER COLUMN STORAGE */ case 'M': /* ALTER COLUMN STORAGE */
AlterTableAlterColumnFlags(stmt->relname, AlterTableAlterColumnFlags(stmt->relation->relname,
interpretInhOption(stmt->inhOpt), interpretInhOption(stmt->relation->inhOpt),
stmt->name, stmt->name,
stmt->def, stmt->def,
&(stmt->subtype)); &(stmt->subtype));
break; break;
case 'D': /* DROP COLUMN */ case 'D': /* DROP COLUMN */
AlterTableDropColumn(stmt->relname, AlterTableDropColumn(stmt->relation->relname,
interpretInhOption(stmt->inhOpt), interpretInhOption(stmt->relation->inhOpt),
stmt->name, stmt->name,
stmt->behavior); stmt->behavior);
break; break;
case 'C': /* ADD CONSTRAINT */ case 'C': /* ADD CONSTRAINT */
AlterTableAddConstraint(stmt->relname, AlterTableAddConstraint(stmt->relation->relname,
interpretInhOption(stmt->inhOpt), interpretInhOption(stmt->relation->inhOpt),
(List *) stmt->def); (List *) stmt->def);
break; break;
case 'X': /* DROP CONSTRAINT */ case 'X': /* DROP CONSTRAINT */
AlterTableDropConstraint(stmt->relname, AlterTableDropConstraint(stmt->relation->relname,
interpretInhOption(stmt->inhOpt), interpretInhOption(stmt->relation->inhOpt),
stmt->name, stmt->name,
stmt->behavior); stmt->behavior);
break; break;
case 'E': /* CREATE TOAST TABLE */ case 'E': /* CREATE TOAST TABLE */
AlterTableCreateToastTable(stmt->relname, AlterTableCreateToastTable(stmt->relation->relname,
false); false);
break; break;
case 'U': /* ALTER OWNER */ case 'U': /* ALTER OWNER */
AlterTableOwner(stmt->relname, AlterTableOwner(stmt->relation->relname,
stmt->name); stmt->name);
break; break;
default: /* oops */ default: /* oops */
@ -487,7 +496,7 @@ ProcessUtility(Node *parsetree,
{ {
ViewStmt *stmt = (ViewStmt *) parsetree; ViewStmt *stmt = (ViewStmt *) parsetree;
DefineView(stmt->viewname, stmt->query); /* retrieve parsetree */ DefineView(stmt->view->relname, stmt->query); /* retrieve parsetree */
} }
break; break;
@ -499,14 +508,14 @@ ProcessUtility(Node *parsetree,
{ {
IndexStmt *stmt = (IndexStmt *) parsetree; IndexStmt *stmt = (IndexStmt *) parsetree;
relname = stmt->relname; relname = stmt->relation->relname;
if (!allowSystemTableMods && IsSystemRelationName(relname)) if (!allowSystemTableMods && IsSystemRelationName(relname))
elog(ERROR, "CREATE INDEX: relation \"%s\" is a system catalog", elog(ERROR, "CREATE INDEX: relation \"%s\" is a system catalog",
relname); relname);
if (!pg_ownercheck(GetUserId(), relname, RELNAME)) if (!pg_ownercheck(GetUserId(), relname, RELNAME))
elog(ERROR, "permission denied"); elog(ERROR, "permission denied");
DefineIndex(stmt->relname, /* relation name */ DefineIndex(stmt->relation->relname, /* relation */
stmt->idxname, /* index name */ stmt->idxname, /* index name */
stmt->accessMethod, /* am name */ stmt->accessMethod, /* am name */
stmt->indexParams, /* parameters */ stmt->indexParams, /* parameters */
@ -522,7 +531,7 @@ ProcessUtility(Node *parsetree,
RuleStmt *stmt = (RuleStmt *) parsetree; RuleStmt *stmt = (RuleStmt *) parsetree;
int aclcheck_result; int aclcheck_result;
relname = stmt->object->relname; relname = stmt->relation->relname;
aclcheck_result = pg_aclcheck(relname, GetUserId(), ACL_RULE); aclcheck_result = pg_aclcheck(relname, GetUserId(), ACL_RULE);
if (aclcheck_result != ACLCHECK_OK) if (aclcheck_result != ACLCHECK_OK)
elog(ERROR, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]); elog(ERROR, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]);
@ -603,7 +612,7 @@ ProcessUtility(Node *parsetree,
{ {
NotifyStmt *stmt = (NotifyStmt *) parsetree; NotifyStmt *stmt = (NotifyStmt *) parsetree;
Async_Notify(stmt->relname); Async_Notify(stmt->relation->relname);
} }
break; break;
@ -611,7 +620,7 @@ ProcessUtility(Node *parsetree,
{ {
ListenStmt *stmt = (ListenStmt *) parsetree; ListenStmt *stmt = (ListenStmt *) parsetree;
Async_Listen(stmt->relname, MyProcPid); Async_Listen(stmt->relation->relname, MyProcPid);
} }
break; break;
@ -619,7 +628,7 @@ ProcessUtility(Node *parsetree,
{ {
UnlistenStmt *stmt = (UnlistenStmt *) parsetree; UnlistenStmt *stmt = (UnlistenStmt *) parsetree;
Async_Unlisten(stmt->relname, MyProcPid); Async_Unlisten(stmt->relation->relname, MyProcPid);
} }
break; break;
@ -636,7 +645,7 @@ ProcessUtility(Node *parsetree,
{ {
ClusterStmt *stmt = (ClusterStmt *) parsetree; ClusterStmt *stmt = (ClusterStmt *) parsetree;
relname = stmt->relname; relname = stmt->relation->relname;
if (IsSystemRelationName(relname)) if (IsSystemRelationName(relname))
elog(ERROR, "CLUSTER: relation \"%s\" is a system catalog", elog(ERROR, "CLUSTER: relation \"%s\" is a system catalog",
relname); relname);
@ -712,7 +721,6 @@ ProcessUtility(Node *parsetree,
/* /*
* ******************************** DOMAIN statements **** * ******************************** DOMAIN statements ****
*
*/ */
case T_CreateDomainStmt: case T_CreateDomainStmt:
DefineDomain((CreateDomainStmt *) parsetree); DefineDomain((CreateDomainStmt *) parsetree);
@ -720,9 +728,7 @@ ProcessUtility(Node *parsetree,
/* /*
* ******************************** USER statements **** * ******************************** USER statements ****
*
*/ */
case T_CreateUserStmt: case T_CreateUserStmt:
CreateUser((CreateUserStmt *) parsetree); CreateUser((CreateUserStmt *) parsetree);
break; break;
@ -774,7 +780,7 @@ ProcessUtility(Node *parsetree,
switch (stmt->reindexType) switch (stmt->reindexType)
{ {
case INDEX: case INDEX:
relname = (char *) stmt->name; relname = (char *) stmt->relation->relname;
if (IsSystemRelationName(relname)) if (IsSystemRelationName(relname))
{ {
if (!allowSystemTableMods) if (!allowSystemTableMods)
@ -789,7 +795,7 @@ ProcessUtility(Node *parsetree,
ReindexIndex(relname, stmt->force); ReindexIndex(relname, stmt->force);
break; break;
case TABLE: case TABLE:
relname = (char *) stmt->name; relname = (char *) stmt->relation->relname;
if (!pg_ownercheck(GetUserId(), relname, RELNAME)) if (!pg_ownercheck(GetUserId(), relname, RELNAME))
elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]); elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
ReindexTable(relname, stmt->force); ReindexTable(relname, stmt->force);

View File

@ -3,7 +3,7 @@
* back to source text * back to source text
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.93 2002/03/12 00:51:59 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.94 2002/03/21 16:01:34 tgl Exp $
* *
* This software is copyrighted by Jan Wieck - Hamburg. * This software is copyrighted by Jan Wieck - Hamburg.
* *
@ -48,6 +48,7 @@
#include "catalog/pg_shadow.h" #include "catalog/pg_shadow.h"
#include "executor/spi.h" #include "executor/spi.h"
#include "lib/stringinfo.h" #include "lib/stringinfo.h"
#include "nodes/makefuncs.h"
#include "optimizer/clauses.h" #include "optimizer/clauses.h"
#include "optimizer/tlist.h" #include "optimizer/tlist.h"
#include "parser/keywords.h" #include "parser/keywords.h"
@ -659,8 +660,7 @@ deparse_context_for(char *relname, Oid relid)
rte->rtekind = RTE_RELATION; rte->rtekind = RTE_RELATION;
rte->relname = relname; rte->relname = relname;
rte->relid = relid; rte->relid = relid;
rte->eref = makeNode(Attr); rte->eref = makeAlias(relname, NIL);
rte->eref->relname = relname;
rte->inh = false; rte->inh = false;
rte->inFromCl = true; rte->inFromCl = true;
@ -755,9 +755,7 @@ deparse_context_for_subplan(const char *name, List *tlist,
rte->rtekind = RTE_SPECIAL; /* XXX */ rte->rtekind = RTE_SPECIAL; /* XXX */
rte->relname = pstrdup(name); rte->relname = pstrdup(name);
rte->relid = InvalidOid; rte->relid = InvalidOid;
rte->eref = makeNode(Attr); rte->eref = makeAlias(rte->relname, attrs);
rte->eref->relname = rte->relname;
rte->eref->attrs = attrs;
rte->inh = false; rte->inh = false;
rte->inFromCl = true; rte->inFromCl = true;
@ -1462,7 +1460,7 @@ get_utility_query_def(Query *query, deparse_context *context)
{ {
NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt; NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
appendStringInfo(buf, "NOTIFY %s", quote_identifier(stmt->relname)); appendStringInfo(buf, "NOTIFY %s", quote_identifier(stmt->relation->relname));
} }
else else
elog(ERROR, "get_utility_query_def: unexpected statement type"); elog(ERROR, "get_utility_query_def: unexpected statement type");
@ -1512,7 +1510,7 @@ get_names_for_var(Var *var, deparse_context *context,
if (rte->rtekind == RTE_JOIN && rte->alias == NULL) if (rte->rtekind == RTE_JOIN && rte->alias == NULL)
*refname = NULL; *refname = NULL;
else else
*refname = rte->eref->relname; *refname = rte->eref->aliasname;
if (var->varattno == InvalidAttrNumber) if (var->varattno == InvalidAttrNumber)
*attname = NULL; *attname = NULL;
@ -1758,12 +1756,11 @@ get_rule_expr(Node *node, deparse_context *context)
/* /*
* If the argument is simple enough, we could emit * If the argument is simple enough, we could emit
* arg.fieldname, but most cases where FieldSelect is used * arg.fieldname, but most cases where FieldSelect is used
* are *not* simple. For now, always use the projection- * are *not* simple. So, always use parenthesized syntax.
* function syntax.
*/ */
appendStringInfo(buf, "%s(", quote_identifier(fieldname)); appendStringInfoChar(buf, '(');
get_rule_expr(fselect->arg, context); get_rule_expr(fselect->arg, context);
appendStringInfoChar(buf, ')'); appendStringInfo(buf, ").%s", quote_identifier(fieldname));
} }
break; break;
@ -2302,9 +2299,9 @@ get_from_clause(Query *query, deparse_context *context)
if (!rte->inFromCl) if (!rte->inFromCl)
continue; continue;
if (strcmp(rte->eref->relname, "*NEW*") == 0) if (strcmp(rte->eref->aliasname, "*NEW*") == 0)
continue; continue;
if (strcmp(rte->eref->relname, "*OLD*") == 0) if (strcmp(rte->eref->aliasname, "*OLD*") == 0)
continue; continue;
} }
@ -2342,15 +2339,15 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
if (rte->alias != NULL) if (rte->alias != NULL)
{ {
appendStringInfo(buf, " %s", appendStringInfo(buf, " %s",
quote_identifier(rte->alias->relname)); quote_identifier(rte->alias->aliasname));
if (rte->alias->attrs != NIL) if (rte->alias->colnames != NIL)
{ {
List *col; List *col;
appendStringInfo(buf, "("); appendStringInfo(buf, "(");
foreach(col, rte->alias->attrs) foreach(col, rte->alias->colnames)
{ {
if (col != rte->alias->attrs) if (col != rte->alias->colnames)
appendStringInfo(buf, ", "); appendStringInfo(buf, ", ");
appendStringInfo(buf, "%s", appendStringInfo(buf, "%s",
quote_identifier(strVal(lfirst(col)))); quote_identifier(strVal(lfirst(col))));
@ -2420,15 +2417,15 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
if (j->alias != NULL) if (j->alias != NULL)
{ {
appendStringInfo(buf, " %s", appendStringInfo(buf, " %s",
quote_identifier(j->alias->relname)); quote_identifier(j->alias->aliasname));
if (j->alias->attrs != NIL) if (j->alias->colnames != NIL)
{ {
List *col; List *col;
appendStringInfo(buf, "("); appendStringInfo(buf, "(");
foreach(col, j->alias->attrs) foreach(col, j->alias->colnames)
{ {
if (col != j->alias->attrs) if (col != j->alias->colnames)
appendStringInfo(buf, ", "); appendStringInfo(buf, ", ");
appendStringInfo(buf, "%s", appendStringInfo(buf, "%s",
quote_identifier(strVal(lfirst(col)))); quote_identifier(strVal(lfirst(col))));

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: catversion.h,v 1.107 2002/03/20 19:44:48 tgl Exp $ * $Id: catversion.h,v 1.108 2002/03/21 16:01:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200203191 #define CATALOG_VERSION_NO 200203211
#endif #endif

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: command.h,v 1.33 2002/03/05 05:33:29 momjian Exp $ * $Id: command.h,v 1.34 2002/03/21 16:01:41 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -72,4 +72,9 @@ extern void AlterTableOwner(const char *relationName, const char *newOwnerName);
*/ */
extern void LockTableCommand(LockStmt *lockstmt); extern void LockTableCommand(LockStmt *lockstmt);
/*
* SCHEMA
*/
extern void CreateSchemaCommand(CreateSchemaStmt *parsetree);
#endif /* COMMAND_H */ #endif /* COMMAND_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: makefuncs.h,v 1.31 2002/03/20 19:45:01 tgl Exp $ * $Id: makefuncs.h,v 1.32 2002/03/21 16:01:43 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -44,7 +44,7 @@ extern Const *makeConst(Oid consttype,
extern Const *makeNullConst(Oid consttype); extern Const *makeNullConst(Oid consttype);
extern Attr *makeAttr(char *relname, char *attname); extern Alias *makeAlias(const char *aliasname, List *colnames);
extern RelabelType *makeRelabelType(Node *arg, Oid rtype, int32 rtypmod); extern RelabelType *makeRelabelType(Node *arg, Oid rtype, int32 rtypmod);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: nodes.h,v 1.101 2002/03/19 02:18:23 momjian Exp $ * $Id: nodes.h,v 1.102 2002/03/21 16:01:44 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -195,21 +195,24 @@ typedef enum NodeTag
T_DropGroupStmt, T_DropGroupStmt,
T_ReindexStmt, T_ReindexStmt,
T_CheckPointStmt, T_CheckPointStmt,
T_CreateSchemaStmt,
T_AlterDatabaseSetStmt, T_AlterDatabaseSetStmt,
T_AlterUserSetStmt, T_AlterUserSetStmt,
T_A_Expr = 700, T_A_Expr = 700,
T_Attr, T_ColumnRef,
T_A_Const, T_ParamRef,
T_ParamNo,
T_Ident, T_Ident,
T_A_Const,
T_FuncCall, T_FuncCall,
T_A_Indices, T_A_Indices,
T_ExprFieldSelect,
T_ResTarget, T_ResTarget,
T_TypeCast, T_TypeCast,
T_RangeSubselect,
T_SortGroupBy, T_SortGroupBy,
T_Alias,
T_RangeVar, T_RangeVar,
T_RangeSubselect,
T_TypeName, T_TypeName,
T_IndexElem, T_IndexElem,
T_ColumnDef, T_ColumnDef,

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: parsenodes.h,v 1.162 2002/03/20 19:45:02 tgl Exp $ * $Id: parsenodes.h,v 1.163 2002/03/21 16:01:46 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -49,10 +49,10 @@ typedef struct Query
* statement */ * statement */
int resultRelation; /* target relation (index into rtable) */ int resultRelation; /* target relation (index into rtable) */
char *into; /* portal (cursor) name */ struct RangeVar *into; /* target relation or portal (cursor)
* for portal just name is meaningful */
bool isPortal; /* is this a retrieve into portal? */ bool isPortal; /* is this a retrieve into portal? */
bool isBinary; /* binary portal? */ bool isBinary; /* binary portal? */
bool isTemp; /* is 'into' a temp table? */
bool hasAggs; /* has aggregates in tlist or havingQual */ bool hasAggs; /* has aggregates in tlist or havingQual */
bool hasSubLinks; /* has subquery SubLink */ bool hasSubLinks; /* has subquery SubLink */
@ -125,15 +125,30 @@ typedef struct TypeName
} TypeName; } TypeName;
/* /*
* ParamNo - specifies a parameter reference * ColumnRef - specifies a reference to a column, or possibly a whole tuple
*
* The "fields" list must be nonempty; its last component may be "*"
* instead of a field name. Subscripts are optional.
*/ */
typedef struct ParamNo typedef struct ColumnRef
{
NodeTag type;
List *fields; /* field names (list of Value strings) */
List *indirection; /* subscripts (list of A_Indices) */
} ColumnRef;
/*
* ParamRef - specifies a parameter reference
*
* The parameter could be qualified with field names and/or subscripts
*/
typedef struct ParamRef
{ {
NodeTag type; NodeTag type;
int number; /* the number of the parameter */ int number; /* the number of the parameter */
TypeName *typename; /* the typecast */ List *fields; /* field names (list of Value strings) */
List *indirection; /* array references */ List *indirection; /* subscripts (list of A_Indices) */
} ParamNo; } ParamRef;
/* /*
* A_Expr - binary expressions * A_Expr - binary expressions
@ -147,22 +162,6 @@ typedef struct A_Expr
Node *rexpr; /* right argument */ Node *rexpr; /* right argument */
} A_Expr; } A_Expr;
/*
* Attr -
* specifies an Attribute (ie. a Column); could have nested dots or
* array references.
*
*/
typedef struct Attr
{
NodeTag type;
char *relname; /* name of relation (can be "*") */
ParamNo *paramNo; /* or a parameter */
List *attrs; /* attributes (possibly nested); list of
* Values (strings) */
List *indirection; /* array refs (list of A_Indices') */
} Attr;
/* /*
* A_Const - a constant expression * A_Const - a constant expression
*/ */
@ -176,11 +175,11 @@ typedef struct A_Const
/* /*
* TypeCast - a CAST expression * TypeCast - a CAST expression
* *
* NOTE: for mostly historical reasons, A_Const and ParamNo parsenodes contain * NOTE: for mostly historical reasons, A_Const parsenodes contain
* room for a TypeName; we only generate a separate TypeCast node if the * room for a TypeName; we only generate a separate TypeCast node if the
* argument to be casted is neither of those kinds of nodes. In theory either * argument to be casted is not a constant. In theory either representation
* representation would work, but it is convenient (especially for A_Const) * would work, but it is convenient to have the target type immediately
* to have the target type immediately available. * available while resolving a constant's datatype.
*/ */
typedef struct TypeCast typedef struct TypeCast
{ {
@ -284,17 +283,13 @@ typedef struct ColumnDef
/* /*
* Ident - * Ident -
* an identifier (could be an attribute or a relation name). Depending * an unqualified identifier. This is currently used only in the context
* on the context at transformStmt time, the identifier is treated as * of column name lists.
* either a relation name (in which case, isRel will be set) or an
* attribute (in which case, it will be transformed into an Attr).
*/ */
typedef struct Ident typedef struct Ident
{ {
NodeTag type; NodeTag type;
char *name; /* its name */ char *name; /* its name */
List *indirection; /* array references */
bool isRel; /* is this a relation or a column? */
} Ident; } Ident;
/* /*
@ -324,6 +319,21 @@ typedef struct A_Indices
Node *uidx; Node *uidx;
} A_Indices; } A_Indices;
/*
* ExprFieldSelect - select a field and/or array element from an expression
*
* This is used in the raw parsetree to represent selection from an
* arbitrary expression (not a column or param reference). Either
* fields or indirection may be NIL if not used.
*/
typedef struct ExprFieldSelect
{
NodeTag type;
Node *arg; /* the thing being selected from */
List *fields; /* field names (list of Value strings) */
List *indirection; /* subscripts (list of A_Indices) */
} ExprFieldSelect;
/* /*
* ResTarget - * ResTarget -
* result target (used in target list of pre-transformed Parse trees) * result target (used in target list of pre-transformed Parse trees)
@ -358,15 +368,37 @@ typedef struct SortGroupBy
Node *node; /* Expression */ Node *node; /* Expression */
} SortGroupBy; } SortGroupBy;
/*
* Alias -
* specifies an alias for a range variable; the alias might also
* specify renaming of columns within the table.
*/
typedef struct Alias
{
NodeTag type;
char *aliasname; /* aliased rel name (never qualified) */
List *colnames; /* optional list of column aliases */
/* Note: colnames is a list of Value nodes (always strings) */
} Alias;
/* /*
* RangeVar - range variable, used in FROM clauses * RangeVar - range variable, used in FROM clauses
*
* Also used to represent table names in utility statements; there, the alias
* field is not used, and inhOpt shows whether to apply the operation
* recursively to child tables. In some contexts it is also useful to carry
* a TEMP table indication here.
*/ */
typedef struct RangeVar typedef struct RangeVar
{ {
NodeTag type; NodeTag type;
char *relname; /* the relation name */ char *catalogname; /* the catalog (database) name, or NULL */
InhOption inhOpt; /* expand rel by inheritance? */ char *schemaname; /* the schema name, or NULL */
Attr *name; /* optional table alias & column aliases */ char *relname; /* the relation/sequence name */
InhOption inhOpt; /* expand rel by inheritance?
* recursively act on children? */
bool istemp; /* is this a temp relation/sequence? */
Alias *alias; /* table alias & optional column aliases */
} RangeVar; } RangeVar;
/* /*
@ -376,7 +408,7 @@ typedef struct RangeSubselect
{ {
NodeTag type; NodeTag type;
Node *subquery; /* the untransformed sub-select clause */ Node *subquery; /* the untransformed sub-select clause */
Attr *name; /* table alias & optional column aliases */ Alias *alias; /* table alias & optional column aliases */
} RangeSubselect; } RangeSubselect;
/* /*
@ -437,7 +469,7 @@ typedef struct TargetEntry
* like outer joins and join-output-column aliasing.) Other special * like outer joins and join-output-column aliasing.) Other special
* RTE types also exist, as indicated by RTEKind. * RTE types also exist, as indicated by RTEKind.
* *
* alias is an Attr node representing the AS alias-clause attached to the * alias is an Alias node representing the AS alias-clause attached to the
* FROM expression, or NULL if no clause. * FROM expression, or NULL if no clause.
* *
* eref is the table reference name and column reference names (either * eref is the table reference name and column reference names (either
@ -489,7 +521,7 @@ typedef struct RangeTblEntry
*/ */
/* /*
* Fields valid for a plain relation or inh_relation RTE (else NULL/zero): * Fields valid for a plain relation RTE (else NULL/zero):
*/ */
char *relname; /* real name of the relation */ char *relname; /* real name of the relation */
Oid relid; /* OID of the relation */ Oid relid; /* OID of the relation */
@ -517,8 +549,8 @@ typedef struct RangeTblEntry
/* /*
* Fields valid in all RTEs: * Fields valid in all RTEs:
*/ */
Attr *alias; /* user-written alias clause, if any */ Alias *alias; /* user-written alias clause, if any */
Attr *eref; /* expanded reference names */ Alias *eref; /* expanded reference names */
bool inh; /* inheritance requested? */ bool inh; /* inheritance requested? */
bool inFromCl; /* present in FROM clause */ bool inFromCl; /* present in FROM clause */
bool checkForRead; /* check rel for read access */ bool checkForRead; /* check rel for read access */
@ -570,7 +602,7 @@ typedef SortClause GroupClause;
typedef struct InsertStmt typedef struct InsertStmt
{ {
NodeTag type; NodeTag type;
char *relname; /* relation to insert into */ RangeVar *relation; /* relation to insert into */
List *cols; /* optional: names of the target columns */ List *cols; /* optional: names of the target columns */
/* /*
@ -589,9 +621,8 @@ typedef struct InsertStmt
typedef struct DeleteStmt typedef struct DeleteStmt
{ {
NodeTag type; NodeTag type;
char *relname; /* relation to delete from */ RangeVar *relation; /* relation to delete from */
Node *whereClause; /* qualifications */ Node *whereClause; /* qualifications */
InhOption inhOpt; /* recursively act on children? */
} DeleteStmt; } DeleteStmt;
/* ---------------------- /* ----------------------
@ -601,11 +632,10 @@ typedef struct DeleteStmt
typedef struct UpdateStmt typedef struct UpdateStmt
{ {
NodeTag type; NodeTag type;
char *relname; /* relation to update */ RangeVar *relation; /* relation to update */
List *targetList; /* the target list (of ResTarget) */ List *targetList; /* the target list (of ResTarget) */
Node *whereClause; /* qualifications */ Node *whereClause; /* qualifications */
List *fromClause; /* the from clause */ List *fromClause; /* optional from clause for more tables */
InhOption inhOpt; /* recursively act on children? */
} UpdateStmt; } UpdateStmt;
/* ---------------------- /* ----------------------
@ -639,8 +669,7 @@ typedef struct SelectStmt
List *distinctClause; /* NULL, list of DISTINCT ON exprs, or List *distinctClause; /* NULL, list of DISTINCT ON exprs, or
* lcons(NIL,NIL) for all (SELECT * lcons(NIL,NIL) for all (SELECT
* DISTINCT) */ * DISTINCT) */
char *into; /* name of table (for select into table) */ RangeVar *into; /* target table (for select into table) */
bool istemp; /* into is a temp table? */
List *intoColNames; /* column names for into table */ List *intoColNames; /* column names for into table */
List *targetList; /* the target list (of ResTarget) */ List *targetList; /* the target list (of ResTarget) */
List *fromClause; /* the FROM clause */ List *fromClause; /* the FROM clause */
@ -703,6 +732,22 @@ typedef struct SetOperationStmt
* field in Query. * field in Query.
*****************************************************************************/ *****************************************************************************/
/* ----------------------
* Create Schema Statement
*
* NOTE: the schemaElts list contains raw parsetrees for component statements
* of the schema, such as CREATE TABLE, GRANT, etc. These are analyzed and
* executed after the schema itself is created.
* ----------------------
*/
typedef struct CreateSchemaStmt
{
NodeTag type;
char *schemaname; /* the name of the schema to create */
char *authid; /* the owner of the created schema */
List *schemaElts; /* schema components (list of parsenodes) */
} CreateSchemaStmt;
/* ---------------------- /* ----------------------
* Alter Table * Alter Table
* *
@ -725,8 +770,7 @@ typedef struct AlterTableStmt
* U = change owner * U = change owner
*------------ *------------
*/ */
char *relname; /* table to work on */ RangeVar *relation; /* table to work on */
InhOption inhOpt; /* recursively act on children? */
char *name; /* column or constraint name to act on, or char *name; /* column or constraint name to act on, or
* new owner */ * new owner */
Node *def; /* definition of new column or constraint */ Node *def; /* definition of new column or constraint */
@ -743,12 +787,12 @@ typedef struct GrantStmt
NodeTag type; NodeTag type;
bool is_grant; /* not revoke */ bool is_grant; /* not revoke */
int objtype; int objtype;
List *objects; /* list of names (as Value strings) */ List *objects; /* list of names (as Value strings)
* or relations (as RangeVar's) */
List *privileges; /* integer list of privilege codes */ List *privileges; /* integer list of privilege codes */
List *grantees; /* list of PrivGrantee nodes */ List *grantees; /* list of PrivGrantee nodes */
} GrantStmt; } GrantStmt;
typedef struct PrivGrantee typedef struct PrivGrantee
{ {
NodeTag type; NodeTag type;
@ -756,7 +800,6 @@ typedef struct PrivGrantee
char *groupname; char *groupname;
} PrivGrantee; } PrivGrantee;
typedef struct FuncWithArgs typedef struct FuncWithArgs
{ {
NodeTag type; NodeTag type;
@ -764,7 +807,6 @@ typedef struct FuncWithArgs
List *funcargs; /* list of Typename nodes */ List *funcargs; /* list of Typename nodes */
} FuncWithArgs; } FuncWithArgs;
/* This is only used internally in gram.y. */ /* This is only used internally in gram.y. */
typedef struct PrivTarget typedef struct PrivTarget
{ {
@ -773,7 +815,6 @@ typedef struct PrivTarget
List *objs; List *objs;
} PrivTarget; } PrivTarget;
/* ---------------------- /* ----------------------
* Close Portal Statement * Close Portal Statement
* ---------------------- * ----------------------
@ -792,7 +833,7 @@ typedef struct CopyStmt
{ {
NodeTag type; NodeTag type;
bool binary; /* is a binary copy? */ bool binary; /* is a binary copy? */
char *relname; /* the relation to copy */ RangeVar *relation; /* the relation to copy */
bool oids; /* copy oid's? */ bool oids; /* copy oid's? */
int direction; /* TO or FROM */ int direction; /* TO or FROM */
char *filename; /* if NULL, use stdin/stdout */ char *filename; /* if NULL, use stdin/stdout */
@ -813,12 +854,10 @@ typedef struct CopyStmt
typedef struct CreateStmt typedef struct CreateStmt
{ {
NodeTag type; NodeTag type;
char *relname; /* name of relation to create */ RangeVar *relation; /* relation to create */
List *tableElts; /* column definitions (list of ColumnDef) */ List *tableElts; /* column definitions (list of ColumnDef) */
List *inhRelnames; /* relations to inherit from (list of List *inhRelations; /* relations to inherit from */
* T_String Values) */
List *constraints; /* constraints (list of Constraint nodes) */ List *constraints; /* constraints (list of Constraint nodes) */
bool istemp; /* is this a temp table? */
bool hasoids; /* should it have OIDs? */ bool hasoids; /* should it have OIDs? */
} CreateStmt; } CreateStmt;
@ -886,7 +925,7 @@ typedef struct FkConstraint
{ {
NodeTag type; NodeTag type;
char *constr_name; /* Constraint name */ char *constr_name; /* Constraint name */
char *pktable_name; /* Primary key table name */ RangeVar *pktable; /* Primary key table */
List *fk_attrs; /* Attributes of foreign key */ List *fk_attrs; /* Attributes of foreign key */
List *pk_attrs; /* Corresponding attrs in PK table */ List *pk_attrs; /* Corresponding attrs in PK table */
char *match_type; /* FULL or PARTIAL */ char *match_type; /* FULL or PARTIAL */
@ -904,7 +943,7 @@ typedef struct CreateTrigStmt
{ {
NodeTag type; NodeTag type;
char *trigname; /* TRIGGER' name */ char *trigname; /* TRIGGER' name */
char *relname; /* triggered relation */ RangeVar *relation; /* triggered relation */
char *funcname; /* function to call (or NULL) */ char *funcname; /* function to call (or NULL) */
List *args; /* list of (T_String) Values or NULL */ List *args; /* list of (T_String) Values or NULL */
bool before; /* BEFORE/AFTER */ bool before; /* BEFORE/AFTER */
@ -920,14 +959,14 @@ typedef struct CreateTrigStmt
bool isconstraint; /* This is an RI trigger */ bool isconstraint; /* This is an RI trigger */
bool deferrable; /* [NOT] DEFERRABLE */ bool deferrable; /* [NOT] DEFERRABLE */
bool initdeferred; /* INITIALLY {DEFERRED|IMMEDIATE} */ bool initdeferred; /* INITIALLY {DEFERRED|IMMEDIATE} */
char *constrrelname; /* opposite relation */ RangeVar *constrrel; /* opposite relation */
} CreateTrigStmt; } CreateTrigStmt;
typedef struct DropTrigStmt typedef struct DropTrigStmt
{ {
NodeTag type; NodeTag type;
char *trigname; /* TRIGGER' name */ char *trigname; /* TRIGGER' name */
char *relname; /* triggered relation */ RangeVar *relation; /* triggered relation */
} DropTrigStmt; } DropTrigStmt;
/* ---------------------- /* ----------------------
@ -1014,8 +1053,7 @@ typedef struct DropGroupStmt
typedef struct CreateSeqStmt typedef struct CreateSeqStmt
{ {
NodeTag type; NodeTag type;
char *seqname; /* the relation to create */ RangeVar *sequence; /* the sequence to create */
bool istemp; /* is this a temp sequence? */
List *options; List *options;
} CreateSeqStmt; } CreateSeqStmt;
@ -1072,7 +1110,7 @@ typedef struct CreateDomainStmt
typedef struct DropStmt typedef struct DropStmt
{ {
NodeTag type; NodeTag type;
List *names; List *objects;
int removeType; int removeType;
int behavior; /* CASCADE or RESTRICT drop behavior */ int behavior; /* CASCADE or RESTRICT drop behavior */
} DropStmt; } DropStmt;
@ -1084,7 +1122,7 @@ typedef struct DropStmt
typedef struct TruncateStmt typedef struct TruncateStmt
{ {
NodeTag type; NodeTag type;
char *relName; /* relation to be truncated */ RangeVar *relation; /* relation to be truncated */
} TruncateStmt; } TruncateStmt;
/* ---------------------- /* ----------------------
@ -1095,6 +1133,8 @@ typedef struct CommentStmt
{ {
NodeTag type; NodeTag type;
int objtype; /* Object's type */ int objtype; /* Object's type */
char *objschema; /* Schema where object is defined,
* if object is schema specific */
char *objname; /* Name of the object */ char *objname; /* Name of the object */
char *objproperty; /* Property Id (such as column) */ char *objproperty; /* Property Id (such as column) */
List *objlist; /* Arguments for VAL objects */ List *objlist; /* Arguments for VAL objects */
@ -1132,7 +1172,7 @@ typedef struct IndexStmt
{ {
NodeTag type; NodeTag type;
char *idxname; /* name of the index */ char *idxname; /* name of the index */
char *relname; /* name of relation to index on */ RangeVar *relation; /* relation to build index on */
char *accessMethod; /* name of access method (eg. btree) */ char *accessMethod; /* name of access method (eg. btree) */
List *indexParams; /* a list of IndexElem */ List *indexParams; /* a list of IndexElem */
Node *whereClause; /* qualification (partial-index predicate) */ Node *whereClause; /* qualification (partial-index predicate) */
@ -1192,14 +1232,13 @@ typedef struct RemoveOperStmt
} RemoveOperStmt; } RemoveOperStmt;
/* ---------------------- /* ----------------------
* Alter Table Statement * Alter Table Rename Statement
* ---------------------- * ----------------------
*/ */
typedef struct RenameStmt typedef struct RenameStmt
{ {
NodeTag type; NodeTag type;
char *relname; /* relation to be altered */ RangeVar *relation; /* relation to be altered */
InhOption inhOpt; /* recursively act on children? */
char *column; /* if NULL, rename the relation name to char *column; /* if NULL, rename the relation name to
* the new name. Otherwise, rename this * the new name. Otherwise, rename this
* column name. */ * column name. */
@ -1213,10 +1252,10 @@ typedef struct RenameStmt
typedef struct RuleStmt typedef struct RuleStmt
{ {
NodeTag type; NodeTag type;
RangeVar *relation; /* relation the rule is for */
char *rulename; /* name of the rule */ char *rulename; /* name of the rule */
Node *whereClause; /* qualifications */ Node *whereClause; /* qualifications */
CmdType event; /* RETRIEVE */ CmdType event; /* SELECT, INSERT, etc */
struct Attr *object; /* object affected */
bool instead; /* is a 'do instead'? */ bool instead; /* is a 'do instead'? */
List *actions; /* the action statements */ List *actions; /* the action statements */
} RuleStmt; } RuleStmt;
@ -1228,7 +1267,7 @@ typedef struct RuleStmt
typedef struct NotifyStmt typedef struct NotifyStmt
{ {
NodeTag type; NodeTag type;
char *relname; /* relation to notify */ RangeVar *relation; /* qualified name to notify */
} NotifyStmt; } NotifyStmt;
/* ---------------------- /* ----------------------
@ -1238,7 +1277,7 @@ typedef struct NotifyStmt
typedef struct ListenStmt typedef struct ListenStmt
{ {
NodeTag type; NodeTag type;
char *relname; /* relation to listen on */ RangeVar *relation; /* qualified name to listen on */
} ListenStmt; } ListenStmt;
/* ---------------------- /* ----------------------
@ -1248,7 +1287,7 @@ typedef struct ListenStmt
typedef struct UnlistenStmt typedef struct UnlistenStmt
{ {
NodeTag type; NodeTag type;
char *relname; /* relation to unlisten on */ RangeVar *relation; /* qualified name to unlisten on, or '*' */
} UnlistenStmt; } UnlistenStmt;
/* ---------------------- /* ----------------------
@ -1268,7 +1307,7 @@ typedef struct TransactionStmt
typedef struct ViewStmt typedef struct ViewStmt
{ {
NodeTag type; NodeTag type;
char *viewname; /* name of the view */ RangeVar *view; /* the view to be created */
List *aliases; /* target column names */ List *aliases; /* target column names */
Query *query; /* the SQL statement */ Query *query; /* the SQL statement */
} ViewStmt; } ViewStmt;
@ -1283,7 +1322,6 @@ typedef struct LoadStmt
char *filename; /* file to load */ char *filename; /* file to load */
} LoadStmt; } LoadStmt;
/* ---------------------- /* ----------------------
* Createdb Statement * Createdb Statement
* ---------------------- * ----------------------
@ -1327,7 +1365,7 @@ typedef struct DropdbStmt
typedef struct ClusterStmt typedef struct ClusterStmt
{ {
NodeTag type; NodeTag type;
char *relname; /* relation being indexed */ RangeVar *relation; /* relation being indexed */
char *indexname; /* original index defined */ char *indexname; /* original index defined */
} ClusterStmt; } ClusterStmt;
@ -1346,8 +1384,7 @@ typedef struct VacuumStmt
bool analyze; /* do ANALYZE step */ bool analyze; /* do ANALYZE step */
bool freeze; /* early-freeze option */ bool freeze; /* early-freeze option */
bool verbose; /* print progress info */ bool verbose; /* print progress info */
char *vacrel; /* name of single table to process, or RangeVar *relation; /* single table to process, or NULL */
* NULL */
List *va_cols; /* list of column names, or NIL for all */ List *va_cols; /* list of column names, or NIL for all */
} VacuumStmt; } VacuumStmt;
@ -1413,7 +1450,7 @@ typedef struct VariableResetStmt
typedef struct LockStmt typedef struct LockStmt
{ {
NodeTag type; NodeTag type;
List *rellist; /* relations to lock */ List *relations; /* relations to lock */
int mode; /* lock mode */ int mode; /* lock mode */
} LockStmt; } LockStmt;
@ -1436,7 +1473,8 @@ typedef struct ReindexStmt
{ {
NodeTag type; NodeTag type;
int reindexType; /* INDEX|TABLE|DATABASE */ int reindexType; /* INDEX|TABLE|DATABASE */
const char *name; /* name to reindex */ RangeVar *relation; /* Table or index to reindex */
const char *name; /* name of database to reindex */
bool force; bool force;
bool all; bool all;
} ReindexStmt; } ReindexStmt;

View File

@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: primnodes.h,v 1.58 2002/03/12 00:52:02 tgl Exp $ * $Id: primnodes.h,v 1.59 2002/03/21 16:01:48 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -508,7 +508,7 @@ typedef struct RangeTblRef
* If he writes ON() then only "quals" is set. Note that NATURAL/USING * If he writes ON() then only "quals" is set. Note that NATURAL/USING
* are not equivalent to ON() since they also affect the output column list. * are not equivalent to ON() since they also affect the output column list.
* *
* alias is an Attr node representing the AS alias-clause attached to the * alias is an Alias node representing the AS alias-clause attached to the
* join expression, or NULL if no clause. NB: presence or absence of the * join expression, or NULL if no clause. NB: presence or absence of the
* alias has a critical impact on semantics, because a join with an alias * alias has a critical impact on semantics, because a join with an alias
* restricts visibility of the tables/columns inside it. * restricts visibility of the tables/columns inside it.
@ -527,7 +527,7 @@ typedef struct JoinExpr
Node *rarg; /* right subtree */ Node *rarg; /* right subtree */
List *using; /* USING clause, if any (list of String) */ List *using; /* USING clause, if any (list of String) */
Node *quals; /* qualifiers on join, if any */ Node *quals; /* qualifiers on join, if any */
struct Attr *alias; /* user-written alias clause, if any */ struct Alias *alias; /* user-written alias clause, if any */
int rtindex; /* RT index assigned for join */ int rtindex; /* RT index assigned for join */
} JoinExpr; } JoinExpr;

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: analyze.h,v 1.18 2001/11/05 17:46:34 momjian Exp $ * $Id: analyze.h,v 1.19 2002/03/21 16:01:53 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -16,6 +16,7 @@
#include "parser/parse_node.h" #include "parser/parse_node.h"
extern List *parse_analyze(Node *parseTree, ParseState *parentParseState); extern List *parse_analyze(Node *parseTree, ParseState *parentParseState);
extern List *analyzeCreateSchemaStmt(CreateSchemaStmt *stmt);
extern void CheckSelectForUpdate(Query *qry); extern void CheckSelectForUpdate(Query *qry);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: parse_agg.h,v 1.20 2001/11/05 17:46:34 momjian Exp $ * $Id: parse_agg.h,v 1.21 2002/03/21 16:01:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -19,8 +19,7 @@
extern void AddAggToParseState(ParseState *pstate, Aggref *aggref); extern void AddAggToParseState(ParseState *pstate, Aggref *aggref);
extern void parseCheckAggregates(ParseState *pstate, Query *qry, Node *qual); extern void parseCheckAggregates(ParseState *pstate, Query *qry, Node *qual);
extern Aggref *ParseAgg(ParseState *pstate, char *aggname, Oid basetype, extern Aggref *ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
List *args, bool agg_star, bool agg_distinct, List *args, bool agg_star, bool agg_distinct);
int precedence);
extern void agg_error(char *caller, char *aggname, Oid basetypeID); extern void agg_error(char *caller, char *aggname, Oid basetypeID);
#endif /* PARSE_AGG_H */ #endif /* PARSE_AGG_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: parse_expr.h,v 1.25 2001/11/05 17:46:34 momjian Exp $ * $Id: parse_expr.h,v 1.26 2002/03/21 16:01:59 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -16,13 +16,12 @@
#include "parser/parse_node.h" #include "parser/parse_node.h"
#define EXPR_COLUMN_FIRST 1
#define EXPR_RELATION_FIRST 2
/* GUC parameters */
extern int max_expr_depth; extern int max_expr_depth;
extern bool Transform_null_equals; extern bool Transform_null_equals;
extern Node *transformExpr(ParseState *pstate, Node *expr, int precedence); extern Node *transformExpr(ParseState *pstate, Node *expr);
extern Oid exprType(Node *expr); extern Oid exprType(Node *expr);
extern int32 exprTypmod(Node *expr); extern int32 exprTypmod(Node *expr);
extern bool exprIsLengthCoercion(Node *expr, int32 *coercedTypmod); extern bool exprIsLengthCoercion(Node *expr, int32 *coercedTypmod);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: parse_func.h,v 1.35 2001/11/05 17:46:35 momjian Exp $ * $Id: parse_func.h,v 1.36 2002/03/21 16:02:01 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -47,12 +47,9 @@ typedef enum
} FuncDetailCode; } FuncDetailCode;
extern Node *ParseNestedFuncOrColumn(ParseState *pstate, Attr *attr,
int precedence);
extern Node *ParseFuncOrColumn(ParseState *pstate, extern Node *ParseFuncOrColumn(ParseState *pstate,
char *funcname, List *fargs, char *funcname, List *fargs,
bool agg_star, bool agg_distinct, bool agg_star, bool agg_distinct, bool is_column);
int precedence);
extern FuncDetailCode func_get_detail(char *funcname, List *fargs, extern FuncDetailCode func_get_detail(char *funcname, List *fargs,
int nargs, Oid *argtypes, int nargs, Oid *argtypes,

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: parse_relation.h,v 1.29 2002/03/12 00:52:04 tgl Exp $ * $Id: parse_relation.h,v 1.30 2002/03/21 16:02:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -29,12 +29,12 @@ extern Node *qualifiedNameToVar(ParseState *pstate, char *refname,
char *colname, bool implicitRTEOK); char *colname, bool implicitRTEOK);
extern RangeTblEntry *addRangeTableEntry(ParseState *pstate, extern RangeTblEntry *addRangeTableEntry(ParseState *pstate,
char *relname, char *relname,
Attr *alias, Alias *alias,
bool inh, bool inh,
bool inFromCl); bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForSubquery(ParseState *pstate, extern RangeTblEntry *addRangeTableEntryForSubquery(ParseState *pstate,
Query *subquery, Query *subquery,
Attr *alias, Alias *alias,
bool inFromCl); bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForJoin(ParseState *pstate, extern RangeTblEntry *addRangeTableEntryForJoin(ParseState *pstate,
List *colnames, List *colnames,
@ -43,7 +43,7 @@ extern RangeTblEntry *addRangeTableEntryForJoin(ParseState *pstate,
List *coltypmods, List *coltypmods,
List *leftcols, List *leftcols,
List *rightcols, List *rightcols,
Attr *alias, Alias *alias,
bool inFromCl); bool inFromCl);
extern void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, extern void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte,
bool addToJoinList, bool addToNameSpace); bool addToJoinList, bool addToNameSpace);

View File

@ -396,7 +396,7 @@ drop table atacc1;
create table atacc1 ( test int ); create table atacc1 ( test int );
-- add a check constraint (fails) -- add a check constraint (fails)
alter table atacc1 add constraint atacc_test1 check (test1>3); alter table atacc1 add constraint atacc_test1 check (test1>3);
ERROR: Attribute 'test1' not found ERROR: Attribute "test1" not found
drop table atacc1; drop table atacc1;
-- something a little more complicated -- something a little more complicated
create table atacc1 ( test int, test2 int, test3 int); create table atacc1 ( test int, test2 int, test3 int);

View File

@ -22,19 +22,19 @@ select * from nonesuch;
ERROR: parser: parse error at or near "select" ERROR: parser: parse error at or near "select"
-- bad name in target list -- bad name in target list
select nonesuch from pg_database; select nonesuch from pg_database;
ERROR: Attribute 'nonesuch' not found ERROR: Attribute "nonesuch" not found
-- bad attribute name on lhs of operator -- bad attribute name on lhs of operator
select * from pg_database where nonesuch = pg_database.datname; select * from pg_database where nonesuch = pg_database.datname;
ERROR: Attribute 'nonesuch' not found ERROR: Attribute "nonesuch" not found
-- bad attribute name on rhs of operator -- bad attribute name on rhs of operator
select * from pg_database where pg_database.datname = nonesuch; select * from pg_database where pg_database.datname = nonesuch;
ERROR: Attribute 'nonesuch' not found ERROR: Attribute "nonesuch" not found
-- bad select distinct on syntax, distinct attribute missing -- bad select distinct on syntax, distinct attribute missing
select distinct on (foobar) from pg_database; select distinct on (foobar) from pg_database;
ERROR: parser: parse error at or near "from" ERROR: parser: parse error at or near "from"
-- bad select distinct on syntax, distinct attribute not in target list -- bad select distinct on syntax, distinct attribute not in target list
select distinct on (foobar) * from pg_database; select distinct on (foobar) * from pg_database;
ERROR: Attribute 'foobar' not found ERROR: Attribute "foobar" not found
-- --
-- DELETE -- DELETE

View File

@ -1177,7 +1177,7 @@ drop rule foorule;
-- this should fail because f1 is not exposed for unqualified reference: -- this should fail because f1 is not exposed for unqualified reference:
create rule foorule as on insert to foo where f1 < 100 create rule foorule as on insert to foo where f1 < 100
do instead insert into foo2 values (f1); do instead insert into foo2 values (f1);
ERROR: Attribute 'f1' not found ERROR: Attribute "f1" not found
-- this is the correct way: -- this is the correct way:
create rule foorule as on insert to foo where f1 < 100 create rule foorule as on insert to foo where f1 < 100
do instead insert into foo2 values (new.f1); do instead insert into foo2 values (new.f1);

View File

@ -406,7 +406,7 @@ ORDER BY q2,q1;
-- This should fail, because q2 isn't a name of an EXCEPT output column -- This should fail, because q2 isn't a name of an EXCEPT output column
SELECT q1 FROM int8_tbl EXCEPT SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1; SELECT q1 FROM int8_tbl EXCEPT SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1;
ERROR: Attribute 'q2' not found ERROR: Attribute "q2" not found
-- But this should work: -- But this should work:
SELECT q1 FROM int8_tbl EXCEPT (((SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1))); SELECT q1 FROM int8_tbl EXCEPT (((SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1)));
q1 q1

View File

@ -170,44 +170,44 @@ SELECT class, aa, a FROM a_star*;
-- joe and sally play basketball, and -- joe and sally play basketball, and
-- everyone else does nothing. -- everyone else does nothing.
-- --
SELECT p.name, p.hobbies.name FROM ONLY person p; SELECT p.name, name(p.hobbies) FROM ONLY person p;
-- --
-- as above, but jeff also does post_hacking. -- as above, but jeff also does post_hacking.
-- --
SELECT p.name, p.hobbies.name FROM person* p; SELECT p.name, name(p.hobbies) FROM person* p;
-- --
-- the next two queries demonstrate how functions generate bogus duplicates. -- the next two queries demonstrate how functions generate bogus duplicates.
-- this is a "feature" .. -- this is a "feature" ..
-- --
SELECT DISTINCT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r; SELECT DISTINCT hobbies_r.name, name(hobbies_r.equipment) FROM hobbies_r;
SELECT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r; SELECT hobbies_r.name, (hobbies_r.equipment).name FROM hobbies_r;
-- --
-- mike needs advil and peet's coffee, -- mike needs advil and peet's coffee,
-- joe and sally need hightops, and -- joe and sally need hightops, and
-- everyone else is fine. -- everyone else is fine.
-- --
SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM ONLY person p; SELECT p.name, name(p.hobbies), name(equipment(p.hobbies)) FROM ONLY person p;
-- --
-- as above, but jeff needs advil and peet's coffee as well. -- as above, but jeff needs advil and peet's coffee as well.
-- --
SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM person* p; SELECT p.name, name(p.hobbies), name(equipment(p.hobbies)) FROM person* p;
-- --
-- just like the last two, but make sure that the target list fixup and -- just like the last two, but make sure that the target list fixup and
-- unflattening is being done correctly. -- unflattening is being done correctly.
-- --
SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM ONLY person p; SELECT name(equipment(p.hobbies)), p.name, name(p.hobbies) FROM ONLY person p;
SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM person* p; SELECT (p.hobbies).equipment.name, p.name, name(p.hobbies) FROM person* p;
SELECT p.hobbies.equipment.name, p.hobbies.name, p.name FROM ONLY person p; SELECT (p.hobbies).equipment.name, name(p.hobbies), p.name FROM ONLY person p;
SELECT p.hobbies.equipment.name, p.hobbies.name, p.name FROM person* p; SELECT name(equipment(p.hobbies)), name(p.hobbies), p.name FROM person* p;
SELECT user_relns() AS user_relns SELECT user_relns() AS user_relns
ORDER BY user_relns; ORDER BY user_relns;

View File

@ -442,7 +442,7 @@ SELECT class, aa, a FROM a_star*;
-- joe and sally play basketball, and -- joe and sally play basketball, and
-- everyone else does nothing. -- everyone else does nothing.
-- --
SELECT p.name, p.hobbies.name FROM ONLY person p; SELECT p.name, name(p.hobbies) FROM ONLY person p;
name | name name | name
-------+------------- -------+-------------
mike | posthacking mike | posthacking
@ -453,7 +453,7 @@ SELECT p.name, p.hobbies.name FROM ONLY person p;
-- --
-- as above, but jeff also does post_hacking. -- as above, but jeff also does post_hacking.
-- --
SELECT p.name, p.hobbies.name FROM person* p; SELECT p.name, name(p.hobbies) FROM person* p;
name | name name | name
-------+------------- -------+-------------
mike | posthacking mike | posthacking
@ -466,7 +466,7 @@ SELECT p.name, p.hobbies.name FROM person* p;
-- the next two queries demonstrate how functions generate bogus duplicates. -- the next two queries demonstrate how functions generate bogus duplicates.
-- this is a "feature" .. -- this is a "feature" ..
-- --
SELECT DISTINCT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r; SELECT DISTINCT hobbies_r.name, name(hobbies_r.equipment) FROM hobbies_r;
name | name name | name
-------------+--------------- -------------+---------------
basketball | hightops basketball | hightops
@ -475,7 +475,7 @@ SELECT DISTINCT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r;
skywalking | guts skywalking | guts
(4 rows) (4 rows)
SELECT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r; SELECT hobbies_r.name, (hobbies_r.equipment).name FROM hobbies_r;
name | name name | name
-------------+--------------- -------------+---------------
posthacking | advil posthacking | advil
@ -492,7 +492,7 @@ SELECT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r;
-- joe and sally need hightops, and -- joe and sally need hightops, and
-- everyone else is fine. -- everyone else is fine.
-- --
SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM ONLY person p; SELECT p.name, name(p.hobbies), name(equipment(p.hobbies)) FROM ONLY person p;
name | name | name name | name | name
-------+-------------+--------------- -------+-------------+---------------
mike | posthacking | advil mike | posthacking | advil
@ -504,7 +504,7 @@ SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM ONLY person p;
-- --
-- as above, but jeff needs advil and peet's coffee as well. -- as above, but jeff needs advil and peet's coffee as well.
-- --
SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM person* p; SELECT p.name, name(p.hobbies), name(equipment(p.hobbies)) FROM person* p;
name | name | name name | name | name
-------+-------------+--------------- -------+-------------+---------------
mike | posthacking | advil mike | posthacking | advil
@ -519,7 +519,7 @@ SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM person* p;
-- just like the last two, but make sure that the target list fixup and -- just like the last two, but make sure that the target list fixup and
-- unflattening is being done correctly. -- unflattening is being done correctly.
-- --
SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM ONLY person p; SELECT name(equipment(p.hobbies)), p.name, name(p.hobbies) FROM ONLY person p;
name | name | name name | name | name
---------------+-------+------------- ---------------+-------+-------------
advil | mike | posthacking advil | mike | posthacking
@ -528,7 +528,7 @@ SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM ONLY person p;
hightops | sally | basketball hightops | sally | basketball
(4 rows) (4 rows)
SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM person* p; SELECT (p.hobbies).equipment.name, p.name, name(p.hobbies) FROM person* p;
name | name | name name | name | name
---------------+-------+------------- ---------------+-------+-------------
advil | mike | posthacking advil | mike | posthacking
@ -539,7 +539,7 @@ SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM person* p;
peet's coffee | jeff | posthacking peet's coffee | jeff | posthacking
(6 rows) (6 rows)
SELECT p.hobbies.equipment.name, p.hobbies.name, p.name FROM ONLY person p; SELECT (p.hobbies).equipment.name, name(p.hobbies), p.name FROM ONLY person p;
name | name | name name | name | name
---------------+-------------+------- ---------------+-------------+-------
advil | posthacking | mike advil | posthacking | mike
@ -548,7 +548,7 @@ SELECT p.hobbies.equipment.name, p.hobbies.name, p.name FROM ONLY person p;
hightops | basketball | sally hightops | basketball | sally
(4 rows) (4 rows)
SELECT p.hobbies.equipment.name, p.hobbies.name, p.name FROM person* p; SELECT name(equipment(p.hobbies)), name(p.hobbies), p.name FROM person* p;
name | name | name name | name | name
---------------+-------------+------- ---------------+-------------+-------
advil | posthacking | mike advil | posthacking | mike