Skip to content

Commit 2d1551d

Browse files
PokIsemainesilezhouadriangbdependabot[bot]jdrouet
authored
feat: ORDER BY ALL (#15772)
* feat: ORDER BY ALL * refactor: orderyby all * refactor: order_by_to_sort_expr * refactor: TODO comment * fix query results for predicates referencing partition columns and data columns (#15935) * fix query results for predicates referencing partition columns and data columns * fmt * add e2e test * newline * chore(deps): bump substrait from 0.55.0 to 0.55.1 (#15941) Bumps [substrait](https://github.com/substrait-io/substrait-rs) from 0.55.0 to 0.55.1. - [Release notes](https://github.com/substrait-io/substrait-rs/releases) - [Changelog](https://github.com/substrait-io/substrait-rs/blob/main/CHANGELOG.md) - [Commits](substrait-io/substrait-rs@v0.55.0...v0.55.1) --- updated-dependencies: - dependency-name: substrait dependency-version: 0.55.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * feat: create helpers to set the max_temp_directory_size (#15919) * feat: create helpers to set the max_temp_directory_size Signed-off-by: Jérémie Drouet <[email protected]> * refactor: use helper in cli Signed-off-by: Jérémie Drouet <[email protected]> * refactor: update error message Signed-off-by: Jérémie Drouet <[email protected]> * refactor: use setter in tests Signed-off-by: Jérémie Drouet <[email protected]> --------- Signed-off-by: Jérémie Drouet <[email protected]> Co-authored-by: Andrew Lamb <[email protected]> * Fix main CI (#15942) * Improve sqllogictest error reporting (#15905) * refactor filter pushdown apis (#15801) * refactor filter pushdown apis * remove commented out code * fix tests * fail to fix bug * fix * add/fix docs * lint * add some docstrings, some minimal cleaup * review suggestions * add more comments * fix doc links * fmt * add comments * make test deterministic * add bench * fix bench * register bench * fix bench * cargo fmt --------- Co-authored-by: berkaysynnada <[email protected]> Co-authored-by: Berkay Şahin <[email protected]> --------- Signed-off-by: dependabot[bot] <[email protected]> Signed-off-by: Jérémie Drouet <[email protected]> Co-authored-by: silezhou <[email protected]> Co-authored-by: Adrian Garcia Badaracco <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jérémie Drouet <[email protected]> Co-authored-by: Andrew Lamb <[email protected]> Co-authored-by: xudong.w <[email protected]> Co-authored-by: Gabriel <[email protected]> Co-authored-by: berkaysynnada <[email protected]> Co-authored-by: Berkay Şahin <[email protected]>
1 parent 48331e6 commit 2d1551d

File tree

4 files changed

+90
-23
lines changed

4 files changed

+90
-23
lines changed

datafusion/sql/src/expr/order_by.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
4141
/// If false, interpret numeric literals as constant values.
4242
pub(crate) fn order_by_to_sort_expr(
4343
&self,
44-
exprs: Vec<OrderByExpr>,
44+
order_by_exprs: Vec<OrderByExpr>,
4545
input_schema: &DFSchema,
4646
planner_context: &mut PlannerContext,
4747
literal_to_column: bool,
4848
additional_schema: Option<&DFSchema>,
4949
) -> Result<Vec<SortExpr>> {
50-
if exprs.is_empty() {
50+
if order_by_exprs.is_empty() {
5151
return Ok(vec![]);
5252
}
5353

@@ -61,13 +61,23 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
6161
None => input_schema,
6262
};
6363

64-
let mut expr_vec = vec![];
65-
for e in exprs {
64+
let mut sort_expr_vec = Vec::with_capacity(order_by_exprs.len());
65+
66+
let make_sort_expr =
67+
|expr: Expr, asc: Option<bool>, nulls_first: Option<bool>| {
68+
let asc = asc.unwrap_or(true);
69+
// When asc is true, by default nulls last to be consistent with postgres
70+
// postgres rule: https://www.postgresql.org/docs/current/queries-order.html
71+
let nulls_first = nulls_first.unwrap_or(!asc);
72+
Sort::new(expr, asc, nulls_first)
73+
};
74+
75+
for order_by_expr in order_by_exprs {
6676
let OrderByExpr {
6777
expr,
6878
options: OrderByOptions { asc, nulls_first },
6979
with_fill,
70-
} = e;
80+
} = order_by_expr;
7181

7282
if let Some(with_fill) = with_fill {
7383
return not_impl_err!("ORDER BY WITH FILL is not supported: {with_fill}");
@@ -102,15 +112,9 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
102112
self.sql_expr_to_logical_expr(e, order_by_schema, planner_context)?
103113
}
104114
};
105-
let asc = asc.unwrap_or(true);
106-
expr_vec.push(Sort::new(
107-
expr,
108-
asc,
109-
// When asc is true, by default nulls last to be consistent with postgres
110-
// postgres rule: https://www.postgresql.org/docs/current/queries-order.html
111-
nulls_first.unwrap_or(!asc),
112-
))
115+
sort_expr_vec.push(make_sort_expr(expr, asc, nulls_first));
113116
}
114-
Ok(expr_vec)
117+
118+
Ok(sort_expr_vec)
115119
}
116120
}

datafusion/sql/src/query.rs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ use crate::planner::{ContextProvider, PlannerContext, SqlToRel};
2222
use crate::stack::StackGuard;
2323
use datafusion_common::{not_impl_err, Constraints, DFSchema, Result};
2424
use datafusion_expr::expr::Sort;
25-
use datafusion_expr::select_expr::SelectExpr;
25+
2626
use datafusion_expr::{
27-
CreateMemoryTable, DdlStatement, Distinct, LogicalPlan, LogicalPlanBuilder,
27+
CreateMemoryTable, DdlStatement, Distinct, Expr, LogicalPlan, LogicalPlanBuilder,
2828
};
2929
use sqlparser::ast::{
30-
Expr as SQLExpr, Offset as SQLOffset, OrderBy, OrderByExpr, OrderByKind, Query,
31-
SelectInto, SetExpr,
30+
Expr as SQLExpr, Ident, Offset as SQLOffset, OrderBy, OrderByExpr, OrderByKind,
31+
Query, SelectInto, SetExpr,
3232
};
33+
use sqlparser::tokenizer::Span;
3334

3435
impl<S: ContextProvider> SqlToRel<'_, S> {
3536
/// Generate a logical plan from an SQL query/subquery
@@ -158,7 +159,7 @@ fn to_order_by_exprs(order_by: Option<OrderBy>) -> Result<Vec<OrderByExpr>> {
158159
/// Returns the order by expressions from the query with the select expressions.
159160
pub(crate) fn to_order_by_exprs_with_select(
160161
order_by: Option<OrderBy>,
161-
_select_exprs: Option<&Vec<SelectExpr>>, // TODO: ORDER BY ALL
162+
select_exprs: Option<&Vec<Expr>>,
162163
) -> Result<Vec<OrderByExpr>> {
163164
let Some(OrderBy { kind, interpolate }) = order_by else {
164165
// If no order by, return an empty array.
@@ -168,7 +169,30 @@ pub(crate) fn to_order_by_exprs_with_select(
168169
return not_impl_err!("ORDER BY INTERPOLATE is not supported");
169170
}
170171
match kind {
171-
OrderByKind::All(_) => not_impl_err!("ORDER BY ALL is not supported"),
172+
OrderByKind::All(order_by_options) => {
173+
let Some(exprs) = select_exprs else {
174+
return Ok(vec![]);
175+
};
176+
let order_by_exprs = exprs
177+
.iter()
178+
.map(|select_expr| match select_expr {
179+
Expr::Column(column) => Ok(OrderByExpr {
180+
expr: SQLExpr::Identifier(Ident {
181+
value: column.name.clone(),
182+
quote_style: None,
183+
span: Span::empty(),
184+
}),
185+
options: order_by_options.clone(),
186+
with_fill: None,
187+
}),
188+
// TODO: Support other types of expressions
189+
_ => not_impl_err!(
190+
"ORDER BY ALL is not supported for non-column expressions"
191+
),
192+
})
193+
.collect::<Result<Vec<_>>>()?;
194+
Ok(order_by_exprs)
195+
}
172196
OrderByKind::Expressions(order_by_exprs) => Ok(order_by_exprs),
173197
}
174198
}

datafusion/sql/src/select.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,13 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
9494
planner_context,
9595
)?;
9696

97-
let order_by =
98-
to_order_by_exprs_with_select(query_order_by, Some(&select_exprs))?;
99-
10097
// Having and group by clause may reference aliases defined in select projection
10198
let projected_plan = self.project(base_plan.clone(), select_exprs)?;
10299
let select_exprs = projected_plan.expressions();
103100

101+
let order_by =
102+
to_order_by_exprs_with_select(query_order_by, Some(&select_exprs))?;
103+
104104
// Place the fields of the base plan at the front so that when there are references
105105
// with the same name, the fields of the base plan will be searched first.
106106
// See https://github.com/apache/datafusion/issues/9162

datafusion/sqllogictest/test_files/order.slt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,3 +1380,42 @@ physical_plan
13801380

13811381
statement ok
13821382
drop table table_with_ordered_not_null;
1383+
1384+
# ORDER BY ALL
1385+
statement ok
1386+
set datafusion.sql_parser.dialect = 'DuckDB';
1387+
1388+
statement ok
1389+
CREATE OR REPLACE TABLE addresses AS
1390+
SELECT '123 Quack Blvd' AS address, 'DuckTown' AS city, '11111' AS zip
1391+
UNION ALL
1392+
SELECT '111 Duck Duck Goose Ln', 'DuckTown', '11111'
1393+
UNION ALL
1394+
SELECT '111 Duck Duck Goose Ln', 'Duck Town', '11111'
1395+
UNION ALL
1396+
SELECT '111 Duck Duck Goose Ln', 'Duck Town', '11111-0001';
1397+
1398+
1399+
query TTT
1400+
SELECT * FROM addresses ORDER BY ALL;
1401+
----
1402+
111 Duck Duck Goose Ln Duck Town 11111
1403+
111 Duck Duck Goose Ln Duck Town 11111-0001
1404+
111 Duck Duck Goose Ln DuckTown 11111
1405+
123 Quack Blvd DuckTown 11111
1406+
1407+
query TTT
1408+
SELECT * FROM addresses ORDER BY ALL DESC;
1409+
----
1410+
123 Quack Blvd DuckTown 11111
1411+
111 Duck Duck Goose Ln DuckTown 11111
1412+
111 Duck Duck Goose Ln Duck Town 11111-0001
1413+
111 Duck Duck Goose Ln Duck Town 11111
1414+
1415+
query TT
1416+
SELECT address, zip FROM addresses ORDER BY ALL;
1417+
----
1418+
111 Duck Duck Goose Ln 11111
1419+
111 Duck Duck Goose Ln 11111
1420+
111 Duck Duck Goose Ln 11111-0001
1421+
123 Quack Blvd 11111

0 commit comments

Comments
 (0)