From 95ef6a344821655ce4d0a74999ac49dd6af6d342 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 21 Mar 2002 16:02:16 +0000 Subject: [PATCH] First phase of SCHEMA changes, concentrating on fixing the grammar and the parsetree representation. As yet we don't *do* anything with schema names, just drop 'em on the floor; but you can enter schema-compatible command syntax, and there's even a primitive CREATE SCHEMA command. No doc updates yet, except to note that you can now extract a field from a function-returning-row's result with (foo(...)).fieldname. --- doc/src/sgml/xfunc.sgml | 52 +- src/backend/catalog/aclchk.c | 4 +- src/backend/catalog/heap.c | 6 +- src/backend/commands/command.c | 114 +++- src/backend/commands/creatinh.c | 20 +- src/backend/commands/explain.c | 8 +- src/backend/commands/sequence.c | 11 +- src/backend/commands/trigger.c | 59 +- src/backend/commands/vacuum.c | 12 +- src/backend/commands/view.c | 28 +- src/backend/executor/execMain.c | 6 +- src/backend/executor/spi.c | 7 +- src/backend/nodes/copyfuncs.c | 205 ++++--- src/backend/nodes/equalfuncs.c | 174 +++--- src/backend/nodes/makefuncs.c | 21 +- src/backend/nodes/nodeFuncs.c | 10 +- src/backend/nodes/outfuncs.c | 165 +++-- src/backend/nodes/print.c | 8 +- src/backend/nodes/readfuncs.c | 150 +++-- src/backend/optimizer/util/clauses.c | 6 +- src/backend/parser/analyze.c | 322 ++++++---- src/backend/parser/gram.y | 700 ++++++++++++---------- src/backend/parser/parse_agg.c | 7 +- src/backend/parser/parse_clause.c | 30 +- src/backend/parser/parse_expr.c | 326 +++++++--- src/backend/parser/parse_func.c | 390 ++++-------- src/backend/parser/parse_node.c | 6 +- src/backend/parser/parse_relation.c | 62 +- src/backend/parser/parse_target.c | 104 +++- src/backend/rewrite/rewriteDefine.c | 86 +-- src/backend/rewrite/rewriteManip.c | 10 +- src/backend/tcop/postgres.c | 8 +- src/backend/tcop/pquery.c | 6 +- src/backend/tcop/utility.c | 82 +-- src/backend/utils/adt/ruleutils.c | 41 +- src/include/catalog/catversion.h | 4 +- src/include/commands/command.h | 7 +- src/include/nodes/makefuncs.h | 4 +- src/include/nodes/nodes.h | 13 +- src/include/nodes/parsenodes.h | 210 ++++--- src/include/nodes/primnodes.h | 6 +- src/include/parser/analyze.h | 3 +- src/include/parser/parse_agg.h | 5 +- src/include/parser/parse_expr.h | 7 +- src/include/parser/parse_func.h | 7 +- src/include/parser/parse_relation.h | 8 +- src/test/regress/expected/alter_table.out | 2 +- src/test/regress/expected/errors.out | 8 +- src/test/regress/expected/rules.out | 2 +- src/test/regress/expected/union.out | 2 +- src/test/regress/input/misc.source | 20 +- src/test/regress/output/misc.source | 20 +- 52 files changed, 2039 insertions(+), 1535 deletions(-) diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index 73c0287d44..262c1e2e8c 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -1,5 +1,5 @@ @@ -306,7 +306,8 @@ CREATE FUNCTION new_emp() RETURNS EMP AS ' 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.) @@ -328,10 +329,35 @@ ERROR: function declared to return emp returns varchar instead of text at colum there are some unpleasant restrictions on how functions returning composite types can be used. Briefly, when calling a function that returns a row, we cannot retrieve the entire row. We must either - project a single attribute out of the row or pass the entire row into + extract a single attribute out of the row or pass the entire row into another function. (Trying to display the entire row value will yield a meaningless number.) For example, + +SELECT (new_emp()).name; + + + + name +------ + None + + + We need the extra parentheses to keep the parser from getting confused: + + +SELECT new_emp().name; +ERROR: parser: parse error at or near "." + + + + + Another approach is to use + functional notation for extracting attributes. The simple way + to explain this is that we can use the + notations attribute(table) and table.attribute + interchangeably: + SELECT name(new_emp()); @@ -343,13 +369,6 @@ SELECT name(new_emp()); - - This example makes use of the - function notation for projecting attributes. The simple way - to explain this is that we can usually use the - notations attribute(table) and table.attribute - interchangeably: - -- -- this is the same as: @@ -367,19 +386,6 @@ SELECT name(EMP) AS youngster - - 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. - - -SELECT new_emp().name AS nobody; -ERROR: parser: parse error at or near "." - - - 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 diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 2bdacbdf3b..2244827f7c 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.56 2002/03/06 06:09:24 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.57 2002/03/21 16:00:29 tgl Exp $ * * NOTES * See acl.h. @@ -200,7 +200,7 @@ ExecuteGrantStmt_Table(GrantStmt *stmt) foreach(i, stmt->objects) { - char *relname = strVal(lfirst(i)); + char *relname = ((RangeVar *) lfirst(i))->relname; Relation relation; HeapTuple tuple; Form_pg_class pg_class_tuple; diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index e7bb128076..629ffe7c2e 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.189 2002/03/20 19:43:34 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.190 2002/03/21 16:00:29 tgl Exp $ * * * INTERFACE ROUTINES @@ -1728,7 +1728,7 @@ AddRelationRawConstraints(Relation rel, /* * Transform raw parsetree to executable expression. */ - expr = transformExpr(pstate, cdef->raw_expr, EXPR_COLUMN_FIRST); + expr = transformExpr(pstate, cdef->raw_expr); /* * Make sure it yields a boolean result. @@ -1863,7 +1863,7 @@ cookDefault(ParseState *pstate, /* * Transform raw parsetree to executable expression. */ - expr = transformExpr(pstate, raw_default, EXPR_COLUMN_FIRST); + expr = transformExpr(pstate, raw_default); /* * Make sure default expr does not refer to any vars. diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index c32be8b02f..5821e1d103 100644 --- a/src/backend/commands/command.c +++ b/src/backend/commands/command.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.161 2002/03/14 22:44:50 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.162 2002/03/21 16:00:31 tgl Exp $ * * NOTES * The PerformAddAttribute() code, like most of the relation @@ -33,7 +33,7 @@ #include "catalog/pg_type.h" #include "commands/command.h" #include "commands/trigger.h" -#include "commands/defrem.h" /* For add constraint unique, primary */ +#include "commands/defrem.h" #include "executor/execdefs.h" #include "executor/executor.h" #include "miscadmin.h" @@ -44,7 +44,8 @@ #include "parser/parse_expr.h" #include "parser/parse_oper.h" #include "parser/parse_relation.h" -#include "parser/analyze.h" /* For add constraint unique, primary */ +#include "parser/analyze.h" +#include "tcop/utility.h" #include "utils/acl.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -1279,8 +1280,7 @@ AlterTableAddConstraint(char *relationName, * Convert the A_EXPR in raw_expr into an * EXPR */ - expr = transformExpr(pstate, constr->raw_expr, - EXPR_COLUMN_FIRST); + expr = transformExpr(pstate, constr->raw_expr); /* * Make sure it yields a boolean result. @@ -1366,7 +1366,7 @@ AlterTableAddConstraint(char *relationName, List *list; int count; - if (is_temp_rel_name(fkconstraint->pktable_name) && + if (is_temp_rel_name(fkconstraint->pktable->relname) && !is_temp_rel_name(relationName)) elog(ERROR, "ALTER TABLE / ADD CONSTRAINT: Unable to reference temporary table from permanent table constraint."); @@ -1375,10 +1375,10 @@ AlterTableAddConstraint(char *relationName, * someone doesn't delete rows out from under us. */ - pkrel = heap_openr(fkconstraint->pktable_name, AccessExclusiveLock); + pkrel = heap_openr(fkconstraint->pktable->relname, AccessExclusiveLock); if (pkrel->rd_rel->relkind != RELKIND_RELATION) elog(ERROR, "referenced table \"%s\" not a relation", - fkconstraint->pktable_name); + fkconstraint->pktable->relname); heap_close(pkrel, NoLock); /* @@ -1417,7 +1417,7 @@ AlterTableAddConstraint(char *relationName, else trig.tgargs[0] = ""; trig.tgargs[1] = (char *) relationName; - trig.tgargs[2] = fkconstraint->pktable_name; + trig.tgargs[2] = fkconstraint->pktable->relname; trig.tgargs[3] = fkconstraint->match_type; count = 4; foreach(list, fkconstraint->fk_attrs) @@ -1936,9 +1936,10 @@ LockTableCommand(LockStmt *lockstmt) * at a time */ - foreach(p, lockstmt->rellist) + foreach(p, lockstmt->relations) { - char *relname = strVal(lfirst(p)); + RangeVar *relation = lfirst(p); + char *relname = relation->relname; int aclresult; Relation rel; @@ -1962,3 +1963,94 @@ LockTableCommand(LockStmt *lockstmt) relation_close(rel, NoLock); /* close rel, keep lock */ } } + + +/* + * CREATE SCHEMA + */ +void +CreateSchemaCommand(CreateSchemaStmt *stmt) +{ + const char *schemaName = stmt->schemaname; + const char *authId = stmt->authid; + List *parsetree_list; + List *parsetree_item; + const char *owner_name; + Oid owner_userid; + Oid saved_userid; + + saved_userid = GetUserId(); + + if (!authId) + { + owner_userid = saved_userid; + owner_name = GetUserName(owner_userid); + } + else if (superuser()) + { + owner_name = authId; + /* The following will error out if user does not exist */ + owner_userid = get_usesysid(owner_name); + /* + * Set the current user to the requested authorization so + * that objects created in the statement have the requested + * owner. (This will revert to session user on error or at + * the end of this routine.) + */ + SetUserId(owner_userid); + } + else /* not superuser */ + { + owner_userid = saved_userid; + owner_name = GetUserName(owner_userid); + if (strcmp(authId, owner_name) != 0) + elog(ERROR, "CREATE SCHEMA: permission denied" + "\n\t\"%s\" is not a superuser, so cannot create a schema for \"%s\"", + owner_name, authId); + } + + /* FIXME FENN: Create the schema here */ + (void) schemaName; /* suppress compiler warning for now... */ + + /* + * Let commands in the schema-element-list know about the schema + */ + CommandCounterIncrement(); + + /* + * Examine the list of commands embedded in the CREATE SCHEMA command, + * and reorganize them into a sequentially executable order with no + * forward references. Note that the result is still a list of raw + * parsetrees in need of parse analysis --- we cannot, in general, + * run analyze.c on one statement until we have actually executed the + * prior ones. + */ + parsetree_list = analyzeCreateSchemaStmt(stmt); + + /* + * Analyze and execute each command contained in the CREATE SCHEMA + */ + foreach(parsetree_item, parsetree_list) + { + Node *parsetree = (Node *) lfirst(parsetree_item); + List *querytree_list, + *querytree_item; + + querytree_list = parse_analyze(parsetree, NULL); + + foreach(querytree_item, querytree_list) + { + Query *querytree = (Query *) lfirst(querytree_item); + + /* schemas should contain only utility stmts */ + Assert(querytree->commandType == CMD_UTILITY); + /* do this step */ + ProcessUtility(querytree->utilityStmt, None, NULL); + /* make sure later steps can see the object created here */ + CommandCounterIncrement(); + } + } + + /* Reset current user */ + SetUserId(saved_userid); +} diff --git a/src/backend/commands/creatinh.c b/src/backend/commands/creatinh.c index c9dee0cbbe..04854a2afa 100644 --- a/src/backend/commands/creatinh.c +++ b/src/backend/commands/creatinh.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.88 2002/03/20 19:43:42 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.89 2002/03/21 16:00:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -69,7 +69,7 @@ DefineRelation(CreateStmt *stmt, char relkind) * Truncate relname to appropriate length (probably a waste of time, * as parser should have done this already). */ - StrNCpy(relname, stmt->relname, NAMEDATALEN); + StrNCpy(relname, (stmt->relation)->relname, NAMEDATALEN); /* * Merge domain attributes into the known columns before processing table @@ -82,8 +82,9 @@ DefineRelation(CreateStmt *stmt, char relkind) * Look up inheritance ancestors and generate relation schema, * including inherited attributes. */ - schema = MergeAttributes(schema, stmt->inhRelnames, stmt->istemp, - &inheritOids, &old_constraints, &parentHasOids); + schema = MergeAttributes(schema, stmt->inhRelations, + stmt->relation->istemp, + &inheritOids, &old_constraints, &parentHasOids); numberOfAttributes = length(schema); if (numberOfAttributes <= 0) @@ -147,7 +148,7 @@ DefineRelation(CreateStmt *stmt, char relkind) relationId = heap_create_with_catalog(relname, descriptor, relkind, stmt->hasoids || parentHasOids, - stmt->istemp, + stmt->relation->istemp, allowSystemTableMods); StoreCatalogInheritance(relationId, inheritOids); @@ -414,6 +415,8 @@ MergeAttributes(List *schema, List *supers, bool istemp, /* * Reject duplicate names in the list of parents, too. + * + * XXX needs to be smarter about schema-qualified table names. */ foreach(entry, supers) { @@ -421,9 +424,10 @@ MergeAttributes(List *schema, List *supers, bool istemp, foreach(rest, lnext(entry)) { - if (strcmp(strVal(lfirst(entry)), strVal(lfirst(rest))) == 0) + if (strcmp(((RangeVar *) lfirst(entry))->relname, + ((RangeVar *) lfirst(rest))->relname) == 0) elog(ERROR, "CREATE TABLE: inherited relation \"%s\" duplicated", - strVal(lfirst(entry))); + ((RangeVar *) lfirst(entry))->relname); } } @@ -435,7 +439,7 @@ MergeAttributes(List *schema, List *supers, bool istemp, child_attno = 0; foreach(entry, supers) { - char *name = strVal(lfirst(entry)); + char *name = ((RangeVar *) lfirst(entry))->relname; Relation relation; TupleDesc tupleDesc; TupleConstr *constr; diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index e230ba598a..95263a5da0 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994-5, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.71 2002/03/12 00:51:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.72 2002/03/21 16:00:32 tgl Exp $ * */ @@ -310,9 +310,9 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) appendStringInfo(str, " on %s", stringStringInfo(rte->relname)); - if (strcmp(rte->eref->relname, rte->relname) != 0) + if (strcmp(rte->eref->aliasname, rte->relname) != 0) appendStringInfo(str, " %s", - stringStringInfo(rte->eref->relname)); + stringStringInfo(rte->eref->aliasname)); } break; case T_SubqueryScan: @@ -322,7 +322,7 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) es->rtable); appendStringInfo(str, " %s", - stringStringInfo(rte->eref->relname)); + stringStringInfo(rte->eref->aliasname)); } break; default: diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 0e57d90dfb..e9df6392bc 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.71 2002/03/15 19:20:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.72 2002/03/21 16:00:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -123,7 +123,7 @@ DefineSequence(CreateSeqStmt *seq) case SEQ_COL_NAME: typnam->name = "name"; coldef->colname = "sequence_name"; - namestrcpy(&name, seq->seqname); + namestrcpy(&name, seq->sequence->relname); value[i - 1] = NameGetDatum(&name); break; case SEQ_COL_LASTVAL: @@ -170,15 +170,14 @@ DefineSequence(CreateSeqStmt *seq) stmt->tableElts = lappend(stmt->tableElts, coldef); } - stmt->relname = seq->seqname; - stmt->inhRelnames = NIL; + stmt->relation = seq->sequence; + stmt->inhRelations = NIL; stmt->constraints = NIL; - stmt->istemp = seq->istemp; stmt->hasoids = false; DefineRelation(stmt, RELKIND_SEQUENCE); - rel = heap_openr(seq->seqname, AccessExclusiveLock); + rel = heap_openr(seq->sequence->relname, AccessExclusiveLock); tupDesc = RelationGetDescr(rel); /* Initialize first page of relation with special magic number */ diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index e25b83b455..5bef86e306 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.105 2002/03/08 04:37:14 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.106 2002/03/21 16:00:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -71,10 +71,11 @@ CreateTrigger(CreateTrigStmt *stmt) char *constrname = ""; Oid constrrelid = InvalidOid; - if (!allowSystemTableMods && IsSystemRelationName(stmt->relname)) - elog(ERROR, "CreateTrigger: can't create trigger for system relation %s", stmt->relname); + if (!allowSystemTableMods && IsSystemRelationName(stmt->relation->relname)) + elog(ERROR, "CreateTrigger: can't create trigger for system relation %s", + stmt->relation->relname); - if (pg_aclcheck(stmt->relname, GetUserId(), + if (pg_aclcheck(stmt->relation->relname, GetUserId(), stmt->isconstraint ? ACL_REFERENCES : ACL_TRIGGER) != ACLCHECK_OK) elog(ERROR, "permission denied"); @@ -89,7 +90,7 @@ CreateTrigger(CreateTrigStmt *stmt) stmt->trigname = constrtrigname; sprintf(constrtrigname, "RI_ConstraintTrigger_%u", newoid()); - if (strcmp(stmt->constrrelname, "") == 0) + if (stmt->constrrel == NULL) constrrelid = InvalidOid; else { @@ -97,17 +98,17 @@ CreateTrigger(CreateTrigStmt *stmt) * NoLock is probably sufficient here, since we're only * interested in getting the relation's OID... */ - rel = heap_openr(stmt->constrrelname, NoLock); + rel = heap_openr(stmt->constrrel->relname, NoLock); constrrelid = rel->rd_id; heap_close(rel, NoLock); } } - rel = heap_openr(stmt->relname, AccessExclusiveLock); + rel = heap_openr(stmt->relation->relname, AccessExclusiveLock); if (rel->rd_rel->relkind != RELKIND_RELATION) elog(ERROR, "CreateTrigger: relation \"%s\" is not a table", - stmt->relname); + stmt->relation->relname); TRIGGER_CLEAR_TYPE(tgtype); if (stmt->before) @@ -159,7 +160,7 @@ CreateTrigger(CreateTrigStmt *stmt) if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0) elog(ERROR, "CreateTrigger: trigger %s already defined on relation %s", - stmt->trigname, stmt->relname); + stmt->trigname, stmt->relation->relname); found++; } systable_endscan(tgscan); @@ -283,11 +284,11 @@ CreateTrigger(CreateTrigStmt *stmt) */ pgrel = heap_openr(RelationRelationName, RowExclusiveLock); tuple = SearchSysCacheCopy(RELNAME, - PointerGetDatum(stmt->relname), + PointerGetDatum(stmt->relation->relname), 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "CreateTrigger: relation %s not found in pg_class", - stmt->relname); + stmt->relation->relname); ((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1; simple_heap_update(pgrel, &tuple->t_self, tuple); @@ -320,19 +321,19 @@ DropTrigger(DropTrigStmt *stmt) int found = 0; int tgfound = 0; - if (!allowSystemTableMods && IsSystemRelationName(stmt->relname)) + if (!allowSystemTableMods && IsSystemRelationName(stmt->relation->relname)) elog(ERROR, "DropTrigger: can't drop trigger for system relation %s", - stmt->relname); + stmt->relation->relname); - if (!pg_ownercheck(GetUserId(), stmt->relname, RELNAME)) - elog(ERROR, "%s: %s", stmt->relname, + if (!pg_ownercheck(GetUserId(), stmt->relation->relname, RELNAME)) + elog(ERROR, "%s: %s", stmt->relation->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]); - rel = heap_openr(stmt->relname, AccessExclusiveLock); + rel = heap_openr(stmt->relation->relname, AccessExclusiveLock); if (rel->rd_rel->relkind != RELKIND_RELATION) elog(ERROR, "DropTrigger: relation \"%s\" is not a table", - stmt->relname); + stmt->relation->relname); /* * Search pg_trigger, delete target trigger, count remaining triggers @@ -366,10 +367,10 @@ DropTrigger(DropTrigStmt *stmt) if (tgfound == 0) elog(ERROR, "DropTrigger: there is no trigger %s on relation %s", - stmt->trigname, stmt->relname); + stmt->trigname, stmt->relation->relname); if (tgfound > 1) elog(NOTICE, "DropTrigger: found (and deleted) %d triggers %s on relation %s", - tgfound, stmt->trigname, stmt->relname); + tgfound, stmt->trigname, stmt->relation->relname); /* * Update relation's pg_class entry. Crucial side-effect: other @@ -378,11 +379,11 @@ DropTrigger(DropTrigStmt *stmt) */ pgrel = heap_openr(RelationRelationName, RowExclusiveLock); tuple = SearchSysCacheCopy(RELNAME, - PointerGetDatum(stmt->relname), + PointerGetDatum(stmt->relation->relname), 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "DropTrigger: relation %s not found in pg_class", - stmt->relname); + stmt->relation->relname); ((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found; simple_heap_update(pgrel, &tuple->t_self, tuple); @@ -478,20 +479,23 @@ RelationRemoveTriggers(Relation rel) { Form_pg_trigger pg_trigger; Relation refrel; - DropTrigStmt stmt; + DropTrigStmt *stmt = makeNode(DropTrigStmt); pg_trigger = (Form_pg_trigger) GETSTRUCT(tup); - stmt.trigname = pstrdup(NameStr(pg_trigger->tgname)); + stmt->trigname = pstrdup(NameStr(pg_trigger->tgname)); /* May as well grab AccessExclusiveLock, since DropTrigger will. */ refrel = heap_open(pg_trigger->tgrelid, AccessExclusiveLock); - stmt.relname = pstrdup(RelationGetRelationName(refrel)); + stmt->relation = makeNode(RangeVar); + /* XXX bogus: what about schema? */ + stmt->relation->relname = pstrdup(RelationGetRelationName(refrel)); heap_close(refrel, NoLock); - elog(NOTICE, "DROP TABLE implicitly drops referential integrity trigger from table \"%s\"", stmt.relname); + elog(NOTICE, "DROP TABLE implicitly drops referential integrity trigger from table \"%s\"", + stmt->relation->relname); - DropTrigger(&stmt); + DropTrigger(stmt); /* * Need to do a command counter increment here to show up new @@ -500,9 +504,6 @@ RelationRemoveTriggers(Relation rel) * FK table defined on the PK table). */ CommandCounterIncrement(); - - pfree(stmt.relname); - pfree(stmt.trigname); } systable_endscan(tgscan); diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 6b94db1077..836091c583 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -13,7 +13,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.217 2002/03/06 06:09:38 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.218 2002/03/21 16:00:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -209,10 +209,10 @@ vacuum(VacuumStmt *vacstmt) ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); - /* Convert vacrel, which is just a string, to a Name */ - if (vacstmt->vacrel) + /* Convert relname, which is just a string, to a Name */ + if (vacstmt->relation) { - namestrcpy(&VacRel, vacstmt->vacrel); + namestrcpy(&VacRel, vacstmt->relation->relname); VacRelName = &VacRel; } else @@ -268,7 +268,7 @@ vacuum(VacuumStmt *vacstmt) static void vacuum_init(VacuumStmt *vacstmt) { - if (vacstmt->vacuum && vacstmt->vacrel == NULL) + if (vacstmt->vacuum && vacstmt->relation == NULL) { /* * Compute the initially applicable OldestXmin and FreezeLimit @@ -308,7 +308,7 @@ vacuum_shutdown(VacuumStmt *vacstmt) * row with info about the transaction IDs used, and try to truncate * pg_clog. */ - if (vacstmt->vacuum && vacstmt->vacrel == NULL) + if (vacstmt->vacuum && vacstmt->relation == NULL) { vac_update_dbstats(MyDatabaseId, initialOldestXmin, initialFreezeLimit); diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index 9d1254a4cb..74a3ac2bca 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: view.c,v 1.58 2001/10/25 05:49:26 momjian Exp $ + * $Id: view.c,v 1.59 2002/03/21 16:00:36 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -41,6 +41,7 @@ static void DefineVirtualRelation(char *relname, List *tlist) { CreateStmt *createStmt = makeNode(CreateStmt); + RangeVar *rel = makeNode(RangeVar); List *attrList, *t; @@ -83,11 +84,13 @@ DefineVirtualRelation(char *relname, List *tlist) * now create the parameters for keys/inheritance etc. All of them are * nil... */ - createStmt->relname = relname; + rel->relname = relname; + rel->schemaname = NULL; /* XXX wrong */ + rel->istemp = false; + createStmt->relation = rel; createStmt->tableElts = attrList; - createStmt->inhRelnames = NIL; + createStmt->inhRelations = NIL; createStmt->constraints = NIL; - createStmt->istemp = false; createStmt->hasoids = false; /* @@ -101,21 +104,24 @@ FormViewRetrieveRule(char *viewName, Query *viewParse) { RuleStmt *rule; char *rname; - Attr *attr; + RangeVar *rel; /* * Create a RuleStmt that corresponds to the suitable rewrite rule * args for DefineQueryRewrite(); */ - rule = makeNode(RuleStmt); rname = MakeRetrieveViewRuleName(viewName); - attr = makeNode(Attr); - attr->relname = pstrdup(viewName); + rel = makeNode(RangeVar); + rel->relname = pstrdup(viewName); + rel->inhOpt = INH_NO; + rel->alias = NULL; + + rule = makeNode(RuleStmt); + rule->relation = rel; rule->rulename = pstrdup(rname); rule->whereClause = NULL; rule->event = CMD_SELECT; - rule->object = attr; rule->instead = true; rule->actions = makeList1(viewParse); @@ -191,10 +197,10 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse) * table... OLD first, then NEW.... */ rt_entry1 = addRangeTableEntry(NULL, viewName, - makeAttr("*OLD*", NULL), + makeAlias("*OLD*", NIL), false, false); rt_entry2 = addRangeTableEntry(NULL, viewName, - makeAttr("*NEW*", NULL), + makeAlias("*NEW*", NIL), false, false); /* Must override addRangeTableEntry's default access-check flags */ rt_entry1->checkForRead = false; diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 35a5c2d713..9b8e358602 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -27,7 +27,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.152 2002/03/06 06:09:42 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.153 2002/03/21 16:00:37 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -707,7 +707,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) /* * create the "into" relation */ - intoName = parseTree->into; + intoName = parseTree->into->relname; /* * have to copy tupType to get rid of constraints @@ -718,7 +718,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) heap_create_with_catalog(intoName, tupdesc, RELKIND_RELATION, true, - parseTree->isTemp, + parseTree->into->istemp, allowSystemTableMods); FreeTupleDesc(tupdesc); diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index c8c65b1cee..f09f90744e 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.67 2002/02/27 19:34:59 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.68 2002/03/21 16:00:38 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -775,7 +775,8 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls) /* Modify the parsetree to be a cursor */ queryTree->isPortal = true; - queryTree->into = pstrdup(name); + queryTree->into = makeNode(RangeVar); + queryTree->into->relname = pstrdup(name); queryTree->isBinary = false; /* Create the QueryDesc object and the executor state */ @@ -1145,7 +1146,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount) if (parseTree->isPortal) { isRetrieveIntoPortal = true; - intoName = parseTree->into; + intoName = parseTree->into->relname; parseTree->isBinary = false; /* */ return SPI_ERROR_CURSOR; diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index ebdc7cf116..fb68866c53 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.171 2002/03/20 19:43:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.172 2002/03/21 16:00:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -733,18 +733,6 @@ _copyVar(Var *from) return newnode; } -static Attr * -_copyAttr(Attr *from) -{ - Attr *newnode = makeNode(Attr); - - if (from->relname) - newnode->relname = pstrdup(from->relname); - Node_Copy(from, newnode, attrs); - - return newnode; -} - /* ---------------- * _copyOper * ---------------- @@ -1515,8 +1503,7 @@ _copyFkConstraint(FkConstraint *from) if (from->constr_name) newnode->constr_name = pstrdup(from->constr_name); - if (from->pktable_name) - newnode->pktable_name = pstrdup(from->pktable_name); + Node_Copy(from, newnode, pktable); Node_Copy(from, newnode, fk_attrs); Node_Copy(from, newnode, pk_attrs); if (from->match_type) @@ -1553,6 +1540,29 @@ _copyAExpr(A_Expr *from) return newnode; } +static ColumnRef * +_copyColumnRef(ColumnRef *from) +{ + ColumnRef *newnode = makeNode(ColumnRef); + + Node_Copy(from, newnode, fields); + Node_Copy(from, newnode, indirection); + + return newnode; +} + +static ParamRef * +_copyParamRef(ParamRef *from) +{ + ParamRef *newnode = makeNode(ParamRef); + + newnode->number = from->number; + Node_Copy(from, newnode, fields); + Node_Copy(from, newnode, indirection); + + return newnode; +} + static A_Const * _copyAConst(A_Const *from) { @@ -1564,27 +1574,12 @@ _copyAConst(A_Const *from) return newnode; } -static ParamNo * -_copyParamNo(ParamNo *from) -{ - ParamNo *newnode = makeNode(ParamNo); - - newnode->number = from->number; - Node_Copy(from, newnode, typename); - Node_Copy(from, newnode, indirection); - - return newnode; -} - static Ident * _copyIdent(Ident *from) { Ident *newnode = makeNode(Ident); - if (from->name) - newnode->name = pstrdup(from->name); - Node_Copy(from, newnode, indirection); - newnode->isRel = from->isRel; + newnode->name = pstrdup(from->name); return newnode; } @@ -1614,6 +1609,18 @@ _copyAIndices(A_Indices *from) return newnode; } +static ExprFieldSelect * +_copyExprFieldSelect(ExprFieldSelect *from) +{ + ExprFieldSelect *newnode = makeNode(ExprFieldSelect); + + Node_Copy(from, newnode, arg); + Node_Copy(from, newnode, fields); + Node_Copy(from, newnode, indirection); + + return newnode; +} + static ResTarget * _copyResTarget(ResTarget *from) { @@ -1654,15 +1661,32 @@ _copySortGroupBy(SortGroupBy *from) return newnode; } +static Alias * +_copyAlias(Alias *from) +{ + Alias *newnode = makeNode(Alias); + + if (from->aliasname) + newnode->aliasname = pstrdup(from->aliasname); + Node_Copy(from, newnode, colnames); + + return newnode; +} + static RangeVar * _copyRangeVar(RangeVar *from) { RangeVar *newnode = makeNode(RangeVar); + if (from->catalogname) + newnode->catalogname = pstrdup(from->catalogname); + if (from->schemaname) + newnode->schemaname = pstrdup(from->schemaname); if (from->relname) newnode->relname = pstrdup(from->relname); newnode->inhOpt = from->inhOpt; - Node_Copy(from, newnode, name); + newnode->istemp = from->istemp; + Node_Copy(from, newnode, alias); return newnode; } @@ -1673,7 +1697,7 @@ _copyRangeSubselect(RangeSubselect *from) RangeSubselect *newnode = makeNode(RangeSubselect); Node_Copy(from, newnode, subquery); - Node_Copy(from, newnode, name); + Node_Copy(from, newnode, alias); return newnode; } @@ -1756,11 +1780,9 @@ _copyQuery(Query *from) newnode->commandType = from->commandType; Node_Copy(from, newnode, utilityStmt); newnode->resultRelation = from->resultRelation; - if (from->into) - newnode->into = pstrdup(from->into); + Node_Copy(from, newnode, into); newnode->isPortal = from->isPortal; newnode->isBinary = from->isBinary; - newnode->isTemp = from->isTemp; newnode->hasAggs = from->hasAggs; newnode->hasSubLinks = from->hasSubLinks; newnode->originalQuery = from->originalQuery; @@ -1798,8 +1820,7 @@ _copyInsertStmt(InsertStmt *from) { InsertStmt *newnode = makeNode(InsertStmt); - if (from->relname) - newnode->relname = pstrdup(from->relname); + Node_Copy(from, newnode, relation); Node_Copy(from, newnode, cols); Node_Copy(from, newnode, targetList); Node_Copy(from, newnode, selectStmt); @@ -1812,10 +1833,8 @@ _copyDeleteStmt(DeleteStmt *from) { DeleteStmt *newnode = makeNode(DeleteStmt); - if (from->relname) - newnode->relname = pstrdup(from->relname); + Node_Copy(from, newnode, relation); Node_Copy(from, newnode, whereClause); - newnode->inhOpt = from->inhOpt; return newnode; } @@ -1825,12 +1844,10 @@ _copyUpdateStmt(UpdateStmt *from) { UpdateStmt *newnode = makeNode(UpdateStmt); - if (from->relname) - newnode->relname = pstrdup(from->relname); + Node_Copy(from, newnode, relation); Node_Copy(from, newnode, targetList); Node_Copy(from, newnode, whereClause); Node_Copy(from, newnode, fromClause); - newnode->inhOpt = from->inhOpt; return newnode; } @@ -1841,9 +1858,7 @@ _copySelectStmt(SelectStmt *from) SelectStmt *newnode = makeNode(SelectStmt); Node_Copy(from, newnode, distinctClause); - if (from->into) - newnode->into = pstrdup(from->into); - newnode->istemp = from->istemp; + Node_Copy(from, newnode, into); Node_Copy(from, newnode, intoColNames); Node_Copy(from, newnode, targetList); Node_Copy(from, newnode, fromClause); @@ -1885,9 +1900,7 @@ _copyAlterTableStmt(AlterTableStmt *from) AlterTableStmt *newnode = makeNode(AlterTableStmt); newnode->subtype = from->subtype; - if (from->relname) - newnode->relname = pstrdup(from->relname); - newnode->inhOpt = from->inhOpt; + Node_Copy(from, newnode, relation); if (from->name) newnode->name = pstrdup(from->name); Node_Copy(from, newnode, def); @@ -1951,8 +1964,7 @@ _copyClusterStmt(ClusterStmt *from) { ClusterStmt *newnode = makeNode(ClusterStmt); - if (from->relname) - newnode->relname = pstrdup(from->relname); + Node_Copy(from, newnode, relation); if (from->indexname) newnode->indexname = pstrdup(from->indexname); @@ -1965,8 +1977,7 @@ _copyCopyStmt(CopyStmt *from) CopyStmt *newnode = makeNode(CopyStmt); newnode->binary = from->binary; - if (from->relname) - newnode->relname = pstrdup(from->relname); + Node_Copy(from, newnode, relation); newnode->oids = from->oids; newnode->direction = from->direction; if (from->filename) @@ -1984,11 +1995,10 @@ _copyCreateStmt(CreateStmt *from) { CreateStmt *newnode = makeNode(CreateStmt); - newnode->relname = pstrdup(from->relname); + Node_Copy(from, newnode, relation); Node_Copy(from, newnode, tableElts); - Node_Copy(from, newnode, inhRelnames); + Node_Copy(from, newnode, inhRelations); Node_Copy(from, newnode, constraints); - newnode->istemp = from->istemp; newnode->hasoids = from->hasoids; return newnode; @@ -2024,7 +2034,7 @@ _copyDropStmt(DropStmt *from) { DropStmt *newnode = makeNode(DropStmt); - Node_Copy(from, newnode, names); + Node_Copy(from, newnode, objects); newnode->removeType = from->removeType; newnode->behavior = from->behavior; @@ -2036,7 +2046,7 @@ _copyTruncateStmt(TruncateStmt *from) { TruncateStmt *newnode = makeNode(TruncateStmt); - newnode->relName = pstrdup(from->relName); + Node_Copy(from, newnode, relation); return newnode; } @@ -2047,6 +2057,8 @@ _copyCommentStmt(CommentStmt *from) CommentStmt *newnode = makeNode(CommentStmt); newnode->objtype = from->objtype; + if (from->objschema) + newnode->objschema = pstrdup(from->objschema); newnode->objname = pstrdup(from->objname); if (from->objproperty) newnode->objproperty = pstrdup(from->objproperty); @@ -2075,7 +2087,7 @@ _copyIndexStmt(IndexStmt *from) IndexStmt *newnode = makeNode(IndexStmt); newnode->idxname = pstrdup(from->idxname); - newnode->relname = pstrdup(from->relname); + Node_Copy(from, newnode, relation); newnode->accessMethod = pstrdup(from->accessMethod); Node_Copy(from, newnode, indexParams); Node_Copy(from, newnode, whereClause); @@ -2140,8 +2152,7 @@ _copyRenameStmt(RenameStmt *from) { RenameStmt *newnode = makeNode(RenameStmt); - newnode->relname = pstrdup(from->relname); - newnode->inhOpt = from->inhOpt; + Node_Copy(from, newnode, relation); if (from->column) newnode->column = pstrdup(from->column); if (from->newname) @@ -2155,10 +2166,10 @@ _copyRuleStmt(RuleStmt *from) { RuleStmt *newnode = makeNode(RuleStmt); + Node_Copy(from, newnode, relation); newnode->rulename = pstrdup(from->rulename); Node_Copy(from, newnode, whereClause); newnode->event = from->event; - Node_Copy(from, newnode, object); newnode->instead = from->instead; Node_Copy(from, newnode, actions); @@ -2170,8 +2181,7 @@ _copyNotifyStmt(NotifyStmt *from) { NotifyStmt *newnode = makeNode(NotifyStmt); - if (from->relname) - newnode->relname = pstrdup(from->relname); + Node_Copy(from, newnode, relation); return newnode; } @@ -2181,8 +2191,7 @@ _copyListenStmt(ListenStmt *from) { ListenStmt *newnode = makeNode(ListenStmt); - if (from->relname) - newnode->relname = pstrdup(from->relname); + Node_Copy(from, newnode, relation); return newnode; } @@ -2192,8 +2201,7 @@ _copyUnlistenStmt(UnlistenStmt *from) { UnlistenStmt *newnode = makeNode(UnlistenStmt); - if (from->relname) - newnode->relname = pstrdup(from->relname); + Node_Copy(from, newnode, relation); return newnode; } @@ -2213,8 +2221,7 @@ _copyViewStmt(ViewStmt *from) { ViewStmt *newnode = makeNode(ViewStmt); - if (from->viewname) - newnode->viewname = pstrdup(from->viewname); + Node_Copy(from, newnode, view); Node_Copy(from, newnode, aliases); Node_Copy(from, newnode, query); @@ -2298,8 +2305,7 @@ _copyVacuumStmt(VacuumStmt *from) newnode->analyze = from->analyze; newnode->freeze = from->freeze; newnode->verbose = from->verbose; - if (from->vacrel) - newnode->vacrel = pstrdup(from->vacrel); + Node_Copy(from, newnode, relation); Node_Copy(from, newnode, va_cols); return newnode; @@ -2322,8 +2328,7 @@ _copyCreateSeqStmt(CreateSeqStmt *from) { CreateSeqStmt *newnode = makeNode(CreateSeqStmt); - if (from->seqname) - newnode->seqname = pstrdup(from->seqname); + Node_Copy(from, newnode, sequence); Node_Copy(from, newnode, options); return newnode; @@ -2370,8 +2375,7 @@ _copyCreateTrigStmt(CreateTrigStmt *from) if (from->trigname) newnode->trigname = pstrdup(from->trigname); - if (from->relname) - newnode->relname = pstrdup(from->relname); + Node_Copy(from, newnode, relation); if (from->funcname) newnode->funcname = pstrdup(from->funcname); Node_Copy(from, newnode, args); @@ -2389,8 +2393,7 @@ _copyCreateTrigStmt(CreateTrigStmt *from) newnode->isconstraint = from->isconstraint; newnode->deferrable = from->deferrable; newnode->initdeferred = from->initdeferred; - if (from->constrrelname) - newnode->constrrelname = pstrdup(from->constrrelname); + Node_Copy(from, newnode, constrrel); return newnode; } @@ -2402,8 +2405,7 @@ _copyDropTrigStmt(DropTrigStmt *from) if (from->trigname) newnode->trigname = pstrdup(from->trigname); - if (from->relname) - newnode->relname = pstrdup(from->relname); + Node_Copy(from, newnode, relation); return newnode; } @@ -2488,7 +2490,7 @@ _copyLockStmt(LockStmt *from) { LockStmt *newnode = makeNode(LockStmt); - Node_Copy(from, newnode, rellist); + Node_Copy(from, newnode, relations); newnode->mode = from->mode; @@ -2548,6 +2550,7 @@ _copyReindexStmt(ReindexStmt *from) ReindexStmt *newnode = makeNode(ReindexStmt); newnode->reindexType = from->reindexType; + Node_Copy(from, newnode, relation); if (from->name) newnode->name = pstrdup(from->name); newnode->force = from->force; @@ -2556,6 +2559,19 @@ _copyReindexStmt(ReindexStmt *from) return newnode; } +static CreateSchemaStmt * +_copyCreateSchemaStmt(CreateSchemaStmt *from) +{ + CreateSchemaStmt *newnode = makeNode(CreateSchemaStmt); + + newnode->schemaname = pstrdup(from->schemaname); + if (from->authid) + newnode->authid = pstrdup(from->authid); + Node_Copy(from, newnode, schemaElts); + + return newnode; +} + /* **************************************************************** * pg_list.h copy functions @@ -2888,6 +2904,9 @@ copyObject(void *from) case T_LoadStmt: retval = _copyLoadStmt(from); break; + case T_CreateDomainStmt: + retval = _copyCreateDomainStmt(from); + break; case T_CreatedbStmt: retval = _copyCreatedbStmt(from); break; @@ -2960,19 +2979,22 @@ copyObject(void *from) case T_CheckPointStmt: retval = (void *) makeNode(CheckPointStmt); break; + case T_CreateSchemaStmt: + retval = _copyCreateSchemaStmt(from); + break; case T_A_Expr: retval = _copyAExpr(from); break; - case T_Attr: - retval = _copyAttr(from); + case T_ColumnRef: + retval = _copyColumnRef(from); + break; + case T_ParamRef: + retval = _copyParamRef(from); break; case T_A_Const: retval = _copyAConst(from); break; - case T_ParamNo: - retval = _copyParamNo(from); - break; case T_Ident: retval = _copyIdent(from); break; @@ -2982,6 +3004,9 @@ copyObject(void *from) case T_A_Indices: retval = _copyAIndices(from); break; + case T_ExprFieldSelect: + retval = _copyExprFieldSelect(from); + break; case T_ResTarget: retval = _copyResTarget(from); break; @@ -2991,6 +3016,9 @@ copyObject(void *from) case T_SortGroupBy: retval = _copySortGroupBy(from); break; + case T_Alias: + retval = _copyAlias(from); + break; case T_RangeVar: retval = _copyRangeVar(from); break; @@ -3045,9 +3073,6 @@ copyObject(void *from) case T_FuncWithArgs: retval = _copyFuncWithArgs(from); break; - case T_CreateDomainStmt: - retval = _copyCreateDomainStmt(from); - break; default: elog(ERROR, "copyObject: don't know how to copy node type %d", diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index c7ed489e09..9788fd2f52 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -20,7 +20,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.119 2002/03/20 19:44:01 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.120 2002/03/21 16:00:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -579,14 +579,12 @@ _equalQuery(Query *a, Query *b) return false; if (a->resultRelation != b->resultRelation) return false; - if (!equalstr(a->into, b->into)) + if (!equal(a->into, b->into)) return false; if (a->isPortal != b->isPortal) return false; if (a->isBinary != b->isBinary) return false; - if (a->isTemp != b->isTemp) - return false; if (a->hasAggs != b->hasAggs) return false; if (a->hasSubLinks != b->hasSubLinks) @@ -629,7 +627,7 @@ _equalQuery(Query *a, Query *b) static bool _equalInsertStmt(InsertStmt *a, InsertStmt *b) { - if (!equalstr(a->relname, b->relname)) + if (!equal(a->relation, b->relation)) return false; if (!equal(a->cols, b->cols)) return false; @@ -644,12 +642,10 @@ _equalInsertStmt(InsertStmt *a, InsertStmt *b) static bool _equalDeleteStmt(DeleteStmt *a, DeleteStmt *b) { - if (!equalstr(a->relname, b->relname)) + if (!equal(a->relation, b->relation)) return false; if (!equal(a->whereClause, b->whereClause)) return false; - if (a->inhOpt != b->inhOpt) - return false; return true; } @@ -657,7 +653,7 @@ _equalDeleteStmt(DeleteStmt *a, DeleteStmt *b) static bool _equalUpdateStmt(UpdateStmt *a, UpdateStmt *b) { - if (!equalstr(a->relname, b->relname)) + if (!equal(a->relation, b->relation)) return false; if (!equal(a->targetList, b->targetList)) return false; @@ -665,8 +661,6 @@ _equalUpdateStmt(UpdateStmt *a, UpdateStmt *b) return false; if (!equal(a->fromClause, b->fromClause)) return false; - if (a->inhOpt != b->inhOpt) - return false; return true; } @@ -676,9 +670,7 @@ _equalSelectStmt(SelectStmt *a, SelectStmt *b) { if (!equal(a->distinctClause, b->distinctClause)) return false; - if (!equalstr(a->into, b->into)) - return false; - if (a->istemp != b->istemp) + if (!equal(a->into, b->into)) return false; if (!equal(a->intoColNames, b->intoColNames)) return false; @@ -738,9 +730,7 @@ _equalAlterTableStmt(AlterTableStmt *a, AlterTableStmt *b) { if (a->subtype != b->subtype) return false; - if (!equalstr(a->relname, b->relname)) - return false; - if (a->inhOpt != b->inhOpt) + if (!equal(a->relation, b->relation)) return false; if (!equalstr(a->name, b->name)) return false; @@ -795,7 +785,7 @@ _equalClosePortalStmt(ClosePortalStmt *a, ClosePortalStmt *b) static bool _equalClusterStmt(ClusterStmt *a, ClusterStmt *b) { - if (!equalstr(a->relname, b->relname)) + if (!equal(a->relation, b->relation)) return false; if (!equalstr(a->indexname, b->indexname)) return false; @@ -808,7 +798,7 @@ _equalCopyStmt(CopyStmt *a, CopyStmt *b) { if (a->binary != b->binary) return false; - if (!equalstr(a->relname, b->relname)) + if (!equal(a->relation, b->relation)) return false; if (a->oids != b->oids) return false; @@ -827,16 +817,14 @@ _equalCopyStmt(CopyStmt *a, CopyStmt *b) static bool _equalCreateStmt(CreateStmt *a, CreateStmt *b) { - if (!equalstr(a->relname, b->relname)) + if (!equal(a->relation, b->relation)) return false; if (!equal(a->tableElts, b->tableElts)) return false; - if (!equal(a->inhRelnames, b->inhRelnames)) + if (!equal(a->inhRelations, b->inhRelations)) return false; if (!equal(a->constraints, b->constraints)) return false; - if (a->istemp != b->istemp) - return false; if (a->hasoids != b->hasoids) return false; @@ -874,7 +862,7 @@ _equalDefineStmt(DefineStmt *a, DefineStmt *b) static bool _equalDropStmt(DropStmt *a, DropStmt *b) { - if (!equal(a->names, b->names)) + if (!equal(a->objects, b->objects)) return false; if (a->removeType != b->removeType) return false; @@ -887,7 +875,7 @@ _equalDropStmt(DropStmt *a, DropStmt *b) static bool _equalTruncateStmt(TruncateStmt *a, TruncateStmt *b) { - if (!equalstr(a->relName, b->relName)) + if (!equal(a->relation, b->relation)) return false; return true; @@ -900,6 +888,8 @@ _equalCommentStmt(CommentStmt *a, CommentStmt *b) return false; if (!equalstr(a->objname, b->objname)) return false; + if (!equalstr(a->objschema, b->objschema)) + return false; if (!equalstr(a->objproperty, b->objproperty)) return false; if (!equal(a->objlist, b->objlist)) @@ -930,7 +920,7 @@ _equalIndexStmt(IndexStmt *a, IndexStmt *b) { if (!equalstr(a->idxname, b->idxname)) return false; - if (!equalstr(a->relname, b->relname)) + if (!equal(a->relation, b->relation)) return false; if (!equalstr(a->accessMethod, b->accessMethod)) return false; @@ -1006,9 +996,7 @@ _equalRemoveOperStmt(RemoveOperStmt *a, RemoveOperStmt *b) static bool _equalRenameStmt(RenameStmt *a, RenameStmt *b) { - if (!equalstr(a->relname, b->relname)) - return false; - if (a->inhOpt != b->inhOpt) + if (!equal(a->relation, b->relation)) return false; if (!equalstr(a->column, b->column)) return false; @@ -1021,14 +1009,14 @@ _equalRenameStmt(RenameStmt *a, RenameStmt *b) static bool _equalRuleStmt(RuleStmt *a, RuleStmt *b) { + if (!equal(a->relation, b->relation)) + return false; if (!equalstr(a->rulename, b->rulename)) return false; if (!equal(a->whereClause, b->whereClause)) return false; if (a->event != b->event) return false; - if (!equal(a->object, b->object)) - return false; if (a->instead != b->instead) return false; if (!equal(a->actions, b->actions)) @@ -1040,7 +1028,7 @@ _equalRuleStmt(RuleStmt *a, RuleStmt *b) static bool _equalNotifyStmt(NotifyStmt *a, NotifyStmt *b) { - if (!equalstr(a->relname, b->relname)) + if (!equal(a->relation, b->relation)) return false; return true; @@ -1049,7 +1037,7 @@ _equalNotifyStmt(NotifyStmt *a, NotifyStmt *b) static bool _equalListenStmt(ListenStmt *a, ListenStmt *b) { - if (!equalstr(a->relname, b->relname)) + if (!equal(a->relation, b->relation)) return false; return true; @@ -1058,7 +1046,7 @@ _equalListenStmt(ListenStmt *a, ListenStmt *b) static bool _equalUnlistenStmt(UnlistenStmt *a, UnlistenStmt *b) { - if (!equalstr(a->relname, b->relname)) + if (!equal(a->relation, b->relation)) return false; return true; @@ -1076,7 +1064,7 @@ _equalTransactionStmt(TransactionStmt *a, TransactionStmt *b) static bool _equalViewStmt(ViewStmt *a, ViewStmt *b) { - if (!equalstr(a->viewname, b->viewname)) + if (!equal(a->view, b->view)) return false; if (!equal(a->aliases, b->aliases)) return false; @@ -1160,7 +1148,7 @@ _equalVacuumStmt(VacuumStmt *a, VacuumStmt *b) return false; if (a->verbose != b->verbose) return false; - if (!equalstr(a->vacrel, b->vacrel)) + if (!equal(a->relation, b->relation)) return false; if (!equal(a->va_cols, b->va_cols)) return false; @@ -1184,7 +1172,7 @@ _equalExplainStmt(ExplainStmt *a, ExplainStmt *b) static bool _equalCreateSeqStmt(CreateSeqStmt *a, CreateSeqStmt *b) { - if (!equalstr(a->seqname, b->seqname)) + if (!equal(a->sequence, b->sequence)) return false; if (!equal(a->options, b->options)) return false; @@ -1226,7 +1214,7 @@ _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b) { if (!equalstr(a->trigname, b->trigname)) return false; - if (!equalstr(a->relname, b->relname)) + if (!equal(a->relation, b->relation)) return false; if (!equalstr(a->funcname, b->funcname)) return false; @@ -1252,7 +1240,7 @@ _equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b) return false; if (a->initdeferred != b->initdeferred) return false; - if (!equalstr(a->constrrelname, b->constrrelname)) + if (!equal(a->constrrel, b->constrrel)) return false; return true; @@ -1263,7 +1251,7 @@ _equalDropTrigStmt(DropTrigStmt *a, DropTrigStmt *b) { if (!equalstr(a->trigname, b->trigname)) return false; - if (!equalstr(a->relname, b->relname)) + if (!equal(a->relation, b->relation)) return false; return true; @@ -1340,7 +1328,7 @@ _equalDropUserStmt(DropUserStmt *a, DropUserStmt *b) static bool _equalLockStmt(LockStmt *a, LockStmt *b) { - if (!equal(a->rellist, b->rellist)) + if (!equal(a->relations, b->relations)) return false; if (a->mode != b->mode) return false; @@ -1397,6 +1385,8 @@ _equalReindexStmt(ReindexStmt *a, ReindexStmt *b) { if (a->reindexType != b->reindexType) return false; + if (!equal(a->relation, b->relation)) + return false; if (!equalstr(a->name, b->name)) return false; if (a->force != b->force) @@ -1407,6 +1397,19 @@ _equalReindexStmt(ReindexStmt *a, ReindexStmt *b) return true; } +static bool +_equalCreateSchemaStmt(CreateSchemaStmt *a, CreateSchemaStmt *b) +{ + if (!equalstr(a->schemaname, b->schemaname)) + return false; + if (!equalstr(a->authid, b->authid)) + return false; + if (!equal(a->schemaElts, b->schemaElts)) + return false; + + return true; +} + static bool _equalAExpr(A_Expr *a, A_Expr *b) { @@ -1423,13 +1426,22 @@ _equalAExpr(A_Expr *a, A_Expr *b) } static bool -_equalAttr(Attr *a, Attr *b) +_equalColumnRef(ColumnRef *a, ColumnRef *b) { - if (strcmp(a->relname, b->relname) != 0) + if (!equal(a->fields, b->fields)) return false; - if (!equal(a->paramNo, b->paramNo)) + if (!equal(a->indirection, b->indirection)) return false; - if (!equal(a->attrs, b->attrs)) + + return true; +} + +static bool +_equalParamRef(ParamRef *a, ParamRef *b) +{ + if (a->number != b->number) + return false; + if (!equal(a->fields, b->fields)) return false; if (!equal(a->indirection, b->indirection)) return false; @@ -1448,28 +1460,11 @@ _equalAConst(A_Const *a, A_Const *b) return true; } -static bool -_equalParamNo(ParamNo *a, ParamNo *b) -{ - if (a->number != b->number) - return false; - if (!equal(a->typename, b->typename)) - return false; - if (!equal(a->indirection, b->indirection)) - return false; - - return true; -} - static bool _equalIdent(Ident *a, Ident *b) { if (!equalstr(a->name, b->name)) return false; - if (!equal(a->indirection, b->indirection)) - return false; - if (a->isRel != b->isRel) - return false; return true; } @@ -1500,6 +1495,19 @@ _equalAIndices(A_Indices *a, A_Indices *b) return true; } +static bool +_equalExprFieldSelect(ExprFieldSelect *a, ExprFieldSelect *b) +{ + if (!equal(a->arg, b->arg)) + return false; + if (!equal(a->fields, b->fields)) + return false; + if (!equal(a->indirection, b->indirection)) + return false; + + return true; +} + static bool _equalResTarget(ResTarget *a, ResTarget *b) { @@ -1535,14 +1543,31 @@ _equalSortGroupBy(SortGroupBy *a, SortGroupBy *b) return true; } +static bool +_equalAlias(Alias *a, Alias *b) +{ + if (!equalstr(a->aliasname, b->aliasname)) + return false; + if (!equal(a->colnames, b->colnames)) + return false; + + return true; +} + static bool _equalRangeVar(RangeVar *a, RangeVar *b) { + if (!equalstr(a->catalogname, b->catalogname)) + return false; + if (!equalstr(a->schemaname, b->schemaname)) + return false; if (!equalstr(a->relname, b->relname)) return false; if (a->inhOpt != b->inhOpt) return false; - if (!equal(a->name, b->name)) + if (a->istemp != b->istemp) + return false; + if (!equal(a->alias, b->alias)) return false; return true; @@ -1553,7 +1578,7 @@ _equalRangeSubselect(RangeSubselect *a, RangeSubselect *b) { if (!equal(a->subquery, b->subquery)) return false; - if (!equal(a->name, b->name)) + if (!equal(a->alias, b->alias)) return false; return true; @@ -1704,7 +1729,7 @@ _equalFkConstraint(FkConstraint *a, FkConstraint *b) { if (!equalstr(a->constr_name, b->constr_name)) return false; - if (!equalstr(a->pktable_name, b->pktable_name)) + if (!equal(a->pktable, b->pktable)) return false; if (!equal(a->fk_attrs, b->fk_attrs)) return false; @@ -2111,19 +2136,22 @@ equal(void *a, void *b) case T_CheckPointStmt: retval = true; break; + case T_CreateSchemaStmt: + retval = _equalCreateSchemaStmt(a, b); + break; case T_A_Expr: retval = _equalAExpr(a, b); break; - case T_Attr: - retval = _equalAttr(a, b); + case T_ColumnRef: + retval = _equalColumnRef(a, b); + break; + case T_ParamRef: + retval = _equalParamRef(a, b); break; case T_A_Const: retval = _equalAConst(a, b); break; - case T_ParamNo: - retval = _equalParamNo(a, b); - break; case T_Ident: retval = _equalIdent(a, b); break; @@ -2133,6 +2161,9 @@ equal(void *a, void *b) case T_A_Indices: retval = _equalAIndices(a, b); break; + case T_ExprFieldSelect: + retval = _equalExprFieldSelect(a, b); + break; case T_ResTarget: retval = _equalResTarget(a, b); break; @@ -2142,6 +2173,9 @@ equal(void *a, void *b) case T_SortGroupBy: retval = _equalSortGroupBy(a, b); break; + case T_Alias: + retval = _equalAlias(a, b); + break; case T_RangeVar: retval = _equalRangeVar(a, b); break; diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index 36f8460b46..d8bf80a52e 100644 --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.27 2002/03/20 19:44:04 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.28 2002/03/21 16:00:40 tgl Exp $ */ #include "postgres.h" @@ -159,19 +159,18 @@ makeNullConst(Oid consttype) } /* - * makeAttr - - * creates an Attr node + * makeAlias - + * creates an Alias node + * + * NOTE: the given name is copied, but the colnames list (if any) isn't. */ -Attr * -makeAttr(char *relname, char *attname) +Alias * +makeAlias(const char *aliasname, List *colnames) { - Attr *a = makeNode(Attr); + Alias *a = makeNode(Alias); - a->relname = pstrdup(relname); - a->paramNo = NULL; - if (attname != NULL) - a->attrs = makeList1(makeString(pstrdup(attname))); - a->indirection = NULL; + a->aliasname = pstrdup(aliasname); + a->colnames = colnames; return a; } diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index 5d43a8e15e..401b34b88c 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/nodeFuncs.c,v 1.16 2001/10/28 06:25:44 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/nodeFuncs.c,v 1.17 2002/03/21 16:00:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,7 +29,9 @@ static bool var_is_inner(Var *var); bool single_node(Node *node) { - if (IsA(node, Ident) ||IsA(node, Const) ||IsA(node, Var) ||IsA(node, Param)) + if (IsA(node, Const) || + IsA(node, Var) || + IsA(node, Param)) return true; else return false; @@ -103,13 +105,13 @@ replace_opid(Oper *oper) * non_null - * Returns t if the node is a non-null constant, e.g., if the node has a * valid `constvalue' field. - * */ bool non_null(Expr *c) { - if (IsA(c, Const) &&!((Const *) c)->constisnull) + if (IsA(c, Const) && + !((Const *) c)->constisnull) return true; else return false; diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 3699fc38ff..aff46e6ba3 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.149 2002/03/12 00:51:39 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.150 2002/03/21 16:00:40 tgl Exp $ * * NOTES * Every (plan) node in POSTGRES has an associated "out" routine which @@ -105,20 +105,19 @@ _outOidList(StringInfo str, List *list) static void _outCreateStmt(StringInfo str, CreateStmt *node) { - appendStringInfo(str, " CREATE :relname "); - _outToken(str, node->relname); + appendStringInfo(str, " CREATE :relation "); + _outNode(str, node->relation); - appendStringInfo(str, " :columns "); + appendStringInfo(str, " :tableElts "); _outNode(str, node->tableElts); - appendStringInfo(str, " :inhRelnames "); - _outNode(str, node->inhRelnames); + appendStringInfo(str, " :inhRelations "); + _outNode(str, node->inhRelations); appendStringInfo(str, " :constraints "); _outNode(str, node->constraints); - appendStringInfo(str, " :istemp %s :hasoids %s ", - booltostr(node->istemp), + appendStringInfo(str, " :hasoids %s ", booltostr(node->hasoids)); } @@ -127,8 +126,8 @@ _outIndexStmt(StringInfo str, IndexStmt *node) { appendStringInfo(str, " INDEX :idxname "); _outToken(str, node->idxname); - appendStringInfo(str, " :relname "); - _outToken(str, node->relname); + appendStringInfo(str, " :relation "); + _outNode(str, node->relation); appendStringInfo(str, " :accessMethod "); _outToken(str, node->accessMethod); appendStringInfo(str, " :indexParams "); @@ -142,6 +141,13 @@ _outIndexStmt(StringInfo str, IndexStmt *node) booltostr(node->primary)); } +static void +_outNotifyStmt(StringInfo str, NotifyStmt *node) +{ + appendStringInfo(str, "NOTIFY :relation "); + _outNode(str, node->relation); +} + static void _outSelectStmt(StringInfo str, SelectStmt *node) { @@ -213,53 +219,40 @@ _outIndexElem(StringInfo str, IndexElem *node) static void _outQuery(StringInfo str, Query *node) { + appendStringInfo(str, " QUERY :command %d :utility ", node->commandType); - appendStringInfo(str, " QUERY :command %d ", node->commandType); - + /* + * Hack to work around missing outfuncs routines for a lot of the + * utility-statement node types. (The only one we actually *need* + * for rules support is NotifyStmt.) Someday we ought to support + * 'em all, but for the meantime do this to avoid getting lots of + * warnings when running with debug_print_parse on. + */ if (node->utilityStmt) { - /* - * Hack to make up for lack of outfuncs for utility-stmt nodes - */ switch (nodeTag(node->utilityStmt)) { case T_CreateStmt: - appendStringInfo(str, " :create "); - _outToken(str, ((CreateStmt *) (node->utilityStmt))->relname); - appendStringInfo(str, " "); - _outNode(str, node->utilityStmt); - break; - case T_IndexStmt: - appendStringInfo(str, " :index "); - _outToken(str, ((IndexStmt *) (node->utilityStmt))->idxname); - appendStringInfo(str, " on "); - _outToken(str, ((IndexStmt *) (node->utilityStmt))->relname); - appendStringInfo(str, " "); + case T_NotifyStmt: _outNode(str, node->utilityStmt); break; - - case T_NotifyStmt: - appendStringInfo(str, " :notify "); - _outToken(str, ((NotifyStmt *) (node->utilityStmt))->relname); - break; - default: - appendStringInfo(str, " :utility ? "); + appendStringInfo(str, "?"); + break; } } else - appendStringInfo(str, " :utility <>"); + appendStringInfo(str, "<>"); appendStringInfo(str, " :resultRelation %d :into ", node->resultRelation); - _outToken(str, node->into); + _outNode(str, node->into); - appendStringInfo(str, " :isPortal %s :isBinary %s :isTemp %s" + appendStringInfo(str, " :isPortal %s :isBinary %s" " :hasAggs %s :hasSubLinks %s :rtable ", booltostr(node->isPortal), booltostr(node->isBinary), - booltostr(node->isTemp), booltostr(node->hasAggs), booltostr(node->hasSubLinks)); _outNode(str, node->rtable); @@ -963,6 +956,15 @@ _outTargetEntry(StringInfo str, TargetEntry *node) _outNode(str, node->expr); } +static void +_outAlias(StringInfo str, Alias *node) +{ + appendStringInfo(str, " ALIAS :aliasname "); + _outToken(str, node->aliasname); + appendStringInfo(str, " :colnames "); + _outNode(str, node->colnames); +} + static void _outRangeTblEntry(StringInfo str, RangeTblEntry *node) { @@ -1311,6 +1313,42 @@ _outValue(StringInfo str, Value *value) } } +static void +_outRangeVar(StringInfo str, RangeVar *node) +{ + appendStringInfo(str, " RANGEVAR :relation "); + /* + * we deliberately ignore catalogname here, since it is presently not + * semantically meaningful + */ + _outToken(str, node->schemaname); + appendStringInfo(str, " . "); + _outToken(str, node->relname); + appendStringInfo(str, " :inhopt %d :istemp %s", + (int) node->inhOpt, + booltostr(node->istemp)); + appendStringInfo(str, " :alias "); + _outNode(str, node->alias); +} + +static void +_outColumnRef(StringInfo str, ColumnRef *node) +{ + appendStringInfo(str, " COLUMNREF :fields "); + _outNode(str, node->fields); + appendStringInfo(str, " :indirection "); + _outNode(str, node->indirection); +} + +static void +_outParamRef(StringInfo str, ParamRef *node) +{ + appendStringInfo(str, " PARAMREF :number %d :fields ", node->number); + _outNode(str, node->fields); + appendStringInfo(str, " :indirection "); + _outNode(str, node->indirection); +} + static void _outIdent(StringInfo str, Ident *node) { @@ -1318,15 +1356,6 @@ _outIdent(StringInfo str, Ident *node) _outToken(str, node->name); } -static void -_outAttr(StringInfo str, Attr *node) -{ - appendStringInfo(str, " ATTR :relname "); - _outToken(str, node->relname); - appendStringInfo(str, " :attrs "); - _outNode(str, node->attrs); -} - static void _outAConst(StringInfo str, A_Const *node) { @@ -1336,6 +1365,17 @@ _outAConst(StringInfo str, A_Const *node) _outNode(str, node->typename); } +static void +_outExprFieldSelect(StringInfo str, ExprFieldSelect *node) +{ + appendStringInfo(str, " EXPRFIELDSELECT :arg "); + _outNode(str, node->arg); + appendStringInfo(str, " :fields "); + _outNode(str, node->fields); + appendStringInfo(str, " :indirection "); + _outNode(str, node->indirection); +} + static void _outConstraint(StringInfo str, Constraint *node) { @@ -1384,8 +1424,8 @@ _outFkConstraint(StringInfo str, FkConstraint *node) { appendStringInfo(str, " FKCONSTRAINT :constr_name "); _outToken(str, node->constr_name); - appendStringInfo(str, " :pktable_name "); - _outToken(str, node->pktable_name); + appendStringInfo(str, " :pktable "); + _outNode(str, node->pktable); appendStringInfo(str, " :fk_attrs "); _outNode(str, node->fk_attrs); appendStringInfo(str, " :pk_attrs "); @@ -1490,6 +1530,12 @@ _outNode(StringInfo str, void *obj) case T_IndexStmt: _outIndexStmt(str, obj); break; + case T_NotifyStmt: + _outNotifyStmt(str, obj); + break; + case T_SelectStmt: + _outSelectStmt(str, obj); + break; case T_ColumnDef: _outColumnDef(str, obj); break; @@ -1628,6 +1674,9 @@ _outNode(StringInfo str, void *obj) case T_TargetEntry: _outTargetEntry(str, obj); break; + case T_Alias: + _outAlias(str, obj); + break; case T_RangeTblEntry: _outRangeTblEntry(str, obj); break; @@ -1670,12 +1719,24 @@ _outNode(StringInfo str, void *obj) case T_A_Expr: _outAExpr(str, obj); break; + case T_RangeVar: + _outRangeVar(str, obj); + break; + case T_ColumnRef: + _outColumnRef(str, obj); + break; + case T_ParamRef: + _outParamRef(str, obj); + break; case T_Ident: _outIdent(str, obj); break; case T_A_Const: _outAConst(str, obj); break; + case T_ExprFieldSelect: + _outExprFieldSelect(str, obj); + break; case T_Constraint: _outConstraint(str, obj); break; @@ -1694,17 +1755,9 @@ _outNode(StringInfo str, void *obj) case T_BooleanTest: _outBooleanTest(str, obj); break; - case T_VariableSetStmt: - break; - case T_SelectStmt: - _outSelectStmt(str, obj); - break; case T_FuncCall: _outFuncCall(str, obj); break; - case T_Attr: - _outAttr(str, obj); - break; default: elog(WARNING, "_outNode: don't know how to print type %d ", diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c index 0d92994102..ebc5d536e7 100644 --- a/src/backend/nodes/print.c +++ b/src/backend/nodes/print.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.51 2001/12/20 02:39:26 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.52 2002/03/21 16:00:41 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -154,10 +154,10 @@ print_rt(List *rtable) if (rte->relname) printf("%d\t%s (%s)\t%u", - i, rte->relname, rte->eref->relname, rte->relid); + i, rte->relname, rte->eref->aliasname, rte->relid); else printf("%d\t[subquery] (%s)\t", - i, rte->eref->relname); + i, rte->eref->aliasname); printf("\t%s\t%s\n", (rte->inh ? "inh" : ""), (rte->inFromCl ? "inFromCl" : "")); @@ -202,7 +202,7 @@ print_expr(Node *expr, List *rtable) Assert(var->varno > 0 && (int) var->varno <= length(rtable)); rte = rt_fetch(var->varno, rtable); - relname = rte->eref->relname; + relname = rte->eref->aliasname; attname = get_rte_attribute_name(rte, var->varattno); } break; diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index c0794123b3..66dd317f39 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.116 2002/03/12 00:51:39 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.117 2002/03/21 16:00:42 tgl Exp $ * * NOTES * Most of the read functions for plan nodes are tested. (In fact, they @@ -119,34 +119,19 @@ _readQuery(void) local_node = makeNode(Query); - token = pg_strtok(&length); /* skip the :command */ - token = pg_strtok(&length); /* get the commandType */ + token = pg_strtok(&length); /* skip :command */ + token = pg_strtok(&length); /* get commandType */ local_node->commandType = atoi(token); token = pg_strtok(&length); /* skip :utility */ - token = pg_strtok(&length); - if (length == 0) - local_node->utilityStmt = NULL; - else - { - /* - * Hack to make up for lack of readfuncs for utility-stmt nodes - * - * we can't get create or index here, can we? - */ - NotifyStmt *n = makeNode(NotifyStmt); + local_node->utilityStmt = nodeRead(true); - n->relname = debackslash(token, length); - local_node->utilityStmt = (Node *) n; - } - - token = pg_strtok(&length); /* skip the :resultRelation */ + token = pg_strtok(&length); /* skip :resultRelation */ token = pg_strtok(&length); /* get the resultRelation */ local_node->resultRelation = atoi(token); token = pg_strtok(&length); /* skip :into */ - token = pg_strtok(&length); /* get into */ - local_node->into = nullable_string(token, length); + local_node->into = nodeRead(true); token = pg_strtok(&length); /* skip :isPortal */ token = pg_strtok(&length); /* get isPortal */ @@ -156,10 +141,6 @@ _readQuery(void) token = pg_strtok(&length); /* get isBinary */ local_node->isBinary = strtobool(token); - token = pg_strtok(&length); /* skip :isTemp */ - token = pg_strtok(&length); /* get isTemp */ - local_node->isTemp = strtobool(token); - token = pg_strtok(&length); /* skip the :hasAggs */ token = pg_strtok(&length); /* get hasAggs */ local_node->hasAggs = strtobool(token); @@ -210,6 +191,25 @@ _readQuery(void) return local_node; } +/* ---------------- + * _readNotifyStmt + * ---------------- + */ +static NotifyStmt * +_readNotifyStmt(void) +{ + NotifyStmt *local_node; + char *token; + int length; + + local_node = makeNode(NotifyStmt); + + token = pg_strtok(&length); /* skip :relation */ + local_node->relation = nodeRead(true); + + return local_node; +} + /* ---------------- * _readSortClause * ---------------- @@ -1394,21 +1394,93 @@ _readTargetEntry(void) return local_node; } -static Attr * -_readAttr(void) +static RangeVar * +_readRangeVar(void) { - Attr *local_node; + RangeVar *local_node; char *token; int length; - local_node = makeNode(Attr); + local_node = makeNode(RangeVar); - token = pg_strtok(&length); /* eat :relname */ + local_node->catalogname = NULL; /* not currently saved in output format */ + + token = pg_strtok(&length); /* eat :relation */ + token = pg_strtok(&length); /* get schemaname */ + local_node->schemaname = nullable_string(token, length); + + token = pg_strtok(&length); /* eat "." */ token = pg_strtok(&length); /* get relname */ - local_node->relname = debackslash(token, length); + local_node->relname = nullable_string(token, length); + + token = pg_strtok(&length); /* eat :inhopt */ + token = pg_strtok(&length); /* get inhopt */ + local_node->inhOpt = (InhOption) atoi(token); + + token = pg_strtok(&length); /* eat :istemp */ + token = pg_strtok(&length); /* get istemp */ + local_node->istemp = strtobool(token); - token = pg_strtok(&length); /* eat :attrs */ - local_node->attrs = nodeRead(true); /* now read it */ + token = pg_strtok(&length); /* eat :alias */ + local_node->alias = nodeRead(true); /* now read it */ + + return local_node; +} + +static ColumnRef * +_readColumnRef(void) +{ + ColumnRef *local_node; + char *token; + int length; + + local_node = makeNode(ColumnRef); + + token = pg_strtok(&length); /* eat :fields */ + local_node->fields = nodeRead(true); /* now read it */ + + token = pg_strtok(&length); /* eat :indirection */ + local_node->indirection = nodeRead(true); /* now read it */ + + return local_node; +} + +static ExprFieldSelect * +_readExprFieldSelect(void) +{ + ExprFieldSelect *local_node; + char *token; + int length; + + local_node = makeNode(ExprFieldSelect); + + token = pg_strtok(&length); /* eat :arg */ + local_node->arg = nodeRead(true); /* now read it */ + + token = pg_strtok(&length); /* eat :fields */ + local_node->fields = nodeRead(true); /* now read it */ + + token = pg_strtok(&length); /* eat :indirection */ + local_node->indirection = nodeRead(true); /* now read it */ + + return local_node; +} + +static Alias * +_readAlias(void) +{ + Alias *local_node; + char *token; + int length; + + local_node = makeNode(Alias); + + token = pg_strtok(&length); /* eat :aliasname */ + token = pg_strtok(&length); /* get aliasname */ + local_node->aliasname = debackslash(token, length); + + token = pg_strtok(&length); /* eat :colnames */ + local_node->colnames = nodeRead(true); /* now read it */ return local_node; } @@ -1994,8 +2066,6 @@ parsePlanString(void) return_value = _readArrayRef(); else if (length == 3 && strncmp(token, "VAR", length) == 0) return_value = _readVar(); - else if (length == 4 && strncmp(token, "ATTR", length) == 0) - return_value = _readAttr(); else if (length == 5 && strncmp(token, "CONST", length) == 0) return_value = _readConst(); else if (length == 4 && strncmp(token, "FUNC", length) == 0) @@ -2006,6 +2076,14 @@ parsePlanString(void) return_value = _readParam(); else if (length == 11 && strncmp(token, "TARGETENTRY", length) == 0) return_value = _readTargetEntry(); + else if (length == 8 && strncmp(token, "RANGEVAR", length) == 0) + return_value = _readRangeVar(); + else if (length == 9 && strncmp(token, "COLUMNREF", length) == 0) + return_value = _readColumnRef(); + else if (length == 15 && strncmp(token, "EXPRFIELDSELECT", length) == 0) + return_value = _readExprFieldSelect(); + else if (length == 5 && strncmp(token, "ALIAS", length) == 0) + return_value = _readAlias(); else if (length == 3 && strncmp(token, "RTE", length) == 0) return_value = _readRangeTblEntry(); else if (length == 4 && strncmp(token, "PATH", length) == 0) @@ -2032,6 +2110,8 @@ parsePlanString(void) return_value = _readIter(); else if (length == 5 && strncmp(token, "QUERY", length) == 0) return_value = _readQuery(); + else if (length == 6 && strncmp(token, "NOTIFY", length) == 0) + return_value = _readNotifyStmt(); else if (length == 10 && strncmp(token, "SORTCLAUSE", length) == 0) return_value = _readSortClause(); else if (length == 11 && strncmp(token, "GROUPCLAUSE", length) == 0) diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 6585fb1905..41cc4cdd53 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.94 2002/03/12 00:51:50 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.95 2002/03/21 16:00:44 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -687,7 +687,7 @@ check_subplans_for_ungrouped_vars_walker(Node *node, rte = rt_fetch(var->varno, context->query->rtable); attname = get_rte_attribute_name(rte, var->varattno); elog(ERROR, "Sub-SELECT uses un-GROUPed attribute %s.%s from outer query", - rte->eref->relname, attname); + rte->eref->aliasname, attname); } } } @@ -1670,7 +1670,6 @@ expression_tree_walker(Node *node, return false; switch (nodeTag(node)) { - case T_Ident: case T_Const: case T_Var: case T_Param: @@ -1963,7 +1962,6 @@ expression_tree_mutator(Node *node, return NULL; switch (nodeTag(node)) { - case T_Ident: case T_Const: case T_Var: case T_Param: diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 98f5030f78..109062c529 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.220 2002/03/12 00:51:52 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.221 2002/03/21 16:00:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -43,13 +43,30 @@ #endif +/* State shared by transformCreateSchemaStmt and its subroutines */ +typedef struct +{ + const char *stmtType; /* "CREATE TABLE" or "ALTER TABLE" */ + char *schemaname; /* name of schema */ + char *authid; /* owner of schema */ + List *tables; /* CREATE TABLE items */ + List *views; /* CREATE VIEW items */ + List *grants; /* GRANT items */ + List *fwconstraints; /* Forward referencing FOREIGN KEY constraints */ + List *alters; /* Generated ALTER items (from the above) */ + List *ixconstraints; /* index-creating constraints */ + List *blist; /* "before list" of things to do before + * creating the schema */ + List *alist; /* "after list" of things to do after + * creating the schema */ +} CreateSchemaStmtContext; + /* State shared by transformCreateStmt and its subroutines */ typedef struct { const char *stmtType; /* "CREATE TABLE" or "ALTER TABLE" */ - char *relname; /* name of relation */ - List *inhRelnames; /* names of relations to inherit from */ - bool istemp; /* is it to be a temp relation? */ + RangeVar *relation; /* relation to create */ + List *inhRelations; /* relations to inherit from */ bool hasoids; /* does relation have an OID column? */ Oid relOid; /* OID of table, if ALTER TABLE case */ List *columns; /* ColumnDef items */ @@ -330,8 +347,8 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt) qry->commandType = CMD_DELETE; /* set up range table with just the result rel */ - qry->resultRelation = setTargetTable(pstate, stmt->relname, - interpretInhOption(stmt->inhOpt), + qry->resultRelation = setTargetTable(pstate, stmt->relation->relname, + interpretInhOption(stmt->relation->inhOpt), true); qry->distinctClause = NIL; @@ -398,7 +415,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt, * table is also mentioned in the SELECT part. Note that the target * table is not added to the joinlist or namespace. */ - qry->resultRelation = setTargetTable(pstate, stmt->relname, + qry->resultRelation = setTargetTable(pstate, stmt->relation->relname, false, false); /* @@ -443,7 +460,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt, */ rte = addRangeTableEntryForSubquery(pstate, selectQuery, - makeAttr("*SELECT*", NULL), + makeAlias("*SELECT*", NIL), true); rtr = makeNode(RangeTblRef); /* assume new rte is at end */ @@ -515,14 +532,15 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt, foreach(tl, qry->targetList) { TargetEntry *tle = (TargetEntry *) lfirst(tl); - Ident *id; + ResTarget *col; Assert(!tle->resdom->resjunk); if (icolumns == NIL || attnos == NIL) elog(ERROR, "INSERT has more expressions than target columns"); - id = (Ident *) lfirst(icolumns); - updateTargetListEntry(pstate, tle, id->name, lfirsti(attnos), - id->indirection); + col = (ResTarget *) lfirst(icolumns); + Assert(IsA(col, ResTarget)); + updateTargetListEntry(pstate, tle, col->name, lfirsti(attnos), + col->indirection); icolumns = lnext(icolumns); attnos = lnext(attnos); } @@ -691,9 +709,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt, List *elements; cxt.stmtType = "CREATE TABLE"; - cxt.relname = stmt->relname; - cxt.inhRelnames = stmt->inhRelnames; - cxt.istemp = stmt->istemp; + cxt.relation = stmt->relation; + cxt.inhRelations = stmt->inhRelations; cxt.hasoids = stmt->hasoids; cxt.relOid = InvalidOid; cxt.columns = NIL; @@ -805,7 +822,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, * conflicting constraints the user wrote (like a different * DEFAULT). */ - sname = makeObjectName(cxt->relname, column->colname, "seq"); + sname = makeObjectName((cxt->relation)->relname, column->colname, "seq"); /* * Create an expression tree representing the function call @@ -845,12 +862,12 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, * CREATE/ALTER TABLE. */ sequence = makeNode(CreateSeqStmt); - sequence->seqname = pstrdup(sname); - sequence->istemp = cxt->istemp; + sequence->sequence = copyObject(cxt->relation); + sequence->sequence->relname = pstrdup(sname); sequence->options = NIL; elog(NOTICE, "%s will create implicit sequence '%s' for SERIAL column '%s.%s'", - cxt->stmtType, sequence->seqname, cxt->relname, column->colname); + cxt->stmtType, sequence->sequence->relname, (cxt->relation)->relname, column->colname); cxt->blist = lappend(cxt->blist, sequence); } @@ -875,9 +892,6 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, Ident *id = makeNode(Ident); id->name = column->colname; - id->indirection = NIL; - id->isRel = false; - fkconstraint->fk_attrs = makeList1(id); cxt->fkconstraints = lappend(cxt->fkconstraints, fkconstraint); @@ -891,7 +905,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, case CONSTR_NULL: if (saw_nullable && column->is_not_null) elog(ERROR, "%s/(NOT) NULL conflicting declaration for '%s.%s'", - cxt->stmtType, cxt->relname, column->colname); + cxt->stmtType, (cxt->relation)->relname, column->colname); column->is_not_null = FALSE; saw_nullable = true; break; @@ -899,7 +913,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, case CONSTR_NOTNULL: if (saw_nullable && !column->is_not_null) elog(ERROR, "%s/(NOT) NULL conflicting declaration for '%s.%s'", - cxt->stmtType, cxt->relname, column->colname); + cxt->stmtType, (cxt->relation)->relname, column->colname); column->is_not_null = TRUE; saw_nullable = true; break; @@ -907,14 +921,14 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, case CONSTR_DEFAULT: if (column->raw_default != NULL) elog(ERROR, "%s/DEFAULT multiple values specified for '%s.%s'", - cxt->stmtType, cxt->relname, column->colname); + cxt->stmtType, (cxt->relation)->relname, column->colname); column->raw_default = constraint->raw_expr; Assert(constraint->cooked_expr == NULL); break; case CONSTR_PRIMARY: if (constraint->name == NULL) - constraint->name = makeObjectName(cxt->relname, + constraint->name = makeObjectName((cxt->relation)->relname, NULL, "pkey"); if (constraint->keys == NIL) @@ -928,7 +942,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, case CONSTR_UNIQUE: if (constraint->name == NULL) - constraint->name = makeObjectName(cxt->relname, + constraint->name = makeObjectName((cxt->relation)->relname, column->colname, "key"); if (constraint->keys == NIL) @@ -942,7 +956,7 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, case CONSTR_CHECK: if (constraint->name == NULL) - constraint->name = makeObjectName(cxt->relname, + constraint->name = makeObjectName((cxt->relation)->relname, column->colname, NULL); cxt->ckconstraints = lappend(cxt->ckconstraints, constraint); @@ -970,7 +984,7 @@ transformTableConstraint(ParseState *pstate, CreateStmtContext *cxt, { case CONSTR_PRIMARY: if (constraint->name == NULL) - constraint->name = makeObjectName(cxt->relname, + constraint->name = makeObjectName((cxt->relation)->relname, NULL, "pkey"); cxt->ixconstraints = lappend(cxt->ixconstraints, constraint); @@ -1034,21 +1048,21 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt) /* In ALTER TABLE case, a primary index might already exist */ if (cxt->pkey != NULL || (OidIsValid(cxt->relOid) && - relationHasPrimaryKey(cxt->relname))) + relationHasPrimaryKey((cxt->relation)->relname))) elog(ERROR, "%s / PRIMARY KEY multiple primary keys" " for table '%s' are not allowed", - cxt->stmtType, cxt->relname); + cxt->stmtType, (cxt->relation)->relname); cxt->pkey = index; } if (constraint->name != NULL) index->idxname = pstrdup(constraint->name); else if (constraint->contype == CONSTR_PRIMARY) - index->idxname = makeObjectName(cxt->relname, NULL, "pkey"); + index->idxname = makeObjectName((cxt->relation)->relname, NULL, "pkey"); else index->idxname = NULL; /* will set it later */ - index->relname = cxt->relname; + index->relation = cxt->relation; index->accessMethod = DEFAULT_INDEX_TYPE; index->indexParams = NIL; index->whereClause = NULL; @@ -1089,19 +1103,19 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt) */ found = true; } - else if (cxt->inhRelnames) + else if (cxt->inhRelations) { /* try inherited tables */ List *inher; - foreach(inher, cxt->inhRelnames) + foreach(inher, cxt->inhRelations) { - Value *inh = lfirst(inher); + RangeVar *inh = lfirst(inher); Relation rel; int count; - Assert(IsA(inh, String)); - rel = heap_openr(strVal(inh), AccessShareLock); + Assert(IsA(inh, RangeVar)); + rel = heap_openr(inh->relname, AccessShareLock); if (rel->rd_rel->relkind != RELKIND_RELATION) elog(ERROR, "inherited table \"%s\" is not a relation", strVal(inh)); @@ -1257,7 +1271,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt) if (index->idxname == NULL && index->indexParams != NIL) { iparam = lfirst(index->indexParams); - index->idxname = CreateIndexName(cxt->relname, iparam->name, + index->idxname = CreateIndexName((cxt->relation)->relname, iparam->name, "key", cxt->alist); } if (index->idxname == NULL) /* should not happen */ @@ -1268,7 +1282,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt) cxt->stmtType, (strcmp(cxt->stmtType, "ALTER TABLE") == 0) ? "ADD " : "", (index->primary ? "PRIMARY KEY" : "UNIQUE"), - index->idxname, cxt->relname); + index->idxname, (cxt->relation)->relname); } } @@ -1328,7 +1342,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt) */ if (fkconstraint->pk_attrs == NIL) { - if (strcmp(fkconstraint->pktable_name, cxt->relname) != 0) + if (strcmp(fkconstraint->pktable->relname, (cxt->relation)->relname) != 0) transformFkeyGetPrimaryKey(fkconstraint, pktypoid); else if (cxt->pkey != NULL) { @@ -1342,8 +1356,6 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt) Ident *pkattr = (Ident *) makeNode(Ident); pkattr->name = pstrdup(ielem->name); - pkattr->indirection = NIL; - pkattr->isRel = false; fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr); if (attnum >= INDEX_MAX_KEYS) @@ -1360,13 +1372,13 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt) transformFkeyGetPrimaryKey(fkconstraint, pktypoid); else elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found", - fkconstraint->pktable_name); + fkconstraint->pktable->relname); } } else { /* Validate the specified referenced key list */ - if (strcmp(fkconstraint->pktable_name, cxt->relname) != 0) + if (strcmp(fkconstraint->pktable->relname, (cxt->relation)->relname) != 0) transformFkeyCheckAttrs(fkconstraint, pktypoid); else { @@ -1422,7 +1434,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt) transformFkeyCheckAttrs(fkconstraint, pktypoid); else elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found", - fkconstraint->pktable_name); + fkconstraint->pktable->relname); } } } @@ -1447,7 +1459,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt) */ fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt); fk_trigger->trigname = fkconstraint->constr_name; - fk_trigger->relname = cxt->relname; + fk_trigger->relation = cxt->relation; fk_trigger->funcname = "RI_FKey_check_ins"; fk_trigger->before = false; fk_trigger->row = true; @@ -1462,15 +1474,15 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt) fk_trigger->isconstraint = true; fk_trigger->deferrable = fkconstraint->deferrable; fk_trigger->initdeferred = fkconstraint->initdeferred; - fk_trigger->constrrelname = fkconstraint->pktable_name; + fk_trigger->constrrel = fkconstraint->pktable; fk_trigger->args = NIL; fk_trigger->args = lappend(fk_trigger->args, makeString(fkconstraint->constr_name)); fk_trigger->args = lappend(fk_trigger->args, - makeString(cxt->relname)); + makeString((cxt->relation)->relname)); fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->pktable_name)); + makeString(fkconstraint->pktable->relname)); fk_trigger->args = lappend(fk_trigger->args, makeString(fkconstraint->match_type)); fk_attr = fkconstraint->fk_attrs; @@ -1478,7 +1490,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt) if (length(fk_attr) != length(pk_attr)) elog(ERROR, "number of key attributes in referenced table must be equal to foreign key" "\n\tIllegal FOREIGN KEY definition references \"%s\"", - fkconstraint->pktable_name); + fkconstraint->pktable->relname); while (fk_attr != NIL) { @@ -1502,7 +1514,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt) */ fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt); fk_trigger->trigname = fkconstraint->constr_name; - fk_trigger->relname = fkconstraint->pktable_name; + fk_trigger->relation = fkconstraint->pktable; fk_trigger->before = false; fk_trigger->row = true; fk_trigger->actions[0] = 'd'; @@ -1515,7 +1527,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt) fk_trigger->isconstraint = true; fk_trigger->deferrable = fkconstraint->deferrable; fk_trigger->initdeferred = fkconstraint->initdeferred; - fk_trigger->constrrelname = cxt->relname; + fk_trigger->constrrel = cxt->relation; switch ((fkconstraint->actions & FKCONSTR_ON_DELETE_MASK) >> FKCONSTR_ON_DELETE_SHIFT) { @@ -1545,9 +1557,9 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt) fk_trigger->args = lappend(fk_trigger->args, makeString(fkconstraint->constr_name)); fk_trigger->args = lappend(fk_trigger->args, - makeString(cxt->relname)); + makeString((cxt->relation)->relname)); fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->pktable_name)); + makeString(fkconstraint->pktable->relname)); fk_trigger->args = lappend(fk_trigger->args, makeString(fkconstraint->match_type)); fk_attr = fkconstraint->fk_attrs; @@ -1574,7 +1586,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt) */ fk_trigger = (CreateTrigStmt *) makeNode(CreateTrigStmt); fk_trigger->trigname = fkconstraint->constr_name; - fk_trigger->relname = fkconstraint->pktable_name; + fk_trigger->relation = fkconstraint->pktable; fk_trigger->before = false; fk_trigger->row = true; fk_trigger->actions[0] = 'u'; @@ -1587,7 +1599,7 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt) fk_trigger->isconstraint = true; fk_trigger->deferrable = fkconstraint->deferrable; fk_trigger->initdeferred = fkconstraint->initdeferred; - fk_trigger->constrrelname = cxt->relname; + fk_trigger->constrrel = cxt->relation; switch ((fkconstraint->actions & FKCONSTR_ON_UPDATE_MASK) >> FKCONSTR_ON_UPDATE_SHIFT) { @@ -1617,9 +1629,9 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt) fk_trigger->args = lappend(fk_trigger->args, makeString(fkconstraint->constr_name)); fk_trigger->args = lappend(fk_trigger->args, - makeString(cxt->relname)); + makeString((cxt->relation)->relname)); fk_trigger->args = lappend(fk_trigger->args, - makeString(fkconstraint->pktable_name)); + makeString(fkconstraint->pktable->relname)); fk_trigger->args = lappend(fk_trigger->args, makeString(fkconstraint->match_type)); fk_attr = fkconstraint->fk_attrs; @@ -1672,7 +1684,7 @@ transformIndexStmt(ParseState *pstate, IndexStmt *stmt) * easily support predicates on indexes created implicitly by * CREATE TABLE. Fortunately, that's not necessary. */ - rte = addRangeTableEntry(pstate, stmt->relname, NULL, false, true); + rte = addRangeTableEntry(pstate, stmt->relation->relname, NULL, false, true); /* no to join list, yes to namespace */ addRTEtoQuery(pstate, rte, false, true); @@ -1712,7 +1724,7 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt, * beforehand. We don't need to hold a refcount on the relcache * entry, however. */ - heap_close(heap_openr(stmt->object->relname, AccessExclusiveLock), + heap_close(heap_openr(stmt->relation->relname, AccessExclusiveLock), NoLock); /* @@ -1721,11 +1733,11 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt, * rule qualification. */ Assert(pstate->p_rtable == NIL); - oldrte = addRangeTableEntry(pstate, stmt->object->relname, - makeAttr("*OLD*", NULL), + oldrte = addRangeTableEntry(pstate, stmt->relation->relname, + makeAlias("*OLD*", NIL), false, true); - newrte = addRangeTableEntry(pstate, stmt->object->relname, - makeAttr("*NEW*", NULL), + newrte = addRangeTableEntry(pstate, stmt->relation->relname, + makeAlias("*NEW*", NIL), false, true); /* Must override addRangeTableEntry's default access-check flags */ oldrte->checkForRead = false; @@ -1812,11 +1824,11 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt, * or they won't be accessible at all. We decide later * whether to put them in the joinlist. */ - oldrte = addRangeTableEntry(sub_pstate, stmt->object->relname, - makeAttr("*OLD*", NULL), + oldrte = addRangeTableEntry(sub_pstate, stmt->relation->relname, + makeAlias("*OLD*", NIL), false, false); - newrte = addRangeTableEntry(sub_pstate, stmt->object->relname, - makeAttr("*NEW*", NULL), + newrte = addRangeTableEntry(sub_pstate, stmt->relation->relname, + makeAlias("*NEW*", NIL), false, false); oldrte->checkForRead = false; newrte->checkForRead = false; @@ -1950,8 +1962,8 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) if (!IsTransactionBlock()) elog(ERROR, "DECLARE CURSOR may only be used in begin/end transaction blocks"); - qry->into = stmt->portalname; - qry->isTemp = stmt->istemp; + qry->into = makeNode(RangeVar); + qry->into->relname = stmt->portalname; qry->isPortal = TRUE; qry->isBinary = stmt->binary; /* internal portal */ } @@ -1959,7 +1971,6 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) { /* SELECT */ qry->into = stmt->into; - qry->isTemp = stmt->istemp; qry->isPortal = FALSE; qry->isBinary = FALSE; } @@ -2033,8 +2044,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) int leftmostRTI; Query *leftmostQuery; SetOperationStmt *sostmt; - char *into; - bool istemp; + RangeVar *into; List *intoColNames; char *portalname; bool binary; @@ -2065,14 +2075,12 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) Assert(leftmostSelect && IsA(leftmostSelect, SelectStmt) && leftmostSelect->larg == NULL); into = leftmostSelect->into; - istemp = leftmostSelect->istemp; intoColNames = leftmostSelect->intoColNames; portalname = stmt->portalname; binary = stmt->binary; /* clear them to prevent complaints in transformSetOperationTree() */ leftmostSelect->into = NULL; - leftmostSelect->istemp = false; leftmostSelect->intoColNames = NIL; stmt->portalname = NULL; stmt->binary = false; @@ -2174,8 +2182,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) if (!IsTransactionBlock()) elog(ERROR, "DECLARE CURSOR may only be used in begin/end transaction blocks"); - qry->into = portalname; - qry->isTemp = istemp; + qry->into = makeNode(RangeVar); + qry->into->relname = portalname; qry->isPortal = TRUE; qry->isBinary = binary; /* internal portal */ } @@ -2183,7 +2191,6 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) { /* SELECT */ qry->into = into; - qry->isTemp = istemp; qry->isPortal = FALSE; qry->isBinary = FALSE; } @@ -2325,8 +2332,7 @@ transformSetOperationTree(ParseState *pstate, SelectStmt *stmt) sprintf(selectName, "*SELECT* %d", length(pstate->p_rtable) + 1); rte = addRangeTableEntryForSubquery(pstate, selectQuery, - makeAttr(pstrdup(selectName), - NULL), + makeAlias(selectName, NIL), false); /* @@ -2468,8 +2474,8 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt) qry->commandType = CMD_UPDATE; pstate->p_is_update = true; - qry->resultRelation = setTargetTable(pstate, stmt->relname, - interpretInhOption(stmt->inhOpt), + qry->resultRelation = setTargetTable(pstate, stmt->relation->relname, + interpretInhOption(stmt->relation->inhOpt), true); /* @@ -2553,11 +2559,11 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt, { case 'A': cxt.stmtType = "ALTER TABLE"; - cxt.relname = stmt->relname; - cxt.inhRelnames = NIL; - cxt.istemp = is_temp_rel_name(stmt->relname); + cxt.relation = stmt->relation; + cxt.inhRelations = NIL; + cxt.relation->istemp = is_temp_rel_name(stmt->relation->relname); cxt.relOid = GetSysCacheOid(RELNAME, - PointerGetDatum(stmt->relname), + PointerGetDatum((stmt->relation)->relname), 0, 0, 0); cxt.hasoids = SearchSysCacheExists(ATTNUM, ObjectIdGetDatum(cxt.relOid), @@ -2585,11 +2591,11 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt, case 'C': cxt.stmtType = "ALTER TABLE"; - cxt.relname = stmt->relname; - cxt.inhRelnames = NIL; - cxt.istemp = is_temp_rel_name(stmt->relname); + cxt.relation = stmt->relation; + cxt.inhRelations = NIL; + cxt.relation->istemp = is_temp_rel_name(stmt->relation->relname); cxt.relOid = GetSysCacheOid(RELNAME, - PointerGetDatum(stmt->relname), + PointerGetDatum((stmt->relation)->relname), 0, 0, 0); cxt.hasoids = SearchSysCacheExists(ATTNUM, ObjectIdGetDatum(cxt.relOid), @@ -2713,15 +2719,18 @@ transformTypeRefsList(ParseState *pstate, List *l) static void transformTypeRef(ParseState *pstate, TypeName *tn) { - Attr *att; + ColumnRef *cref; Node *n; Var *v; char *tyn; if (tn->attrname == NULL) return; - att = makeAttr(tn->name, tn->attrname); - n = transformExpr(pstate, (Node *) att, EXPR_COLUMN_FIRST); + /* XXX this needs work; can't type name be qualified? */ + cref = makeNode(ColumnRef); + cref->fields = makeList2(makeString(tn->name), makeString(tn->attrname)); + cref->indirection = NIL; + n = transformExpr(pstate, (Node *) cref); if (!IsA(n, Var)) elog(ERROR, "unsupported expression in %%TYPE"); v = (Var *) n; @@ -2791,7 +2800,7 @@ transformForUpdate(Query *qry, List *forUpdate) RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt); ++i; - if (strcmp(rte->eref->relname, relname) == 0) + if (strcmp(rte->eref->aliasname, relname) == 0) { if (rte->subquery) { @@ -2835,11 +2844,11 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid) /* * Open the referenced table */ - pkrel = heap_openr(fkconstraint->pktable_name, AccessShareLock); + pkrel = heap_openr(fkconstraint->pktable->relname, AccessShareLock); if (pkrel->rd_rel->relkind != RELKIND_RELATION) elog(ERROR, "Referenced relation \"%s\" is not a table", - fkconstraint->pktable_name); + fkconstraint->pktable->relname); /* * Get the list of index OIDs for the table from the relcache, and @@ -2901,7 +2910,7 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid) } if (!found) elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found", - fkconstraint->pktable_name); + fkconstraint->pktable->relname); freeList(indexoidlist); heap_close(pkrel, AccessShareLock); @@ -2928,11 +2937,11 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid) /* * Open the referenced table */ - pkrel = heap_openr(fkconstraint->pktable_name, AccessShareLock); + pkrel = heap_openr(fkconstraint->pktable->relname, AccessShareLock); if (pkrel->rd_rel->relkind != RELKIND_RELATION) elog(ERROR, "Referenced relation \"%s\" is not a table", - fkconstraint->pktable_name); + fkconstraint->pktable->relname); /* * Get the list of index OIDs for the table from the relcache, and @@ -2965,7 +2974,7 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid) */ if (indexStruct == NULL) elog(ERROR, "PRIMARY KEY for referenced table \"%s\" not found", - fkconstraint->pktable_name); + fkconstraint->pktable->relname); /* * Now build the list of PK attributes from the indkey definition @@ -2977,8 +2986,6 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid) Ident *pkattr = makeNode(Ident); pkattr->name = pstrdup(NameStr(*attnumAttName(pkrel, pkattno))); - pkattr->indirection = NIL; - pkattr->isRel = false; pktypoid[attnum++] = attnumTypeId(pkrel, pkattno); fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr); @@ -3070,14 +3077,14 @@ transformFkeyGetColType(CreateStmtContext *cxt, char *colname) if (sysatt) return sysatt->atttypid; /* Look for column among inherited columns (if CREATE TABLE case) */ - foreach(inher, cxt->inhRelnames) + foreach(inher, cxt->inhRelations) { - Value *inh = lfirst(inher); + RangeVar *inh = lfirst(inher); Relation rel; int count; - Assert(IsA(inh, String)); - rel = heap_openr(strVal(inh), AccessShareLock); + Assert(IsA(inh, RangeVar)); + rel = heap_openr(inh->relname, AccessShareLock); if (rel->rd_rel->relkind != RELKIND_RELATION) elog(ERROR, "inherited table \"%s\" is not a relation", strVal(inh)); @@ -3248,3 +3255,104 @@ transformColumnType(ParseState *pstate, ColumnDef *column) ReleaseSysCache(ctype); } + +/* + * analyzeCreateSchemaStmt - + * analyzes the "create schema" statement + * + * Split the schema element list into individual commands and place + * them in the result list in an order such that there are no + * forward references (e.g. GRANT to a table created later in the list). + * + * SQL92 also allows constraints to make forward references, so thumb through + * the table columns and move forward references to a posterior alter-table + * command. + * + * The result is a list of parse nodes that still need to be analyzed --- + * but we can't analyze the later commands until we've executed the earlier + * ones, because of possible inter-object references. + * + * Note: Called from commands/command.c + */ +List * +analyzeCreateSchemaStmt(CreateSchemaStmt *stmt) +{ + CreateSchemaStmtContext cxt; + List *result; + List *elements; + + cxt.stmtType = "CREATE SCHEMA"; + cxt.schemaname = stmt->schemaname; + cxt.authid = stmt->authid; + cxt.tables = NIL; + cxt.views = NIL; + cxt.grants = NIL; + cxt.fwconstraints = NIL; + cxt.alters = NIL; + cxt.blist = NIL; + cxt.alist = NIL; + + /* + * Run through each schema element in the schema element list. + * Separate statements by type, and do preliminary analysis. + */ + foreach(elements, stmt->schemaElts) + { + Node *element = lfirst(elements); + + switch (nodeTag(element)) + { + case T_CreateStmt: + { + CreateStmt *elp = (CreateStmt *) element; + + if (elp->relation->schemaname == NULL) + elp->relation->schemaname = cxt.schemaname; + else if (strcmp(cxt.schemaname, elp->relation->schemaname)) + elog(ERROR, "New table refers to a schema (%s)" + " different from the one being created (%s)", + elp->relation->schemaname, cxt.schemaname); + + /* + * XXX todo: deal with constraints + */ + + cxt.tables = lappend(cxt.tables, element); + } + break; + + case T_ViewStmt: + { + ViewStmt *elp = (ViewStmt *) element; + + if (elp->view->schemaname == NULL) + elp->view->schemaname = cxt.schemaname; + else if (strcmp(cxt.schemaname, elp->view->schemaname)) + elog(ERROR, "New view refers to a schema (%s)" + " different from the one being created (%s)", + elp->view->schemaname, cxt.schemaname); + + /* + * XXX todo: deal with references between views + */ + + cxt.views = lappend(cxt.views, element); + } + break; + + case T_GrantStmt: + cxt.grants = lappend(cxt.grants, element); + break; + + default: + elog(ERROR, "parser: unsupported schema node (internal error)"); + } + } + + result = NIL; + result = nconc(result, cxt.tables); + result = nconc(result, cxt.views); + result = nconc(result, cxt.grants); + + return result; +} diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 6951653ce8..f94eaea509 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * 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 @@ -98,6 +98,7 @@ static void doNegateFloat(Value *v); %} + %union { int ival; @@ -108,19 +109,17 @@ static void doNegateFloat(Value *v); 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; @@ -129,7 +128,7 @@ static void doNegateFloat(Value *v); InsertStmt *istmt; } -%type stmt, +%type stmt, schema_stmt, AlterDatabaseSetStmt, AlterGroupStmt, AlterSchemaStmt, AlterTableStmt, AlterUserStmt, AlterUserSetStmt, AnalyzeStmt, ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt, @@ -166,11 +165,12 @@ static void doNegateFloat(Value *v); %type OptUserList %type OptUserElem +%type OptSchemaName +%type OptSchemaEltList + %type TriggerActionTime, TriggerForSpec, opt_trusted, opt_procedural %type opt_lancompiler -%type OptConstrFromTable - %type TriggerEvents %type TriggerFuncArg @@ -178,6 +178,8 @@ static void doNegateFloat(Value *v); database_name, access_method_clause, access_method, attr_name, class, index_name, name, func_name, file_name +%type qualified_name, OptConstrFromTable + %type opt_id, all_Op, MathOp, opt_name, OptUseOp, opt_class, SpecialRuleRelation @@ -193,17 +195,19 @@ static void doNegateFloat(Value *v); %type TriggerOneEvent %type 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 into_clause, OptTempTableName + %type func_arg, func_return, func_type, aggr_argtype %type opt_arg, TriggerForOpt, TriggerForType, OptTemp, OptWithOids @@ -240,7 +244,7 @@ static void doNegateFloat(Value *v); %type OptTableElement, ConstraintElem %type columnDef %type def_elem -%type def_arg, columnElem, where_clause, +%type def_arg, columnElem, where_clause, insert_column_item, a_expr, b_expr, c_expr, AexprConst, in_expr, having_clause %type row_descriptor, row_list, in_expr_nodes @@ -252,14 +256,14 @@ static void doNegateFloat(Value *v); %type OptCreateAs, CreateAsList %type CreateAsElement %type NumericOnly, FloatOnly, IntegerOnly -%type event_object, attr, alias_clause +%type columnref +%type alias_clause %type sortby %type index_elem, func_index %type table_ref %type joined_table %type relation_expr %type target_el, update_target_el -%type ParamNo %type Typename, SimpleTypename, ConstTypename GenericType, Numeric, Character, ConstDatetime, ConstInterval, Bit @@ -290,6 +294,7 @@ static void doNegateFloat(Value *v); %type opt_as + /* * If you make any token changes, remember to: * - use "yacc -d" and update parse.h @@ -753,35 +758,57 @@ DropGroupStmt: DROP GROUP UserId * *****************************************************************************/ -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 + ; /***************************************************************************** * @@ -978,6 +1005,7 @@ opt_encoding: Sconst { $$ = $1; } ColId_or_Sconst: ColId { $$ = $1; } | SCONST { $$ = $1; } + ; VariableShowStmt: SHOW ColId @@ -1073,8 +1101,7 @@ AlterTableStmt: { AlterTableStmt *n = makeNode(AlterTableStmt); n->subtype = 'A'; - n->relname = $3->relname; - n->inhOpt = $3->inhOpt; + n->relation = $3; n->def = $6; $$ = (Node *)n; } @@ -1083,8 +1110,7 @@ AlterTableStmt: { 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; @@ -1094,8 +1120,7 @@ AlterTableStmt: { 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; @@ -1105,8 +1130,7 @@ AlterTableStmt: { 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; @@ -1116,8 +1140,7 @@ AlterTableStmt: { 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; @@ -1127,8 +1150,7 @@ AlterTableStmt: { AlterTableStmt *n = makeNode(AlterTableStmt); n->subtype = 'C'; - n->relname = $3->relname; - n->inhOpt = $3->inhOpt; + n->relation = $3; n->def = $5; $$ = (Node *)n; } @@ -1137,28 +1159,27 @@ AlterTableStmt: { 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 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 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; } @@ -1183,7 +1204,8 @@ drop_behavior: CASCADE { $$ = CASCADE; } opt_drop_behavior: CASCADE { $$ = CASCADE; } | RESTRICT { $$ = RESTRICT; } | /* EMPTY */ { $$ = RESTRICT; /* default */ } - ; + ; + /***************************************************************************** @@ -1214,11 +1236,11 @@ opt_id: ColId { $$ = $1; } * *****************************************************************************/ -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; @@ -1263,8 +1285,9 @@ opt_using: USING { $$ = TRUE; } | /*EMPTY*/ { $$ = TRUE; } ; -copy_null: WITH NULL_P AS Sconst { $$ = $4; } - | /*EMPTY*/ { $$ = "\\N"; } +copy_null: WITH NULL_P AS Sconst { $$ = $4; } + | /*EMPTY*/ { $$ = "\\N"; } + ; /***************************************************************************** * @@ -1273,14 +1296,14 @@ copy_null: WITH NULL_P AS Sconst { $$ = $4; } * *****************************************************************************/ -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; } @@ -1448,10 +1471,7 @@ ColConstraintElem: 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 @@ -1462,11 +1482,11 @@ ColConstraintElem: 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; @@ -1573,12 +1593,12 @@ ConstraintElem: CHECK '(' a_expr ')' 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; @@ -1589,6 +1609,24 @@ ConstraintElem: CHECK '(' a_expr ')' } ; +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"; @@ -1624,7 +1662,7 @@ key_reference: NO ACTION { $$ = FKCONSTR_ON_KEY_NOACTION; } | SET DEFAULT { $$ = FKCONSTR_ON_KEY_SETDEFAULT; } ; -OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; } +OptInherit: INHERITS '(' qualified_name_list ')' { $$ = $3; } | /*EMPTY*/ { $$ = NIL; } ; @@ -1639,7 +1677,7 @@ OptWithOids: WITH OIDS { $$ = TRUE; } * 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 @@ -1651,7 +1689,7 @@ CreateAsStmt: CREATE OptTemp TABLE relation_name OptCreateAs AS SelectStmt 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; @@ -1687,11 +1725,11 @@ CreateAsElement: ColId * *****************************************************************************/ -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; } @@ -1742,6 +1780,7 @@ OptSeqElem: CACHE NumericOnly NumericOnly: FloatOnly { $$ = $1; } | IntegerOnly { $$ = $1; } + ; FloatOnly: FCONST { @@ -1791,6 +1830,7 @@ opt_trusted: TRUSTED { $$ = TRUE; } opt_lancompiler: LANCOMPILER Sconst { $$ = $2; } | /*EMPTY*/ { $$ = ""; } + ; DropPLangStmt: DROP opt_procedural LANGUAGE ColId_or_Sconst { @@ -1813,12 +1853,12 @@ opt_procedural: PROCEDURAL { $$ = TRUE; } *****************************************************************************/ 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; @@ -1832,17 +1872,17 @@ CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON 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; @@ -1857,7 +1897,7 @@ CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON n->deferrable = ($10 & 1) != 0; n->initdeferred = ($10 & 2) != 0; - n->constrrelname = $9; + n->constrrel = $9; $$ = (Node *)n; } ; @@ -1937,9 +1977,9 @@ TriggerFuncArg: ICONST OptConstrFromTable: /* Empty */ { - $$ = ""; + $$ = NULL; } - | FROM relation_name + | FROM qualified_name { $$ = $2; } @@ -1983,11 +2023,11 @@ ConstraintTimeSpec: INITIALLY IMMEDIATE ; -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; } ; @@ -2063,11 +2103,14 @@ def_arg: func_return { $$ = (Node *)$1; } * *****************************************************************************/ -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; } @@ -2089,10 +2132,10 @@ drop_type: TABLE { $$ = DROP_TABLE; } * *****************************************************************************/ -TruncateStmt: TRUNCATE opt_table relation_name +TruncateStmt: TRUNCATE opt_table qualified_name { TruncateStmt *n = makeNode(TruncateStmt); - n->relName = $3; + n->relation = $3; $$ = (Node *)n; } ; @@ -2120,20 +2163,41 @@ CommentStmt: COMMENT ON comment_type name IS comment_text 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); @@ -2145,6 +2209,7 @@ CommentStmt: COMMENT ON comment_type name IS comment_text /* 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); @@ -2155,6 +2220,7 @@ CommentStmt: COMMENT ON comment_type name IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = FUNCTION; + n->objschema = NULL; n->objname = $4; n->objproperty = NULL; n->objlist = $5; @@ -2165,18 +2231,21 @@ CommentStmt: COMMENT ON comment_type name IS comment_text { 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; @@ -2414,14 +2483,14 @@ privilege: SELECT { $$ = SELECT; } /* 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; @@ -2513,13 +2582,13 @@ function_with_argtypes: func_name func_args * *****************************************************************************/ -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; @@ -2783,11 +2852,21 @@ oper_argtypes: Typename * *****************************************************************************/ -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; } @@ -2795,8 +2874,8 @@ ReindexStmt: REINDEX reindex_type name opt_force reindex_type: INDEX { $$ = INDEX; } | TABLE { $$ = TABLE; } - | DATABASE { $$ = DATABASE; } ; + opt_force: FORCE { $$ = TRUE; } | /* EMPTY */ { $$ = FALSE; } ; @@ -2813,8 +2892,7 @@ opt_force: FORCE { $$ = TRUE; } 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; @@ -2832,23 +2910,20 @@ opt_column: COLUMN { $$ = COLUMN; } /***************************************************************************** * - * QUERY: Define Rewrite Rule , Define Tuple Rule - * Define Rule - * - * 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; @@ -2888,24 +2963,6 @@ RuleActionStmtOrEmpty: RuleActionStmt { $$ = (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; } @@ -2921,40 +2978,42 @@ opt_instead: INSTEAD { $$ = TRUE; } /***************************************************************************** * * QUERY: - * NOTIFY can appear both in rule bodies and + * NOTIFY 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; } -; + ; /***************************************************************************** @@ -3036,10 +3095,10 @@ opt_chain: AND NO CHAIN * *****************************************************************************/ -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; @@ -3067,7 +3126,6 @@ LoadStmt: LOAD file_name * * CREATE DATABASE * - * *****************************************************************************/ CreatedbStmt: CREATE DATABASE database_name WITH createdb_opt_list @@ -3190,21 +3248,6 @@ opt_equal: '=' { $$ = TRUE; } ; -/***************************************************************************** - * - * DROP DATABASE - * - *****************************************************************************/ - -DropdbStmt: DROP DATABASE database_name - { - DropdbStmt *n = makeNode(DropdbStmt); - n->dbname = $3; - $$ = (Node *)n; - } - ; - - /***************************************************************************** * * ALTER DATABASE @@ -3229,11 +3272,26 @@ AlterDatabaseSetStmt: ALTER DATABASE database_name VariableSetStmt } ; + +/***************************************************************************** + * + * DROP DATABASE + * + *****************************************************************************/ + +DropdbStmt: DROP DATABASE database_name + { + DropdbStmt *n = makeNode(DropdbStmt); + n->dbname = $3; + $$ = (Node *)n; + } + ; + + /***************************************************************************** * * Manipulate a domain * - * *****************************************************************************/ CreateDomainStmt: CREATE DOMAIN_P name opt_as Typename ColQualList opt_collate @@ -3254,17 +3312,18 @@ opt_as: AS {$$ = TRUE; } | /* EMPTY */ {$$ = FALSE; } ; + /***************************************************************************** * * QUERY: - * cluster on + * cluster on * *****************************************************************************/ -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; } @@ -3286,11 +3345,11 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose 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; @@ -3298,7 +3357,7 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose n->full = $2; n->freeze = $3; n->verbose = $4; - n->vacrel = $5; + n->relation = $5; n->va_cols = NIL; $$ = (Node *)n; } @@ -3321,11 +3380,11 @@ AnalyzeStmt: analyze_keyword opt_verbose 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; @@ -3333,7 +3392,7 @@ AnalyzeStmt: analyze_keyword opt_verbose n->full = false; n->freeze = false; n->verbose = $2; - n->vacrel = $3; + n->relation = $3; n->va_cols = $4; $$ = (Node *)n; } @@ -3413,15 +3472,9 @@ OptimizableStmt: SelectStmt * *****************************************************************************/ -/* 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; } ; @@ -3447,14 +3500,14 @@ insert_rest: VALUES '(' target_list ')' $$->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; @@ -3463,22 +3516,19 @@ insert_rest: VALUES '(' target_list ')' } ; -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; } ; @@ -3493,18 +3543,17 @@ columnElem: ColId opt_indirection 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; } @@ -3538,8 +3587,7 @@ UpdateStmt: UPDATE relation_expr 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; @@ -3687,8 +3735,7 @@ simple_select: SELECT opt_distinct target_list 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; @@ -3710,40 +3757,56 @@ simple_select: SELECT opt_distinct target_list } ; - /* 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; } @@ -3878,13 +3941,6 @@ select_offset_value: Iconst * ...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; } @@ -3938,7 +3994,7 @@ table_ref: relation_expr } | relation_expr alias_clause { - $1->name = $2; + $1->alias = $2; $$ = (Node *) $1; } | select_with_parens @@ -3962,7 +4018,7 @@ table_ref: relation_expr { RangeSubselect *n = makeNode(RangeSubselect); n->subquery = $1; - n->name = $2; + n->alias = $2; $$ = (Node *) n; } | joined_table @@ -4077,25 +4133,25 @@ joined_table: '(' 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; } ; @@ -4124,29 +4180,26 @@ join_qual: USING '(' name_list ')' { $$ = (Node *) $3; } ; -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; } ; @@ -4357,6 +4410,7 @@ bit: BIT opt_varying else type = xlateSqlType("bit"); $$ = type; } + ; /* @@ -5010,20 +5064,32 @@ b_expr: c_expr * 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 - { - /* could be a column name or a relation_name */ - Ident *n = makeNode(Ident); - n->name = $1; - n->indirection = $2; - $$ = (Node *)n; - } | AexprConst { $$ = $1; } + | PARAM attrs opt_indirection + { + /* + * 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; + } | '(' 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 @@ -5569,34 +5635,40 @@ case_arg: a_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; } + ; /***************************************************************************** * @@ -5617,39 +5689,25 @@ target_el: a_expr AS ColLabel { $$ = 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; } ; @@ -5685,6 +5743,42 @@ relation_name: SpecialRuleRelation $$ = $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; }; @@ -5761,8 +5855,14 @@ AexprConst: Iconst $$ = (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); @@ -5791,14 +5891,6 @@ AexprConst: Iconst } ; -ParamNo: PARAM opt_indirection - { - $$ = makeNode(ParamNo); - $$->number = $1; - $$->indirection = $2; - } - ; - Iconst: ICONST { $$ = $1; }; Sconst: SCONST { $$ = $1; }; UserId: ColId { $$ = $1; }; @@ -5866,7 +5958,6 @@ unreserved_keyword: | AGGREGATE { $$ = "aggregate"; } | ALTER { $$ = "alter"; } | AT { $$ = "at"; } - | AUTHORIZATION { $$ = "authorization"; } | BACKWARD { $$ = "backward"; } | BEFORE { $$ = "before"; } | BEGIN_TRANS { $$ = "begin"; } @@ -5883,7 +5974,6 @@ unreserved_keyword: | COMMITTED { $$ = "committed"; } | CONSTRAINTS { $$ = "constraints"; } | COPY { $$ = "copy"; } - | CREATE { $$ = "create"; } | CREATEDB { $$ = "createdb"; } | CREATEUSER { $$ = "createuser"; } | CURSOR { $$ = "cursor"; } @@ -5909,7 +5999,6 @@ unreserved_keyword: | FORWARD { $$ = "forward"; } | FUNCTION { $$ = "function"; } | GLOBAL { $$ = "global"; } - | GRANT { $$ = "grant"; } | HANDLER { $$ = "handler"; } | HOUR_P { $$ = "hour"; } | IMMEDIATE { $$ = "immediate"; } @@ -6061,7 +6150,8 @@ col_name_keyword: * - thomas 2000-11-28 */ func_name_keyword: - BETWEEN { $$ = "between"; } + AUTHORIZATION { $$ = "authorization"; } + | BETWEEN { $$ = "between"; } | BINARY { $$ = "binary"; } | CROSS { $$ = "cross"; } | FREEZE { $$ = "freeze"; } @@ -6104,6 +6194,7 @@ reserved_keyword: | COLLATE { $$ = "collate"; } | COLUMN { $$ = "column"; } | CONSTRAINT { $$ = "constraint"; } + | CREATE { $$ = "create"; } | CURRENT_DATE { $$ = "current_date"; } | CURRENT_TIME { $$ = "current_time"; } | CURRENT_TIMESTAMP { $$ = "current_timestamp"; } @@ -6120,6 +6211,7 @@ reserved_keyword: | FOR { $$ = "for"; } | FOREIGN { $$ = "foreign"; } | FROM { $$ = "from"; } + | GRANT { $$ = "grant"; } | GROUP { $$ = "group"; } | HAVING { $$ = "having"; } | INITIALLY { $$ = "initially"; } @@ -6189,7 +6281,7 @@ static Node * 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. @@ -6200,12 +6292,6 @@ makeTypeCast(Node *arg, TypeName *typename) ((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); diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index d6ad0a07ea..dc939a7180 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.46 2001/10/25 05:49:36 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.47 2002/03/21 16:00:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -116,7 +116,7 @@ check_ungrouped_columns_walker(Node *node, rte = rt_fetch(var->varno, context->pstate->p_rtable); attname = get_rte_attribute_name(rte, var->varattno); elog(ERROR, "Attribute %s.%s must be GROUPed or used in an aggregate function", - rte->eref->relname, attname); + rte->eref->aliasname, attname); } /* Otherwise, recurse. */ return expression_tree_walker(node, check_ungrouped_columns_walker, @@ -188,8 +188,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry, Node *qual) Aggref * ParseAgg(ParseState *pstate, char *aggname, Oid basetype, - List *args, bool agg_star, bool agg_distinct, - int precedence) + List *args, bool agg_star, bool agg_distinct) { HeapTuple aggtuple; Form_pg_aggregate aggform; diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 2f1eda4a9b..6e8868f8ea 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.84 2002/03/12 00:51:54 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.85 2002/03/21 16:00:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -285,7 +285,7 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars) * transformJoinOnClause() does. Just invoke transformExpr() to fix * up the operators, and we're done. */ - result = transformExpr(pstate, result, EXPR_COLUMN_FIRST); + result = transformExpr(pstate, result); /* * We expect the result to yield bool directly, otherwise complain. We @@ -326,7 +326,7 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j, pstate->p_namespace = makeList2(j->larg, j->rarg); /* This part is just like transformWhereClause() */ - result = transformExpr(pstate, j->quals, EXPR_COLUMN_FIRST); + result = transformExpr(pstate, j->quals); if (!coerce_to_boolean(pstate, &result)) elog(ERROR, "JOIN/ON clause must return type boolean, not type %s", @@ -350,7 +350,7 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j, if (!intMember(varno, containedRels)) { elog(ERROR, "JOIN/ON clause refers to \"%s\", which is not part of JOIN", - rt_fetch(varno, pstate->p_rtable)->eref->relname); + rt_fetch(varno, pstate->p_rtable)->eref->aliasname); } } freeList(clause_varnos); @@ -375,7 +375,7 @@ transformTableEntry(ParseState *pstate, RangeVar *r) * automatically generate the range variable if not specified. However * there are times we need to know whether the entries are legitimate. */ - rte = addRangeTableEntry(pstate, relname, r->name, + rte = addRangeTableEntry(pstate, relname, r->alias, interpretInhOption(r->inhOpt), true); /* @@ -408,7 +408,7 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r) * relax this, we'd have to be prepared to gin up a unique alias for * an unlabeled subselect. */ - if (r->name == NULL) + if (r->alias == NULL) elog(ERROR, "sub-select in FROM must have an alias"); /* @@ -444,7 +444,7 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r) /* * OK, build an RTE for the subquery. */ - rte = addRangeTableEntryForSubquery(pstate, query, r->name, true); + rte = addRangeTableEntryForSubquery(pstate, query, r->alias, true); /* * We create a RangeTblRef, but we do not add it to the joinlist or @@ -748,11 +748,11 @@ transformFromClauseItem(ParseState *pstate, Node *n, List **containedRels) */ if (j->alias) { - if (j->alias->attrs != NIL) + if (j->alias->colnames != NIL) { - if (length(j->alias->attrs) > length(res_colnames)) + if (length(j->alias->colnames) > length(res_colnames)) elog(ERROR, "Column alias list for \"%s\" has too many entries", - j->alias->relname); + j->alias->aliasname); } } @@ -791,7 +791,7 @@ transformWhereClause(ParseState *pstate, Node *clause) if (clause == NULL) return NULL; - qual = transformExpr(pstate, clause, EXPR_COLUMN_FIRST); + qual = transformExpr(pstate, clause); if (!coerce_to_boolean(pstate, &qual)) elog(ERROR, "WHERE clause must return type boolean, not type %s", @@ -858,9 +858,11 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause) * an expression. *---------- */ - if (IsA(node, Ident) &&((Ident *) node)->indirection == NIL) + if (IsA(node, ColumnRef) && + length(((ColumnRef *) node)->fields) == 1 && + ((ColumnRef *) node)->indirection == NIL) { - char *name = ((Ident *) node)->name; + char *name = strVal(lfirst(((ColumnRef *) node)->fields)); if (clause == GROUP_CLAUSE) { @@ -934,7 +936,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause) * willing to match a resjunk target here, though the above cases must * ignore resjunk targets. */ - expr = transformExpr(pstate, node, EXPR_COLUMN_FIRST); + expr = transformExpr(pstate, node); foreach(tl, tlist) { diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 6409ef3226..73cd89fd3d 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.110 2002/03/20 19:44:25 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.111 2002/03/21 16:01:03 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,6 +17,7 @@ #include "catalog/pg_operator.h" #include "catalog/pg_proc.h" +#include "miscadmin.h" #include "nodes/makefuncs.h" #include "nodes/params.h" #include "parser/analyze.h" @@ -41,8 +42,7 @@ bool Transform_null_equals = false; static Node *parser_typecast_constant(Value *expr, TypeName *typename); static Node *parser_typecast_expression(ParseState *pstate, Node *expr, TypeName *typename); -static Node *transformAttr(ParseState *pstate, Attr *att, int precedence); -static Node *transformIdent(ParseState *pstate, Ident *ident, int precedence); +static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref); static Node *transformIndirection(ParseState *pstate, Node *basenode, List *indirection); @@ -85,7 +85,7 @@ parse_expr_init(void) * input and output of transformExpr; see SubLink for example. */ Node * -transformExpr(ParseState *pstate, Node *expr, int precedence) +transformExpr(ParseState *pstate, Node *expr) { Node *result = NULL; @@ -105,9 +105,37 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) switch (nodeTag(expr)) { - case T_Attr: + case T_ColumnRef: { - result = transformAttr(pstate, (Attr *) expr, precedence); + result = transformColumnRef(pstate, (ColumnRef *) expr); + break; + } + case T_ParamRef: + { + ParamRef *pref = (ParamRef *) expr; + int paramno = pref->number; + Oid paramtyp = param_type(paramno); + Param *param; + List *fields; + + if (!OidIsValid(paramtyp)) + elog(ERROR, "Parameter '$%d' is out of range", paramno); + param = makeNode(Param); + param->paramkind = PARAM_NUM; + param->paramid = (AttrNumber) paramno; + param->paramname = ""; + param->paramtype = paramtyp; + result = (Node *) param; + /* handle qualification, if any */ + foreach(fields, pref->fields) + { + result = ParseFuncOrColumn(pstate, strVal(lfirst(fields)), + makeList1(result), + false, false, true); + } + /* handle subscripts, if any */ + result = transformIndirection(pstate, result, + pref->indirection); break; } case T_A_Const: @@ -121,31 +149,28 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) result = (Node *) make_const(val); break; } - case T_ParamNo: + case T_ExprFieldSelect: { - ParamNo *pno = (ParamNo *) expr; - int paramno = pno->number; - Oid toid = param_type(paramno); - Param *param = makeNode(Param); + ExprFieldSelect *efs = (ExprFieldSelect *) expr; + List *fields; - if (!OidIsValid(toid)) - elog(ERROR, "Parameter '$%d' is out of range", paramno); - param->paramkind = PARAM_NUM; - param->paramid = (AttrNumber) paramno; - param->paramname = ""; - param->paramtype = toid; - result = transformIndirection(pstate, (Node *) param, - pno->indirection); - /* cope with typecast applied to param */ - if (pno->typename != NULL) - result = parser_typecast_expression(pstate, result, - pno->typename); + result = transformExpr(pstate, efs->arg); + /* handle qualification, if any */ + foreach(fields, efs->fields) + { + result = ParseFuncOrColumn(pstate, strVal(lfirst(fields)), + makeList1(result), + false, false, true); + } + /* handle subscripts, if any */ + result = transformIndirection(pstate, result, + efs->indirection); break; } case T_TypeCast: { TypeCast *tc = (TypeCast *) expr; - Node *arg = transformExpr(pstate, tc->arg, precedence); + Node *arg = transformExpr(pstate, tc->arg); result = parser_typecast_expression(pstate, arg, tc->typename); break; @@ -179,17 +204,14 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) n->arg = a->lexpr; result = transformExpr(pstate, - (Node *) n, - precedence); + (Node *) n); } else { Node *lexpr = transformExpr(pstate, - a->lexpr, - precedence); + a->lexpr); Node *rexpr = transformExpr(pstate, - a->rexpr, - precedence); + a->rexpr); result = (Node *) make_op(a->opname, lexpr, @@ -200,11 +222,9 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) case AND: { Node *lexpr = transformExpr(pstate, - a->lexpr, - precedence); + a->lexpr); Node *rexpr = transformExpr(pstate, - a->rexpr, - precedence); + a->rexpr); Expr *expr = makeNode(Expr); if (!coerce_to_boolean(pstate, &lexpr)) @@ -226,11 +246,9 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) case OR: { Node *lexpr = transformExpr(pstate, - a->lexpr, - precedence); + a->lexpr); Node *rexpr = transformExpr(pstate, - a->rexpr, - precedence); + a->rexpr); Expr *expr = makeNode(Expr); if (!coerce_to_boolean(pstate, &lexpr)) @@ -252,8 +270,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) case NOT: { Node *rexpr = transformExpr(pstate, - a->rexpr, - precedence); + a->rexpr); Expr *expr = makeNode(Expr); if (!coerce_to_boolean(pstate, &rexpr)) @@ -270,11 +287,6 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) } break; } - case T_Ident: - { - result = transformIdent(pstate, (Ident *) expr, precedence); - break; - } case T_FuncCall: { FuncCall *fn = (FuncCall *) expr; @@ -283,14 +295,13 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) /* transform the list of arguments */ foreach(args, fn->args) lfirst(args) = transformExpr(pstate, - (Node *) lfirst(args), - precedence); + (Node *) lfirst(args)); result = ParseFuncOrColumn(pstate, fn->funcname, fn->args, fn->agg_star, fn->agg_distinct, - precedence); + false); break; } case T_SubLink: @@ -357,8 +368,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) List *elist; foreach(elist, left_list) - lfirst(elist) = transformExpr(pstate, lfirst(elist), - precedence); + lfirst(elist) = transformExpr(pstate, lfirst(elist)); Assert(IsA(sublink->oper, A_Expr)); op = ((A_Expr *) sublink->oper)->opname; @@ -455,7 +465,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) a->rexpr = warg; warg = (Node *) a; } - neww->expr = transformExpr(pstate, warg, precedence); + neww->expr = transformExpr(pstate, warg); if (!coerce_to_boolean(pstate, &neww->expr)) elog(ERROR, "WHEN clause must have a boolean result"); @@ -472,7 +482,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) n->val.type = T_Null; warg = (Node *) n; } - neww->result = transformExpr(pstate, warg, precedence); + neww->result = transformExpr(pstate, warg); newargs = lappend(newargs, neww); typeids = lappendi(typeids, exprType(neww->result)); @@ -496,7 +506,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) n->val.type = T_Null; defresult = (Node *) n; } - newc->defresult = transformExpr(pstate, defresult, precedence); + newc->defresult = transformExpr(pstate, defresult); /* * Note: default result is considered the most significant @@ -534,7 +544,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) { NullTest *n = (NullTest *) expr; - n->arg = transformExpr(pstate, n->arg, precedence); + n->arg = transformExpr(pstate, n->arg); /* the argument can be any type, so don't coerce it */ result = expr; break; @@ -544,7 +554,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) { BooleanTest *b = (BooleanTest *) expr; - b->arg = transformExpr(pstate, b->arg, precedence); + b->arg = transformExpr(pstate, b->arg); if (!coerce_to_boolean(pstate, &b->arg)) { @@ -627,47 +637,183 @@ transformIndirection(ParseState *pstate, Node *basenode, List *indirection) } static Node * -transformAttr(ParseState *pstate, Attr *att, int precedence) +transformColumnRef(ParseState *pstate, ColumnRef *cref) { - Node *basenode; + int numnames = length(cref->fields); + Node *node; + RangeVar *rv; - basenode = ParseNestedFuncOrColumn(pstate, att, precedence); - return transformIndirection(pstate, basenode, att->indirection); -} - -static Node * -transformIdent(ParseState *pstate, Ident *ident, int precedence) -{ - Node *result = NULL; - int sublevels_up; - - /* - * try to find the ident as a relation ... but not if subscripts - * appear + /*---------- + * The allowed syntaxes are: + * + * A First try to resolve as unqualified column name; + * if no luck, try to resolve as unqual. table name (A.*). + * A.B A is an unqual. table name; B is either a + * column or function name (trying column name first). + * A.B.C schema A, table B, col or func name C. + * A.B.C.D catalog A, schema B, table C, col or func D. + * A.* A is an unqual. table name; means whole-row value. + * A.B.* whole-row value of table B in schema A. + * A.B.C.* whole-row value of table C in schema B in catalog A. + * + * We do not need to cope with bare "*"; that will only be accepted by + * the grammar at the top level of a SELECT list, and transformTargetList + * will take care of it before it ever gets here. + * + * Currently, if a catalog name is given then it must equal the current + * database name; we check it here and then discard it. + * + * For whole-row references, the result is an untransformed RangeVar, + * which will work as the argument to a function call, but not in any + * other context at present. (We could instead coerce to a whole-row Var, + * but that will fail for subselect and join RTEs, because there is no + * pg_type entry for their rowtypes.) + *---------- */ - if (ident->indirection == NIL && - refnameRangeTblEntry(pstate, ident->name, &sublevels_up) != NULL) + switch (numnames) { - ident->isRel = TRUE; - result = (Node *) ident; - } - - if (result == NULL || precedence == EXPR_COLUMN_FIRST) - { - /* try to find the ident as a column */ - Node *var = colnameToVar(pstate, ident->name); - - if (var != NULL) + case 1: { - ident->isRel = FALSE; - result = transformIndirection(pstate, var, ident->indirection); + char *name = strVal(lfirst(cref->fields)); + + /* Try to identify as an unqualified column */ + node = colnameToVar(pstate, name); + if (node == NULL) + { + /* + * Not known as a column of any range-table entry, so + * try to find the name as a relation ... but not if + * subscripts appear. Note also that only relations + * already entered into the rangetable will be recognized. + */ + int levels_up; + + if (cref->indirection == NIL && + refnameRangeTblEntry(pstate, name, &levels_up) != NULL) + { + rv = makeNode(RangeVar); + rv->relname = name; + rv->inhOpt = INH_DEFAULT; + node = (Node *) rv; + } + else + elog(ERROR, "Attribute \"%s\" not found", name); + } + break; } + case 2: + { + char *name1 = strVal(lfirst(cref->fields)); + char *name2 = strVal(lsecond(cref->fields)); + + /* Whole-row reference? */ + if (strcmp(name2, "*") == 0) + { + rv = makeNode(RangeVar); + rv->relname = name1; + rv->inhOpt = INH_DEFAULT; + node = (Node *) rv; + break; + } + + /* Try to identify as a once-qualified column */ + node = qualifiedNameToVar(pstate, name1, name2, true); + if (node == NULL) + { + /* + * Not known as a column of any range-table entry, so + * try it as a function call. Here, we will create an + * implicit RTE for tables not already entered. + */ + rv = makeNode(RangeVar); + rv->relname = name1; + rv->inhOpt = INH_DEFAULT; + node = ParseFuncOrColumn(pstate, name2, + makeList1(rv), + false, false, true); + } + break; + } + case 3: + { + char *name1 = strVal(lfirst(cref->fields)); + char *name2 = strVal(lsecond(cref->fields)); + char *name3 = strVal(lfirst(lnext(lnext(cref->fields)))); + + /* Whole-row reference? */ + if (strcmp(name3, "*") == 0) + { + rv = makeNode(RangeVar); + rv->schemaname = name1; + rv->relname = name2; + rv->inhOpt = INH_DEFAULT; + node = (Node *) rv; + break; + } + + /* Try to identify as a twice-qualified column */ + /* XXX do something with schema name here */ + node = qualifiedNameToVar(pstate, name2, name3, true); + if (node == NULL) + { + /* Try it as a function call */ + rv = makeNode(RangeVar); + rv->schemaname = name1; + rv->relname = name2; + rv->inhOpt = INH_DEFAULT; + node = ParseFuncOrColumn(pstate, name3, + makeList1(rv), + false, false, true); + } + break; + } + case 4: + { + char *name1 = strVal(lfirst(cref->fields)); + char *name2 = strVal(lsecond(cref->fields)); + char *name3 = strVal(lfirst(lnext(lnext(cref->fields)))); + char *name4 = strVal(lfirst(lnext(lnext(lnext(cref->fields))))); + + /* + * We check the catalog name and then ignore it. + */ + if (strcmp(name1, DatabaseName) != 0) + elog(ERROR, "Cross-database references are not implemented"); + + /* Whole-row reference? */ + if (strcmp(name4, "*") == 0) + { + rv = makeNode(RangeVar); + rv->schemaname = name2; + rv->relname = name3; + rv->inhOpt = INH_DEFAULT; + node = (Node *) rv; + break; + } + + /* Try to identify as a twice-qualified column */ + /* XXX do something with schema name here */ + node = qualifiedNameToVar(pstate, name3, name4, true); + if (node == NULL) + { + /* Try it as a function call */ + rv = makeNode(RangeVar); + rv->schemaname = name2; + rv->relname = name3; + rv->inhOpt = INH_DEFAULT; + node = ParseFuncOrColumn(pstate, name4, + makeList1(rv), + false, false, true); + } + break; + } + default: + elog(ERROR, "Invalid qualified name syntax (too many names)"); + node = NULL; /* keep compiler quiet */ + break; } - if (result == NULL) - elog(ERROR, "Attribute '%s' not found", ident->name); - - return result; + return transformIndirection(pstate, node, cref->indirection); } /* @@ -748,10 +894,6 @@ exprType(Node *expr) case T_BooleanTest: type = BOOLOID; break; - case T_Ident: - /* XXX is this right? */ - type = UNKNOWNOID; - break; default: elog(ERROR, "Do not know how to get type for %d node", nodeTag(expr)); diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 6dc7b440fa..ee1bf6c057 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -8,11 +8,10 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.118 2002/03/20 19:44:29 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.119 2002/03/21 16:01:06 tgl Exp $ * *------------------------------------------------------------------------- */ - #include "postgres.h" #include "access/genam.h" @@ -36,8 +35,7 @@ static Node *ParseComplexProjection(ParseState *pstate, char *funcname, - Node *first_arg, - bool *attisset); + Node *first_arg); static Oid **argtype_inherit(int nargs, Oid *argtypes); static int find_inheritors(Oid relid, Oid **supervec); @@ -60,75 +58,31 @@ static Oid agg_select_candidate(Oid typeid, CandidateList candidates); /* - ** ParseNestedFuncOrColumn - ** Given a nested dot expression (i.e. (relation func ... attr), build up - ** a tree with of Iter and Func nodes. - */ -Node * -ParseNestedFuncOrColumn(ParseState *pstate, Attr *attr, int precedence) -{ - List *mutator_iter; - Node *retval = NULL; - - if (attr->paramNo != NULL) - { - Param *param = (Param *) transformExpr(pstate, - (Node *) attr->paramNo, - EXPR_RELATION_FIRST); - - retval = ParseFuncOrColumn(pstate, strVal(lfirst(attr->attrs)), - makeList1(param), - false, false, - precedence); - } - else - { - Ident *ident = makeNode(Ident); - - ident->name = attr->relname; - ident->isRel = TRUE; - retval = ParseFuncOrColumn(pstate, strVal(lfirst(attr->attrs)), - makeList1(ident), - false, false, - precedence); - } - - /* Do more attributes follow this one? */ - foreach(mutator_iter, lnext(attr->attrs)) - { - retval = ParseFuncOrColumn(pstate, strVal(lfirst(mutator_iter)), - makeList1(retval), - false, false, - precedence); - } - - return retval; -} - -/* - * parse function + * Parse a function call * - * This code is confusing because the database can accept - * relation.column, column.function, or relation.column.function. - * In these cases, funcname is the last parameter, and fargs are - * the rest. + * For historical reasons, Postgres tries to treat the notations tab.col + * and col(tab) as equivalent: if a single-argument function call has an + * argument of complex type and the function name matches any attribute + * of the type, we take it as a column projection. * - * It can also be called as func(col) or func(col,col). - * In this case, Funcname is the part before parens, and fargs - * are the part in parens. - * - * FYI, projection is choosing column from a table. + * Hence, both cases come through here. The is_column parameter tells us + * which syntactic construct is actually being dealt with, but this is + * intended to be used only to deliver an appropriate error message, + * not to affect the semantics. When is_column is true, we should have + * a single argument (the putative table), function name equal to the + * column name, and no aggregate decoration. * + * In the function-call case, the argument expressions have been transformed + * already. In the column case, we may get either a transformed expression + * or a RangeVar node as argument. */ Node * ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, - bool agg_star, bool agg_distinct, - int precedence) + bool agg_star, bool agg_distinct, bool is_column) { - Oid rettype = InvalidOid; - Oid argrelid = InvalidOid; - Oid funcid = InvalidOid; - List *i = NIL; + Oid rettype; + Oid funcid; + List *i; Node *first_arg = NULL; char *refname; int nargs = length(fargs); @@ -140,9 +94,8 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, bool retset; bool must_be_agg = agg_star || agg_distinct; bool could_be_agg; - bool attisset = false; - Oid toid = InvalidOid; Expr *expr; + FuncDetailCode fdresult; /* * Most of the rest of the parser just assumes that functions do not @@ -157,33 +110,26 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, if (fargs) { first_arg = lfirst(fargs); - if (first_arg == NULL) + if (first_arg == NULL) /* should not happen */ elog(ERROR, "Function '%s' does not allow NULL input", funcname); } /* - * test for relation.column - * - * check for projection methods: if function takes one argument, and that - * argument is a relation, param, or PQ function returning a complex * - * type, then the function could be a projection. + * check for column projection: if function has one argument, and that + * argument is of complex type, then the function could be a projection. */ /* We only have one parameter, and it's not got aggregate decoration */ if (nargs == 1 && !must_be_agg) { - /* Is it a plain Relation name from the parser? */ - if (IsA(first_arg, Ident) &&((Ident *) first_arg)->isRel) + /* Is it a not-yet-transformed RangeVar node? */ + if (IsA(first_arg, RangeVar)) { - Ident *ident = (Ident *) first_arg; - /* First arg is a relation. This could be a projection. */ - refname = ident->name; + refname = ((RangeVar *) first_arg)->relname; retval = qualifiedNameToVar(pstate, refname, funcname, true); if (retval) return retval; - - /* else drop through - attr is a set or function */ } else if (ISCOMPLEX(exprType(first_arg))) { @@ -194,24 +140,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, */ retval = ParseComplexProjection(pstate, funcname, - first_arg, - &attisset); - if (attisset) - { - toid = exprType(first_arg); - argrelid = typeidTypeRelid(toid); - if (argrelid == InvalidOid) - elog(ERROR, "Type '%s' is not a relation type", - typeidTypeName(toid)); - - /* - * A projection must match an attribute name of the rel. - */ - if (get_attnum(argrelid, funcname) == InvalidAttrNumber) - elog(ERROR, "No such attribute or function '%s'", - funcname); - } - + first_arg); if (retval) return retval; } @@ -226,15 +155,14 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, if (nargs != 1) elog(ERROR, "Aggregate functions may only have one parameter"); /* Agg's argument can't be a relation name, either */ - if (IsA(first_arg, Ident) &&((Ident *) first_arg)->isRel) + if (IsA(first_arg, RangeVar)) elog(ERROR, "Aggregate functions cannot be applied to relation names"); could_be_agg = true; } else { /* Try to parse as an aggregate if above-mentioned checks are OK */ - could_be_agg = (nargs == 1) && - !(IsA(first_arg, Ident) &&((Ident *) first_arg)->isRel); + could_be_agg = (nargs == 1) && !(IsA(first_arg, RangeVar)); } if (could_be_agg) @@ -249,8 +177,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, ObjectIdGetDatum(basetype), 0, 0)) return (Node *) ParseAgg(pstate, funcname, basetype, - fargs, agg_star, agg_distinct, - precedence); + fargs, agg_star, agg_distinct); /* check for aggregate-that-accepts-any-type (eg, COUNT) */ if (SearchSysCacheExists(AGGNAME, @@ -258,8 +185,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, ObjectIdGetDatum(0), 0, 0)) return (Node *) ParseAgg(pstate, funcname, 0, - fargs, agg_star, agg_distinct, - precedence); + fargs, agg_star, agg_distinct); /* * No exact match yet, so see if there is another entry in the @@ -277,8 +203,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, basetype, type, -1); basetype = type; return (Node *) ParseAgg(pstate, funcname, basetype, - fargs, agg_star, agg_distinct, - precedence); + fargs, agg_star, agg_distinct); } else { @@ -300,10 +225,9 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, } /* - * If we dropped through to here it's really a function (or a set, - * which is implemented as a function). Extract arg type info and - * transform relation name arguments into varnodes of the appropriate - * form. + * Okay, it's not a column projection, so it must really be a function. + * Extract arg type info and transform RangeVar arguments into varnodes + * of the appropriate form. */ MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid)); @@ -311,8 +235,9 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, foreach(i, fargs) { Node *arg = lfirst(i); + Oid toid; - if (IsA(arg, Ident) &&((Ident *) arg)->isRel) + if (IsA(arg, RangeVar)) { RangeTblEntry *rte; int vnum; @@ -321,7 +246,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, /* * a relation */ - refname = ((Ident *) arg)->name; + refname = ((RangeVar *) arg)->relname; rte = refnameRangeTblEntry(pstate, refname, &sublevels_up); @@ -346,16 +271,9 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, * RTE is a join or subselect; must fail for lack of a * named tuple type */ - if (nargs == 1) - { - /* - * Here, we probably have an unrecognized attribute of - * a sub-select; again can't tell if it was x.f or - * f(x) - */ - elog(ERROR, "No such attribute or function %s.%s", + if (is_column) + elog(ERROR, "No such attribute %s.%s", refname, funcname); - } else { elog(ERROR, "Cannot pass result of sub-select or join %s to a function", @@ -365,93 +283,53 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, toid = typenameTypeId(rte->relname); - /* replace it in the arg list */ + /* replace RangeVar in the arg list */ lfirst(i) = makeVar(vnum, InvalidAttrNumber, toid, sizeof(Pointer), sublevels_up); } - else if (!attisset) - toid = exprType(arg); else - { - /* if attisset is true, we already set toid for the single arg */ - } + toid = exprType(arg); oid_array[argn++] = toid; } /* - * Is it a set, or a function? + * func_get_detail looks up the function in the catalogs, does + * disambiguation for polymorphic functions, handles inheritance, + * and returns the funcid and type and set or singleton status of + * the function's return value. it also returns the true argument + * types to the function. */ - if (attisset) - { /* we know all of these fields already */ - - /* - * We create a funcnode with a placeholder function seteval(). At - * runtime, seteval() will execute the function identified by the - * funcid it receives as parameter. - * - * Example: retrieve (emp.mgr.name). The plan for this will scan the - * emp relation, projecting out the mgr attribute, which is a - * funcid. This function is then called (via seteval()) and "name" - * is projected from its result. - */ - funcid = F_SETEVAL; - rettype = toid; - retset = true; - true_oid_array = oid_array; - } - else + fdresult = func_get_detail(funcname, fargs, nargs, oid_array, + &funcid, &rettype, &retset, + &true_oid_array); + if (fdresult == FUNCDETAIL_COERCION) { - FuncDetailCode fdresult; - /* - * func_get_detail looks up the function in the catalogs, does - * disambiguation for polymorphic functions, handles inheritance, - * and returns the funcid and type and set or singleton status of - * the function's return value. it also returns the true argument - * types to the function. + * We can do it as a trivial coercion. coerce_type can handle + * these cases, so why duplicate code... */ - fdresult = func_get_detail(funcname, fargs, nargs, oid_array, - &funcid, &rettype, &retset, - &true_oid_array); - if (fdresult == FUNCDETAIL_COERCION) - { - /* - * We can do it as a trivial coercion. coerce_type can handle - * these cases, so why duplicate code... - */ - return coerce_type(pstate, lfirst(fargs), - oid_array[0], rettype, -1); - } - if (fdresult != FUNCDETAIL_NORMAL) - { - /* - * Oops. Time to die. - * - * If there is a single argument of complex type, we might be - * dealing with the PostQuel notation rel.function instead of - * the more usual function(rel). Give a nonspecific error - * message that will cover both cases. - */ - if (nargs == 1) - { - Type tp = typeidType(oid_array[0]); - - if (typeTypeFlag(tp) == 'c') - elog(ERROR, "No such attribute or function '%s'", - funcname); - ReleaseSysCache(tp); - } - - /* Else generate a detailed complaint */ - func_error(NULL, funcname, nargs, oid_array, - "Unable to identify a function that satisfies the " - "given argument types" - "\n\tYou may need to add explicit typecasts"); - } + return coerce_type(pstate, lfirst(fargs), + oid_array[0], rettype, -1); + } + if (fdresult != FUNCDETAIL_NORMAL) + { + /* + * Oops. Time to die. + * + * If we are dealing with the attribute notation rel.function, + * give an error message that is appropriate for that case. + */ + if (is_column) + elog(ERROR, "Attribute \"%s\" not found", funcname); + /* Else generate a detailed complaint */ + func_error(NULL, funcname, nargs, oid_array, + "Unable to identify a function that satisfies the " + "given argument types" + "\n\tYou may need to add explicit typecasts"); } /* got it */ @@ -470,26 +348,12 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, expr->args = fargs; retval = (Node *) expr; - /* - * For sets, we want to project out the desired attribute of the - * tuples. - */ - if (attisset) - { - FieldSelect *fselect; - - fselect = setup_field_select(retval, funcname, argrelid); - rettype = fselect->resulttype; - retval = (Node *) fselect; - } - /* * if the function returns a set of values, then we need to iterate * over all the returned values in the executor, so we stick an iter * node here. if it returns a singleton, then we don't need the iter * node. */ - if (retset) { Iter *iter = makeNode(Iter); @@ -1497,10 +1361,10 @@ make_arguments(ParseState *pstate, } /* - ** setup_field_select - ** Build a FieldSelect node that says which attribute to project to. - ** This routine is called by ParseFuncOrColumn() when we have found - ** a projection on a function result or parameter. + * setup_field_select + * Build a FieldSelect node that says which attribute to project to. + * This routine is called by ParseFuncOrColumn() when we have found + * a projection on a function result or parameter. */ static FieldSelect * setup_field_select(Node *input, char *attname, Oid relid) @@ -1521,18 +1385,31 @@ setup_field_select(Node *input, char *attname, Oid relid) /* * ParseComplexProjection - * handles function calls with a single argument that is of complex type. - * This routine returns NULL if it can't handle the projection (eg. sets). + * If the function call is actually a column projection, return a suitably + * transformed expression tree. If not, return NULL. + * + * NB: argument is expected to be transformed already, ie, not a RangeVar. */ static Node * ParseComplexProjection(ParseState *pstate, char *funcname, - Node *first_arg, - bool *attisset) + Node *first_arg) { - Oid argtype; + Oid argtype = exprType(first_arg); Oid argrelid; + AttrNumber attnum; FieldSelect *fselect; + argrelid = typeidTypeRelid(argtype); + if (!argrelid) + return NULL; /* probably should not happen */ + attnum = get_attnum(argrelid, funcname); + if (attnum == InvalidAttrNumber) + return NULL; /* funcname does not match any column */ + + /* + * Check for special cases where we don't want to return a FieldSelect. + */ switch (nodeTag(first_arg)) { case T_Iter: @@ -1540,75 +1417,42 @@ ParseComplexProjection(ParseState *pstate, Iter *iter = (Iter *) first_arg; /* - * If the argument of the Iter returns a tuple, funcname - * may be a projection. If so, we stick the FieldSelect + * If it's an Iter, we stick the FieldSelect * *inside* the Iter --- this is klugy, but necessary * because ExecTargetList() currently does the right thing * only when the Iter node is at the top level of a * targetlist item. + * + * XXX Iter should go away altogether... */ - argtype = iter->itertype; - argrelid = typeidTypeRelid(argtype); - if (argrelid && - get_attnum(argrelid, funcname) != InvalidAttrNumber) - { - fselect = setup_field_select(iter->iterexpr, - funcname, argrelid); - iter->iterexpr = (Node *) fselect; - iter->itertype = fselect->resulttype; - return (Node *) iter; - } + fselect = setup_field_select(iter->iterexpr, + funcname, argrelid); + iter->iterexpr = (Node *) fselect; + iter->itertype = fselect->resulttype; + return (Node *) iter; break; } case T_Var: { - /* - * The argument is a set, so this is either a projection - * or a function call on this set. - */ - *attisset = true; - break; - } - case T_Expr: - { - Expr *expr = (Expr *) first_arg; - Func *funcnode; - - if (expr->opType != FUNC_EXPR) - break; + Var *var = (Var *) first_arg; /* - * If the argument is a function returning a tuple, - * funcname may be a projection + * If the Var is a whole-row tuple, we can just replace it + * with a simple Var reference. */ - funcnode = (Func *) expr->oper; - argtype = funcnode->functype; - argrelid = typeidTypeRelid(argtype); - if (argrelid && - get_attnum(argrelid, funcname) != InvalidAttrNumber) + if (var->varattno == InvalidAttrNumber) { - fselect = setup_field_select((Node *) expr, - funcname, argrelid); - return (Node *) fselect; - } - break; - } - case T_Param: - { - Param *param = (Param *) first_arg; + Oid vartype; + int32 vartypmod; - /* - * If the Param is a complex type, this could be a - * projection - */ - argtype = param->paramtype; - argrelid = typeidTypeRelid(argtype); - if (argrelid && - get_attnum(argrelid, funcname) != InvalidAttrNumber) - { - fselect = setup_field_select((Node *) param, - funcname, argrelid); - return (Node *) fselect; + get_atttypetypmod(argrelid, attnum, + &vartype, &vartypmod); + + return (Node *) makeVar(var->varno, + attnum, + vartype, + vartypmod, + var->varlevelsup); } break; } @@ -1616,7 +1460,9 @@ ParseComplexProjection(ParseState *pstate, break; } - return NULL; + /* Else generate a FieldSelect expression */ + fselect = setup_field_select(first_arg, funcname, argrelid); + return (Node *) fselect; } /* diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c index be825c26f9..8b259e97c1 100644 --- a/src/backend/parser/parse_node.c +++ b/src/backend/parser/parse_node.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.59 2002/03/12 00:51:55 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.60 2002/03/21 16:01:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -285,7 +285,7 @@ transformArraySubscripts(ParseState *pstate, { if (ai->lidx) { - subexpr = transformExpr(pstate, ai->lidx, EXPR_COLUMN_FIRST); + subexpr = transformExpr(pstate, ai->lidx); /* If it's not int4 already, try to coerce */ subexpr = CoerceTargetExpr(pstate, subexpr, exprType(subexpr), INT4OID, -1); @@ -305,7 +305,7 @@ transformArraySubscripts(ParseState *pstate, } lowerIndexpr = lappend(lowerIndexpr, subexpr); } - subexpr = transformExpr(pstate, ai->uidx, EXPR_COLUMN_FIRST); + subexpr = transformExpr(pstate, ai->uidx); /* If it's not int4 already, try to coerce */ subexpr = CoerceTargetExpr(pstate, subexpr, exprType(subexpr), INT4OID, -1); diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index 1609c89ce0..5cf868a4d1 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.63 2002/03/12 00:51:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.64 2002/03/21 16:01:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -104,7 +104,7 @@ scanNameSpaceForRefname(ParseState *pstate, Node *nsnode, int varno = ((RangeTblRef *) nsnode)->rtindex; RangeTblEntry *rte = rt_fetch(varno, pstate->p_rtable); - if (strcmp(rte->eref->relname, refname) == 0) + if (strcmp(rte->eref->aliasname, refname) == 0) result = (Node *) rte; } else if (IsA(nsnode, JoinExpr)) @@ -113,7 +113,7 @@ scanNameSpaceForRefname(ParseState *pstate, Node *nsnode, if (j->alias) { - if (strcmp(j->alias->relname, refname) == 0) + if (strcmp(j->alias->aliasname, refname) == 0) return (Node *) j; /* matched a join alias */ /* @@ -175,7 +175,7 @@ checkNameSpaceConflicts(ParseState *pstate, Node *namespace1, int varno = ((RangeTblRef *) namespace1)->rtindex; RangeTblEntry *rte = rt_fetch(varno, pstate->p_rtable); - scanNameSpaceForConflict(pstate, namespace2, rte->eref->relname); + scanNameSpaceForConflict(pstate, namespace2, rte->eref->aliasname); } else if (IsA(namespace1, JoinExpr)) { @@ -183,7 +183,7 @@ checkNameSpaceConflicts(ParseState *pstate, Node *namespace1, if (j->alias) { - scanNameSpaceForConflict(pstate, namespace2, j->alias->relname); + scanNameSpaceForConflict(pstate, namespace2, j->alias->aliasname); /* * Tables within an aliased join are invisible from outside @@ -268,7 +268,7 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname) * Scan the user column names (or aliases) for a match. Complain if * multiple matches. */ - foreach(c, rte->eref->attrs) + foreach(c, rte->eref->colnames) { attnum++; if (strcmp(strVal(lfirst(c)), colname) == 0) @@ -420,15 +420,15 @@ qualifiedNameToVar(ParseState *pstate, char *refname, char *colname, RangeTblEntry * addRangeTableEntry(ParseState *pstate, char *relname, - Attr *alias, + Alias *alias, bool inh, bool inFromCl) { RangeTblEntry *rte = makeNode(RangeTblEntry); - char *refname = alias ? alias->relname : relname; + char *refname = alias ? alias->aliasname : relname; LOCKMODE lockmode; Relation rel; - Attr *eref; + Alias *eref; int maxattrs; int numaliases; int varattno; @@ -447,8 +447,8 @@ addRangeTableEntry(ParseState *pstate, rel = heap_openr(relname, lockmode); rte->relid = RelationGetRelid(rel); - eref = alias ? (Attr *) copyObject(alias) : makeAttr(refname, NULL); - numaliases = length(eref->attrs); + eref = alias ? (Alias *) copyObject(alias) : makeAlias(refname, NIL); + numaliases = length(eref->colnames); /* * Since the rel is open anyway, let's check that the number of column @@ -459,13 +459,13 @@ addRangeTableEntry(ParseState *pstate, elog(ERROR, "Table \"%s\" has %d columns available but %d columns specified", refname, maxattrs, numaliases); - /* fill in any unspecified alias columns */ + /* fill in any unspecified alias columns using actual column names */ for (varattno = numaliases; varattno < maxattrs; varattno++) { char *attrname; attrname = pstrdup(NameStr(rel->rd_att->attrs[varattno]->attname)); - eref->attrs = lappend(eref->attrs, makeString(attrname)); + eref->colnames = lappend(eref->colnames, makeString(attrname)); } rte->eref = eref; @@ -512,12 +512,12 @@ addRangeTableEntry(ParseState *pstate, RangeTblEntry * addRangeTableEntryForSubquery(ParseState *pstate, Query *subquery, - Attr *alias, + Alias *alias, bool inFromCl) { RangeTblEntry *rte = makeNode(RangeTblEntry); - char *refname = alias->relname; - Attr *eref; + char *refname = alias->aliasname; + Alias *eref; int numaliases; int varattno; List *tlistitem; @@ -529,7 +529,7 @@ addRangeTableEntryForSubquery(ParseState *pstate, rte->alias = alias; eref = copyObject(alias); - numaliases = length(eref->attrs); + numaliases = length(eref->colnames); /* fill in any unspecified alias columns */ varattno = 0; @@ -546,7 +546,7 @@ addRangeTableEntryForSubquery(ParseState *pstate, char *attrname; attrname = pstrdup(te->resdom->resname); - eref->attrs = lappend(eref->attrs, makeString(attrname)); + eref->colnames = lappend(eref->colnames, makeString(attrname)); } } if (varattno < numaliases) @@ -594,11 +594,11 @@ addRangeTableEntryForJoin(ParseState *pstate, List *coltypmods, List *leftcols, List *rightcols, - Attr *alias, + Alias *alias, bool inFromCl) { RangeTblEntry *rte = makeNode(RangeTblEntry); - Attr *eref; + Alias *eref; int numaliases; rte->rtekind = RTE_JOIN; @@ -612,15 +612,15 @@ addRangeTableEntryForJoin(ParseState *pstate, rte->joinrightcols = rightcols; rte->alias = alias; - eref = alias ? (Attr *) copyObject(alias) : makeAttr("unnamed_join", NULL); - numaliases = length(eref->attrs); + eref = alias ? (Alias *) copyObject(alias) : makeAlias("unnamed_join", NIL); + numaliases = length(eref->colnames); /* fill in any unspecified alias columns */ if (numaliases < length(colnames)) { while (numaliases-- > 0) colnames = lnext(colnames); - eref->attrs = nconc(eref->attrs, colnames); + eref->colnames = nconc(eref->colnames, colnames); } rte->eref = eref; @@ -759,7 +759,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte, rel = heap_openr(rte->relname, AccessShareLock); maxattrs = RelationGetNumberOfAttributes(rel); - numaliases = length(rte->eref->attrs); + numaliases = length(rte->eref->colnames); for (varattno = 0; varattno < maxattrs; varattno++) { @@ -775,7 +775,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte, char *label; if (varattno < numaliases) - label = strVal(nth(varattno, rte->eref->attrs)); + label = strVal(nth(varattno, rte->eref->colnames)); else label = NameStr(attr->attname); *colnames = lappend(*colnames, makeString(pstrdup(label))); @@ -798,7 +798,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte, else if (rte->rtekind == RTE_SUBQUERY) { /* Subquery RTE */ - List *aliasp = rte->eref->attrs; + List *aliasp = rte->eref->colnames; List *tlistitem; varattno = 0; @@ -836,7 +836,7 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte, else if (rte->rtekind == RTE_JOIN) { /* Join RTE */ - List *aliasp = rte->eref->attrs; + List *aliasp = rte->eref->colnames; List *coltypes = rte->joincoltypes; List *coltypmods = rte->joincoltypmods; @@ -936,8 +936,8 @@ get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum) * If there is an alias, use it. (This path should always be taken * for non-relation RTEs.) */ - if (attnum > 0 && attnum <= length(rte->eref->attrs)) - return strVal(nth(attnum - 1, rte->eref->attrs)); + if (attnum > 0 && attnum <= length(rte->eref->colnames)) + return strVal(nth(attnum - 1, rte->eref->colnames)); /* * Can get here for a system attribute (which never has an alias), or @@ -946,7 +946,7 @@ get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum) */ if (rte->rtekind != RTE_RELATION) elog(ERROR, "Invalid attnum %d for rangetable entry %s", - attnum, rte->eref->relname); + attnum, rte->eref->aliasname); /* * Use the real name of the table's column @@ -1002,7 +1002,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum, } /* falling off end of list shouldn't happen... */ elog(ERROR, "Subquery %s does not have attribute %d", - rte->eref->relname, attnum); + rte->eref->aliasname, attnum); } else if (rte->rtekind == RTE_JOIN) { diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index f5791298f3..a4b7816517 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -8,13 +8,13 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.77 2002/03/12 00:51:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.78 2002/03/21 16:01:10 tgl Exp $ * *------------------------------------------------------------------------- */ - #include "postgres.h" +#include "miscadmin.h" #include "nodes/makefuncs.h" #include "parser/parsetree.h" #include "parser/parse_coerce.h" @@ -56,9 +56,9 @@ transformTargetEntry(ParseState *pstate, /* Transform the node if caller didn't do it already */ if (expr == NULL) - expr = transformExpr(pstate, node, EXPR_COLUMN_FIRST); + expr = transformExpr(pstate, node); - if (IsA(expr, Ident) &&((Ident *) expr)->isRel) + if (IsA(expr, RangeVar)) elog(ERROR, "You can't use relation names alone in the target list, try relation.*."); type_id = exprType(expr); @@ -99,11 +99,13 @@ transformTargetList(ParseState *pstate, List *targetlist) { ResTarget *res = (ResTarget *) lfirst(targetlist); - if (IsA(res->val, Attr)) + if (IsA(res->val, ColumnRef)) { - Attr *att = (Attr *) res->val; + ColumnRef *cref = (ColumnRef *) res->val; + List *fields = cref->fields; + int numnames = length(fields); - if (att->relname != NULL && strcmp(att->relname, "*") == 0) + if (numnames == 1 && strcmp(strVal(lfirst(fields)), "*") == 0) { /* * Target item is a single '*', expand all tables (eg. @@ -112,27 +114,59 @@ transformTargetList(ParseState *pstate, List *targetlist) p_target = nconc(p_target, ExpandAllTables(pstate)); } - else if (att->attrs != NIL && - strcmp(strVal(lfirst(att->attrs)), "*") == 0) + else if (strcmp(strVal(nth(numnames-1, fields)), "*") == 0) { /* * Target item is relation.*, expand that table (eg. * SELECT emp.*, dname FROM emp, dept) */ + char *schemaname; + char *relname; RangeTblEntry *rte; int sublevels_up; - rte = refnameRangeTblEntry(pstate, att->relname, + switch (numnames) + { + case 2: + schemaname = NULL; + relname = strVal(lfirst(fields)); + break; + case 3: + schemaname = strVal(lfirst(fields)); + relname = strVal(lsecond(fields)); + break; + case 4: + { + char *name1 = strVal(lfirst(fields)); + + /* + * We check the catalog name and then ignore it. + */ + if (strcmp(name1, DatabaseName) != 0) + elog(ERROR, "Cross-database references are not implemented"); + schemaname = strVal(lsecond(fields)); + relname = strVal(lfirst(lnext(lnext(fields)))); + break; + } + default: + elog(ERROR, "Invalid qualified name syntax (too many names)"); + schemaname = NULL; /* keep compiler quiet */ + relname = NULL; + break; + } + + /* XXX do something with schema name */ + rte = refnameRangeTblEntry(pstate, relname, &sublevels_up); if (rte == NULL) - rte = addImplicitRTE(pstate, att->relname); + rte = addImplicitRTE(pstate, relname); p_target = nconc(p_target, expandRelAttrs(pstate, rte)); } else { - /* Plain Attr node, treat it as an expression */ + /* Plain ColumnRef node, treat it as an expression */ p_target = lappend(p_target, transformTargetEntry(pstate, res->val, @@ -143,7 +177,7 @@ transformTargetList(ParseState *pstate, List *targetlist) } else { - /* Everything else but Attr */ + /* Everything else but ColumnRef */ p_target = lappend(p_target, transformTargetEntry(pstate, res->val, @@ -317,10 +351,9 @@ CoerceTargetExpr(ParseState *pstate, /* * checkInsertTargets - - * generate a list of column names if not supplied or + * generate a list of INSERT column targets if not supplied, or * test supplied column names to make sure they are in target table. * Also return an integer list of the columns' attribute numbers. - * (used exclusively for inserts) */ List * checkInsertTargets(ParseState *pstate, List *cols, List **attrnos) @@ -338,17 +371,16 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos) for (i = 0; i < numcol; i++) { - Ident *id = makeNode(Ident); + ResTarget *col = makeNode(ResTarget); #ifdef _DROP_COLUMN_HACK__ if (COLUMN_IS_DROPPED(attr[i])) continue; #endif /* _DROP_COLUMN_HACK__ */ - id->name = palloc(NAMEDATALEN); - StrNCpy(id->name, NameStr(attr[i]->attname), NAMEDATALEN); - id->indirection = NIL; - id->isRel = false; - cols = lappend(cols, id); + col->name = pstrdup(NameStr(attr[i]->attname)); + col->indirection = NIL; + col->val = NULL; + cols = lappend(cols, col); *attrnos = lappendi(*attrnos, i + 1); } } @@ -361,7 +393,7 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos) foreach(tl, cols) { - char *name = ((Ident *) lfirst(tl))->name; + char *name = ((ResTarget *) lfirst(tl))->name; int attrno; /* Lookup column name, elog on failure */ @@ -458,19 +490,35 @@ FigureColnameInternal(Node *node, char **name) case T_Ident: *name = ((Ident *) node)->name; return 2; - case T_Attr: + case T_ColumnRef: { - List *attrs = ((Attr *) node)->attrs; + List *fields = ((ColumnRef *) node)->fields; - if (attrs) + while (lnext(fields) != NIL) + fields = lnext(fields); + if (strcmp(strVal(lfirst(fields)), "*") != 0) { - while (lnext(attrs) != NIL) - attrs = lnext(attrs); - *name = strVal(lfirst(attrs)); + *name = strVal(lfirst(fields)); return 2; } } break; + case T_ExprFieldSelect: + { + List *fields = ((ExprFieldSelect *) node)->fields; + + if (fields) + { + while (lnext(fields) != NIL) + fields = lnext(fields); + if (strcmp(strVal(lfirst(fields)), "*") != 0) + { + *name = strVal(lfirst(fields)); + return 2; + } + } + } + break; case T_FuncCall: *name = ((FuncCall *) node)->funcname; return 2; diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index b0315157e4..0b47aa9c92 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.63 2001/08/12 21:35:18 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.64 2002/03/21 16:01:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -110,63 +110,17 @@ InsertRule(char *rulname, return rewriteObjectId; } -/* - * for now, event_object must be a single attribute - */ -static void -ValidateRule(int event_type, - char *eobj_string, - char *eslot_string, - Node *event_qual, - List **action, - int is_instead, - Oid event_attype) -{ - if (((event_type == CMD_INSERT) || (event_type == CMD_DELETE)) && - eslot_string) - { - elog(ERROR, - "rules not allowed for insert or delete events to an attribute"); - } - -#ifdef NOT_USED - - /*--------- - * on retrieve to class.attribute do instead nothing is converted to - * 'on retrieve to class.attribute do instead: - * - * retrieve (attribute = NULL)' - * - * this is also a terrible hack that works well -- glass - *--------- - */ - if (is_instead && !*action && eslot_string && event_type == CMD_SELECT) - { - char *temp_buffer = (char *) palloc(strlen(template) + 80); - - sprintf(temp_buffer, template, event_attype, - get_typlen(event_attype), eslot_string, - event_attype); - - *action = (List *) stringToNode(temp_buffer); - - pfree(temp_buffer); - } -#endif -} - void DefineQueryRewrite(RuleStmt *stmt) { - CmdType event_type = stmt->event; - Attr *event_obj = stmt->object; + RangeVar *event_obj = stmt->relation; Node *event_qual = stmt->whereClause; + CmdType event_type = stmt->event; bool is_instead = stmt->instead; List *action = stmt->actions; Relation event_relation; Oid ev_relid; Oid ruleId; - char *eslot_string = NULL; int event_attno; Oid event_attype; char *actionP, @@ -186,23 +140,6 @@ DefineQueryRewrite(RuleStmt *stmt) event_relation = heap_openr(event_obj->relname, AccessExclusiveLock); ev_relid = RelationGetRelid(event_relation); - /* - * The current rewrite handler is known to work on relation level - * rules only. And for SELECT events, it expects one non-nothing - * action that is instead and returns exactly a tuple of the rewritten - * relation. This restricts SELECT rules to views. - * - * Jan - */ - if (event_obj->attrs) - elog(ERROR, "attribute level rules currently not supported"); - - /* - * eslot_string = strVal(lfirst(event_obj->attrs)); - */ - else - eslot_string = NULL; - /* * No rule actions that modify OLD or NEW */ @@ -358,21 +295,8 @@ DefineQueryRewrite(RuleStmt *stmt) /* * This rule is allowed - prepare to install it. */ - if (eslot_string == NULL) - { - event_attno = -1; - event_attype = InvalidOid; - } - else - { - event_attno = attnameAttNum(event_relation, eslot_string); - event_attype = attnumTypeId(event_relation, event_attno); - } - - /* fix bug about instead nothing */ - ValidateRule(event_type, event_obj->relname, - eslot_string, event_qual, &action, - is_instead, event_attype); + event_attno = -1; + event_attype = InvalidOid; /* * We want the rule's table references to be checked as though by the diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index af413cab93..86a158f94f 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.62 2002/03/12 00:51:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.63 2002/03/21 16:01:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -573,9 +573,9 @@ getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr) * they've been pushed down to the SELECT. */ if (length(parsetree->rtable) >= 2 && - strcmp(rt_fetch(PRS2_OLD_VARNO, parsetree->rtable)->eref->relname, + strcmp(rt_fetch(PRS2_OLD_VARNO, parsetree->rtable)->eref->aliasname, "*OLD*") == 0 && - strcmp(rt_fetch(PRS2_NEW_VARNO, parsetree->rtable)->eref->relname, + strcmp(rt_fetch(PRS2_NEW_VARNO, parsetree->rtable)->eref->aliasname, "*NEW*") == 0) return parsetree; Assert(parsetree->jointree && IsA(parsetree->jointree, FromExpr)); @@ -589,9 +589,9 @@ getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr) selectquery->commandType == CMD_SELECT)) elog(ERROR, "getInsertSelectQuery: expected to find SELECT subquery"); if (length(selectquery->rtable) >= 2 && - strcmp(rt_fetch(PRS2_OLD_VARNO, selectquery->rtable)->eref->relname, + strcmp(rt_fetch(PRS2_OLD_VARNO, selectquery->rtable)->eref->aliasname, "*OLD*") == 0 && - strcmp(rt_fetch(PRS2_NEW_VARNO, selectquery->rtable)->eref->relname, + strcmp(rt_fetch(PRS2_NEW_VARNO, selectquery->rtable)->eref->aliasname, "*NEW*") == 0) { if (subquery_ptr) diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 9542170d34..8443fe6591 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.257 2002/03/19 16:10:48 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.258 2002/03/21 16:01:25 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -1722,7 +1722,7 @@ PostgresMain(int argc, char *argv[], const char *username) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.257 $ $Date: 2002/03/19 16:10:48 $\n"); + puts("$Revision: 1.258 $ $Date: 2002/03/21 16:01:25 $\n"); } /* @@ -2216,6 +2216,10 @@ CreateCommandTag(Node *parsetree) tag = "CREATE DOMAIN"; break; + case T_CreateSchemaStmt: + tag = "CREATE"; + break; + case T_CreateStmt: tag = "CREATE"; break; diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c index ef4b4edd40..4599a27a64 100644 --- a/src/backend/tcop/pquery.c +++ b/src/backend/tcop/pquery.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.50 2002/03/06 06:10:10 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.51 2002/03/21 16:01:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -181,12 +181,12 @@ ProcessQuery(Query *parsetree, */ if (isRetrieveIntoPortal) { - intoName = parsetree->into; + intoName = parsetree->into->relname; portal = PreparePortal(intoName); oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); parsetree = copyObject(parsetree); plan = copyObject(plan); - intoName = parsetree->into; /* use copied name in QueryDesc */ + intoName = parsetree->into->relname; /* use copied name in QueryDesc */ /* * We stay in portal's memory context for now, so that query desc, diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index db8d440034..9a6813635c 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.135 2002/03/20 19:44:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.136 2002/03/21 16:01:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -218,6 +218,14 @@ ProcessUtility(Node *parsetree, /* * relation and attribute manipulation */ + case T_CreateSchemaStmt: + { + CreateSchemaStmt *stmt = (CreateSchemaStmt *) parsetree; + + CreateSchemaCommand(stmt); + } + break; + case T_CreateStmt: DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION); @@ -226,19 +234,19 @@ ProcessUtility(Node *parsetree, * secondary relation too. */ CommandCounterIncrement(); - AlterTableCreateToastTable(((CreateStmt *) parsetree)->relname, + AlterTableCreateToastTable(((CreateStmt *) parsetree)->relation->relname, true); break; case T_DropStmt: { DropStmt *stmt = (DropStmt *) parsetree; - List *args = stmt->names; + List *args = stmt->objects; List *arg; foreach(arg, args) { - relname = strVal(lfirst(arg)); + relname = ((RangeVar *) lfirst(arg))->relname; switch (stmt->removeType) { @@ -299,7 +307,8 @@ ProcessUtility(Node *parsetree, case T_TruncateStmt: { - TruncateRelation(((TruncateStmt *) parsetree)->relName); + relname = ((TruncateStmt *) parsetree)->relation->relname; + TruncateRelation(relname); } break; @@ -322,7 +331,7 @@ ProcessUtility(Node *parsetree, if (stmt->direction != FROM) SetQuerySnapshot(); - DoCopy(stmt->relname, + DoCopy(stmt->relation->relname, stmt->binary, stmt->oids, (bool) (stmt->direction == FROM), @@ -345,7 +354,7 @@ ProcessUtility(Node *parsetree, { RenameStmt *stmt = (RenameStmt *) parsetree; - relname = stmt->relname; + relname = stmt->relation->relname; if (!allowSystemTableMods && IsSystemRelationName(relname)) elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog", relname); @@ -380,7 +389,7 @@ ProcessUtility(Node *parsetree, renameatt(relname, /* relname */ stmt->column, /* old att name */ stmt->newname, /* new att name */ - interpretInhOption(stmt->inhOpt)); /* recursive? */ + interpretInhOption(stmt->relation->inhOpt)); /* recursive? */ } } break; @@ -398,47 +407,47 @@ ProcessUtility(Node *parsetree, switch (stmt->subtype) { case 'A': /* ADD COLUMN */ - AlterTableAddColumn(stmt->relname, - interpretInhOption(stmt->inhOpt), + AlterTableAddColumn(stmt->relation->relname, + interpretInhOption((stmt->relation)->inhOpt), (ColumnDef *) stmt->def); break; case 'T': /* ALTER COLUMN DEFAULT */ - AlterTableAlterColumnDefault(stmt->relname, - interpretInhOption(stmt->inhOpt), + AlterTableAlterColumnDefault(stmt->relation->relname, + interpretInhOption((stmt->relation)->inhOpt), stmt->name, stmt->def); break; case 'S': /* ALTER COLUMN STATISTICS */ case 'M': /* ALTER COLUMN STORAGE */ - AlterTableAlterColumnFlags(stmt->relname, - interpretInhOption(stmt->inhOpt), + AlterTableAlterColumnFlags(stmt->relation->relname, + interpretInhOption(stmt->relation->inhOpt), stmt->name, stmt->def, &(stmt->subtype)); break; case 'D': /* DROP COLUMN */ - AlterTableDropColumn(stmt->relname, - interpretInhOption(stmt->inhOpt), + AlterTableDropColumn(stmt->relation->relname, + interpretInhOption(stmt->relation->inhOpt), stmt->name, stmt->behavior); break; case 'C': /* ADD CONSTRAINT */ - AlterTableAddConstraint(stmt->relname, - interpretInhOption(stmt->inhOpt), + AlterTableAddConstraint(stmt->relation->relname, + interpretInhOption(stmt->relation->inhOpt), (List *) stmt->def); break; case 'X': /* DROP CONSTRAINT */ - AlterTableDropConstraint(stmt->relname, - interpretInhOption(stmt->inhOpt), + AlterTableDropConstraint(stmt->relation->relname, + interpretInhOption(stmt->relation->inhOpt), stmt->name, stmt->behavior); break; case 'E': /* CREATE TOAST TABLE */ - AlterTableCreateToastTable(stmt->relname, + AlterTableCreateToastTable(stmt->relation->relname, false); break; case 'U': /* ALTER OWNER */ - AlterTableOwner(stmt->relname, + AlterTableOwner(stmt->relation->relname, stmt->name); break; default: /* oops */ @@ -487,7 +496,7 @@ ProcessUtility(Node *parsetree, { ViewStmt *stmt = (ViewStmt *) parsetree; - DefineView(stmt->viewname, stmt->query); /* retrieve parsetree */ + DefineView(stmt->view->relname, stmt->query); /* retrieve parsetree */ } break; @@ -499,17 +508,17 @@ ProcessUtility(Node *parsetree, { IndexStmt *stmt = (IndexStmt *) parsetree; - relname = stmt->relname; + relname = stmt->relation->relname; if (!allowSystemTableMods && IsSystemRelationName(relname)) elog(ERROR, "CREATE INDEX: relation \"%s\" is a system catalog", relname); if (!pg_ownercheck(GetUserId(), relname, RELNAME)) elog(ERROR, "permission denied"); - DefineIndex(stmt->relname, /* relation name */ - stmt->idxname, /* index name */ - stmt->accessMethod, /* am name */ - stmt->indexParams, /* parameters */ + DefineIndex(stmt->relation->relname, /* relation */ + stmt->idxname, /* index name */ + stmt->accessMethod, /* am name */ + stmt->indexParams, /* parameters */ stmt->unique, stmt->primary, (Expr *) stmt->whereClause, @@ -522,7 +531,7 @@ ProcessUtility(Node *parsetree, RuleStmt *stmt = (RuleStmt *) parsetree; int aclcheck_result; - relname = stmt->object->relname; + relname = stmt->relation->relname; aclcheck_result = pg_aclcheck(relname, GetUserId(), ACL_RULE); if (aclcheck_result != ACLCHECK_OK) elog(ERROR, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]); @@ -603,7 +612,7 @@ ProcessUtility(Node *parsetree, { NotifyStmt *stmt = (NotifyStmt *) parsetree; - Async_Notify(stmt->relname); + Async_Notify(stmt->relation->relname); } break; @@ -611,7 +620,7 @@ ProcessUtility(Node *parsetree, { ListenStmt *stmt = (ListenStmt *) parsetree; - Async_Listen(stmt->relname, MyProcPid); + Async_Listen(stmt->relation->relname, MyProcPid); } break; @@ -619,7 +628,7 @@ ProcessUtility(Node *parsetree, { UnlistenStmt *stmt = (UnlistenStmt *) parsetree; - Async_Unlisten(stmt->relname, MyProcPid); + Async_Unlisten(stmt->relation->relname, MyProcPid); } break; @@ -636,7 +645,7 @@ ProcessUtility(Node *parsetree, { ClusterStmt *stmt = (ClusterStmt *) parsetree; - relname = stmt->relname; + relname = stmt->relation->relname; if (IsSystemRelationName(relname)) elog(ERROR, "CLUSTER: relation \"%s\" is a system catalog", relname); @@ -712,7 +721,6 @@ ProcessUtility(Node *parsetree, /* * ******************************** DOMAIN statements **** - * */ case T_CreateDomainStmt: DefineDomain((CreateDomainStmt *) parsetree); @@ -720,9 +728,7 @@ ProcessUtility(Node *parsetree, /* * ******************************** USER statements **** - * */ - case T_CreateUserStmt: CreateUser((CreateUserStmt *) parsetree); break; @@ -774,7 +780,7 @@ ProcessUtility(Node *parsetree, switch (stmt->reindexType) { case INDEX: - relname = (char *) stmt->name; + relname = (char *) stmt->relation->relname; if (IsSystemRelationName(relname)) { if (!allowSystemTableMods) @@ -789,7 +795,7 @@ ProcessUtility(Node *parsetree, ReindexIndex(relname, stmt->force); break; case TABLE: - relname = (char *) stmt->name; + relname = (char *) stmt->relation->relname; if (!pg_ownercheck(GetUserId(), relname, RELNAME)) elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]); ReindexTable(relname, stmt->force); diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index d47bf3bb94..0e4472faff 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -3,7 +3,7 @@ * back to source text * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.93 2002/03/12 00:51:59 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.94 2002/03/21 16:01:34 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -48,6 +48,7 @@ #include "catalog/pg_shadow.h" #include "executor/spi.h" #include "lib/stringinfo.h" +#include "nodes/makefuncs.h" #include "optimizer/clauses.h" #include "optimizer/tlist.h" #include "parser/keywords.h" @@ -659,8 +660,7 @@ deparse_context_for(char *relname, Oid relid) rte->rtekind = RTE_RELATION; rte->relname = relname; rte->relid = relid; - rte->eref = makeNode(Attr); - rte->eref->relname = relname; + rte->eref = makeAlias(relname, NIL); rte->inh = false; rte->inFromCl = true; @@ -755,9 +755,7 @@ deparse_context_for_subplan(const char *name, List *tlist, rte->rtekind = RTE_SPECIAL; /* XXX */ rte->relname = pstrdup(name); rte->relid = InvalidOid; - rte->eref = makeNode(Attr); - rte->eref->relname = rte->relname; - rte->eref->attrs = attrs; + rte->eref = makeAlias(rte->relname, attrs); rte->inh = false; rte->inFromCl = true; @@ -1462,7 +1460,7 @@ get_utility_query_def(Query *query, deparse_context *context) { NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt; - appendStringInfo(buf, "NOTIFY %s", quote_identifier(stmt->relname)); + appendStringInfo(buf, "NOTIFY %s", quote_identifier(stmt->relation->relname)); } else elog(ERROR, "get_utility_query_def: unexpected statement type"); @@ -1512,7 +1510,7 @@ get_names_for_var(Var *var, deparse_context *context, if (rte->rtekind == RTE_JOIN && rte->alias == NULL) *refname = NULL; else - *refname = rte->eref->relname; + *refname = rte->eref->aliasname; if (var->varattno == InvalidAttrNumber) *attname = NULL; @@ -1758,12 +1756,11 @@ get_rule_expr(Node *node, deparse_context *context) /* * If the argument is simple enough, we could emit * arg.fieldname, but most cases where FieldSelect is used - * are *not* simple. For now, always use the projection- - * function syntax. + * are *not* simple. So, always use parenthesized syntax. */ - appendStringInfo(buf, "%s(", quote_identifier(fieldname)); + appendStringInfoChar(buf, '('); get_rule_expr(fselect->arg, context); - appendStringInfoChar(buf, ')'); + appendStringInfo(buf, ").%s", quote_identifier(fieldname)); } break; @@ -2302,9 +2299,9 @@ get_from_clause(Query *query, deparse_context *context) if (!rte->inFromCl) continue; - if (strcmp(rte->eref->relname, "*NEW*") == 0) + if (strcmp(rte->eref->aliasname, "*NEW*") == 0) continue; - if (strcmp(rte->eref->relname, "*OLD*") == 0) + if (strcmp(rte->eref->aliasname, "*OLD*") == 0) continue; } @@ -2342,15 +2339,15 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context) if (rte->alias != NULL) { appendStringInfo(buf, " %s", - quote_identifier(rte->alias->relname)); - if (rte->alias->attrs != NIL) + quote_identifier(rte->alias->aliasname)); + if (rte->alias->colnames != NIL) { List *col; appendStringInfo(buf, "("); - foreach(col, rte->alias->attrs) + foreach(col, rte->alias->colnames) { - if (col != rte->alias->attrs) + if (col != rte->alias->colnames) appendStringInfo(buf, ", "); appendStringInfo(buf, "%s", quote_identifier(strVal(lfirst(col)))); @@ -2420,15 +2417,15 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context) if (j->alias != NULL) { appendStringInfo(buf, " %s", - quote_identifier(j->alias->relname)); - if (j->alias->attrs != NIL) + quote_identifier(j->alias->aliasname)); + if (j->alias->colnames != NIL) { List *col; appendStringInfo(buf, "("); - foreach(col, j->alias->attrs) + foreach(col, j->alias->colnames) { - if (col != j->alias->attrs) + if (col != j->alias->colnames) appendStringInfo(buf, ", "); appendStringInfo(buf, "%s", quote_identifier(strVal(lfirst(col)))); diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index a049a23935..5e0fa208cf 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: catversion.h,v 1.107 2002/03/20 19:44:48 tgl Exp $ + * $Id: catversion.h,v 1.108 2002/03/21 16:01:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200203191 +#define CATALOG_VERSION_NO 200203211 #endif diff --git a/src/include/commands/command.h b/src/include/commands/command.h index cf09111af4..36757b1f70 100644 --- a/src/include/commands/command.h +++ b/src/include/commands/command.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: command.h,v 1.33 2002/03/05 05:33:29 momjian Exp $ + * $Id: command.h,v 1.34 2002/03/21 16:01:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -72,4 +72,9 @@ extern void AlterTableOwner(const char *relationName, const char *newOwnerName); */ extern void LockTableCommand(LockStmt *lockstmt); +/* + * SCHEMA + */ +extern void CreateSchemaCommand(CreateSchemaStmt *parsetree); + #endif /* COMMAND_H */ diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h index 384241990b..2de7c03cf6 100644 --- a/src/include/nodes/makefuncs.h +++ b/src/include/nodes/makefuncs.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: makefuncs.h,v 1.31 2002/03/20 19:45:01 tgl Exp $ + * $Id: makefuncs.h,v 1.32 2002/03/21 16:01:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -44,7 +44,7 @@ extern Const *makeConst(Oid consttype, extern Const *makeNullConst(Oid consttype); -extern Attr *makeAttr(char *relname, char *attname); +extern Alias *makeAlias(const char *aliasname, List *colnames); extern RelabelType *makeRelabelType(Node *arg, Oid rtype, int32 rtypmod); diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index d25bc5f156..95aba8dfaa 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: nodes.h,v 1.101 2002/03/19 02:18:23 momjian Exp $ + * $Id: nodes.h,v 1.102 2002/03/21 16:01:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -195,21 +195,24 @@ typedef enum NodeTag T_DropGroupStmt, T_ReindexStmt, T_CheckPointStmt, + T_CreateSchemaStmt, T_AlterDatabaseSetStmt, T_AlterUserSetStmt, T_A_Expr = 700, - T_Attr, - T_A_Const, - T_ParamNo, + T_ColumnRef, + T_ParamRef, T_Ident, + T_A_Const, T_FuncCall, T_A_Indices, + T_ExprFieldSelect, T_ResTarget, T_TypeCast, - T_RangeSubselect, T_SortGroupBy, + T_Alias, T_RangeVar, + T_RangeSubselect, T_TypeName, T_IndexElem, T_ColumnDef, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 1b1f01bd28..4f5d139011 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.162 2002/03/20 19:45:02 tgl Exp $ + * $Id: parsenodes.h,v 1.163 2002/03/21 16:01:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -49,10 +49,10 @@ typedef struct Query * statement */ int resultRelation; /* target relation (index into rtable) */ - char *into; /* portal (cursor) name */ + struct RangeVar *into; /* target relation or portal (cursor) + * for portal just name is meaningful */ bool isPortal; /* is this a retrieve into portal? */ bool isBinary; /* binary portal? */ - bool isTemp; /* is 'into' a temp table? */ bool hasAggs; /* has aggregates in tlist or havingQual */ bool hasSubLinks; /* has subquery SubLink */ @@ -125,15 +125,30 @@ typedef struct TypeName } TypeName; /* - * ParamNo - specifies a parameter reference + * ColumnRef - specifies a reference to a column, or possibly a whole tuple + * + * The "fields" list must be nonempty; its last component may be "*" + * instead of a field name. Subscripts are optional. */ -typedef struct ParamNo +typedef struct ColumnRef +{ + NodeTag type; + List *fields; /* field names (list of Value strings) */ + List *indirection; /* subscripts (list of A_Indices) */ +} ColumnRef; + +/* + * ParamRef - specifies a parameter reference + * + * The parameter could be qualified with field names and/or subscripts + */ +typedef struct ParamRef { NodeTag type; int number; /* the number of the parameter */ - TypeName *typename; /* the typecast */ - List *indirection; /* array references */ -} ParamNo; + List *fields; /* field names (list of Value strings) */ + List *indirection; /* subscripts (list of A_Indices) */ +} ParamRef; /* * A_Expr - binary expressions @@ -147,22 +162,6 @@ typedef struct A_Expr Node *rexpr; /* right argument */ } A_Expr; -/* - * Attr - - * specifies an Attribute (ie. a Column); could have nested dots or - * array references. - * - */ -typedef struct Attr -{ - NodeTag type; - char *relname; /* name of relation (can be "*") */ - ParamNo *paramNo; /* or a parameter */ - List *attrs; /* attributes (possibly nested); list of - * Values (strings) */ - List *indirection; /* array refs (list of A_Indices') */ -} Attr; - /* * A_Const - a constant expression */ @@ -176,11 +175,11 @@ typedef struct A_Const /* * TypeCast - a CAST expression * - * NOTE: for mostly historical reasons, A_Const and ParamNo parsenodes contain + * NOTE: for mostly historical reasons, A_Const parsenodes contain * room for a TypeName; we only generate a separate TypeCast node if the - * argument to be casted is neither of those kinds of nodes. In theory either - * representation would work, but it is convenient (especially for A_Const) - * to have the target type immediately available. + * argument to be casted is not a constant. In theory either representation + * would work, but it is convenient to have the target type immediately + * available while resolving a constant's datatype. */ typedef struct TypeCast { @@ -284,17 +283,13 @@ typedef struct ColumnDef /* * Ident - - * an identifier (could be an attribute or a relation name). Depending - * on the context at transformStmt time, the identifier is treated as - * either a relation name (in which case, isRel will be set) or an - * attribute (in which case, it will be transformed into an Attr). + * an unqualified identifier. This is currently used only in the context + * of column name lists. */ typedef struct Ident { NodeTag type; char *name; /* its name */ - List *indirection; /* array references */ - bool isRel; /* is this a relation or a column? */ } Ident; /* @@ -324,6 +319,21 @@ typedef struct A_Indices Node *uidx; } A_Indices; +/* + * ExprFieldSelect - select a field and/or array element from an expression + * + * This is used in the raw parsetree to represent selection from an + * arbitrary expression (not a column or param reference). Either + * fields or indirection may be NIL if not used. + */ +typedef struct ExprFieldSelect +{ + NodeTag type; + Node *arg; /* the thing being selected from */ + List *fields; /* field names (list of Value strings) */ + List *indirection; /* subscripts (list of A_Indices) */ +} ExprFieldSelect; + /* * ResTarget - * result target (used in target list of pre-transformed Parse trees) @@ -358,15 +368,37 @@ typedef struct SortGroupBy Node *node; /* Expression */ } SortGroupBy; +/* + * Alias - + * specifies an alias for a range variable; the alias might also + * specify renaming of columns within the table. + */ +typedef struct Alias +{ + NodeTag type; + char *aliasname; /* aliased rel name (never qualified) */ + List *colnames; /* optional list of column aliases */ + /* Note: colnames is a list of Value nodes (always strings) */ +} Alias; + /* * RangeVar - range variable, used in FROM clauses + * + * Also used to represent table names in utility statements; there, the alias + * field is not used, and inhOpt shows whether to apply the operation + * recursively to child tables. In some contexts it is also useful to carry + * a TEMP table indication here. */ typedef struct RangeVar { NodeTag type; - char *relname; /* the relation name */ - InhOption inhOpt; /* expand rel by inheritance? */ - Attr *name; /* optional table alias & column aliases */ + char *catalogname; /* the catalog (database) name, or NULL */ + char *schemaname; /* the schema name, or NULL */ + char *relname; /* the relation/sequence name */ + InhOption inhOpt; /* expand rel by inheritance? + * recursively act on children? */ + bool istemp; /* is this a temp relation/sequence? */ + Alias *alias; /* table alias & optional column aliases */ } RangeVar; /* @@ -376,7 +408,7 @@ typedef struct RangeSubselect { NodeTag type; Node *subquery; /* the untransformed sub-select clause */ - Attr *name; /* table alias & optional column aliases */ + Alias *alias; /* table alias & optional column aliases */ } RangeSubselect; /* @@ -437,7 +469,7 @@ typedef struct TargetEntry * like outer joins and join-output-column aliasing.) Other special * RTE types also exist, as indicated by RTEKind. * - * alias is an Attr node representing the AS alias-clause attached to the + * alias is an Alias node representing the AS alias-clause attached to the * FROM expression, or NULL if no clause. * * eref is the table reference name and column reference names (either @@ -489,7 +521,7 @@ typedef struct RangeTblEntry */ /* - * Fields valid for a plain relation or inh_relation RTE (else NULL/zero): + * Fields valid for a plain relation RTE (else NULL/zero): */ char *relname; /* real name of the relation */ Oid relid; /* OID of the relation */ @@ -517,8 +549,8 @@ typedef struct RangeTblEntry /* * Fields valid in all RTEs: */ - Attr *alias; /* user-written alias clause, if any */ - Attr *eref; /* expanded reference names */ + Alias *alias; /* user-written alias clause, if any */ + Alias *eref; /* expanded reference names */ bool inh; /* inheritance requested? */ bool inFromCl; /* present in FROM clause */ bool checkForRead; /* check rel for read access */ @@ -570,7 +602,7 @@ typedef SortClause GroupClause; typedef struct InsertStmt { NodeTag type; - char *relname; /* relation to insert into */ + RangeVar *relation; /* relation to insert into */ List *cols; /* optional: names of the target columns */ /* @@ -589,9 +621,8 @@ typedef struct InsertStmt typedef struct DeleteStmt { NodeTag type; - char *relname; /* relation to delete from */ + RangeVar *relation; /* relation to delete from */ Node *whereClause; /* qualifications */ - InhOption inhOpt; /* recursively act on children? */ } DeleteStmt; /* ---------------------- @@ -601,11 +632,10 @@ typedef struct DeleteStmt typedef struct UpdateStmt { NodeTag type; - char *relname; /* relation to update */ + RangeVar *relation; /* relation to update */ List *targetList; /* the target list (of ResTarget) */ Node *whereClause; /* qualifications */ - List *fromClause; /* the from clause */ - InhOption inhOpt; /* recursively act on children? */ + List *fromClause; /* optional from clause for more tables */ } UpdateStmt; /* ---------------------- @@ -639,8 +669,7 @@ typedef struct SelectStmt List *distinctClause; /* NULL, list of DISTINCT ON exprs, or * lcons(NIL,NIL) for all (SELECT * DISTINCT) */ - char *into; /* name of table (for select into table) */ - bool istemp; /* into is a temp table? */ + RangeVar *into; /* target table (for select into table) */ List *intoColNames; /* column names for into table */ List *targetList; /* the target list (of ResTarget) */ List *fromClause; /* the FROM clause */ @@ -703,6 +732,22 @@ typedef struct SetOperationStmt * field in Query. *****************************************************************************/ +/* ---------------------- + * Create Schema Statement + * + * NOTE: the schemaElts list contains raw parsetrees for component statements + * of the schema, such as CREATE TABLE, GRANT, etc. These are analyzed and + * executed after the schema itself is created. + * ---------------------- + */ +typedef struct CreateSchemaStmt +{ + NodeTag type; + char *schemaname; /* the name of the schema to create */ + char *authid; /* the owner of the created schema */ + List *schemaElts; /* schema components (list of parsenodes) */ +} CreateSchemaStmt; + /* ---------------------- * Alter Table * @@ -725,8 +770,7 @@ typedef struct AlterTableStmt * U = change owner *------------ */ - char *relname; /* table to work on */ - InhOption inhOpt; /* recursively act on children? */ + RangeVar *relation; /* table to work on */ char *name; /* column or constraint name to act on, or * new owner */ Node *def; /* definition of new column or constraint */ @@ -743,12 +787,12 @@ typedef struct GrantStmt NodeTag type; bool is_grant; /* not revoke */ int objtype; - List *objects; /* list of names (as Value strings) */ + List *objects; /* list of names (as Value strings) + * or relations (as RangeVar's) */ List *privileges; /* integer list of privilege codes */ List *grantees; /* list of PrivGrantee nodes */ } GrantStmt; - typedef struct PrivGrantee { NodeTag type; @@ -756,7 +800,6 @@ typedef struct PrivGrantee char *groupname; } PrivGrantee; - typedef struct FuncWithArgs { NodeTag type; @@ -764,7 +807,6 @@ typedef struct FuncWithArgs List *funcargs; /* list of Typename nodes */ } FuncWithArgs; - /* This is only used internally in gram.y. */ typedef struct PrivTarget { @@ -773,7 +815,6 @@ typedef struct PrivTarget List *objs; } PrivTarget; - /* ---------------------- * Close Portal Statement * ---------------------- @@ -792,7 +833,7 @@ typedef struct CopyStmt { NodeTag type; bool binary; /* is a binary copy? */ - char *relname; /* the relation to copy */ + RangeVar *relation; /* the relation to copy */ bool oids; /* copy oid's? */ int direction; /* TO or FROM */ char *filename; /* if NULL, use stdin/stdout */ @@ -813,12 +854,10 @@ typedef struct CopyStmt typedef struct CreateStmt { NodeTag type; - char *relname; /* name of relation to create */ + RangeVar *relation; /* relation to create */ List *tableElts; /* column definitions (list of ColumnDef) */ - List *inhRelnames; /* relations to inherit from (list of - * T_String Values) */ + List *inhRelations; /* relations to inherit from */ List *constraints; /* constraints (list of Constraint nodes) */ - bool istemp; /* is this a temp table? */ bool hasoids; /* should it have OIDs? */ } CreateStmt; @@ -886,7 +925,7 @@ typedef struct FkConstraint { NodeTag type; char *constr_name; /* Constraint name */ - char *pktable_name; /* Primary key table name */ + RangeVar *pktable; /* Primary key table */ List *fk_attrs; /* Attributes of foreign key */ List *pk_attrs; /* Corresponding attrs in PK table */ char *match_type; /* FULL or PARTIAL */ @@ -904,7 +943,7 @@ typedef struct CreateTrigStmt { NodeTag type; char *trigname; /* TRIGGER' name */ - char *relname; /* triggered relation */ + RangeVar *relation; /* triggered relation */ char *funcname; /* function to call (or NULL) */ List *args; /* list of (T_String) Values or NULL */ bool before; /* BEFORE/AFTER */ @@ -920,14 +959,14 @@ typedef struct CreateTrigStmt bool isconstraint; /* This is an RI trigger */ bool deferrable; /* [NOT] DEFERRABLE */ bool initdeferred; /* INITIALLY {DEFERRED|IMMEDIATE} */ - char *constrrelname; /* opposite relation */ + RangeVar *constrrel; /* opposite relation */ } CreateTrigStmt; typedef struct DropTrigStmt { NodeTag type; char *trigname; /* TRIGGER' name */ - char *relname; /* triggered relation */ + RangeVar *relation; /* triggered relation */ } DropTrigStmt; /* ---------------------- @@ -1014,8 +1053,7 @@ typedef struct DropGroupStmt typedef struct CreateSeqStmt { NodeTag type; - char *seqname; /* the relation to create */ - bool istemp; /* is this a temp sequence? */ + RangeVar *sequence; /* the sequence to create */ List *options; } CreateSeqStmt; @@ -1072,7 +1110,7 @@ typedef struct CreateDomainStmt typedef struct DropStmt { NodeTag type; - List *names; + List *objects; int removeType; int behavior; /* CASCADE or RESTRICT drop behavior */ } DropStmt; @@ -1084,7 +1122,7 @@ typedef struct DropStmt typedef struct TruncateStmt { NodeTag type; - char *relName; /* relation to be truncated */ + RangeVar *relation; /* relation to be truncated */ } TruncateStmt; /* ---------------------- @@ -1095,6 +1133,8 @@ typedef struct CommentStmt { NodeTag type; int objtype; /* Object's type */ + char *objschema; /* Schema where object is defined, + * if object is schema specific */ char *objname; /* Name of the object */ char *objproperty; /* Property Id (such as column) */ List *objlist; /* Arguments for VAL objects */ @@ -1132,7 +1172,7 @@ typedef struct IndexStmt { NodeTag type; char *idxname; /* name of the index */ - char *relname; /* name of relation to index on */ + RangeVar *relation; /* relation to build index on */ char *accessMethod; /* name of access method (eg. btree) */ List *indexParams; /* a list of IndexElem */ Node *whereClause; /* qualification (partial-index predicate) */ @@ -1192,14 +1232,13 @@ typedef struct RemoveOperStmt } RemoveOperStmt; /* ---------------------- - * Alter Table Statement + * Alter Table Rename Statement * ---------------------- */ typedef struct RenameStmt { NodeTag type; - char *relname; /* relation to be altered */ - InhOption inhOpt; /* recursively act on children? */ + RangeVar *relation; /* relation to be altered */ char *column; /* if NULL, rename the relation name to * the new name. Otherwise, rename this * column name. */ @@ -1213,10 +1252,10 @@ typedef struct RenameStmt typedef struct RuleStmt { NodeTag type; + RangeVar *relation; /* relation the rule is for */ char *rulename; /* name of the rule */ Node *whereClause; /* qualifications */ - CmdType event; /* RETRIEVE */ - struct Attr *object; /* object affected */ + CmdType event; /* SELECT, INSERT, etc */ bool instead; /* is a 'do instead'? */ List *actions; /* the action statements */ } RuleStmt; @@ -1228,7 +1267,7 @@ typedef struct RuleStmt typedef struct NotifyStmt { NodeTag type; - char *relname; /* relation to notify */ + RangeVar *relation; /* qualified name to notify */ } NotifyStmt; /* ---------------------- @@ -1238,7 +1277,7 @@ typedef struct NotifyStmt typedef struct ListenStmt { NodeTag type; - char *relname; /* relation to listen on */ + RangeVar *relation; /* qualified name to listen on */ } ListenStmt; /* ---------------------- @@ -1248,7 +1287,7 @@ typedef struct ListenStmt typedef struct UnlistenStmt { NodeTag type; - char *relname; /* relation to unlisten on */ + RangeVar *relation; /* qualified name to unlisten on, or '*' */ } UnlistenStmt; /* ---------------------- @@ -1268,7 +1307,7 @@ typedef struct TransactionStmt typedef struct ViewStmt { NodeTag type; - char *viewname; /* name of the view */ + RangeVar *view; /* the view to be created */ List *aliases; /* target column names */ Query *query; /* the SQL statement */ } ViewStmt; @@ -1283,7 +1322,6 @@ typedef struct LoadStmt char *filename; /* file to load */ } LoadStmt; - /* ---------------------- * Createdb Statement * ---------------------- @@ -1327,7 +1365,7 @@ typedef struct DropdbStmt typedef struct ClusterStmt { NodeTag type; - char *relname; /* relation being indexed */ + RangeVar *relation; /* relation being indexed */ char *indexname; /* original index defined */ } ClusterStmt; @@ -1346,8 +1384,7 @@ typedef struct VacuumStmt bool analyze; /* do ANALYZE step */ bool freeze; /* early-freeze option */ bool verbose; /* print progress info */ - char *vacrel; /* name of single table to process, or - * NULL */ + RangeVar *relation; /* single table to process, or NULL */ List *va_cols; /* list of column names, or NIL for all */ } VacuumStmt; @@ -1413,7 +1450,7 @@ typedef struct VariableResetStmt typedef struct LockStmt { NodeTag type; - List *rellist; /* relations to lock */ + List *relations; /* relations to lock */ int mode; /* lock mode */ } LockStmt; @@ -1436,7 +1473,8 @@ typedef struct ReindexStmt { NodeTag type; int reindexType; /* INDEX|TABLE|DATABASE */ - const char *name; /* name to reindex */ + RangeVar *relation; /* Table or index to reindex */ + const char *name; /* name of database to reindex */ bool force; bool all; } ReindexStmt; diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 43e4d5a41e..f732305825 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -10,7 +10,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: primnodes.h,v 1.58 2002/03/12 00:52:02 tgl Exp $ + * $Id: primnodes.h,v 1.59 2002/03/21 16:01:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -508,7 +508,7 @@ typedef struct RangeTblRef * If he writes ON() then only "quals" is set. Note that NATURAL/USING * are not equivalent to ON() since they also affect the output column list. * - * alias is an Attr node representing the AS alias-clause attached to the + * alias is an Alias node representing the AS alias-clause attached to the * join expression, or NULL if no clause. NB: presence or absence of the * alias has a critical impact on semantics, because a join with an alias * restricts visibility of the tables/columns inside it. @@ -527,7 +527,7 @@ typedef struct JoinExpr Node *rarg; /* right subtree */ List *using; /* USING clause, if any (list of String) */ Node *quals; /* qualifiers on join, if any */ - struct Attr *alias; /* user-written alias clause, if any */ + struct Alias *alias; /* user-written alias clause, if any */ int rtindex; /* RT index assigned for join */ } JoinExpr; diff --git a/src/include/parser/analyze.h b/src/include/parser/analyze.h index 09cdde3786..7d520eef5c 100644 --- a/src/include/parser/analyze.h +++ b/src/include/parser/analyze.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: analyze.h,v 1.18 2001/11/05 17:46:34 momjian Exp $ + * $Id: analyze.h,v 1.19 2002/03/21 16:01:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,6 +16,7 @@ #include "parser/parse_node.h" extern List *parse_analyze(Node *parseTree, ParseState *parentParseState); +extern List *analyzeCreateSchemaStmt(CreateSchemaStmt *stmt); extern void CheckSelectForUpdate(Query *qry); diff --git a/src/include/parser/parse_agg.h b/src/include/parser/parse_agg.h index 22d046e48f..666e4ede76 100644 --- a/src/include/parser/parse_agg.h +++ b/src/include/parser/parse_agg.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parse_agg.h,v 1.20 2001/11/05 17:46:34 momjian Exp $ + * $Id: parse_agg.h,v 1.21 2002/03/21 16:01:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,8 +19,7 @@ extern void AddAggToParseState(ParseState *pstate, Aggref *aggref); extern void parseCheckAggregates(ParseState *pstate, Query *qry, Node *qual); extern Aggref *ParseAgg(ParseState *pstate, char *aggname, Oid basetype, - List *args, bool agg_star, bool agg_distinct, - int precedence); + List *args, bool agg_star, bool agg_distinct); extern void agg_error(char *caller, char *aggname, Oid basetypeID); #endif /* PARSE_AGG_H */ diff --git a/src/include/parser/parse_expr.h b/src/include/parser/parse_expr.h index 6c906420de..e330f8c249 100644 --- a/src/include/parser/parse_expr.h +++ b/src/include/parser/parse_expr.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parse_expr.h,v 1.25 2001/11/05 17:46:34 momjian Exp $ + * $Id: parse_expr.h,v 1.26 2002/03/21 16:01:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,13 +16,12 @@ #include "parser/parse_node.h" -#define EXPR_COLUMN_FIRST 1 -#define EXPR_RELATION_FIRST 2 +/* GUC parameters */ extern int max_expr_depth; extern bool Transform_null_equals; -extern Node *transformExpr(ParseState *pstate, Node *expr, int precedence); +extern Node *transformExpr(ParseState *pstate, Node *expr); extern Oid exprType(Node *expr); extern int32 exprTypmod(Node *expr); extern bool exprIsLengthCoercion(Node *expr, int32 *coercedTypmod); diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h index ff70080f21..603ea9369c 100644 --- a/src/include/parser/parse_func.h +++ b/src/include/parser/parse_func.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parse_func.h,v 1.35 2001/11/05 17:46:35 momjian Exp $ + * $Id: parse_func.h,v 1.36 2002/03/21 16:02:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -47,12 +47,9 @@ typedef enum } FuncDetailCode; -extern Node *ParseNestedFuncOrColumn(ParseState *pstate, Attr *attr, - int precedence); extern Node *ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, - bool agg_star, bool agg_distinct, - int precedence); + bool agg_star, bool agg_distinct, bool is_column); extern FuncDetailCode func_get_detail(char *funcname, List *fargs, int nargs, Oid *argtypes, diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h index 1b579850f4..656c70a688 100644 --- a/src/include/parser/parse_relation.h +++ b/src/include/parser/parse_relation.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parse_relation.h,v 1.29 2002/03/12 00:52:04 tgl Exp $ + * $Id: parse_relation.h,v 1.30 2002/03/21 16:02:05 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,12 +29,12 @@ extern Node *qualifiedNameToVar(ParseState *pstate, char *refname, char *colname, bool implicitRTEOK); extern RangeTblEntry *addRangeTableEntry(ParseState *pstate, char *relname, - Attr *alias, + Alias *alias, bool inh, bool inFromCl); extern RangeTblEntry *addRangeTableEntryForSubquery(ParseState *pstate, Query *subquery, - Attr *alias, + Alias *alias, bool inFromCl); extern RangeTblEntry *addRangeTableEntryForJoin(ParseState *pstate, List *colnames, @@ -43,7 +43,7 @@ extern RangeTblEntry *addRangeTableEntryForJoin(ParseState *pstate, List *coltypmods, List *leftcols, List *rightcols, - Attr *alias, + Alias *alias, bool inFromCl); extern void addRTEtoQuery(ParseState *pstate, RangeTblEntry *rte, bool addToJoinList, bool addToNameSpace); diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index 0e01eeaef5..ae5a7f4f63 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -396,7 +396,7 @@ drop table atacc1; create table atacc1 ( test int ); -- add a check constraint (fails) alter table atacc1 add constraint atacc_test1 check (test1>3); -ERROR: Attribute 'test1' not found +ERROR: Attribute "test1" not found drop table atacc1; -- something a little more complicated create table atacc1 ( test int, test2 int, test3 int); diff --git a/src/test/regress/expected/errors.out b/src/test/regress/expected/errors.out index f767c875a9..625c6d7499 100644 --- a/src/test/regress/expected/errors.out +++ b/src/test/regress/expected/errors.out @@ -22,19 +22,19 @@ select * from nonesuch; ERROR: parser: parse error at or near "select" -- bad name in target list select nonesuch from pg_database; -ERROR: Attribute 'nonesuch' not found +ERROR: Attribute "nonesuch" not found -- bad attribute name on lhs of operator select * from pg_database where nonesuch = pg_database.datname; -ERROR: Attribute 'nonesuch' not found +ERROR: Attribute "nonesuch" not found -- bad attribute name on rhs of operator select * from pg_database where pg_database.datname = nonesuch; -ERROR: Attribute 'nonesuch' not found +ERROR: Attribute "nonesuch" not found -- bad select distinct on syntax, distinct attribute missing select distinct on (foobar) from pg_database; ERROR: parser: parse error at or near "from" -- bad select distinct on syntax, distinct attribute not in target list select distinct on (foobar) * from pg_database; -ERROR: Attribute 'foobar' not found +ERROR: Attribute "foobar" not found -- -- DELETE diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 4f54ed3a7c..8633aa5670 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1177,7 +1177,7 @@ drop rule foorule; -- this should fail because f1 is not exposed for unqualified reference: create rule foorule as on insert to foo where f1 < 100 do instead insert into foo2 values (f1); -ERROR: Attribute 'f1' not found +ERROR: Attribute "f1" not found -- this is the correct way: create rule foorule as on insert to foo where f1 < 100 do instead insert into foo2 values (new.f1); diff --git a/src/test/regress/expected/union.out b/src/test/regress/expected/union.out index fb24220156..0adad8c119 100644 --- a/src/test/regress/expected/union.out +++ b/src/test/regress/expected/union.out @@ -406,7 +406,7 @@ ORDER BY q2,q1; -- This should fail, because q2 isn't a name of an EXCEPT output column SELECT q1 FROM int8_tbl EXCEPT SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1; -ERROR: Attribute 'q2' not found +ERROR: Attribute "q2" not found -- But this should work: SELECT q1 FROM int8_tbl EXCEPT (((SELECT q2 FROM int8_tbl ORDER BY q2 LIMIT 1))); q1 diff --git a/src/test/regress/input/misc.source b/src/test/regress/input/misc.source index 9c7a707f1c..18bf4e8af7 100644 --- a/src/test/regress/input/misc.source +++ b/src/test/regress/input/misc.source @@ -170,44 +170,44 @@ SELECT class, aa, a FROM a_star*; -- joe and sally play basketball, and -- everyone else does nothing. -- -SELECT p.name, p.hobbies.name FROM ONLY person p; +SELECT p.name, name(p.hobbies) FROM ONLY person p; -- -- as above, but jeff also does post_hacking. -- -SELECT p.name, p.hobbies.name FROM person* p; +SELECT p.name, name(p.hobbies) FROM person* p; -- -- the next two queries demonstrate how functions generate bogus duplicates. -- this is a "feature" .. -- -SELECT DISTINCT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r; +SELECT DISTINCT hobbies_r.name, name(hobbies_r.equipment) FROM hobbies_r; -SELECT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r; +SELECT hobbies_r.name, (hobbies_r.equipment).name FROM hobbies_r; -- -- mike needs advil and peet's coffee, -- joe and sally need hightops, and -- everyone else is fine. -- -SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM ONLY person p; +SELECT p.name, name(p.hobbies), name(equipment(p.hobbies)) FROM ONLY person p; -- -- as above, but jeff needs advil and peet's coffee as well. -- -SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM person* p; +SELECT p.name, name(p.hobbies), name(equipment(p.hobbies)) FROM person* p; -- -- just like the last two, but make sure that the target list fixup and -- unflattening is being done correctly. -- -SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM ONLY person p; +SELECT name(equipment(p.hobbies)), p.name, name(p.hobbies) FROM ONLY person p; -SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM person* p; +SELECT (p.hobbies).equipment.name, p.name, name(p.hobbies) FROM person* p; -SELECT p.hobbies.equipment.name, p.hobbies.name, p.name FROM ONLY person p; +SELECT (p.hobbies).equipment.name, name(p.hobbies), p.name FROM ONLY person p; -SELECT p.hobbies.equipment.name, p.hobbies.name, p.name FROM person* p; +SELECT name(equipment(p.hobbies)), name(p.hobbies), p.name FROM person* p; SELECT user_relns() AS user_relns ORDER BY user_relns; diff --git a/src/test/regress/output/misc.source b/src/test/regress/output/misc.source index e3a5109a02..971ccfca10 100644 --- a/src/test/regress/output/misc.source +++ b/src/test/regress/output/misc.source @@ -442,7 +442,7 @@ SELECT class, aa, a FROM a_star*; -- joe and sally play basketball, and -- everyone else does nothing. -- -SELECT p.name, p.hobbies.name FROM ONLY person p; +SELECT p.name, name(p.hobbies) FROM ONLY person p; name | name -------+------------- mike | posthacking @@ -453,7 +453,7 @@ SELECT p.name, p.hobbies.name FROM ONLY person p; -- -- as above, but jeff also does post_hacking. -- -SELECT p.name, p.hobbies.name FROM person* p; +SELECT p.name, name(p.hobbies) FROM person* p; name | name -------+------------- mike | posthacking @@ -466,7 +466,7 @@ SELECT p.name, p.hobbies.name FROM person* p; -- the next two queries demonstrate how functions generate bogus duplicates. -- this is a "feature" .. -- -SELECT DISTINCT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r; +SELECT DISTINCT hobbies_r.name, name(hobbies_r.equipment) FROM hobbies_r; name | name -------------+--------------- basketball | hightops @@ -475,7 +475,7 @@ SELECT DISTINCT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r; skywalking | guts (4 rows) -SELECT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r; +SELECT hobbies_r.name, (hobbies_r.equipment).name FROM hobbies_r; name | name -------------+--------------- posthacking | advil @@ -492,7 +492,7 @@ SELECT hobbies_r.name, hobbies_r.equipment.name FROM hobbies_r; -- joe and sally need hightops, and -- everyone else is fine. -- -SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM ONLY person p; +SELECT p.name, name(p.hobbies), name(equipment(p.hobbies)) FROM ONLY person p; name | name | name -------+-------------+--------------- mike | posthacking | advil @@ -504,7 +504,7 @@ SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM ONLY person p; -- -- as above, but jeff needs advil and peet's coffee as well. -- -SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM person* p; +SELECT p.name, name(p.hobbies), name(equipment(p.hobbies)) FROM person* p; name | name | name -------+-------------+--------------- mike | posthacking | advil @@ -519,7 +519,7 @@ SELECT p.name, p.hobbies.name, p.hobbies.equipment.name FROM person* p; -- just like the last two, but make sure that the target list fixup and -- unflattening is being done correctly. -- -SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM ONLY person p; +SELECT name(equipment(p.hobbies)), p.name, name(p.hobbies) FROM ONLY person p; name | name | name ---------------+-------+------------- advil | mike | posthacking @@ -528,7 +528,7 @@ SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM ONLY person p; hightops | sally | basketball (4 rows) -SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM person* p; +SELECT (p.hobbies).equipment.name, p.name, name(p.hobbies) FROM person* p; name | name | name ---------------+-------+------------- advil | mike | posthacking @@ -539,7 +539,7 @@ SELECT p.hobbies.equipment.name, p.name, p.hobbies.name FROM person* p; peet's coffee | jeff | posthacking (6 rows) -SELECT p.hobbies.equipment.name, p.hobbies.name, p.name FROM ONLY person p; +SELECT (p.hobbies).equipment.name, name(p.hobbies), p.name FROM ONLY person p; name | name | name ---------------+-------------+------- advil | posthacking | mike @@ -548,7 +548,7 @@ SELECT p.hobbies.equipment.name, p.hobbies.name, p.name FROM ONLY person p; hightops | basketball | sally (4 rows) -SELECT p.hobbies.equipment.name, p.hobbies.name, p.name FROM person* p; +SELECT name(equipment(p.hobbies)), name(p.hobbies), p.name FROM person* p; name | name | name ---------------+-------------+------- advil | posthacking | mike