This is an automated email from the ASF dual-hosted git repository.
yihua pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hudi-rs.git
The following commit(s) were added to refs/heads/main by this push:
new c7e3f033 test(core): cover event-time ordering losing in the gold
corpus (#680)
c7e3f033 is described below
commit c7e3f033cc564c42495737a63892f2f190cd671f
Author: Lin Liu <[email protected]>
AuthorDate: Tue Sep 1 16:52:48 2026 -0700
test(core): cover event-time ordering losing in the gold corpus (#680)
---
crates/core/tests/gold_parity_tests.rs | 1 +
.../mor/avro/table_event_time_stale.sql | 69 +++++++++++++++++++++
.../mor/avro/table_event_time_stale.zip | Bin 0 -> 37278 bytes
crates/test/src/lib.rs | 19 ++++++
4 files changed, 89 insertions(+)
diff --git a/crates/core/tests/gold_parity_tests.rs
b/crates/core/tests/gold_parity_tests.rs
index 7a7007fa..a1f4dfd7 100644
--- a/crates/core/tests/gold_parity_tests.rs
+++ b/crates/core/tests/gold_parity_tests.rs
@@ -107,6 +107,7 @@ const EXPECTED_OPTION_FIXTURES: &[&str] = &[
"table_delete_ord_long [MorAvro]",
"table_delete_ord_string [MorAvro]",
"table_delete_ord_timestamp [MorAvro]",
+ "table_event_time_stale [MorAvro]",
"table_evo_add_col [MorAvro]",
"table_evo_promotion [MorAvro]",
"table_log_compaction [MorAvro]",
diff --git
a/crates/test/data/quickstart_trips_table/mor/avro/table_event_time_stale.sql
b/crates/test/data/quickstart_trips_table/mor/avro/table_event_time_stale.sql
new file mode 100644
index 00000000..0c27b464
--- /dev/null
+++
b/crates/test/data/quickstart_trips_table/mor/avro/table_event_time_stale.sql
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+-- Event-time ordering where a log update LOSES to the base row.
+--
+-- Generated with Spark 3.5.3 and Hudi 1.2.0-SNAPSHOT. gold_data is
+-- `spark.read.format("hudi").load(<table>)` written as one parquet file beside
+-- the table directory; gold_options comes from `gold_options.scala`.
+
+CREATE TABLE table_event_time_stale (
+ ts BIGINT,
+ uuid STRING,
+ rider STRING,
+ fare DOUBLE
+) USING HUDI
+TBLPROPERTIES (
+ type = 'mor',
+ primaryKey = 'uuid',
+ preCombineField = 'ts',
+ 'hoodie.write.table.version' = '9',
+ 'hoodie.record.merge.mode' = 'EVENT_TIME_ORDERING',
+ 'hoodie.metadata.enable' = 'false',
+ 'hoodie.parquet.small.file.limit' = '0',
+ 'hoodie.compact.inline' = 'false'
+)
+LOCATION 'FIXTURE_LOCATION';
+
+INSERT INTO table_event_time_stale VALUES
+ (100, 'a', 'rider-A', 10.0),
+ (100, 'b', 'rider-B', 20.0),
+ (100, 'c', 'rider-C', 30.0),
+ (100, 'd', 'rider-D', 40.0);
+
+-- Ordering value BELOW the base row: the base row must survive this update.
+UPDATE table_event_time_stale SET fare = 99.0, rider = 'stale-A', ts = 50
WHERE uuid = 'a';
+
+-- Ordering value ABOVE the base row: this update must win. Present so that
+-- inverting the comparison fails the fixture rather than passing it.
+UPDATE table_event_time_stale SET fare = 22.0, rider = 'fresh-B', ts = 200
WHERE uuid = 'b';
+
+-- A delete record carries the ordering value of the source row it matched, so
+-- MERGE INTO is what puts a delete BELOW the live row. This one is stale and
+-- the row survives it.
+MERGE INTO table_event_time_stale AS t
+USING (SELECT 'c' AS uuid, 50L AS ts, 'zz' AS rider, 0.0 AS fare) AS s
+ON t.uuid = s.uuid
+WHEN MATCHED THEN DELETE;
+
+-- The same shape above the live row: this delete applies.
+MERGE INTO table_event_time_stale AS t
+USING (SELECT 'd' AS uuid, 300L AS ts, 'zz' AS rider, 0.0 AS fare) AS s
+ON t.uuid = s.uuid
+WHEN MATCHED THEN DELETE;
diff --git
a/crates/test/data/quickstart_trips_table/mor/avro/table_event_time_stale.zip
b/crates/test/data/quickstart_trips_table/mor/avro/table_event_time_stale.zip
new file mode 100644
index 00000000..2411910a
Binary files /dev/null and
b/crates/test/data/quickstart_trips_table/mor/avro/table_event_time_stale.zip
differ
diff --git a/crates/test/src/lib.rs b/crates/test/src/lib.rs
index 2388a7bc..21d4116c 100644
--- a/crates/test/src/lib.rs
+++ b/crates/test/src/lib.rs
@@ -309,6 +309,25 @@ pub enum QuickstartTripsTable {
/// `hoodie.merge.use.record.positions=true`.
#[strum(serialize = "table_duplicate_keys")]
MorLayoutDuplicateKeys,
+ /// v9 MOR non-partitioned, EVENT_TIME_ORDERING, where a log update and a
+ /// delete each LOSE to the live row on ordering value.
+ ///
+ /// Provenance: `table_event_time_stale.sql` beside this zip
+ /// (Spark 3.5.3 / Hudi 1.2.0-SNAPSHOT).
+ /// Schema: ts LONG, uuid STRING, rider STRING, fare DOUBLE
(non-partitioned).
+ /// Layout: base .parquet (4 rows, all at ts 100) + one log file per write:
+ /// `a` updated at ts 50, `b` updated at ts 200, `c` deleted at ts 50,
+ /// `d` deleted at ts 300.
+ /// Semantics: `a` keeps the base row and `c` survives its delete, both
+ /// because the log side's ordering value sits below the live row; `b`
takes
+ /// its update and `d` is removed, because theirs sit above. Everywhere
else
+ /// the corpus only ever writes at or above the live ordering value, so
+ /// nothing else in it notices if event-time ordering degrades to
+ /// last-writer-wins. Both directions of both shapes live in this one
+ /// fixture, so inverting a comparison does not pass either.
+ /// gold_data = Spark `SELECT *` snapshot, 3 rows.
+ #[strum(serialize = "table_event_time_stale")]
+ MorEventTimeStale,
//
-------------------------------------------------------------------------
// Delete-block orderingVal wrapper-type fixtures (Task 7).