Age Owner Branch data TLA 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
545 tgl@sss.pgh.pa.us 49 :CBC 203 : 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];
638 peter@eisentraut.org 57 : 203 : bool nulls[Natts_pg_cast] = {0};
58 : : ObjectAddress myself,
59 : : referenced;
60 : : ObjectAddresses *addrs;
61 : :
1496 alvherre@alvh.no-ip. 62 : 203 : 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 : 203 : tuple = SearchSysCache2(CASTSOURCETARGET,
70 : : ObjectIdGetDatum(sourcetypeid),
71 : : ObjectIdGetDatum(targettypeid));
72 [ - + ]: 203 : if (HeapTupleIsValid(tuple))
1496 alvherre@alvh.no-ip. 73 [ # # ]:UBC 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 */
1496 alvherre@alvh.no-ip. 80 :CBC 203 : castid = GetNewOidWithIndex(relation, CastOidIndexId, Anum_pg_cast_oid);
81 : 203 : values[Anum_pg_cast_oid - 1] = ObjectIdGetDatum(castid);
82 : 203 : values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);
83 : 203 : values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);
84 : 203 : values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
85 : 203 : values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext);
86 : 203 : values[Anum_pg_cast_castmethod - 1] = CharGetDatum(castmethod);
87 : :
88 : 203 : tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
89 : :
90 : 203 : CatalogTupleInsert(relation, tuple);
91 : :
1317 michael@paquier.xyz 92 : 203 : addrs = new_object_addresses();
93 : :
94 : : /* make dependency entries */
95 : 203 : ObjectAddressSet(myself, CastRelationId, castid);
96 : :
97 : : /* dependency on source type */
98 : 203 : ObjectAddressSet(referenced, TypeRelationId, sourcetypeid);
99 : 203 : add_exact_object_address(&referenced, addrs);
100 : :
101 : : /* dependency on target type */
102 : 203 : ObjectAddressSet(referenced, TypeRelationId, targettypeid);
103 : 203 : add_exact_object_address(&referenced, addrs);
104 : :
105 : : /* dependency on function */
1496 alvherre@alvh.no-ip. 106 [ + + ]: 203 : if (OidIsValid(funcid))
107 : : {
1317 michael@paquier.xyz 108 : 119 : ObjectAddressSet(referenced, ProcedureRelationId, funcid);
109 : 119 : add_exact_object_address(&referenced, addrs);
110 : : }
111 : :
112 : : /* dependencies on casts required for function */
545 tgl@sss.pgh.pa.us 113 [ - + ]: 203 : if (OidIsValid(incastid))
114 : : {
545 tgl@sss.pgh.pa.us 115 :UBC 0 : ObjectAddressSet(referenced, CastRelationId, incastid);
116 : 0 : add_exact_object_address(&referenced, addrs);
117 : : }
545 tgl@sss.pgh.pa.us 118 [ + + ]:CBC 203 : if (OidIsValid(outcastid))
119 : : {
120 : 4 : ObjectAddressSet(referenced, CastRelationId, outcastid);
121 : 4 : add_exact_object_address(&referenced, addrs);
122 : : }
123 : :
1317 michael@paquier.xyz 124 : 203 : record_object_address_dependencies(&myself, addrs, behavior);
125 : 203 : free_object_addresses(addrs);
126 : :
127 : : /* dependency on extension */
1496 alvherre@alvh.no-ip. 128 : 203 : recordDependencyOnCurrentExtension(&myself, false);
129 : :
130 : : /* Post creation hook for new cast */
131 [ - + ]: 203 : InvokeObjectPostCreateHook(CastRelationId, castid, 0);
132 : :
133 : 203 : heap_freetuple(tuple);
134 : :
135 : 203 : table_close(relation, RowExclusiveLock);
136 : :
137 : 203 : return myself;
138 : : }
|