Age Owner 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-2023, 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
174 tgl 49 GNC 196 : 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;
1060 tgl 56 ECB : Datum values[Natts_pg_cast];
267 peter 57 GNC 196 : bool nulls[Natts_pg_cast] = {0};
58 : ObjectAddress myself,
59 : referenced;
60 : ObjectAddresses *addrs;
61 :
1125 alvherre 62 GIC 196 : relation = table_open(CastRelationId, RowExclusiveLock);
63 :
1125 alvherre 64 ECB : /*
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 : */
1125 alvherre 69 CBC 196 : tuple = SearchSysCache2(CASTSOURCETARGET,
70 : ObjectIdGetDatum(sourcetypeid),
71 : ObjectIdGetDatum(targettypeid));
1125 alvherre 72 GIC 196 : if (HeapTupleIsValid(tuple))
1125 alvherre 73 UIC 0 : ereport(ERROR,
74 : (errcode(ERRCODE_DUPLICATE_OBJECT),
75 : errmsg("cast from type %s to type %s already exists",
1125 alvherre 76 ECB : format_type_be(sourcetypeid),
77 : format_type_be(targettypeid))));
78 :
79 : /* ready to go */
1125 alvherre 80 GBC 196 : castid = GetNewOidWithIndex(relation, CastOidIndexId, Anum_pg_cast_oid);
1125 alvherre 81 GIC 196 : values[Anum_pg_cast_oid - 1] = ObjectIdGetDatum(castid);
82 196 : values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);
83 196 : values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);
84 196 : values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
85 196 : values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext);
86 196 : values[Anum_pg_cast_castmethod - 1] = CharGetDatum(castmethod);
1125 alvherre 87 ECB :
1125 alvherre 88 CBC 196 : tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
1125 alvherre 89 ECB :
1125 alvherre 90 CBC 196 : CatalogTupleInsert(relation, tuple);
1125 alvherre 91 ECB :
946 michael 92 GIC 196 : addrs = new_object_addresses();
946 michael 93 ECB :
94 : /* make dependency entries */
946 michael 95 CBC 196 : ObjectAddressSet(myself, CastRelationId, castid);
96 :
1125 alvherre 97 ECB : /* dependency on source type */
946 michael 98 GIC 196 : ObjectAddressSet(referenced, TypeRelationId, sourcetypeid);
99 196 : add_exact_object_address(&referenced, addrs);
1125 alvherre 100 ECB :
101 : /* dependency on target type */
946 michael 102 GIC 196 : ObjectAddressSet(referenced, TypeRelationId, targettypeid);
946 michael 103 CBC 196 : add_exact_object_address(&referenced, addrs);
1125 alvherre 104 ECB :
105 : /* dependency on function */
1125 alvherre 106 GIC 196 : if (OidIsValid(funcid))
1125 alvherre 107 ECB : {
946 michael 108 CBC 112 : ObjectAddressSet(referenced, ProcedureRelationId, funcid);
946 michael 109 GIC 112 : add_exact_object_address(&referenced, addrs);
110 : }
1125 alvherre 111 ECB :
112 : /* dependencies on casts required for function */
174 tgl 113 GNC 196 : if (OidIsValid(incastid))
114 : {
174 tgl 115 UNC 0 : ObjectAddressSet(referenced, CastRelationId, incastid);
116 0 : add_exact_object_address(&referenced, addrs);
117 : }
174 tgl 118 GNC 196 : if (OidIsValid(outcastid))
119 : {
120 4 : ObjectAddressSet(referenced, CastRelationId, outcastid);
121 4 : add_exact_object_address(&referenced, addrs);
122 : }
123 :
946 michael 124 GIC 196 : record_object_address_dependencies(&myself, addrs, behavior);
946 michael 125 CBC 196 : free_object_addresses(addrs);
946 michael 126 ECB :
127 : /* dependency on extension */
1125 alvherre 128 GIC 196 : recordDependencyOnCurrentExtension(&myself, false);
129 :
1125 alvherre 130 ECB : /* Post creation hook for new cast */
1125 alvherre 131 GIC 196 : InvokeObjectPostCreateHook(CastRelationId, castid, 0);
1125 alvherre 132 EUB :
1125 alvherre 133 GBC 196 : heap_freetuple(tuple);
134 :
1125 alvherre 135 CBC 196 : table_close(relation, RowExclusiveLock);
136 :
137 196 : return myself;
1125 alvherre 138 ECB : }
|