PostgreSQL Source Code  git master
pg_type.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/binary_upgrade.h"
#include "catalog/catalog.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 "commands/typecmds.h"
#include "mb/pg_wchar.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"
Include dependency graph for pg_type.c:

Go to the source code of this file.

Functions

static char * makeUniqueTypeName (const char *typeName, Oid typeNamespace, bool tryOriginal)
 
ObjectAddress TypeShellMake (const char *typeName, Oid typeNamespace, Oid ownerId)
 
ObjectAddress 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 subscriptProcedure, 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 (HeapTuple typeTuple, Relation typeCatalog, Node *defaultExpr, void *typacl, char relationKind, bool isImplicitArray, bool isDependentType, 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)
 
char * makeMultirangeTypeName (const char *rangeTypeName, Oid typeNamespace)
 

Variables

Oid binary_upgrade_next_pg_type_oid = InvalidOid
 

Function Documentation

◆ GenerateTypeDependencies()

void GenerateTypeDependencies ( HeapTuple  typeTuple,
Relation  typeCatalog,
Node defaultExpr,
void *  typacl,
char  relationKind,
bool  isImplicitArray,
bool  isDependentType,
bool  rebuild 
)

Definition at line 549 of file pg_type.c.

References add_exact_object_address(), DatumGetAclPCopy, deleteDependencyRecordsFor(), deleteSharedDependencyRecordsFor(), DEPENDENCY_INTERNAL, DEPENDENCY_NORMAL, free_object_addresses(), GETSTRUCT, heap_getattr, new_object_addresses(), NIL, ObjectAddressSet, OidIsValid, record_object_address_dependencies(), recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnExpr(), recordDependencyOnNewAcl(), recordDependencyOnOwner(), RelationGetDescr, stringToNode(), and TextDatumGetCString.

Referenced by AlterDomainDefault(), AlterTypeRecurse(), TypeCreate(), and TypeShellMake().

557 {
558  Form_pg_type typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
559  Oid typeObjectId = typeForm->oid;
560  Datum datum;
561  bool isNull;
562  ObjectAddress myself,
563  referenced;
564  ObjectAddresses *addrs_normal;
565 
566  /* Extract defaultExpr if caller didn't pass it */
567  if (defaultExpr == NULL)
568  {
569  datum = heap_getattr(typeTuple, Anum_pg_type_typdefaultbin,
570  RelationGetDescr(typeCatalog), &isNull);
571  if (!isNull)
572  defaultExpr = stringToNode(TextDatumGetCString(datum));
573  }
574  /* Extract typacl if caller didn't pass it */
575  if (typacl == NULL)
576  {
577  datum = heap_getattr(typeTuple, Anum_pg_type_typacl,
578  RelationGetDescr(typeCatalog), &isNull);
579  if (!isNull)
580  typacl = DatumGetAclPCopy(datum);
581  }
582 
583  /* If rebuild, first flush old dependencies, except extension deps */
584  if (rebuild)
585  {
586  deleteDependencyRecordsFor(TypeRelationId, typeObjectId, true);
587  deleteSharedDependencyRecordsFor(TypeRelationId, typeObjectId, 0);
588  }
589 
590  ObjectAddressSet(myself, TypeRelationId, typeObjectId);
591 
592  /*
593  * Make dependencies on namespace, owner, ACL, extension.
594  *
595  * Skip these for a dependent type, since it will have such dependencies
596  * indirectly through its depended-on type or relation.
597  */
598 
599  /* placeholder for all normal dependencies */
600  addrs_normal = new_object_addresses();
601 
602  if (!isDependentType)
603  {
604  ObjectAddressSet(referenced, NamespaceRelationId,
605  typeForm->typnamespace);
606  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
607 
608  recordDependencyOnOwner(TypeRelationId, typeObjectId,
609  typeForm->typowner);
610 
611  recordDependencyOnNewAcl(TypeRelationId, typeObjectId, 0,
612  typeForm->typowner, typacl);
613 
614  recordDependencyOnCurrentExtension(&myself, rebuild);
615  }
616 
617  /* Normal dependencies on the I/O and support functions */
618  if (OidIsValid(typeForm->typinput))
619  {
620  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typinput);
621  add_exact_object_address(&referenced, addrs_normal);
622  }
623 
624  if (OidIsValid(typeForm->typoutput))
625  {
626  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typoutput);
627  add_exact_object_address(&referenced, addrs_normal);
628  }
629 
630  if (OidIsValid(typeForm->typreceive))
631  {
632  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typreceive);
633  add_exact_object_address(&referenced, addrs_normal);
634  }
635 
636  if (OidIsValid(typeForm->typsend))
637  {
638  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typsend);
639  add_exact_object_address(&referenced, addrs_normal);
640  }
641 
642  if (OidIsValid(typeForm->typmodin))
643  {
644  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typmodin);
645  add_exact_object_address(&referenced, addrs_normal);
646  }
647 
648  if (OidIsValid(typeForm->typmodout))
649  {
650  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typmodout);
651  add_exact_object_address(&referenced, addrs_normal);
652  }
653 
654  if (OidIsValid(typeForm->typanalyze))
655  {
656  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typanalyze);
657  add_exact_object_address(&referenced, addrs_normal);
658  }
659 
660  if (OidIsValid(typeForm->typsubscript))
661  {
662  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typsubscript);
663  add_exact_object_address(&referenced, addrs_normal);
664  }
665 
666  /* Normal dependency from a domain to its base type. */
667  if (OidIsValid(typeForm->typbasetype))
668  {
669  ObjectAddressSet(referenced, TypeRelationId, typeForm->typbasetype);
670  add_exact_object_address(&referenced, addrs_normal);
671  }
672 
673  /*
674  * Normal dependency from a domain to its collation. We know the default
675  * collation is pinned, so don't bother recording it.
676  */
677  if (OidIsValid(typeForm->typcollation) &&
678  typeForm->typcollation != DEFAULT_COLLATION_OID)
679  {
680  ObjectAddressSet(referenced, CollationRelationId, typeForm->typcollation);
681  add_exact_object_address(&referenced, addrs_normal);
682  }
683 
685  free_object_addresses(addrs_normal);
686 
687  /* Normal dependency on the default expression. */
688  if (defaultExpr)
689  recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);
690 
691  /*
692  * If the type is a rowtype for a relation, mark it as internally
693  * dependent on the relation, *unless* it is a stand-alone composite type
694  * relation. For the latter case, we have to reverse the dependency.
695  *
696  * In the former case, this allows the type to be auto-dropped when the
697  * relation is, and not otherwise. And in the latter, of course we get the
698  * opposite effect.
699  */
700  if (OidIsValid(typeForm->typrelid))
701  {
702  ObjectAddressSet(referenced, RelationRelationId, typeForm->typrelid);
703 
704  if (relationKind != RELKIND_COMPOSITE_TYPE)
705  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
706  else
707  recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
708  }
709 
710  /*
711  * If the type is an implicitly-created array type, mark it as internally
712  * dependent on the element type. Otherwise, if it has an element type,
713  * the dependency is a normal one.
714  */
715  if (OidIsValid(typeForm->typelem))
716  {
717  ObjectAddressSet(referenced, TypeRelationId, typeForm->typelem);
718  recordDependencyOn(&myself, &referenced,
719  isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL);
720  }
721 }
#define NIL
Definition: pg_list.h:65
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:503
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2691
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:236
void * stringToNode(const char *str)
Definition: read.c:89
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2482
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:163
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2427
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2722
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1568
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:997
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:411
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:184
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
void recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, Acl *acl)
Definition: aclchk.c:5597
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ makeArrayTypeName()

char* makeArrayTypeName ( const char *  typeName,
Oid  typeNamespace 
)

Definition at line 808 of file pg_type.c.

References ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, and makeUniqueTypeName().

Referenced by DefineDomain(), DefineEnum(), DefineRange(), DefineType(), heap_create_with_catalog(), moveArrayTypeName(), and RenameTypeInternal().

809 {
810  char *arr;
811 
812  arr = makeUniqueTypeName(typeName, typeNamespace, false);
813  if (arr == NULL)
814  ereport(ERROR,
816  errmsg("could not form array type name for type \"%s\"",
817  typeName)));
818 
819  return arr;
820 }
int errcode(int sqlerrcode)
Definition: elog.c:698
static char * makeUniqueTypeName(const char *typeName, Oid typeNamespace, bool tryOriginal)
Definition: pg_type.c:937
#define ERROR
Definition: elog.h:46
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32

◆ makeMultirangeTypeName()

char* makeMultirangeTypeName ( const char *  rangeTypeName,
Oid  typeNamespace 
)

Definition at line 893 of file pg_type.c.

References buf, CStringGetDatum, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errdetail(), errhint(), errmsg(), ERROR, NAMEDATALEN, ObjectIdGetDatum, pg_mbcliplen(), pnstrdup(), psprintf(), pstrdup(), SearchSysCacheExists2, and TYPENAMENSP.

Referenced by DefineRange().

894 {
895  char *buf;
896  char *rangestr;
897 
898  /*
899  * If the range type name contains "range" then change that to
900  * "multirange". Otherwise add "_multirange" to the end.
901  */
902  rangestr = strstr(rangeTypeName, "range");
903  if (rangestr)
904  {
905  char *prefix = pnstrdup(rangeTypeName, rangestr - rangeTypeName);
906 
907  buf = psprintf("%s%s%s", prefix, "multi", rangestr);
908  }
909  else
910  buf = psprintf("%s_multirange", pnstrdup(rangeTypeName, NAMEDATALEN - 12));
911 
912  /* clip it at NAMEDATALEN-1 bytes */
913  buf[pg_mbcliplen(buf, strlen(buf), NAMEDATALEN - 1)] = '\0';
914 
916  CStringGetDatum(buf),
917  ObjectIdGetDatum(typeNamespace)))
918  ereport(ERROR,
920  errmsg("type \"%s\" already exists", buf),
921  errdetail("Failed while creating a multirange type for type \"%s\".", rangeTypeName),
922  errhint("You can manually specify a multirange type name using the \"multirange_type_name\" attribute")));
923 
924  return pstrdup(buf);
925 }
int errhint(const char *fmt,...)
Definition: elog.c:1156
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1310
char * pstrdup(const char *in)
Definition: mcxt.c:1299
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
int errcode(int sqlerrcode)
Definition: elog.c:698
#define NAMEDATALEN
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:1026
static char * buf
Definition: pg_test_fsync.c:68
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define CStringGetDatum(X)
Definition: postgres.h:622
#define ereport(elevel,...)
Definition: elog.h:157
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition: syscache.h:186
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32

◆ makeUniqueTypeName()

static char * makeUniqueTypeName ( const char *  typeName,
Oid  typeNamespace,
bool  tryOriginal 
)
static

Definition at line 937 of file pg_type.c.

References Assert, CStringGetDatum, generate_unaccent_rules::dest, i, NAMEDATALEN, ObjectIdGetDatum, pstrdup(), SearchSysCacheExists2, strlcpy(), truncate_identifier(), and TYPENAMENSP.

Referenced by makeArrayTypeName().

938 {
939  int i;
940  int namelen;
941  char dest[NAMEDATALEN];
942 
943  Assert(strlen(typeName) <= NAMEDATALEN - 1);
944 
945  if (tryOriginal &&
947  CStringGetDatum(typeName),
948  ObjectIdGetDatum(typeNamespace)))
949  return pstrdup(typeName);
950 
951  /*
952  * The idea is to prepend underscores as needed until we make a name that
953  * doesn't collide with anything ...
954  */
955  namelen = strlen(typeName);
956  for (i = 1; i < NAMEDATALEN - 1; i++)
957  {
958  dest[i - 1] = '_';
959  strlcpy(dest + i, typeName, NAMEDATALEN - i);
960  if (namelen + i >= NAMEDATALEN)
961  truncate_identifier(dest, NAMEDATALEN, false);
962 
964  CStringGetDatum(dest),
965  ObjectIdGetDatum(typeNamespace)))
966  return pstrdup(dest);
967  }
968 
969  return NULL;
970 }
char * pstrdup(const char *in)
Definition: mcxt.c:1299
#define NAMEDATALEN
void truncate_identifier(char *ident, int len, bool warn)
Definition: scansup.c:93
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define CStringGetDatum(X)
Definition: postgres.h:622
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define Assert(condition)
Definition: c.h:804
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition: syscache.h:186
int i

◆ moveArrayTypeName()

bool moveArrayTypeName ( Oid  typeOid,
const char *  typeName,
Oid  typeNamespace 
)

Definition at line 848 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(), heap_create_with_catalog(), and RenameTypeInternal().

849 {
850  Oid elemOid;
851  char *newname;
852 
853  /* We need do nothing if it's a shell type. */
854  if (!get_typisdefined(typeOid))
855  return true;
856 
857  /* Can't change it if it's not an autogenerated array type. */
858  elemOid = get_element_type(typeOid);
859  if (!OidIsValid(elemOid) ||
860  get_array_type(elemOid) != typeOid)
861  return false;
862 
863  /*
864  * OK, use makeArrayTypeName to pick an unused modification of the name.
865  * Note that since makeArrayTypeName is an iterative process, this will
866  * produce a name that it might have produced the first time, had the
867  * conflicting type we are about to create already existed.
868  */
869  newname = makeArrayTypeName(typeName, typeNamespace);
870 
871  /* Apply the rename */
872  RenameTypeInternal(typeOid, newname, typeNamespace);
873 
874  /*
875  * We must bump the command counter so that any subsequent use of
876  * makeArrayTypeName sees what we just did and doesn't pick the same name.
877  */
879 
880  pfree(newname);
881 
882  return true;
883 }
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:808
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2706
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2734
bool get_typisdefined(Oid typid)
Definition: lsyscache.c:2120
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
void pfree(void *pointer)
Definition: mcxt.c:1169
void RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
Definition: pg_type.c:733
void CommandCounterIncrement(void)
Definition: xact.c:1021

◆ RenameTypeInternal()

void RenameTypeInternal ( Oid  typeOid,
const char *  newTypeName,
Oid  typeNamespace 
)

Definition at line 733 of file pg_type.c.

References Assert, CatalogTupleUpdate(), CStringGetDatum, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, get_typisdefined(), GETSTRUCT, GetSysCacheOid2, heap_freetuple(), HeapTupleIsValid, InvokeObjectPostAlterHook, makeArrayTypeName(), moveArrayTypeName(), namestrcpy(), ObjectIdGetDatum, OidIsValid, pfree(), RenameTypeInternal(), RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, table_close(), table_open(), TYPENAMENSP, and TYPEOID.

Referenced by moveArrayTypeName(), RenameRelationInternal(), RenameType(), and RenameTypeInternal().

734 {
735  Relation pg_type_desc;
736  HeapTuple tuple;
737  Form_pg_type typ;
738  Oid arrayOid;
739  Oid oldTypeOid;
740 
741  pg_type_desc = table_open(TypeRelationId, RowExclusiveLock);
742 
743  tuple = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
744  if (!HeapTupleIsValid(tuple))
745  elog(ERROR, "cache lookup failed for type %u", typeOid);
746  typ = (Form_pg_type) GETSTRUCT(tuple);
747 
748  /* We are not supposed to be changing schemas here */
749  Assert(typeNamespace == typ->typnamespace);
750 
751  arrayOid = typ->typarray;
752 
753  /* Check for a conflicting type name. */
754  oldTypeOid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
755  CStringGetDatum(newTypeName),
756  ObjectIdGetDatum(typeNamespace));
757 
758  /*
759  * If there is one, see if it's an autogenerated array type, and if so
760  * rename it out of the way. (But we must skip that for a shell type
761  * because moveArrayTypeName will do the wrong thing in that case.)
762  * Otherwise, we can at least give a more friendly error than unique-index
763  * violation.
764  */
765  if (OidIsValid(oldTypeOid))
766  {
767  if (get_typisdefined(oldTypeOid) &&
768  moveArrayTypeName(oldTypeOid, newTypeName, typeNamespace))
769  /* successfully dodged the problem */ ;
770  else
771  ereport(ERROR,
773  errmsg("type \"%s\" already exists", newTypeName)));
774  }
775 
776  /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
777  namestrcpy(&(typ->typname), newTypeName);
778 
779  CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple);
780 
781  InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
782 
783  heap_freetuple(tuple);
784  table_close(pg_type_desc, RowExclusiveLock);
785 
786  /*
787  * If the type has an array type, recurse to handle that. But we don't
788  * need to do anything more if we already renamed that array type above
789  * (which would happen when, eg, renaming "foo" to "_foo").
790  */
791  if (OidIsValid(arrayOid) && arrayOid != oldTypeOid)
792  {
793  char *arrname = makeArrayTypeName(newTypeName, typeNamespace);
794 
795  RenameTypeInternal(arrayOid, arrname, typeNamespace);
796  pfree(arrname);
797  }
798 }
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:808
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
void namestrcpy(Name name, const char *str)
Definition: name.c:233
bool get_typisdefined(Oid typid)
Definition: lsyscache.c:2120
int errcode(int sqlerrcode)
Definition: elog.c:698
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition: pg_type.c:848
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:622
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
void RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
Definition: pg_type.c:733
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:195
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:175
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32

◆ TypeCreate()

ObjectAddress 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  subscriptProcedure,
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 197 of file pg_type.c.

References aclcheck_error(), ACLCHECK_NOT_OWNER, binary_upgrade_next_pg_type_oid, BoolGetDatum, CatalogTupleInsert(), CatalogTupleUpdate(), CharGetDatum, CStringGetDatum, CStringGetTextDatum, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, GenerateTypeDependencies(), get_user_default_acl(), GetNewOidWithIndex(), GETSTRUCT, heap_form_tuple(), heap_modify_tuple(), HeapTupleIsValid, i, Int16GetDatum, Int32GetDatum, InvalidOid, InvokeObjectPostCreateHook, IsBinaryUpgrade, IsBootstrapProcessingMode, name, NameGetDatum, namestrcpy(), OBJECT_TYPE, ObjectAddressSet, ObjectIdGetDatum, OidIsValid, PointerGetDatum, RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy2, stringToNode(), HeapTupleData::t_self, table_close(), table_open(), TYPENAMENSP, and values.

Referenced by AddNewRelationType(), DefineDomain(), DefineEnum(), DefineRange(), DefineType(), and heap_create_with_catalog().

229 {
230  Relation pg_type_desc;
231  Oid typeObjectId;
232  bool isDependentType;
233  bool rebuildDeps = false;
234  Acl *typacl;
235  HeapTuple tup;
236  bool nulls[Natts_pg_type];
237  bool replaces[Natts_pg_type];
238  Datum values[Natts_pg_type];
239  NameData name;
240  int i;
241  ObjectAddress address;
242 
243  /*
244  * We assume that the caller validated the arguments individually, but did
245  * not check for bad combinations.
246  *
247  * Validate size specifications: either positive (fixed-length) or -1
248  * (varlena) or -2 (cstring).
249  */
250  if (!(internalSize > 0 ||
251  internalSize == -1 ||
252  internalSize == -2))
253  ereport(ERROR,
254  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
255  errmsg("invalid type internal size %d",
256  internalSize)));
257 
258  if (passedByValue)
259  {
260  /*
261  * Pass-by-value types must have a fixed length that is one of the
262  * values supported by fetch_att() and store_att_byval(); and the
263  * alignment had better agree, too. All this code must match
264  * access/tupmacs.h!
265  */
266  if (internalSize == (int16) sizeof(char))
267  {
268  if (alignment != TYPALIGN_CHAR)
269  ereport(ERROR,
270  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
271  errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
272  alignment, internalSize)));
273  }
274  else if (internalSize == (int16) sizeof(int16))
275  {
276  if (alignment != TYPALIGN_SHORT)
277  ereport(ERROR,
278  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
279  errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
280  alignment, internalSize)));
281  }
282  else if (internalSize == (int16) sizeof(int32))
283  {
284  if (alignment != TYPALIGN_INT)
285  ereport(ERROR,
286  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
287  errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
288  alignment, internalSize)));
289  }
290 #if SIZEOF_DATUM == 8
291  else if (internalSize == (int16) sizeof(Datum))
292  {
293  if (alignment != TYPALIGN_DOUBLE)
294  ereport(ERROR,
295  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
296  errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
297  alignment, internalSize)));
298  }
299 #endif
300  else
301  ereport(ERROR,
302  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
303  errmsg("internal size %d is invalid for passed-by-value type",
304  internalSize)));
305  }
306  else
307  {
308  /* varlena types must have int align or better */
309  if (internalSize == -1 &&
310  !(alignment == TYPALIGN_INT || alignment == TYPALIGN_DOUBLE))
311  ereport(ERROR,
312  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
313  errmsg("alignment \"%c\" is invalid for variable-length type",
314  alignment)));
315  /* cstring must have char alignment */
316  if (internalSize == -2 && !(alignment == TYPALIGN_CHAR))
317  ereport(ERROR,
318  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
319  errmsg("alignment \"%c\" is invalid for variable-length type",
320  alignment)));
321  }
322 
323  /* Only varlena types can be toasted */
324  if (storage != TYPSTORAGE_PLAIN && internalSize != -1)
325  ereport(ERROR,
326  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
327  errmsg("fixed-size types must have storage PLAIN")));
328 
329  /*
330  * This is a dependent type if it's an implicitly-created array type, or
331  * if it's a relation rowtype that's not a composite type. For such types
332  * we'll leave the ACL empty, and we'll skip creating some dependency
333  * records because there will be a dependency already through the
334  * depended-on type or relation. (Caution: this is closely intertwined
335  * with some behavior in GenerateTypeDependencies.)
336  */
337  isDependentType = isImplicitArray ||
338  (OidIsValid(relationOid) && relationKind != RELKIND_COMPOSITE_TYPE);
339 
340  /*
341  * initialize arrays needed for heap_form_tuple or heap_modify_tuple
342  */
343  for (i = 0; i < Natts_pg_type; ++i)
344  {
345  nulls[i] = false;
346  replaces[i] = true;
347  values[i] = (Datum) 0;
348  }
349 
350  /*
351  * insert data values
352  */
353  namestrcpy(&name, typeName);
354  values[Anum_pg_type_typname - 1] = NameGetDatum(&name);
355  values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace);
356  values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId);
357  values[Anum_pg_type_typlen - 1] = Int16GetDatum(internalSize);
358  values[Anum_pg_type_typbyval - 1] = BoolGetDatum(passedByValue);
359  values[Anum_pg_type_typtype - 1] = CharGetDatum(typeType);
360  values[Anum_pg_type_typcategory - 1] = CharGetDatum(typeCategory);
361  values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(typePreferred);
362  values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(true);
363  values[Anum_pg_type_typdelim - 1] = CharGetDatum(typDelim);
364  values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(relationOid);
365  values[Anum_pg_type_typsubscript - 1] = ObjectIdGetDatum(subscriptProcedure);
366  values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(elementType);
367  values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(arrayType);
368  values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(inputProcedure);
369  values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(outputProcedure);
370  values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(receiveProcedure);
371  values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(sendProcedure);
372  values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(typmodinProcedure);
373  values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(typmodoutProcedure);
374  values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(analyzeProcedure);
375  values[Anum_pg_type_typalign - 1] = CharGetDatum(alignment);
376  values[Anum_pg_type_typstorage - 1] = CharGetDatum(storage);
377  values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(typeNotNull);
378  values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(baseType);
379  values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(typeMod);
380  values[Anum_pg_type_typndims - 1] = Int32GetDatum(typNDims);
381  values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(typeCollation);
382 
383  /*
384  * initialize the default binary value for this type. Check for nulls of
385  * course.
386  */
387  if (defaultTypeBin)
388  values[Anum_pg_type_typdefaultbin - 1] = CStringGetTextDatum(defaultTypeBin);
389  else
390  nulls[Anum_pg_type_typdefaultbin - 1] = true;
391 
392  /*
393  * initialize the default value for this type.
394  */
395  if (defaultTypeValue)
396  values[Anum_pg_type_typdefault - 1] = CStringGetTextDatum(defaultTypeValue);
397  else
398  nulls[Anum_pg_type_typdefault - 1] = true;
399 
400  /*
401  * Initialize the type's ACL, too. But dependent types don't get one.
402  */
403  if (isDependentType)
404  typacl = NULL;
405  else
406  typacl = get_user_default_acl(OBJECT_TYPE, ownerId,
407  typeNamespace);
408  if (typacl != NULL)
409  values[Anum_pg_type_typacl - 1] = PointerGetDatum(typacl);
410  else
411  nulls[Anum_pg_type_typacl - 1] = true;
412 
413  /*
414  * open pg_type and prepare to insert or update a row.
415  *
416  * NOTE: updating will not work correctly in bootstrap mode; but we don't
417  * expect to be overwriting any shell types in bootstrap mode.
418  */
419  pg_type_desc = table_open(TypeRelationId, RowExclusiveLock);
420 
422  CStringGetDatum(typeName),
423  ObjectIdGetDatum(typeNamespace));
424  if (HeapTupleIsValid(tup))
425  {
426  Form_pg_type typform = (Form_pg_type) GETSTRUCT(tup);
427 
428  /*
429  * check that the type is not already defined. It may exist as a
430  * shell type, however.
431  */
432  if (typform->typisdefined)
433  ereport(ERROR,
435  errmsg("type \"%s\" already exists", typeName)));
436 
437  /*
438  * shell type must have been created by same owner
439  */
440  if (typform->typowner != ownerId)
442 
443  /* trouble if caller wanted to force the OID */
444  if (OidIsValid(newTypeOid))
445  elog(ERROR, "cannot assign new OID to existing shell type");
446 
447  replaces[Anum_pg_type_oid - 1] = false;
448 
449  /*
450  * Okay to update existing shell type tuple
451  */
452  tup = heap_modify_tuple(tup,
453  RelationGetDescr(pg_type_desc),
454  values,
455  nulls,
456  replaces);
457 
458  CatalogTupleUpdate(pg_type_desc, &tup->t_self, tup);
459 
460  typeObjectId = typform->oid;
461 
462  rebuildDeps = true; /* get rid of shell type's dependencies */
463  }
464  else
465  {
466  /* Force the OID if requested by caller */
467  if (OidIsValid(newTypeOid))
468  typeObjectId = newTypeOid;
469  /* Use binary-upgrade override for pg_type.oid, if supplied. */
470  else if (IsBinaryUpgrade)
471  {
473  ereport(ERROR,
474  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
475  errmsg("pg_type OID value not set when in binary upgrade mode")));
476 
477  typeObjectId = binary_upgrade_next_pg_type_oid;
479  }
480  else
481  {
482  typeObjectId = GetNewOidWithIndex(pg_type_desc, TypeOidIndexId,
483  Anum_pg_type_oid);
484  }
485 
486  values[Anum_pg_type_oid - 1] = ObjectIdGetDatum(typeObjectId);
487 
488  tup = heap_form_tuple(RelationGetDescr(pg_type_desc),
489  values, nulls);
490 
491  CatalogTupleInsert(pg_type_desc, tup);
492  }
493 
494  /*
495  * Create dependencies. We can/must skip this in bootstrap mode.
496  */
499  pg_type_desc,
500  (defaultTypeBin ?
501  stringToNode(defaultTypeBin) :
502  NULL),
503  typacl,
504  relationKind,
505  isImplicitArray,
506  isDependentType,
507  rebuildDeps);
508 
509  /* Post creation hook for new type */
510  InvokeObjectPostCreateHook(TypeRelationId, typeObjectId, 0);
511 
512  ObjectAddressSet(address, TypeRelationId, typeObjectId);
513 
514  /*
515  * finish up
516  */
517  table_close(pg_type_desc, RowExclusiveLock);
518 
519  return address;
520 }
signed short int16
Definition: c.h:428
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:381
#define NameGetDatum(X)
Definition: postgres.h:639
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
#define RelationGetDescr(relation)
Definition: rel.h:503
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define PointerGetDatum(X)
Definition: postgres.h:600
#define Int16GetDatum(X)
Definition: postgres.h:495
int errcode(int sqlerrcode)
Definition: elog.c:698
void * stringToNode(const char *str)
Definition: read.c:89
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
bool IsBinaryUpgrade
Definition: globals.c:113
signed int int32
Definition: c.h:429
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
Definition: c.h:675
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:622
Oid binary_upgrade_next_pg_type_oid
Definition: pg_type.c:44
uintptr_t Datum
Definition: postgres.h:411
#define BoolGetDatum(X)
Definition: postgres.h:446
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void GenerateTypeDependencies(HeapTuple typeTuple, Relation typeCatalog, Node *defaultExpr, void *typacl, char relationKind, bool isImplicitArray, bool isDependentType, bool rebuild)
Definition: pg_type.c:549
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
const char * name
Definition: encode.c:515
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define CharGetDatum(X)
Definition: postgres.h:460
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:406
#define Int32GetDatum(X)
Definition: postgres.h:523
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:82
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:177
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
Acl * get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
Definition: aclchk.c:5521

◆ TypeShellMake()

ObjectAddress TypeShellMake ( const char *  typeName,
Oid  typeNamespace,
Oid  ownerId 
)

Definition at line 60 of file pg_type.c.

References Assert, binary_upgrade_next_pg_type_oid, BoolGetDatum, CatalogTupleInsert(), CharGetDatum, DEFAULT_TYPDELIM, ereport, errcode(), errmsg(), ERROR, GenerateTypeDependencies(), GetNewOidWithIndex(), heap_form_tuple(), heap_freetuple(), i, Int16GetDatum, Int32GetDatum, InvalidOid, InvokeObjectPostCreateHook, IsBinaryUpgrade, IsBootstrapProcessingMode, name, NameGetDatum, namestrcpy(), ObjectAddressSet, ObjectIdGetDatum, OidIsValid, PointerIsValid, RelationData::rd_att, RowExclusiveLock, table_close(), table_open(), and values.

Referenced by compute_return_type(), and DefineType().

61 {
62  Relation pg_type_desc;
63  TupleDesc tupDesc;
64  int i;
65  HeapTuple tup;
66  Datum values[Natts_pg_type];
67  bool nulls[Natts_pg_type];
68  Oid typoid;
69  NameData name;
70  ObjectAddress address;
71 
72  Assert(PointerIsValid(typeName));
73 
74  /*
75  * open pg_type
76  */
77  pg_type_desc = table_open(TypeRelationId, RowExclusiveLock);
78  tupDesc = pg_type_desc->rd_att;
79 
80  /*
81  * initialize our *nulls and *values arrays
82  */
83  for (i = 0; i < Natts_pg_type; ++i)
84  {
85  nulls[i] = false;
86  values[i] = (Datum) NULL; /* redundant, but safe */
87  }
88 
89  /*
90  * initialize *values with the type name and dummy values
91  *
92  * The representational details are the same as int4 ... it doesn't really
93  * matter what they are so long as they are consistent. Also note that we
94  * give it typtype = TYPTYPE_PSEUDO as extra insurance that it won't be
95  * mistaken for a usable type.
96  */
97  namestrcpy(&name, typeName);
98  values[Anum_pg_type_typname - 1] = NameGetDatum(&name);
99  values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace);
100  values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId);
101  values[Anum_pg_type_typlen - 1] = Int16GetDatum(sizeof(int32));
102  values[Anum_pg_type_typbyval - 1] = BoolGetDatum(true);
103  values[Anum_pg_type_typtype - 1] = CharGetDatum(TYPTYPE_PSEUDO);
104  values[Anum_pg_type_typcategory - 1] = CharGetDatum(TYPCATEGORY_PSEUDOTYPE);
105  values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(false);
106  values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(false);
107  values[Anum_pg_type_typdelim - 1] = CharGetDatum(DEFAULT_TYPDELIM);
108  values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(InvalidOid);
109  values[Anum_pg_type_typsubscript - 1] = ObjectIdGetDatum(InvalidOid);
110  values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(InvalidOid);
111  values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(InvalidOid);
112  values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(F_SHELL_IN);
113  values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(F_SHELL_OUT);
114  values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(InvalidOid);
115  values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(InvalidOid);
116  values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(InvalidOid);
117  values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(InvalidOid);
118  values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(InvalidOid);
119  values[Anum_pg_type_typalign - 1] = CharGetDatum(TYPALIGN_INT);
120  values[Anum_pg_type_typstorage - 1] = CharGetDatum(TYPSTORAGE_PLAIN);
121  values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(false);
122  values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(InvalidOid);
123  values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(-1);
124  values[Anum_pg_type_typndims - 1] = Int32GetDatum(0);
125  values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(InvalidOid);
126  nulls[Anum_pg_type_typdefaultbin - 1] = true;
127  nulls[Anum_pg_type_typdefault - 1] = true;
128  nulls[Anum_pg_type_typacl - 1] = true;
129 
130  /* Use binary-upgrade override for pg_type.oid? */
131  if (IsBinaryUpgrade)
132  {
134  ereport(ERROR,
135  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
136  errmsg("pg_type OID value not set when in binary upgrade mode")));
137 
140  }
141  else
142  {
143  typoid = GetNewOidWithIndex(pg_type_desc, TypeOidIndexId,
144  Anum_pg_type_oid);
145  }
146 
147  values[Anum_pg_type_oid - 1] = ObjectIdGetDatum(typoid);
148 
149  /*
150  * create a new type tuple
151  */
152  tup = heap_form_tuple(tupDesc, values, nulls);
153 
154  /*
155  * insert the tuple in the relation and get the tuple's oid.
156  */
157  CatalogTupleInsert(pg_type_desc, tup);
158 
159  /*
160  * Create dependencies. We can/must skip this in bootstrap mode.
161  */
164  pg_type_desc,
165  NULL,
166  NULL,
167  0,
168  false,
169  false,
170  false);
171 
172  /* Post creation hook for new shell type */
173  InvokeObjectPostCreateHook(TypeRelationId, typoid, 0);
174 
175  ObjectAddressSet(address, TypeRelationId, typoid);
176 
177  /*
178  * clean up and return the type-oid
179  */
180  heap_freetuple(tup);
181  table_close(pg_type_desc, RowExclusiveLock);
182 
183  return address;
184 }
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:381
#define NameGetDatum(X)
Definition: postgres.h:639
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define Int16GetDatum(X)
Definition: postgres.h:495
int errcode(int sqlerrcode)
Definition: elog.c:698
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
bool IsBinaryUpgrade
Definition: globals.c:113
signed int int32
Definition: c.h:429
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
Definition: c.h:675
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid binary_upgrade_next_pg_type_oid
Definition: pg_type.c:44
uintptr_t Datum
Definition: postgres.h:411
TupleDesc rd_att
Definition: rel.h:110
#define BoolGetDatum(X)
Definition: postgres.h:446
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
#define DEFAULT_TYPDELIM
Definition: typecmds.h:22
#define Assert(condition)
Definition: c.h:804
void GenerateTypeDependencies(HeapTuple typeTuple, Relation typeCatalog, Node *defaultExpr, void *typacl, char relationKind, bool isImplicitArray, bool isDependentType, bool rebuild)
Definition: pg_type.c:549
const char * name
Definition: encode.c:515
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define CharGetDatum(X)
Definition: postgres.h:460
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:406
#define Int32GetDatum(X)
Definition: postgres.h:523
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
#define PointerIsValid(pointer)
Definition: c.h:698
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221

Variable Documentation

◆ binary_upgrade_next_pg_type_oid

Oid binary_upgrade_next_pg_type_oid = InvalidOid

Definition at line 44 of file pg_type.c.

Referenced by binary_upgrade_set_next_pg_type_oid(), TypeCreate(), and TypeShellMake().