|
24 | 24 | pytestmark = [pytest.mark.engine, pytest.mark.mssql]
|
25 | 25 |
|
26 | 26 |
|
27 |
| -def test_columns(make_mocked_engine_adapter: t.Callable): |
28 |
| - adapter = make_mocked_engine_adapter(MSSQLEngineAdapter) |
| 27 | +@pytest.fixture |
| 28 | +def adapter(make_mocked_engine_adapter: t.Callable) -> MSSQLEngineAdapter: |
| 29 | + return make_mocked_engine_adapter(MSSQLEngineAdapter) |
| 30 | + |
29 | 31 |
|
| 32 | +def test_columns(adapter: MSSQLEngineAdapter): |
30 | 33 | adapter.cursor.fetchall.return_value = [
|
31 | 34 | ("decimal_ps", "decimal", None, 5, 4),
|
32 | 35 | ("decimal", "decimal", None, 18, 0),
|
@@ -504,7 +507,8 @@ def test_replace_query(make_mocked_engine_adapter: t.Callable):
|
504 | 507 |
|
505 | 508 | assert to_sql_calls(adapter) == [
|
506 | 509 | """SELECT 1 FROM [information_schema].[tables] WHERE [table_name] = 'test_table';""",
|
507 |
| - "MERGE INTO [test_table] AS [__MERGE_TARGET__] USING (SELECT [a] AS [a] FROM [tbl]) AS [__MERGE_SOURCE__] ON (1 = 0) WHEN NOT MATCHED BY SOURCE THEN DELETE WHEN NOT MATCHED THEN INSERT ([a]) VALUES ([a]);", |
| 510 | + "TRUNCATE TABLE [test_table];", |
| 511 | + "INSERT INTO [test_table] ([a]) SELECT [a] FROM [tbl];", |
508 | 512 | ]
|
509 | 513 |
|
510 | 514 |
|
@@ -551,7 +555,8 @@ def temp_table_exists(table: exp.Table) -> bool:
|
551 | 555 |
|
552 | 556 | assert to_sql_calls(adapter) == [
|
553 | 557 | f"""IF NOT EXISTS (SELECT * FROM information_schema.tables WHERE table_name = '{temp_table_name}') EXEC('CREATE TABLE [{temp_table_name}] ([a] INTEGER, [b] INTEGER)');""",
|
554 |
| - "MERGE INTO [test_table] AS [__MERGE_TARGET__] USING (SELECT CAST([a] AS INTEGER) AS [a], CAST([b] AS INTEGER) AS [b] FROM [__temp_test_table_abcdefgh]) AS [__MERGE_SOURCE__] ON (1 = 0) WHEN NOT MATCHED BY SOURCE THEN DELETE WHEN NOT MATCHED THEN INSERT ([a], [b]) VALUES ([a], [b]);", |
| 558 | + "TRUNCATE TABLE [test_table];", |
| 559 | + f"INSERT INTO [test_table] ([a], [b]) SELECT CAST([a] AS INTEGER) AS [a], CAST([b] AS INTEGER) AS [b] FROM [{temp_table_name}];", |
555 | 560 | f"DROP TABLE IF EXISTS [{temp_table_name}];",
|
556 | 561 | ]
|
557 | 562 |
|
@@ -751,3 +756,68 @@ def test_create_table_from_query(make_mocked_engine_adapter: t.Callable, mocker:
|
751 | 756 | "CREATE VIEW [__temp_ctas_test_random_id] AS SELECT * FROM (SELECT TOP 1 * FROM [t]);"
|
752 | 757 | in to_sql_calls(adapter)
|
753 | 758 | )
|
| 759 | + |
| 760 | + |
| 761 | +def test_replace_query_strategy(adapter: MSSQLEngineAdapter, mocker: MockerFixture): |
| 762 | + # ref issue 4472: https://github.com/TobikoData/sqlmesh/issues/4472 |
| 763 | + # The FULL strategy calls EngineAdapter.replace_query() which calls _insert_overwrite_by_condition() should use DELETE+INSERT and not MERGE |
| 764 | + expressions = d.parse( |
| 765 | + f""" |
| 766 | + MODEL ( |
| 767 | + name db.table, |
| 768 | + kind FULL, |
| 769 | + dialect tsql |
| 770 | + ); |
| 771 | +
|
| 772 | + select a, b from db.upstream_table; |
| 773 | + """ |
| 774 | + ) |
| 775 | + model = load_sql_based_model(expressions) |
| 776 | + |
| 777 | + exists_mock = mocker.patch( |
| 778 | + "sqlmesh.core.engine_adapter.mssql.MSSQLEngineAdapter.table_exists", |
| 779 | + return_value=False, |
| 780 | + ) |
| 781 | + |
| 782 | + assert not adapter.table_exists("test_table") |
| 783 | + |
| 784 | + # initial - table doesnt exist |
| 785 | + adapter.replace_query( |
| 786 | + "test_table", |
| 787 | + model.render_query_or_raise(), |
| 788 | + table_format=model.table_format, |
| 789 | + storage_format=model.storage_format, |
| 790 | + partitioned_by=model.partitioned_by, |
| 791 | + partition_interval_unit=model.partition_interval_unit, |
| 792 | + clustered_by=model.clustered_by, |
| 793 | + table_properties=model.physical_properties, |
| 794 | + table_description=model.description, |
| 795 | + column_descriptions=model.column_descriptions, |
| 796 | + columns_to_types=model.columns_to_types_or_raise, |
| 797 | + ) |
| 798 | + |
| 799 | + # subsequent - table exists |
| 800 | + exists_mock.return_value = True |
| 801 | + assert adapter.table_exists("test_table") |
| 802 | + |
| 803 | + adapter.replace_query( |
| 804 | + "test_table", |
| 805 | + model.render_query_or_raise(), |
| 806 | + table_format=model.table_format, |
| 807 | + storage_format=model.storage_format, |
| 808 | + partitioned_by=model.partitioned_by, |
| 809 | + partition_interval_unit=model.partition_interval_unit, |
| 810 | + clustered_by=model.clustered_by, |
| 811 | + table_properties=model.physical_properties, |
| 812 | + table_description=model.description, |
| 813 | + column_descriptions=model.column_descriptions, |
| 814 | + columns_to_types=model.columns_to_types_or_raise, |
| 815 | + ) |
| 816 | + |
| 817 | + assert to_sql_calls(adapter) == [ |
| 818 | + # initial - create table if not exists |
| 819 | + "IF NOT EXISTS (SELECT * FROM information_schema.tables WHERE table_name = 'test_table') EXEC('SELECT * INTO [test_table] FROM (SELECT [a] AS [a], [b] AS [b] FROM [db].[upstream_table] AS [upstream_table]) AS temp');", |
| 820 | + # subsequent - truncate + insert |
| 821 | + "TRUNCATE TABLE [test_table];", |
| 822 | + "INSERT INTO [test_table] ([a], [b]) SELECT [a] AS [a], [b] AS [b] FROM [db].[upstream_table] AS [upstream_table];", |
| 823 | + ] |
0 commit comments