servers/http/result/
json_result.rs1use axum::http::{header, HeaderValue};
16use axum::response::{IntoResponse, Response};
17use common_error::status_code::StatusCode;
18use common_query::Output;
19use mime_guess::mime;
20use serde::{Deserialize, Serialize};
21use serde_json::{json, Map, Value};
22
23use crate::http::header::{GREPTIME_DB_HEADER_EXECUTION_TIME, GREPTIME_DB_HEADER_FORMAT};
24use crate::http::result::error_result::ErrorResponse;
25use crate::http::{handler, process_with_limit, GreptimeQueryOutput, HttpResponse, ResponseFormat};
26
27#[derive(Serialize, Deserialize, Debug)]
30pub struct JsonResponse {
31 output: Vec<GreptimeQueryOutput>,
32 execution_time_ms: u64,
33}
34
35impl JsonResponse {
36 pub async fn from_output(outputs: Vec<crate::error::Result<Output>>) -> HttpResponse {
37 match handler::from_output(outputs).await {
38 Err(err) => HttpResponse::Error(err),
39 Ok((output, _)) => {
40 if output.len() > 1 {
41 HttpResponse::Error(ErrorResponse::from_error_message(
42 StatusCode::InvalidArguments,
43 "cannot output multi-statements result in json format".to_string(),
44 ))
45 } else {
46 HttpResponse::Json(JsonResponse {
47 output,
48 execution_time_ms: 0,
49 })
50 }
51 }
52 }
53 }
54
55 pub fn output(&self) -> &[GreptimeQueryOutput] {
56 &self.output
57 }
58
59 pub fn with_execution_time(mut self, execution_time: u64) -> Self {
60 self.execution_time_ms = execution_time;
61 self
62 }
63
64 pub fn execution_time_ms(&self) -> u64 {
65 self.execution_time_ms
66 }
67
68 pub fn with_limit(mut self, limit: usize) -> Self {
69 self.output = process_with_limit(self.output, limit);
70 self
71 }
72}
73
74impl IntoResponse for JsonResponse {
75 fn into_response(mut self) -> Response {
76 debug_assert!(
77 self.output.len() <= 1,
78 "self.output has extra elements: {}",
79 self.output.len()
80 );
81
82 let execution_time = self.execution_time_ms;
83 let payload = match self.output.pop() {
84 None => String::default(),
85 Some(GreptimeQueryOutput::AffectedRows(n)) => json!({
86 "data": [],
87 "affected_rows": n,
88 "execution_time_ms": execution_time,
89 })
90 .to_string(),
91
92 Some(GreptimeQueryOutput::Records(records)) => {
93 let schema = records.schema();
94
95 let data: Vec<Map<String, Value>> = records
96 .rows
97 .iter()
98 .map(|row| {
99 schema
100 .column_schemas
101 .iter()
102 .enumerate()
103 .map(|(i, col)| (col.name.clone(), row[i].clone()))
104 .collect::<Map<String, Value>>()
105 })
106 .collect();
107
108 json!({
109 "data": data,
110 "execution_time_ms": execution_time,
111 })
112 .to_string()
113 }
114 };
115
116 (
117 [
118 (
119 header::CONTENT_TYPE,
120 HeaderValue::from_static(mime::APPLICATION_JSON.as_ref()),
121 ),
122 (
123 GREPTIME_DB_HEADER_FORMAT.clone(),
124 HeaderValue::from_static(ResponseFormat::Json.as_str()),
125 ),
126 (
127 GREPTIME_DB_HEADER_EXECUTION_TIME.clone(),
128 HeaderValue::from(execution_time),
129 ),
130 ],
131 payload,
132 )
133 .into_response()
134 }
135}