You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datafusion.apache.org by gi...@apache.org on 2026/10/18 03:37:54 UTC

(datafusion) branch gh-readonly-queue/main/pr-26414-290ad15cc842167ca4d3c0774ccdf3a1d9d61862 created (now 16b6833255)

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

github-merge-queue[bot] pushed a change to branch gh-readonly-queue/main/pr-26414-290ad15cc842167ca4d3c0774ccdf3a1d9d61862
in repository https://gitbox.apache.org/repos/asf/datafusion.git


      at 16b6833255 fix: preserve input strictness in `from_unixtime` (#26414)

This branch includes the following new commits:

     new 16b6833255 fix: preserve input strictness in `from_unixtime` (#26414)

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org


(datafusion) 01/01: fix: preserve input strictness in `from_unixtime` (#26414)

Posted by gi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-26414-290ad15cc842167ca4d3c0774ccdf3a1d9d61862
in repository https://gitbox.apache.org/repos/asf/datafusion.git

commit 16b683325508d5701a88af906d7aa05c4d76f198
Author: Huaijin <ha...@gmail.com>
AuthorDate: Sun Oct 18 03:37:29 2026 +0000

    fix: preserve input strictness in `from_unixtime` (#26414)
    
    ## Which issue does this PR close?
    
    Found while reviewing #26111; no separate issue. This fix is independent
    of that PR.
    
    ## Rationale for this change
    
    `from_unixtime(CAST(seconds AS BIGINT))` could incorrectly eliminate a
    multi-key sort. Ordered input rows `(seconds, id) = (1.1, 1), (1.9, 0)`
    produce the same timestamp, but the IDs must be reordered to `0, 1`.
    
    ## What changes are included in this PR?
    
    Propagate the first argument's strict ordering property instead of
    unconditionally returning `true`.
    
    ## What is the testing strategy for this PR?
    
    Three compact SQL cases in `datetime/timestamps.slt` check the result
    ordering with and without a timezone, including NULLs, and verify that
    direct integer inputs still avoid an extra sort. The two regression
    cases fail without the fix.
    
    Validated with the targeted SQL test file, all 10 `from_unixtime` unit
    tests, formatting, and `git diff --check`.
    
    ## Are there any user-facing changes?
    
    Yes. Queries with lossy nested inputs to `from_unixtime` retain required
    sorts and return correctly ordered rows.
---
 datafusion/functions/src/datetime/from_unixtime.rs |  8 ++---
 .../test_files/datetime/timestamps.slt             | 41 ++++++++++++++++++++++
 2 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/datafusion/functions/src/datetime/from_unixtime.rs b/datafusion/functions/src/datetime/from_unixtime.rs
index 89a7e807e3..c1914d1f48 100644
--- a/datafusion/functions/src/datetime/from_unixtime.rs
+++ b/datafusion/functions/src/datetime/from_unixtime.rs
@@ -212,11 +212,9 @@ impl ScalarUDFImpl for FromUnixtimeFunc {
         Ok(true)
     }
 
-    fn strictly_order_preserving(&self, _inputs: &[ExprProperties]) -> Result<bool> {
-        // `from_unixtime` stores the input's exact `Int64` value as a
-        // `Timestamp(Second)`: the mapping is one-to-one, order-preserving,
-        // and maps nulls to nulls.
-        Ok(true)
+    fn strictly_order_preserving(&self, inputs: &[ExprProperties]) -> Result<bool> {
+        // A lossless cast cannot restore strictness lost by its input.
+        Ok(inputs[0].strictly_order_preserving)
     }
 
     fn documentation(&self) -> Option<&Documentation> {
diff --git a/datafusion/sqllogictest/test_files/datetime/timestamps.slt b/datafusion/sqllogictest/test_files/datetime/timestamps.slt
index 162846779a..a0f4af894a 100644
--- a/datafusion/sqllogictest/test_files/datetime/timestamps.slt
+++ b/datafusion/sqllogictest/test_files/datetime/timestamps.slt
@@ -460,6 +460,47 @@ SELECT from_unixtime(ts / 1000000000, 'UTC') FROM ts_data LIMIT 3;
 2020-09-08T12:42:29Z
 2020-09-08T11:42:29Z
 
+# LIMIT makes the inner sort necessary; the lossy cast creates tied seconds.
+statement ok
+CREATE VIEW fractional_epochs AS
+SELECT * FROM (VALUES (1.1::DOUBLE, 1), (1.9, 0), (NULL, 2), (2.1, 3)) AS v(seconds, id)
+ORDER BY seconds ASC NULLS FIRST, id LIMIT 3;
+
+query PI
+SELECT from_unixtime(CAST(seconds AS BIGINT)) AS t, id
+FROM fractional_epochs ORDER BY t ASC NULLS FIRST, id;
+----
+NULL 2
+1970-01-01T00:00:01 0
+1970-01-01T00:00:01 1
+
+query PI
+SELECT from_unixtime(CAST(seconds AS BIGINT), 'UTC') AS t, id
+FROM fractional_epochs ORDER BY t ASC NULLS FIRST, id;
+----
+NULL 2
+1970-01-01T00:00:01Z 0
+1970-01-01T00:00:01Z 1
+
+statement ok
+SET datafusion.explain.physical_plan_only = true;
+
+# A direct integer input still preserves the ordering of subsequent keys.
+query TT
+EXPLAIN SELECT from_unixtime(seconds, 'UTC') AS t, id
+FROM (
+  SELECT * FROM (VALUES (1::BIGINT, 1), (2, 0), (3, 2)) AS v(seconds, id)
+  ORDER BY seconds, id LIMIT 2
+) ORDER BY t, id;
+----
+physical_plan
+01)ProjectionExec: expr=[from_unixtime(column1@0, UTC) as t, column2@1 as id]
+02)--SortExec: TopK(fetch=2), expr=[column1@0 ASC NULLS LAST, column2@1 ASC NULLS LAST], preserve_partitioning=[false]
+03)----DataSourceExec: partitions=1, partition_sizes=[1]
+
+statement ok
+RESET datafusion.explain.physical_plan_only;
+
 # to_timestamp
 
 query I


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org