#include "postgres.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/xact.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "catalog/pg_type_fn.h"
#include "commands/typecmds.h"
#include "miscadmin.h"
#include "parser/scansup.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/syscache.h"
Go to the source code of this file.
Functions | |
Oid | TypeShellMake (const char *typeName, Oid typeNamespace, Oid ownerId) |
Oid | TypeCreate (Oid newTypeOid, const char *typeName, Oid typeNamespace, Oid relationOid, char relationKind, Oid ownerId, int16 internalSize, char typeType, char typeCategory, bool typePreferred, char typDelim, Oid inputProcedure, Oid outputProcedure, Oid receiveProcedure, Oid sendProcedure, Oid typmodinProcedure, Oid typmodoutProcedure, Oid analyzeProcedure, Oid elementType, bool isImplicitArray, Oid arrayType, Oid baseType, const char *defaultTypeValue, char *defaultTypeBin, bool passedByValue, char alignment, char storage, int32 typeMod, int32 typNDims, bool typeNotNull, Oid typeCollation) |
void | GenerateTypeDependencies (Oid typeNamespace, Oid typeObjectId, Oid relationOid, char relationKind, Oid owner, Oid inputProcedure, Oid outputProcedure, Oid receiveProcedure, Oid sendProcedure, Oid typmodinProcedure, Oid typmodoutProcedure, Oid analyzeProcedure, Oid elementType, bool isImplicitArray, Oid baseType, Oid typeCollation, Node *defaultExpr, bool rebuild) |
void | RenameTypeInternal (Oid typeOid, const char *newTypeName, Oid typeNamespace) |
char * | makeArrayTypeName (const char *typeName, Oid typeNamespace) |
bool | moveArrayTypeName (Oid typeOid, const char *typeName, Oid typeNamespace) |
Variables | |
Oid | binary_upgrade_next_pg_type_oid = InvalidOid |
void GenerateTypeDependencies | ( | Oid | typeNamespace, | |
Oid | typeObjectId, | |||
Oid | relationOid, | |||
char | relationKind, | |||
Oid | owner, | |||
Oid | inputProcedure, | |||
Oid | outputProcedure, | |||
Oid | receiveProcedure, | |||
Oid | sendProcedure, | |||
Oid | typmodinProcedure, | |||
Oid | typmodoutProcedure, | |||
Oid | analyzeProcedure, | |||
Oid | elementType, | |||
bool | isImplicitArray, | |||
Oid | baseType, | |||
Oid | typeCollation, | |||
Node * | defaultExpr, | |||
bool | rebuild | |||
) |
Definition at line 500 of file pg_type.c.
References ObjectAddress::classId, DEFAULT_COLLATION_OID, deleteDependencyRecordsFor(), deleteSharedDependencyRecordsFor(), DEPENDENCY_INTERNAL, DEPENDENCY_NORMAL, NIL, ObjectAddress::objectId, ObjectAddress::objectSubId, OidIsValid, recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnExpr(), recordDependencyOnOwner(), RELKIND_COMPOSITE_TYPE, and TypeRelationId.
Referenced by AlterDomainDefault(), TypeCreate(), and TypeShellMake().
{ ObjectAddress myself, referenced; /* If rebuild, first flush old dependencies, except extension deps */ if (rebuild) { deleteDependencyRecordsFor(TypeRelationId, typeObjectId, true); deleteSharedDependencyRecordsFor(TypeRelationId, typeObjectId, 0); } myself.classId = TypeRelationId; myself.objectId = typeObjectId; myself.objectSubId = 0; /* * Make dependencies on namespace, owner, extension. * * For a relation rowtype (that's not a composite type), we should skip * these because we'll depend on them indirectly through the pg_class * entry. Likewise, skip for implicit arrays since we'll depend on them * through the element type. */ if ((!OidIsValid(relationOid) || relationKind == RELKIND_COMPOSITE_TYPE) && !isImplicitArray) { referenced.classId = NamespaceRelationId; referenced.objectId = typeNamespace; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); recordDependencyOnOwner(TypeRelationId, typeObjectId, owner); recordDependencyOnCurrentExtension(&myself, rebuild); } /* Normal dependencies on the I/O functions */ if (OidIsValid(inputProcedure)) { referenced.classId = ProcedureRelationId; referenced.objectId = inputProcedure; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } if (OidIsValid(outputProcedure)) { referenced.classId = ProcedureRelationId; referenced.objectId = outputProcedure; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } if (OidIsValid(receiveProcedure)) { referenced.classId = ProcedureRelationId; referenced.objectId = receiveProcedure; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } if (OidIsValid(sendProcedure)) { referenced.classId = ProcedureRelationId; referenced.objectId = sendProcedure; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } if (OidIsValid(typmodinProcedure)) { referenced.classId = ProcedureRelationId; referenced.objectId = typmodinProcedure; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } if (OidIsValid(typmodoutProcedure)) { referenced.classId = ProcedureRelationId; referenced.objectId = typmodoutProcedure; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } if (OidIsValid(analyzeProcedure)) { referenced.classId = ProcedureRelationId; referenced.objectId = analyzeProcedure; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } /* * If the type is a rowtype for a relation, mark it as internally * dependent on the relation, *unless* it is a stand-alone composite type * relation. For the latter case, we have to reverse the dependency. * * In the former case, this allows the type to be auto-dropped when the * relation is, and not otherwise. And in the latter, of course we get the * opposite effect. */ if (OidIsValid(relationOid)) { referenced.classId = RelationRelationId; referenced.objectId = relationOid; referenced.objectSubId = 0; if (relationKind != RELKIND_COMPOSITE_TYPE) recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL); else recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL); } /* * If the type is an implicitly-created array type, mark it as internally * dependent on the element type. Otherwise, if it has an element type, * the dependency is a normal one. */ if (OidIsValid(elementType)) { referenced.classId = TypeRelationId; referenced.objectId = elementType; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL); } /* Normal dependency from a domain to its base type. */ if (OidIsValid(baseType)) { referenced.classId = TypeRelationId; referenced.objectId = baseType; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } /* Normal dependency from a domain to its collation. */ /* We know the default collation is pinned, so don't bother recording it */ if (OidIsValid(typeCollation) && typeCollation != DEFAULT_COLLATION_OID) { referenced.classId = CollationRelationId; referenced.objectId = typeCollation; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } /* Normal dependency on the default expression. */ if (defaultExpr) recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL); }
char* makeArrayTypeName | ( | const char * | typeName, | |
Oid | typeNamespace | |||
) |
Definition at line 738 of file pg_type.c.
References AccessShareLock, CStringGetDatum, ereport, errcode(), errmsg(), ERROR, heap_close, heap_open(), i, NAMEDATALEN, ObjectIdGetDatum, palloc(), SearchSysCacheExists2, truncate_identifier(), TYPENAMENSP, and TypeRelationId.
Referenced by DefineEnum(), DefineRange(), DefineType(), heap_create_with_catalog(), moveArrayTypeName(), and RenameTypeInternal().
{ char *arr = (char *) palloc(NAMEDATALEN); int namelen = strlen(typeName); Relation pg_type_desc; int i; /* * The idea is to prepend underscores as needed until we make a name that * doesn't collide with anything... */ pg_type_desc = heap_open(TypeRelationId, AccessShareLock); for (i = 1; i < NAMEDATALEN - 1; i++) { arr[i - 1] = '_'; if (i + namelen < NAMEDATALEN) strcpy(arr + i, typeName); else { memcpy(arr + i, typeName, NAMEDATALEN - i); truncate_identifier(arr, NAMEDATALEN, false); } if (!SearchSysCacheExists2(TYPENAMENSP, CStringGetDatum(arr), ObjectIdGetDatum(typeNamespace))) break; } heap_close(pg_type_desc, AccessShareLock); if (i >= NAMEDATALEN - 1) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("could not form array type name for type \"%s\"", typeName))); return arr; }
Definition at line 804 of file pg_type.c.
References CommandCounterIncrement(), get_array_type(), get_element_type(), get_typisdefined(), makeArrayTypeName(), OidIsValid, pfree(), and RenameTypeInternal().
Referenced by DefineCompositeType(), DefineDomain(), DefineEnum(), DefineRange(), DefineType(), and heap_create_with_catalog().
{ Oid elemOid; char *newname; /* We need do nothing if it's a shell type. */ if (!get_typisdefined(typeOid)) return true; /* Can't change it if it's not an autogenerated array type. */ elemOid = get_element_type(typeOid); if (!OidIsValid(elemOid) || get_array_type(elemOid) != typeOid) return false; /* * OK, use makeArrayTypeName to pick an unused modification of the name. * Note that since makeArrayTypeName is an iterative process, this will * produce a name that it might have produced the first time, had the * conflicting type we are about to create already existed. */ newname = makeArrayTypeName(typeName, typeNamespace); /* Apply the rename */ RenameTypeInternal(typeOid, newname, typeNamespace); /* * We must bump the command counter so that any subsequent use of * makeArrayTypeName sees what we just did and doesn't pick the same name. */ CommandCounterIncrement(); pfree(newname); return true; }
Definition at line 680 of file pg_type.c.
References Assert, CatalogUpdateIndexes(), CStringGetDatum, elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, heap_close, heap_freetuple(), heap_open(), HeapTupleIsValid, InvokeObjectPostAlterHook, makeArrayTypeName(), namestrcpy(), ObjectIdGetDatum, OidIsValid, pfree(), RenameTypeInternal(), RowExclusiveLock, SearchSysCacheCopy1, SearchSysCacheExists2, simple_heap_update(), HeapTupleData::t_self, TYPENAMENSP, TYPEOID, and TypeRelationId.
Referenced by moveArrayTypeName(), RenameRelationInternal(), RenameType(), and RenameTypeInternal().
{ Relation pg_type_desc; HeapTuple tuple; Form_pg_type typ; Oid arrayOid; pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock); tuple = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid)); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for type %u", typeOid); typ = (Form_pg_type) GETSTRUCT(tuple); /* We are not supposed to be changing schemas here */ Assert(typeNamespace == typ->typnamespace); 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))); /* 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); 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)) { char *arrname = makeArrayTypeName(newTypeName, typeNamespace); RenameTypeInternal(arrayOid, arrname, typeNamespace); pfree(arrname); } }
Oid TypeCreate | ( | Oid | newTypeOid, | |
const char * | typeName, | |||
Oid | typeNamespace, | |||
Oid | relationOid, | |||
char | relationKind, | |||
Oid | ownerId, | |||
int16 | internalSize, | |||
char | typeType, | |||
char | typeCategory, | |||
bool | typePreferred, | |||
char | typDelim, | |||
Oid | inputProcedure, | |||
Oid | outputProcedure, | |||
Oid | receiveProcedure, | |||
Oid | sendProcedure, | |||
Oid | typmodinProcedure, | |||
Oid | typmodoutProcedure, | |||
Oid | analyzeProcedure, | |||
Oid | elementType, | |||
bool | isImplicitArray, | |||
Oid | arrayType, | |||
Oid | baseType, | |||
const char * | defaultTypeValue, | |||
char * | defaultTypeBin, | |||
bool | passedByValue, | |||
char | alignment, | |||
char | storage, | |||
int32 | typeMod, | |||
int32 | typNDims, | |||
bool | typeNotNull, | |||
Oid | typeCollation | |||
) |
Definition at line 188 of file pg_type.c.
References ACL_KIND_TYPE, ACL_OBJECT_TYPE, aclcheck_error(), ACLCHECK_NOT_OWNER, Anum_pg_type_typacl, Anum_pg_type_typalign, Anum_pg_type_typanalyze, Anum_pg_type_typarray, Anum_pg_type_typbasetype, Anum_pg_type_typbyval, Anum_pg_type_typcategory, Anum_pg_type_typcollation, Anum_pg_type_typdefault, Anum_pg_type_typdefaultbin, Anum_pg_type_typdelim, Anum_pg_type_typelem, Anum_pg_type_typinput, Anum_pg_type_typisdefined, Anum_pg_type_typispreferred, Anum_pg_type_typlen, Anum_pg_type_typmodin, Anum_pg_type_typmodout, Anum_pg_type_typname, Anum_pg_type_typnamespace, Anum_pg_type_typndims, Anum_pg_type_typnotnull, Anum_pg_type_typoutput, Anum_pg_type_typowner, Anum_pg_type_typreceive, Anum_pg_type_typrelid, Anum_pg_type_typsend, Anum_pg_type_typstorage, Anum_pg_type_typtype, Anum_pg_type_typtypmod, binary_upgrade_next_pg_type_oid, BoolGetDatum, CatalogUpdateIndexes(), CharGetDatum, CStringGetDatum, CStringGetTextDatum, elog, ereport, errcode(), errmsg(), ERROR, GenerateTypeDependencies(), get_user_default_acl(), GETSTRUCT, heap_close, heap_form_tuple(), heap_modify_tuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, HeapTupleSetOid, i, Int16GetDatum, Int32GetDatum, InvokeObjectPostCreateHook, IsBinaryUpgrade, IsBootstrapProcessingMode, name, NameGetDatum, namestrcpy(), NULL, ObjectIdGetDatum, OidIsValid, PointerGetDatum, RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy2, simple_heap_insert(), simple_heap_update(), stringToNode(), HeapTupleData::t_self, TYPENAMENSP, TypeRelationId, and values.
Referenced by AddNewRelationType(), DefineDomain(), DefineEnum(), DefineRange(), DefineType(), and heap_create_with_catalog().
{ Relation pg_type_desc; Oid typeObjectId; bool rebuildDeps = false; HeapTuple tup; bool nulls[Natts_pg_type]; bool replaces[Natts_pg_type]; Datum values[Natts_pg_type]; NameData name; int i; Acl *typacl = NULL; /* * We assume that the caller validated the arguments individually, but did * not check for bad combinations. * * Validate size specifications: either positive (fixed-length) or -1 * (varlena) or -2 (cstring). */ if (!(internalSize > 0 || internalSize == -1 || internalSize == -2)) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("invalid type internal size %d", internalSize))); if (passedByValue) { /* * Pass-by-value types must have a fixed length that is one of the * values supported by fetch_att() and store_att_byval(); and the * alignment had better agree, too. All this code must match * access/tupmacs.h! */ if (internalSize == (int16) sizeof(char)) { if (alignment != 'c') ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d", alignment, internalSize))); } else if (internalSize == (int16) sizeof(int16)) { if (alignment != 's') ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d", alignment, internalSize))); } else if (internalSize == (int16) sizeof(int32)) { if (alignment != 'i') ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d", alignment, internalSize))); } #if SIZEOF_DATUM == 8 else if (internalSize == (int16) sizeof(Datum)) { if (alignment != 'd') ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d", alignment, internalSize))); } #endif else ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("internal size %d is invalid for passed-by-value type", internalSize))); } else { /* varlena types must have int align or better */ if (internalSize == -1 && !(alignment == 'i' || alignment == 'd')) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("alignment \"%c\" is invalid for variable-length type", alignment))); /* cstring must have char alignment */ if (internalSize == -2 && !(alignment == 'c')) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("alignment \"%c\" is invalid for variable-length type", alignment))); } /* Only varlena types can be toasted */ if (storage != 'p' && internalSize != -1) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("fixed-size types must have storage PLAIN"))); /* * initialize arrays needed for heap_form_tuple or heap_modify_tuple */ for (i = 0; i < Natts_pg_type; ++i) { nulls[i] = false; replaces[i] = true; values[i] = (Datum) 0; } /* * insert data values */ namestrcpy(&name, typeName); values[Anum_pg_type_typname - 1] = NameGetDatum(&name); values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace); values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId); values[Anum_pg_type_typlen - 1] = Int16GetDatum(internalSize); values[Anum_pg_type_typbyval - 1] = BoolGetDatum(passedByValue); values[Anum_pg_type_typtype - 1] = CharGetDatum(typeType); values[Anum_pg_type_typcategory - 1] = CharGetDatum(typeCategory); values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(typePreferred); values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(true); values[Anum_pg_type_typdelim - 1] = CharGetDatum(typDelim); values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(relationOid); values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(elementType); values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(arrayType); values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(inputProcedure); values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(outputProcedure); values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(receiveProcedure); values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(sendProcedure); values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(typmodinProcedure); values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(typmodoutProcedure); values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(analyzeProcedure); values[Anum_pg_type_typalign - 1] = CharGetDatum(alignment); values[Anum_pg_type_typstorage - 1] = CharGetDatum(storage); values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(typeNotNull); values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(baseType); values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(typeMod); values[Anum_pg_type_typndims - 1] = Int32GetDatum(typNDims); values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(typeCollation); /* * initialize the default binary value for this type. Check for nulls of * course. */ if (defaultTypeBin) values[Anum_pg_type_typdefaultbin - 1] = CStringGetTextDatum(defaultTypeBin); else nulls[Anum_pg_type_typdefaultbin - 1] = true; /* * initialize the default value for this type. */ if (defaultTypeValue) values[Anum_pg_type_typdefault - 1] = CStringGetTextDatum(defaultTypeValue); else nulls[Anum_pg_type_typdefault - 1] = true; typacl = get_user_default_acl(ACL_OBJECT_TYPE, ownerId, typeNamespace); if (typacl != NULL) values[Anum_pg_type_typacl - 1] = PointerGetDatum(typacl); else nulls[Anum_pg_type_typacl - 1] = true; /* * open pg_type and prepare to insert or update a row. * * NOTE: updating will not work correctly in bootstrap mode; but we don't * expect to be overwriting any shell types in bootstrap mode. */ pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock); tup = SearchSysCacheCopy2(TYPENAMENSP, CStringGetDatum(typeName), ObjectIdGetDatum(typeNamespace)); if (HeapTupleIsValid(tup)) { /* * check that the type is not already defined. It may exist as a * shell type, however. */ if (((Form_pg_type) GETSTRUCT(tup))->typisdefined) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("type \"%s\" already exists", typeName))); /* * shell type must have been created by same owner */ if (((Form_pg_type) GETSTRUCT(tup))->typowner != ownerId) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, typeName); /* trouble if caller wanted to force the OID */ if (OidIsValid(newTypeOid)) elog(ERROR, "cannot assign new OID to existing shell type"); /* * Okay to update existing shell type tuple */ tup = heap_modify_tuple(tup, RelationGetDescr(pg_type_desc), values, nulls, replaces); simple_heap_update(pg_type_desc, &tup->t_self, tup); typeObjectId = HeapTupleGetOid(tup); rebuildDeps = true; /* get rid of shell type's dependencies */ } else { tup = heap_form_tuple(RelationGetDescr(pg_type_desc), values, nulls); /* Force the OID if requested by caller */ if (OidIsValid(newTypeOid)) HeapTupleSetOid(tup, newTypeOid); /* Use binary-upgrade override for pg_type.oid, if supplied. */ else if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_pg_type_oid)) { HeapTupleSetOid(tup, binary_upgrade_next_pg_type_oid); binary_upgrade_next_pg_type_oid = InvalidOid; } /* else allow system to assign oid */ typeObjectId = simple_heap_insert(pg_type_desc, tup); } /* Update indexes */ CatalogUpdateIndexes(pg_type_desc, tup); /* * Create dependencies. We can/must skip this in bootstrap mode. */ if (!IsBootstrapProcessingMode()) GenerateTypeDependencies(typeNamespace, typeObjectId, relationOid, relationKind, ownerId, inputProcedure, outputProcedure, receiveProcedure, sendProcedure, typmodinProcedure, typmodoutProcedure, analyzeProcedure, elementType, isImplicitArray, baseType, typeCollation, (defaultTypeBin ? stringToNode(defaultTypeBin) : NULL), rebuildDeps); /* Post creation hook for new type */ InvokeObjectPostCreateHook(TypeRelationId, typeObjectId, 0); /* * finish up */ heap_close(pg_type_desc, RowExclusiveLock); return typeObjectId; }
Definition at line 55 of file pg_type.c.
References Anum_pg_type_typacl, Anum_pg_type_typalign, Anum_pg_type_typanalyze, Anum_pg_type_typarray, Anum_pg_type_typbasetype, Anum_pg_type_typbyval, Anum_pg_type_typcategory, Anum_pg_type_typcollation, Anum_pg_type_typdefault, Anum_pg_type_typdefaultbin, Anum_pg_type_typdelim, Anum_pg_type_typelem, Anum_pg_type_typinput, Anum_pg_type_typisdefined, Anum_pg_type_typispreferred, Anum_pg_type_typlen, Anum_pg_type_typmodin, Anum_pg_type_typmodout, Anum_pg_type_typname, Anum_pg_type_typnamespace, Anum_pg_type_typndims, Anum_pg_type_typnotnull, Anum_pg_type_typoutput, Anum_pg_type_typowner, Anum_pg_type_typreceive, Anum_pg_type_typrelid, Anum_pg_type_typsend, Anum_pg_type_typstorage, Anum_pg_type_typtype, Anum_pg_type_typtypmod, Assert, binary_upgrade_next_pg_type_oid, BoolGetDatum, CatalogUpdateIndexes(), CharGetDatum, DEFAULT_TYPDELIM, GenerateTypeDependencies(), heap_close, heap_form_tuple(), heap_freetuple(), heap_open(), HeapTupleSetOid, i, Int16GetDatum, Int32GetDatum, InvalidOid, InvokeObjectPostCreateHook, IsBinaryUpgrade, IsBootstrapProcessingMode, name, NameGetDatum, namestrcpy(), NULL, ObjectIdGetDatum, OidIsValid, PointerIsValid, RelationData::rd_att, RowExclusiveLock, simple_heap_insert(), TYPCATEGORY_PSEUDOTYPE, TypeRelationId, TYPTYPE_PSEUDO, and values.
Referenced by compute_return_type(), DefineRange(), and DefineType().
{ Relation pg_type_desc; TupleDesc tupDesc; int i; HeapTuple tup; Datum values[Natts_pg_type]; bool nulls[Natts_pg_type]; Oid typoid; NameData name; Assert(PointerIsValid(typeName)); /* * open pg_type */ pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock); tupDesc = pg_type_desc->rd_att; /* * initialize our *nulls and *values arrays */ for (i = 0; i < Natts_pg_type; ++i) { nulls[i] = false; values[i] = (Datum) NULL; /* redundant, but safe */ } /* * initialize *values with the type name and dummy values * * The representational details are the same as int4 ... it doesn't really * matter what they are so long as they are consistent. Also note that we * give it typtype = TYPTYPE_PSEUDO as extra insurance that it won't be * mistaken for a usable type. */ namestrcpy(&name, typeName); values[Anum_pg_type_typname - 1] = NameGetDatum(&name); values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace); values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId); values[Anum_pg_type_typlen - 1] = Int16GetDatum(sizeof(int32)); values[Anum_pg_type_typbyval - 1] = BoolGetDatum(true); values[Anum_pg_type_typtype - 1] = CharGetDatum(TYPTYPE_PSEUDO); values[Anum_pg_type_typcategory - 1] = CharGetDatum(TYPCATEGORY_PSEUDOTYPE); values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(false); values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(false); values[Anum_pg_type_typdelim - 1] = CharGetDatum(DEFAULT_TYPDELIM); values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(InvalidOid); values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(InvalidOid); values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(InvalidOid); values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(F_SHELL_IN); values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(F_SHELL_OUT); values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(InvalidOid); values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(InvalidOid); values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(InvalidOid); values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(InvalidOid); values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(InvalidOid); values[Anum_pg_type_typalign - 1] = CharGetDatum('i'); values[Anum_pg_type_typstorage - 1] = CharGetDatum('p'); values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(false); values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(InvalidOid); values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(-1); values[Anum_pg_type_typndims - 1] = Int32GetDatum(0); values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(InvalidOid); nulls[Anum_pg_type_typdefaultbin - 1] = true; nulls[Anum_pg_type_typdefault - 1] = true; nulls[Anum_pg_type_typacl - 1] = true; /* * create a new type tuple */ tup = heap_form_tuple(tupDesc, values, nulls); /* Use binary-upgrade override for pg_type.oid, if supplied. */ if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_pg_type_oid)) { 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); /* * Create dependencies. We can/must skip this in bootstrap mode. */ if (!IsBootstrapProcessingMode()) GenerateTypeDependencies(typeNamespace, typoid, InvalidOid, 0, ownerId, F_SHELL_IN, F_SHELL_OUT, InvalidOid, InvalidOid, InvalidOid, InvalidOid, InvalidOid, InvalidOid, false, InvalidOid, InvalidOid, NULL, false); /* Post creation hook for new shell type */ InvokeObjectPostCreateHook(TypeRelationId, typoid, 0); /* * clean up and return the type-oid */ heap_freetuple(tup); heap_close(pg_type_desc, RowExclusiveLock); return typoid; }
Oid binary_upgrade_next_pg_type_oid = InvalidOid |
Definition at line 39 of file pg_type.c.
Referenced by set_next_pg_type_oid(), TypeCreate(), and TypeShellMake().