Uh oh!
There was an error while loading. Please reload this page.
[fix](sqlcache) Do not replay the MySQL sql cache on an Arrow Flight connection - #67381
Merged
Conversation
… connection The FE sql cache is keyed by "<catalog>.<db>:<user>:<sql text>" and is shared by every protocol, but its rows are MySQL wire protocol packets that StmtExecutor.sendCachedValues replays through a MysqlChannel. An Arrow Flight SQL connection has no channel, so a cache entry created by an identical MySQL query made handleQueryStmt take the cached-plan branch and fail Preconditions.checkState(connectType == MYSQL) in sendFields(), reaching the client as "INTERNAL ... IllegalStateException, msg: null" for any result type. The report was on raw HLL / QUANTILE_STATE columns, but those types are not the cause: both the FE schema helper and the BE map them to Arrow binary and have Arrow writers, and they read back fine once the query is actually executed. They only looked special because that sql text was the one primed through the MySQL control session. Look the sql cache up only for a MySQL connection, so any other protocol re-executes the query and gets its result from the BE. Such a connection never populates the cache either, so this only removes a broken read path. Also assert the channel in the cached-plan branch so a future regression names the protocol instead of throwing a bare IllegalStateException. While here, mark return_object_data_as_binary as affectQueryResultInExecution. It is forwarded to the BE and decides whether the MySQL result writer serializes HLL / BITMAP / QUANTILE_STATE as their raw bytes or as NULL, so it changes the cached rows and must take part in the cache key comparison; without it a session that turns it on is served the NULLs cached by a session that had it off. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LPwhYhsSio1HYk2kFnx7KY
hello-stephen
commented
Sep 1, 2026
Contributor
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
924060929
approved these changes
Sep 1, 2026
morningman
commented
Sep 1, 2026
ContributorAuthor
run buildall |
1 similar comment
morningman
commented
Sep 1, 2026
ContributorAuthor
run buildall |
hello-stephen
commented
Sep 1, 2026
Contributor
TPC-H: Total hot run time: 16737 ms |
hello-stephen
commented
Sep 1, 2026
Contributor
TPC-DS: Total hot run time: 81625 ms |
hello-stephen
commented
Sep 1, 2026
Contributor
ClickBench: Total hot run time: 14.58 s |
morningman
commented
Sep 2, 2026
ContributorAuthor
run external_p0 |
morningman
commented
Sep 2, 2026
ContributorAuthor
run external |
morningman
commented
Sep 2, 2026
ContributorAuthor
run external |
Uh oh!
There was an error while loading. Please reload this page.
hello-stephen
commented
Sep 2, 2026
Contributor
FE Regression Coverage ReportIncrement line coverage |
Merged
12 tasks
morningman added a commit
that referenced
this pull request
Sep 4, 2026
…rrow Flight connection (#67487) ### What problem does this PR solve? Issue Number: close#67368 Related PR: #67381 (sibling fix in the same tracking series), #62259 Problem Summary: A `UNIQUE KEY` point query that qualifies for the short-circuit path returned no Flight endpoint over Arrow Flight SQL. The client failed with ``` fetch arrow flight schema failed, no FlightSqlEndpointsLocations ``` and the row was silently dropped. The identical query with `SET_VAR(enable_short_circuit_query=false)` returned it on the same connection. **Root cause** — the short circuit produces no Arrow result at either end, and nothing prevented an Arrow Flight connection from planning one: * It executes on `PointQueryExecutor`, not a `Coordinator`, and `Coordinator`/`NereidsCoordinator` are the only places that register a `FlightSqlEndpointsLocation`. `StmtExecutor.executeAndSendResult` then returns early through its Arrow Flight branch with nothing registered and without ever calling `getNext()`, so `GetFlightInfo` found an empty endpoint list. * The BE cannot be pointed at either. `tablet_fetch_data` serializes with `VMysqlResultWriter` into `PTabletKeyLookupResponse.row_batch` and runs no fragment, so the `ArrowFlightResultBlockBuffer` that `fetch_arrow_flight_schema` looks up by finst id never exists. `LogicalResultSinkToShortCircuitPointQuery` did not look at the connect type, and `enable_short_circuit_query` defaults to `true`, so every ADBC / Arrow Flight JDBC point query on a MoW + light-schema-change + `store_row_column` table hit this. Prepared statements go through the same `executeQueryStatement` and failed identically. **Fix** — keep Arrow Flight SQL on the normal execution path. This has to be decided at plan time rather than when picking the executor: `OlapScanNode.computeTabletInfo` and several rewrite/property rules (`ChildOutputPropertyDeriver`, `ShuffleKeyPruner`, `NestedColumnPruning`, `PruneOlapScanPartition`) read `StatementContext.isShortCircuitQuery()` while the plan is being built, so flipping the flag later would run a coordinator over a plan shaped for a different execution mode. MySQL connections keep the short circuit unchanged. Returning the point-query result from the FE instead was considered and rejected for now: `FlightSqlChannel.addResult` builds varchar vectors only, so every column would come back as `Utf8`, inconsistent with the normal Flight path. Full support (Arrow serialization in the BE lookup RPC plus a result buffer to hand out an endpoint) is a larger change and out of scope here. Also refreshes a now-stale comment in `StmtExecutor` that said point queries reach the Arrow Flight deferral gate.
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 freeto 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.
What problem does this PR solve?
Issue Number: close#67364
Related PR: #65182, #65615
Problem Summary:
Reading anything over Arrow Flight SQL fails with
INTERNAL/IllegalStateExceptionas soon as the query hits the FE sql cache.The FE sql cache is keyed by
<catalog>.<db>:<user>:<sql text>(NereidsSqlCacheManager.generateCacheKey) and is shared by every protocol, but its rows are MySQL wire protocol packets thatStmtExecutor.sendCachedValuesreplays through aMysqlChannel. An Arrow Flight SQL connection has no channel, so an entry created by an identical MySQL query makeshandleQueryStmttake the cached-plan branch and failPreconditions.checkState(connectType == MYSQL)insendFields(). The client sees:The
CacheAnalyzerbranch right below it is already gated onchannel != nullwith a// TODO support arrow flight sql; only this cached-plan replay was left unguarded.This is not about
HLL/QUANTILE_STATE. The issue was reported on raw aggregate-state columns, but both the FE schema helper and the BE mapHLL/BITMAP/QUANTILE_STATEto Arrowbinaryand have Arrow writers for them, and they read back correctly once the query is actually executed. They only looked special because that sql text was the one primed through the MySQL control session;select 1fails exactly the same way.Two conditions have to line up, which is why this is not seen more often:
NereidsSqlCacheManager.usedVariablesChangedover theaffectQueryResult*set). The MySQL JDBC driver addsSTRICT_TRANS_TABLEStosql_modeat connect time while the Arrow Flight JDBC driver does not, so a JDBC control session masks the bug -- amysqlCLI session, or any client that leavessql_modealone, does not.What is changed
ConnectProcessor.executeQuery: look the sql cache up only for a MySQL connection. Any other protocol re-executes the query and gets its result from the BE. Such a connection never populates the cache either, so this only removes a broken read path; it does not change MySQL behaviour.StmtExecutor.handleQueryStmt: assert the channel in the cached-plan branch, so a future regression names the protocol instead of throwing a bareIllegalStateException.SessionVariable: markreturn_object_data_as_binaryasaffectQueryResultInExecution. It is forwarded to the BE and decides whether the MySQL result writer serializesHLL/BITMAP/QUANTILE_STATEas their raw bytes or as NULL, so it changes the cached rows and must take part in the cache key comparison. Without it, a session that turns it on is served the NULLs cached by a session that had it off -- a separate, pure-MySQL-protocol correctness bug in the same family.Release note
Fix an
IllegalStateExceptionwhen an Arrow Flight SQL query hits the FE sql cache, and fixreturn_object_data_as_binarynot being part of the sql cache key.Check List (For Author)
Test
regression-test/suites/arrow_flight_sql_p0/test_sql_cache_over_arrow_flight.groovyprimes the cache on a MySQL connection and reads the identical statement back over Arrow Flight, for a FE-cached constant result, a table scalar, the rawHLL/QUANTILE_STATEcolumns from the issue, and theirhll_cardinality/quantile_percentconversions.regression-test/suites/query_p0/cache/sql_cache_object_type.groovycovers thereturn_object_data_as_binarycache key.Both were verified to actually catch their bug: reverted individually against a live single-FE/single-BE cluster,
test_sql_cache_over_arrow_flightfails with the exact reportedIllegalStateExceptionandsql_cache_object_typefails onreturn_object_data_as_binary=true must not reuse the entry cached with it off. Note for anyone extending these:Suite.arrow_flight_sql()prependsUSE <db>;to the statement, which changes the sql text and therefore the cache key, so the flight statements are sent on the raw flight connection, and both sessions alignsql_modeexplicitly.Behavior changed:
return_object_data_as_binarydiffers from the one that populated the cache now gets its own entry instead of the other session's rows.Does this need documentation?