Skip to content

Commit 4e50143

Browse files
committed
feat: Added a new trait to expose SchemaProvider
1 parent b8e889e commit 4e50143

3 files changed

Lines changed: 59 additions & 29 deletions

File tree

src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,12 @@ pub mod validator;
5858
use std::time::Duration;
5959

6060
// Public re-exports of crates being used in enterprise
61+
pub use arrow_array;
62+
pub use arrow_flight;
63+
pub use arrow_ipc;
64+
pub use catalog as parseable_catalog;
6165
pub use datafusion;
66+
pub use datafusion_proto;
6267
pub use handlers::http::modal::{
6368
ParseableServer, ingest_server::IngestServer, query_server::QueryServer, server::Server,
6469
};
@@ -68,6 +73,7 @@ use parseable::PARSEABLE;
6873
use reqwest::{Client, ClientBuilder};
6974
pub use {opentelemetry, opentelemetry_otlp, opentelemetry_proto, opentelemetry_sdk};
7075
pub use {tracing_actix_web, tracing_opentelemetry, tracing_subscriber};
76+
pub use utils as parseable_utils;
7177

7278
// It is very unlikely that panic will occur when dealing with locks.
7379
pub const LOCK_EXPECT: &str = "Thread shouldn't panic while holding a lock";

src/query/mod.rs

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use arrow_schema::SchemaRef;
2525
use chrono::NaiveDateTime;
2626
use chrono::{DateTime, Duration, Utc};
2727
use datafusion::arrow::record_batch::RecordBatch;
28+
use datafusion::catalog::SchemaProvider;
2829
use datafusion::common::tree_node::Transformed;
2930
use datafusion::execution::disk_manager::DiskManager;
3031
use datafusion::execution::{
@@ -45,7 +46,7 @@ use datafusion::sql::sqlparser::dialect::PostgreSqlDialect;
4546
use futures::Stream;
4647
use futures::stream::select_all;
4748
use itertools::Itertools;
48-
use once_cell::sync::Lazy;
49+
use once_cell::sync::{Lazy, OnceCell};
4950
use serde::{Deserialize, Serialize};
5051
use serde_json::{Value, json};
5152
use std::ops::Bound;
@@ -57,7 +58,6 @@ use sysinfo::System;
5758
use tokio::runtime::Runtime;
5859

5960
use self::error::ExecuteError;
60-
use self::stream_schema_provider::GlobalSchemaProvider;
6161
pub use self::stream_schema_provider::PartialTimeFilter;
6262
use crate::alerts::alert_structs::Conditions;
6363
use crate::alerts::alerts_utils::get_filter_string;
@@ -70,7 +70,8 @@ use crate::handlers::http::query::QueryError;
7070
use crate::metrics::increment_bytes_scanned_in_query_by_date;
7171
use crate::option::Mode;
7272
use 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};
7475
use 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

99101
pub 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+
113124
pub 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

src/query/stream_schema_provider.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ pub enum PartialTimeFilter {
702702
}
703703

704704
impl PartialTimeFilter {
705-
fn try_from_expr(expr: &Expr, time_partition: &Option<String>) -> Option<Self> {
705+
pub fn try_from_expr(expr: &Expr, time_partition: &Option<String>) -> Option<Self> {
706706
let Expr::BinaryExpr(binexpr) = expr else {
707707
return None;
708708
};

0 commit comments

Comments
 (0)