-<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_conversion.sgml,v 1.4 2002/09/21 18:32:54 petere Exp $ -->
+<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_conversion.sgml,v 1.5 2002/11/02 02:33:03 tgl Exp $ -->
<refentry id="SQL-CREATECONVERSION">
<refmeta>
<refsynopsisdiv>
<synopsis>
CREATE [DEFAULT] CONVERSION <replaceable>conversion_name</replaceable>
- FOR <replaceable>source_encoding</replaceable>
- TO <replaceable>dest_encoding</replaceable> FROM <replaceable>funcname</replaceable>
+ FOR <replaceable>source_encoding</replaceable> TO <replaceable>dest_encoding</replaceable> FROM <replaceable>funcname</replaceable>
</synopsis>
</refsynopsisdiv>
<para>
<command>CREATE CONVERSION</command> defines a new encoding
- conversion. There are two kinds of conversions. A default
- conversion is used for an automatic encoding conversion between
- frontend and backend. There should be only one default conversion
- for source/destination encodings pair in a schema. None default
- conversion never be used for the automatic conversion. Instead it
- can be used for CONVERT() function.
+ conversion. Conversion names may be used in the CONVERT() function
+ to specify a particular encoding conversion. Also, conversions that
+ are marked DEFAULT can be used for automatic encoding conversion between
+ frontend and backend. For this purpose, two conversions, from encoding A to
+ B AND from encoding B to A, must be defined.
</para>
<para>
To be able to create a conversion, you must have the execute right
- on the function and the usage right on the schema the function
- belongs to.
+ on the function and the create right on the destination schema.
</para>
<variablelist>
The <literal>DEFAULT</> clause indicates that this conversion
is the default for this particular source to destination
encoding. There should be only one default encoding in a schema
- for the encoding pair. A default encoding can be used for not
- only CONVERT() function, but also for the automatic encoding
- conversion between frontend and backend. For this purpose, two
- conversions, from encoding A to B AND encoding B to A, must be
- defined.
+ for the encoding pair.
</para>
</listitem>
</varlistentry>
<listitem>
<para>
The name of the conversion. The conversion name may be
- schema-qualified. If it is not, a conversion is defined in the
- current schema. The conversion name must be unique with in a
+ schema-qualified. If it is not, the conversion is defined in the
+ current schema. The conversion name must be unique within a
schema.
</para>
</listitem>
</para>
<para>
- The function must have following signature:
+ The function must have the following signature:
<programlisting>
conv_proc(
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.36 2002/09/23 20:43:40 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.37 2002/11/02 02:33:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Oid
FindConversionByName(List *name)
{
+ char *schemaname;
char *conversion_name;
Oid namespaceId;
Oid conoid;
List *lptr;
- /* Convert list of names to a name and namespace */
- namespaceId = QualifiedNameGetCreationNamespace(name, &conversion_name);
+ /* deconstruct the name list */
+ DeconstructQualifiedName(name, &schemaname, &conversion_name);
- if (length(name) > 1)
+ if (schemaname)
{
- /* Check we have usage rights in target namespace */
- if (pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
- return InvalidOid;
-
+ /* use exact schema given */
+ namespaceId = LookupExplicitNamespace(schemaname);
return FindConversion(conversion_name, namespaceId);
}
-
- recomputeNamespacePath();
-
- foreach(lptr, namespaceSearchPath)
+ else
{
- Oid namespaceId = (Oid) lfirsti(lptr);
+ /* search for it in search path */
+ recomputeNamespacePath();
- conoid = FindConversion(conversion_name, namespaceId);
- if (OidIsValid(conoid))
- return conoid;
+ foreach(lptr, namespaceSearchPath)
+ {
+ namespaceId = (Oid) lfirsti(lptr);
+ conoid = FindConversion(conversion_name, namespaceId);
+ if (OidIsValid(conoid))
+ return conoid;
+ }
}
/* Not found in path */
}
/*
- * FindDefaultConversionProc - find default encoding cnnversion proc
+ * FindDefaultConversionProc - find default encoding conversion proc
*/
Oid
FindDefaultConversionProc(int4 for_encoding, int4 to_encoding)
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_conversion.c,v 1.6 2002/09/04 20:31:14 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_conversion.c,v 1.7 2002/11/02 02:33:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "utils/acl.h"
#include "miscadmin.h"
-/* ----------------
+/*
* ConversionCreate
*
- * Add a new tuple to pg_coversion.
- * ---------------
+ * Add a new tuple to pg_conversion.
*/
Oid
ConversionCreate(const char *conname, Oid connamespace,
int32 conowner,
- int4 conforencoding, int4 contoencoding,
+ int32 conforencoding, int32 contoencoding,
Oid conproc, bool def)
{
int i;
elog(ERROR, "no conversion name supplied");
/* make sure there is no existing conversion of same name */
- if (SearchSysCacheExists(CONNAMESP,
+ if (SearchSysCacheExists(CONNAMENSP,
PointerGetDatum(conname),
ObjectIdGetDatum(connamespace),
0, 0))
conforencoding,
contoencoding))
elog(ERROR, "default conversion for %s to %s already exists",
- pg_encoding_to_char(conforencoding), pg_encoding_to_char(contoencoding));
+ pg_encoding_to_char(conforencoding),
+ pg_encoding_to_char(contoencoding));
}
/* open pg_conversion */
values[Anum_pg_conversion_conforencoding - 1] = Int32GetDatum(conforencoding);
values[Anum_pg_conversion_contoencoding - 1] = Int32GetDatum(contoencoding);
values[Anum_pg_conversion_conproc - 1] = ObjectIdGetDatum(conproc);
- if (def == true)
- values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
- else
- nulls[Anum_pg_conversion_condefault - 1] = 'n';
+ values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
tup = heap_formtuple(tupDesc, values, nulls);
/* update the index if any */
CatalogUpdateIndexes(rel, tup);
- myself.classId = get_system_catalog_relid(ConversionRelationName);
+ myself.classId = RelationGetRelid(rel);
myself.objectId = HeapTupleGetOid(tup);
myself.objectSubId = 0;
- /* dependency on conversion procedure */
+ /* create dependency on conversion procedure */
referenced.classId = RelOid_pg_proc;
referenced.objectId = conproc;
referenced.objectSubId = 0;
return oid;
}
-/* ----------------
+/*
* ConversionDrop
*
- * Drop a conversion and do dependency check.
- * ---------------
+ * Drop a conversion after doing permission checks.
*/
void
-ConversionDrop(const char *conname, Oid connamespace,
- int32 conowner, DropBehavior behavior)
+ConversionDrop(Oid conversionOid, DropBehavior behavior)
{
- Relation rel;
- TupleDesc tupDesc;
HeapTuple tuple;
- HeapScanDesc scan;
- ScanKeyData scanKeyData;
- Form_pg_conversion body;
ObjectAddress object;
- Oid myoid;
-
- /* sanity checks */
- if (!conname)
- elog(ERROR, "no conversion name supplied");
-
- ScanKeyEntryInitialize(&scanKeyData,
- 0,
- Anum_pg_conversion_connamespace,
- F_OIDEQ,
- ObjectIdGetDatum(connamespace));
-
- /* open pg_conversion */
- rel = heap_openr(ConversionRelationName, AccessShareLock);
- tupDesc = rel->rd_att;
-
- scan = heap_beginscan(rel, SnapshotNow,
- 1, &scanKeyData);
-
- /* search for the target tuple */
- while (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
- {
- body = (Form_pg_conversion) GETSTRUCT(tuple);
- if (!strncmp(NameStr(body->conname), conname, NAMEDATALEN))
- break;
- }
+ tuple = SearchSysCache(CONOID,
+ ObjectIdGetDatum(conversionOid),
+ 0, 0, 0);
if (!HeapTupleIsValid(tuple))
- {
- elog(ERROR, "conversion %s not found", conname);
- return;
- }
+ elog(ERROR, "Conversion %u search from syscache failed",
+ conversionOid);
- if (!superuser() && ((Form_pg_conversion) GETSTRUCT(tuple))->conowner != GetUserId())
+ if (!superuser() &&
+ ((Form_pg_conversion) GETSTRUCT(tuple))->conowner != GetUserId())
elog(ERROR, "permission denied");
- myoid = HeapTupleGetOid(tuple);
- heap_endscan(scan);
- heap_close(rel, AccessShareLock);
+ ReleaseSysCache(tuple);
/*
* Do the deletion
*/
object.classId = get_system_catalog_relid(ConversionRelationName);
- object.objectId = myoid;
+ object.objectId = conversionOid;
object.objectSubId = 0;
performDeletion(&object, behavior);
}
-/* ----------------
+/*
* RemoveConversionById
*
- * Remove a tuple from pg_conversion by Oid. This function is soley
+ * Remove a tuple from pg_conversion by Oid. This function is solely
* called inside catalog/dependency.c
- * --------------- */
+ */
void
RemoveConversionById(Oid conversionOid)
{
heap_close(rel, RowExclusiveLock);
}
-/* ----------------
+/*
* FindDefaultConversion
*
- * Find "default" conversion proc by for_encoding and to_encoding in this name space.
- * If found, returns the procedure's oid, otherwise InvalidOid.
- * ---------------
+ * Find "default" conversion proc by for_encoding and to_encoding in the
+ * given namespace.
+ *
+ * If found, returns the procedure's oid, otherwise InvalidOid. Note that
+ * you get the procedure's OID not the conversion's OID!
*/
Oid
-FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding)
+FindDefaultConversion(Oid name_space, int32 for_encoding, int32 to_encoding)
{
CatCList *catlist;
HeapTuple tuple;
Oid proc = InvalidOid;
int i;
- /* Check we have usage rights in target namespace */
- if (pg_namespace_aclcheck(name_space, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
- return proc;
-
catlist = SearchSysCacheList(CONDEFAULT, 3,
ObjectIdGetDatum(name_space),
Int32GetDatum(for_encoding),
{
tuple = &catlist->members[i]->tuple;
body = (Form_pg_conversion) GETSTRUCT(tuple);
- if (body->condefault == TRUE)
+ if (body->condefault)
{
proc = body->conproc;
break;
return proc;
}
-/* ----------------
- * FindConversionByName
+/*
+ * FindConversion
*
* Find conversion by namespace and conversion name.
- * Returns conversion oid.
- * ---------------
+ * Returns conversion OID.
*/
Oid
FindConversion(const char *conname, Oid connamespace)
AclResult aclresult;
/* search pg_conversion by connamespace and conversion name */
- tuple = SearchSysCache(CONNAMESP,
+ tuple = SearchSysCache(CONNAMENSP,
PointerGetDatum(conname),
ObjectIdGetDatum(connamespace),
0, 0);
-
if (!HeapTupleIsValid(tuple))
return InvalidOid;
+
procoid = ((Form_pg_conversion) GETSTRUCT(tuple))->conproc;
conoid = HeapTupleGetOid(tuple);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/conversioncmds.c,v 1.4 2002/09/04 20:31:14 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/conversioncmds.c,v 1.5 2002/11/02 02:33:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
int for_encoding;
int to_encoding;
Oid funcoid;
- Oid funcnamespace;
- char *dummy;
-
const char *for_encoding_name = stmt->for_encoding_name;
const char *to_encoding_name = stmt->to_encoding_name;
List *func_name = stmt->func_name;
-
static Oid funcargs[] = {INT4OID, INT4OID, CSTRINGOID, CSTRINGOID, INT4OID};
/* Convert list of names to a name and namespace */
- namespaceId = QualifiedNameGetCreationNamespace(stmt->conversion_name, &conversion_name);
+ namespaceId = QualifiedNameGetCreationNamespace(stmt->conversion_name,
+ &conversion_name);
/* Check we have creation rights in target namespace */
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
*/
funcoid = LookupFuncName(func_name, sizeof(funcargs) / sizeof(Oid), funcargs);
if (!OidIsValid(funcoid))
- elog(ERROR, "Function %s does not exist", NameListToString(func_name));
-
- /* Check the rights for this function and name space */
- funcnamespace = QualifiedNameGetCreationNamespace(func_name, &dummy);
- aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
- if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, get_namespace_name(funcnamespace));
+ func_error("CreateConversion", func_name,
+ sizeof(funcargs) / sizeof(Oid), funcargs, NULL);
+ /* Check we have EXECUTE rights for the function */
aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE);
if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, get_namespace_name(funcnamespace));
+ aclcheck_error(aclresult, NameListToString(func_name));
/*
* All seem ok, go ahead (possible failure would be a duplicate
void
DropConversionCommand(List *name, DropBehavior behavior)
{
- Oid namespaceId;
- char *conversion_name;
- AclResult aclresult;
+ Oid conversionOid;
- /* Convert list of names to a name and namespace */
- namespaceId = QualifiedNameGetCreationNamespace(name, &conversion_name);
+ conversionOid = FindConversionByName(name);
- /* Check we have creation rights in target namespace */
- aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
- if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, get_namespace_name(namespaceId));
+ if (!OidIsValid(conversionOid))
+ elog(ERROR, "conversion %s not found", NameListToString(name));
- /*
- * Go ahead (possible failure would be: none existing conversion not
- * ower of this conversion
- */
- ConversionDrop(conversion_name, namespaceId, GetUserId(), behavior);
+ ConversionDrop(conversionOid, behavior);
}
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_conversion.h,v 1.6 2002/09/04 20:31:37 momjian Exp $
+ * $Id: pg_conversion.h,v 1.7 2002/11/02 02:33:03 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
extern Oid ConversionCreate(const char *conname, Oid connamespace,
int32 conowner,
- int4 conforencoding, int4 contoencoding,
+ int32 conforencoding, int32 contoencoding,
Oid conproc, bool def);
-extern void ConversionDrop(const char *conname, Oid connamespace,
- int32 conowner, DropBehavior behavior);
+extern void ConversionDrop(Oid conversionOid, DropBehavior behavior);
extern void RemoveConversionById(Oid conversionOid);
extern Oid FindConversion(const char *conname, Oid connamespace);
-extern Oid FindDefaultConversion(Oid connamespace, int4 for_encoding, int4 to_encoding);
+extern Oid FindDefaultConversion(Oid connamespace, int32 for_encoding, int32 to_encoding);
#endif /* PG_CONVERSION_H */
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: syscache.h,v 1.53 2002/09/04 20:31:46 momjian Exp $
+ * $Id: syscache.h,v 1.54 2002/11/02 02:33:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#define CLAAMNAMENSP 9
#define CLAOID 10
#define CONDEFAULT 11
-#define CONNAMESP 12
+#define CONNAMENSP 12
#define CONOID 13
#define GRONAME 14
#define GROSYSID 15