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-2024, 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/table.h"
19 #include "access/xact.h"
20 #include "catalog/binary_upgrade.h"
21 #include "catalog/catalog.h"
22 #include "catalog/dependency.h"
23 #include "catalog/indexing.h"
24 #include "catalog/objectaccess.h"
25 #include "catalog/pg_collation.h"
26 #include "catalog/pg_namespace.h"
27 #include "catalog/pg_proc.h"
28 #include "catalog/pg_type.h"
29 #include "commands/defrem.h"
30 #include "commands/typecmds.h"
31 #include "mb/pg_wchar.h"
32 #include "miscadmin.h"
33 #include "utils/acl.h"
34 #include "utils/builtins.h"
35 #include "utils/fmgroids.h"
36 #include "utils/lsyscache.h"
37 #include "utils/rel.h"
38 #include "utils/syscache.h"
39 
40 /* Potentially set by pg_upgrade_support functions */
42 
43 /* ----------------------------------------------------------------
44  * TypeShellMake
45  *
46  * This procedure inserts a "shell" tuple into the pg_type relation.
47  * The type tuple inserted has valid but dummy values, and its
48  * "typisdefined" field is false indicating it's not really defined.
49  *
50  * This is used so that a tuple exists in the catalogs. The I/O
51  * functions for the type will link to this tuple. When the full
52  * CREATE TYPE command is issued, the bogus values will be replaced
53  * with correct ones, and "typisdefined" will be set to true.
54  * ----------------------------------------------------------------
55  */
57 TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
58 {
59  Relation pg_type_desc;
60  TupleDesc tupDesc;
61  int i;
62  HeapTuple tup;
63  Datum values[Natts_pg_type];
64  bool nulls[Natts_pg_type];
65  Oid typoid;
66  NameData name;
67  ObjectAddress address;
68 
69  Assert(PointerIsValid(typeName));
70 
71  /*
72  * open pg_type
73  */
74  pg_type_desc = table_open(TypeRelationId, RowExclusiveLock);
75  tupDesc = pg_type_desc->rd_att;
76 
77  /*
78  * initialize our *nulls and *values arrays
79  */
80  for (i = 0; i < Natts_pg_type; ++i)
81  {
82  nulls[i] = false;
83  values[i] = (Datum) NULL; /* redundant, but safe */
84  }
85 
86  /*
87  * initialize *values with the type name and dummy values
88  *
89  * The representational details are the same as int4 ... it doesn't really
90  * matter what they are so long as they are consistent. Also note that we
91  * give it typtype = TYPTYPE_PSEUDO as extra insurance that it won't be
92  * mistaken for a usable type.
93  */
94  namestrcpy(&name, typeName);
95  values[Anum_pg_type_typname - 1] = NameGetDatum(&name);
96  values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace);
97  values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId);
98  values[Anum_pg_type_typlen - 1] = Int16GetDatum(sizeof(int32));
99  values[Anum_pg_type_typbyval - 1] = BoolGetDatum(true);
100  values[Anum_pg_type_typtype - 1] = CharGetDatum(TYPTYPE_PSEUDO);
101  values[Anum_pg_type_typcategory - 1] = CharGetDatum(TYPCATEGORY_PSEUDOTYPE);
102  values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(false);
103  values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(false);
104  values[Anum_pg_type_typdelim - 1] = CharGetDatum(DEFAULT_TYPDELIM);
105  values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(InvalidOid);
106  values[Anum_pg_type_typsubscript - 1] = ObjectIdGetDatum(InvalidOid);
107  values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(InvalidOid);
108  values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(InvalidOid);
109  values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(F_SHELL_IN);
110  values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(F_SHELL_OUT);
111  values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(InvalidOid);
112  values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(InvalidOid);
113  values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(InvalidOid);
114  values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(InvalidOid);
115  values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(InvalidOid);
116  values[Anum_pg_type_typalign - 1] = CharGetDatum(TYPALIGN_INT);
117  values[Anum_pg_type_typstorage - 1] = CharGetDatum(TYPSTORAGE_PLAIN);
118  values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(false);
119  values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(InvalidOid);
120  values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(-1);
121  values[Anum_pg_type_typndims - 1] = Int32GetDatum(0);
122  values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(InvalidOid);
123  nulls[Anum_pg_type_typdefaultbin - 1] = true;
124  nulls[Anum_pg_type_typdefault - 1] = true;
125  nulls[Anum_pg_type_typacl - 1] = true;
126 
127  /* Use binary-upgrade override for pg_type.oid? */
128  if (IsBinaryUpgrade)
129  {
131  ereport(ERROR,
132  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
133  errmsg("pg_type OID value not set when in binary upgrade mode")));
134 
137  }
138  else
139  {
140  typoid = GetNewOidWithIndex(pg_type_desc, TypeOidIndexId,
141  Anum_pg_type_oid);
142  }
143 
144  values[Anum_pg_type_oid - 1] = ObjectIdGetDatum(typoid);
145 
146  /*
147  * create a new type tuple
148  */
149  tup = heap_form_tuple(tupDesc, values, nulls);
150 
151  /*
152  * insert the tuple in the relation and get the tuple's oid.
153  */
154  CatalogTupleInsert(pg_type_desc, tup);
155 
156  /*
157  * Create dependencies. We can/must skip this in bootstrap mode.
158  */
161  pg_type_desc,
162  NULL,
163  NULL,
164  0,
165  false,
166  false,
167  true, /* make extension dependency */
168  false);
169 
170  /* Post creation hook for new shell type */
171  InvokeObjectPostCreateHook(TypeRelationId, typoid, 0);
172 
173  ObjectAddressSet(address, TypeRelationId, typoid);
174 
175  /*
176  * clean up and return the type-oid
177  */
178  heap_freetuple(tup);
179  table_close(pg_type_desc, RowExclusiveLock);
180 
181  return address;
182 }
183 
184 /* ----------------------------------------------------------------
185  * TypeCreate
186  *
187  * This does all the necessary work needed to define a new type.
188  *
189  * Returns the ObjectAddress assigned to the new type.
190  * If newTypeOid is zero (the normal case), a new OID is created;
191  * otherwise we use exactly that OID.
192  * ----------------------------------------------------------------
193  */
195 TypeCreate(Oid newTypeOid,
196  const char *typeName,
197  Oid typeNamespace,
198  Oid relationOid, /* only for relation rowtypes */
199  char relationKind, /* ditto */
200  Oid ownerId,
201  int16 internalSize,
202  char typeType,
203  char typeCategory,
204  bool typePreferred,
205  char typDelim,
206  Oid inputProcedure,
207  Oid outputProcedure,
208  Oid receiveProcedure,
209  Oid sendProcedure,
210  Oid typmodinProcedure,
211  Oid typmodoutProcedure,
212  Oid analyzeProcedure,
213  Oid subscriptProcedure,
214  Oid elementType,
215  bool isImplicitArray,
216  Oid arrayType,
217  Oid baseType,
218  const char *defaultTypeValue, /* human-readable rep */
219  char *defaultTypeBin, /* cooked rep */
220  bool passedByValue,
221  char alignment,
222  char storage,
223  int32 typeMod,
224  int32 typNDims, /* Array dimensions for baseType */
225  bool typeNotNull,
226  Oid typeCollation)
227 {
228  Relation pg_type_desc;
229  Oid typeObjectId;
230  bool isDependentType;
231  bool rebuildDeps = false;
232  Acl *typacl;
233  HeapTuple tup;
234  bool nulls[Natts_pg_type];
235  bool replaces[Natts_pg_type];
236  Datum values[Natts_pg_type];
237  NameData name;
238  int i;
239  ObjectAddress address;
240 
241  /*
242  * We assume that the caller validated the arguments individually, but did
243  * not check for bad combinations.
244  *
245  * Validate size specifications: either positive (fixed-length) or -1
246  * (varlena) or -2 (cstring).
247  */
248  if (!(internalSize > 0 ||
249  internalSize == -1 ||
250  internalSize == -2))
251  ereport(ERROR,
252  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
253  errmsg("invalid type internal size %d",
254  internalSize)));
255 
256  if (passedByValue)
257  {
258  /*
259  * Pass-by-value types must have a fixed length that is one of the
260  * values supported by fetch_att() and store_att_byval(); and the
261  * alignment had better agree, too. All this code must match
262  * access/tupmacs.h!
263  */
264  if (internalSize == (int16) sizeof(char))
265  {
266  if (alignment != TYPALIGN_CHAR)
267  ereport(ERROR,
268  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
269  errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
270  alignment, internalSize)));
271  }
272  else if (internalSize == (int16) sizeof(int16))
273  {
274  if (alignment != TYPALIGN_SHORT)
275  ereport(ERROR,
276  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
277  errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
278  alignment, internalSize)));
279  }
280  else if (internalSize == (int16) sizeof(int32))
281  {
282  if (alignment != TYPALIGN_INT)
283  ereport(ERROR,
284  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
285  errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
286  alignment, internalSize)));
287  }
288 #if SIZEOF_DATUM == 8
289  else if (internalSize == (int16) sizeof(Datum))
290  {
291  if (alignment != TYPALIGN_DOUBLE)
292  ereport(ERROR,
293  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
294  errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
295  alignment, internalSize)));
296  }
297 #endif
298  else
299  ereport(ERROR,
300  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
301  errmsg("internal size %d is invalid for passed-by-value type",
302  internalSize)));
303  }
304  else
305  {
306  /* varlena types must have int align or better */
307  if (internalSize == -1 &&
308  !(alignment == TYPALIGN_INT || alignment == TYPALIGN_DOUBLE))
309  ereport(ERROR,
310  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
311  errmsg("alignment \"%c\" is invalid for variable-length type",
312  alignment)));
313  /* cstring must have char alignment */
314  if (internalSize == -2 && !(alignment == TYPALIGN_CHAR))
315  ereport(ERROR,
316  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
317  errmsg("alignment \"%c\" is invalid for variable-length type",
318  alignment)));
319  }
320 
321  /* Only varlena types can be toasted */
322  if (storage != TYPSTORAGE_PLAIN && internalSize != -1)
323  ereport(ERROR,
324  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
325  errmsg("fixed-size types must have storage PLAIN")));
326 
327  /*
328  * This is a dependent type if it's an implicitly-created array type or
329  * multirange type, or if it's a relation rowtype that's not a composite
330  * type. For such types we'll leave the ACL empty, and we'll skip
331  * creating some dependency records because there will be a dependency
332  * already through the depended-on type or relation. (Caution: this is
333  * closely intertwined with some behavior in GenerateTypeDependencies.)
334  */
335  isDependentType = isImplicitArray ||
336  typeType == TYPTYPE_MULTIRANGE ||
337  (OidIsValid(relationOid) && relationKind != RELKIND_COMPOSITE_TYPE);
338 
339  /*
340  * initialize arrays needed for heap_form_tuple or heap_modify_tuple
341  */
342  for (i = 0; i < Natts_pg_type; ++i)
343  {
344  nulls[i] = false;
345  replaces[i] = true;
346  values[i] = (Datum) 0;
347  }
348 
349  /*
350  * insert data values
351  */
352  namestrcpy(&name, typeName);
353  values[Anum_pg_type_typname - 1] = NameGetDatum(&name);
354  values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace);
355  values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId);
356  values[Anum_pg_type_typlen - 1] = Int16GetDatum(internalSize);
357  values[Anum_pg_type_typbyval - 1] = BoolGetDatum(passedByValue);
358  values[Anum_pg_type_typtype - 1] = CharGetDatum(typeType);
359  values[Anum_pg_type_typcategory - 1] = CharGetDatum(typeCategory);
360  values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(typePreferred);
361  values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(true);
362  values[Anum_pg_type_typdelim - 1] = CharGetDatum(typDelim);
363  values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(relationOid);
364  values[Anum_pg_type_typsubscript - 1] = ObjectIdGetDatum(subscriptProcedure);
365  values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(elementType);
366  values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(arrayType);
367  values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(inputProcedure);
368  values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(outputProcedure);
369  values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(receiveProcedure);
370  values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(sendProcedure);
371  values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(typmodinProcedure);
372  values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(typmodoutProcedure);
373  values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(analyzeProcedure);
374  values[Anum_pg_type_typalign - 1] = CharGetDatum(alignment);
375  values[Anum_pg_type_typstorage - 1] = CharGetDatum(storage);
376  values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(typeNotNull);
377  values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(baseType);
378  values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(typeMod);
379  values[Anum_pg_type_typndims - 1] = Int32GetDatum(typNDims);
380  values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(typeCollation);
381 
382  /*
383  * initialize the default binary value for this type. Check for nulls of
384  * course.
385  */
386  if (defaultTypeBin)
387  values[Anum_pg_type_typdefaultbin - 1] = CStringGetTextDatum(defaultTypeBin);
388  else
389  nulls[Anum_pg_type_typdefaultbin - 1] = true;
390 
391  /*
392  * initialize the default value for this type.
393  */
394  if (defaultTypeValue)
395  values[Anum_pg_type_typdefault - 1] = CStringGetTextDatum(defaultTypeValue);
396  else
397  nulls[Anum_pg_type_typdefault - 1] = true;
398 
399  /*
400  * Initialize the type's ACL, too. But dependent types don't get one.
401  */
402  if (isDependentType)
403  typacl = NULL;
404  else
405  typacl = get_user_default_acl(OBJECT_TYPE, ownerId,
406  typeNamespace);
407  if (typacl != NULL)
408  values[Anum_pg_type_typacl - 1] = PointerGetDatum(typacl);
409  else
410  nulls[Anum_pg_type_typacl - 1] = true;
411 
412  /*
413  * open pg_type and prepare to insert or update a row.
414  *
415  * NOTE: updating will not work correctly in bootstrap mode; but we don't
416  * expect to be overwriting any shell types in bootstrap mode.
417  */
418  pg_type_desc = table_open(TypeRelationId, RowExclusiveLock);
419 
420  tup = SearchSysCacheCopy2(TYPENAMENSP,
421  CStringGetDatum(typeName),
422  ObjectIdGetDatum(typeNamespace));
423  if (HeapTupleIsValid(tup))
424  {
425  Form_pg_type typform = (Form_pg_type) GETSTRUCT(tup);
426 
427  /*
428  * check that the type is not already defined. It may exist as a
429  * shell type, however.
430  */
431  if (typform->typisdefined)
432  ereport(ERROR,
434  errmsg("type \"%s\" already exists", typeName)));
435 
436  /*
437  * shell type must have been created by same owner
438  */
439  if (typform->typowner != ownerId)
441 
442  /* trouble if caller wanted to force the OID */
443  if (OidIsValid(newTypeOid))
444  elog(ERROR, "cannot assign new OID to existing shell type");
445 
446  replaces[Anum_pg_type_oid - 1] = false;
447 
448  /*
449  * Okay to update existing shell type tuple
450  */
451  tup = heap_modify_tuple(tup,
452  RelationGetDescr(pg_type_desc),
453  values,
454  nulls,
455  replaces);
456 
457  CatalogTupleUpdate(pg_type_desc, &tup->t_self, tup);
458 
459  typeObjectId = typform->oid;
460 
461  rebuildDeps = true; /* get rid of shell type's dependencies */
462  }
463  else
464  {
465  /* Force the OID if requested by caller */
466  if (OidIsValid(newTypeOid))
467  typeObjectId = newTypeOid;
468  /* Use binary-upgrade override for pg_type.oid, if supplied. */
469  else if (IsBinaryUpgrade)
470  {
472  ereport(ERROR,
473  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
474  errmsg("pg_type OID value not set when in binary upgrade mode")));
475 
476  typeObjectId = binary_upgrade_next_pg_type_oid;
478  }
479  else
480  {
481  typeObjectId = GetNewOidWithIndex(pg_type_desc, TypeOidIndexId,
482  Anum_pg_type_oid);
483  }
484 
485  values[Anum_pg_type_oid - 1] = ObjectIdGetDatum(typeObjectId);
486 
487  tup = heap_form_tuple(RelationGetDescr(pg_type_desc),
488  values, nulls);
489 
490  CatalogTupleInsert(pg_type_desc, tup);
491  }
492 
493  /*
494  * Create dependencies. We can/must skip this in bootstrap mode.
495  */
498  pg_type_desc,
499  (defaultTypeBin ?
500  stringToNode(defaultTypeBin) :
501  NULL),
502  typacl,
503  relationKind,
504  isImplicitArray,
505  isDependentType,
506  true, /* make extension dependency */
507  rebuildDeps);
508 
509  /* Post creation hook for new type */
510  InvokeObjectPostCreateHook(TypeRelationId, typeObjectId, 0);
511 
512  ObjectAddressSet(address, TypeRelationId, typeObjectId);
513 
514  /*
515  * finish up
516  */
517  table_close(pg_type_desc, RowExclusiveLock);
518 
519  return address;
520 }
521 
522 /*
523  * GenerateTypeDependencies: build the dependencies needed for a type
524  *
525  * Most of what this function needs to know about the type is passed as the
526  * new pg_type row, typeTuple. We make callers pass the pg_type Relation
527  * as well, so that we have easy access to a tuple descriptor for the row.
528  *
529  * While this is able to extract the defaultExpr and typacl from the tuple,
530  * doing so is relatively expensive, and callers may have those values at
531  * hand already. Pass those if handy, otherwise pass NULL. (typacl is really
532  * "Acl *", but we declare it "void *" to avoid including acl.h in pg_type.h.)
533  *
534  * relationKind and isImplicitArray are likewise somewhat expensive to deduce
535  * from the tuple, so we make callers pass those (they're not optional).
536  *
537  * isDependentType is true if this is an implicit array, multirange, or
538  * relation rowtype; that means it doesn't need its own dependencies on owner
539  * etc.
540  *
541  * We make an extension-membership dependency if we're in an extension
542  * script and makeExtensionDep is true.
543  * makeExtensionDep should be true when creating a new type or replacing a
544  * shell type, but not for ALTER TYPE on an existing type. Passing false
545  * causes the type's extension membership to be left alone.
546  *
547  * rebuild should be true if this is a pre-existing type. We will remove
548  * existing dependencies and rebuild them from scratch. This is needed for
549  * ALTER TYPE, and also when replacing a shell type. We don't remove any
550  * existing extension dependency, though; hence, if makeExtensionDep is also
551  * true and we're in an extension script, an error will occur unless the
552  * type already belongs to the current extension. That's the behavior we
553  * want when replacing a shell type, which is the only case where both flags
554  * are true.
555  */
556 void
558  Relation typeCatalog,
559  Node *defaultExpr,
560  void *typacl,
561  char relationKind, /* only for relation rowtypes */
562  bool isImplicitArray,
563  bool isDependentType,
564  bool makeExtensionDep,
565  bool rebuild)
566 {
567  Form_pg_type typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
568  Oid typeObjectId = typeForm->oid;
569  Datum datum;
570  bool isNull;
571  ObjectAddress myself,
572  referenced;
573  ObjectAddresses *addrs_normal;
574 
575  /* Extract defaultExpr if caller didn't pass it */
576  if (defaultExpr == NULL)
577  {
578  datum = heap_getattr(typeTuple, Anum_pg_type_typdefaultbin,
579  RelationGetDescr(typeCatalog), &isNull);
580  if (!isNull)
581  defaultExpr = stringToNode(TextDatumGetCString(datum));
582  }
583  /* Extract typacl if caller didn't pass it */
584  if (typacl == NULL)
585  {
586  datum = heap_getattr(typeTuple, Anum_pg_type_typacl,
587  RelationGetDescr(typeCatalog), &isNull);
588  if (!isNull)
589  typacl = DatumGetAclPCopy(datum);
590  }
591 
592  /* If rebuild, first flush old dependencies, except extension deps */
593  if (rebuild)
594  {
595  deleteDependencyRecordsFor(TypeRelationId, typeObjectId, true);
596  deleteSharedDependencyRecordsFor(TypeRelationId, typeObjectId, 0);
597  }
598 
599  ObjectAddressSet(myself, TypeRelationId, typeObjectId);
600 
601  /*
602  * Make dependencies on namespace, owner, ACL.
603  *
604  * Skip these for a dependent type, since it will have such dependencies
605  * indirectly through its depended-on type or relation. An exception is
606  * that multiranges need their own namespace dependency, since we don't
607  * force them to be in the same schema as their range type.
608  */
609 
610  /* collects normal dependencies for bulk recording */
611  addrs_normal = new_object_addresses();
612 
613  if (!isDependentType || typeForm->typtype == TYPTYPE_MULTIRANGE)
614  {
615  ObjectAddressSet(referenced, NamespaceRelationId,
616  typeForm->typnamespace);
617  add_exact_object_address(&referenced, addrs_normal);
618  }
619 
620  if (!isDependentType)
621  {
622  recordDependencyOnOwner(TypeRelationId, typeObjectId,
623  typeForm->typowner);
624 
625  recordDependencyOnNewAcl(TypeRelationId, typeObjectId, 0,
626  typeForm->typowner, typacl);
627  }
628 
629  /*
630  * Make extension dependency if requested.
631  *
632  * We used to skip this for dependent types, but it seems better to record
633  * their extension membership explicitly; otherwise code such as
634  * postgres_fdw's shippability test will be fooled.
635  */
636  if (makeExtensionDep)
637  recordDependencyOnCurrentExtension(&myself, rebuild);
638 
639  /* Normal dependencies on the I/O and support functions */
640  if (OidIsValid(typeForm->typinput))
641  {
642  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typinput);
643  add_exact_object_address(&referenced, addrs_normal);
644  }
645 
646  if (OidIsValid(typeForm->typoutput))
647  {
648  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typoutput);
649  add_exact_object_address(&referenced, addrs_normal);
650  }
651 
652  if (OidIsValid(typeForm->typreceive))
653  {
654  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typreceive);
655  add_exact_object_address(&referenced, addrs_normal);
656  }
657 
658  if (OidIsValid(typeForm->typsend))
659  {
660  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typsend);
661  add_exact_object_address(&referenced, addrs_normal);
662  }
663 
664  if (OidIsValid(typeForm->typmodin))
665  {
666  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typmodin);
667  add_exact_object_address(&referenced, addrs_normal);
668  }
669 
670  if (OidIsValid(typeForm->typmodout))
671  {
672  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typmodout);
673  add_exact_object_address(&referenced, addrs_normal);
674  }
675 
676  if (OidIsValid(typeForm->typanalyze))
677  {
678  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typanalyze);
679  add_exact_object_address(&referenced, addrs_normal);
680  }
681 
682  if (OidIsValid(typeForm->typsubscript))
683  {
684  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typsubscript);
685  add_exact_object_address(&referenced, addrs_normal);
686  }
687 
688  /* Normal dependency from a domain to its base type. */
689  if (OidIsValid(typeForm->typbasetype))
690  {
691  ObjectAddressSet(referenced, TypeRelationId, typeForm->typbasetype);
692  add_exact_object_address(&referenced, addrs_normal);
693  }
694 
695  /*
696  * Normal dependency from a domain to its collation. We know the default
697  * collation is pinned, so don't bother recording it.
698  */
699  if (OidIsValid(typeForm->typcollation) &&
700  typeForm->typcollation != DEFAULT_COLLATION_OID)
701  {
702  ObjectAddressSet(referenced, CollationRelationId, typeForm->typcollation);
703  add_exact_object_address(&referenced, addrs_normal);
704  }
705 
707  free_object_addresses(addrs_normal);
708 
709  /* Normal dependency on the default expression. */
710  if (defaultExpr)
711  recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);
712 
713  /*
714  * If the type is a rowtype for a relation, mark it as internally
715  * dependent on the relation, *unless* it is a stand-alone composite type
716  * relation. For the latter case, we have to reverse the dependency.
717  *
718  * In the former case, this allows the type to be auto-dropped when the
719  * relation is, and not otherwise. And in the latter, of course we get the
720  * opposite effect.
721  */
722  if (OidIsValid(typeForm->typrelid))
723  {
724  ObjectAddressSet(referenced, RelationRelationId, typeForm->typrelid);
725 
726  if (relationKind != RELKIND_COMPOSITE_TYPE)
727  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
728  else
729  recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
730  }
731 
732  /*
733  * If the type is an implicitly-created array type, mark it as internally
734  * dependent on the element type. Otherwise, if it has an element type,
735  * the dependency is a normal one.
736  */
737  if (OidIsValid(typeForm->typelem))
738  {
739  ObjectAddressSet(referenced, TypeRelationId, typeForm->typelem);
740  recordDependencyOn(&myself, &referenced,
741  isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL);
742  }
743 
744  /*
745  * Note: you might expect that we should record an internal dependency of
746  * a multirange on its range type here, by analogy with the cases above.
747  * But instead, that is done by RangeCreate(), which also handles
748  * recording of other range-type-specific dependencies. That's pretty
749  * bogus. It's okay for now, because there are no cases where we need to
750  * regenerate the dependencies of a range or multirange type. But someday
751  * we might need to move that logic here to allow such regeneration.
752  */
753 }
754 
755 /*
756  * RenameTypeInternal
757  * This renames a type, as well as any associated array type.
758  *
759  * Caller must have already checked privileges.
760  *
761  * Currently this is used for renaming table rowtypes and for
762  * ALTER TYPE RENAME TO command.
763  */
764 void
765 RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
766 {
767  Relation pg_type_desc;
768  HeapTuple tuple;
769  Form_pg_type typ;
770  Oid arrayOid;
771  Oid oldTypeOid;
772 
773  pg_type_desc = table_open(TypeRelationId, RowExclusiveLock);
774 
775  tuple = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
776  if (!HeapTupleIsValid(tuple))
777  elog(ERROR, "cache lookup failed for type %u", typeOid);
778  typ = (Form_pg_type) GETSTRUCT(tuple);
779 
780  /* We are not supposed to be changing schemas here */
781  Assert(typeNamespace == typ->typnamespace);
782 
783  arrayOid = typ->typarray;
784 
785  /* Check for a conflicting type name. */
786  oldTypeOid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
787  CStringGetDatum(newTypeName),
788  ObjectIdGetDatum(typeNamespace));
789 
790  /*
791  * If there is one, see if it's an autogenerated array type, and if so
792  * rename it out of the way. (But we must skip that for a shell type
793  * because moveArrayTypeName will do the wrong thing in that case.)
794  * Otherwise, we can at least give a more friendly error than unique-index
795  * violation.
796  */
797  if (OidIsValid(oldTypeOid))
798  {
799  if (get_typisdefined(oldTypeOid) &&
800  moveArrayTypeName(oldTypeOid, newTypeName, typeNamespace))
801  /* successfully dodged the problem */ ;
802  else
803  ereport(ERROR,
805  errmsg("type \"%s\" already exists", newTypeName)));
806  }
807 
808  /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
809  namestrcpy(&(typ->typname), newTypeName);
810 
811  CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple);
812 
813  InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
814 
815  heap_freetuple(tuple);
816  table_close(pg_type_desc, RowExclusiveLock);
817 
818  /*
819  * If the type has an array type, recurse to handle that. But we don't
820  * need to do anything more if we already renamed that array type above
821  * (which would happen when, eg, renaming "foo" to "_foo").
822  */
823  if (OidIsValid(arrayOid) && arrayOid != oldTypeOid)
824  {
825  char *arrname = makeArrayTypeName(newTypeName, typeNamespace);
826 
827  RenameTypeInternal(arrayOid, arrname, typeNamespace);
828  pfree(arrname);
829  }
830 }
831 
832 
833 /*
834  * makeArrayTypeName
835  * - given a base type name, make an array type name for it
836  *
837  * the caller is responsible for pfreeing the result
838  */
839 char *
840 makeArrayTypeName(const char *typeName, Oid typeNamespace)
841 {
842  char *arr_name;
843  int pass = 0;
844  char suffix[NAMEDATALEN];
845 
846  /*
847  * Per ancient Postgres tradition, array type names are made by prepending
848  * an underscore to the base type name. Much client code knows that
849  * convention, so don't muck with it. However, the tradition is less
850  * clear about what to do in the corner cases where the resulting name is
851  * too long or conflicts with an existing name. Our current rules are (1)
852  * truncate the base name on the right as needed, and (2) if there is a
853  * conflict, append another underscore and some digits chosen to make it
854  * unique. This is similar to what ChooseRelationName() does.
855  *
856  * The actual name generation can be farmed out to makeObjectName() by
857  * giving it an empty first name component.
858  */
859 
860  /* First, try with no numeric suffix */
861  arr_name = makeObjectName("", typeName, NULL);
862 
863  for (;;)
864  {
865  if (!SearchSysCacheExists2(TYPENAMENSP,
866  CStringGetDatum(arr_name),
867  ObjectIdGetDatum(typeNamespace)))
868  break;
869 
870  /* That attempt conflicted. Prepare a new name with some digits. */
871  pfree(arr_name);
872  snprintf(suffix, sizeof(suffix), "%d", ++pass);
873  arr_name = makeObjectName("", typeName, suffix);
874  }
875 
876  return arr_name;
877 }
878 
879 
880 /*
881  * moveArrayTypeName
882  * - try to reassign an array type name that the user wants to use.
883  *
884  * The given type name has been discovered to already exist (with the given
885  * OID). If it is an autogenerated array type, change the array type's name
886  * to not conflict. This allows the user to create type "foo" followed by
887  * type "_foo" without problems. (Of course, there are race conditions if
888  * two backends try to create similarly-named types concurrently, but the
889  * worst that can happen is an unnecessary failure --- anything we do here
890  * will be rolled back if the type creation fails due to conflicting names.)
891  *
892  * Note that this must be called *before* calling makeArrayTypeName to
893  * determine the new type's own array type name; else the latter will
894  * certainly pick the same name.
895  *
896  * Returns true if successfully moved the type, false if not.
897  *
898  * We also return true if the given type is a shell type. In this case
899  * the type has not been renamed out of the way, but nonetheless it can
900  * be expected that TypeCreate will succeed. This behavior is convenient
901  * for most callers --- those that need to distinguish the shell-type case
902  * must do their own typisdefined test.
903  */
904 bool
905 moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
906 {
907  Oid elemOid;
908  char *newname;
909 
910  /* We need do nothing if it's a shell type. */
911  if (!get_typisdefined(typeOid))
912  return true;
913 
914  /* Can't change it if it's not an autogenerated array type. */
915  elemOid = get_element_type(typeOid);
916  if (!OidIsValid(elemOid) ||
917  get_array_type(elemOid) != typeOid)
918  return false;
919 
920  /*
921  * OK, use makeArrayTypeName to pick an unused modification of the name.
922  * Note that since makeArrayTypeName is an iterative process, this will
923  * produce a name that it might have produced the first time, had the
924  * conflicting type we are about to create already existed.
925  */
926  newname = makeArrayTypeName(typeName, typeNamespace);
927 
928  /* Apply the rename */
929  RenameTypeInternal(typeOid, newname, typeNamespace);
930 
931  /*
932  * We must bump the command counter so that any subsequent use of
933  * makeArrayTypeName sees what we just did and doesn't pick the same name.
934  */
936 
937  pfree(newname);
938 
939  return true;
940 }
941 
942 
943 /*
944  * makeMultirangeTypeName
945  * - given a range type name, make a multirange type name for it
946  *
947  * caller is responsible for pfreeing the result
948  */
949 char *
950 makeMultirangeTypeName(const char *rangeTypeName, Oid typeNamespace)
951 {
952  char *buf;
953  char *rangestr;
954 
955  /*
956  * If the range type name contains "range" then change that to
957  * "multirange". Otherwise add "_multirange" to the end.
958  */
959  rangestr = strstr(rangeTypeName, "range");
960  if (rangestr)
961  {
962  char *prefix = pnstrdup(rangeTypeName, rangestr - rangeTypeName);
963 
964  buf = psprintf("%s%s%s", prefix, "multi", rangestr);
965  }
966  else
967  buf = psprintf("%s_multirange", pnstrdup(rangeTypeName, NAMEDATALEN - 12));
968 
969  /* clip it at NAMEDATALEN-1 bytes */
970  buf[pg_mbcliplen(buf, strlen(buf), NAMEDATALEN - 1)] = '\0';
971 
972  if (SearchSysCacheExists2(TYPENAMENSP,
974  ObjectIdGetDatum(typeNamespace)))
975  ereport(ERROR,
977  errmsg("type \"%s\" already exists", buf),
978  errdetail("Failed while creating a multirange type for type \"%s\".", rangeTypeName),
979  errhint("You can manually specify a multirange type name using the \"multirange_type_name\" attribute.")));
980 
981  return pstrdup(buf);
982 }
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
#define DatumGetAclPCopy(X)
Definition: acl.h:121
void recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, Acl *acl)
Definition: aclchk.c:4379
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2702
Acl * get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
Definition: aclchk.c:4303
static Datum values[MAXATTR]
Definition: bootstrap.c:152
#define CStringGetTextDatum(s)
Definition: builtins.h:97
#define TextDatumGetCString(d)
Definition: builtins.h:98
signed short int16
Definition: c.h:493
signed int int32
Definition: c.h:494
#define Assert(condition)
Definition: c.h:858
#define PointerIsValid(pointer)
Definition: c.h:763
#define OidIsValid(objectId)
Definition: c.h:775
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:391
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2740
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1551
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2485
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2531
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2771
@ DEPENDENCY_INTERNAL
Definition: dependency.h:35
@ DEPENDENCY_NORMAL
Definition: dependency.h:33
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:857
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define ereport(elevel,...)
Definition: elog.h:149
bool IsBinaryUpgrade
Definition: globals.c:118
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition: heaptuple.c:1209
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1116
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1434
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
#define storage
Definition: indent_codes.h:68
char * makeObjectName(const char *name1, const char *name2, const char *label)
Definition: indexcmds.c:2409
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
int i
Definition: isn.c:73
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2759
bool get_typisdefined(Oid typid)
Definition: lsyscache.c:2173
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2787
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:1083
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1706
char * pstrdup(const char *in)
Definition: mcxt.c:1695
void pfree(void *pointer)
Definition: mcxt.c:1520
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:454
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:173
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
@ OBJECT_TYPE
Definition: parsenodes.h:2310
#define NAMEDATALEN
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:46
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:302
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:194
#define NIL
Definition: pg_list.h:68
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:1039
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:165
static char * buf
Definition: pg_test_fsync.c:73
char * makeMultirangeTypeName(const char *rangeTypeName, Oid typeNamespace)
Definition: pg_type.c:950
void GenerateTypeDependencies(HeapTuple typeTuple, Relation typeCatalog, Node *defaultExpr, void *typacl, char relationKind, bool isImplicitArray, bool isDependentType, bool makeExtensionDep, bool rebuild)
Definition: pg_type.c:557
void RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
Definition: pg_type.c:765
Oid binary_upgrade_next_pg_type_oid
Definition: pg_type.c:41
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:195
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:840
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition: pg_type.c:905
ObjectAddress TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
Definition: pg_type.c:57
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
#define snprintf
Definition: port.h:238
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:172
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Datum NameGetDatum(const NameData *X)
Definition: postgres.h:373
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
static Datum CharGetDatum(char X)
Definition: postgres.h:122
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
void * stringToNode(const char *str)
Definition: read.c:90
#define RelationGetDescr(relation)
Definition: rel.h:531
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
ItemPointerData t_self
Definition: htup.h:65
Definition: nodes.h:129
TupleDesc rd_att
Definition: rel.h:112
Definition: c.h:741
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:86
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:88
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition: syscache.h:97
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:106
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
#define DEFAULT_TYPDELIM
Definition: typecmds.h:22
const char * name
void CommandCounterIncrement(void)
Definition: xact.c:1097