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-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_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
7893 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 */
7948 ishii@postgresql.org 55 [ - + ]: 32 : if (!conname)
7948 ishii@postgresql.org 56 [ # # ]:UBC 0 : elog(ERROR, "no conversion name supplied");
57 : :
58 : : /* make sure there is no existing conversion of same name */
5173 rhaas@postgresql.org 59 [ + + ]:CBC 32 : if (SearchSysCacheExists2(CONNAMENSP,
60 : : PointerGetDatum(conname),
61 : : ObjectIdGetDatum(connamespace)))
7573 tgl@sss.pgh.pa.us 62 [ + - ]: 3 : ereport(ERROR,
63 : : (errcode(ERRCODE_DUPLICATE_OBJECT),
64 : : errmsg("conversion \"%s\" already exists", conname)));
65 : :
7948 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))
7573 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 */
1910 andres@anarazel.de 83 : 26 : rel = table_open(ConversionRelationId, RowExclusiveLock);
7948 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 : : {
5642 tgl@sss.pgh.pa.us 89 : 208 : nulls[i] = false;
7948 ishii@postgresql.org 90 : 208 : values[i] = (Datum) NULL;
91 : : }
92 : :
93 : : /* form a tuple */
94 : 26 : namestrcpy(&cname, conname);
1972 andres@anarazel.de 95 : 26 : oid = GetNewOidWithIndex(rel, ConversionOidIndexId,
96 : : Anum_pg_conversion_oid);
97 : 26 : values[Anum_pg_conversion_oid - 1] = ObjectIdGetDatum(oid);
7948 ishii@postgresql.org 98 : 26 : values[Anum_pg_conversion_conname - 1] = NameGetDatum(&cname);
99 : 26 : values[Anum_pg_conversion_connamespace - 1] = ObjectIdGetDatum(connamespace);
6865 tgl@sss.pgh.pa.us 100 : 26 : values[Anum_pg_conversion_conowner - 1] = ObjectIdGetDatum(conowner);
7948 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);
7834 tgl@sss.pgh.pa.us 104 : 26 : values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
105 : :
5642 106 : 26 : tup = heap_form_tuple(tupDesc, values, nulls);
107 : :
108 : : /* insert a new tuple */
2630 alvherre@alvh.no-ip. 109 : 26 : CatalogTupleInsert(rel, tup);
110 : :
6940 tgl@sss.pgh.pa.us 111 : 26 : myself.classId = ConversionRelationId;
1972 andres@anarazel.de 112 : 26 : myself.objectId = oid;
7934 ishii@postgresql.org 113 : 26 : myself.objectSubId = 0;
114 : :
115 : : /* create dependency on conversion procedure */
6940 tgl@sss.pgh.pa.us 116 : 26 : referenced.classId = ProcedureRelationId;
7934 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 */
6529 bruce@momjian.us 122 : 26 : referenced.classId = NamespaceRelationId;
123 : 26 : referenced.objectId = connamespace;
6436 tgl@sss.pgh.pa.us 124 : 26 : referenced.objectSubId = 0;
6529 bruce@momjian.us 125 : 26 : recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
126 : :
127 : : /* create dependency on owner */
1972 andres@anarazel.de 128 : 26 : recordDependencyOnOwner(ConversionRelationId, oid, conowner);
129 : :
130 : : /* dependency on extension */
4649 tgl@sss.pgh.pa.us 131 : 26 : recordDependencyOnCurrentExtension(&myself, false);
132 : :
133 : : /* Post creation hook for new conversion */
1972 andres@anarazel.de 134 [ - + ]: 26 : InvokeObjectPostCreateHook(ConversionRelationId, oid, 0);
135 : :
7934 ishii@postgresql.org 136 : 26 : heap_freetuple(tup);
1910 andres@anarazel.de 137 : 26 : table_close(rel, RowExclusiveLock);
138 : :
3330 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
7834 tgl@sss.pgh.pa.us 152 : 3347 : FindDefaultConversion(Oid name_space, int32 for_encoding, int32 to_encoding)
153 : : {
154 : : CatCList *catlist;
155 : : HeapTuple tuple;
156 : : Form_pg_conversion body;
7893 bruce@momjian.us 157 : 3347 : Oid proc = InvalidOid;
158 : : int i;
159 : :
5173 rhaas@postgresql.org 160 : 3347 : catlist = SearchSysCacheList3(CONDEFAULT,
161 : : ObjectIdGetDatum(name_space),
162 : : Int32GetDatum(for_encoding),
163 : : Int32GetDatum(to_encoding));
164 : :
7934 ishii@postgresql.org 165 [ + + ]: 3353 : for (i = 0; i < catlist->n_members; i++)
166 : : {
167 : 3349 : tuple = &catlist->members[i]->tuple;
7893 bruce@momjian.us 168 : 3349 : body = (Form_pg_conversion) GETSTRUCT(tuple);
7834 tgl@sss.pgh.pa.us 169 [ + + ]: 3349 : if (body->condefault)
170 : : {
7934 ishii@postgresql.org 171 : 3343 : proc = body->conproc;
172 : 3343 : break;
173 : : }
174 : : }
175 : 3347 : ReleaseSysCacheList(catlist);
176 : 3347 : return proc;
177 : : }
|