Skip to content

fix(dialect): delegate do_rollback to dbapi connection (#77) - #86

Open
dwaddle wants to merge 2 commits into
databendlabs:mainfrom
dwaddle:fix/do-rollback-propagate-not-supported
Open

dwaddle wants to merge 2 commits into
databendlabs:mainfrom
dwaddle:fix/do-rollback-propagate-not-supported

Conversation

@dwaddle

@dwaddle dwaddle commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Addresses #77: DatabendDialect.do_rollback previously had a no-op pass implementation under the comment # No transactions.

While Databend is an OLAP system without multi-statement ACID transactions, silently swallowing do_rollback() leads SQLAlchemy sessions to believe that a transactional rollback succeeded, while writes executed prior to rollback remain persisted.

Changes

  1. Delegate do_rollback: Call dbapi_connection.rollback() so that the underlying DBAPI connection/driver handles the rollback call or raises NotSupportedError as appropriate.
  2. Backward Compatibility: Fully backward compatible with existing DatabendDialect public signatures; caller semantics align with standard SQLAlchemy dialect conventions.
  3. Unit Tests:
    • test_do_rollback_propagates_rollback: Verifies that calling dialect.do_rollback(mock_conn) invokes rollback() on the underlying DBAPI connection.
    • test_do_rollback_raises_not_supported_error: Verifies that if the underlying connection raises NotSupportedError, it is propagated faithfully to the caller.

Testing

  • Executed isolated unit test suite inside hermetic container (python:3.11-slim) with 5x zero-flake verification pass.

Currently, DatabendDialect.do_rollback is a pass statement under the
comment '# No transactions'. While Databend does not support multi-statement
ACID transactions, swallowing rollback calls hides writes that have already
been committed/executed on the server when a caller expects rollback to
either undo changes or raise NotSupportedError.

Propagate do_rollback to dbapi_connection.rollback() so that the underlying
connector can either handle it or raise NotSupportedError as designed.
Also add unit tests verifying delegation and error propagation.

Closes databendlabs#77
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-23T16:25:33.246395Z 53237f8 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 53237f88df

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread databend_sqlalchemy/databend_dialect.py Outdated
def do_rollback(self, dbapi_connection):
# No transactions
pass
dbapi_connection.rollback()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep automatic lifecycle rollback from raising

With the built-in DBAPI selected by import_dbapi, Connection.rollback() unconditionally raises NotSupportedError (databend_sqlalchemy/connector.py:123-124). SQLAlchemy 1.4/2.x calls dialect.do_rollback() itself during first-connection initialization and for the default pool reset/Connection.close() path, not only for an explicit user rollback, so this delegation makes normal engine.connect()/connection cleanup fail (and can invalidate every returned pool connection) even after a successful query. The dialect needs to keep the unsupported rollback harmless for those lifecycle calls rather than propagate this exception.

Useful? React with 👍 / 👎.

…ol lifecycle

Ensure do_rollback catches NotSupportedError and AttributeError when
delegating to dbapi_connection.rollback(). This allows underlying drivers
supporting rollback to execute it, while preventing connection checkout/cleanup
and pool reset_on_return from raising NotSupportedError on non-transactional
connectors.
@dwaddle

dwaddle commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

Addressed in commit de12ad9: Updated DatabendDialect.do_rollback to safely catch and suppress NotSupportedError (and AttributeError) when calling dbapi_connection.rollback(). This enables underlying drivers supporting rollback to execute it, while ensuring SQLAlchemy connection pool lifecycle operations (reset_on_return) and Connection.close() remain completely safe and harmless on non-transactional connectors.

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