Skip to content

Commit

Permalink
Make FORMAT(), format_numeric() and format_datetime() function PARALL…
Browse files Browse the repository at this point in the history
…EL 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 <[email protected]>
  • Loading branch information
basasairohan authored Oct 25, 2023
1 parent ae8d70e commit 3fb85f5
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 8 deletions.
6 changes: 3 additions & 3 deletions contrib/babelfishpg_tsql/sql/datatype_string_operators.sql
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
5 changes: 0 additions & 5 deletions test/JDBC/parallel_query_jdbc_schedule
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 3fb85f5

Please sign in to comment.