|
51 | 51 |
|
52 | 52 | from tests.e2e.common.uc_volume_tests import PySQLUCVolumeTestSuiteMixin |
53 | 53 |
|
54 | | -from databricks.sql.exc import SessionAlreadyClosedError, CursorAlreadyClosedError |
| 54 | +from databricks.sql.exc import SessionAlreadyClosedError |
55 | 55 |
|
56 | 56 | log = logging.getLogger(__name__) |
57 | 57 |
|
@@ -809,142 +809,6 @@ def test_catalogs_returns_arrow_table(self): |
809 | 809 | results = cursor.fetchall_arrow() |
810 | 810 | assert isinstance(results, pyarrow.Table) |
811 | 811 |
|
812 | | - def test_close_connection_closes_cursors(self): |
813 | | - |
814 | | - from databricks.sql.thrift_api.TCLIService import ttypes |
815 | | - |
816 | | - with self.connection() as conn: |
817 | | - cursor = conn.cursor() |
818 | | - cursor.execute( |
819 | | - "SELECT id, id `id2`, id `id3` FROM RANGE(1000000) order by RANDOM()" |
820 | | - ) |
821 | | - ars = cursor.active_result_set |
822 | | - |
823 | | - # We must manually run this check because thrift_backend always forces `has_been_closed_server_side` to True |
824 | | - # Cursor op state should be open before connection is closed |
825 | | - status_request = ttypes.TGetOperationStatusReq( |
826 | | - operationHandle=ars.command_id.to_thrift_handle(), |
827 | | - getProgressUpdate=False, |
828 | | - ) |
829 | | - op_status_at_server = ars.backend._client.GetOperationStatus(status_request) |
830 | | - assert op_status_at_server.operationState != CommandState.CLOSED |
831 | | - |
832 | | - conn.close() |
833 | | - |
834 | | - # When connection closes, any cursor operations should no longer exist at the server |
835 | | - with pytest.raises(SessionAlreadyClosedError) as cm: |
836 | | - op_status_at_server = ars.backend._client.GetOperationStatus( |
837 | | - status_request |
838 | | - ) |
839 | | - |
840 | | - def test_closing_a_closed_connection_doesnt_fail(self, caplog): |
841 | | - caplog.set_level(logging.DEBUG) |
842 | | - # Second .close() call is when this context manager exits |
843 | | - with self.connection() as conn: |
844 | | - # First .close() call is explicit here |
845 | | - conn.close() |
846 | | - assert "Session appears to have been closed already" in caplog.text |
847 | | - |
848 | | - conn = None |
849 | | - try: |
850 | | - with pytest.raises(KeyboardInterrupt): |
851 | | - with self.connection() as c: |
852 | | - conn = c |
853 | | - raise KeyboardInterrupt("Simulated interrupt") |
854 | | - finally: |
855 | | - if conn is not None: |
856 | | - assert ( |
857 | | - not conn.open |
858 | | - ), "Connection should be closed after KeyboardInterrupt" |
859 | | - |
860 | | - def test_cursor_close_properly_closes_operation(self): |
861 | | - """Test that Cursor.close() properly closes the active operation handle on the server.""" |
862 | | - with self.connection() as conn: |
863 | | - cursor = conn.cursor() |
864 | | - try: |
865 | | - cursor.execute("SELECT 1 AS test") |
866 | | - assert cursor.active_command_id is not None |
867 | | - cursor.close() |
868 | | - assert cursor.active_command_id is None |
869 | | - assert not cursor.open |
870 | | - finally: |
871 | | - if cursor.open: |
872 | | - cursor.close() |
873 | | - |
874 | | - conn = None |
875 | | - cursor = None |
876 | | - try: |
877 | | - with self.connection() as c: |
878 | | - conn = c |
879 | | - with pytest.raises(KeyboardInterrupt): |
880 | | - with conn.cursor() as cur: |
881 | | - cursor = cur |
882 | | - raise KeyboardInterrupt("Simulated interrupt") |
883 | | - finally: |
884 | | - if cursor is not None: |
885 | | - assert ( |
886 | | - not cursor.open |
887 | | - ), "Cursor should be closed after KeyboardInterrupt" |
888 | | - |
889 | | - def test_nested_cursor_context_managers(self): |
890 | | - """Test that nested cursor context managers properly close operations on the server.""" |
891 | | - with self.connection() as conn: |
892 | | - with conn.cursor() as cursor1: |
893 | | - cursor1.execute("SELECT 1 AS test1") |
894 | | - assert cursor1.active_command_id is not None |
895 | | - |
896 | | - with conn.cursor() as cursor2: |
897 | | - cursor2.execute("SELECT 2 AS test2") |
898 | | - assert cursor2.active_command_id is not None |
899 | | - |
900 | | - # After inner context manager exit, cursor2 should be not open |
901 | | - assert not cursor2.open |
902 | | - assert cursor2.active_command_id is None |
903 | | - |
904 | | - # After outer context manager exit, cursor1 should be not open |
905 | | - assert not cursor1.open |
906 | | - assert cursor1.active_command_id is None |
907 | | - |
908 | | - def test_cursor_error_handling(self): |
909 | | - """Test that cursor close handles errors properly to prevent orphaned operations.""" |
910 | | - with self.connection() as conn: |
911 | | - cursor = conn.cursor() |
912 | | - |
913 | | - cursor.execute("SELECT 1 AS test") |
914 | | - |
915 | | - op_handle = cursor.active_command_id |
916 | | - |
917 | | - assert op_handle is not None |
918 | | - |
919 | | - # Manually close the operation to simulate server-side closure |
920 | | - conn.session.backend.close_command(op_handle) |
921 | | - |
922 | | - cursor.close() |
923 | | - |
924 | | - assert not cursor.open |
925 | | - |
926 | | - def test_result_set_close(self): |
927 | | - """Test that ResultSet.close() properly closes operations on the server and handles state correctly.""" |
928 | | - with self.connection() as conn: |
929 | | - cursor = conn.cursor() |
930 | | - try: |
931 | | - cursor.execute("SELECT * FROM RANGE(10)") |
932 | | - |
933 | | - result_set = cursor.active_result_set |
934 | | - assert result_set is not None |
935 | | - |
936 | | - initial_op_state = result_set.status |
937 | | - |
938 | | - result_set.close() |
939 | | - |
940 | | - assert result_set.status == CommandState.CLOSED |
941 | | - assert result_set.status != initial_op_state |
942 | | - |
943 | | - # Closing the result set again should be a no-op and not raise exceptions |
944 | | - result_set.close() |
945 | | - finally: |
946 | | - cursor.close() |
947 | | - |
948 | 812 |
|
949 | 813 | # use a RetrySuite to encapsulate these tests which we'll typically want to run together; however keep |
950 | 814 | # the 429/503 subsuites separate since they execute under different circumstances. |
|
0 commit comments