18
18
19
19
use actix_web:: http:: header:: ContentType ;
20
20
use actix_web:: web:: { self , Json } ;
21
- use actix_web:: { FromRequest , HttpRequest , Responder } ;
21
+ use actix_web:: { FromRequest , HttpRequest , HttpResponse , Responder } ;
22
22
use chrono:: { DateTime , Utc } ;
23
23
use datafusion:: common:: tree_node:: TreeNode ;
24
24
use datafusion:: error:: DataFusionError ;
25
25
use datafusion:: execution:: context:: SessionState ;
26
26
use futures_util:: Future ;
27
27
use http:: StatusCode ;
28
+ use serde:: { Deserialize , Serialize } ;
29
+ use serde_json:: { json, Value } ;
28
30
use std:: collections:: HashMap ;
29
31
use std:: pin:: Pin ;
30
32
use std:: sync:: Arc ;
@@ -39,7 +41,7 @@ use crate::event::commit_schema;
39
41
use crate :: metrics:: QUERY_EXECUTE_TIME ;
40
42
use crate :: option:: { Mode , CONFIG } ;
41
43
use crate :: query:: error:: ExecuteError ;
42
- use crate :: query:: Query as LogicalQuery ;
44
+ use crate :: query:: { DateBinRequest , DateBinResponse , Query as LogicalQuery } ;
43
45
use crate :: query:: { TableScanVisitor , QUERY_SESSION } ;
44
46
use crate :: rbac:: Users ;
45
47
use crate :: response:: QueryResponse ;
@@ -52,7 +54,7 @@ use crate::utils::user_auth_for_query;
52
54
use super :: modal:: utils:: logstream_utils:: create_stream_and_schema_from_storage;
53
55
54
56
/// Query Request through http endpoint.
55
- #[ derive( Debug , serde :: Deserialize , serde :: Serialize , Clone ) ]
57
+ #[ derive( Debug , Deserialize , Serialize , Clone ) ]
56
58
#[ serde( rename_all = "camelCase" ) ]
57
59
pub struct Query {
58
60
pub query : String ,
@@ -66,7 +68,7 @@ pub struct Query {
66
68
pub filter_tags : Option < Vec < String > > ,
67
69
}
68
70
69
- pub async fn query ( req : HttpRequest , query_request : Query ) -> Result < impl Responder , QueryError > {
71
+ pub async fn query ( req : HttpRequest , query_request : Query ) -> Result < HttpResponse , QueryError > {
70
72
let session_state = QUERY_SESSION . state ( ) ;
71
73
let raw_logical_plan = match session_state
72
74
. create_logical_plan ( & query_request. query )
@@ -81,11 +83,10 @@ pub async fn query(req: HttpRequest, query_request: Query) -> Result<impl Respon
81
83
. await ?
82
84
}
83
85
} ;
84
-
85
86
let time_range =
86
87
TimeRange :: parse_human_time ( & query_request. start_time , & query_request. end_time ) ?;
87
88
88
- // create a visitor to extract the table names present in query
89
+ // Create a visitor to extract the table names present in query
89
90
let mut visitor = TableScanVisitor :: default ( ) ;
90
91
let _ = raw_logical_plan. visit ( & mut visitor) ;
91
92
@@ -103,6 +104,31 @@ pub async fn query(req: HttpRequest, query_request: Query) -> Result<impl Respon
103
104
user_auth_for_query ( & permissions, & tables) ?;
104
105
105
106
let time = Instant :: now ( ) ;
107
+ if let Some ( column_name) = query. is_logical_plan_count_without_filters ( ) {
108
+ let date_bin_request = DateBinRequest {
109
+ stream : table_name. clone ( ) ,
110
+ start_time : query_request. start_time . clone ( ) ,
111
+ end_time : query_request. end_time . clone ( ) ,
112
+ num_bins : 1 ,
113
+ } ;
114
+ let date_bin_records = date_bin_request. get_bin_density ( ) . await ?;
115
+ let response = if query_request. fields {
116
+ json ! ( {
117
+ "fields" : vec![ & column_name] ,
118
+ "records" : vec![ json!( { column_name: date_bin_records[ 0 ] . log_count} ) ]
119
+ } )
120
+ } else {
121
+ Value :: Array ( vec ! [ json!( { column_name: date_bin_records[ 0 ] . log_count} ) ] )
122
+ } ;
123
+
124
+ let time = time. elapsed ( ) . as_secs_f64 ( ) ;
125
+
126
+ QUERY_EXECUTE_TIME
127
+ . with_label_values ( & [ & table_name] )
128
+ . observe ( time) ;
129
+
130
+ return Ok ( HttpResponse :: Ok ( ) . json ( response) ) ;
131
+ }
106
132
let ( records, fields) = query. execute ( table_name. clone ( ) ) . await ?;
107
133
108
134
let response = QueryResponse {
@@ -122,6 +148,24 @@ pub async fn query(req: HttpRequest, query_request: Query) -> Result<impl Respon
122
148
Ok ( response)
123
149
}
124
150
151
+ pub async fn get_date_bin (
152
+ req : HttpRequest ,
153
+ date_bin : Json < DateBinRequest > ,
154
+ ) -> Result < impl Responder , QueryError > {
155
+ let creds = extract_session_key_from_req ( & req) ?;
156
+ let permissions = Users . get_permissions ( & creds) ;
157
+
158
+ // does user have access to table?
159
+ user_auth_for_query ( & permissions, & [ date_bin. stream . clone ( ) ] ) ?;
160
+
161
+ let date_bin_records = date_bin. get_bin_density ( ) . await ?;
162
+
163
+ Ok ( web:: Json ( DateBinResponse {
164
+ fields : vec ! [ "date_bin_timestamp" . into( ) , "log_count" . into( ) ] ,
165
+ records : date_bin_records,
166
+ } ) )
167
+ }
168
+
125
169
pub async fn update_schema_when_distributed ( tables : & Vec < String > ) -> Result < ( ) , QueryError > {
126
170
if CONFIG . options . mode == Mode :: Query {
127
171
for table in tables {
0 commit comments