Skip to content

Commit 4d43264

Browse files
authored
fix(FlightSQL): empty query result set need a schema FlightData. (#10867)
1 parent b584f7e commit 4d43264

File tree

3 files changed

+30
-12
lines changed

3 files changed

+30
-12
lines changed

src/query/service/src/servers/flight_sql/flight_sql_service/query.rs

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414

1515
use std::sync::Arc;
1616

17-
use arrow_flight::utils::batches_to_flight_data;
1817
use arrow_flight::FlightData;
18+
use arrow_flight::SchemaAsIpc;
19+
use arrow_ipc::writer;
20+
use arrow_ipc::writer::IpcWriteOptions;
21+
use arrow_schema::Schema as ArrowSchema;
1922
use async_stream::stream;
2023
use common_exception::ErrorCode;
2124
use common_exception::Result;
@@ -35,16 +38,25 @@ use crate::interpreters::InterpreterFactory;
3538
use crate::sessions::Session;
3639

3740
impl FlightSqlServiceImpl {
38-
pub(super) fn block_to_flight_data(
39-
block: DataBlock,
40-
data_schema: &DataSchema,
41-
) -> Result<Vec<FlightData>> {
41+
pub(crate) fn schema_to_flight_data(data_schema: DataSchema) -> FlightData {
42+
let arrow_schema = ArrowSchema::from(&data_schema);
43+
let options = IpcWriteOptions::default();
44+
SchemaAsIpc::new(&arrow_schema, &options).into()
45+
}
46+
47+
pub fn block_to_flight_data(block: DataBlock, data_schema: &DataSchema) -> Result<FlightData> {
4248
let batch = block
4349
.to_record_batch(data_schema)
4450
.map_err(|e| ErrorCode::Internal(format!("{e:?}")))?;
45-
let schema = (*batch.schema()).clone();
46-
let batches = vec![batch];
47-
batches_to_flight_data(schema, batches).map_err(|e| ErrorCode::Internal(format!("{e:?}")))
51+
let options = IpcWriteOptions::default();
52+
let data_gen = writer::IpcDataGenerator::default();
53+
let mut dictionary_tracker = writer::DictionaryTracker::new(false);
54+
55+
let (_encoded_dictionaries, encoded_batch) = data_gen
56+
.encoded_batch(&batch, &mut dictionary_tracker, &options)
57+
.map_err(|e| ErrorCode::Internal(format!("{e:?}")))?;
58+
59+
Ok(encoded_batch.into())
4860
}
4961

5062
#[async_backtrace::framed]
@@ -101,18 +113,18 @@ impl FlightSqlServiceImpl {
101113
context.attach_query_str(plan.to_string(), plan_extras.stament.to_mask_sql());
102114
let interpreter = InterpreterFactory::get(context.clone(), plan).await?;
103115
let data_schema = interpreter.schema();
116+
let schema_flight_data = Self::schema_to_flight_data((*data_schema).clone());
104117

105118
let mut data_stream = interpreter.execute(context.clone()).await?;
106119

107120
let stream = stream! {
121+
yield Ok(schema_flight_data);
108122
while let Some(block) = data_stream.next().await {
109123
match block {
110124
Ok(block) => {
111125
match Self::block_to_flight_data(block, &data_schema) {
112-
Ok(data) => {
113-
for d in data {
114-
yield Ok(d)
115-
}
126+
Ok(flight_data) => {
127+
yield Ok(flight_data)
116128
}
117129
Err(err) => {
118130
yield Err(status!("Could not convert batches", err))

src/query/service/tests/it/servers/flight_sql/flight_sql_handler.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ async fn test_query() -> Result<()> {
115115
debug!("Auth succeeded with token: {:?}", token);
116116
let cases = [
117117
"select 1, 'abc', 1.1, 1.1::float32, 1::nullable(int)",
118+
"show tables",
118119
// "drop table if exists test1",
119120
// "create table test1(a int, b string)",
120121
// "insert into table test1(a, b) values (1, 'x'), (2, 'y')",

src/query/service/tests/it/servers/flight_sql/testdata/query.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@ select 1, 'abc', 1.1, 1.1::float32, 1::nullable(int)
66
+---+--------+-----+--------------+---------------+
77
| 1 | 616263 | 1.1 | 1.1 | 1 |
88
+---+--------+-----+--------------+---------------+
9+
---------- Input ----------
10+
show tables
11+
---------- Output ---------
12+
++
13+
++

0 commit comments

Comments
 (0)