From 948d8b90831526415f18bc8bed943114cbe5ff9e Mon Sep 17 00:00:00 2001 From: Nirmit Shah <44708230+shah-nirmit@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:53:56 +0530 Subject: [PATCH] Fix leading whitespace in convert function (#3543) There was a whitespace difference between tsql and babelfish for cast and convert function when converting from float to varchar/char , this was mainly due to the to_char function which added a leading space before the data, explicitly added ltrim function call on the final result before padding to fix the issue. Issues Resolved BABEL-5459 Signed-off-by: Nirmit Shah nirmisha@amazon.com --- contrib/babelfishpg_common/src/varchar.c | 21 +++--- .../sql/sys_function_helpers.sql | 4 +- .../babelfishpg_tsql--5.1.0--5.2.0.sql | 73 +++++++++++++++++++ test/JDBC/expected/BABEL-1193.out | 6 +- test/JDBC/expected/babel_function.out | 8 +- .../chinese_prc_ci_as/babel_function.out | 8 +- ...t_conv_float_to_varchar_char-vu-verify.out | 54 +++++++------- ..._to_varchar_char_before_17_4-vu-verify.out | 52 ++++++------- 8 files changed, 148 insertions(+), 78 deletions(-) diff --git a/contrib/babelfishpg_common/src/varchar.c b/contrib/babelfishpg_common/src/varchar.c index 0827e2205d9..ab73e1f7b3e 100644 --- a/contrib/babelfishpg_common/src/varchar.c +++ b/contrib/babelfishpg_common/src/varchar.c @@ -1248,7 +1248,7 @@ float82bpchar(PG_FUNCTION_ARGS) /* 32 length as double_to_shortest_decimal_buf always returns string with length less that 30*/ char *ascii = (char *) palloc0(32); char *buf_padded; - int str_len = -1; + int str_len; /* Handle special cases */ if (unlikely(isinf(num)|| isnan(num))) @@ -1265,21 +1265,18 @@ float82bpchar(PG_FUNCTION_ARGS) double_to_shortest_decimal_buf(num, ascii); /* Check if the number fits within the specified length */ - if (maxlen > 0) + str_len = strlen(ascii); + if (str_len > maxlen) { - str_len = strlen(ascii); - if (str_len > maxlen) - { - ereport(ERROR, - (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION), - errmsg("There is insufficient result space to convert a float value to char/nchar."))); - } + ereport(ERROR, + (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION), + errmsg("There is insufficient result space to convert a float value to char/nchar."))); } - /* Left pad float value with the spaces */ + /* Right pad float value with the spaces */ buf_padded = (char *) palloc0(maxlen + 1); - memset(buf_padded, ' ', maxlen - str_len); - memcpy(buf_padded + maxlen - str_len, ascii, str_len); + memcpy(buf_padded, ascii, str_len); + memset(buf_padded + str_len, ' ', maxlen - str_len); res = DirectFunctionCall3(bpcharin, CStringGetDatum(buf_padded), diff --git a/contrib/babelfishpg_tsql/sql/sys_function_helpers.sql b/contrib/babelfishpg_tsql/sql/sys_function_helpers.sql index 514e113a682..4a61d71c56b 100644 --- a/contrib/babelfishpg_tsql/sql/sys_function_helpers.sql +++ b/contrib/babelfishpg_tsql/sql/sys_function_helpers.sql @@ -11004,9 +11004,9 @@ BEGIN v_res_length := substring(p_datatype COLLATE "C", MASK_REGEXP)::SMALLINT; IF v_res_length IS NULL THEN - RETURN v_result; + RETURN ltrim(v_result); ELSE - RETURN rpad(v_result, v_res_length, ' '); + RETURN rpad(ltrim(v_result), v_res_length, ' '); END IF; EXCEPTION WHEN invalid_parameter_value THEN diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--5.1.0--5.2.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--5.1.0--5.2.0.sql index fb578636653..91d09f8eead 100644 --- a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--5.1.0--5.2.0.sql +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--5.1.0--5.2.0.sql @@ -450,6 +450,79 @@ BEGIN END; $$; +CREATE OR REPLACE FUNCTION sys.babelfish_try_conv_float_to_string(IN p_datatype TEXT, + IN p_floatval FLOAT, + IN p_style NUMERIC DEFAULT 0) +RETURNS TEXT +AS +$BODY$ +DECLARE + v_style SMALLINT; + v_format VARCHAR COLLATE "C"; + v_floatval NUMERIC := abs(p_floatval); + v_digits SMALLINT; + v_integral_digits SMALLINT; + v_decimal_digits SMALLINT; + v_sign SMALLINT := sign(p_floatval); + v_result TEXT; + v_res_length SMALLINT; + MASK_REGEXP CONSTANT VARCHAR COLLATE "C" := '^\s*(?:character varying)\s*\(\s*(\d+|MAX)\s*\)\s*$'; +BEGIN + v_style := floor(p_style)::SMALLINT; + IF (v_style = 0) THEN + v_digits := length(v_floatval::NUMERIC::TEXT); + v_decimal_digits := scale(v_floatval); + IF (v_decimal_digits > 0) THEN + v_integral_digits := v_digits - v_decimal_digits - 1; + ELSE + v_integral_digits := v_digits; + END IF; + IF (v_floatval >= 999999.5) THEN + v_format := '9D99999EEEE'; + v_result := to_char(v_sign::NUMERIC * ceiling(v_floatval), v_format); + v_result := to_char(substring(v_result, 1, 8)::NUMERIC, 'FM9D99999')::NUMERIC::TEXT || substring(v_result, 9); + ELSE + IF (6 - v_integral_digits < v_decimal_digits) AND (trunc(abs(v_floatval)) != 0) THEN + v_decimal_digits := 6 - v_integral_digits; + ELSIF (6 - v_integral_digits < v_decimal_digits) THEN + v_decimal_digits := 6; + END IF; + v_format := (pow(10, v_integral_digits)-10)::TEXT || 'D'; + IF (v_decimal_digits > 0) THEN + v_format := v_format || (pow(10, v_decimal_digits)-1)::TEXT; + END IF; + v_result := to_char(p_floatval, v_format); + END IF; + ELSIF (v_style = 1) THEN + v_format := '9D9999999EEEE'; + v_result := to_char(p_floatval, v_format); + ELSIF (v_style = 2) THEN + v_format := '9D999999999999999EEEE'; + v_result := to_char(p_floatval, v_format); + ELSIF (v_style = 3) THEN + v_format := '9D9999999999999999EEEE'; + v_result := to_char(p_floatval, v_format); + ELSE + RAISE invalid_parameter_value; + END IF; + + v_res_length := substring(p_datatype COLLATE "C", MASK_REGEXP)::SMALLINT; + IF v_res_length IS NULL THEN + RETURN ltrim(v_result); + ELSE + RETURN rpad(ltrim(v_result), v_res_length, ' '); + END IF; +EXCEPTION + WHEN invalid_parameter_value THEN + RAISE USING MESSAGE := pg_catalog.format('%s is not a valid style number when converting from FLOAT to a character string.', v_style), + DETAIL := 'Use of incorrect "style" parameter value during conversion process.', + HINT := 'Change "style" parameter to the proper value and try again.'; +END; +$BODY$ +LANGUAGE plpgsql +STABLE +RETURNS NULL ON NULL INPUT; + -- After upgrade, always run analyze for all babelfish catalogs. CALL sys.analyze_babelfish_catalogs(); -- Reset search_path to not affect any subsequent scripts diff --git a/test/JDBC/expected/BABEL-1193.out b/test/JDBC/expected/BABEL-1193.out index a81750592a9..5f992ada809 100644 --- a/test/JDBC/expected/BABEL-1193.out +++ b/test/JDBC/expected/BABEL-1193.out @@ -237,9 +237,9 @@ SELECT * FROM t15; GO ~~START~~ char#!#char#!#char#!#char#!#char#!#char#!#char#!#char -12 #!#4553 #!#123456 #!#12.345 #!# 2344.456#!#12.34 #!# 456.33#!# 1123.68 --12 #!#-1234 #!#-123456 #!#-12.345 #!# -2344.456#!#12.34 #!# -456.33#!# -1123.68 -0 #!#0 #!#0 #!#0 #!# 0#!#0.00 #!# 0.00#!# 0.00 +12 #!#4553 #!#123456 #!#12.345 #!#2344.456 #!#12.34 #!# 456.33#!# 1123.68 +-12 #!#-1234 #!#-123456 #!#-12.345 #!#-2344.456 #!#12.34 #!# -456.33#!# -1123.68 +0 #!#0 #!#0 #!#0 #!#0 #!#0.00 #!# 0.00#!# 0.00 ~~END~~ diff --git a/test/JDBC/expected/babel_function.out b/test/JDBC/expected/babel_function.out index 0d2e6398ee3..bf5a3334142 100644 --- a/test/JDBC/expected/babel_function.out +++ b/test/JDBC/expected/babel_function.out @@ -165,21 +165,21 @@ select CONVERT(varchar(30), CAST(11234561231231.234 AS float), 1); GO ~~START~~ varchar - 1.1234561e+13 +1.1234561e+13 ~~END~~ select CONVERT(varchar(30), CAST(11234561231231.234 AS float), 2); GO ~~START~~ varchar - 1.123456123123123e+13 +1.123456123123123e+13 ~~END~~ select CONVERT(varchar(30), CAST(11234561231231.234 AS float), 3); GO ~~START~~ varchar - 1.1234561231231234e+13 +1.1234561231231234e+13 ~~END~~ @@ -304,7 +304,7 @@ select TRY_CONVERT(varchar(30), CAST('11234561231231.234'AS float), 1); GO ~~START~~ varchar - 1.1234561e+13 +1.1234561e+13 ~~END~~ select TRY_CONVERT(varchar(10), CAST(4936.56 AS MONEY), 0); diff --git a/test/JDBC/expected/non_default_server_collation/chinese_prc_ci_as/babel_function.out b/test/JDBC/expected/non_default_server_collation/chinese_prc_ci_as/babel_function.out index cd3b7fd394c..b515a422a1d 100644 --- a/test/JDBC/expected/non_default_server_collation/chinese_prc_ci_as/babel_function.out +++ b/test/JDBC/expected/non_default_server_collation/chinese_prc_ci_as/babel_function.out @@ -165,21 +165,21 @@ select CONVERT(varchar(30), CAST(11234561231231.234 AS float), 1); GO ~~START~~ varchar - 1.1234561e+13 +1.1234561e+13 ~~END~~ select CONVERT(varchar(30), CAST(11234561231231.234 AS float), 2); GO ~~START~~ varchar - 1.123456123123123e+13 +1.123456123123123e+13 ~~END~~ select CONVERT(varchar(30), CAST(11234561231231.234 AS float), 3); GO ~~START~~ varchar - 1.1234561231231234e+13 +1.1234561231231234e+13 ~~END~~ @@ -304,7 +304,7 @@ select TRY_CONVERT(varchar(30), CAST('11234561231231.234'AS float), 1); GO ~~START~~ varchar - 1.1234561e+13 +1.1234561e+13 ~~END~~ select TRY_CONVERT(varchar(10), CAST(4936.56 AS MONEY), 0); diff --git a/test/JDBC/expected/test_conv_float_to_varchar_char-vu-verify.out b/test/JDBC/expected/test_conv_float_to_varchar_char-vu-verify.out index fbcc3fa121d..e129a1db4b3 100644 --- a/test/JDBC/expected/test_conv_float_to_varchar_char-vu-verify.out +++ b/test/JDBC/expected/test_conv_float_to_varchar_char-vu-verify.out @@ -49,49 +49,49 @@ GO ~~START~~ varchar#!#varchar#!#varchar#!#varchar#!#varchar#!#varchar -Direct Conversion#!#CAST vs CONVERT#!#Standard positive decimal#!# 123.456#!# 123.456 #!# -Direct Conversion#!#CAST vs CONVERT#!#Negative decimal#!# -123.456#!#-123.456 #!# -Direct Conversion#!#CAST vs CONVERT#!#Zero value#!# 0#!# 0 #!# -Direct Conversion#!#CAST vs CONVERT#!#Scientific notation - large#!# 10000000000#!#1e+10 #!# -Direct Conversion#!#CAST vs CONVERT#!#Scientific notation - small#!# 0#!# 0.000000 #!# -Direct Conversion#!#CAST vs CONVERT#!#Large decimal#!# 9999999999.99#!#1e+10 #!# -Direct Conversion#!#CAST vs CONVERT#!#Very small decimal#!# 0#!# 0.000000 #!# +Direct Conversion#!#CAST vs CONVERT#!#Standard positive decimal#!#123.456 #!#123.456 #!# +Direct Conversion#!#CAST vs CONVERT#!#Negative decimal#!#-123.456 #!#-123.456 #!# +Direct Conversion#!#CAST vs CONVERT#!#Zero value#!#0 #!#0 #!# +Direct Conversion#!#CAST vs CONVERT#!#Scientific notation - large#!#10000000000 #!#1e+10 #!# +Direct Conversion#!#CAST vs CONVERT#!#Scientific notation - small#!#0 #!#0.000000 #!# +Direct Conversion#!#CAST vs CONVERT#!#Large decimal#!#9999999999.99 #!#1e+10 #!# +Direct Conversion#!#CAST vs CONVERT#!#Very small decimal#!#0 #!#0.000000 #!# Direct Conversion#!#CAST vs CONVERT#!#NULL Value#!##!##!# ~~END~~ ~~START~~ char#!#char - 123.456#!# 123.456 +123.456 #!#123.456 ~~END~~ ~~START~~ char#!#char - -123.456#!#-123.456 +-123.456 #!#-123.456 ~~END~~ ~~START~~ char#!#char - 0#!# 0 +0 #!#0 ~~END~~ ~~START~~ char#!#char - 10000000000#!#1e+10 +10000000000 #!#1e+10 ~~END~~ ~~START~~ char#!#char - 0#!# 0.000000 +0 #!#0.000000 ~~END~~ ~~START~~ char#!#char - 9999999999.99#!#1e+10 +9999999999.99 #!#1e+10 ~~END~~ ~~START~~ char#!#char - 0#!# 0.000000 +0 #!#0.000000 ~~END~~ ~~START~~ @@ -106,7 +106,7 @@ SELECT * FROM float_char_v2; GO ~~START~~ char#!#char - -123.456326#!# -123.456326 +-123.456326 #!#-123.456326 ~~END~~ ~~START~~ @@ -121,12 +121,12 @@ SELECT float_char_f2('123.4567') GO ~~START~~ varchar - 123.4567 +123.4567 ~~END~~ ~~START~~ varchar - 123.457 +123.457 ~~END~~ @@ -182,19 +182,19 @@ GO ~~START~~ varchar#!#varchar#!#varchar#!#varchar#!#varchar#!#varchar -Direct Conversion#!#CAST vs CONVERT#!#Standard positive decimal#!#123.456#!# 123.456 #!# +Direct Conversion#!#CAST vs CONVERT#!#Standard positive decimal#!#123.456#!#123.456 #!# Direct Conversion#!#CAST vs CONVERT#!#Negative decimal#!#-123.456#!#-123.456 #!# -Direct Conversion#!#CAST vs CONVERT#!#Zero value#!#0#!# 0 #!# +Direct Conversion#!#CAST vs CONVERT#!#Zero value#!#0#!#0 #!# Direct Conversion#!#CAST vs CONVERT#!#Scientific notation - large#!#10000000000#!#1e+10 #!# -Direct Conversion#!#CAST vs CONVERT#!#Scientific notation - small#!#0#!# 0.000000 #!# +Direct Conversion#!#CAST vs CONVERT#!#Scientific notation - small#!#0#!#0.000000 #!# Direct Conversion#!#CAST vs CONVERT#!#Large decimal#!#9999999999.99#!#1e+10 #!# -Direct Conversion#!#CAST vs CONVERT#!#Very small decimal#!#0#!# 0.000000 #!# +Direct Conversion#!#CAST vs CONVERT#!#Very small decimal#!#0#!#0.000000 #!# Direct Conversion#!#CAST vs CONVERT#!#NULL Value#!##!##!# ~~END~~ ~~START~~ varchar#!#varchar -123.456#!# 123.456 +123.456#!#123.456 ~~END~~ ~~START~~ @@ -204,7 +204,7 @@ varchar#!#varchar ~~START~~ varchar#!#varchar -0#!# 0 +0#!#0 ~~END~~ ~~START~~ @@ -214,7 +214,7 @@ varchar#!#varchar ~~START~~ varchar#!#varchar -0#!# 0.000000 +0#!#0.000000 ~~END~~ ~~START~~ @@ -224,7 +224,7 @@ varchar#!#varchar ~~START~~ varchar#!#varchar -0#!# 0.000000 +0#!#0.000000 ~~END~~ ~~START~~ @@ -260,7 +260,7 @@ varchar ~~START~~ varchar - 123.457 +123.457 ~~END~~ @@ -341,6 +341,6 @@ SELECT cast(@flt1*@flt2 as varchar(30)),cast(@flt1/@flt2 as varchar(30)),cast(@f GO ~~START~~ varchar#!#varchar#!#char#!#char --71820.376206#!#-2.4e-05#!# -54234.107967#!# -2.4e-05 +-71820.376206#!#-2.4e-05#!#-54234.107967 #!#-2.4e-05 ~~END~~ diff --git a/test/JDBC/expected/test_conv_float_to_varchar_char_before_17_4-vu-verify.out b/test/JDBC/expected/test_conv_float_to_varchar_char_before_17_4-vu-verify.out index 405727ae047..f6324d7ec71 100644 --- a/test/JDBC/expected/test_conv_float_to_varchar_char_before_17_4-vu-verify.out +++ b/test/JDBC/expected/test_conv_float_to_varchar_char_before_17_4-vu-verify.out @@ -49,49 +49,49 @@ GO ~~START~~ varchar#!#varchar#!#varchar#!#varchar#!#varchar#!#varchar -Direct Conversion#!#CAST vs CONVERT#!#Standard positive decimal#!# 123.456#!# 123.456 #!# -Direct Conversion#!#CAST vs CONVERT#!#Negative decimal#!# -123.456#!#-123.456 #!# -Direct Conversion#!#CAST vs CONVERT#!#Zero value#!# 0#!# 0 #!# -Direct Conversion#!#CAST vs CONVERT#!#Scientific notation - large#!# 10000000000#!#1e+10 #!# -Direct Conversion#!#CAST vs CONVERT#!#Scientific notation - small#!# 0#!# 0.000000 #!# -Direct Conversion#!#CAST vs CONVERT#!#Large decimal#!# 9999999999.99#!#1e+10 #!# -Direct Conversion#!#CAST vs CONVERT#!#Very small decimal#!# 0#!# 0.000000 #!# +Direct Conversion#!#CAST vs CONVERT#!#Standard positive decimal#!#123.456 #!#123.456 #!# +Direct Conversion#!#CAST vs CONVERT#!#Negative decimal#!#-123.456 #!#-123.456 #!# +Direct Conversion#!#CAST vs CONVERT#!#Zero value#!#0 #!#0 #!# +Direct Conversion#!#CAST vs CONVERT#!#Scientific notation - large#!#10000000000 #!#1e+10 #!# +Direct Conversion#!#CAST vs CONVERT#!#Scientific notation - small#!#0 #!#0.000000 #!# +Direct Conversion#!#CAST vs CONVERT#!#Large decimal#!#9999999999.99 #!#1e+10 #!# +Direct Conversion#!#CAST vs CONVERT#!#Very small decimal#!#0 #!#0.000000 #!# Direct Conversion#!#CAST vs CONVERT#!#NULL Value#!##!##!# ~~END~~ ~~START~~ char#!#char - 123.456#!# 123.456 +123.456 #!#123.456 ~~END~~ ~~START~~ char#!#char - -123.456#!#-123.456 +-123.456 #!#-123.456 ~~END~~ ~~START~~ char#!#char - 0#!# 0 +0 #!#0 ~~END~~ ~~START~~ char#!#char - 10000000000#!#1e+10 +10000000000 #!#1e+10 ~~END~~ ~~START~~ char#!#char - 0#!# 0.000000 +0 #!#0.000000 ~~END~~ ~~START~~ char#!#char - 9999999999.99#!#1e+10 +9999999999.99 #!#1e+10 ~~END~~ ~~START~~ char#!#char - 0#!# 0.000000 +0 #!#0.000000 ~~END~~ ~~START~~ @@ -121,12 +121,12 @@ SELECT float_char_f2('123.4567') GO ~~START~~ varchar - 123.4567 +123.4567 ~~END~~ ~~START~~ varchar - 123.457 +123.457 ~~END~~ @@ -182,19 +182,19 @@ GO ~~START~~ varchar#!#varchar#!#varchar#!#varchar#!#varchar#!#varchar -Direct Conversion#!#CAST vs CONVERT#!#Standard positive decimal#!#123.456#!# 123.456 #!# +Direct Conversion#!#CAST vs CONVERT#!#Standard positive decimal#!#123.456#!#123.456 #!# Direct Conversion#!#CAST vs CONVERT#!#Negative decimal#!#-123.456#!#-123.456 #!# -Direct Conversion#!#CAST vs CONVERT#!#Zero value#!#0#!# 0 #!# +Direct Conversion#!#CAST vs CONVERT#!#Zero value#!#0#!#0 #!# Direct Conversion#!#CAST vs CONVERT#!#Scientific notation - large#!#10000000000#!#1e+10 #!# -Direct Conversion#!#CAST vs CONVERT#!#Scientific notation - small#!#0#!# 0.000000 #!# +Direct Conversion#!#CAST vs CONVERT#!#Scientific notation - small#!#0#!#0.000000 #!# Direct Conversion#!#CAST vs CONVERT#!#Large decimal#!#9999999999.99#!#1e+10 #!# -Direct Conversion#!#CAST vs CONVERT#!#Very small decimal#!#0#!# 0.000000 #!# +Direct Conversion#!#CAST vs CONVERT#!#Very small decimal#!#0#!#0.000000 #!# Direct Conversion#!#CAST vs CONVERT#!#NULL Value#!##!##!# ~~END~~ ~~START~~ varchar#!#varchar -123.456#!# 123.456 +123.456#!#123.456 ~~END~~ ~~START~~ @@ -204,7 +204,7 @@ varchar#!#varchar ~~START~~ varchar#!#varchar -0#!# 0 +0#!#0 ~~END~~ ~~START~~ @@ -214,7 +214,7 @@ varchar#!#varchar ~~START~~ varchar#!#varchar -0#!# 0.000000 +0#!#0.000000 ~~END~~ ~~START~~ @@ -224,7 +224,7 @@ varchar#!#varchar ~~START~~ varchar#!#varchar -0#!# 0.000000 +0#!#0.000000 ~~END~~ ~~START~~ @@ -260,7 +260,7 @@ varchar ~~START~~ varchar - 123.457 +123.457 ~~END~~ @@ -341,6 +341,6 @@ SELECT cast(@flt1*@flt2 as varchar(30)),cast(@flt1/@flt2 as varchar(30)),cast(@f GO ~~START~~ varchar#!#varchar#!#char#!#char --71820.376206#!#-2.4e-05#!# -54234.107967#!# -2.4e-05 +-71820.376206#!#-2.4e-05#!#-54234.107967 #!#-2.4e-05 ~~END~~