diff --git a/datafusion/core/src/datasource/listing_table_factory.rs b/datafusion/core/src/datasource/listing_table_factory.rs index fed63ec12b496..701a13477b5bb 100644 --- a/datafusion/core/src/datasource/listing_table_factory.rs +++ b/datafusion/core/src/datasource/listing_table_factory.rs @@ -197,6 +197,7 @@ mod tests { schema: Arc::new(DFSchema::empty()), table_partition_cols: vec![], if_not_exists: false, + temporary: false, definition: None, order_exprs: vec![], unbounded: false, @@ -236,6 +237,7 @@ mod tests { schema: Arc::new(DFSchema::empty()), table_partition_cols: vec![], if_not_exists: false, + temporary: false, definition: None, order_exprs: vec![], unbounded: false, diff --git a/datafusion/core/src/execution/context/mod.rs b/datafusion/core/src/execution/context/mod.rs index b0951d9ec44cd..91a95a08d51d7 100644 --- a/datafusion/core/src/execution/context/mod.rs +++ b/datafusion/core/src/execution/context/mod.rs @@ -761,10 +761,16 @@ impl SessionContext { or_replace, constraints, column_defaults, + temporary, } = cmd; let input = Arc::unwrap_or_clone(input); let input = self.state().optimize(&input)?; + + if temporary { + return not_impl_err!("CREATE TEMPORARY table"); + } + let table = self.table(name.clone()).await; match (if_not_exists, or_replace, table) { (true, false, Ok(_)) => self.return_empty_dataframe(), @@ -813,10 +819,15 @@ impl SessionContext { input, or_replace, definition, + temporary, } = cmd; let view = self.table(name.clone()).await; + if temporary { + return not_impl_err!("CREATE TEMPORARY view"); + } + match (or_replace, view) { (true, Ok(_)) => { self.deregister_table(name.clone())?; diff --git a/datafusion/expr/src/logical_plan/ddl.rs b/datafusion/expr/src/logical_plan/ddl.rs index 9aaa5c98037ac..025636db3d1a2 100644 --- a/datafusion/expr/src/logical_plan/ddl.rs +++ b/datafusion/expr/src/logical_plan/ddl.rs @@ -298,6 +298,8 @@ pub struct CreateMemoryTable { pub or_replace: bool, /// Default values for columns pub column_defaults: Vec<(String, Expr)>, + /// Wheter the table is `TableType::Temporary` + pub temporary: bool, } /// Creates a view. @@ -311,6 +313,8 @@ pub struct CreateView { pub or_replace: bool, /// SQL used to create the view, if available pub definition: Option, + /// Wheter the view is ephemeral + pub temporary: bool, } /// Creates a catalog (aka "Database"). diff --git a/datafusion/expr/src/logical_plan/plan.rs b/datafusion/expr/src/logical_plan/plan.rs index 443d23804adb2..7c728af531b4c 100644 --- a/datafusion/expr/src/logical_plan/plan.rs +++ b/datafusion/expr/src/logical_plan/plan.rs @@ -992,6 +992,7 @@ impl LogicalPlan { if_not_exists, or_replace, column_defaults, + temporary, .. })) => { self.assert_no_expressions(expr)?; @@ -1004,6 +1005,7 @@ impl LogicalPlan { if_not_exists: *if_not_exists, or_replace: *or_replace, column_defaults: column_defaults.clone(), + temporary: *temporary, }, ))) } @@ -1011,6 +1013,7 @@ impl LogicalPlan { name, or_replace, definition, + temporary, .. })) => { self.assert_no_expressions(expr)?; @@ -1019,6 +1022,7 @@ impl LogicalPlan { input: Arc::new(input), name: name.clone(), or_replace: *or_replace, + temporary: *temporary, definition: definition.clone(), }))) } diff --git a/datafusion/expr/src/logical_plan/tree_node.rs b/datafusion/expr/src/logical_plan/tree_node.rs index 8ba68697bd4d7..83206a2b2af5b 100644 --- a/datafusion/expr/src/logical_plan/tree_node.rs +++ b/datafusion/expr/src/logical_plan/tree_node.rs @@ -285,6 +285,7 @@ impl TreeNode for LogicalPlan { if_not_exists, or_replace, column_defaults, + temporary, }) => rewrite_arc(input, f)?.update_data(|input| { DdlStatement::CreateMemoryTable(CreateMemoryTable { name, @@ -293,6 +294,7 @@ impl TreeNode for LogicalPlan { if_not_exists, or_replace, column_defaults, + temporary, }) }), DdlStatement::CreateView(CreateView { @@ -300,12 +302,14 @@ impl TreeNode for LogicalPlan { input, or_replace, definition, + temporary, }) => rewrite_arc(input, f)?.update_data(|input| { DdlStatement::CreateView(CreateView { name, input, or_replace, definition, + temporary, }) }), // no inputs in these statements diff --git a/datafusion/proto/src/generated/prost.rs b/datafusion/proto/src/generated/prost.rs index 436347330d929..04b783f403473 100644 --- a/datafusion/proto/src/generated/prost.rs +++ b/datafusion/proto/src/generated/prost.rs @@ -240,6 +240,8 @@ pub struct CreateExternalTableNode { pub table_partition_cols: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, #[prost(bool, tag = "6")] pub if_not_exists: bool, + #[prost(bool, optional, tag = "14")] + pub temporary: Option, #[prost(string, tag = "7")] pub definition: ::prost::alloc::string::String, #[prost(message, repeated, tag = "10")] @@ -305,6 +307,8 @@ pub struct CreateViewNode { pub or_replace: bool, #[prost(string, tag = "4")] pub definition: ::prost::alloc::string::String, + #[prost(bool, optional, tag = "6")] + pub temporary: Option, } /// a node containing data for defining values list. unlike in SQL where it's two dimensional, here /// the list is flattened, and with the field n_cols it can be parsed and partitioned into rows diff --git a/datafusion/proto/src/logical_plan/mod.rs b/datafusion/proto/src/logical_plan/mod.rs index 7156cee66affa..2088f18e680d9 100644 --- a/datafusion/proto/src/logical_plan/mod.rs +++ b/datafusion/proto/src/logical_plan/mod.rs @@ -601,6 +601,7 @@ impl AsLogicalPlan for LogicalPlanNode { Ok(LogicalPlan::Ddl(DdlStatement::CreateView(CreateView { name: from_table_reference(create_view.name.as_ref(), "CreateView")?, + temporary: false, input: Arc::new(plan), or_replace: create_view.or_replace, definition, @@ -1386,6 +1387,7 @@ impl AsLogicalPlan for LogicalPlanNode { options, constraints, column_defaults, + temporary, }, )) => { let mut converted_order_exprs: Vec = vec![]; @@ -1412,6 +1414,7 @@ impl AsLogicalPlan for LogicalPlanNode { schema: Some(df_schema.try_into()?), table_partition_cols: table_partition_cols.clone(), if_not_exists: *if_not_exists, + temporary: Some(*temporary), order_exprs: converted_order_exprs, definition: definition.clone().unwrap_or_default(), unbounded: *unbounded, @@ -1427,6 +1430,7 @@ impl AsLogicalPlan for LogicalPlanNode { input, or_replace, definition, + temporary, })) => Ok(protobuf::LogicalPlanNode { logical_plan_type: Some(LogicalPlanType::CreateView(Box::new( protobuf::CreateViewNode { @@ -1436,6 +1440,7 @@ impl AsLogicalPlan for LogicalPlanNode { extension_codec, )?)), or_replace: *or_replace, + temporary: Some(*temporary), definition: definition.clone().unwrap_or_default(), }, ))), diff --git a/datafusion/sql/src/parser.rs b/datafusion/sql/src/parser.rs index 2df8d89c59bc8..02c71f1ea8bc4 100644 --- a/datafusion/sql/src/parser.rs +++ b/datafusion/sql/src/parser.rs @@ -923,6 +923,7 @@ mod tests { table_partition_cols: vec![], order_exprs: vec![], if_not_exists: false, + temporary: false, unbounded: false, options: vec![], constraints: vec![], @@ -939,6 +940,7 @@ mod tests { table_partition_cols: vec![], order_exprs: vec![], if_not_exists: false, + temporary: false, unbounded: false, options: vec![], constraints: vec![], @@ -956,6 +958,7 @@ mod tests { table_partition_cols: vec![], order_exprs: vec![], if_not_exists: false, + temporary: false, unbounded: false, options: vec![], constraints: vec![], @@ -973,6 +976,7 @@ mod tests { table_partition_cols: vec![], order_exprs: vec![], if_not_exists: false, + temporary: false, unbounded: false, options: vec![( "format.delimiter".into(), @@ -993,6 +997,7 @@ mod tests { table_partition_cols: vec!["p1".to_string(), "p2".to_string()], order_exprs: vec![], if_not_exists: false, + temporary: false, unbounded: false, options: vec![], constraints: vec![], @@ -1020,6 +1025,7 @@ mod tests { table_partition_cols: vec![], order_exprs: vec![], if_not_exists: false, + temporary: false, unbounded: false, options: vec![( "format.compression".into(), @@ -1040,6 +1046,7 @@ mod tests { table_partition_cols: vec![], order_exprs: vec![], if_not_exists: false, + temporary: false, unbounded: false, options: vec![], constraints: vec![], @@ -1056,6 +1063,7 @@ mod tests { table_partition_cols: vec![], order_exprs: vec![], if_not_exists: false, + temporary: false, unbounded: false, options: vec![], constraints: vec![], @@ -1072,6 +1080,7 @@ mod tests { table_partition_cols: vec![], order_exprs: vec![], if_not_exists: false, + temporary: false, unbounded: false, options: vec![], constraints: vec![], @@ -1089,6 +1098,7 @@ mod tests { table_partition_cols: vec![], order_exprs: vec![], if_not_exists: true, + temporary: false, unbounded: false, options: vec![], constraints: vec![], @@ -1109,6 +1119,7 @@ mod tests { table_partition_cols: vec!["p1".to_string()], order_exprs: vec![], if_not_exists: false, + temporary: false, unbounded: false, options: vec![], constraints: vec![], @@ -1139,6 +1150,7 @@ mod tests { table_partition_cols: vec![], order_exprs: vec![], if_not_exists: false, + temporary: false, unbounded: false, options: vec![("k1".into(), Value::SingleQuotedString("v1".into()))], constraints: vec![], @@ -1156,6 +1168,7 @@ mod tests { table_partition_cols: vec![], order_exprs: vec![], if_not_exists: false, + temporary: false, unbounded: false, options: vec![ ("k1".into(), Value::SingleQuotedString("v1".into())), @@ -1203,6 +1216,7 @@ mod tests { with_fill: None, }]], if_not_exists: false, + temporary: false, unbounded: false, options: vec![], constraints: vec![], @@ -1243,6 +1257,7 @@ mod tests { }, ]], if_not_exists: false, + temporary: false, unbounded: false, options: vec![], constraints: vec![], @@ -1278,6 +1293,7 @@ mod tests { with_fill: None, }]], if_not_exists: false, + temporary: false, unbounded: false, options: vec![], constraints: vec![], @@ -1322,6 +1338,7 @@ mod tests { with_fill: None, }]], if_not_exists: true, + temporary: false, unbounded: true, options: vec![ ( diff --git a/datafusion/sql/src/query.rs b/datafusion/sql/src/query.rs index 71328cfd018c3..6134edc3eea6a 100644 --- a/datafusion/sql/src/query.rs +++ b/datafusion/sql/src/query.rs @@ -150,6 +150,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> { input: Arc::new(plan), if_not_exists: false, or_replace: false, + temporary: false, column_defaults: vec![], }, ))), diff --git a/datafusion/sql/src/statement.rs b/datafusion/sql/src/statement.rs index 895285c59737e..fbbeab219ad12 100644 --- a/datafusion/sql/src/statement.rs +++ b/datafusion/sql/src/statement.rs @@ -440,6 +440,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> { if_not_exists, or_replace, column_defaults, + temporary, }, ))) } @@ -463,6 +464,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> { if_not_exists, or_replace, column_defaults, + temporary, }, ))) } @@ -526,6 +528,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> { input: Arc::new(plan), or_replace, definition: sql, + temporary, }))) } Statement::ShowCreate { obj_type, obj_name } => match obj_type { @@ -1256,7 +1259,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> { unbounded, options: options_map, constraints, - column_defaults, + column_defaults }, ))) } diff --git a/datafusion/sqllogictest/test_files/ddl.slt b/datafusion/sqllogictest/test_files/ddl.slt index 21edb458fe567..d3a38a5c38c06 100644 --- a/datafusion/sqllogictest/test_files/ddl.slt +++ b/datafusion/sqllogictest/test_files/ddl.slt @@ -775,3 +775,9 @@ physical_plan CsvExec: file_groups={1 group: [[WORKSPACE_ROOT/datafusion/core/te statement ok drop table t; + +statement ok +set datafusion.explain.logical_plan_only=true; + +statement error DataFusion error: This feature is not implemented: Temporary views not supported +explain CREATE TEMPORARY VIEW y AS VALUES (1,2,3);