morningman opened a new pull request, #67381:
URL: https://github.com/apache/doris/pull/67381
### 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` /
`IllegalStateException` as 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 that
`StmtExecutor.sendCachedValues` replays through a `MysqlChannel`. An Arrow
Flight SQL connection has no channel, so an entry created by an identical MySQL
query makes `handleQueryStmt` take the cached-plan branch and fail
`Preconditions.checkState(connectType == MYSQL)` in `sendFields()`. The client
sees:
```
INTERNAL: get flight info statement failed, after executeQueryStatement
handleQuery,
error code: ERR_UNKNOWN_ERROR, error msg: IllegalStateException, msg: null
```
The `CacheAnalyzer` branch right below it is already gated on `channel !=
null` with 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 map `HLL`
/ `BITMAP` / `QUANTILE_STATE` to Arrow `binary` and 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 1` fails exactly the same way.
Two conditions have to line up, which is why this is not seen more often:
1. The same sql text must have been run on a MySQL connection first (an
Arrow Flight connection never populates the cache).
2. Both sessions must agree on every session variable the cache compares
(`NereidsSqlCacheManager.usedVariablesChanged` over the `affectQueryResult*`
set). The MySQL **JDBC driver** adds `STRICT_TRANS_TABLES` to `sql_mode` at
connect time while the Arrow Flight JDBC driver does not, so a JDBC control
session masks the bug -- a `mysql` CLI session, or any client that leaves
`sql_mode` alone, 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 bare
`IllegalStateException`.
- `SessionVariable`: 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 -- a separate, pure-MySQL-protocol
correctness bug in the same family.
### Release note
Fix an `IllegalStateException` when an Arrow Flight SQL query hits the FE
sql cache, and fix `return_object_data_as_binary` not being part of the sql
cache key.
### Check List (For Author)
- Test
- [x] Regression test
`regression-test/suites/arrow_flight_sql_p0/test_sql_cache_over_arrow_flight.groovy`
primes 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 raw
`HLL` / `QUANTILE_STATE` columns from the issue, and their `hll_cardinality` /
`quantile_percent` conversions.
`regression-test/suites/query_p0/cache/sql_cache_object_type.groovy`
covers the `return_object_data_as_binary` cache key.
Both were verified to actually catch their bug: reverted individually
against a live single-FE/single-BE cluster, `test_sql_cache_over_arrow_flight`
fails with the exact reported `IllegalStateException` and
`sql_cache_object_type` fails on `return_object_data_as_binary=true must not
reuse the entry cached with it off`. Note for anyone extending these:
`Suite.arrow_flight_sql()` prepends `USE <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 align `sql_mode` explicitly.
- [ ] Unit Test
- [ ] Manual test (add detailed scripts or steps below)
- [ ] No need to test or manual test. Explain why:
- Behavior changed:
- [x] Yes. An Arrow Flight SQL connection no longer reads the FE sql
cache (it never wrote to it), so such a query is always executed instead of
failing. A session whose `return_object_data_as_binary` differs from the one
that populated the cache now gets its own entry instead of the other session's
rows.
- Does this need documentation?
- [x] No.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]