Age Owner 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-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_conversion.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
17 : #include "access/heapam.h"
18 : #include "access/htup_details.h"
19 : #include "access/sysattr.h"
20 : #include "access/tableam.h"
21 : #include "catalog/catalog.h"
22 : #include "catalog/dependency.h"
23 : #include "catalog/indexing.h"
24 : #include "catalog/objectaccess.h"
25 : #include "catalog/pg_conversion.h"
26 : #include "catalog/pg_namespace.h"
27 : #include "catalog/pg_proc.h"
28 : #include "mb/pg_wchar.h"
29 : #include "utils/builtins.h"
30 : #include "utils/catcache.h"
31 : #include "utils/fmgroids.h"
32 : #include "utils/rel.h"
33 : #include "utils/syscache.h"
34 :
35 : /*
36 : * ConversionCreate
37 : *
38 : * Add a new tuple to pg_conversion.
39 : */
40 : ObjectAddress
7522 bruce 41 CBC 32 : ConversionCreate(const char *conname, Oid connamespace,
42 : Oid conowner,
43 : int32 conforencoding, int32 contoencoding,
44 : Oid conproc, bool def)
45 : {
46 : int i;
47 : Relation rel;
48 : TupleDesc tupDesc;
49 : HeapTuple tup;
50 : Oid oid;
51 : bool nulls[Natts_pg_conversion];
52 : Datum values[Natts_pg_conversion];
53 : NameData cname;
54 : ObjectAddress myself,
55 : referenced;
56 :
57 : /* sanity checks */
7577 ishii 58 32 : if (!conname)
7577 ishii 59 UBC 0 : elog(ERROR, "no conversion name supplied");
60 :
61 : /* make sure there is no existing conversion of same name */
4802 rhaas 62 CBC 32 : if (SearchSysCacheExists2(CONNAMENSP,
63 : PointerGetDatum(conname),
64 : ObjectIdGetDatum(connamespace)))
7202 tgl 65 3 : ereport(ERROR,
66 : (errcode(ERRCODE_DUPLICATE_OBJECT),
67 : errmsg("conversion \"%s\" already exists", conname)));
68 :
7577 ishii 69 29 : if (def)
70 : {
71 : /*
72 : * make sure there is no existing default <for encoding><to encoding>
73 : * pair in this name space
74 : */
75 7 : if (FindDefaultConversion(connamespace,
76 : conforencoding,
77 : contoencoding))
7202 tgl 78 3 : ereport(ERROR,
79 : (errcode(ERRCODE_DUPLICATE_OBJECT),
80 : errmsg("default conversion for %s to %s already exists",
81 : pg_encoding_to_char(conforencoding),
82 : pg_encoding_to_char(contoencoding))));
83 : }
84 :
85 : /* open pg_conversion */
1539 andres 86 26 : rel = table_open(ConversionRelationId, RowExclusiveLock);
7577 ishii 87 26 : tupDesc = rel->rd_att;
88 :
89 : /* initialize nulls and values */
90 234 : for (i = 0; i < Natts_pg_conversion; i++)
91 : {
5271 tgl 92 208 : nulls[i] = false;
7577 ishii 93 208 : values[i] = (Datum) NULL;
94 : }
95 :
96 : /* form a tuple */
97 26 : namestrcpy(&cname, conname);
1601 andres 98 26 : oid = GetNewOidWithIndex(rel, ConversionOidIndexId,
99 : Anum_pg_conversion_oid);
100 26 : values[Anum_pg_conversion_oid - 1] = ObjectIdGetDatum(oid);
7577 ishii 101 26 : values[Anum_pg_conversion_conname - 1] = NameGetDatum(&cname);
102 26 : values[Anum_pg_conversion_connamespace - 1] = ObjectIdGetDatum(connamespace);
6494 tgl 103 26 : values[Anum_pg_conversion_conowner - 1] = ObjectIdGetDatum(conowner);
7577 ishii 104 26 : values[Anum_pg_conversion_conforencoding - 1] = Int32GetDatum(conforencoding);
105 26 : values[Anum_pg_conversion_contoencoding - 1] = Int32GetDatum(contoencoding);
106 26 : values[Anum_pg_conversion_conproc - 1] = ObjectIdGetDatum(conproc);
7463 tgl 107 26 : values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
108 :
5271 109 26 : tup = heap_form_tuple(tupDesc, values, nulls);
110 :
111 : /* insert a new tuple */
2259 alvherre 112 26 : CatalogTupleInsert(rel, tup);
113 :
6569 tgl 114 26 : myself.classId = ConversionRelationId;
1601 andres 115 26 : myself.objectId = oid;
7563 ishii 116 26 : myself.objectSubId = 0;
117 :
118 : /* create dependency on conversion procedure */
6569 tgl 119 26 : referenced.classId = ProcedureRelationId;
7563 ishii 120 26 : referenced.objectId = conproc;
121 26 : referenced.objectSubId = 0;
122 26 : recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
123 :
124 : /* create dependency on namespace */
6158 bruce 125 26 : referenced.classId = NamespaceRelationId;
126 26 : referenced.objectId = connamespace;
6065 tgl 127 26 : referenced.objectSubId = 0;
6158 bruce 128 26 : recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
129 :
130 : /* create dependency on owner */
1601 andres 131 26 : recordDependencyOnOwner(ConversionRelationId, oid, conowner);
132 :
133 : /* dependency on extension */
4278 tgl 134 26 : recordDependencyOnCurrentExtension(&myself, false);
135 :
136 : /* Post creation hook for new conversion */
1601 andres 137 26 : InvokeObjectPostCreateHook(ConversionRelationId, oid, 0);
138 :
7563 ishii 139 26 : heap_freetuple(tup);
1539 andres 140 26 : table_close(rel, RowExclusiveLock);
141 :
2959 alvherre 142 26 : return myself;
143 : }
144 :
145 : /*
146 : * FindDefaultConversion
147 : *
148 : * Find "default" conversion proc by for_encoding and to_encoding in the
149 : * given namespace.
150 : *
151 : * If found, returns the procedure's oid, otherwise InvalidOid. Note that
152 : * you get the procedure's OID not the conversion's OID!
153 : */
154 : Oid
7463 tgl 155 3465 : FindDefaultConversion(Oid name_space, int32 for_encoding, int32 to_encoding)
156 : {
157 : CatCList *catlist;
158 : HeapTuple tuple;
159 : Form_pg_conversion body;
7522 bruce 160 3465 : Oid proc = InvalidOid;
161 : int i;
162 :
4802 rhaas 163 3465 : catlist = SearchSysCacheList3(CONDEFAULT,
164 : ObjectIdGetDatum(name_space),
165 : Int32GetDatum(for_encoding),
166 : Int32GetDatum(to_encoding));
167 :
7563 ishii 168 3471 : for (i = 0; i < catlist->n_members; i++)
169 : {
170 3467 : tuple = &catlist->members[i]->tuple;
7522 bruce 171 3467 : body = (Form_pg_conversion) GETSTRUCT(tuple);
7463 tgl 172 3467 : if (body->condefault)
173 : {
7563 ishii 174 3461 : proc = body->conproc;
175 3461 : break;
176 : }
177 : }
178 3465 : ReleaseSysCacheList(catlist);
179 3465 : return proc;
180 : }
|