Skip to content

FEAT: TVP support for async queries - #814

Merged
Subrata (subrata-ms) merged 26 commits into
mainfrom
subrata-ms/AQEIntegration
Nov 3, 2026
Merged

Subrata (subrata-ms) merged 26 commits into
mainfrom
subrata-ms/AQEIntegration

Conversation

@subrata-ms

@subrata-ms Subrata (subrata-ms) commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Work Item / Issue Reference

AB#47998,48435

GitHub Issue: #<ISSUE_NUMBER>


Summary

This pull request introduces several improvements and enhancements to the mssql_python.async_query async API, focusing on better native type integration, more robust and consistent cursor behavior, and improved handling of parameter iterables in executemany. It also expands the test suite to cover these changes and edge cases.

Key highlights include:

  • Lazy exposure of native SQL type hints and the table-valued parameter constructor.
  • Improved type and error handling for parameter iterables in executemany.
  • New and clarified properties and behaviors for async cursors, including a closed property.
  • Expanded and refined test coverage for new and existing features.

Native type integration and exports

  • Added lazy exports for native SQL type hints (SQL_MONEY, SQL_SMALLMONEY, SQL_XML, SQL_JSON, SQL_VECTOR) and the internal _TableValuedParameter constructor, with dynamic loading and error reporting if the native dependency is missing. These are now included in __all__ and dir() as appropriate.
  • Added tests to verify that these native exports are correctly exposed, loaded only when accessed, and report missing features properly.

AsyncCursor API and behavior improvements

  • Added a closed property to async cursors to reflect both wrapper and parent connection state, with tests for idempotency and parent connection closure propagation.
  • Clarified and enhanced docstrings for nextset, close, description, and rowcount to document async-specific behaviors and differences from the synchronous API.
  • Added tests to ensure nextset correctly tracks rowcount and description per result, including edge cases.

Executemany and parameter iterable handling

  • Changed executemany signatures to accept any synchronous iterable (not just sequences), improved error handling for non-iterables, and ensured iterables are consumed only once. Streaming/asynchronous iterables are explicitly not supported.
  • Added tests for handling of empty generators, iterator failures, and correct consumption of parameter iterables.

Logging and test adjustments

  • Updated logging to remove reliance on batch_count for executemany and adjusted test expectations accordingly.
  • Minor imports and test harness updates to support new features.

These changes make the async query API more robust, Pythonic, and consistent with both native and DB-API expectations.

Expose native TVP and SQL type-hint helpers lazily. Support iterable executemany batches and preserve result state on iteration failure. Add cursor closed-state reporting, document async result contracts, and cover these behaviors with async integration tests.
Copilot AI lite review requested due to automatic review settings September 24, 2026 10:08
@github-actions

github-actions Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

PR Performance Report

✅ No regression detected

No consistent slowdowns detected across all 2 environments.

0 IMPROVEMENTS 0 SLOWDOWNS 2/2 ENVIRONMENTS

Coverage: 2 of 2 environments completed. Advisory result; does not block merging.

Performance diagnostics

Phase times are inclusive diagnostics and must not be added together. They identify where measured time changed, not why it changed.

No affected phases or call-count changes were recorded.

All database tasks and timings

Unix / SQL Server 2022

Database task Before After Paired change Result
Connection opening 11.357 ms 11.083 ms -3.8% no signal
SELECT queries 1.042 ms 1.023 ms +0.4% no signal
Row insertion 32.218 ms 32.468 ms +0.4% no signal
Executemany inserts 165.137 ms 162.997 ms -2.5% no signal
Fetch-all queries 124.550 ms 125.501 ms +0.8% no signal
Row-by-row fetching 14.810 ms 14.657 ms -1.8% no signal
Batched row fetching 122.117 ms 121.583 ms +0.3% no signal
Transaction commit and rollback 105.807 ms 105.917 ms +0.0% no signal
Arrow row fetching 91.420 ms 91.932 ms +0.7% no signal
100,000-row insertion 473.031 ms 469.142 ms -0.7% no signal
Row fetching in batches of 100 124.097 ms 122.687 ms -0.8% no signal
Row fetching in batches of 10,000 136.839 ms 135.654 ms -0.9% no signal
Repeated positional queries 31.689 ms 31.876 ms +0.3% no signal
Repeated named-parameter queries 34.477 ms 34.337 ms +0.8% no signal
Legacy 100,000-row insertion 382.804 ms 388.752 ms +0.4% no signal
Insertion with explicit input sizes 515.878 ms 535.607 ms +2.6% no signal
Joined aggregation queries 178.090 ms 177.275 ms -0.9% no signal
Large joined-result fetching 206.271 ms 209.993 ms +1.8% no signal
1.2-million-row fetching 3515.363 ms 3506.891 ms -1.1% no signal
Common table expression queries 5.779 ms 5.561 ms -1.9% no signal
256 KiB VARCHAR(MAX) / fetchall() 1.600 ms 1.610 ms +0.7% no signal
10,000 scalar values / fetchval() (debug disabled) 107.374 ms 109.179 ms -0.1% no signal

Unix / SQL Server 2025

Database task Before After Paired change Result
Connection opening 96.108 ms 96.366 ms +0.1% no signal
SELECT queries 0.995 ms 0.981 ms -1.4% no signal
Row insertion 31.732 ms 31.894 ms +0.5% no signal
Executemany inserts 150.446 ms 150.916 ms +0.6% no signal
Fetch-all queries 118.327 ms 120.885 ms +2.2% no signal
Row-by-row fetching 14.376 ms 14.505 ms +2.3% no signal
Batched row fetching 114.578 ms 117.217 ms +2.5% no signal
Transaction commit and rollback 106.451 ms 107.115 ms +0.2% no signal
Arrow row fetching 87.127 ms 88.296 ms +2.0% no signal
100,000-row insertion 421.108 ms 420.606 ms +0.6% no signal
Row fetching in batches of 100 121.482 ms 122.397 ms +0.9% no signal
Row fetching in batches of 10,000 128.060 ms 136.846 ms +3.9% no signal
Repeated positional queries 31.278 ms 31.286 ms -0.8% no signal
Repeated named-parameter queries 33.593 ms 33.926 ms +0.1% no signal
Legacy 100,000-row insertion 338.315 ms 343.105 ms +0.7% no signal
Insertion with explicit input sizes 479.021 ms 472.832 ms -1.6% no signal
Joined aggregation queries 158.886 ms 158.218 ms -0.4% no signal
Large joined-result fetching 182.534 ms 186.938 ms +2.4% no signal
1.2-million-row fetching 3387.004 ms 3413.604 ms +0.4% no signal
Common table expression queries 5.005 ms 5.024 ms -0.3% no signal
256 KiB VARCHAR(MAX) / fetchall() 1.939 ms 1.888 ms -0.9% no signal
10,000 scalar values / fetchval() (debug disabled) 105.672 ms 106.576 ms +1.8% no signal
Build and measurement details

ADO build 188563

PR head: 883d3526eac1ddfc297665cc535e50baefd8bcd0
Base: 4456be7894502d6d5da59286105063a795c4328d
Measured merge: d934fc63c81727ae097a148898db9bc768760f8f

  • Unix / SQL Server 2022: Python 3.12.3, x86_64, SQL 16.0.4305.5; 5 paired comparisons and 1 warmup.
  • Unix / SQL Server 2025: Python 3.12.3, x86_64, SQL 17.0.5035.5; 5 paired comparisons and 1 warmup.

A consistent change requires more than 20% median paired movement, at least 1 ms between the median runtimes, and at least 80% of pairs exceeding the relative threshold in the same direction. A slowdown without enough pair agreement is reported as inconsistent.

The displayed change is the median of paired before-and-after ratios. It is not recalculated from the two displayed median runtimes.

Both revisions use profiling-enabled builds on the same agent and database, with alternating order and discarded warmups. Results are diagnostic and do not represent production-wheel latency.

Raw samples and logs are attached to the ADO run as profiler-* artifacts.

@subrata-ms Subrata (subrata-ms) changed the title FEAT: Add preview TVP support for async queries FEAT: Add TVP support for async queries Sep 24, 2026
@github-actions github-actions Bot added the pr-size: medium Moderate update size label Sep 24, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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

Guard the optional native dependency test and complete the required PR metadata.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 Medium severity

Open (1)
What changed in this PR

Adds preview async TVP/type-hint support, iterable executemany, cursor state reporting, and expanded integration tests.

Changes:

  • Adds lazy native TVP and SQL type-hint exports.
  • Supports synchronous iterable batches and failure-result preservation.
  • Documents and tests async cursor/result behavior.
File Summary
tests/​AsyncTest/​test_006_async_execute.py Tests iterable batches, TVPs, and type hints.
tests/​AsyncTest/​test_005_async_cursor.py Tests cursor state and result behavior.
tests/​AsyncTest/​test_004_async_logging.py Updates execution logging expectations.
tests/​AsyncTest/​test_001_async_query_native.py Tests native exports. Finding: moderate, 2 votes—add an importorskip guard for the optional dependency at lines 55 and 65.
mssql_python/​async_query/​async_execute.py Adds iterable batch execution and failure handling.
mssql_python/​async_query/​async_cursor.py Adds cursor state and result-contract documentation.
mssql_python/​async_query/​__init__.py Adds lazy native exports. Finding: nit, 1 vote—replace PR placeholders and empty summary with valid metadata.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 24, 2026 10:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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

Fix the indentation error that prevents the native async test module from being collected.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity

Open (1)
Resolved since last review (1)

Copilot AI review requested due to automatic review settings September 24, 2026 11:05
@github-actions github-actions Bot added pr-size: large Substantial code update and removed pr-size: medium Moderate update size labels Sep 24, 2026
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

Fix the indentation error that prevents the native async test module from being collected.

Review effort: Lite
Findings: None

Resolved since last review (1)

Copilot AI review requested due to automatic review settings September 24, 2026 11:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

Cancellation handling and version-specific collation test behavior need correction.

Review effort: Lite
Findings: None

@github-actions

github-actions Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

📊 Code Coverage Report

🔥 Diff Coverage

91%


🎯 Overall Coverage

85%


📈 Total Lines Covered: 9662 out of 11360
📁 Project: mssql-python


Diff Coverage

Diff: main...HEAD, staged and unstaged changes

  • mssql_python/async_query/init.py (100%)
  • mssql_python/async_query/async_cursor.py (100%)
  • mssql_python/async_query/async_execute.py (85.7%): Missing lines 105-107,112

Summary

  • Total: 49 lines
  • Missing: 4 lines
  • Coverage: 91%

mssql_python/async_query/async_execute.py

Lines 101-116

  101     def parameter_rows():
  102         nonlocal iteration_error
  103         try:
  104             iterator = iter(seq_of_parameters)
! 105         except BaseException as error:
! 106             iteration_error = error
! 107             raise
  108         while True:
  109             try:
  110                 row = next(iterator)
  111             except StopIteration:
! 112                 return
  113             except BaseException as error:
  114                 iteration_error = error
  115                 raise
  116             yield row


📋 Files Needing Attention

📉 Files with overall lowest coverage (click to expand)
mssql_python.pybind.performance_counter.hpp: 0.7%
mssql_python.pybind.logger_bridge.cpp: 57.9%
mssql_python.pybind.ddbc_bindings.h: 62.6%
mssql_python.pybind.logger_bridge.hpp: 70.8%
mssql_python.pybind.connection.connection_pool.cpp: 81.3%
mssql_python.pybind.connection.connection.cpp: 82.5%
mssql_python.logging.py: 86.2%
mssql_python.pooling.py: 90.1%
mssql_python.pybind.fetch_temporal.hpp: 92.1%
mssql_python.cursor.py: 92.5%

🔗 Quick Links

⚙️ Build Summary 📋 Coverage Details

View Azure DevOps Build

Browse Full Coverage Report

Copilot AI review requested due to automatic review settings September 24, 2026 11:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

The pinned native core dependency must be updated or the new exports gated before approval.

Review effort: Lite
Findings: None

Copilot AI balanced review requested due to automatic review settings November 2, 2026 09:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Parameter iterator failures can still be translated from RuntimeError to InterfaceError during call-time or await-time consumption, losing the original exception’s type and identity.

3 open issues

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings November 3, 2026 04:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Caller iterator exceptions are still incorrectly translated into database errors, and native-dependent tests fail in supported namespace-package and missing-extension configurations.

5 open issues

Review effort: Balanced

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 3, 2026 05:47
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Iterator-origin exceptions are still translated into database errors, masking the original exception and breaking callers that catch it.

2 open issues
3 resolved since last review

Review effort: Balanced

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 3, 2026 06:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Iterator error handling can replace row-validation failures with GeneratorExit, bypassing ordinary exception handlers, and strip explicit exception causes needed for root-cause diagnostics.

2 open issues
2 resolved since last review

Review effort: Balanced

Refactor parameter_rows to use an iterator for seq_of_parameters.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 3, 2026 06:19
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

TVP serialization, metadata fidelity, and pre-dispatch iterable validation depend on unavailable native code and require verification against the pinned dependency and a live SQL Server.

No open issues 🎉

2 resolved since last review

Review effort: Balanced

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 3, 2026 07:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

TVP metadata, serialization, and pre-dispatch iterable validation depend on native code absent from this snapshot and require SQL Server integration validation unavailable in this review environment.

No open issues 🎉

Review effort: Balanced

@subrata-ms
Subrata (subrata-ms) enabled auto-merge (squash) November 3, 2026 07:36
@subrata-ms
Subrata (subrata-ms) merged commit 5fd2331 into main Nov 3, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-size: large Substantial code update

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants