Index: doc/src/sgml/func.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/func.sgml,v
retrieving revision 1.105
diff -c -r1.105 func.sgml
*** doc/src/sgml/func.sgml 31 Jul 2002 02:27:28 -0000 1.105
--- doc/src/sgml/func.sgml 31 Jul 2002 05:20:09 -0000
***************
*** 858,863 ****
--- 858,876 ----
+ convert(string
+ using conversion_name)
+ text
+ Change encoding using specified conversion name.
+ Conversions can be defined by CREATE CONVERSION.
+ Also there are some pre-defined conversion names.
+ See for available
+ conversion names.
+ convert('PostgreSQL' using iso8859_1_to_utf8)
+ 'PostgreSQL' in UNICODE(UTF-8) encoding
+
+
+
lower(string)
text
Convert string to lower case.
***************
*** 943,948 ****
--- 956,1360 ----
upper('tom')
TOM
+
+
+
+
+
+ Available conversion names
+
+
+
+ conversion
+ source encoding
+ destination encoding
+
+
+
+
+ ascii_to_utf8
+ SQL_ASCII
+ UNICODE
+
+
+
+ big5_to_euc_tw
+ BIG5
+ EUC_TW
+
+
+
+ big5_to_mic
+ BIG5
+ MULE_INTERNAL
+
+
+
+ big5_to_utf8
+ BIG5
+ UNICODE
+
+
+
+ euc_cn_to_utf8
+ EUC_CN
+ UNICODE
+
+
+
+ euc_jp_to_mic
+ EUC_JP
+ MULE_INTERNAL
+
+
+
+ euc_jp_to_sjis
+ EUC_JP
+ SJIS
+
+
+
+ euc_jp_to_utf8
+ EUC_JP
+ UNICODE
+
+
+
+ euc_kr_to_utf8
+ EUC_KR
+ UNICODE
+
+
+
+ euc_tw_to_big5
+ EUC_TW
+ BIG5
+
+
+
+ euc_tw_to_mic
+ EUC_TW
+ MULE_INTERNAL
+
+
+
+ euc_tw_to_utf8
+ EUC_TW
+ UNICODE
+
+
+
+ gb18030_to_utf8
+ GB18030
+ UNICODE
+
+
+
+ gbk_to_utf8
+ GBK
+ UNICODE
+
+
+
+ iso8859_10_to_utf8
+ LATIN6
+ UNICODE
+
+
+
+ iso8859_13_to_utf8
+ LATIN7
+ UNICODE
+
+
+
+ iso8859_14_to_utf8
+ LATIN8
+ UNICODE
+
+
+
+ iso8859_15_to_utf8
+ LATIN9
+ UNICODE
+
+
+
+ iso8859_16_to_utf8
+ LATIN10
+ UNICODE
+
+
+
+ iso8859_1_to_utf8
+ LATIN1
+ UNICODE
+
+
+
+ iso8859_2_to_utf8
+ LATIN2
+ UNICODE
+
+
+
+ iso8859_3_to_utf8
+ LATIN3
+ UNICODE
+
+
+
+ iso8859_4_to_utf8
+ LATIN4
+ UNICODE
+
+
+
+ iso8859_5_to_utf8
+ ISO_8859_5
+ UNICODE
+
+
+
+ iso8859_6_to_utf8
+ ISO_8859_6
+ UNICODE
+
+
+
+ iso8859_7_to_utf8
+ ISO_8859_7
+ UNICODE
+
+
+
+ iso8859_8_to_utf8
+ ISO_8859_8
+ UNICODE
+
+
+
+ iso8859_9_to_utf8
+ LATIN5
+ UNICODE
+
+
+
+ johab_to_utf8
+ JOHAB
+ UNICODE
+
+
+
+ mic_to_big5
+ MULE_INTERNAL
+ BIG5
+
+
+
+ mic_to_euc_jp
+ MULE_INTERNAL
+ EUC_JP
+
+
+
+ mic_to_euc_tw
+ MULE_INTERNAL
+ EUC_TW
+
+
+
+ mic_to_sjis
+ MULE_INTERNAL
+ SJIS
+
+
+
+ sjis_to_euc_jp
+ SJIS
+ EUC_JP
+
+
+
+ sjis_to_mic
+ SJIS
+ MULE_INTERNAL
+
+
+
+ sjis_to_utf8
+ SJIS
+ UNICODE
+
+
+
+ tcvn_to_utf8
+ TCVN
+ UNICODE
+
+
+
+ uhc_to_utf8
+ UHC
+ UNICODE
+
+
+
+ utf8_to_ascii
+ UNICODE
+ SQL_ASCII
+
+
+
+ utf8_to_big5
+ UNICODE
+ BIG5
+
+
+
+ utf8_to_euc_cn
+ UNICODE
+ EUC_CN
+
+
+
+ utf8_to_euc_jp
+ UNICODE
+ EUC_JP
+
+
+
+ utf8_to_euc_kr
+ UNICODE
+ EUC_KR
+
+
+
+ utf8_to_euc_tw
+ UNICODE
+ EUC_TW
+
+
+
+ utf8_to_gb18030
+ UNICODE
+ GB18030
+
+
+
+ utf8_to_gbk
+ UNICODE
+ GBK
+
+
+
+ utf8_to_iso8859_1
+ UNICODE
+ LATIN1
+
+
+
+ utf8_to_iso8859_10
+ UNICODE
+ LATIN6
+
+
+
+ utf8_to_iso8859_13
+ UNICODE
+ LATIN7
+
+
+
+ utf8_to_iso8859_14
+ UNICODE
+ LATIN8
+
+
+
+ utf8_to_iso8859_15
+ UNICODE
+ LATIN9
+
+
+
+ utf8_to_iso8859_16
+ UNICODE
+ LATIN10
+
+
+
+ utf8_to_iso8859_2
+ UNICODE
+ LATIN2
+
+
+
+ utf8_to_iso8859_3
+ UNICODE
+ LATIN3
+
+
+
+ utf8_to_iso8859_4
+ UNICODE
+ LATIN4
+
+
+
+ utf8_to_iso8859_5
+ UNICODE
+ ISO_8859_5
+
+
+
+ utf8_to_iso8859_6
+ UNICODE
+ ISO_8859_6
+
+
+
+ utf8_to_iso8859_7
+ UNICODE
+ ISO_8859_7
+
+
+
+ utf8_to_iso8859_8
+ UNICODE
+ ISO_8859_8
+
+
+
+ utf8_to_iso8859_9
+ UNICODE
+ LATIN5
+
+
+
+ utf8_to_johab
+ UNICODE
+ JOHAB
+
+
+
+ utf8_to_sjis
+ UNICODE
+ SJIS
+
+
+
+ utf8_to_tcvn
+ UNICODE
+ TCVN
+
+
+
+ utf8_to_uhc
+ UNICODE
+ UHC
+
+
Index: src/backend/catalog/namespace.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/catalog/namespace.c,v
retrieving revision 1.27
diff -c -r1.27 namespace.c
*** src/backend/catalog/namespace.c 29 Jul 2002 23:46:35 -0000 1.27
--- src/backend/catalog/namespace.c 31 Jul 2002 05:20:12 -0000
***************
*** 1239,1244 ****
--- 1239,1281 ----
}
/*
+ * FindConversionByName - find a conversion by possibly qualified name
+ */
+ Oid FindConversionByName(List *name)
+ {
+ char *conversion_name;
+ Oid namespaceId;
+ Oid conoid;
+ List *lptr;
+
+ /* Convert list of names to a name and namespace */
+ namespaceId = QualifiedNameGetCreationNamespace(name, &conversion_name);
+
+ if (length(name) > 1)
+ {
+ /* Check we have usage rights in target namespace */
+ if (pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
+ return InvalidOid;
+
+ return FindConversion(conversion_name, namespaceId);
+ }
+
+ recomputeNamespacePath();
+
+ foreach(lptr, namespaceSearchPath)
+ {
+ Oid namespaceId = (Oid) lfirsti(lptr);
+
+ conoid = FindConversion(conversion_name, namespaceId);
+ if (OidIsValid(conoid))
+ return conoid;
+ }
+
+ /* Not found in path */
+ return InvalidOid;
+ }
+
+ /*
* FindDefaultConversionProc - find default encoding cnnversion proc
*/
Oid FindDefaultConversionProc(int4 for_encoding, int4 to_encoding)
Index: src/backend/catalog/pg_conversion.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/catalog/pg_conversion.c,v
retrieving revision 1.3
diff -c -r1.3 pg_conversion.c
*** src/backend/catalog/pg_conversion.c 25 Jul 2002 10:07:10 -0000 1.3
--- src/backend/catalog/pg_conversion.c 31 Jul 2002 05:20:12 -0000
***************
*** 228,234 ****
if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
simple_heap_delete(rel, &tuple->t_self);
else
! elog(ERROR, "Conversion %u does not exist", conversionOid);
heap_endscan(scan);
heap_close(rel, RowExclusiveLock);
}
--- 228,234 ----
if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
simple_heap_delete(rel, &tuple->t_self);
else
! elog(ERROR, "conversion %u does not exist", conversionOid);
heap_endscan(scan);
heap_close(rel, RowExclusiveLock);
}
***************
*** 240,286 ****
* If found, returns the procedure's oid, otherwise InvalidOid.
* ---------------
*/
- #ifdef NOT_USED
- Oid FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding)
- {
- Relation rel;
- HeapScanDesc scan;
- ScanKeyData scanKeyData;
- HeapTuple tuple;
- Form_pg_conversion body;
- Oid proc = InvalidOid;
-
- /* Check we have usage rights in target namespace */
- if (pg_namespace_aclcheck(name_space, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
- return InvalidOid;
-
- ScanKeyEntryInitialize(&scanKeyData,
- 0,
- Anum_pg_conversion_connamespace,
- F_OIDEQ,
- ObjectIdGetDatum(name_space));
-
- rel = heap_openr(ConversionRelationName, AccessShareLock);
- scan = heap_beginscan(rel, SnapshotNow,
- 1, &scanKeyData);
-
- while (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
- {
- body = (Form_pg_conversion)GETSTRUCT(tuple);
- if (body->conforencoding == for_encoding &&
- body->contoencoding == to_encoding &&
- body->condefault == TRUE)
- {
- proc = body->conproc;
- break;
- }
- }
- heap_endscan(scan);
- heap_close(rel, AccessShareLock);
- return proc;
- }
- #endif
-
Oid FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding)
{
CatCList *catlist;
--- 240,245 ----
***************
*** 316,349 ****
/* ----------------
* FindConversionByName
*
! * Find conversion proc by possibly qualified conversion name.
* ---------------
*/
! Oid FindConversionByName(List *name)
{
HeapTuple tuple;
- char *conversion_name;
- Oid namespaceId;
Oid procoid;
AclResult aclresult;
! /* Convert list of names to a name and namespace */
! namespaceId = QualifiedNameGetCreationNamespace(name, &conversion_name);
!
! /* Check we have usage rights in target namespace */
! if (pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
! return InvalidOid;
!
! /* search pg_conversion by namespaceId and conversion name */
tuple = SearchSysCache(CONNAMESP,
! PointerGetDatum(conversion_name),
! ObjectIdGetDatum(namespaceId),
0,0);
if (!HeapTupleIsValid(tuple))
return InvalidOid;
-
procoid = ((Form_pg_conversion)GETSTRUCT(tuple))->conproc;
ReleaseSysCache(tuple);
--- 275,301 ----
/* ----------------
* FindConversionByName
*
! * Find conversion by namespace and conversion name.
! * Returns conversion oid.
* ---------------
*/
! Oid FindConversion(const char *conname, Oid connamespace)
{
HeapTuple tuple;
Oid procoid;
+ Oid conoid;
AclResult aclresult;
! /* search pg_conversion by connamespace and conversion name */
tuple = SearchSysCache(CONNAMESP,
! PointerGetDatum(conname),
! ObjectIdGetDatum(connamespace),
0,0);
if (!HeapTupleIsValid(tuple))
return InvalidOid;
procoid = ((Form_pg_conversion)GETSTRUCT(tuple))->conproc;
+ conoid = HeapTupleGetOid(tuple);
ReleaseSysCache(tuple);
***************
*** 352,357 ****
if (aclresult != ACLCHECK_OK)
return InvalidOid;
! return procoid;
}
--- 304,372 ----
if (aclresult != ACLCHECK_OK)
return InvalidOid;
! return conoid;
}
+ /*
+ * Execute SQL99's CONVERT function.
+ *
+ * CONVERT
+ * USING
+ *
+ * TEXT convert3(TEXT string, OID conversion_oid);
+ */
+ Datum
+ pg_convert3(PG_FUNCTION_ARGS)
+ {
+ text *string = PG_GETARG_TEXT_P(0);
+ Oid convoid = PG_GETARG_OID(1);
+ HeapTuple tuple;
+ Form_pg_conversion body;
+ text *retval;
+ unsigned char *str;
+ unsigned char *result;
+ int len;
+
+ if (!OidIsValid(convoid))
+ elog(ERROR, "Conversion does not exist");
+
+ /* make sure that source string is null terminated */
+ len = VARSIZE(string) - VARHDRSZ;
+ str = palloc(len + 1);
+ memcpy(str, VARDATA(string), len);
+ *(str + len) = '\0';
+
+ tuple = SearchSysCache(CONOID,
+ ObjectIdGetDatum(convoid),
+ 0,0,0);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "Conversion %u search from syscache failed", convoid);
+
+ result = palloc(len * 4 + 1);
+
+ body = (Form_pg_conversion)GETSTRUCT(tuple);
+ OidFunctionCall5(body->conproc,
+ Int32GetDatum(body->conforencoding),
+ Int32GetDatum(body->contoencoding),
+ CStringGetDatum(str),
+ CStringGetDatum(result),
+ Int32GetDatum(len));
+
+ ReleaseSysCache(tuple);
+
+ /* build text data type structre. we cannot use textin() here,
+ since textin assumes that input string encoding is same as
+ database encoding. */
+ len = strlen(result) + VARHDRSZ;
+ retval = palloc(len);
+ VARATT_SIZEP(retval) = len;
+ memcpy(VARDATA(retval), result, len - VARHDRSZ);
+
+ pfree(result);
+ pfree(str);
+
+ /* free memory if allocated by the toaster */
+ PG_FREE_IF_COPY(string, 0);
+
+ PG_RETURN_TEXT_P(retval);
+ }
Index: src/backend/parser/gram.y
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.351
diff -c -r2.351 gram.y
*** src/backend/parser/gram.y 30 Jul 2002 16:55:44 -0000 2.351
--- src/backend/parser/gram.y 31 Jul 2002 05:20:21 -0000
***************
*** 53,58 ****
--- 53,59 ----
#include "access/htup.h"
#include "catalog/index.h"
#include "catalog/namespace.h"
+ #include "catalog/pg_conversion.h"
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
#include "nodes/params.h"
***************
*** 218,224 ****
target_list, update_target_list, insert_column_list,
insert_target_list, def_list, opt_indirection,
group_clause, TriggerFuncArgs, select_limit,
! opt_select_limit, opclass_item_list
%type into_clause, OptTempTableName
--- 219,225 ----
target_list, update_target_list, insert_column_list,
insert_target_list, def_list, opt_indirection,
group_clause, TriggerFuncArgs, select_limit,
! opt_select_limit, opclass_item_list, expr_list2
%type into_clause, OptTempTableName
***************
*** 234,240 ****
%type join_type
%type extract_list, overlay_list, position_list
! %type substr_list, trim_list
%type opt_interval
%type overlay_placing, substr_from, substr_for
--- 235,241 ----
%type join_type
%type extract_list, overlay_list, position_list
! %type substr_list, trim_list, convert_list
%type opt_interval
%type overlay_placing, substr_from, substr_for
***************
*** 328,334 ****
CACHE, CALLED, CASCADE, CASE, CAST, CHAIN, CHAR_P,
CHARACTER, CHARACTERISTICS, CHECK, CHECKPOINT, CLASS, CLOSE,
CLUSTER, COALESCE, COLLATE, COLUMN, COMMENT, COMMIT,
! COMMITTED, CONSTRAINT, CONSTRAINTS, CONVERSION_P, COPY, CREATE, CREATEDB,
CREATEUSER, CROSS, CURRENT_DATE, CURRENT_TIME,
CURRENT_TIMESTAMP, CURRENT_USER, CURSOR, CYCLE,
--- 329,336 ----
CACHE, CALLED, CASCADE, CASE, CAST, CHAIN, CHAR_P,
CHARACTER, CHARACTERISTICS, CHECK, CHECKPOINT, CLASS, CLOSE,
CLUSTER, COALESCE, COLLATE, COLUMN, COMMENT, COMMIT,
! COMMITTED, CONSTRAINT, CONSTRAINTS, CONVERSION_P, CONVERT_P,
! COPY, CREATE, CREATEDB,
CREATEUSER, CROSS, CURRENT_DATE, CURRENT_TIME,
CURRENT_TIMESTAMP, CURRENT_USER, CURSOR, CYCLE,
***************
*** 6085,6090 ****
--- 6087,6101 ----
n->agg_distinct = FALSE;
$$ = (Node *)n;
}
+ | CONVERT_P '(' convert_list ')'
+ {
+ FuncCall *n = makeNode(FuncCall);
+ n->funcname = SystemFuncName("convert");
+ n->args = $3;
+ n->agg_star = FALSE;
+ n->agg_distinct = FALSE;
+ $$ = (Node *)n;
+ }
| select_with_parens %prec UMINUS
{
SubLink *n = makeNode(SubLink);
***************
*** 6237,6242 ****
--- 6248,6294 ----
trim_list: a_expr FROM expr_list { $$ = lappend($3, $1); }
| FROM expr_list { $$ = $2; }
| expr_list { $$ = $1; }
+ ;
+
+ /* CONVERT() arguments. We accept followings:
+ * SQL99 syntax
+ * o CONVERT(TEXT string USING conversion_name)
+ *
+ * Function calls
+ * o CONVERT(TEXT string, NAME src_encoding_name, NAME dest_encoding_name)
+ * o CONVERT(TEXT string, NAME encoding_name)
+ */
+ convert_list:
+ a_expr USING any_name
+ {
+ Oid oid = FindConversionByName($3);
+ Const *convoid = makeNode(Const);
+
+ if (!OidIsValid(oid))
+ {
+ elog(ERROR, "Conversion \"%s\" does not exist",
+ NameListToString($3));
+ }
+
+ convoid->consttype = OIDOID;
+ convoid->constlen = sizeof(Oid);
+ convoid->constvalue = oid;
+ convoid->constisnull = FALSE;
+ convoid->constbyval = TRUE;
+ convoid->constisset = FALSE;
+ convoid->constiscast = FALSE;
+ $$ = makeList2($1, convoid);
+ }
+ | expr_list2
+ {
+ $$ = $1;
+ }
+ | /*EMPTY*/
+ { $$ = NIL; }
+ ;
+
+ expr_list2: a_expr { $$ = makeList1($1); }
+ | expr_list2 ',' a_expr { $$ = lappend($1, $3); }
;
in_expr: select_with_parens
Index: src/backend/parser/keywords.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/keywords.c,v
retrieving revision 1.123
diff -c -r1.123 keywords.c
*** src/backend/parser/keywords.c 29 Jul 2002 22:14:11 -0000 1.123
--- src/backend/parser/keywords.c 31 Jul 2002 05:20:21 -0000
***************
*** 80,85 ****
--- 80,86 ----
{"constraint", CONSTRAINT},
{"constraints", CONSTRAINTS},
{"conversion", CONVERSION_P},
+ {"convert", CONVERT_P},
{"copy", COPY},
{"create", CREATE},
{"createdb", CREATEDB},
Index: src/include/catalog/namespace.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/namespace.h,v
retrieving revision 1.17
diff -c -r1.17 namespace.h
*** src/include/catalog/namespace.h 29 Jul 2002 23:46:35 -0000 1.17
--- src/include/catalog/namespace.h 31 Jul 2002 05:20:23 -0000
***************
*** 80,85 ****
--- 80,86 ----
extern void PushSpecialNamespace(Oid namespaceId);
extern void PopSpecialNamespace(Oid namespaceId);
+ extern Oid FindConversionByName(List *conname);
extern Oid FindDefaultConversionProc(int4 for_encoding, int4 to_encoding);
/* initialization & transaction cleanup code */
Index: src/include/catalog/pg_conversion.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_conversion.h,v
retrieving revision 1.2
diff -c -r1.2 pg_conversion.h
*** src/include/catalog/pg_conversion.h 25 Jul 2002 10:07:13 -0000 1.2
--- src/include/catalog/pg_conversion.h 31 Jul 2002 05:20:23 -0000
***************
*** 90,96 ****
extern void ConversionDrop(const char *conname, Oid connamespace,
int32 conowner, DropBehavior behavior);
extern void RemoveConversionById(Oid conversionOid);
! extern Oid FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding);
! extern Oid FindConversionByName(List *conname);
#endif /* PG_CONVERSION_H */
--- 90,98 ----
extern void ConversionDrop(const char *conname, Oid connamespace,
int32 conowner, 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 Datum pg_convert3(PG_FUNCTION_ARGS);
#endif /* PG_CONVERSION_H */
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_proc.h,v
retrieving revision 1.248
diff -c -r1.248 pg_proc.h
*** src/include/catalog/pg_proc.h 31 Jul 2002 01:49:13 -0000 1.248
--- src/include/catalog/pg_proc.h 31 Jul 2002 05:20:28 -0000
***************
*** 2149,2154 ****
--- 2149,2157 ----
DATA(insert OID = 1813 ( convert PGNSP PGUID 12 f f t f s 3 25 "25 19 19" pg_convert2 - _null_ ));
DESCR("convert string with specified encoding names");
+ DATA(insert OID = 90 ( convert PGNSP PGUID 12 f f t f s 2 25 "25 26" pg_convert3 - _null_ ));
+ DESCR("convert string with specified conversion oid");
+
DATA(insert OID = 1264 ( pg_char_to_encoding PGNSP PGUID 12 f f t f s 1 23 "19" PG_char_to_encoding - _null_ ));
DESCR("convert encoding name to encoding id");