I wrote:
> I still think however that search-path-based lookup of default encoding
> conversions is a Bad Idea, and that we only ought to allow one default
> conversion to exist for any pair of encodings.
> I realized that we could implement that without too much trouble by
> redefining pg_conversion.condefault as being true for default conversions
> and NULL (not false) for non-default ones. With this definition, a
> unique index on pg_conversion (conforencoding, contoencoding, condefault)
> would have the behavior we want --- sort of a poor man's partial unique
> index, except that it would work correctly on a system catalog whereas
> a true partial index wouldn't.
Turns out that indeed that works just fine. See attached draft patch.
regards, tom lane
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 97ef618..dcb8b8e 100644
*** a/doc/src/sgml/catalogs.sgml
--- b/doc/src/sgml/catalogs.sgml
***************
*** 2538,2544 ****
<entry><structfield>condefault</structfield></entry>
<entry><type>bool</type></entry>
<entry></entry>
! <entry>True if this is the default conversion</entry>
</row>
</tbody>
--- 2538,2545 ----
<entry><structfield>condefault</structfield></entry>
<entry><type>bool</type></entry>
<entry></entry>
! <entry>True if this is the default conversion for these two encodings,
! else NULL</entry>
</row>
</tbody>
diff --git a/doc/src/sgml/charset.sgml b/doc/src/sgml/charset.sgml
index f8c7ac3..eb39a9f 100644
*** a/doc/src/sgml/charset.sgml
--- b/doc/src/sgml/charset.sgml
*************** $ <userinput>psql -l</userinput>
*** 1102,1108 ****
<literal>pg_conversion</> system catalog. <productname>PostgreSQL</>
comes with some predefined conversions, as shown in <xref
linkend="multibyte-translation-table">. You can create a new
! conversion using the SQL command <command>CREATE CONVERSION</command>.
</para>
<table id="multibyte-translation-table">
--- 1102,1108 ----
<literal>pg_conversion</> system catalog. <productname>PostgreSQL</>
comes with some predefined conversions, as shown in <xref
linkend="multibyte-translation-table">. You can create a new
! conversion using the SQL command <xref linkend="sql-createconversion">.
</para>
<table id="multibyte-translation-table">
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index a0b42c2..f57d891 100644
*** a/doc/src/sgml/func.sgml
--- b/doc/src/sgml/func.sgml
***************
*** 1488,1494 ****
original encoding is specified by
<parameter>src_encoding</parameter>. The
<parameter>string</parameter> must be valid in this encoding.
! Conversions can be defined by <command>CREATE CONVERSION</command>.
Also there are some predefined conversions. See <xref
linkend="conversion-names"> for available conversions.
</entry>
--- 1488,1494 ----
original encoding is specified by
<parameter>src_encoding</parameter>. The
<parameter>string</parameter> must be valid in this encoding.
! Conversions can be defined with <xref linkend="sql-createconversion">.
Also there are some predefined conversions. See <xref
linkend="conversion-names"> for available conversions.
</entry>
***************
*** 1525,1534 ****
</entry>
<entry><type>bytea</type></entry>
<entry>
! Convert string to <parameter>dest_encoding</parameter>.
</entry>
<entry><literal>convert_to('some text', 'UTF8')</literal></entry>
! <entry><literal>some text</literal> represented in the UTF8 encoding</entry>
</row>
<row>
--- 1525,1535 ----
</entry>
<entry><type>bytea</type></entry>
<entry>
! Convert string from the database encoding
! to <parameter>dest_encoding</parameter>.
</entry>
<entry><literal>convert_to('some text', 'UTF8')</literal></entry>
! <entry><literal>some text</literal> represented in UTF8 encoding</entry>
</row>
<row>
diff --git a/doc/src/sgml/ref/create_conversion.sgml b/doc/src/sgml/ref/create_conversion.sgml
index d2e2c01..1933107 100644
*** a/doc/src/sgml/ref/create_conversion.sgml
--- b/doc/src/sgml/ref/create_conversion.sgml
*************** CREATE [ DEFAULT ] CONVERSION <replaceab
*** 28,34 ****
<para>
<command>CREATE CONVERSION</command> defines a new conversion between
! character set encodings. Also, conversions that
are marked <literal>DEFAULT</> can be used for automatic encoding
conversion between
client and server. For this purpose, two conversions, from encoding A to
--- 28,34 ----
<para>
<command>CREATE CONVERSION</command> defines a new conversion between
! character set encodings. Conversions that
are marked <literal>DEFAULT</> can be used for automatic encoding
conversion between
client and server. For this purpose, two conversions, from encoding A to
*************** CREATE [ DEFAULT ] CONVERSION <replaceab
*** 53,59 ****
<para>
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.
</para>
</listitem>
--- 53,59 ----
<para>
The <literal>DEFAULT</> clause indicates that this conversion
is the default for this particular source to destination
! encoding. There can be only one default conversion in a database
for the encoding pair.
</para>
</listitem>
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 8b105fe..98977f6 100644
*** a/src/backend/catalog/namespace.c
--- b/src/backend/catalog/namespace.c
***************
*** 28,34 ****
#include "catalog/pg_authid.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_conversion.h"
- #include "catalog/pg_conversion_fn.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
--- 28,33 ----
*************** get_conversion_oid(List *name, bool miss
*** 3416,3448 ****
}
/*
- * FindDefaultConversionProc - find default encoding conversion proc
- */
- Oid
- FindDefaultConversionProc(int32 for_encoding, int32 to_encoding)
- {
- Oid proc;
- ListCell *l;
-
- recomputeNamespacePath();
-
- foreach(l, activeSearchPath)
- {
- Oid namespaceId = lfirst_oid(l);
-
- if (namespaceId == myTempNamespace)
- continue; /* do not look in temp namespace */
-
- proc = FindDefaultConversion(namespaceId, for_encoding, to_encoding);
- if (OidIsValid(proc))
- return proc;
- }
-
- /* Not found in path */
- return InvalidOid;
- }
-
- /*
* recomputeNamespacePath - recompute path derived variables if needed.
*/
static void
--- 3415,3420 ----
diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c
index e2feb17..89b1ccf 100644
*** a/src/backend/catalog/pg_conversion.c
--- b/src/backend/catalog/pg_conversion.c
***************
*** 14,19 ****
--- 14,20 ----
*/
#include "postgres.h"
+ #include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
*************** ConversionCreate(const char *conname, Oi
*** 68,79 ****
if (def)
{
/*
! * make sure there is no existing default <for encoding><to encoding>
! * pair in this name space
*/
! if (FindDefaultConversion(connamespace,
! conforencoding,
! contoencoding))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("default conversion for %s to %s already exists",
--- 69,79 ----
if (def)
{
/*
! * make sure there is no existing default conversion for same
! * encodings
*/
! if (OidIsValid(FindDefaultConversionProc(conforencoding,
! contoencoding)))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("default conversion for %s to %s already exists",
*************** ConversionCreate(const char *conname, Oi
*** 100,106 ****
values[Anum_pg_conversion_conforencoding - 1] = Int32GetDatum(conforencoding);
values[Anum_pg_conversion_contoencoding - 1] = Int32GetDatum(contoencoding);
values[Anum_pg_conversion_conproc - 1] = ObjectIdGetDatum(conproc);
! values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
tup = heap_form_tuple(tupDesc, values, nulls);
--- 100,109 ----
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)
! values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(true);
! else
! nulls[Anum_pg_conversion_condefault - 1] = true;
tup = heap_form_tuple(tupDesc, values, nulls);
*************** ConversionCreate(const char *conname, Oi
*** 145,159 ****
/*
* RemoveConversionById
*
! * Remove a tuple from pg_conversion by Oid. This function is solely
! * called inside catalog/dependency.c
*/
void
RemoveConversionById(Oid conversionOid)
{
Relation rel;
HeapTuple tuple;
! HeapScanDesc scan;
ScanKeyData scanKeyData;
ScanKeyInit(&scanKeyData,
--- 148,162 ----
/*
* RemoveConversionById
*
! * Remove a tuple from pg_conversion by Oid.
! * This function is solely called inside catalog/dependency.c.
*/
void
RemoveConversionById(Oid conversionOid)
{
Relation rel;
HeapTuple tuple;
! SysScanDesc scan;
ScanKeyData scanKeyData;
ScanKeyInit(&scanKeyData,
*************** RemoveConversionById(Oid conversionOid)
*** 161,213 ****
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(conversionOid));
- /* open pg_conversion */
rel = heap_open(ConversionRelationId, RowExclusiveLock);
! scan = heap_beginscan_catalog(rel, 1, &scanKeyData);
! /* search for the target tuple */
! if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
simple_heap_delete(rel, &tuple->t_self);
else
elog(ERROR, "could not find tuple for conversion %u", conversionOid);
! heap_endscan(scan);
heap_close(rel, RowExclusiveLock);
}
/*
! * FindDefaultConversion
*
! * 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, int32 for_encoding, int32 to_encoding)
{
! CatCList *catlist;
! HeapTuple tuple;
! Form_pg_conversion body;
! Oid proc = InvalidOid;
! int i;
! catlist = SearchSysCacheList3(CONDEFAULT,
! ObjectIdGetDatum(name_space),
! Int32GetDatum(for_encoding),
! Int32GetDatum(to_encoding));
! for (i = 0; i < catlist->n_members; i++)
{
! tuple = &catlist->members[i]->tuple;
! body = (Form_pg_conversion) GETSTRUCT(tuple);
! if (body->condefault)
! {
! proc = body->conproc;
! break;
! }
}
! ReleaseSysCacheList(catlist);
! return proc;
}
--- 164,229 ----
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(conversionOid));
rel = heap_open(ConversionRelationId, RowExclusiveLock);
! scan = systable_beginscan(rel, ConversionOidIndexId, true,
! NULL, 1, &scanKeyData);
! if (HeapTupleIsValid(tuple = systable_getnext(scan)))
simple_heap_delete(rel, &tuple->t_self);
else
elog(ERROR, "could not find tuple for conversion %u", conversionOid);
!
! systable_endscan(scan);
heap_close(rel, RowExclusiveLock);
}
/*
! * FindDefaultConversionProc
*
! * Find "default" conversion proc converting from for_encoding to to_encoding.
*
* If found, returns the procedure's oid, otherwise InvalidOid. Note that
* you get the procedure's OID not the conversion's OID!
*/
Oid
! FindDefaultConversionProc(int32 for_encoding, int32 to_encoding)
{
! Oid result = InvalidOid;
! Relation conRel;
! ScanKeyData key[3];
! SysScanDesc conScan;
! HeapTuple conTup;
! conRel = heap_open(ConversionRelationId, AccessShareLock);
! ScanKeyInit(&key[0],
! Anum_pg_conversion_conforencoding,
! BTEqualStrategyNumber, F_INT4EQ,
! Int32GetDatum(for_encoding));
! ScanKeyInit(&key[1],
! Anum_pg_conversion_contoencoding,
! BTEqualStrategyNumber, F_INT4EQ,
! Int32GetDatum(to_encoding));
! ScanKeyInit(&key[2],
! Anum_pg_conversion_condefault,
! BTEqualStrategyNumber, F_BOOLEQ,
! BoolGetDatum(true));
!
! conScan = systable_beginscan(conRel, ConversionDefaultIndexId, true,
! NULL, 3, key);
!
! /* Assume there can be at most one match */
! if (HeapTupleIsValid(conTup = systable_getnext(conScan)))
{
! Form_pg_conversion conForm = (Form_pg_conversion) GETSTRUCT(conTup);
!
! result = conForm->conproc;
}
!
! systable_endscan(conScan);
!
! relation_close(conRel, AccessShareLock);
!
! return result;
}
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 6eb2ac6..3d6f82b 100644
*** a/src/backend/utils/cache/syscache.c
--- b/src/backend/utils/cache/syscache.c
*************** static const struct cachedesc cacheinfo[
*** 303,319 ****
},
8
},
- {ConversionRelationId, /* CONDEFAULT */
- ConversionDefaultIndexId,
- 4,
- {
- Anum_pg_conversion_connamespace,
- Anum_pg_conversion_conforencoding,
- Anum_pg_conversion_contoencoding,
- ObjectIdAttributeNumber,
- },
- 8
- },
{ConversionRelationId, /* CONNAMENSP */
ConversionNameNspIndexId,
2,
--- 303,308 ----
diff --git a/src/backend/utils/mb/mbutils.c b/src/backend/utils/mb/mbutils.c
index 7f1c881..b9a9686 100644
*** a/src/backend/utils/mb/mbutils.c
--- b/src/backend/utils/mb/mbutils.c
***************
*** 35,41 ****
#include "postgres.h"
#include "access/xact.h"
! #include "catalog/namespace.h"
#include "mb/pg_wchar.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
--- 35,41 ----
#include "postgres.h"
#include "access/xact.h"
! #include "catalog/pg_conversion_fn.h"
#include "mb/pg_wchar.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 56c0528..3421b12 100644
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
*************** dumpConversion(Archive *fout, DumpOption
*** 12178,12183 ****
--- 12178,12184 ----
conforencoding = PQgetvalue(res, 0, i_conforencoding);
contoencoding = PQgetvalue(res, 0, i_contoencoding);
conproc = PQgetvalue(res, 0, i_conproc);
+ /* condefault might be true, false, or null; this works regardless */
condefault = (PQgetvalue(res, 0, i_condefault)[0] == 't');
/*
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index ab2c1a8..25a465b 100644
*** a/src/include/catalog/indexing.h
--- b/src/include/catalog/indexing.h
*************** DECLARE_INDEX(pg_constraint_contypid_ind
*** 123,129 ****
DECLARE_UNIQUE_INDEX(pg_constraint_oid_index, 2667, on pg_constraint using btree(oid oid_ops));
#define ConstraintOidIndexId 2667
! DECLARE_UNIQUE_INDEX(pg_conversion_default_index, 2668, on pg_conversion using btree(connamespace oid_ops,
conforencodingint4_ops, contoencoding int4_ops, oid oid_ops));
#define ConversionDefaultIndexId 2668
DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index, 2669, on pg_conversion using btree(conname name_ops, connamespace
oid_ops));
#define ConversionNameNspIndexId 2669
--- 123,130 ----
DECLARE_UNIQUE_INDEX(pg_constraint_oid_index, 2667, on pg_constraint using btree(oid oid_ops));
#define ConstraintOidIndexId 2667
! /* NB: this index will not enforce uniqueness for rows with null condefault */
! DECLARE_UNIQUE_INDEX(pg_conversion_default_index, 2668, on pg_conversion using btree(conforencoding int4_ops,
contoencodingint4_ops, condefault bool_ops));
#define ConversionDefaultIndexId 2668
DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index, 2669, on pg_conversion using btree(conname name_ops, connamespace
oid_ops));
#define ConversionNameNspIndexId 2669
diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h
index 2ccb3a7..35b0369 100644
*** a/src/include/catalog/namespace.h
--- b/src/include/catalog/namespace.h
*************** extern void PopOverrideSearchPath(void);
*** 135,141 ****
extern Oid get_collation_oid(List *collname, bool missing_ok);
extern Oid get_conversion_oid(List *conname, bool missing_ok);
- extern Oid FindDefaultConversionProc(int32 for_encoding, int32 to_encoding);
/* initialization & transaction cleanup code */
extern void InitializeSearchPath(void);
--- 135,140 ----
diff --git a/src/include/catalog/pg_conversion.h b/src/include/catalog/pg_conversion.h
index 1cfe57c..7b8fff0 100644
*** a/src/include/catalog/pg_conversion.h
--- b/src/include/catalog/pg_conversion.h
***************
*** 32,38 ****
* conforencoding FOR encoding id
* contoencoding TO encoding id
* conproc OID of the conversion proc
! * condefault TRUE if this is a default conversion
* ----------------------------------------------------------------
*/
#define ConversionRelationId 2607
--- 32,41 ----
* conforencoding FOR encoding id
* contoencoding TO encoding id
* conproc OID of the conversion proc
! * condefault TRUE if this is a default conversion, else NULL
! *
! * (The odd definition of condefault allows us to make a poor man's
! * partial unique index on conforencoding/contoencoding.)
* ----------------------------------------------------------------
*/
#define ConversionRelationId 2607
*************** CATALOG(pg_conversion,2607)
*** 45,51 ****
int32 conforencoding;
int32 contoencoding;
regproc conproc;
! bool condefault;
} FormData_pg_conversion;
/* ----------------
--- 48,57 ----
int32 conforencoding;
int32 contoencoding;
regproc conproc;
!
! #ifdef CATALOG_VARLEN /* variable-length fields start here */
! bool condefault BKI_FORCE_NULL;
! #endif
} FormData_pg_conversion;
/* ----------------
diff --git a/src/include/catalog/pg_conversion_fn.h b/src/include/catalog/pg_conversion_fn.h
index 9fcdde6..fb4eef7 100644
*** a/src/include/catalog/pg_conversion_fn.h
--- b/src/include/catalog/pg_conversion_fn.h
*************** extern ObjectAddress ConversionCreate(co
*** 22,27 ****
int32 conforencoding, int32 contoencoding,
Oid conproc, bool def);
extern void RemoveConversionById(Oid conversionOid);
! extern Oid FindDefaultConversion(Oid connamespace, int32 for_encoding, int32 to_encoding);
#endif /* PG_CONVERSION_FN_H */
--- 22,27 ----
int32 conforencoding, int32 contoencoding,
Oid conproc, bool def);
extern void RemoveConversionById(Oid conversionOid);
! extern Oid FindDefaultConversionProc(int32 for_encoding, int32 to_encoding);
#endif /* PG_CONVERSION_FN_H */
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index 256615b..cd390b0 100644
*** a/src/include/utils/syscache.h
--- b/src/include/utils/syscache.h
*************** enum SysCacheIdentifier
*** 48,54 ****
CLAOID,
COLLNAMEENCNSP,
COLLOID,
- CONDEFAULT,
CONNAMENSP,
CONSTROID,
CONVOID,
--- 48,53 ----
diff --git a/src/test/regress/expected/conversion.out b/src/test/regress/expected/conversion.out
index 37965ae..7260ed2 100644
*** a/src/test/regress/expected/conversion.out
--- b/src/test/regress/expected/conversion.out
*************** CREATE CONVERSION myconv FOR 'LATIN1' TO
*** 10,23 ****
CREATE CONVERSION myconv FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8;
ERROR: conversion "myconv" already exists
--
! -- create default conversion with qualified name
--
! CREATE DEFAULT CONVERSION public.mydef FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8;
--
! -- cannot make default conversion with same schema/for_encoding/to_encoding
--
! CREATE DEFAULT CONVERSION public.mydef2 FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8;
! ERROR: default conversion for LATIN1 to UTF8 already exists
-- test comments
COMMENT ON CONVERSION myconv_bad IS 'foo';
ERROR: conversion "myconv_bad" does not exist
--- 10,29 ----
CREATE CONVERSION myconv FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8;
ERROR: conversion "myconv" already exists
--
! -- create a default conversion --- has to not match any built-in default,
! -- so we use a dummy function from regress.c
--
! CREATE DEFAULT CONVERSION public.mydef FOR 'LATIN1' TO 'BIG5' FROM iso8859_1_to_big5;
--
! -- cannot make two default conversions for same encodings
--
! CREATE DEFAULT CONVERSION mydef2 FOR 'LATIN1' TO 'BIG5' FROM iso8859_1_to_big5;
! ERROR: default conversion for LATIN1 to BIG5 already exists
! --
! -- verify that we notice if wrong conversion function is specified
! --
! CREATE CONVERSION bogus FOR 'BIG5' TO 'UTF8' FROM iso8859_1_to_utf8;
! ERROR: expected source encoding "LATIN1", but got "BIG5"
-- test comments
COMMENT ON CONVERSION myconv_bad IS 'foo';
ERROR: conversion "myconv_bad" does not exist
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index 616e674..2618f69 100644
*** a/src/test/regress/expected/opr_sanity.out
--- b/src/test/regress/expected/opr_sanity.out
*************** WHERE p.oid = c.conproc AND
*** 853,859 ****
-- there is no way to ask convert() to invoke them, and we cannot call
-- them directly from SQL. But there are no non-default built-in
-- conversions anyway.
- -- (Similarly, this doesn't cope with any search path issues.)
SELECT p1.oid, p1.conname
FROM pg_conversion as p1
WHERE condefault AND
--- 853,858 ----
diff --git a/src/test/regress/input/create_function_1.source b/src/test/regress/input/create_function_1.source
index f2b1561..6ed53a5 100644
*** a/src/test/regress/input/create_function_1.source
--- b/src/test/regress/input/create_function_1.source
*************** CREATE FUNCTION test_atomic_ops()
*** 62,67 ****
--- 62,72 ----
AS '@libdir@/regress@DLSUFFIX@'
LANGUAGE C;
+ CREATE FUNCTION iso8859_1_to_big5(int4, int4, cstring, internal, int4)
+ RETURNS void
+ AS '@libdir@/regress@DLSUFFIX@'
+ LANGUAGE C STRICT;
+
-- Things that shouldn't work:
CREATE FUNCTION test1 (int) RETURNS int LANGUAGE SQL
diff --git a/src/test/regress/output/create_function_1.source b/src/test/regress/output/create_function_1.source
index 30c2936..603499c 100644
*** a/src/test/regress/output/create_function_1.source
--- b/src/test/regress/output/create_function_1.source
*************** CREATE FUNCTION test_atomic_ops()
*** 55,60 ****
--- 55,64 ----
RETURNS bool
AS '@libdir@/regress@DLSUFFIX@'
LANGUAGE C;
+ CREATE FUNCTION iso8859_1_to_big5(int4, int4, cstring, internal, int4)
+ RETURNS void
+ AS '@libdir@/regress@DLSUFFIX@'
+ LANGUAGE C STRICT;
-- Things that shouldn't work:
CREATE FUNCTION test1 (int) RETURNS int LANGUAGE SQL
AS 'SELECT ''not an integer'';';
diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c
index bb30629..294cdc4 100644
*** a/src/test/regress/regress.c
--- b/src/test/regress/regress.c
***************
*** 29,34 ****
--- 29,35 ----
#include "commands/trigger.h"
#include "executor/executor.h"
#include "executor/spi.h"
+ #include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "port/atomics.h"
#include "utils/builtins.h"
*************** test_atomic_ops(PG_FUNCTION_ARGS)
*** 1120,1122 ****
--- 1121,1153 ----
PG_RETURN_BOOL(true);
}
+
+
+ PG_FUNCTION_INFO_V1(iso8859_1_to_big5);
+ Datum
+ iso8859_1_to_big5(PG_FUNCTION_ARGS)
+ {
+ unsigned char *src = (unsigned char *) PG_GETARG_CSTRING(2);
+ unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
+ int len = PG_GETARG_INT32(4);
+ unsigned short c;
+
+ CHECK_ENCODING_CONVERSION_ARGS(PG_LATIN1, PG_BIG5);
+
+ /*
+ * Since this is a dummy implementation, just throw error for non-ASCII
+ * characters.
+ */
+ while (len > 0)
+ {
+ c = *src;
+ if (c == 0 || IS_HIGHBIT_SET(c))
+ report_invalid_encoding(PG_LATIN1, (const char *) src, len);
+ *dest++ = c;
+ src++;
+ len--;
+ }
+ *dest = '\0';
+
+ PG_RETURN_VOID();
+ }
diff --git a/src/test/regress/sql/conversion.sql b/src/test/regress/sql/conversion.sql
index e31876b..68fb6e2 100644
*** a/src/test/regress/sql/conversion.sql
--- b/src/test/regress/sql/conversion.sql
***************
*** 3,21 ****
--
CREATE USER conversion_test_user WITH NOCREATEDB NOCREATEROLE;
SET SESSION AUTHORIZATION conversion_test_user;
CREATE CONVERSION myconv FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8;
--
-- cannot make same name conversion in same schema
--
CREATE CONVERSION myconv FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8;
--
! -- create default conversion with qualified name
--
! CREATE DEFAULT CONVERSION public.mydef FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8;
--
! -- cannot make default conversion with same schema/for_encoding/to_encoding
--
! CREATE DEFAULT CONVERSION public.mydef2 FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8;
-- test comments
COMMENT ON CONVERSION myconv_bad IS 'foo';
COMMENT ON CONVERSION myconv IS 'bar';
--- 3,28 ----
--
CREATE USER conversion_test_user WITH NOCREATEDB NOCREATEROLE;
SET SESSION AUTHORIZATION conversion_test_user;
+
CREATE CONVERSION myconv FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8;
--
-- cannot make same name conversion in same schema
--
CREATE CONVERSION myconv FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8;
--
! -- create a default conversion --- has to not match any built-in default,
! -- so we use a dummy function from regress.c
--
! CREATE DEFAULT CONVERSION public.mydef FOR 'LATIN1' TO 'BIG5' FROM iso8859_1_to_big5;
--
! -- cannot make two default conversions for same encodings
--
! CREATE DEFAULT CONVERSION mydef2 FOR 'LATIN1' TO 'BIG5' FROM iso8859_1_to_big5;
! --
! -- verify that we notice if wrong conversion function is specified
! --
! CREATE CONVERSION bogus FOR 'BIG5' TO 'UTF8' FROM iso8859_1_to_utf8;
!
-- test comments
COMMENT ON CONVERSION myconv_bad IS 'foo';
COMMENT ON CONVERSION myconv IS 'bar';
diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql
index d6aa2e8..6216083 100644
*** a/src/test/regress/sql/opr_sanity.sql
--- b/src/test/regress/sql/opr_sanity.sql
*************** WHERE p.oid = c.conproc AND
*** 488,494 ****
-- there is no way to ask convert() to invoke them, and we cannot call
-- them directly from SQL. But there are no non-default built-in
-- conversions anyway.
- -- (Similarly, this doesn't cope with any search path issues.)
SELECT p1.oid, p1.conname
FROM pg_conversion as p1
--- 488,493 ----