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