@@ -25,6 +25,7 @@ use arrow_schema::SchemaRef;
2525use chrono:: NaiveDateTime ;
2626use chrono:: { DateTime , Duration , Utc } ;
2727use datafusion:: arrow:: record_batch:: RecordBatch ;
28+ use datafusion:: catalog:: SchemaProvider ;
2829use datafusion:: common:: tree_node:: Transformed ;
2930use datafusion:: execution:: disk_manager:: DiskManager ;
3031use datafusion:: execution:: {
@@ -45,7 +46,7 @@ use datafusion::sql::sqlparser::dialect::PostgreSqlDialect;
4546use futures:: Stream ;
4647use futures:: stream:: select_all;
4748use itertools:: Itertools ;
48- use once_cell:: sync:: Lazy ;
49+ use once_cell:: sync:: { Lazy , OnceCell } ;
4950use serde:: { Deserialize , Serialize } ;
5051use serde_json:: { Value , json} ;
5152use std:: ops:: Bound ;
@@ -57,7 +58,6 @@ use sysinfo::System;
5758use tokio:: runtime:: Runtime ;
5859
5960use self :: error:: ExecuteError ;
60- use self :: stream_schema_provider:: GlobalSchemaProvider ;
6161pub use self :: stream_schema_provider:: PartialTimeFilter ;
6262use crate :: alerts:: alert_structs:: Conditions ;
6363use crate :: alerts:: alerts_utils:: get_filter_string;
@@ -70,7 +70,8 @@ use crate::handlers::http::query::QueryError;
7070use crate :: metrics:: increment_bytes_scanned_in_query_by_date;
7171use crate :: option:: Mode ;
7272use crate :: parseable:: { DEFAULT_TENANT , PARSEABLE } ;
73- use crate :: storage:: { ObjectStorageProvider , ObjectStoreFormat } ;
73+ use crate :: query:: stream_schema_provider:: GlobalSchemaProvider ;
74+ use crate :: storage:: { ObjectStorage , ObjectStorageProvider , ObjectStoreFormat } ;
7475use crate :: utils:: time:: TimeRange ;
7576
7677/// Boxed record-batch stream used as the streaming half of query results.
@@ -95,6 +96,7 @@ type QueryResult = Result<(Either<Vec<RecordBatch>, BoxedBatchStream>, Vec<Strin
9596
9697// pub static QUERY_SESSION: Lazy<SessionContext> =
9798// Lazy::new(|| Query::create_session_context(PARSEABLE.storage()));
99+ pub static SCHEMA_PROVIDER : OnceCell < Box < dyn ParseableSchemaProvider > > = OnceCell :: new ( ) ;
98100
99101pub static QUERY_SESSION_STATE : Lazy < SessionState > =
100102 Lazy :: new ( || Query :: create_session_state ( PARSEABLE . storage ( ) ) ) ;
@@ -110,6 +112,15 @@ pub static QUERY_SESSION: Lazy<InMemorySessionContext> = Lazy::new(|| {
110112 }
111113} ) ;
112114
115+ /// Trait to enable implementation of SchemaProvider
116+ pub trait ParseableSchemaProvider : Send + Sync {
117+ fn new_provider (
118+ & self ,
119+ storage : Option < Arc < dyn ObjectStorage > > ,
120+ tenant_id : & Option < String > ,
121+ ) -> Box < dyn SchemaProvider > ;
122+ }
123+
113124pub struct InMemorySessionContext {
114125 session_context : Arc < RwLock < SessionContext > > ,
115126}
@@ -124,18 +135,23 @@ impl InMemorySessionContext {
124135 }
125136
126137 pub fn add_schema ( & self , tenant_id : & str ) {
138+ let schema_provider = if let Some ( provider) = SCHEMA_PROVIDER . get ( ) {
139+ provider. new_provider (
140+ Some ( PARSEABLE . storage ( ) . get_object_store ( ) ) ,
141+ & Some ( tenant_id. to_owned ( ) ) ,
142+ )
143+ } else {
144+ Box :: new ( GlobalSchemaProvider {
145+ storage : PARSEABLE . storage ( ) . get_object_store ( ) ,
146+ tenant_id : Some ( tenant_id. to_owned ( ) ) ,
147+ } )
148+ } ;
127149 self . session_context
128150 . write ( )
129151 . expect ( "SessionContext should be writeable" )
130152 . catalog ( "datafusion" )
131153 . expect ( "Default catalog should be available" )
132- . register_schema (
133- tenant_id,
134- Arc :: new ( GlobalSchemaProvider {
135- storage : PARSEABLE . storage ( ) . get_object_store ( ) ,
136- tenant_id : Some ( tenant_id. to_owned ( ) ) ,
137- } ) ,
138- )
154+ . register_schema ( tenant_id, schema_provider. into ( ) )
139155 . expect ( "Should be able to register new schema" ) ;
140156 }
141157
@@ -184,29 +200,41 @@ impl Query {
184200 // register multiple schemas
185201 if let Some ( tenants) = PARSEABLE . list_tenants ( ) {
186202 for t in tenants. iter ( ) {
187- let schema_provider = Arc :: new ( GlobalSchemaProvider {
188- storage : storage. get_object_store ( ) ,
189- tenant_id : Some ( t. clone ( ) ) ,
190- } ) ;
191- let _ = catalog. register_schema ( t, schema_provider) ;
203+ let schema_provider = if let Some ( provider) = SCHEMA_PROVIDER . get ( ) {
204+ provider. new_provider (
205+ Some ( PARSEABLE . storage ( ) . get_object_store ( ) ) ,
206+ & Some ( t. to_owned ( ) ) ,
207+ )
208+ } else {
209+ Box :: new ( GlobalSchemaProvider {
210+ storage : PARSEABLE . storage ( ) . get_object_store ( ) ,
211+ tenant_id : Some ( t. to_owned ( ) ) ,
212+ } )
213+ } ;
214+ let _ = catalog. register_schema ( t, schema_provider. into ( ) ) ;
192215 }
193216 }
194217 } else {
195218 // register just one schema
196- let schema_provider = Arc :: new ( GlobalSchemaProvider {
197- storage : storage. get_object_store ( ) ,
198- tenant_id : None ,
199- } ) ;
219+ let schema_provider = if let Some ( provider) = SCHEMA_PROVIDER . get ( ) {
220+ provider. new_provider ( Some ( PARSEABLE . storage ( ) . get_object_store ( ) ) , & None )
221+ } else {
222+ Box :: new ( GlobalSchemaProvider {
223+ storage : PARSEABLE . storage ( ) . get_object_store ( ) ,
224+ tenant_id : None ,
225+ } )
226+ } ;
227+
200228 let _ = catalog. register_schema (
201229 & state. config_options ( ) . catalog . default_schema ,
202- schema_provider,
230+ schema_provider. into ( ) ,
203231 ) ;
204232 }
205233
206234 SessionContext :: new_with_state ( state)
207235 }
208236
209- fn create_session_state ( storage : Arc < dyn ObjectStorageProvider > ) -> SessionState {
237+ pub fn create_session_state ( storage : Arc < dyn ObjectStorageProvider > ) -> SessionState {
210238 let runtime_config = storage
211239 . get_datafusion_runtime ( )
212240 . with_disk_manager_builder ( DiskManager :: builder ( ) ) ;
@@ -288,14 +316,10 @@ impl Query {
288316 return Ok ( ( Either :: Left ( vec ! [ ] ) , fields) ) ;
289317 }
290318
291- let plan = QUERY_SESSION
292- . get_ctx ( )
293- . state ( )
294- . create_physical_plan ( df. logical_plan ( ) )
295- . await ?;
319+ let plan = ctx. state ( ) . create_physical_plan ( df. logical_plan ( ) ) . await ?;
296320
297321 let results = if !is_streaming {
298- let task_ctx = QUERY_SESSION . get_ctx ( ) . task_ctx ( ) ;
322+ let task_ctx = ctx . task_ctx ( ) ;
299323
300324 let batches = collect_partitioned ( plan. clone ( ) , task_ctx. clone ( ) )
301325 . await ?
@@ -311,7 +335,7 @@ impl Query {
311335
312336 Either :: Left ( batches)
313337 } else {
314- let task_ctx = QUERY_SESSION . get_ctx ( ) . task_ctx ( ) ;
338+ let task_ctx = ctx . task_ctx ( ) ;
315339
316340 let output_partitions = plan. output_partitioning ( ) . partition_count ( ) ;
317341
0 commit comments