Repository: meltano/sdk
Pull request #2548 (2024-07-19 03:23:12)

test: Add (DuckDB) SQL sink tests


<!-- readthedocs-preview meltano-sdk start -->
----
📚 Documentation preview 📚: https://meltano-sdk--2548.org.readthedocs.build/en/2548/

<!-- readthedocs-preview meltano-sdk end -->

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/meltano/sdk/pull/2548?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=meltano) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 89.42%. Comparing base [(`6811b31`)](https://app.codecov.io/gh/meltano/sdk/commit/6811b319d9d189fb528883d0f8643585fd58fdc7?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=meltano) to head [(`2796f08`)](https://app.codecov.io/gh/meltano/sdk/commit/2796f0808116db109753e4af98b42143613cf578?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=meltano).
> Report is 1 commits behind head on main.

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##             main    #2548   +/-   ##
=======================================
  Coverage   89.42%   89.42%           
=======================================
  Files          58       58           
  Lines        4783     4783           
  Branches      933      933           
=======================================
  Hits         4277     4277           
  Misses        353      353           
  Partials      153      153           
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/meltano/sdk/pull/2548?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=meltano).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=meltano).

codspeed-hq[bot]: ## [CodSpeed Performance Report](https://codspeed.io/meltano/sdk/branches/edgarrmondragon/test/add-sql-sink-tests)

### Merging #2548 will **not alter performance**

<sub>Comparing <code>edgarrmondragon/test/add-sql-sink-tests</code> (2796f08) with <code>main</code> (6811b31)</sub>



### Summary

`✅ 6` untouched benchmarks






Patch:
diff --git a/samples/sample_duckdb/__init__.py b/samples/sample_duckdb/__init__.py
new file mode 100644
index 00000000..bbfa0772
--- /dev/null
+++ b/samples/sample_duckdb/__init__.py
@@ -0,0 +1,7 @@
+from __future__ import annotations
+
+from .connector import DuckDBConnector
+
+__all__ = [
+    "DuckDBConnector",
+]
diff --git a/samples/sample_duckdb/connector.py b/samples/sample_duckdb/connector.py
new file mode 100644
index 00000000..e8c6c251
--- /dev/null
+++ b/samples/sample_duckdb/connector.py
@@ -0,0 +1,24 @@
+from __future__ import annotations
+
+import sqlalchemy as sa
+
+from singer_sdk.connectors import SQLConnector
+
+
+class DuckDBConnector(SQLConnector):
+    allow_column_alter = True
+
+    @staticmethod
+    def get_column_alter_ddl(
+        table_name: str,
+        column_name: str,
+        column_type: sa.types.TypeEngine,
+    ) -> sa.DDL:
+        return sa.DDL(
+            "ALTER TABLE %(table_name)s ALTER COLUMN %(column_name)s TYPE %(column_type)s",  # noqa: E501
+            {
+                "table_name": table_name,
+                "column_name": column_name,
+                "column_type": column_type,
+            },
+        )


Test patch:
diff --git a/tests/core/sinks/test_sql_sink.py b/tests/core/sinks/test_sql_sink.py
new file mode 100644
index 00000000..c20be40f
--- /dev/null
+++ b/tests/core/sinks/test_sql_sink.py
@@ -0,0 +1,64 @@
+from __future__ import annotations
+
+import typing as t
+from textwrap import dedent
+
+import pytest
+
+from samples.sample_duckdb import DuckDBConnector
+from singer_sdk.sinks.sql import SQLSink
+from singer_sdk.target_base import SQLTarget
+
+
+class DuckDBSink(SQLSink):
+    connector_class = DuckDBConnector
+
+
+class DuckDBTarget(SQLTarget):
+    """DuckDB target class."""
+
+    name = "sql-target-mock"
+    config_jsonschema: t.ClassVar[dict] = {"type": "object", "properties": {}}
+    default_sink_class = DuckDBSink
+
+
+class TestDuckDBSink:
+    @pytest.fixture
+    def target(self) -> DuckDBTarget:
+        return DuckDBTarget(config={"sqlalchemy_url": "duckdb:///"})
+
+    @pytest.fixture
+    def schema(self) -> dict:
+        return {
+            "properties": {
+                "id": {
+                    "type": ["string", "null"],
+                },
+                "col_ts": {
+                    "format": "date-time",
+                    "type": ["string", "null"],
+                },
+                "table": {
+                    "type": ["string", "null"],
+                },
+            },
+        }
+
+    @pytest.fixture
+    def sink(self, target: DuckDBTarget, schema: dict) -> DuckDBSink:
+        return DuckDBSink(
+            target,
+            stream_name="foo",
+            schema=schema,
+            key_properties=["id"],
+        )
+
+    def test_generate_insert_statement(self, sink: DuckDBSink, schema: dict):
+        """Test that the insert statement is generated correctly."""
+        expected = dedent(
+            """\
+            INSERT INTO foo
+            (id, col_ts, "table")
+            VALUES (:id, :col_ts, :table)"""
+        )
+        assert sink.generate_insert_statement("foo", schema=schema) == expected
diff --git a/tests/core/test_connector_sql.py b/tests/core/test_connector_sql.py
index ff3ac573..10ee0c0f 100644
--- a/tests/core/test_connector_sql.py
+++ b/tests/core/test_connector_sql.py
@@ -8,6 +8,7 @@ import pytest
 import sqlalchemy as sa
 from sqlalchemy.dialects import registry, sqlite
 
+from samples.sample_duckdb import DuckDBConnector
 from singer_sdk.connectors import SQLConnector
 from singer_sdk.exceptions import ConfigValidationError
 
@@ -289,25 +290,6 @@ class TestConnectorSQL:  # noqa: PLR0904
             ]
 
 
-class DuckDBConnector(SQLConnector):
-    allow_column_alter = True
-
-    @staticmethod
-    def get_column_alter_ddl(
-        table_name: str,
-        column_name: str,
-        column_type: sa.types.TypeEngine,
-    ) -> sa.DDL:
-        return sa.DDL(
-            "ALTER TABLE %(table_name)s ALTER COLUMN %(column_name)s TYPE %(column_type)s",  # noqa: E501
-            {
-                "table_name": table_name,
-                "column_name": column_name,
-                "column_type": column_type,
-            },
-        )
-
-
 class TestDuckDBConnector:
     @pytest.fixture
     def connector(self):