This is an automated email from the ASF dual-hosted git repository.
dheres pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-datafusion.git
The following commit(s) were added to refs/heads/master by this push:
new 301e863 fix: make nulls-order consistent with postgres (#1344)
301e863 is described below
commit 301e8631f444c8a9d5e2ff440cd5c30bf63e518a
Author: Carlos <[email protected]>
AuthorDate: Sun Nov 21 06:06:34 2021 +0800
fix: make nulls-order consistent with postgres (#1344)
---
datafusion/src/sql/planner.rs | 83 +++++++++++-----------
datafusion/tests/sql.rs | 78 +++++++++++++++++++-
integration-tests/create_test_table.sql | 4 +-
.../simple_sort_nulls_order.sql} | 24 ++-----
integration-tests/test_psql_parity.py | 2 +-
5 files changed, 127 insertions(+), 64 deletions(-)
diff --git a/datafusion/src/sql/planner.rs b/datafusion/src/sql/planner.rs
index 575acd0..9f1d243 100644
--- a/datafusion/src/sql/planner.rs
+++ b/datafusion/src/sql/planner.rs
@@ -1026,12 +1026,15 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
/// convert sql OrderByExpr to Expr::Sort
fn order_by_to_sort_expr(&self, e: &OrderByExpr, schema: &DFSchema) ->
Result<Expr> {
- Ok(Expr::Sort {
- expr: Box::new(self.sql_expr_to_logical_expr(&e.expr, schema)?),
- // by default asc
- asc: e.asc.unwrap_or(true),
- // by default nulls first to be consistent with spark
- nulls_first: e.nulls_first.unwrap_or(true),
+ Ok({
+ let asc = e.asc.unwrap_or(true);
+ Expr::Sort {
+ expr: Box::new(self.sql_expr_to_logical_expr(&e.expr,
schema)?),
+ asc,
+ // when asc is true, by default nulls last to be consistent
with postgres
+ // postgres rule:
https://www.postgresql.org/docs/current/queries-order.html
+ nulls_first: e.nulls_first.unwrap_or(!asc),
+ }
})
}
@@ -2962,7 +2965,7 @@ mod tests {
#[test]
fn select_order_by() {
let sql = "SELECT id FROM person ORDER BY id";
- let expected = "Sort: #person.id ASC NULLS FIRST\
+ let expected = "Sort: #person.id ASC NULLS LAST\
\n Projection: #person.id\
\n TableScan: person projection=None";
quick_test(sql, expected);
@@ -3280,9 +3283,9 @@ mod tests {
fn empty_over_dup_with_different_sort() {
let sql = "SELECT order_id oid, MAX(order_id) OVER (), MAX(order_id)
OVER (ORDER BY order_id) from orders";
let expected = "\
- Projection: #orders.order_id AS oid, #MAX(orders.order_id),
#MAX(orders.order_id) ORDER BY [#orders.order_id ASC NULLS FIRST]\
+ Projection: #orders.order_id AS oid, #MAX(orders.order_id),
#MAX(orders.order_id) ORDER BY [#orders.order_id ASC NULLS LAST]\
\n WindowAggr: windowExpr=[[MAX(#orders.order_id)]]\
- \n WindowAggr: windowExpr=[[MAX(#orders.order_id) ORDER BY
[#orders.order_id ASC NULLS FIRST]]]\
+ \n WindowAggr: windowExpr=[[MAX(#orders.order_id) ORDER BY
[#orders.order_id ASC NULLS LAST]]]\
\n TableScan: orders projection=None";
quick_test(sql, expected);
}
@@ -3343,8 +3346,8 @@ mod tests {
fn over_order_by() {
let sql = "SELECT order_id, MAX(qty) OVER (ORDER BY order_id),
MIN(qty) OVER (ORDER BY order_id DESC) from orders";
let expected = "\
- Projection: #orders.order_id, #MAX(orders.qty) ORDER BY
[#orders.order_id ASC NULLS FIRST], #MIN(orders.qty) ORDER BY [#orders.order_id
DESC NULLS FIRST]\
- \n WindowAggr: windowExpr=[[MAX(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS FIRST]]]\
+ Projection: #orders.order_id, #MAX(orders.qty) ORDER BY
[#orders.order_id ASC NULLS LAST], #MIN(orders.qty) ORDER BY [#orders.order_id
DESC NULLS FIRST]\
+ \n WindowAggr: windowExpr=[[MAX(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS LAST]]]\
\n WindowAggr: windowExpr=[[MIN(#orders.qty) ORDER BY
[#orders.order_id DESC NULLS FIRST]]]\
\n TableScan: orders projection=None";
quick_test(sql, expected);
@@ -3354,8 +3357,8 @@ mod tests {
fn over_order_by_with_window_frame_double_end() {
let sql = "SELECT order_id, MAX(qty) OVER (ORDER BY order_id ROWS
BETWEEN 3 PRECEDING and 3 FOLLOWING), MIN(qty) OVER (ORDER BY order_id DESC)
from orders";
let expected = "\
- Projection: #orders.order_id, #MAX(orders.qty) ORDER BY
[#orders.order_id ASC NULLS FIRST] ROWS BETWEEN 3 PRECEDING AND 3 FOLLOWING,
#MIN(orders.qty) ORDER BY [#orders.order_id DESC NULLS FIRST]\
- \n WindowAggr: windowExpr=[[MAX(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS FIRST] ROWS BETWEEN 3 PRECEDING AND 3 FOLLOWING]]\
+ Projection: #orders.order_id, #MAX(orders.qty) ORDER BY
[#orders.order_id ASC NULLS LAST] ROWS BETWEEN 3 PRECEDING AND 3 FOLLOWING,
#MIN(orders.qty) ORDER BY [#orders.order_id DESC NULLS FIRST]\
+ \n WindowAggr: windowExpr=[[MAX(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS LAST] ROWS BETWEEN 3 PRECEDING AND 3 FOLLOWING]]\
\n WindowAggr: windowExpr=[[MIN(#orders.qty) ORDER BY
[#orders.order_id DESC NULLS FIRST]]]\
\n TableScan: orders projection=None";
quick_test(sql, expected);
@@ -3365,8 +3368,8 @@ mod tests {
fn over_order_by_with_window_frame_single_end() {
let sql = "SELECT order_id, MAX(qty) OVER (ORDER BY order_id ROWS 3
PRECEDING), MIN(qty) OVER (ORDER BY order_id DESC) from orders";
let expected = "\
- Projection: #orders.order_id, #MAX(orders.qty) ORDER BY
[#orders.order_id ASC NULLS FIRST] ROWS BETWEEN 3 PRECEDING AND CURRENT ROW,
#MIN(orders.qty) ORDER BY [#orders.order_id DESC NULLS FIRST]\
- \n WindowAggr: windowExpr=[[MAX(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS FIRST] ROWS BETWEEN 3 PRECEDING AND CURRENT ROW]]\
+ Projection: #orders.order_id, #MAX(orders.qty) ORDER BY
[#orders.order_id ASC NULLS LAST] ROWS BETWEEN 3 PRECEDING AND CURRENT ROW,
#MIN(orders.qty) ORDER BY [#orders.order_id DESC NULLS FIRST]\
+ \n WindowAggr: windowExpr=[[MAX(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS LAST] ROWS BETWEEN 3 PRECEDING AND CURRENT ROW]]\
\n WindowAggr: windowExpr=[[MIN(#orders.qty) ORDER BY
[#orders.order_id DESC NULLS FIRST]]]\
\n TableScan: orders projection=None";
quick_test(sql, expected);
@@ -3408,8 +3411,8 @@ mod tests {
fn over_order_by_with_window_frame_single_end_groups() {
let sql = "SELECT order_id, MAX(qty) OVER (ORDER BY order_id GROUPS 3
PRECEDING), MIN(qty) OVER (ORDER BY order_id DESC) from orders";
let expected = "\
- Projection: #orders.order_id, #MAX(orders.qty) ORDER BY
[#orders.order_id ASC NULLS FIRST] GROUPS BETWEEN 3 PRECEDING AND CURRENT ROW,
#MIN(orders.qty) ORDER BY [#orders.order_id DESC NULLS FIRST]\
- \n WindowAggr: windowExpr=[[MAX(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS FIRST] GROUPS BETWEEN 3 PRECEDING AND CURRENT ROW]]\
+ Projection: #orders.order_id, #MAX(orders.qty) ORDER BY
[#orders.order_id ASC NULLS LAST] GROUPS BETWEEN 3 PRECEDING AND CURRENT ROW,
#MIN(orders.qty) ORDER BY [#orders.order_id DESC NULLS FIRST]\
+ \n WindowAggr: windowExpr=[[MAX(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS LAST] GROUPS BETWEEN 3 PRECEDING AND CURRENT ROW]]\
\n WindowAggr: windowExpr=[[MIN(#orders.qty) ORDER BY
[#orders.order_id DESC NULLS FIRST]]]\
\n TableScan: orders projection=None";
quick_test(sql, expected);
@@ -3431,9 +3434,9 @@ mod tests {
fn over_order_by_two_sort_keys() {
let sql = "SELECT order_id, MAX(qty) OVER (ORDER BY order_id),
MIN(qty) OVER (ORDER BY (order_id + 1)) from orders";
let expected = "\
- Projection: #orders.order_id, #MAX(orders.qty) ORDER BY
[#orders.order_id ASC NULLS FIRST], #MIN(orders.qty) ORDER BY [#orders.order_id
+ Int64(1) ASC NULLS FIRST]\
- \n WindowAggr: windowExpr=[[MAX(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS FIRST]]]\
- \n WindowAggr: windowExpr=[[MIN(#orders.qty) ORDER BY
[#orders.order_id + Int64(1) ASC NULLS FIRST]]]\
+ Projection: #orders.order_id, #MAX(orders.qty) ORDER BY
[#orders.order_id ASC NULLS LAST], #MIN(orders.qty) ORDER BY [#orders.order_id
+ Int64(1) ASC NULLS LAST]\
+ \n WindowAggr: windowExpr=[[MAX(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS LAST]]]\
+ \n WindowAggr: windowExpr=[[MIN(#orders.qty) ORDER BY
[#orders.order_id + Int64(1) ASC NULLS LAST]]]\
\n TableScan: orders projection=None";
quick_test(sql, expected);
}
@@ -3455,10 +3458,10 @@ mod tests {
fn over_order_by_sort_keys_sorting() {
let sql = "SELECT order_id, MAX(qty) OVER (ORDER BY qty, order_id),
SUM(qty) OVER (), MIN(qty) OVER (ORDER BY order_id, qty) from orders";
let expected = "\
- Projection: #orders.order_id, #MAX(orders.qty) ORDER BY [#orders.qty
ASC NULLS FIRST, #orders.order_id ASC NULLS FIRST], #SUM(orders.qty),
#MIN(orders.qty) ORDER BY [#orders.order_id ASC NULLS FIRST, #orders.qty ASC
NULLS FIRST]\
+ Projection: #orders.order_id, #MAX(orders.qty) ORDER BY [#orders.qty
ASC NULLS LAST, #orders.order_id ASC NULLS LAST], #SUM(orders.qty),
#MIN(orders.qty) ORDER BY [#orders.order_id ASC NULLS LAST, #orders.qty ASC
NULLS LAST]\
\n WindowAggr: windowExpr=[[SUM(#orders.qty)]]\
- \n WindowAggr: windowExpr=[[MAX(#orders.qty) ORDER BY [#orders.qty
ASC NULLS FIRST, #orders.order_id ASC NULLS FIRST]]]\
- \n WindowAggr: windowExpr=[[MIN(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS FIRST, #orders.qty ASC NULLS FIRST]]]\
+ \n WindowAggr: windowExpr=[[MAX(#orders.qty) ORDER BY [#orders.qty
ASC NULLS LAST, #orders.order_id ASC NULLS LAST]]]\
+ \n WindowAggr: windowExpr=[[MIN(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS LAST, #orders.qty ASC NULLS LAST]]]\
\n TableScan: orders projection=None";
quick_test(sql, expected);
}
@@ -3480,10 +3483,10 @@ mod tests {
fn over_order_by_sort_keys_sorting_prefix_compacting() {
let sql = "SELECT order_id, MAX(qty) OVER (ORDER BY order_id),
SUM(qty) OVER (), MIN(qty) OVER (ORDER BY order_id, qty) from orders";
let expected = "\
- Projection: #orders.order_id, #MAX(orders.qty) ORDER BY
[#orders.order_id ASC NULLS FIRST], #SUM(orders.qty), #MIN(orders.qty) ORDER BY
[#orders.order_id ASC NULLS FIRST, #orders.qty ASC NULLS FIRST]\
+ Projection: #orders.order_id, #MAX(orders.qty) ORDER BY
[#orders.order_id ASC NULLS LAST], #SUM(orders.qty), #MIN(orders.qty) ORDER BY
[#orders.order_id ASC NULLS LAST, #orders.qty ASC NULLS LAST]\
\n WindowAggr: windowExpr=[[SUM(#orders.qty)]]\
- \n WindowAggr: windowExpr=[[MAX(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS FIRST]]]\
- \n WindowAggr: windowExpr=[[MIN(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS FIRST, #orders.qty ASC NULLS FIRST]]]\
+ \n WindowAggr: windowExpr=[[MAX(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS LAST]]]\
+ \n WindowAggr: windowExpr=[[MIN(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS LAST, #orders.qty ASC NULLS LAST]]]\
\n TableScan: orders projection=None";
quick_test(sql, expected);
}
@@ -3508,11 +3511,11 @@ mod tests {
fn over_order_by_sort_keys_sorting_global_order_compacting() {
let sql = "SELECT order_id, MAX(qty) OVER (ORDER BY qty, order_id),
SUM(qty) OVER (), MIN(qty) OVER (ORDER BY order_id, qty) from orders ORDER BY
order_id";
let expected = "\
- Sort: #orders.order_id ASC NULLS FIRST\
- \n Projection: #orders.order_id, #MAX(orders.qty) ORDER BY
[#orders.qty ASC NULLS FIRST, #orders.order_id ASC NULLS FIRST],
#SUM(orders.qty), #MIN(orders.qty) ORDER BY [#orders.order_id ASC NULLS FIRST,
#orders.qty ASC NULLS FIRST]\
+ Sort: #orders.order_id ASC NULLS LAST\
+ \n Projection: #orders.order_id, #MAX(orders.qty) ORDER BY
[#orders.qty ASC NULLS LAST, #orders.order_id ASC NULLS LAST],
#SUM(orders.qty), #MIN(orders.qty) ORDER BY [#orders.order_id ASC NULLS LAST,
#orders.qty ASC NULLS LAST]\
\n WindowAggr: windowExpr=[[SUM(#orders.qty)]]\
- \n WindowAggr: windowExpr=[[MAX(#orders.qty) ORDER BY
[#orders.qty ASC NULLS FIRST, #orders.order_id ASC NULLS FIRST]]]\
- \n WindowAggr: windowExpr=[[MIN(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS FIRST, #orders.qty ASC NULLS FIRST]]]\
+ \n WindowAggr: windowExpr=[[MAX(#orders.qty) ORDER BY
[#orders.qty ASC NULLS LAST, #orders.order_id ASC NULLS LAST]]]\
+ \n WindowAggr: windowExpr=[[MIN(#orders.qty) ORDER BY
[#orders.order_id ASC NULLS LAST, #orders.qty ASC NULLS LAST]]]\
\n TableScan: orders projection=None";
quick_test(sql, expected);
}
@@ -3531,8 +3534,8 @@ mod tests {
let sql =
"SELECT order_id, MAX(qty) OVER (PARTITION BY order_id ORDER BY
qty) from orders";
let expected = "\
- Projection: #orders.order_id, #MAX(orders.qty) PARTITION BY
[#orders.order_id] ORDER BY [#orders.qty ASC NULLS FIRST]\
- \n WindowAggr: windowExpr=[[MAX(#orders.qty) PARTITION BY
[#orders.order_id] ORDER BY [#orders.qty ASC NULLS FIRST]]]\
+ Projection: #orders.order_id, #MAX(orders.qty) PARTITION BY
[#orders.order_id] ORDER BY [#orders.qty ASC NULLS LAST]\
+ \n WindowAggr: windowExpr=[[MAX(#orders.qty) PARTITION BY
[#orders.order_id] ORDER BY [#orders.qty ASC NULLS LAST]]]\
\n TableScan: orders projection=None";
quick_test(sql, expected);
}
@@ -3551,8 +3554,8 @@ mod tests {
let sql =
"SELECT order_id, MAX(qty) OVER (PARTITION BY order_id, qty ORDER
BY qty) from orders";
let expected = "\
- Projection: #orders.order_id, #MAX(orders.qty) PARTITION BY
[#orders.order_id, #orders.qty] ORDER BY [#orders.qty ASC NULLS FIRST]\
- \n WindowAggr: windowExpr=[[MAX(#orders.qty) PARTITION BY
[#orders.order_id, #orders.qty] ORDER BY [#orders.qty ASC NULLS FIRST]]]\
+ Projection: #orders.order_id, #MAX(orders.qty) PARTITION BY
[#orders.order_id, #orders.qty] ORDER BY [#orders.qty ASC NULLS LAST]\
+ \n WindowAggr: windowExpr=[[MAX(#orders.qty) PARTITION BY
[#orders.order_id, #orders.qty] ORDER BY [#orders.qty ASC NULLS LAST]]]\
\n TableScan: orders projection=None";
quick_test(sql, expected);
}
@@ -3574,9 +3577,9 @@ mod tests {
let sql =
"SELECT order_id, MAX(qty) OVER (PARTITION BY order_id, qty ORDER
BY qty), MIN(qty) OVER (PARTITION BY qty ORDER BY order_id) from orders";
let expected = "\
- Projection: #orders.order_id, #MAX(orders.qty) PARTITION BY
[#orders.order_id, #orders.qty] ORDER BY [#orders.qty ASC NULLS FIRST],
#MIN(orders.qty) PARTITION BY [#orders.qty] ORDER BY [#orders.order_id ASC
NULLS FIRST]\
- \n WindowAggr: windowExpr=[[MAX(#orders.qty) PARTITION BY
[#orders.order_id, #orders.qty] ORDER BY [#orders.qty ASC NULLS FIRST]]]\
- \n WindowAggr: windowExpr=[[MIN(#orders.qty) PARTITION BY
[#orders.qty] ORDER BY [#orders.order_id ASC NULLS FIRST]]]\
+ Projection: #orders.order_id, #MAX(orders.qty) PARTITION BY
[#orders.order_id, #orders.qty] ORDER BY [#orders.qty ASC NULLS LAST],
#MIN(orders.qty) PARTITION BY [#orders.qty] ORDER BY [#orders.order_id ASC
NULLS LAST]\
+ \n WindowAggr: windowExpr=[[MIN(#orders.qty) PARTITION BY
[#orders.qty] ORDER BY [#orders.order_id ASC NULLS LAST]]]\
+ \n WindowAggr: windowExpr=[[MAX(#orders.qty) PARTITION BY
[#orders.order_id, #orders.qty] ORDER BY [#orders.qty ASC NULLS LAST]]]\
\n TableScan: orders projection=None";
quick_test(sql, expected);
}
@@ -3597,9 +3600,9 @@ mod tests {
let sql =
"SELECT order_id, MAX(qty) OVER (PARTITION BY order_id ORDER BY
qty), MIN(qty) OVER (PARTITION BY order_id, qty ORDER BY price) from orders";
let expected = "\
- Projection: #orders.order_id, #MAX(orders.qty) PARTITION BY
[#orders.order_id] ORDER BY [#orders.qty ASC NULLS FIRST], #MIN(orders.qty)
PARTITION BY [#orders.order_id, #orders.qty] ORDER BY [#orders.price ASC NULLS
FIRST]\
- \n WindowAggr: windowExpr=[[MAX(#orders.qty) PARTITION BY
[#orders.order_id] ORDER BY [#orders.qty ASC NULLS FIRST]]]\
- \n WindowAggr: windowExpr=[[MIN(#orders.qty) PARTITION BY
[#orders.order_id, #orders.qty] ORDER BY [#orders.price ASC NULLS FIRST]]]\
+ Projection: #orders.order_id, #MAX(orders.qty) PARTITION BY
[#orders.order_id] ORDER BY [#orders.qty ASC NULLS LAST], #MIN(orders.qty)
PARTITION BY [#orders.order_id, #orders.qty] ORDER BY [#orders.price ASC NULLS
LAST]\
+ \n WindowAggr: windowExpr=[[MAX(#orders.qty) PARTITION BY
[#orders.order_id] ORDER BY [#orders.qty ASC NULLS LAST]]]\
+ \n WindowAggr: windowExpr=[[MIN(#orders.qty) PARTITION BY
[#orders.order_id, #orders.qty] ORDER BY [#orders.price ASC NULLS LAST]]]\
\n TableScan: orders projection=None";
quick_test(sql, expected);
}
diff --git a/datafusion/tests/sql.rs b/datafusion/tests/sql.rs
index c910e55..e761633 100644
--- a/datafusion/tests/sql.rs
+++ b/datafusion/tests/sql.rs
@@ -2412,10 +2412,10 @@ async fn right_join() -> Result<()> {
"+-------+---------+---------+",
"| t1_id | t1_name | t2_name |",
"+-------+---------+---------+",
- "| | | w |",
"| 11 | a | z |",
"| 22 | b | y |",
"| 44 | d | x |",
+ "| | | w |",
"+-------+---------+---------+",
];
for sql in equivalent_sql.iter() {
@@ -2436,11 +2436,11 @@ async fn full_join() -> Result<()> {
"+-------+---------+---------+",
"| t1_id | t1_name | t2_name |",
"+-------+---------+---------+",
- "| | | w |",
"| 11 | a | z |",
"| 22 | b | y |",
"| 33 | c | |",
"| 44 | d | x |",
+ "| | | w |",
"+-------+---------+---------+",
];
for sql in equivalent_sql.iter() {
@@ -3025,7 +3025,7 @@ async fn explain_analyze_baseline_metrics() {
);
assert_metrics!(
&formatted,
- "SortExec: [c1@0 ASC]",
+ "SortExec: [c1@0 ASC NULLS LAST]",
"metrics=[output_rows=5, elapsed_compute="
);
assert_metrics!(
@@ -6204,3 +6204,75 @@ async fn test_expect_distinct() -> Result<()> {
assert_batches_eq!(expected, &actual);
Ok(())
}
+
+#[tokio::test]
+async fn test_nulls_first_asc() -> Result<()> {
+ let mut ctx = ExecutionContext::new();
+ let sql = "SELECT * FROM (VALUES (1, 'one'), (2, 'two'), (null, 'three'))
AS t (num,letter) ORDER BY num";
+ let actual = execute_to_batches(&mut ctx, sql).await;
+ let expected = vec![
+ "+-----+--------+",
+ "| num | letter |",
+ "+-----+--------+",
+ "| 1 | one |",
+ "| 2 | two |",
+ "| | three |",
+ "+-----+--------+",
+ ];
+ assert_batches_eq!(expected, &actual);
+ Ok(())
+}
+
+#[tokio::test]
+async fn test_nulls_first_desc() -> Result<()> {
+ let mut ctx = ExecutionContext::new();
+ let sql = "SELECT * FROM (VALUES (1, 'one'), (2, 'two'), (null, 'three'))
AS t (num,letter) ORDER BY num DESC";
+ let actual = execute_to_batches(&mut ctx, sql).await;
+ let expected = vec![
+ "+-----+--------+",
+ "| num | letter |",
+ "+-----+--------+",
+ "| | three |",
+ "| 2 | two |",
+ "| 1 | one |",
+ "+-----+--------+",
+ ];
+ assert_batches_eq!(expected, &actual);
+ Ok(())
+}
+
+#[tokio::test]
+async fn test_specific_nulls_last_desc() -> Result<()> {
+ let mut ctx = ExecutionContext::new();
+ let sql = "SELECT * FROM (VALUES (1, 'one'), (2, 'two'), (null, 'three'))
AS t (num,letter) ORDER BY num DESC NULLS LAST";
+ let actual = execute_to_batches(&mut ctx, sql).await;
+ let expected = vec![
+ "+-----+--------+",
+ "| num | letter |",
+ "+-----+--------+",
+ "| 2 | two |",
+ "| 1 | one |",
+ "| | three |",
+ "+-----+--------+",
+ ];
+ assert_batches_eq!(expected, &actual);
+ Ok(())
+}
+
+#[tokio::test]
+async fn test_specific_nulls_first_asc() -> Result<()> {
+ let mut ctx = ExecutionContext::new();
+ let sql = "SELECT * FROM (VALUES (1, 'one'), (2, 'two'), (null, 'three'))
AS t (num,letter) ORDER BY num ASC NULLS FIRST";
+ let actual = execute_to_batches(&mut ctx, sql).await;
+ let expected = vec![
+ "+-----+--------+",
+ "| num | letter |",
+ "+-----+--------+",
+ "| | three |",
+ "| 1 | one |",
+ "| 2 | two |",
+ "+-----+--------+",
+ ];
+ assert_batches_eq!(expected, &actual);
+ Ok(())
+}
diff --git a/integration-tests/create_test_table.sql
b/integration-tests/create_test_table.sql
index 89b0861..580ca0a 100644
--- a/integration-tests/create_test_table.sql
+++ b/integration-tests/create_test_table.sql
@@ -18,8 +18,8 @@ CREATE EXTERNAL TABLE test (
c1 VARCHAR NOT NULL,
c2 INT NOT NULL,
c3 SMALLINT NOT NULL,
- c4 SMALLINT NOT NULL,
- c5 INT NOT NULL,
+ c4 SMALLINT,
+ c5 INT,
c6 BIGINT NOT NULL,
c7 SMALLINT NOT NULL,
c8 INT NOT NULL,
diff --git a/integration-tests/create_test_table.sql
b/integration-tests/sqls/simple_sort_nulls_order.sql
similarity index 64%
copy from integration-tests/create_test_table.sql
copy to integration-tests/sqls/simple_sort_nulls_order.sql
index 89b0861..f5c61aa 100644
--- a/integration-tests/create_test_table.sql
+++ b/integration-tests/sqls/simple_sort_nulls_order.sql
@@ -14,21 +14,9 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
-CREATE EXTERNAL TABLE test (
- c1 VARCHAR NOT NULL,
- c2 INT NOT NULL,
- c3 SMALLINT NOT NULL,
- c4 SMALLINT NOT NULL,
- c5 INT NOT NULL,
- c6 BIGINT NOT NULL,
- c7 SMALLINT NOT NULL,
- c8 INT NOT NULL,
- c9 BIGINT NOT NULL,
- c10 VARCHAR NOT NULL,
- c11 FLOAT NOT NULL,
- c12 DOUBLE NOT NULL,
- c13 VARCHAR NOT NULL
-)
-STORED AS CSV
-WITH HEADER ROW
-LOCATION 'testing/data/csv/aggregate_test_100.csv';
+SELECT
+ c5,
+ c4,
+ c10
+FROM test
+ORDER BY c5 ASC, c4 DESC, c10;
\ No newline at end of file
diff --git a/integration-tests/test_psql_parity.py
b/integration-tests/test_psql_parity.py
index 8cd94ba..8a1091c 100644
--- a/integration-tests/test_psql_parity.py
+++ b/integration-tests/test_psql_parity.py
@@ -77,7 +77,7 @@ test_files = set(root.glob("*.sql"))
class TestPsqlParity:
def test_tests_count(self):
- assert len(test_files) == 20, "tests are missed"
+ assert len(test_files) == 21, "tests are missed"
@pytest.mark.parametrize("fname", test_files)
def test_sql_file(self, fname):