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 618 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().

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

Referenced by 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  /*
539  * If the type has a typcollation attribute, report that and we're done.
540  * Otherwise, it could be a container type that we should recurse into.
541  */
542  if (OidIsValid(typeTup->typcollation))
543  result = list_make1_oid(typeTup->typcollation);
544  else if (typeTup->typtype == TYPTYPE_COMPOSITE)
545  {
546  Relation rel = relation_open(typeTup->typrelid, AccessShareLock);
547  TupleDesc desc = RelationGetDescr(rel);
548 
549  for (int i = 0; i < RelationGetNumberOfAttributes(rel); i++)
550  {
551  Form_pg_attribute att = TupleDescAttr(desc, i);
552 
553  if (att->attisdropped)
554  continue;
555  if (OidIsValid(att->attcollation))
556  result = list_append_unique_oid(result, att->attcollation);
557  else
558  result = list_concat_unique_oid(result,
559  GetTypeCollations(att->atttypid));
560  }
561 
562  relation_close(rel, NoLock);
563  }
564  else if (typeTup->typtype == TYPTYPE_DOMAIN)
565  {
566  Assert(OidIsValid(typeTup->typbasetype));
567  result = GetTypeCollations(typeTup->typbasetype);
568  }
569  else if (typeTup->typtype == TYPTYPE_RANGE)
570  {
571  Oid rangecoll = get_range_collation(typeTup->oid);
572 
573  if (OidIsValid(rangecoll))
574  result = list_make1_oid(rangecoll);
575  else
576  {
577  Oid rangeid = get_range_subtype(typeTup->oid);
578 
579  Assert(OidIsValid(rangeid));
580  result = GetTypeCollations(rangeid);
581  }
582  }
583  else if (IsTrueArrayType(typeTup))
584  result = GetTypeCollations(typeTup->typelem);
585 
586  ReleaseSysCache(tuple);
587 
588  return result;
589 }
#define NIL
Definition: pg_list.h:65
List * list_append_unique_oid(List *list, Oid datum)
Definition: list.c:1232
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#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:710
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
List * list_concat_unique_oid(List *list1, const List *list2)
Definition: list.c:1316
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:203
Oid get_range_collation(Oid rangeOid)
Definition: lsyscache.c:3383
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define list_make1_oid(x1)
Definition: pg_list.h:236
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define Assert(condition)
Definition: c.h:804
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:232
int i
Definition: pg_list.h:50
Oid get_range_subtype(Oid rangeOid)
Definition: lsyscache.c:3357

◆ makeArrayTypeName()

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

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

878 {
879  char *arr;
880 
881  arr = makeUniqueTypeName(typeName, typeNamespace, false);
882  if (arr == NULL)
883  ereport(ERROR,
885  errmsg("could not form array type name for type \"%s\"",
886  typeName)));
887 
888  return arr;
889 }
int errcode(int sqlerrcode)
Definition: elog.c:698
static char * makeUniqueTypeName(const char *typeName, Oid typeNamespace, bool tryOriginal)
Definition: pg_type.c:1006
#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 962 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().

963 {
964  char *buf;
965  char *rangestr;
966 
967  /*
968  * If the range type name contains "range" then change that to
969  * "multirange". Otherwise add "_multirange" to the end.
970  */
971  rangestr = strstr(rangeTypeName, "range");
972  if (rangestr)
973  {
974  char *prefix = pnstrdup(rangeTypeName, rangestr - rangeTypeName);
975 
976  buf = psprintf("%s%s%s", prefix, "multi", rangestr);
977  }
978  else
979  buf = psprintf("%s_multirange", pnstrdup(rangeTypeName, NAMEDATALEN - 12));
980 
981  /* clip it at NAMEDATALEN-1 bytes */
982  buf[pg_mbcliplen(buf, strlen(buf), NAMEDATALEN - 1)] = '\0';
983 
985  CStringGetDatum(buf),
986  ObjectIdGetDatum(typeNamespace)))
987  ereport(ERROR,
989  errmsg("type \"%s\" already exists", buf),
990  errdetail("Failed while creating a multirange type for type \"%s\".", rangeTypeName),
991  errhint("You can manually specify a multirange type name using the \"multirange_type_name\" attribute")));
992 
993  return pstrdup(buf);
994 }
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 1006 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().

1007 {
1008  int i;
1009  int namelen;
1010  char dest[NAMEDATALEN];
1011 
1012  Assert(strlen(typeName) <= NAMEDATALEN - 1);
1013 
1014  if (tryOriginal &&
1016  CStringGetDatum(typeName),
1017  ObjectIdGetDatum(typeNamespace)))
1018  return pstrdup(typeName);
1019 
1020  /*
1021  * The idea is to prepend underscores as needed until we make a name that
1022  * doesn't collide with anything ...
1023  */
1024  namelen = strlen(typeName);
1025  for (i = 1; i < NAMEDATALEN - 1; i++)
1026  {
1027  dest[i - 1] = '_';
1028  strlcpy(dest + i, typeName, NAMEDATALEN - i);
1029  if (namelen + i >= NAMEDATALEN)
1030  truncate_identifier(dest, NAMEDATALEN, false);
1031 
1033  CStringGetDatum(dest),
1034  ObjectIdGetDatum(typeNamespace)))
1035  return pstrdup(dest);
1036  }
1037 
1038  return NULL;
1039 }
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 917 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().

918 {
919  Oid elemOid;
920  char *newname;
921 
922  /* We need do nothing if it's a shell type. */
923  if (!get_typisdefined(typeOid))
924  return true;
925 
926  /* Can't change it if it's not an autogenerated array type. */
927  elemOid = get_element_type(typeOid);
928  if (!OidIsValid(elemOid) ||
929  get_array_type(elemOid) != typeOid)
930  return false;
931 
932  /*
933  * OK, use makeArrayTypeName to pick an unused modification of the name.
934  * Note that since makeArrayTypeName is an iterative process, this will
935  * produce a name that it might have produced the first time, had the
936  * conflicting type we are about to create already existed.
937  */
938  newname = makeArrayTypeName(typeName, typeNamespace);
939 
940  /* Apply the rename */
941  RenameTypeInternal(typeOid, newname, typeNamespace);
942 
943  /*
944  * We must bump the command counter so that any subsequent use of
945  * makeArrayTypeName sees what we just did and doesn't pick the same name.
946  */
948 
949  pfree(newname);
950 
951  return true;
952 }
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:877
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:802
void CommandCounterIncrement(void)
Definition: xact.c:1021

◆ RenameTypeInternal()

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

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

803 {
804  Relation pg_type_desc;
805  HeapTuple tuple;
806  Form_pg_type typ;
807  Oid arrayOid;
808  Oid oldTypeOid;
809 
810  pg_type_desc = table_open(TypeRelationId, RowExclusiveLock);
811 
812  tuple = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
813  if (!HeapTupleIsValid(tuple))
814  elog(ERROR, "cache lookup failed for type %u", typeOid);
815  typ = (Form_pg_type) GETSTRUCT(tuple);
816 
817  /* We are not supposed to be changing schemas here */
818  Assert(typeNamespace == typ->typnamespace);
819 
820  arrayOid = typ->typarray;
821 
822  /* Check for a conflicting type name. */
823  oldTypeOid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
824  CStringGetDatum(newTypeName),
825  ObjectIdGetDatum(typeNamespace));
826 
827  /*
828  * If there is one, see if it's an autogenerated array type, and if so
829  * rename it out of the way. (But we must skip that for a shell type
830  * because moveArrayTypeName will do the wrong thing in that case.)
831  * Otherwise, we can at least give a more friendly error than unique-index
832  * violation.
833  */
834  if (OidIsValid(oldTypeOid))
835  {
836  if (get_typisdefined(oldTypeOid) &&
837  moveArrayTypeName(oldTypeOid, newTypeName, typeNamespace))
838  /* successfully dodged the problem */ ;
839  else
840  ereport(ERROR,
842  errmsg("type \"%s\" already exists", newTypeName)));
843  }
844 
845  /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
846  namestrcpy(&(typ->typname), newTypeName);
847 
848  CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple);
849 
850  InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
851 
852  heap_freetuple(tuple);
853  table_close(pg_type_desc, RowExclusiveLock);
854 
855  /*
856  * If the type has an array type, recurse to handle that. But we don't
857  * need to do anything more if we already renamed that array type above
858  * (which would happen when, eg, renaming "foo" to "_foo").
859  */
860  if (OidIsValid(arrayOid) && arrayOid != oldTypeOid)
861  {
862  char *arrname = makeArrayTypeName(newTypeName, typeNamespace);
863 
864  RenameTypeInternal(arrayOid, arrname, typeNamespace);
865  pfree(arrname);
866  }
867 }
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:877
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:917
#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:802
#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 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:428
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:322
#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:483
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define PointerGetDatum(X)
Definition: postgres.h:600
#define TypeOidIndexId
Definition: pg_type.h:266
#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:3313
#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:45
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:618
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:394
#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:5526

◆ 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:322
#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 TypeOidIndexId
Definition: pg_type.h:266
#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:45
uintptr_t Datum
Definition: postgres.h:411
TupleDesc rd_att
Definition: rel.h:111
#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:618
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:394
#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 45 of file pg_type.c.

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