@@ -1110,7 +1110,7 @@ EXPLAIN SELECT * FROM reversed_parquet ORDER BY id ASC;
11101110logical_plan
1111111101)Sort: reversed_parquet.id ASC NULLS LAST
1112111202)--TableScan: reversed_parquet projection=[id, value]
1113- physical_plan DataSourceExec: file_groups={1 group: [[WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/reversed/c_low.parquet, WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/reversed/b_mid.parquet, WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/reversed/a_high.parquet]]}, projection=[id, value], output_ordering=[id@0 ASC NULLS LAST], file_type=parquet, sort_order_for_reorder=[id@0 ASC NULLS LAST]
1113+ physical_plan DataSourceExec: file_groups={1 group: [[WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/reversed/c_low.parquet, WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/reversed/b_mid.parquet, WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/reversed/a_high.parquet]]}, projection=[id, value], output_ordering=[id@0 ASC NULLS LAST], file_type=parquet
11141114
11151115# Test 4.2: Results must be correct
11161116query II
@@ -1336,7 +1336,7 @@ EXPLAIN SELECT * FROM reversed_with_order_parquet ORDER BY id ASC;
13361336logical_plan
1337133701)Sort: reversed_with_order_parquet.id ASC NULLS LAST
1338133802)--TableScan: reversed_with_order_parquet projection=[id, value]
1339- physical_plan DataSourceExec: file_groups={1 group: [[WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/reversed/c_low.parquet, WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/reversed/b_mid.parquet, WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/reversed/a_high.parquet]]}, projection=[id, value], output_ordering=[id@0 ASC NULLS LAST], file_type=parquet, sort_order_for_reorder=[id@0 ASC NULLS LAST]
1339+ physical_plan DataSourceExec: file_groups={1 group: [[WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/reversed/c_low.parquet, WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/reversed/b_mid.parquet, WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/reversed/a_high.parquet]]}, projection=[id, value], output_ordering=[id@0 ASC NULLS LAST], file_type=parquet
13401340
13411341# Test 6.2: Results must be correct
13421342query II
@@ -1473,7 +1473,7 @@ EXPLAIN SELECT * FROM desc_reversed_parquet ORDER BY id DESC;
14731473logical_plan
1474147401)Sort: desc_reversed_parquet.id DESC NULLS FIRST
1475147502)--TableScan: desc_reversed_parquet projection=[id, value]
1476- physical_plan DataSourceExec: file_groups={1 group: [[WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/desc_reversed/b_high.parquet, WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/desc_reversed/a_low.parquet]]}, projection=[id, value], output_ordering=[id@0 DESC], file_type=parquet, sort_order_for_reorder=[id@0 DESC], reverse_row_groups=true
1476+ physical_plan DataSourceExec: file_groups={1 group: [[WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/desc_reversed/b_high.parquet, WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/desc_reversed/a_low.parquet]]}, projection=[id, value], output_ordering=[id@0 DESC], file_type=parquet
14771477
14781478# Test 8.2: Results must be correct
14791479query II
@@ -1486,6 +1486,78 @@ SELECT * FROM desc_reversed_parquet ORDER BY id DESC;
148614862 200
148714871 100
14881488
1489+ # Test 8b: DESC with multiple row groups per file sharing a min value.
1490+ # Regression test for the Inexact→Exact upgrade: when SortExec is eliminated
1491+ # the files must be read in natural order. The opener's runtime row-group
1492+ # reorder (sort ASC-by-min then reverse) mis-orders two row groups in one file
1493+ # that share the same min — so the upgrade must NOT leave those hints active.
1494+ #
1495+ # File b_high is DESC-sorted [10,8,8,8] written with 2 rows per row group:
1496+ # RG0 = [10, 8] (min 8, max 10)
1497+ # RG1 = [ 8, 8] (min 8, max 8)
1498+ # Both row groups have min=8. Naively reordering RGs ASC-by-min then reversing
1499+ # yields [RG1, RG0] → 8,8,10,8 (wrong). Natural order [RG0, RG1] is correct.
1500+
1501+ statement ok
1502+ CREATE TABLE rg_desc_high(id INT, value INT) AS VALUES (10, 100), (8, 801), (8, 802), (8, 803);
1503+
1504+ statement ok
1505+ CREATE TABLE rg_desc_low(id INT, value INT) AS VALUES (3, 300), (2, 200), (1, 100);
1506+
1507+ query I
1508+ COPY (SELECT * FROM rg_desc_high ORDER BY id DESC)
1509+ TO 'test_files/scratch/sort_pushdown/rg_desc/b_high.parquet'
1510+ OPTIONS ('format.max_row_group_size' '2');
1511+ ----
1512+ 4
1513+
1514+ query I
1515+ COPY (SELECT * FROM rg_desc_low ORDER BY id DESC)
1516+ TO 'test_files/scratch/sort_pushdown/rg_desc/a_low.parquet'
1517+ OPTIONS ('format.max_row_group_size' '2');
1518+ ----
1519+ 3
1520+
1521+ # Files named so filesystem order [a_low, b_high] is wrong for DESC → the
1522+ # Inexact path fires, stats reorder makes file groups [b_high, a_low]
1523+ # non-overlapping, and the upgrade eliminates SortExec.
1524+ statement ok
1525+ CREATE EXTERNAL TABLE rg_desc_parquet(id INT, value INT)
1526+ STORED AS PARQUET
1527+ LOCATION 'test_files/scratch/sort_pushdown/rg_desc/'
1528+ WITH ORDER (id DESC);
1529+
1530+ # SortExec eliminated, files reordered, NO sort_order_for_reorder /
1531+ # reverse_row_groups (natural read is correct after the upgrade).
1532+ query TT
1533+ EXPLAIN SELECT id FROM rg_desc_parquet ORDER BY id DESC;
1534+ ----
1535+ logical_plan
1536+ 01)Sort: rg_desc_parquet.id DESC NULLS FIRST
1537+ 02)--TableScan: rg_desc_parquet projection=[id]
1538+ physical_plan DataSourceExec: file_groups={1 group: [[WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/rg_desc/b_high.parquet, WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/rg_desc/a_low.parquet]]}, projection=[id], output_ordering=[id@0 DESC], file_type=parquet
1539+
1540+ # Results must be in DESC order — id=10 first.
1541+ query I
1542+ SELECT id FROM rg_desc_parquet ORDER BY id DESC;
1543+ ----
1544+ 10
1545+ 8
1546+ 8
1547+ 8
1548+ 3
1549+ 2
1550+ 1
1551+
1552+ statement ok
1553+ DROP TABLE rg_desc_parquet;
1554+
1555+ statement ok
1556+ DROP TABLE rg_desc_high;
1557+
1558+ statement ok
1559+ DROP TABLE rg_desc_low;
1560+
14891561# Test 9: Multi-column sort key validation
14901562# Files have (category, id) ordering. Files share a boundary value on category='B'
14911563# so column-level min/max statistics overlap on the primary key column.
@@ -2366,7 +2438,7 @@ logical_plan
23662438physical_plan
2367243901)SortPreservingMergeExec: [id@0 ASC NULLS LAST]
2368244002)--BufferExec: capacity=1073741824
2369- 03)----DataSourceExec: file_groups={2 groups: [[WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/tg_buffer/b_mid.parquet, WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/tg_buffer/a_high.parquet], [WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/tg_buffer/c_low.parquet]]}, projection=[id, value], output_ordering=[id@0 ASC NULLS LAST], file_type=parquet, sort_order_for_reorder=[id@0 ASC NULLS LAST]
2441+ 03)----DataSourceExec: file_groups={2 groups: [[WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/tg_buffer/b_mid.parquet, WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/tg_buffer/a_high.parquet], [WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/tg_buffer/c_low.parquet]]}, projection=[id, value], output_ordering=[id@0 ASC NULLS LAST], file_type=parquet
23702442
23712443# Verify correctness
23722444query II
@@ -2393,7 +2465,7 @@ logical_plan
23932465physical_plan
2394246601)SortPreservingMergeExec: [id@0 ASC NULLS LAST], fetch=3
2395246702)--BufferExec: capacity=1073741824
2396- 03)----DataSourceExec: file_groups={2 groups: [[WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/tg_buffer/b_mid.parquet, WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/tg_buffer/a_high.parquet], [WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/tg_buffer/c_low.parquet]]}, projection=[id, value], limit=3, output_ordering=[id@0 ASC NULLS LAST], file_type=parquet, sort_order_for_reorder=[id@0 ASC NULLS LAST]
2468+ 03)----DataSourceExec: file_groups={2 groups: [[WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/tg_buffer/b_mid.parquet, WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/tg_buffer/a_high.parquet], [WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/sort_pushdown/tg_buffer/c_low.parquet]]}, projection=[id, value], limit=3, output_ordering=[id@0 ASC NULLS LAST], file_type=parquet
23972469
23982470query II
23992471SELECT * FROM tg_buffer ORDER BY id ASC LIMIT 3;
0 commit comments