diff --git a/Cargo.lock b/Cargo.lock index 2529044629972..c753529139353 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2960,7 +2960,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -5049,7 +5049,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] @@ -5430,7 +5430,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -5938,9 +5938,9 @@ dependencies = [ [[package]] name = "sqlparser" -version = "0.62.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c6d1b651dc4edf07eead2a0c6c78016ce971bc2c10da5266861b13f25e7cec" +checksum = "3679862809bd1f92e563cf6fd820e28f39135303668001c10331d5027183e8b4" dependencies = [ "log", "recursive", @@ -5949,13 +5949,13 @@ dependencies = [ [[package]] name = "sqlparser_derive" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6dd45d8fc1c79299bfbb7190e42ccbbdf6a5f52e4a6ad98d92357ea965bd289" +checksum = "2905ae8e8148d8f7f5748ea95d1e949fa4fc1d7f5161547b758ad118b2e4b0aa" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.5", ] [[package]] @@ -6188,7 +6188,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -7133,7 +7133,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -7249,16 +7249,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", + "windows-targets", ] [[package]] @@ -7276,31 +7267,14 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] @@ -7318,96 +7292,48 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winnow" version = "1.0.2" diff --git a/Cargo.toml b/Cargo.toml index 5f11c5717c4f5..a3804ddd2b7c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -199,7 +199,7 @@ regex = "1.12" rstest = "0.26.1" serde_json = "1" sha2 = "^0.11.0" -sqlparser = { version = "0.62.0", default-features = false, features = ["std", "visitor"] } +sqlparser = { version = "0.63.0", default-features = false, features = ["std", "visitor"] } stacker = "0.1.24" strum = "0.28.0" strum_macros = "0.28.0" diff --git a/datafusion/sql/src/expr/function.rs b/datafusion/sql/src/expr/function.rs index a7f7979a67b36..4bbf3834dee35 100644 --- a/datafusion/sql/src/expr/function.rs +++ b/datafusion/sql/src/expr/function.rs @@ -166,6 +166,11 @@ impl FunctionArgs { "Calling {name}: LIMIT not supported in function arguments: {limit}" ); } + FunctionArgumentClause::Where(predicate) => { + return not_impl_err!( + "Calling {name}: WHERE not supported in function arguments: {predicate}" + ); + } FunctionArgumentClause::OnOverflow(overflow) => { return not_impl_err!( "Calling {name}: ON OVERFLOW not supported in function arguments: {overflow}" diff --git a/datafusion/sql/src/expr/mod.rs b/datafusion/sql/src/expr/mod.rs index 0fa1fc16bff00..ea2ed8eea33ce 100644 --- a/datafusion/sql/src/expr/mod.rs +++ b/datafusion/sql/src/expr/mod.rs @@ -450,16 +450,11 @@ impl SqlToRel<'_, S> { planner_context, ), - SQLExpr::Cast { array: true, .. } => { - not_impl_err!("`CAST(... AS type ARRAY`) not supported") - } - SQLExpr::Cast { kind: CastKind::Cast | CastKind::DoubleColon, expr, data_type, format, - array: false, } => { self.sql_cast_to_expr(*expr, &data_type, format, schema, planner_context) } @@ -469,7 +464,6 @@ impl SqlToRel<'_, S> { expr, data_type, format, - array: false, } => { if let Some(format) = format { return not_impl_err!("CAST with format is not supported: {format}"); @@ -1068,7 +1062,7 @@ impl SqlToRel<'_, S> { negated: bool, expr: SQLExpr, pattern: SQLExpr, - escape_char: Option, + escape_char: Option>, schema: &DFSchema, planner_context: &mut PlannerContext, case_insensitive: bool, @@ -1078,13 +1072,14 @@ impl SqlToRel<'_, S> { return not_impl_err!("ANY in LIKE expression"); } let pattern = self.sql_expr_to_logical_expr(pattern, schema, planner_context)?; - let escape_char = match escape_char.map(|v| v.value) { - Some(Value::SingleQuotedString(char)) if char.len() == 1 => { - Some(char.chars().next().unwrap()) - } - Some(value) => { + let escape_char = match escape_char.map(|e| *e) { + Some(SQLExpr::Value(ValueWithSpan { + value: Value::SingleQuotedString(char), + .. + })) if char.len() == 1 => Some(char.chars().next().unwrap()), + Some(expr) => { return plan_err!( - "Invalid escape character in LIKE expression. Expected a single character wrapped with single quotes, got {value}" + "Invalid escape character in LIKE expression. Expected a single character wrapped with single quotes, got {expr}" ); } None => None, @@ -1103,18 +1098,19 @@ impl SqlToRel<'_, S> { negated: bool, expr: SQLExpr, pattern: SQLExpr, - escape_char: Option, + escape_char: Option>, schema: &DFSchema, planner_context: &mut PlannerContext, ) -> Result { let pattern = self.sql_expr_to_logical_expr(pattern, schema, planner_context)?; - let escape_char = match escape_char.map(|v| v.value) { - Some(Value::SingleQuotedString(char)) if char.len() == 1 => { - Some(char.chars().next().unwrap()) - } - Some(value) => { + let escape_char = match escape_char.map(|e| *e) { + Some(SQLExpr::Value(ValueWithSpan { + value: Value::SingleQuotedString(char), + .. + })) if char.len() == 1 => Some(char.chars().next().unwrap()), + Some(expr) => { return plan_err!( - "Invalid escape character in SIMILAR TO expression. Expected a single character wrapped with single quotes, got {value}" + "Invalid escape character in SIMILAR TO expression. Expected a single character wrapped with single quotes, got {expr}" ); } None => None, diff --git a/datafusion/sql/src/expr/order_by.rs b/datafusion/sql/src/expr/order_by.rs index 0067a1ebd708c..fcf14d5dc8f1d 100644 --- a/datafusion/sql/src/expr/order_by.rs +++ b/datafusion/sql/src/expr/order_by.rs @@ -22,7 +22,7 @@ use datafusion_common::{ use datafusion_expr::expr::Sort; use datafusion_expr::{Expr, SortExpr}; use sqlparser::ast::{ - Expr as SQLExpr, OrderByExpr, OrderByOptions, Value, ValueWithSpan, + Expr as SQLExpr, OrderByExpr, OrderByOptions, OrderBySort, Value, ValueWithSpan, }; impl SqlToRel<'_, S> { @@ -75,7 +75,7 @@ impl SqlToRel<'_, S> { for order_by_expr in order_by_exprs { let OrderByExpr { expr, - options: OrderByOptions { asc, nulls_first }, + options: OrderByOptions { sort, nulls_first }, with_fill, } = order_by_expr; @@ -83,6 +83,15 @@ impl SqlToRel<'_, S> { return not_impl_err!("ORDER BY WITH FILL is not supported: {with_fill}"); } + let asc = match sort { + Some(OrderBySort::Asc) => Some(true), + Some(OrderBySort::Desc) => Some(false), + Some(OrderBySort::Using(op)) => { + return not_impl_err!("ORDER BY USING is not supported: {op}"); + } + None => None, + }; + let expr = match expr { SQLExpr::Value(ValueWithSpan { value: Value::Number(v, _), diff --git a/datafusion/sql/src/parser.rs b/datafusion/sql/src/parser.rs index fcf4708f1bf94..60562bbccee84 100644 --- a/datafusion/sql/src/parser.rs +++ b/datafusion/sql/src/parser.rs @@ -24,7 +24,7 @@ use datafusion_common::DataFusionError; use datafusion_common::config::{ConfigNonZeroUsize, SqlParserOptions}; use datafusion_common::format::{ExplainFormat, ExplainStatementOptions}; use datafusion_common::{Diagnostic, Span, sql_err}; -use sqlparser::ast::{ExprWithAlias, Ident, OrderByOptions}; +use sqlparser::ast::{ExprWithAlias, Ident, OrderByOptions, OrderBySort}; use sqlparser::tokenizer::TokenWithSpan; use sqlparser::{ ast::{ @@ -998,10 +998,10 @@ impl<'a> DFParser<'a> { pub fn parse_order_by_expr(&mut self) -> Result { let expr = self.parser.parse_expr()?; - let asc = if self.parser.parse_keyword(Keyword::ASC) { - Some(true) + let sort = if self.parser.parse_keyword(Keyword::ASC) { + Some(OrderBySort::Asc) } else if self.parser.parse_keyword(Keyword::DESC) { - Some(false) + Some(OrderBySort::Desc) } else { None }; @@ -1019,7 +1019,7 @@ impl<'a> DFParser<'a> { Ok(OrderByExpr { expr, - options: OrderByOptions { asc, nulls_first }, + options: OrderByOptions { sort, nulls_first }, with_fill: None, }) } @@ -1619,7 +1619,16 @@ mod tests { quote_style: None, span: Span::empty(), }), - options: OrderByOptions { asc, nulls_first }, + options: OrderByOptions { + sort: asc.map(|asc| { + if asc { + OrderBySort::Asc + } else { + OrderBySort::Desc + } + }), + nulls_first, + }, with_fill: None, }]], ..make_create_external_table("foo.csv") @@ -1643,7 +1652,7 @@ mod tests { span: Span::empty(), }), options: OrderByOptions { - asc: Some(true), + sort: Some(OrderBySort::Asc), nulls_first: None, }, with_fill: None, @@ -1655,7 +1664,7 @@ mod tests { span: Span::empty(), }), options: OrderByOptions { - asc: Some(false), + sort: Some(OrderBySort::Desc), nulls_first: Some(true), }, with_fill: None, @@ -1688,7 +1697,7 @@ mod tests { })), }, options: OrderByOptions { - asc: Some(true), + sort: Some(OrderBySort::Asc), nulls_first: None, }, with_fill: None, @@ -1731,7 +1740,7 @@ mod tests { })), }, options: OrderByOptions { - asc: Some(true), + sort: Some(OrderBySort::Asc), nulls_first: None, }, with_fill: None, @@ -1795,7 +1804,7 @@ mod tests { })), }, options: OrderByOptions { - asc: Some(true), + sort: Some(OrderBySort::Asc), nulls_first: None, }, with_fill: None, diff --git a/datafusion/sql/src/planner.rs b/datafusion/sql/src/planner.rs index a3e6d75fdbfac..e3f51cb075d0c 100644 --- a/datafusion/sql/src/planner.rs +++ b/datafusion/sql/src/planner.rs @@ -838,7 +838,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> { .collect::>>()?; Ok(DataType::Struct(Fields::from(fields))) } - SQLDataType::Map(key_type, value_type) => { + SQLDataType::Map(key_type, value_type, _) => { let key_field = Arc::new(Field::new( "key", self.convert_data_type_to_field(key_type)?.data_type().clone(), false )); diff --git a/datafusion/sql/src/query.rs b/datafusion/sql/src/query.rs index d23d1a008f7d7..f26411cd603c1 100644 --- a/datafusion/sql/src/query.rs +++ b/datafusion/sql/src/query.rs @@ -27,9 +27,9 @@ use datafusion_expr::{ CreateMemoryTable, DdlStatement, Distinct, Expr, LogicalPlan, LogicalPlanBuilder, }; use sqlparser::ast::{ - Expr as SQLExpr, ExprWithAliasAndOrderBy, LimitClause, Offset, OffsetRows, OrderBy, - OrderByExpr, OrderByKind, PipeOperator, Query, SelectInto, SetExpr, SetOperator, - SetQuantifier, TableAlias, Value, + Expr as SQLExpr, ExprWithAliasAndOrderBy, LimitClause, ObjectName, Offset, + OffsetRows, OrderBy, OrderByExpr, OrderByKind, PipeOperator, Query, SelectInto, + SetExpr, SetOperator, SetQuantifier, TableAlias, Value, }; impl SqlToRel<'_, S> { @@ -362,17 +362,30 @@ impl SqlToRel<'_, S> { select_into: Option, ) -> Result { match select_into { - Some(into) => Ok(LogicalPlan::Ddl(DdlStatement::CreateMemoryTable( - CreateMemoryTable { - name: self.object_name_to_table_reference(into.name)?, - constraints: Constraints::default(), - input: Arc::new(plan), - if_not_exists: false, - or_replace: false, - temporary: false, - column_defaults: vec![], - }, - ))), + Some(into) => { + let name = match into.targets.as_slice() { + [SQLExpr::Identifier(ident)] => ObjectName::from(vec![ident.clone()]), + [SQLExpr::CompoundIdentifier(idents)] => { + ObjectName::from(idents.clone()) + } + _ => { + return not_impl_err!( + "SELECT INTO only supports a single table name target" + ); + } + }; + Ok(LogicalPlan::Ddl(DdlStatement::CreateMemoryTable( + CreateMemoryTable { + name: self.object_name_to_table_reference(name)?, + constraints: Constraints::default(), + input: Arc::new(plan), + if_not_exists: false, + or_replace: false, + temporary: false, + column_defaults: vec![], + }, + ))) + } _ => Ok(plan), } } @@ -393,7 +406,7 @@ fn to_order_by_exprs( OrderByKind::All(options) => Ok((1..=order_by_all_column_count) .map(|position| OrderByExpr { expr: SQLExpr::value(Value::Number(position.to_string(), false)), - options, + options: options.clone(), with_fill: None, }) .collect()), diff --git a/datafusion/sql/src/statement.rs b/datafusion/sql/src/statement.rs index c61f09f6f5cf5..90c620c27d46f 100644 --- a/datafusion/sql/src/statement.rs +++ b/datafusion/sql/src/statement.rs @@ -118,6 +118,7 @@ fn calc_inline_constraints_from_columns(columns: &[ColumnDef]) -> Vec constraints.push(TableConstraint::Unique(UniqueConstraint { @@ -129,13 +130,14 @@ fn calc_inline_constraints_from_columns(columns: &[ColumnDef]) -> Vec Vec { constraints.push(TableConstraint::PrimaryKey(PrimaryKeyConstraint { @@ -156,13 +159,14 @@ fn calc_inline_constraints_from_columns(columns: &[ColumnDef]) -> Vec Vec constraints.push(TableConstraint::Check(CheckConstraint { name: name.clone(), expr: expr.clone(), + no_inherit: false, enforced: None, })), ast::ColumnOption::Default(_) @@ -362,6 +368,11 @@ impl SqlToRel<'_, S> { distkey, sortkey, backup, + unlogged, + with_connection, + multiset, + fallback, + with_data, }) => { if temporary { return not_impl_err!("Temporary tables not supported"); @@ -533,6 +544,21 @@ impl SqlToRel<'_, S> { if backup.is_some() { return not_impl_err!("BACKUP not supported"); } + if unlogged { + return not_impl_err!("UNLOGGED tables not supported"); + } + if with_connection.is_some() { + return not_impl_err!("WITH CONNECTION not supported"); + } + if multiset.is_some() { + return not_impl_err!("MULTISET tables not supported"); + } + if fallback.is_some() { + return not_impl_err!("FALLBACK not supported"); + } + if with_data.is_some() { + return not_impl_err!("WITH [NO] DATA not supported"); + } // Merge inline constraints and existing constraints let mut all_constraints = constraints; let inline_constraints = calc_inline_constraints_from_columns(&columns); @@ -1765,7 +1791,15 @@ impl SqlToRel<'_, S> { schema, planner_context, )?; - let asc = order_by_expr.options.asc.unwrap_or(true); + let asc = match &order_by_expr.options.sort { + Some(ast::OrderBySort::Asc) | None => true, + Some(ast::OrderBySort::Desc) => false, + Some(ast::OrderBySort::Using(op)) => { + return not_impl_err!( + "ORDER BY USING is not supported: {op}" + ); + } + }; let nulls_first = order_by_expr.options.nulls_first.unwrap_or_else(|| { self.options.default_null_ordering.nulls_first(asc) @@ -1932,6 +1966,7 @@ impl SqlToRel<'_, S> { index_type_display: _, index_type: _, columns, + include: _, index_options: _, characteristics: _, nulls_distinct: _, @@ -1953,6 +1988,7 @@ impl SqlToRel<'_, S> { index_name: _, index_type: _, columns, + include: _, index_options: _, characteristics: _, }) => { @@ -1967,6 +2003,9 @@ impl SqlToRel<'_, S> { TableConstraint::ForeignKey { .. } => { _plan_err!("Foreign key constraints are not currently supported") } + TableConstraint::Exclude(_) => { + _plan_err!("Exclude constraints are not currently supported") + } TableConstraint::Check { .. } => { _plan_err!("Check constraints are not currently supported") } @@ -2723,8 +2762,13 @@ impl SqlToRel<'_, S> { "MERGE UPDATE DELETE WHERE predicates are not supported" ); } - let assignments = update_expr - .assignments + let sql_assignments = match update_expr.kind { + ast::MergeUpdateKind::Set(assignments) => assignments, + ast::MergeUpdateKind::Wildcard => { + return not_impl_err!("MERGE UPDATE SET * is not supported"); + } + }; + let assignments = sql_assignments .into_iter() .map(|assign| { let col_name = match &assign.target { @@ -2802,11 +2846,17 @@ impl SqlToRel<'_, S> { ast::MergeInsertKind::Row => { return not_impl_err!("MERGE INSERT ROW is not supported"); } + ast::MergeInsertKind::Wildcard => { + return not_impl_err!("MERGE INSERT * is not supported"); + } }; MergeIntoAction::Insert { columns, values } } ast::MergeAction::Delete { .. } => MergeIntoAction::Delete, + ast::MergeAction::DoNothing { .. } => { + return not_impl_err!("MERGE DO NOTHING is not supported"); + } }; Ok(MergeIntoClause { diff --git a/datafusion/sql/src/unparser/dialect.rs b/datafusion/sql/src/unparser/dialect.rs index 545da7a95c2d8..bea4e353001cd 100644 --- a/datafusion/sql/src/unparser/dialect.rs +++ b/datafusion/sql/src/unparser/dialect.rs @@ -465,7 +465,6 @@ impl PostgreSqlDialect { kind: ast::CastKind::Cast, expr: Box::new(expr.clone()), data_type: ast::DataType::Numeric(ast::ExactNumberInfo::None), - array: false, format: None, }; } diff --git a/datafusion/sql/src/unparser/expr.rs b/datafusion/sql/src/unparser/expr.rs index d5cbe64cae486..0f2cef167cc9d 100644 --- a/datafusion/sql/src/unparser/expr.rs +++ b/datafusion/sql/src/unparser/expr.rs @@ -360,8 +360,9 @@ impl Unparser<'_> { negated: *negated, expr: Box::new(self.expr_to_sql_inner(expr)?), pattern: Box::new(self.expr_to_sql_inner(pattern)?), - escape_char: escape_char - .map(|c| SingleQuotedString(c.to_string()).into()), + escape_char: escape_char.map(|c| { + Box::new(ast::Expr::Value(SingleQuotedString(c.to_string()).into())) + }), any: false, }), Expr::Like(Like { @@ -374,8 +375,9 @@ impl Unparser<'_> { let negated = *negated; let expr = Box::new(self.expr_to_sql_inner(expr)?); let pattern = Box::new(self.expr_to_sql_inner(pattern)?); - let escape_char = - escape_char.map(|c| SingleQuotedString(c.to_string()).into()); + let escape_char = escape_char.map(|c| { + Box::new(ast::Expr::Value(SingleQuotedString(c.to_string()).into())) + }); if *case_insensitive { Ok(ast::Expr::ILike { @@ -562,7 +564,6 @@ impl Unparser<'_> { kind: ast::CastKind::TryCast, expr: Box::new(inner_expr), data_type: self.arrow_dtype_to_ast_dtype(field)?, - array: false, format: None, }) } @@ -868,7 +869,11 @@ impl Unparser<'_> { Ok(ast::OrderByExpr { expr: sql_parser_expr, options: OrderByOptions { - asc: Some(*asc), + sort: Some(if *asc { + ast::OrderBySort::Asc + } else { + ast::OrderBySort::Desc + }), nulls_first, }, with_fill: None, @@ -1249,7 +1254,6 @@ impl Unparser<'_> { kind: ast::CastKind::Cast, expr: Box::new(ast::Expr::value(SingleQuotedString(ts))), data_type: self.dialect.timestamp_cast_dtype(&time_unit, &None), - array: false, format: None, }) } @@ -1272,7 +1276,6 @@ impl Unparser<'_> { kind: ast::CastKind::Cast, expr: Box::new(ast::Expr::value(SingleQuotedString(time))), data_type: ast::DataType::Time(None, TimezoneInfo::None), - array: false, format: None, }) } @@ -1293,7 +1296,6 @@ impl Unparser<'_> { kind: ast::CastKind::Cast, expr: Box::new(inner_expr), data_type: self.arrow_dtype_to_ast_dtype(field)?, - array: false, format: None, }), }, @@ -1301,7 +1303,6 @@ impl Unparser<'_> { kind: ast::CastKind::Cast, expr: Box::new(inner_expr), data_type: self.arrow_dtype_to_ast_dtype(field)?, - array: false, format: None, }), } @@ -1452,7 +1453,6 @@ impl Unparser<'_> { date.to_string(), ))), data_type: ast::DataType::Date, - array: false, format: None, }) } @@ -1476,7 +1476,6 @@ impl Unparser<'_> { datetime.to_string(), ))), data_type: self.ast_type_for_date64_in_cast(), - array: false, format: None, }) } diff --git a/datafusion/sql/tests/cases/params.rs b/datafusion/sql/tests/cases/params.rs index 8b025d3945db1..d7ad61b2bceaf 100644 --- a/datafusion/sql/tests/cases/params.rs +++ b/datafusion/sql/tests/cases/params.rs @@ -171,7 +171,7 @@ fn test_non_prepare_statement_should_infer_types() { #[test] #[should_panic( - expected = "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [form] NORMALIZED FROM after IS, found: $1" + expected = "Expected: [NOT] NULL | TRUE | FALSE | DISTINCT | [NOT] JSON [VALUE | SCALAR | ARRAY | OBJECT] [WITH | WITHOUT UNIQUE [KEYS]] | [form] NORMALIZED FROM after IS, found: $1" )] fn test_prepare_statement_to_plan_panic_is_param() { let sql = "PREPARE my_plan(INT) AS SELECT id, age FROM person WHERE age is $1"; diff --git a/datafusion/sqllogictest/test_files/array_agg.slt b/datafusion/sqllogictest/test_files/array_agg.slt index b3cd60b9fed8c..cd9e3d9172275 100644 --- a/datafusion/sqllogictest/test_files/array_agg.slt +++ b/datafusion/sqllogictest/test_files/array_agg.slt @@ -596,6 +596,9 @@ physical_plan statement error This feature is not implemented: Calling array_agg: LIMIT not supported in function arguments: 1 SELECT array_agg(c13 LIMIT 1) FROM aggregate_test_100 +statement error This feature is not implemented: Calling array_agg: WHERE not supported in function arguments: c2 > 1 +SELECT array_agg(c13 WHERE c2 > 1) FROM aggregate_test_100 + query error Error during planning: WITHIN GROUP is only supported for ordered-set aggregate functions SELECT array_agg(a_varchar) WITHIN GROUP (ORDER BY a_varchar) FROM (VALUES ('a'), ('d'), ('c'), ('a')) t(a_varchar); diff --git a/datafusion/sqllogictest/test_files/ddl.slt b/datafusion/sqllogictest/test_files/ddl.slt index d47aad0b19c84..21c195c3d2d80 100644 --- a/datafusion/sqllogictest/test_files/ddl.slt +++ b/datafusion/sqllogictest/test_files/ddl.slt @@ -377,6 +377,10 @@ SELECT * FROM new_table statement ok DROP TABLE new_table; +# Select into only supports a single table name target +statement error DataFusion error: This feature is not implemented: SELECT INTO only supports a single table name target +SELECT * INTO new_table, other_table FROM test_table + # Create table as without alias names of window aggregates statement ok CREATE TABLE new_table AS SELECT SUM(c1) OVER(ORDER BY c2), c2, c3 FROM test_table @@ -846,6 +850,18 @@ CREATE EXTERNAL TEMPORARY TABLE tty STORED as ARROW LOCATION '../datasource-arro statement error DataFusion error: This feature is not implemented: Temporary views not supported CREATE TEMPORARY VIEW y AS VALUES (1,2,3); +statement error DataFusion error: This feature is not implemented: UNLOGGED tables not supported +CREATE UNLOGGED TABLE foo (x int); + +statement error DataFusion error: This feature is not implemented: MULTISET tables not supported +CREATE MULTISET TABLE foo (x int); + +statement error DataFusion error: This feature is not implemented: WITH \[NO\] DATA not supported +CREATE TABLE foo AS SELECT 1 WITH NO DATA; + +statement error DataFusion error: Error during planning: Exclude constraints are not currently supported +CREATE TABLE foo (x int, EXCLUDE USING gist (x WITH =)); + query error DataFusion error: Schema error: No field named a\. EXPLAIN CREATE TABLE t(a int) AS VALUES (a + a); diff --git a/datafusion/sqllogictest/test_files/merge_into.slt b/datafusion/sqllogictest/test_files/merge_into.slt index 5049bf8825d07..ad358c2379f91 100644 --- a/datafusion/sqllogictest/test_files/merge_into.slt +++ b/datafusion/sqllogictest/test_files/merge_into.slt @@ -241,6 +241,18 @@ statement error DataFusion error: This feature is not implemented: MERGE INSERT merge into target using source on target.id = source.id when not matched then insert row; +statement error DataFusion error: This feature is not implemented: MERGE UPDATE SET \* is not supported +merge into target using source on target.id = source.id +when matched then update set *; + +statement error DataFusion error: This feature is not implemented: MERGE INSERT \* is not supported +merge into target using source on target.id = source.id +when not matched then insert *; + +statement error DataFusion error: This feature is not implemented: MERGE DO NOTHING is not supported +merge into target using source on target.id = source.id +when matched then do nothing; + statement ok drop table target; diff --git a/datafusion/sqllogictest/test_files/order.slt b/datafusion/sqllogictest/test_files/order.slt index d080139bc709c..d974eb9dd06fc 100644 --- a/datafusion/sqllogictest/test_files/order.slt +++ b/datafusion/sqllogictest/test_files/order.slt @@ -634,6 +634,16 @@ ORDER BY sum(value) + sum(value); statement error DataFusion error: This feature is not implemented: SORT BY select * from t SORT BY time; +## ORDER BY USING (PostgreSQL) is not supported +statement ok +set datafusion.sql_parser.dialect = 'PostgreSQL'; + +statement error DataFusion error: This feature is not implemented: ORDER BY USING is not supported: < +select * from t ORDER BY time USING <; + +statement ok +reset datafusion.sql_parser.dialect; + # distinct on a column not in the select list should not work statement error DataFusion error: Error during planning: For SELECT DISTINCT, ORDER BY expressions t\.time must appear in select list