Skip to content

fix: equalize with delta/delta-rs (v0.52) - #55

Open
mandrush wants to merge 645 commits into
relativityone:mainfrom
delta-io:main
Open

fix: equalize with delta/delta-rs (v0.52)#55
mandrush wants to merge 645 commits into
relativityone:mainfrom
delta-io:main

Conversation

@mandrush

Copy link
Copy Markdown
Collaborator

Description

The description of the main changes of your pull request

Related Issue(s)

Documentation

@github-actions github-actions Bot added binding/python binding/rust delta-inspect documentation Improvements or additions to documentation labels Feb 17, 2026
adampolomski
adampolomski previously approved these changes Feb 17, 2026
rtyler and others added 14 commits May 16, 2026 20:44
Signed-off-by: R. Tyler Croy <rtyler@brokenco.de>
This test doesn't really perform a useful check. The reader being
_capable_ of reading DeletionVectors and ColumnMapping is not tied to
the features on the table per se

Signed-off-by: R. Tyler Croy <rtyler@brokenco.de>
Based on my read of the dioscussion
[here](delta-io/delta-kernel-rs#2267) the
id ordering assertion made by this test was not correct and should just
be removed

Signed-off-by: R. Tyler Croy <rtyler@brokenco.de>
Variant support was initially introduced in
[21.0.0](https://arrow.apache.org/release/21.0.0.html) released in July
2025. Lower versions simply won't work with variant types

IMHO it's not worth trying to maintain compatibility with older pyarrow
and carving out a bunch of conditional logic for variant

Signed-off-by: R. Tyler Croy <rtyler@brokenco.de>
Signed-off-by: R. Tyler Croy <rtyler@brokenco.de>
Signed-off-by: R. Tyler Croy <rtyler@brokenco.de>
Signed-off-by: R. Tyler Croy <rtyler@brokenco.de>
Signed-off-by: R. Tyler Croy <rtyler@brokenco.de>
…cuuming

Closes #3896

Signed-off-by: R. Tyler Croy <rtyler@brokenco.de>
Closes #4468

Signed-off-by: R. Tyler Croy <rtyler@brokenco.de>
Skip child pushdown adaptation for filters that reference columns materialized by DeltaScanExec rather than present in the Parquet child schema. This preserves correctness for join dynamic filters while retaining Parquet pushdown for native child columns.

Refs #4467

Signed-off-by: Ethan Urbanski <ethan@urbanskitech.com>
Signed-off-by: Ethan Urbanski <ethan@urbanskitech.com>
Signed-off-by: Ethan Urbanski <ethan@urbanskitech.com>
This is largely a port of the regression test in #3172, with a little
human intelligence added in 😄

Signed-off-by: R Tyler Croy <rtyler@brokenco.de>
ethan-tyler and others added 30 commits August 26, 2026 05:32
Signed-off-by: Ethan Urbanski <ethan@urbanskitech.com>
…park

This is mostly to prove to myself the behavior of append writes to a
table which is also being optimized by Apache Spark. I don't fully trust
these tests even though they logically make sense and demonstrate the
behavior I was expecting.

I feel like there _must_ be some possible race condition with a
distributed system like S3 but because the Rust side of the equation
will always use conditional puts, I _think_ that ensures safey in a
multi-write system where a Rust process is appending and a Spark process
is optimizing.

I **don't** think this would be safe if there were multiple Spark
writers running concurrently however.

References #4482

Co-Authored-By: Devstral 2 <vibe@mistral.ai>
Signed-off-by: R. Tyler Croy <rtyler@brokenco.de>
…right jobs

Signed-off-by: R. Tyler Croy <rtyler@brokenco.de>
DeltaTable.scan(columns, predicate) returns an arro3 RecordBatchReader
backed by the kernel DataFusion provider, reusing the QueryBuilder
session setup and the DataFrame API with no SQL string assembly. The
predicate is a row filter executed by the engine, unlike the listing
APIs' file_pruning_predicate which only skips whole files. Works on
column-mapped and deletion-vector tables.

Signed-off-by: Frank Portman <frank1214@gmail.com>
Adds a scan section to the querying usage page and notes in both the
guide and the docstring that the predicate follows DataFusion SQL
semantics (three-valued NULL logic, SQL type coercion), which differ
from pyarrow dataset filters in edge cases.

Signed-off-by: Frank Portman <frank1214@gmail.com>
Review nit on #4675: DataFusion SQL, generic dialect, identifier
normalization disabled per DeltaParserOptions, so unquoted column names
match case sensitively.

Signed-off-by: Frank Portman <frank1214@gmail.com>
Signed-off-by: Frank Portman <frank1214@gmail.com>
… methods

On to_pandas and to_pyarrow_table, filters already prunes files: each
dataset fragment carries partition values and min/max statistics as a
guarantee expression, so files that cannot match are skipped before any
data is read, then rows filter exactly. A pruning parameter there is a
second way to pass the same tuples with weaker semantics. It stays where
nothing else can do the job: file_uris, partitions, to_pyarrow_dataset.

The parameter landed in #4585 and has not been released, so this is not
a breaking change. It is one only if it waits past the next release.

Follow up to #4585.

Signed-off-by: Frank Portman <frank1214@gmail.com>
The warning told users to pass file_pruning_predicate, which this change
removes from these two methods. The dataframe methods now warn with the
replacement that exists there and route the legacy value through the
dataset parameter that still accepts it.

Signed-off-by: Frank Portman <frank1214@gmail.com>
The dataframe methods are thin wrappers over to_pyarrow_dataset; showing
the equivalent unrolled chain makes it apparent where pre-scan pruning
via file_pruning_predicate slots in, which can matter on tables with
very large file counts.

Signed-off-by: Frank Portman <frank1214@gmail.com>
A row group cannot span files, so when target_file_size is reached the
PartitionWriter closes the file with whatever partial row group is
buffered, truncating every file's last group wherever the byte target
happens to land. Readers that map one Parquet row group to one
in-memory segment degrade on those runt tail groups.

With DELTARS_ROLL_ON_ROW_GROUP_BOUNDARY=1 (or
PartitionWriterConfig::with_roll_on_row_group_boundary), the roll
defers until the open row group completes: slices are aligned so they
never straddle a group boundary, and the byte check only fires when
the writer sits exactly on one. Every row group is then exactly
max_row_group_row_count rows -- the single end-of-data remainder at
close is the only exception -- and a file may overshoot
target_file_size by up to one row group. Only effective when row
groups are bounded by row count alone; byte-bounded groups keep the
legacy roll. Default off: existing behavior (including
test_unflushed_row_group_size) is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: djouallah <djouallah@users.noreply.github.com>
…nating

Address review comments on #4677:
- PartitionWriterConfig::try_new now errors on write_batch_size = 0, which
  would otherwise spin the write loop forever (previously step_by panicked).
- The roll-on-row-group-boundary test now writes 700-row batches so slices
  straddle the 1024-row group boundary, and asserts as a negative control
  that the plain byte roll truncates groups under the same setup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: djouallah <djouallah@users.noreply.github.com>
Signed-off-by: Adam Reeve <adam.reeve@gr-oss.io>
Signed-off-by: Adam Reeve <adam.reeve@gr-oss.io>
Signed-off-by: Ethan Urbanski <ethan@urbanskitech.com>
Signed-off-by: Ethan Urbanski <ethan@urbanskitech.com>
Signed-off-by: Ethan Urbanski <ethan@urbanskitech.com>
Signed-off-by: Ethan Urbanski <ethan@urbanskitech.com>
When deletion vectors are present the inner parquet plan's row counts do
not account for deleted rows; an exact num_rows lets DataFusion's
AggregateStatistics optimizer short-circuit COUNT(*) with inflated
counts. Ported from Nordalf/delta-rs (original: 6b523d7) onto the
statistics_from_inputs contract.

Signed-off-by: Alexander Falk <alexfalk7@gmail.com>
…tables

While cleaning up logging in delta-kernel-rs I decided to point the
:parrot: at our codebase for log statements that might produce excess
log lines when working with larger tables.

Any log statement which may result in a debug print of a `Snapshot`
runs the risk of printing a `Debug` representation of the entire
reconciled transaction log v_v

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: R Tyler Croy <rtyler@scribd.com>
Verify FSCK behavior for physical paths containing spaces and literal percent
sequences, including dry runs, Remove encoding, and snapshot replay.

Exercise restore_file_key through Snapshot with valid deletion vectors and
distinct offsets. Replace the invalid inline offset fixture and duplicated
formatter assertion.

Follow up to #4684.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: R Tyler Croy <rtyler@scribd.com>
Signed-off-by: Ethan Urbanski <ethan@urbanskitech.com>
Updates the requirements on [brotli-decompressor](https://github.com/dropbox/rust-brotli-decompressor) to permit the latest version.
- [Commits](dropbox/rust-brotli-decompressor@5.0.1...6.0.0)

---
updated-dependencies:
- dependency-name: brotli-decompressor
  dependency-version: 6.0.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
# Description
Right now, there are several duplicated read and write paths for
creating parquet files within delta-rs. The purpose of this PR is to
consolidate these paths behind a more abstract interface in two parts:
1. A basic interface that needs only the parquet library.
2. An extended interface using datafusion and supporting advanced
features such as predicates and projections.

There are a few reasons for doing this:
1. Code maintenance. Having (mostly) a single path for reads and writes
helps reduce maintenance and makes it easier to control behavior around
how underlying reads and writes are handled.
2. Consolidating these paths makes it a lot easier to attach advanced
parquet properties to reads and writes. Examples would include future
encryption support and content defined chunking as discussed in
#4465
3. I believe that having the simplified read and write paths will also
help with delta-rs kernel integration.

This PR follows from the ideas discussed at the deltabricks summit and
the slack channel at:
https://delta-users.slack.com/archives/C013LCAEB98/p1781571891482589


AI notes: This PR was created with (and reviewed with) the help of AI.
However, the design and individual pieces were reviewed and tested by
me. I believe them to be correct and an improvement to the project.

## Behavior changes in the legacy writers

The `JsonWriter`/`RecordBatchWriter` rewrite (now streaming through the
consolidated write path) intentionally changes a few observable
behaviors — flagging them explicitly for reviewers:

1. **All-or-nothing flush windows.** Batches stream to storage as they
are written, and a flush window commits atomically: an IO error on any
write discards *every* batch buffered since the last flush (the aborted
uploads are invisible to vacuum; finalized files are left for vacuum).
The old writers buffered in memory and lost only the failing batch.
Documented on both writers.
2. **`JsonWriter` no longer quarantines bad records.** A write
containing malformed JSON records now rejects the whole call and writes
nothing, instead of writing the good records and returning
`PartialParquetWrite` with the skipped values. (The error enum was
already crate-private, so this is a behavior change, not an API break.)
3. **`write_partition` + `MergeSchema`:** unpartitioned widening now
updates the writer's schema, and a later `flush_and_commit` commits the
metadata evolution; widening on a partitioned table is rejected (fixes
the class of bug in #3783 where files could carry columns absent from
table metadata).
4. **Counter semantics:** `buffered_record_batch_count` counts write
calls (previously one per partition touched per call), and `buffer_len`
approximates encoded parquet size written this window (previously
in-memory buffer bytes). Documented on the methods.

---------

Signed-off-by: Corwin Joy <corwin.joy@gmail.com>
Signed-off-by: R. Tyler Croy <rtyler@brokenco.de>
Signed-off-by: R Tyler Croy <rtyler@scribd.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: R. Tyler Croy <rtyler@brokenco.de>
Co-authored-by: R Tyler Croy <rtyler@scribd.com>
Signed-off-by: Ethan Urbanski <ethan@urbanskitech.com>
Signed-off-by: Ethan Urbanski <ethan@urbanskitech.com>
Remove the stale selection_vectors reference introduced by the main merge; map_statistics already makes deletion-vector statistics inexact. Rename the absent DV state to NotPresent, restore DashMap in the replay helper, and document the per-execution mask copy.

Signed-off-by: Ethan Urbanski <ethan@urbanskitech.com>
Signed-off-by: Ethan Urbanski <ethan@urbanskitech.com>
Signed-off-by: Adam Reeve <adam.reeve@gr-oss.io>
Signed-off-by: Adam Reeve <adam.reeve@gr-oss.io>
Signed-off-by: Ion Koutsouris <15728914+ion-elgreco@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.