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/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/typecmds.h"
30 #include "mb/pg_wchar.h"
31 #include "miscadmin.h"
32 #include "parser/scansup.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 static char *makeUniqueTypeName(const char *typeName, Oid typeNamespace,
41  bool tryOriginal);
42 
43 /* Potentially set by pg_upgrade_support functions */
45 
46 /* ----------------------------------------------------------------
47  * TypeShellMake
48  *
49  * This procedure inserts a "shell" tuple into the pg_type relation.
50  * The type tuple inserted has valid but dummy values, and its
51  * "typisdefined" field is false indicating it's not really defined.
52  *
53  * This is used so that a tuple exists in the catalogs. The I/O
54  * functions for the type will link to this tuple. When the full
55  * CREATE TYPE command is issued, the bogus values will be replaced
56  * with correct ones, and "typisdefined" will be set to true.
57  * ----------------------------------------------------------------
58  */
60 TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
61 {
62  Relation pg_type_desc;
63  TupleDesc tupDesc;
64  int i;
65  HeapTuple tup;
66  Datum values[Natts_pg_type];
67  bool nulls[Natts_pg_type];
68  Oid typoid;
69  NameData name;
70  ObjectAddress address;
71 
72  Assert(PointerIsValid(typeName));
73 
74  /*
75  * open pg_type
76  */
77  pg_type_desc = table_open(TypeRelationId, RowExclusiveLock);
78  tupDesc = pg_type_desc->rd_att;
79 
80  /*
81  * initialize our *nulls and *values arrays
82  */
83  for (i = 0; i < Natts_pg_type; ++i)
84  {
85  nulls[i] = false;
86  values[i] = (Datum) NULL; /* redundant, but safe */
87  }
88 
89  /*
90  * initialize *values with the type name and dummy values
91  *
92  * The representational details are the same as int4 ... it doesn't really
93  * matter what they are so long as they are consistent. Also note that we
94  * give it typtype = TYPTYPE_PSEUDO as extra insurance that it won't be
95  * mistaken for a usable type.
96  */
97  namestrcpy(&name, typeName);
98  values[Anum_pg_type_typname - 1] = NameGetDatum(&name);
99  values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace);
100  values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId);
101  values[Anum_pg_type_typlen - 1] = Int16GetDatum(sizeof(int32));
102  values[Anum_pg_type_typbyval - 1] = BoolGetDatum(true);
103  values[Anum_pg_type_typtype - 1] = CharGetDatum(TYPTYPE_PSEUDO);
104  values[Anum_pg_type_typcategory - 1] = CharGetDatum(TYPCATEGORY_PSEUDOTYPE);
105  values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(false);
106  values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(false);
107  values[Anum_pg_type_typdelim - 1] = CharGetDatum(DEFAULT_TYPDELIM);
108  values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(InvalidOid);
109  values[Anum_pg_type_typsubscript - 1] = ObjectIdGetDatum(InvalidOid);
110  values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(InvalidOid);
111  values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(InvalidOid);
112  values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(F_SHELL_IN);
113  values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(F_SHELL_OUT);
114  values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(InvalidOid);
115  values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(InvalidOid);
116  values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(InvalidOid);
117  values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(InvalidOid);
118  values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(InvalidOid);
119  values[Anum_pg_type_typalign - 1] = CharGetDatum(TYPALIGN_INT);
120  values[Anum_pg_type_typstorage - 1] = CharGetDatum(TYPSTORAGE_PLAIN);
121  values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(false);
122  values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(InvalidOid);
123  values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(-1);
124  values[Anum_pg_type_typndims - 1] = Int32GetDatum(0);
125  values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(InvalidOid);
126  nulls[Anum_pg_type_typdefaultbin - 1] = true;
127  nulls[Anum_pg_type_typdefault - 1] = true;
128  nulls[Anum_pg_type_typacl - 1] = true;
129 
130  /* Use binary-upgrade override for pg_type.oid? */
131  if (IsBinaryUpgrade)
132  {
134  ereport(ERROR,
135  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
136  errmsg("pg_type OID value not set when in binary upgrade mode")));
137 
140  }
141  else
142  {
143  typoid = GetNewOidWithIndex(pg_type_desc, TypeOidIndexId,
144  Anum_pg_type_oid);
145  }
146 
147  values[Anum_pg_type_oid - 1] = ObjectIdGetDatum(typoid);
148 
149  /*
150  * create a new type tuple
151  */
152  tup = heap_form_tuple(tupDesc, values, nulls);
153 
154  /*
155  * insert the tuple in the relation and get the tuple's oid.
156  */
157  CatalogTupleInsert(pg_type_desc, tup);
158 
159  /*
160  * Create dependencies. We can/must skip this in bootstrap mode.
161  */
164  pg_type_desc,
165  NULL,
166  NULL,
167  0,
168  false,
169  false,
170  true, /* make extension dependency */
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  true, /* make extension dependency */
509  rebuildDeps);
510 
511  /* Post creation hook for new type */
512  InvokeObjectPostCreateHook(TypeRelationId, typeObjectId, 0);
513 
514  ObjectAddressSet(address, TypeRelationId, typeObjectId);
515 
516  /*
517  * finish up
518  */
519  table_close(pg_type_desc, RowExclusiveLock);
520 
521  return address;
522 }
523 
524 /*
525  * GenerateTypeDependencies: build the dependencies needed for a type
526  *
527  * Most of what this function needs to know about the type is passed as the
528  * new pg_type row, typeTuple. We make callers pass the pg_type Relation
529  * as well, so that we have easy access to a tuple descriptor for the row.
530  *
531  * While this is able to extract the defaultExpr and typacl from the tuple,
532  * doing so is relatively expensive, and callers may have those values at
533  * hand already. Pass those if handy, otherwise pass NULL. (typacl is really
534  * "Acl *", but we declare it "void *" to avoid including acl.h in pg_type.h.)
535  *
536  * relationKind and isImplicitArray are likewise somewhat expensive to deduce
537  * from the tuple, so we make callers pass those (they're not optional).
538  *
539  * isDependentType is true if this is an implicit array or relation rowtype;
540  * that means it doesn't need its own dependencies on owner 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 the type belongs to some other extension, an error will occur).
553  */
554 void
556  Relation typeCatalog,
557  Node *defaultExpr,
558  void *typacl,
559  char relationKind, /* only for relation rowtypes */
560  bool isImplicitArray,
561  bool isDependentType,
562  bool makeExtensionDep,
563  bool rebuild)
564 {
565  Form_pg_type typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
566  Oid typeObjectId = typeForm->oid;
567  Datum datum;
568  bool isNull;
569  ObjectAddress myself,
570  referenced;
571  ObjectAddresses *addrs_normal;
572 
573  /* Extract defaultExpr if caller didn't pass it */
574  if (defaultExpr == NULL)
575  {
576  datum = heap_getattr(typeTuple, Anum_pg_type_typdefaultbin,
577  RelationGetDescr(typeCatalog), &isNull);
578  if (!isNull)
579  defaultExpr = stringToNode(TextDatumGetCString(datum));
580  }
581  /* Extract typacl if caller didn't pass it */
582  if (typacl == NULL)
583  {
584  datum = heap_getattr(typeTuple, Anum_pg_type_typacl,
585  RelationGetDescr(typeCatalog), &isNull);
586  if (!isNull)
587  typacl = DatumGetAclPCopy(datum);
588  }
589 
590  /* If rebuild, first flush old dependencies, except extension deps */
591  if (rebuild)
592  {
593  deleteDependencyRecordsFor(TypeRelationId, typeObjectId, true);
594  deleteSharedDependencyRecordsFor(TypeRelationId, typeObjectId, 0);
595  }
596 
597  ObjectAddressSet(myself, TypeRelationId, typeObjectId);
598 
599  /*
600  * Make dependencies on namespace, owner, ACL, extension.
601  *
602  * Skip these for a dependent type, since it will have such dependencies
603  * indirectly through its depended-on type or relation.
604  */
605 
606  /* placeholder for all normal dependencies */
607  addrs_normal = new_object_addresses();
608 
609  if (!isDependentType)
610  {
611  ObjectAddressSet(referenced, NamespaceRelationId,
612  typeForm->typnamespace);
613  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
614 
615  recordDependencyOnOwner(TypeRelationId, typeObjectId,
616  typeForm->typowner);
617 
618  recordDependencyOnNewAcl(TypeRelationId, typeObjectId, 0,
619  typeForm->typowner, typacl);
620 
621  if (makeExtensionDep)
622  recordDependencyOnCurrentExtension(&myself, rebuild);
623  }
624 
625  /* Normal dependencies on the I/O and support functions */
626  if (OidIsValid(typeForm->typinput))
627  {
628  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typinput);
629  add_exact_object_address(&referenced, addrs_normal);
630  }
631 
632  if (OidIsValid(typeForm->typoutput))
633  {
634  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typoutput);
635  add_exact_object_address(&referenced, addrs_normal);
636  }
637 
638  if (OidIsValid(typeForm->typreceive))
639  {
640  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typreceive);
641  add_exact_object_address(&referenced, addrs_normal);
642  }
643 
644  if (OidIsValid(typeForm->typsend))
645  {
646  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typsend);
647  add_exact_object_address(&referenced, addrs_normal);
648  }
649 
650  if (OidIsValid(typeForm->typmodin))
651  {
652  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typmodin);
653  add_exact_object_address(&referenced, addrs_normal);
654  }
655 
656  if (OidIsValid(typeForm->typmodout))
657  {
658  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typmodout);
659  add_exact_object_address(&referenced, addrs_normal);
660  }
661 
662  if (OidIsValid(typeForm->typanalyze))
663  {
664  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typanalyze);
665  add_exact_object_address(&referenced, addrs_normal);
666  }
667 
668  if (OidIsValid(typeForm->typsubscript))
669  {
670  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typsubscript);
671  add_exact_object_address(&referenced, addrs_normal);
672  }
673 
674  /* Normal dependency from a domain to its base type. */
675  if (OidIsValid(typeForm->typbasetype))
676  {
677  ObjectAddressSet(referenced, TypeRelationId, typeForm->typbasetype);
678  add_exact_object_address(&referenced, addrs_normal);
679  }
680 
681  /*
682  * Normal dependency from a domain to its collation. We know the default
683  * collation is pinned, so don't bother recording it.
684  */
685  if (OidIsValid(typeForm->typcollation) &&
686  typeForm->typcollation != DEFAULT_COLLATION_OID)
687  {
688  ObjectAddressSet(referenced, CollationRelationId, typeForm->typcollation);
689  add_exact_object_address(&referenced, addrs_normal);
690  }
691 
693  free_object_addresses(addrs_normal);
694 
695  /* Normal dependency on the default expression. */
696  if (defaultExpr)
697  recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);
698 
699  /*
700  * If the type is a rowtype for a relation, mark it as internally
701  * dependent on the relation, *unless* it is a stand-alone composite type
702  * relation. For the latter case, we have to reverse the dependency.
703  *
704  * In the former case, this allows the type to be auto-dropped when the
705  * relation is, and not otherwise. And in the latter, of course we get the
706  * opposite effect.
707  */
708  if (OidIsValid(typeForm->typrelid))
709  {
710  ObjectAddressSet(referenced, RelationRelationId, typeForm->typrelid);
711 
712  if (relationKind != RELKIND_COMPOSITE_TYPE)
713  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
714  else
715  recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
716  }
717 
718  /*
719  * If the type is an implicitly-created array type, mark it as internally
720  * dependent on the element type. Otherwise, if it has an element type,
721  * the dependency is a normal one.
722  */
723  if (OidIsValid(typeForm->typelem))
724  {
725  ObjectAddressSet(referenced, TypeRelationId, typeForm->typelem);
726  recordDependencyOn(&myself, &referenced,
727  isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL);
728  }
729 }
730 
731 /*
732  * RenameTypeInternal
733  * This renames a type, as well as any associated array type.
734  *
735  * Caller must have already checked privileges.
736  *
737  * Currently this is used for renaming table rowtypes and for
738  * ALTER TYPE RENAME TO command.
739  */
740 void
741 RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
742 {
743  Relation pg_type_desc;
744  HeapTuple tuple;
745  Form_pg_type typ;
746  Oid arrayOid;
747  Oid oldTypeOid;
748 
749  pg_type_desc = table_open(TypeRelationId, RowExclusiveLock);
750 
751  tuple = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
752  if (!HeapTupleIsValid(tuple))
753  elog(ERROR, "cache lookup failed for type %u", typeOid);
754  typ = (Form_pg_type) GETSTRUCT(tuple);
755 
756  /* We are not supposed to be changing schemas here */
757  Assert(typeNamespace == typ->typnamespace);
758 
759  arrayOid = typ->typarray;
760 
761  /* Check for a conflicting type name. */
762  oldTypeOid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
763  CStringGetDatum(newTypeName),
764  ObjectIdGetDatum(typeNamespace));
765 
766  /*
767  * If there is one, see if it's an autogenerated array type, and if so
768  * rename it out of the way. (But we must skip that for a shell type
769  * because moveArrayTypeName will do the wrong thing in that case.)
770  * Otherwise, we can at least give a more friendly error than unique-index
771  * violation.
772  */
773  if (OidIsValid(oldTypeOid))
774  {
775  if (get_typisdefined(oldTypeOid) &&
776  moveArrayTypeName(oldTypeOid, newTypeName, typeNamespace))
777  /* successfully dodged the problem */ ;
778  else
779  ereport(ERROR,
781  errmsg("type \"%s\" already exists", newTypeName)));
782  }
783 
784  /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
785  namestrcpy(&(typ->typname), newTypeName);
786 
787  CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple);
788 
789  InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
790 
791  heap_freetuple(tuple);
792  table_close(pg_type_desc, RowExclusiveLock);
793 
794  /*
795  * If the type has an array type, recurse to handle that. But we don't
796  * need to do anything more if we already renamed that array type above
797  * (which would happen when, eg, renaming "foo" to "_foo").
798  */
799  if (OidIsValid(arrayOid) && arrayOid != oldTypeOid)
800  {
801  char *arrname = makeArrayTypeName(newTypeName, typeNamespace);
802 
803  RenameTypeInternal(arrayOid, arrname, typeNamespace);
804  pfree(arrname);
805  }
806 }
807 
808 
809 /*
810  * makeArrayTypeName
811  * - given a base type name, make an array type name for it
812  *
813  * the caller is responsible for pfreeing the result
814  */
815 char *
816 makeArrayTypeName(const char *typeName, Oid typeNamespace)
817 {
818  char *arr;
819 
820  arr = makeUniqueTypeName(typeName, typeNamespace, false);
821  if (arr == NULL)
822  ereport(ERROR,
824  errmsg("could not form array type name for type \"%s\"",
825  typeName)));
826 
827  return arr;
828 }
829 
830 
831 /*
832  * moveArrayTypeName
833  * - try to reassign an array type name that the user wants to use.
834  *
835  * The given type name has been discovered to already exist (with the given
836  * OID). If it is an autogenerated array type, change the array type's name
837  * to not conflict. This allows the user to create type "foo" followed by
838  * type "_foo" without problems. (Of course, there are race conditions if
839  * two backends try to create similarly-named types concurrently, but the
840  * worst that can happen is an unnecessary failure --- anything we do here
841  * will be rolled back if the type creation fails due to conflicting names.)
842  *
843  * Note that this must be called *before* calling makeArrayTypeName to
844  * determine the new type's own array type name; else the latter will
845  * certainly pick the same name.
846  *
847  * Returns true if successfully moved the type, false if not.
848  *
849  * We also return true if the given type is a shell type. In this case
850  * the type has not been renamed out of the way, but nonetheless it can
851  * be expected that TypeCreate will succeed. This behavior is convenient
852  * for most callers --- those that need to distinguish the shell-type case
853  * must do their own typisdefined test.
854  */
855 bool
856 moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
857 {
858  Oid elemOid;
859  char *newname;
860 
861  /* We need do nothing if it's a shell type. */
862  if (!get_typisdefined(typeOid))
863  return true;
864 
865  /* Can't change it if it's not an autogenerated array type. */
866  elemOid = get_element_type(typeOid);
867  if (!OidIsValid(elemOid) ||
868  get_array_type(elemOid) != typeOid)
869  return false;
870 
871  /*
872  * OK, use makeArrayTypeName to pick an unused modification of the name.
873  * Note that since makeArrayTypeName is an iterative process, this will
874  * produce a name that it might have produced the first time, had the
875  * conflicting type we are about to create already existed.
876  */
877  newname = makeArrayTypeName(typeName, typeNamespace);
878 
879  /* Apply the rename */
880  RenameTypeInternal(typeOid, newname, typeNamespace);
881 
882  /*
883  * We must bump the command counter so that any subsequent use of
884  * makeArrayTypeName sees what we just did and doesn't pick the same name.
885  */
887 
888  pfree(newname);
889 
890  return true;
891 }
892 
893 
894 /*
895  * makeMultirangeTypeName
896  * - given a range type name, make a multirange type name for it
897  *
898  * caller is responsible for pfreeing the result
899  */
900 char *
901 makeMultirangeTypeName(const char *rangeTypeName, Oid typeNamespace)
902 {
903  char *buf;
904  char *rangestr;
905 
906  /*
907  * If the range type name contains "range" then change that to
908  * "multirange". Otherwise add "_multirange" to the end.
909  */
910  rangestr = strstr(rangeTypeName, "range");
911  if (rangestr)
912  {
913  char *prefix = pnstrdup(rangeTypeName, rangestr - rangeTypeName);
914 
915  buf = psprintf("%s%s%s", prefix, "multi", rangestr);
916  }
917  else
918  buf = psprintf("%s_multirange", pnstrdup(rangeTypeName, NAMEDATALEN - 12));
919 
920  /* clip it at NAMEDATALEN-1 bytes */
921  buf[pg_mbcliplen(buf, strlen(buf), NAMEDATALEN - 1)] = '\0';
922 
924  CStringGetDatum(buf),
925  ObjectIdGetDatum(typeNamespace)))
926  ereport(ERROR,
928  errmsg("type \"%s\" already exists", buf),
929  errdetail("Failed while creating a multirange type for type \"%s\".", rangeTypeName),
930  errhint("You can manually specify a multirange type name using the \"multirange_type_name\" attribute.")));
931 
932  return pstrdup(buf);
933 }
934 
935 /*
936  * makeUniqueTypeName
937  * Generate a unique name for a prospective new type
938  *
939  * Given a typeName, return a new palloc'ed name by prepending underscores
940  * until a non-conflicting name results.
941  *
942  * If tryOriginal, first try with zero underscores.
943  */
944 static char *
945 makeUniqueTypeName(const char *typeName, Oid typeNamespace, bool tryOriginal)
946 {
947  int i;
948  int namelen;
949  char dest[NAMEDATALEN];
950 
951  Assert(strlen(typeName) <= NAMEDATALEN - 1);
952 
953  if (tryOriginal &&
955  CStringGetDatum(typeName),
956  ObjectIdGetDatum(typeNamespace)))
957  return pstrdup(typeName);
958 
959  /*
960  * The idea is to prepend underscores as needed until we make a name that
961  * doesn't collide with anything ...
962  */
963  namelen = strlen(typeName);
964  for (i = 1; i < NAMEDATALEN - 1; i++)
965  {
966  dest[i - 1] = '_';
967  strlcpy(dest + i, typeName, NAMEDATALEN - i);
968  if (namelen + i >= NAMEDATALEN)
969  truncate_identifier(dest, NAMEDATALEN, false);
970 
972  CStringGetDatum(dest),
973  ObjectIdGetDatum(typeNamespace)))
974  return pstrdup(dest);
975  }
976 
977  return NULL;
978 }
signed short int16
Definition: c.h:428
#define NIL
Definition: pg_list.h:65
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:381
#define NameGetDatum(X)
Definition: postgres.h:639
char * makeArrayTypeName(const char *typeName, Oid typeNamespace)
Definition: pg_type.c:816
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
int errhint(const char *fmt,...)
Definition: elog.c:1156
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1310
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
#define RelationGetDescr(relation)
Definition: rel.h:503
void namestrcpy(Name name, const char *str)
Definition: name.c:233
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2706
#define PointerGetDatum(X)
Definition: postgres.h:600
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2734
char * pstrdup(const char *in)
Definition: mcxt.c:1299
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
Definition: dependency.c:2700
long deleteDependencyRecordsFor(Oid classId, Oid objectId, bool skipExtensionDeps)
Definition: pg_depend.c:243
#define Int16GetDatum(X)
Definition: postgres.h:495
Definition: nodes.h:538
bool get_typisdefined(Oid typid)
Definition: lsyscache.c:2120
int errcode(int sqlerrcode)
Definition: elog.c:698
void * stringToNode(const char *str)
Definition: read.c:89
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2491
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:163
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2436
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2731
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:60
#define OidIsValid(objectId)
Definition: c.h:710
bool IsBinaryUpgrade
Definition: globals.c:113
signed int int32
Definition: c.h:429
#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:3308
void pfree(void *pointer)
Definition: mcxt.c:1169
static char * makeUniqueTypeName(const char *typeName, Oid typeNamespace, bool tryOriginal)
Definition: pg_type.c:945
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:1026
Definition: c.h:675
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition: pg_type.c:856
static char * buf
Definition: pg_test_fsync.c:68
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define CStringGetDatum(X)
Definition: postgres.h:622
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1577
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:1000
Oid binary_upgrade_next_pg_type_oid
Definition: pg_type.c:44
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
void RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
Definition: pg_type.c:741
#define TextDatumGetCString(d)
Definition: builtins.h:87
void GenerateTypeDependencies(HeapTuple typeTuple, Relation typeCatalog, Node *defaultExpr, void *typacl, char relationKind, bool isImplicitArray, bool isDependentType, bool makeExtensionDep, bool rebuild)
Definition: pg_type.c:555
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1022
TupleDesc rd_att
Definition: rel.h:110
#define BoolGetDatum(X)
Definition: postgres.h:446
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
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
#define Assert(condition)
Definition: c.h:804
void recordDependencyOnCurrentExtension(const ObjectAddress *object, bool isReplace)
Definition: pg_depend.c:191
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:197
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
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:901
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition: syscache.h:188
const char * name
Definition: encode.c:561
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define CharGetDatum(X)
Definition: postgres.h:460
void recordDependencyOnNewAcl(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, Acl *acl)
Definition: aclchk.c:5599
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:406
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:177
#define Int32GetDatum(X)
Definition: postgres.h:523
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
int i
#define CStringGetTextDatum(s)
Definition: builtins.h:86
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:179
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
#define PointerIsValid(pointer)
Definition: c.h:698
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
Acl * get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
Definition: aclchk.c:5523
#define DatumGetAclPCopy(X)
Definition: acl.h:121