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 2022/11/30 18:44:05 UTC
[arrow-adbc] branch main updated: feat(c/driver/sqlite): add Python SQLite driver bindings (#201)
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 ddd715a feat(c/driver/sqlite): add Python SQLite driver bindings (#201)
ddd715a is described below
commit ddd715a443cf2e5edd15c639af3845afe81af4ee
Author: David Li <li...@gmail.com>
AuthorDate: Wed Nov 30 13:44:00 2022 -0500
feat(c/driver/sqlite): add Python SQLite driver bindings (#201)
---
.github/workflows/cpp.yml | 22 +++
c/driver/sqlite/CMakeLists.txt | 15 +-
c/driver/sqlite/sqlite.c | 1 +
c/driver/sqlite/utils.h | 11 +-
c/driver_manager/adbc_driver_manager.cc | 8 +-
ci/scripts/python_build.sh | 10 +-
ci/scripts/python_sdist_build.sh | 5 +-
ci/scripts/python_test.sh | 5 +
ci/scripts/python_util.sh | 65 +++++--
ci/scripts/python_wheel_unix_build.sh | 9 +-
ci/scripts/python_wheel_windows_build.bat | 28 ++-
ci/scripts/python_wheel_windows_test.bat | 4 +-
docs/source/cpp/driver/index.rst | 1 +
docs/source/cpp/driver/postgres.rst | 4 +-
.../source/cpp/driver/{postgres.rst => sqlite.rst} | 28 +--
docs/source/cpp/install.rst | 22 +++
go/adbc/drivermgr/wrapper_sqlite_test.go | 2 +-
python/adbc_driver_postgres/README.md | 6 +-
.../adbc_driver_sqlite/.gitignore | 28 +--
.../adbc_driver_sqlite/MANIFEST.in | 26 +--
.../README.md | 28 +--
.../adbc_driver_sqlite/__init__.py | 33 ++--
.../adbc_driver_sqlite/_static_version.py | 33 ++--
.../adbc_driver_sqlite/_version.py | 210 +++++++++++++++++++++
.../adbc_driver_sqlite/adbc_driver_sqlite/dbapi.py | 117 ++++++++++++
.../adbc_driver_sqlite/pyproject.toml | 39 ++--
python/adbc_driver_sqlite/setup.py | 70 +++++++
.../adbc_driver_sqlite/tests/__init__.py | 26 ---
.../adbc_driver_sqlite/tests/test_dbapi.py | 31 +--
.../adbc_driver_sqlite/tests/test_lowlevel.py | 35 ++--
30 files changed, 666 insertions(+), 256 deletions(-)
diff --git a/.github/workflows/cpp.yml b/.github/workflows/cpp.yml
index 4b47db3..df811c9 100644
--- a/.github/workflows/cpp.yml
+++ b/.github/workflows/cpp.yml
@@ -195,6 +195,20 @@ jobs:
ctest --output-on-failure --no-tests=error
if %errorlevel% neq 0 then exit /b %errorlevel%
cd ..\..
+ - name: Build/Test SQLite Driver
+ shell: cmd /C call {0}
+ run: |
+ mkdir build\driver_sqlite
+ cd build\driver_sqlite
+ cmake -GNinja ..\..\c\driver\sqlite -DADBC_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=%CONDA_PREFIX% -DADBC_BUILD_SHARED=ON -DADBC_BUILD_STATIC=OFF
+ if %errorlevel% neq 0 then exit /b %errorlevel%
+ cmake --build .
+ dir
+ if %errorlevel% neq 0 then exit /b %errorlevel%
+ set PATH=%PATH%;${{ github.workspace }}\build\driver_sqlite
+ ctest --output-on-failure --no-tests=error
+ if %errorlevel% neq 0 then exit /b %errorlevel%
+ cd ..\..
- name: Build/Test Python Driver Manager
shell: cmd /C call {0}
run: |
@@ -203,3 +217,11 @@ jobs:
set PATH=%PATH%;${{ github.workspace }}\build\driver_sqlite
python -m pytest -vv
cd ..\..
+ - name: Build/Test Python Driver SQLite
+ shell: cmd /C call {0}
+ run: |
+ cd python\adbc_driver_sqlite
+ set ADBC_SQLITE_LIBRARY=${{ github.workspace }}\build\driver_sqlite\adbc_driver_sqlite.dll
+ pip install -e .
+ python -m pytest -vv
+ cd ..\..
diff --git a/c/driver/sqlite/CMakeLists.txt b/c/driver/sqlite/CMakeLists.txt
index 1a40a3f..a80fd0d 100644
--- a/c/driver/sqlite/CMakeLists.txt
+++ b/c/driver/sqlite/CMakeLists.txt
@@ -25,9 +25,16 @@ project(adbc_driver_sqlite
VERSION "${ADBC_BASE_VERSION}"
LANGUAGES CXX)
include(CTest)
-find_package(PkgConfig)
-find_package(SQLite3 REQUIRED)
+if(WIN32)
+ # XXX: for now, assume vcpkg
+ find_package(unofficial-sqlite3 CONFIG REQUIRED)
+ set(SQLite3_LINK_LIBRARIES unofficial::sqlite3::sqlite3)
+ set(SQLite3_INCLUDE_DIRS)
+else()
+ find_package(SQLite3 REQUIRED)
+ set(SQLite3_LINK_LIBRARIES SQLite::SQLite3)
+endif()
add_arrow_lib(adbc_driver_sqlite
SOURCES
@@ -39,10 +46,10 @@ add_arrow_lib(adbc_driver_sqlite
SHARED_LINK_FLAGS
${ADBC_LINK_FLAGS}
SHARED_LINK_LIBS
- SQLite::SQLite3
+ ${SQLite3_LINK_LIBRARIES}
nanoarrow
STATIC_LINK_LIBS
- SQLite::SQLite3
+ ${SQLite3_LINK_LIBRARIES}
nanoarrow
${LIBPQ_STATIC_LIBRARIES})
include_directories(SYSTEM ${REPOSITORY_ROOT})
diff --git a/c/driver/sqlite/sqlite.c b/c/driver/sqlite/sqlite.c
index 233e5c1..82eac6c 100644
--- a/c/driver/sqlite/sqlite.c
+++ b/c/driver/sqlite/sqlite.c
@@ -1783,6 +1783,7 @@ AdbcStatusCode AdbcStatementExecutePartitions(struct AdbcStatement* statement,
} // NOLINT(whitespace/indent)
// due to https://github.com/cpplint/cpplint/pull/189
+ADBC_EXPORT
AdbcStatusCode AdbcDriverInit(int version, void* driver, struct AdbcError* error) {
return SqliteDriverInit(version, driver, error);
}
diff --git a/c/driver/sqlite/utils.h b/c/driver/sqlite/utils.h
index 5d65d88..3fb3b1e 100644
--- a/c/driver/sqlite/utils.h
+++ b/c/driver/sqlite/utils.h
@@ -21,9 +21,16 @@
#include <adbc.h>
+#if defined(__GNUC__)
+#define SET_ERROR_ATTRIBUTE __attribute__((format(printf, 2, 3)))
+#else
+#define SET_ERROR_ATTRIBUTE
+#endif
+
/// Set error details using a format string.
-void SetError(struct AdbcError* error, const char* format, ...)
- __attribute__((format(printf, 2, 3)));
+void SetError(struct AdbcError* error, const char* format, ...) SET_ERROR_ATTRIBUTE;
+
+#undef SET_ERROR_ATTRIBUTE
/// Wrap a single batch as a stream.
AdbcStatusCode BatchToArrayStream(struct ArrowArray* values, struct ArrowSchema* schema,
diff --git a/c/driver_manager/adbc_driver_manager.cc b/c/driver_manager/adbc_driver_manager.cc
index 80b0358..236073b 100644
--- a/c/driver_manager/adbc_driver_manager.cc
+++ b/c/driver_manager/adbc_driver_manager.cc
@@ -665,7 +665,9 @@ AdbcStatusCode AdbcLoadDriver(const char* driver_name, const char* entrypoint,
void* load_handle = GetProcAddress(handle, entrypoint);
init_func = reinterpret_cast<AdbcDriverInitFunc>(load_handle);
if (!init_func) {
- std::string message = "GetProcAddress() failed: ";
+ std::string message = "GetProcAddress(";
+ message += entrypoint;
+ message += ") failed: ";
GetWinError(&message);
if (!FreeLibrary(handle)) {
message += "\nFreeLibrary() failed: ";
@@ -722,7 +724,9 @@ AdbcStatusCode AdbcLoadDriver(const char* driver_name, const char* entrypoint,
void* load_handle = dlsym(handle, entrypoint);
if (!load_handle) {
- std::string message = "dlsym() failed: ";
+ std::string message = "dlsym(";
+ message += entrypoint;
+ message += ") failed: ";
message += dlerror();
SetError(error, message);
return ADBC_STATUS_INTERNAL;
diff --git a/ci/scripts/python_build.sh b/ci/scripts/python_build.sh
index 6d39a53..135f643 100755
--- a/ci/scripts/python_build.sh
+++ b/ci/scripts/python_build.sh
@@ -21,6 +21,7 @@ set -e
: ${BUILD_ALL:=1}
: ${BUILD_DRIVER_MANAGER:=${BUILD_ALL}}
: ${BUILD_DRIVER_POSTGRES:=${BUILD_ALL}}
+: ${BUILD_DRIVER_SQLITE:=${BUILD_ALL}}
if [[ $(uname) = "Darwin" ]]; then
ADBC_LIBRARY_SUFFIX="dylib"
@@ -33,10 +34,13 @@ build_subproject() {
local -r install_dir="${2}"
local -r subproject="${3}"
- if [[ "${subproject}" -eq "adbc_driver_postgres" ]]; then
+ if [[ "${subproject}" = "adbc_driver_postgres" ]]; then
export ADBC_POSTGRES_LIBRARY="${install_dir}/lib/libadbc_driver_postgres.${ADBC_LIBRARY_SUFFIX}"
+ elif [[ "${subproject}" = "adbc_driver_sqlite" ]]; then
+ export ADBC_SQLITE_LIBRARY="${install_dir}/lib/libadbc_driver_sqlite.${ADBC_LIBRARY_SUFFIX}"
fi
+ echo foo $subproject $ADBC_SQLITE_LIBRARY
python -m pip install -e "${source_dir}/python/${subproject}"
}
@@ -56,6 +60,10 @@ main() {
if [[ "${BUILD_DRIVER_POSTGRES}" -gt 0 ]]; then
build_subproject "${source_dir}" "${install_dir}" adbc_driver_postgres
fi
+
+ if [[ "${BUILD_DRIVER_SQLITE}" -gt 0 ]]; then
+ build_subproject "${source_dir}" "${install_dir}" adbc_driver_sqlite
+ fi
}
main "$@"
diff --git a/ci/scripts/python_sdist_build.sh b/ci/scripts/python_sdist_build.sh
index ea33375..535331c 100755
--- a/ci/scripts/python_sdist_build.sh
+++ b/ci/scripts/python_sdist_build.sh
@@ -20,6 +20,9 @@
set -ex
source_dir=${1}
+script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+source "${script_dir}/python_util.sh"
echo "=== (${PYTHON_VERSION}) Building ADBC sdists ==="
@@ -30,7 +33,7 @@ pip install --upgrade pip setuptools
# For drivers, which bundle shared libraries, defer that to install time
export _ADBC_IS_SDIST=1
-for component in adbc_driver_manager adbc_driver_postgres; do
+for component in ${COMPONENTS}; do
pushd ${source_dir}/python/$component
echo "=== (${PYTHON_VERSION}) Building $component sdist ==="
diff --git a/ci/scripts/python_test.sh b/ci/scripts/python_test.sh
index 17c56c1..c858420 100755
--- a/ci/scripts/python_test.sh
+++ b/ci/scripts/python_test.sh
@@ -21,6 +21,7 @@ set -e
: ${BUILD_ALL:=1}
: ${BUILD_DRIVER_MANAGER:=${BUILD_ALL}}
: ${BUILD_DRIVER_POSTGRES:=${BUILD_ALL}}
+: ${BUILD_DRIVER_SQLITE:=${BUILD_ALL}}
test_subproject() {
local -r source_dir=${1}
@@ -53,6 +54,10 @@ main() {
if [[ "${BUILD_DRIVER_POSTGRES}" -gt 0 ]]; then
test_subproject "${source_dir}" "${install_dir}" adbc_driver_postgres
fi
+
+ if [[ "${BUILD_DRIVER_SQLITE}" -gt 0 ]]; then
+ test_subproject "${source_dir}" "${install_dir}" adbc_driver_sqlite
+ fi
}
main "$@"
diff --git a/ci/scripts/python_util.sh b/ci/scripts/python_util.sh
index fb06d6c..bd2a01b 100644
--- a/ci/scripts/python_util.sh
+++ b/ci/scripts/python_util.sh
@@ -17,7 +17,7 @@
# specific language governing permissions and limitations
# under the License.
-COMPONENTS="adbc_driver_manager adbc_driver_postgres"
+COMPONENTS="adbc_driver_manager adbc_driver_postgres adbc_driver_sqlite"
function build_drivers {
local -r source_dir="$1"
@@ -30,21 +30,29 @@ function build_drivers {
# Enable manifest mode
: ${VCPKG_FEATURE_FLAGS:=manifests}
# Add our custom triplets
- : ${VCPKG_OVERLAY_TRIPLETS:="${source_dir}/ci/vcpkg/triplets/"}
+ export VCPKG_OVERLAY_TRIPLETS="${source_dir}/ci/vcpkg/triplets/"
if [[ $(uname) == "Linux" ]]; then
export ADBC_POSTGRES_LIBRARY=${build_dir}/lib/libadbc_driver_postgres.so
+ export ADBC_SQLITE_LIBRARY=${build_dir}/lib/libadbc_driver_sqlite.so
export VCPKG_DEFAULT_TRIPLET="x64-linux-static-release"
+
+ # XXX: Patch the portfile
+ sed -i "s|include/postgresql/server/pg_config.h|include/server/pg_config.h|" \
+ "${VCPKG_ROOT}/ports/libpq/portfile.cmake"
else # macOS
export ADBC_POSTGRES_LIBRARY=${build_dir}/lib/libadbc_driver_postgres.dylib
+ export ADBC_SQLITE_LIBRARY=${build_dir}/lib/libadbc_driver_sqlite.dylib
export VCPKG_DEFAULT_TRIPLET="x64-osx-static-release"
- fi
- echo ${VCPKG_DEFAULT_TRIPLET}
-
- mkdir -p ${build_dir}
- pushd ${build_dir}
+ # XXX: Patch the portfile
+ sed -i '.bak' "s|include/postgresql/server/pg_config.h|include/server/pg_config.h|" \
+ "${VCPKG_ROOT}/ports/libpq/portfile.cmake"
+ fi
+ echo "=== Building driver/postgres ==="
+ mkdir -p ${build_dir}/driver/postgres
+ pushd ${build_dir}/driver/postgres
cmake \
-G ${CMAKE_GENERATOR} \
-DADBC_BUILD_SHARED=ON \
@@ -53,23 +61,44 @@ function build_drivers {
-DCMAKE_INSTALL_PREFIX=${build_dir} \
-DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake \
-DCMAKE_UNITY_BUILD=${CMAKE_UNITY_BUILD} \
+ -DVCPKG_OVERLAY_TRIPLETS="${VCPKG_OVERLAY_TRIPLETS}" \
+ -DVCPKG_TARGET_TRIPLET="${VCPKG_DEFAULT_TRIPLET}" \
${source_dir}/c/driver/postgres
cmake --build . --target install -j
popd
+
+ echo "=== Building driver/sqlite ==="
+ mkdir -p ${build_dir}/driver/sqlite
+ pushd ${build_dir}/driver/sqlite
+ cmake \
+ -G ${CMAKE_GENERATOR} \
+ -DADBC_BUILD_SHARED=ON \
+ -DADBC_BUILD_STATIC=OFF \
+ -DCMAKE_INSTALL_LIBDIR=lib \
+ -DCMAKE_INSTALL_PREFIX=${build_dir} \
+ -DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake \
+ -DCMAKE_UNITY_BUILD=${CMAKE_UNITY_BUILD} \
+ -DVCPKG_OVERLAY_TRIPLETS="${VCPKG_OVERLAY_TRIPLETS}" \
+ -DVCPKG_TARGET_TRIPLET="${VCPKG_DEFAULT_TRIPLET}" \
+ ${source_dir}/c/driver/sqlite
+ cmake --build . --target install -j
+ popd
}
function test_packages {
- python -c "
-import adbc_driver_manager
-import adbc_driver_manager.dbapi
-import adbc_driver_postgres
-import adbc_driver_postgres.dbapi
+ for component in ${COMPONENTS}; do
+ echo "=== Testing $component ==="
+
+ python -c "
+import $component
+import $component.dbapi
"
- # Will only run some smoke tests
- # --import-mode required, else tries to import from the source dir instead of installed package
- echo "=== Testing adbc_driver_manager ==="
- python -m pytest -vvx --import-mode append -k "not sqlite" ${source_dir}/python/adbc_driver_manager/tests
- echo "=== Testing adbc_driver_postgres ==="
- python -m pytest -vvx --import-mode append ${source_dir}/python/adbc_driver_postgres/tests
+ # --import-mode required, else tries to import from the source dir instead of installed package
+ if [[ "${component}" = "adbc_driver_manager" ]]; then
+ python -m pytest -vvx --import-mode append -k "not sqlite" ${source_dir}/python/$component/tests
+ else
+ python -m pytest -vvx --import-mode append ${source_dir}/python/$component/tests
+ fi
+ done
}
diff --git a/ci/scripts/python_wheel_unix_build.sh b/ci/scripts/python_wheel_unix_build.sh
index 58c4e61..616462c 100755
--- a/ci/scripts/python_wheel_unix_build.sh
+++ b/ci/scripts/python_wheel_unix_build.sh
@@ -62,18 +62,19 @@ function check_wheels {
fi
}
-echo "=== (${PYTHON_VERSION}) Building ADBC libpq driver ==="
-# Sets ADBC_POSTGRES_LIBRARY
+echo "=== (${PYTHON_VERSION}) Building C/C++ driver components ==="
+# Sets ADBC_POSTGRES_LIBRARY, ADBC_SQLITE_LIBRARY
build_drivers "${source_dir}" "${build_dir}"
# Check that we don't expose any unwanted symbols
check_visibility $ADBC_POSTGRES_LIBRARY
+check_visibility $ADBC_SQLITE_LIBRARY
# https://github.com/pypa/pip/issues/7555
# Get the latest pip so we have in-tree-build by default
-pip install --upgrade pip
+pip install --upgrade pip auditwheel
-for component in adbc_driver_manager adbc_driver_postgres; do
+for component in $COMPONENTS; do
pushd ${source_dir}/python/$component
echo "=== (${PYTHON_VERSION}) Clean build artifacts==="
diff --git a/ci/scripts/python_wheel_windows_build.bat b/ci/scripts/python_wheel_windows_build.bat
index 654dbfd..3dcea73 100644
--- a/ci/scripts/python_wheel_windows_build.bat
+++ b/ci/scripts/python_wheel_windows_build.bat
@@ -30,8 +30,10 @@ set VCPKG_TARGET_TRIPLET=x64-windows-static
IF NOT DEFINED VCPKG_ROOT (echo "Must set VCPKG_ROOT" && exit /B 1)
-mkdir %build_dir%
-pushd %build_dir%
+%VCPKG_ROOT%\vcpkg install --triplet=%VCPKG_TARGET_TRIPLET% libpq sqlite3
+
+mkdir %build_dir%\postgres
+pushd %build_dir%\postgres
cmake ^
-G "%CMAKE_GENERATOR%" ^
@@ -50,9 +52,29 @@ set ADBC_POSTGRES_LIBRARY=%build_dir%\bin\adbc_driver_postgres.dll
popd
+mkdir %build_dir%\sqlite
+pushd %build_dir%\sqlite
+
+cmake ^
+ -G "%CMAKE_GENERATOR%" ^
+ -DADBC_BUILD_SHARED=ON ^
+ -DADBC_BUILD_STATIC=OFF ^
+ -DCMAKE_BUILD_TYPE=%CMAKE_BUILD_TYPE% ^
+ -DCMAKE_INSTALL_PREFIX=%build_dir% ^
+ -DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%/scripts/buildsystems/vcpkg.cmake ^
+ -DCMAKE_UNITY_BUILD=%CMAKE_UNITY_BUILD% ^
+ -DVCPKG_TARGET_TRIPLET=%VCPKG_TARGET_TRIPLET% ^
+ %source_dir%\c\driver\sqlite || exit /B 1
+cmake --build . --config %CMAKE_BUILD_TYPE% --target install -j || exit /B 1
+
+@REM XXX: CMake installs it to bin instead of lib for some reason
+set ADBC_SQLITE_LIBRARY=%build_dir%\bin\adbc_driver_sqlite.dll
+
+popd
+
python -m pip install --upgrade pip delvewheel
-FOR %%c IN (adbc_driver_manager adbc_driver_postgres) DO (
+FOR %%c IN (adbc_driver_manager adbc_driver_postgres adbc_driver_sqlite) DO (
pushd %source_dir%\python\%%c
echo "=== (%PYTHON_VERSION%) Building %%c wheel ==="
diff --git a/ci/scripts/python_wheel_windows_test.bat b/ci/scripts/python_wheel_windows_test.bat
index 7273f35..19305ca 100644
--- a/ci/scripts/python_wheel_windows_test.bat
+++ b/ci/scripts/python_wheel_windows_test.bat
@@ -21,7 +21,7 @@ set source_dir=%1
echo "=== (%PYTHON_VERSION%) Installing wheels ==="
-FOR %%c IN (adbc_driver_manager adbc_driver_postgres) DO (
+FOR %%c IN (adbc_driver_manager adbc_driver_postgres adbc_driver_sqlite) DO (
FOR %%w IN (%source_dir%\python\%%c\dist\*.whl) DO (
pip install --force-reinstall %%w || exit /B 1
)
@@ -31,7 +31,7 @@ pip install pytest pyarrow pandas
echo "=== (%PYTHON_VERSION%) Testing wheels ==="
-FOR %%c IN (adbc_driver_manager adbc_driver_postgres) DO (
+FOR %%c IN (adbc_driver_manager adbc_driver_postgres adbc_driver_sqlite) DO (
echo "=== Testing %%c ==="
python -c "import %%c" || exit /B 1
python -c "import %%c.dbapi" || exit /B 1
diff --git a/docs/source/cpp/driver/index.rst b/docs/source/cpp/driver/index.rst
index 7a05c79..df901a7 100644
--- a/docs/source/cpp/driver/index.rst
+++ b/docs/source/cpp/driver/index.rst
@@ -27,3 +27,4 @@ protocols/databases. More may be available from third parties.
flight_sql
postgres
+ sqlite
diff --git a/docs/source/cpp/driver/postgres.rst b/docs/source/cpp/driver/postgres.rst
index 6a8f0b4..eb2ee96 100644
--- a/docs/source/cpp/driver/postgres.rst
+++ b/docs/source/cpp/driver/postgres.rst
@@ -19,8 +19,8 @@
libpq-based Driver
==================
-The Flight SQL Driver provides access to any database that supports
-the Postgres wire format.
+The Postgres driver provides access to any database that supports the
+Postgres wire format.
Installation
============
diff --git a/docs/source/cpp/driver/postgres.rst b/docs/source/cpp/driver/sqlite.rst
similarity index 66%
copy from docs/source/cpp/driver/postgres.rst
copy to docs/source/cpp/driver/sqlite.rst
index 6a8f0b4..19788fa 100644
--- a/docs/source/cpp/driver/postgres.rst
+++ b/docs/source/cpp/driver/sqlite.rst
@@ -15,25 +15,27 @@
.. specific language governing permissions and limitations
.. under the License.
-==================
-libpq-based Driver
-==================
+=============
+SQLite Driver
+=============
-The Flight SQL Driver provides access to any database that supports
-the Postgres wire format.
+The SQLite driver provides access to any database that supports the
+Postgres wire format.
Installation
============
-The libpq-based driver is shipped as a standalone library. See
-:ref:`Installation <cpp-install-libpq>`.
+The SQLite driver is shipped as a standalone library. See
+:ref:`Installation <cpp-install-sqlite>`.
Usage
=====
To connect to a database, supply the "uri" parameter when constructing
-the :cpp:class:`AdbcDatabase`. This should be a `connection URI
-<https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING>`_.
+the :cpp:class:`AdbcDatabase`. This should be a filename or `URI
+filename <https://www.sqlite.org/c3ref/open.html#urifilenamesinsqlite3open>`_.
+If omitted, it will default to an in-memory database, but one that is
+shared across all connections.
.. tab-set::
@@ -47,7 +49,7 @@ the :cpp:class:`AdbcDatabase`. This should be a `connection URI
// Ignoring error handling
struct AdbcDatabase database;
AdbcDatabaseNew(&database, nullptr);
- AdbcDatabaseSetOption(&database, "uri", "postgresql://localhost:5433", nullptr);
+ AdbcDatabaseSetOption(&database, "uri", "file:mydb.db", nullptr);
AdbcDatabaseInit(&database, nullptr);
.. tab-item:: Python
@@ -55,9 +57,7 @@ the :cpp:class:`AdbcDatabase`. This should be a `connection URI
.. code-block:: python
- import adbc_driver_postgres.dbapi
+ import adbc_driver_sqlite.dbapi
-
- uri = "postgresql://localhost:5433"
- with adbc_driver_postgres.dbapi.connect(uri) as conn:
+ with adbc_driver_sqlite.dbapi.connect() as conn:
pass
diff --git a/docs/source/cpp/install.rst b/docs/source/cpp/install.rst
index ee2a57b..0fad01a 100644
--- a/docs/source/cpp/install.rst
+++ b/docs/source/cpp/install.rst
@@ -81,6 +81,28 @@ Flight SQL Driver
libpq-based Driver
==================
+.. tab-set::
+
+ .. tab-item:: C++
+ :sync: cpp
+
+ .. note:: Under construction
+
+ .. tab-item:: Python (pip)
+ :sync: python
+
+ .. note:: Under construction
+
+ .. tab-item:: Python (conda-forge)
+ :sync: python-conda-forge
+
+ .. note:: Under construction
+
+.. _cpp-install-sqlite:
+
+SQLite Driver
+=============
+
.. tab-set::
.. tab-item:: C++
diff --git a/go/adbc/drivermgr/wrapper_sqlite_test.go b/go/adbc/drivermgr/wrapper_sqlite_test.go
index ba3b277..8ec3af0 100644
--- a/go/adbc/drivermgr/wrapper_sqlite_test.go
+++ b/go/adbc/drivermgr/wrapper_sqlite_test.go
@@ -216,7 +216,7 @@ func TestDriverMgrCustomInitFunc(t *testing.T) {
var exp *adbc.Error
assert.ErrorAs(t, err, &exp)
assert.Equal(t, adbc.StatusInternal, exp.Code)
- assert.Contains(t, exp.Msg, "dlsym() failed")
+ assert.Contains(t, exp.Msg, "dlsym(ThisSymbolDoesNotExist) failed")
switch runtime.GOOS {
case "darwin":
assert.Contains(t, exp.Msg, "ThisSymbolDoesNotExist): symbol not found")
diff --git a/python/adbc_driver_postgres/README.md b/python/adbc_driver_postgres/README.md
index b5dcf40..af697da 100644
--- a/python/adbc_driver_postgres/README.md
+++ b/python/adbc_driver_postgres/README.md
@@ -30,10 +30,8 @@ manager](../adbc_driver_manager/README.md) to provide a [DBAPI 2.0/PEP
Dependencies: a build of the libpq driver.
-Set the environment variable `ADBC_POSTGRES_LIBRARY` to the directory
-containing `libadbc_driver_postgres.so` before running `pip install`.
-
-(This library does not yet support Windows/MacOS.)
+Set the environment variable `ADBC_POSTGRES_LIBRARY` to the path to
+`libadbc_driver_postgres.{dll,dylib,so}` before running `pip install`.
See [CONTRIBUTING.md](../../CONTRIBUTING.md) for details on the
general build process.
diff --git a/ci/scripts/python_sdist_build.sh b/python/adbc_driver_sqlite/.gitignore
old mode 100755
new mode 100644
similarity index 53%
copy from ci/scripts/python_sdist_build.sh
copy to python/adbc_driver_sqlite/.gitignore
index ea33375..126488c
--- a/ci/scripts/python_sdist_build.sh
+++ b/python/adbc_driver_sqlite/.gitignore
@@ -1,5 +1,3 @@
-#!/usr/bin/env bash
-#
# 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
@@ -17,26 +15,6 @@
# specific language governing permissions and limitations
# under the License.
-set -ex
-
-source_dir=${1}
-
-echo "=== (${PYTHON_VERSION}) Building ADBC sdists ==="
-
-# https://github.com/pypa/pip/issues/7555
-# Get the latest pip so we have in-tree-build by default
-pip install --upgrade pip setuptools
-
-# For drivers, which bundle shared libraries, defer that to install time
-export _ADBC_IS_SDIST=1
-
-for component in adbc_driver_manager adbc_driver_postgres; do
- pushd ${source_dir}/python/$component
-
- echo "=== (${PYTHON_VERSION}) Building $component sdist ==="
- # python -m build copies to a tempdir, so we can't reference other files in the repo
- # https://github.com/pypa/pip/issues/5519
- python setup.py sdist
-
- popd
-done
+adbc_driver_postgres/*.c
+adbc_driver_postgres/*.cpp
+build/
diff --git a/ci/scripts/python_sdist_build.sh b/python/adbc_driver_sqlite/MANIFEST.in
old mode 100755
new mode 100644
similarity index 53%
copy from ci/scripts/python_sdist_build.sh
copy to python/adbc_driver_sqlite/MANIFEST.in
index ea33375..f9de8e7
--- a/ci/scripts/python_sdist_build.sh
+++ b/python/adbc_driver_sqlite/MANIFEST.in
@@ -1,5 +1,3 @@
-#!/usr/bin/env bash
-#
# 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
@@ -17,26 +15,6 @@
# specific language governing permissions and limitations
# under the License.
-set -ex
-
-source_dir=${1}
-
-echo "=== (${PYTHON_VERSION}) Building ADBC sdists ==="
-
-# https://github.com/pypa/pip/issues/7555
-# Get the latest pip so we have in-tree-build by default
-pip install --upgrade pip setuptools
-
-# For drivers, which bundle shared libraries, defer that to install time
-export _ADBC_IS_SDIST=1
-
-for component in adbc_driver_manager adbc_driver_postgres; do
- pushd ${source_dir}/python/$component
-
- echo "=== (${PYTHON_VERSION}) Building $component sdist ==="
- # python -m build copies to a tempdir, so we can't reference other files in the repo
- # https://github.com/pypa/pip/issues/5519
- python setup.py sdist
+# setuptools manifest
- popd
-done
+include adbc_driver_sqlite/libadbc_driver_sqlite.so
diff --git a/python/adbc_driver_postgres/README.md b/python/adbc_driver_sqlite/README.md
similarity index 60%
copy from python/adbc_driver_postgres/README.md
copy to python/adbc_driver_sqlite/README.md
index b5dcf40..88b0528 100644
--- a/python/adbc_driver_postgres/README.md
+++ b/python/adbc_driver_sqlite/README.md
@@ -17,10 +17,10 @@
under the License.
-->
-# ADBC libpq Driver for Python
+# ADBC SQLite Driver for Python
-This package contains bindings for the [libpq
-driver](../../c/driver/postgres/README.md), using the [driver
+This package contains bindings for the [SQLite
+driver](../../c/driver/sqlite/README.md), using the [driver
manager](../adbc_driver_manager/README.md) to provide a [DBAPI 2.0/PEP
249-compatible][dbapi] interface on top.
@@ -28,33 +28,19 @@ manager](../adbc_driver_manager/README.md) to provide a [DBAPI 2.0/PEP
## Building
-Dependencies: a build of the libpq driver.
+Dependencies: a build of the SQLite driver.
-Set the environment variable `ADBC_POSTGRES_LIBRARY` to the directory
-containing `libadbc_driver_postgres.so` before running `pip install`.
-
-(This library does not yet support Windows/MacOS.)
+Set the environment variable `ADBC_SQLITE_LIBRARY` to the path to
+`libadbc_driver_sqlite.{dll,dylib,so}` before running `pip install`.
See [CONTRIBUTING.md](../../CONTRIBUTING.md) for details on the
general build process.
## Testing
-A running instance of Postgres is required. For example, using Docker:
-
-```shell
-$ docker run -it --rm \
- -e POSTGRES_PASSWORD=password \
- -e POSTGRES_DB=tempdb \
- -p 5432:5432 \
- postgres
-```
-
-Then, to run the tests, set the environment variable specifying the
-Postgres URI before running tests:
+To run the tests, use pytest:
```shell
-$ export ADBC_POSTGRES_TEST_URI=postgres://localhost:5432/postgres?user=postgres&password=password
$ pytest -vvx
```
diff --git a/ci/scripts/python_sdist_build.sh b/python/adbc_driver_sqlite/adbc_driver_sqlite/__init__.py
old mode 100755
new mode 100644
similarity index 53%
copy from ci/scripts/python_sdist_build.sh
copy to python/adbc_driver_sqlite/adbc_driver_sqlite/__init__.py
index ea33375..c01ea88
--- a/ci/scripts/python_sdist_build.sh
+++ b/python/adbc_driver_sqlite/adbc_driver_sqlite/__init__.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env bash
-#
# 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
@@ -17,26 +15,21 @@
# specific language governing permissions and limitations
# under the License.
-set -ex
-
-source_dir=${1}
-
-echo "=== (${PYTHON_VERSION}) Building ADBC sdists ==="
+import importlib.resources
+import typing
-# https://github.com/pypa/pip/issues/7555
-# Get the latest pip so we have in-tree-build by default
-pip install --upgrade pip setuptools
+import adbc_driver_manager
-# For drivers, which bundle shared libraries, defer that to install time
-export _ADBC_IS_SDIST=1
+from ._version import __version__
-for component in adbc_driver_manager adbc_driver_postgres; do
- pushd ${source_dir}/python/$component
+__all__ = ["connect", "__version__"]
- echo "=== (${PYTHON_VERSION}) Building $component sdist ==="
- # python -m build copies to a tempdir, so we can't reference other files in the repo
- # https://github.com/pypa/pip/issues/5519
- python setup.py sdist
- popd
-done
+def connect(uri: typing.Optional[str] = None) -> adbc_driver_manager.AdbcDatabase:
+ """Create a low level ADBC connection to SQLite."""
+ with importlib.resources.path(
+ __package__, "libadbc_driver_sqlite.so"
+ ) as entrypoint:
+ if uri is None:
+ return adbc_driver_manager.AdbcDatabase(driver=str(entrypoint))
+ return adbc_driver_manager.AdbcDatabase(driver=str(entrypoint), uri=uri)
diff --git a/ci/scripts/python_sdist_build.sh b/python/adbc_driver_sqlite/adbc_driver_sqlite/_static_version.py
old mode 100755
new mode 100644
similarity index 53%
copy from ci/scripts/python_sdist_build.sh
copy to python/adbc_driver_sqlite/adbc_driver_sqlite/_static_version.py
index ea33375..7ca903c
--- a/ci/scripts/python_sdist_build.sh
+++ b/python/adbc_driver_sqlite/adbc_driver_sqlite/_static_version.py
@@ -1,5 +1,4 @@
-#!/usr/bin/env bash
-#
+# -*- coding: utf-8 -*-
# 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
@@ -17,26 +16,16 @@
# specific language governing permissions and limitations
# under the License.
-set -ex
-
-source_dir=${1}
-
-echo "=== (${PYTHON_VERSION}) Building ADBC sdists ==="
+# Generated by miniver (CC0).
-# https://github.com/pypa/pip/issues/7555
-# Get the latest pip so we have in-tree-build by default
-pip install --upgrade pip setuptools
-
-# For drivers, which bundle shared libraries, defer that to install time
-export _ADBC_IS_SDIST=1
-
-for component in adbc_driver_manager adbc_driver_postgres; do
- pushd ${source_dir}/python/$component
+# This file is part of 'miniver': https://github.com/jbweston/miniver
+#
+# This file will be overwritten by setup.py when a source or binary
+# distribution is made. The magic value "__use_git__" is interpreted by
+# _version.py.
- echo "=== (${PYTHON_VERSION}) Building $component sdist ==="
- # python -m build copies to a tempdir, so we can't reference other files in the repo
- # https://github.com/pypa/pip/issues/5519
- python setup.py sdist
+version = "__use_git__"
- popd
-done
+# These values are only set if the distribution was created with 'git archive'
+refnames = "$Format:%D$"
+git_hash = "$Format:%h$"
diff --git a/python/adbc_driver_sqlite/adbc_driver_sqlite/_version.py b/python/adbc_driver_sqlite/adbc_driver_sqlite/_version.py
new file mode 100644
index 0000000..09bfd6f
--- /dev/null
+++ b/python/adbc_driver_sqlite/adbc_driver_sqlite/_version.py
@@ -0,0 +1,210 @@
+# -*- coding: utf-8 -*-
+# 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.
+
+# Generated by miniver (CC0).
+
+import os
+
+# This file is part of 'miniver': https://github.com/jbweston/miniver
+#
+from collections import namedtuple
+
+Version = namedtuple("Version", ("release", "dev", "labels"))
+
+# No public API
+__all__ = []
+
+package_root = os.path.dirname(os.path.realpath(__file__))
+package_name = os.path.basename(package_root)
+
+STATIC_VERSION_FILE = "_static_version.py"
+
+
+def get_version(version_file=STATIC_VERSION_FILE):
+ version_info = get_static_version_info(version_file)
+ version = version_info["version"]
+ if version == "__use_git__":
+ version = get_version_from_git()
+ if not version:
+ version = get_version_from_git_archive(version_info)
+ if not version:
+ version = Version("unknown", None, None)
+ return pep440_format(version)
+ else:
+ return version
+
+
+def get_static_version_info(version_file=STATIC_VERSION_FILE):
+ version_info = {}
+ with open(os.path.join(package_root, version_file), "rb") as f:
+ exec(f.read(), {}, version_info)
+ return version_info
+
+
+def version_is_from_git(version_file=STATIC_VERSION_FILE):
+ return get_static_version_info(version_file)["version"] == "__use_git__"
+
+
+def pep440_format(version_info):
+ release, dev, labels = version_info
+
+ version_parts = [release]
+ if dev:
+ if release.endswith("-dev") or release.endswith(".dev"):
+ version_parts.append(dev)
+ else: # prefer PEP440 over strict adhesion to semver
+ version_parts.append(".dev{}".format(dev))
+
+ if labels:
+ version_parts.append("+")
+ version_parts.append(".".join(labels))
+
+ return "".join(version_parts)
+
+
+def get_version_from_git():
+ import subprocess
+
+ # git describe --first-parent does not take into account tags from branches
+ # that were merged-in. The '--long' flag gets us the 'dev' version and
+ # git hash, '--always' returns the git hash even if there are no tags.
+ for opts in [["--first-parent"], []]:
+ try:
+ p = subprocess.Popen(
+ ["git", "describe", "--long", "--always"] + opts,
+ cwd=package_root,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
+ except OSError:
+ return
+ if p.wait() == 0:
+ break
+ else:
+ return
+
+ description = (
+ p.communicate()[0]
+ .decode()
+ .strip("v") # Tags can have a leading 'v', but the version should not
+ .rstrip("\n")
+ .rsplit("-", 3) # Split the latest tag, commits since tag, and hash
+ )
+
+ try:
+ _, release, dev, git = description
+ except ValueError: # No tags, only the git hash
+ # prepend 'g' to match with format returned by 'git describe'
+ git = "g{}".format(*description)
+ # XXX: assume version if not given
+ release = "0.0.0"
+ dev = None
+
+ labels = []
+ if dev == "0":
+ dev = None
+ else:
+ labels.append(git)
+
+ try:
+ p = subprocess.Popen(["git", "diff", "--quiet"], cwd=package_root)
+ except OSError:
+ labels.append("confused") # This should never happen.
+ else:
+ if p.wait() == 1:
+ labels.append("dirty")
+
+ return Version(release, dev, labels)
+
+
+# TODO: change this logic when there is a git pretty-format
+# that gives the same output as 'git describe'.
+# Currently we can only tell the tag the current commit is
+# pointing to, or its hash (with no version info)
+# if it is not tagged.
+def get_version_from_git_archive(version_info):
+ try:
+ refnames = version_info["refnames"]
+ git_hash = version_info["git_hash"]
+ except KeyError:
+ # These fields are not present if we are running from an sdist.
+ # Execution should never reach here, though
+ return None
+
+ if git_hash.startswith("$Format") or refnames.startswith("$Format"):
+ # variables not expanded during 'git archive'
+ return None
+
+ VTAG = "tag: adbc-"
+ refs = set(r.strip() for r in refnames.split(","))
+ version_tags = set(r[len(VTAG) :] for r in refs if r.startswith(VTAG))
+ if version_tags:
+ release, *_ = sorted(version_tags) # prefer e.g. "2.0" over "2.0rc1"
+ return Version(release, dev=None, labels=None)
+ else:
+ return Version("unknown", dev=None, labels=["g{}".format(git_hash)])
+
+
+__version__ = get_version()
+
+
+# The following section defines a 'get_cmdclass' function
+# that can be used from setup.py. The '__version__' module
+# global is used (but not modified).
+
+
+def _write_version(fname):
+ # This could be a hard link, so try to delete it first. Is there any way
+ # to do this atomically together with opening?
+ try:
+ os.remove(fname)
+ except OSError:
+ pass
+ with open(fname, "w") as f:
+ f.write(
+ "# This file has been created by setup.py.\n"
+ "version = '{}'\n".format(__version__)
+ )
+
+
+def get_cmdclass(pkg_source_path):
+ from setuptools.command.build_py import build_py as build_py_orig
+ from setuptools.command.sdist import sdist as sdist_orig
+
+ class _build_py(build_py_orig):
+ def run(self):
+ super().run()
+
+ src_marker = "".join(["src", os.path.sep])
+
+ if pkg_source_path.startswith(src_marker):
+ path = pkg_source_path[len(src_marker) :]
+ else:
+ path = pkg_source_path
+ _write_version(os.path.join(self.build_lib, path, STATIC_VERSION_FILE))
+
+ class _sdist(sdist_orig):
+ def make_release_tree(self, base_dir, files):
+ super().make_release_tree(base_dir, files)
+ _write_version(os.path.join(base_dir, pkg_source_path, STATIC_VERSION_FILE))
+
+ return dict(sdist=_sdist, build_py=_build_py)
+
+
+if __name__ == "__main__":
+ print("Version: ", get_version())
diff --git a/python/adbc_driver_sqlite/adbc_driver_sqlite/dbapi.py b/python/adbc_driver_sqlite/adbc_driver_sqlite/dbapi.py
new file mode 100644
index 0000000..e85766f
--- /dev/null
+++ b/python/adbc_driver_sqlite/adbc_driver_sqlite/dbapi.py
@@ -0,0 +1,117 @@
+# 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.
+
+"""
+DBAPI 2.0-compatible facade for the ADBC libpq driver.
+"""
+
+import typing
+
+import adbc_driver_sqlite
+
+import adbc_driver_manager
+import adbc_driver_manager.dbapi
+
+__all__ = [
+ "BINARY",
+ "DATETIME",
+ "NUMBER",
+ "ROWID",
+ "STRING",
+ "Connection",
+ "Cursor",
+ "DataError",
+ "DatabaseError",
+ "Date",
+ "DateFromTicks",
+ "Error",
+ "IntegrityError",
+ "InterfaceError",
+ "InternalError",
+ "NotSupportedError",
+ "OperationalError",
+ "ProgrammingError",
+ "Time",
+ "TimeFromTicks",
+ "Timestamp",
+ "TimestampFromTicks",
+ "Warning",
+ "apilevel",
+ "connect",
+ "paramstyle",
+ "threadsafety",
+]
+
+# ----------------------------------------------------------
+# Globals
+
+apilevel = adbc_driver_manager.dbapi.apilevel
+threadsafety = adbc_driver_manager.dbapi.threadsafety
+paramstyle = "qmark"
+
+Warning = adbc_driver_manager.dbapi.Warning
+Error = adbc_driver_manager.dbapi.Error
+InterfaceError = adbc_driver_manager.dbapi.InterfaceError
+DatabaseError = adbc_driver_manager.dbapi.DatabaseError
+DataError = adbc_driver_manager.dbapi.DataError
+OperationalError = adbc_driver_manager.dbapi.OperationalError
+IntegrityError = adbc_driver_manager.dbapi.IntegrityError
+InternalError = adbc_driver_manager.dbapi.InternalError
+ProgrammingError = adbc_driver_manager.dbapi.ProgrammingError
+NotSupportedError = adbc_driver_manager.dbapi.NotSupportedError
+
+# ----------------------------------------------------------
+# Types
+
+Date = adbc_driver_manager.dbapi.Date
+Time = adbc_driver_manager.dbapi.Time
+Timestamp = adbc_driver_manager.dbapi.Timestamp
+DateFromTicks = adbc_driver_manager.dbapi.DateFromTicks
+TimeFromTicks = adbc_driver_manager.dbapi.TimeFromTicks
+TimestampFromTicks = adbc_driver_manager.dbapi.TimestampFromTicks
+STRING = adbc_driver_manager.dbapi.STRING
+BINARY = adbc_driver_manager.dbapi.BINARY
+NUMBER = adbc_driver_manager.dbapi.NUMBER
+DATETIME = adbc_driver_manager.dbapi.DATETIME
+ROWID = adbc_driver_manager.dbapi.ROWID
+
+# ----------------------------------------------------------
+# Functions
+
+
+def connect(uri: typing.Optional[str] = None) -> "Connection":
+ """Connect to SQLite via ADBC."""
+ db = None
+ conn = None
+
+ try:
+ db = adbc_driver_sqlite.connect(uri)
+ conn = adbc_driver_manager.AdbcConnection(db)
+ return adbc_driver_manager.dbapi.Connection(db, conn)
+ except Exception:
+ if conn:
+ conn.close()
+ if db:
+ db.close()
+ raise
+
+
+# ----------------------------------------------------------
+# Classes
+
+Connection = adbc_driver_manager.dbapi.Connection
+Cursor = adbc_driver_manager.dbapi.Cursor
diff --git a/ci/scripts/python_sdist_build.sh b/python/adbc_driver_sqlite/pyproject.toml
old mode 100755
new mode 100644
similarity index 53%
copy from ci/scripts/python_sdist_build.sh
copy to python/adbc_driver_sqlite/pyproject.toml
index ea33375..ea720f5
--- a/ci/scripts/python_sdist_build.sh
+++ b/python/adbc_driver_sqlite/pyproject.toml
@@ -1,5 +1,3 @@
-#!/usr/bin/env bash
-#
# 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
@@ -17,26 +15,25 @@
# specific language governing permissions and limitations
# under the License.
-set -ex
-
-source_dir=${1}
-
-echo "=== (${PYTHON_VERSION}) Building ADBC sdists ==="
-
-# https://github.com/pypa/pip/issues/7555
-# Get the latest pip so we have in-tree-build by default
-pip install --upgrade pip setuptools
+[project]
+name = "adbc_driver_sqlite"
+description = "An ADBC driver for working with SQLite."
+authors = [{name = "Apache Arrow Developers", email = "dev@arrow.apache.org"}]
+license = {text = "Apache-2.0"}
+requires-python = ">=3.8"
+dynamic = ["version"]
-# For drivers, which bundle shared libraries, defer that to install time
-export _ADBC_IS_SDIST=1
+[project.optional-dependencies]
+dbapi = ["pandas", "pyarrow>=8.0.0"]
+test = ["pandas", "pyarrow>=8.0.0", "pytest"]
-for component in adbc_driver_manager adbc_driver_postgres; do
- pushd ${source_dir}/python/$component
+[project.urls]
+homepage = "https://arrow.apache.org"
+repository = "https://github.com/apache/arrow-adbc"
- echo "=== (${PYTHON_VERSION}) Building $component sdist ==="
- # python -m build copies to a tempdir, so we can't reference other files in the repo
- # https://github.com/pypa/pip/issues/5519
- python setup.py sdist
+[build-system]
+requires = ["setuptools >= 61.0.0"]
+build-backend = "setuptools.build_meta"
- popd
-done
+[tool.setuptools]
+include-package-data = true
diff --git a/python/adbc_driver_sqlite/setup.py b/python/adbc_driver_sqlite/setup.py
new file mode 100644
index 0000000..4f72ceb
--- /dev/null
+++ b/python/adbc_driver_sqlite/setup.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+
+# 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 os
+import shutil
+from pathlib import Path
+
+from setuptools import setup
+
+source_root = Path(__file__).parent
+repo_root = source_root.joinpath("../../")
+
+# ------------------------------------------------------------
+# Resolve Shared Library
+
+library = os.environ.get("ADBC_SQLITE_LIBRARY")
+if not library:
+ if os.environ.get("_ADBC_IS_SDIST", "").strip().lower() in ("1", "true"):
+ print("Building sdist, not requiring ADBC_SQLITE_LIBRARY")
+ else:
+ raise ValueError("Must provide ADBC_SQLITE_LIBRARY")
+else:
+ target = source_root.joinpath(
+ "./adbc_driver_sqlite/libadbc_driver_sqlite.so"
+ ).resolve()
+ shutil.copy(library, target)
+
+# ------------------------------------------------------------
+# Resolve Version (miniver)
+
+
+def get_version_and_cmdclass(pkg_path):
+ """
+ Load version.py module without importing the whole package.
+
+ Template code from miniver.
+ """
+ from importlib.util import module_from_spec, spec_from_file_location
+
+ spec = spec_from_file_location("version", os.path.join(pkg_path, "_version.py"))
+ module = module_from_spec(spec)
+ spec.loader.exec_module(module)
+ return module.__version__, module.get_cmdclass(pkg_path)
+
+
+version, cmdclass = get_version_and_cmdclass("adbc_driver_sqlite")
+
+# ------------------------------------------------------------
+# Setup
+
+setup(
+ cmdclass=cmdclass,
+ version=version,
+)
diff --git a/ci/scripts/python_sdist_build.sh b/python/adbc_driver_sqlite/tests/__init__.py
old mode 100755
new mode 100644
similarity index 53%
copy from ci/scripts/python_sdist_build.sh
copy to python/adbc_driver_sqlite/tests/__init__.py
index ea33375..13a8339
--- a/ci/scripts/python_sdist_build.sh
+++ b/python/adbc_driver_sqlite/tests/__init__.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env bash
-#
# 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
@@ -16,27 +14,3 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-
-set -ex
-
-source_dir=${1}
-
-echo "=== (${PYTHON_VERSION}) Building ADBC sdists ==="
-
-# https://github.com/pypa/pip/issues/7555
-# Get the latest pip so we have in-tree-build by default
-pip install --upgrade pip setuptools
-
-# For drivers, which bundle shared libraries, defer that to install time
-export _ADBC_IS_SDIST=1
-
-for component in adbc_driver_manager adbc_driver_postgres; do
- pushd ${source_dir}/python/$component
-
- echo "=== (${PYTHON_VERSION}) Building $component sdist ==="
- # python -m build copies to a tempdir, so we can't reference other files in the repo
- # https://github.com/pypa/pip/issues/5519
- python setup.py sdist
-
- popd
-done
diff --git a/ci/scripts/python_sdist_build.sh b/python/adbc_driver_sqlite/tests/test_dbapi.py
old mode 100755
new mode 100644
similarity index 53%
copy from ci/scripts/python_sdist_build.sh
copy to python/adbc_driver_sqlite/tests/test_dbapi.py
index ea33375..74a221d
--- a/ci/scripts/python_sdist_build.sh
+++ b/python/adbc_driver_sqlite/tests/test_dbapi.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env bash
-#
# 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
@@ -17,26 +15,17 @@
# specific language governing permissions and limitations
# under the License.
-set -ex
-
-source_dir=${1}
-
-echo "=== (${PYTHON_VERSION}) Building ADBC sdists ==="
-
-# https://github.com/pypa/pip/issues/7555
-# Get the latest pip so we have in-tree-build by default
-pip install --upgrade pip setuptools
+import pytest
+from adbc_driver_sqlite import dbapi
-# For drivers, which bundle shared libraries, defer that to install time
-export _ADBC_IS_SDIST=1
-for component in adbc_driver_manager adbc_driver_postgres; do
- pushd ${source_dir}/python/$component
+@pytest.fixture
+def sqlite():
+ with dbapi.connect() as conn:
+ yield conn
- echo "=== (${PYTHON_VERSION}) Building $component sdist ==="
- # python -m build copies to a tempdir, so we can't reference other files in the repo
- # https://github.com/pypa/pip/issues/5519
- python setup.py sdist
- popd
-done
+def test_query_trivial(sqlite):
+ with sqlite.cursor() as cur:
+ cur.execute("SELECT 1")
+ assert cur.fetchone() == (1,)
diff --git a/ci/scripts/python_sdist_build.sh b/python/adbc_driver_sqlite/tests/test_lowlevel.py
old mode 100755
new mode 100644
similarity index 53%
copy from ci/scripts/python_sdist_build.sh
copy to python/adbc_driver_sqlite/tests/test_lowlevel.py
index ea33375..051676a
--- a/ci/scripts/python_sdist_build.sh
+++ b/python/adbc_driver_sqlite/tests/test_lowlevel.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env bash
-#
# 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
@@ -17,26 +15,27 @@
# specific language governing permissions and limitations
# under the License.
-set -ex
+import adbc_driver_sqlite
+import pyarrow
+import pytest
-source_dir=${1}
+import adbc_driver_manager
-echo "=== (${PYTHON_VERSION}) Building ADBC sdists ==="
-# https://github.com/pypa/pip/issues/7555
-# Get the latest pip so we have in-tree-build by default
-pip install --upgrade pip setuptools
+@pytest.fixture
+def sqlite():
+ with adbc_driver_sqlite.connect() as db:
+ with adbc_driver_manager.AdbcConnection(db) as conn:
+ yield conn
-# For drivers, which bundle shared libraries, defer that to install time
-export _ADBC_IS_SDIST=1
-for component in adbc_driver_manager adbc_driver_postgres; do
- pushd ${source_dir}/python/$component
+def test_query_trivial(sqlite):
+ with adbc_driver_manager.AdbcStatement(sqlite) as stmt:
+ stmt.set_sql_query("SELECT 1")
+ stream, _ = stmt.execute_query()
+ reader = pyarrow.RecordBatchReader._import_from_c(stream.address)
+ assert reader.read_all()
- echo "=== (${PYTHON_VERSION}) Building $component sdist ==="
- # python -m build copies to a tempdir, so we can't reference other files in the repo
- # https://github.com/pypa/pip/issues/5519
- python setup.py sdist
- popd
-done
+def test_version():
+ assert adbc_driver_sqlite.__version__