You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by li...@apache.org on 2023/06/05 13:17:51 UTC

[arrow-adbc] branch main updated: test(python/adbc_driver_manager): add DuckDB integration test (#721)

This is an automated email from the ASF dual-hosted git repository.

lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git


The following commit(s) were added to refs/heads/main by this push:
     new 5504963d test(python/adbc_driver_manager): add DuckDB integration test (#721)
5504963d is described below

commit 5504963d798b3db944c075217c39ad19200ba8b7
Author: David Li <li...@gmail.com>
AuthorDate: Mon Jun 5 09:17:44 2023 -0400

    test(python/adbc_driver_manager): add DuckDB integration test (#721)
    
    Fixes #719.
---
 ci/conda_env_python.txt                         |  1 +
 ci/scripts/python_util.sh                       |  2 +-
 ci/scripts/python_wheel_windows_test.bat        |  2 +-
 python/adbc_driver_manager/pyproject.toml       |  3 +-
 python/adbc_driver_manager/tests/test_duckdb.py | 97 +++++++++++++++++++++++++
 5 files changed, 102 insertions(+), 3 deletions(-)

diff --git a/ci/conda_env_python.txt b/ci/conda_env_python.txt
index 46690ee6..b5348b04 100644
--- a/ci/conda_env_python.txt
+++ b/ci/conda_env_python.txt
@@ -23,3 +23,4 @@ setuptools
 
 # For integration testing
 polars
+python-duckdb
diff --git a/ci/scripts/python_util.sh b/ci/scripts/python_util.sh
index 144c561c..635e50e5 100644
--- a/ci/scripts/python_util.sh
+++ b/ci/scripts/python_util.sh
@@ -147,7 +147,7 @@ import $component.dbapi
 
         # --import-mode required, else tries to import from the source dir instead of installed package
         if [[ "${component}" = "adbc_driver_manager" ]]; then
-            export PYTEST_ADDOPTS="-k 'not sqlite'"
+            export PYTEST_ADDOPTS="-k 'not duckdb and not sqlite'"
         elif [[ "${component}" = "adbc_driver_postgresql" ]]; then
             export PYTEST_ADDOPTS="-k 'not polars'"
         fi
diff --git a/ci/scripts/python_wheel_windows_test.bat b/ci/scripts/python_wheel_windows_test.bat
index 744bbc4b..f598fbbd 100644
--- a/ci/scripts/python_wheel_windows_test.bat
+++ b/ci/scripts/python_wheel_windows_test.bat
@@ -35,5 +35,5 @@ FOR %%c IN (adbc_driver_manager adbc_driver_flightsql adbc_driver_postgresql adb
     echo "=== Testing %%c ==="
     python -c "import %%c" || exit /B 1
     python -c "import %%c.dbapi" || exit /B 1
-    python -m pytest -vvx --import-mode append -k "not sqlite and not polars" %source_dir%\python\%%c\tests || exit /B 1
+    python -m pytest -vvx --import-mode append -k "not duckdb and not sqlite and not polars" %source_dir%\python\%%c\tests || exit /B 1
 )
diff --git a/python/adbc_driver_manager/pyproject.toml b/python/adbc_driver_manager/pyproject.toml
index d2f980fe..50cd31b5 100644
--- a/python/adbc_driver_manager/pyproject.toml
+++ b/python/adbc_driver_manager/pyproject.toml
@@ -25,7 +25,7 @@ dynamic = ["version"]
 
 [project.optional-dependencies]
 dbapi = ["pandas", "pyarrow>=8.0.0"]
-test = ["pandas", "pyarrow>=8.0.0", "pytest"]
+test = ["duckdb", "pandas", "pyarrow>=8.0.0", "pytest"]
 
 [project.urls]
 homepage = "https://arrow.apache.org"
@@ -37,6 +37,7 @@ build-backend = "setuptools.build_meta"
 
 [tool.pytest.ini_options]
 markers = [
+    "duckdb: tests that require DuckDB",
     "sqlite: tests that require the SQLite driver",
 ]
 
diff --git a/python/adbc_driver_manager/tests/test_duckdb.py b/python/adbc_driver_manager/tests/test_duckdb.py
new file mode 100644
index 00000000..ce66e158
--- /dev/null
+++ b/python/adbc_driver_manager/tests/test_duckdb.py
@@ -0,0 +1,97 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import sys
+
+import pyarrow
+import pytest
+
+from adbc_driver_manager import dbapi
+
+try:
+    import duckdb
+except ImportError:
+    pass
+
+pytestmark = pytest.mark.duckdb
+
+
+@pytest.fixture
+def conn():
+    if sys.platform.startswith("win"):
+        pytest.xfail("not supported on Windows")
+    with dbapi.connect(driver=duckdb.__file__, entrypoint="duckdb_adbc_init") as conn:
+        yield conn
+
+
+@pytest.mark.xfail
+def test_connection_get_info(conn):
+    assert conn.adbc_get_info() != {}
+
+
+def test_connection_get_objects(conn):
+    with conn.cursor() as cursor:
+        cursor.execute("CREATE TABLE getobjects (ints BIGINT)")
+    assert conn.adbc_get_objects(depth="all").read_all().to_pylist() != []
+
+
+@pytest.mark.xfail
+def test_connection_get_table_schema(conn):
+    with conn.cursor() as cursor:
+        cursor.execute("CREATE TABLE tableschema (ints BIGINT)")
+    assert conn.adbc_get_table_schema("tableschema") == pyarrow.schema(
+        [
+            ("ints", "int64"),
+        ]
+    )
+
+
+def test_connection_get_table_types(conn):
+    assert conn.adbc_get_table_types() == []
+
+
+@pytest.mark.xfail
+def test_statement_ingest(conn):
+    table = pyarrow.table(
+        [
+            [1, 2, 3, 4],
+            ["a", "b", None, "d"],
+        ],
+        names=["ints", "strs"],
+    )
+    with conn.cursor() as cursor:
+        cursor.adbc_ingest("ingest", table)
+        cursor.execute("SELECT * FROM ingest")
+        assert cursor.fetch_arrow_table() == table
+
+
+def test_statement_prepare(conn):
+    with conn.cursor() as cursor:
+        cursor.adbc_prepare("SELECT 1")
+        cursor.execute("SELECT 1")
+        assert cursor.fetchone() == (1,)
+        assert cursor.fetchone() is None
+
+
+def test_statement_query(conn):
+    with conn.cursor() as cursor:
+        cursor.execute("SELECT 1")
+        assert cursor.fetchone() == (1,)
+        assert cursor.fetchone() is None
+
+        cursor.execute("SELECT 1 AS foo")
+        assert cursor.fetch_arrow_table().to_pylist() == [{"foo": 1}]