* Move specified type to new namespace. * * Caller must have already checked privileges. * * The function automatically recurses to process the type's array type, * if any. isImplicitArray should be true only when doing this internal * recursion (outside callers must never try to move an array type directly). * * If errorOnTableType is true, the function errors out if the type is * a tab
| 4075 | * Returns the type's old namespace OID. |
| 4076 | */ |
| 4077 | Oid |
| 4078 | AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, |
| 4079 | bool isImplicitArray, |
| 4080 | bool errorOnTableType, |
| 4081 | ObjectAddresses *objsMoved) |
| 4082 | { |
| 4083 | Relation rel; |
| 4084 | HeapTuple tup; |
| 4085 | Form_pg_type typform; |
| 4086 | Oid oldNspOid; |
| 4087 | Oid arrayOid; |
| 4088 | bool isCompositeType; |
| 4089 | ObjectAddress thisobj; |
| 4090 | |
| 4091 | /* |
| 4092 | * Make sure we haven't moved this object previously. |
| 4093 | */ |
| 4094 | thisobj.classId = TypeRelationId; |
| 4095 | thisobj.objectId = typeOid; |
| 4096 | thisobj.objectSubId = 0; |
| 4097 | |
| 4098 | if (object_address_present(&thisobj, objsMoved)) |
| 4099 | return InvalidOid; |
| 4100 | |
| 4101 | rel = table_open(TypeRelationId, RowExclusiveLock); |
| 4102 | |
| 4103 | tup = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid)); |
| 4104 | if (!HeapTupleIsValid(tup)) |
| 4105 | elog(ERROR, "cache lookup failed for type %u", typeOid); |
| 4106 | typform = (Form_pg_type) GETSTRUCT(tup); |
| 4107 | |
| 4108 | oldNspOid = typform->typnamespace; |
| 4109 | arrayOid = typform->typarray; |
| 4110 | |
| 4111 | /* If the type is already there, we scan skip these next few checks. */ |
| 4112 | if (oldNspOid != nspOid) |
| 4113 | { |
| 4114 | /* common checks on switching namespaces */ |
| 4115 | CheckSetNamespace(oldNspOid, nspOid); |
| 4116 | |
| 4117 | /* check for duplicate name (more friendly than unique-index failure) */ |
| 4118 | if (SearchSysCacheExists2(TYPENAMENSP, |
| 4119 | NameGetDatum(&typform->typname), |
| 4120 | ObjectIdGetDatum(nspOid))) |
| 4121 | ereport(ERROR, |
| 4122 | (errcode(ERRCODE_DUPLICATE_OBJECT), |
| 4123 | errmsg("type \"%s\" already exists in schema \"%s\"", |
| 4124 | NameStr(typform->typname), |
| 4125 | get_namespace_name(nspOid)))); |
| 4126 | } |
| 4127 | |
| 4128 | /* Detect whether type is a composite type (but not a table rowtype) */ |
| 4129 | isCompositeType = |
| 4130 | (typform->typtype == TYPTYPE_COMPOSITE && |
| 4131 | get_rel_relkind(typform->typrelid) == RELKIND_COMPOSITE_TYPE); |
| 4132 | |
| 4133 | /* Enforce not-table-type if requested */ |
| 4134 | if (typform->typtype == TYPTYPE_COMPOSITE && !isCompositeType && |
no test coverage detected