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

pg_type has a typnamespace column; system now supports creating types

in different namespaces.  Also, cleanup work on relation namespace
support: drop, alter, rename commands work for tables in non-default
namespaces.
This commit is contained in:
Tom Lane
2002-03-29 19:06:29 +00:00
parent 7c1ff35410
commit d5e99ab4d6
68 changed files with 2074 additions and 2266 deletions

View File

@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.73 2002/03/26 19:15:35 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.74 2002/03/29 19:06:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -129,7 +129,7 @@ cluster(RangeVar *oldrelation, char *oldindexname)
CommandCounterIncrement();
/* Destroy old heap (along with its index) and rename new. */
heap_drop_with_catalog(saveoldrelation->relname, allowSystemTableMods);
heap_drop_with_catalog(OIDOldHeap, allowSystemTableMods);
CommandCounterIncrement();

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.166 2002/03/26 19:15:36 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.167 2002/03/29 19:06:03 tgl Exp $
*
* NOTES
* The PerformAddAttribute() code, like most of the relation
@@ -42,11 +42,12 @@
#include "optimizer/clauses.h"
#include "optimizer/planmain.h"
#include "optimizer/prep.h"
#include "parser/analyze.h"
#include "parser/parse.h"
#include "parser/parse_expr.h"
#include "parser/parse_oper.h"
#include "parser/parse_relation.h"
#include "parser/analyze.h"
#include "parser/parse_type.h"
#include "tcop/utility.h"
#include "utils/acl.h"
#include "utils/builtins.h"
@@ -58,9 +59,9 @@
static void drop_default(Oid relid, int16 attnum);
static bool needs_toast_table(Relation rel);
static void AlterTableOwnerId(Oid relationOid, int32 newOwnerSysId);
static void CheckTupleType(Form_pg_class tuple_class);
/* --------------------------------
* PortalCleanup
* --------------------------------
@@ -309,13 +310,13 @@ PerformPortalClose(char *name, CommandDest dest)
* ----------------
*/
void
AlterTableAddColumn(const char *relationName,
AlterTableAddColumn(Oid myrelid,
bool inherits,
ColumnDef *colDef)
{
Relation rel,
pgclass,
attrdesc;
Oid myrelid;
HeapTuple reltup;
HeapTuple newreltup;
HeapTuple attributeTuple;
@@ -326,19 +327,17 @@ AlterTableAddColumn(const char *relationName,
maxatts;
HeapTuple typeTuple;
Form_pg_type tform;
char *typename;
int attndims;
/*
* Grab an exclusive lock on the target table, which we will NOT
* release until end of transaction.
*/
rel = heap_openr(relationName, AccessExclusiveLock);
myrelid = RelationGetRelid(rel);
rel = heap_open(myrelid, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
relationName);
RelationGetRelationName(rel));
/*
* permissions checking. this would normally be done in utility.c,
@@ -346,13 +345,13 @@ AlterTableAddColumn(const char *relationName,
*
* normally, only the owner of a class can change its schema.
*/
if (!allowSystemTableMods && IsSystemRelationName(relationName))
if (!allowSystemTableMods
&& IsSystemRelationName(RelationGetRelationName(rel)))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relationName);
RelationGetRelationName(rel));
if (!pg_class_ownercheck(myrelid, GetUserId()))
elog(ERROR, "ALTER TABLE: permission denied");
heap_close(rel, NoLock); /* close rel but keep lock! */
elog(ERROR, "ALTER TABLE: \"%s\": permission denied",
RelationGetRelationName(rel));
/*
* Recurse to add the column to child classes, if requested.
@@ -377,17 +376,11 @@ AlterTableAddColumn(const char *relationName,
foreach(child, children)
{
Oid childrelid = lfirsti(child);
char *childrelname;
if (childrelid == myrelid)
continue;
rel = heap_open(childrelid, AccessExclusiveLock);
childrelname = pstrdup(RelationGetRelationName(rel));
heap_close(rel, AccessExclusiveLock);
AlterTableAddColumn(childrelname, false, colDef);
pfree(childrelname);
AlterTableAddColumn(childrelid, false, colDef);
}
}
@@ -412,23 +405,21 @@ AlterTableAddColumn(const char *relationName,
elog(ERROR, "Adding NOT NULL columns is not implemented."
"\n\tAdd the column, then use ALTER TABLE ADD CONSTRAINT.");
rel = heap_openr(RelationRelationName, RowExclusiveLock);
pgclass = heap_openr(RelationRelationName, RowExclusiveLock);
reltup = SearchSysCache(RELOID,
ObjectIdGetDatum(myrelid),
0, 0, 0);
if (!HeapTupleIsValid(reltup))
elog(ERROR, "ALTER TABLE: relation \"%s\" not found",
relationName);
RelationGetRelationName(rel));
if (SearchSysCacheExists(ATTNAME,
ObjectIdGetDatum(myrelid),
PointerGetDatum(colDef->colname),
0, 0))
elog(ERROR, "ALTER TABLE: column name \"%s\" already exists in table \"%s\"",
colDef->colname, relationName);
colDef->colname, RelationGetRelationName(rel));
minattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts;
maxatts = minattnum + 1;
@@ -440,21 +431,11 @@ AlterTableAddColumn(const char *relationName,
attrdesc = heap_openr(AttributeRelationName, RowExclusiveLock);
if (colDef->typename->arrayBounds)
{
attndims = length(colDef->typename->arrayBounds);
typename = makeArrayTypeName(colDef->typename->name);
}
else
{
attndims = 0;
typename = colDef->typename->name;
}
typeTuple = SearchSysCache(TYPENAME,
PointerGetDatum(typename),
0, 0, 0);
if (!HeapTupleIsValid(typeTuple))
elog(ERROR, "ALTER TABLE: type \"%s\" does not exist", typename);
typeTuple = typenameType(colDef->typename);
tform = (Form_pg_type) GETSTRUCT(typeTuple);
attributeTuple = heap_addheader(Natts_pg_attribute,
@@ -494,7 +475,7 @@ AlterTableAddColumn(const char *relationName,
CatalogCloseIndices(Num_pg_attr_indices, idescs);
}
heap_close(attrdesc, NoLock);
heap_close(attrdesc, RowExclusiveLock);
/*
* Update number of attributes in pg_class tuple
@@ -502,22 +483,24 @@ AlterTableAddColumn(const char *relationName,
newreltup = heap_copytuple(reltup);
((Form_pg_class) GETSTRUCT(newreltup))->relnatts = maxatts;
simple_heap_update(rel, &newreltup->t_self, newreltup);
simple_heap_update(pgclass, &newreltup->t_self, newreltup);
/* keep catalog indices current */
if (RelationGetForm(rel)->relhasindex)
if (RelationGetForm(pgclass)->relhasindex)
{
Relation ridescs[Num_pg_class_indices];
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
CatalogIndexInsert(ridescs, Num_pg_class_indices, rel, newreltup);
CatalogIndexInsert(ridescs, Num_pg_class_indices, pgclass, newreltup);
CatalogCloseIndices(Num_pg_class_indices, ridescs);
}
heap_freetuple(newreltup);
ReleaseSysCache(reltup);
heap_close(rel, NoLock);
heap_close(pgclass, NoLock);
heap_close(rel, NoLock); /* close rel but keep lock! */
/*
* Make our catalog updates visible for subsequent steps.
@@ -549,29 +532,28 @@ AlterTableAddColumn(const char *relationName,
* ALTER TABLE ALTER COLUMN SET/DROP DEFAULT
*/
void
AlterTableAlterColumnDefault(const char *relationName,
AlterTableAlterColumnDefault(Oid myrelid,
bool inh, const char *colName,
Node *newDefault)
{
Relation rel;
HeapTuple tuple;
int16 attnum;
Oid myrelid;
rel = heap_openr(relationName, AccessExclusiveLock);
myrelid = RelationGetRelid(rel);
rel = heap_open(myrelid, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
relationName);
RelationGetRelationName(rel));
if (!allowSystemTableMods && IsSystemRelationName(relationName))
if (!allowSystemTableMods
&& IsSystemRelationName(RelationGetRelationName(rel)))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relationName);
if (!pg_class_ownercheck(myrelid, GetUserId()))
elog(ERROR, "ALTER TABLE: permission denied");
RelationGetRelationName(rel));
heap_close(rel, NoLock);
if (!pg_class_ownercheck(myrelid, GetUserId()))
elog(ERROR, "ALTER TABLE: \"%s\" permission denied",
RelationGetRelationName(rel));
/*
* Propagate to children if desired
@@ -595,18 +577,13 @@ AlterTableAlterColumnDefault(const char *relationName,
if (childrelid == myrelid)
continue;
rel = heap_open(childrelid, AccessExclusiveLock);
AlterTableAlterColumnDefault(RelationGetRelationName(rel),
AlterTableAlterColumnDefault(childrelid,
false, colName, newDefault);
heap_close(rel, AccessExclusiveLock);
}
}
/* -= now do the thing on this relation =- */
/* reopen the business */
rel = heap_openr(relationName, AccessExclusiveLock);
/*
* get the number of the attribute
*/
@@ -616,7 +593,7 @@ AlterTableAlterColumnDefault(const char *relationName,
0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "ALTER TABLE: relation \"%s\" has no column \"%s\"",
relationName, colName);
RelationGetRelationName(rel), colName);
attnum = ((Form_pg_attribute) GETSTRUCT(tuple))->attnum;
ReleaseSysCache(tuple);
@@ -718,43 +695,42 @@ drop_default(Oid relid, int16 attnum)
* ALTER TABLE ALTER COLUMN SET STATISTICS / STORAGE
*/
void
AlterTableAlterColumnFlags(const char *relationName,
AlterTableAlterColumnFlags(Oid myrelid,
bool inh, const char *colName,
Node *flagValue, const char *flagType)
{
Relation rel;
Oid myrelid;
int newtarget = 1;
char newstorage = 'x';
char *storagemode;
Relation attrelation;
HeapTuple tuple;
rel = heap_openr(relationName, AccessExclusiveLock);
myrelid = RelationGetRelid(rel);
rel = heap_open(myrelid, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
relationName);
RelationGetRelationName(rel));
/* we allow statistics case for system tables */
if (*flagType == 'M' &&
!allowSystemTableMods && IsSystemRelationName(relationName))
/*
* we allow statistics case for system tables
*/
if (*flagType != 'S' &&
!allowSystemTableMods
&& IsSystemRelationName(RelationGetRelationName(rel)))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relationName);
RelationGetRelationName(rel));
if (!pg_class_ownercheck(myrelid, GetUserId()))
elog(ERROR, "ALTER TABLE: permission denied");
heap_close(rel, NoLock); /* close rel, but keep lock! */
elog(ERROR, "ALTER TABLE: \"%s\" permission denied",
RelationGetRelationName(rel));
/*
* Check the supplied parameters before anything else
*/
if (*flagType == 'S') /*
* STATISTICS
*/
if (*flagType == 'S')
{
/* STATISTICS */
Assert(IsA(flagValue, Integer));
newtarget = intVal(flagValue);
@@ -766,10 +742,9 @@ AlterTableAlterColumnFlags(const char *relationName,
else if (newtarget > 1000)
newtarget = 1000;
}
else if (*flagType == 'M') /*
* STORAGE
*/
else if (*flagType == 'M')
{
/* STORAGE */
Assert(IsA(flagValue, Value));
storagemode = strVal(flagValue);
@@ -813,10 +788,8 @@ AlterTableAlterColumnFlags(const char *relationName,
if (childrelid == myrelid)
continue;
rel = heap_open(childrelid, AccessExclusiveLock);
AlterTableAlterColumnFlags(RelationGetRelationName(rel),
false, colName, flagValue, flagType);
heap_close(rel, AccessExclusiveLock);
AlterTableAlterColumnFlags(childrelid,
false, colName, flagValue, flagType);
}
}
@@ -830,7 +803,7 @@ AlterTableAlterColumnFlags(const char *relationName,
0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "ALTER TABLE: relation \"%s\" has no column \"%s\"",
relationName, colName);
RelationGetRelationName(rel), colName);
if (((Form_pg_attribute) GETSTRUCT(tuple))->attnum < 0)
elog(ERROR, "ALTER TABLE: cannot change system attribute \"%s\"",
@@ -864,6 +837,7 @@ AlterTableAlterColumnFlags(const char *relationName,
heap_freetuple(tuple);
heap_close(attrelation, NoLock);
heap_close(rel, NoLock); /* close rel, but keep lock! */
}
@@ -1006,14 +980,13 @@ RemoveColumnReferences(Oid reloid, int attnum, bool checkonly, HeapTuple reltup)
* ALTER TABLE DROP COLUMN
*/
void
AlterTableDropColumn(const char *relationName,
AlterTableDropColumn(Oid myrelid,
bool inh, const char *colName,
int behavior)
{
#ifdef _DROP_COLUMN_HACK__
Relation rel,
attrdesc;
Oid myrelid;
HeapTuple reltup;
HeapTupleData classtuple;
Buffer buffer;
@@ -1031,12 +1004,16 @@ AlterTableDropColumn(const char *relationName,
* Grab an exclusive lock on the target table, which we will NOT
* release until end of transaction.
*/
rel = heap_openr(relationName, AccessExclusiveLock);
myrelid = RelationGetRelid(rel);
rel = heap_open(myrelid, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
relationName);
RelationGetRelationName(rel));
if (!allowSystemTableMods
&& IsSystemRelationName(RelationGetRelationName(rel))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
RelationGetRelationName(rel));
/*
* permissions checking. this would normally be done in utility.c,
@@ -1044,9 +1021,6 @@ AlterTableDropColumn(const char *relationName,
*
* normally, only the owner of a class can change its schema.
*/
if (!allowSystemTableMods && IsSystemRelationName(relationName))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relationName);
if (!pg_class_ownercheck(myrelid, GetUserId()))
elog(ERROR, "ALTER TABLE: permission denied");
@@ -1066,8 +1040,17 @@ AlterTableDropColumn(const char *relationName,
ObjectIdGetDatum(myrelid),
0, 0, 0);
if (!HeapTupleIsValid(reltup))
{
Relation myrel;
char *myrelname;
myrel = heap_open(myrelid, AccessExclusiveLock);
myrelname = pstrdup(RelationGetRelationName(myrel));
heap_close(myrel, AccessExclusiveLock);
elog(ERROR, "ALTER TABLE: relation \"%s\" not found",
relationName);
myrelname);
}
classtuple.t_self = reltup->t_self;
ReleaseSysCache(reltup);
@@ -1092,8 +1075,17 @@ AlterTableDropColumn(const char *relationName,
PointerGetDatum(colName),
0, 0);
if (!HeapTupleIsValid(tup))
{
Relation myrel;
char *myrelname;
myrel = heap_open(myrelid, AccessExclusiveLock);
myrelname = pstrdup(RelationGetRelationName(myrel));
heap_close(myrel, AccessExclusiveLock);
elog(ERROR, "ALTER TABLE: column name \"%s\" doesn't exist in table \"%s\"",
colName, relationName);
colName, myrelname);
}
attribute = (Form_pg_attribute) GETSTRUCT(tup);
attnum = attribute->attnum;
@@ -1164,29 +1156,30 @@ AlterTableDropColumn(const char *relationName,
* ALTER TABLE ADD CONSTRAINT
*/
void
AlterTableAddConstraint(char *relationName,
AlterTableAddConstraint(Oid myrelid,
bool inh, List *newConstraints)
{
Relation rel;
Oid myrelid;
List *listptr;
/*
* Grab an exclusive lock on the target table, which we will NOT
* release until end of transaction.
*/
rel = heap_openr(relationName, AccessExclusiveLock);
myrelid = RelationGetRelid(rel);
rel = heap_open(myrelid, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
relationName);
RelationGetRelationName(rel));
if (!allowSystemTableMods && IsSystemRelationName(relationName))
if (!allowSystemTableMods
&& IsSystemRelationName(RelationGetRelationName(rel)))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relationName);
RelationGetRelationName(rel));
if (!pg_class_ownercheck(myrelid, GetUserId()))
elog(ERROR, "ALTER TABLE: permission denied");
elog(ERROR, "ALTER TABLE: \"%s\": permission denied",
RelationGetRelationName(rel));
if (inh)
{
@@ -1204,16 +1197,10 @@ AlterTableAddConstraint(char *relationName,
foreach(child, children)
{
Oid childrelid = lfirsti(child);
char *childrelname;
Relation childrel;
if (childrelid == myrelid)
continue;
childrel = heap_open(childrelid, AccessExclusiveLock);
childrelname = pstrdup(RelationGetRelationName(childrel));
heap_close(childrel, AccessExclusiveLock);
AlterTableAddConstraint(childrelname, false, newConstraints);
pfree(childrelname);
AlterTableAddConstraint(childrelid, false, newConstraints);
}
}
@@ -1262,7 +1249,7 @@ AlterTableAddConstraint(char *relationName,
pstate = make_parsestate(NULL);
rte = addRangeTableEntryForRelation(pstate,
myrelid,
makeAlias(relationName, NIL),
makeAlias(RelationGetRelationName(rel), NIL),
false,
true);
addRTEtoQuery(pstate, rte, true, true);
@@ -1286,7 +1273,7 @@ AlterTableAddConstraint(char *relationName,
*/
if (length(pstate->p_rtable) != 1)
elog(ERROR, "Only relation '%s' can be referenced in CHECK",
relationName);
RelationGetRelationName(rel));
/*
* Might as well try to reduce any
@@ -1358,7 +1345,7 @@ AlterTableAddConstraint(char *relationName,
int count;
if (is_temp_rel_name(fkconstraint->pktable->relname) &&
!is_temp_rel_name(relationName))
!is_temp_rel_name(RelationGetRelationName(rel)))
elog(ERROR, "ALTER TABLE / ADD CONSTRAINT: Unable to reference temporary table from permanent table constraint.");
/*
@@ -1408,7 +1395,7 @@ AlterTableAddConstraint(char *relationName,
trig.tgargs[0] = fkconstraint->constr_name;
else
trig.tgargs[0] = "<unknown>";
trig.tgargs[1] = (char *) relationName;
trig.tgargs[1] = pstrdup(RelationGetRelationName(rel));
trig.tgargs[2] = fkconstraint->pktable->relname;
trig.tgargs[3] = fkconstraint->match_type;
count = 4;
@@ -1483,12 +1470,11 @@ AlterTableAddConstraint(char *relationName,
* Christopher Kings-Lynne
*/
void
AlterTableDropConstraint(const char *relationName,
AlterTableDropConstraint(Oid myrelid,
bool inh, const char *constrName,
int behavior)
{
Relation rel;
Oid myrelid;
int deleted;
/*
@@ -1502,19 +1488,21 @@ AlterTableDropConstraint(const char *relationName,
* Acquire an exclusive lock on the target relation for the duration
* of the operation.
*/
rel = heap_openr(relationName, AccessExclusiveLock);
myrelid = RelationGetRelid(rel);
rel = heap_open(myrelid, AccessExclusiveLock);
/* Disallow DROP CONSTRAINT on views, indexes, sequences, etc */
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
relationName);
RelationGetRelationName(rel));
if (!allowSystemTableMods && IsSystemRelationName(relationName))
if (!allowSystemTableMods
&& IsSystemRelationName(RelationGetRelationName(rel)))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relationName);
RelationGetRelationName(rel));
if (!pg_class_ownercheck(myrelid, GetUserId()))
elog(ERROR, "ALTER TABLE: permission denied");
elog(ERROR, "ALTER TABLE: \"%s\": permission denied",
RelationGetRelationName(rel));
/*
* Since all we have is the name of the constraint, we have to look
@@ -1554,30 +1542,7 @@ AlterTableDropConstraint(const char *relationName,
* ALTER TABLE OWNER
*/
void
AlterTableOwner(const RangeVar *tgtrel, const char *newOwnerName)
{
Relation rel;
Oid myrelid;
int32 newOwnerSysId;
/* check that we are the superuser */
if (!superuser())
elog(ERROR, "ALTER TABLE: permission denied");
/* lookup the OID of the target relation */
rel = relation_openrv(tgtrel, AccessExclusiveLock);
myrelid = RelationGetRelid(rel);
heap_close(rel, NoLock); /* close rel but keep lock! */
/* lookup the sysid of the new owner */
newOwnerSysId = get_usesysid(newOwnerName);
/* do all the actual work */
AlterTableOwnerId(myrelid, newOwnerSysId);
}
static void
AlterTableOwnerId(Oid relationOid, int32 newOwnerSysId)
AlterTableOwner(Oid relationOid, int32 newOwnerSysId)
{
Relation target_rel;
Relation class_rel;
@@ -1629,7 +1594,7 @@ AlterTableOwnerId(Oid relationOid, int32 newOwnerSysId)
/* For each index, recursively change its ownership */
foreach(i, index_oid_list)
{
AlterTableOwnerId(lfirsti(i), newOwnerSysId);
AlterTableOwner(lfirsti(i), newOwnerSysId);
}
freeList(index_oid_list);
@@ -1640,7 +1605,7 @@ AlterTableOwnerId(Oid relationOid, int32 newOwnerSysId)
/* If it has a toast table, recurse to change its ownership */
if (tuple_class->reltoastrelid != InvalidOid)
{
AlterTableOwnerId(tuple_class->reltoastrelid, newOwnerSysId);
AlterTableOwner(tuple_class->reltoastrelid, newOwnerSysId);
}
}

View File

@@ -7,7 +7,7 @@
* Copyright (c) 1999-2001, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.37 2002/03/26 19:15:38 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.38 2002/03/29 19:06:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -27,9 +27,10 @@
#include "catalog/pg_type.h"
#include "commands/comment.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "parser/parse_agg.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
#include "parser/parse_type.h"
#include "parser/parse.h"
#include "rewrite/rewriteRemove.h"
#include "utils/acl.h"
@@ -51,14 +52,16 @@
static void CommentRelation(int objtype, char * schemaname, char *relation,
char *comment);
static void CommentAttribute(char *relation, char *attrib, char *comment);
static void CommentAttribute(char * schemaname, char *relation,
char *attrib, char *comment);
static void CommentDatabase(char *database, char *comment);
static void CommentRewrite(char *rule, char *comment);
static void CommentType(char *type, char *comment);
static void CommentAggregate(char *aggregate, List *arguments, char *comment);
static void CommentProc(char *function, List *arguments, char *comment);
static void CommentOperator(char *opname, List *arguments, char *comment);
static void CommentTrigger(char *trigger, char *relation, char *comments);
static void CommentTrigger(char *trigger, char *schemaname, char *relation,
char *comments);
/*------------------------------------------------------------------
@@ -88,7 +91,7 @@ CommentObject(int objtype, char *schemaname, char *objname, char *objproperty,
CommentRelation(objtype, schemaname, objname, comment);
break;
case COLUMN:
CommentAttribute(objname, objproperty, comment);
CommentAttribute(schemaname, objname, objproperty, comment);
break;
case DATABASE:
CommentDatabase(objname, comment);
@@ -109,7 +112,7 @@ CommentObject(int objtype, char *schemaname, char *objname, char *objproperty,
CommentOperator(objname, objlist, comment);
break;
case TRIGGER:
CommentTrigger(objname, objproperty, comment);
CommentTrigger(objname, schemaname, objproperty, comment);
break;
default:
elog(ERROR, "An attempt was made to comment on a unknown type: %d",
@@ -391,14 +394,18 @@ CommentRelation(int reltype, char *schemaname, char *relname, char *comment)
*/
static void
CommentAttribute(char *relname, char *attrname, char *comment)
CommentAttribute(char *schemaname, char *relname, char *attrname, char *comment)
{
RangeVar *rel = makeNode(RangeVar);
Relation relation;
AttrNumber attnum;
/* Open the containing relation to ensure it won't go away meanwhile */
relation = heap_openr(relname, AccessShareLock);
rel->relname = relname;
rel->schemaname = schemaname;
rel->istemp = false;
relation = heap_openrv(rel, AccessShareLock);
/* Check object security */
@@ -539,11 +546,8 @@ CommentType(char *type, char *comment)
/* Find the type's oid */
oid = GetSysCacheOid(TYPENAME,
PointerGetDatum(type),
0, 0, 0);
if (!OidIsValid(oid))
elog(ERROR, "type '%s' does not exist", type);
/* XXX WRONG: need to deal with qualified type names */
oid = typenameTypeId(makeTypeName(type));
/* Check object security */
@@ -570,21 +574,13 @@ static void
CommentAggregate(char *aggregate, List *arguments, char *comment)
{
TypeName *aggtype = (TypeName *) lfirst(arguments);
char *aggtypename;
Oid baseoid,
oid;
Oid classoid;
bool defined;
/* First, attempt to determine the base aggregate oid */
if (aggtype)
{
aggtypename = TypeNameToInternalName(aggtype);
baseoid = TypeGet(aggtypename, &defined);
if (!OidIsValid(baseoid))
elog(ERROR, "type '%s' does not exist", aggtypename);
}
baseoid = typenameTypeId(aggtype);
else
baseoid = InvalidOid;
@@ -648,20 +644,19 @@ CommentProc(char *function, List *arguments, char *comment)
for (i = 0; i < argcount; i++)
{
TypeName *t = (TypeName *) lfirst(arguments);
char *typnam = TypeNameToInternalName(t);
argoids[i] = LookupTypeName(t);
if (!OidIsValid(argoids[i]))
{
char *typnam = TypeNameToString(t);
if (strcmp(typnam, "opaque") == 0)
argoids[i] = InvalidOid;
else
elog(ERROR, "Type \"%s\" does not exist", typnam);
}
arguments = lnext(arguments);
if (strcmp(typnam, "opaque") == 0)
argoids[i] = InvalidOid;
else
{
argoids[i] = GetSysCacheOid(TYPENAME,
PointerGetDatum(typnam),
0, 0, 0);
if (!OidIsValid(argoids[i]))
elog(ERROR, "CommentProc: type '%s' not found", typnam);
}
}
/* Now, find the corresponding oid for this procedure */
@@ -707,40 +702,20 @@ CommentOperator(char *opername, List *arguments, char *comment)
{
TypeName *typenode1 = (TypeName *) lfirst(arguments);
TypeName *typenode2 = (TypeName *) lsecond(arguments);
char oprtype = 0,
*lefttype = NULL,
*righttype = NULL;
char oprtype = 0;
Form_pg_operator data;
HeapTuple optuple;
Oid oid,
leftoid = InvalidOid,
rightoid = InvalidOid;
bool defined;
/* Initialize our left and right argument types */
/* Attempt to fetch the left type oid, if specified */
if (typenode1 != NULL)
lefttype = TypeNameToInternalName(typenode1);
leftoid = typenameTypeId(typenode1);
/* Attempt to fetch the right type oid, if specified */
if (typenode2 != NULL)
righttype = TypeNameToInternalName(typenode2);
/* Attempt to fetch the left oid, if specified */
if (lefttype != NULL)
{
leftoid = TypeGet(lefttype, &defined);
if (!OidIsValid(leftoid))
elog(ERROR, "left type '%s' does not exist", lefttype);
}
/* Attempt to fetch the right oid, if specified */
if (righttype != NULL)
{
rightoid = TypeGet(righttype, &defined);
if (!OidIsValid(rightoid))
elog(ERROR, "right type '%s' does not exist", righttype);
}
rightoid = typenameTypeId(typenode2);
/* Determine operator type */
@@ -797,8 +772,9 @@ CommentOperator(char *opername, List *arguments, char *comment)
*/
static void
CommentTrigger(char *trigger, char *relname, char *comment)
CommentTrigger(char *trigger, char *schemaname, char *relname, char *comment)
{
RangeVar *rel = makeNode(RangeVar);
Relation pg_trigger,
relation;
HeapTuple triggertuple;
@@ -808,7 +784,10 @@ CommentTrigger(char *trigger, char *relname, char *comment)
/* First, validate the user's action */
relation = heap_openr(relname, AccessShareLock);
rel->relname = relname;
rel->schemaname = schemaname;
rel->istemp = false;
relation = heap_openrv(rel, AccessShareLock);
if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
elog(ERROR, "you are not permitted to comment on trigger '%s' %s '%s'",

View File

@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.151 2002/03/21 23:27:20 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.152 2002/03/29 19:06:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,6 +21,7 @@
#include "access/printtup.h"
#include "catalog/catname.h"
#include "catalog/index.h"
#include "catalog/namespace.h"
#include "catalog/pg_index.h"
#include "catalog/pg_shadow.h"
#include "catalog/pg_type.h"
@@ -228,7 +229,7 @@ CopyDonePeek(FILE *fp, int c, bool pickup)
/*
* DoCopy executes the SQL COPY statement.
*
* Either unload or reload contents of table <relname>, depending on <from>.
* Either unload or reload contents of table <relation>, depending on <from>.
* (<from> = TRUE means we are inserting into the table.)
*
* If <pipe> is false, transfer is between the table and the file named
@@ -260,7 +261,7 @@ CopyDonePeek(FILE *fp, int c, bool pickup)
* the table.
*/
void
DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
DoCopy(const RangeVar *relation, bool binary, bool oids, bool from, bool pipe,
char *filename, char *delim, char *null_print)
{
FILE *fp;
@@ -271,7 +272,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
/*
* Open and lock the relation, using the appropriate lock type.
*/
rel = heap_openr(relname, (from ? RowExclusiveLock : AccessShareLock));
rel = heap_openrv(relation, (from ? RowExclusiveLock : AccessShareLock));
/* Check permissions. */
aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
@@ -312,11 +313,14 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
if (rel->rd_rel->relkind != RELKIND_RELATION)
{
if (rel->rd_rel->relkind == RELKIND_VIEW)
elog(ERROR, "You cannot copy view %s", relname);
elog(ERROR, "You cannot copy view %s",
RelationGetRelationName(rel));
else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
elog(ERROR, "You cannot change sequence relation %s", relname);
elog(ERROR, "You cannot change sequence relation %s",
RelationGetRelationName(rel));
else
elog(ERROR, "You cannot copy object %s", relname);
elog(ERROR, "You cannot copy object %s",
RelationGetRelationName(rel));
}
if (pipe)
{
@@ -354,11 +358,14 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
if (rel->rd_rel->relkind != RELKIND_RELATION)
{
if (rel->rd_rel->relkind == RELKIND_VIEW)
elog(ERROR, "You cannot copy view %s", relname);
elog(ERROR, "You cannot copy view %s",
RelationGetRelationName(rel));
else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
elog(ERROR, "You cannot copy sequence %s", relname);
elog(ERROR, "You cannot copy sequence %s",
RelationGetRelationName(rel));
else
elog(ERROR, "You cannot copy object %s", relname);
elog(ERROR, "You cannot copy object %s",
RelationGetRelationName(rel));
}
if (pipe)
{

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.92 2002/03/26 19:15:40 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.93 2002/03/29 19:06:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -27,6 +27,7 @@
#include "commands/creatinh.h"
#include "miscadmin.h"
#include "optimizer/clauses.h"
#include "parser/parse_type.h"
#include "utils/acl.h"
#include "utils/syscache.h"
#include "utils/temprel.h"
@@ -108,7 +109,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
* (BuildDescForRelation takes care of the inherited defaults, but we
* have to copy inherited constraints here.)
*/
descriptor = BuildDescForRelation(schema, relname);
descriptor = BuildDescForRelation(schema);
if (old_constraints != NIL)
{
@@ -238,10 +239,12 @@ DefineRelation(CreateStmt *stmt, char relkind)
* themselves will be destroyed, too.
*/
void
RemoveRelation(const char *name)
RemoveRelation(const RangeVar *relation)
{
AssertArg(name);
heap_drop_with_catalog(name, allowSystemTableMods);
Oid relOid;
relOid = RangeVarGetRelid(relation, false);
heap_drop_with_catalog(relOid, allowSystemTableMods);
}
/*
@@ -255,34 +258,36 @@ RemoveRelation(const char *name)
* Rows are removed, indices are truncated and reconstructed.
*/
void
TruncateRelation(const char *relname)
TruncateRelation(const RangeVar *relation)
{
Oid relid;
Relation rel;
AssertArg(relname);
relid = RangeVarGetRelid(relation, false);
/* Grab exclusive lock in preparation for truncate */
rel = heap_openr(relname, AccessExclusiveLock);
rel = heap_open(relid, AccessExclusiveLock);
if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
elog(ERROR, "TRUNCATE cannot be used on sequences. '%s' is a sequence",
relname);
RelationGetRelationName(rel));
if (rel->rd_rel->relkind == RELKIND_VIEW)
elog(ERROR, "TRUNCATE cannot be used on views. '%s' is a view",
relname);
RelationGetRelationName(rel));
if (!allowSystemTableMods && IsSystemRelationName(relname))
if (!allowSystemTableMods && IsSystemRelationName(RelationGetRelationName(rel)))
elog(ERROR, "TRUNCATE cannot be used on system tables. '%s' is a system table",
relname);
RelationGetRelationName(rel));
if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
elog(ERROR, "you do not own relation \"%s\"", relname);
elog(ERROR, "you do not own relation \"%s\"",
RelationGetRelationName(rel));
/* Keep the lock until transaction commit */
heap_close(rel, NoLock);
heap_truncate(relname);
heap_truncate(relid);
}
@@ -308,12 +313,7 @@ MergeDomainAttributes(List *schema)
HeapTuple tuple;
Form_pg_type typeTup;
tuple = SearchSysCache(TYPENAME,
CStringGetDatum(coldef->typename->name),
0,0,0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "MergeDomainAttributes: Type %s does not exist",
coldef->typename->name);
tuple = typenameType(coldef->typename);
typeTup = (Form_pg_type) GETSTRUCT(tuple);
if (typeTup->typtype == 'd')
@@ -486,26 +486,11 @@ MergeAttributes(List *schema, List *supers, bool istemp,
parent_attno++)
{
Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1];
char *attributeName;
char *attributeType;
HeapTuple tuple;
char *attributeName = NameStr(attribute->attname);
int exist_attno;
ColumnDef *def;
TypeName *typename;
/*
* Get name and type name of attribute
*/
attributeName = NameStr(attribute->attname);
tuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(attribute->atttypid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "CREATE TABLE: cache lookup failed for type %u",
attribute->atttypid);
attributeType = pstrdup(NameStr(((Form_pg_type) GETSTRUCT(tuple))->typname));
ReleaseSysCache(tuple);
/*
* Does it conflict with some previously inherited column?
*/
@@ -519,10 +504,12 @@ MergeAttributes(List *schema, List *supers, bool istemp,
elog(NOTICE, "CREATE TABLE: merging multiple inherited definitions of attribute \"%s\"",
attributeName);
def = (ColumnDef *) nth(exist_attno - 1, inhSchema);
if (strcmp(def->typename->name, attributeType) != 0 ||
if (typenameTypeId(def->typename) != attribute->atttypid ||
def->typename->typmod != attribute->atttypmod)
elog(ERROR, "CREATE TABLE: inherited attribute \"%s\" type conflict (%s and %s)",
attributeName, def->typename->name, attributeType);
attributeName,
TypeNameToString(def->typename),
typeidTypeName(attribute->atttypid));
/* Merge of NOT NULL constraints = OR 'em together */
def->is_not_null |= attribute->attnotnull;
/* Default and other constraints are handled below */
@@ -536,7 +523,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
def = makeNode(ColumnDef);
def->colname = pstrdup(attributeName);
typename = makeNode(TypeName);
typename->name = attributeType;
typename->typeid = attribute->atttypid;
typename->typmod = attribute->atttypmod;
def->typename = typename;
def->is_not_null = attribute->attnotnull;
@@ -640,7 +627,6 @@ MergeAttributes(List *schema, List *supers, bool istemp,
{
ColumnDef *newdef = lfirst(entry);
char *attributeName = newdef->colname;
char *attributeType = newdef->typename->name;
int exist_attno;
/*
@@ -658,10 +644,12 @@ MergeAttributes(List *schema, List *supers, bool istemp,
elog(NOTICE, "CREATE TABLE: merging attribute \"%s\" with inherited definition",
attributeName);
def = (ColumnDef *) nth(exist_attno - 1, inhSchema);
if (strcmp(def->typename->name, attributeType) != 0 ||
if (typenameTypeId(def->typename) != typenameTypeId(newdef->typename) ||
def->typename->typmod != newdef->typename->typmod)
elog(ERROR, "CREATE TABLE: attribute \"%s\" type conflict (%s and %s)",
attributeName, def->typename->name, attributeType);
attributeName,
TypeNameToString(def->typename),
TypeNameToString(newdef->typename));
/* Merge of NOT NULL constraints = OR 'em together */
def->is_not_null |= newdef->is_not_null;
/* If new def has a default, override previous default */

View File

@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.71 2002/03/20 19:43:44 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.72 2002/03/29 19:06:06 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -41,6 +41,7 @@
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/heap.h"
#include "catalog/namespace.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_language.h"
#include "catalog/pg_operator.h"
@@ -50,13 +51,19 @@
#include "fmgr.h"
#include "miscadmin.h"
#include "optimizer/cost.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
#include "parser/parse_type.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
static Oid findTypeIOFunction(const char *procname, bool isOutput);
static char *defGetString(DefElem *def);
static double defGetNumeric(DefElem *def);
static TypeName *defGetTypeName(DefElem *def);
static int defGetTypeLength(DefElem *def);
#define DEFAULT_TYPDELIM ','
@@ -77,16 +84,59 @@ case_translate_language_name(const char *input, char *output)
}
static void
compute_return_type(TypeName *returnType,
char **prorettype_p, bool *returnsSet_p)
{
/*
* Examine the "returns" clause returnType of the CREATE FUNCTION statement
* and return information about it as *prorettype_p and *returnsSet.
*
* This is more complex than the average typename lookup because we want to
* allow a shell type to be used, or even created if the specified return type
* doesn't exist yet. (Without this, there's no way to define the I/O procs
* for a new type.) But SQL function creation won't cope, so error out if
* the target language is SQL.
*/
*prorettype_p = TypeNameToInternalName(returnType);
static void
compute_return_type(TypeName *returnType, Oid languageOid,
Oid *prorettype_p, bool *returnsSet_p)
{
Oid rettype;
rettype = LookupTypeName(returnType);
if (OidIsValid(rettype))
{
if (!get_typisdefined(rettype))
{
if (languageOid == SQLlanguageId)
elog(ERROR, "SQL functions cannot return shell types");
else
elog(WARNING, "Return type \"%s\" is only a shell",
TypeNameToString(returnType));
}
}
else
{
char *typnam = TypeNameToString(returnType);
if (strcmp(typnam, "opaque") == 0)
rettype = InvalidOid;
else
{
Oid namespaceId;
char *typname;
if (languageOid == SQLlanguageId)
elog(ERROR, "Type \"%s\" does not exist", typnam);
elog(WARNING, "ProcedureCreate: type %s is not yet defined",
typnam);
namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
&typname);
rettype = TypeShellMake(typname, namespaceId);
if (!OidIsValid(rettype))
elog(ERROR, "could not create type %s", typnam);
}
}
*prorettype_p = rettype;
*returnsSet_p = returnType->setof;
}
@@ -211,34 +261,31 @@ interpret_AS_clause(Oid languageOid, const char *languageName, const List *as,
void
CreateFunction(ProcedureStmt *stmt)
{
/* pathname of executable file that executes this function, if any */
char *probin_str;
/* SQL that executes this function, if any */
char *prosrc_str;
/* Type of return value (or member of set of values) from function */
char *prorettype;
/* name of language of function, with case adjusted */
char languageName[NAMEDATALEN];
/* The function returns a set of values, as opposed to a singleton. */
Oid prorettype;
bool returnsSet;
/*
* The following are optional user-supplied attributes of the
* function.
*/
char languageName[NAMEDATALEN];
Oid languageOid;
char *funcname;
Oid namespaceId;
int32 byte_pct,
perbyte_cpu,
percall_cpu,
outin_ratio;
bool canCache,
isStrict;
HeapTuple languageTuple;
Form_pg_language languageStruct;
Oid languageOid;
/* Convert list of names to a name and namespace */
namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
&funcname);
/* Convert language name to canonical case */
case_translate_language_name(stmt->language, languageName);
/* Look up the language and validate permissions */
languageTuple = SearchSysCache(LANGNAME,
PointerGetDatum(languageName),
0, 0, 0);
@@ -259,21 +306,22 @@ CreateFunction(ProcedureStmt *stmt)
* Convert remaining parameters of CREATE to form wanted by
* ProcedureCreate.
*/
Assert(IsA(stmt->returnType, TypeName));
compute_return_type((TypeName *) stmt->returnType,
compute_return_type(stmt->returnType, languageOid,
&prorettype, &returnsSet);
compute_full_attributes(stmt->withClause,
&byte_pct, &perbyte_cpu, &percall_cpu,
&outin_ratio, &canCache, &isStrict);
interpret_AS_clause(languageOid, languageName, stmt->as, &prosrc_str, &probin_str);
interpret_AS_clause(languageOid, languageName, stmt->as,
&prosrc_str, &probin_str);
/*
* And now that we have all the parameters, and know we're permitted
* to do so, go ahead and create the function.
*/
ProcedureCreate(stmt->funcname,
ProcedureCreate(funcname,
namespaceId,
stmt->replace,
returnsSet,
prorettype,
@@ -292,27 +340,28 @@ CreateFunction(ProcedureStmt *stmt)
/* --------------------------------
/*
* DefineOperator
*
* this function extracts all the information from the
* parameter list generated by the parser and then has
* OperatorCreate() do all the actual work.
*
* 'parameters' is a list of DefElem
* --------------------------------
*/
void
DefineOperator(char *oprName,
List *parameters)
DefineOperator(List *names, List *parameters)
{
char *oprName;
Oid oprNamespace;
uint16 precedence = 0; /* operator precedence */
bool canHash = false; /* operator hashes */
bool isLeftAssociative = true; /* operator is left
* associative */
char *functionName = NULL; /* function for operator */
char *typeName1 = NULL; /* first type name */
char *typeName2 = NULL; /* second type name */
TypeName *typeName1 = NULL; /* first type name */
TypeName *typeName2 = NULL; /* second type name */
Oid typeId1 = InvalidOid; /* types converted to OID */
Oid typeId2 = InvalidOid;
char *commutatorName = NULL; /* optional commutator operator
* name */
char *negatorName = NULL; /* optional negator operator name */
@@ -323,6 +372,9 @@ DefineOperator(char *oprName,
char *sortName2 = NULL; /* optional second sort operator */
List *pl;
/* Convert list of names to a name and namespace */
oprNamespace = QualifiedNameGetCreationNamespace(names, &oprName);
/*
* loop over the definition list and extract the information we need.
*/
@@ -332,16 +384,14 @@ DefineOperator(char *oprName,
if (strcasecmp(defel->defname, "leftarg") == 0)
{
typeName1 = defGetString(defel);
if (IsA(defel->arg, TypeName) &&
((TypeName *) defel->arg)->setof)
typeName1 = defGetTypeName(defel);
if (typeName1->setof)
elog(ERROR, "setof type not implemented for leftarg");
}
else if (strcasecmp(defel->defname, "rightarg") == 0)
{
typeName2 = defGetString(defel);
if (IsA(defel->arg, TypeName) &&
((TypeName *) defel->arg)->setof)
typeName2 = defGetTypeName(defel);
if (typeName2->setof)
elog(ERROR, "setof type not implemented for rightarg");
}
else if (strcasecmp(defel->defname, "procedure") == 0)
@@ -367,15 +417,7 @@ DefineOperator(char *oprName,
else if (strcasecmp(defel->defname, "hashes") == 0)
canHash = TRUE;
else if (strcasecmp(defel->defname, "sort1") == 0)
{
/* ----------------
* XXX ( ... [ , sort1 = oprname ] [ , sort2 = oprname ] ... )
* XXX is undocumented in the reference manual source as of
* 89/8/22.
* ----------------
*/
sortName1 = defGetString(defel);
}
else if (strcasecmp(defel->defname, "sort2") == 0)
sortName2 = defGetString(defel);
else
@@ -391,12 +433,18 @@ DefineOperator(char *oprName,
if (functionName == NULL)
elog(ERROR, "Define: \"procedure\" unspecified");
/* Transform type names to type OIDs */
if (typeName1)
typeId1 = typenameTypeId(typeName1);
if (typeName2)
typeId2 = typenameTypeId(typeName2);
/*
* now have OperatorCreate do all the work..
*/
OperatorCreate(oprName, /* operator name */
typeName1, /* first type name */
typeName2, /* second type name */
typeId1, /* left type id */
typeId2, /* right type id */
functionName, /* function for operator */
precedence, /* operator precedence */
isLeftAssociative, /* operator is left associative */
@@ -412,20 +460,26 @@ DefineOperator(char *oprName,
}
/* -------------------
/*
* DefineAggregate
* ------------------
*/
void
DefineAggregate(char *aggName, List *parameters)
DefineAggregate(List *names, List *parameters)
{
char *aggName;
Oid aggNamespace;
char *transfuncName = NULL;
char *finalfuncName = NULL;
char *baseType = NULL;
char *transType = NULL;
TypeName *baseType = NULL;
TypeName *transType = NULL;
char *initval = NULL;
Oid baseTypeId;
Oid transTypeId;
List *pl;
/* Convert list of names to a name and namespace */
aggNamespace = QualifiedNameGetCreationNamespace(names, &aggName);
foreach(pl, parameters)
{
DefElem *defel = (DefElem *) lfirst(pl);
@@ -441,11 +495,11 @@ DefineAggregate(char *aggName, List *parameters)
else if (strcasecmp(defel->defname, "finalfunc") == 0)
finalfuncName = defGetString(defel);
else if (strcasecmp(defel->defname, "basetype") == 0)
baseType = defGetString(defel);
baseType = defGetTypeName(defel);
else if (strcasecmp(defel->defname, "stype") == 0)
transType = defGetString(defel);
transType = defGetTypeName(defel);
else if (strcasecmp(defel->defname, "stype1") == 0)
transType = defGetString(defel);
transType = defGetTypeName(defel);
else if (strcasecmp(defel->defname, "initcond") == 0)
initval = defGetString(defel);
else if (strcasecmp(defel->defname, "initcond1") == 0)
@@ -465,14 +519,40 @@ DefineAggregate(char *aggName, List *parameters)
if (transfuncName == NULL)
elog(ERROR, "Define: \"sfunc\" unspecified");
/*
* Handle the aggregate's base type (input data type). This can be
* specified as 'ANY' for a data-independent transition function, such
* as COUNT(*).
*/
baseTypeId = LookupTypeName(baseType);
if (OidIsValid(baseTypeId))
{
/* no need to allow aggregates on as-yet-undefined types */
if (!get_typisdefined(baseTypeId))
elog(ERROR, "Type \"%s\" is only a shell",
TypeNameToString(baseType));
}
else
{
char *typnam = TypeNameToString(baseType);
if (strcasecmp(typnam, "ANY") != 0)
elog(ERROR, "Type \"%s\" does not exist", typnam);
baseTypeId = InvalidOid;
}
/* handle transtype --- no special cases here */
transTypeId = typenameTypeId(transType);
/*
* Most of the argument-checking is done inside of AggregateCreate
*/
AggregateCreate(aggName, /* aggregate name */
aggNamespace, /* namespace */
transfuncName, /* step function name */
finalfuncName, /* final function name */
baseType, /* type of data being aggregated */
transType, /* transition data type */
baseTypeId, /* type of data being aggregated */
transTypeId, /* transition data type */
initval); /* initial condition */
}
@@ -483,12 +563,14 @@ DefineAggregate(char *aggName, List *parameters)
void
DefineDomain(CreateDomainStmt *stmt)
{
char *domainName;
Oid domainNamespace;
int16 internalLength;
int16 externalLength;
char *inputName;
char *outputName;
char *sendName;
char *receiveName;
Oid inputProcedure;
Oid outputProcedure;
Oid receiveProcedure;
Oid sendProcedure;
bool byValue;
char delimiter;
char alignment;
@@ -500,46 +582,27 @@ DefineDomain(CreateDomainStmt *stmt)
char *defaultValueBin = NULL;
bool typNotNull = false;
Oid basetypelem;
char *elemName = NULL;
int32 typNDims = 0; /* No array dimensions by default */
int32 typNDims = length(stmt->typename->arrayBounds);
HeapTuple typeTup;
char *typeName = stmt->typename->name;
List *schema = stmt->constraints;
List *listptr;
/* Convert list of names to a name and namespace */
domainNamespace = QualifiedNameGetCreationNamespace(stmt->domainname,
&domainName);
/*
* Domainnames, unlike typenames don't need to account for the '_'
* prefix. So they can be one character longer.
*/
if (strlen(stmt->domainname) > (NAMEDATALEN - 1))
if (strlen(domainName) > (NAMEDATALEN - 1))
elog(ERROR, "CREATE DOMAIN: domain names must be %d characters or less",
NAMEDATALEN - 1);
/* Test for existing Domain (or type) of that name */
typeTup = SearchSysCache(TYPENAME,
PointerGetDatum(stmt->domainname),
0, 0, 0);
if (HeapTupleIsValid(typeTup))
elog(ERROR, "CREATE DOMAIN: domain or type %s already exists",
stmt->domainname);
/*
* When the type is an array for some reason we don't actually receive
* the name here. We receive the base types name. Lets set Dims while
* were at it.
* Look up the base type.
*/
if (stmt->typename->arrayBounds > 0) {
typeName = makeArrayTypeName(stmt->typename->name);
typNDims = length(stmt->typename->arrayBounds);
}
typeTup = SearchSysCache(TYPENAME,
PointerGetDatum(typeName),
0, 0, 0);
if (!HeapTupleIsValid(typeTup))
elog(ERROR, "CREATE DOMAIN: type %s does not exist",
stmt->typename->name);
typeTup = typenameType(stmt->typename);
/*
* What we really don't want is domains of domains. This could cause all sorts
@@ -550,7 +613,7 @@ DefineDomain(CreateDomainStmt *stmt)
typtype = ((Form_pg_type) GETSTRUCT(typeTup))->typtype;
if (typtype != 'b')
elog(ERROR, "DefineDomain: %s is not a basetype",
stmt->typename->name);
TypeNameToString(stmt->typename));
/* passed by value */
byValue = ((Form_pg_type) GETSTRUCT(typeTup))->typbyval;
@@ -570,43 +633,20 @@ DefineDomain(CreateDomainStmt *stmt)
/* Array element Delimiter */
delimiter = ((Form_pg_type) GETSTRUCT(typeTup))->typdelim;
/*
* XXX this is pretty bogus: should be passing function OIDs to
* TypeCreate, not names which aren't unique.
*/
/* Input Function Name */
datum = SysCacheGetAttr(TYPENAME, typeTup, Anum_pg_type_typinput, &isnull);
Assert(!isnull);
inputName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
/* Output Function Name */
datum = SysCacheGetAttr(TYPENAME, typeTup, Anum_pg_type_typoutput, &isnull);
Assert(!isnull);
outputName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
/* ReceiveName */
datum = SysCacheGetAttr(TYPENAME, typeTup, Anum_pg_type_typreceive, &isnull);
Assert(!isnull);
receiveName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
/* SendName */
datum = SysCacheGetAttr(TYPENAME, typeTup, Anum_pg_type_typsend, &isnull);
Assert(!isnull);
sendName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
/* I/O Functions */
inputProcedure = ((Form_pg_type) GETSTRUCT(typeTup))->typinput;
outputProcedure = ((Form_pg_type) GETSTRUCT(typeTup))->typoutput;
receiveProcedure = ((Form_pg_type) GETSTRUCT(typeTup))->typreceive;
sendProcedure = ((Form_pg_type) GETSTRUCT(typeTup))->typsend;
/* Inherited default value */
datum = SysCacheGetAttr(TYPENAME, typeTup,
datum = SysCacheGetAttr(TYPEOID, typeTup,
Anum_pg_type_typdefault, &isnull);
if (!isnull)
defaultValue = DatumGetCString(DirectFunctionCall1(textout, datum));
/* Inherited default binary value */
datum = SysCacheGetAttr(TYPENAME, typeTup,
datum = SysCacheGetAttr(TYPEOID, typeTup,
Anum_pg_type_typdefaultbin, &isnull);
if (!isnull)
defaultValueBin = DatumGetCString(DirectFunctionCall1(textout, datum));
@@ -617,16 +657,6 @@ DefineDomain(CreateDomainStmt *stmt)
* This is what enables us to make a domain of an array
*/
basetypelem = ((Form_pg_type) GETSTRUCT(typeTup))->typelem;
if (basetypelem != InvalidOid)
{
HeapTuple tup;
tup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(basetypelem),
0, 0, 0);
elemName = pstrdup(NameStr(((Form_pg_type) GETSTRUCT(tup))->typname));
ReleaseSysCache(tup);
}
/*
* Run through constraints manually to avoid the additional
@@ -661,14 +691,14 @@ DefineDomain(CreateDomainStmt *stmt)
expr = cookDefault(pstate, colDef->raw_expr,
typeTup->t_data->t_oid,
stmt->typename->typmod,
stmt->typename->name);
domainName);
/*
* Expression must be stored as a nodeToString result,
* but we also require a valid textual representation
* (mainly to make life easier for pg_dump).
*/
defaultValue = deparse_expression(expr,
deparse_context_for(stmt->domainname,
deparse_context_for(domainName,
InvalidOid),
false);
defaultValueBin = nodeToString(expr);
@@ -723,19 +753,20 @@ DefineDomain(CreateDomainStmt *stmt)
/*
* Have TypeCreate do all the real work.
*/
TypeCreate(stmt->domainname, /* type name */
TypeCreate(domainName, /* type name */
domainNamespace, /* namespace */
InvalidOid, /* preassigned type oid (not done here) */
InvalidOid, /* relation oid (n/a here) */
internalLength, /* internal size */
externalLength, /* external size */
'd', /* type-type (domain type) */
delimiter, /* array element delimiter */
inputName, /* input procedure */
outputName, /* output procedure */
receiveName, /* receive procedure */
sendName, /* send procedure */
elemName, /* element type name */
typeName, /* base type name */
inputProcedure, /* input procedure */
outputProcedure, /* output procedure */
receiveProcedure, /* receive procedure */
sendProcedure, /* send procedure */
basetypelem, /* element type ID */
typeTup->t_data->t_oid, /* base type ID */
defaultValue, /* default type value (text) */
defaultValueBin, /* default type value (binary) */
byValue, /* passed by value */
@@ -743,7 +774,7 @@ DefineDomain(CreateDomainStmt *stmt)
storage, /* TOAST strategy */
stmt->typename->typmod, /* typeMod value */
typNDims, /* Array dimensions for base type */
typNotNull); /* Type NOT NULL */
typNotNull); /* Type NOT NULL */
/*
* Now we can clean up.
@@ -756,11 +787,13 @@ DefineDomain(CreateDomainStmt *stmt)
* Registers a new type.
*/
void
DefineType(char *typeName, List *parameters)
DefineType(List *names, List *parameters)
{
char *typeName;
Oid typeNamespace;
int16 internalLength = -1; /* int2 */
int16 externalLength = -1; /* int2 */
char *elemName = NULL;
Oid elemType = InvalidOid;
char *inputName = NULL;
char *outputName = NULL;
char *sendName = NULL;
@@ -768,10 +801,18 @@ DefineType(char *typeName, List *parameters)
char *defaultValue = NULL;
bool byValue = false;
char delimiter = DEFAULT_TYPDELIM;
char *shadow_type;
List *pl;
char alignment = 'i'; /* default alignment */
char storage = 'p'; /* default TOAST storage method */
Oid inputOid;
Oid outputOid;
Oid sendOid;
Oid receiveOid;
char *shadow_type;
List *pl;
Oid typoid;
/* Convert list of names to a name and namespace */
typeNamespace = QualifiedNameGetCreationNamespace(names, &typeName);
/*
* Type names must be one character shorter than other names, allowing
@@ -796,16 +837,16 @@ DefineType(char *typeName, List *parameters)
outputName = defGetString(defel);
else if (strcasecmp(defel->defname, "send") == 0)
sendName = defGetString(defel);
else if (strcasecmp(defel->defname, "receive") == 0)
receiveName = defGetString(defel);
else if (strcasecmp(defel->defname, "delimiter") == 0)
{
char *p = defGetString(defel);
delimiter = p[0];
}
else if (strcasecmp(defel->defname, "receive") == 0)
receiveName = defGetString(defel);
else if (strcasecmp(defel->defname, "element") == 0)
elemName = defGetString(defel);
elemType = typenameTypeId(defGetTypeName(defel));
else if (strcasecmp(defel->defname, "default") == 0)
defaultValue = defGetString(defel);
else if (strcasecmp(defel->defname, "passedbyvalue") == 0)
@@ -867,30 +908,44 @@ DefineType(char *typeName, List *parameters)
if (outputName == NULL)
elog(ERROR, "Define: \"output\" unspecified");
/* Convert I/O proc names to OIDs */
inputOid = findTypeIOFunction(inputName, false);
outputOid = findTypeIOFunction(outputName, true);
if (sendName)
sendOid = findTypeIOFunction(sendName, true);
else
sendOid = outputOid;
if (receiveName)
receiveOid = findTypeIOFunction(receiveName, false);
else
receiveOid = inputOid;
/*
* now have TypeCreate do all the real work.
*/
TypeCreate(typeName, /* type name */
InvalidOid, /* preassigned type oid (not done here) */
InvalidOid, /* relation oid (n/a here) */
internalLength, /* internal size */
externalLength, /* external size */
'b', /* type-type (base type) */
delimiter, /* array element delimiter */
inputName, /* input procedure */
outputName, /* output procedure */
receiveName, /* receive procedure */
sendName, /* send procedure */
elemName, /* element type name */
NULL, /* base type name (only for domains) */
defaultValue, /* default type value */
NULL, /* no binary form available */
byValue, /* passed by value */
alignment, /* required alignment */
storage, /* TOAST strategy */
-1, /* typMod (Domains only) */
0, /* Array Dimensions of typbasetype */
'f'); /* Type NOT NULL */
typoid =
TypeCreate(typeName, /* type name */
typeNamespace, /* namespace */
InvalidOid, /* preassigned type oid (not done here) */
InvalidOid, /* relation oid (n/a here) */
internalLength, /* internal size */
externalLength, /* external size */
'b', /* type-type (base type) */
delimiter, /* array element delimiter */
inputOid, /* input procedure */
outputOid, /* output procedure */
receiveOid, /* receive procedure */
sendOid, /* send procedure */
elemType, /* element type ID */
InvalidOid, /* base type ID (only for domains) */
defaultValue, /* default type value */
NULL, /* no binary form available */
byValue, /* passed by value */
alignment, /* required alignment */
storage, /* TOAST strategy */
-1, /* typMod (Domains only) */
0, /* Array Dimensions of typbasetype */
false); /* Type NOT NULL */
/*
* When we create a base type (as opposed to a complex type) we need
@@ -902,18 +957,19 @@ DefineType(char *typeName, List *parameters)
alignment = (alignment == 'd') ? 'd' : 'i';
TypeCreate(shadow_type, /* type name */
typeNamespace, /* namespace */
InvalidOid, /* preassigned type oid (not done here) */
InvalidOid, /* relation oid (n/a here) */
-1, /* internal size */
-1, /* external size */
'b', /* type-type (base type) */
DEFAULT_TYPDELIM, /* array element delimiter */
"array_in", /* input procedure */
"array_out", /* output procedure */
"array_in", /* receive procedure */
"array_out", /* send procedure */
typeName, /* element type name */
NULL, /* base type name */
F_ARRAY_IN, /* input procedure */
F_ARRAY_OUT, /* output procedure */
F_ARRAY_IN, /* receive procedure */
F_ARRAY_OUT, /* send procedure */
typoid, /* element type ID */
InvalidOid, /* base type ID */
NULL, /* never a default type value */
NULL, /* binary default isn't sent either */
false, /* never passed by value */
@@ -921,11 +977,65 @@ DefineType(char *typeName, List *parameters)
'x', /* ARRAY is always toastable */
-1, /* typMod (Domains only) */
0, /* Array dimensions of typbasetype */
'f'); /* Type NOT NULL */
false); /* Type NOT NULL */
pfree(shadow_type);
}
static Oid
findTypeIOFunction(const char *procname, bool isOutput)
{
Oid argList[FUNC_MAX_ARGS];
int nargs;
Oid procOid;
/*
* First look for a 1-argument func with all argtypes 0. This is
* valid for all kinds of procedure.
*/
MemSet(argList, 0, FUNC_MAX_ARGS * sizeof(Oid));
procOid = GetSysCacheOid(PROCNAME,
PointerGetDatum(procname),
Int32GetDatum(1),
PointerGetDatum(argList),
0);
if (!OidIsValid(procOid))
{
/*
* Alternatively, input procedures may take 3 args (data
* value, element OID, atttypmod); the pg_proc argtype
* signature is 0,OIDOID,INT4OID. Output procedures may
* take 2 args (data value, element OID).
*/
if (isOutput)
{
/* output proc */
nargs = 2;
argList[1] = OIDOID;
}
else
{
/* input proc */
nargs = 3;
argList[1] = OIDOID;
argList[2] = INT4OID;
}
procOid = GetSysCacheOid(PROCNAME,
PointerGetDatum(procname),
Int32GetDatum(nargs),
PointerGetDatum(argList),
0);
if (!OidIsValid(procOid))
func_error("TypeCreate", procname, 1, argList, NULL);
}
return procOid;
}
static char *
defGetString(DefElem *def)
{
@@ -951,7 +1061,7 @@ defGetString(DefElem *def)
case T_String:
return strVal(def->arg);
case T_TypeName:
return TypeNameToInternalName((TypeName *) def->arg);
return TypeNameToString((TypeName *) def->arg);
default:
elog(ERROR, "Define: cannot interpret argument of \"%s\"",
def->defname);
@@ -978,6 +1088,32 @@ defGetNumeric(DefElem *def)
return 0; /* keep compiler quiet */
}
static TypeName *
defGetTypeName(DefElem *def)
{
if (def->arg == NULL)
elog(ERROR, "Define: \"%s\" requires a parameter",
def->defname);
switch (nodeTag(def->arg))
{
case T_TypeName:
return (TypeName *) def->arg;
case T_String:
{
/* Allow quoted typename for backwards compatibility */
TypeName *n = makeNode(TypeName);
n->names = makeList1(def->arg);
n->typmod = -1;
return n;
}
default:
elog(ERROR, "Define: argument of \"%s\" must be a type name",
def->defname);
}
return NULL; /* keep compiler quiet */
}
static int
defGetTypeLength(DefElem *def)
{
@@ -998,7 +1134,7 @@ defGetTypeLength(DefElem *def)
break;
case T_TypeName:
/* cope if grammar chooses to believe "variable" is a typename */
if (strcasecmp(TypeNameToInternalName((TypeName *) def->arg),
if (strcasecmp(TypeNameToString((TypeName *) def->arg),
"variable") == 0)
return -1; /* variable length */
break;

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.71 2002/03/21 23:27:21 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.72 2002/03/29 19:06:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -24,8 +24,8 @@
#include "miscadmin.h"
#include "parser/parse.h"
#include "parser/parse_agg.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
#include "parser/parse_type.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
@@ -43,29 +43,20 @@
*/
void
RemoveOperator(char *operatorName, /* operator name */
char *typeName1, /* left argument type name */
char *typeName2) /* right argument type name */
TypeName *typeName1, /* left argument type name */
TypeName *typeName2) /* right argument type name */
{
Relation relation;
HeapTuple tup;
Oid typeId1 = InvalidOid;
Oid typeId2 = InvalidOid;
bool defined;
char oprtype;
if (typeName1)
{
typeId1 = TypeGet(typeName1, &defined);
if (!OidIsValid(typeId1))
elog(ERROR, "RemoveOperator: type '%s' does not exist", typeName1);
}
typeId1 = typenameTypeId(typeName1);
if (typeName2)
{
typeId2 = TypeGet(typeName2, &defined);
if (!OidIsValid(typeId2))
elog(ERROR, "RemoveOperator: type '%s' does not exist", typeName2);
}
typeId2 = typenameTypeId(typeName2);
if (OidIsValid(typeId1) && OidIsValid(typeId2))
oprtype = 'b';
@@ -99,20 +90,20 @@ RemoveOperator(char *operatorName, /* operator name */
{
elog(ERROR, "RemoveOperator: binary operator '%s' taking '%s' and '%s' does not exist",
operatorName,
typeName1,
typeName2);
TypeNameToString(typeName1),
TypeNameToString(typeName2));
}
else if (OidIsValid(typeId1))
{
elog(ERROR, "RemoveOperator: right unary operator '%s' taking '%s' does not exist",
operatorName,
typeName1);
TypeNameToString(typeName1));
}
else
{
elog(ERROR, "RemoveOperator: left unary operator '%s' taking '%s' does not exist",
operatorName,
typeName2);
TypeNameToString(typeName2));
}
}
heap_freetuple(tup);
@@ -213,16 +204,13 @@ AttributeAndRelationRemove(Oid typeOid)
rel = heap_openr(RelationRelationName, RowExclusiveLock);
while (PointerIsValid((char *) optr->next))
{
key[0].sk_argument = (Datum) (optr++)->reloid;
Oid relOid = (optr++)->reloid;
key[0].sk_argument = ObjectIdGetDatum(relOid);
scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
tup = heap_getnext(scan, 0);
if (HeapTupleIsValid(tup))
{
char *name;
name = NameStr(((Form_pg_class) GETSTRUCT(tup))->relname);
heap_drop_with_catalog(name, allowSystemTableMods);
}
heap_drop_with_catalog(relOid, allowSystemTableMods);
heap_endscan(scan);
}
heap_close(rel, RowExclusiveLock);
@@ -231,42 +219,68 @@ AttributeAndRelationRemove(Oid typeOid)
/*
* TypeRemove
* Removes the type 'typeName' and all attributes and relations that
* use it.
* Removes a datatype.
*
* NOTE: since this tries to remove the associated array type too, it'll
* only work on scalar types.
*/
void
RemoveType(char *typeName) /* type name to be removed */
RemoveType(List *names)
{
TypeName *typename;
Relation relation;
Oid typeoid;
HeapTuple tup;
char *shadow_type;
/* Make a TypeName so we can use standard type lookup machinery */
typename = makeNode(TypeName);
typename->names = names;
typename->typmod = -1;
typename->arrayBounds = NIL;
relation = heap_openr(TypeRelationName, RowExclusiveLock);
tup = SearchSysCache(TYPENAME,
PointerGetDatum(typeName),
/* Use LookupTypeName here so that shell types can be removed. */
typeoid = LookupTypeName(typename);
if (!OidIsValid(typeoid))
elog(ERROR, "Type \"%s\" does not exist",
TypeNameToString(typename));
tup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typeoid),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "RemoveType: type '%s' does not exist", typeName);
elog(ERROR, "Type \"%s\" does not exist",
TypeNameToString(typename));
if (!pg_type_ownercheck(tup->t_data->t_oid, GetUserId()))
if (!pg_type_ownercheck(typeoid, GetUserId()))
elog(ERROR, "RemoveType: type '%s': permission denied",
typeName);
TypeNameToString(typename));
/* Delete any comments associated with this type */
DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
DeleteComments(typeoid, RelationGetRelid(relation));
/* Remove the type tuple from pg_type */
simple_heap_delete(relation, &tup->t_self);
ReleaseSysCache(tup);
/* Also, delete the "array of" that type */
shadow_type = makeArrayTypeName(typeName);
tup = SearchSysCache(TYPENAME,
PointerGetDatum(shadow_type),
/* Now, delete the "array of" that type */
typename->arrayBounds = makeList1(makeInteger(1));
typeoid = LookupTypeName(typename);
if (!OidIsValid(typeoid))
elog(ERROR, "Type \"%s\" does not exist",
TypeNameToString(typename));
tup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typeoid),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "RemoveType: type '%s' does not exist", shadow_type);
elog(ERROR, "Type \"%s\" does not exist",
TypeNameToString(typename));
DeleteComments(typeoid, RelationGetRelid(relation));
simple_heap_delete(relation, &tup->t_self);
@@ -277,13 +291,14 @@ RemoveType(char *typeName) /* type name to be removed */
/*
* RemoveDomain
* Removes the domain 'typeName' and all attributes and relations that
* use it.
* Removes a domain.
*/
void
RemoveDomain(char *domainName, int behavior)
RemoveDomain(List *names, int behavior)
{
TypeName *typename;
Relation relation;
Oid typeoid;
HeapTuple tup;
char typtype;
@@ -291,31 +306,44 @@ RemoveDomain(char *domainName, int behavior)
if (behavior == CASCADE)
elog(ERROR, "DROP DOMAIN does not support the CASCADE keyword");
/* Make a TypeName so we can use standard type lookup machinery */
typename = makeNode(TypeName);
typename->names = names;
typename->typmod = -1;
typename->arrayBounds = NIL;
relation = heap_openr(TypeRelationName, RowExclusiveLock);
tup = SearchSysCache(TYPENAME,
PointerGetDatum(domainName),
typeoid = typenameTypeId(typename);
tup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typeoid),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "RemoveType: type '%s' does not exist", domainName);
elog(ERROR, "RemoveDomain: type '%s' does not exist",
TypeNameToString(typename));
if (!pg_type_ownercheck(tup->t_data->t_oid, GetUserId()))
if (!pg_type_ownercheck(typeoid, GetUserId()))
elog(ERROR, "RemoveDomain: type '%s': permission denied",
domainName);
TypeNameToString(typename));
/* Check that this is actually a domain */
typtype = ((Form_pg_type) GETSTRUCT(tup))->typtype;
if (typtype != 'd')
elog(ERROR, "%s is not a domain", domainName);
elog(ERROR, "%s is not a domain",
TypeNameToString(typename));
/* Delete any comments associated with this type */
DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
DeleteComments(typeoid, RelationGetRelid(relation));
/* Remove the type tuple from pg_type */
simple_heap_delete(relation, &tup->t_self);
ReleaseSysCache(tup);
/* At present, domains don't have associated array types */
heap_close(relation, RowExclusiveLock);
}
@@ -345,20 +373,19 @@ RemoveFunction(char *functionName, /* function name to be removed */
for (i = 0; i < nargs; i++)
{
TypeName *t = (TypeName *) lfirst(argTypes);
char *typnam = TypeNameToInternalName(t);
argList[i] = LookupTypeName(t);
if (!OidIsValid(argList[i]))
{
char *typnam = TypeNameToString(t);
if (strcmp(typnam, "opaque") == 0)
argList[i] = InvalidOid;
else
elog(ERROR, "Type \"%s\" does not exist", typnam);
}
argTypes = lnext(argTypes);
if (strcmp(typnam, "opaque") == 0)
argList[i] = InvalidOid;
else
{
argList[i] = GetSysCacheOid(TYPENAME,
PointerGetDatum(typnam),
0, 0, 0);
if (!OidIsValid(argList[i]))
elog(ERROR, "RemoveFunction: type '%s' not found", typnam);
}
}
relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
@@ -393,12 +420,11 @@ RemoveFunction(char *functionName, /* function name to be removed */
}
void
RemoveAggregate(char *aggName, char *aggType)
RemoveAggregate(char *aggName, TypeName *aggType)
{
Relation relation;
HeapTuple tup;
Oid basetypeID;
bool defined;
/*
* if a basetype is passed in, then attempt to find an aggregate for
@@ -410,11 +436,7 @@ RemoveAggregate(char *aggName, char *aggType)
*/
if (aggType)
{
basetypeID = TypeGet(aggType, &defined);
if (!OidIsValid(basetypeID))
elog(ERROR, "RemoveAggregate: type '%s' does not exist", aggType);
}
basetypeID = typenameTypeId(aggType);
else
basetypeID = InvalidOid;

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.65 2002/03/26 19:15:43 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.66 2002/03/29 19:06:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -69,16 +69,14 @@ static void update_ri_trigger_args(Oid relid,
* delete original attribute from attribute catalog
*/
void
renameatt(char *relname,
renameatt(Oid relid,
char *oldattname,
char *newattname,
int recurse)
bool recurse)
{
Relation targetrelation;
Relation attrelation;
HeapTuple reltup,
atttup;
Oid relid;
HeapTuple atttup;
List *indexoidlist;
List *indexoidscan;
@@ -86,8 +84,7 @@ renameatt(char *relname,
* Grab an exclusive lock on the target table, which we will NOT
* release until end of transaction.
*/
targetrelation = heap_openr(relname, AccessExclusiveLock);
relid = RelationGetRelid(targetrelation);
targetrelation = heap_open(relid, AccessExclusiveLock);
/*
* permissions checking. this would normally be done in utility.c,
@@ -95,12 +92,13 @@ renameatt(char *relname,
*
* normally, only the owner of a class can change its schema.
*/
if (!allowSystemTableMods && IsSystemRelationName(relname))
if (!allowSystemTableMods
&& IsSystemRelationName(RelationGetRelationName(targetrelation)))
elog(ERROR, "renameatt: class \"%s\" is a system catalog",
relname);
RelationGetRelationName(targetrelation));
if (!pg_class_ownercheck(relid, GetUserId()))
elog(ERROR, "renameatt: you do not own class \"%s\"",
relname);
RelationGetRelationName(targetrelation));
/*
* if the 'recurse' flag is set then we are supposed to rename this
@@ -127,25 +125,11 @@ renameatt(char *relname,
foreach(child, children)
{
Oid childrelid = lfirsti(child);
char childname[NAMEDATALEN];
if (childrelid == relid)
continue;
reltup = SearchSysCache(RELOID,
ObjectIdGetDatum(childrelid),
0, 0, 0);
if (!HeapTupleIsValid(reltup))
{
elog(ERROR, "renameatt: can't find catalog entry for inheriting class with oid %u",
childrelid);
}
/* make copy of cache value, could disappear in call */
StrNCpy(childname,
NameStr(((Form_pg_class) GETSTRUCT(reltup))->relname),
NAMEDATALEN);
ReleaseSysCache(reltup);
/* note we need not recurse again! */
renameatt(childname, oldattname, newattname, 0);
renameatt(childrelid, oldattname, newattname, false);
}
}
@@ -356,7 +340,7 @@ renamerel(const RangeVar *relation, const char *newrelname)
* Also rename the associated type, if any.
*/
if (relkind != RELKIND_INDEX)
TypeRename(relation->relname, newrelname);
TypeRename(relation->relname, namespaceId, newrelname);
/*
* If it's a view, must also rename the associated ON SELECT rule.

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.74 2002/03/22 02:56:31 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.75 2002/03/29 19:06:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -17,6 +17,7 @@
#include <ctype.h>
#include "access/heapam.h"
#include "catalog/pg_type.h"
#include "commands/creatinh.h"
#include "commands/sequence.h"
#include "miscadmin.h"
@@ -85,8 +86,6 @@ DefineSequence(CreateSeqStmt *seq)
{
FormData_pg_sequence new;
CreateStmt *stmt = makeNode(CreateStmt);
ColumnDef *coldef;
TypeName *typnam;
Oid seqoid;
Relation rel;
Buffer buf;
@@ -108,9 +107,12 @@ DefineSequence(CreateSeqStmt *seq)
stmt->tableElts = NIL;
for (i = SEQ_COL_FIRSTCOL; i <= SEQ_COL_LASTCOL; i++)
{
ColumnDef *coldef;
TypeName *typnam;
typnam = makeNode(TypeName);
typnam->setof = FALSE;
typnam->arrayBounds = NULL;
typnam->arrayBounds = NIL;
typnam->typmod = -1;
coldef = makeNode(ColumnDef);
coldef->typename = typnam;
@@ -122,48 +124,48 @@ DefineSequence(CreateSeqStmt *seq)
switch (i)
{
case SEQ_COL_NAME:
typnam->name = "name";
typnam->typeid = NAMEOID;
coldef->colname = "sequence_name";
namestrcpy(&name, seq->sequence->relname);
value[i - 1] = NameGetDatum(&name);
break;
case SEQ_COL_LASTVAL:
typnam->name = "int8";
typnam->typeid = INT8OID;
coldef->colname = "last_value";
value[i - 1] = Int64GetDatumFast(new.last_value);
break;
case SEQ_COL_INCBY:
typnam->name = "int8";
typnam->typeid = INT8OID;
coldef->colname = "increment_by";
value[i - 1] = Int64GetDatumFast(new.increment_by);
break;
case SEQ_COL_MAXVALUE:
typnam->name = "int8";
typnam->typeid = INT8OID;
coldef->colname = "max_value";
value[i - 1] = Int64GetDatumFast(new.max_value);
break;
case SEQ_COL_MINVALUE:
typnam->name = "int8";
typnam->typeid = INT8OID;
coldef->colname = "min_value";
value[i - 1] = Int64GetDatumFast(new.min_value);
break;
case SEQ_COL_CACHE:
typnam->name = "int8";
typnam->typeid = INT8OID;
coldef->colname = "cache_value";
value[i - 1] = Int64GetDatumFast(new.cache_value);
break;
case SEQ_COL_LOG:
typnam->name = "int8";
typnam->typeid = INT8OID;
coldef->colname = "log_cnt";
value[i - 1] = Int64GetDatum((int64) 1);
break;
case SEQ_COL_CYCLE:
typnam->name = "bool";
typnam->typeid = BOOLOID;
coldef->colname = "is_cycled";
value[i - 1] = BoolGetDatum(new.is_cycled);
break;
case SEQ_COL_CALLED:
typnam->name = "bool";
typnam->typeid = BOOLOID;
coldef->colname = "is_called";
value[i - 1] = BoolGetDatum(false);
break;

View File

@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.60 2002/03/06 06:09:39 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.61 2002/03/29 19:06:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,11 +21,12 @@
#include "access/xact.h"
#include "catalog/pg_shadow.h"
#include "catalog/pg_type.h"
#include "commands/variable.h"
#include "miscadmin.h"
#include "optimizer/cost.h"
#include "optimizer/paths.h"
#include "parser/parse_expr.h"
#include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/guc.h"
@@ -390,7 +391,9 @@ parse_timezone(List *args)
type = p->typename;
if (type != NULL)
{
if (strcmp(type->name, "interval") == 0)
Oid typeOid = typenameTypeId(type);
if (typeOid == INTERVALOID)
{
Interval *interval;
@@ -402,7 +405,7 @@ parse_timezone(List *args)
elog(ERROR, "SET TIME ZONE illegal INTERVAL; month not allowed");
CTimeZone = interval->time;
}
else if (strcmp(type->name, "float8") == 0)
else if (typeOid == FLOAT8OID)
{
float8 time;
@@ -414,7 +417,7 @@ parse_timezone(List *args)
* We do not actually generate an integer constant in gram.y
* so this is not used...
*/
else if (strcmp(type->name, "int4") == 0)
else if (typeOid == INT4OID)
{
int32 time;

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.60 2002/03/22 02:56:31 tgl Exp $
* $Id: view.c,v 1.61 2002/03/29 19:06:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -14,6 +14,7 @@
#include "access/xact.h"
#include "catalog/heap.h"
#include "catalog/namespace.h"
#include "commands/creatinh.h"
#include "commands/view.h"
#include "miscadmin.h"
@@ -24,6 +25,7 @@
#include "rewrite/rewriteManip.h"
#include "rewrite/rewriteRemove.h"
#include "rewrite/rewriteSupport.h"
#include "utils/syscache.h"
/*---------------------------------------------------------------------
@@ -38,10 +40,9 @@
*---------------------------------------------------------------------
*/
static Oid
DefineVirtualRelation(char *relname, List *tlist)
DefineVirtualRelation(const RangeVar *relation, List *tlist)
{
CreateStmt *createStmt = makeNode(CreateStmt);
RangeVar *rel = makeNode(RangeVar);
List *attrList,
*t;
@@ -57,14 +58,12 @@ DefineVirtualRelation(char *relname, List *tlist)
if (!res->resjunk)
{
char *resname = res->resname;
char *restypename = typeidTypeName(res->restype);
ColumnDef *def = makeNode(ColumnDef);
TypeName *typename = makeNode(TypeName);
def->colname = pstrdup(resname);
def->colname = pstrdup(res->resname);
typename->name = pstrdup(restypename);
typename->typeid = res->restype;
typename->typmod = res->restypmod;
def->typename = typename;
@@ -84,10 +83,7 @@ DefineVirtualRelation(char *relname, List *tlist)
* now create the parameters for keys/inheritance etc. All of them are
* nil...
*/
rel->relname = relname;
rel->schemaname = NULL; /* XXX wrong */
rel->istemp = false;
createStmt->relation = rel;
createStmt->relation = (RangeVar *) relation;
createStmt->tableElts = attrList;
createStmt->inhRelations = NIL;
createStmt->constraints = NIL;
@@ -100,25 +96,19 @@ DefineVirtualRelation(char *relname, List *tlist)
}
static RuleStmt *
FormViewRetrieveRule(char *viewName, Query *viewParse)
FormViewRetrieveRule(const RangeVar *view, Query *viewParse)
{
RuleStmt *rule;
char *rname;
RangeVar *rel;
/*
* Create a RuleStmt that corresponds to the suitable rewrite rule
* args for DefineQueryRewrite();
*/
rname = MakeRetrieveViewRuleName(viewName);
rel = makeNode(RangeVar);
rel->relname = pstrdup(viewName);
rel->inhOpt = INH_NO;
rel->alias = NULL;
rname = MakeRetrieveViewRuleName(view->relname);
rule = makeNode(RuleStmt);
rule->relation = rel;
rule->relation = copyObject((RangeVar *) view);
rule->rulename = pstrdup(rname);
rule->whereClause = NULL;
rule->event = CMD_SELECT;
@@ -129,7 +119,7 @@ FormViewRetrieveRule(char *viewName, Query *viewParse)
}
static void
DefineViewRules(char *viewName, Query *viewParse)
DefineViewRules(const RangeVar *view, Query *viewParse)
{
RuleStmt *retrieve_rule;
@@ -139,13 +129,13 @@ DefineViewRules(char *viewName, Query *viewParse)
RuleStmt *delete_rule;
#endif
retrieve_rule = FormViewRetrieveRule(viewName, viewParse);
retrieve_rule = FormViewRetrieveRule(view, viewParse);
#ifdef NOTYET
replace_rule = FormViewReplaceRule(viewName, viewParse);
append_rule = FormViewAppendRule(viewName, viewParse);
delete_rule = FormViewDeleteRule(viewName, viewParse);
replace_rule = FormViewReplaceRule(view, viewParse);
append_rule = FormViewAppendRule(view, viewParse);
delete_rule = FormViewDeleteRule(view, viewParse);
#endif
DefineQueryRewrite(retrieve_rule);
@@ -231,7 +221,7 @@ UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse)
*-------------------------------------------------------------------
*/
void
DefineView(char *viewName, Query *viewParse)
DefineView(const RangeVar *view, Query *viewParse)
{
Oid viewOid;
@@ -240,7 +230,7 @@ DefineView(char *viewName, Query *viewParse)
*
* NOTE: if it already exists, the xact will be aborted.
*/
viewOid = DefineVirtualRelation(viewName, viewParse->targetList);
viewOid = DefineVirtualRelation(view, viewParse->targetList);
/*
* The relation we have just created is not visible to any other
@@ -258,7 +248,7 @@ DefineView(char *viewName, Query *viewParse)
/*
* Now create the rules associated with the view.
*/
DefineViewRules(viewName, viewParse);
DefineViewRules(view, viewParse);
}
/*------------------------------------------------------------------
@@ -268,11 +258,14 @@ DefineView(char *viewName, Query *viewParse)
*------------------------------------------------------------------
*/
void
RemoveView(char *viewName)
RemoveView(const RangeVar *view)
{
Oid viewOid;
viewOid = RangeVarGetRelid(view, false);
/*
* We just have to drop the relation; the associated rules will be
* cleaned up automatically.
*/
heap_drop_with_catalog(viewName, allowSystemTableMods);
heap_drop_with_catalog(viewOid, allowSystemTableMods);
}