Skip to content

Commit 6a7273e

Browse files
committed
Fix permissions-checking bugs and namespace-search-path bugs in
CONVERSION code. Still need to figure out what to do about inappropriate coding in parsing.
1 parent 08dd92c commit 6a7273e

File tree

6 files changed

+86
-148
lines changed

6 files changed

+86
-148
lines changed

doc/src/sgml/ref/create_conversion.sgml

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_conversion.sgml,v 1.4 2002/09/21 18:32:54 petere Exp $ -->
1+
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_conversion.sgml,v 1.5 2002/11/02 02:33:03 tgl Exp $ -->
22

33
<refentry id="SQL-CREATECONVERSION">
44
<refmeta>
@@ -14,8 +14,7 @@
1414
<refsynopsisdiv>
1515
<synopsis>
1616
CREATE [DEFAULT] CONVERSION <replaceable>conversion_name</replaceable>
17-
FOR <replaceable>source_encoding</replaceable>
18-
TO <replaceable>dest_encoding</replaceable> FROM <replaceable>funcname</replaceable>
17+
FOR <replaceable>source_encoding</replaceable> TO <replaceable>dest_encoding</replaceable> FROM <replaceable>funcname</replaceable>
1918
</synopsis>
2019
</refsynopsisdiv>
2120

@@ -24,18 +23,16 @@ CREATE [DEFAULT] CONVERSION <replaceable>conversion_name</replaceable>
2423

2524
<para>
2625
<command>CREATE CONVERSION</command> defines a new encoding
27-
conversion. There are two kinds of conversions. A default
28-
conversion is used for an automatic encoding conversion between
29-
frontend and backend. There should be only one default conversion
30-
for source/destination encodings pair in a schema. None default
31-
conversion never be used for the automatic conversion. Instead it
32-
can be used for CONVERT() function.
26+
conversion. Conversion names may be used in the CONVERT() function
27+
to specify a particular encoding conversion. Also, conversions that
28+
are marked DEFAULT can be used for automatic encoding conversion between
29+
frontend and backend. For this purpose, two conversions, from encoding A to
30+
B AND from encoding B to A, must be defined.
3331
</para>
3432

3533
<para>
3634
To be able to create a conversion, you must have the execute right
37-
on the function and the usage right on the schema the function
38-
belongs to.
35+
on the function and the create right on the destination schema.
3936
</para>
4037

4138
<variablelist>
@@ -49,11 +46,7 @@ CREATE [DEFAULT] CONVERSION <replaceable>conversion_name</replaceable>
4946
The <literal>DEFAULT</> clause indicates that this conversion
5047
is the default for this particular source to destination
5148
encoding. There should be only one default encoding in a schema
52-
for the encoding pair. A default encoding can be used for not
53-
only CONVERT() function, but also for the automatic encoding
54-
conversion between frontend and backend. For this purpose, two
55-
conversions, from encoding A to B AND encoding B to A, must be
56-
defined.
49+
for the encoding pair.
5750
</para>
5851
</listitem>
5952
</varlistentry>
@@ -64,8 +57,8 @@ CREATE [DEFAULT] CONVERSION <replaceable>conversion_name</replaceable>
6457
<listitem>
6558
<para>
6659
The name of the conversion. The conversion name may be
67-
schema-qualified. If it is not, a conversion is defined in the
68-
current schema. The conversion name must be unique with in a
60+
schema-qualified. If it is not, the conversion is defined in the
61+
current schema. The conversion name must be unique within a
6962
schema.
7063
</para>
7164
</listitem>
@@ -102,7 +95,7 @@ CREATE [DEFAULT] CONVERSION <replaceable>conversion_name</replaceable>
10295
</para>
10396

10497
<para>
105-
The function must have following signature:
98+
The function must have the following signature:
10699

107100
<programlisting>
108101
conv_proc(

src/backend/catalog/namespace.c

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* Portions Copyright (c) 1994, Regents of the University of California
1414
*
1515
* IDENTIFICATION
16-
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.36 2002/09/23 20:43:40 tgl Exp $
16+
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.37 2002/11/02 02:33:03 tgl Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -1275,40 +1275,41 @@ PopSpecialNamespace(Oid namespaceId)
12751275
Oid
12761276
FindConversionByName(List *name)
12771277
{
1278+
char *schemaname;
12781279
char *conversion_name;
12791280
Oid namespaceId;
12801281
Oid conoid;
12811282
List *lptr;
12821283

1283-
/* Convert list of names to a name and namespace */
1284-
namespaceId = QualifiedNameGetCreationNamespace(name, &conversion_name);
1284+
/* deconstruct the name list */
1285+
DeconstructQualifiedName(name, &schemaname, &conversion_name);
12851286

1286-
if (length(name) > 1)
1287+
if (schemaname)
12871288
{
1288-
/* Check we have usage rights in target namespace */
1289-
if (pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
1290-
return InvalidOid;
1291-
1289+
/* use exact schema given */
1290+
namespaceId = LookupExplicitNamespace(schemaname);
12921291
return FindConversion(conversion_name, namespaceId);
12931292
}
1294-
1295-
recomputeNamespacePath();
1296-
1297-
foreach(lptr, namespaceSearchPath)
1293+
else
12981294
{
1299-
Oid namespaceId = (Oid) lfirsti(lptr);
1295+
/* search for it in search path */
1296+
recomputeNamespacePath();
13001297

1301-
conoid = FindConversion(conversion_name, namespaceId);
1302-
if (OidIsValid(conoid))
1303-
return conoid;
1298+
foreach(lptr, namespaceSearchPath)
1299+
{
1300+
namespaceId = (Oid) lfirsti(lptr);
1301+
conoid = FindConversion(conversion_name, namespaceId);
1302+
if (OidIsValid(conoid))
1303+
return conoid;
1304+
}
13041305
}
13051306

13061307
/* Not found in path */
13071308
return InvalidOid;
13081309
}
13091310

13101311
/*
1311-
* FindDefaultConversionProc - find default encoding cnnversion proc
1312+
* FindDefaultConversionProc - find default encoding conversion proc
13121313
*/
13131314
Oid
13141315
FindDefaultConversionProc(int4 for_encoding, int4 to_encoding)

src/backend/catalog/pg_conversion.c

Lines changed: 38 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_conversion.c,v 1.6 2002/09/04 20:31:14 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_conversion.c,v 1.7 2002/11/02 02:33:03 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -30,16 +30,15 @@
3030
#include "utils/acl.h"
3131
#include "miscadmin.h"
3232

33-
/* ----------------
33+
/*
3434
* ConversionCreate
3535
*
36-
* Add a new tuple to pg_coversion.
37-
* ---------------
36+
* Add a new tuple to pg_conversion.
3837
*/
3938
Oid
4039
ConversionCreate(const char *conname, Oid connamespace,
4140
int32 conowner,
42-
int4 conforencoding, int4 contoencoding,
41+
int32 conforencoding, int32 contoencoding,
4342
Oid conproc, bool def)
4443
{
4544
int i;
@@ -58,7 +57,7 @@ ConversionCreate(const char *conname, Oid connamespace,
5857
elog(ERROR, "no conversion name supplied");
5958

6059
/* make sure there is no existing conversion of same name */
61-
if (SearchSysCacheExists(CONNAMESP,
60+
if (SearchSysCacheExists(CONNAMENSP,
6261
PointerGetDatum(conname),
6362
ObjectIdGetDatum(connamespace),
6463
0, 0))
@@ -74,7 +73,8 @@ ConversionCreate(const char *conname, Oid connamespace,
7473
conforencoding,
7574
contoencoding))
7675
elog(ERROR, "default conversion for %s to %s already exists",
77-
pg_encoding_to_char(conforencoding), pg_encoding_to_char(contoencoding));
76+
pg_encoding_to_char(conforencoding),
77+
pg_encoding_to_char(contoencoding));
7878
}
7979

8080
/* open pg_conversion */
@@ -96,10 +96,7 @@ ConversionCreate(const char *conname, Oid connamespace,
9696
values[Anum_pg_conversion_conforencoding - 1] = Int32GetDatum(conforencoding);
9797
values[Anum_pg_conversion_contoencoding - 1] = Int32GetDatum(contoencoding);
9898
values[Anum_pg_conversion_conproc - 1] = ObjectIdGetDatum(conproc);
99-
if (def == true)
100-
values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
101-
else
102-
nulls[Anum_pg_conversion_condefault - 1] = 'n';
99+
values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
103100

104101
tup = heap_formtuple(tupDesc, values, nulls);
105102

@@ -110,11 +107,11 @@ ConversionCreate(const char *conname, Oid connamespace,
110107
/* update the index if any */
111108
CatalogUpdateIndexes(rel, tup);
112109

113-
myself.classId = get_system_catalog_relid(ConversionRelationName);
110+
myself.classId = RelationGetRelid(rel);
114111
myself.objectId = HeapTupleGetOid(tup);
115112
myself.objectSubId = 0;
116113

117-
/* dependency on conversion procedure */
114+
/* create dependency on conversion procedure */
118115
referenced.classId = RelOid_pg_proc;
119116
referenced.objectId = conproc;
120117
referenced.objectSubId = 0;
@@ -126,79 +123,46 @@ ConversionCreate(const char *conname, Oid connamespace,
126123
return oid;
127124
}
128125

129-
/* ----------------
126+
/*
130127
* ConversionDrop
131128
*
132-
* Drop a conversion and do dependency check.
133-
* ---------------
129+
* Drop a conversion after doing permission checks.
134130
*/
135131
void
136-
ConversionDrop(const char *conname, Oid connamespace,
137-
int32 conowner, DropBehavior behavior)
132+
ConversionDrop(Oid conversionOid, DropBehavior behavior)
138133
{
139-
Relation rel;
140-
TupleDesc tupDesc;
141134
HeapTuple tuple;
142-
HeapScanDesc scan;
143-
ScanKeyData scanKeyData;
144-
Form_pg_conversion body;
145135
ObjectAddress object;
146-
Oid myoid;
147-
148-
/* sanity checks */
149-
if (!conname)
150-
elog(ERROR, "no conversion name supplied");
151-
152-
ScanKeyEntryInitialize(&scanKeyData,
153-
0,
154-
Anum_pg_conversion_connamespace,
155-
F_OIDEQ,
156-
ObjectIdGetDatum(connamespace));
157-
158-
/* open pg_conversion */
159-
rel = heap_openr(ConversionRelationName, AccessShareLock);
160-
tupDesc = rel->rd_att;
161-
162-
scan = heap_beginscan(rel, SnapshotNow,
163-
1, &scanKeyData);
164-
165-
/* search for the target tuple */
166-
while (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
167-
{
168-
body = (Form_pg_conversion) GETSTRUCT(tuple);
169-
if (!strncmp(NameStr(body->conname), conname, NAMEDATALEN))
170-
break;
171-
}
172136

137+
tuple = SearchSysCache(CONOID,
138+
ObjectIdGetDatum(conversionOid),
139+
0, 0, 0);
173140
if (!HeapTupleIsValid(tuple))
174-
{
175-
elog(ERROR, "conversion %s not found", conname);
176-
return;
177-
}
141+
elog(ERROR, "Conversion %u search from syscache failed",
142+
conversionOid);
178143

179-
if (!superuser() && ((Form_pg_conversion) GETSTRUCT(tuple))->conowner != GetUserId())
144+
if (!superuser() &&
145+
((Form_pg_conversion) GETSTRUCT(tuple))->conowner != GetUserId())
180146
elog(ERROR, "permission denied");
181147

182-
myoid = HeapTupleGetOid(tuple);
183-
heap_endscan(scan);
184-
heap_close(rel, AccessShareLock);
148+
ReleaseSysCache(tuple);
185149

186150
/*
187151
* Do the deletion
188152
*/
189153
object.classId = get_system_catalog_relid(ConversionRelationName);
190-
object.objectId = myoid;
154+
object.objectId = conversionOid;
191155
object.objectSubId = 0;
192156

193157
performDeletion(&object, behavior);
194158
}
195159

196-
/* ----------------
160+
/*
197161
* RemoveConversionById
198162
*
199-
* Remove a tuple from pg_conversion by Oid. This function is soley
163+
* Remove a tuple from pg_conversion by Oid. This function is solely
200164
* called inside catalog/dependency.c
201-
* --------------- */
165+
*/
202166
void
203167
RemoveConversionById(Oid conversionOid)
204168
{
@@ -230,26 +194,24 @@ RemoveConversionById(Oid conversionOid)
230194
heap_close(rel, RowExclusiveLock);
231195
}
232196

233-
/* ----------------
197+
/*
234198
* FindDefaultConversion
235199
*
236-
* Find "default" conversion proc by for_encoding and to_encoding in this name space.
237-
* If found, returns the procedure's oid, otherwise InvalidOid.
238-
* ---------------
200+
* Find "default" conversion proc by for_encoding and to_encoding in the
201+
* given namespace.
202+
*
203+
* If found, returns the procedure's oid, otherwise InvalidOid. Note that
204+
* you get the procedure's OID not the conversion's OID!
239205
*/
240206
Oid
241-
FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding)
207+
FindDefaultConversion(Oid name_space, int32 for_encoding, int32 to_encoding)
242208
{
243209
CatCList *catlist;
244210
HeapTuple tuple;
245211
Form_pg_conversion body;
246212
Oid proc = InvalidOid;
247213
int i;
248214

249-
/* Check we have usage rights in target namespace */
250-
if (pg_namespace_aclcheck(name_space, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
251-
return proc;
252-
253215
catlist = SearchSysCacheList(CONDEFAULT, 3,
254216
ObjectIdGetDatum(name_space),
255217
Int32GetDatum(for_encoding),
@@ -260,7 +222,7 @@ FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding)
260222
{
261223
tuple = &catlist->members[i]->tuple;
262224
body = (Form_pg_conversion) GETSTRUCT(tuple);
263-
if (body->condefault == TRUE)
225+
if (body->condefault)
264226
{
265227
proc = body->conproc;
266228
break;
@@ -270,12 +232,11 @@ FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding)
270232
return proc;
271233
}
272234

273-
/* ----------------
274-
* FindConversionByName
235+
/*
236+
* FindConversion
275237
*
276238
* Find conversion by namespace and conversion name.
277-
* Returns conversion oid.
278-
* ---------------
239+
* Returns conversion OID.
279240
*/
280241
Oid
281242
FindConversion(const char *conname, Oid connamespace)
@@ -286,13 +247,13 @@ FindConversion(const char *conname, Oid connamespace)
286247
AclResult aclresult;
287248

288249
/* search pg_conversion by connamespace and conversion name */
289-
tuple = SearchSysCache(CONNAMESP,
250+
tuple = SearchSysCache(CONNAMENSP,
290251
PointerGetDatum(conname),
291252
ObjectIdGetDatum(connamespace),
292253
0, 0);
293-
294254
if (!HeapTupleIsValid(tuple))
295255
return InvalidOid;
256+
296257
procoid = ((Form_pg_conversion) GETSTRUCT(tuple))->conproc;
297258
conoid = HeapTupleGetOid(tuple);
298259

0 commit comments

Comments
 (0)