Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * pg_cast.c
4 : * routines to support manipulation of the pg_cast 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_cast.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
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"
29 :
30 : /*
31 : * ----------------------------------------------------------------
32 : * CastCreate
33 : *
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).
37 : *
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.
42 : *
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 : * ----------------------------------------------------------------
47 : */
48 : ObjectAddress
49 408 : CastCreate(Oid sourcetypeid, Oid targettypeid,
50 : Oid funcid, Oid incastid, Oid outcastid,
51 : char castcontext, char castmethod, DependencyType behavior)
52 : {
53 : Relation relation;
54 : HeapTuple tuple;
55 : Oid castid;
56 : Datum values[Natts_pg_cast];
57 408 : bool nulls[Natts_pg_cast] = {0};
58 : ObjectAddress myself,
59 : referenced;
60 : ObjectAddresses *addrs;
61 :
62 408 : relation = table_open(CastRelationId, RowExclusiveLock);
63 :
64 : /*
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
67 : * conditions).
68 : */
69 408 : tuple = SearchSysCache2(CASTSOURCETARGET,
70 : ObjectIdGetDatum(sourcetypeid),
71 : ObjectIdGetDatum(targettypeid));
72 408 : if (HeapTupleIsValid(tuple))
73 0 : ereport(ERROR,
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))));
78 :
79 : /* ready to go */
80 408 : castid = GetNewOidWithIndex(relation, CastOidIndexId, Anum_pg_cast_oid);
81 408 : values[Anum_pg_cast_oid - 1] = ObjectIdGetDatum(castid);
82 408 : values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);
83 408 : values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);
84 408 : values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
85 408 : values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext);
86 408 : values[Anum_pg_cast_castmethod - 1] = CharGetDatum(castmethod);
87 :
88 408 : tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
89 :
90 408 : CatalogTupleInsert(relation, tuple);
91 :
92 408 : addrs = new_object_addresses();
93 :
94 : /* make dependency entries */
95 408 : ObjectAddressSet(myself, CastRelationId, castid);
96 :
97 : /* dependency on source type */
98 408 : ObjectAddressSet(referenced, TypeRelationId, sourcetypeid);
99 408 : add_exact_object_address(&referenced, addrs);
100 :
101 : /* dependency on target type */
102 408 : ObjectAddressSet(referenced, TypeRelationId, targettypeid);
103 408 : add_exact_object_address(&referenced, addrs);
104 :
105 : /* dependency on function */
106 408 : if (OidIsValid(funcid))
107 : {
108 240 : ObjectAddressSet(referenced, ProcedureRelationId, funcid);
109 240 : add_exact_object_address(&referenced, addrs);
110 : }
111 :
112 : /* dependencies on casts required for function */
113 408 : if (OidIsValid(incastid))
114 : {
115 0 : ObjectAddressSet(referenced, CastRelationId, incastid);
116 0 : add_exact_object_address(&referenced, addrs);
117 : }
118 408 : if (OidIsValid(outcastid))
119 : {
120 8 : ObjectAddressSet(referenced, CastRelationId, outcastid);
121 8 : add_exact_object_address(&referenced, addrs);
122 : }
123 :
124 408 : record_object_address_dependencies(&myself, addrs, behavior);
125 408 : free_object_addresses(addrs);
126 :
127 : /* dependency on extension */
128 408 : recordDependencyOnCurrentExtension(&myself, false);
129 :
130 : /* Post creation hook for new cast */
131 408 : InvokeObjectPostCreateHook(CastRelationId, castid, 0);
132 :
133 408 : heap_freetuple(tuple);
134 :
135 408 : table_close(relation, RowExclusiveLock);
136 :
137 408 : return myself;
138 : }
|