Trino version
483
Please describe the bug
Environment
- Trino versions tested:
- 479 - fails consistently
- 482, 483 - fail consistently with join_distribution_type = 'PARTITIONED', often succeed without
- Catalog: Iceberg (JDBC PostgreSQL)
- File format: Parquet, Iceberg format-version 2
- Engine path: dbt-trino or DBeaver
Summary
MERGE into a Partitioned Iceberg table fails with a false positive error, when neither the source table nor the target table contain duplicates on the merge key.
One MERGE target table row matched more than one source row
Reproduction
-- 1. Bucket-partitioned Iceberg target, 3,000 rows
CREATE TABLE repro_t WITH (partitioning = ARRAY['bucket(k1, 16)', 'bucket(k2, 8)']) AS
SELECT 'a-' || cast(i AS varchar) AS k1, 'b-' || cast(i AS varchar) AS k2,
'UPDATED' AS a, TIMESTAMP '2026-01-01 00:00:00.000000' AS ts
FROM UNNEST(sequence(1, 3000)) t(i);
-- 2. Source: BOTH row classes are required —
-- 3,000 rows matching target pairs with EQUAL timestamps (blocked by the update guard)
-- + 42,000 unmatched rows with a = 'DELETED' (blocked by the insert condition)
CREATE TABLE repro_s AS
SELECT 'a-' || cast(i AS varchar) AS k1, 'b-' || cast(i AS varchar) AS k2,
'UPDATED' AS a, TIMESTAMP '2026-01-01 00:00:00.000000' AS ts
FROM UNNEST(sequence(1, 3000)) t(i)
UNION ALL
SELECT 'x-' || cast(a.i AS varchar) || '-' || cast(b.j AS varchar),
'y-' || cast(a.i AS varchar) || '-' || cast(b.j AS varchar),
'DELETED', TIMESTAMP '2026-01-02 00:00:00.000000'
FROM UNNEST(sequence(1, 6000)) a(i) CROSS JOIN UNNEST(sequence(1, 7)) b(j);
-- no duplicates
select k1, k2 from repro_s group by k1, k2 having count(*) > 1;
select k1, k2 from repro_t group by k1, k2 having count(*) > 1;
-- 3. Force the flipped merge-join plan (multi-node optimizers pick it unforced)
SET SESSION join_distribution_type = 'PARTITIONED';
-- 4. The merge: every row is blocked by a condition, so the CORRECT result is
-- "MERGE: 0 rows". Instead it fails:
-- "One MERGE target table row matched more than one source row"
MERGE INTO repro_t t USING repro_s s
ON t.k1 = s.k1 AND t.k2 = s.k2
WHEN MATCHED AND s.ts > t.ts THEN UPDATE SET a = s.a, ts = s.ts
WHEN NOT MATCHED AND s.a <> 'DELETED' THEN INSERT (k1, k2, a, ts) VALUES (s.k1, s.k2, s.a, s.ts);
Stack trace (failed run, Trino 483)
io.trino.spi.TrinoException: One MERGE target table row matched more than one source row
at io.trino.operator.scalar.FailureFunction.fail(FailureFunction.java:62)
at io.trino.$gen.PageFilter_20260810_092523_242.filter(Unknown Source)
at io.trino.$gen.PageFilter_20260810_092523_242.filter(Unknown Source)
at io.trino.operator.project.DictionaryAwarePageFilter.filter(DictionaryAwarePageFilter.java:82)
at io.trino.sql.gen.columnar.PageFilterEvaluator.evaluate(PageFilterEvaluator.java:42)
at io.trino.operator.project.PageProcessor.createWorkProcessor(PageProcessor.java:123)
at io.trino.operator.FilterAndProjectOperator.lambda$new$0(FilterAndProjectOperator.java:58)
at io.trino.operator.WorkProcessorUtils.lambda$flatMap$0(WorkProcessorUtils.java:285)
at io.trino.operator.WorkProcessorUtils$3.process(WorkProcessorUtils.java:359)
at io.trino.operator.WorkProcessorUtils$ProcessWorkProcessor.process(WorkProcessorUtils.java:426)
at io.trino.operator.WorkProcessorUtils$3.process(WorkProcessorUtils.java:346)
at io.trino.operator.WorkProcessorUtils$ProcessWorkProcessor.process(WorkProcessorUtils.java:426)
at io.trino.operator.WorkProcessorUtils$3.process(WorkProcessorUtils.java:346)
at io.trino.operator.WorkProcessorUtils$ProcessWorkProcessor.process(WorkProcessorUtils.java:426)
at io.trino.operator.WorkProcessorUtils.getNextState(WorkProcessorUtils.java:261)
at io.trino.operator.WorkProcessorUtils$BlockingProcess.process(WorkProcessorUtils.java:207)
at io.trino.operator.WorkProcessorUtils$ProcessWorkProcessor.process(WorkProcessorUtils.java:426)
at io.trino.operator.WorkProcessorOperatorAdapter.getOutput(WorkProcessorOperatorAdapter.java:139)
at io.trino.operator.Driver.processInternal(Driver.java:403)
at io.trino.operator.Driver.lambda$process$0(Driver.java:306)
at io.trino.operator.Driver.tryWithLock(Driver.java:709)
at io.trino.operator.Driver.process(Driver.java:298)
at io.trino.operator.Driver.processForDuration(Driver.java:269)
at io.trino.execution.SqlTaskExecution$DriverSplitRunner.processFor(SqlTaskExecution.java:852)
at io.trino.execution.executor.dedicated.SplitProcessor.run(SplitProcessor.java:77)
at io.trino.execution.executor.dedicated.TaskEntry$VersionEmbedderBridge.lambda$run$0(TaskEntry.java:205)
at io.trino.$gen.Trino_483____20260810_091753_2.run(Unknown Source)
at io.trino.execution.executor.dedicated.TaskEntry$VersionEmbedderBridge.run(TaskEntry.java:206)
at io.trino.execution.executor.scheduler.FairScheduler.runTask(FairScheduler.java:177)
at io.trino.execution.executor.scheduler.FairScheduler.lambda$submit$0(FairScheduler.java:164)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545)
at com.google.common.util.concurrent.TrustedListenableFutureTask$TrustedFutureInterruptibleTask.runInterruptibly(TrustedListenableFutureTask.java:128)
at com.google.common.util.concurrent.InterruptibleTask.run(InterruptibleTask.java:74)
at com.google.common.util.concurrent.TrustedListenableFutureTask.run(TrustedListenableFutureTask.java:80)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614)
at java.base/java.lang.Thread.run(Thread.java:1474)
20260810_093132_00028_h7f4w.json
MERGE produces duplicate rows in Iceberg table (regression in Trino 477) #26968 is fixed before the Trino version we face an issue on.
Trino version
483
Please describe the bug
Environment
- 479 - fails consistently
- 482, 483 - fail consistently with join_distribution_type = 'PARTITIONED', often succeed without
Summary
MERGE into a Partitioned Iceberg table fails with a false positive error, when neither the source table nor the target table contain duplicates on the merge key.
Reproduction
Stack trace (failed run, Trino 483)
20260810_093132_00028_h7f4w.json
MERGE produces duplicate rows in Iceberg table (regression in Trino 477) #26968 is fixed before the Trino version we face an issue on.