Skip to content

fix(c/driver/sqlite): accept unprefixed named parameters - #4773

Open
emecii wants to merge 4 commits into
apache:mainfrom
emecii:fix/sqlite-unprefixed-named-parameters
Open

emecii wants to merge 4 commits into
apache:mainfrom
emecii:fix/sqlite-unprefixed-named-parameters

Conversation

@emecii

@emecii emecii commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Accept unprefixed names for SQLite's :, @, and $ named parameters when the match is unique.

AI disclosure: OpenAI Codex generated this implementation, tests, and PR description; automated validation is listed above.

Closes #3520

Preserve exact named bindings and reject ambiguous prefix-free matches. Add native and Python regression coverage and document the matching rules.

Generated-by: OpenAI Codex

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Alias and exact input names can resolve to one index while another SQL parameter remains silently unbound.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Enables SQLite named binding without :, @, or $ prefixes when uniquely matched.

Changes:

  • Adds unique unprefixed-name resolution and ambiguity errors.
  • Adds native and Python regression coverage.
  • Documents matching and precedence rules.
File summaries
File Description
c/driver/sqlite/statement_reader.c Implements unprefixed matching.
c/driver/sqlite/sqlite_test.cc Adds native binding tests.
python/adbc_driver_sqlite/tests/test_dbapi.py Adds DB-API regressions.
docs/source/driver/sqlite.rst Documents named parameters.
Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread c/driver/sqlite/statement_reader.c
@lidavidm lidavidm added this to the ADBC Libraries 25 milestone Sep 21, 2026

@lidavidm lidavidm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable overall. One question though.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we verified this against what the stdlib sqlite does?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified against Python 3.12.12’s sqlite3. Common unprefixed bindings agree, including repeated parameters and executemany. Differences: stdlib reuses a for both :a/@a and ignores extra keys; ADBC preserves exact-prefixed keys, enforces field count, and rejects ambiguous aliases. Numbered ?1 uses "1" in stdlib versus "?1" here. Added direct comparisons and documentation in bafb27e; all 12 named-parameter tests pass. Production behavior is unchanged.

AI-generated reply (OpenAI Codex).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't ask to add tests here and I don't think testing the stdlib is reasonable, I just wanted to ask about comparing against stdlib sqlite and/or justifying any difference. It appears sqlite itself considers the prefix part of the name so the current behavior was reasonable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the stdlib comparisons and their imports in 1187eb8, restoring the ADBC-only regression tests. Exact-prefixed and unique unprefixed matching are unchanged; all 10 named-parameter tests pass.

AI-generated reply (OpenAI Codex).

Comment thread docs/source/driver/sqlite.rst Outdated
Comment on lines +144 to +157
When binding by name, parameter names may include their ``:``, ``@``, or ``$``
prefix, or omit it when the remaining name identifies a unique SQL parameter.
For example, Python's ``cursor.execute("SELECT :a", {"a": 1})`` and
``cursor.execute("SELECT :a", {":a": 1})`` are both supported.
Exact prefixed names take precedence. If a query contains both ``:a`` and
``@a``, an unprefixed ``a`` is ambiguous and must be replaced by the exact
prefixed names.

These rules differ from Python's standard library ``sqlite3`` module, which
requires unprefixed dictionary keys, uses the same key for SQL parameters with
different prefixes (for example, ``:a`` and ``@a``), and ignores extra keys.
ADBC retains exact prefixed names and requires the number of supplied fields
to match the number of SQLite parameter slots; each field must resolve to a
different slot.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
When binding by name, parameter names may include their ``:``, ``@``, or ``$``
prefix, or omit it when the remaining name identifies a unique SQL parameter.
For example, Python's ``cursor.execute("SELECT :a", {"a": 1})`` and
``cursor.execute("SELECT :a", {":a": 1})`` are both supported.
Exact prefixed names take precedence. If a query contains both ``:a`` and
``@a``, an unprefixed ``a`` is ambiguous and must be replaced by the exact
prefixed names.
These rules differ from Python's standard library ``sqlite3`` module, which
requires unprefixed dictionary keys, uses the same key for SQL parameters with
different prefixes (for example, ``:a`` and ``@a``), and ignores extra keys.
ADBC retains exact prefixed names and requires the number of supplied fields
to match the number of SQLite parameter slots; each field must resolve to a
different slot.
When specifying bind parameters by name, the driver tries to match parameters
to fields in the schema of the supplied bind parameters. The names may include
the prefixes (``:``, ``@``, or ``$``), or omit the prefix if unambiguous. For
example, in Python, both ``cursor.execute("SELECT :a", {"a": 1})`` and
``cursor.execute("SELECT :a", {":a": 1})`` are acceptable, but
``cursor.execute("SELECT :a, @a", {"a": 1})`` is not. (Note that this differs
from Python's standard library sqlite3 module.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied this documentation suggestion verbatim in 1187eb8.

AI-generated reply (OpenAI Codex).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't ask to add tests here and I don't think testing the stdlib is reasonable, I just wanted to ask about comparing against stdlib sqlite and/or justifying any difference. It appears sqlite itself considers the prefix part of the name so the current behavior was reasonable.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

An unnamed Arrow parameter field can trigger a NULL-pointer crash in the new fallback.

Review effort: Balanced
Findings: 1 High severity

Open (1)
Resolved since last review (1)

Comment thread c/driver/sqlite/statement_reader.c
Reject NULL field names before resolving SQLite parameter indexes and reset the cache sentinel on failure. Cover first and later unnamed fields, including repeated attempts.

Apply the requested named-parameter documentation and remove stdlib comparison tests while preserving ADBC regressions.

Generated-by: OpenAI Codex

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: Named parameter binding not consistent with DBAPI (stdlib sqlite)

3 participants