#include "postgres.h" #include "fmgr.h" #include "lib/stringinfo.h" #include "mb/pg_wchar.h" #include "utils/builtins.h" #include "utils/numeric.h" #include "utils/pg_locale.h" #include "orafunc.h" #include "builtins.h" PG_FUNCTION_INFO_V1(orafce_to_char_int4); PG_FUNCTION_INFO_V1(orafce_to_char_int8); PG_FUNCTION_INFO_V1(orafce_to_char_float4); PG_FUNCTION_INFO_V1(orafce_to_char_float8); PG_FUNCTION_INFO_V1(orafce_to_char_numeric); PG_FUNCTION_INFO_V1(orafce_to_number); PG_FUNCTION_INFO_V1(orafce_to_multi_byte); Datum orafce_to_char_int4(PG_FUNCTION_ARGS) { int32 arg0 = PG_GETARG_INT32(0); StringInfo buf = makeStringInfo(); appendStringInfo(buf, "%d", arg0); PG_RETURN_TEXT_P(cstring_to_text(buf->data)); } Datum orafce_to_char_int8(PG_FUNCTION_ARGS) { int64 arg0 = PG_GETARG_INT64(0); StringInfo buf = makeStringInfo(); appendStringInfo(buf, INT64_FORMAT, arg0); PG_RETURN_TEXT_P(cstring_to_text(buf->data)); } Datum orafce_to_char_float4(PG_FUNCTION_ARGS) { float4 arg0 = PG_GETARG_FLOAT4(0); StringInfo buf = makeStringInfo(); struct lconv *lconv = PGLC_localeconv(); char *p; appendStringInfo(buf, "%f", arg0); for (p = buf->data; *p; p++) if (*p == '.') *p = lconv->decimal_point[0]; PG_RETURN_TEXT_P(cstring_to_text(buf->data)); } Datum orafce_to_char_float8(PG_FUNCTION_ARGS) { float8 arg0 = PG_GETARG_FLOAT8(0); StringInfo buf = makeStringInfo(); struct lconv *lconv = PGLC_localeconv(); char *p; appendStringInfo(buf, "%f", arg0); for (p = buf->data; *p; p++) if (*p == '.') *p = lconv->decimal_point[0]; PG_RETURN_TEXT_P(cstring_to_text(buf->data)); } Datum orafce_to_char_numeric(PG_FUNCTION_ARGS) { Numeric arg0 = PG_GETARG_NUMERIC(0); StringInfo buf = makeStringInfo(); struct lconv *lconv = PGLC_localeconv(); char *p; appendStringInfoString(buf, DatumGetCString(DirectFunctionCall1(numeric_out, NumericGetDatum(arg0)))); for (p = buf->data; *p; p++) if (*p == '.') *p = lconv->decimal_point[0]; PG_RETURN_TEXT_P(cstring_to_text(buf->data)); } Datum orafce_to_number(PG_FUNCTION_ARGS) { text *arg0 = PG_GETARG_TEXT_PP(0); char *buf; struct lconv *lconv = PGLC_localeconv(); Numeric res; char *p; buf = text_to_cstring(arg0); for (p = buf; *p; p++) if (*p == lconv->decimal_point[0] && lconv->decimal_point[0]) *p = '.'; else if (*p == lconv->thousands_sep[0] && lconv->thousands_sep[0]) *p = ','; res = DatumGetNumeric(DirectFunctionCall3(numeric_in, CStringGetDatum(buf), 0, -1)); PG_RETURN_NUMERIC(res); } /* 3 is enough, but it is defined as 4 in backend code. */ #ifndef MAX_CONVERSION_GROWTH #define MAX_CONVERSION_GROWTH 4 #endif /* * Convert a tilde (~) to ... * 1: a full width tilde. (same as JA16EUCTILDE in oracle) * 0: a full width overline. (same as JA16EUC in oracle) */ #define JA_TO_FULL_WIDTH_TILDE 1 static const char * TO_MULTI_BYTE_UTF8[95] = { "\343\200\200", "\357\274\201", "\342\200\235", "\357\274\203", "\357\274\204", "\357\274\205", "\357\274\206", "\342\200\231", "\357\274\210", "\357\274\211", "\357\274\212", "\357\274\213", "\357\274\214", "\357\274\215", "\357\274\216", "\357\274\217", "\357\274\220", "\357\274\221", "\357\274\222", "\357\274\223", "\357\274\224", "\357\274\225", "\357\274\226", "\357\274\227", "\357\274\230", "\357\274\231", "\357\274\232", "\357\274\233", "\357\274\234", "\357\274\235", "\357\274\236", "\357\274\237", "\357\274\240", "\357\274\241", "\357\274\242", "\357\274\243", "\357\274\244", "\357\274\245", "\357\274\246", "\357\274\247", "\357\274\250", "\357\274\251", "\357\274\252", "\357\274\253", "\357\274\254", "\357\274\255", "\357\274\256", "\357\274\257", "\357\274\260", "\357\274\261", "\357\274\262", "\357\274\263", "\357\274\264", "\357\274\265", "\357\274\266", "\357\274\267", "\357\274\270", "\357\274\271", "\357\274\272", "\357\274\273", "\357\277\245", "\357\274\275", "\357\274\276", "\357\274\277", "\342\200\230", "\357\275\201", "\357\275\202", "\357\275\203", "\357\275\204", "\357\275\205", "\357\275\206", "\357\275\207", "\357\275\210", "\357\275\211", "\357\275\212", "\357\275\213", "\357\275\214", "\357\275\215", "\357\275\216", "\357\275\217", "\357\275\220", "\357\275\221", "\357\275\222", "\357\275\223", "\357\275\224", "\357\275\225", "\357\275\226", "\357\275\227", "\357\275\230", "\357\275\231", "\357\275\232", "\357\275\233", "\357\275\234", "\357\275\235", #if JA_TO_FULL_WIDTH_TILDE "\357\275\236" #else "\357\277\243" #endif }; static const char * TO_MULTI_BYTE_EUCJP[95] = { "\241\241", "\241\252", "\241\311", "\241\364", "\241\360", "\241\363", "\241\365", "\241\307", "\241\312", "\241\313", "\241\366", "\241\334", "\241\244", "\241\335", "\241\245", "\241\277", "\243\260", "\243\261", "\243\262", "\243\263", "\243\264", "\243\265", "\243\266", "\243\267", "\243\270", "\243\271", "\241\247", "\241\250", "\241\343", "\241\341", "\241\344", "\241\251", "\241\367", "\243\301", "\243\302", "\243\303", "\243\304", "\243\305", "\243\306", "\243\307", "\243\310", "\243\311", "\243\312", "\243\313", "\243\314", "\243\315", "\243\316", "\243\317", "\243\320", "\243\321", "\243\322", "\243\323", "\243\324", "\243\325", "\243\326", "\243\327", "\243\330", "\243\331", "\243\332", "\241\316", "\241\357", "\241\317", "\241\260", "\241\262", "\241\306", "\243\341", "\243\342", "\243\343", "\243\344", "\243\345", "\243\346", "\243\347", "\243\350", "\243\351", "\243\352", "\243\353", "\243\354", "\243\355", "\243\356", "\243\357", "\243\360", "\243\361", "\243\362", "\243\363", "\243\364", "\243\365", "\243\366", "\243\367", "\243\370", "\243\371", "\243\372", "\241\320", "\241\303", "\241\321", #if JA_TO_FULL_WIDTH_TILDE "\241\301" #else "\241\261" #endif }; Datum orafce_to_multi_byte(PG_FUNCTION_ARGS) { text *src; text *dst; const char *s; char *d; int srclen; int dstlen; int i; const char **map; switch (GetDatabaseEncoding()) { case PG_UTF8: map = TO_MULTI_BYTE_UTF8; break; case PG_EUC_JP: #if PG_VERSION_NUM >= 80300 case PG_EUC_JIS_2004: #endif map = TO_MULTI_BYTE_EUCJP; break; /* * TODO: Add converter for encodings. */ default: /* no need to convert */ PG_RETURN_DATUM(PG_GETARG_DATUM(0)); } src = PG_GETARG_TEXT_PP(0); s = VARDATA_ANY(src); srclen = VARSIZE_ANY_EXHDR(src); dst = (text *) palloc(VARHDRSZ + srclen * MAX_CONVERSION_GROWTH); d = VARDATA(dst); for (i = 0; i < srclen; i++) { unsigned char u = (unsigned char) s[i]; if (0x20 <= u && u <= 0x7e) { const char *m = map[u - 0x20]; while (*m) { *d++ = *m++; } } else { *d++ = s[i]; } } dstlen = d - VARDATA(dst); SET_VARSIZE(dst, VARHDRSZ + dstlen); PG_RETURN_TEXT_P(dst); }