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]

Reply via email to