Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * pg_conversion.c
4 : : * routines to support manipulation of the pg_conversion relation
5 : : *
6 : : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 : : * Portions Copyright (c) 1994, Regents of the University of California
8 : : *
9 : : *
10 : : * IDENTIFICATION
11 : : * src/backend/catalog/pg_conversion.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_conversion.h"
24 : : #include "catalog/pg_namespace.h"
25 : : #include "catalog/pg_proc.h"
26 : : #include "mb/pg_wchar.h"
27 : : #include "utils/builtins.h"
28 : : #include "utils/catcache.h"
29 : : #include "utils/rel.h"
30 : : #include "utils/syscache.h"
31 : :
32 : : /*
33 : : * ConversionCreate
34 : : *
35 : : * Add a new tuple to pg_conversion.
36 : : */
37 : : ObjectAddress
8403 bruce@momjian.us 38 :CBC 32 : ConversionCreate(const char *conname, Oid connamespace,
39 : : Oid conowner,
40 : : int32 conforencoding, int32 contoencoding,
41 : : Oid conproc, bool def)
42 : : {
43 : : int i;
44 : : Relation rel;
45 : : TupleDesc tupDesc;
46 : : HeapTuple tup;
47 : : Oid oid;
48 : : bool nulls[Natts_pg_conversion];
49 : : Datum values[Natts_pg_conversion];
50 : : NameData cname;
51 : : ObjectAddress myself,
52 : : referenced;
53 : :
54 : : /* sanity checks */
8458 ishii@postgresql.org 55 [ - + ]: 32 : if (!conname)
8458 ishii@postgresql.org 56 [ # # ]:UBC 0 : elog(ERROR, "no conversion name supplied");
57 : :
58 : : /* make sure there is no existing conversion of same name */
5683 rhaas@postgresql.org 59 [ + + ]:CBC 32 : if (SearchSysCacheExists2(CONNAMENSP,
60 : : PointerGetDatum(conname),
61 : : ObjectIdGetDatum(connamespace)))
8083 tgl@sss.pgh.pa.us 62 [ + - ]: 3 : ereport(ERROR,
63 : : (errcode(ERRCODE_DUPLICATE_OBJECT),
64 : : errmsg("conversion \"%s\" already exists", conname)));
65 : :
8458 ishii@postgresql.org 66 [ + + ]: 29 : if (def)
67 : : {
68 : : /*
69 : : * make sure there is no existing default <for encoding><to encoding>
70 : : * pair in this name space
71 : : */
72 [ + + ]: 7 : if (FindDefaultConversion(connamespace,
73 : : conforencoding,
74 : : contoencoding))
8083 tgl@sss.pgh.pa.us 75 [ + - ]: 3 : ereport(ERROR,
76 : : (errcode(ERRCODE_DUPLICATE_OBJECT),
77 : : errmsg("default conversion for %s to %s already exists",
78 : : pg_encoding_to_char(conforencoding),
79 : : pg_encoding_to_char(contoencoding))));
80 : : }
81 : :
82 : : /* open pg_conversion */
2420 andres@anarazel.de 83 : 26 : rel = table_open(ConversionRelationId, RowExclusiveLock);
8458 ishii@postgresql.org 84 : 26 : tupDesc = rel->rd_att;
85 : :
86 : : /* initialize nulls and values */
87 [ + + ]: 234 : for (i = 0; i < Natts_pg_conversion; i++)
88 : : {
6152 tgl@sss.pgh.pa.us 89 : 208 : nulls[i] = false;
29 tgl@sss.pgh.pa.us 90 :GNC 208 : values[i] = (Datum) 0;
91 : : }
92 : :
93 : : /* form a tuple */
8458 ishii@postgresql.org 94 :CBC 26 : namestrcpy(&cname, conname);
2482 andres@anarazel.de 95 : 26 : oid = GetNewOidWithIndex(rel, ConversionOidIndexId,
96 : : Anum_pg_conversion_oid);
97 : 26 : values[Anum_pg_conversion_oid - 1] = ObjectIdGetDatum(oid);
8458 ishii@postgresql.org 98 : 26 : values[Anum_pg_conversion_conname - 1] = NameGetDatum(&cname);
99 : 26 : values[Anum_pg_conversion_connamespace - 1] = ObjectIdGetDatum(connamespace);
7375 tgl@sss.pgh.pa.us 100 : 26 : values[Anum_pg_conversion_conowner - 1] = ObjectIdGetDatum(conowner);
8458 ishii@postgresql.org 101 : 26 : values[Anum_pg_conversion_conforencoding - 1] = Int32GetDatum(conforencoding);
102 : 26 : values[Anum_pg_conversion_contoencoding - 1] = Int32GetDatum(contoencoding);
103 : 26 : values[Anum_pg_conversion_conproc - 1] = ObjectIdGetDatum(conproc);
8344 tgl@sss.pgh.pa.us 104 : 26 : values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
105 : :
6152 106 : 26 : tup = heap_form_tuple(tupDesc, values, nulls);
107 : :
108 : : /* insert a new tuple */
3140 alvherre@alvh.no-ip. 109 : 26 : CatalogTupleInsert(rel, tup);
110 : :
7450 tgl@sss.pgh.pa.us 111 : 26 : myself.classId = ConversionRelationId;
2482 andres@anarazel.de 112 : 26 : myself.objectId = oid;
8444 ishii@postgresql.org 113 : 26 : myself.objectSubId = 0;
114 : :
115 : : /* create dependency on conversion procedure */
7450 tgl@sss.pgh.pa.us 116 : 26 : referenced.classId = ProcedureRelationId;
8444 ishii@postgresql.org 117 : 26 : referenced.objectId = conproc;
118 : 26 : referenced.objectSubId = 0;
119 : 26 : recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
120 : :
121 : : /* create dependency on namespace */
7039 bruce@momjian.us 122 : 26 : referenced.classId = NamespaceRelationId;
123 : 26 : referenced.objectId = connamespace;
6946 tgl@sss.pgh.pa.us 124 : 26 : referenced.objectSubId = 0;
7039 bruce@momjian.us 125 : 26 : recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
126 : :
127 : : /* create dependency on owner */
2482 andres@anarazel.de 128 : 26 : recordDependencyOnOwner(ConversionRelationId, oid, conowner);
129 : :
130 : : /* dependency on extension */
5159 tgl@sss.pgh.pa.us 131 : 26 : recordDependencyOnCurrentExtension(&myself, false);
132 : :
133 : : /* Post creation hook for new conversion */
2482 andres@anarazel.de 134 [ - + ]: 26 : InvokeObjectPostCreateHook(ConversionRelationId, oid, 0);
135 : :
8444 ishii@postgresql.org 136 : 26 : heap_freetuple(tup);
2420 andres@anarazel.de 137 : 26 : table_close(rel, RowExclusiveLock);
138 : :
3840 alvherre@alvh.no-ip. 139 : 26 : return myself;
140 : : }
141 : :
142 : : /*
143 : : * FindDefaultConversion
144 : : *
145 : : * Find "default" conversion proc by for_encoding and to_encoding in the
146 : : * given namespace.
147 : : *
148 : : * If found, returns the procedure's oid, otherwise InvalidOid. Note that
149 : : * you get the procedure's OID not the conversion's OID!
150 : : */
151 : : Oid
8344 tgl@sss.pgh.pa.us 152 : 3389 : FindDefaultConversion(Oid name_space, int32 for_encoding, int32 to_encoding)
153 : : {
154 : : CatCList *catlist;
155 : : HeapTuple tuple;
156 : : Form_pg_conversion body;
8403 bruce@momjian.us 157 : 3389 : Oid proc = InvalidOid;
158 : : int i;
159 : :
5683 rhaas@postgresql.org 160 : 3389 : catlist = SearchSysCacheList3(CONDEFAULT,
161 : : ObjectIdGetDatum(name_space),
162 : : Int32GetDatum(for_encoding),
163 : : Int32GetDatum(to_encoding));
164 : :
8444 ishii@postgresql.org 165 [ + + ]: 3395 : for (i = 0; i < catlist->n_members; i++)
166 : : {
167 : 3391 : tuple = &catlist->members[i]->tuple;
8403 bruce@momjian.us 168 : 3391 : body = (Form_pg_conversion) GETSTRUCT(tuple);
8344 tgl@sss.pgh.pa.us 169 [ + + ]: 3391 : if (body->condefault)
170 : : {
8444 ishii@postgresql.org 171 : 3385 : proc = body->conproc;
172 : 3385 : break;
173 : : }
174 : : }
175 : 3389 : ReleaseSysCacheList(catlist);
176 : 3389 : return proc;
177 : : }
|