1 /*-------------------------------------------------------------------------
4 * routines to support manipulation of the pg_cast relation
6 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/catalog/pg_cast.c
13 *-------------------------------------------------------------------------
17 #include "access/htup_details.h"
18 #include "access/table.h"
19 #include "catalog/catalog.h"
20 #include "catalog/dependency.h"
21 #include "catalog/indexing.h"
22 #include "catalog/objectaccess.h"
23 #include "catalog/pg_cast.h"
24 #include "catalog/pg_proc.h"
25 #include "catalog/pg_type.h"
26 #include "utils/builtins.h"
27 #include "utils/rel.h"
28 #include "utils/syscache.h"
31 * ----------------------------------------------------------------
34 * Forms and inserts catalog tuples for a new cast being created.
35 * Caller must have already checked privileges, and done consistency
36 * checks on the given datatypes and cast function (if applicable).
38 * Since we allow binary coercibility of the datatypes to the cast
39 * function's input and result, there could be one or two WITHOUT FUNCTION
40 * casts that this one depends on. We don't record that explicitly
41 * in pg_cast, but we still need to make dependencies on those casts.
43 * 'behavior' indicates the types of the dependencies that the new
44 * cast will have on its input and output types, the cast function,
45 * and the other casts if any.
46 * ----------------------------------------------------------------
49 CastCreate(Oid sourcetypeid
, Oid targettypeid
,
50 Oid funcid
, Oid incastid
, Oid outcastid
,
51 char castcontext
, char castmethod
, DependencyType behavior
)
56 Datum values
[Natts_pg_cast
];
57 bool nulls
[Natts_pg_cast
] = {0};
60 ObjectAddresses
*addrs
;
62 relation
= table_open(CastRelationId
, RowExclusiveLock
);
65 * Check for duplicate. This is just to give a friendly error message,
66 * the unique index would catch it anyway (so no need to sweat about race
69 tuple
= SearchSysCache2(CASTSOURCETARGET
,
70 ObjectIdGetDatum(sourcetypeid
),
71 ObjectIdGetDatum(targettypeid
));
72 if (HeapTupleIsValid(tuple
))
74 (errcode(ERRCODE_DUPLICATE_OBJECT
),
75 errmsg("cast from type %s to type %s already exists",
76 format_type_be(sourcetypeid
),
77 format_type_be(targettypeid
))));
80 castid
= GetNewOidWithIndex(relation
, CastOidIndexId
, Anum_pg_cast_oid
);
81 values
[Anum_pg_cast_oid
- 1] = ObjectIdGetDatum(castid
);
82 values
[Anum_pg_cast_castsource
- 1] = ObjectIdGetDatum(sourcetypeid
);
83 values
[Anum_pg_cast_casttarget
- 1] = ObjectIdGetDatum(targettypeid
);
84 values
[Anum_pg_cast_castfunc
- 1] = ObjectIdGetDatum(funcid
);
85 values
[Anum_pg_cast_castcontext
- 1] = CharGetDatum(castcontext
);
86 values
[Anum_pg_cast_castmethod
- 1] = CharGetDatum(castmethod
);
88 tuple
= heap_form_tuple(RelationGetDescr(relation
), values
, nulls
);
90 CatalogTupleInsert(relation
, tuple
);
92 addrs
= new_object_addresses();
94 /* make dependency entries */
95 ObjectAddressSet(myself
, CastRelationId
, castid
);
97 /* dependency on source type */
98 ObjectAddressSet(referenced
, TypeRelationId
, sourcetypeid
);
99 add_exact_object_address(&referenced
, addrs
);
101 /* dependency on target type */
102 ObjectAddressSet(referenced
, TypeRelationId
, targettypeid
);
103 add_exact_object_address(&referenced
, addrs
);
105 /* dependency on function */
106 if (OidIsValid(funcid
))
108 ObjectAddressSet(referenced
, ProcedureRelationId
, funcid
);
109 add_exact_object_address(&referenced
, addrs
);
112 /* dependencies on casts required for function */
113 if (OidIsValid(incastid
))
115 ObjectAddressSet(referenced
, CastRelationId
, incastid
);
116 add_exact_object_address(&referenced
, addrs
);
118 if (OidIsValid(outcastid
))
120 ObjectAddressSet(referenced
, CastRelationId
, outcastid
);
121 add_exact_object_address(&referenced
, addrs
);
124 record_object_address_dependencies(&myself
, addrs
, behavior
);
125 free_object_addresses(addrs
);
127 /* dependency on extension */
128 recordDependencyOnCurrentExtension(&myself
, false);
130 /* Post creation hook for new cast */
131 InvokeObjectPostCreateHook(CastRelationId
, castid
, 0);
133 heap_freetuple(tuple
);
135 table_close(relation
, RowExclusiveLock
);