PostgreSQL Source Code  git master
pg_type.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * pg_type.c
4  * routines to support manipulation of the pg_type relation
5  *
6  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/catalog/pg_type.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include "access/htup_details.h"
18 #include "access/relation.h"
19 #include "access/table.h"
20 #include "access/xact.h"
21 #include "catalog/binary_upgrade.h"
22 #include "catalog/catalog.h"
23 #include "catalog/dependency.h"
24 #include "catalog/indexing.h"
25 #include "catalog/objectaccess.h"
26 #include "catalog/pg_collation.h"
27 #include "catalog/pg_namespace.h"
28 #include "catalog/pg_proc.h"
29 #include "catalog/pg_type.h"
30 #include "commands/typecmds.h"
31 #include "mb/pg_wchar.h"
32 #include "miscadmin.h"
33 #include "parser/scansup.h"
34 #include "utils/acl.h"
35 #include "utils/builtins.h"
36 #include "utils/fmgroids.h"
37 #include "utils/lsyscache.h"
38 #include "utils/rel.h"
39 #include "utils/syscache.h"
40 
41 static char *makeUniqueTypeName(const char *typeName, Oid typeNamespace,
42  bool tryOriginal);
43 
44 /* Potentially set by pg_upgrade_support functions */
46 
47 /* ----------------------------------------------------------------
48  * TypeShellMake
49  *
50  * This procedure inserts a "shell" tuple into the pg_type relation.
51  * The type tuple inserted has valid but dummy values, and its
52  * "typisdefined" field is false indicating it's not really defined.
53  *
54  * This is used so that a tuple exists in the catalogs. The I/O
55  * functions for the type will link to this tuple. When the full
56  * CREATE TYPE command is issued, the bogus values will be replaced
57  * with correct ones, and "typisdefined" will be set to true.
58  * ----------------------------------------------------------------
59  */
61 TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
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 }
186 
187 /* ----------------------------------------------------------------
188  * TypeCreate
189  *
190  * This does all the necessary work needed to define a new type.
191  *
192  * Returns the ObjectAddress assigned to the new type.
193  * If newTypeOid is zero (the normal case), a new OID is created;
194  * otherwise we use exactly that OID.
195  * ----------------------------------------------------------------
196  */
198 TypeCreate(Oid newTypeOid,
199  const char *typeName,
200  Oid typeNamespace,
201  Oid relationOid, /* only for relation rowtypes */
202  char relationKind, /* ditto */
203  Oid ownerId,
204  int16 internalSize,
205  char typeType,
206  char typeCategory,
207  bool typePreferred,
208  char typDelim,
209  Oid inputProcedure,
210  Oid outputProcedure,
211  Oid receiveProcedure,
212  Oid sendProcedure,
213  Oid typmodinProcedure,
214  Oid typmodoutProcedure,
215  Oid analyzeProcedure,
216  Oid subscriptProcedure,
217  Oid elementType,
218  bool isImplicitArray,
219  Oid arrayType,
220  Oid baseType,
221  const char *defaultTypeValue, /* human-readable rep */
222  char *defaultTypeBin, /* cooked rep */
223  bool passedByValue,
224  char alignment,
225  char storage,
226  int32 typeMod,
227  int32 typNDims, /* Array dimensions for baseType */
228  bool typeNotNull,
229  Oid typeCollation)
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 }
522 
523 /*
524  * Get a list of all distinct collations that the given type depends on.
525  */
526 List *
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 }
581 
582 /*
583  * GenerateTypeDependencies: build the dependencies needed for a type
584  *
585  * Most of what this function needs to know about the type is passed as the
586  * new pg_type row, typeTuple. We make callers pass the pg_type Relation
587  * as well, so that we have easy access to a tuple descriptor for the row.
588  *
589  * While this is able to extract the defaultExpr and typacl from the tuple,
590  * doing so is relatively expensive, and callers may have those values at
591  * hand already. Pass those if handy, otherwise pass NULL. (typacl is really
592  * "Acl *", but we declare it "void *" to avoid including acl.h in pg_type.h.)
593  *
594  * relationKind and isImplicitArray are likewise somewhat expensive to deduce
595  * from the tuple, so we make callers pass those (they're not optional).
596  *
597  * isDependentType is true if this is an implicit array or relation rowtype;
598  * that means it doesn't need its own dependencies on owner etc.
599  *
600  * If rebuild is true, we remove existing dependencies and rebuild them
601  * from scratch. This is needed for ALTER TYPE, and also when replacing
602  * a shell type. We don't remove an existing extension dependency, though.
603  * (That means an extension can't absorb a shell type created in another
604  * extension, nor ALTER a type created by another extension. Also, if it
605  * replaces a free-standing shell type or ALTERs a free-standing type,
606  * that type will become a member of the extension.)
607  */
608 void
610  Relation typeCatalog,
611  Node *defaultExpr,
612  void *typacl,
613  char relationKind, /* only for relation rowtypes */
614  bool isImplicitArray,
615  bool isDependentType,
616  bool rebuild)
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 }
782 
783 /*
784  * RenameTypeInternal
785  * This renames a type, as well as any associated array type.
786  *
787  * Caller must have already checked privileges.
788  *
789  * Currently this is used for renaming table rowtypes and for
790  * ALTER TYPE RENAME TO command.
791  */
792 void
793 RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
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 }
859 
860 
861 /*
862  * makeArrayTypeName
863  * - given a base type name, make an array type name for it
864  *
865  * the caller is responsible for pfreeing the result
866  */
867 char *
868 makeArrayTypeName(const char *typeName, Oid typeNamespace)
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 }
881 
882 
883 /*
884  * moveArrayTypeName
885  * - try to reassign an array type name that the user wants to use.
886  *
887  * The given type name has been discovered to already exist (with the given
888  * OID). If it is an autogenerated array type, change the array type's name
889  * to not conflict. This allows the user to create type "foo" followed by
890  * type "_foo" without problems. (Of course, there are race conditions if
891  * two backends try to create similarly-named types concurrently, but the
892  * worst that can happen is an unnecessary failure --- anything we do here
893  * will be rolled back if the type creation fails due to conflicting names.)
894  *
895  * Note that this must be called *before* calling makeArrayTypeName to
896  * determine the new type's own array type name; else the latter will
897  * certainly pick the same name.
898  *
899  * Returns true if successfully moved the type, false if not.
900  *
901  * We also return true if the given type is a shell type. In this case
902  * the type has not been renamed out of the way, but nonetheless it can
903  * be expected that TypeCreate will succeed. This behavior is convenient
904  * for most callers --- those that need to distinguish the shell-type case
905  * must do their own typisdefined test.
906  */
907 bool
908 moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
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 }
944 
945 
946 /*
947  * makeMultirangeTypeName
948  * - given a range type name, make a multirange type name for it
949  *
950  * caller is responsible for pfreeing the result
951  */
952 char *
953 makeMultirangeTypeName(const char *rangeTypeName, Oid typeNamespace)
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 }
986 
987 /*
988  * makeUniqueTypeName
989  * Generate a unique name for a prospective new type
990  *
991  * Given a typeName, return a new palloc'ed name by preprending underscores
992  * until a non-conflicting name results.
993  *
994  * If tryOriginal, first try with zero underscores.
995  */
996 static char *
997 makeUniqueTypeName(const char *typeName, Oid typeNamespace, bool tryOriginal)
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 }
signed short int16
Definition: c.h:416
#define NIL
Definition: pg_list.h:65
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:315
#define NameGetDatum(X)
Definition: postgres.h:595
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:868
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
int errhint(const char *fmt,...)
Definition: elog.c:1162
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1198
List * list_append_unique_oid(List *list, Oid datum)
Definition: list.c:1217
#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 RelationGetNumberOfAttributes(relation)
Definition: rel.h:463
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2679
#define PointerGetDatum(X)
Definition: postgres.h:556
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2707
char * pstrdup(const char *in)
Definition: mcxt.c:1187
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
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
#define TypeOidIndexId
Definition: pg_type.h:266
#define Int16GetDatum(X)
Definition: postgres.h:451
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:528
bool get_typisdefined(Oid typid)
Definition: lsyscache.c:2093
int errcode(int sqlerrcode)
Definition: elog.c:704
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
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
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
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
ObjectAddress TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
Definition: pg_type.c:61
#define OidIsValid(objectId)
Definition: c.h:698
bool IsBinaryUpgrade
Definition: globals.c:111
signed int int32
Definition: c.h:417
#define NAMEDATALEN
void truncate_identifier(char *ident, int len, bool warn)
Definition: scansup.c:93
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3294
void pfree(void *pointer)
Definition: mcxt.c:1057
static char * makeUniqueTypeName(const char *typeName, Oid typeNamespace, bool tryOriginal)
Definition: pg_type.c:997
#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
ItemPointerData t_self
Definition: htup.h:65
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:967
Definition: c.h:663
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition: pg_type.c:908
#define NoLock
Definition: lockdefs.h:34
static char * buf
Definition: pg_test_fsync.c:68
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:1048
#define CStringGetDatum(X)
Definition: postgres.h:578
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1689
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:1001
Oid binary_upgrade_next_pg_type_oid
Definition: pg_type.c:45
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
void RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
Definition: pg_type.c:793
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
#define TextDatumGetCString(d)
Definition: builtins.h:83
uintptr_t Datum
Definition: postgres.h:367
void CommandCounterIncrement(void)
Definition: xact.c:1021
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
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
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define DEFAULT_TYPDELIM
Definition: typecmds.h:22
#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
void GenerateTypeDependencies(HeapTuple typeTuple, Relation typeCatalog, Node *defaultExpr, void *typacl, char relationKind, bool isImplicitArray, bool isDependentType, bool rebuild)
Definition: pg_type.c:609
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:220
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:195
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:302
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: pg_type.c:198
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
char * makeMultirangeTypeName(const char *rangeTypeName, Oid typeNamespace)
Definition: pg_type.c:953
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition: syscache.h:186
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
void recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, Acl *acl)
Definition: aclchk.c:5466
static Datum values[MAXATTR]
Definition: bootstrap.c:165
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:394
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:175
#define Int32GetDatum(X)
Definition: postgres.h:479
List * GetTypeCollations(Oid typeoid)
Definition: pg_type.c:527
int errmsg(const char *fmt,...)
Definition: elog.c:915
#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
Definition: pg_list.h:50
#define PointerIsValid(pointer)
Definition: c.h:686
Oid get_range_subtype(Oid rangeOid)
Definition: lsyscache.c:3330
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
#define DatumGetAclPCopy(X)
Definition: acl.h:121