Add experimental ADBC backend - #783
Open
axellpadilla wants to merge 1 commit into
Open
Conversation
Adds an experimental `adbc` backend (`backend: adbc`) as a third connection path alongside pyodbc and mssql-python, talking to SQL Server via go-mssqldb instead of an ODBC/DB-API bridge. - New dbt-sqlserver[adbc] extra; driver binary installed separately via the `dbc` CLI (not on PyPI). Full guide in docs/adbc_backend.md. - SQL Server (user/password) authentication only for now. - ? -> @pn placeholder rewriting, quote/bracket-aware so a literal ? in an identifier or string literal never misaligns a binding. - AdapterResponse.rows_affected recovered via a scoped @@rowcount query (ADBC's own cursor.rowcount is always -1), gated to DML statements with no pending result set so it never races an unfetched SELECT (no MARS support) and isn't paid for on DDL/SELECT/transaction-control statements. - Arrow type-code/DataType column metadata mapped to the same SQL Server type names as pyodbc/mssql-python; unrecognized codes raise instead of silently mistyping a column. - cursor.nextset() (unsupported by the driver) drained safely by checking the driver's exception type. CI: new adbc Docker image stage + publish-docker.yml matrix entry, new backend: adbc row in integration-tests-sqlserver.yml (Python 3.13 / SQL Server 2025, continue-on-error while experimental), and devcontainer setup now installs the driver binary automatically. Closes #771
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an experimental
adbcbackend (backend: adbcin a profile target) as a third connection path alongsidepyodbcandmssql-python. ADBC (Arrow Database Connectivity) talks to SQL Server viago-mssqldbinstead of an ODBC/DB-API bridge, avoiding row-based marshalling overhead.dbt-sqlserver[adbc]extra (adbc-driver-manager,pyarrow); the driver binary itself ships separately via thedbcCLI (not on PyPI). Full setup/config/troubleshooting guide indocs/adbc_backend.md;README.mdgets the new backend row and a matching setup section.?to T-SQL@pN(go-mssqldb doesn't supportqmarkbinding), skipping?characters that appear inside bracket-quoted identifiers or string literals so a literal?never misaligns a binding.AdapterResponse.rows_affectedis recovered via a scoped@@ROWCOUNTquery, since ADBC's owncursor.rowcountis always-1: only run when the statement is DML and has no pending result set to fetch, so it never races an unfetched SELECT on the same connection (no MARS support) and isn't paid for on DDL/SELECT/transaction-control statements. Other backends' rowcount values are untouched.DataType/type-code column metadata is mapped to the same SQL Server type names pyodbc/mssql-python report; an unrecognized type code raises instead of silently mistyping a column.cursor.nextset()(unsupported by the ADBC driver) is drained safely by checking the driver's exception type rather than pyodbc-style return values.CI / tooling
adbcDocker CI image stage (installs thedbcdriver-manager CLI + mssql driver binary) and matrix entry inpublish-docker.yml.backend: adbcrow inintegration-tests-sqlserver.ymlon Python 3.13 / SQL Server 2025 (latest), markedcontinue-on-errorsince the backend is still experimental.setup_env.sh) installs the ADBC driver binary and setsADBC_DRIVER_PATHautomatically on container start.Closes #771
Test plan
pytest tests/unit— 400 passedpytest tests/functionalagainst a live SQL Server withbackend: adbc— 320 passed, 48 skipped, 2 xfailed, 0 failedpre-commit run --all-files— clean (ruff check/format, mypy, etc.)publish-docker.ymlonly rebuilds CI images on push tomaster, so the newCI-3.13-adbcimage won't exist until that runs once after merge — the new integration-test row will fail-but-not-block until then (or trigger it manually viaworkflow_dispatch).