@@ -25,9 +25,9 @@ use actix_web::{Either, FromRequest, HttpRequest, HttpResponse, Responder};
25
25
use arrow_array:: RecordBatch ;
26
26
use bytes:: Bytes ;
27
27
use chrono:: { DateTime , Utc } ;
28
- use datafusion:: common:: tree_node:: TreeNode ;
29
28
use datafusion:: error:: DataFusionError ;
30
29
use datafusion:: execution:: context:: SessionState ;
30
+ use datafusion:: sql:: sqlparser:: parser:: ParserError ;
31
31
use futures:: stream:: once;
32
32
use futures:: { future, Stream , StreamExt } ;
33
33
use futures_util:: Future ;
@@ -44,11 +44,10 @@ use tracing::{error, warn};
44
44
45
45
use crate :: event:: commit_schema;
46
46
use crate :: metrics:: QUERY_EXECUTE_TIME ;
47
- use crate :: option:: Mode ;
48
47
use crate :: parseable:: { StreamNotFound , PARSEABLE } ;
49
48
use crate :: query:: error:: ExecuteError ;
49
+ use crate :: query:: { resolve_stream_names, QUERY_SESSION } ;
50
50
use crate :: query:: { execute, CountsRequest , Query as LogicalQuery } ;
51
- use crate :: query:: { TableScanVisitor , QUERY_SESSION } ;
52
51
use crate :: rbac:: Users ;
53
52
use crate :: response:: QueryResponse ;
54
53
use crate :: storage:: ObjectStorageError ;
@@ -81,31 +80,21 @@ pub async fn get_records_and_fields(
81
80
query_request : & Query ,
82
81
req : & HttpRequest ,
83
82
) -> Result < ( Option < Vec < RecordBatch > > , Option < Vec < String > > ) , QueryError > {
83
+ let tables = resolve_stream_names ( & query_request. query ) ?;
84
84
let session_state = QUERY_SESSION . state ( ) ;
85
85
86
- // get the logical plan and extract the table name
87
- let raw_logical_plan = session_state
88
- . create_logical_plan ( & query_request. query )
89
- . await ?;
90
-
91
86
let time_range =
92
87
TimeRange :: parse_human_time ( & query_request. start_time , & query_request. end_time ) ?;
93
- // create a visitor to extract the table name
94
- let mut visitor = TableScanVisitor :: default ( ) ;
95
- let _ = raw_logical_plan. visit ( & mut visitor) ;
96
-
97
- let tables = visitor. into_inner ( ) ;
98
- update_schema_when_distributed ( & tables) . await ?;
99
- let query: LogicalQuery = into_query ( query_request, & session_state, time_range) . await ?;
100
88
89
+ let query: LogicalQuery =
90
+ into_query ( query_request, & session_state, time_range, & tables) . await ?;
101
91
let creds = extract_session_key_from_req ( req) ?;
102
92
let permissions = Users . get_permissions ( & creds) ;
103
93
104
- let table_name = query
105
- . first_table_name ( )
94
+ let table_name = tables
95
+ . first ( )
106
96
. ok_or_else ( || QueryError :: MalformedQuery ( "No table name found in query" ) ) ?;
107
-
108
- user_auth_for_datasets ( & permissions, & tables) ?;
97
+ user_auth_for_datasets ( & permissions, & tables) . await ?;
109
98
110
99
let ( records, fields) = execute ( query, & table_name, false ) . await ?;
111
100
@@ -121,35 +110,18 @@ pub async fn get_records_and_fields(
121
110
122
111
pub async fn query ( req : HttpRequest , query_request : Query ) -> Result < HttpResponse , QueryError > {
123
112
let session_state = QUERY_SESSION . state ( ) ;
124
- let raw_logical_plan = match session_state
125
- . create_logical_plan ( & query_request. query )
126
- . await
127
- {
128
- Ok ( raw_logical_plan) => raw_logical_plan,
129
- Err ( _) => {
130
- create_streams_for_querier ( ) . await ?;
131
- session_state
132
- . create_logical_plan ( & query_request. query )
133
- . await ?
134
- }
135
- } ;
136
113
let time_range =
137
114
TimeRange :: parse_human_time ( & query_request. start_time , & query_request. end_time ) ?;
138
-
139
- let mut visitor = TableScanVisitor :: default ( ) ;
140
- let _ = raw_logical_plan. visit ( & mut visitor) ;
141
- let tables = visitor. into_inner ( ) ;
142
- update_schema_when_distributed ( & tables) . await ?;
143
- let query: LogicalQuery = into_query ( & query_request, & session_state, time_range) . await ?;
144
-
115
+ let tables = resolve_stream_names ( & query_request. query ) ?;
116
+ let query: LogicalQuery =
117
+ into_query ( & query_request, & session_state, time_range, & tables) . await ?;
145
118
let creds = extract_session_key_from_req ( & req) ?;
146
119
let permissions = Users . get_permissions ( & creds) ;
147
120
148
- let table_name = query
149
- . first_table_name ( )
121
+ let table_name = tables
122
+ . first ( )
150
123
. ok_or_else ( || QueryError :: MalformedQuery ( "No table name found in query" ) ) ?;
151
-
152
- user_auth_for_datasets ( & permissions, & tables) ?;
124
+ user_auth_for_datasets ( & permissions, & tables) . await ?;
153
125
154
126
let time = Instant :: now ( ) ;
155
127
@@ -372,7 +344,7 @@ pub async fn get_counts(
372
344
let body = counts_request. into_inner ( ) ;
373
345
374
346
// does user have access to table?
375
- user_auth_for_datasets ( & permissions, & [ body. stream . clone ( ) ] ) ?;
347
+ user_auth_for_datasets ( & permissions, & [ body. stream . clone ( ) ] ) . await ?;
376
348
377
349
// if the user has given a sql query (counts call with filters applied), then use this flow
378
350
// this could include filters or group by
@@ -420,11 +392,9 @@ pub async fn update_schema_when_distributed(tables: &Vec<String>) -> Result<(),
420
392
// if the mode is query or prism, we need to update the schema in memory
421
393
// no need to commit schema to storage
422
394
// as the schema is read from memory everytime
423
- if PARSEABLE . options . mode == Mode :: Query || PARSEABLE . options . mode == Mode :: Prism {
424
- for table in tables {
425
- if let Ok ( new_schema) = fetch_schema ( table) . await {
426
- commit_schema ( table, Arc :: new ( new_schema) ) ?;
427
- }
395
+ for table in tables {
396
+ if let Ok ( new_schema) = fetch_schema ( table) . await {
397
+ commit_schema ( table, Arc :: new ( new_schema) ) ?;
428
398
}
429
399
}
430
400
@@ -520,6 +490,7 @@ pub async fn into_query(
520
490
query : & Query ,
521
491
session_state : & SessionState ,
522
492
time_range : TimeRange ,
493
+ tables : & Vec < String > ,
523
494
) -> Result < LogicalQuery , QueryError > {
524
495
if query. query . is_empty ( ) {
525
496
return Err ( QueryError :: EmptyQuery ) ;
@@ -532,9 +503,36 @@ pub async fn into_query(
532
503
if query. end_time . is_empty ( ) {
533
504
return Err ( QueryError :: EmptyEndTime ) ;
534
505
}
506
+ let raw_logical_plan = match session_state. create_logical_plan ( & query. query ) . await {
507
+ Ok ( plan) => plan,
508
+ Err ( _) => {
509
+ let mut join_set = JoinSet :: new ( ) ;
510
+ for stream_name in tables {
511
+ let stream_name = stream_name. clone ( ) ;
512
+ join_set. spawn ( async move {
513
+ let result = PARSEABLE
514
+ . create_stream_and_schema_from_storage ( & stream_name)
515
+ . await ;
516
+
517
+ if let Err ( e) = & result {
518
+ warn ! ( "Failed to create stream '{}': {}" , stream_name, e) ;
519
+ }
520
+
521
+ ( stream_name, result)
522
+ } ) ;
523
+ }
524
+
525
+ while let Some ( result) = join_set. join_next ( ) . await {
526
+ if let Err ( join_error) = result {
527
+ warn ! ( "Task join error: {}" , join_error) ;
528
+ }
529
+ }
530
+ session_state. create_logical_plan ( & query. query ) . await ?
531
+ }
532
+ } ;
535
533
536
534
Ok ( crate :: query:: Query {
537
- raw_logical_plan : session_state . create_logical_plan ( & query . query ) . await ? ,
535
+ raw_logical_plan,
538
536
time_range,
539
537
filter_tag : query. filter_tags . clone ( ) ,
540
538
} )
@@ -618,6 +616,8 @@ Description: {0}"#
618
616
CustomError ( String ) ,
619
617
#[ error( "No available queriers found" ) ]
620
618
NoAvailableQuerier ,
619
+ #[ error( "{0}" ) ]
620
+ ParserError ( #[ from] ParserError ) ,
621
621
}
622
622
623
623
impl actix_web:: ResponseError for QueryError {
0 commit comments