<!--
-$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">
<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>
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 name(new_emp());
+SELECT (new_emp()).name;
</programlisting>
<screen>
------
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>
- This example makes use of the
- function notation for projecting attributes. The simple way
- to explain this is that we can usually use the
+ 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>
+
+<screen>
+ name
+------
+ None
+</screen>
+ </para>
+
+<programlisting>
--
-- this is the same as:
-- SELECT EMP.name AS youngster FROM EMP WHERE EMP.age < 30
</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
result to it:
*
*
* 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.
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;
*
*
* 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
/*
* 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.
/*
* 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.
*
*
* 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
#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"
#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"
* 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.
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.");
* 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);
/*
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)
* 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;
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);
+}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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
* 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)
relationId = heap_create_with_catalog(relname, descriptor,
relkind,
stmt->hasoids || parentHasOids,
- stmt->istemp,
+ stmt->relation->istemp,
allowSystemTableMods);
StoreCatalogInheritance(relationId, inheritOids);
/*
* Reject duplicate names in the list of parents, too.
+ *
+ * XXX needs to be smarter about schema-qualified table names.
*/
foreach(entry, supers)
{
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);
}
}
child_attno = 0;
foreach(entry, supers)
{
- char *name = strVal(lfirst(entry));
+ char *name = ((RangeVar *) lfirst(entry))->relname;
Relation relation;
TupleDesc tupleDesc;
TupleConstr *constr;
* 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 $
*
*/
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:
es->rtable);
appendStringInfo(str, " %s",
- stringStringInfo(rte->eref->relname));
+ stringStringInfo(rte->eref->aliasname));
}
break;
default:
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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:
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 */
* 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 $
*
*-------------------------------------------------------------------------
*/
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");
stmt->trigname = constrtrigname;
sprintf(constrtrigname, "RI_ConstraintTrigger_%u", newoid());
- if (strcmp(stmt->constrrelname, "") == 0)
+ if (stmt->constrrel == NULL)
constrrelid = InvalidOid;
else
{
* 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)
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);
*/
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);
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
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
*/
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);
{
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
* FK table defined on the PK table).
*/
CommandCounterIncrement();
-
- pfree(stmt.relname);
- pfree(stmt.trigname);
}
systable_endscan(tgscan);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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
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
* 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);
* 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 $
*
*-------------------------------------------------------------------------
*/
DefineVirtualRelation(char *relname, List *tlist)
{
CreateStmt *createStmt = makeNode(CreateStmt);
+ RangeVar *rel = makeNode(RangeVar);
List *attrList,
*t;
* 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;
/*
{
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);
* 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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/*
* create the "into" relation
*/
- intoName = parseTree->into;
+ intoName = parseTree->into->relname;
/*
* have to copy tupType to get rid of constraints
heap_create_with_catalog(intoName,
tupdesc,
RELKIND_RELATION, true,
- parseTree->isTemp,
+ parseTree->into->istemp,
allowSystemTableMods);
FreeTupleDesc(tupdesc);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/* 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 */
if (parseTree->isPortal)
{
isRetrieveIntoPortal = true;
- intoName = parseTree->into;
+ intoName = parseTree->into->relname;
parseTree->isBinary = false; /* */
return SPI_ERROR_CURSOR;
* 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 $
*
*-------------------------------------------------------------------------
*/
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
* ----------------
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)
return newnode;
}
-static A_Const *
-_copyAConst(A_Const *from)
+static ColumnRef *
+_copyColumnRef(ColumnRef *from)
{
- A_Const *newnode = makeNode(A_Const);
+ ColumnRef *newnode = makeNode(ColumnRef);
- newnode->val = *((Value *) (copyObject(&(from->val))));
- Node_Copy(from, newnode, typename);
+ Node_Copy(from, newnode, fields);
+ Node_Copy(from, newnode, indirection);
return newnode;
}
-static ParamNo *
-_copyParamNo(ParamNo *from)
+static ParamRef *
+_copyParamRef(ParamRef *from)
{
- ParamNo *newnode = makeNode(ParamNo);
+ ParamRef *newnode = makeNode(ParamRef);
newnode->number = from->number;
- Node_Copy(from, newnode, typename);
+ Node_Copy(from, newnode, fields);
Node_Copy(from, newnode, indirection);
return newnode;
}
+static A_Const *
+_copyAConst(A_Const *from)
+{
+ A_Const *newnode = makeNode(A_Const);
+
+ newnode->val = *((Value *) (copyObject(&(from->val))));
+ Node_Copy(from, newnode, typename);
+
+ 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;
}
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)
{
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;
}
RangeSubselect *newnode = makeNode(RangeSubselect);
Node_Copy(from, newnode, subquery);
- Node_Copy(from, newnode, name);
+ Node_Copy(from, newnode, alias);
return newnode;
}
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;
{
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);
{
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;
}
{
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;
}
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);
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);
{
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);
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)
{
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;
{
DropStmt *newnode = makeNode(DropStmt);
- Node_Copy(from, newnode, names);
+ Node_Copy(from, newnode, objects);
newnode->removeType = from->removeType;
newnode->behavior = from->behavior;
{
TruncateStmt *newnode = makeNode(TruncateStmt);
- newnode->relName = pstrdup(from->relName);
+ Node_Copy(from, newnode, relation);
return newnode;
}
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);
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);
{
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)
{
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);
{
NotifyStmt *newnode = makeNode(NotifyStmt);
- if (from->relname)
- newnode->relname = pstrdup(from->relname);
+ Node_Copy(from, newnode, relation);
return newnode;
}
{
ListenStmt *newnode = makeNode(ListenStmt);
- if (from->relname)
- newnode->relname = pstrdup(from->relname);
+ Node_Copy(from, newnode, relation);
return newnode;
}
{
UnlistenStmt *newnode = makeNode(UnlistenStmt);
- if (from->relname)
- newnode->relname = pstrdup(from->relname);
+ Node_Copy(from, newnode, relation);
return newnode;
}
{
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);
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;
{
CreateSeqStmt *newnode = makeNode(CreateSeqStmt);
- if (from->seqname)
- newnode->seqname = pstrdup(from->seqname);
+ Node_Copy(from, newnode, sequence);
Node_Copy(from, newnode, options);
return newnode;
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);
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;
}
if (from->trigname)
newnode->trigname = pstrdup(from->trigname);
- if (from->relname)
- newnode->relname = pstrdup(from->relname);
+ Node_Copy(from, newnode, relation);
return newnode;
}
{
LockStmt *newnode = makeNode(LockStmt);
- Node_Copy(from, newnode, rellist);
+ Node_Copy(from, newnode, relations);
newnode->mode = from->mode;
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;
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
case T_LoadStmt:
retval = _copyLoadStmt(from);
break;
+ case T_CreateDomainStmt:
+ retval = _copyCreateDomainStmt(from);
+ break;
case T_CreatedbStmt:
retval = _copyCreatedbStmt(from);
break;
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;
case T_A_Indices:
retval = _copyAIndices(from);
break;
+ case T_ExprFieldSelect:
+ retval = _copyExprFieldSelect(from);
+ break;
case T_ResTarget:
retval = _copyResTarget(from);
break;
case T_SortGroupBy:
retval = _copySortGroupBy(from);
break;
+ case T_Alias:
+ retval = _copyAlias(from);
+ break;
case T_RangeVar:
retval = _copyRangeVar(from);
break;
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",
* 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 $
*
*-------------------------------------------------------------------------
*/
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)
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;
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;
}
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;
return false;
if (!equal(a->fromClause, b->fromClause))
return false;
- if (a->inhOpt != b->inhOpt)
- return false;
return true;
}
{
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;
{
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;
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;
{
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;
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;
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;
static bool
_equalTruncateStmt(TruncateStmt *a, TruncateStmt *b)
{
- if (!equalstr(a->relName, b->relName))
+ if (!equal(a->relation, b->relation))
return false;
return true;
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))
{
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;
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;
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))
static bool
_equalNotifyStmt(NotifyStmt *a, NotifyStmt *b)
{
- if (!equalstr(a->relname, b->relname))
+ if (!equal(a->relation, b->relation))
return false;
return true;
static bool
_equalListenStmt(ListenStmt *a, ListenStmt *b)
{
- if (!equalstr(a->relname, b->relname))
+ if (!equal(a->relation, b->relation))
return false;
return true;
static bool
_equalUnlistenStmt(UnlistenStmt *a, UnlistenStmt *b)
{
- if (!equalstr(a->relname, b->relname))
+ if (!equal(a->relation, b->relation))
return false;
return true;
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;
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;
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;
{
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;
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;
{
if (!equalstr(a->trigname, b->trigname))
return false;
- if (!equalstr(a->relname, b->relname))
+ if (!equal(a->relation, b->relation))
return false;
return true;
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;
{
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)
}
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)
{
if (a->oper != b->oper)
}
static bool
-_equalAttr(Attr *a, Attr *b)
+_equalColumnRef(ColumnRef *a, ColumnRef *b)
{
- if (strcmp(a->relname, b->relname) != 0)
- return false;
- if (!equal(a->paramNo, b->paramNo))
- return false;
- if (!equal(a->attrs, b->attrs))
+ if (!equal(a->fields, b->fields))
return false;
if (!equal(a->indirection, b->indirection))
return false;
}
static bool
-_equalAConst(A_Const *a, A_Const *b)
+_equalParamRef(ParamRef *a, ParamRef *b)
{
- if (!equal(&a->val, &b->val))
+ if (a->number != b->number)
return false;
- if (!equal(a->typename, b->typename))
+ if (!equal(a->fields, b->fields))
+ return false;
+ if (!equal(a->indirection, b->indirection))
return false;
return true;
}
static bool
-_equalParamNo(ParamNo *a, ParamNo *b)
+_equalAConst(A_Const *a, A_Const *b)
{
- if (a->number != b->number)
+ if (!equal(&a->val, &b->val))
return false;
if (!equal(a->typename, b->typename))
return false;
- if (!equal(a->indirection, b->indirection))
- return false;
return true;
}
{
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;
}
}
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)
{
if (!equalstr(a->name, b->name))
}
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;
{
if (!equal(a->subquery, b->subquery))
return false;
- if (!equal(a->name, b->name))
+ if (!equal(a->alias, b->alias))
return false;
return true;
{
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;
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;
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;
case T_SortGroupBy:
retval = _equalSortGroupBy(a, b);
break;
+ case T_Alias:
+ retval = _equalAlias(a, b);
+ break;
case T_RangeVar:
retval = _equalRangeVar(a, b);
break;
*
*
* 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"
}
/*
- * 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;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
* 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;
* 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
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));
}
{
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 ");
}
static void
+_outNotifyStmt(StringInfo str, NotifyStmt *node)
+{
+ appendStringInfo(str, "NOTIFY :relation ");
+ _outNode(str, node->relation);
+}
+
+static void
_outSelectStmt(StringInfo str, SelectStmt *node)
{
/* XXX this is pretty durn incomplete */
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, " ");
- _outNode(str, node->utilityStmt);
- break;
-
case T_NotifyStmt:
- appendStringInfo(str, " :notify ");
- _outToken(str, ((NotifyStmt *) (node->utilityStmt))->relname);
+ _outNode(str, node->utilityStmt);
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);
}
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)
{
appendStringInfo(str, " RTE :rtekind %d :relname ",
}
static void
-_outIdent(StringInfo str, Ident *node)
+_outRangeVar(StringInfo str, RangeVar *node)
{
- appendStringInfo(str, " IDENT ");
- _outToken(str, node->name);
+ 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
-_outAttr(StringInfo str, Attr *node)
+_outColumnRef(StringInfo str, ColumnRef *node)
{
- appendStringInfo(str, " ATTR :relname ");
- _outToken(str, node->relname);
- appendStringInfo(str, " :attrs ");
- _outNode(str, node->attrs);
+ 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)
+{
+ appendStringInfo(str, " IDENT ");
+ _outToken(str, node->name);
}
static void
}
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)
{
appendStringInfo(str, " CONSTRAINT :name ");
{
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 ");
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;
case T_TargetEntry:
_outTargetEntry(str, obj);
break;
+ case T_Alias:
+ _outAlias(str, obj);
+ break;
case T_RangeTblEntry:
_outRangeTblEntry(str, obj);
break;
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;
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 ",
*
*
* 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
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" : ""));
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;
*
*
* 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
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);
-
- n->relname = debackslash(token, length);
- local_node->utilityStmt = (Node *) n;
- }
+ local_node->utilityStmt = nodeRead(true);
- 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 */
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);
}
/* ----------------
+ * _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
* ----------------
*/
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 :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 :attrs */
- local_node->attrs = nodeRead(true); /* now read it */
+ token = pg_strtok(&length); /* eat :colnames */
+ local_node->colnames = nodeRead(true); /* now read it */
return local_node;
}
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)
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)
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)
*
*
* 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
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);
}
}
}
return false;
switch (nodeTag(node))
{
- case T_Ident:
case T_Const:
case T_Var:
case T_Param:
return NULL;
switch (nodeTag(node))
{
- case T_Ident:
case T_Const:
case T_Var:
case T_Param:
* 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 $
*
*-------------------------------------------------------------------------
*/
#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 */
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;
* 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);
/*
*/
rte = addRangeTableEntryForSubquery(pstate,
selectQuery,
- makeAttr("*SELECT*", NULL),
+ makeAlias("*SELECT*", NIL),
true);
rtr = makeNode(RangeTblRef);
/* assume new rte is at end */
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);
}
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;
* 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
* 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);
}
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);
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;
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;
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)
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)
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);
{
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);
/* 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;
*/
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));
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 */
cxt->stmtType,
(strcmp(cxt->stmtType, "ALTER TABLE") == 0) ? "ADD " : "",
(index->primary ? "PRIMARY KEY" : "UNIQUE"),
- index->idxname, cxt->relname);
+ index->idxname, (cxt->relation)->relname);
}
}
*/
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)
{
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)
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
{
transformFkeyCheckAttrs(fkconstraint, pktypoid);
else
elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found",
- fkconstraint->pktable_name);
+ fkconstraint->pktable->relname);
}
}
}
*/
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;
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;
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)
{
*/
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';
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)
{
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;
*/
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';
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)
{
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;
* 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);
* 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);
/*
* 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;
* 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;
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 */
}
{
/* SELECT */
qry->into = stmt->into;
- qry->isTemp = stmt->istemp;
qry->isPortal = FALSE;
qry->isBinary = FALSE;
}
int leftmostRTI;
Query *leftmostQuery;
SetOperationStmt *sostmt;
- char *into;
- bool istemp;
+ RangeVar *into;
List *intoColNames;
char *portalname;
bool binary;
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;
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 */
}
{
/* SELECT */
qry->into = into;
- qry->isTemp = istemp;
qry->isPortal = FALSE;
qry->isBinary = FALSE;
}
sprintf(selectName, "*SELECT* %d", length(pstate->p_rtable) + 1);
rte = addRangeTableEntryForSubquery(pstate,
selectQuery,
- makeAttr(pstrdup(selectName),
- NULL),
+ makeAlias(selectName, NIL),
false);
/*
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);
/*
{
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),
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),
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;
RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
++i;
- if (strcmp(rte->eref->relname, relname) == 0)
+ if (strcmp(rte->eref->aliasname, relname) == 0)
{
if (rte->subquery)
{
/*
* 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
}
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);
/*
* 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
*/
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
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);
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));
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;
+}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.294 2002/03/20 19:44:21 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.295 2002/03/21 16:00:50 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
%}
+
%union
{
int ival;
List *list;
Node *node;
Value *value;
-
- Attr *attr;
- Ident *ident;
+ ColumnRef *columnref;
TypeName *typnam;
DefElem *defelt;
SortGroupBy *sortgroupby;
JoinExpr *jexpr;
IndexElem *ielem;
+ Alias *alias;
RangeVar *range;
A_Indices *aind;
ResTarget *target;
- ParamNo *paramno;
PrivTarget *privtarget;
VersionStmt *vstmt;
InsertStmt *istmt;
}
-%type <node> stmt,
+%type <node> stmt, schema_stmt,
AlterDatabaseSetStmt, AlterGroupStmt, AlterSchemaStmt, AlterTableStmt,
AlterUserStmt, AlterUserSetStmt, AnalyzeStmt,
ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt,
%type <list> OptUserList
%type <defelt> OptUserElem
+%type <str> OptSchemaName
+%type <list> OptSchemaEltList
+
%type <boolean> TriggerActionTime, TriggerForSpec, opt_trusted, opt_procedural
%type <str> opt_lancompiler
-%type <str> OptConstrFromTable
-
%type <str> TriggerEvents
%type <value> TriggerFuncArg
database_name, access_method_clause, access_method, attr_name,
class, index_name, name, func_name, file_name
+%type <range> qualified_name, OptConstrFromTable
+
%type <str> opt_id,
all_Op, MathOp, opt_name,
OptUseOp, opt_class, SpecialRuleRelation
%type <chr> TriggerOneEvent
%type <list> stmtblock, stmtmulti,
- into_clause, OptTempTableName, relation_name_list,
OptTableElementList, OptInherit, definition, opt_distinct,
opt_with, func_args, func_args_list, func_as,
oper_argtypes, RuleActionList, RuleActionMulti,
opt_column_list, columnList, opt_name_list,
sort_clause, sortby_list, index_params, index_list, name_list,
- from_clause, from_list, opt_array_bounds,
- expr_list, attrs, target_list, update_target_list,
+ from_clause, from_list, opt_array_bounds, qualified_name_list,
+ expr_list, attrs, opt_attrs, target_list, update_target_list,
+ insert_column_list,
def_list, opt_indirection, group_clause, TriggerFuncArgs,
select_limit, opt_select_limit
+%type <range> into_clause, OptTempTableName
+
%type <typnam> func_arg, func_return, func_type, aggr_argtype
%type <boolean> opt_arg, TriggerForOpt, TriggerForType, OptTemp, OptWithOids
%type <node> OptTableElement, ConstraintElem
%type <node> columnDef
%type <defelt> def_elem
-%type <node> def_arg, columnElem, where_clause,
+%type <node> def_arg, columnElem, where_clause, insert_column_item,
a_expr, b_expr, c_expr, AexprConst,
in_expr, having_clause
%type <list> row_descriptor, row_list, in_expr_nodes
%type <list> OptCreateAs, CreateAsList
%type <node> CreateAsElement
%type <value> NumericOnly, FloatOnly, IntegerOnly
-%type <attr> event_object, attr, alias_clause
+%type <columnref> columnref
+%type <alias> alias_clause
%type <sortgroupby> sortby
%type <ielem> index_elem, func_index
%type <node> table_ref
%type <jexpr> joined_table
%type <range> relation_expr
%type <target> target_el, update_target_el
-%type <paramno> ParamNo
%type <typnam> Typename, SimpleTypename, ConstTypename
GenericType, Numeric, Character, ConstDatetime, ConstInterval, Bit
%type <boolean> opt_as
+
/*
* If you make any token changes, remember to:
* - use "yacc -d" and update parse.h
*
*****************************************************************************/
-CreateSchemaStmt: CREATE SCHEMA UserId
+CreateSchemaStmt: CREATE SCHEMA OptSchemaName AUTHORIZATION UserId OptSchemaEltList
{
- /* for now, just make this the same as CREATE DATABASE */
- CreatedbStmt *n = makeNode(CreatedbStmt);
- n->dbname = $3;
- n->dbowner = NULL;
- n->dbpath = NULL;
- n->dbtemplate = NULL;
- n->encoding = -1;
+ CreateSchemaStmt *n = makeNode(CreateSchemaStmt);
+ /* One can omit the schema name or the authorization id... */
+ if ($3 != NULL)
+ n->schemaname = $3;
+ else
+ n->schemaname = $5;
+ n->authid = $5;
+ n->schemaElts = $6;
+ $$ = (Node *)n;
+ }
+ | CREATE SCHEMA ColId OptSchemaEltList
+ {
+ CreateSchemaStmt *n = makeNode(CreateSchemaStmt);
+ /* ...but not both */
+ n->schemaname = $3;
+ n->authid = NULL;
+ n->schemaElts = $4;
$$ = (Node *)n;
}
;
-AlterSchemaStmt: ALTER SCHEMA UserId
+AlterSchemaStmt: ALTER SCHEMA ColId
{
elog(ERROR, "ALTER SCHEMA not yet supported");
}
;
-DropSchemaStmt: DROP SCHEMA UserId
+DropSchemaStmt: DROP SCHEMA ColId
{
- DropdbStmt *n = makeNode(DropdbStmt);
- n->dbname = $3;
- $$ = (Node *)n;
+ elog(ERROR, "DROP SCHEMA not yet supported");
}
;
+OptSchemaName: ColId { $$ = $1; }
+ | /* EMPTY */ { $$ = NULL; }
+ ;
+
+OptSchemaEltList: OptSchemaEltList schema_stmt { $$ = lappend($1, $2); }
+ | /* EMPTY */ { $$ = NIL; }
+ ;
-
+/*
+ * schema_stmt are the ones that can show up inside a CREATE SCHEMA
+ * statement (in addition to by themselves).
+ */
+schema_stmt: CreateStmt
+ | GrantStmt
+ | ViewStmt
+ ;
/*****************************************************************************
*
ColId_or_Sconst: ColId { $$ = $1; }
| SCONST { $$ = $1; }
+ ;
VariableShowStmt: SHOW ColId
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->subtype = 'A';
- n->relname = $3->relname;
- n->inhOpt = $3->inhOpt;
+ n->relation = $3;
n->def = $6;
$$ = (Node *)n;
}
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->subtype = 'T';
- n->relname = $3->relname;
- n->inhOpt = $3->inhOpt;
+ n->relation = $3;
n->name = $6;
n->def = $7;
$$ = (Node *)n;
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->subtype = 'S';
- n->relname = $3->relname;
- n->inhOpt = $3->inhOpt;
+ n->relation = $3;
n->name = $6;
n->def = (Node *) makeInteger($9);
$$ = (Node *)n;
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->subtype = 'M';
- n->relname = $3->relname;
- n->inhOpt = $3->inhOpt;
+ n->relation = $3;
n->name = $6;
n->def = (Node *) makeString($9);
$$ = (Node *)n;
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->subtype = 'D';
- n->relname = $3->relname;
- n->inhOpt = $3->inhOpt;
+ n->relation = $3;
n->name = $6;
n->behavior = $7;
$$ = (Node *)n;
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->subtype = 'C';
- n->relname = $3->relname;
- n->inhOpt = $3->inhOpt;
+ n->relation = $3;
n->def = $5;
$$ = (Node *)n;
}
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->subtype = 'X';
- n->relname = $3->relname;
- n->inhOpt = $3->inhOpt;
+ n->relation = $3;
n->name = $6;
n->behavior = $7;
$$ = (Node *)n;
}
/* ALTER TABLE <name> CREATE TOAST TABLE */
- | ALTER TABLE relation_name CREATE TOAST TABLE
+ | ALTER TABLE qualified_name CREATE TOAST TABLE
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->subtype = 'E';
- n->relname = $3;
- n->inhOpt = INH_NO;
+ $3->inhOpt = INH_NO;
+ n->relation = $3;
$$ = (Node *)n;
}
/* ALTER TABLE <name> OWNER TO UserId */
- | ALTER TABLE relation_name OWNER TO UserId
+ | ALTER TABLE qualified_name OWNER TO UserId
{
AlterTableStmt *n = makeNode(AlterTableStmt);
n->subtype = 'U';
- n->relname = $3;
- n->inhOpt = INH_NO;
+ $3->inhOpt = INH_NO;
+ n->relation = $3;
n->name = $6;
$$ = (Node *)n;
}
opt_drop_behavior: CASCADE { $$ = CASCADE; }
| RESTRICT { $$ = RESTRICT; }
| /* EMPTY */ { $$ = RESTRICT; /* default */ }
- ;
+ ;
+
/*****************************************************************************
*
*****************************************************************************/
-CopyStmt: COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name copy_delimiter copy_null
+CopyStmt: COPY opt_binary qualified_name opt_with_copy copy_dirn copy_file_name copy_delimiter copy_null
{
CopyStmt *n = makeNode(CopyStmt);
n->binary = $2;
- n->relname = $3;
+ n->relation = $3;
n->oids = $4;
n->direction = $5;
n->filename = $6;
| /*EMPTY*/ { $$ = TRUE; }
;
-copy_null: WITH NULL_P AS Sconst { $$ = $4; }
- | /*EMPTY*/ { $$ = "\\N"; }
+copy_null: WITH NULL_P AS Sconst { $$ = $4; }
+ | /*EMPTY*/ { $$ = "\\N"; }
+ ;
/*****************************************************************************
*
*
*****************************************************************************/
-CreateStmt: CREATE OptTemp TABLE relation_name '(' OptTableElementList ')' OptInherit OptWithOids
+CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' OptInherit OptWithOids
{
CreateStmt *n = makeNode(CreateStmt);
- n->relname = $4;
+ $4->istemp = $2;
+ n->relation = $4;
n->tableElts = $6;
- n->inhRelnames = $8;
+ n->inhRelations = $8;
n->constraints = NIL;
- n->istemp = $2;
n->hasoids = $9;
$$ = (Node *)n;
}
n->name = NULL;
if (exprIsNullConstant($2))
{
- /*
- * DEFAULT NULL should be reported as empty expr
- * Required for NOT NULL Domain overrides
- */
+ /* DEFAULT NULL should be reported as empty expr */
n->raw_expr = NULL;
}
else
n->keys = NULL;
$$ = (Node *)n;
}
- | REFERENCES ColId opt_column_list key_match key_actions
+ | REFERENCES qualified_name opt_column_list key_match key_actions
{
FkConstraint *n = makeNode(FkConstraint);
n->constr_name = NULL;
- n->pktable_name = $2;
+ n->pktable = $2;
n->fk_attrs = NIL;
n->pk_attrs = $3;
n->match_type = $4;
n->keys = $4;
$$ = (Node *)n;
}
- | FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list
+ | FOREIGN KEY '(' columnList ')' REFERENCES qualified_name opt_column_list
key_match key_actions ConstraintAttributeSpec
{
FkConstraint *n = makeNode(FkConstraint);
n->constr_name = NULL;
- n->pktable_name = $7;
+ n->pktable = $7;
n->fk_attrs = $4;
n->pk_attrs = $8;
n->match_type = $9;
}
;
+opt_column_list: '(' columnList ')' { $$ = $2; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
+columnList: columnList ',' columnElem
+ { $$ = lappend($1, $3); }
+ | columnElem
+ { $$ = makeList1($1); }
+ ;
+
+columnElem: ColId
+ {
+ Ident *id = makeNode(Ident);
+ id->name = $1;
+ $$ = (Node *)id;
+ }
+ ;
+
key_match: MATCH FULL
{
$$ = "FULL";
| SET DEFAULT { $$ = FKCONSTR_ON_KEY_SETDEFAULT; }
;
-OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; }
+OptInherit: INHERITS '(' qualified_name_list ')' { $$ = $3; }
| /*EMPTY*/ { $$ = NIL; }
;
* SELECT ... INTO.
*/
-CreateAsStmt: CREATE OptTemp TABLE relation_name OptCreateAs AS SelectStmt
+CreateAsStmt: CREATE OptTemp TABLE qualified_name OptCreateAs AS SelectStmt
{
/*
* When the SelectStmt is a set-operation tree, we must
SelectStmt *n = findLeftmostSelect((SelectStmt *) $7);
if (n->into != NULL)
elog(ERROR,"CREATE TABLE AS may not specify INTO");
- n->istemp = $2;
+ $4->istemp = $2;
n->into = $4;
n->intoColNames = $5;
$$ = $7;
*
*****************************************************************************/
-CreateSeqStmt: CREATE OptTemp SEQUENCE relation_name OptSeqList
+CreateSeqStmt: CREATE OptTemp SEQUENCE qualified_name OptSeqList
{
CreateSeqStmt *n = makeNode(CreateSeqStmt);
- n->istemp = $2;
- n->seqname = $4;
+ $4->istemp = $2;
+ n->sequence = $4;
n->options = $5;
$$ = (Node *)n;
}
NumericOnly: FloatOnly { $$ = $1; }
| IntegerOnly { $$ = $1; }
+ ;
FloatOnly: FCONST
{
opt_lancompiler: LANCOMPILER Sconst { $$ = $2; }
| /*EMPTY*/ { $$ = ""; }
+ ;
DropPLangStmt: DROP opt_procedural LANGUAGE ColId_or_Sconst
{
*****************************************************************************/
CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
- relation_name TriggerForSpec EXECUTE PROCEDURE
+ qualified_name TriggerForSpec EXECUTE PROCEDURE
name '(' TriggerFuncArgs ')'
{
CreateTrigStmt *n = makeNode(CreateTrigStmt);
n->trigname = $3;
- n->relname = $7;
+ n->relation = $7;
n->funcname = $11;
n->args = $13;
n->before = $4;
n->isconstraint = FALSE;
n->deferrable = FALSE;
n->initdeferred = FALSE;
- n->constrrelname = NULL;
+ n->constrrel = NULL;
$$ = (Node *)n;
}
| CREATE CONSTRAINT TRIGGER name AFTER TriggerEvents ON
- relation_name OptConstrFromTable
+ qualified_name OptConstrFromTable
ConstraintAttributeSpec
FOR EACH ROW EXECUTE PROCEDURE name '(' TriggerFuncArgs ')'
{
CreateTrigStmt *n = makeNode(CreateTrigStmt);
n->trigname = $4;
- n->relname = $8;
+ n->relation = $8;
n->funcname = $16;
n->args = $18;
n->before = FALSE;
n->deferrable = ($10 & 1) != 0;
n->initdeferred = ($10 & 2) != 0;
- n->constrrelname = $9;
+ n->constrrel = $9;
$$ = (Node *)n;
}
;
OptConstrFromTable: /* Empty */
{
- $$ = "";
+ $$ = NULL;
}
- | FROM relation_name
+ | FROM qualified_name
{
$$ = $2;
}
;
-DropTrigStmt: DROP TRIGGER name ON relation_name
+DropTrigStmt: DROP TRIGGER name ON qualified_name
{
DropTrigStmt *n = makeNode(DropTrigStmt);
n->trigname = $3;
- n->relname = $5;
+ n->relation = $5;
$$ = (Node *) n;
}
;
*
*****************************************************************************/
-DropStmt: DROP drop_type name_list opt_drop_behavior
+/* DropStmt needs to use qualified_name_list as many of the objects
+ * are relations or other schema objects (names can be schema-qualified) */
+
+DropStmt: DROP drop_type qualified_name_list opt_drop_behavior
{
DropStmt *n = makeNode(DropStmt);
n->removeType = $2;
- n->names = $3;
+ n->objects = $3;
n->behavior = $4;
$$ = (Node *)n;
}
*
*****************************************************************************/
-TruncateStmt: TRUNCATE opt_table relation_name
+TruncateStmt: TRUNCATE opt_table qualified_name
{
TruncateStmt *n = makeNode(TruncateStmt);
- n->relName = $3;
+ n->relation = $3;
$$ = (Node *)n;
}
;
n->comment = $6;
$$ = (Node *) n;
}
- | COMMENT ON COLUMN relation_name '.' attr_name IS comment_text
+ | COMMENT ON COLUMN ColId '.' attr_name IS comment_text
{
+ /*
+ * We can't use qualified_name here as the '.' causes a shift/red;
+ * with ColId we do not test for NEW and OLD as table names, but it is OK
+ * as they would fail anyway as COMMENT cannot appear in a RULE.
+ * ColumnRef is also innapropriate as we don't take subscripts
+ * or '*' and have a very precise number of elements (2 or 3)
+ * so we do it from scratch.
+ */
CommentStmt *n = makeNode(CommentStmt);
n->objtype = COLUMN;
+ n->objschema = NULL;
n->objname = $4;
n->objproperty = $6;
n->objlist = NULL;
n->comment = $8;
$$ = (Node *) n;
}
+ | COMMENT ON COLUMN ColId '.' ColId '.' attr_name IS comment_text
+ {
+ CommentStmt *n = makeNode(CommentStmt);
+ n->objtype = COLUMN;
+ n->objschema = $4;
+ n->objname = $6;
+ n->objproperty = $8;
+ n->objlist = NULL;
+ n->comment = $10;
+ $$ = (Node *) n;
+ }
| COMMENT ON AGGREGATE name '(' aggr_argtype ')' IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = AGGREGATE;
+ n->objschema = NULL;
n->objname = $4;
n->objproperty = NULL;
n->objlist = makeList1($6);
/* Obsolete syntax, but must support for awhile */
CommentStmt *n = makeNode(CommentStmt);
n->objtype = AGGREGATE;
+ n->objschema = NULL;
n->objname = $4;
n->objproperty = NULL;
n->objlist = makeList1($5);
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = FUNCTION;
+ n->objschema = NULL;
n->objname = $4;
n->objproperty = NULL;
n->objlist = $5;
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = OPERATOR;
+ n->objschema = NULL;
n->objname = $4;
n->objproperty = NULL;
n->objlist = $6;
n->comment = $9;
$$ = (Node *) n;
}
- | COMMENT ON TRIGGER name ON relation_name IS comment_text
+ | COMMENT ON TRIGGER name ON qualified_name IS comment_text
{
CommentStmt *n = makeNode(CommentStmt);
n->objtype = TRIGGER;
+ /* NOTE: schemaname here refers to the table in objproperty */
+ n->objschema = $6->schemaname;
n->objname = $4;
- n->objproperty = $6;
+ n->objproperty = $6->relname;
n->objlist = NULL;
n->comment = $8;
$$ = (Node *) n;
/* Don't bother trying to fold the first two rules into one using
opt_table. You're going to get conflicts. */
-privilege_target: relation_name_list
+privilege_target: qualified_name_list
{
PrivTarget *n = makeNode(PrivTarget);
n->objtype = TABLE;
n->objs = $1;
$$ = n;
}
- | TABLE relation_name_list
+ | TABLE qualified_name_list
{
PrivTarget *n = makeNode(PrivTarget);
n->objtype = TABLE;
*
*****************************************************************************/
-IndexStmt: CREATE index_opt_unique INDEX index_name ON relation_name
+IndexStmt: CREATE index_opt_unique INDEX index_name ON qualified_name
access_method_clause '(' index_params ')' where_clause
{
IndexStmt *n = makeNode(IndexStmt);
n->unique = $2;
n->idxname = $4;
- n->relname = $6;
+ n->relation = $6;
n->accessMethod = $7;
n->indexParams = $9;
n->whereClause = $11;
*
*****************************************************************************/
-ReindexStmt: REINDEX reindex_type name opt_force
+ReindexStmt: REINDEX reindex_type qualified_name opt_force
{
ReindexStmt *n = makeNode(ReindexStmt);
n->reindexType = $2;
+ n->relation = $3;
+ n->name = NULL;
+ n->force = $4;
+ $$ = (Node *)n;
+ }
+ | REINDEX DATABASE name opt_force
+ {
+ ReindexStmt *n = makeNode(ReindexStmt);
+ n->reindexType = DATABASE;
n->name = $3;
+ n->relation = NULL;
n->force = $4;
$$ = (Node *)n;
}
reindex_type: INDEX { $$ = INDEX; }
| TABLE { $$ = TABLE; }
- | DATABASE { $$ = DATABASE; }
;
+
opt_force: FORCE { $$ = TRUE; }
| /* EMPTY */ { $$ = FALSE; }
;
RenameStmt: ALTER TABLE relation_expr RENAME opt_column opt_name TO name
{
RenameStmt *n = makeNode(RenameStmt);
- n->relname = $3->relname;
- n->inhOpt = $3->inhOpt;
+ n->relation = $3;
n->column = $6;
n->newname = $8;
$$ = (Node *)n;
/*****************************************************************************
*
- * QUERY: Define Rewrite Rule , Define Tuple Rule
- * Define Rule <old rules >
- *
- * only rewrite rule is supported -- ay 9/94
+ * QUERY: Define Rewrite Rule
*
*****************************************************************************/
RuleStmt: CREATE RULE name AS
{ QueryIsRule=TRUE; }
- ON event TO event_object where_clause
+ ON event TO qualified_name where_clause
DO opt_instead RuleActionList
{
RuleStmt *n = makeNode(RuleStmt);
+ n->relation = $9;
n->rulename = $3;
- n->event = $7;
- n->object = $9;
n->whereClause = $10;
+ n->event = $7;
n->instead = $12;
n->actions = $13;
$$ = (Node *)n;
{ $$ = (Node *)NULL; }
;
-event_object: relation_name '.' attr_name
- {
- $$ = makeNode(Attr);
- $$->relname = $1;
- $$->paramNo = NULL;
- $$->attrs = makeList1(makeString($3));
- $$->indirection = NIL;
- }
- | relation_name
- {
- $$ = makeNode(Attr);
- $$->relname = $1;
- $$->paramNo = NULL;
- $$->attrs = NIL;
- $$->indirection = NIL;
- }
- ;
-
/* change me to select, update, etc. some day */
event: SELECT { $$ = CMD_SELECT; }
| UPDATE { $$ = CMD_UPDATE; }
/*****************************************************************************
*
* QUERY:
- * NOTIFY <relation_name> can appear both in rule bodies and
+ * NOTIFY <qualified_name> can appear both in rule bodies and
* as a query-level command
*
*****************************************************************************/
-NotifyStmt: NOTIFY relation_name
+NotifyStmt: NOTIFY qualified_name
{
NotifyStmt *n = makeNode(NotifyStmt);
- n->relname = $2;
+ n->relation = $2;
$$ = (Node *)n;
}
;
-ListenStmt: LISTEN relation_name
+ListenStmt: LISTEN qualified_name
{
ListenStmt *n = makeNode(ListenStmt);
- n->relname = $2;
+ n->relation = $2;
$$ = (Node *)n;
}
-;
+ ;
-UnlistenStmt: UNLISTEN relation_name
+UnlistenStmt: UNLISTEN qualified_name
{
UnlistenStmt *n = makeNode(UnlistenStmt);
- n->relname = $2;
+ n->relation = $2;
$$ = (Node *)n;
}
| UNLISTEN '*'
{
UnlistenStmt *n = makeNode(UnlistenStmt);
- n->relname = "*";
+ n->relation = makeNode(RangeVar);
+ n->relation->relname = "*";
+ n->relation->schemaname = NULL;
$$ = (Node *)n;
}
-;
+ ;
/*****************************************************************************
*
*****************************************************************************/
-ViewStmt: CREATE VIEW name opt_column_list AS SelectStmt
+ViewStmt: CREATE VIEW qualified_name opt_column_list AS SelectStmt
{
ViewStmt *n = makeNode(ViewStmt);
- n->viewname = $3;
+ n->view = $3;
n->aliases = $4;
n->query = (Query *) $6;
$$ = (Node *)n;
*
* CREATE DATABASE
*
- *
*****************************************************************************/
CreatedbStmt: CREATE DATABASE database_name WITH createdb_opt_list
/*****************************************************************************
*
- * DROP DATABASE
- *
- *****************************************************************************/
-
-DropdbStmt: DROP DATABASE database_name
- {
- DropdbStmt *n = makeNode(DropdbStmt);
- n->dbname = $3;
- $$ = (Node *)n;
- }
- ;
-
-
-/*****************************************************************************
- *
* ALTER DATABASE
*
*****************************************************************************/
}
;
+
/*****************************************************************************
*
- * Manipulate a domain
+ * DROP DATABASE
+ *
+ *****************************************************************************/
+
+DropdbStmt: DROP DATABASE database_name
+ {
+ DropdbStmt *n = makeNode(DropdbStmt);
+ n->dbname = $3;
+ $$ = (Node *)n;
+ }
+ ;
+
+
+/*****************************************************************************
*
+ * Manipulate a domain
*
*****************************************************************************/
| /* EMPTY */ {$$ = FALSE; }
;
+
/*****************************************************************************
*
* QUERY:
- * cluster <index_name> on <relation_name>
+ * cluster <index_name> on <qualified_name>
*
*****************************************************************************/
-ClusterStmt: CLUSTER index_name ON relation_name
+ClusterStmt: CLUSTER index_name ON qualified_name
{
ClusterStmt *n = makeNode(ClusterStmt);
- n->relname = $4;
+ n->relation = $4;
n->indexname = $2;
$$ = (Node*)n;
}
n->full = $2;
n->freeze = $3;
n->verbose = $4;
- n->vacrel = NULL;
+ n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
}
- | VACUUM opt_full opt_freeze opt_verbose relation_name
+ | VACUUM opt_full opt_freeze opt_verbose qualified_name
{
VacuumStmt *n = makeNode(VacuumStmt);
n->vacuum = true;
n->full = $2;
n->freeze = $3;
n->verbose = $4;
- n->vacrel = $5;
+ n->relation = $5;
n->va_cols = NIL;
$$ = (Node *)n;
}
n->full = false;
n->freeze = false;
n->verbose = $2;
- n->vacrel = NULL;
+ n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
}
- | analyze_keyword opt_verbose relation_name opt_name_list
+ | analyze_keyword opt_verbose qualified_name opt_name_list
{
VacuumStmt *n = makeNode(VacuumStmt);
n->vacuum = false;
n->full = false;
n->freeze = false;
n->verbose = $2;
- n->vacrel = $3;
+ n->relation = $3;
n->va_cols = $4;
$$ = (Node *)n;
}
*
*****************************************************************************/
-/* This rule used 'opt_column_list' between 'relation_name' and 'insert_rest'
- * originally. When the second rule of 'insert_rest' was changed to use the
- * new 'SelectStmt' rule (for INTERSECT and EXCEPT) it produced a shift/reduce
- * conflict. So I just changed the rules 'InsertStmt' and 'insert_rest' to
- * accept the same statements without any shift/reduce conflicts
- */
-InsertStmt: INSERT INTO relation_name insert_rest
+InsertStmt: INSERT INTO qualified_name insert_rest
{
- $4->relname = $3;
+ $4->relation = $3;
$$ = (Node *) $4;
}
;
$$->targetList = NIL;
$$->selectStmt = $1;
}
- | '(' columnList ')' VALUES '(' target_list ')'
+ | '(' insert_column_list ')' VALUES '(' target_list ')'
{
$$ = makeNode(InsertStmt);
$$->cols = $2;
$$->targetList = $6;
$$->selectStmt = NULL;
}
- | '(' columnList ')' SelectStmt
+ | '(' insert_column_list ')' SelectStmt
{
$$ = makeNode(InsertStmt);
$$->cols = $2;
}
;
-opt_column_list: '(' columnList ')' { $$ = $2; }
- | /*EMPTY*/ { $$ = NIL; }
- ;
-
-columnList: columnList ',' columnElem
+insert_column_list: insert_column_list ',' insert_column_item
{ $$ = lappend($1, $3); }
- | columnElem
+ | insert_column_item
{ $$ = makeList1($1); }
;
-columnElem: ColId opt_indirection
+insert_column_item: ColId opt_indirection
{
- Ident *id = makeNode(Ident);
- id->name = $1;
- id->indirection = $2;
- $$ = (Node *)id;
+ ResTarget *n = makeNode(ResTarget);
+ n->name = $1;
+ n->indirection = $2;
+ n->val = NULL;
+ $$ = (Node *)n;
}
;
DeleteStmt: DELETE FROM relation_expr where_clause
{
DeleteStmt *n = makeNode(DeleteStmt);
- n->relname = $3->relname;
- n->inhOpt = $3->inhOpt;
+ n->relation = $3;
n->whereClause = $4;
$$ = (Node *)n;
}
;
-LockStmt: LOCK_P opt_table relation_name_list opt_lock
+LockStmt: LOCK_P opt_table qualified_name_list opt_lock
{
LockStmt *n = makeNode(LockStmt);
- n->rellist = $3;
+ n->relations = $3;
n->mode = $4;
$$ = (Node *)n;
}
where_clause
{
UpdateStmt *n = makeNode(UpdateStmt);
- n->relname = $2->relname;
- n->inhOpt = $2->inhOpt;
+ n->relation = $2;
n->targetList = $4;
n->fromClause = $5;
n->whereClause = $6;
SelectStmt *n = makeNode(SelectStmt);
n->distinctClause = $2;
n->targetList = $3;
- n->istemp = (bool) ((Value *) lfirst($4))->val.ival;
- n->into = (char *) lnext($4);
+ n->into = $4;
n->intoColNames = NIL;
n->fromClause = $5;
n->whereClause = $6;
}
;
- /* easy way to return two values. Can someone improve this? bjm */
into_clause: INTO OptTempTableName { $$ = $2; }
- | /*EMPTY*/ { $$ = makeList1(makeInteger(FALSE)); }
+ | /*EMPTY*/ { $$ = NULL; }
;
/*
* Redundancy here is needed to avoid shift/reduce conflicts,
* since TEMP is not a reserved word. See also OptTemp.
- *
- * The result is a cons cell (not a true list!) containing
- * a boolean and a table name.
*/
-OptTempTableName: TEMPORARY opt_table relation_name
- { $$ = lcons(makeInteger(TRUE), (List *) $3); }
- | TEMP opt_table relation_name
- { $$ = lcons(makeInteger(TRUE), (List *) $3); }
- | LOCAL TEMPORARY opt_table relation_name
- { $$ = lcons(makeInteger(TRUE), (List *) $4); }
- | LOCAL TEMP opt_table relation_name
- { $$ = lcons(makeInteger(TRUE), (List *) $4); }
- | GLOBAL TEMPORARY opt_table relation_name
+OptTempTableName: TEMPORARY opt_table qualified_name
+ {
+ $$ = $3;
+ $$->istemp = true;
+ }
+ | TEMP opt_table qualified_name
+ {
+ $$ = $3;
+ $$->istemp = true;
+ }
+ | LOCAL TEMPORARY opt_table qualified_name
+ {
+ $$ = $4;
+ $$->istemp = true;
+ }
+ | LOCAL TEMP opt_table qualified_name
+ {
+ $$ = $4;
+ $$->istemp = true;
+ }
+ | GLOBAL TEMPORARY opt_table qualified_name
{
elog(ERROR, "GLOBAL TEMPORARY TABLE is not currently supported");
- $$ = lcons(makeInteger(TRUE), (List *) $4);
+ $$ = $4;
+ $$->istemp = true;
}
- | GLOBAL TEMP opt_table relation_name
+ | GLOBAL TEMP opt_table qualified_name
{
elog(ERROR, "GLOBAL TEMPORARY TABLE is not currently supported");
- $$ = lcons(makeInteger(TRUE), (List *) $4);
+ $$ = $4;
+ $$->istemp = true;
+ }
+ | TABLE qualified_name
+ {
+ $$ = $2;
+ $$->istemp = false;
+ }
+ | qualified_name
+ {
+ $$ = $1;
+ $$->istemp = false;
}
- | TABLE relation_name
- { $$ = lcons(makeInteger(FALSE), (List *) $2); }
- | relation_name
- { $$ = lcons(makeInteger(FALSE), (List *) $1); }
;
opt_table: TABLE { $$ = TRUE; }
* ...however, recursive addattr and rename supported. make special
* cases for these.
*/
-relation_name_list: name_list;
-
-name_list: name
- { $$ = makeList1(makeString($1)); }
- | name_list ',' name
- { $$ = lappend($1, makeString($3)); }
- ;
group_clause: GROUP BY expr_list { $$ = $3; }
| /*EMPTY*/ { $$ = NIL; }
}
| relation_expr alias_clause
{
- $1->name = $2;
+ $1->alias = $2;
$$ = (Node *) $1;
}
| select_with_parens
{
RangeSubselect *n = makeNode(RangeSubselect);
n->subquery = $1;
- n->name = $2;
+ n->alias = $2;
$$ = (Node *) n;
}
| joined_table
alias_clause: AS ColId '(' name_list ')'
{
- $$ = makeNode(Attr);
- $$->relname = $2;
- $$->attrs = $4;
+ $$ = makeNode(Alias);
+ $$->aliasname = $2;
+ $$->colnames = $4;
}
| AS ColId
{
- $$ = makeNode(Attr);
- $$->relname = $2;
+ $$ = makeNode(Alias);
+ $$->aliasname = $2;
}
| ColId '(' name_list ')'
{
- $$ = makeNode(Attr);
- $$->relname = $1;
- $$->attrs = $3;
+ $$ = makeNode(Alias);
+ $$->aliasname = $1;
+ $$->colnames = $3;
}
| ColId
{
- $$ = makeNode(Attr);
- $$->relname = $1;
+ $$ = makeNode(Alias);
+ $$->aliasname = $1;
}
;
;
-relation_expr: relation_name
+relation_expr: qualified_name
{
/* default inheritance */
- $$ = makeNode(RangeVar);
- $$->relname = $1;
+ $$ = $1;
$$->inhOpt = INH_DEFAULT;
- $$->name = NULL;
+ $$->alias = NULL;
}
- | relation_name '*'
+ | qualified_name '*'
{
/* inheritance query */
- $$ = makeNode(RangeVar);
- $$->relname = $1;
+ $$ = $1;
$$->inhOpt = INH_YES;
- $$->name = NULL;
+ $$->alias = NULL;
}
- | ONLY relation_name
+ | ONLY qualified_name
{
/* no inheritance */
- $$ = makeNode(RangeVar);
- $$->relname = $2;
+ $$ = $2;
$$->inhOpt = INH_NO;
- $$->name = NULL;
+ $$->alias = NULL;
}
;
else type = xlateSqlType("bit");
$$ = type;
}
+ ;
/*
* inside parentheses, such as function arguments; that cannot introduce
* ambiguity to the b_expr syntax.
*/
-c_expr: attr
+c_expr: columnref
{ $$ = (Node *) $1; }
- | ColId opt_indirection
+ | AexprConst
+ { $$ = $1; }
+ | PARAM attrs opt_indirection
{
- /* could be a column name or a relation_name */
- Ident *n = makeNode(Ident);
- n->name = $1;
- n->indirection = $2;
+ /*
+ * PARAM without field names is considered a constant,
+ * but with 'em, it is not. Not very consistent ...
+ */
+ ParamRef *n = makeNode(ParamRef);
+ n->number = $1;
+ n->fields = $2;
+ n->indirection = $3;
$$ = (Node *)n;
}
- | AexprConst
- { $$ = $1; }
| '(' a_expr ')'
{ $$ = $2; }
+ | '(' a_expr ')' attrs opt_indirection
+ {
+ ExprFieldSelect *n = makeNode(ExprFieldSelect);
+ n->arg = $2;
+ n->fields = $4;
+ n->indirection = $5;
+ $$ = (Node *)n;
+ }
| CAST '(' a_expr AS Typename ')'
{ $$ = makeTypeCast($3, $5); }
| case_expr
{ $$ = NULL; }
;
-attr: relation_name '.' attrs opt_indirection
+/*
+ * columnref starts with relation_name not ColId, so that OLD and NEW
+ * references can be accepted. Note that when there are more than two
+ * dotted names, the first name is not actually a relation name...
+ */
+columnref: relation_name opt_indirection
{
- $$ = makeNode(Attr);
- $$->relname = $1;
- $$->paramNo = NULL;
- $$->attrs = $3;
- $$->indirection = $4;
+ $$ = makeNode(ColumnRef);
+ $$->fields = makeList1(makeString($1));
+ $$->indirection = $2;
}
- | ParamNo '.' attrs opt_indirection
+ | relation_name attrs opt_indirection
{
- $$ = makeNode(Attr);
- $$->relname = NULL;
- $$->paramNo = $1;
- $$->attrs = $3;
- $$->indirection = $4;
+ $$ = makeNode(ColumnRef);
+ $$->fields = lcons(makeString($1), $2);
+ $$->indirection = $3;
}
;
-attrs: attr_name
- { $$ = makeList1(makeString($1)); }
- | attrs '.' attr_name
+attrs: opt_attrs '.' attr_name
{ $$ = lappend($1, makeString($3)); }
- | attrs '.' '*'
+ | opt_attrs '.' '*'
{ $$ = lappend($1, makeString("*")); }
;
+opt_attrs: /*EMPTY*/
+ { $$ = NIL; }
+ | opt_attrs '.' attr_name
+ { $$ = lappend($1, makeString($3)); }
+ ;
+
opt_empty_parentheses: '(' ')' { $$ = TRUE; }
| /*EMPTY*/ { $$ = TRUE; }
+ ;
/*****************************************************************************
*
{
$$ = makeNode(ResTarget);
$$->name = $3;
- $$->indirection = NULL;
+ $$->indirection = NIL;
$$->val = (Node *)$1;
}
| a_expr
{
$$ = makeNode(ResTarget);
$$->name = NULL;
- $$->indirection = NULL;
+ $$->indirection = NIL;
$$->val = (Node *)$1;
}
- | relation_name '.' '*'
- {
- Attr *att = makeNode(Attr);
- att->relname = $1;
- att->paramNo = NULL;
- att->attrs = makeList1(makeString("*"));
- att->indirection = NIL;
- $$ = makeNode(ResTarget);
- $$->name = NULL;
- $$->indirection = NULL;
- $$->val = (Node *)att;
- }
| '*'
{
- Attr *att = makeNode(Attr);
- att->relname = "*";
- att->paramNo = NULL;
- att->attrs = NULL;
- att->indirection = NIL;
+ ColumnRef *n = makeNode(ColumnRef);
+ n->fields = makeList1(makeString("*"));
+ n->indirection = NIL;
$$ = makeNode(ResTarget);
$$->name = NULL;
- $$->indirection = NULL;
- $$->val = (Node *)att;
+ $$->indirection = NIL;
+ $$->val = (Node *)n;
}
;
$$ = $1;
}
;
+
+qualified_name_list: qualified_name
+ { $$ = makeList1($1); }
+ | qualified_name_list ',' qualified_name
+ { $$ = lappend($1, $3); }
+ ;
+
+qualified_name: ColId
+ {
+ $$ = makeNode(RangeVar);
+ $$->catalogname = NULL;
+ $$->schemaname = NULL;
+ $$->relname = $1;
+ }
+ | ColId '.' ColId
+ {
+ $$ = makeNode(RangeVar);
+ $$->catalogname = NULL;
+ $$->schemaname = $1;
+ $$->relname = $3;
+ }
+ | ColId '.' ColId '.' ColId
+ {
+ $$ = makeNode(RangeVar);
+ $$->catalogname = $1;
+ $$->schemaname = $3;
+ $$->relname = $5;
+ }
+ ;
+
+name_list: name
+ { $$ = makeList1(makeString($1)); }
+ | name_list ',' name
+ { $$ = lappend($1, makeString($3)); }
+ ;
+
name: ColId { $$ = $1; };
database_name: ColId { $$ = $1; };
$$ = (Node *)n;
}
- | ParamNo
- { $$ = (Node *)$1; }
+ | PARAM opt_indirection
+ {
+ ParamRef *n = makeNode(ParamRef);
+ n->number = $1;
+ n->fields = NIL;
+ n->indirection = $2;
+ $$ = (Node *)n;
+ }
| TRUE_P
{
A_Const *n = makeNode(A_Const);
}
;
-ParamNo: PARAM opt_indirection
- {
- $$ = makeNode(ParamNo);
- $$->number = $1;
- $$->indirection = $2;
- }
- ;
-
Iconst: ICONST { $$ = $1; };
Sconst: SCONST { $$ = $1; };
UserId: ColId { $$ = $1; };
| AGGREGATE { $$ = "aggregate"; }
| ALTER { $$ = "alter"; }
| AT { $$ = "at"; }
- | AUTHORIZATION { $$ = "authorization"; }
| BACKWARD { $$ = "backward"; }
| BEFORE { $$ = "before"; }
| BEGIN_TRANS { $$ = "begin"; }
| COMMITTED { $$ = "committed"; }
| CONSTRAINTS { $$ = "constraints"; }
| COPY { $$ = "copy"; }
- | CREATE { $$ = "create"; }
| CREATEDB { $$ = "createdb"; }
| CREATEUSER { $$ = "createuser"; }
| CURSOR { $$ = "cursor"; }
| FORWARD { $$ = "forward"; }
| FUNCTION { $$ = "function"; }
| GLOBAL { $$ = "global"; }
- | GRANT { $$ = "grant"; }
| HANDLER { $$ = "handler"; }
| HOUR_P { $$ = "hour"; }
| IMMEDIATE { $$ = "immediate"; }
* - thomas 2000-11-28
*/
func_name_keyword:
- BETWEEN { $$ = "between"; }
+ AUTHORIZATION { $$ = "authorization"; }
+ | BETWEEN { $$ = "between"; }
| BINARY { $$ = "binary"; }
| CROSS { $$ = "cross"; }
| FREEZE { $$ = "freeze"; }
| COLLATE { $$ = "collate"; }
| COLUMN { $$ = "column"; }
| CONSTRAINT { $$ = "constraint"; }
+ | CREATE { $$ = "create"; }
| CURRENT_DATE { $$ = "current_date"; }
| CURRENT_TIME { $$ = "current_time"; }
| CURRENT_TIMESTAMP { $$ = "current_timestamp"; }
| FOR { $$ = "for"; }
| FOREIGN { $$ = "foreign"; }
| FROM { $$ = "from"; }
+ | GRANT { $$ = "grant"; }
| GROUP { $$ = "group"; }
| HAVING { $$ = "having"; }
| INITIALLY { $$ = "initially"; }
makeTypeCast(Node *arg, TypeName *typename)
{
/*
- * If arg is an A_Const or ParamNo, just stick the typename into the
+ * If arg is an A_Const, just stick the typename into the
* field reserved for it --- unless there's something there already!
* (We don't want to collapse x::type1::type2 into just x::type2.)
* Otherwise, generate a TypeCast node.
((A_Const *) arg)->typename = typename;
return arg;
}
- else if (IsA(arg, ParamNo) &&
- ((ParamNo *) arg)->typename == NULL)
- {
- ((ParamNo *) arg)->typename = typename;
- return arg;
- }
else
{
TypeCast *n = makeNode(TypeCast);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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,
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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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
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",
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);
* 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);
/*
* 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");
/*
/*
* 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
*/
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);
}
}
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",
* 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)
{
* 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)
{
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
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);
* 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;
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:
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;
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,
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))
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))
case NOT:
{
Node *rexpr = transformExpr(pstate,
- a->rexpr,
- precedence);
+ a->rexpr);
Expr *expr = makeNode(Expr);
if (!coerce_to_boolean(pstate, &rexpr))
}
break;
}
- case T_Ident:
- {
- result = transformIdent(pstate, (Ident *) expr, precedence);
- break;
- }
case T_FuncCall:
{
FuncCall *fn = (FuncCall *) expr;
/* 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:
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;
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");
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));
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
{
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;
{
BooleanTest *b = (BooleanTest *) expr;
- b->arg = transformExpr(pstate, b->arg, precedence);
+ b->arg = transformExpr(pstate, b->arg);
if (!coerce_to_boolean(pstate, &b->arg))
{
}
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;
+
+ /*----------
+ * The allowed syntaxes are:
+ *
+ * A First try to resolve as unqualified column name;
+ * if no luck, try to resolve as unqual. table name (A.*).
+ * A.B A is an unqual. table name; B is either a
+ * column or function name (trying column name first).
+ * A.B.C schema A, table B, col or func name C.
+ * A.B.C.D catalog A, schema B, table C, col or func D.
+ * A.* A is an unqual. table name; means whole-row value.
+ * A.B.* whole-row value of table B in schema A.
+ * A.B.C.* whole-row value of table C in schema B in catalog A.
+ *
+ * We do not need to cope with bare "*"; that will only be accepted by
+ * the grammar at the top level of a SELECT list, and transformTargetList
+ * will take care of it before it ever gets here.
+ *
+ * Currently, if a catalog name is given then it must equal the current
+ * database name; we check it here and then discard it.
+ *
+ * For whole-row references, the result is an untransformed RangeVar,
+ * which will work as the argument to a function call, but not in any
+ * other context at present. (We could instead coerce to a whole-row Var,
+ * but that will fail for subselect and join RTEs, because there is no
+ * pg_type entry for their rowtypes.)
+ *----------
+ */
+ switch (numnames)
+ {
+ case 1:
+ {
+ char *name = strVal(lfirst(cref->fields));
- basenode = ParseNestedFuncOrColumn(pstate, att, precedence);
- return transformIndirection(pstate, basenode, att->indirection);
-}
+ /* 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;
-static Node *
-transformIdent(ParseState *pstate, Ident *ident, int precedence)
-{
- Node *result = NULL;
- int sublevels_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));
- /*
- * try to find the ident as a relation ... but not if subscripts
- * appear
- */
- if (ident->indirection == NIL &&
- refnameRangeTblEntry(pstate, ident->name, &sublevels_up) != NULL)
- {
- ident->isRel = TRUE;
- result = (Node *) ident;
- }
+ /* Whole-row reference? */
+ if (strcmp(name2, "*") == 0)
+ {
+ rv = makeNode(RangeVar);
+ rv->relname = name1;
+ rv->inhOpt = INH_DEFAULT;
+ node = (Node *) rv;
+ break;
+ }
- if (result == NULL || precedence == EXPR_COLUMN_FIRST)
- {
- /* try to find the ident as a column */
- Node *var = colnameToVar(pstate, ident->name);
+ /* 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))));
- if (var != NULL)
+ /* 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:
{
- ident->isRel = FALSE;
- result = transformIndirection(pstate, var, ident->indirection);
+ 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);
}
/*
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));
*
*
* 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"
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);
/*
- ** 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
- *
- * 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.
+ * Parse a function call
*
- * 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.
+ * 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.
*
- * 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);
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
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)))
{
*/
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;
}
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)
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,
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
basetype, type, -1);
basetype = type;
return (Node *) ParseAgg(pstate, funcname, basetype,
- fargs, agg_star, agg_distinct,
- precedence);
+ fargs, agg_star, agg_distinct);
}
else
{
}
/*
- * 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));
foreach(i, fargs)
{
Node *arg = lfirst(i);
+ Oid toid;
- if (IsA(arg, Ident) &&((Ident *) arg)->isRel)
+ if (IsA(arg, RangeVar))
{
RangeTblEntry *rte;
int vnum;
/*
* a relation
*/
- refname = ((Ident *) arg)->name;
+ refname = ((RangeVar *) arg)->relname;
rte = refnameRangeTblEntry(pstate, refname,
&sublevels_up);
* 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",
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 */
-
+ fdresult = func_get_detail(funcname, fargs, nargs, oid_array,
+ &funcid, &rettype, &retset,
+ &true_oid_array);
+ if (fdresult == FUNCDETAIL_COERCION)
+ {
/*
- * 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.
+ * We can do it as a trivial coercion. coerce_type can handle
+ * these cases, so why duplicate code...
*/
- funcid = F_SETEVAL;
- rettype = toid;
- retset = true;
- true_oid_array = oid_array;
+ return coerce_type(pstate, lfirst(fargs),
+ oid_array[0], rettype, -1);
}
- else
+ if (fdresult != FUNCDETAIL_NORMAL)
{
- 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.
+ * Oops. Time to die.
+ *
+ * If we are dealing with the attribute notation rel.function,
+ * give an error message that is appropriate for that case.
*/
- 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");
- }
+ 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 */
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);
}
/*
- ** 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)
/*
* 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:
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;
}
break;
}
- return NULL;
+ /* Else generate a FieldSelect expression */
+ fselect = setup_field_select(first_arg, funcname, argrelid);
+ return (Node *) fselect;
}
/*
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
{
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);
}
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);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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))
if (j->alias)
{
- if (strcmp(j->alias->relname, refname) == 0)
+ if (strcmp(j->alias->aliasname, refname) == 0)
return (Node *) j; /* matched a join alias */
/*
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))
{
if (j->alias)
{
- scanNameSpaceForConflict(pstate, namespace2, j->alias->relname);
+ scanNameSpaceForConflict(pstate, namespace2, j->alias->aliasname);
/*
* Tables within an aliased join are invisible from outside
* 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)
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;
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
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;
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;
rte->alias = alias;
eref = copyObject(alias);
- numaliases = length(eref->attrs);
+ numaliases = length(eref->colnames);
/* fill in any unspecified alias columns */
varattno = 0;
char *attrname;
attrname = pstrdup(te->resdom->resname);
- eref->attrs = lappend(eref->attrs, makeString(attrname));
+ eref->colnames = lappend(eref->colnames, makeString(attrname));
}
}
if (varattno < numaliases)
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;
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;
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++)
{
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)));
else if (rte->rtekind == RTE_SUBQUERY)
{
/* Subquery RTE */
- List *aliasp = rte->eref->attrs;
+ List *aliasp = rte->eref->colnames;
List *tlistitem;
varattno = 0;
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;
* 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
*/
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
}
/* 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)
{
*
*
* 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"
/* 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);
{
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.
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,
}
else
{
- /* Everything else but Attr */
+ /* Everything else but ColumnRef */
p_target = lappend(p_target,
transformTargetEntry(pstate,
res->val,
/*
* 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)
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);
}
}
foreach(tl, cols)
{
- char *name = ((Ident *) lfirst(tl))->name;
+ char *name = ((ResTarget *) lfirst(tl))->name;
int attrno;
/* Lookup column name, elog on failure */
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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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,
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
*/
foreach(l, action)
/*
* 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
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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));
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)
*
*
* 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
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");
}
/*
tag = "CREATE DOMAIN";
break;
+ case T_CreateSchemaStmt:
+ tag = "CREATE";
+ break;
+
case T_CreateStmt:
tag = "CREATE";
break;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
*/
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,
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/*
* relation and attribute manipulation
*/
+ case T_CreateSchemaStmt:
+ {
+ CreateSchemaStmt *stmt = (CreateSchemaStmt *) parsetree;
+
+ CreateSchemaCommand(stmt);
+ }
+ break;
+
case T_CreateStmt:
DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION);
* 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)
{
case T_TruncateStmt:
{
- TruncateRelation(((TruncateStmt *) parsetree)->relName);
+ relname = ((TruncateStmt *) parsetree)->relation->relname;
+ TruncateRelation(relname);
}
break;
if (stmt->direction != FROM)
SetQuerySnapshot();
- DoCopy(stmt->relname,
+ DoCopy(stmt->relation->relname,
stmt->binary,
stmt->oids,
(bool) (stmt->direction == FROM),
{
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);
renameatt(relname, /* relname */
stmt->column, /* old att name */
stmt->newname, /* new att name */
- interpretInhOption(stmt->inhOpt)); /* recursive? */
+ interpretInhOption(stmt->relation->inhOpt)); /* recursive? */
}
}
break;
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 */
{
ViewStmt *stmt = (ViewStmt *) parsetree;
- DefineView(stmt->viewname, stmt->query); /* retrieve parsetree */
+ DefineView(stmt->view->relname, stmt->query); /* retrieve parsetree */
}
break;
{
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,
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]);
{
NotifyStmt *stmt = (NotifyStmt *) parsetree;
- Async_Notify(stmt->relname);
+ Async_Notify(stmt->relation->relname);
}
break;
{
ListenStmt *stmt = (ListenStmt *) parsetree;
- Async_Listen(stmt->relname, MyProcPid);
+ Async_Listen(stmt->relation->relname, MyProcPid);
}
break;
{
UnlistenStmt *stmt = (UnlistenStmt *) parsetree;
- Async_Unlisten(stmt->relname, MyProcPid);
+ Async_Unlisten(stmt->relation->relname, MyProcPid);
}
break;
{
ClusterStmt *stmt = (ClusterStmt *) parsetree;
- relname = stmt->relname;
+ relname = stmt->relation->relname;
if (IsSystemRelationName(relname))
elog(ERROR, "CLUSTER: relation \"%s\" is a system catalog",
relname);
/*
* ******************************** DOMAIN statements ****
- *
*/
case T_CreateDomainStmt:
DefineDomain((CreateDomainStmt *) parsetree);
/*
* ******************************** USER statements ****
- *
*/
-
case T_CreateUserStmt:
CreateUser((CreateUserStmt *) parsetree);
break;
switch (stmt->reindexType)
{
case INDEX:
- relname = (char *) stmt->name;
+ relname = (char *) stmt->relation->relname;
if (IsSystemRelationName(relname))
{
if (!allowSystemTableMods)
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);
* 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.
*
#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"
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;
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;
{
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");
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;
/*
* 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;
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;
}
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))));
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))));
* 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 $
*
*-------------------------------------------------------------------------
*/
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200203191
+#define CATALOG_VERSION_NO 200203211
#endif
* 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 $
*
*-------------------------------------------------------------------------
*/
*/
extern void LockTableCommand(LockStmt *lockstmt);
+/*
+ * SCHEMA
+ */
+extern void CreateSchemaCommand(CreateSchemaStmt *parsetree);
+
#endif /* COMMAND_H */
* 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 $
*
*-------------------------------------------------------------------------
*/
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);
* 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 $
*
*-------------------------------------------------------------------------
*/
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,
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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 */
} 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 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 ParamNo
+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
} 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
*/
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
{
/*
* 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;
/*
} 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)
*
} 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;
/*
{
NodeTag type;
Node *subquery; /* the untransformed sub-select clause */
- Attr *name; /* table alias & optional column aliases */
+ Alias *alias; /* table alias & optional column aliases */
} RangeSubselect;
/*
* 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
*/
/*
- * 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 */
/*
* 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 */
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 */
/*
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;
/* ----------------------
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;
/* ----------------------
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 */
*****************************************************************************/
/* ----------------------
+ * 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
*
* The fields are used in different ways by the different variants of
* 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 */
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;
char *groupname;
} PrivGrantee;
-
typedef struct FuncWithArgs
{
NodeTag type;
List *funcargs; /* list of Typename nodes */
} FuncWithArgs;
-
/* This is only used internally in gram.y. */
typedef struct PrivTarget
{
List *objs;
} PrivTarget;
-
/* ----------------------
* Close Portal Statement
* ----------------------
{
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 */
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;
{
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 */
{
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 */
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;
/* ----------------------
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;
typedef struct DropStmt
{
NodeTag type;
- List *names;
+ List *objects;
int removeType;
int behavior; /* CASCADE or RESTRICT drop behavior */
} DropStmt;
typedef struct TruncateStmt
{
NodeTag type;
- char *relName; /* relation to be truncated */
+ RangeVar *relation; /* relation to be truncated */
} TruncateStmt;
/* ----------------------
{
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 */
{
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) */
} 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. */
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;
typedef struct NotifyStmt
{
NodeTag type;
- char *relname; /* relation to notify */
+ RangeVar *relation; /* qualified name to notify */
} NotifyStmt;
/* ----------------------
typedef struct ListenStmt
{
NodeTag type;
- char *relname; /* relation to listen on */
+ RangeVar *relation; /* qualified name to listen on */
} ListenStmt;
/* ----------------------
typedef struct UnlistenStmt
{
NodeTag type;
- char *relname; /* relation to unlisten on */
+ RangeVar *relation; /* qualified name to unlisten on, or '*' */
} UnlistenStmt;
/* ----------------------
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;
char *filename; /* file to load */
} LoadStmt;
-
/* ----------------------
* Createdb Statement
* ----------------------
typedef struct ClusterStmt
{
NodeTag type;
- char *relname; /* relation being indexed */
+ RangeVar *relation; /* relation being indexed */
char *indexname; /* original index defined */
} ClusterStmt;
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;
typedef struct LockStmt
{
NodeTag type;
- List *rellist; /* relations to lock */
+ List *relations; /* relations to lock */
int mode; /* lock mode */
} LockStmt;
{
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;
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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.
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;
* 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 $
*
*-------------------------------------------------------------------------
*/
#include "parser/parse_node.h"
extern List *parse_analyze(Node *parseTree, ParseState *parentParseState);
+extern List *analyzeCreateSchemaStmt(CreateSchemaStmt *stmt);
extern void CheckSelectForUpdate(Query *qry);
* 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 $
*
*-------------------------------------------------------------------------
*/
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 */
* 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 $
*
*-------------------------------------------------------------------------
*/
#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);
* 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 $
*
*-------------------------------------------------------------------------
*/
} 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,
* 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 $
*
*-------------------------------------------------------------------------
*/
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,
List *coltypmods,
List *leftcols,
List *rightcols,
- Attr *alias,
+ Alias *alias,
bool inFromCl);
extern void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte,
bool addToJoinList, bool addToNameSpace);
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);
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
-- 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);
-- 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
-- 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;
-- 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
--
-- 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
-- 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
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
-- 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
--
-- 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
-- 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
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
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
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