From 8e40917123d391464e1770ff00deac1d65a7f673 Mon Sep 17 00:00:00 2001 From: Kushaal Shroff <51415286+KushaalShroff@users.noreply.github.com> Date: Wed, 9 Aug 2023 12:06:31 +0530 Subject: [PATCH] Date functions returns time of transaction instead of time of query (#1693) Get Current Date/time type functions inside a batch were returning the same datetime. This was because we were calling SetCurrentStatementStartTimestamp only at batch level. To fix this, we now call SetCurrentStatementStartTimestamp at statement level. Moreover, this commit removes the extra definition for GETUTCDATE which was causing behaviour differences. Issues Resolved BABEL-4187 Signed-off-by: Kushaal Shroff kushaal@amazon.com --- .../babelfishpg_tsql/sql/sys_functions.sql | 6 - contrib/babelfishpg_tsql/src/iterative_exec.c | 3 + test/JDBC/expected/getdatetest.out | 399 ++++++++++++++++++ test/JDBC/input/getdatetest.sql | 250 +++++++++++ 4 files changed, 652 insertions(+), 6 deletions(-) diff --git a/contrib/babelfishpg_tsql/sql/sys_functions.sql b/contrib/babelfishpg_tsql/sql/sys_functions.sql index d20d9497df..c8cd1db3b8 100644 --- a/contrib/babelfishpg_tsql/sql/sys_functions.sql +++ b/contrib/babelfishpg_tsql/sql/sys_functions.sql @@ -1676,12 +1676,6 @@ $BODY$ STRICT LANGUAGE sql IMMUTABLE; -CREATE OR REPLACE FUNCTION sys.GETUTCDATE() RETURNS sys.DATETIME AS -$BODY$ -SELECT CAST(CURRENT_TIMESTAMP AT TIME ZONE 'UTC'::pg_catalog.text AS sys.DATETIME); -$BODY$ -LANGUAGE SQL STABLE PARALLEL SAFE; - -- These come from the built-in pg_catalog.count in pg_aggregate.dat CREATE AGGREGATE sys.count(*) ( diff --git a/contrib/babelfishpg_tsql/src/iterative_exec.c b/contrib/babelfishpg_tsql/src/iterative_exec.c index 6f82aceefc..e069c0d49c 100644 --- a/contrib/babelfishpg_tsql/src/iterative_exec.c +++ b/contrib/babelfishpg_tsql/src/iterative_exec.c @@ -1414,6 +1414,9 @@ exec_stmt_iterative(PLtsql_execstate *estate, ExecCodes *exec_codes, ExecConfig_ reset_exec_error_data(estate); + /* Set the current Statement Start time at satement level and not at batch. */ + SetCurrentStatementStartTimestamp(); + /* * Let the protocol plugin know that we are about to execute this * statement diff --git a/test/JDBC/expected/getdatetest.out b/test/JDBC/expected/getdatetest.out index eb18c62a0f..d9ef1499ab 100644 --- a/test/JDBC/expected/getdatetest.out +++ b/test/JDBC/expected/getdatetest.out @@ -1,4 +1,5 @@ + -- NOTE: Each test is expected to take a lot of time -- We do not need Upgrade tests for these function -- We can only test the stability of this function in the framework since the results are dynamic @@ -86,3 +87,401 @@ int 65536 ~~END~~ + + +-- Testing for consistency withing a batch and within a transaction as well +-- getdate +declare @a datetime +declare @b datetime +set @a = getdate() +exec pg_sleep 1 +set @b = getdate() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + + +Create procedure proc_1 as declare @a datetime;declare @b datetime;set @a = getdate();exec pg_sleep 1;set @b = getdate(); if @a = @b SELECT 'FAILURE' ELSE SELECT 'PASS' +go + +declare @a datetime +declare @b datetime +set @a = getdate() +exec proc_1; +set @b = getdate() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + +~~START~~ +varchar +PASS +~~END~~ + + +Begin transaction +go + +declare @a datetime +declare @b datetime +set @a = getdate() +exec pg_sleep 1 +set @b = getdate() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + + +declare @a datetime +declare @b datetime +set @a = getdate() +exec proc_1; +set @b = getdate() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + +~~START~~ +varchar +PASS +~~END~~ + + +Rollback +go + +Drop procedure proc_1; +go + + +-- getutcdate +declare @a datetime +declare @b datetime +set @a = getutcdate() +exec pg_sleep 1 +set @b = getutcdate() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + + +Create procedure proc_1 as declare @a datetime;declare @b datetime;set @a = getutcdate();exec pg_sleep 1;set @b = getutcdate(); if @a = @b SELECT 'FAILURE' ELSE SELECT 'PASS' +go + +declare @a datetime +declare @b datetime +set @a = getutcdate() +exec proc_1; +set @b = getutcdate() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + +~~START~~ +varchar +PASS +~~END~~ + + +Begin transaction +go + +declare @a datetime +declare @b datetime +set @a = getutcdate() +exec pg_sleep 1 +set @b = getutcdate() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + + +declare @a datetime +declare @b datetime +set @a = getutcdate() +exec proc_1; +set @b = getutcdate() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + +~~START~~ +varchar +PASS +~~END~~ + + +Rollback +go + +Drop procedure proc_1; +go + +-- sysutcdatetime +declare @a datetime +declare @b datetime +set @a = sysutcdatetime() +exec pg_sleep 1 +set @b = sysutcdatetime() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + + +Create procedure proc_1 as declare @a datetime;declare @b datetime;set @a = sysutcdatetime();exec pg_sleep 1;set @b = sysutcdatetime(); if @a = @b SELECT 'FAILURE' ELSE SELECT 'PASS' +go + +declare @a datetime +declare @b datetime +set @a = sysutcdatetime() +exec proc_1; +set @b = sysutcdatetime() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + +~~START~~ +varchar +PASS +~~END~~ + + +Begin transaction +go + +declare @a datetime +declare @b datetime +set @a = sysutcdatetime() +exec pg_sleep 1 +set @b = sysutcdatetime() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + + +declare @a datetime +declare @b datetime +set @a = sysutcdatetime() +exec proc_1; +set @b = sysutcdatetime() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + +~~START~~ +varchar +PASS +~~END~~ + + +Rollback +go + +Drop procedure proc_1; +go + +-- sysdatetime +declare @a datetime +declare @b datetime +set @a = sysdatetime() +exec pg_sleep 1 +set @b = sysdatetime() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + + +Create procedure proc_1 as declare @a datetime;declare @b datetime;set @a = sysdatetime();exec pg_sleep 1;set @b = sysdatetime(); if @a = @b SELECT 'FAILURE' ELSE SELECT 'PASS' +go + +declare @a datetime +declare @b datetime +set @a = sysdatetime() +exec proc_1; +set @b = sysdatetime() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + +~~START~~ +varchar +PASS +~~END~~ + + +Begin transaction +go + +declare @a datetime +declare @b datetime +set @a = sysdatetime() +exec pg_sleep 1 +set @b = sysdatetime() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + + +declare @a datetime +declare @b datetime +set @a = sysdatetime() +exec proc_1; +set @b = sysdatetime() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + +~~START~~ +varchar +PASS +~~END~~ + + +Rollback +go + +Drop procedure proc_1; +go + +-- sysdatetimeoffset +declare @a datetime +declare @b datetime +set @a = sysdatetimeoffset() +exec pg_sleep 1 +set @b = sysdatetimeoffset() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + + +Create procedure proc_1 as declare @a datetime;declare @b datetime;set @a = sysdatetimeoffset();exec pg_sleep 1;set @b = sysdatetimeoffset(); if @a = @b SELECT 'FAILURE' ELSE SELECT 'PASS' +go + +declare @a datetime +declare @b datetime +set @a = sysdatetimeoffset() +exec proc_1; +set @b = sysdatetimeoffset() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + +~~START~~ +varchar +PASS +~~END~~ + + +Begin transaction +go + +declare @a datetime +declare @b datetime +set @a = sysdatetimeoffset() +exec pg_sleep 1 +set @b = sysdatetimeoffset() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + + +declare @a datetime +declare @b datetime +set @a = sysdatetimeoffset() +exec proc_1; +set @b = sysdatetimeoffset() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go +~~START~~ +varchar +PASS +~~END~~ + +~~START~~ +varchar +PASS +~~END~~ + + +Rollback +go + +Drop procedure proc_1; +go diff --git a/test/JDBC/input/getdatetest.sql b/test/JDBC/input/getdatetest.sql index b6eec5a2a3..4c70edb361 100644 --- a/test/JDBC/input/getdatetest.sql +++ b/test/JDBC/input/getdatetest.sql @@ -1,3 +1,5 @@ +-- sla 50000 + -- NOTE: Each test is expected to take a lot of time -- We do not need Upgrade tests for these function -- We can only test the stability of this function in the framework since the results are dynamic @@ -61,3 +63,251 @@ SELECT count(min_getdate) FROM Tally WHERE min_getdate = sys.getutcdate() go + +-- Testing for consistency withing a batch and within a transaction as well + +-- getdate +declare @a datetime +declare @b datetime +set @a = getdate() +exec pg_sleep 1 +set @b = getdate() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +Create procedure proc_1 as declare @a datetime;declare @b datetime;set @a = getdate();exec pg_sleep 1;set @b = getdate(); if @a = @b SELECT 'FAILURE' ELSE SELECT 'PASS' +go + +declare @a datetime +declare @b datetime +set @a = getdate() +exec proc_1; +set @b = getdate() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +Begin transaction +go + +declare @a datetime +declare @b datetime +set @a = getdate() +exec pg_sleep 1 +set @b = getdate() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +declare @a datetime +declare @b datetime +set @a = getdate() +exec proc_1; +set @b = getdate() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +Rollback +go + +Drop procedure proc_1; +go + +-- getutcdate + +declare @a datetime +declare @b datetime +set @a = getutcdate() +exec pg_sleep 1 +set @b = getutcdate() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +Create procedure proc_1 as declare @a datetime;declare @b datetime;set @a = getutcdate();exec pg_sleep 1;set @b = getutcdate(); if @a = @b SELECT 'FAILURE' ELSE SELECT 'PASS' +go + +declare @a datetime +declare @b datetime +set @a = getutcdate() +exec proc_1; +set @b = getutcdate() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +Begin transaction +go + +declare @a datetime +declare @b datetime +set @a = getutcdate() +exec pg_sleep 1 +set @b = getutcdate() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +declare @a datetime +declare @b datetime +set @a = getutcdate() +exec proc_1; +set @b = getutcdate() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +Rollback +go + +Drop procedure proc_1; +go + +-- sysutcdatetime +declare @a datetime +declare @b datetime +set @a = sysutcdatetime() +exec pg_sleep 1 +set @b = sysutcdatetime() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +Create procedure proc_1 as declare @a datetime;declare @b datetime;set @a = sysutcdatetime();exec pg_sleep 1;set @b = sysutcdatetime(); if @a = @b SELECT 'FAILURE' ELSE SELECT 'PASS' +go + +declare @a datetime +declare @b datetime +set @a = sysutcdatetime() +exec proc_1; +set @b = sysutcdatetime() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +Begin transaction +go + +declare @a datetime +declare @b datetime +set @a = sysutcdatetime() +exec pg_sleep 1 +set @b = sysutcdatetime() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +declare @a datetime +declare @b datetime +set @a = sysutcdatetime() +exec proc_1; +set @b = sysutcdatetime() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +Rollback +go + +Drop procedure proc_1; +go + +-- sysdatetime +declare @a datetime +declare @b datetime +set @a = sysdatetime() +exec pg_sleep 1 +set @b = sysdatetime() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +Create procedure proc_1 as declare @a datetime;declare @b datetime;set @a = sysdatetime();exec pg_sleep 1;set @b = sysdatetime(); if @a = @b SELECT 'FAILURE' ELSE SELECT 'PASS' +go + +declare @a datetime +declare @b datetime +set @a = sysdatetime() +exec proc_1; +set @b = sysdatetime() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +Begin transaction +go + +declare @a datetime +declare @b datetime +set @a = sysdatetime() +exec pg_sleep 1 +set @b = sysdatetime() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +declare @a datetime +declare @b datetime +set @a = sysdatetime() +exec proc_1; +set @b = sysdatetime() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +Rollback +go + +Drop procedure proc_1; +go + +-- sysdatetimeoffset +declare @a datetime +declare @b datetime +set @a = sysdatetimeoffset() +exec pg_sleep 1 +set @b = sysdatetimeoffset() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +Create procedure proc_1 as declare @a datetime;declare @b datetime;set @a = sysdatetimeoffset();exec pg_sleep 1;set @b = sysdatetimeoffset(); if @a = @b SELECT 'FAILURE' ELSE SELECT 'PASS' +go + +declare @a datetime +declare @b datetime +set @a = sysdatetimeoffset() +exec proc_1; +set @b = sysdatetimeoffset() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +Begin transaction +go + +declare @a datetime +declare @b datetime +set @a = sysdatetimeoffset() +exec pg_sleep 1 +set @b = sysdatetimeoffset() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +declare @a datetime +declare @b datetime +set @a = sysdatetimeoffset() +exec proc_1; +set @b = sysdatetimeoffset() +if @a = @b SELECT 'FAILURE' + ELSE SELECT 'PASS' +go + +Rollback +go + +Drop procedure proc_1; +go \ No newline at end of file