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 7076bee4f feat(python/adbc_driver_manager): add convenience methods 
(#3539)
7076bee4f is described below

commit 7076bee4fc1f30a49668723bcccb7ea25bb19fc8
Author: David Li <[email protected]>
AuthorDate: Wed Oct 15 09:38:37 2025 +0900

    feat(python/adbc_driver_manager): add convenience methods (#3539)
    
    Closes #3263.
---
 docs/source/python/quickstart.rst                  |  5 +++++
 .../adbc_driver_manager/dbapi.py                   | 26 +++++++++++++++++++++-
 python/adbc_driver_manager/tests/test_dbapi.py     | 13 +++++++++++
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/docs/source/python/quickstart.rst 
b/docs/source/python/quickstart.rst
index 9d6165f2d..0aef7c97b 100644
--- a/docs/source/python/quickstart.rst
+++ b/docs/source/python/quickstart.rst
@@ -73,6 +73,7 @@ row-oriented DBAPI interface:
    :skipif: adbc_driver_sqlite is None
 
    >>> cursor.execute("SELECT 1, 2.0, 'Hello, world!'")
+   <adbc_driver_manager.dbapi.Cursor ...>
    >>> cursor.fetchone()
    (1, 2.0, 'Hello, world!')
    >>> cursor.fetchone()
@@ -83,6 +84,7 @@ We can also get the results as Arrow data via a non-standard 
method:
    :skipif: adbc_driver_sqlite is None
 
    >>> cursor.execute("SELECT 1, 2.0, 'Hello, world!'")
+   <adbc_driver_manager.dbapi.Cursor ...>
    >>> cursor.fetch_arrow_table()
    pyarrow.Table
    1: int64
@@ -102,6 +104,7 @@ We can bind parameters in our queries:
    :skipif: adbc_driver_sqlite is None
 
    >>> cursor.execute("SELECT ? + 1 AS the_answer", parameters=(41,))
+   <adbc_driver_manager.dbapi.Cursor ...>
    >>> cursor.fetch_arrow_table()
    pyarrow.Table
    the_answer: int64
@@ -123,6 +126,7 @@ table of Arrow data into a new database table:
    >>> cursor.adbc_ingest("sample", table)
    2
    >>> cursor.execute("SELECT COUNT(DISTINCT ints) FROM sample")
+   <adbc_driver_manager.dbapi.Cursor ...>
    >>> cursor.fetchall()
    [(2,)]
 
@@ -135,6 +139,7 @@ We can also append to an existing table:
    >>> cursor.adbc_ingest("sample", table, mode="append")
    2
    >>> cursor.execute("SELECT COUNT(DISTINCT ints) FROM sample")
+   <adbc_driver_manager.dbapi.Cursor ...>
    >>> cursor.fetchall()
    [(3,)]
 
diff --git a/python/adbc_driver_manager/adbc_driver_manager/dbapi.py 
b/python/adbc_driver_manager/adbc_driver_manager/dbapi.py
index 4c3641dca..cd0ecd72e 100644
--- a/python/adbc_driver_manager/adbc_driver_manager/dbapi.py
+++ b/python/adbc_driver_manager/adbc_driver_manager/dbapi.py
@@ -386,6 +386,22 @@ class Connection(_Closeable):
     # API Extensions
     # ------------------------------------------------------------
 
+    def execute(
+        self,
+        operation: Union[bytes, str],
+        parameters=None,
+        *,
+        adbc_stmt_kwargs: Optional[Dict[str, Any]] = None,
+    ) -> "Cursor":
+        """
+        Execute a query on a new cursor.
+
+        This is a convenience for creating a new cursor and executing a query.
+        """
+        return self.cursor(adbc_stmt_kwargs=adbc_stmt_kwargs).execute(
+            operation, parameters
+        )
+
     def adbc_cancel(self) -> None:
         """
         Cancel any ongoing operations on this connection.
@@ -723,7 +739,7 @@ class Cursor(_Closeable):
                 )
                 self._bind_by_name = False
 
-    def execute(self, operation: Union[bytes, str], parameters=None) -> None:
+    def execute(self, operation: Union[bytes, str], parameters=None) -> "Self":
         """
         Execute a query.
 
@@ -744,6 +760,11 @@ class Cursor(_Closeable):
 
             Note that providing a list of tuples is not supported (this mode
             of usage is deprecated in DBAPI-2.0; use executemany() instead).
+
+        Returns
+        -------
+        Self
+            This cursor (to enable chaining).
         """
         self._clear()
         self._prepare_execute(operation, parameters)
@@ -752,6 +773,7 @@ class Cursor(_Closeable):
             self._stmt.execute_query, (), {}, self._stmt.cancel
         )
         self._results = _RowIterator(self._stmt, handle)
+        return self
 
     def executemany(self, operation: Union[bytes, str], seq_of_parameters) -> 
None:
         """
@@ -775,6 +797,8 @@ class Cursor(_Closeable):
         -----
         Allowing ``None`` for parameters is outside of the DB-API
         specification.
+
+        This does not return ``self`` as there is no result set.
         """
         self._clear()
         if operation != self._last_query:
diff --git a/python/adbc_driver_manager/tests/test_dbapi.py 
b/python/adbc_driver_manager/tests/test_dbapi.py
index 72ae18f9e..b68cca210 100644
--- a/python/adbc_driver_manager/tests/test_dbapi.py
+++ b/python/adbc_driver_manager/tests/test_dbapi.py
@@ -530,3 +530,16 @@ def test_driver_path():
     ):
         with dbapi.connect(driver=pathlib.Path("/tmp/thisdriverdoesnotexist")):
             pass
+
+
[email protected]
+def test_dbapi_extensions(sqlite):
+    with sqlite.execute("SELECT ?", (1,)) as cur:
+        assert cur.fetchone() == (1,)
+        assert cur.fetchone() is None
+
+        assert cur.execute("SELECT 2").fetchall() == [(2,)]
+
+    with sqlite.cursor() as cur:
+        assert cur.execute("SELECT 1").fetchall() == [(1,)]
+        assert cur.execute("SELECT 42").fetchall() == [(42,)]

Reply via email to