This is an automated email from the ASF dual-hosted git repository.

jonah pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git


The following commit(s) were added to refs/heads/main by this push:
     new a20b3183b3 feat: support `DEALLOCATE` to remove prepared statements 
(#13327)
a20b3183b3 is described below

commit a20b3183b33337a4dc0539393b4630dd32b76232
Author: Jonah Gao <[email protected]>
AuthorDate: Sun Nov 10 22:04:27 2024 +0800

    feat: support `DEALLOCATE` to remove prepared statements (#13327)
---
 datafusion/core/src/execution/context/mod.rs   |  6 +++
 datafusion/core/src/execution/session_state.rs | 11 ++++++
 datafusion/expr/src/logical_plan/mod.rs        |  2 +-
 datafusion/expr/src/logical_plan/statement.rs  | 14 +++++++
 datafusion/sql/src/statement.rs                | 17 +++++++--
 datafusion/sqllogictest/test_files/prepare.slt | 52 ++++++++++++++++++++++++++
 6 files changed, 97 insertions(+), 5 deletions(-)

diff --git a/datafusion/core/src/execution/context/mod.rs 
b/datafusion/core/src/execution/context/mod.rs
index ff009a0164..e04fe6bdde 100644
--- a/datafusion/core/src/execution/context/mod.rs
+++ b/datafusion/core/src/execution/context/mod.rs
@@ -715,6 +715,12 @@ impl SessionContext {
             LogicalPlan::Statement(Statement::Execute(execute)) => {
                 self.execute_prepared(execute)
             }
+            LogicalPlan::Statement(Statement::Deallocate(deallocate)) => {
+                self.state
+                    .write()
+                    .remove_prepared(deallocate.name.as_str())?;
+                self.return_empty_dataframe()
+            }
             plan => Ok(DataFrame::new(self.state(), plan)),
         }
     }
diff --git a/datafusion/core/src/execution/session_state.rs 
b/datafusion/core/src/execution/session_state.rs
index f65bd2a597..d0bbc95a1b 100644
--- a/datafusion/core/src/execution/session_state.rs
+++ b/datafusion/core/src/execution/session_state.rs
@@ -934,6 +934,17 @@ impl SessionState {
     pub(crate) fn get_prepared(&self, name: &str) -> Option<Arc<PreparedPlan>> 
{
         self.prepared_plans.get(name).map(Arc::clone)
     }
+
+    /// Remove the prepared plan with the given name.
+    pub(crate) fn remove_prepared(
+        &mut self,
+        name: &str,
+    ) -> datafusion_common::Result<()> {
+        match self.prepared_plans.remove(name) {
+            Some(_) => Ok(()),
+            None => exec_err!("Prepared statement '{}' does not exist", name),
+        }
+    }
 }
 
 /// A builder to be used for building [`SessionState`]'s. Defaults will
diff --git a/datafusion/expr/src/logical_plan/mod.rs 
b/datafusion/expr/src/logical_plan/mod.rs
index b5bd2e0128..5d613d4e80 100644
--- a/datafusion/expr/src/logical_plan/mod.rs
+++ b/datafusion/expr/src/logical_plan/mod.rs
@@ -42,7 +42,7 @@ pub use plan::{
     SubqueryAlias, TableScan, ToStringifiedPlan, Union, Unnest, Values, Window,
 };
 pub use statement::{
-    Execute, Prepare, SetVariable, Statement, TransactionAccessMode,
+    Deallocate, Execute, Prepare, SetVariable, Statement, 
TransactionAccessMode,
     TransactionConclusion, TransactionEnd, TransactionIsolationLevel, 
TransactionStart,
 };
 
diff --git a/datafusion/expr/src/logical_plan/statement.rs 
b/datafusion/expr/src/logical_plan/statement.rs
index 9ba8170f8e..05e2b1af14 100644
--- a/datafusion/expr/src/logical_plan/statement.rs
+++ b/datafusion/expr/src/logical_plan/statement.rs
@@ -48,6 +48,9 @@ pub enum Statement {
     Prepare(Prepare),
     /// Execute a prepared statement. This is used to implement SQL 'EXECUTE'.
     Execute(Execute),
+    /// Deallocate a prepared statement.
+    /// This is used to implement SQL 'DEALLOCATE'.
+    Deallocate(Deallocate),
 }
 
 impl Statement {
@@ -65,6 +68,7 @@ impl Statement {
             Statement::SetVariable(_) => "SetVariable",
             Statement::Prepare(_) => "Prepare",
             Statement::Execute(_) => "Execute",
+            Statement::Deallocate(_) => "Deallocate",
         }
     }
 
@@ -167,6 +171,9 @@ impl Statement {
                             expr_vec_fmt!(parameters)
                         )
                     }
+                    Statement::Deallocate(Deallocate { name }) => {
+                        write!(f, "Deallocate: {}", name)
+                    }
                 }
             }
         }
@@ -245,3 +252,10 @@ pub struct Execute {
     /// The execute parameters
     pub parameters: Vec<Expr>,
 }
+
+/// Deallocate a prepared statement.
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Hash)]
+pub struct Deallocate {
+    /// The name of the prepared statement to deallocate
+    pub name: String,
+}
diff --git a/datafusion/sql/src/statement.rs b/datafusion/sql/src/statement.rs
index 3b32a43757..0ac804b706 100644
--- a/datafusion/sql/src/statement.rs
+++ b/datafusion/sql/src/statement.rs
@@ -46,10 +46,10 @@ use datafusion_expr::utils::expr_to_columns;
 use datafusion_expr::{
     cast, col, Analyze, CreateCatalog, CreateCatalogSchema,
     CreateExternalTable as PlanCreateExternalTable, CreateFunction, 
CreateFunctionBody,
-    CreateIndex as PlanCreateIndex, CreateMemoryTable, CreateView, 
DescribeTable,
-    DmlStatement, DropCatalogSchema, DropFunction, DropTable, DropView, 
EmptyRelation,
-    Execute, Explain, Expr, ExprSchemable, Filter, LogicalPlan, 
LogicalPlanBuilder,
-    OperateFunctionArg, PlanType, Prepare, SetVariable, SortExpr,
+    CreateIndex as PlanCreateIndex, CreateMemoryTable, CreateView, Deallocate,
+    DescribeTable, DmlStatement, DropCatalogSchema, DropFunction, DropTable, 
DropView,
+    EmptyRelation, Execute, Explain, Expr, ExprSchemable, Filter, LogicalPlan,
+    LogicalPlanBuilder, OperateFunctionArg, PlanType, Prepare, SetVariable, 
SortExpr,
     Statement as PlanStatement, ToStringifiedPlan, TransactionAccessMode,
     TransactionConclusion, TransactionEnd, TransactionIsolationLevel, 
TransactionStart,
     Volatility, WriteOp,
@@ -665,6 +665,15 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
                     parameters,
                 })))
             }
+            Statement::Deallocate {
+                name,
+                // Similar to PostgreSQL, the PREPARE keyword is ignored
+                prepare: _,
+            } => Ok(LogicalPlan::Statement(PlanStatement::Deallocate(
+                Deallocate {
+                    name: ident_to_string(&name),
+                },
+            ))),
 
             Statement::ShowTables {
                 extended,
diff --git a/datafusion/sqllogictest/test_files/prepare.slt 
b/datafusion/sqllogictest/test_files/prepare.slt
index f149cec96f..c3bd15c086 100644
--- a/datafusion/sqllogictest/test_files/prepare.slt
+++ b/datafusion/sqllogictest/test_files/prepare.slt
@@ -64,6 +64,10 @@ PREPARE my_plan AS SELECT $1;
 statement error Prepared statement \'my_plan\' does not exist
 EXECUTE my_plan('Foo', 'Bar');
 
+# deallocate a non-existing plan
+statement error Prepared statement \'my_plan\' does not exist
+DEALLOCATE my_plan;
+
 statement ok
 PREPARE my_plan(STRING, STRING) AS SELECT * FROM (VALUES(1, $1), (2, $2)) AS t 
(num, letter);
 
@@ -77,6 +81,28 @@ EXECUTE my_plan('Foo', 'Bar');
 statement error Prepared statement \'my_plan\' already exists
 PREPARE my_plan(STRING, STRING) AS SELECT * FROM (VALUES(1, $1), (2, $2)) AS t 
(num, letter);
 
+# deallocate a plan
+statement ok
+DEALLOCATE my_plan;
+
+# can't EXECUTE a deallocated plan
+statement error Prepared statement \'my_plan\' does not exist
+EXECUTE my_plan('Foo', 'Bar');
+
+# re-prepare a deallocated plan
+statement ok
+PREPARE my_plan(STRING, STRING) AS SELECT * FROM (VALUES(1, $1), (2, $2)) AS t 
(num, letter);
+
+query IT
+EXECUTE my_plan('Foo', 'Bar');
+----
+1 Foo
+2 Bar
+
+# deallocate with the PREPARE keyword
+statement ok
+DEALLOCATE PREPARE my_plan;
+
 statement error Prepare specifies 1 data types but query has 0 parameters
 PREPARE my_plan(INT) AS SELECT id, age  FROM person WHERE age = 10;
 
@@ -89,6 +115,9 @@ EXECUTE my_plan2;
 ----
 1 20
 
+statement ok
+DEALLOCATE my_plan2;
+
 statement ok
 PREPARE my_plan3(INT) AS SELECT $1;
 
@@ -97,6 +126,9 @@ EXECUTE my_plan3(10);
 ----
 10
 
+statement ok
+DEALLOCATE my_plan3;
+
 statement ok
 PREPARE my_plan4(INT) AS SELECT 1 + $1;
 
@@ -105,6 +137,9 @@ EXECUTE my_plan4(10);
 ----
 11
 
+statement ok
+DEALLOCATE my_plan4;
+
 statement ok
 PREPARE my_plan5(INT, DOUBLE) AS SELECT 1 + $1 + $2;
 
@@ -113,6 +148,9 @@ EXECUTE my_plan5(10, 20.5);
 ----
 31.5
 
+statement ok
+DEALLOCATE my_plan5;
+
 statement ok
 PREPARE my_plan6(INT) AS SELECT id, age FROM person WHERE age = $1;
 
@@ -140,6 +178,9 @@ EXECUTE my_plan6('foo');
 statement error Unsupported parameter type
 EXECUTE my_plan6(10 + 20);
 
+statement ok
+DEALLOCATE my_plan6;
+
 statement ok
 PREPARE my_plan7(INT, STRING, DOUBLE, INT, DOUBLE, STRING)
     AS
@@ -150,6 +191,9 @@ EXECUTE my_plan7(10, 'jane', 99999.45, 20, 200000.45, 
'foo');
 ----
 1 20 foo
 
+statement ok
+DEALLOCATE my_plan7;
+
 statement ok
 PREPARE my_plan8(INT, DOUBLE, DOUBLE, DOUBLE)
     AS
@@ -161,6 +205,9 @@ EXECUTE my_plan8(100000, 99999.45, 100000.45, 200000.45);
 ----
 1 20
 
+statement ok
+DEALLOCATE my_plan8;
+
 statement ok
 PREPARE my_plan9(STRING, STRING) AS SELECT * FROM (VALUES(1, $1), (2, $2)) AS 
t (num, letter);
 
@@ -170,6 +217,8 @@ EXECUTE my_plan9('Foo', 'Bar');
 1 Foo
 2 Bar
 
+statement ok
+DEALLOCATE my_plan9;
 
 # Test issue: https://github.com/apache/datafusion/issues/12294
 # prepare argument is in the LIMIT clause
@@ -196,6 +245,9 @@ EXECUTE get_N_rand_ints_from_last_run(2);
 1
 1
 
+statement ok
+DEALLOCATE get_N_rand_ints_from_last_run;
+
 statement ok
 DROP TABLE test;
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to