Add end-to-end Parquet VARIANT support - #19101
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #19101 +/- ##
============================================
+ Coverage 65.60% 65.82% +0.21%
- Complexity 1423 1496 +73
============================================
Files 3450 3464 +14
Lines 218378 220337 +1959
Branches 34670 35015 +345
============================================
+ Hits 143275 145028 +1753
+ Misses 63538 63537 -1
- Partials 11565 11772 +207
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
3e4dc18 to
acfba94
Compare
acfba94 to
ca98faf
Compare
Introduce the VARIANT logical type and envelope, Parquet reconstruction, scalar and transform functions, and segment and query validation across the single-stage and multi-stage engines. Propagate VARIANT through schemas, wire formats, responses, clients, DDL, quickstart, and integration coverage while rejecting raw operations that require ordering, equality, or hashing.
Allow SQL NULL literals to participate in comparison validation without being classified as raw VARIANT values. Keep equality and DISTINCT FROM behavior aligned in the single-stage transform layer and the multi-stage filter operand, with regression coverage for both engines.
Exercise new-broker/old-server, mixed-server, and old-broker/new-server compatibility, including deterministic handling of the VARIANT wire type before server upgrade and rejection of partial mixed-fleet results. Centralize join-key validation, clarify reusable extraction ownership, and strengthen scalar, null-placeholder, window, and end-to-end coverage.
ca98faf to
b1a2872
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds end-to-end support for the VARIANT logical type across Pinot ingestion (notably Parquet VARIANT(1)), query planning/execution (single-stage + multi-stage), response encoders, and Java/JDBC client surfaces, while explicitly rejecting unsupported raw-VARIANT operations (e.g., ordering/grouping/join keys) with actionable errors.
Changes:
- Introduces
VARIANTas a first-class Pinot data type, including schema/DDL handling, wire/proto support, and null-sentinel semantics. - Adds Parquet
VARIANT(1)ingestion support via the native Parquet reader and includes a packaged “variant batch” quickstart with resources and CI coverage. - Adds query-time VARIANT functions (parse/get/existence/type/json rendering) and enforces operator-level restrictions where raw VARIANT lacks equality/hash/ordering semantics.
Reviewed changes
Copilot reviewed 174 out of 175 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| pom.xml | Adds managed dependency for org.apache.parquet:parquet-variant. |
| pinot-tools/src/test/java/org/apache/pinot/tools/admin/command/QuickStartTest.java | Maps new quickstart command strings to VariantQuickStart. |
| pinot-tools/src/main/resources/examples/batch/variantEvents/* | Adds VARIANT batch quickstart schema/table config, ingestion spec, and documentation. |
| pinot-tools/pom.xml | Adds packaged quick-start-variant-batch program entry. |
| pinot-sql-ddl/src/main/, src/test/ | Adds DDL compile/reverse/roundtrip support for VARIANT and validates default emission rules. |
| pinot-spi/src/main/, src/test/ | Adds PinotDataType.VARIANT conversion/ingestion mapping and schema validation updates. |
| pinot-segment-spi/src/main/** | Handles VARIANT default-null sentinel persisted as empty string in segment metadata. |
| pinot-segment-local/src/main/, src/test/ | Adds VARIANT validation/sanitization rules; disables min/max, ordering, dictionary creation where unsupported; adds targeted tests. |
| pinot-query-planner/src/main/, src/test/ | Adds VARIANT type mapping (Calcite/plan nodes), plan validation, constant-folding guardrails, and serde coverage. |
| pinot-query-runtime/src/main/, src/test/ | Enforces VARIANT restrictions at runtime operators (sort/window/set/group-by/etc.) and adds operator tests. |
| pinot-core/src/main/, src/test/ | Enforces VARIANT restrictions in single-stage operators/aggregations/distinct/order-by and adds tests. |
| pinot-common/src/main/, src/test/ | Adds VARIANT to encoders, datablock equality, proto enum, function canonicalization, and introduces scalar VariantFunctions. |
| pinot-clients/pinot-jdbc-client/src/main/, src/test/ | Treats VARIANT as canonical JSON text (VARCHAR) while preserving encoded-variant-null vs SQL-null behavior. |
| pinot-clients/pinot-java-client/src/main/, src/test/ | Preserves legacy getString() null behavior while distinguishing VARIANT nulls. |
| pinot-plugins/pinot-input-format/pinot-parquet/src/main/** | Enhances Parquet reader selection/metadata helpers and initializes native reader with schema-bound converters for VARIANT. |
| pinot-controller/src/main/, src/test/ | Ensures stored-vs-compiled schema default comparisons handle VARIANT byte[] defaults by content. |
| pinot-compatibility-verifier/** | Adds file-contains operation and VARIANT mixed-version suite coverage including old-broker/new-servers phase. |
| .github/workflows/scripts/.pinot_quickstart.sh | Adds CI validation for the packaged VARIANT batch quickstart. |
| for (int i = 0; i < groupKeyIds.length; i++) { | ||
| ColumnDataType dataType = resultSchema.getColumnDataType(i); | ||
| if (!dataType.supportsEquality() || !dataType.supportsHashing()) { | ||
| throw new IllegalArgumentException( | ||
| "Raw VARIANT values do not support GROUP BY; extract a typed path with variantGet first"); | ||
| } | ||
| } |
Summary
Add an end-to-end
VARIANTuser journey for Apache Pinot:VARIANTdimension retained in Pinot's raw forward indexVARIANT(1)values from unshredded and shredded filesRaw Variant values are deliberately opaque to operations that require equality, hashing, or ordering. Queries must extract a typed scalar before comparing, grouping, joining, sorting, using set operations, or applying general aggregates.
COUNT(raw_variant)remains supported.The persisted format, null semantics, ownership boundaries, and rollout contract are documented in
pinot-spi/VARIANT_DESIGN.md.End-to-end flow
Define a table column with
"dataType": "VARIANT", storage null handling enabled, dictionary disabled, and a raw forward index. The native Parquet reader reconstructsVARIANT(1)metadata/value pairs—including supported shredded layouts—into Pinot's versionedPVARenvelope.Frequently queried fields can be materialized with ingestion transforms while the full Variant remains available:
Supported scope
VARIANT(1)columnsVARIANTdimensions without dictionariesSET enableNullHandling=trueNested/repeated Variant columns, streaming ingestion, and quoted path keys are outside the initial scope.
A JSON index is intentionally not accepted on a
VARIANTcolumn. The existing JSON index expects Pinot JSON text and its query rewrite semantics; treating the binaryPVARenvelope as JSON would be incorrect. Indexing Variant paths should be introduced separately with an explicit physical/index contract. Materialized scalar columns are the supported indexed path for this PR.The automatic Parquet reader selection preserves existing Avro-metadata precedence. Files containing Avro metadata must explicitly select the native Parquet reader to ingest Variant.
Production safety
PVARframing and validation inVariantEnvelopeand freezes version-1 bytes with golden tests24to Variant while preserving UUID/UUID_ARRAY at22/23"null", missing paths, and conversion failures across query and client response formatsRolling upgrades
Variant remains an explicit full-fleet activation feature: upgrade controllers, brokers, servers, clients, and external ingestion jobs before registering a Variant schema, and do not roll back while Variant tables are active.
Compatibility coverage verifies:
Quickstart
The quickstart registers
variantEvents, ingests the committed five-row Parquet fixture, uploads the segment, and runs materialized-field, nested-extraction, JSON-rendering, and null-semantics queries. Its resources live underpinot-tools/src/main/resources/examples/batch/variantEvents.Verification
VariantTypeTestscenarios across both query engines in the full integration-test reactorupstream/mastergit diff --checkThe JSON-versus-Variant performance harness and workstation measurements are intentionally excluded from this feature PR and will be proposed separately so the production API and compatibility contract can be reviewed without benchmark-suite scope.
Review areas
This PR changes public SPI and query-wire behavior. The main ownership reviews are: