1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-09 06:21:09 +03:00

First phase of SCHEMA changes, concentrating on fixing the grammar and

the parsetree representation.  As yet we don't *do* anything with schema
names, just drop 'em on the floor; but you can enter schema-compatible
command syntax, and there's even a primitive CREATE SCHEMA command.
No doc updates yet, except to note that you can now extract a field
from a function-returning-row's result with (foo(...)).fieldname.
This commit is contained in:
Tom Lane
2002-03-21 16:02:16 +00:00
parent 8c9c8ca2b5
commit 95ef6a3448
52 changed files with 2039 additions and 1535 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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