1 /*-------------------------------------------------------------------------
4 * routines to support manipulation of the pg_conversion relation
6 * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/catalog/pg_conversion.c
13 *-------------------------------------------------------------------------
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"
38 * Add a new tuple to pg_conversion.
41 ConversionCreate(const char *conname
, Oid connamespace
,
43 int32 conforencoding
, int32 contoencoding
,
44 Oid conproc
, bool def
)
51 bool nulls
[Natts_pg_conversion
];
52 Datum values
[Natts_pg_conversion
];
59 elog(ERROR
, "no conversion name supplied");
61 /* make sure there is no existing conversion of same name */
62 if (SearchSysCacheExists2(CONNAMENSP
,
63 PointerGetDatum(conname
),
64 ObjectIdGetDatum(connamespace
)))
66 (errcode(ERRCODE_DUPLICATE_OBJECT
),
67 errmsg("conversion \"%s\" already exists", conname
)));
72 * make sure there is no existing default <for encoding><to encoding>
73 * pair in this name space
75 if (FindDefaultConversion(connamespace
,
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
))));
85 /* open pg_conversion */
86 rel
= table_open(ConversionRelationId
, RowExclusiveLock
);
87 tupDesc
= rel
->rd_att
;
89 /* initialize nulls and values */
90 for (i
= 0; i
< Natts_pg_conversion
; i
++)
93 values
[i
] = (Datum
) NULL
;
97 namestrcpy(&cname
, conname
);
98 oid
= GetNewOidWithIndex(rel
, ConversionOidIndexId
,
99 Anum_pg_conversion_oid
);
100 values
[Anum_pg_conversion_oid
- 1] = ObjectIdGetDatum(oid
);
101 values
[Anum_pg_conversion_conname
- 1] = NameGetDatum(&cname
);
102 values
[Anum_pg_conversion_connamespace
- 1] = ObjectIdGetDatum(connamespace
);
103 values
[Anum_pg_conversion_conowner
- 1] = ObjectIdGetDatum(conowner
);
104 values
[Anum_pg_conversion_conforencoding
- 1] = Int32GetDatum(conforencoding
);
105 values
[Anum_pg_conversion_contoencoding
- 1] = Int32GetDatum(contoencoding
);
106 values
[Anum_pg_conversion_conproc
- 1] = ObjectIdGetDatum(conproc
);
107 values
[Anum_pg_conversion_condefault
- 1] = BoolGetDatum(def
);
109 tup
= heap_form_tuple(tupDesc
, values
, nulls
);
111 /* insert a new tuple */
112 CatalogTupleInsert(rel
, tup
);
114 myself
.classId
= ConversionRelationId
;
115 myself
.objectId
= oid
;
116 myself
.objectSubId
= 0;
118 /* create dependency on conversion procedure */
119 referenced
.classId
= ProcedureRelationId
;
120 referenced
.objectId
= conproc
;
121 referenced
.objectSubId
= 0;
122 recordDependencyOn(&myself
, &referenced
, DEPENDENCY_NORMAL
);
124 /* create dependency on namespace */
125 referenced
.classId
= NamespaceRelationId
;
126 referenced
.objectId
= connamespace
;
127 referenced
.objectSubId
= 0;
128 recordDependencyOn(&myself
, &referenced
, DEPENDENCY_NORMAL
);
130 /* create dependency on owner */
131 recordDependencyOnOwner(ConversionRelationId
, oid
, conowner
);
133 /* dependency on extension */
134 recordDependencyOnCurrentExtension(&myself
, false);
136 /* Post creation hook for new conversion */
137 InvokeObjectPostCreateHook(ConversionRelationId
, oid
, 0);
140 table_close(rel
, RowExclusiveLock
);
146 * FindDefaultConversion
148 * Find "default" conversion proc by for_encoding and to_encoding in the
151 * If found, returns the procedure's oid, otherwise InvalidOid. Note that
152 * you get the procedure's OID not the conversion's OID!
155 FindDefaultConversion(Oid name_space
, int32 for_encoding
, int32 to_encoding
)
159 Form_pg_conversion body
;
160 Oid proc
= InvalidOid
;
163 catlist
= SearchSysCacheList3(CONDEFAULT
,
164 ObjectIdGetDatum(name_space
),
165 Int32GetDatum(for_encoding
),
166 Int32GetDatum(to_encoding
));
168 for (i
= 0; i
< catlist
->n_members
; i
++)
170 tuple
= &catlist
->members
[i
]->tuple
;
171 body
= (Form_pg_conversion
) GETSTRUCT(tuple
);
172 if (body
->condefault
)
174 proc
= body
->conproc
;
178 ReleaseSysCacheList(catlist
);