do_rollback() swallows the connector's NotSupportedError, so a rollback reports success over a write that stands
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 68/100
Línea de trabajo
Localice DatabendDialect.do_rollback e inspeccione el comportamiento de connector Connection.rollback descrito en el issue. Verifique que rollback ya no informe de éxito ante una operación no compatible, y añada o actualice la cobertura para las rutas de error de rollback explícito y SQLAlchemy si el repositorio tiene pruebas correspondientes.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Versions
- databend-sqlalchemy 0.5.5
- databend-driver 0.34.2
- SQLAlchemy 2.0.51
- Python 3.12.9, macOS
- Server:
datafuselabs/databend:v1.2.925-patch-4in Docker
What happens
connector.Connection.rollback() is honest — it raises:
class Connection:
def commit(self): pass
def rollback(self):
raise NotSupportedError("Transactions are not supported")
but the dialect overrides do_rollback and swallows it:
class DatabendDialect:
def do_rollback(self, dbapi_connection):
# No transactions
pass
So sqlalchemy.Connection.rollback() returns normally over a write that is still there afterwards. Nothing raises, nothing warns.
Three sequences, one variable changed each time, row count read back on a fresh connection:
| sequence | rows afterwards |
|---|---|
| INSERT, connection closed without committing | 1 |
INSERT, then an explicit Connection.rollback() |
1 |
BEGIN, INSERT, ROLLBACK sent as plain statements |
1 |
Expected: either the rollback raises (the connector underneath already does), or it rolls something back.
Why this is worse than simply not having transactions
Wrapping writes in a transaction and rolling back on error is ordinary code, and this turns it from loudly unsupported into silently wrong. with engine.begin(): around a block that fails reports a clean rollback and leaves the partial write in place. SQLAlchemy's own error path issues a rollback when a statement fails inside a transaction, so that gets the same false report without the caller writing a rollback at all.
I ran into it building a compatibility layer that treats "can this engine undo a write" as a capability it has to answer per backend. Databend is the second engine I've seen answer that question wrongly, and the only one where the wrong answer comes from a deliberate override rather than an accident further down.
One thing worth stating precisely
"Databend has no transactions" isn't accurate, and the distinction matters for how you'd fix this. BEGIN/COMMIT are real statements, and every HTTP response carries a txn_state field (AutoCommit, in this configuration). Reaching them needs the client to carry the session back between requests — session_id and need_sticky in the response are how — and the blocking cursor path in databend-driver doesn't. So transactions are unreachable through this adapter rather than absent from the database. That's clearly a bigger piece of work; this issue is only about the false success.
Related: get_isolation_level raises NotImplementedError, so a caller can't ask the engine what it's going to do instead.
Suggested fix
Drop the do_rollback override and let the connector's NotSupportedError propagate. If that breaks too much for existing users, a warning would at least make it discoverable. The current shape is the one that can't be detected from outside.
- Lenguaje dominante
- Python
- Estrellas
- 15
- Forks
- 5
- Merge medio
- 1 d 15 h
- PR fusionados (30 d)
- 1
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de databendlabs/databend-sqlalchemy
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
-
Index.create() reports success and creates nothing: the compiler emits an empty string and the connector returns earlyPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
-
Time is rendered as DATETIME, so a time-of-day is silently stored as a 1970-01-01 timestampPosiblemente ocupada @dwaddle la tomó hace 3 días. Abierto
Dificultad 3/5 1-2 días Aptitud para principiantes 58/100
-
Dificultad 4/5 3-5 días Aptitud para principiantes 25/100
databendlabs/databend-sqlalchemy#58 · 1 comentario ·
Todos los issues de databendlabs/databend-sqlalchemy
Issues similares
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
conda-forge/conda-forge-bot#7025 ·
Los mantenedores suelen responder en 1 día
-
chore(ci): publish.yml's release-job comment counts the hand-created Releases as all of themAbiertoarea:ci
Dificultad 1/5 Menos de una hora Aptitud para principiantes 74/100
catincloud-labs/dagster-dex#149 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
home-assistant/core#188424 ·
Los mantenedores suelen responder en 1 día
-
Review backlog (docs-currency): README 'CI run' link lands on a run whose overall badge is cancelledAbiertoagent/reviewer needs-kind needs-triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 63/100
projectbluefin/utah#880 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
redis/memtier_benchmark#850 ·
Los mantenedores suelen responder en 1 día