Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for sys.sp_reset_connection stored procedure #2758

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions contrib/babelfishpg_tds/src/backend/tds/tds_srv.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ pe_tds_init(void)
pltsql_plugin_handler_ptr->set_context_info = &set_tds_context_info;
pltsql_plugin_handler_ptr->get_datum_from_byte_ptr = &TdsBytePtrToDatum;
pltsql_plugin_handler_ptr->get_datum_from_date_time_struct = &TdsDateTimeTypeToDatum;
pltsql_plugin_handler_ptr->set_reset_tds_connection_flag = &SetResetTDSConnectionFlag;

invalidate_stat_table_hook = invalidate_stat_table;
guc_newval_hook = TdsSetGucStatVariable;
Expand Down
30 changes: 26 additions & 4 deletions contrib/babelfishpg_tds/src/backend/tds/tdsprotocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ typedef ResetConnectionData *ResetConnection;
TdsRequestCtrlData *TdsRequestCtrl = NULL;

ResetConnection resetCon = NULL;
static bool resetTdsConnectionFlag = false;

/* Local functions */
static void ResetTDSConnection(void);
Expand Down Expand Up @@ -154,13 +155,28 @@ ResetTDSConnection(void)
TdsResetCache();
TdsResponseReset();
TdsResetBcpOffset();
SetConfigOption("default_transaction_isolation", isolationOld,
PGC_BACKEND, PGC_S_CLIENT);
/* Retore previous isolation level when not called by sys.sp_reset_connection */
if (!resetTdsConnectionFlag)
{
SetConfigOption("default_transaction_isolation", isolationOld,
PGC_BACKEND, PGC_S_CLIENT);
}

tvp_lookup_list = NIL;

/* send an environement change token */
TdsSendEnvChange(TDS_ENVID_RESETCON, NULL, NULL);
/* send an environement change token is its not called via sys.sp_reset_connection procedure */
if (!resetTdsConnectionFlag)
{
TdsSendEnvChange(TDS_ENVID_RESETCON, NULL, NULL);
}
}

/*
* SetResetTDSConnectionFlag - Sets reset tds connection flag
*/
void SetResetTDSConnectionFlag()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On diving deep, Found 2 behaviour differences:

  1. sys.sp_reset_connection should not send Env change token and TDSResetConnection should send
  2. Isolation levels are reset for sp_reset_connection but retained for TDSResetConnection

We have not fixed this for sp_reset_connection and this is paramount for feature complete. Lets focus on testing and aligning TSQL Behaviour and using wireshark

{
resetTdsConnectionFlag = true;
}

/*
Expand Down Expand Up @@ -674,6 +690,12 @@ TdsSocketBackend(void)
/* Ready to fetch the next request */
TdsRequestCtrl->phase = TDS_REQUEST_PHASE_FETCH;

if (resetTdsConnectionFlag)
{
ResetTDSConnection();
resetTdsConnectionFlag = false;
}

break;
}
case TDS_REQUEST_PHASE_ERROR:
Expand Down
1 change: 1 addition & 0 deletions contrib/babelfishpg_tds/src/include/tds_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,6 @@ typedef struct
} TdsRequestCtrlData;

extern TdsRequestCtrlData *TdsRequestCtrl;
extern void SetResetTDSConnectionFlag(void);

#endif /* TDS_PROTOCOL_H */
4 changes: 4 additions & 0 deletions contrib/babelfishpg_tsql/sql/sys_procedures.sql
Original file line number Diff line number Diff line change
Expand Up @@ -329,3 +329,7 @@ GRANT EXECUTE ON PROCEDURE sys.sp_dropextendedproperty TO PUBLIC;
CREATE OR REPLACE PROCEDURE sys.sp_enum_oledb_providers()
AS 'babelfishpg_tsql', 'sp_enum_oledb_providers_internal' LANGUAGE C;
GRANT EXECUTE on PROCEDURE sys.sp_enum_oledb_providers() TO PUBLIC;

CREATE OR REPLACE PROCEDURE sys.sp_reset_connection()
AS 'babelfishpg_tsql', 'sp_reset_connection_internal' LANGUAGE C;
GRANT EXECUTE ON PROCEDURE sys.sp_reset_connection() TO PUBLIC;
Original file line number Diff line number Diff line change
Expand Up @@ -1857,6 +1857,10 @@ CALL sys.babelfish_drop_deprecated_object('function', 'sys', 'sp_tables_internal
-- Please have this be one of the last statements executed in this upgrade script.
DROP PROCEDURE sys.babelfish_drop_deprecated_object(varchar, varchar, varchar);

CREATE OR REPLACE PROCEDURE sys.sp_reset_connection()
AS 'babelfishpg_tsql', 'sp_reset_connection_internal' LANGUAGE C;
GRANT EXECUTE ON PROCEDURE sys.sp_reset_connection() TO PUBLIC;

-- After upgrade, always run analyze for all babelfish catalogs.
CALL sys.analyze_babelfish_catalogs();

Expand Down
3 changes: 2 additions & 1 deletion contrib/babelfishpg_tsql/src/pltsql.h
Original file line number Diff line number Diff line change
Expand Up @@ -1797,6 +1797,8 @@ typedef struct PLtsql_protocol_plugin

char *(*get_physical_schema_name) (char *db_name, const char *schema_name);

void (*set_reset_tds_connection_flag) ();

/* Session level GUCs */
bool quoted_identifier;
bool arithabort;
Expand All @@ -1810,7 +1812,6 @@ typedef struct PLtsql_protocol_plugin
int datefirst;
int lock_timeout;
const char *language;

} PLtsql_protocol_plugin;

/*
Expand Down
12 changes: 12 additions & 0 deletions contrib/babelfishpg_tsql/src/procedures.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ PG_FUNCTION_INFO_V1(sp_babelfish_volatility);
PG_FUNCTION_INFO_V1(sp_rename_internal);
PG_FUNCTION_INFO_V1(sp_execute_postgresql);
PG_FUNCTION_INFO_V1(sp_enum_oledb_providers_internal);
PG_FUNCTION_INFO_V1(sp_reset_connection_internal);
PG_FUNCTION_INFO_V1(sp_renamedb_internal);

extern void delete_cached_batch(int handle);
Expand Down Expand Up @@ -4198,3 +4199,14 @@ sp_enum_oledb_providers_internal(PG_FUNCTION_ARGS)

PG_RETURN_VOID();
}

Datum
sp_reset_connection_internal(PG_FUNCTION_ARGS)
{
if (*pltsql_protocol_plugin_ptr)
{
(*pltsql_protocol_plugin_ptr)->set_reset_tds_connection_flag();
}

PG_RETURN_VOID();
}
109 changes: 109 additions & 0 deletions test/JDBC/expected/Test-sp_reset_connection.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
-- 1. Test resets GUC variables
SET lock_timeout 0;
GO
SELECT @@lock_timeout;
GO
~~START~~
int
0
~~END~~

EXEC sys.sp_reset_connection
-- TODO: GUC is not resetting
SELECT @@lock_timeout;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming the default value was 0. How are we really testing the reset in this case?

GO
~~START~~
int
0
~~END~~


-- 2. Test open transactions are aborted on reset
DROP TABLE IF EXISTS sp_reset_connection_test_table;
CREATE TABLE sp_reset_connection_test_table(id int);
BEGIN TRANSACTION
INSERT INTO sp_reset_connection_test_table VALUES(1)
GO
~~ROW COUNT: 1~~

EXEC sys.sp_reset_connection
GO
COMMIT TRANSACTION
GO
~~ERROR (Code: 3902)~~

~~ERROR (Message: COMMIT can only be used in transaction blocks)~~

SELECT * FROM sp_reset_connection_test_table
GO
~~START~~
int
~~END~~


-- 3. Test temp tables are deleted on reset
CREATE TABLE #babel_temp_table (ID INT identity(1,1), Data INT)
INSERT INTO #babel_temp_table (Data) VALUES (100), (200), (300)
GO
~~ROW COUNT: 3~~

SELECT * from #babel_temp_table
GO
~~START~~
int#!#int
1#!#100
2#!#200
3#!#300
~~END~~

EXEC sys.sp_reset_connection
GO
SELECT * from #babel_temp_table
GO
~~ERROR (Code: 33557097)~~

~~ERROR (Message: relation "#babel_temp_table" does not exist)~~


-- 4. Test isolation level is reset
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
GO
select transaction_isolation_level from sys.dm_exec_sessions where session_id=@@SPID
GO
~~START~~
smallint
1
~~END~~

EXEC sys.sp_reset_connection
GO
select transaction_isolation_level from sys.dm_exec_sessions where session_id=@@SPID
GO
~~START~~
smallint
2
~~END~~


-- 5. Test sp_reset_connection called with sp_prepexec
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
GO
select transaction_isolation_level from sys.dm_exec_sessions where session_id=@@SPID
GO
~~START~~
smallint
1
~~END~~

DECLARE @handle int;
EXEC SP_PREPARE @handle output, NULL, N'exec sys.sp_reset_connection'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my previous comments, we have still not added RPC tests

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my previous comments, we have still not added RPC tests

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I see the these are added in .net

EXEC SP_EXECUTE @handle
GO
GO
select transaction_isolation_level from sys.dm_exec_sessions where session_id=@@SPID
GO
~~START~~
smallint
2
~~END~~

56 changes: 56 additions & 0 deletions test/JDBC/input/storedProcedures/Test-sp_reset_connection.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
-- 1. Test resets GUC variables
SET lock_timeout 0;
GO
SELECT @@lock_timeout;
GO
EXEC sys.sp_reset_connection
-- TODO: GUC is not resetting
SELECT @@lock_timeout;
GO

-- 2. Test open transactions are aborted on reset
DROP TABLE IF EXISTS sp_reset_connection_test_table;
CREATE TABLE sp_reset_connection_test_table(id int);
BEGIN TRANSACTION
INSERT INTO sp_reset_connection_test_table VALUES(1)
GO
EXEC sys.sp_reset_connection
GO
COMMIT TRANSACTION
GO
SELECT * FROM sp_reset_connection_test_table
GO

-- 3. Test temp tables are deleted on reset
CREATE TABLE #babel_temp_table (ID INT identity(1,1), Data INT)
INSERT INTO #babel_temp_table (Data) VALUES (100), (200), (300)
GO
SELECT * from #babel_temp_table
GO
EXEC sys.sp_reset_connection
GO
SELECT * from #babel_temp_table
GO

-- 4. Test isolation level is reset
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
GO
select transaction_isolation_level from sys.dm_exec_sessions where session_id=@@SPID
GO
EXEC sys.sp_reset_connection
GO
select transaction_isolation_level from sys.dm_exec_sessions where session_id=@@SPID
GO

-- 5. Test sp_reset_connection called with sp_prepexec
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
GO
select transaction_isolation_level from sys.dm_exec_sessions where session_id=@@SPID
GO
DECLARE @handle int;
EXEC SP_PREPARE @handle output, NULL, N'exec sys.sp_reset_connection'
EXEC SP_EXECUTE @handle
GO
GO
select transaction_isolation_level from sys.dm_exec_sessions where session_id=@@SPID
GO
1 change: 0 additions & 1 deletion test/JDBC/jdbc_schedule
Original file line number Diff line number Diff line change
Expand Up @@ -386,4 +386,3 @@ ignore#!#string_agg-before-14_5-vu-cleanup
ignore#!#string_agg_within-16_4-vu-prepare
ignore#!#string_agg_within-16_4-vu-verify
ignore#!#string_agg_within-16_4-vu-cleanup

36 changes: 36 additions & 0 deletions test/dotnet/ExpectedOutput/TestSpResetConnection.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#Q#DROP TABLE IF EXISTS sp_reset_connection_test_table;
#Q#CREATE TABLE sp_reset_connection_test_table(id int);
#Q#INSERT INTO sp_reset_connection_test_table VALUES(1)
#Q#INSERT INTO sp_reset_connection_test_table VALUES(2)
#Q#sys.sp_reset_connection
#Q#SELECT * FROM sp_reset_connection_test_table
#D#int
1
#Q#CREATE TABLE #babel_temp_table (ID INT identity(1,1), Data INT)
#Q#INSERT INTO #babel_temp_table (Data) VALUES (100), (200), (300)
#Q#SELECT * from #babel_temp_table
#D#int#!#int
1#!#100
2#!#200
3#!#300
#Q#sys.sp_reset_connection
#Q#SELECT * from #babel_temp_table
#E#relation "#babel_temp_table" does not exist
#Q#select current_setting('transaction_isolation')
#D#text
repeatable read
#Q#sys.sp_reset_connection
#Q#select current_setting('transaction_isolation')
#D#text
read committed
#Q#CREATE TABLE #babel_temp_table (ID INT identity(1,1), Data INT)
#Q#INSERT INTO #babel_temp_table (Data) VALUES (100), (200), (300)
#Q#SELECT * from #babel_temp_table
#D#int#!#int
1#!#100
2#!#200
3#!#300
#Q#sys.sp_reset_connection
#Q#sys.sp_reset_connection
#Q#SELECT * from #babel_temp_table
#E#relation "#babel_temp_table" does not exist
35 changes: 35 additions & 0 deletions test/dotnet/input/Storedproc/TestSpResetConnection.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Test (1): Test abort open transaction
DROP TABLE IF EXISTS sp_reset_connection_test_table;
CREATE TABLE sp_reset_connection_test_table(id int);
INSERT INTO sp_reset_connection_test_table VALUES(1)
txn#!#begin
INSERT INTO sp_reset_connection_test_table VALUES(2)
storedproc#!#prep#!#sys.sp_reset_connection#!#
txn#!#commit
SELECT * FROM sp_reset_connection_test_table
# Test (1): End

# Test (2): Test temp table deletion
CREATE TABLE #babel_temp_table (ID INT identity(1,1), Data INT)
INSERT INTO #babel_temp_table (Data) VALUES (100), (200), (300)
SELECT * from #babel_temp_table
storedproc#!#prep#!#sys.sp_reset_connection#!#
SELECT * from #babel_temp_table
# Test (2): End

# Test (3): Test reset of isolation level
txn#!#begin#!#isolation#!#ss
select current_setting('transaction_isolation')
storedproc#!#prep#!#sys.sp_reset_connection#!#
select current_setting('transaction_isolation')
txn#!#commit
# Test (3): End

# Test (4): Test prepexec sp_reset_connection
CREATE TABLE #babel_temp_table (ID INT identity(1,1), Data INT)
INSERT INTO #babel_temp_table (Data) VALUES (100), (200), (300)
SELECT * from #babel_temp_table
prepst#!#sys.sp_reset_connection#!#
prepst#!#exec#!#
SELECT * from #babel_temp_table
# Test (4): End
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ Could not find upgrade tests for procedure sys.sp_cursor_list
Could not find upgrade tests for procedure sys.sp_describe_cursor
Could not find upgrade tests for procedure sys.sp_oledb_ro_usrname
Could not find upgrade tests for procedure sys.sp_prepare
Could not find upgrade tests for procedure sys.sp_reset_connection
Could not find upgrade tests for procedure sys.sp_unprepare
Could not find upgrade tests for procedure sys.sp_updatestats
Could not find upgrade tests for table sys.babelfish_configurations
Expand Down
Loading