diff --git a/datafusion/common/src/config.rs b/datafusion/common/src/config.rs index c9900204b97f..cb08ce80e11a 100644 --- a/datafusion/common/src/config.rs +++ b/datafusion/common/src/config.rs @@ -256,6 +256,9 @@ config_namespace! { /// query (i.e. [`Span`](sqlparser::tokenizer::Span)) will be collected /// and recorded in the logical plan nodes. pub collect_spans: bool, default = false + + /// Specifies the recursion depth limit when parsing complex SQL Queries + pub recursion_limit: usize, default = 50 } } diff --git a/datafusion/core/src/execution/session_state.rs b/datafusion/core/src/execution/session_state.rs index 85c2b2a0fd78..eddb40b3f52a 100644 --- a/datafusion/core/src/execution/session_state.rs +++ b/datafusion/core/src/execution/session_state.rs @@ -522,7 +522,10 @@ impl SessionState { ) })?; - let expr = DFParser::parse_sql_into_expr_with_dialect(sql, dialect.as_ref())?; + let mut parser = DFParser::new_with_dialect(sql, dialect.as_ref())? + .with_recursion_limit(self.config.options().sql_parser.recursion_limit); + + let expr = parser.parse_expr()?; Ok(expr) } diff --git a/datafusion/expr-common/src/type_coercion/binary.rs b/datafusion/expr-common/src/type_coercion/binary.rs index 3be35490a4d0..4235524ed84a 100644 --- a/datafusion/expr-common/src/type_coercion/binary.rs +++ b/datafusion/expr-common/src/type_coercion/binary.rs @@ -146,7 +146,7 @@ impl<'a> BinaryTypeCoercer<'a> { } And | Or => if matches!((self.lhs, self.rhs), (Boolean | Null, Boolean | Null)) { // Logical binary boolean operators can only be evaluated for - // boolean or null arguments. + // boolean or null arguments. Ok(Signature::uniform(Boolean)) } else { plan_err!( @@ -502,6 +502,14 @@ pub fn type_union_resolution(data_types: &[DataType]) -> Option { } } + // HACK: DataType::Utf8View is not a meaningful dictionary value type, so + // just pull this out if we dict-encoded it + if let Some(DataType::Dictionary(_, value_type)) = &candidate_type { + if value_type.as_ref() == &DataType::Utf8View { + candidate_type = Some(DataType::Utf8View); + } + } + candidate_type } diff --git a/datafusion/sql/src/parser.rs b/datafusion/sql/src/parser.rs index 9725166b8ae0..f33ae86cce3a 100644 --- a/datafusion/sql/src/parser.rs +++ b/datafusion/sql/src/parser.rs @@ -291,6 +291,13 @@ impl<'a> DFParser<'a> { }) } + /// Specify the maximum recursion limit while parsing. + pub fn with_recursion_limit(mut self, recursion_limit: usize) -> Self { + self.parser = self.parser.with_recursion_limit(recursion_limit); + self + } + + /// Parse a sql string into one or [`Statement`]s using the /// [`GenericDialect`]. pub fn parse_sql(sql: &str) -> Result, ParserError> { diff --git a/datafusion/sql/src/unparser/expr.rs b/datafusion/sql/src/unparser/expr.rs index 909533773435..4c72a72eeb61 100644 --- a/datafusion/sql/src/unparser/expr.rs +++ b/datafusion/sql/src/unparser/expr.rs @@ -1617,9 +1617,7 @@ impl Unparser<'_> { DataType::Union(_, _) => { not_impl_err!("Unsupported DataType: conversion: {data_type:?}") } - DataType::Dictionary(_, _) => { - not_impl_err!("Unsupported DataType: conversion: {data_type:?}") - } + DataType::Dictionary(_, val) => self.arrow_dtype_to_ast_dtype(val), DataType::Decimal128(precision, scale) | DataType::Decimal256(precision, scale) => { let mut new_precision = *precision as u64;