Skip to content

Commit 8821e01

Browse files
authored
Merge pull request #19 from kryvashek/sakhart/feat/adding-delete-limit-support
adding delete limit support
2 parents 3da0c0d + 36d83e3 commit 8821e01

File tree

4 files changed

+49
-24
lines changed

4 files changed

+49
-24
lines changed

datafusion-cli/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ rust-version = "1.82.0"
2929
readme = "README.md"
3030

3131
[dependencies]
32-
arrow = { version = "54.0.0" }
32+
arrow = { workspace = true }
3333
async-trait = "0.1.73"
3434
aws-config = "1.5.5"
3535
# begin pin aws-sdk crates otherwise CI MSRV check fails
@@ -57,7 +57,7 @@ futures = "0.3"
5757
mimalloc = { version = "0.1", default-features = false }
5858
object_store = { version = "0.11.0", features = ["aws", "gcp", "http"] }
5959
parking_lot = { version = "0.12" }
60-
parquet = { version = "54.0.0", default-features = false }
60+
parquet = { workspace = true, default-features = false }
6161
regex = "1.8"
6262
rustyline = "14.0"
6363
tokio = { version = "1.24", features = ["macros", "rt", "rt-multi-thread", "sync", "parking_lot", "signal"] }

datafusion/sql/src/query.rs

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -86,29 +86,15 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
8686
}
8787

8888
let skip = match skip {
89-
Some(skip_expr) => {
90-
let expr = self.sql_to_expr(
91-
skip_expr.value,
92-
input.schema(),
93-
&mut PlannerContext::new(),
94-
)?;
95-
let n = get_constant_result(&expr, "OFFSET")?;
96-
convert_usize_with_check(n, "OFFSET")
97-
}
89+
Some(skip_expr) => self.get_constant_usize_result(skip_expr.value, input.schema(), "OFFSET"),
9890
_ => Ok(0),
9991
}?;
10092

10193
let fetch = match fetch {
10294
Some(limit_expr)
10395
if limit_expr != sqlparser::ast::Expr::Value(Value::Null) =>
10496
{
105-
let expr = self.sql_to_expr(
106-
limit_expr,
107-
input.schema(),
108-
&mut PlannerContext::new(),
109-
)?;
110-
let n = get_constant_result(&expr, "LIMIT")?;
111-
Some(convert_usize_with_check(n, "LIMIT")?)
97+
Some(self.get_constant_usize_result(limit_expr, input.schema(), "LIMIT")?)
11298
}
11399
_ => None,
114100
};
@@ -156,6 +142,28 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
156142
_ => Ok(plan),
157143
}
158144
}
145+
146+
/// Retrieves the constant usize result of an SQL expression, evaluating it if possible.
147+
///
148+
/// This function takes an SQL expression, a related scheme and an argument name as input and returns
149+
/// a `Result<usize>` indicating either the constant result of the expression or an
150+
/// error if the expression cannot be evaluated.
151+
///
152+
/// # Arguments
153+
///
154+
/// * `expr` - An `SQLExpr` representing the expression to evaluate.
155+
/// * `schema` - A related DataFusion schema to apply while converting an `expr` into a logical expression.
156+
/// * `arg_name` - The name of the argument for error messages.
157+
///
158+
/// # Returns
159+
///
160+
/// * `Result<usize>` - An `Ok` variant containing the constant result if evaluation is successful,
161+
/// or an `Err` variant containing an error message if evaluation fails.
162+
pub(super) fn get_constant_usize_result(&self, expr: SQLExpr, schema: &datafusion_common::DFSchema, arg_name: &str) -> Result<usize> {
163+
let expr = self.sql_to_expr(expr, schema, &mut PlannerContext::new())?;
164+
let value = get_constant_result(&expr, arg_name)?;
165+
convert_usize_with_check(value, arg_name)
166+
}
159167
}
160168

161169
/// Retrieves the constant result of an expression, evaluating it if possible.

datafusion/sql/src/statement.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -568,12 +568,8 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
568568
plan_err!("Delete-order-by clause not yet supported")?;
569569
}
570570

571-
if limit.is_some() {
572-
plan_err!("Delete-limit clause not yet supported")?;
573-
}
574-
575571
let table_name = self.get_delete_target(from)?;
576-
self.delete_to_plan(table_name, selection)
572+
self.delete_to_plan(table_name, selection, limit)
577573
}
578574

579575
Statement::StartTransaction {
@@ -1223,6 +1219,7 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
12231219
&self,
12241220
table_name: ObjectName,
12251221
predicate_expr: Option<SQLExpr>,
1222+
limit: Option<SQLExpr>
12261223
) -> Result<LogicalPlan> {
12271224
// Do a table lookup to verify the table exists
12281225
let table_ref = self.object_name_to_table_reference(table_name.clone())?;
@@ -1237,7 +1234,7 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
12371234
.build()?;
12381235
let mut planner_context = PlannerContext::new();
12391236

1240-
let source = match predicate_expr {
1237+
let mut source = match predicate_expr {
12411238
None => scan,
12421239
Some(predicate_expr) => {
12431240
let filter_expr =
@@ -1254,6 +1251,14 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
12541251
}
12551252
};
12561253

1254+
if let Some(limit_expr) = limit {
1255+
let limit = (limit_expr != SQLExpr::Value(Value::Null))
1256+
.then(|| self.get_constant_usize_result(limit_expr, source.schema(), "LIMIT"))
1257+
.transpose()?;
1258+
1259+
source = LogicalPlanBuilder::from(source).limit(0, limit)?.build()?
1260+
}
1261+
12571262
let plan = LogicalPlan::Dml(DmlStatement::new(
12581263
table_ref,
12591264
table_source,

datafusion/sql/tests/sql_integration.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,18 @@ Dml: op=[Delete] table=[person]
621621
quick_test(sql, plan);
622622
}
623623

624+
#[test]
625+
fn plan_delete_limited() {
626+
let sql = "delete from person limit 2";
627+
let plan = r#"
628+
Dml: op=[Delete] table=[person]
629+
Limit: skip=0, fetch=2
630+
TableScan: person
631+
"#
632+
.trim();
633+
quick_test(sql, plan);
634+
}
635+
624636
#[test]
625637
fn select_column_does_not_exist() {
626638
let sql = "SELECT doesnotexist FROM person";

0 commit comments

Comments
 (0)