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 262e0666d docs: add recipe for `adbc_prepare` and low-level bindings 
(#2097)
262e0666d is described below

commit 262e0666d43c104fd530180c3c9262cdc5d0aa15
Author: David Li <[email protected]>
AuthorDate: Sat Aug 24 10:29:50 2024 +0900

    docs: add recipe for `adbc_prepare` and low-level bindings (#2097)
    
    Relates to #2040.
---
 docs/source/python/recipe/driver_manager.rst       | 19 +++++-
 .../python/recipe/driver_manager_lowlevel.py       | 67 ++++++++++++++++++++++
 .../source/python/recipe/driver_manager_prepare.py | 58 +++++++++++++++++++
 3 files changed, 141 insertions(+), 3 deletions(-)

diff --git a/docs/source/python/recipe/driver_manager.rst 
b/docs/source/python/recipe/driver_manager.rst
index e819c0108..526829b4b 100644
--- a/docs/source/python/recipe/driver_manager.rst
+++ b/docs/source/python/recipe/driver_manager.rst
@@ -15,6 +15,19 @@
 .. specific language governing permissions and limitations
 .. under the License.
 
-======================
-Driver Manager Recipes
-======================
+============================
+DBAPI/Driver Manager Recipes
+============================
+
+These recipes show general functionality of the ADBC Python libraries that
+isn't necessarily specific to any one driver.
+
+Direct use of the low-level bindings
+====================================
+
+.. recipe:: driver_manager_lowlevel.py
+
+Manually preparing a statement
+==============================
+
+.. recipe:: driver_manager_prepare.py
diff --git a/docs/source/python/recipe/driver_manager_lowlevel.py 
b/docs/source/python/recipe/driver_manager_lowlevel.py
new file mode 100644
index 000000000..ed34650b1
--- /dev/null
+++ b/docs/source/python/recipe/driver_manager_lowlevel.py
@@ -0,0 +1,67 @@
+# 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.
+
+# RECIPE STARTS HERE
+#: While the DB-API_ bindings are recommended for general use, the low-level
+#: bindings are also available.  These mostly mirror the ADBC C API directly.
+#: They can be useful to opt out of some behaviors of the DB-API wrapper.
+#:
+#: .. _DB-API: https://peps.python.org/pep-0249/
+
+import pyarrow
+
+import adbc_driver_manager
+import adbc_driver_sqlite
+
+#: The driver packages do still have conveniences to create the root
+#: :class:`AdbcDatabase <adbc_driver_manager.AdbcDatabase>` object.
+db: adbc_driver_manager.AdbcDatabase = adbc_driver_sqlite.connect()
+#: The database must then be wrapped in a :class:`AdbcConnection
+#: <adbc_driver_manager.AdbcConnection>`.  This is similar in scope to the
+#: DB-API :class:`Connection <adbc_driver_manager.dbapi.Connection>` class.
+conn = adbc_driver_manager.AdbcConnection(db)
+#: Finally, we can wrap the connection in a :class:`AdbcStatement
+#: <adbc_driver_manager.AdbcStatement>`, which corresponds roughly to the
+#: DB-API :class:`Cursor <adbc_driver_manager.dbapi.Cursor>` class.
+stmt = adbc_driver_manager.AdbcStatement(conn)
+
+#: Now we can directly set the query.  Unlike the regular DB-API bindings, this
+#: will not prepare the statement.  (Depending on the driver, this may or may
+#: not make a difference, especially if executing the same query multiple
+#: times.)
+stmt.set_sql_query("SELECT 1 AS THEANSWER")
+
+#: When we execute the query, we get an `Arrow C Stream Interface`_ handle
+#: (wrapped as a PyCapsule_) that we need to import using a library like
+#: PyArrow_.
+#:
+#: .. _Arrow C Stream Interface:
+#:    https://arrow.apache.org/docs/format/CStreamInterface.html
+#: .. _PyArrow: https://pypi.org/project/pyarrow/
+#: .. _PyCapsule: https://docs.python.org/3/c-api/capsule.html
+handle, rowcount = stmt.execute_query()
+#: The SQLite driver does not know the row count of the result set up front
+#: (other drivers, like the PostgreSQL driver, may know).
+assert rowcount == -1
+#: We can use the PyArrow APIs to read the result.
+reader = 
pyarrow.RecordBatchReader._import_from_c_capsule(handle.__arrow_c_stream__())
+assert reader.schema == pyarrow.schema([("THEANSWER", "int64")])
+#: Finally, we have to clean up all the objects.  (They also support the
+#: context manager protocol.)
+stmt.close()
+conn.close()
+db.close()
diff --git a/docs/source/python/recipe/driver_manager_prepare.py 
b/docs/source/python/recipe/driver_manager_prepare.py
new file mode 100644
index 000000000..b99e94484
--- /dev/null
+++ b/docs/source/python/recipe/driver_manager_prepare.py
@@ -0,0 +1,58 @@
+# 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.
+
+# RECIPE STARTS HERE
+#: The DBAPI bindings prepare all statements before execution, because of this
+#: part of the `DB-API specification`_:
+#:
+#:     A reference to the operation will be retained by the cursor. If the same
+#:     operation object is passed in again, then the cursor can optimize its
+#:     behavior.
+#:
+#: However, you may want to prepare the statement yourself, mostly because this
+#: will give you the schema of the parameters (if supported by the server).
+#: This can be done with :meth:`Cursor.adbc_prepare
+#: <adbc_driver_manager.dbapi.Cursor.adbc_prepare>`.
+#:
+#: We'll demo this with the SQLite driver, though other drivers also support
+#: this.
+#:
+#: .. _DB-API specification: https://peps.python.org/pep-0249/#id19
+
+import pyarrow
+
+import adbc_driver_sqlite.dbapi
+
+conn = adbc_driver_sqlite.dbapi.connect()
+
+with conn.cursor() as cur:
+    param_schema = cur.adbc_prepare("SELECT ? + 1")
+    assert param_schema == pyarrow.schema([("0", "null")])
+
+    #: Note that the type of the parameter here is NULL, because the driver
+    #: does not know the exact type.
+
+    #: If we now execute the same query with the parameter, the statement will
+    #: not be prepared a second time.
+
+    cur.execute("SELECT ? + 1", parameters=(1,))
+    assert cur.fetchone() == (2,)
+
+    cur.execute("SELECT ? + 1", parameters=(41,))
+    assert cur.fetchone() == (42,)
+
+conn.close()

Reply via email to