Repository navigation
Fix missing description for statements that do not start with SELECT - #33
Merged
CollierKing merged 1 commit intoOct 2, 2026
Merged
Conversation
cursor.description was only built when the SQL started with SELECT, PRAGMA or WITH, or contained RETURNING. A leading comment, EXPLAIN and VALUES all return rows, but came back with no description, so SQLAlchemy treated them as returning nothing. Use the column names D1 sends whenever there are any, and keep the keyword test as the fallback for replies without them. The async adapter now follows the cursor's description instead of its own copy of the keyword test. Fixes CollierKing#32
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
cursor.descriptionisNonefor statements that return rows but do not start withSELECT,PRAGMAorWITH(#32): a leading comment,EXPLAIN QUERY PLAN,VALUES, aSELECTin brackets. SQLAlchemy then treats them as returning nothing and raisesThis result object does not return rows.Fix
_build_descriptionnow uses the column names from D1 whenever there are any, and keeps the keyword test only as the fallback for replies with no columns. Statements D1 sends no columns for (INSERT,UPDATE,CREATEand so on) still getNone.The async adapter in
dialect_async.pyhad its own copy of the keyword test, so it now follows the cursor's description instead.Tests
/rawreplies throughhttpx.MockTransport: a leading--or/* */comment, a bracketedSELECT,EXPLAIN QUERY PLANandVALUESall get a description; anINSERTwith no columns still getsNone; aSELECTwith no columns keeps[]; a commentedSELECTreturns rows through both the sync and the async engine. The new tests fail without the fix. Unit suite: 54 passed on Python 3.11 and 3.9.TestDescriptionWithoutSelectKeywordclass. 6 of its 7 tests fail onmain(theINSERTguard passes on both). With the fix, the REST API and base URL integration files pass: 93 passed.ruff check,ruff format --diff,mypy src/,codespellandpre-commit run --all-filesare clean._build_description, so it gets the same change.Left as is: in the Worker path, the
raw()fallback for empty results still only runs for statements that start withSELECT, because it runs the statement a second time.This PR and #34 touch different lines and merge cleanly together.
Fixes #32