新增TO_NUMBER函数对支持子句和 DEFAULT NULL ON CONVERSION ERROR, fmt子句支持

This commit is contained in:
yueny
2024-10-11 20:55:53 +08:00
parent 8d538a2e12
commit 2551a82b2a
15 changed files with 2140 additions and 68 deletions

View File

@ -12154,13 +12154,17 @@ AddFuncGroup(
AddBuiltinFunc(_0(1847), _1("to_ascii"), _2(2), _3(true), _4(false), _5(to_ascii_encname), _6(25), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 25, 19), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("to_ascii_encname"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("encode text from encoding to ASCII text"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
),
AddFuncGroup(
"to_binary_float", 6,
"to_binary_float", 10,
AddBuiltinFunc(_0(7012), _1("to_binary_float"), _2(3), _3(false), _4(false), _5(to_binary_float_text), _6(700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(4, 25, 25, 16, 16), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("to_binary_float_text"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("convert text to a single precision floating-point number, with default return expr on convert error"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)),
AddBuiltinFunc(_0(7013), _1("to_binary_float"), _2(1), _3(false), _4(false), _5(NULL), _6(700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(SQLlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 25), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("select pg_catalog.to_binary_float($1, ' ', false, false)"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("convert text to a single precision floating-point number"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)),
AddBuiltinFunc(_0(7014), _1("to_binary_float"), _2(3), _3(false), _4(false), _5(to_binary_float_number), _6(700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(4, 701, 701, 16, 16), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("to_binary_float_number"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("convert float8 to a single precision floating-point number, with default return expr on convert error"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)),
AddBuiltinFunc(_0(7015), _1("to_binary_float"), _2(1), _3(false), _4(false), _5(NULL), _6(700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(SQLlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 701), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("select pg_catalog.to_binary_float($1, 0, false, false)"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("convert float8 to a single precision floating-point number"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)),
AddBuiltinFunc(_0(7016), _1("to_binary_float"), _2(3), _3(false), _4(false), _5(NULL), _6(700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(SQLlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(4, 701, 25, 16, 16), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("select pg_catalog.to_binary_float($1, 0, false, false)"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("convert float8 to a single precision floating-point number, with default return expr on convert error"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)),
AddBuiltinFunc(_0(7017), _1("to_binary_float"), _2(3), _3(false), _4(false), _5(to_binary_float_text_number), _6(700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(4, 25, 701, 16, 16), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("to_binary_float_text_number"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("convert text to a single precision floating-point number, with default return expr on convert error"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
AddBuiltinFunc(_0(7017), _1("to_binary_float"), _2(3), _3(false), _4(false), _5(to_binary_float_text_number), _6(700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(4, 25, 701, 16, 16), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("to_binary_float_text_number"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("convert text to a single precision floating-point number, with default return expr on convert error"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)),
AddBuiltinFunc(_0(7018), _1("to_binary_float"), _2(6), _3(false), _4(false), _5(NULL), _6(700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(SQLlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(6, 25, 25, 16, 16, 25, 25), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("select pg_catalog.to_binary_float($1, $2, $3, $4)"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("convert text to a single precision floating-point number, with default return expr on convert error"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)),
AddBuiltinFunc(_0(7019), _1("to_binary_float"), _2(6), _3(false), _4(false), _5(NULL), _6(700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(SQLlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(6, 701, 701, 16, 16, 25, 25), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("select pg_catalog.to_binary_float($1, $2, $3, $4)"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("convert float8 to a single precision floating-point number, with default return expr on convert error"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)),
AddBuiltinFunc(_0(7020), _1("to_binary_float"), _2(6), _3(false), _4(false), _5(NULL), _6(700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(SQLlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(6, 701, 25, 16, 16, 25, 25), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("select pg_catalog.to_binary_float($1, $2, $3, $4)"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("convert float8 to a single precision floating-point number, with default return expr on convert error"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)),
AddBuiltinFunc(_0(7021), _1("to_binary_float"), _2(6), _3(false), _4(false), _5(NULL), _6(700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(SQLlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(6, 25, 701, 16, 16, 25, 25), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("select pg_catalog.to_binary_float($1, $2, $3, $4)"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("convert text to a single precision floating-point number, with default return expr on convert error"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
),
AddFuncGroup(
"to_char", 11,
@ -12191,8 +12195,10 @@ AddFuncGroup(
AddBuiltinFunc(_0(3446), _1("to_json"), _2(1), _3(true), _4(false), _5(to_json), _6(114), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(1, 2283), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("to_json"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(false), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
),
AddFuncGroup(
"to_number", 1,
AddBuiltinFunc(_0(TONUMBERFUNCOID), _1("to_number"), _2(2), _3(true), _4(false), _5(numeric_to_number), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(2, 25, 25), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_to_number"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(true), _32(false), _33("convert text to numeric"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
"to_number", 3,
AddBuiltinFunc(_0(TONUMBERFUNCOID), _1("to_number"), _2(2), _3(true), _4(false), _5(numeric_to_number), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(2, 25, 25), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_to_number"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(true), _32(false), _33("convert text to numeric"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)),
AddBuiltinFunc(_0(5258), _1("to_number"), _2(6), _3(false), _4(false), _5(numeric_to_text_number), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(6, 25, 1700, 16, 16, 25, 25), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_to_text_number"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("convert text to numeric with default return value"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0)),
AddBuiltinFunc(_0(5260), _1("to_number"), _2(6), _3(false), _4(false), _5(numeric_to_default_without_defaultval), _6(1700), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(6, 25, 25, 16, 16, 25, 25), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("numeric_to_default_without_defaultval"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("convert text to numeric without default"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
),
AddFuncGroup(
"to_timestamp", 3,

View File

@ -525,6 +525,7 @@ static char* IdentResolveToChar(char *ident, core_yyscan_t yyscanner);
%type <ival> defacl_privilege_target
%type <defelt> DefACLOption
%type <list> DefACLOptionList
%type <node> opt_default_fmt_clause
%type <list> stmtblock stmtmulti
OptTableElementList TableElementList OptInherit definition tsconf_definition
@ -28772,7 +28773,7 @@ func_application_special: func_name '(' ')'
n->call_func = false;
$$ = (Node *)n;
}
| func_name '(' func_arg_list DEFAULT func_arg_expr ON CONVERSION_P ERROR_P opt_sort_clause ')'
| func_name '(' func_arg_list DEFAULT func_arg_expr ON CONVERSION_P ERROR_P opt_default_fmt_clause ')'
{
if (u_sess->attr.attr_sql.sql_compatibility != A_FORMAT) {
ereport(ERROR,
@ -28781,18 +28782,30 @@ func_application_special: func_name '(' ')'
}
FuncCall *n = makeNode(FuncCall);
n->funcname = $1;
n->args = lappend($3, $5);
n->funcname = $1;
// args:
// input_expr, default_val,
// is DEFAULT gramy, default expr is column ref,
// fmt constraints, nls param constraints
n->args = lappend($3, $5);
// is DEFAULT gramy
n->args = lappend(n->args, makeBoolAConst(TRUE, -1));
// default expr is column ref
n->args = lappend(n->args, makeBoolAConst(IsA($5, ColumnRef), -1));
n->agg_order = $9;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
n->location = @1;
n->call_func = false;
$$ = (Node *) n;
// There may be fmt constraints
n->args = lappend(n->args, $9);
// There may be nls param constraints
n->args = lappend(n->args, makeNullAConst(-1));
n->agg_order = NIL;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
n->func_variadic = FALSE;
n->over = NULL;
n->location = @1;
n->call_func = false;
$$ = (Node *) n;
}
| func_name '(' VARIADIC func_arg_expr opt_sort_clause ')'
{
@ -28880,6 +28893,13 @@ func_application_special: func_name '(' ')'
}
;
opt_default_fmt_clause:
',' a_expr { $$ = $2; }
| /*EMPTY*/ {
$$ = makeNullAConst(-1);
}
;
/*
* Function with SEPARATOR keword arguments;
*/

View File

@ -68,6 +68,7 @@
#include <math.h>
#include <float.h>
#include <limits.h>
#include <cmath>
/*
* towlower() and friends should be in <wctype.h>, but some pre-C99 systems
@ -1823,6 +1824,9 @@ static int from_char_seq_search(int* dest, char** src, char** array, int type, i
*/
static void do_to_timestamp(text* date_txt, text* fmt, struct pg_tm* tm, fsec_t* fsec);
static char* fill_str(char* str, int c, int max);
static Datum to_numeric_number_internal_with_fmt(text* value, text* fmt, bool withDefault, Oid fncollation, bool *err);
static Datum to_numeric_number_internal_without_fmt(text* sourceValue, Oid fncollation, bool *err);
static Datum to_numeric_to_number_internal(text* value, text* fmt, Oid fncollation, bool *resultNull);
static FormatNode* NUM_cache(int len, NUMDesc* Num, text* pars_str, bool* shouldFree);
static char* int_to_roman(int number);
static void NUM_prepare_locale(NUMProc* Np);
@ -6564,78 +6568,312 @@ static char* NUM_processor(FormatNode* node, NUMDesc* Num, char* inout, char* nu
SET_VARSIZE(result, len + VARHDRSZ); \
} while (0)
Datum to_numeric_number_internal_with_fmt(text* sourceValue, text* fmt, bool withDefault,
Oid fncollation, bool *resultNull)
{
Datum result;
// Number description: fmt
NUMDesc numDesc;
FormatNode* format = NULL;
char* sourceNumstr = NULL;
bool shouldFree = false;
int len = 0;
int valuelen = 0;
char* fmtstr = NULL;
unsigned int scale;
unsigned int precision;
len = VARSIZE(fmt) - VARHDRSZ;
if (len <= 0 || len >= INT_MAX / NUM_MAX_ITEM_SIZ) {
*resultNull = true;
return 0;
}
fmtstr = (char*)palloc(len + 1);
errno_t rc = EOK;
// Copy the data part of the fmt value to fmtstr.
rc = strncpy_s(fmtstr, len + 1, VARDATA(fmt), len);
securec_check(rc, "\0", "\0");
fmtstr[len] = '\0';
// When converting a hexadecimal string to a decimal number,
// characters other than 'x' or 'X' are not allowed in the format string.
// otherwise an error will be reported.
if (NULL != strchr(fmtstr, 'x') || NULL != strchr(fmtstr, 'X')) {
int i = 0;
for (i = 0; i < len; i++) {
if ('x' != fmtstr[i] && 'X' != fmtstr[i]) {
pfree_ext(fmtstr);
if (withDefault) {
*resultNull = true;
return 0;
} else {
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid number format model")));
}
}
}
valuelen = VARSIZE(sourceValue) - VARHDRSZ;
if (valuelen > len) {
pfree_ext(fmtstr);
if (withDefault) {
*resultNull = true;
return 0;
} else {
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid number")));
}
}
}
pfree_ext(fmtstr);
format = NUM_cache(len, &numDesc, fmt, &shouldFree);
sourceNumstr = (char*)palloc((len * NUM_MAX_ITEM_SIZ) + 1);
(void)NUM_processor(format,
&numDesc,
VARDATA(sourceValue),
sourceNumstr,
(len * NUM_MAX_ITEM_SIZ) + 1,
VARSIZE(sourceValue) - VARHDRSZ,
0,
false,
fncollation);
scale = (unsigned int)numDesc.post;
precision = Max(0, numDesc.pre) + scale;
if (shouldFree)
pfree_ext(format);
// empty strings
if (*sourceNumstr == '\0' && withDefault) {
pfree_ext(sourceNumstr);
*resultNull = true;
return 0;
}
// into numeric_in func
result = DirectFunctionCall3(numeric_in,
CStringGetDatum(sourceNumstr),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(((precision << 16) | scale) + VARHDRSZ));
pfree_ext(sourceNumstr);
return result;
}
Datum to_numeric_number_internal_without_fmt(text* sourceValue, Oid fncollation, bool *resultNull)
{
Datum result;
char* valueNumstr = NULL;
int valueLen = VARSIZE(sourceValue) - VARHDRSZ;
valueNumstr = (char*)palloc(valueLen + 1);
errno_t value_rc = EOK;
value_rc = strncpy_s(valueNumstr, valueLen + 1, VARDATA(sourceValue), valueLen);
securec_check(value_rc, "\0", "\0");
// empty strings
if (*valueNumstr == '\0') {
pfree_ext(valueNumstr);
*resultNull = true;
return 0;
}
result = DirectFunctionCall3(numeric_in, CStringGetDatum(valueNumstr),
// ObjectIdGetDatum(0),
ObjectIdGetDatum(InvalidOid), Int32GetDatum(-1));
pfree_ext(valueNumstr);
return result;
}
/**
* Common implementation of processing value and fmt
*/
Datum to_numeric_to_number_internal(text* value, text* fmt, Oid fncollation, bool *resultNull)
{
Datum result = to_numeric_number_internal_with_fmt(value, fmt, false, fncollation, resultNull);
return result;
}
/* -------------------
* NUMERIC to_number() (convert string to numeric)
* NUMERIC to_number()(convert string to numeric with fmt)
* -------------------
*/
Datum numeric_to_number(PG_FUNCTION_ARGS)
{
text* value = PG_GETARG_TEXT_P(0);
text* fmt = PG_GETARG_TEXT_P(1);
NUMDesc Num;
// NUMDesc Num;
Datum result;
FormatNode* format = NULL;
char* numstr = NULL;
bool shouldFree = false;
int len = 0;
int valuelen = 0;
char* fmtstr = NULL;
bool resultNull = false;
unsigned int scale;
unsigned int precision;
PG_TRY();
{
result = to_numeric_to_number_internal(value, fmt, PG_GET_COLLATION(), &resultNull);
}
PG_CATCH();
{
char* msg = Geterrmsg();
int errcode = geterrcode();
FlushErrorState();
ereport(ERROR, (errcode, errmsg("%s", msg)));
}
PG_END_TRY();
len = VARSIZE(fmt) - VARHDRSZ;
if (len <= 0 || len >= INT_MAX / NUM_MAX_ITEM_SIZ)
if (resultNull) {
PG_RETURN_NULL();
} else {
return result;
}
}
fmtstr = (char*)palloc(len + 1);
errno_t rc = EOK;
rc = strncpy_s(fmtstr, len + 1, VARDATA(fmt), len);
securec_check(rc, "\0", "\0");
fmtstr[len] = '\0';
if (NULL != strchr(fmtstr, 'x') || NULL != strchr(fmtstr, 'X')) {
int i = 0;
for (i = 0; i < len; i++) {
if ('x' != fmtstr[i] && 'X' != fmtstr[i]) {
pfree_ext(fmtstr);
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid number format model")));
}
}
valuelen = VARSIZE(value) - VARHDRSZ;
if (valuelen > len) {
pfree_ext(fmtstr);
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid number")));
Datum numeric_to_text_number(PG_FUNCTION_ARGS)
{
if (PG_ARGISNULL(0)) {
PG_RETURN_NULL();
}
text* sourceValue = PG_GETARG_TEXT_P(0);
bool defaultNumValIsNull = PG_ARGISNULL(1);
bool withDefault = PG_GETARG_BOOL(2);
bool fmtIsNull = PG_ARGISNULL(4);
text* fmt;
Datum result;
bool resultNull = false;
PG_TRY();
{
if (fmtIsNull) {
result = to_numeric_number_internal_without_fmt(sourceValue,
PG_GET_COLLATION(), &resultNull);
} else {
fmt = PG_GETARG_TEXT_P(4);
result = to_numeric_number_internal_with_fmt(sourceValue, fmt, withDefault,
PG_GET_COLLATION(), &resultNull);
}
}
pfree_ext(fmtstr);
PG_CATCH();
{
if (withDefault) {
FlushErrorState();
format = NUM_cache(len, &Num, fmt, &shouldFree);
if (defaultNumValIsNull) {
resultNull = true;
} else {
Numeric defaultNumVal = PG_GETARG_NUMERIC(1); // 1700
numstr = (char*)palloc((len * NUM_MAX_ITEM_SIZ) + 1);
if (!fmtIsNull) {
// Number description: fmt
NUMDesc numDesc;
bool shouldFree = false;
int len = VARSIZE(fmt) - VARHDRSZ;
FormatNode* format = NUM_cache(len, &numDesc, fmt, &shouldFree);
// Integer digits
unsigned int formatPrecision = Max(0, numDesc.pre);
if (shouldFree)
pfree_ext(format);
(void)NUM_processor(format,
&Num,
VARDATA(value),
numstr,
(len * NUM_MAX_ITEM_SIZ) + 1,
VARSIZE(value) - VARHDRSZ,
0,
false,
PG_GET_COLLATION());
// Calculate the formatPrecision power of 10.
double powerOfMax = pow(10, formatPrecision);
scale = (unsigned int)Num.post;
precision = Max(0, Num.pre) + scale;
// into numeric_float8 func
double defaultValue = (double)DatumGetFloat8(DirectFunctionCall1(numeric_float8,
NumericGetDatum(defaultNumVal)));
if (defaultValue > (powerOfMax - 1)) {
ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("Exceeding the maximum value required by fmt")));
}
}
if (shouldFree)
pfree_ext(format);
result = NumericGetDatum(defaultNumVal);
}
} else {
char* msg = Geterrmsg();
int errcode = geterrcode();
FlushErrorState();
result = DirectFunctionCall3(numeric_in,
CStringGetDatum(numstr),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(((precision << 16) | scale) + VARHDRSZ));
pfree_ext(numstr);
return result;
ereport(ERROR, (errcode, errmsg("%s", msg)));
}
}
PG_END_TRY();
if (resultNull) {
PG_RETURN_NULL();
} else {
return result;
}
}
Datum numeric_to_default_without_defaultval(PG_FUNCTION_ARGS)
{
if (PG_ARGISNULL(0)) {
PG_RETURN_NULL();
}
text* sourceValue = PG_GETARG_TEXT_P(0);
bool defaultNumValIsNull = PG_ARGISNULL(1);
bool withDefault = PG_GETARG_BOOL(2);
bool fmtIsNull = PG_ARGISNULL(4);
text* fmt;
Datum result;
bool resultNull = false;
PG_TRY();
{
if (fmtIsNull) {
result = to_numeric_number_internal_without_fmt(sourceValue,
PG_GET_COLLATION(), &resultNull);
} else {
fmt = PG_GETARG_TEXT_P(4);
result = to_numeric_number_internal_with_fmt(sourceValue, fmt, withDefault,
PG_GET_COLLATION(), &resultNull);
}
}
PG_CATCH();
{
if (withDefault) {
FlushErrorState();
if (defaultNumValIsNull) {
resultNull = true;
} else {
// The value of default value is processed here. Is no longer a conversion process under default, so withDefault is set to true.
withDefault = false;
resultNull = false;
text* default_num_val = PG_GETARG_TEXT_P(1); // 25
if (fmtIsNull) {
result = to_numeric_number_internal_without_fmt(default_num_val,
PG_GET_COLLATION(), &resultNull);
} else {
result = to_numeric_to_number_internal(default_num_val, fmt,
PG_GET_COLLATION(), &resultNull);
}
}
} else {
char* msg = Geterrmsg();
int errcode = geterrcode();
FlushErrorState();
ereport(ERROR, (errcode, errmsg("%s", msg)));
}
}
PG_END_TRY();
if (resultNull) {
PG_RETURN_NULL();
} else {
return result;
}
}
/* ------------------

View File

@ -77,7 +77,7 @@ bool will_shutdown = false;
*
********************************************/
const uint32 GRAND_VERSION_NUM = 93005;
const uint32 GRAND_VERSION_NUM = 93006;
/********************************************
* 2.VERSION NUM FOR EACH FEATURE

View File

@ -11800,6 +11800,7 @@ unreserved_keyword:
| ENDS
| ENUM_P
| EOL
| ERROR_P
| ERRORS
| ESCAPE
| ESCAPED

View File

@ -0,0 +1,12 @@
DROP FUNCTION IF EXISTS pg_catalog.to_number(text, numeric, bool, bool, text, text) CASCADE;
DROP FUNCTION IF EXISTS pg_catalog.to_number(text, text, bool, bool, text, text) CASCADE;
DROP FUNCTION IF EXISTS pg_catalog.to_binary_float(float8, text, bool, bool, text, text) CASCADE;
DROP FUNCTION IF EXISTS pg_catalog.to_binary_float(text, float8, bool, bool, text, text) CASCADE;
DROP FUNCTION IF EXISTS pg_catalog.to_binary_float(float8, float8, bool, bool, text, text) CASCADE;
DROP FUNCTION IF EXISTS pg_catalog.to_binary_float(text, text, bool, bool, text, text) CASCADE;

View File

@ -0,0 +1,12 @@
DROP FUNCTION IF EXISTS pg_catalog.to_number(text, numeric, bool, bool, text, text) CASCADE;
DROP FUNCTION IF EXISTS pg_catalog.to_number(text, text, bool, bool, text, text) CASCADE;
DROP FUNCTION IF EXISTS pg_catalog.to_binary_float(float8, text, bool, bool, text, text) CASCADE;
DROP FUNCTION IF EXISTS pg_catalog.to_binary_float(text, float8, bool, bool, text, text) CASCADE;
DROP FUNCTION IF EXISTS pg_catalog.to_binary_float(float8, float8, bool, bool, text, text) CASCADE;
DROP FUNCTION IF EXISTS pg_catalog.to_binary_float(text, text, bool, bool, text, text) CASCADE;

View File

@ -0,0 +1,66 @@
DROP FUNCTION IF EXISTS pg_catalog.to_number(text, numeric, bool, bool, text, text) CASCADE;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5258;
CREATE FUNCTION pg_catalog.to_number(text, numeric, bool, bool, text, text)
RETURNS INTERVAL
as 'numeric_to_text_number'
LANGUAGE INTERNAL
IMMUTABLE;
COMMENT ON FUNCTION pg_catalog.to_number(text, numeric, bool, bool, text, text) IS 'convert text to numeric with default return value';
DROP FUNCTION IF EXISTS pg_catalog.to_number(text, text, bool, bool, text, text) CASCADE;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5260;
CREATE FUNCTION pg_catalog.to_number(text, text, bool, bool, text, text)
RETURNS INTERVAL
as 'numeric_to_default_without_defaultval'
LANGUAGE INTERNAL
IMMUTABLE;
COMMENT ON FUNCTION pg_catalog.to_number(text, text, bool, bool, text, text) IS 'convert text to numeric without default';
DROP FUNCTION IF EXISTS pg_catalog.to_binary_float(text, text, bool, bool, text, text) CASCADE;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 7018;
CREATE FUNCTION pg_catalog.to_binary_float(text, text, bool, bool, text, text)
RETURNS float4 AS
$$
BEGIN
RETURN (select pg_catalog.to_binary_float($1, $2, $3, $4));
END;
$$
LANGUAGE plpgsql;
COMMENT ON FUNCTION pg_catalog.to_binary_float(text, text, bool, bool, text, text) IS 'convert text to a single precision floating-point number, with default return expr on convert error';
DROP FUNCTION IF EXISTS pg_catalog.to_binary_float(float8, float8, bool, bool text, text) CASCADE;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 7019;
CREATE FUNCTION pg_catalog.to_binary_float(float8, float8, bool, bool text, text)
RETURNS float4 AS
$$
BEGIN
RETURN (select pg_catalog.to_binary_float($1, $2, $3, $4));
END;
$$
LANGUAGE plpgsql;
COMMENT ON FUNCTION pg_catalog.to_binary_float(float8, float8, bool, bool text, text) IS 'convert float8 to a single precision floating-point number, with default return expr on convert error';
DROP FUNCTION IF EXISTS pg_catalog.to_binary_float(float8, text, bool, bool, text, text) CASCADE;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 7020;
CREATE FUNCTION pg_catalog.to_binary_float(float8, text, bool, bool, text, text)
RETURNS float4 AS
$$
BEGIN
RETURN (select pg_catalog.to_binary_float($1, $2, $3, $4));
END;
$$
LANGUAGE plpgsql;
COMMENT ON FUNCTION pg_catalog.to_binary_float(float8, text, bool, bool, text, text) IS 'convert float8 to a single precision floating-point number, with default return expr on convert error';
DROP FUNCTION IF EXISTS pg_catalog.to_binary_float(text, float8, bool, bool, text, text) CASCADE;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 7021;
CREATE FUNCTION pg_catalog.to_binary_float(text, float8, bool, bool, text, text)
RETURNS float4 AS
$$
BEGIN
RETURN (select pg_catalog.to_binary_float($1, $2, $3, $4));
END;
$$
LANGUAGE plpgsql;
COMMENT ON FUNCTION pg_catalog.to_binary_float(text, float8, bool, bool, text, text) IS 'convert text to a single precision floating-point number, with default return expr on convert error';

View File

@ -0,0 +1,66 @@
DROP FUNCTION IF EXISTS pg_catalog.to_number(text, numeric, bool, bool, text, text) CASCADE;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5258;
CREATE FUNCTION pg_catalog.to_number(text, numeric, bool, bool, text, text)
RETURNS INTERVAL
as 'numeric_to_text_number'
LANGUAGE INTERNAL
IMMUTABLE;
COMMENT ON FUNCTION pg_catalog.to_number(text, numeric, bool, bool, text, text) IS 'convert text to numeric with default return value';
DROP FUNCTION IF EXISTS pg_catalog.to_number(text, text, bool, bool, text, text) CASCADE;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 5260;
CREATE FUNCTION pg_catalog.to_number(text, text, bool, bool, text, text)
RETURNS INTERVAL
as 'numeric_to_default_without_defaultval'
LANGUAGE INTERNAL
IMMUTABLE;
COMMENT ON FUNCTION pg_catalog.to_number(text, text, bool, bool, text, text) IS 'convert text to numeric without default';
DROP FUNCTION IF EXISTS pg_catalog.to_binary_float(text, text, bool, bool, text, text) CASCADE;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 7018;
CREATE FUNCTION pg_catalog.to_binary_float(text, text, bool, bool, text, text)
RETURNS float4 AS
$$
BEGIN
RETURN (select pg_catalog.to_binary_float($1, $2, $3, $4));
END;
$$
LANGUAGE plpgsql;
COMMENT ON FUNCTION pg_catalog.to_binary_float(text, text, bool, bool, text, text) IS 'convert text to a single precision floating-point number, with default return expr on convert error';
DROP FUNCTION IF EXISTS pg_catalog.to_binary_float(float8, float8, bool, bool text, text) CASCADE;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 7019;
CREATE FUNCTION pg_catalog.to_binary_float(float8, float8, bool, bool text, text)
RETURNS float4 AS
$$
BEGIN
RETURN (select pg_catalog.to_binary_float($1, $2, $3, $4));
END;
$$
LANGUAGE plpgsql;
COMMENT ON FUNCTION pg_catalog.to_binary_float(float8, float8, bool, bool text, text) IS 'convert float8 to a single precision floating-point number, with default return expr on convert error';
DROP FUNCTION IF EXISTS pg_catalog.to_binary_float(float8, text, bool, bool, text, text) CASCADE;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 7020;
CREATE FUNCTION pg_catalog.to_binary_float(float8, text, bool, bool, text, text)
RETURNS float4 AS
$$
BEGIN
RETURN (select pg_catalog.to_binary_float($1, $2, $3, $4));
END;
$$
LANGUAGE plpgsql;
COMMENT ON FUNCTION pg_catalog.to_binary_float(float8, text, bool, bool, text, text) IS 'convert float8 to a single precision floating-point number, with default return expr on convert error';
DROP FUNCTION IF EXISTS pg_catalog.to_binary_float(text, float8, bool, bool, text, text) CASCADE;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 7021;
CREATE FUNCTION pg_catalog.to_binary_float(text, float8, bool, bool, text, text)
RETURNS float4 AS
$$
BEGIN
RETURN (select pg_catalog.to_binary_float($1, $2, $3, $4));
END;
$$
LANGUAGE plpgsql;
COMMENT ON FUNCTION pg_catalog.to_binary_float(text, float8, bool, bool, text, text) IS 'convert text to a single precision floating-point number, with default return expr on convert error';

View File

@ -96,6 +96,8 @@ extern Datum interval_to_char(PG_FUNCTION_ARGS);
extern Datum to_timestamp(PG_FUNCTION_ARGS);
extern Datum to_date(PG_FUNCTION_ARGS);
extern Datum numeric_to_number(PG_FUNCTION_ARGS);
extern Datum numeric_to_text_number(PG_FUNCTION_ARGS);
extern Datum numeric_to_default_without_defaultval(PG_FUNCTION_ARGS);
extern Datum numeric_to_char(PG_FUNCTION_ARGS);
extern Datum int4_to_char(PG_FUNCTION_ARGS);
extern Datum int8_to_char(PG_FUNCTION_ARGS);

View File

@ -446,6 +446,8 @@ SELECT TO_BINARY_FLOAT(' 6.66 ' DEFAULT 3.14 ON CONVERSION ERROR);
SELECT TO_BINARY_FLOAT('today' DEFAULT 'roll' ON CONVERSION ERROR); -- error
ERROR: invalid input syntax for type real
CONTEXT: referenced column: to_binary_float
SQL function "to_binary_float" statement 1
referenced column: to_binary_float
SELECT TO_BINARY_FLOAT(3.402E+100);
to_binary_float
-----------------

File diff suppressed because it is too large Load Diff

View File

@ -1136,3 +1136,6 @@ test: on_update_session1 on_update_session2
test: ts_gb18030_utf8
test: backup_tool_audit
# to_number func
test: to_number_default

View File

@ -193,4 +193,7 @@ test: user_host_test
# test for new_expr_by_flatten
test: enable_expr_fusion_flatten
# to_number func
test: to_number_default

View File

@ -0,0 +1,286 @@
-- For function TO_NUMBER
-- create new schema
drop schema if exists func_to_number;
create schema func_to_number;
set search_path=func_to_number;
CREATE TABLE tonumber (c1 int, c2 float4, c3 float8, c4 char(50), c5 varchar(50), c6 text);
INSERT INTO tonumber VALUES (1, 1.23, 1.23, '1.23', '1.23', '1.23');
INSERT INTO tonumber VALUES (2, 3.141567, 3.141567, '3.141567', '3.141567', '3.141567');
INSERT INTO tonumber VALUES (3, 202405291733, 202405291733, '202405291733', '202405291733', '3.141567');
INSERT INTO tonumber VALUES (4, NULL, NULL, NULL, NULL, NULL);
INSERT INTO tonumber VALUES (5, NULL, NULL, 'tonight', '12.34yesterday', 'sunday6.66');
INSERT INTO tonumber VALUES (6, CAST('NAN' as float4), CAST('NAN' as float8), 'nan', 'NAN', 'NaN');
INSERT INTO tonumber VALUES (7, 3.40282E+38, 1.79769313486231E+100, '3.40282E+38F', '3.40282E+38', '1.79769313486231E+308');
SELECT c1, c2, TO_NUMBER(c2) FROM tonumber ORDER BY c1;
SELECT c1, c3, TO_NUMBER(c3) FROM tonumber ORDER BY c1;
SELECT c1, c4, TO_NUMBER(c4) FROM tonumber WHERE c1 NOT IN (5, 7) ORDER BY c1;
SELECT c1, c4, TO_NUMBER(c4) FROM tonumber WHERE c1 = 5 ORDER BY c1; -- error: invalid input syntax for type numeric: "tonight"
SELECT c1, c4, TO_NUMBER(c4) FROM tonumber WHERE c1 = 7 ORDER BY c1; -- error: invalid input syntax for type numeric: "3.40282E+38F"
SELECT c1, c5, TO_NUMBER(c5) FROM tonumber WHERE c1 NOT IN (5) ORDER BY c1;
SELECT c1, c5, TO_NUMBER(c5) FROM tonumber WHERE c1 = 5 ORDER BY c1; -- error: invalid input syntax for type numeric: "12.34yesterday"
SELECT c1, c6, TO_NUMBER(c6) FROM tonumber WHERE c1 NOT IN (5) ORDER BY c1;
SELECT c1, c6, TO_NUMBER(c6) FROM tonumber WHERE c1 = 7 ORDER BY c1;
SELECT c1, c6, TO_NUMBER(c6) FROM tonumber WHERE c1 = 5 ORDER BY c1; -- error: invalid input syntax for type numeric: "sunday6.66"
select TO_NUMBER('2.00');;
select TO_NUMBER('2.11');
select TO_NUMBER('200');
select TO_NUMBER('2a.ab'); -- error: invalid input syntax for type numeric: "2a.ab"
select TO_NUMBER('a.ab'); -- error: invalid input syntax for type numeric: "a.ab"
select TO_NUMBER('1A3E'); -- error: invalid input syntax for type numeric: "1A3E"
select TO_NUMBER(2.11);
SELECT TO_NUMBER(1.79769313486231E+100);
SELECT TO_NUMBER(2.22507485850720E-100);
SELECT TO_NUMBER(1.79769313486231E+255);
SELECT TO_NUMBER(1.79769313486231E+300);
SELECT TO_NUMBER(1.79769313486231E+308);
SELECT TO_NUMBER(1.79769313486231E+309);
SELECT TO_NUMBER(1.79769313486231E+310);
SELECT TO_NUMBER(1.79769313486231E+6310); -- error: overflow. invalid input syntax for type numeric: "1.79769313486231E+6310"
SELECT TO_NUMBER('1.79769313486231E+100');
SELECT TO_NUMBER('2.22507485850720E-100');
SELECT TO_NUMBER('1.79769313486231E+310');
SELECT TO_NUMBER(1.79769313486231E+6310); -- error: overflow. invalid input syntax for type numeric: "1.79769313486231E+6310"
SELECT TO_NUMBER('1.79769313486231E+100');
SELECT TO_NUMBER('2.22507485850720E-100');
SELECT TO_NUMBER('1.79769313486231E+310');
-- with default
SELECT TO_NUMBER(c1 DEFAULT 3.14 ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c1 DEFAULT '3.14' ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c1 DEFAULT '3.14FDW' ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c1 DEFAULT NULL ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER('abd' DEFAULT c1 ON CONVERSION ERROR) FROM tonumber ORDER By c1; -- error, Default param can't be ColumnRef
SELECT TO_NUMBER(3.14 DEFAULT c1 ON CONVERSION ERROR) FROM tonumber ORDER By c1; -- error, Default param can't be ColumnRef
SELECT TO_NUMBER(c2 DEFAULT 3.14 ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c2 DEFAULT '3.14' ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c2 DEFAULT '3.14FDW' ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c2 DEFAULT NULL ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c3 DEFAULT 3.14 ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c3 DEFAULT '3.14' ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c3 DEFAULT '3.14FDW' ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c3 DEFAULT NULL ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT c1, TO_NUMBER(c4 DEFAULT 3.14 ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT c1, TO_NUMBER(c4 DEFAULT '3.14' ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT c1, TO_NUMBER(c4 DEFAULT '3.14FDW' ON CONVERSION ERROR) FROM tonumber WHERE c1 NOT IN (5, 7) ORDER By c1;
SELECT c1, TO_NUMBER(c4 DEFAULT '3.14FDW' ON CONVERSION ERROR) FROM tonumber where c1 = 7 ORDER By c1; -- erro: invalid input syntax for type numeric: "3.14FDW"
SELECT c1, TO_NUMBER(c4 DEFAULT '3.14FDW' ON CONVERSION ERROR) FROM tonumber where c1 = 5 ORDER By c1; -- error: invalid input syntax for type numeric: "3.14FDW"
SELECT c1, TO_NUMBER(c4 DEFAULT NULL ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c5 DEFAULT 3.14 ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c5 DEFAULT '3.14' ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c5 DEFAULT '3.14FDW' ON CONVERSION ERROR) FROM tonumber ORDER By c1; -- error: invalid input syntax for type numeric: "3.14FDW"
SELECT TO_NUMBER(c5 DEFAULT NULL ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c6 DEFAULT 3.14 ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c6 DEFAULT '3.14' ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c6 DEFAULT '3.14FDW' ON CONVERSION ERROR) FROM tonumber ORDER By c1; -- error: invalid input syntax for type numeric: "3.14FDW"
SELECT TO_NUMBER(c6 DEFAULT NULL ON CONVERSION ERROR) FROM tonumber ORDER By c1;
SELECT TO_NUMBER(3.145 DEFAULT 'tomorrow' ON CONVERSION ERROR);
SELECT TO_NUMBER('today' DEFAULT 3.14 ON CONVERSION ERROR);
SELECT TO_NUMBER('today' DEFAULT '3.14' ON CONVERSION ERROR);
SELECT TO_NUMBER('3.15today' DEFAULT 3.14 ON CONVERSION ERROR);
SELECT TO_NUMBER(' 6.66 ' DEFAULT 3.14 ON CONVERSION ERROR);
SELECT TO_NUMBER('today' DEFAULT 'roll' ON CONVERSION ERROR); -- error: invalid input syntax for type numeric: "roll"
select TO_NUMBER('1A3F' DEFAULT 199 ON CONVERSION ERROR, 'XXXX');
select TO_NUMBER('1A3E' DEFAULT 199 ON CONVERSION ERROR, 'XXXX');
-- with fmt
SELECT TO_NUMBER(1.79769313486231E+100, '9G999D99'); -- error: overflow. numeric field overflow
SELECT TO_NUMBER(2.22507485850720E-100, '9G999D99');
select TO_NUMBER('100.00', '9G999D99');
select TO_NUMBER('100.1212', '9G999D99');
select TO_NUMBER('2a.ab', '9G999D99');
select TO_NUMBER('', '9G999D99');
select TO_NUMBER(' ', '9G999D99'); -- error: invalid input syntax for type numeric: " "
select TO_NUMBER('a.ab', '9G999D99'); -- error: invalid input syntax for type numeric: " "
select TO_NUMBER(2.11, '9G999D99');
select TO_NUMBER(25.123456, '9G999D99');
select TO_NUMBER(100.1212, '9G999D99');
/*
* TO_NUMBER XXXX
*/
select TO_NUMBER('1A3F', 'XXXX');
select TO_NUMBER('1A3E', 'XXXX');
select TO_NUMBER('1A3E', 'XAXX');
select TO_NUMBER(null,'XXXX');
select TO_NUMBER('127.532','XXXX');
select TO_NUMBER('1234567890abcdefABCDEF','XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
--to_number only support 16 bytes hex to decimal conversion or plen less than 0
select TO_NUMBER('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF','XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
select TO_NUMBER('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF','xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
select TO_NUMBER('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF','XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
create table TONUM_001(COL_NUM numeric);
insert into TONUM_001 values(TO_NUMBER('A0', 'X'));
insert into TONUM_001 values(TO_NUMBER('A0', 'XX'));
insert into TONUM_001 values(TO_NUMBER('A0', 'XXX'));
select COL_NUM as RESULT from TONUM_001;
drop table TONUM_001;
select TO_NUMBER('-ABF1','-xxxx');
select TO_NUMBER('AA','XXXZ');
select TO_NUMBER('-AA','-XX');
select TO_NUMBER('AA','-XX');
select TO_NUMBER('-AA','XX');
select TO_NUMBER('+AA','XX');
select TO_NUMBER('+AA','XX');
select TO_NUMBER('AA','X');
select TO_NUMBER('aa','x');
select TO_NUMBER('AA.A','XXX.X');
select TO_NUMBER('A0','XX X');
select TO_NUMBER('A0','XX.X');
select TO_NUMBER('A0','+xxx');
select TO_NUMBER('A0','-xxx');
SELECT TO_NUMBER('-34,338,492', '99G999G999');
SELECT TO_NUMBER('-34,338,492.654,878', '99G999G999D999G999');
SELECT TO_NUMBER('<564646.654564>', '999999.999999PR');
SELECT TO_NUMBER('0.00001-', '9.999999S');
SELECT TO_NUMBER('5.01-', 'FM9.999999S');
SELECT TO_NUMBER('5.01-', 'FM9.999999MI');
SELECT TO_NUMBER('5 4 4 4 4 8 . 7 8', '9 9 9 9 9 9 . 9 9');
SELECT TO_NUMBER('.01', 'FM9.99');
SELECT TO_NUMBER('.0', '99999999.99999999');
SELECT TO_NUMBER('0', '99.99');
SELECT TO_NUMBER('.-01', 'S99.99');
SELECT TO_NUMBER('.01-', '99.99S');
SELECT TO_NUMBER(' . 0 1-', ' 9 9 . 9 9 S');
-- with default and fmt
SELECT TO_NUMBER(c1 DEFAULT 3.14 ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c1 DEFAULT '3.14' ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c1 DEFAULT '3.14FDW' ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c1 DEFAULT NULL ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER('abd' DEFAULT c1 ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1; -- error, Default param can't be ColumnRef
SELECT TO_NUMBER(3.14 DEFAULT c1 ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1; -- error, Default param can't be ColumnRef
SELECT TO_NUMBER(c2 DEFAULT 3.14 ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c2 DEFAULT '3.14' ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c2 DEFAULT '3.14FDW' ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c2 DEFAULT NULL ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c3 DEFAULT 3.14 ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c3 DEFAULT '3.14' ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c3 DEFAULT '3.14FDW' ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c3 DEFAULT NULL ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT c1, TO_NUMBER(c4 DEFAULT 3.14 ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT c1, TO_NUMBER(c4 DEFAULT '3.14' ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT c1, TO_NUMBER(c4 DEFAULT '3.14FDW' ON CONVERSION ERROR, '99D999') FROM tonumber WHERE c1 NOT IN (5, 7) ORDER By c1;
SELECT c1, TO_NUMBER(c4 DEFAULT '3.14FDW' ON CONVERSION ERROR, '99D999') FROM tonumber where c1 = 7 ORDER By c1;
SELECT c1, TO_NUMBER(c4 DEFAULT '3.14FDW' ON CONVERSION ERROR, '99D999') FROM tonumber where c1 = 5 ORDER By c1;
SELECT c1, TO_NUMBER(c4 DEFAULT NULL ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c5 DEFAULT 3.14 ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c5 DEFAULT '3.14' ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c5 DEFAULT '3.14FDW' ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c5 DEFAULT NULL ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c6 DEFAULT 3.14 ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c6 DEFAULT '3.14' ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c6 DEFAULT '3.14FDW' ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(c6 DEFAULT NULL ON CONVERSION ERROR, '99D999') FROM tonumber ORDER By c1;
SELECT TO_NUMBER(3.145 DEFAULT 'tomorrow' ON CONVERSION ERROR, '99D999');
SELECT TO_NUMBER('today' DEFAULT 3.14 ON CONVERSION ERROR, '99D999');
SELECT TO_NUMBER('today' DEFAULT '3.14' ON CONVERSION ERROR, '99D999');
SELECT TO_NUMBER('3.15today' DEFAULT 3.14 ON CONVERSION ERROR, '99D999');
SELECT TO_NUMBER(' 6.66 ' DEFAULT 3.14 ON CONVERSION ERROR, '99D999');
SELECT TO_NUMBER('today' DEFAULT 'roll' ON CONVERSION ERROR, '99D999'); -- error: invalid input syntax for type numeric: "roll"
-- test overflow and null
SELECT TO_NUMBER(1.79769313486231E+100 DEFAULT 3.14 ON CONVERSION ERROR);
SELECT TO_NUMBER(2.22507485850720E-100 DEFAULT 3.14 ON CONVERSION ERROR);
SELECT TO_NUMBER('1.79769313486231E+100' DEFAULT 3.14 ON CONVERSION ERROR);
SELECT TO_NUMBER('2.22507485850720E-100' DEFAULT 3.14 ON CONVERSION ERROR);
SELECT TO_NUMBER(1.79769313486231E+310 DEFAULT 3.14 ON CONVERSION ERROR);
SELECT TO_NUMBER('1.79769313486231E+310' DEFAULT 3.14 ON CONVERSION ERROR);
SELECT TO_NUMBER(3.14 DEFAULT 1.79769313486231E+100 ON CONVERSION ERROR);
SELECT TO_NUMBER(3.14 DEFAULT '1.79769313486231E+100' ON CONVERSION ERROR);
SELECT TO_NUMBER(3.14 DEFAULT 1.79769313486231E+310 ON CONVERSION ERROR);
SELECT TO_NUMBER(3.14 DEFAULT '1.79769313486231E+310' ON CONVERSION ERROR);
SELECT TO_NUMBER('today' DEFAULT 1.79769313486231E+310 ON CONVERSION ERROR);
SELECT TO_NUMBER('today' DEFAULT '1.79769313486231E+310' ON CONVERSION ERROR);
SELECT TO_NUMBER(1.79769313486231E+100 DEFAULT NULL ON CONVERSION ERROR);
SELECT TO_NUMBER('1.79769313486231E+100' DEFAULT NULL ON CONVERSION ERROR);
SELECT TO_NUMBER(1.79769313486231E+310 DEFAULT NULL ON CONVERSION ERROR);
SELECT TO_NUMBER('1.79769313486231E+310' DEFAULT NULL ON CONVERSION ERROR);
SELECT TO_NUMBER(NULL DEFAULT 1.79769313486231E+100 ON CONVERSION ERROR);
SELECT TO_NUMBER(NULL DEFAULT '1.79769313486231E+100' ON CONVERSION ERROR);
SELECT TO_NUMBER(NULL DEFAULT 1.79769313486231E+310 ON CONVERSION ERROR);
SELECT TO_NUMBER(NULL DEFAULT '1.79769313486231E+310' ON CONVERSION ERROR);
CREATE TABLE tonumber_exec (c1 int, func_info text, res float4);
PREPARE default_param_text2(int, text, text) AS
INSERT INTO tonumber_exec VALUES ($1, CONCAT('TO_NUMBER(', $2, ' DEFAULT ', $3, ' ON CONVERSION ERROR)'), TO_NUMBER($2 DEFAULT $3 ON CONVERSION ERROR));
EXECUTE default_param_text2(1, '3.14', '6.66');
EXECUTE default_param_text2(2, '3.14#', '6.66');
EXECUTE default_param_text2(3, '#3.14', '6.66#'); -- error: invalid input syntax for type numeric: "6.66#"
EXECUTE default_param_text2(4, ' -3.14 ', '6.66');
EXECUTE default_param_text2(5, NULL, '6.66');
EXECUTE default_param_text2(6, '6.66', NULL);
EXECUTE default_param_text2(7, '1.79769313486231E+100', NULL); -- error: value out of range: overflow
EXECUTE default_param_text2(8, NULL, '1.79769313486231E+100');
EXECUTE default_param_text2(9, '1.79769313486231E+400', NULL); -- error: '1.79769313486231E+400' is out of range for type real
EXECUTE default_param_text2(10, NULL, '1.79769313486231E+400');
PREPARE default_param_num2(int, float8, float8) AS
INSERT INTO tonumber_exec VALUES ($1, CONCAT('TO_NUMBER(', $2, ' DEFAULT ', $3, ' ON CONVERSION ERROR)'), TO_NUMBER($2 DEFAULT $3 ON CONVERSION ERROR));
EXECUTE default_param_num2(11, 3.14, 6.666666);
EXECUTE default_param_num2(12, 3.14, NULL);
EXECUTE default_param_num2(13, NULL, 3.14);
EXECUTE default_param_text2(14, 1.79769313486231E+100, 3.14); -- error: value out of range: overflow
EXECUTE default_param_text2(15, 3.14, 1.79769313486231E+100);
EXECUTE default_param_text2(16, 1.79769313486231E+400, 3.14); -- error: is out of range for type real
EXECUTE default_param_text2(17, 3.14, 1.79769313486231E+400);
EXECUTE default_param_text2(18, 1.79769313486231E+400, NULL); -- error: is out of range for type real
EXECUTE default_param_text2(19, NULL, 1.79769313486231E+400);
PREPARE default_param_text_num(int, text, float8) AS
INSERT INTO tonumber_exec VALUES ($1, CONCAT('TO_NUMBER(', $2, ' DEFAULT ', $3, ' ON CONVERSION ERROR)'), TO_NUMBER($2 DEFAULT $3 ON CONVERSION ERROR));
EXECUTE default_param_text_num(20, '3.14', 6.666666);
EXECUTE default_param_text_num(21, ' +3.14 ', 6.666666);
EXECUTE default_param_text_num(22, '1.79769313486231E+100', 6.666666); -- error: value out of range: overflow
EXECUTE default_param_text_num(23, '6.666666', 1.79769313486231E+100);
EXECUTE default_param_text_num(24, '1.79769313486231E+400', 6.666666); -- error: is out of range for type real
EXECUTE default_param_text_num(25, '6.666666', 1.79769313486231E+400); -- error: is out of range for type double precision
PREPARE default_param_num_text(int, float8, text) AS
INSERT INTO tonumber_exec VALUES ($1, CONCAT('TO_NUMBER(', $2, ' DEFAULT ', $3, ' ON CONVERSION ERROR)'), TO_NUMBER($2 DEFAULT $3 ON CONVERSION ERROR));
EXECUTE default_param_num_text(26, 1.79769313486231E+100, '6.666666');
EXECUTE default_param_num_text(27, 6.666666, '1.79769313486231E+100');
EXECUTE default_param_num_text(28, 1.79769313486231E+400, '6.666666');
EXECUTE default_param_num_text(29, 6.666666, '1.79769313486231E+400');
SELECT * FROM tonumber_exec ORDER BY c1;
DROP TABLE tonumber;
DROP TABLE tonumber_exec;
drop schema if exists func_to_number cascade;