PostgreSQL Source Code  git master
pg_type.c File Reference
#include "postgres.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/xact.h"
#include "catalog/binary_upgrade.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 "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

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 elementType, bool isImplicitArray, Oid arrayType, Oid baseType, const char *defaultTypeValue, char *defaultTypeBin, bool passedByValue, char alignment, char storage, int32 typeMod, int32 typNDims, bool typeNotNull, Oid typeCollation)
 
void GenerateTypeDependencies (Oid typeNamespace, Oid typeObjectId, Oid relationOid, char relationKind, Oid owner, Oid inputProcedure, Oid outputProcedure, Oid receiveProcedure, Oid sendProcedure, Oid typmodinProcedure, Oid typmodoutProcedure, Oid analyzeProcedure, Oid elementType, bool isImplicitArray, Oid baseType, Oid typeCollation, Node *defaultExpr, bool rebuild)
 
void RenameTypeInternal (Oid typeOid, const char *newTypeName, Oid typeNamespace)
 
char * makeArrayTypeName (const char *typeName, Oid typeNamespace)
 
bool moveArrayTypeName (Oid typeOid, const char *typeName, Oid typeNamespace)
 

Variables

Oid binary_upgrade_next_pg_type_oid = InvalidOid
 

Function Documentation

◆ GenerateTypeDependencies()

void GenerateTypeDependencies ( Oid  typeNamespace,
Oid  typeObjectId,
Oid  relationOid,
char  relationKind,
Oid  owner,
Oid  inputProcedure,
Oid  outputProcedure,
Oid  receiveProcedure,
Oid  sendProcedure,
Oid  typmodinProcedure,
Oid  typmodoutProcedure,
Oid  analyzeProcedure,
Oid  elementType,
bool  isImplicitArray,
Oid  baseType,
Oid  typeCollation,
Node defaultExpr,
bool  rebuild 
)

Definition at line 511 of file pg_type.c.

References ObjectAddress::classId, deleteDependencyRecordsFor(), deleteSharedDependencyRecordsFor(), DEPENDENCY_INTERNAL, DEPENDENCY_NORMAL, NIL, ObjectAddress::objectId, ObjectAddress::objectSubId, OidIsValid, recordDependencyOn(), recordDependencyOnCurrentExtension(), recordDependencyOnExpr(), and recordDependencyOnOwner().

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

529 {
530  ObjectAddress myself,
531  referenced;
532 
533  /* If rebuild, first flush old dependencies, except extension deps */
534  if (rebuild)
535  {
536  deleteDependencyRecordsFor(TypeRelationId, typeObjectId, true);
537  deleteSharedDependencyRecordsFor(TypeRelationId, typeObjectId, 0);
538  }
539 
540  myself.classId = TypeRelationId;
541  myself.objectId = typeObjectId;
542  myself.objectSubId = 0;
543 
544  /*
545  * Make dependencies on namespace, owner, extension.
546  *
547  * For a relation rowtype (that's not a composite type), we should skip
548  * these because we'll depend on them indirectly through the pg_class
549  * entry. Likewise, skip for implicit arrays since we'll depend on them
550  * through the element type.
551  */
552  if ((!OidIsValid(relationOid) || relationKind == RELKIND_COMPOSITE_TYPE) &&
553  !isImplicitArray)
554  {
555  referenced.classId = NamespaceRelationId;
556  referenced.objectId = typeNamespace;
557  referenced.objectSubId = 0;
558  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
559 
560  recordDependencyOnOwner(TypeRelationId, typeObjectId, owner);
561 
562  recordDependencyOnCurrentExtension(&myself, rebuild);
563  }
564 
565  /* Normal dependencies on the I/O functions */
566  if (OidIsValid(inputProcedure))
567  {
568  referenced.classId = ProcedureRelationId;
569  referenced.objectId = inputProcedure;
570  referenced.objectSubId = 0;
571  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
572  }
573 
574  if (OidIsValid(outputProcedure))
575  {
576  referenced.classId = ProcedureRelationId;
577  referenced.objectId = outputProcedure;
578  referenced.objectSubId = 0;
579  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
580  }
581 
582  if (OidIsValid(receiveProcedure))
583  {
584  referenced.classId = ProcedureRelationId;
585  referenced.objectId = receiveProcedure;
586  referenced.objectSubId = 0;
587  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
588  }
589 
590  if (OidIsValid(sendProcedure))
591  {
592  referenced.classId = ProcedureRelationId;
593  referenced.objectId = sendProcedure;
594  referenced.objectSubId = 0;
595  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
596  }
597 
598  if (OidIsValid(typmodinProcedure))
599  {
600  referenced.classId = ProcedureRelationId;
601  referenced.objectId = typmodinProcedure;
602  referenced.objectSubId = 0;
603  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
604  }
605 
606  if (OidIsValid(typmodoutProcedure))
607  {
608  referenced.classId = ProcedureRelationId;
609  referenced.objectId = typmodoutProcedure;
610  referenced.objectSubId = 0;
611  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
612  }
613 
614  if (OidIsValid(analyzeProcedure))
615  {
616  referenced.classId = ProcedureRelationId;
617  referenced.objectId = analyzeProcedure;
618  referenced.objectSubId = 0;
619  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
620  }
621 
622  /*
623  * If the type is a rowtype for a relation, mark it as internally
624  * dependent on the relation, *unless* it is a stand-alone composite type
625  * relation. For the latter case, we have to reverse the dependency.
626  *
627  * In the former case, this allows the type to be auto-dropped when the
628  * relation is, and not otherwise. And in the latter, of course we get the
629  * opposite effect.
630  */
631  if (OidIsValid(relationOid))
632  {
633  referenced.classId = RelationRelationId;
634  referenced.objectId = relationOid;
635  referenced.objectSubId = 0;
636 
637  if (relationKind != RELKIND_COMPOSITE_TYPE)
638  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
639  else
640  recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
641  }
642 
643  /*
644  * If the type is an implicitly-created array type, mark it as internally
645  * dependent on the element type. Otherwise, if it has an element type,
646  * the dependency is a normal one.
647  */
648  if (OidIsValid(elementType))
649  {
650  referenced.classId = TypeRelationId;
651  referenced.objectId = elementType;
652  referenced.objectSubId = 0;
653  recordDependencyOn(&myself, &referenced,
654  isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL);
655  }
656 
657  /* Normal dependency from a domain to its base type. */
658  if (OidIsValid(baseType))
659  {
660  referenced.classId = TypeRelationId;
661  referenced.objectId = baseType;
662  referenced.objectSubId = 0;
663  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
664  }
665 
666  /* Normal dependency from a domain to its collation. */
667  /* We know the default collation is pinned, so don't bother recording it */
668  if (OidIsValid(typeCollation) && typeCollation != DEFAULT_COLLATION_OID)
669  {
670  referenced.classId = CollationRelationId;
671  referenced.objectId = typeCollation;
672  referenced.objectSubId = 0;
673  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
674  }
675 
676  /* Normal dependency on the default expression. */
677  if (defaultExpr)
678  recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);
679 }
#define NIL
Definition: pg_list.h:69
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:191
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:159
#define OidIsValid(objectId)
Definition: c.h:605
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1360
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:823
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:139

◆ makeArrayTypeName()

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

Definition at line 766 of file pg_type.c.

References AccessShareLock, CStringGetDatum, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errmsg(), ERROR, heap_close, heap_open(), i, NAMEDATALEN, ObjectIdGetDatum, palloc(), SearchSysCacheExists2, truncate_identifier(), and TYPENAMENSP.

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

767 {
768  char *arr = (char *) palloc(NAMEDATALEN);
769  int namelen = strlen(typeName);
770  Relation pg_type_desc;
771  int i;
772 
773  /*
774  * The idea is to prepend underscores as needed until we make a name that
775  * doesn't collide with anything...
776  */
777  pg_type_desc = heap_open(TypeRelationId, AccessShareLock);
778 
779  for (i = 1; i < NAMEDATALEN - 1; i++)
780  {
781  arr[i - 1] = '_';
782  if (i + namelen < NAMEDATALEN)
783  strcpy(arr + i, typeName);
784  else
785  {
786  memcpy(arr + i, typeName, NAMEDATALEN - i);
787  truncate_identifier(arr, NAMEDATALEN, false);
788  }
790  CStringGetDatum(arr),
791  ObjectIdGetDatum(typeNamespace)))
792  break;
793  }
794 
795  heap_close(pg_type_desc, AccessShareLock);
796 
797  if (i >= NAMEDATALEN - 1)
798  ereport(ERROR,
800  errmsg("could not form array type name for type \"%s\"",
801  typeName)));
802 
803  return arr;
804 }
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
#define NAMEDATALEN
void truncate_identifier(char *ident, int len, bool warn)
Definition: scansup.c:187
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
#define CStringGetDatum(X)
Definition: postgres.h:563
#define ereport(elevel, rest)
Definition: elog.h:122
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition: syscache.h:184
void * palloc(Size size)
Definition: mcxt.c:924
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32

◆ moveArrayTypeName()

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

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

833 {
834  Oid elemOid;
835  char *newname;
836 
837  /* We need do nothing if it's a shell type. */
838  if (!get_typisdefined(typeOid))
839  return true;
840 
841  /* Can't change it if it's not an autogenerated array type. */
842  elemOid = get_element_type(typeOid);
843  if (!OidIsValid(elemOid) ||
844  get_array_type(elemOid) != typeOid)
845  return false;
846 
847  /*
848  * OK, use makeArrayTypeName to pick an unused modification of the name.
849  * Note that since makeArrayTypeName is an iterative process, this will
850  * produce a name that it might have produced the first time, had the
851  * conflicting type we are about to create already existed.
852  */
853  newname = makeArrayTypeName(typeName, typeNamespace);
854 
855  /* Apply the rename */
856  RenameTypeInternal(typeOid, newname, typeNamespace);
857 
858  /*
859  * We must bump the command counter so that any subsequent use of
860  * makeArrayTypeName sees what we just did and doesn't pick the same name.
861  */
863 
864  pfree(newname);
865 
866  return true;
867 }
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:766
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2502
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2530
bool get_typisdefined(Oid typid)
Definition: lsyscache.c:1927
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:605
void pfree(void *pointer)
Definition: mcxt.c:1031
void RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
Definition: pg_type.c:691
void CommandCounterIncrement(void)
Definition: xact.c:914

◆ RenameTypeInternal()

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

Definition at line 691 of file pg_type.c.

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

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

692 {
693  Relation pg_type_desc;
694  HeapTuple tuple;
695  Form_pg_type typ;
696  Oid arrayOid;
697  Oid oldTypeOid;
698 
699  pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);
700 
701  tuple = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
702  if (!HeapTupleIsValid(tuple))
703  elog(ERROR, "cache lookup failed for type %u", typeOid);
704  typ = (Form_pg_type) GETSTRUCT(tuple);
705 
706  /* We are not supposed to be changing schemas here */
707  Assert(typeNamespace == typ->typnamespace);
708 
709  arrayOid = typ->typarray;
710 
711  /* Check for a conflicting type name. */
712  oldTypeOid = GetSysCacheOid2(TYPENAMENSP,
713  CStringGetDatum(newTypeName),
714  ObjectIdGetDatum(typeNamespace));
715 
716  /*
717  * If there is one, see if it's an autogenerated array type, and if so
718  * rename it out of the way. (But we must skip that for a shell type
719  * because moveArrayTypeName will do the wrong thing in that case.)
720  * Otherwise, we can at least give a more friendly error than unique-index
721  * violation.
722  */
723  if (OidIsValid(oldTypeOid))
724  {
725  if (get_typisdefined(oldTypeOid) &&
726  moveArrayTypeName(oldTypeOid, newTypeName, typeNamespace))
727  /* successfully dodged the problem */ ;
728  else
729  ereport(ERROR,
731  errmsg("type \"%s\" already exists", newTypeName)));
732  }
733 
734  /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
735  namestrcpy(&(typ->typname), newTypeName);
736 
737  CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple);
738 
739  InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
740 
741  heap_freetuple(tuple);
742  heap_close(pg_type_desc, RowExclusiveLock);
743 
744  /*
745  * If the type has an array type, recurse to handle that. But we don't
746  * need to do anything more if we already renamed that array type above
747  * (which would happen when, eg, renaming "foo" to "_foo").
748  */
749  if (OidIsValid(arrayOid) && arrayOid != oldTypeOid)
750  {
751  char *arrname = makeArrayTypeName(newTypeName, typeNamespace);
752 
753  RenameTypeInternal(arrayOid, arrname, typeNamespace);
754  pfree(arrname);
755  }
756 }
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:766
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
bool get_typisdefined(Oid typid)
Definition: lsyscache.c:1927
int errcode(int sqlerrcode)
Definition: elog.c:575
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
unsigned int Oid
Definition: postgres_ext.h:31
int namestrcpy(Name name, const char *str)
Definition: name.c:216
#define OidIsValid(objectId)
Definition: c.h:605
#define GetSysCacheOid2(cacheId, key1, key2)
Definition: syscache.h:193
void pfree(void *pointer)
Definition: mcxt.c:1031
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition: pg_type.c:832
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:563
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
void RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
Definition: pg_type.c:691
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:699
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:211
FormData_pg_type * Form_pg_type
Definition: pg_type.h:248
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#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  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 194 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(), GETSTRUCT, heap_close, heap_form_tuple(), heap_modify_tuple(), heap_open(), HeapTupleGetOid, HeapTupleIsValid, HeapTupleSetOid, i, Int16GetDatum, Int32GetDatum, InvalidOid, InvokeObjectPostCreateHook, IsBinaryUpgrade, IsBootstrapProcessingMode, name, NameGetDatum, namestrcpy(), OBJECT_TYPE, ObjectAddressSet, ObjectIdGetDatum, OidIsValid, PointerGetDatum, RelationGetDescr, RowExclusiveLock, SearchSysCacheCopy2, stringToNode(), HeapTupleData::t_self, TYPENAMENSP, and values.

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

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

◆ TypeShellMake()

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

Definition at line 55 of file pg_type.c.

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

Referenced by compute_return_type(), DefineRange(), and DefineType().

56 {
57  Relation pg_type_desc;
58  TupleDesc tupDesc;
59  int i;
60  HeapTuple tup;
61  Datum values[Natts_pg_type];
62  bool nulls[Natts_pg_type];
63  Oid typoid;
64  NameData name;
65  ObjectAddress address;
66 
67  Assert(PointerIsValid(typeName));
68 
69  /*
70  * open pg_type
71  */
72  pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);
73  tupDesc = pg_type_desc->rd_att;
74 
75  /*
76  * initialize our *nulls and *values arrays
77  */
78  for (i = 0; i < Natts_pg_type; ++i)
79  {
80  nulls[i] = false;
81  values[i] = (Datum) NULL; /* redundant, but safe */
82  }
83 
84  /*
85  * initialize *values with the type name and dummy values
86  *
87  * The representational details are the same as int4 ... it doesn't really
88  * matter what they are so long as they are consistent. Also note that we
89  * give it typtype = TYPTYPE_PSEUDO as extra insurance that it won't be
90  * mistaken for a usable type.
91  */
92  namestrcpy(&name, typeName);
93  values[Anum_pg_type_typname - 1] = NameGetDatum(&name);
94  values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace);
95  values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId);
96  values[Anum_pg_type_typlen - 1] = Int16GetDatum(sizeof(int32));
97  values[Anum_pg_type_typbyval - 1] = BoolGetDatum(true);
98  values[Anum_pg_type_typtype - 1] = CharGetDatum(TYPTYPE_PSEUDO);
99  values[Anum_pg_type_typcategory - 1] = CharGetDatum(TYPCATEGORY_PSEUDOTYPE);
100  values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(false);
101  values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(false);
102  values[Anum_pg_type_typdelim - 1] = CharGetDatum(DEFAULT_TYPDELIM);
103  values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(InvalidOid);
104  values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(InvalidOid);
105  values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(InvalidOid);
106  values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(F_SHELL_IN);
107  values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(F_SHELL_OUT);
108  values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(InvalidOid);
109  values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(InvalidOid);
110  values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(InvalidOid);
111  values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(InvalidOid);
112  values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(InvalidOid);
113  values[Anum_pg_type_typalign - 1] = CharGetDatum('i');
114  values[Anum_pg_type_typstorage - 1] = CharGetDatum('p');
115  values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(false);
116  values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(InvalidOid);
117  values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(-1);
118  values[Anum_pg_type_typndims - 1] = Int32GetDatum(0);
119  values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(InvalidOid);
120  nulls[Anum_pg_type_typdefaultbin - 1] = true;
121  nulls[Anum_pg_type_typdefault - 1] = true;
122  nulls[Anum_pg_type_typacl - 1] = true;
123 
124  /*
125  * create a new type tuple
126  */
127  tup = heap_form_tuple(tupDesc, values, nulls);
128 
129  /* Use binary-upgrade override for pg_type.oid? */
130  if (IsBinaryUpgrade)
131  {
133  ereport(ERROR,
134  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
135  errmsg("pg_type OID value not set when in binary upgrade mode")));
136 
139  }
140 
141  /*
142  * insert the tuple in the relation and get the tuple's oid.
143  */
144  typoid = CatalogTupleInsert(pg_type_desc, tup);
145 
146  /*
147  * Create dependencies. We can/must skip this in bootstrap mode.
148  */
150  GenerateTypeDependencies(typeNamespace,
151  typoid,
152  InvalidOid,
153  0,
154  ownerId,
155  F_SHELL_IN,
156  F_SHELL_OUT,
157  InvalidOid,
158  InvalidOid,
159  InvalidOid,
160  InvalidOid,
161  InvalidOid,
162  InvalidOid,
163  false,
164  InvalidOid,
165  InvalidOid,
166  NULL,
167  false);
168 
169  /* Post creation hook for new shell type */
170  InvokeObjectPostCreateHook(TypeRelationId, typoid, 0);
171 
172  ObjectAddressSet(address, TypeRelationId, typoid);
173 
174  /*
175  * clean up and return the type-oid
176  */
177  heap_freetuple(tup);
178  heap_close(pg_type_desc, RowExclusiveLock);
179 
180  return address;
181 }
#define NameGetDatum(X)
Definition: postgres.h:580
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define Int16GetDatum(X)
Definition: postgres.h:436
int errcode(int sqlerrcode)
Definition: elog.c:575
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1074
#define heap_close(r, l)
Definition: heapam.h:97
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1773
unsigned int Oid
Definition: postgres_ext.h:31
int namestrcpy(Name name, const char *str)
Definition: name.c:216
#define OidIsValid(objectId)
Definition: c.h:605
bool IsBinaryUpgrade
Definition: globals.c:109
signed int int32
Definition: c.h:313
#define HeapTupleSetOid(tuple, oid)
Definition: htup_details.h:710
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:163
Definition: c.h:570
#define RowExclusiveLock
Definition: lockdefs.h:38
#define ereport(elevel, rest)
Definition: elog.h:122
Oid binary_upgrade_next_pg_type_oid
Definition: pg_type.c:39
uintptr_t Datum
Definition: postgres.h:367
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
TupleDesc rd_att
Definition: rel.h:85
#define BoolGetDatum(X)
Definition: postgres.h:387
#define InvalidOid
Definition: postgres_ext.h:36
#define DEFAULT_TYPDELIM
Definition: typecmds.h:22
#define Assert(condition)
Definition: c.h:699
const char * name
Definition: encode.c:521
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define CharGetDatum(X)
Definition: postgres.h:401
static Datum values[MAXATTR]
Definition: bootstrap.c:164
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:372
#define Int32GetDatum(X)
Definition: postgres.h:464
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
void GenerateTypeDependencies(Oid typeNamespace, Oid typeObjectId, Oid relationOid, char relationKind, Oid owner, Oid inputProcedure, Oid outputProcedure, Oid receiveProcedure, Oid sendProcedure, Oid typmodinProcedure, Oid typmodoutProcedure, Oid analyzeProcedure, Oid elementType, bool isImplicitArray, Oid baseType, Oid typeCollation, Node *defaultExpr, bool rebuild)
Definition: pg_type.c:511
#define PointerIsValid(pointer)
Definition: c.h:593

Variable Documentation

◆ binary_upgrade_next_pg_type_oid

Oid binary_upgrade_next_pg_type_oid = InvalidOid

Definition at line 39 of file pg_type.c.

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