PostgreSQL Source Code  git master
pg_type.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/relation.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)
 
ListGetTypeCollations (Oid typeoid)
 
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 609 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().

617 {
618  Form_pg_type typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
619  Oid typeObjectId = typeForm->oid;
620  Datum datum;
621  bool isNull;
622  ObjectAddress myself,
623  referenced;
624  ObjectAddresses *addrs_normal;
625 
626  /* Extract defaultExpr if caller didn't pass it */
627  if (defaultExpr == NULL)
628  {
629  datum = heap_getattr(typeTuple, Anum_pg_type_typdefaultbin,
630  RelationGetDescr(typeCatalog), &isNull);
631  if (!isNull)
632  defaultExpr = stringToNode(TextDatumGetCString(datum));
633  }
634  /* Extract typacl if caller didn't pass it */
635  if (typacl == NULL)
636  {
637  datum = heap_getattr(typeTuple, Anum_pg_type_typacl,
638  RelationGetDescr(typeCatalog), &isNull);
639  if (!isNull)
640  typacl = DatumGetAclPCopy(datum);
641  }
642 
643  /* If rebuild, first flush old dependencies, except extension deps */
644  if (rebuild)
645  {
646  deleteDependencyRecordsFor(TypeRelationId, typeObjectId, true);
647  deleteSharedDependencyRecordsFor(TypeRelationId, typeObjectId, 0);
648  }
649 
650  ObjectAddressSet(myself, TypeRelationId, typeObjectId);
651 
652  /*
653  * Make dependencies on namespace, owner, ACL, extension.
654  *
655  * Skip these for a dependent type, since it will have such dependencies
656  * indirectly through its depended-on type or relation.
657  */
658 
659  /* placeholder for all normal dependencies */
660  addrs_normal = new_object_addresses();
661 
662  if (!isDependentType)
663  {
664  ObjectAddressSet(referenced, NamespaceRelationId,
665  typeForm->typnamespace);
666  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
667 
668  recordDependencyOnOwner(TypeRelationId, typeObjectId,
669  typeForm->typowner);
670 
671  recordDependencyOnNewAcl(TypeRelationId, typeObjectId, 0,
672  typeForm->typowner, typacl);
673 
674  recordDependencyOnCurrentExtension(&myself, rebuild);
675  }
676 
677  /* Normal dependencies on the I/O and support functions */
678  if (OidIsValid(typeForm->typinput))
679  {
680  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typinput);
681  add_exact_object_address(&referenced, addrs_normal);
682  }
683 
684  if (OidIsValid(typeForm->typoutput))
685  {
686  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typoutput);
687  add_exact_object_address(&referenced, addrs_normal);
688  }
689 
690  if (OidIsValid(typeForm->typreceive))
691  {
692  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typreceive);
693  add_exact_object_address(&referenced, addrs_normal);
694  }
695 
696  if (OidIsValid(typeForm->typsend))
697  {
698  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typsend);
699  add_exact_object_address(&referenced, addrs_normal);
700  }
701 
702  if (OidIsValid(typeForm->typmodin))
703  {
704  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typmodin);
705  add_exact_object_address(&referenced, addrs_normal);
706  }
707 
708  if (OidIsValid(typeForm->typmodout))
709  {
710  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typmodout);
711  add_exact_object_address(&referenced, addrs_normal);
712  }
713 
714  if (OidIsValid(typeForm->typanalyze))
715  {
716  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typanalyze);
717  add_exact_object_address(&referenced, addrs_normal);
718  }
719 
720  if (OidIsValid(typeForm->typsubscript))
721  {
722  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typsubscript);
723  add_exact_object_address(&referenced, addrs_normal);
724  }
725 
726  /* Normal dependency from a domain to its base type. */
727  if (OidIsValid(typeForm->typbasetype))
728  {
729  ObjectAddressSet(referenced, TypeRelationId, typeForm->typbasetype);
730  add_exact_object_address(&referenced, addrs_normal);
731  }
732 
733  /*
734  * Normal dependency from a domain to its collation. We know the default
735  * collation is pinned, so don't bother recording it.
736  */
737  if (OidIsValid(typeForm->typcollation) &&
738  typeForm->typcollation != DEFAULT_COLLATION_OID)
739  {
740  ObjectAddressSet(referenced, CollationRelationId, typeForm->typcollation);
741  add_exact_object_address(&referenced, addrs_normal);
742  }
743 
745  free_object_addresses(addrs_normal);
746 
747  /* Normal dependency on the default expression. */
748  if (defaultExpr)
749  recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);
750 
751  /*
752  * If the type is a rowtype for a relation, mark it as internally
753  * dependent on the relation, *unless* it is a stand-alone composite type
754  * relation. For the latter case, we have to reverse the dependency.
755  *
756  * In the former case, this allows the type to be auto-dropped when the
757  * relation is, and not otherwise. And in the latter, of course we get the
758  * opposite effect.
759  */
760  if (OidIsValid(typeForm->typrelid))
761  {
762  ObjectAddressSet(referenced, RelationRelationId, typeForm->typrelid);
763 
764  if (relationKind != RELKIND_COMPOSITE_TYPE)
765  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
766  else
767  recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
768  }
769 
770  /*
771  * If the type is an implicitly-created array type, mark it as internally
772  * dependent on the element type. Otherwise, if it has an element type,
773  * the dependency is a normal one.
774  */
775  if (OidIsValid(typeForm->typelem))
776  {
777  ObjectAddressSet(referenced, TypeRelationId, typeForm->typelem);
778  recordDependencyOn(&myself, &referenced,
779  isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL);
780  }
781 }
#define NIL
Definition: pg_list.h:65
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:483
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2819
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:272
void * stringToNode(const char *str)
Definition: read.c:89
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:46
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2610
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:165
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2555
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2851
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:698
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1689
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:1001
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:367
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:220
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:5466
#define DatumGetAclPCopy(X)
Definition: acl.h:121

◆ GetTypeCollations()

List* GetTypeCollations ( Oid  typeoid)

Definition at line 527 of file pg_type.c.

References AccessShareLock, Assert, elog, ERROR, get_range_subtype(), GETSTRUCT, GetTypeCollations(), HeapTupleIsValid, i, list_append_unique_oid(), list_concat_unique_oid(), NIL, NoLock, ObjectIdGetDatum, OidIsValid, relation_close(), relation_open(), RelationGetDescr, RelationGetNumberOfAttributes, ReleaseSysCache(), SearchSysCache1(), TupleDescAttr, and TYPEOID.

Referenced by find_expr_references_walker(), GetTypeCollations(), and index_create().

528 {
529  List *result = NIL;
530  HeapTuple tuple;
531  Form_pg_type typeTup;
532 
533  tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeoid));
534  if (!HeapTupleIsValid(tuple))
535  elog(ERROR, "cache lookup failed for type %u", typeoid);
536  typeTup = (Form_pg_type) GETSTRUCT(tuple);
537 
538  if (OidIsValid(typeTup->typcollation))
539  result = list_append_unique_oid(result, typeTup->typcollation);
540  else if (typeTup->typtype == TYPTYPE_COMPOSITE)
541  {
542  Relation rel = relation_open(typeTup->typrelid, AccessShareLock);
543  TupleDesc desc = RelationGetDescr(rel);
544 
545  for (int i = 0; i < RelationGetNumberOfAttributes(rel); i++)
546  {
547  Form_pg_attribute att = TupleDescAttr(desc, i);
548 
549  if (OidIsValid(att->attcollation))
550  result = list_append_unique_oid(result, att->attcollation);
551  else
552  result = list_concat_unique_oid(result,
553  GetTypeCollations(att->atttypid));
554  }
555 
556  relation_close(rel, NoLock);
557  }
558  else if (typeTup->typtype == TYPTYPE_DOMAIN)
559  {
560  Assert(OidIsValid(typeTup->typbasetype));
561 
562  result = list_concat_unique_oid(result,
563  GetTypeCollations(typeTup->typbasetype));
564  }
565  else if (typeTup->typtype == TYPTYPE_RANGE)
566  {
567  Oid rangeid = get_range_subtype(typeTup->oid);
568 
569  Assert(OidIsValid(rangeid));
570 
571  result = list_concat_unique_oid(result, GetTypeCollations(rangeid));
572  }
573  else if (OidIsValid(typeTup->typelem))
574  result = list_concat_unique_oid(result,
575  GetTypeCollations(typeTup->typelem));
576 
577  ReleaseSysCache(tuple);
578 
579  return result;
580 }
#define NIL
Definition: pg_list.h:65
List * list_append_unique_oid(List *list, Oid datum)
Definition: list.c:1217
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
#define RelationGetDescr(relation)
Definition: rel.h:483
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:463
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define AccessShareLock
Definition: lockdefs.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:698
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
List * list_concat_unique_oid(List *list1, const List *list2)
Definition: list.c:1301
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
#define NoLock
Definition: lockdefs.h:34
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define Assert(condition)
Definition: c.h:792
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
List * GetTypeCollations(Oid typeoid)
Definition: pg_type.c:527
#define elog(elevel,...)
Definition: elog.h:228
int i
Definition: pg_list.h:50
Oid get_range_subtype(Oid rangeOid)
Definition: lsyscache.c:3330

◆ makeArrayTypeName()

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

Definition at line 868 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().

869 {
870  char *arr;
871 
872  arr = makeUniqueTypeName(typeName, typeNamespace, false);
873  if (arr == NULL)
874  ereport(ERROR,
876  errmsg("could not form array type name for type \"%s\"",
877  typeName)));
878 
879  return arr;
880 }
int errcode(int sqlerrcode)
Definition: elog.c:696
static char * makeUniqueTypeName(const char *typeName, Oid typeNamespace, bool tryOriginal)
Definition: pg_type.c:997
#define ERROR
Definition: elog.h:45
#define ereport(elevel,...)
Definition: elog.h:155
int errmsg(const char *fmt,...)
Definition: elog.c:907
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32

◆ makeMultirangeTypeName()

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

Definition at line 953 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().

954 {
955  char *buf;
956  char *rangestr;
957 
958  /*
959  * If the range type name contains "range" then change that to
960  * "multirange". Otherwise add "_multirange" to the end.
961  */
962  rangestr = strstr(rangeTypeName, "range");
963  if (rangestr)
964  {
965  char *prefix = pnstrdup(rangeTypeName, rangestr - rangeTypeName);
966 
967  buf = psprintf("%s%s%s", prefix, "multi", rangestr);
968  }
969  else
970  buf = psprintf("%s_multirange", pnstrdup(rangeTypeName, NAMEDATALEN - 12));
971 
972  /* clip it at NAMEDATALEN-1 bytes */
973  buf[pg_mbcliplen(buf, strlen(buf), NAMEDATALEN - 1)] = '\0';
974 
976  CStringGetDatum(buf),
977  ObjectIdGetDatum(typeNamespace)))
978  ereport(ERROR,
980  errmsg("type \"%s\" already exists", buf),
981  errdetail("Failed while creating a multirange type for type \"%s\".", rangeTypeName),
982  errhint("You can manually specify a multirange type name using the \"multirange_type_name\" attribute")));
983 
984  return pstrdup(buf);
985 }
int errhint(const char *fmt,...)
Definition: elog.c:1154
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1198
char * pstrdup(const char *in)
Definition: mcxt.c:1187
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
int errcode(int sqlerrcode)
Definition: elog.c:696
#define NAMEDATALEN
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:967
static char * buf
Definition: pg_test_fsync.c:68
int errdetail(const char *fmt,...)
Definition: elog.c:1040
#define CStringGetDatum(X)
Definition: postgres.h:578
#define ereport(elevel,...)
Definition: elog.h:155
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition: syscache.h:186
int errmsg(const char *fmt,...)
Definition: elog.c:907
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32

◆ makeUniqueTypeName()

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

Definition at line 997 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().

998 {
999  int i;
1000  int namelen;
1001  char dest[NAMEDATALEN];
1002 
1003  Assert(strlen(typeName) <= NAMEDATALEN - 1);
1004 
1005  if (tryOriginal &&
1007  CStringGetDatum(typeName),
1008  ObjectIdGetDatum(typeNamespace)))
1009  return pstrdup(typeName);
1010 
1011  /*
1012  * The idea is to prepend underscores as needed until we make a name that
1013  * doesn't collide with anything ...
1014  */
1015  namelen = strlen(typeName);
1016  for (i = 1; i < NAMEDATALEN - 1; i++)
1017  {
1018  dest[i - 1] = '_';
1019  strlcpy(dest + i, typeName, NAMEDATALEN - i);
1020  if (namelen + i >= NAMEDATALEN)
1021  truncate_identifier(dest, NAMEDATALEN, false);
1022 
1024  CStringGetDatum(dest),
1025  ObjectIdGetDatum(typeNamespace)))
1026  return pstrdup(dest);
1027  }
1028 
1029  return NULL;
1030 }
char * pstrdup(const char *in)
Definition: mcxt.c:1187
#define NAMEDATALEN
void truncate_identifier(char *ident, int len, bool warn)
Definition: scansup.c:93
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define CStringGetDatum(X)
Definition: postgres.h:578
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define Assert(condition)
Definition: c.h:792
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition: syscache.h:186
int i

◆ moveArrayTypeName()

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

Definition at line 908 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().

909 {
910  Oid elemOid;
911  char *newname;
912 
913  /* We need do nothing if it's a shell type. */
914  if (!get_typisdefined(typeOid))
915  return true;
916 
917  /* Can't change it if it's not an autogenerated array type. */
918  elemOid = get_element_type(typeOid);
919  if (!OidIsValid(elemOid) ||
920  get_array_type(elemOid) != typeOid)
921  return false;
922 
923  /*
924  * OK, use makeArrayTypeName to pick an unused modification of the name.
925  * Note that since makeArrayTypeName is an iterative process, this will
926  * produce a name that it might have produced the first time, had the
927  * conflicting type we are about to create already existed.
928  */
929  newname = makeArrayTypeName(typeName, typeNamespace);
930 
931  /* Apply the rename */
932  RenameTypeInternal(typeOid, newname, typeNamespace);
933 
934  /*
935  * We must bump the command counter so that any subsequent use of
936  * makeArrayTypeName sees what we just did and doesn't pick the same name.
937  */
939 
940  pfree(newname);
941 
942  return true;
943 }
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:868
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2679
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2707
bool get_typisdefined(Oid typid)
Definition: lsyscache.c:2093
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:698
void pfree(void *pointer)
Definition: mcxt.c:1057
void RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
Definition: pg_type.c:793
void CommandCounterIncrement(void)
Definition: xact.c:1021

◆ RenameTypeInternal()

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

Definition at line 793 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().

794 {
795  Relation pg_type_desc;
796  HeapTuple tuple;
797  Form_pg_type typ;
798  Oid arrayOid;
799  Oid oldTypeOid;
800 
801  pg_type_desc = table_open(TypeRelationId, RowExclusiveLock);
802 
803  tuple = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
804  if (!HeapTupleIsValid(tuple))
805  elog(ERROR, "cache lookup failed for type %u", typeOid);
806  typ = (Form_pg_type) GETSTRUCT(tuple);
807 
808  /* We are not supposed to be changing schemas here */
809  Assert(typeNamespace == typ->typnamespace);
810 
811  arrayOid = typ->typarray;
812 
813  /* Check for a conflicting type name. */
814  oldTypeOid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
815  CStringGetDatum(newTypeName),
816  ObjectIdGetDatum(typeNamespace));
817 
818  /*
819  * If there is one, see if it's an autogenerated array type, and if so
820  * rename it out of the way. (But we must skip that for a shell type
821  * because moveArrayTypeName will do the wrong thing in that case.)
822  * Otherwise, we can at least give a more friendly error than unique-index
823  * violation.
824  */
825  if (OidIsValid(oldTypeOid))
826  {
827  if (get_typisdefined(oldTypeOid) &&
828  moveArrayTypeName(oldTypeOid, newTypeName, typeNamespace))
829  /* successfully dodged the problem */ ;
830  else
831  ereport(ERROR,
833  errmsg("type \"%s\" already exists", newTypeName)));
834  }
835 
836  /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
837  namestrcpy(&(typ->typname), newTypeName);
838 
839  CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple);
840 
841  InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
842 
843  heap_freetuple(tuple);
844  table_close(pg_type_desc, RowExclusiveLock);
845 
846  /*
847  * If the type has an array type, recurse to handle that. But we don't
848  * need to do anything more if we already renamed that array type above
849  * (which would happen when, eg, renaming "foo" to "_foo").
850  */
851  if (OidIsValid(arrayOid) && arrayOid != oldTypeOid)
852  {
853  char *arrname = makeArrayTypeName(newTypeName, typeNamespace);
854 
855  RenameTypeInternal(arrayOid, arrname, typeNamespace);
856  pfree(arrname);
857  }
858 }
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:868
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
void namestrcpy(Name name, const char *str)
Definition: name.c:233
bool get_typisdefined(Oid typid)
Definition: lsyscache.c:2093
int errcode(int sqlerrcode)
Definition: elog.c:696
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:698
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
ItemPointerData t_self
Definition: htup.h:65
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition: pg_type.c:908
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:578
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
void RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
Definition: pg_type.c:793
#define ereport(elevel,...)
Definition: elog.h:155
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:792
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:195
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:302
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:907
#define elog(elevel,...)
Definition: elog.h:228
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 198 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, TypeOidIndexId, and values.

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

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

◆ TypeShellMake()

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

Definition at line 61 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(), TypeOidIndexId, and values.

Referenced by compute_return_type(), and DefineType().

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

Variable Documentation

◆ binary_upgrade_next_pg_type_oid

Oid binary_upgrade_next_pg_type_oid = InvalidOid

Definition at line 45 of file pg_type.c.

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