From 3fb85f5ef28b8b8554e694766281803f5d3b7b91 Mon Sep 17 00:00:00 2001 From: Sai Rohan Basa <108261379+basasairohan@users.noreply.github.com> Date: Wed, 25 Oct 2023 15:37:24 +0530 Subject: [PATCH] Make FORMAT(), format_numeric() and format_datetime() function PARALLEL UNSAFE (#1949) In FORMAT() function we do the following operations which makes it PARALLEL UNSAFE : EXCEPTION statement is being used which will create a subtransaction. Subtransactions can not be started during a parallel operation. FORMAT() is internally calling format_numeric() and format_datetime() functions where we modify some GUCs like extra_float_digits. We can not modify GUCs during a parallel operation. This change makes the functions FORMAT(), format_numeric() and format_datetime() PARALLEL UNSAFE. Task: BABEL-4394 Signed-off-by: Sai Rohan Basa --- .../sql/datatype_string_operators.sql | 6 +- .../babelfishpg_tsql--3.3.0--3.4.0.sql | 69 +++++++++++++++++++ test/JDBC/parallel_query_jdbc_schedule | 5 -- 3 files changed, 72 insertions(+), 8 deletions(-) diff --git a/contrib/babelfishpg_tsql/sql/datatype_string_operators.sql b/contrib/babelfishpg_tsql/sql/datatype_string_operators.sql index ac26898f8c..147f950af5 100644 --- a/contrib/babelfishpg_tsql/sql/datatype_string_operators.sql +++ b/contrib/babelfishpg_tsql/sql/datatype_string_operators.sql @@ -58,11 +58,11 @@ AS 'babelfishpg_tsql', 'formatmessage' LANGUAGE C IMMUTABLE PARALLEL SAFE; GRANT EXECUTE ON FUNCTION sys.formatmessage(IN VARCHAR, VARIADIC "any") TO PUBLIC; CREATE OR REPLACE FUNCTION sys.format_datetime(IN value anyelement, IN format_pattern NVARCHAR,IN culture VARCHAR, IN data_type VARCHAR DEFAULT '') RETURNS sys.nvarchar -AS 'babelfishpg_tsql', 'format_datetime' LANGUAGE C IMMUTABLE PARALLEL SAFE; +AS 'babelfishpg_tsql', 'format_datetime' LANGUAGE C IMMUTABLE PARALLEL UNSAFE; GRANT EXECUTE ON FUNCTION sys.format_datetime(IN anyelement, IN NVARCHAR, IN VARCHAR, IN VARCHAR) TO PUBLIC; CREATE OR REPLACE FUNCTION sys.format_numeric(IN value anyelement, IN format_pattern NVARCHAR,IN culture VARCHAR, IN data_type VARCHAR DEFAULT '', IN e_position INT DEFAULT -1) RETURNS sys.nvarchar -AS 'babelfishpg_tsql', 'format_numeric' LANGUAGE C IMMUTABLE PARALLEL SAFE; +AS 'babelfishpg_tsql', 'format_numeric' LANGUAGE C IMMUTABLE PARALLEL UNSAFE; GRANT EXECUTE ON FUNCTION sys.format_numeric(IN anyelement, IN NVARCHAR, IN VARCHAR, IN VARCHAR, IN INT) TO PUBLIC; CREATE OR REPLACE FUNCTION sys.FORMAT(IN arg anyelement, IN p_format_pattern NVARCHAR, IN p_culture VARCHAR default 'en-us') @@ -123,7 +123,7 @@ EXCEPTION HINT := 'Convert it to valid datatype and try again.'; END; $BODY$ -LANGUAGE plpgsql IMMUTABLE PARALLEL SAFE; +LANGUAGE plpgsql IMMUTABLE PARALLEL UNSAFE; GRANT EXECUTE ON FUNCTION sys.FORMAT(IN anyelement, IN NVARCHAR, IN VARCHAR) TO PUBLIC; CREATE OR REPLACE FUNCTION sys.STR(IN float_expression NUMERIC, IN length INTEGER DEFAULT 10, IN decimal_point INTEGER DEFAULT 0) RETURNS VARCHAR diff --git a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.3.0--3.4.0.sql b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.3.0--3.4.0.sql index 25946badd2..c822e93d3c 100644 --- a/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.3.0--3.4.0.sql +++ b/contrib/babelfishpg_tsql/sql/upgrades/babelfishpg_tsql--3.3.0--3.4.0.sql @@ -2520,6 +2520,75 @@ CALL sys.babelfish_update_user_catalog_for_guest_schema(); -- Drop this procedure after it gets executed once. DROP PROCEDURE sys.babelfish_update_user_catalog_for_guest_schema(); +CREATE OR REPLACE FUNCTION sys.format_datetime(IN value anyelement, IN format_pattern NVARCHAR,IN culture VARCHAR, IN data_type VARCHAR DEFAULT '') RETURNS sys.nvarchar +AS 'babelfishpg_tsql', 'format_datetime' LANGUAGE C IMMUTABLE PARALLEL UNSAFE; +GRANT EXECUTE ON FUNCTION sys.format_datetime(IN anyelement, IN NVARCHAR, IN VARCHAR, IN VARCHAR) TO PUBLIC; + +CREATE OR REPLACE FUNCTION sys.format_numeric(IN value anyelement, IN format_pattern NVARCHAR,IN culture VARCHAR, IN data_type VARCHAR DEFAULT '', IN e_position INT DEFAULT -1) RETURNS sys.nvarchar +AS 'babelfishpg_tsql', 'format_numeric' LANGUAGE C IMMUTABLE PARALLEL UNSAFE; +GRANT EXECUTE ON FUNCTION sys.format_numeric(IN anyelement, IN NVARCHAR, IN VARCHAR, IN VARCHAR, IN INT) TO PUBLIC; + +CREATE OR REPLACE FUNCTION sys.FORMAT(IN arg anyelement, IN p_format_pattern NVARCHAR, IN p_culture VARCHAR default 'en-us') +RETURNS sys.NVARCHAR +AS +$BODY$ +DECLARE + arg_type regtype; + v_temp_integer INTEGER; +BEGIN + arg_type := pg_typeof(arg); + + CASE + WHEN arg_type IN ('time'::regtype ) THEN + RETURN sys.format_datetime(arg, p_format_pattern, p_culture, 'time'); + + WHEN arg_type IN ('date'::regtype, 'sys.datetime'::regtype, 'sys.smalldatetime'::regtype, 'sys.datetime2'::regtype ) THEN + RETURN sys.format_datetime(arg::timestamp, p_format_pattern, p_culture); + + WHEN arg_type IN ('sys.tinyint'::regtype) THEN + RETURN sys.format_numeric(arg::SMALLINT, p_format_pattern, p_culture, 'tinyint'); + + WHEN arg_type IN ('smallint'::regtype) THEN + RETURN sys.format_numeric(arg::SMALLINT, p_format_pattern, p_culture, 'smallint'); + + WHEN arg_type IN ('integer'::regtype) THEN + RETURN sys.format_numeric(arg, p_format_pattern, p_culture, 'integer'); + + WHEN arg_type IN ('bigint'::regtype) THEN + RETURN sys.format_numeric(arg, p_format_pattern, p_culture, 'bigint'); + + WHEN arg_type IN ('numeric'::regtype) THEN + RETURN sys.format_numeric(arg, p_format_pattern, p_culture, 'numeric'); + + WHEN arg_type IN ('sys.decimal'::regtype) THEN + RETURN sys.format_numeric(arg::numeric, p_format_pattern, p_culture, 'numeric'); + + WHEN arg_type IN ('real'::regtype) THEN + IF(p_format_pattern LIKE 'R%') THEN + v_temp_integer := length(nullif((regexp_matches(arg::real::text, '(?<=\d*\.).*(?=[eE].*)')::text[])[1], '')); + ELSE v_temp_integer:= -1; + END IF; + + RETURN sys.format_numeric(arg, p_format_pattern, p_culture, 'real', v_temp_integer); + + WHEN arg_type IN ('float'::regtype) THEN + RETURN sys.format_numeric(arg, p_format_pattern, p_culture, 'float'); + + WHEN pg_typeof(arg) IN ('sys.smallmoney'::regtype, 'sys.money'::regtype) THEN + RETURN sys.format_numeric(arg::numeric, p_format_pattern, p_culture, 'numeric'); + ELSE + RAISE datatype_mismatch; + END CASE; +EXCEPTION + WHEN datatype_mismatch THEN + RAISE USING MESSAGE := format('Argument data type % is invalid for argument 1 of format function.', pg_typeof(arg)), + DETAIL := 'Invalid datatype.', + HINT := 'Convert it to valid datatype and try again.'; +END; +$BODY$ +LANGUAGE plpgsql IMMUTABLE PARALLEL UNSAFE; +GRANT EXECUTE ON FUNCTION sys.FORMAT(IN anyelement, IN NVARCHAR, IN VARCHAR) TO PUBLIC; + -- Drops the temporary procedure used by the upgrade script. -- Please have this be one of the last statements executed in this upgrade script. diff --git a/test/JDBC/parallel_query_jdbc_schedule b/test/JDBC/parallel_query_jdbc_schedule index a4abceef5c..2899949974 100644 --- a/test/JDBC/parallel_query_jdbc_schedule +++ b/test/JDBC/parallel_query_jdbc_schedule @@ -33,11 +33,6 @@ ignore#!#sys-eomonth-vu-verify ignore#!#babel_datetime2 ignore#!#babel_collation -# Group 2: cannot start subtransactions during a parallel operation BABEL-4394 -ignore#!#babel_format_standard_date_time -ignore#!#babel_format_standard_numeric -ignore#!#format-vu-verify - # Group 3: “could not access file "pg_hint_plan": No such file or directory" BABEL-4395 ignore#!#BABEL-3291 ignore#!#BABEL-3292