Skip to content

Stage 2: ODBC pooling primitives (ADO #47338) - #296

Draft
Saurabh Singh (saurabh500) wants to merge 1 commit into
saurabh500-stage-1-tds-reset-correctnessfrom
saurabh500-stage-2-odbc-pooling-primitives
Draft

Stage 2: ODBC pooling primitives (ADO #47338)#296
Saurabh Singh (saurabh500) wants to merge 1 commit into
saurabh500-stage-1-tds-reset-correctnessfrom
saurabh500-stage-2-odbc-pooling-primitives

Conversation

@saurabh500

@saurabh500 Saurabh Singh (saurabh500) commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Stage 2 of the mssql-odbc connection pooling effort ([AB#47338](https://sqlclientdrivers.visualstudio.com/b95cf060-8083-439d-8ef1-405d5bf219d8/_workitems/edit/47338)). Wires the two ODBC pooling attributes into mssql-odbc, building on the Stage 1 TDS reset/liveness primitives.

B1 — Constants (api/odbc_types.rs)

  • SQL_ATTR_CONNECTION_DEAD = 1209, SQL_CD_TRUE = 1, SQL_CD_FALSE = 0
  • SQL_ATTR_RESET_CONNECTION = 116, SQL_RESET_CONNECTION_YES = 1

B2 — SQLGetConnectAttr(SQL_ATTR_CONNECTION_DEAD) (api/get_connect_attr.rs)

  • Returns SQL_CD_FALSE only when the DBC is connected and client.is_connection_dead() is false; otherwise SQL_CD_TRUE.
  • Disconnected / never-connected ⇒ SQL_CD_TRUE (D1: msodbcsql defaults DEAD until a successful token read).
  • Cached read, no network probe (D2). Peeks the client under the short DBC mutex — never take()s it (D8).

B3 — SQLSetConnectAttr(SQL_ATTR_RESET_CONNECTION, YES) (api/set_connect_attr.rs + api/txn.rs)

  • Routed from set_connect_attr.rs into a new reset_connection handler in txn.rs.
  • Value validation (D7): only SQL_RESET_CONNECTION_YES accepted; any other value ⇒ HY024.
  • Claims the idle client via claim_dbc_client (busy/active_stmt ⇒ connection-busy; disconnected ⇒ 08003, D7).
  • Rolls back a live local transaction first (D4), then arms the full reset via prepare_reset_connection(false) (pool checkout does not preserve).
  • Clears state.local_tran_started. Never holds the DBC mutex across I/O.
  • The bit rides the next request; the self-acking round-trip is deferred to Stage 3 (A2/B4).

B7 (partial) — Tests

  • SQL_ATTR_CONNECTION_DEAD: SQL_CD_TRUE when disconnected / connected-without-client; SQL_CD_FALSE when connected-and-alive; null-pointer rejected.
  • SQL_ATTR_RESET_CONNECTION: non-YES ⇒ HY024; disconnected ⇒ 08003; busy (active_stmt) rejected; success clears local_tran_started and leaves the idle client in place.

Validation

  • cargo bfmt
  • cargo bclippy ✅ (warnings-as-errors)
  • cargo nextest run -p mssql-odbc ✅ 573 passed

Stacking

This PR targets saurabh500-stage-1-tds-reset-correctness, not main. It is stacked on Stage 1 PR #294 (which stacks on base PR #293).

[AB#47338](https://sqlclientdrivers.visualstudio.com/b95cf060-8083-439d-8ef1-405d5bf219d8/_workitems/edit/47338)

Add SQL_ATTR_CONNECTION_DEAD and SQL_ATTR_RESET_CONNECTION support for
connection pooling (Stage 2, ADO #47338).

- B1: add SQL_ATTR_CONNECTION_DEAD/SQL_CD_TRUE/SQL_CD_FALSE and
  SQL_ATTR_RESET_CONNECTION/SQL_RESET_CONNECTION_YES constants.
- B2: SQLGetConnectAttr(SQL_ATTR_CONNECTION_DEAD) returns a cached,
  never-probe liveness read; disconnected/never-connected reads DEAD.
- B3: SQLSetConnectAttr(SQL_ATTR_RESET_CONNECTION) validates the value
  (HY024 otherwise), rolls back a live local transaction, arms the full
  RESETCONNECTION bit via prepare_reset_connection(false), and clears
  local_tran_started; disconnected surfaces 08003, busy is rejected.
- Unit tests cover both attributes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 63e24621-7665-4572-a5b8-e5dfa55060a0
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.

1 participant