|
13 | 13 | from synapseclient.api import ViewEntityType, ViewTypeMask |
14 | 14 | from synapseclient.core.constants.concrete_types import ( |
15 | 15 | QUERY_BUNDLE_REQUEST, |
| 16 | + QUERY_RESULT, |
16 | 17 | QUERY_TABLE_CSV_REQUEST, |
17 | 18 | ) |
18 | 19 | from synapseclient.core.utils import MB |
|
34 | 35 | ViewUpdateMixin, |
35 | 36 | _query_table_csv, |
36 | 37 | _query_table_next_page, |
| 38 | + _query_table_row_set, |
37 | 39 | ) |
38 | 40 | from synapseclient.models.table_components import ( |
39 | 41 | ActionRequiredCount, |
@@ -2496,6 +2498,179 @@ def test_fill_from_dict_with_complete_response(self): |
2496 | 2498 | assert result.headers[1].id == "222" |
2497 | 2499 |
|
2498 | 2500 |
|
| 2501 | +class TestQueryTableRowSet: |
| 2502 | + """Test suite for the _query_table_row_set function.""" |
| 2503 | + |
| 2504 | + @pytest.fixture |
| 2505 | + def mock_synapse_client(self): |
| 2506 | + """Mock Synapse client for testing.""" |
| 2507 | + mock_client = MagicMock() |
| 2508 | + return mock_client |
| 2509 | + |
| 2510 | + @pytest.fixture |
| 2511 | + def sample_query_result_bundle(self): |
| 2512 | + """Sample QueryResultBundle response.""" |
| 2513 | + return QueryResultBundle( |
| 2514 | + query_result=QueryResult( |
| 2515 | + concrete_type=QUERY_RESULT, |
| 2516 | + query_results=RowSet( |
| 2517 | + table_id="syn123456", |
| 2518 | + etag="test-etag", |
| 2519 | + headers=[ |
| 2520 | + SelectColumn( |
| 2521 | + name="test_col", column_type=ColumnType.STRING, id="242777" |
| 2522 | + ), |
| 2523 | + SelectColumn( |
| 2524 | + name="test_col2", column_type=ColumnType.STRING, id="242778" |
| 2525 | + ), |
| 2526 | + ], |
| 2527 | + rows=[ |
| 2528 | + Row( |
| 2529 | + row_id=1, |
| 2530 | + version_number=1, |
| 2531 | + etag=None, |
| 2532 | + values=["random string1", "random string2"], |
| 2533 | + ) |
| 2534 | + ], |
| 2535 | + ), |
| 2536 | + next_page_token=None, |
| 2537 | + ), |
| 2538 | + query_count=1, |
| 2539 | + select_columns=[ |
| 2540 | + SelectColumn(name="col1", column_type=ColumnType.STRING, id="111"), |
| 2541 | + SelectColumn(name="col2", column_type=ColumnType.INTEGER, id="222"), |
| 2542 | + ], |
| 2543 | + max_rows_per_page=1000, |
| 2544 | + column_models=[ |
| 2545 | + Column( |
| 2546 | + id="242777", |
| 2547 | + name="test_col", |
| 2548 | + column_type=ColumnType.STRING, |
| 2549 | + facet_type=None, |
| 2550 | + default_value=None, |
| 2551 | + maximum_size=50, |
| 2552 | + maximum_list_length=None, |
| 2553 | + enum_values=None, |
| 2554 | + json_sub_columns=None, |
| 2555 | + ), |
| 2556 | + Column( |
| 2557 | + id="242778", |
| 2558 | + name="test_col2", |
| 2559 | + column_type=ColumnType.STRING, |
| 2560 | + facet_type=None, |
| 2561 | + default_value=None, |
| 2562 | + maximum_size=50, |
| 2563 | + maximum_list_length=None, |
| 2564 | + enum_values=None, |
| 2565 | + json_sub_columns=None, |
| 2566 | + ), |
| 2567 | + ], |
| 2568 | + facets=[], |
| 2569 | + sum_file_sizes=SumFileSizes(sum_file_size_bytes=1024, greater_than=False), |
| 2570 | + last_updated_on="2025-08-26T21:38:31.677Z", |
| 2571 | + combined_sql="SELECT col1, col2 FROM syn123456", |
| 2572 | + actions_required=None, |
| 2573 | + ) |
| 2574 | + |
| 2575 | + @pytest.mark.asyncio |
| 2576 | + async def test_query_table_row_set_basic( |
| 2577 | + self, mock_synapse_client, sample_query_result_bundle |
| 2578 | + ): |
| 2579 | + """Test basic query_table_row_set functionality.""" |
| 2580 | + # GIVEN a query and mock response |
| 2581 | + query = "SELECT col1, col2 FROM syn123456" |
| 2582 | + |
| 2583 | + with ( |
| 2584 | + patch( |
| 2585 | + "synapseclient.models.mixins.table_components.extract_synapse_id_from_query", |
| 2586 | + return_value="syn123456", |
| 2587 | + ) as mock_extract_id, |
| 2588 | + patch.object( |
| 2589 | + QueryBundleRequest, |
| 2590 | + "send_job_and_wait_async", |
| 2591 | + return_value=sample_query_result_bundle, |
| 2592 | + ) as mock_send_job, |
| 2593 | + ): |
| 2594 | + # WHEN calling _query_table_row_set |
| 2595 | + result = await _query_table_row_set( |
| 2596 | + query=query, |
| 2597 | + synapse=mock_synapse_client, |
| 2598 | + ) |
| 2599 | + |
| 2600 | + # THEN verify the result |
| 2601 | + assert isinstance(result, QueryResultBundle) |
| 2602 | + assert result.query_count == 1 |
| 2603 | + assert result.query_result == sample_query_result_bundle.query_result |
| 2604 | + assert result.select_columns == sample_query_result_bundle.select_columns |
| 2605 | + assert result.sum_file_sizes == sample_query_result_bundle.sum_file_sizes |
| 2606 | + assert result.last_updated_on == sample_query_result_bundle.last_updated_on |
| 2607 | + assert result.combined_sql == sample_query_result_bundle.combined_sql |
| 2608 | + assert result.column_models == sample_query_result_bundle.column_models |
| 2609 | + assert result.facets == sample_query_result_bundle.facets |
| 2610 | + assert ( |
| 2611 | + result.actions_required == sample_query_result_bundle.actions_required |
| 2612 | + ) |
| 2613 | + |
| 2614 | + # Verify extract_synapse_id_from_query was called correctly |
| 2615 | + mock_extract_id.assert_called_once_with(query) |
| 2616 | + |
| 2617 | + # Verify send_job_and_wait_async was called correctly |
| 2618 | + mock_send_job.assert_called_once_with(synapse_client=mock_synapse_client) |
| 2619 | + |
| 2620 | + @pytest.mark.asyncio |
| 2621 | + async def test_query_table_row_set_with_parameters( |
| 2622 | + self, mock_synapse_client, sample_query_result_bundle |
| 2623 | + ): |
| 2624 | + """Test _query_table_row_set with all optional parameters.""" |
| 2625 | + # GIVEN a query with all parameters |
| 2626 | + query = "SELECT col1, col2 FROM syn123456" |
| 2627 | + limit = 100 |
| 2628 | + offset = 50 |
| 2629 | + part_mask = 0x1 | 0x2 | 0x4 # Query results + count + select columns |
| 2630 | + |
| 2631 | + with ( |
| 2632 | + patch( |
| 2633 | + "synapseclient.models.mixins.table_components.extract_synapse_id_from_query", |
| 2634 | + return_value="syn123456", |
| 2635 | + ) as mock_extract_id, |
| 2636 | + patch( |
| 2637 | + "synapseclient.models.mixins.table_components.Query" |
| 2638 | + ) as mock_query_class, |
| 2639 | + patch.object( |
| 2640 | + QueryBundleRequest, |
| 2641 | + "send_job_and_wait_async", |
| 2642 | + return_value=sample_query_result_bundle, |
| 2643 | + ) as mock_send_job, |
| 2644 | + ): |
| 2645 | + # Create mock instances |
| 2646 | + mock_query_instance = MagicMock() |
| 2647 | + mock_query_class.return_value = mock_query_instance |
| 2648 | + |
| 2649 | + # WHEN calling _query_table_row_set with parameters |
| 2650 | + result = await _query_table_row_set( |
| 2651 | + query=query, |
| 2652 | + synapse=mock_synapse_client, |
| 2653 | + limit=limit, |
| 2654 | + offset=offset, |
| 2655 | + part_mask=part_mask, |
| 2656 | + ) |
| 2657 | + # THEN verify the Query was created with correct parameters |
| 2658 | + mock_query_class.assert_called_once_with( |
| 2659 | + sql=query, |
| 2660 | + include_entity_etag=True, |
| 2661 | + limit=limit, |
| 2662 | + offset=offset, |
| 2663 | + ) |
| 2664 | + |
| 2665 | + # THEN verify the result structure |
| 2666 | + assert isinstance(result, QueryResultBundle) |
| 2667 | + assert result.query_count == 1 |
| 2668 | + assert result.query_result == sample_query_result_bundle.query_result |
| 2669 | + |
| 2670 | + # Verify the QueryBundleRequest was created with correct parameters |
| 2671 | + mock_send_job.assert_called_once_with(synapse_client=mock_synapse_client) |
| 2672 | + |
| 2673 | + |
2499 | 2674 | class TestQueryTableNextPage: |
2500 | 2675 | """Test suite for the _query_table_next_page function.""" |
2501 | 2676 |
|
|
0 commit comments