diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/namespace.c | 39 | ||||
-rw-r--r-- | src/backend/catalog/pg_conversion.c | 133 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 61 | ||||
-rw-r--r-- | src/backend/parser/keywords.c | 3 | ||||
-rw-r--r-- | src/backend/utils/mb/Makefile | 4 | ||||
-rw-r--r-- | src/backend/utils/mb/conversion_procs/Makefile | 32 | ||||
-rw-r--r-- | src/backend/utils/mb/conversion_procs/regress_epilogue | 5 | ||||
-rw-r--r-- | src/backend/utils/mb/conversion_procs/regress_prolog | 25 |
8 files changed, 229 insertions, 73 deletions
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 0425e44c1cd..bc2098034f3 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -13,7 +13,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.27 2002/07/29 23:46:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.28 2002/08/06 05:40:44 ishii Exp $ * *------------------------------------------------------------------------- */ @@ -1239,6 +1239,43 @@ PopSpecialNamespace(Oid namespaceId) } /* + * 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) diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c index c422e33e317..7dfd0679a22 100644 --- a/src/backend/catalog/pg_conversion.c +++ b/src/backend/catalog/pg_conversion.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_conversion.c,v 1.4 2002/08/05 03:29:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_conversion.c,v 1.5 2002/08/06 05:40:45 ishii Exp $ * *------------------------------------------------------------------------- */ @@ -221,7 +221,7 @@ RemoveConversionById(Oid conversionOid) if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection))) simple_heap_delete(rel, &tuple->t_self); else - elog(ERROR, "Conversion %u does not exist", conversionOid); + elog(ERROR, "conversion %u does not exist", conversionOid); heap_endscan(scan); heap_close(rel, RowExclusiveLock); } @@ -233,47 +233,6 @@ RemoveConversionById(Oid conversionOid) * 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; @@ -309,34 +268,27 @@ Oid FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding) /* ---------------- * FindConversionByName * - * Find conversion proc by possibly qualified conversion name. + * Find conversion by namespace and conversion name. + * Returns conversion oid. * --------------- */ -Oid FindConversionByName(List *name) +Oid FindConversion(const char *conname, Oid connamespace) { HeapTuple tuple; - char *conversion_name; - Oid namespaceId; Oid procoid; + Oid conoid; 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 */ + /* search pg_conversion by connamespace and conversion name */ tuple = SearchSysCache(CONNAMESP, - PointerGetDatum(conversion_name), - ObjectIdGetDatum(namespaceId), + PointerGetDatum(conname), + ObjectIdGetDatum(connamespace), 0,0); if (!HeapTupleIsValid(tuple)) return InvalidOid; - procoid = ((Form_pg_conversion)GETSTRUCT(tuple))->conproc; + conoid = HeapTupleGetOid(tuple); ReleaseSysCache(tuple); @@ -345,6 +297,69 @@ Oid FindConversionByName(List *name) if (aclresult != ACLCHECK_OK) return InvalidOid; - return procoid; + return conoid; } +/* + * Execute SQL99's CONVERT function. + * + * CONVERT <left paren> <character value expression> + * USING <form-of-use conversion name> <right paren> + * + * 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); +} diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 5c77aebfe62..f57f461124d 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.356 2002/08/05 02:30:50 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.357 2002/08/06 05:40:45 ishii Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -53,6 +53,7 @@ #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" @@ -216,7 +217,8 @@ static void doNegateFloat(Value *v); insert_target_list, def_list, opt_indirection, group_clause, TriggerFuncArgs, select_limit, opt_select_limit, opclass_item_list, trans_options, - TableFuncElementList, OptTableFuncElementList + TableFuncElementList, OptTableFuncElementList, + convert_args %type <range> into_clause, OptTempTableName @@ -232,7 +234,7 @@ static void doNegateFloat(Value *v); %type <jtype> join_type %type <list> extract_list, overlay_list, position_list -%type <list> substr_list, trim_list +%type <list> substr_list, trim_list, convert_list %type <ival> opt_interval %type <node> overlay_placing, substr_from, substr_for @@ -329,7 +331,7 @@ static void doNegateFloat(Value *v); 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, + COMMITTED, CONSTRAINT, CONSTRAINTS, CONVERSION_P, CONVERT, COPY, CREATE, CREATEDB, CREATEUSER, CROSS, CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR, CYCLE, @@ -6253,6 +6255,15 @@ c_expr: columnref { $$ = (Node *) $1; } n->agg_distinct = FALSE; $$ = (Node *)n; } + | CONVERT '(' 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); @@ -6418,6 +6429,48 @@ trim_list: a_expr FROM expr_list { $$ = lappend($3, $1); } | 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); + } + | convert_args + { + $$ = $1; + } + | /*EMPTY*/ + { $$ = NIL; } + ; + +convert_args: a_expr { $$ = makeList1($1); } + | convert_args ',' a_expr { $$ = lappend($1, $3); } + ; + + in_expr: select_with_parens { SubLink *n = makeNode(SubLink); diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c index 32733d8f546..2ae62ac18d9 100644 --- a/src/backend/parser/keywords.c +++ b/src/backend/parser/keywords.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.123 2002/07/29 22:14:11 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.124 2002/08/06 05:40:45 ishii Exp $ * *------------------------------------------------------------------------- */ @@ -80,6 +80,7 @@ static const ScanKeyword ScanKeywords[] = { {"constraint", CONSTRAINT}, {"constraints", CONSTRAINTS}, {"conversion", CONVERSION_P}, + {"convert", CONVERT}, {"copy", COPY}, {"create", CREATE}, {"createdb", CREATEDB}, diff --git a/src/backend/utils/mb/Makefile b/src/backend/utils/mb/Makefile index 64b60a510a4..ea460aa5297 100644 --- a/src/backend/utils/mb/Makefile +++ b/src/backend/utils/mb/Makefile @@ -4,7 +4,7 @@ # Makefile for utils/mb # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/utils/mb/Makefile,v 1.18 2002/07/18 02:02:30 ishii Exp $ +# $Header: /cvsroot/pgsql/src/backend/utils/mb/Makefile,v 1.19 2002/08/06 05:40:45 ishii Exp $ # #------------------------------------------------------------------------- @@ -24,7 +24,7 @@ clean distclean maintainer-clean: SUBSYS.o: $(OBJS) @for dir in $(DIRS); do $(MAKE) -C $$dir all || exit; done - $(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS) + $(LD) $(LDREL) $(LDOUT) $@ $^ depend dep: $(CC) -MM $(CFLAGS) *.c >depend diff --git a/src/backend/utils/mb/conversion_procs/Makefile b/src/backend/utils/mb/conversion_procs/Makefile index 30ff1384080..a1ab66bc282 100644 --- a/src/backend/utils/mb/conversion_procs/Makefile +++ b/src/backend/utils/mb/conversion_procs/Makefile @@ -4,7 +4,7 @@ # Makefile for utils/mb/conversion_procs # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/utils/mb/conversion_procs/Makefile,v 1.2 2002/07/18 22:58:08 petere Exp $ +# $Header: /cvsroot/pgsql/src/backend/utils/mb/conversion_procs/Makefile,v 1.3 2002/08/06 05:40:45 ishii Exp $ # #------------------------------------------------------------------------- @@ -14,6 +14,9 @@ include $(top_builddir)/src/Makefile.global SQLSCRIPT = conversion_create.sql +# This file can be placed as src/test/regress/conversion.sql +REGRESSION_SCRIPT = conversion.sql + DIRS = \ utf8_and_ascii utf8_and_iso8859_1 \ utf8_and_euc_jp utf8_and_euc_kr utf8_and_euc_cn utf8_and_euc_tw \ @@ -21,9 +24,7 @@ DIRS = \ utf8_and_uhc utf8_and_johab utf8_and_tcvn utf8_and_iso8859 \ euc_jp_and_sjis euc_tw_and_big5 -# conversion_name source_encoding destination_encoding function object -$(SQLSCRIPT): Makefile - @set \ +CONVERSIONS = \ utf8_to_ascii UNICODE SQL_ASCII utf8_to_ascii utf8_and_ascii \ ascii_to_utf8 SQL_ASCII UNICODE ascii_to_utf8 utf8_and_ascii \ utf8_to_iso8859_1 UNICODE LATIN1 utf8_to_iso8859_1 utf8_and_iso8859_1 \ @@ -87,8 +88,11 @@ $(SQLSCRIPT): Makefile euc_tw_to_mic EUC_TW MULE_INTERNAL euc_tw_to_mic euc_tw_and_big5 \ big5_to_mic BIG5 MULE_INTERNAL big5_to_mic euc_tw_and_big5 \ mic_to_euc_tw MULE_INTERNAL EUC_TW mic_to_euc_tw euc_tw_and_big5 \ - mic_to_big5 MULE_INTERNAL BIG5 mic_to_big5 euc_tw_and_big5 \ - ; \ + mic_to_big5 MULE_INTERNAL BIG5 mic_to_big5 euc_tw_and_big5 + +# conversion_name source_encoding destination_encoding function object +$(SQLSCRIPT): Makefile + @set $(CONVERSIONS) ; \ while [ "$$#" -gt 0 ] ; \ do \ name=$$1;shift; \ @@ -102,6 +106,22 @@ $(SQLSCRIPT): Makefile echo "CREATE DEFAULT CONVERSION pg_catalog.$$name FOR '$$se' TO '$$de' FROM $$func;"; \ done > $@ +$(REGRESSION_SCRIPT): Makefile + @cp regress_prolog $@; \ + set $(CONVERSIONS) ; \ + while [ "$$#" -gt 0 ] ; \ + do \ + name=$$1;shift; \ + se=$$1;shift; \ + de=$$1; shift; \ + func=$$1; shift; \ + obj=$$1; shift; \ + echo "-- $$se --> $$de"; \ + echo "SELECT CONVERT('foo' USING $$name);"; \ + echo "SELECT CONVERT('foo', '$$se', '$$de');"; \ + done >> $@; \ + cat regress_epilogue >> $@; + install: all installdirs $(INSTALL_DATA) $(SQLSCRIPT) $(DESTDIR)$(datadir) @for dir in $(DIRS); do $(MAKE) -C $$dir $@ || exit; done diff --git a/src/backend/utils/mb/conversion_procs/regress_epilogue b/src/backend/utils/mb/conversion_procs/regress_epilogue new file mode 100644 index 00000000000..da8238b9f39 --- /dev/null +++ b/src/backend/utils/mb/conversion_procs/regress_epilogue @@ -0,0 +1,5 @@ +-- +-- return to the super user +-- +RESET SESSION AUTHORIZATION; +DROP USER foo; diff --git a/src/backend/utils/mb/conversion_procs/regress_prolog b/src/backend/utils/mb/conversion_procs/regress_prolog new file mode 100644 index 00000000000..62a90d20b63 --- /dev/null +++ b/src/backend/utils/mb/conversion_procs/regress_prolog @@ -0,0 +1,25 @@ +-- +-- create user defined conversion +-- +CREATE USER foo WITH NOCREATEDB NOCREATEUSER; +SET SESSION AUTHORIZATION foo; +CREATE CONVERSION myconv FOR 'LATIN1' TO 'UNICODE' FROM iso8859_1_to_utf8; +-- +-- cannot make same name conversion in same schema +-- +CREATE CONVERSION myconv FOR 'LATIN1' TO 'UNICODE' FROM iso8859_1_to_utf8; +-- +-- create default conversion with qualified name +-- +CREATE DEFAULT CONVERSION public.mydef FOR 'LATIN1' TO 'UNICODE' FROM iso8859_1_to_utf8; +-- +-- cannot make default conversion with same shcema/for_encoding/to_encoding +-- +CREATE DEFAULT CONVERSION public.mydef2 FOR 'LATIN1' TO 'UNICODE' FROM iso8859_1_to_utf8; +-- +-- drop user defined conversion +-- +DROP CONVERSION myconv; +DROP CONVERSION mydef; +-- +-- make sure all pre-defined conversions are fine. |