blob: 47ab026dd182d905bf201858baede34db1590caf [file] [log] [blame]
#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);
}