use std::sync::Arc;
use arrow::datatypes::DataType;
use chrono::{DateTime, Utc};
use datafusion_common::config::ConfigOptions;
use datafusion_common::{DFSchema, DFSchemaRef, Result};
use crate::{Expr, ExprSchemable};
#[derive(Debug, Clone)]
pub struct SimplifyContext {
schema: DFSchemaRef,
query_execution_start_time: Option<DateTime<Utc>>,
config_options: Arc<ConfigOptions>,
}
#[derive(Debug, Default)]
pub struct SimplifyContextBuilder {
schema: Option<DFSchemaRef>,
query_execution_start_time: Option<DateTime<Utc>>,
config_options: Option<Arc<ConfigOptions>>,
}
impl Default for SimplifyContext {
fn default() -> Self {
Self {
schema: Arc::new(DFSchema::empty()),
query_execution_start_time: None,
config_options: Arc::new(ConfigOptions::default()),
}
}
}
impl SimplifyContext {
pub fn builder() -> SimplifyContextBuilder {
SimplifyContextBuilder::default()
}
#[deprecated(
since = "54.0.0",
note = "Use SimplifyContextBuilder if you intend to use non-default values."
)]
pub fn with_config_options(mut self, config_options: Arc<ConfigOptions>) -> Self {
self.config_options = config_options;
self
}
#[deprecated(
since = "54.0.0",
note = "Use SimplifyContextBuilder if you intend to use non-default values."
)]
pub fn with_schema(mut self, schema: DFSchemaRef) -> Self {
self.schema = schema;
self
}
#[deprecated(
since = "54.0.0",
note = "Use SimplifyContextBuilder if you intend to use non-default values."
)]
pub fn with_query_execution_start_time(
mut self,
query_execution_start_time: Option<DateTime<Utc>>,
) -> Self {
self.query_execution_start_time = query_execution_start_time;
self
}
#[deprecated(
since = "54.0.0",
note = "Use SimplifyContextBuilder if you intend to use non-default values."
)]
pub fn with_current_time(mut self) -> Self {
self.query_execution_start_time = Some(Utc::now());
self
}
pub fn schema(&self) -> &DFSchemaRef {
&self.schema
}
pub fn is_boolean_type(&self, expr: &Expr) -> Result<bool> {
Ok(expr.get_type(&self.schema)? == DataType::Boolean)
}
pub fn nullable(&self, expr: &Expr) -> Result<bool> {
expr.nullable(self.schema.as_ref())
}
pub fn get_data_type(&self, expr: &Expr) -> Result<DataType> {
expr.get_type(&self.schema)
}
pub fn query_execution_start_time(&self) -> Option<DateTime<Utc>> {
self.query_execution_start_time
}
pub fn config_options(&self) -> &Arc<ConfigOptions> {
&self.config_options
}
}
impl SimplifyContextBuilder {
pub fn with_config_options(mut self, config_options: Arc<ConfigOptions>) -> Self {
self.config_options = Some(config_options);
self
}
pub fn with_schema(mut self, schema: DFSchemaRef) -> Self {
self.schema = Some(schema);
self
}
pub fn with_query_execution_start_time(
mut self,
query_execution_start_time: Option<DateTime<Utc>>,
) -> Self {
self.query_execution_start_time = query_execution_start_time;
self
}
pub fn with_current_time(mut self) -> Self {
self.query_execution_start_time = Some(Utc::now());
self
}
pub fn build(self) -> SimplifyContext {
SimplifyContext {
schema: self.schema.unwrap_or_else(|| Arc::new(DFSchema::empty())),
query_execution_start_time: self.query_execution_start_time,
config_options: self
.config_options
.unwrap_or_else(|| Arc::new(ConfigOptions::default())),
}
}
}
#[derive(Debug)]
pub enum ExprSimplifyResult {
Simplified(Expr),
Original(Vec<Expr>),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn simplify_context_builder_builds_default_context() {
let context = SimplifyContext::builder().build();
let default_options = ConfigOptions::default();
assert_eq!(context.schema().as_ref(), &DFSchema::empty());
assert_eq!(context.query_execution_start_time(), None);
assert_eq!(
context.config_options().optimizer.max_passes,
default_options.optimizer.max_passes
);
}
#[test]
fn simplify_context_builder_uses_overrides() {
let schema = Arc::new(DFSchema::empty());
let config_options = Arc::new(ConfigOptions::default());
let current_time = Utc::now();
let context = SimplifyContext::builder()
.with_schema(Arc::clone(&schema))
.with_config_options(Arc::clone(&config_options))
.with_query_execution_start_time(Some(current_time))
.build();
assert_eq!(context.schema().as_ref(), schema.as_ref());
assert_eq!(context.query_execution_start_time(), Some(current_time));
assert!(Arc::ptr_eq(context.config_options(), &config_options));
}
}