@@ -134,113 +134,6 @@ def test_metadata_catalog_escaping(
134134 assert getattr (request , thrift_field ) == value
135135
136136
137- @pytest .mark .skipif (pyarrow is None , reason = "PyArrow is not installed" )
138- @pytest .mark .parametrize (
139- "operation_state,count,expected_count" ,
140- [
141- (ttypes .TOperationState .FINISHED_STATE , 7 , 7 ),
142- (ttypes .TOperationState .FINISHED_STATE , 0 , 0 ),
143- (ttypes .TOperationState .FINISHED_STATE , None , None ),
144- (ttypes .TOperationState .RUNNING_STATE , 7 , None ),
145- ],
146- )
147- @pytest .mark .parametrize ("cache_status" , [True , False ])
148- def test_async_result_reads_only_terminal_status_count_and_preserves_rows (
149- operation_state , count , expected_count , cache_status
150- ):
151- with (
152- patch (
153- "databricks.sql.backend.thrift_backend.TCLIService.Client" , autospec = True
154- ),
155- patch ("databricks.sql.backend.thrift_backend.ThriftResultSet" ) as result_set ,
156- ):
157- backend = ThriftDatabricksClient (
158- "foobar" ,
159- 443 ,
160- "path" ,
161- [],
162- auth_provider = AuthProvider (),
163- ssl_options = SSLOptions (),
164- http_client = MagicMock (),
165- )
166- operation_status = ttypes .TGetOperationStatusResp (
167- status = ThriftBackendTestSuite .okay_status ,
168- operationState = operation_state ,
169- numModifiedRows = count ,
170- )
171- backend ._poll_for_status = Mock (return_value = operation_status )
172- metadata = ttypes .TGetResultSetMetadataResp (
173- schema = ttypes .TTableSchema (columns = []),
174- arrowSchema = pyarrow .schema ([]).serialize ().to_pybytes (),
175- resultFormat = ttypes .TSparkRowSetType .ARROW_BASED_SET ,
176- )
177- backend .make_request = Mock (
178- return_value = Mock (
179- resultSetMetadata = metadata ,
180- results = sentinel .counter_rows ,
181- hasMoreRows = False ,
182- )
183- )
184- cid = CommandId .from_thrift_handle (ThriftBackendTestSuite .operation_handle )
185- if cache_status :
186- expected_state = (
187- CommandState .SUCCEEDED
188- if operation_state == ttypes .TOperationState .FINISHED_STATE
189- else CommandState .RUNNING
190- )
191- assert backend .get_query_state (cid ) == expected_state
192- backend .get_execution_result (cid , Mock ())
193-
194- expected_polls = (
195- 2
196- if cache_status and operation_state == ttypes .TOperationState .RUNNING_STATE
197- else 1
198- )
199- assert backend ._poll_for_status .call_count == expected_polls
200- backend ._poll_for_status .assert_called_with (cid .to_thrift_handle ())
201- response = result_set .call_args .kwargs ["execute_response" ]
202- assert response .num_modified_rows == expected_count
203- assert result_set .call_args .kwargs ["t_row_set" ] is sentinel .counter_rows
204-
205-
206- @pytest .mark .parametrize (
207- "operation_state,exception_type" ,
208- [
209- (ttypes .TOperationState .ERROR_STATE , ServerOperationError ),
210- (ttypes .TOperationState .CLOSED_STATE , DatabaseError ),
211- ],
212- )
213- def test_async_result_rejects_terminal_error_state_before_fetch (
214- operation_state , exception_type
215- ):
216- with patch (
217- "databricks.sql.backend.thrift_backend.TCLIService.Client" , autospec = True
218- ):
219- backend = ThriftDatabricksClient (
220- "foobar" ,
221- 443 ,
222- "path" ,
223- [],
224- auth_provider = AuthProvider (),
225- ssl_options = SSLOptions (),
226- http_client = MagicMock (),
227- )
228- backend ._poll_for_status = Mock (
229- return_value = ttypes .TGetOperationStatusResp (
230- status = ThriftBackendTestSuite .okay_status ,
231- operationState = operation_state ,
232- errorMessage = "async operation failed" ,
233- )
234- )
235- backend .make_request = Mock ()
236- cid = CommandId .from_thrift_handle (ThriftBackendTestSuite .operation_handle )
237-
238- with pytest .raises (exception_type ):
239- backend .get_execution_result (cid , Mock ())
240-
241- backend .make_request .assert_not_called ()
242-
243-
244137@pytest .mark .skipif (pyarrow is None , reason = "PyArrow is not installed" )
245138class ThriftBackendTestSuite (unittest .TestCase ):
246139 okay_status = ttypes .TStatus (statusCode = ttypes .TStatusCode .SUCCESS_STATUS )
@@ -320,6 +213,64 @@ def _make_fake_thrift_backend(self):
320213 thrift_backend ._create_arrow_table .return_value = (MagicMock (), Mock ())
321214 return thrift_backend
322215
216+ @patch ("databricks.sql.backend.thrift_backend.ThriftResultSet" )
217+ @patch ("databricks.sql.backend.thrift_backend.TCLIService.Client" , autospec = True )
218+ def test_async_result_rowcount (self , tcli_service_class , result_set ):
219+ for state , count , expected_count , polled in [
220+ (ttypes .TOperationState .FINISHED_STATE , 7 , 7 , True ),
221+ (ttypes .TOperationState .FINISHED_STATE , 0 , 0 , True ),
222+ (ttypes .TOperationState .FINISHED_STATE , None , None , True ),
223+ (ttypes .TOperationState .FINISHED_STATE , 7 , 7 , False ),
224+ (ttypes .TOperationState .RUNNING_STATE , 7 , None , False ),
225+ ]:
226+ with self .subTest (state = state , count = count , polled = polled ):
227+ backend = self ._make_fake_thrift_backend ()
228+ backend ._poll_for_status = Mock (
229+ return_value = ttypes .TGetOperationStatusResp (
230+ status = self .okay_status ,
231+ operationState = state ,
232+ numModifiedRows = count ,
233+ )
234+ )
235+ backend .make_request = Mock (
236+ return_value = Mock (
237+ resultSetMetadata = self .metadata_resp ,
238+ results = sentinel .counter_rows ,
239+ hasMoreRows = False ,
240+ )
241+ )
242+ cid = CommandId .from_thrift_handle (self .operation_handle )
243+ if polled :
244+ self .assertEqual (
245+ backend .get_query_state (cid ), CommandState .SUCCEEDED
246+ )
247+ backend .get_execution_result (cid , Mock ())
248+
249+ backend ._poll_for_status .assert_called_once_with (cid .to_thrift_handle ())
250+ response = result_set .call_args .kwargs ["execute_response" ]
251+ self .assertEqual (response .num_modified_rows , expected_count )
252+ self .assertIs (
253+ result_set .call_args .kwargs ["t_row_set" ], sentinel .counter_rows
254+ )
255+
256+ @patch ("databricks.sql.backend.thrift_backend.TCLIService.Client" , autospec = True )
257+ def test_async_result_checks_status_before_fetch (self , tcli_service_class ):
258+ backend = self ._make_fake_thrift_backend ()
259+ backend ._poll_for_status = Mock (
260+ return_value = ttypes .TGetOperationStatusResp (
261+ status = self .okay_status ,
262+ operationState = ttypes .TOperationState .ERROR_STATE ,
263+ errorMessage = "async operation failed" ,
264+ )
265+ )
266+ backend .make_request = Mock ()
267+ cid = CommandId .from_thrift_handle (self .operation_handle )
268+
269+ with self .assertRaises (ServerOperationError ):
270+ backend .get_execution_result (cid , Mock ())
271+
272+ backend .make_request .assert_not_called ()
273+
323274 def test_hive_schema_to_arrow_schema_preserves_column_names (self ):
324275 columns = [
325276 ttypes .TColumnDesc (
0 commit comments