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">
@ -306,7 +306,8 @@ CREATE FUNCTION new_emp() RETURNS EMP AS '
<para>
The target list order must be exactly the same as
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>
</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
composite types can be used. Briefly, when calling a function that
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
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>
SELECT name(new_emp());
</programlisting>
@ -343,13 +369,6 @@ SELECT name(new_emp());
</screen>
</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>
--
-- this is the same as:
@ -367,19 +386,6 @@ SELECT name(EMP) AS youngster
</screen>
</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>
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

View File

@ -8,7 +8,7 @@
*
*
* 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
* See acl.h.
@ -200,7 +200,7 @@ ExecuteGrantStmt_Table(GrantStmt *stmt)
foreach(i, stmt->objects)
{
char *relname = strVal(lfirst(i));
char *relname = ((RangeVar *) lfirst(i))->relname;
Relation relation;
HeapTuple tuple;
Form_pg_class pg_class_tuple;

View File

@ -8,7 +8,7 @@
*
*
* 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
@ -1728,7 +1728,7 @@ AddRelationRawConstraints(Relation rel,
/*
* 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.
@ -1863,7 +1863,7 @@ cookDefault(ParseState *pstate,
/*
* 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.

View File

@ -8,7 +8,7 @@
*
*
* 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
* The PerformAddAttribute() code, like most of the relation
@ -33,7 +33,7 @@
#include "catalog/pg_type.h"
#include "commands/command.h"
#include "commands/trigger.h"
#include "commands/defrem.h" /* For add constraint unique, primary */
#include "commands/defrem.h"
#include "executor/execdefs.h"
#include "executor/executor.h"
#include "miscadmin.h"
@ -44,7 +44,8 @@
#include "parser/parse_expr.h"
#include "parser/parse_oper.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/builtins.h"
#include "utils/fmgroids.h"
@ -1279,8 +1280,7 @@ AlterTableAddConstraint(char *relationName,
* Convert the A_EXPR in raw_expr into an
* EXPR
*/
expr = transformExpr(pstate, constr->raw_expr,
EXPR_COLUMN_FIRST);
expr = transformExpr(pstate, constr->raw_expr);
/*
* Make sure it yields a boolean result.
@ -1366,7 +1366,7 @@ AlterTableAddConstraint(char *relationName,
List *list;
int count;
if (is_temp_rel_name(fkconstraint->pktable_name) &&
if (is_temp_rel_name(fkconstraint->pktable->relname) &&
!is_temp_rel_name(relationName))
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.
*/
pkrel = heap_openr(fkconstraint->pktable_name, AccessExclusiveLock);
pkrel = heap_openr(fkconstraint->pktable->relname, AccessExclusiveLock);
if (pkrel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "referenced table \"%s\" not a relation",
fkconstraint->pktable_name);
fkconstraint->pktable->relname);
heap_close(pkrel, NoLock);
/*
@ -1417,7 +1417,7 @@ AlterTableAddConstraint(char *relationName,
else
trig.tgargs[0] = "<unknown>";
trig.tgargs[1] = (char *) relationName;
trig.tgargs[2] = fkconstraint->pktable_name;
trig.tgargs[2] = fkconstraint->pktable->relname;
trig.tgargs[3] = fkconstraint->match_type;
count = 4;
foreach(list, fkconstraint->fk_attrs)
@ -1936,9 +1936,10 @@ LockTableCommand(LockStmt *lockstmt)
* 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;
Relation rel;
@ -1962,3 +1963,94 @@ LockTableCommand(LockStmt *lockstmt)
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
* $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,
* 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
@ -82,8 +82,9 @@ DefineRelation(CreateStmt *stmt, char relkind)
* Look up inheritance ancestors and generate relation schema,
* including inherited attributes.
*/
schema = MergeAttributes(schema, stmt->inhRelnames, stmt->istemp,
&inheritOids, &old_constraints, &parentHasOids);
schema = MergeAttributes(schema, stmt->inhRelations,
stmt->relation->istemp,
&inheritOids, &old_constraints, &parentHasOids);
numberOfAttributes = length(schema);
if (numberOfAttributes <= 0)
@ -147,7 +148,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
relationId = heap_create_with_catalog(relname, descriptor,
relkind,
stmt->hasoids || parentHasOids,
stmt->istemp,
stmt->relation->istemp,
allowSystemTableMods);
StoreCatalogInheritance(relationId, inheritOids);
@ -414,6 +415,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
/*
* Reject duplicate names in the list of parents, too.
*
* XXX needs to be smarter about schema-qualified table names.
*/
foreach(entry, supers)
{
@ -421,9 +424,10 @@ MergeAttributes(List *schema, List *supers, bool istemp,
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",
strVal(lfirst(entry)));
((RangeVar *) lfirst(entry))->relname);
}
}
@ -435,7 +439,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
child_attno = 0;
foreach(entry, supers)
{
char *name = strVal(lfirst(entry));
char *name = ((RangeVar *) lfirst(entry))->relname;
Relation relation;
TupleDesc tupleDesc;
TupleConstr *constr;

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* 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",
stringStringInfo(rte->relname));
if (strcmp(rte->eref->relname, rte->relname) != 0)
if (strcmp(rte->eref->aliasname, rte->relname) != 0)
appendStringInfo(str, " %s",
stringStringInfo(rte->eref->relname));
stringStringInfo(rte->eref->aliasname));
}
break;
case T_SubqueryScan:
@ -322,7 +322,7 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es)
es->rtable);
appendStringInfo(str, " %s",
stringStringInfo(rte->eref->relname));
stringStringInfo(rte->eref->aliasname));
}
break;
default:

View File

@ -8,7 +8,7 @@
*
*
* 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:
typnam->name = "name";
coldef->colname = "sequence_name";
namestrcpy(&name, seq->seqname);
namestrcpy(&name, seq->sequence->relname);
value[i - 1] = NameGetDatum(&name);
break;
case SEQ_COL_LASTVAL:
@ -170,15 +170,14 @@ DefineSequence(CreateSeqStmt *seq)
stmt->tableElts = lappend(stmt->tableElts, coldef);
}
stmt->relname = seq->seqname;
stmt->inhRelnames = NIL;
stmt->relation = seq->sequence;
stmt->inhRelations = NIL;
stmt->constraints = NIL;
stmt->istemp = seq->istemp;
stmt->hasoids = false;
DefineRelation(stmt, RELKIND_SEQUENCE);
rel = heap_openr(seq->seqname, AccessExclusiveLock);
rel = heap_openr(seq->sequence->relname, AccessExclusiveLock);
tupDesc = RelationGetDescr(rel);
/* 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
*
* 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 = "";
Oid constrrelid = InvalidOid;
if (!allowSystemTableMods && IsSystemRelationName(stmt->relname))
elog(ERROR, "CreateTrigger: can't create trigger for system relation %s", stmt->relname);
if (!allowSystemTableMods && IsSystemRelationName(stmt->relation->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)
!= ACLCHECK_OK)
elog(ERROR, "permission denied");
@ -89,7 +90,7 @@ CreateTrigger(CreateTrigStmt *stmt)
stmt->trigname = constrtrigname;
sprintf(constrtrigname, "RI_ConstraintTrigger_%u", newoid());
if (strcmp(stmt->constrrelname, "") == 0)
if (stmt->constrrel == NULL)
constrrelid = InvalidOid;
else
{
@ -97,17 +98,17 @@ CreateTrigger(CreateTrigStmt *stmt)
* NoLock is probably sufficient here, since we're only
* interested in getting the relation's OID...
*/
rel = heap_openr(stmt->constrrelname, NoLock);
rel = heap_openr(stmt->constrrel->relname, NoLock);
constrrelid = rel->rd_id;
heap_close(rel, NoLock);
}
}
rel = heap_openr(stmt->relname, AccessExclusiveLock);
rel = heap_openr(stmt->relation->relname, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "CreateTrigger: relation \"%s\" is not a table",
stmt->relname);
stmt->relation->relname);
TRIGGER_CLEAR_TYPE(tgtype);
if (stmt->before)
@ -159,7 +160,7 @@ CreateTrigger(CreateTrigStmt *stmt)
if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0)
elog(ERROR, "CreateTrigger: trigger %s already defined on relation %s",
stmt->trigname, stmt->relname);
stmt->trigname, stmt->relation->relname);
found++;
}
systable_endscan(tgscan);
@ -283,11 +284,11 @@ CreateTrigger(CreateTrigStmt *stmt)
*/
pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheCopy(RELNAME,
PointerGetDatum(stmt->relname),
PointerGetDatum(stmt->relation->relname),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "CreateTrigger: relation %s not found in pg_class",
stmt->relname);
stmt->relation->relname);
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;
simple_heap_update(pgrel, &tuple->t_self, tuple);
@ -320,19 +321,19 @@ DropTrigger(DropTrigStmt *stmt)
int found = 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",
stmt->relname);
stmt->relation->relname);
if (!pg_ownercheck(GetUserId(), stmt->relname, RELNAME))
elog(ERROR, "%s: %s", stmt->relname,
if (!pg_ownercheck(GetUserId(), stmt->relation->relname, RELNAME))
elog(ERROR, "%s: %s", stmt->relation->relname,
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)
elog(ERROR, "DropTrigger: relation \"%s\" is not a table",
stmt->relname);
stmt->relation->relname);
/*
* Search pg_trigger, delete target trigger, count remaining triggers
@ -366,10 +367,10 @@ DropTrigger(DropTrigStmt *stmt)
if (tgfound == 0)
elog(ERROR, "DropTrigger: there is no trigger %s on relation %s",
stmt->trigname, stmt->relname);
stmt->trigname, stmt->relation->relname);
if (tgfound > 1)
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
@ -378,11 +379,11 @@ DropTrigger(DropTrigStmt *stmt)
*/
pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheCopy(RELNAME,
PointerGetDatum(stmt->relname),
PointerGetDatum(stmt->relation->relname),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "DropTrigger: relation %s not found in pg_class",
stmt->relname);
stmt->relation->relname);
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found;
simple_heap_update(pgrel, &tuple->t_self, tuple);
@ -478,20 +479,23 @@ RelationRemoveTriggers(Relation rel)
{
Form_pg_trigger pg_trigger;
Relation refrel;
DropTrigStmt stmt;
DropTrigStmt *stmt = makeNode(DropTrigStmt);
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. */
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);
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
@ -500,9 +504,6 @@ RelationRemoveTriggers(Relation rel)
* FK table defined on the PK table).
*/
CommandCounterIncrement();
pfree(stmt.relname);
pfree(stmt.trigname);
}
systable_endscan(tgscan);

View File

@ -13,7 +13,7 @@
*
*
* 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_MAXSIZE);
/* Convert vacrel, which is just a string, to a Name */
if (vacstmt->vacrel)
/* Convert relname, which is just a string, to a Name */
if (vacstmt->relation)
{
namestrcpy(&VacRel, vacstmt->vacrel);
namestrcpy(&VacRel, vacstmt->relation->relname);
VacRelName = &VacRel;
}
else
@ -268,7 +268,7 @@ vacuum(VacuumStmt *vacstmt)
static void
vacuum_init(VacuumStmt *vacstmt)
{
if (vacstmt->vacuum && vacstmt->vacrel == NULL)
if (vacstmt->vacuum && vacstmt->relation == NULL)
{
/*
* 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
* pg_clog.
*/
if (vacstmt->vacuum && vacstmt->vacrel == NULL)
if (vacstmt->vacuum && vacstmt->relation == NULL)
{
vac_update_dbstats(MyDatabaseId,
initialOldestXmin, initialFreezeLimit);

View File

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

View File

@ -27,7 +27,7 @@
*
*
* 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
*/
intoName = parseTree->into;
intoName = parseTree->into->relname;
/*
* 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,
tupdesc,
RELKIND_RELATION, true,
parseTree->isTemp,
parseTree->into->istemp,
allowSystemTableMods);
FreeTupleDesc(tupdesc);

View File

@ -8,7 +8,7 @@
*
*
* 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 */
queryTree->isPortal = true;
queryTree->into = pstrdup(name);
queryTree->into = makeNode(RangeVar);
queryTree->into->relname = pstrdup(name);
queryTree->isBinary = false;
/* Create the QueryDesc object and the executor state */
@ -1145,7 +1146,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
if (parseTree->isPortal)
{
isRetrieveIntoPortal = true;
intoName = parseTree->into;
intoName = parseTree->into->relname;
parseTree->isBinary = false; /* */
return SPI_ERROR_CURSOR;

View File

@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* 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;
}
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
* ----------------
@ -1515,8 +1503,7 @@ _copyFkConstraint(FkConstraint *from)
if (from->constr_name)
newnode->constr_name = pstrdup(from->constr_name);
if (from->pktable_name)
newnode->pktable_name = pstrdup(from->pktable_name);
Node_Copy(from, newnode, pktable);
Node_Copy(from, newnode, fk_attrs);
Node_Copy(from, newnode, pk_attrs);
if (from->match_type)
@ -1553,6 +1540,29 @@ _copyAExpr(A_Expr *from)
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 *
_copyAConst(A_Const *from)
{
@ -1564,27 +1574,12 @@ _copyAConst(A_Const *from)
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 *
_copyIdent(Ident *from)
{
Ident *newnode = makeNode(Ident);
if (from->name)
newnode->name = pstrdup(from->name);
Node_Copy(from, newnode, indirection);
newnode->isRel = from->isRel;
newnode->name = pstrdup(from->name);
return newnode;
}
@ -1614,6 +1609,18 @@ _copyAIndices(A_Indices *from)
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 *
_copyResTarget(ResTarget *from)
{
@ -1654,15 +1661,32 @@ _copySortGroupBy(SortGroupBy *from)
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 *
_copyRangeVar(RangeVar *from)
{
RangeVar *newnode = makeNode(RangeVar);
if (from->catalogname)
newnode->catalogname = pstrdup(from->catalogname);
if (from->schemaname)
newnode->schemaname = pstrdup(from->schemaname);
if (from->relname)
newnode->relname = pstrdup(from->relname);
newnode->inhOpt = from->inhOpt;
Node_Copy(from, newnode, name);
newnode->istemp = from->istemp;
Node_Copy(from, newnode, alias);
return newnode;
}
@ -1673,7 +1697,7 @@ _copyRangeSubselect(RangeSubselect *from)
RangeSubselect *newnode = makeNode(RangeSubselect);
Node_Copy(from, newnode, subquery);
Node_Copy(from, newnode, name);
Node_Copy(from, newnode, alias);
return newnode;
}
@ -1756,11 +1780,9 @@ _copyQuery(Query *from)
newnode->commandType = from->commandType;
Node_Copy(from, newnode, utilityStmt);
newnode->resultRelation = from->resultRelation;
if (from->into)
newnode->into = pstrdup(from->into);
Node_Copy(from, newnode, into);
newnode->isPortal = from->isPortal;
newnode->isBinary = from->isBinary;
newnode->isTemp = from->isTemp;
newnode->hasAggs = from->hasAggs;
newnode->hasSubLinks = from->hasSubLinks;
newnode->originalQuery = from->originalQuery;
@ -1798,8 +1820,7 @@ _copyInsertStmt(InsertStmt *from)
{
InsertStmt *newnode = makeNode(InsertStmt);
if (from->relname)
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, relation);
Node_Copy(from, newnode, cols);
Node_Copy(from, newnode, targetList);
Node_Copy(from, newnode, selectStmt);
@ -1812,10 +1833,8 @@ _copyDeleteStmt(DeleteStmt *from)
{
DeleteStmt *newnode = makeNode(DeleteStmt);
if (from->relname)
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, relation);
Node_Copy(from, newnode, whereClause);
newnode->inhOpt = from->inhOpt;
return newnode;
}
@ -1825,12 +1844,10 @@ _copyUpdateStmt(UpdateStmt *from)
{
UpdateStmt *newnode = makeNode(UpdateStmt);
if (from->relname)
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, relation);
Node_Copy(from, newnode, targetList);
Node_Copy(from, newnode, whereClause);
Node_Copy(from, newnode, fromClause);
newnode->inhOpt = from->inhOpt;
return newnode;
}
@ -1841,9 +1858,7 @@ _copySelectStmt(SelectStmt *from)
SelectStmt *newnode = makeNode(SelectStmt);
Node_Copy(from, newnode, distinctClause);
if (from->into)
newnode->into = pstrdup(from->into);
newnode->istemp = from->istemp;
Node_Copy(from, newnode, into);
Node_Copy(from, newnode, intoColNames);
Node_Copy(from, newnode, targetList);
Node_Copy(from, newnode, fromClause);
@ -1885,9 +1900,7 @@ _copyAlterTableStmt(AlterTableStmt *from)
AlterTableStmt *newnode = makeNode(AlterTableStmt);
newnode->subtype = from->subtype;
if (from->relname)
newnode->relname = pstrdup(from->relname);
newnode->inhOpt = from->inhOpt;
Node_Copy(from, newnode, relation);
if (from->name)
newnode->name = pstrdup(from->name);
Node_Copy(from, newnode, def);
@ -1951,8 +1964,7 @@ _copyClusterStmt(ClusterStmt *from)
{
ClusterStmt *newnode = makeNode(ClusterStmt);
if (from->relname)
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, relation);
if (from->indexname)
newnode->indexname = pstrdup(from->indexname);
@ -1965,8 +1977,7 @@ _copyCopyStmt(CopyStmt *from)
CopyStmt *newnode = makeNode(CopyStmt);
newnode->binary = from->binary;
if (from->relname)
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, relation);
newnode->oids = from->oids;
newnode->direction = from->direction;
if (from->filename)
@ -1984,11 +1995,10 @@ _copyCreateStmt(CreateStmt *from)
{
CreateStmt *newnode = makeNode(CreateStmt);
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, relation);
Node_Copy(from, newnode, tableElts);
Node_Copy(from, newnode, inhRelnames);
Node_Copy(from, newnode, inhRelations);
Node_Copy(from, newnode, constraints);
newnode->istemp = from->istemp;
newnode->hasoids = from->hasoids;
return newnode;
@ -2024,7 +2034,7 @@ _copyDropStmt(DropStmt *from)
{
DropStmt *newnode = makeNode(DropStmt);
Node_Copy(from, newnode, names);
Node_Copy(from, newnode, objects);
newnode->removeType = from->removeType;
newnode->behavior = from->behavior;
@ -2036,7 +2046,7 @@ _copyTruncateStmt(TruncateStmt *from)
{
TruncateStmt *newnode = makeNode(TruncateStmt);
newnode->relName = pstrdup(from->relName);
Node_Copy(from, newnode, relation);
return newnode;
}
@ -2047,6 +2057,8 @@ _copyCommentStmt(CommentStmt *from)
CommentStmt *newnode = makeNode(CommentStmt);
newnode->objtype = from->objtype;
if (from->objschema)
newnode->objschema = pstrdup(from->objschema);
newnode->objname = pstrdup(from->objname);
if (from->objproperty)
newnode->objproperty = pstrdup(from->objproperty);
@ -2075,7 +2087,7 @@ _copyIndexStmt(IndexStmt *from)
IndexStmt *newnode = makeNode(IndexStmt);
newnode->idxname = pstrdup(from->idxname);
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, relation);
newnode->accessMethod = pstrdup(from->accessMethod);
Node_Copy(from, newnode, indexParams);
Node_Copy(from, newnode, whereClause);
@ -2140,8 +2152,7 @@ _copyRenameStmt(RenameStmt *from)
{
RenameStmt *newnode = makeNode(RenameStmt);
newnode->relname = pstrdup(from->relname);
newnode->inhOpt = from->inhOpt;
Node_Copy(from, newnode, relation);
if (from->column)
newnode->column = pstrdup(from->column);
if (from->newname)
@ -2155,10 +2166,10 @@ _copyRuleStmt(RuleStmt *from)
{
RuleStmt *newnode = makeNode(RuleStmt);
Node_Copy(from, newnode, relation);
newnode->rulename = pstrdup(from->rulename);
Node_Copy(from, newnode, whereClause);
newnode->event = from->event;
Node_Copy(from, newnode, object);
newnode->instead = from->instead;
Node_Copy(from, newnode, actions);
@ -2170,8 +2181,7 @@ _copyNotifyStmt(NotifyStmt *from)
{
NotifyStmt *newnode = makeNode(NotifyStmt);
if (from->relname)
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, relation);
return newnode;
}
@ -2181,8 +2191,7 @@ _copyListenStmt(ListenStmt *from)
{
ListenStmt *newnode = makeNode(ListenStmt);
if (from->relname)
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, relation);
return newnode;
}
@ -2192,8 +2201,7 @@ _copyUnlistenStmt(UnlistenStmt *from)
{
UnlistenStmt *newnode = makeNode(UnlistenStmt);
if (from->relname)
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, relation);
return newnode;
}
@ -2213,8 +2221,7 @@ _copyViewStmt(ViewStmt *from)
{
ViewStmt *newnode = makeNode(ViewStmt);
if (from->viewname)
newnode->viewname = pstrdup(from->viewname);
Node_Copy(from, newnode, view);
Node_Copy(from, newnode, aliases);
Node_Copy(from, newnode, query);
@ -2298,8 +2305,7 @@ _copyVacuumStmt(VacuumStmt *from)
newnode->analyze = from->analyze;
newnode->freeze = from->freeze;
newnode->verbose = from->verbose;
if (from->vacrel)
newnode->vacrel = pstrdup(from->vacrel);
Node_Copy(from, newnode, relation);
Node_Copy(from, newnode, va_cols);
return newnode;
@ -2322,8 +2328,7 @@ _copyCreateSeqStmt(CreateSeqStmt *from)
{
CreateSeqStmt *newnode = makeNode(CreateSeqStmt);
if (from->seqname)
newnode->seqname = pstrdup(from->seqname);
Node_Copy(from, newnode, sequence);
Node_Copy(from, newnode, options);
return newnode;
@ -2370,8 +2375,7 @@ _copyCreateTrigStmt(CreateTrigStmt *from)
if (from->trigname)
newnode->trigname = pstrdup(from->trigname);
if (from->relname)
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, relation);
if (from->funcname)
newnode->funcname = pstrdup(from->funcname);
Node_Copy(from, newnode, args);
@ -2389,8 +2393,7 @@ _copyCreateTrigStmt(CreateTrigStmt *from)
newnode->isconstraint = from->isconstraint;
newnode->deferrable = from->deferrable;
newnode->initdeferred = from->initdeferred;
if (from->constrrelname)
newnode->constrrelname = pstrdup(from->constrrelname);
Node_Copy(from, newnode, constrrel);
return newnode;
}
@ -2402,8 +2405,7 @@ _copyDropTrigStmt(DropTrigStmt *from)
if (from->trigname)
newnode->trigname = pstrdup(from->trigname);
if (from->relname)
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, relation);
return newnode;
}
@ -2488,7 +2490,7 @@ _copyLockStmt(LockStmt *from)
{
LockStmt *newnode = makeNode(LockStmt);
Node_Copy(from, newnode, rellist);
Node_Copy(from, newnode, relations);
newnode->mode = from->mode;
@ -2548,6 +2550,7 @@ _copyReindexStmt(ReindexStmt *from)
ReindexStmt *newnode = makeNode(ReindexStmt);
newnode->reindexType = from->reindexType;
Node_Copy(from, newnode, relation);
if (from->name)
newnode->name = pstrdup(from->name);
newnode->force = from->force;
@ -2556,6 +2559,19 @@ _copyReindexStmt(ReindexStmt *from)
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
@ -2888,6 +2904,9 @@ copyObject(void *from)
case T_LoadStmt:
retval = _copyLoadStmt(from);
break;
case T_CreateDomainStmt:
retval = _copyCreateDomainStmt(from);
break;
case T_CreatedbStmt:
retval = _copyCreatedbStmt(from);
break;
@ -2960,19 +2979,22 @@ copyObject(void *from)
case T_CheckPointStmt:
retval = (void *) makeNode(CheckPointStmt);
break;
case T_CreateSchemaStmt:
retval = _copyCreateSchemaStmt(from);
break;
case T_A_Expr:
retval = _copyAExpr(from);
break;
case T_Attr:
retval = _copyAttr(from);
case T_ColumnRef:
retval = _copyColumnRef(from);
break;
case T_ParamRef:
retval = _copyParamRef(from);
break;
case T_A_Const:
retval = _copyAConst(from);
break;
case T_ParamNo:
retval = _copyParamNo(from);
break;
case T_Ident:
retval = _copyIdent(from);
break;
@ -2982,6 +3004,9 @@ copyObject(void *from)
case T_A_Indices:
retval = _copyAIndices(from);
break;
case T_ExprFieldSelect:
retval = _copyExprFieldSelect(from);
break;
case T_ResTarget:
retval = _copyResTarget(from);
break;
@ -2991,6 +3016,9 @@ copyObject(void *from)
case T_SortGroupBy:
retval = _copySortGroupBy(from);
break;
case T_Alias:
retval = _copyAlias(from);
break;
case T_RangeVar:
retval = _copyRangeVar(from);
break;
@ -3045,9 +3073,6 @@ copyObject(void *from)
case T_FuncWithArgs:
retval = _copyFuncWithArgs(from);
break;
case T_CreateDomainStmt:
retval = _copyCreateDomainStmt(from);
break;
default:
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
*
* 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;
if (a->resultRelation != b->resultRelation)
return false;
if (!equalstr(a->into, b->into))
if (!equal(a->into, b->into))
return false;
if (a->isPortal != b->isPortal)
return false;
if (a->isBinary != b->isBinary)
return false;
if (a->isTemp != b->isTemp)
return false;
if (a->hasAggs != b->hasAggs)
return false;
if (a->hasSubLinks != b->hasSubLinks)
@ -629,7 +627,7 @@ _equalQuery(Query *a, Query *b)
static bool
_equalInsertStmt(InsertStmt *a, InsertStmt *b)
{
if (!equalstr(a->relname, b->relname))
if (!equal(a->relation, b->relation))
return false;
if (!equal(a->cols, b->cols))
return false;
@ -644,12 +642,10 @@ _equalInsertStmt(InsertStmt *a, InsertStmt *b)
static bool
_equalDeleteStmt(DeleteStmt *a, DeleteStmt *b)
{
if (!equalstr(a->relname, b->relname))
if (!equal(a->relation, b->relation))
return false;
if (!equal(a->whereClause, b->whereClause))
return false;
if (a->inhOpt != b->inhOpt)
return false;
return true;
}
@ -657,7 +653,7 @@ _equalDeleteStmt(DeleteStmt *a, DeleteStmt *b)
static bool
_equalUpdateStmt(UpdateStmt *a, UpdateStmt *b)
{
if (!equalstr(a->relname, b->relname))
if (!equal(a->relation, b->relation))
return false;
if (!equal(a->targetList, b->targetList))
return false;
@ -665,8 +661,6 @@ _equalUpdateStmt(UpdateStmt *a, UpdateStmt *b)
return false;
if (!equal(a->fromClause, b->fromClause))
return false;
if (a->inhOpt != b->inhOpt)
return false;
return true;
}
@ -676,9 +670,7 @@ _equalSelectStmt(SelectStmt *a, SelectStmt *b)
{
if (!equal(a->distinctClause, b->distinctClause))
return false;
if (!equalstr(a->into, b->into))
return false;
if (a->istemp != b->istemp)
if (!equal(a->into, b->into))
return false;
if (!equal(a->intoColNames, b->intoColNames))
return false;
@ -738,9 +730,7 @@ _equalAlterTableStmt(AlterTableStmt *a, AlterTableStmt *b)
{
if (a->subtype != b->subtype)
return false;
if (!equalstr(a->relname, b->relname))
return false;
if (a->inhOpt != b->inhOpt)
if (!equal(a->relation, b->relation))
return false;
if (!equalstr(a->name, b->name))
return false;
@ -795,7 +785,7 @@ _equalClosePortalStmt(ClosePortalStmt *a, ClosePortalStmt *b)
static bool
_equalClusterStmt(ClusterStmt *a, ClusterStmt *b)
{
if (!equalstr(a->relname, b->relname))
if (!equal(a->relation, b->relation))
return false;
if (!equalstr(a->indexname, b->indexname))
return false;
@ -808,7 +798,7 @@ _equalCopyStmt(CopyStmt *a, CopyStmt *b)
{
if (a->binary != b->binary)
return false;
if (!equalstr(a->relname, b->relname))
if (!equal(a->relation, b->relation))
return false;
if (a->oids != b->oids)
return false;
@ -827,16 +817,14 @@ _equalCopyStmt(CopyStmt *a, CopyStmt *b)
static bool
_equalCreateStmt(CreateStmt *a, CreateStmt *b)
{
if (!equalstr(a->relname, b->relname))
if (!equal(a->relation, b->relation))
return false;
if (!equal(a->tableElts, b->tableElts))
return false;
if (!equal(a->inhRelnames, b->inhRelnames))
if (!equal(a->inhRelations, b->inhRelations))
return false;
if (!equal(a->constraints, b->constraints))
return false;
if (a->istemp != b->istemp)
return false;
if (a->hasoids != b->hasoids)
return false;
@ -874,7 +862,7 @@ _equalDefineStmt(DefineStmt *a, DefineStmt *b)
static bool
_equalDropStmt(DropStmt *a, DropStmt *b)
{
if (!equal(a->names, b->names))
if (!equal(a->objects, b->objects))
return false;
if (a->removeType != b->removeType)
return false;
@ -887,7 +875,7 @@ _equalDropStmt(DropStmt *a, DropStmt *b)
static bool
_equalTruncateStmt(TruncateStmt *a, TruncateStmt *b)
{
if (!equalstr(a->relName, b->relName))
if (!equal(a->relation, b->relation))
return false;
return true;
@ -900,6 +888,8 @@ _equalCommentStmt(CommentStmt *a, CommentStmt *b)
return false;
if (!equalstr(a->objname, b->objname))
return false;
if (!equalstr(a->objschema, b->objschema))
return false;
if (!equalstr(a->objproperty, b->objproperty))
return false;
if (!equal(a->objlist, b->objlist))
@ -930,7 +920,7 @@ _equalIndexStmt(IndexStmt *a, IndexStmt *b)
{
if (!equalstr(a->idxname, b->idxname))
return false;
if (!equalstr(a->relname, b->relname))
if (!equal(a->relation, b->relation))
return false;
if (!equalstr(a->accessMethod, b->accessMethod))
return false;
@ -1006,9 +996,7 @@ _equalRemoveOperStmt(RemoveOperStmt *a, RemoveOperStmt *b)
static bool
_equalRenameStmt(RenameStmt *a, RenameStmt *b)
{
if (!equalstr(a->relname, b->relname))
return false;
if (a->inhOpt != b->inhOpt)
if (!equal(a->relation, b->relation))
return false;
if (!equalstr(a->column, b->column))
return false;
@ -1021,14 +1009,14 @@ _equalRenameStmt(RenameStmt *a, RenameStmt *b)
static bool
_equalRuleStmt(RuleStmt *a, RuleStmt *b)
{
if (!equal(a->relation, b->relation))
return false;
if (!equalstr(a->rulename, b->rulename))
return false;
if (!equal(a->whereClause, b->whereClause))
return false;
if (a->event != b->event)
return false;
if (!equal(a->object, b->object))
return false;
if (a->instead != b->instead)
return false;
if (!equal(a->actions, b->actions))
@ -1040,7 +1028,7 @@ _equalRuleStmt(RuleStmt *a, RuleStmt *b)
static bool
_equalNotifyStmt(NotifyStmt *a, NotifyStmt *b)
{
if (!equalstr(a->relname, b->relname))
if (!equal(a->relation, b->relation))
return false;
return true;
@ -1049,7 +1037,7 @@ _equalNotifyStmt(NotifyStmt *a, NotifyStmt *b)
static bool
_equalListenStmt(ListenStmt *a, ListenStmt *b)
{
if (!equalstr(a->relname, b->relname))
if (!equal(a->relation, b->relation))
return false;
return true;
@ -1058,7 +1046,7 @@ _equalListenStmt(ListenStmt *a, ListenStmt *b)
static bool
_equalUnlistenStmt(UnlistenStmt *a, UnlistenStmt *b)
{
if (!equalstr(a->relname, b->relname))
if (!equal(a->relation, b->relation))
return false;
return true;
@ -1076,7 +1064,7 @@ _equalTransactionStmt(TransactionStmt *a, TransactionStmt *b)
static bool
_equalViewStmt(ViewStmt *a, ViewStmt *b)
{
if (!equalstr(a->viewname, b->viewname))
if (!equal(a->view, b->view))
return false;
if (!equal(a->aliases, b->aliases))
return false;
@ -1160,7 +1148,7 @@ _equalVacuumStmt(VacuumStmt *a, VacuumStmt *b)
return false;
if (a->verbose != b->verbose)
return false;
if (!equalstr(a->vacrel, b->vacrel))
if (!equal(a->relation, b->relation))
return false;
if (!equal(a->va_cols, b->va_cols))
return false;
@ -1184,7 +1172,7 @@ _equalExplainStmt(ExplainStmt *a, ExplainStmt *b)
static bool
_equalCreateSeqStmt(CreateSeqStmt *a, CreateSeqStmt *b)
{
if (!equalstr(a->seqname, b->seqname))
if (!equal(a->sequence, b->sequence))
return false;
if (!equal(a->options, b->options))
return false;
@ -1226,7 +1214,7 @@ _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b)
{
if (!equalstr(a->trigname, b->trigname))
return false;
if (!equalstr(a->relname, b->relname))
if (!equal(a->relation, b->relation))
return false;
if (!equalstr(a->funcname, b->funcname))
return false;
@ -1252,7 +1240,7 @@ _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b)
return false;
if (a->initdeferred != b->initdeferred)
return false;
if (!equalstr(a->constrrelname, b->constrrelname))
if (!equal(a->constrrel, b->constrrel))
return false;
return true;
@ -1263,7 +1251,7 @@ _equalDropTrigStmt(DropTrigStmt *a, DropTrigStmt *b)
{
if (!equalstr(a->trigname, b->trigname))
return false;
if (!equalstr(a->relname, b->relname))
if (!equal(a->relation, b->relation))
return false;
return true;
@ -1340,7 +1328,7 @@ _equalDropUserStmt(DropUserStmt *a, DropUserStmt *b)
static bool
_equalLockStmt(LockStmt *a, LockStmt *b)
{
if (!equal(a->rellist, b->rellist))
if (!equal(a->relations, b->relations))
return false;
if (a->mode != b->mode)
return false;
@ -1397,6 +1385,8 @@ _equalReindexStmt(ReindexStmt *a, ReindexStmt *b)
{
if (a->reindexType != b->reindexType)
return false;
if (!equal(a->relation, b->relation))
return false;
if (!equalstr(a->name, b->name))
return false;
if (a->force != b->force)
@ -1407,6 +1397,19 @@ _equalReindexStmt(ReindexStmt *a, ReindexStmt *b)
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
_equalAExpr(A_Expr *a, A_Expr *b)
{
@ -1423,13 +1426,22 @@ _equalAExpr(A_Expr *a, A_Expr *b)
}
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;
if (!equal(a->paramNo, b->paramNo))
if (!equal(a->indirection, b->indirection))
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;
if (!equal(a->indirection, b->indirection))
return false;
@ -1448,28 +1460,11 @@ _equalAConst(A_Const *a, A_Const *b)
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
_equalIdent(Ident *a, Ident *b)
{
if (!equalstr(a->name, b->name))
return false;
if (!equal(a->indirection, b->indirection))
return false;
if (a->isRel != b->isRel)
return false;
return true;
}
@ -1500,6 +1495,19 @@ _equalAIndices(A_Indices *a, A_Indices *b)
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
_equalResTarget(ResTarget *a, ResTarget *b)
{
@ -1535,14 +1543,31 @@ _equalSortGroupBy(SortGroupBy *a, SortGroupBy *b)
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
_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))
return false;
if (a->inhOpt != b->inhOpt)
return false;
if (!equal(a->name, b->name))
if (a->istemp != b->istemp)
return false;
if (!equal(a->alias, b->alias))
return false;
return true;
@ -1553,7 +1578,7 @@ _equalRangeSubselect(RangeSubselect *a, RangeSubselect *b)
{
if (!equal(a->subquery, b->subquery))
return false;
if (!equal(a->name, b->name))
if (!equal(a->alias, b->alias))
return false;
return true;
@ -1704,7 +1729,7 @@ _equalFkConstraint(FkConstraint *a, FkConstraint *b)
{
if (!equalstr(a->constr_name, b->constr_name))
return false;
if (!equalstr(a->pktable_name, b->pktable_name))
if (!equal(a->pktable, b->pktable))
return false;
if (!equal(a->fk_attrs, b->fk_attrs))
return false;
@ -2111,19 +2136,22 @@ equal(void *a, void *b)
case T_CheckPointStmt:
retval = true;
break;
case T_CreateSchemaStmt:
retval = _equalCreateSchemaStmt(a, b);
break;
case T_A_Expr:
retval = _equalAExpr(a, b);
break;
case T_Attr:
retval = _equalAttr(a, b);
case T_ColumnRef:
retval = _equalColumnRef(a, b);
break;
case T_ParamRef:
retval = _equalParamRef(a, b);
break;
case T_A_Const:
retval = _equalAConst(a, b);
break;
case T_ParamNo:
retval = _equalParamNo(a, b);
break;
case T_Ident:
retval = _equalIdent(a, b);
break;
@ -2133,6 +2161,9 @@ equal(void *a, void *b)
case T_A_Indices:
retval = _equalAIndices(a, b);
break;
case T_ExprFieldSelect:
retval = _equalExprFieldSelect(a, b);
break;
case T_ResTarget:
retval = _equalResTarget(a, b);
break;
@ -2142,6 +2173,9 @@ equal(void *a, void *b)
case T_SortGroupBy:
retval = _equalSortGroupBy(a, b);
break;
case T_Alias:
retval = _equalAlias(a, b);
break;
case T_RangeVar:
retval = _equalRangeVar(a, b);
break;

View File

@ -8,7 +8,7 @@
*
*
* 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"
@ -159,19 +159,18 @@ makeNullConst(Oid consttype)
}
/*
* makeAttr -
* creates an Attr node
* makeAlias -
* creates an Alias node
*
* NOTE: the given name is copied, but the colnames list (if any) isn't.
*/
Attr *
makeAttr(char *relname, char *attname)
Alias *
makeAlias(const char *aliasname, List *colnames)
{
Attr *a = makeNode(Attr);
Alias *a = makeNode(Alias);
a->relname = pstrdup(relname);
a->paramNo = NULL;
if (attname != NULL)
a->attrs = makeList1(makeString(pstrdup(attname)));
a->indirection = NULL;
a->aliasname = pstrdup(aliasname);
a->colnames = colnames;
return a;
}

View File

@ -8,7 +8,7 @@
*
*
* 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
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;
else
return false;
@ -103,13 +105,13 @@ replace_opid(Oper *oper)
* non_null -
* Returns t if the node is a non-null constant, e.g., if the node has a
* valid `constvalue' field.
*
*/
bool
non_null(Expr *c)
{
if (IsA(c, Const) &&!((Const *) c)->constisnull)
if (IsA(c, Const) &&
!((Const *) c)->constisnull)
return true;
else
return false;

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* 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
* Every (plan) node in POSTGRES has an associated "out" routine which
@ -105,20 +105,19 @@ _outOidList(StringInfo str, List *list)
static void
_outCreateStmt(StringInfo str, CreateStmt *node)
{
appendStringInfo(str, " CREATE :relname ");
_outToken(str, node->relname);
appendStringInfo(str, " CREATE :relation ");
_outNode(str, node->relation);
appendStringInfo(str, " :columns ");
appendStringInfo(str, " :tableElts ");
_outNode(str, node->tableElts);
appendStringInfo(str, " :inhRelnames ");
_outNode(str, node->inhRelnames);
appendStringInfo(str, " :inhRelations ");
_outNode(str, node->inhRelations);
appendStringInfo(str, " :constraints ");
_outNode(str, node->constraints);
appendStringInfo(str, " :istemp %s :hasoids %s ",
booltostr(node->istemp),
appendStringInfo(str, " :hasoids %s ",
booltostr(node->hasoids));
}
@ -127,8 +126,8 @@ _outIndexStmt(StringInfo str, IndexStmt *node)
{
appendStringInfo(str, " INDEX :idxname ");
_outToken(str, node->idxname);
appendStringInfo(str, " :relname ");
_outToken(str, node->relname);
appendStringInfo(str, " :relation ");
_outNode(str, node->relation);
appendStringInfo(str, " :accessMethod ");
_outToken(str, node->accessMethod);
appendStringInfo(str, " :indexParams ");
@ -142,6 +141,13 @@ _outIndexStmt(StringInfo str, IndexStmt *node)
booltostr(node->primary));
}
static void
_outNotifyStmt(StringInfo str, NotifyStmt *node)
{
appendStringInfo(str, "NOTIFY :relation ");
_outNode(str, node->relation);
}
static void
_outSelectStmt(StringInfo str, SelectStmt *node)
{
@ -213,53 +219,40 @@ _outIndexElem(StringInfo str, IndexElem *node)
static void
_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)
{
/*
* Hack to make up for lack of outfuncs for utility-stmt nodes
*/
switch (nodeTag(node->utilityStmt))
{
case T_CreateStmt:
appendStringInfo(str, " :create ");
_outToken(str, ((CreateStmt *) (node->utilityStmt))->relname);
appendStringInfo(str, " ");
_outNode(str, node->utilityStmt);
break;
case T_IndexStmt:
appendStringInfo(str, " :index ");
_outToken(str, ((IndexStmt *) (node->utilityStmt))->idxname);
appendStringInfo(str, " on ");
_outToken(str, ((IndexStmt *) (node->utilityStmt))->relname);
appendStringInfo(str, " ");
case T_NotifyStmt:
_outNode(str, node->utilityStmt);
break;
case T_NotifyStmt:
appendStringInfo(str, " :notify ");
_outToken(str, ((NotifyStmt *) (node->utilityStmt))->relname);
break;
default:
appendStringInfo(str, " :utility ? ");
appendStringInfo(str, "?");
break;
}
}
else
appendStringInfo(str, " :utility <>");
appendStringInfo(str, "<>");
appendStringInfo(str, " :resultRelation %d :into ",
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 ",
booltostr(node->isPortal),
booltostr(node->isBinary),
booltostr(node->isTemp),
booltostr(node->hasAggs),
booltostr(node->hasSubLinks));
_outNode(str, node->rtable);
@ -963,6 +956,15 @@ _outTargetEntry(StringInfo str, TargetEntry *node)
_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
_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
_outIdent(StringInfo str, Ident *node)
{
@ -1318,15 +1356,6 @@ _outIdent(StringInfo str, Ident *node)
_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
_outAConst(StringInfo str, A_Const *node)
{
@ -1336,6 +1365,17 @@ _outAConst(StringInfo str, A_Const *node)
_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
_outConstraint(StringInfo str, Constraint *node)
{
@ -1384,8 +1424,8 @@ _outFkConstraint(StringInfo str, FkConstraint *node)
{
appendStringInfo(str, " FKCONSTRAINT :constr_name ");
_outToken(str, node->constr_name);
appendStringInfo(str, " :pktable_name ");
_outToken(str, node->pktable_name);
appendStringInfo(str, " :pktable ");
_outNode(str, node->pktable);
appendStringInfo(str, " :fk_attrs ");
_outNode(str, node->fk_attrs);
appendStringInfo(str, " :pk_attrs ");
@ -1490,6 +1530,12 @@ _outNode(StringInfo str, void *obj)
case T_IndexStmt:
_outIndexStmt(str, obj);
break;
case T_NotifyStmt:
_outNotifyStmt(str, obj);
break;
case T_SelectStmt:
_outSelectStmt(str, obj);
break;
case T_ColumnDef:
_outColumnDef(str, obj);
break;
@ -1628,6 +1674,9 @@ _outNode(StringInfo str, void *obj)
case T_TargetEntry:
_outTargetEntry(str, obj);
break;
case T_Alias:
_outAlias(str, obj);
break;
case T_RangeTblEntry:
_outRangeTblEntry(str, obj);
break;
@ -1670,12 +1719,24 @@ _outNode(StringInfo str, void *obj)
case T_A_Expr:
_outAExpr(str, obj);
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:
_outIdent(str, obj);
break;
case T_A_Const:
_outAConst(str, obj);
break;
case T_ExprFieldSelect:
_outExprFieldSelect(str, obj);
break;
case T_Constraint:
_outConstraint(str, obj);
break;
@ -1694,17 +1755,9 @@ _outNode(StringInfo str, void *obj)
case T_BooleanTest:
_outBooleanTest(str, obj);
break;
case T_VariableSetStmt:
break;
case T_SelectStmt:
_outSelectStmt(str, obj);
break;
case T_FuncCall:
_outFuncCall(str, obj);
break;
case T_Attr:
_outAttr(str, obj);
break;
default:
elog(WARNING, "_outNode: don't know how to print type %d ",

View File

@ -8,7 +8,7 @@
*
*
* 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
* AUTHOR DATE MAJOR EVENT
@ -154,10 +154,10 @@ print_rt(List *rtable)
if (rte->relname)
printf("%d\t%s (%s)\t%u",
i, rte->relname, rte->eref->relname, rte->relid);
i, rte->relname, rte->eref->aliasname, rte->relid);
else
printf("%d\t[subquery] (%s)\t",
i, rte->eref->relname);
i, rte->eref->aliasname);
printf("\t%s\t%s\n",
(rte->inh ? "inh" : ""),
(rte->inFromCl ? "inFromCl" : ""));
@ -202,7 +202,7 @@ print_expr(Node *expr, List *rtable)
Assert(var->varno > 0 &&
(int) var->varno <= length(rtable));
rte = rt_fetch(var->varno, rtable);
relname = rte->eref->relname;
relname = rte->eref->aliasname;
attname = get_rte_attribute_name(rte, var->varattno);
}
break;

View File

@ -8,7 +8,7 @@
*
*
* 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
* Most of the read functions for plan nodes are tested. (In fact, they
@ -119,34 +119,19 @@ _readQuery(void)
local_node = makeNode(Query);
token = pg_strtok(&length); /* skip the :command */
token = pg_strtok(&length); /* get the commandType */
token = pg_strtok(&length); /* skip :command */
token = pg_strtok(&length); /* get commandType */
local_node->commandType = atoi(token);
token = pg_strtok(&length); /* skip :utility */
token = pg_strtok(&length);
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);
local_node->utilityStmt = nodeRead(true);
n->relname = debackslash(token, length);
local_node->utilityStmt = (Node *) n;
}
token = pg_strtok(&length); /* skip the :resultRelation */
token = pg_strtok(&length); /* skip :resultRelation */
token = pg_strtok(&length); /* get the resultRelation */
local_node->resultRelation = atoi(token);
token = pg_strtok(&length); /* skip :into */
token = pg_strtok(&length); /* get into */
local_node->into = nullable_string(token, length);
local_node->into = nodeRead(true);
token = pg_strtok(&length); /* skip :isPortal */
token = pg_strtok(&length); /* get isPortal */
@ -156,10 +141,6 @@ _readQuery(void)
token = pg_strtok(&length); /* get isBinary */
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); /* get hasAggs */
local_node->hasAggs = strtobool(token);
@ -210,6 +191,25 @@ _readQuery(void)
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
* ----------------
@ -1394,21 +1394,93 @@ _readTargetEntry(void)
return local_node;
}
static Attr *
_readAttr(void)
static RangeVar *
_readRangeVar(void)
{
Attr *local_node;
RangeVar *local_node;
char *token;
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 */
local_node->relname = debackslash(token, length);
local_node->relname = nullable_string(token, length);
token = pg_strtok(&length); /* eat :inhopt */
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 :attrs */
local_node->attrs = nodeRead(true); /* now read it */
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;
}
@ -1994,8 +2066,6 @@ parsePlanString(void)
return_value = _readArrayRef();
else if (length == 3 && strncmp(token, "VAR", length) == 0)
return_value = _readVar();
else if (length == 4 && strncmp(token, "ATTR", length) == 0)
return_value = _readAttr();
else if (length == 5 && strncmp(token, "CONST", length) == 0)
return_value = _readConst();
else if (length == 4 && strncmp(token, "FUNC", length) == 0)
@ -2006,6 +2076,14 @@ parsePlanString(void)
return_value = _readParam();
else if (length == 11 && strncmp(token, "TARGETENTRY", length) == 0)
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)
return_value = _readRangeTblEntry();
else if (length == 4 && strncmp(token, "PATH", length) == 0)
@ -2032,6 +2110,8 @@ parsePlanString(void)
return_value = _readIter();
else if (length == 5 && strncmp(token, "QUERY", length) == 0)
return_value = _readQuery();
else if (length == 6 && strncmp(token, "NOTIFY", length) == 0)
return_value = _readNotifyStmt();
else if (length == 10 && strncmp(token, "SORTCLAUSE", length) == 0)
return_value = _readSortClause();
else if (length == 11 && strncmp(token, "GROUPCLAUSE", length) == 0)

View File

@ -8,7 +8,7 @@
*
*
* 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
* AUTHOR DATE MAJOR EVENT
@ -687,7 +687,7 @@ check_subplans_for_ungrouped_vars_walker(Node *node,
rte = rt_fetch(var->varno, context->query->rtable);
attname = get_rte_attribute_name(rte, var->varattno);
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;
switch (nodeTag(node))
{
case T_Ident:
case T_Const:
case T_Var:
case T_Param:
@ -1963,7 +1962,6 @@ expression_tree_mutator(Node *node,
return NULL;
switch (nodeTag(node))
{
case T_Ident:
case T_Const:
case T_Var:
case T_Param:

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* 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
/* 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 */
typedef struct
{
const char *stmtType; /* "CREATE TABLE" or "ALTER TABLE" */
char *relname; /* name of relation */
List *inhRelnames; /* names of relations to inherit from */
bool istemp; /* is it to be a temp relation? */
RangeVar *relation; /* relation to create */
List *inhRelations; /* relations to inherit from */
bool hasoids; /* does relation have an OID column? */
Oid relOid; /* OID of table, if ALTER TABLE case */
List *columns; /* ColumnDef items */
@ -330,8 +347,8 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
qry->commandType = CMD_DELETE;
/* set up range table with just the result rel */
qry->resultRelation = setTargetTable(pstate, stmt->relname,
interpretInhOption(stmt->inhOpt),
qry->resultRelation = setTargetTable(pstate, stmt->relation->relname,
interpretInhOption(stmt->relation->inhOpt),
true);
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 not added to the joinlist or namespace.
*/
qry->resultRelation = setTargetTable(pstate, stmt->relname,
qry->resultRelation = setTargetTable(pstate, stmt->relation->relname,
false, false);
/*
@ -443,7 +460,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
*/
rte = addRangeTableEntryForSubquery(pstate,
selectQuery,
makeAttr("*SELECT*", NULL),
makeAlias("*SELECT*", NIL),
true);
rtr = makeNode(RangeTblRef);
/* assume new rte is at end */
@ -515,14 +532,15 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
foreach(tl, qry->targetList)
{
TargetEntry *tle = (TargetEntry *) lfirst(tl);
Ident *id;
ResTarget *col;
Assert(!tle->resdom->resjunk);
if (icolumns == NIL || attnos == NIL)
elog(ERROR, "INSERT has more expressions than target columns");
id = (Ident *) lfirst(icolumns);
updateTargetListEntry(pstate, tle, id->name, lfirsti(attnos),
id->indirection);
col = (ResTarget *) lfirst(icolumns);
Assert(IsA(col, ResTarget));
updateTargetListEntry(pstate, tle, col->name, lfirsti(attnos),
col->indirection);
icolumns = lnext(icolumns);
attnos = lnext(attnos);
}
@ -691,9 +709,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt,
List *elements;
cxt.stmtType = "CREATE TABLE";
cxt.relname = stmt->relname;
cxt.inhRelnames = stmt->inhRelnames;
cxt.istemp = stmt->istemp;
cxt.relation = stmt->relation;
cxt.inhRelations = stmt->inhRelations;
cxt.hasoids = stmt->hasoids;
cxt.relOid = InvalidOid;
cxt.columns = NIL;
@ -805,7 +822,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
* conflicting constraints the user wrote (like a different
* DEFAULT).
*/
sname = makeObjectName(cxt->relname, column->colname, "seq");
sname = makeObjectName((cxt->relation)->relname, column->colname, "seq");
/*
* Create an expression tree representing the function call
@ -845,12 +862,12 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
* CREATE/ALTER TABLE.
*/
sequence = makeNode(CreateSeqStmt);
sequence->seqname = pstrdup(sname);
sequence->istemp = cxt->istemp;
sequence->sequence = copyObject(cxt->relation);
sequence->sequence->relname = pstrdup(sname);
sequence->options = NIL;
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);
}
@ -875,9 +892,6 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
Ident *id = makeNode(Ident);
id->name = column->colname;
id->indirection = NIL;
id->isRel = false;
fkconstraint->fk_attrs = makeList1(id);
cxt->fkconstraints = lappend(cxt->fkconstraints, fkconstraint);
@ -891,7 +905,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
case CONSTR_NULL:
if (saw_nullable && column->is_not_null)
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;
saw_nullable = true;
break;
@ -899,7 +913,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
case CONSTR_NOTNULL:
if (saw_nullable && !column->is_not_null)
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;
saw_nullable = true;
break;
@ -907,14 +921,14 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
case CONSTR_DEFAULT:
if (column->raw_default != NULL)
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;
Assert(constraint->cooked_expr == NULL);
break;
case CONSTR_PRIMARY:
if (constraint->name == NULL)
constraint->name = makeObjectName(cxt->relname,
constraint->name = makeObjectName((cxt->relation)->relname,
NULL,
"pkey");
if (constraint->keys == NIL)
@ -928,7 +942,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
case CONSTR_UNIQUE:
if (constraint->name == NULL)
constraint->name = makeObjectName(cxt->relname,
constraint->name = makeObjectName((cxt->relation)->relname,
column->colname,
"key");
if (constraint->keys == NIL)
@ -942,7 +956,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
case CONSTR_CHECK:
if (constraint->name == NULL)
constraint->name = makeObjectName(cxt->relname,
constraint->name = makeObjectName((cxt->relation)->relname,
column->colname,
NULL);
cxt->ckconstraints = lappend(cxt->ckconstraints, constraint);
@ -970,7 +984,7 @@ transformTableConstraint(ParseState *pstate, CreateStmtContext *cxt,
{
case CONSTR_PRIMARY:
if (constraint->name == NULL)
constraint->name = makeObjectName(cxt->relname,
constraint->name = makeObjectName((cxt->relation)->relname,
NULL,
"pkey");
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 */
if (cxt->pkey != NULL ||
(OidIsValid(cxt->relOid) &&
relationHasPrimaryKey(cxt->relname)))
relationHasPrimaryKey((cxt->relation)->relname)))
elog(ERROR, "%s / PRIMARY KEY multiple primary keys"
" for table '%s' are not allowed",
cxt->stmtType, cxt->relname);
cxt->stmtType, (cxt->relation)->relname);
cxt->pkey = index;
}
if (constraint->name != NULL)
index->idxname = pstrdup(constraint->name);
else if (constraint->contype == CONSTR_PRIMARY)
index->idxname = makeObjectName(cxt->relname, NULL, "pkey");
index->idxname = makeObjectName((cxt->relation)->relname, NULL, "pkey");
else
index->idxname = NULL; /* will set it later */
index->relname = cxt->relname;
index->relation = cxt->relation;
index->accessMethod = DEFAULT_INDEX_TYPE;
index->indexParams = NIL;
index->whereClause = NULL;
@ -1089,19 +1103,19 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
*/
found = true;
}
else if (cxt->inhRelnames)
else if (cxt->inhRelations)
{
/* try inherited tables */
List *inher;
foreach(inher, cxt->inhRelnames)
foreach(inher, cxt->inhRelations)
{
Value *inh = lfirst(inher);
RangeVar *inh = lfirst(inher);
Relation rel;
int count;
Assert(IsA(inh, String));
rel = heap_openr(strVal(inh), AccessShareLock);
Assert(IsA(inh, RangeVar));
rel = heap_openr(inh->relname, AccessShareLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "inherited table \"%s\" is not a relation",
strVal(inh));
@ -1257,7 +1271,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
if (index->idxname == NULL && index->indexParams != NIL)
{
iparam = lfirst(index->indexParams);
index->idxname = CreateIndexName(cxt->relname, iparam->name,
index->idxname = CreateIndexName((cxt->relation)->relname, iparam->name,
"key", cxt->alist);
}
if (index->idxname == NULL) /* should not happen */
@ -1268,7 +1282,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
cxt->stmtType,
(strcmp(cxt->stmtType, "ALTER TABLE") == 0) ? "ADD " : "",
(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 (strcmp(fkconstraint->pktable_name, cxt->relname) != 0)
if (strcmp(fkconstraint->pktable->relname, (cxt->relation)->relname) != 0)
transformFkeyGetPrimaryKey(fkconstraint, pktypoid);
else if (cxt->pkey != NULL)
{
@ -1342,8 +1356,6 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
Ident *pkattr = (Ident *) makeNode(Ident);
pkattr->name = pstrdup(ielem->name);
pkattr->indirection = NIL;
pkattr->isRel = false;
fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs,
pkattr);
if (attnum >= INDEX_MAX_KEYS)
@ -1360,13 +1372,13 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
transformFkeyGetPrimaryKey(fkconstraint, pktypoid);
else
elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found",
fkconstraint->pktable_name);
fkconstraint->pktable->relname);
}
}
else
{
/* 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);
else
{
@ -1422,7 +1434,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
transformFkeyCheckAttrs(fkconstraint, pktypoid);
else
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->trigname = fkconstraint->constr_name;
fk_trigger->relname = cxt->relname;
fk_trigger->relation = cxt->relation;
fk_trigger->funcname = "RI_FKey_check_ins";
fk_trigger->before = false;
fk_trigger->row = true;
@ -1462,15 +1474,15 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
fk_trigger->isconstraint = true;
fk_trigger->deferrable = fkconstraint->deferrable;
fk_trigger->initdeferred = fkconstraint->initdeferred;
fk_trigger->constrrelname = fkconstraint->pktable_name;
fk_trigger->constrrel = fkconstraint->pktable;
fk_trigger->args = NIL;
fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->constr_name));
fk_trigger->args = lappend(fk_trigger->args,
makeString(cxt->relname));
makeString((cxt->relation)->relname));
fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->pktable_name));
makeString(fkconstraint->pktable->relname));
fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->match_type));
fk_attr = fkconstraint->fk_attrs;
@ -1478,7 +1490,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
if (length(fk_attr) != length(pk_attr))
elog(ERROR, "number of key attributes in referenced table must be equal to foreign key"
"\n\tIllegal FOREIGN KEY definition references \"%s\"",
fkconstraint->pktable_name);
fkconstraint->pktable->relname);
while (fk_attr != NIL)
{
@ -1502,7 +1514,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
*/
fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
fk_trigger->trigname = fkconstraint->constr_name;
fk_trigger->relname = fkconstraint->pktable_name;
fk_trigger->relation = fkconstraint->pktable;
fk_trigger->before = false;
fk_trigger->row = true;
fk_trigger->actions[0] = 'd';
@ -1515,7 +1527,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
fk_trigger->isconstraint = true;
fk_trigger->deferrable = fkconstraint->deferrable;
fk_trigger->initdeferred = fkconstraint->initdeferred;
fk_trigger->constrrelname = cxt->relname;
fk_trigger->constrrel = cxt->relation;
switch ((fkconstraint->actions & FKCONSTR_ON_DELETE_MASK)
>> FKCONSTR_ON_DELETE_SHIFT)
{
@ -1545,9 +1557,9 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->constr_name));
fk_trigger->args = lappend(fk_trigger->args,
makeString(cxt->relname));
makeString((cxt->relation)->relname));
fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->pktable_name));
makeString(fkconstraint->pktable->relname));
fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->match_type));
fk_attr = fkconstraint->fk_attrs;
@ -1574,7 +1586,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
*/
fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt);
fk_trigger->trigname = fkconstraint->constr_name;
fk_trigger->relname = fkconstraint->pktable_name;
fk_trigger->relation = fkconstraint->pktable;
fk_trigger->before = false;
fk_trigger->row = true;
fk_trigger->actions[0] = 'u';
@ -1587,7 +1599,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
fk_trigger->isconstraint = true;
fk_trigger->deferrable = fkconstraint->deferrable;
fk_trigger->initdeferred = fkconstraint->initdeferred;
fk_trigger->constrrelname = cxt->relname;
fk_trigger->constrrel = cxt->relation;
switch ((fkconstraint->actions & FKCONSTR_ON_UPDATE_MASK)
>> FKCONSTR_ON_UPDATE_SHIFT)
{
@ -1617,9 +1629,9 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt)
fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->constr_name));
fk_trigger->args = lappend(fk_trigger->args,
makeString(cxt->relname));
makeString((cxt->relation)->relname));
fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->pktable_name));
makeString(fkconstraint->pktable->relname));
fk_trigger->args = lappend(fk_trigger->args,
makeString(fkconstraint->match_type));
fk_attr = fkconstraint->fk_attrs;
@ -1672,7 +1684,7 @@ transformIndexStmt(ParseState *pstate, IndexStmt *stmt)
* easily support predicates on indexes created implicitly by
* 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 */
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
* entry, however.
*/
heap_close(heap_openr(stmt->object->relname, AccessExclusiveLock),
heap_close(heap_openr(stmt->relation->relname, AccessExclusiveLock),
NoLock);
/*
@ -1721,11 +1733,11 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
* rule qualification.
*/
Assert(pstate->p_rtable == NIL);
oldrte = addRangeTableEntry(pstate, stmt->object->relname,
makeAttr("*OLD*", NULL),
oldrte = addRangeTableEntry(pstate, stmt->relation->relname,
makeAlias("*OLD*", NIL),
false, true);
newrte = addRangeTableEntry(pstate, stmt->object->relname,
makeAttr("*NEW*", NULL),
newrte = addRangeTableEntry(pstate, stmt->relation->relname,
makeAlias("*NEW*", NIL),
false, true);
/* Must override addRangeTableEntry's default access-check flags */
oldrte->checkForRead = false;
@ -1812,11 +1824,11 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
* or they won't be accessible at all. We decide later
* whether to put them in the joinlist.
*/
oldrte = addRangeTableEntry(sub_pstate, stmt->object->relname,
makeAttr("*OLD*", NULL),
oldrte = addRangeTableEntry(sub_pstate, stmt->relation->relname,
makeAlias("*OLD*", NIL),
false, false);
newrte = addRangeTableEntry(sub_pstate, stmt->object->relname,
makeAttr("*NEW*", NULL),
newrte = addRangeTableEntry(sub_pstate, stmt->relation->relname,
makeAlias("*NEW*", NIL),
false, false);
oldrte->checkForRead = false;
newrte->checkForRead = false;
@ -1950,8 +1962,8 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
if (!IsTransactionBlock())
elog(ERROR, "DECLARE CURSOR may only be used in begin/end transaction blocks");
qry->into = stmt->portalname;
qry->isTemp = stmt->istemp;
qry->into = makeNode(RangeVar);
qry->into->relname = stmt->portalname;
qry->isPortal = TRUE;
qry->isBinary = stmt->binary; /* internal portal */
}
@ -1959,7 +1971,6 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
{
/* SELECT */
qry->into = stmt->into;
qry->isTemp = stmt->istemp;
qry->isPortal = FALSE;
qry->isBinary = FALSE;
}
@ -2033,8 +2044,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
int leftmostRTI;
Query *leftmostQuery;
SetOperationStmt *sostmt;
char *into;
bool istemp;
RangeVar *into;
List *intoColNames;
char *portalname;
bool binary;
@ -2065,14 +2075,12 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
Assert(leftmostSelect && IsA(leftmostSelect, SelectStmt) &&
leftmostSelect->larg == NULL);
into = leftmostSelect->into;
istemp = leftmostSelect->istemp;
intoColNames = leftmostSelect->intoColNames;
portalname = stmt->portalname;
binary = stmt->binary;
/* clear them to prevent complaints in transformSetOperationTree() */
leftmostSelect->into = NULL;
leftmostSelect->istemp = false;
leftmostSelect->intoColNames = NIL;
stmt->portalname = NULL;
stmt->binary = false;
@ -2174,8 +2182,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
if (!IsTransactionBlock())
elog(ERROR, "DECLARE CURSOR may only be used in begin/end transaction blocks");
qry->into = portalname;
qry->isTemp = istemp;
qry->into = makeNode(RangeVar);
qry->into->relname = portalname;
qry->isPortal = TRUE;
qry->isBinary = binary; /* internal portal */
}
@ -2183,7 +2191,6 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
{
/* SELECT */
qry->into = into;
qry->isTemp = istemp;
qry->isPortal = FALSE;
qry->isBinary = FALSE;
}
@ -2325,8 +2332,7 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt)
sprintf(selectName, "*SELECT* %d", length(pstate->p_rtable) + 1);
rte = addRangeTableEntryForSubquery(pstate,
selectQuery,
makeAttr(pstrdup(selectName),
NULL),
makeAlias(selectName, NIL),
false);
/*
@ -2468,8 +2474,8 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
qry->commandType = CMD_UPDATE;
pstate->p_is_update = true;
qry->resultRelation = setTargetTable(pstate, stmt->relname,
interpretInhOption(stmt->inhOpt),
qry->resultRelation = setTargetTable(pstate, stmt->relation->relname,
interpretInhOption(stmt->relation->inhOpt),
true);
/*
@ -2553,11 +2559,11 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
{
case 'A':
cxt.stmtType = "ALTER TABLE";
cxt.relname = stmt->relname;
cxt.inhRelnames = NIL;
cxt.istemp = is_temp_rel_name(stmt->relname);
cxt.relation = stmt->relation;
cxt.inhRelations = NIL;
cxt.relation->istemp = is_temp_rel_name(stmt->relation->relname);
cxt.relOid = GetSysCacheOid(RELNAME,
PointerGetDatum(stmt->relname),
PointerGetDatum((stmt->relation)->relname),
0, 0, 0);
cxt.hasoids = SearchSysCacheExists(ATTNUM,
ObjectIdGetDatum(cxt.relOid),
@ -2585,11 +2591,11 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
case 'C':
cxt.stmtType = "ALTER TABLE";
cxt.relname = stmt->relname;
cxt.inhRelnames = NIL;
cxt.istemp = is_temp_rel_name(stmt->relname);
cxt.relation = stmt->relation;
cxt.inhRelations = NIL;
cxt.relation->istemp = is_temp_rel_name(stmt->relation->relname);
cxt.relOid = GetSysCacheOid(RELNAME,
PointerGetDatum(stmt->relname),
PointerGetDatum((stmt->relation)->relname),
0, 0, 0);
cxt.hasoids = SearchSysCacheExists(ATTNUM,
ObjectIdGetDatum(cxt.relOid),
@ -2713,15 +2719,18 @@ transformTypeRefsList(ParseState *pstate, List *l)
static void
transformTypeRef(ParseState *pstate, TypeName *tn)
{
Attr *att;
ColumnRef *cref;
Node *n;
Var *v;
char *tyn;
if (tn->attrname == NULL)
return;
att = makeAttr(tn->name, tn->attrname);
n = transformExpr(pstate, (Node *) att, EXPR_COLUMN_FIRST);
/* XXX this needs work; can't type name be qualified? */
cref = makeNode(ColumnRef);
cref->fields = makeList2(makeString(tn->name), makeString(tn->attrname));
cref->indirection = NIL;
n = transformExpr(pstate, (Node *) cref);
if (!IsA(n, Var))
elog(ERROR, "unsupported expression in %%TYPE");
v = (Var *) n;
@ -2791,7 +2800,7 @@ transformForUpdate(Query *qry, List *forUpdate)
RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
++i;
if (strcmp(rte->eref->relname, relname) == 0)
if (strcmp(rte->eref->aliasname, relname) == 0)
{
if (rte->subquery)
{
@ -2835,11 +2844,11 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid)
/*
* 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)
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
@ -2901,7 +2910,7 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid)
}
if (!found)
elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found",
fkconstraint->pktable_name);
fkconstraint->pktable->relname);
freeList(indexoidlist);
heap_close(pkrel, AccessShareLock);
@ -2928,11 +2937,11 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
/*
* 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)
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
@ -2965,7 +2974,7 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
*/
if (indexStruct == NULL)
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
@ -2977,8 +2986,6 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
Ident *pkattr = makeNode(Ident);
pkattr->name = pstrdup(NameStr(*attnumAttName(pkrel, pkattno)));
pkattr->indirection = NIL;
pkattr->isRel = false;
pktypoid[attnum++] = attnumTypeId(pkrel, pkattno);
fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr);
@ -3070,14 +3077,14 @@ transformFkeyGetColType(CreateStmtContext *cxt, char *colname)
if (sysatt)
return sysatt->atttypid;
/* 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;
int count;
Assert(IsA(inh, String));
rel = heap_openr(strVal(inh), AccessShareLock);
Assert(IsA(inh, RangeVar));
rel = heap_openr(inh->relname, AccessShareLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "inherited table \"%s\" is not a relation",
strVal(inh));
@ -3248,3 +3255,104 @@ transformColumnType(ParseState *pstate, ColumnDef *column)
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
* $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);
attname = get_rte_attribute_name(rte, var->varattno);
elog(ERROR, "Attribute %s.%s must be GROUPed or used in an aggregate function",
rte->eref->relname, attname);
rte->eref->aliasname, attname);
}
/* Otherwise, recurse. */
return expression_tree_walker(node, check_ungrouped_columns_walker,
@ -188,8 +188,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry, Node *qual)
Aggref *
ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
List *args, bool agg_star, bool agg_distinct,
int precedence)
List *args, bool agg_star, bool agg_distinct)
{
HeapTuple aggtuple;
Form_pg_aggregate aggform;

View File

@ -8,7 +8,7 @@
*
*
* 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
* 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
@ -326,7 +326,7 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j,
pstate->p_namespace = makeList2(j->larg, j->rarg);
/* 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))
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))
{
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);
@ -375,7 +375,7 @@ transformTableEntry(ParseState *pstate, RangeVar *r)
* automatically generate the range variable if not specified. However
* 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);
/*
@ -408,7 +408,7 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
* relax this, we'd have to be prepared to gin up a unique alias for
* an unlabeled subselect.
*/
if (r->name == NULL)
if (r->alias == NULL)
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.
*/
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
@ -748,11 +748,11 @@ transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels)
*/
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",
j->alias->relname);
j->alias->aliasname);
}
}
@ -791,7 +791,7 @@ transformWhereClause(ParseState *pstate, Node *clause)
if (clause == NULL)
return NULL;
qual = transformExpr(pstate, clause, EXPR_COLUMN_FIRST);
qual = transformExpr(pstate, clause);
if (!coerce_to_boolean(pstate, &qual))
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.
*----------
*/
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)
{
@ -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
* ignore resjunk targets.
*/
expr = transformExpr(pstate, node, EXPR_COLUMN_FIRST);
expr = transformExpr(pstate, node);
foreach(tl, tlist)
{

View File

@ -8,7 +8,7 @@
*
*
* 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_proc.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/params.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_expression(ParseState *pstate,
Node *expr, TypeName *typename);
static Node *transformAttr(ParseState *pstate, Attr *att, int precedence);
static Node *transformIdent(ParseState *pstate, Ident *ident, int precedence);
static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
static Node *transformIndirection(ParseState *pstate, Node *basenode,
List *indirection);
@ -85,7 +85,7 @@ parse_expr_init(void)
* input and output of transformExpr; see SubLink for example.
*/
Node *
transformExpr(ParseState *pstate, Node *expr, int precedence)
transformExpr(ParseState *pstate, Node *expr)
{
Node *result = NULL;
@ -105,9 +105,37 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
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;
}
case T_A_Const:
@ -121,31 +149,28 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
result = (Node *) make_const(val);
break;
}
case T_ParamNo:
case T_ExprFieldSelect:
{
ParamNo *pno = (ParamNo *) expr;
int paramno = pno->number;
Oid toid = param_type(paramno);
Param *param = makeNode(Param);
ExprFieldSelect *efs = (ExprFieldSelect *) expr;
List *fields;
if (!OidIsValid(toid))
elog(ERROR, "Parameter '$%d' is out of range", paramno);
param->paramkind = PARAM_NUM;
param->paramid = (AttrNumber) paramno;
param->paramname = "<unnamed>";
param->paramtype = toid;
result = transformIndirection(pstate, (Node *) param,
pno->indirection);
/* cope with typecast applied to param */
if (pno->typename != NULL)
result = parser_typecast_expression(pstate, result,
pno->typename);
result = transformExpr(pstate, efs->arg);
/* handle qualification, if any */
foreach(fields, efs->fields)
{
result = ParseFuncOrColumn(pstate, strVal(lfirst(fields)),
makeList1(result),
false, false, true);
}
/* handle subscripts, if any */
result = transformIndirection(pstate, result,
efs->indirection);
break;
}
case T_TypeCast:
{
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);
break;
@ -179,17 +204,14 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
n->arg = a->lexpr;
result = transformExpr(pstate,
(Node *) n,
precedence);
(Node *) n);
}
else
{
Node *lexpr = transformExpr(pstate,
a->lexpr,
precedence);
a->lexpr);
Node *rexpr = transformExpr(pstate,
a->rexpr,
precedence);
a->rexpr);
result = (Node *) make_op(a->opname,
lexpr,
@ -200,11 +222,9 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
case AND:
{
Node *lexpr = transformExpr(pstate,
a->lexpr,
precedence);
a->lexpr);
Node *rexpr = transformExpr(pstate,
a->rexpr,
precedence);
a->rexpr);
Expr *expr = makeNode(Expr);
if (!coerce_to_boolean(pstate, &lexpr))
@ -226,11 +246,9 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
case OR:
{
Node *lexpr = transformExpr(pstate,
a->lexpr,
precedence);
a->lexpr);
Node *rexpr = transformExpr(pstate,
a->rexpr,
precedence);
a->rexpr);
Expr *expr = makeNode(Expr);
if (!coerce_to_boolean(pstate, &lexpr))
@ -252,8 +270,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
case NOT:
{
Node *rexpr = transformExpr(pstate,
a->rexpr,
precedence);
a->rexpr);
Expr *expr = makeNode(Expr);
if (!coerce_to_boolean(pstate, &rexpr))
@ -270,11 +287,6 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
}
break;
}
case T_Ident:
{
result = transformIdent(pstate, (Ident *) expr, precedence);
break;
}
case T_FuncCall:
{
FuncCall *fn = (FuncCall *) expr;
@ -283,14 +295,13 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
/* transform the list of arguments */
foreach(args, fn->args)
lfirst(args) = transformExpr(pstate,
(Node *) lfirst(args),
precedence);
(Node *) lfirst(args));
result = ParseFuncOrColumn(pstate,
fn->funcname,
fn->args,
fn->agg_star,
fn->agg_distinct,
precedence);
false);
break;
}
case T_SubLink:
@ -357,8 +368,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
List *elist;
foreach(elist, left_list)
lfirst(elist) = transformExpr(pstate, lfirst(elist),
precedence);
lfirst(elist) = transformExpr(pstate, lfirst(elist));
Assert(IsA(sublink->oper, A_Expr));
op = ((A_Expr *) sublink->oper)->opname;
@ -455,7 +465,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
a->rexpr = warg;
warg = (Node *) a;
}
neww->expr = transformExpr(pstate, warg, precedence);
neww->expr = transformExpr(pstate, warg);
if (!coerce_to_boolean(pstate, &neww->expr))
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;
warg = (Node *) n;
}
neww->result = transformExpr(pstate, warg, precedence);
neww->result = transformExpr(pstate, warg);
newargs = lappend(newargs, neww);
typeids = lappendi(typeids, exprType(neww->result));
@ -496,7 +506,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
n->val.type = T_Null;
defresult = (Node *) n;
}
newc->defresult = transformExpr(pstate, defresult, precedence);
newc->defresult = transformExpr(pstate, defresult);
/*
* Note: default result is considered the most significant
@ -534,7 +544,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
{
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 */
result = expr;
break;
@ -544,7 +554,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
{
BooleanTest *b = (BooleanTest *) expr;
b->arg = transformExpr(pstate, b->arg, precedence);
b->arg = transformExpr(pstate, b->arg);
if (!coerce_to_boolean(pstate, &b->arg))
{
@ -627,47 +637,183 @@ transformIndirection(ParseState *pstate, Node *basenode, List *indirection)
}
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);
}
static Node *
transformIdent(ParseState *pstate, Ident *ident, int precedence)
{
Node *result = NULL;
int sublevels_up;
/*
* try to find the ident as a relation ... but not if subscripts
* appear
/*----------
* 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.)
*----------
*/
if (ident->indirection == NIL &&
refnameRangeTblEntry(pstate, ident->name, &sublevels_up) != NULL)
switch (numnames)
{
ident->isRel = TRUE;
result = (Node *) ident;
}
if (result == NULL || precedence == EXPR_COLUMN_FIRST)
{
/* try to find the ident as a column */
Node *var = colnameToVar(pstate, ident->name);
if (var != NULL)
case 1:
{
ident->isRel = FALSE;
result = transformIndirection(pstate, var, ident->indirection);
char *name = strVal(lfirst(cref->fields));
/* Try to identify as an unqualified column */
node = colnameToVar(pstate, name);
if (node == NULL)
{
/*
* 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)))));
/*
* We check the catalog name and then ignore it.
*/
if (strcmp(name1, DatabaseName) != 0)
elog(ERROR, "Cross-database references are not implemented");
/* Whole-row reference? */
if (strcmp(name4, "*") == 0)
{
rv = makeNode(RangeVar);
rv->schemaname = name2;
rv->relname = name3;
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, name3, name4, true);
if (node == NULL)
{
/* Try it as a function call */
rv = makeNode(RangeVar);
rv->schemaname = name2;
rv->relname = name3;
rv->inhOpt = INH_DEFAULT;
node = ParseFuncOrColumn(pstate, name4,
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)
elog(ERROR, "Attribute '%s' not found", ident->name);
return result;
return transformIndirection(pstate, node, cref->indirection);
}
/*
@ -748,10 +894,6 @@ exprType(Node *expr)
case T_BooleanTest:
type = BOOLOID;
break;
case T_Ident:
/* XXX is this right? */
type = UNKNOWNOID;
break;
default:
elog(ERROR, "Do not know how to get type for %d node",
nodeTag(expr));

View File

@ -8,11 +8,10 @@
*
*
* 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 "access/genam.h"
@ -36,8 +35,7 @@
static Node *ParseComplexProjection(ParseState *pstate,
char *funcname,
Node *first_arg,
bool *attisset);
Node *first_arg);
static Oid **argtype_inherit(int nargs, Oid *argtypes);
static int find_inheritors(Oid relid, Oid **supervec);
@ -60,75 +58,31 @@ static Oid agg_select_candidate(Oid typeid, CandidateList candidates);
/*
** ParseNestedFuncOrColumn
** 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
* Parse a function call
*
* This code is confusing because the database can accept
* relation.column, column.function, or relation.column.function.
* In these cases, funcname is the last parameter, and fargs are
* the rest.
* For historical reasons, Postgres tries to treat the notations tab.col
* and col(tab) as equivalent: if a single-argument function call has an
* argument of complex type and the function name matches any attribute
* of the type, we take it as a column projection.
*
* It can also be called as func(col) or func(col,col).
* In this case, Funcname is the part before parens, and fargs
* are the part in parens.
*
* FYI, projection is choosing column from a table.
* Hence, both cases come through here. The is_column parameter tells us
* which syntactic construct is actually being dealt with, but this is
* intended to be used only to deliver an appropriate error message,
* not to affect the semantics. When is_column is true, we should have
* 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 *
ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
bool agg_star, bool agg_distinct,
int precedence)
bool agg_star, bool agg_distinct, bool is_column)
{
Oid rettype = InvalidOid;
Oid argrelid = InvalidOid;
Oid funcid = InvalidOid;
List *i = NIL;
Oid rettype;
Oid funcid;
List *i;
Node *first_arg = NULL;
char *refname;
int nargs = length(fargs);
@ -140,9 +94,8 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
bool retset;
bool must_be_agg = agg_star || agg_distinct;
bool could_be_agg;
bool attisset = false;
Oid toid = InvalidOid;
Expr *expr;
FuncDetailCode fdresult;
/*
* 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)
{
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);
}
/*
* test for relation.column
*
* 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.
* check for column projection: if function has one argument, and that
* argument is of complex type, then the function could be a projection.
*/
/* We only have one parameter, and it's not got aggregate decoration */
if (nargs == 1 && !must_be_agg)
{
/* Is it a plain Relation name from the parser? */
if (IsA(first_arg, Ident) &&((Ident *) first_arg)->isRel)
/* Is it a not-yet-transformed RangeVar node? */
if (IsA(first_arg, RangeVar))
{
Ident *ident = (Ident *) first_arg;
/* First arg is a relation. This could be a projection. */
refname = ident->name;
refname = ((RangeVar *) first_arg)->relname;
retval = qualifiedNameToVar(pstate, refname, funcname, true);
if (retval)
return retval;
/* else drop through - attr is a set or function */
}
else if (ISCOMPLEX(exprType(first_arg)))
{
@ -194,24 +140,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
*/
retval = ParseComplexProjection(pstate,
funcname,
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);
}
first_arg);
if (retval)
return retval;
}
@ -226,15 +155,14 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
if (nargs != 1)
elog(ERROR, "Aggregate functions may only have one parameter");
/* 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");
could_be_agg = true;
}
else
{
/* Try to parse as an aggregate if above-mentioned checks are OK */
could_be_agg = (nargs == 1) &&
!(IsA(first_arg, Ident) &&((Ident *) first_arg)->isRel);
could_be_agg = (nargs == 1) && !(IsA(first_arg, RangeVar));
}
if (could_be_agg)
@ -249,8 +177,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
ObjectIdGetDatum(basetype),
0, 0))
return (Node *) ParseAgg(pstate, funcname, basetype,
fargs, agg_star, agg_distinct,
precedence);
fargs, agg_star, agg_distinct);
/* check for aggregate-that-accepts-any-type (eg, COUNT) */
if (SearchSysCacheExists(AGGNAME,
@ -258,8 +185,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
ObjectIdGetDatum(0),
0, 0))
return (Node *) ParseAgg(pstate, funcname, 0,
fargs, agg_star, agg_distinct,
precedence);
fargs, agg_star, agg_distinct);
/*
* 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;
return (Node *) ParseAgg(pstate, funcname, basetype,
fargs, agg_star, agg_distinct,
precedence);
fargs, agg_star, agg_distinct);
}
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,
* which is implemented as a function). Extract arg type info and
* transform relation name arguments into varnodes of the appropriate
* form.
* Okay, it's not a column projection, so it must really be a function.
* Extract arg type info and transform RangeVar arguments into varnodes
* of the appropriate form.
*/
MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
@ -311,8 +235,9 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
foreach(i, fargs)
{
Node *arg = lfirst(i);
Oid toid;
if (IsA(arg, Ident) &&((Ident *) arg)->isRel)
if (IsA(arg, RangeVar))
{
RangeTblEntry *rte;
int vnum;
@ -321,7 +246,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
/*
* a relation
*/
refname = ((Ident *) arg)->name;
refname = ((RangeVar *) arg)->relname;
rte = refnameRangeTblEntry(pstate, refname,
&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
* named tuple type
*/
if (nargs == 1)
{
/*
* 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",
if (is_column)
elog(ERROR, "No such attribute %s.%s",
refname, funcname);
}
else
{
elog(ERROR, "Cannot pass result of sub-select or join %s to a function",
@ -365,93 +283,53 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
toid = typenameTypeId(rte->relname);
/* replace it in the arg list */
/* replace RangeVar in the arg list */
lfirst(i) = makeVar(vnum,
InvalidAttrNumber,
toid,
sizeof(Pointer),
sublevels_up);
}
else if (!attisset)
toid = exprType(arg);
else
{
/* if attisset is true, we already set toid for the single arg */
}
toid = exprType(arg);
oid_array[argn++] = toid;
}
/*
* Is it a set, or a function?
* func_get_detail looks up the function in the catalogs, does
* disambiguation for polymorphic functions, handles inheritance,
* and returns the funcid and type and set or singleton status of
* the function's return value. it also returns the true argument
* types to the 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
fdresult = func_get_detail(funcname, fargs, nargs, oid_array,
&funcid, &rettype, &retset,
&true_oid_array);
if (fdresult == FUNCDETAIL_COERCION)
{
FuncDetailCode fdresult;
/*
* func_get_detail looks up the function in the catalogs, does
* disambiguation for polymorphic functions, handles inheritance,
* and returns the funcid and type and set or singleton status of
* the function's return value. it also returns the true argument
* types to the function.
* We can do it as a trivial coercion. coerce_type can handle
* these cases, so why duplicate code...
*/
fdresult = func_get_detail(funcname, fargs, nargs, oid_array,
&funcid, &rettype, &retset,
&true_oid_array);
if (fdresult == FUNCDETAIL_COERCION)
{
/*
* We can do it as a trivial coercion. coerce_type can handle
* these cases, so why duplicate code...
*/
return coerce_type(pstate, lfirst(fargs),
oid_array[0], rettype, -1);
}
if (fdresult != FUNCDETAIL_NORMAL)
{
/*
* Oops. Time to die.
*
* If there is a single argument of complex type, we might be
* dealing with the PostQuel notation rel.function instead of
* the more usual function(rel). Give a nonspecific error
* message that will cover both cases.
*/
if (nargs == 1)
{
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 */
func_error(NULL, funcname, nargs, oid_array,
"Unable to identify a function that satisfies the "
"given argument types"
"\n\tYou may need to add explicit typecasts");
}
return coerce_type(pstate, lfirst(fargs),
oid_array[0], rettype, -1);
}
if (fdresult != FUNCDETAIL_NORMAL)
{
/*
* Oops. Time to die.
*
* If we are dealing with the attribute notation rel.function,
* give an error message that is appropriate for that case.
*/
if (is_column)
elog(ERROR, "Attribute \"%s\" not found", funcname);
/* Else generate a detailed complaint */
func_error(NULL, funcname, nargs, oid_array,
"Unable to identify a function that satisfies the "
"given argument types"
"\n\tYou may need to add explicit typecasts");
}
/* got it */
@ -470,26 +348,12 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
expr->args = fargs;
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
* 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.
*/
if (retset)
{
Iter *iter = makeNode(Iter);
@ -1497,10 +1361,10 @@ make_arguments(ParseState *pstate,
}
/*
** setup_field_select
** Build a FieldSelect node that says which attribute to project to.
** This routine is called by ParseFuncOrColumn() when we have found
** a projection on a function result or parameter.
* setup_field_select
* Build a FieldSelect node that says which attribute to project to.
* This routine is called by ParseFuncOrColumn() when we have found
* a projection on a function result or parameter.
*/
static FieldSelect *
setup_field_select(Node *input, char *attname, Oid relid)
@ -1521,18 +1385,31 @@ setup_field_select(Node *input, char *attname, Oid relid)
/*
* ParseComplexProjection -
* 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 *
ParseComplexProjection(ParseState *pstate,
char *funcname,
Node *first_arg,
bool *attisset)
Node *first_arg)
{
Oid argtype;
Oid argtype = exprType(first_arg);
Oid argrelid;
AttrNumber attnum;
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))
{
case T_Iter:
@ -1540,75 +1417,42 @@ ParseComplexProjection(ParseState *pstate,
Iter *iter = (Iter *) first_arg;
/*
* If the argument of the Iter returns a tuple, funcname
* may be a projection. If so, we stick the FieldSelect
* If it's an Iter, we stick the FieldSelect
* *inside* the Iter --- this is klugy, but necessary
* because ExecTargetList() currently does the right thing
* only when the Iter node is at the top level of a
* 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,
funcname, argrelid);
iter->iterexpr = (Node *) fselect;
iter->itertype = fselect->resulttype;
return (Node *) iter;
}
fselect = setup_field_select(iter->iterexpr,
funcname, argrelid);
iter->iterexpr = (Node *) fselect;
iter->itertype = fselect->resulttype;
return (Node *) iter;
break;
}
case T_Var:
{
/*
* 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;
Var *var = (Var *) first_arg;
/*
* If the argument is a function returning a tuple,
* funcname may be a projection
* If the Var is a whole-row tuple, we can just replace it
* with a simple Var reference.
*/
funcnode = (Func *) expr->oper;
argtype = funcnode->functype;
argrelid = typeidTypeRelid(argtype);
if (argrelid &&
get_attnum(argrelid, funcname) != InvalidAttrNumber)
if (var->varattno == InvalidAttrNumber)
{
fselect = setup_field_select((Node *) expr,
funcname, argrelid);
return (Node *) fselect;
}
break;
}
case T_Param:
{
Param *param = (Param *) first_arg;
Oid vartype;
int32 vartypmod;
/*
* If the Param is a complex type, this could be a
* projection
*/
argtype = param->paramtype;
argrelid = typeidTypeRelid(argtype);
if (argrelid &&
get_attnum(argrelid, funcname) != InvalidAttrNumber)
{
fselect = setup_field_select((Node *) param,
funcname, argrelid);
return (Node *) fselect;
get_atttypetypmod(argrelid, attnum,
&vartype, &vartypmod);
return (Node *) makeVar(var->varno,
attnum,
vartype,
vartypmod,
var->varlevelsup);
}
break;
}
@ -1616,7 +1460,9 @@ ParseComplexProjection(ParseState *pstate,
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
* $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)
{
subexpr = transformExpr(pstate, ai->lidx, EXPR_COLUMN_FIRST);
subexpr = transformExpr(pstate, ai->lidx);
/* If it's not int4 already, try to coerce */
subexpr = CoerceTargetExpr(pstate, subexpr, exprType(subexpr),
INT4OID, -1);
@ -305,7 +305,7 @@ transformArraySubscripts(ParseState *pstate,
}
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 */
subexpr = CoerceTargetExpr(pstate, subexpr, exprType(subexpr),
INT4OID, -1);

View File

@ -8,7 +8,7 @@
*
*
* 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;
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;
}
else if (IsA(nsnode, JoinExpr))
@ -113,7 +113,7 @@ scanNameSpaceForRefname(ParseState *pstate, Node *nsnode,
if (j->alias)
{
if (strcmp(j->alias->relname, refname) == 0)
if (strcmp(j->alias->aliasname, refname) == 0)
return (Node *) j; /* matched a join alias */
/*
@ -175,7 +175,7 @@ checkNameSpaceConflicts(ParseState *pstate, Node *namespace1,
int varno = ((RangeTblRef *) namespace1)->rtindex;
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))
{
@ -183,7 +183,7 @@ checkNameSpaceConflicts(ParseState *pstate, Node *namespace1,
if (j->alias)
{
scanNameSpaceForConflict(pstate, namespace2, j->alias->relname);
scanNameSpaceForConflict(pstate, namespace2, j->alias->aliasname);
/*
* 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
* multiple matches.
*/
foreach(c, rte->eref->attrs)
foreach(c, rte->eref->colnames)
{
attnum++;
if (strcmp(strVal(lfirst(c)), colname) == 0)
@ -420,15 +420,15 @@ qualifiedNameToVar(ParseState *pstate, char *refname, char *colname,
RangeTblEntry *
addRangeTableEntry(ParseState *pstate,
char *relname,
Attr *alias,
Alias *alias,
bool inh,
bool inFromCl)
{
RangeTblEntry *rte = makeNode(RangeTblEntry);
char *refname = alias ? alias->relname : relname;
char *refname = alias ? alias->aliasname : relname;
LOCKMODE lockmode;
Relation rel;
Attr *eref;
Alias *eref;
int maxattrs;
int numaliases;
int varattno;
@ -447,8 +447,8 @@ addRangeTableEntry(ParseState *pstate,
rel = heap_openr(relname, lockmode);
rte->relid = RelationGetRelid(rel);
eref = alias ? (Attr *) copyObject(alias) : makeAttr(refname, NULL);
numaliases = length(eref->attrs);
eref = alias ? (Alias *) copyObject(alias) : makeAlias(refname, NIL);
numaliases = length(eref->colnames);
/*
* 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",
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++)
{
char *attrname;
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;
@ -512,12 +512,12 @@ addRangeTableEntry(ParseState *pstate,
RangeTblEntry *
addRangeTableEntryForSubquery(ParseState *pstate,
Query *subquery,
Attr *alias,
Alias *alias,
bool inFromCl)
{
RangeTblEntry *rte = makeNode(RangeTblEntry);
char *refname = alias->relname;
Attr *eref;
char *refname = alias->aliasname;
Alias *eref;
int numaliases;
int varattno;
List *tlistitem;
@ -529,7 +529,7 @@ addRangeTableEntryForSubquery(ParseState *pstate,
rte->alias = alias;
eref = copyObject(alias);
numaliases = length(eref->attrs);
numaliases = length(eref->colnames);
/* fill in any unspecified alias columns */
varattno = 0;
@ -546,7 +546,7 @@ addRangeTableEntryForSubquery(ParseState *pstate,
char *attrname;
attrname = pstrdup(te->resdom->resname);
eref->attrs = lappend(eref->attrs, makeString(attrname));
eref->colnames = lappend(eref->colnames, makeString(attrname));
}
}
if (varattno < numaliases)
@ -594,11 +594,11 @@ addRangeTableEntryForJoin(ParseState *pstate,
List *coltypmods,
List *leftcols,
List *rightcols,
Attr *alias,
Alias *alias,
bool inFromCl)
{
RangeTblEntry *rte = makeNode(RangeTblEntry);
Attr *eref;
Alias *eref;
int numaliases;
rte->rtekind = RTE_JOIN;
@ -612,15 +612,15 @@ addRangeTableEntryForJoin(ParseState *pstate,
rte->joinrightcols = rightcols;
rte->alias = alias;
eref = alias ? (Attr *) copyObject(alias) : makeAttr("unnamed_join", NULL);
numaliases = length(eref->attrs);
eref = alias ? (Alias *) copyObject(alias) : makeAlias("unnamed_join", NIL);
numaliases = length(eref->colnames);
/* fill in any unspecified alias columns */
if (numaliases < length(colnames))
{
while (numaliases-- > 0)
colnames = lnext(colnames);
eref->attrs = nconc(eref->attrs, colnames);
eref->colnames = nconc(eref->colnames, colnames);
}
rte->eref = eref;
@ -759,7 +759,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
rel = heap_openr(rte->relname, AccessShareLock);
maxattrs = RelationGetNumberOfAttributes(rel);
numaliases = length(rte->eref->attrs);
numaliases = length(rte->eref->colnames);
for (varattno = 0; varattno < maxattrs; varattno++)
{
@ -775,7 +775,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
char *label;
if (varattno < numaliases)
label = strVal(nth(varattno, rte->eref->attrs));
label = strVal(nth(varattno, rte->eref->colnames));
else
label = NameStr(attr->attname);
*colnames = lappend(*colnames, makeString(pstrdup(label)));
@ -798,7 +798,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
else if (rte->rtekind == RTE_SUBQUERY)
{
/* Subquery RTE */
List *aliasp = rte->eref->attrs;
List *aliasp = rte->eref->colnames;
List *tlistitem;
varattno = 0;
@ -836,7 +836,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
else if (rte->rtekind == RTE_JOIN)
{
/* Join RTE */
List *aliasp = rte->eref->attrs;
List *aliasp = rte->eref->colnames;
List *coltypes = rte->joincoltypes;
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
* for non-relation RTEs.)
*/
if (attnum > 0 && attnum <= length(rte->eref->attrs))
return strVal(nth(attnum - 1, rte->eref->attrs));
if (attnum > 0 && attnum <= length(rte->eref->colnames))
return strVal(nth(attnum - 1, rte->eref->colnames));
/*
* 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)
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
@ -1002,7 +1002,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
}
/* falling off end of list shouldn't happen... */
elog(ERROR, "Subquery %s does not have attribute %d",
rte->eref->relname, attnum);
rte->eref->aliasname, attnum);
}
else if (rte->rtekind == RTE_JOIN)
{

View File

@ -8,13 +8,13 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.77 2002/03/12 00:51:56 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.78 2002/03/21 16:01:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "parser/parsetree.h"
#include "parser/parse_coerce.h"
@ -56,9 +56,9 @@ transformTargetEntry(ParseState *pstate,
/* Transform the node if caller didn't do it already */
if (expr == NULL)
expr = transformExpr(pstate, node, EXPR_COLUMN_FIRST);
expr = transformExpr(pstate, node);
if (IsA(expr, Ident) &&((Ident *) expr)->isRel)
if (IsA(expr, RangeVar))
elog(ERROR, "You can't use relation names alone in the target list, try relation.*.");
type_id = exprType(expr);
@ -99,11 +99,13 @@ transformTargetList(ParseState *pstate, List *targetlist)
{
ResTarget *res = (ResTarget *) lfirst(targetlist);
if (IsA(res->val, Attr))
if (IsA(res->val, ColumnRef))
{
Attr *att = (Attr *) res->val;
ColumnRef *cref = (ColumnRef *) res->val;
List *fields = cref->fields;
int numnames = length(fields);
if (att->relname != NULL && strcmp(att->relname, "*") == 0)
if (numnames == 1 && strcmp(strVal(lfirst(fields)), "*") == 0)
{
/*
* Target item is a single '*', expand all tables (eg.
@ -112,27 +114,59 @@ transformTargetList(ParseState *pstate, List *targetlist)
p_target = nconc(p_target,
ExpandAllTables(pstate));
}
else if (att->attrs != NIL &&
strcmp(strVal(lfirst(att->attrs)), "*") == 0)
else if (strcmp(strVal(nth(numnames-1, fields)), "*") == 0)
{
/*
* Target item is relation.*, expand that table (eg.
* SELECT emp.*, dname FROM emp, dept)
*/
char *schemaname;
char *relname;
RangeTblEntry *rte;
int sublevels_up;
rte = refnameRangeTblEntry(pstate, att->relname,
switch (numnames)
{
case 2:
schemaname = NULL;
relname = strVal(lfirst(fields));
break;
case 3:
schemaname = strVal(lfirst(fields));
relname = strVal(lsecond(fields));
break;
case 4:
{
char *name1 = strVal(lfirst(fields));
/*
* We check the catalog name and then ignore it.
*/
if (strcmp(name1, DatabaseName) != 0)
elog(ERROR, "Cross-database references are not implemented");
schemaname = strVal(lsecond(fields));
relname = strVal(lfirst(lnext(lnext(fields))));
break;
}
default:
elog(ERROR, "Invalid qualified name syntax (too many names)");
schemaname = NULL; /* keep compiler quiet */
relname = NULL;
break;
}
/* XXX do something with schema name */
rte = refnameRangeTblEntry(pstate, relname,
&sublevels_up);
if (rte == NULL)
rte = addImplicitRTE(pstate, att->relname);
rte = addImplicitRTE(pstate, relname);
p_target = nconc(p_target,
expandRelAttrs(pstate, rte));
}
else
{
/* Plain Attr node, treat it as an expression */
/* Plain ColumnRef node, treat it as an expression */
p_target = lappend(p_target,
transformTargetEntry(pstate,
res->val,
@ -143,7 +177,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
}
else
{
/* Everything else but Attr */
/* Everything else but ColumnRef */
p_target = lappend(p_target,
transformTargetEntry(pstate,
res->val,
@ -317,10 +351,9 @@ CoerceTargetExpr(ParseState *pstate,
/*
* checkInsertTargets -
* generate a list of column names if not supplied or
* generate a list of INSERT column targets if not supplied, or
* test supplied column names to make sure they are in target table.
* Also return an integer list of the columns' attribute numbers.
* (used exclusively for inserts)
*/
List *
checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
@ -338,17 +371,16 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
for (i = 0; i < numcol; i++)
{
Ident *id = makeNode(Ident);
ResTarget *col = makeNode(ResTarget);
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(attr[i]))
continue;
#endif /* _DROP_COLUMN_HACK__ */
id->name = palloc(NAMEDATALEN);
StrNCpy(id->name, NameStr(attr[i]->attname), NAMEDATALEN);
id->indirection = NIL;
id->isRel = false;
cols = lappend(cols, id);
col->name = pstrdup(NameStr(attr[i]->attname));
col->indirection = NIL;
col->val = NULL;
cols = lappend(cols, col);
*attrnos = lappendi(*attrnos, i + 1);
}
}
@ -361,7 +393,7 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
foreach(tl, cols)
{
char *name = ((Ident *) lfirst(tl))->name;
char *name = ((ResTarget *) lfirst(tl))->name;
int attrno;
/* Lookup column name, elog on failure */
@ -458,19 +490,35 @@ FigureColnameInternal(Node *node, char **name)
case T_Ident:
*name = ((Ident *) node)->name;
return 2;
case T_Attr:
case T_ColumnRef:
{
List *attrs = ((Attr *) node)->attrs;
List *fields = ((ColumnRef *) node)->fields;
if (attrs)
while (lnext(fields) != NIL)
fields = lnext(fields);
if (strcmp(strVal(lfirst(fields)), "*") != 0)
{
while (lnext(attrs) != NIL)
attrs = lnext(attrs);
*name = strVal(lfirst(attrs));
*name = strVal(lfirst(fields));
return 2;
}
}
break;
case T_ExprFieldSelect:
{
List *fields = ((ExprFieldSelect *) node)->fields;
if (fields)
{
while (lnext(fields) != NIL)
fields = lnext(fields);
if (strcmp(strVal(lfirst(fields)), "*") != 0)
{
*name = strVal(lfirst(fields));
return 2;
}
}
}
break;
case T_FuncCall:
*name = ((FuncCall *) node)->funcname;
return 2;

View File

@ -8,7 +8,7 @@
*
*
* 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;
}
/*
* 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
DefineQueryRewrite(RuleStmt *stmt)
{
CmdType event_type = stmt->event;
Attr *event_obj = stmt->object;
RangeVar *event_obj = stmt->relation;
Node *event_qual = stmt->whereClause;
CmdType event_type = stmt->event;
bool is_instead = stmt->instead;
List *action = stmt->actions;
Relation event_relation;
Oid ev_relid;
Oid ruleId;
char *eslot_string = NULL;
int event_attno;
Oid event_attype;
char *actionP,
@ -186,23 +140,6 @@ DefineQueryRewrite(RuleStmt *stmt)
event_relation = heap_openr(event_obj->relname, AccessExclusiveLock);
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
*/
@ -358,21 +295,8 @@ DefineQueryRewrite(RuleStmt *stmt)
/*
* This rule is allowed - prepare to install it.
*/
if (eslot_string == NULL)
{
event_attno = -1;
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);
event_attno = -1;
event_attype = InvalidOid;
/*
* We want the rule's table references to be checked as though by the

View File

@ -7,7 +7,7 @@
*
*
* 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.
*/
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 &&
strcmp(rt_fetch(PRS2_NEW_VARNO, parsetree->rtable)->eref->relname,
strcmp(rt_fetch(PRS2_NEW_VARNO, parsetree->rtable)->eref->aliasname,
"*NEW*") == 0)
return parsetree;
Assert(parsetree->jointree && IsA(parsetree->jointree, FromExpr));
@ -589,9 +589,9 @@ getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr)
selectquery->commandType == CMD_SELECT))
elog(ERROR, "getInsertSelectQuery: expected to find SELECT subquery");
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 &&
strcmp(rt_fetch(PRS2_NEW_VARNO, selectquery->rtable)->eref->relname,
strcmp(rt_fetch(PRS2_NEW_VARNO, selectquery->rtable)->eref->aliasname,
"*NEW*") == 0)
{
if (subquery_ptr)

View File

@ -8,7 +8,7 @@
*
*
* 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
* this is the "main" module of the postgres backend and
@ -1722,7 +1722,7 @@ PostgresMain(int argc, char *argv[], const char *username)
if (!IsUnderPostmaster)
{
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";
break;
case T_CreateSchemaStmt:
tag = "CREATE";
break;
case T_CreateStmt:
tag = "CREATE";
break;

View File

@ -8,7 +8,7 @@
*
*
* 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)
{
intoName = parsetree->into;
intoName = parsetree->into->relname;
portal = PreparePortal(intoName);
oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
parsetree = copyObject(parsetree);
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,

View File

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

View File

@ -3,7 +3,7 @@
* back to source text
*
* 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.
*
@ -48,6 +48,7 @@
#include "catalog/pg_shadow.h"
#include "executor/spi.h"
#include "lib/stringinfo.h"
#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/tlist.h"
#include "parser/keywords.h"
@ -659,8 +660,7 @@ deparse_context_for(char *relname, Oid relid)
rte->rtekind = RTE_RELATION;
rte->relname = relname;
rte->relid = relid;
rte->eref = makeNode(Attr);
rte->eref->relname = relname;
rte->eref = makeAlias(relname, NIL);
rte->inh = false;
rte->inFromCl = true;
@ -755,9 +755,7 @@ deparse_context_for_subplan(const char *name, List *tlist,
rte->rtekind = RTE_SPECIAL; /* XXX */
rte->relname = pstrdup(name);
rte->relid = InvalidOid;
rte->eref = makeNode(Attr);
rte->eref->relname = rte->relname;
rte->eref->attrs = attrs;
rte->eref = makeAlias(rte->relname, attrs);
rte->inh = false;
rte->inFromCl = true;
@ -1462,7 +1460,7 @@ get_utility_query_def(Query *query, deparse_context *context)
{
NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt;
appendStringInfo(buf, "NOTIFY %s", quote_identifier(stmt->relname));
appendStringInfo(buf, "NOTIFY %s", quote_identifier(stmt->relation->relname));
}
else
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)
*refname = NULL;
else
*refname = rte->eref->relname;
*refname = rte->eref->aliasname;
if (var->varattno == InvalidAttrNumber)
*attname = NULL;
@ -1758,12 +1756,11 @@ get_rule_expr(Node *node, deparse_context *context)
/*
* If the argument is simple enough, we could emit
* arg.fieldname, but most cases where FieldSelect is used
* are *not* simple. For now, always use the projection-
* function syntax.
* are *not* simple. So, always use parenthesized syntax.
*/
appendStringInfo(buf, "%s(", quote_identifier(fieldname));
appendStringInfoChar(buf, '(');
get_rule_expr(fselect->arg, context);
appendStringInfoChar(buf, ')');
appendStringInfo(buf, ").%s", quote_identifier(fieldname));
}
break;
@ -2302,9 +2299,9 @@ get_from_clause(Query *query, deparse_context *context)
if (!rte->inFromCl)
continue;
if (strcmp(rte->eref->relname, "*NEW*") == 0)
if (strcmp(rte->eref->aliasname, "*NEW*") == 0)
continue;
if (strcmp(rte->eref->relname, "*OLD*") == 0)
if (strcmp(rte->eref->aliasname, "*OLD*") == 0)
continue;
}
@ -2342,15 +2339,15 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
if (rte->alias != NULL)
{
appendStringInfo(buf, " %s",
quote_identifier(rte->alias->relname));
if (rte->alias->attrs != NIL)
quote_identifier(rte->alias->aliasname));
if (rte->alias->colnames != NIL)
{
List *col;
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, "%s",
quote_identifier(strVal(lfirst(col))));
@ -2420,15 +2417,15 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
if (j->alias != NULL)
{
appendStringInfo(buf, " %s",
quote_identifier(j->alias->relname));
if (j->alias->attrs != NIL)
quote_identifier(j->alias->aliasname));
if (j->alias->colnames != NIL)
{
List *col;
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, "%s",
quote_identifier(strVal(lfirst(col))));

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* 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 */
#define CATALOG_VERSION_NO 200203191
#define CATALOG_VERSION_NO 200203211
#endif

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* 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);
/*
* SCHEMA
*/
extern void CreateSchemaCommand(CreateSchemaStmt *parsetree);
#endif /* COMMAND_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* 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 Attr *makeAttr(char *relname, char *attname);
extern Alias *makeAlias(const char *aliasname, List *colnames);
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) 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_ReindexStmt,
T_CheckPointStmt,
T_CreateSchemaStmt,
T_AlterDatabaseSetStmt,
T_AlterUserSetStmt,
T_A_Expr = 700,
T_Attr,
T_A_Const,
T_ParamNo,
T_ColumnRef,
T_ParamRef,
T_Ident,
T_A_Const,
T_FuncCall,
T_A_Indices,
T_ExprFieldSelect,
T_ResTarget,
T_TypeCast,
T_RangeSubselect,
T_SortGroupBy,
T_Alias,
T_RangeVar,
T_RangeSubselect,
T_TypeName,
T_IndexElem,
T_ColumnDef,

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* 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 */
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 isBinary; /* binary portal? */
bool isTemp; /* is 'into' a temp table? */
bool hasAggs; /* has aggregates in tlist or havingQual */
bool hasSubLinks; /* has subquery SubLink */
@ -125,15 +125,30 @@ typedef struct 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;
int number; /* the number of the parameter */
TypeName *typename; /* the typecast */
List *indirection; /* array references */
} ParamNo;
List *fields; /* field names (list of Value strings) */
List *indirection; /* subscripts (list of A_Indices) */
} ParamRef;
/*
* A_Expr - binary expressions
@ -147,22 +162,6 @@ typedef struct A_Expr
Node *rexpr; /* right argument */
} 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
*/
@ -176,11 +175,11 @@ typedef struct A_Const
/*
* 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
* argument to be casted is neither of those kinds of nodes. In theory either
* representation would work, but it is convenient (especially for A_Const)
* to have the target type immediately available.
* argument to be casted is not a constant. In theory either representation
* would work, but it is convenient to have the target type immediately
* available while resolving a constant's datatype.
*/
typedef struct TypeCast
{
@ -284,17 +283,13 @@ typedef struct ColumnDef
/*
* Ident -
* an identifier (could be an attribute or a relation name). Depending
* on the context at transformStmt time, the identifier is treated as
* either a relation name (in which case, isRel will be set) or an
* attribute (in which case, it will be transformed into an Attr).
* an unqualified identifier. This is currently used only in the context
* of column name lists.
*/
typedef struct Ident
{
NodeTag type;
char *name; /* its name */
List *indirection; /* array references */
bool isRel; /* is this a relation or a column? */
} Ident;
/*
@ -324,6 +319,21 @@ typedef struct A_Indices
Node *uidx;
} 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 -
* result target (used in target list of pre-transformed Parse trees)
@ -358,15 +368,37 @@ typedef struct SortGroupBy
Node *node; /* Expression */
} 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
*
* 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
{
NodeTag type;
char *relname; /* the relation name */
InhOption inhOpt; /* expand rel by inheritance? */
Attr *name; /* optional table alias & column aliases */
char *catalogname; /* the catalog (database) name, or NULL */
char *schemaname; /* the schema name, or NULL */
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;
/*
@ -376,7 +408,7 @@ typedef struct RangeSubselect
{
NodeTag type;
Node *subquery; /* the untransformed sub-select clause */
Attr *name; /* table alias & optional column aliases */
Alias *alias; /* table alias & optional column aliases */
} RangeSubselect;
/*
@ -437,7 +469,7 @@ typedef struct TargetEntry
* like outer joins and join-output-column aliasing.) Other special
* 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.
*
* 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 */
Oid relid; /* OID of the relation */
@ -517,8 +549,8 @@ typedef struct RangeTblEntry
/*
* Fields valid in all RTEs:
*/
Attr *alias; /* user-written alias clause, if any */
Attr *eref; /* expanded reference names */
Alias *alias; /* user-written alias clause, if any */
Alias *eref; /* expanded reference names */
bool inh; /* inheritance requested? */
bool inFromCl; /* present in FROM clause */
bool checkForRead; /* check rel for read access */
@ -570,7 +602,7 @@ typedef SortClause GroupClause;
typedef struct InsertStmt
{
NodeTag type;
char *relname; /* relation to insert into */
RangeVar *relation; /* relation to insert into */
List *cols; /* optional: names of the target columns */
/*
@ -589,9 +621,8 @@ typedef struct InsertStmt
typedef struct DeleteStmt
{
NodeTag type;
char *relname; /* relation to delete from */
RangeVar *relation; /* relation to delete from */
Node *whereClause; /* qualifications */
InhOption inhOpt; /* recursively act on children? */
} DeleteStmt;
/* ----------------------
@ -601,11 +632,10 @@ typedef struct DeleteStmt
typedef struct UpdateStmt
{
NodeTag type;
char *relname; /* relation to update */
RangeVar *relation; /* relation to update */
List *targetList; /* the target list (of ResTarget) */
Node *whereClause; /* qualifications */
List *fromClause; /* the from clause */
InhOption inhOpt; /* recursively act on children? */
List *fromClause; /* optional from clause for more tables */
} UpdateStmt;
/* ----------------------
@ -639,8 +669,7 @@ typedef struct SelectStmt
List *distinctClause; /* NULL, list of DISTINCT ON exprs, or
* lcons(NIL,NIL) for all (SELECT
* DISTINCT) */
char *into; /* name of table (for select into table) */
bool istemp; /* into is a temp table? */
RangeVar *into; /* target table (for select into table) */
List *intoColNames; /* column names for into table */
List *targetList; /* the target list (of ResTarget) */
List *fromClause; /* the FROM clause */
@ -703,6 +732,22 @@ typedef struct SetOperationStmt
* 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
*
@ -725,8 +770,7 @@ typedef struct AlterTableStmt
* U = change owner
*------------
*/
char *relname; /* table to work on */
InhOption inhOpt; /* recursively act on children? */
RangeVar *relation; /* table to work on */
char *name; /* column or constraint name to act on, or
* new owner */
Node *def; /* definition of new column or constraint */
@ -743,12 +787,12 @@ typedef struct GrantStmt
NodeTag type;
bool is_grant; /* not revoke */
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 *grantees; /* list of PrivGrantee nodes */
} GrantStmt;
typedef struct PrivGrantee
{
NodeTag type;
@ -756,7 +800,6 @@ typedef struct PrivGrantee
char *groupname;
} PrivGrantee;
typedef struct FuncWithArgs
{
NodeTag type;
@ -764,7 +807,6 @@ typedef struct FuncWithArgs
List *funcargs; /* list of Typename nodes */
} FuncWithArgs;
/* This is only used internally in gram.y. */
typedef struct PrivTarget
{
@ -773,7 +815,6 @@ typedef struct PrivTarget
List *objs;
} PrivTarget;
/* ----------------------
* Close Portal Statement
* ----------------------
@ -792,7 +833,7 @@ typedef struct CopyStmt
{
NodeTag type;
bool binary; /* is a binary copy? */
char *relname; /* the relation to copy */
RangeVar *relation; /* the relation to copy */
bool oids; /* copy oid's? */
int direction; /* TO or FROM */
char *filename; /* if NULL, use stdin/stdout */
@ -813,12 +854,10 @@ typedef struct CopyStmt
typedef struct CreateStmt
{
NodeTag type;
char *relname; /* name of relation to create */
RangeVar *relation; /* relation to create */
List *tableElts; /* column definitions (list of ColumnDef) */
List *inhRelnames; /* relations to inherit from (list of
* T_String Values) */
List *inhRelations; /* relations to inherit from */
List *constraints; /* constraints (list of Constraint nodes) */
bool istemp; /* is this a temp table? */
bool hasoids; /* should it have OIDs? */
} CreateStmt;
@ -886,7 +925,7 @@ typedef struct FkConstraint
{
NodeTag type;
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 *pk_attrs; /* Corresponding attrs in PK table */
char *match_type; /* FULL or PARTIAL */
@ -904,7 +943,7 @@ typedef struct CreateTrigStmt
{
NodeTag type;
char *trigname; /* TRIGGER' name */
char *relname; /* triggered relation */
RangeVar *relation; /* triggered relation */
char *funcname; /* function to call (or NULL) */
List *args; /* list of (T_String) Values or NULL */
bool before; /* BEFORE/AFTER */
@ -920,14 +959,14 @@ typedef struct CreateTrigStmt
bool isconstraint; /* This is an RI trigger */
bool deferrable; /* [NOT] DEFERRABLE */
bool initdeferred; /* INITIALLY {DEFERRED|IMMEDIATE} */
char *constrrelname; /* opposite relation */
RangeVar *constrrel; /* opposite relation */
} CreateTrigStmt;
typedef struct DropTrigStmt
{
NodeTag type;
char *trigname; /* TRIGGER' name */
char *relname; /* triggered relation */
RangeVar *relation; /* triggered relation */
} DropTrigStmt;
/* ----------------------
@ -1014,8 +1053,7 @@ typedef struct DropGroupStmt
typedef struct CreateSeqStmt
{
NodeTag type;
char *seqname; /* the relation to create */
bool istemp; /* is this a temp sequence? */
RangeVar *sequence; /* the sequence to create */
List *options;
} CreateSeqStmt;
@ -1072,7 +1110,7 @@ typedef struct CreateDomainStmt
typedef struct DropStmt
{
NodeTag type;
List *names;
List *objects;
int removeType;
int behavior; /* CASCADE or RESTRICT drop behavior */
} DropStmt;
@ -1084,7 +1122,7 @@ typedef struct DropStmt
typedef struct TruncateStmt
{
NodeTag type;
char *relName; /* relation to be truncated */
RangeVar *relation; /* relation to be truncated */
} TruncateStmt;
/* ----------------------
@ -1095,6 +1133,8 @@ typedef struct CommentStmt
{
NodeTag 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 *objproperty; /* Property Id (such as column) */
List *objlist; /* Arguments for VAL objects */
@ -1132,7 +1172,7 @@ typedef struct IndexStmt
{
NodeTag type;
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) */
List *indexParams; /* a list of IndexElem */
Node *whereClause; /* qualification (partial-index predicate) */
@ -1192,14 +1232,13 @@ typedef struct RemoveOperStmt
} RemoveOperStmt;
/* ----------------------
* Alter Table Statement
* Alter Table Rename Statement
* ----------------------
*/
typedef struct RenameStmt
{
NodeTag type;
char *relname; /* relation to be altered */
InhOption inhOpt; /* recursively act on children? */
RangeVar *relation; /* relation to be altered */
char *column; /* if NULL, rename the relation name to
* the new name. Otherwise, rename this
* column name. */
@ -1213,10 +1252,10 @@ typedef struct RenameStmt
typedef struct RuleStmt
{
NodeTag type;
RangeVar *relation; /* relation the rule is for */
char *rulename; /* name of the rule */
Node *whereClause; /* qualifications */
CmdType event; /* RETRIEVE */
struct Attr *object; /* object affected */
CmdType event; /* SELECT, INSERT, etc */
bool instead; /* is a 'do instead'? */
List *actions; /* the action statements */
} RuleStmt;
@ -1228,7 +1267,7 @@ typedef struct RuleStmt
typedef struct NotifyStmt
{
NodeTag type;
char *relname; /* relation to notify */
RangeVar *relation; /* qualified name to notify */
} NotifyStmt;
/* ----------------------
@ -1238,7 +1277,7 @@ typedef struct NotifyStmt
typedef struct ListenStmt
{
NodeTag type;
char *relname; /* relation to listen on */
RangeVar *relation; /* qualified name to listen on */
} ListenStmt;
/* ----------------------
@ -1248,7 +1287,7 @@ typedef struct ListenStmt
typedef struct UnlistenStmt
{
NodeTag type;
char *relname; /* relation to unlisten on */
RangeVar *relation; /* qualified name to unlisten on, or '*' */
} UnlistenStmt;
/* ----------------------
@ -1268,7 +1307,7 @@ typedef struct TransactionStmt
typedef struct ViewStmt
{
NodeTag type;
char *viewname; /* name of the view */
RangeVar *view; /* the view to be created */
List *aliases; /* target column names */
Query *query; /* the SQL statement */
} ViewStmt;
@ -1283,7 +1322,6 @@ typedef struct LoadStmt
char *filename; /* file to load */
} LoadStmt;
/* ----------------------
* Createdb Statement
* ----------------------
@ -1327,7 +1365,7 @@ typedef struct DropdbStmt
typedef struct ClusterStmt
{
NodeTag type;
char *relname; /* relation being indexed */
RangeVar *relation; /* relation being indexed */
char *indexname; /* original index defined */
} ClusterStmt;
@ -1346,8 +1384,7 @@ typedef struct VacuumStmt
bool analyze; /* do ANALYZE step */
bool freeze; /* early-freeze option */
bool verbose; /* print progress info */
char *vacrel; /* name of single table to process, or
* NULL */
RangeVar *relation; /* single table to process, or NULL */
List *va_cols; /* list of column names, or NIL for all */
} VacuumStmt;
@ -1413,7 +1450,7 @@ typedef struct VariableResetStmt
typedef struct LockStmt
{
NodeTag type;
List *rellist; /* relations to lock */
List *relations; /* relations to lock */
int mode; /* lock mode */
} LockStmt;
@ -1436,7 +1473,8 @@ typedef struct ReindexStmt
{
NodeTag type;
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 all;
} ReindexStmt;

View File

@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* 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
* 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
* alias has a critical impact on semantics, because a join with an alias
* restricts visibility of the tables/columns inside it.
@ -527,7 +527,7 @@ typedef struct JoinExpr
Node *rarg; /* right subtree */
List *using; /* USING clause, if any (list of String) */
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 */
} JoinExpr;

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* 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"
extern List *parse_analyze(Node *parseTree, ParseState *parentParseState);
extern List *analyzeCreateSchemaStmt(CreateSchemaStmt *stmt);
extern void CheckSelectForUpdate(Query *qry);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* 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 parseCheckAggregates(ParseState *pstate, Query *qry, Node *qual);
extern Aggref *ParseAgg(ParseState *pstate, char *aggname, Oid basetype,
List *args, bool agg_star, bool agg_distinct,
int precedence);
List *args, bool agg_star, bool agg_distinct);
extern void agg_error(char *caller, char *aggname, Oid basetypeID);
#endif /* PARSE_AGG_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* 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"
#define EXPR_COLUMN_FIRST 1
#define EXPR_RELATION_FIRST 2
/* GUC parameters */
extern int max_expr_depth;
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 int32 exprTypmod(Node *expr);
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) 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;
extern Node *ParseNestedFuncOrColumn(ParseState *pstate, Attr *attr,
int precedence);
extern Node *ParseFuncOrColumn(ParseState *pstate,
char *funcname, List *fargs,
bool agg_star, bool agg_distinct,
int precedence);
bool agg_star, bool agg_distinct, bool is_column);
extern FuncDetailCode func_get_detail(char *funcname, List *fargs,
int nargs, Oid *argtypes,

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* 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);
extern RangeTblEntry *addRangeTableEntry(ParseState *pstate,
char *relname,
Attr *alias,
Alias *alias,
bool inh,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForSubquery(ParseState *pstate,
Query *subquery,
Attr *alias,
Alias *alias,
bool inFromCl);
extern RangeTblEntry *addRangeTableEntryForJoin(ParseState *pstate,
List *colnames,
@ -43,7 +43,7 @@ extern RangeTblEntry *addRangeTableEntryForJoin(ParseState *pstate,
List *coltypmods,
List *leftcols,
List *rightcols,
Attr *alias,
Alias *alias,
bool inFromCl);
extern void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte,
bool addToJoinList, bool addToNameSpace);

View File

@ -396,7 +396,7 @@ drop table atacc1;
create table atacc1 ( test int );
-- add a check constraint (fails)
alter table atacc1 add constraint atacc_test1 check (test1>3);
ERROR: Attribute 'test1' not found
ERROR: Attribute "test1" not found
drop table atacc1;
-- something a little more complicated
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"
-- bad name in target list
select nonesuch from pg_database;
ERROR: Attribute 'nonesuch' not found
ERROR: Attribute "nonesuch" not found
-- bad attribute name on lhs of operator
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
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
select distinct on (foobar) from pg_database;
ERROR: parser: parse error at or near "from"
-- bad select distinct on syntax, distinct attribute not in target list
select distinct on (foobar) * from pg_database;
ERROR: Attribute 'foobar' not found
ERROR: Attribute "foobar" not found
--
-- DELETE

View File

@ -1177,7 +1177,7 @@ drop rule foorule;
-- this should fail because f1 is not exposed for unqualified reference:
create rule foorule as on insert to foo where f1 < 100
do instead insert into foo2 values (f1);
ERROR: Attribute 'f1' not found
ERROR: Attribute "f1" not found
-- this is the correct way:
create rule foorule as on insert to foo where f1 < 100
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
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:
SELECT q1 FROM int8_tbl EXCEPT (((SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1)));
q1

View File

@ -170,44 +170,44 @@ SELECT class, aa, a FROM a_star*;
-- joe and sally play basketball, and
-- 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.
--
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.
-- 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,
-- joe and sally need hightops, and
-- 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.
--
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
-- 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
ORDER BY user_relns;

View File

@ -442,7 +442,7 @@ SELECT class, aa, a FROM a_star*;
-- joe and sally play basketball, and
-- 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
-------+-------------
mike | posthacking
@ -453,7 +453,7 @@ SELECT p.name, p.hobbies.name FROM ONLY person p;
--
-- 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
-------+-------------
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.
-- 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
-------------+---------------
basketball | hightops
@ -475,7 +475,7 @@ SELECT DISTINCT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r;
skywalking | guts
(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
-------------+---------------
posthacking | advil
@ -492,7 +492,7 @@ SELECT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r;
-- joe and sally need hightops, and
-- 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
-------+-------------+---------------
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.
--
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
-------+-------------+---------------
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
-- 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
---------------+-------+-------------
advil | mike | posthacking
@ -528,7 +528,7 @@ SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM ONLY person p;
hightops | sally | basketball
(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
---------------+-------+-------------
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
(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
---------------+-------------+-------
advil | posthacking | mike
@ -548,7 +548,7 @@ SELECT p.hobbies.equipment.name, p.hobbies.name, p.name FROM ONLY person p;
hightops | basketball | sally
(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
---------------+-------------+-------
advil | posthacking | mike