diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/cluster.c | 4 | ||||
-rw-r--r-- | src/backend/commands/command.c | 257 | ||||
-rw-r--r-- | src/backend/commands/comment.c | 101 | ||||
-rw-r--r-- | src/backend/commands/copy.c | 27 | ||||
-rw-r--r-- | src/backend/commands/creatinh.c | 72 | ||||
-rw-r--r-- | src/backend/commands/define.c | 490 | ||||
-rw-r--r-- | src/backend/commands/remove.c | 160 | ||||
-rw-r--r-- | src/backend/commands/rename.c | 38 | ||||
-rw-r--r-- | src/backend/commands/sequence.c | 28 | ||||
-rw-r--r-- | src/backend/commands/variable.c | 13 | ||||
-rw-r--r-- | src/backend/commands/view.c | 53 |
11 files changed, 661 insertions, 582 deletions
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 0bd64232d1a..151577ae2d2 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -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(); diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index bf7980d42c8..9180c539ff2 100644 --- a/src/backend/commands/command.c +++ b/src/backend/commands/command.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.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); - if (!pg_class_ownercheck(myrelid, GetUserId())) - elog(ERROR, "ALTER TABLE: permission denied"); - - heap_close(rel, NoLock); /* close rel, but keep lock! */ + RelationGetRelationName(rel)); + if (!pg_class_ownercheck(myrelid, GetUserId())) + 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); } } diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index cdc8ce35be3..f8e5bc6fc6f 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -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); - - arguments = lnext(arguments); - if (strcmp(typnam, "opaque") == 0) - argoids[i] = InvalidOid; - else + argoids[i] = LookupTypeName(t); + if (!OidIsValid(argoids[i])) { - argoids[i] = GetSysCacheOid(TYPENAME, - PointerGetDatum(typnam), - 0, 0, 0); - if (!OidIsValid(argoids[i])) - elog(ERROR, "CommentProc: type '%s' not found", typnam); + char *typnam = TypeNameToString(t); + + if (strcmp(typnam, "opaque") == 0) + argoids[i] = InvalidOid; + else + elog(ERROR, "Type \"%s\" does not exist", typnam); } + + arguments = lnext(arguments); } /* 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); - 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 */ + leftoid = typenameTypeId(typenode1); - if (righttype != NULL) - { - rightoid = TypeGet(righttype, &defined); - if (!OidIsValid(rightoid)) - elog(ERROR, "right type '%s' does not exist", righttype); - } + /* Attempt to fetch the right type oid, if specified */ + if (typenode2 != NULL) + 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'", diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index fc4f80468cd..45e108027fd 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -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) { diff --git a/src/backend/commands/creatinh.c b/src/backend/commands/creatinh.c index 2d68d5d6e7f..1cf84f17a3e 100644 --- a/src/backend/commands/creatinh.c +++ b/src/backend/commands/creatinh.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.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,27 +486,12 @@ 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? */ exist_attno = findAttrByName(attributeName, inhSchema); @@ -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 */ diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c index 2441e49bcaa..1d1139bd362 100644 --- a/src/backend/commands/define.c +++ b/src/backend/commands/define.c @@ -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) @@ -466,13 +520,39 @@ DefineAggregate(char *aggName, List *parameters) 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; diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c index 0dbadd95779..fb73fe3bd02 100644 --- a/src/backend/commands/remove.c +++ b/src/backend/commands/remove.c @@ -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); - - argTypes = lnext(argTypes); - if (strcmp(typnam, "opaque") == 0) - argList[i] = InvalidOid; - else + argList[i] = LookupTypeName(t); + if (!OidIsValid(argList[i])) { - argList[i] = GetSysCacheOid(TYPENAME, - PointerGetDatum(typnam), - 0, 0, 0); - if (!OidIsValid(argList[i])) - elog(ERROR, "RemoveFunction: type '%s' not found", typnam); + char *typnam = TypeNameToString(t); + + if (strcmp(typnam, "opaque") == 0) + argList[i] = InvalidOid; + else + elog(ERROR, "Type \"%s\" does not exist", typnam); } + + argTypes = lnext(argTypes); } 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; diff --git a/src/backend/commands/rename.c b/src/backend/commands/rename.c index f050aa9f7fc..0f4c83fbebf 100644 --- a/src/backend/commands/rename.c +++ b/src/backend/commands/rename.c @@ -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. diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index d0b1f7d4d58..54ca1d19a10 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.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; diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c index 466bfec202f..1794d2bda73 100644 --- a/src/backend/commands/variable.c +++ b/src/backend/commands/variable.c @@ -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; diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index 3b4bf7da13f..6b8652db5b7 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: view.c,v 1.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); } |