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-2022, 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  * if it's a relation rowtype that's not a composite type. For such types
331  * we'll leave the ACL empty, and we'll skip creating some dependency
332  * records because there will be a dependency already through the
333  * depended-on type or relation. (Caution: this is closely intertwined
334  * with some behavior in GenerateTypeDependencies.)
335  */
336  isDependentType = isImplicitArray ||
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 
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 or relation rowtype;
538  * that means it doesn't need its own dependencies on owner etc.
539  *
540  * We make an extension-membership dependency if we're in an extension
541  * script and makeExtensionDep is true (and isDependentType isn't true).
542  * makeExtensionDep should be true when creating a new type or replacing a
543  * shell type, but not for ALTER TYPE on an existing type. Passing false
544  * causes the type's extension membership to be left alone.
545  *
546  * rebuild should be true if this is a pre-existing type. We will remove
547  * existing dependencies and rebuild them from scratch. This is needed for
548  * ALTER TYPE, and also when replacing a shell type. We don't remove any
549  * existing extension dependency, though; hence, if makeExtensionDep is also
550  * true and we're in an extension script, an error will occur unless the
551  * type already belongs to the current extension. That's the behavior we
552  * want when replacing a shell type, which is the only case where both flags
553  * are true.
554  */
555 void
557  Relation typeCatalog,
558  Node *defaultExpr,
559  void *typacl,
560  char relationKind, /* only for relation rowtypes */
561  bool isImplicitArray,
562  bool isDependentType,
563  bool makeExtensionDep,
564  bool rebuild)
565 {
566  Form_pg_type typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
567  Oid typeObjectId = typeForm->oid;
568  Datum datum;
569  bool isNull;
570  ObjectAddress myself,
571  referenced;
572  ObjectAddresses *addrs_normal;
573 
574  /* Extract defaultExpr if caller didn't pass it */
575  if (defaultExpr == NULL)
576  {
577  datum = heap_getattr(typeTuple, Anum_pg_type_typdefaultbin,
578  RelationGetDescr(typeCatalog), &isNull);
579  if (!isNull)
580  defaultExpr = stringToNode(TextDatumGetCString(datum));
581  }
582  /* Extract typacl if caller didn't pass it */
583  if (typacl == NULL)
584  {
585  datum = heap_getattr(typeTuple, Anum_pg_type_typacl,
586  RelationGetDescr(typeCatalog), &isNull);
587  if (!isNull)
588  typacl = DatumGetAclPCopy(datum);
589  }
590 
591  /* If rebuild, first flush old dependencies, except extension deps */
592  if (rebuild)
593  {
594  deleteDependencyRecordsFor(TypeRelationId, typeObjectId, true);
595  deleteSharedDependencyRecordsFor(TypeRelationId, typeObjectId, 0);
596  }
597 
598  ObjectAddressSet(myself, TypeRelationId, typeObjectId);
599 
600  /*
601  * Make dependencies on namespace, owner, ACL, extension.
602  *
603  * Skip these for a dependent type, since it will have such dependencies
604  * indirectly through its depended-on type or relation.
605  */
606 
607  /* placeholder for all normal dependencies */
608  addrs_normal = new_object_addresses();
609 
610  if (!isDependentType)
611  {
612  ObjectAddressSet(referenced, NamespaceRelationId,
613  typeForm->typnamespace);
614  recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
615 
616  recordDependencyOnOwner(TypeRelationId, typeObjectId,
617  typeForm->typowner);
618 
619  recordDependencyOnNewAcl(TypeRelationId, typeObjectId, 0,
620  typeForm->typowner, typacl);
621 
622  if (makeExtensionDep)
623  recordDependencyOnCurrentExtension(&myself, rebuild);
624  }
625 
626  /* Normal dependencies on the I/O and support functions */
627  if (OidIsValid(typeForm->typinput))
628  {
629  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typinput);
630  add_exact_object_address(&referenced, addrs_normal);
631  }
632 
633  if (OidIsValid(typeForm->typoutput))
634  {
635  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typoutput);
636  add_exact_object_address(&referenced, addrs_normal);
637  }
638 
639  if (OidIsValid(typeForm->typreceive))
640  {
641  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typreceive);
642  add_exact_object_address(&referenced, addrs_normal);
643  }
644 
645  if (OidIsValid(typeForm->typsend))
646  {
647  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typsend);
648  add_exact_object_address(&referenced, addrs_normal);
649  }
650 
651  if (OidIsValid(typeForm->typmodin))
652  {
653  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typmodin);
654  add_exact_object_address(&referenced, addrs_normal);
655  }
656 
657  if (OidIsValid(typeForm->typmodout))
658  {
659  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typmodout);
660  add_exact_object_address(&referenced, addrs_normal);
661  }
662 
663  if (OidIsValid(typeForm->typanalyze))
664  {
665  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typanalyze);
666  add_exact_object_address(&referenced, addrs_normal);
667  }
668 
669  if (OidIsValid(typeForm->typsubscript))
670  {
671  ObjectAddressSet(referenced, ProcedureRelationId, typeForm->typsubscript);
672  add_exact_object_address(&referenced, addrs_normal);
673  }
674 
675  /* Normal dependency from a domain to its base type. */
676  if (OidIsValid(typeForm->typbasetype))
677  {
678  ObjectAddressSet(referenced, TypeRelationId, typeForm->typbasetype);
679  add_exact_object_address(&referenced, addrs_normal);
680  }
681 
682  /*
683  * Normal dependency from a domain to its collation. We know the default
684  * collation is pinned, so don't bother recording it.
685  */
686  if (OidIsValid(typeForm->typcollation) &&
687  typeForm->typcollation != DEFAULT_COLLATION_OID)
688  {
689  ObjectAddressSet(referenced, CollationRelationId, typeForm->typcollation);
690  add_exact_object_address(&referenced, addrs_normal);
691  }
692 
694  free_object_addresses(addrs_normal);
695 
696  /* Normal dependency on the default expression. */
697  if (defaultExpr)
698  recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);
699 
700  /*
701  * If the type is a rowtype for a relation, mark it as internally
702  * dependent on the relation, *unless* it is a stand-alone composite type
703  * relation. For the latter case, we have to reverse the dependency.
704  *
705  * In the former case, this allows the type to be auto-dropped when the
706  * relation is, and not otherwise. And in the latter, of course we get the
707  * opposite effect.
708  */
709  if (OidIsValid(typeForm->typrelid))
710  {
711  ObjectAddressSet(referenced, RelationRelationId, typeForm->typrelid);
712 
713  if (relationKind != RELKIND_COMPOSITE_TYPE)
714  recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
715  else
716  recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
717  }
718 
719  /*
720  * If the type is an implicitly-created array type, mark it as internally
721  * dependent on the element type. Otherwise, if it has an element type,
722  * the dependency is a normal one.
723  */
724  if (OidIsValid(typeForm->typelem))
725  {
726  ObjectAddressSet(referenced, TypeRelationId, typeForm->typelem);
727  recordDependencyOn(&myself, &referenced,
728  isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL);
729  }
730 }
731 
732 /*
733  * RenameTypeInternal
734  * This renames a type, as well as any associated array type.
735  *
736  * Caller must have already checked privileges.
737  *
738  * Currently this is used for renaming table rowtypes and for
739  * ALTER TYPE RENAME TO command.
740  */
741 void
742 RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
743 {
744  Relation pg_type_desc;
745  HeapTuple tuple;
746  Form_pg_type typ;
747  Oid arrayOid;
748  Oid oldTypeOid;
749 
750  pg_type_desc = table_open(TypeRelationId, RowExclusiveLock);
751 
752  tuple = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
753  if (!HeapTupleIsValid(tuple))
754  elog(ERROR, "cache lookup failed for type %u", typeOid);
755  typ = (Form_pg_type) GETSTRUCT(tuple);
756 
757  /* We are not supposed to be changing schemas here */
758  Assert(typeNamespace == typ->typnamespace);
759 
760  arrayOid = typ->typarray;
761 
762  /* Check for a conflicting type name. */
763  oldTypeOid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
764  CStringGetDatum(newTypeName),
765  ObjectIdGetDatum(typeNamespace));
766 
767  /*
768  * If there is one, see if it's an autogenerated array type, and if so
769  * rename it out of the way. (But we must skip that for a shell type
770  * because moveArrayTypeName will do the wrong thing in that case.)
771  * Otherwise, we can at least give a more friendly error than unique-index
772  * violation.
773  */
774  if (OidIsValid(oldTypeOid))
775  {
776  if (get_typisdefined(oldTypeOid) &&
777  moveArrayTypeName(oldTypeOid, newTypeName, typeNamespace))
778  /* successfully dodged the problem */ ;
779  else
780  ereport(ERROR,
782  errmsg("type \"%s\" already exists", newTypeName)));
783  }
784 
785  /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
786  namestrcpy(&(typ->typname), newTypeName);
787 
788  CatalogTupleUpdate(pg_type_desc, &tuple->t_self, tuple);
789 
790  InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
791 
792  heap_freetuple(tuple);
793  table_close(pg_type_desc, RowExclusiveLock);
794 
795  /*
796  * If the type has an array type, recurse to handle that. But we don't
797  * need to do anything more if we already renamed that array type above
798  * (which would happen when, eg, renaming "foo" to "_foo").
799  */
800  if (OidIsValid(arrayOid) && arrayOid != oldTypeOid)
801  {
802  char *arrname = makeArrayTypeName(newTypeName, typeNamespace);
803 
804  RenameTypeInternal(arrayOid, arrname, typeNamespace);
805  pfree(arrname);
806  }
807 }
808 
809 
810 /*
811  * makeArrayTypeName
812  * - given a base type name, make an array type name for it
813  *
814  * the caller is responsible for pfreeing the result
815  */
816 char *
817 makeArrayTypeName(const char *typeName, Oid typeNamespace)
818 {
819  char *arr_name;
820  int pass = 0;
821  char suffix[NAMEDATALEN];
822 
823  /*
824  * Per ancient Postgres tradition, array type names are made by prepending
825  * an underscore to the base type name. Much client code knows that
826  * convention, so don't muck with it. However, the tradition is less
827  * clear about what to do in the corner cases where the resulting name is
828  * too long or conflicts with an existing name. Our current rules are (1)
829  * truncate the base name on the right as needed, and (2) if there is a
830  * conflict, append another underscore and some digits chosen to make it
831  * unique. This is similar to what ChooseRelationName() does.
832  *
833  * The actual name generation can be farmed out to makeObjectName() by
834  * giving it an empty first name component.
835  */
836 
837  /* First, try with no numeric suffix */
838  arr_name = makeObjectName("", typeName, NULL);
839 
840  for (;;)
841  {
843  CStringGetDatum(arr_name),
844  ObjectIdGetDatum(typeNamespace)))
845  break;
846 
847  /* That attempt conflicted. Prepare a new name with some digits. */
848  pfree(arr_name);
849  snprintf(suffix, sizeof(suffix), "%d", ++pass);
850  arr_name = makeObjectName("", typeName, suffix);
851  }
852 
853  return arr_name;
854 }
855 
856 
857 /*
858  * moveArrayTypeName
859  * - try to reassign an array type name that the user wants to use.
860  *
861  * The given type name has been discovered to already exist (with the given
862  * OID). If it is an autogenerated array type, change the array type's name
863  * to not conflict. This allows the user to create type "foo" followed by
864  * type "_foo" without problems. (Of course, there are race conditions if
865  * two backends try to create similarly-named types concurrently, but the
866  * worst that can happen is an unnecessary failure --- anything we do here
867  * will be rolled back if the type creation fails due to conflicting names.)
868  *
869  * Note that this must be called *before* calling makeArrayTypeName to
870  * determine the new type's own array type name; else the latter will
871  * certainly pick the same name.
872  *
873  * Returns true if successfully moved the type, false if not.
874  *
875  * We also return true if the given type is a shell type. In this case
876  * the type has not been renamed out of the way, but nonetheless it can
877  * be expected that TypeCreate will succeed. This behavior is convenient
878  * for most callers --- those that need to distinguish the shell-type case
879  * must do their own typisdefined test.
880  */
881 bool
882 moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
883 {
884  Oid elemOid;
885  char *newname;
886 
887  /* We need do nothing if it's a shell type. */
888  if (!get_typisdefined(typeOid))
889  return true;
890 
891  /* Can't change it if it's not an autogenerated array type. */
892  elemOid = get_element_type(typeOid);
893  if (!OidIsValid(elemOid) ||
894  get_array_type(elemOid) != typeOid)
895  return false;
896 
897  /*
898  * OK, use makeArrayTypeName to pick an unused modification of the name.
899  * Note that since makeArrayTypeName is an iterative process, this will
900  * produce a name that it might have produced the first time, had the
901  * conflicting type we are about to create already existed.
902  */
903  newname = makeArrayTypeName(typeName, typeNamespace);
904 
905  /* Apply the rename */
906  RenameTypeInternal(typeOid, newname, typeNamespace);
907 
908  /*
909  * We must bump the command counter so that any subsequent use of
910  * makeArrayTypeName sees what we just did and doesn't pick the same name.
911  */
913 
914  pfree(newname);
915 
916  return true;
917 }
918 
919 
920 /*
921  * makeMultirangeTypeName
922  * - given a range type name, make a multirange type name for it
923  *
924  * caller is responsible for pfreeing the result
925  */
926 char *
927 makeMultirangeTypeName(const char *rangeTypeName, Oid typeNamespace)
928 {
929  char *buf;
930  char *rangestr;
931 
932  /*
933  * If the range type name contains "range" then change that to
934  * "multirange". Otherwise add "_multirange" to the end.
935  */
936  rangestr = strstr(rangeTypeName, "range");
937  if (rangestr)
938  {
939  char *prefix = pnstrdup(rangeTypeName, rangestr - rangeTypeName);
940 
941  buf = psprintf("%s%s%s", prefix, "multi", rangestr);
942  }
943  else
944  buf = psprintf("%s_multirange", pnstrdup(rangeTypeName, NAMEDATALEN - 12));
945 
946  /* clip it at NAMEDATALEN-1 bytes */
947  buf[pg_mbcliplen(buf, strlen(buf), NAMEDATALEN - 1)] = '\0';
948 
951  ObjectIdGetDatum(typeNamespace)))
952  ereport(ERROR,
954  errmsg("type \"%s\" already exists", buf),
955  errdetail("Failed while creating a multirange type for type \"%s\".", rangeTypeName),
956  errhint("You can manually specify a multirange type name using the \"multirange_type_name\" attribute.")));
957 
958  return pstrdup(buf);
959 }
@ 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:5006
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3477
Acl * get_user_default_acl(ObjectType objtype, Oid ownerId, Oid nsp_oid)
Definition: aclchk.c:4930
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define CStringGetTextDatum(s)
Definition: builtins.h:85
#define TextDatumGetCString(d)
Definition: builtins.h:86
signed short int16
Definition: c.h:429
signed int int32
Definition: c.h:430
#define PointerIsValid(pointer)
Definition: c.h:699
#define OidIsValid(objectId)
Definition: c.h:711
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:2790
void recordDependencyOnExpr(const ObjectAddress *depender, Node *expr, List *rtable, DependencyType behavior)
Definition: dependency.c:1596
ObjectAddresses * new_object_addresses(void)
Definition: dependency.c:2526
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
Definition: dependency.c:2581
void free_object_addresses(ObjectAddresses *addrs)
Definition: dependency.c:2821
@ DEPENDENCY_INTERNAL
Definition: dependency.h:35
@ DEPENDENCY_NORMAL
Definition: dependency.h:33
int errdetail(const char *fmt,...)
Definition: elog.c:1039
int errhint(const char *fmt,...)
Definition: elog.c:1153
int errcode(int sqlerrcode)
Definition: elog.c:695
int errmsg(const char *fmt,...)
Definition: elog.c:906
#define ERROR
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:145
const char * name
Definition: encode.c:561
bool IsBinaryUpgrade
Definition: globals.c:114
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:788
#define GETSTRUCT(TUP)
Definition: htup_details.h:649
char * makeObjectName(const char *name1, const char *name2, const char *label)
Definition: indexcmds.c:2330
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
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:2717
bool get_typisdefined(Oid typid)
Definition: lsyscache.c:2131
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2745
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:1026
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1494
char * pstrdup(const char *in)
Definition: mcxt.c:1483
void pfree(void *pointer)
Definition: mcxt.c:1306
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:402
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:1909
#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:66
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:67
char * makeMultirangeTypeName(const char *rangeTypeName, Oid typeNamespace)
Definition: pg_type.c:927
void GenerateTypeDependencies(HeapTuple typeTuple, Relation typeCatalog, Node *defaultExpr, void *typacl, char relationKind, bool isImplicitArray, bool isDependentType, bool makeExtensionDep, bool rebuild)
Definition: pg_type.c:556
void RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
Definition: pg_type.c:742
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:817
bool moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
Definition: pg_type.c:882
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:670
uintptr_t Datum
Definition: postgres.h:412
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:520
static Datum BoolGetDatum(bool X)
Definition: postgres.h:450
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:600
static Datum NameGetDatum(const NameData *X)
Definition: postgres.h:721
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:698
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:560
static Datum CharGetDatum(char X)
Definition: postgres.h:470
#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:527
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
ItemPointerData t_self
Definition: htup.h:65
Definition: nodes.h:112
TupleDesc rd_att
Definition: rel.h:111
Definition: c.h:677
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:179
#define SearchSysCacheCopy2(cacheId, key1, key2)
Definition: syscache.h:181
@ TYPEOID
Definition: syscache.h:114
@ TYPENAMENSP
Definition: syscache.h:113
#define SearchSysCacheExists2(cacheId, key1, key2)
Definition: syscache.h:190
#define GetSysCacheOid2(cacheId, oidcol, key1, key2)
Definition: syscache.h:199
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
void CommandCounterIncrement(void)
Definition: xact.c:1077