Skip to content

Commit 4f221a0

Browse files
authored
feat: http handler return geometry_output_format with data. (#18963)
1 parent 4f03b8d commit 4f221a0

File tree

6 files changed

+66
-42
lines changed

6 files changed

+66
-42
lines changed

src/query/service/src/servers/http/v1/http_query_handlers.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use std::collections::BTreeMap;
1615
use std::collections::HashMap;
1716
use std::sync::Arc;
1817

@@ -142,6 +141,14 @@ impl QueryResponseField {
142141
}
143142
}
144143

144+
// settings also used by driver, may be set in query/session/global level
145+
// only available after binding
146+
#[derive(Serialize, Debug, Clone)]
147+
pub struct ResultFormatSettings {
148+
pub timezone: String,
149+
pub geometry_output_format: String,
150+
}
151+
145152
#[derive(Serialize, Debug, Clone)]
146153
pub struct QueryResponse {
147154
pub id: String,
@@ -161,11 +168,9 @@ pub struct QueryResponse {
161168
pub data: Arc<BlocksSerializer>,
162169
pub affect: Option<QueryAffect>,
163170
pub result_timeout_secs: Option<u64>,
164-
// settings also used by driver, may be set in query/session/global level
165-
// only include timezone for now
166-
// only available after binding
171+
167172
#[serde(skip_serializing_if = "Option::is_none")]
168-
pub settings: Option<BTreeMap<String, String>>,
173+
pub settings: Option<ResultFormatSettings>,
169174

170175
pub stats: QueryStats,
171176

@@ -195,7 +200,7 @@ impl QueryResponse {
195200
affect,
196201
error,
197202
warnings,
198-
driver_settings,
203+
result_format_settings: driver_settings,
199204
},
200205
}: HttpQueryResponseInternal,
201206
is_final: bool,

src/query/service/src/servers/http/v1/query/execute_state.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use std::collections::BTreeMap;
1615
use std::collections::HashMap;
1716
use std::sync::Arc;
1817
use std::time::SystemTime;
@@ -45,6 +44,7 @@ use crate::interpreters::interpreter_plan_sql;
4544
use crate::interpreters::Interpreter;
4645
use crate::interpreters::InterpreterFactory;
4746
use crate::interpreters::InterpreterQueryLog;
47+
use crate::servers::http::v1::http_query_handlers::ResultFormatSettings;
4848
use crate::sessions::AcquireQueueGuard;
4949
use crate::sessions::QueryAffect;
5050
use crate::sessions::QueryContext;
@@ -130,15 +130,15 @@ pub struct ExecuteRunning {
130130
// mainly used to get progress for now
131131
pub(crate) ctx: Arc<QueryContext>,
132132
schema: DataSchemaRef,
133-
driver_settings: Option<BTreeMap<String, String>>,
133+
result_format_settings: Option<ResultFormatSettings>,
134134
has_result_set: bool,
135135
#[allow(dead_code)]
136136
queue_guard: AcquireQueueGuard,
137137
}
138138

139139
pub struct ExecuteStopped {
140140
pub schema: DataSchemaRef,
141-
pub driver_settings: Option<BTreeMap<String, String>>,
141+
pub result_format_settings: Option<ResultFormatSettings>,
142142
pub has_result_set: Option<bool>,
143143
pub stats: Progresses,
144144
pub affect: Option<QueryAffect>,
@@ -200,18 +200,18 @@ impl Executor {
200200
Stopped(f) => f.schema.clone(),
201201
};
202202

203-
let driver_settings = match &self.state {
203+
let result_format_settings = match &self.state {
204204
Starting(_) => None,
205-
Running(r) => r.driver_settings.clone(),
206-
Stopped(f) => f.driver_settings.clone(),
205+
Running(r) => r.result_format_settings.clone(),
206+
Stopped(f) => f.result_format_settings.clone(),
207207
};
208208

209209
ResponseState {
210210
running_time_ms: self.get_query_duration_ms(),
211211
progresses: self.get_progress(),
212212
state: exe_state,
213213
error: err,
214-
driver_settings,
214+
result_format_settings,
215215
warnings: self.get_warnings(),
216216
affect: self.get_affect(),
217217
schema,
@@ -319,7 +319,7 @@ impl Executor {
319319
ExecuteStopped {
320320
stats: Default::default(),
321321
schema: Default::default(),
322-
driver_settings: None,
322+
result_format_settings: None,
323323
has_result_set: None,
324324
reason: reason.clone(),
325325
session_state: ExecutorSessionState::new(s.ctx.get_current_session()),
@@ -342,7 +342,7 @@ impl Executor {
342342
ExecuteStopped {
343343
stats: Progresses::from_context(&r.ctx),
344344
schema: r.schema.clone(),
345-
driver_settings: r.driver_settings.clone(),
345+
result_format_settings: r.result_format_settings.clone(),
346346
has_result_set: Some(r.has_result_set),
347347
reason: reason.clone(),
348348
session_state: ExecutorSessionState::new(r.ctx.get_current_session()),
@@ -401,15 +401,23 @@ impl ExecuteState {
401401
} else {
402402
Default::default()
403403
};
404-
let tz = ctx.get_settings().get_timezone().with_context(make_error)?;
405-
let driver_settings = Some(BTreeMap::from_iter([("timezone".to_string(), tz)]));
404+
let settings = ctx.get_settings();
405+
let timezone = settings.get_timezone().with_context(make_error)?;
406+
let geometry_output_format = settings
407+
.get_geometry_output_format()
408+
.with_context(make_error)?
409+
.to_string();
410+
let result_format_settings = Some(ResultFormatSettings {
411+
timezone,
412+
geometry_output_format,
413+
});
406414

407415
let running_state = ExecuteRunning {
408416
session,
409417
ctx: ctx.clone(),
410418
queue_guard,
411419
schema,
412-
driver_settings,
420+
result_format_settings,
413421
has_result_set,
414422
};
415423
info!("[HTTP-QUERY] Query state changed to Running");

src/query/service/src/servers/http/v1/query/http_query.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ use super::PageManager;
6767
use super::ResponseData;
6868
use super::Wait;
6969
use crate::servers::http::error::QueryError;
70+
use crate::servers::http::v1::http_query_handlers::ResultFormatSettings;
7071
use crate::servers::http::v1::ClientSessionManager;
7172
use crate::servers::http::v1::HttpQueryManager;
7273
use crate::servers::http::v1::QueryResponse;
@@ -491,7 +492,7 @@ pub struct StageAttachmentConf {
491492
pub struct ResponseState {
492493
pub has_result_set: Option<bool>,
493494
pub schema: DataSchemaRef,
494-
pub driver_settings: Option<BTreeMap<String, String>>,
495+
pub result_format_settings: Option<ResultFormatSettings>,
495496
pub running_time_ms: i64,
496497
pub progresses: Progresses,
497498
pub state: ExecuteStateKind,
@@ -848,7 +849,7 @@ impl HttpQuery {
848849
let state = ExecuteStopped {
849850
stats: Progresses::default(),
850851
schema: Default::default(),
851-
driver_settings: None,
852+
result_format_settings: None,
852853
has_result_set: None,
853854
reason: Err(e.clone()),
854855
session_state: ExecutorSessionState::new(

tests/nox/suites/1_stateful/09_http_handler/test_09_0001_json_response.py

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,3 @@ def test_json_response_errors():
4444
assert response3.json() == json.loads(
4545
'{"error": {"code": 404, "message": "not found"}}'
4646
)
47-
48-
def query_page_0(sql):
49-
data = {
50-
'sql': sql,
51-
"pagination": { "wait_time_secs": 5}
52-
}
53-
data = json.dumps(data)
54-
response = requests.post(
55-
query_url,
56-
auth=auth,
57-
headers={"Content-Type": "application/json"},
58-
data=data,
59-
)
60-
return response.json()
61-
62-
def test_timezone():
63-
timezone = 'Asia/Shanghai'
64-
r = query_page_0(f"settings (timezone='{timezone}') select 1")
65-
assert r.get('settings', {}).get('timezone') == timezone

tests/nox/suites/1_stateful/09_http_handler/test_09_0014_query_lifecycle.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
STICKY_HEADER = "X-DATABEND-STICKY-NODE"
99

1010
timezone = 'Asia/Shanghai'
11+
geometry_output_format = 'EWKB'
1112

1213
scan_progress = "scan_progress"
1314

@@ -25,7 +26,8 @@ def do_query(query, timeout=10, pagination=None, port=8000, patch=True):
2526
session = {
2627
"settings": {
2728
"http_handler_result_timeout_secs": f"{timeout}",
28-
"timezone": f"{timezone}"
29+
"timezone": f"{timezone}",
30+
"geometry_output_format": f"{geometry_output_format}"
2931
}
3032
}
3133

@@ -154,15 +156,17 @@ def test_query_lifecycle_finalized(rows):
154156
"final_uri": f"/v1/query/{query_id}/final",
155157
"next_uri": f"/v1/query/{query_id}/page/1",
156158
"kill_uri": f"/v1/query/{query_id}/kill",
157-
'settings': {'timezone': 'Asia/Shanghai'},
159+
'settings': {'timezone': 'Asia/Shanghai',
160+
"geometry_output_format": f"{geometry_output_format}" },
158161
'session': {'catalog': 'default',
159162
'database': 'default',
160163
'internal': sessions_internal,
161164
'need_keep_alive': False,
162165
'need_sticky': False,
163166
'role': 'account_admin',
164167
'settings': {'http_handler_result_timeout_secs': f'{timeout}',
165-
'timezone': f"{timezone}"},
168+
'timezone': f"{timezone}",
169+
"geometry_output_format": f"{geometry_output_format}" },
166170
'txn_state': 'AutoCommit'}
167171
}
168172

tests/nox/suites/1_stateful/09_http_handler/test_09_0015_arrow_ipc.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,28 @@ def drain_reader(reader):
6969

7070
rows.sort()
7171
assert rows == [x for x in range(97)]
72+
73+
def query_page_0(sql):
74+
query_url = "http://localhost:8000/v1/query"
75+
76+
data = {
77+
'sql': sql,
78+
"pagination": { "wait_time_secs": 5}
79+
}
80+
data = json.dumps(data)
81+
response = requests.post(
82+
query_url,
83+
auth=auth,
84+
headers={"Content-Type": "application/json"},
85+
data=data,
86+
)
87+
return response.json()
88+
89+
def test_result_format_settings():
90+
timezone = 'Asia/Shanghai'
91+
r = query_page_0(f"settings (timezone='{timezone}') select 1")
92+
assert r.get('settings', {}).get('timezone') == timezone
93+
94+
geometry_output_format = 'EWKB'
95+
r = query_page_0(f"settings (geometry_output_format='{geometry_output_format}') select 1")
96+
assert r.get('settings', {}).get('geometry_output_format') == geometry_output_format

0 commit comments

Comments
 (0)