Skip to content

feat(java): describe physical batches and writes without a format - #961

Open
keksmd wants to merge 3 commits into
apache:mainfrom
keksmd:java-io-api-values
Open

feat(java): describe physical batches and writes without a format#961
keksmd wants to merge 3 commits into
apache:mainfrom
keksmd:java-io-api-values

Conversation

@keksmd

@keksmd keksmd commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Reason for this PR

Part of #947, tracked by #959. The reader and writer verticals both need one format-neutral description of a physical batch before either can name a file format. Without it, the Parquet backend and the GraphAr reader would each invent their own representation and the two would have to be reconciled later.

What changes are included in this PR?

A new dependency-light graphar-io-api module holding a columnar physical-batch description plus the write half of the physical IO boundary:

  • ColumnType, Field, Schema — recursive Arrow-shaped schema descriptions. Nested LIST, FIXED_SIZE_LIST, STRUCT, and MAP retain child field names/nullability; fixed binary and decimal parameters are explicit. Duplicate field names are valid because physical access is by position.
  • ValueVector, VectorRecordBatch, BatchCursor — a batch is a schema, same-length vectors, and a row count. VectorRecordBatch rejects mismatched schema fields, vector width, and value counts before publication. It deliberately resembles Arrow's vector access shape without imposing Arrow buffers, allocators, or a transitive runtime dependency.
  • WriteRequest, WriteMode, PhysicalWriter — a URI, a schema, a target disposition, and the writer that drains a cursor. CREATE_NEW, OVERWRITE, and APPEND are explicit.

A format adapter owns vector lifetime and the Java representation returned by ValueVector#getObject. That lets a Parquet or Arrow adapter expose native/lifecycle-bound data when safe, while keeping the base API usable without Arrow.

The read half of the boundary (ReadRequest, projection, filter, row range, capability reporting, PhysicalReader) is deliberately left out and will follow as its own PR against this base.

Are these changes tested?

Yes — 33 tests. They cover value-object equality, indexed duplicate schema fields, recursive nested types, vector/batch structural validation, nullable list elements, vector-based cursor traversal, cursor ownership, schema mismatch, and all three write dispositions against an in-memory reference writer.

mvn --no-transfer-progress -f maven-projects/pom.xml -pl io-api -am verify
Tests run: 33, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS

Are there any user-facing changes?

A new module and package org.apache.graphar.io. Nothing existing changes.

Checklist

  • I have performed a self-review of my own code.
  • I have formatted my own code using make cpplint before submitting when changed files are in the cpp directory.
  • I have performed pre-commit run before commit the changed files.
  • I have added tests to prove my changes are effective.

The reader and writer verticals both need one neutral description of a
row group before either can name a file format. This adds that
description: a recursive column type, a named field, an ordered schema,
a row whose values follow one documented Java mapping, a finite record
batch, and a closeable cursor over batches.

The write half of the physical IO boundary rides along, because it is
the smaller consumer of those types and shares every one of them: a
write request binds a URI, a schema, and a target disposition, and a
physical writer drains a cursor into that target.

The module depends on nothing else in the project, so a format backend
can implement it without inheriting the metadata or storage layers.

Part of apache#947.

Rejected: exposing Arrow as the public batch representation, which
would make every consumer inherit an Arrow runtime for a contract that
only needs row access.

Not-tested: no format backend implements these interfaces yet; the
contract is pinned against an in-memory reference implementation.
Comment thread maven-projects/io-api/src/main/java/org/apache/graphar/io/Schema.java Outdated
Replace the provisional row access shape with a validated vector batch so physical backends can align with Arrow without imposing its runtime on every Java consumer. Preserve indexed duplicate schema fields, model recursive nested shapes, and make append an explicit write disposition.\n\nPart of apache#959.\n\nRejected: making Apache Arrow a mandatory dependency of graphar-io-api.\n\nDirective: format adapters own vector lifetime and Java value representation.\n\nNot-tested: no physical format backend implements this boundary yet.
@keksmd

keksmd commented Aug 23, 2026

Copy link
Copy Markdown
Contributor Author

@SemyonSinchenko Спасибо, поправил все пять пунктов в 5837bd5.

  1. Field теперь value object (equals/hashCode по name/type/nullability).
  2. Schema сохраняет duplicate names: физический доступ только по индексу.
  3. Row удалён: RecordBatch теперь schema + ValueVector-ы + row count, а VectorRecordBatch проверяет field order, width и value count.
  4. ColumnType стал recursive Field-shape: child names/nullability сохраняются для LIST/FIXED_SIZE_LIST/STRUCT/MAP; есть fixed binary и decimal. Так можно расширять Parquet/Arrow shapes, не замораживая плоский enum. Arrow не стал обязательной зависимостью — адаптеры сами владеют native vector lifetime.
  5. Добавил APPEND и контрактный тест с реальным накоплением значений.

Focused verify: 33 tests, 0 failures; spotless и pre-commit также прошли.

Comment thread maven-projects/io-api/src/main/java/org/apache/graphar/io/ColumnType.java Outdated
@SemyonSinchenko

Copy link
Copy Markdown
Member

@keksmd Спасибо! Мне нравится, я оставил пару минорных комментов

@keksmd Thanks! Much better, I left two minor comments.

keksmd added a commit to keksmd/incubator-graphar that referenced this pull request Aug 24, 2026
Complete the core-only ordered-adjacency contract: validate offset chunks, select exact half-open edge chunk ranges, and delegate URI resolution to immutable GraphAr metadata.

Relates to apache#967.

Rejected: reading Parquet offsets in graphar-core; io-parquet remains behind the open apache#961 API change.
Make column-kind classification exhaustive and give immutable schema and write requests value semantics for deduplication and queued write planning.

Relates to apache#961.
@keksmd

keksmd commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

@SemyonSinchenko Спасибо за второй проход — сверил весь набор review-комментариев и поправил оставшиеся два minor пункта в fa967da:

  1. ColumnType.isScalar теперь исчерпывающий switch: новый Kind нельзя молча принять как scalar; unhandled value падает явно.
  2. Добавил value semantics для Schema и WriteRequest (equals/hashCode) и тесты на одинаковые независимые schema/request.

Предыдущие пять замечаний из первого review также остаются закрытыми: value Field, duplicate schema names, vector RecordBatch, recursive Arrow-shaped ColumnType, и APPEND.

Проверка: mvn --no-transfer-progress -q -f maven-projects/pom.xml -pl io-api -am verify — 35 tests, 0 failures; Spotless, pre-commit и git diff --check прошли.

Когда будет минутка, пожалуйста, посмотри ещё раз и, если всё ок, approve.

@SemyonSinchenko SemyonSinchenko left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

~LGTM

@SemyonSinchenko

Copy link
Copy Markdown
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants