* pg_type.c
* routines to support manipulation of the pg_type relation
*
- * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
#include "utils/rel.h"
#include "utils/syscache.h"
-/* Potentially set by contrib/pg_upgrade_support functions */
+/* Potentially set by pg_upgrade_support functions */
Oid binary_upgrade_next_pg_type_oid = InvalidOid;
/* ----------------------------------------------------------------
* with correct ones, and "typisdefined" will be set to true.
* ----------------------------------------------------------------
*/
-Oid
+ObjectAddress
TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
{
Relation pg_type_desc;
bool nulls[Natts_pg_type];
Oid typoid;
NameData name;
+ ObjectAddress address;
Assert(PointerIsValid(typeName));
for (i = 0; i < Natts_pg_type; ++i)
{
nulls[i] = false;
- values[i] = (Datum) NULL; /* redundant, but safe */
+ values[i] = (Datum) NULL; /* redundant, but safe */
}
/*
if (!OidIsValid(binary_upgrade_next_pg_type_oid))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("pg_type OID value not set when in binary upgrade mode")));
+ errmsg("pg_type OID value not set when in binary upgrade mode")));
HeapTupleSetOid(tup, binary_upgrade_next_pg_type_oid);
binary_upgrade_next_pg_type_oid = InvalidOid;
/*
* insert the tuple in the relation and get the tuple's oid.
*/
- typoid = simple_heap_insert(pg_type_desc, tup);
-
- CatalogUpdateIndexes(pg_type_desc, tup);
+ typoid = CatalogTupleInsert(pg_type_desc, tup);
/*
* Create dependencies. We can/must skip this in bootstrap mode.
/* Post creation hook for new shell type */
InvokeObjectPostCreateHook(TypeRelationId, typoid, 0);
+ ObjectAddressSet(address, TypeRelationId, typoid);
+
/*
* clean up and return the type-oid
*/
heap_freetuple(tup);
heap_close(pg_type_desc, RowExclusiveLock);
- return typoid;
+ return address;
}
/* ----------------------------------------------------------------
*
* This does all the necessary work needed to define a new type.
*
- * Returns the OID assigned to the new type. If newTypeOid is
- * zero (the normal case), a new OID is created; otherwise we
- * use exactly that OID.
+ * Returns the ObjectAddress assigned to the new type.
+ * If newTypeOid is zero (the normal case), a new OID is created;
+ * otherwise we use exactly that OID.
* ----------------------------------------------------------------
*/
-Oid
+ObjectAddress
TypeCreate(Oid newTypeOid,
const char *typeName,
Oid typeNamespace,
bool isImplicitArray,
Oid arrayType,
Oid baseType,
- const char *defaultTypeValue, /* human readable rep */
+ const char *defaultTypeValue, /* human readable rep */
char *defaultTypeBin, /* cooked rep */
bool passedByValue,
char alignment,
NameData name;
int i;
Acl *typacl = NULL;
+ ObjectAddress address;
/*
* We assume that the caller validated the arguments individually, but did
nulls,
replaces);
- simple_heap_update(pg_type_desc, &tup->t_self, tup);
+ CatalogTupleUpdate(pg_type_desc, &tup->t_self, tup);
typeObjectId = HeapTupleGetOid(tup);
}
/* else allow system to assign oid */
- typeObjectId = simple_heap_insert(pg_type_desc, tup);
+ typeObjectId = CatalogTupleInsert(pg_type_desc, tup);
}
- /* Update indexes */
- CatalogUpdateIndexes(pg_type_desc, tup);
-
/*
* Create dependencies. We can/must skip this in bootstrap mode.
*/
/* Post creation hook for new type */
InvokeObjectPostCreateHook(TypeRelationId, typeObjectId, 0);
+ ObjectAddressSet(address, TypeRelationId, typeObjectId);
+
/*
* finish up
*/
heap_close(pg_type_desc, RowExclusiveLock);
- return typeObjectId;
+ return address;
}
/*
void
GenerateTypeDependencies(Oid typeNamespace,
Oid typeObjectId,
- Oid relationOid, /* only for relation rowtypes */
- char relationKind, /* ditto */
+ Oid relationOid, /* only for relation rowtypes */
+ char relationKind, /* ditto */
Oid owner,
Oid inputProcedure,
Oid outputProcedure,
HeapTuple tuple;
Form_pg_type typ;
Oid arrayOid;
+ Oid oldTypeOid;
pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);
arrayOid = typ->typarray;
- /* Just to give a more friendly error than unique-index violation */
- if (SearchSysCacheExists2(TYPENAMENSP,
- CStringGetDatum(newTypeName),
- ObjectIdGetDatum(typeNamespace)))
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_OBJECT),
- errmsg("type \"%s\" already exists", newTypeName)));
+ /* Check for a conflicting type name. */
+ oldTypeOid = GetSysCacheOid2(TYPENAMENSP,
+ CStringGetDatum(newTypeName),
+ ObjectIdGetDatum(typeNamespace));
+
+ /*
+ * If there is one, see if it's an autogenerated array type, and if so
+ * rename it out of the way. (But we must skip that for a shell type
+ * because moveArrayTypeName will do the wrong thing in that case.)
+ * Otherwise, we can at least give a more friendly error than unique-index
+ * violation.
+ */
+ if (OidIsValid(oldTypeOid))
+ {
+ if (get_typisdefined(oldTypeOid) &&
+ moveArrayTypeName(oldTypeOid, newTypeName, typeNamespace))
+ /* successfully dodged the problem */ ;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_DUPLICATE_OBJECT),
+ errmsg("type \"%s\" already exists", newTypeName)));
+ }
/* OK, do the rename --- tuple is a copy, so OK to scribble on it */
namestrcpy(&(typ->typname), newTypeName);
- simple_heap_update(pg_type_desc, &tuple->t_self, tuple);
-
- /* update the system catalog indexes */
- CatalogUpdateIndexes(pg_type_desc, tuple);
+ CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple);
InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
heap_freetuple(tuple);
heap_close(pg_type_desc, RowExclusiveLock);
- /* If the type has an array type, recurse to handle that */
- if (OidIsValid(arrayOid))
+ /*
+ * If the type has an array type, recurse to handle that. But we don't
+ * need to do anything more if we already renamed that array type above
+ * (which would happen when, eg, renaming "foo" to "_foo").
+ */
+ if (OidIsValid(arrayOid) && arrayOid != oldTypeOid)
{
char *arrname = makeArrayTypeName(newTypeName, typeNamespace);