Allow non-immutable ingestion transforms for offline tables - #19244
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request relaxes validation for table-level ingestion transforms so that OFFLINE tables may use registered scalar functions across all volatility categories, while keeping REALTIME ingestion transforms restricted to IMMUTABLE functions (with legacy/grandfathering behavior preserved for unchanged existing configs).
Changes:
- Skip ingestion-transform volatility validation for
TableType.OFFLINEwhile retaining it forTableType.REALTIME. - Update SPI documentation strings/comments to describe the updated volatility policy and its implications.
- Expand/adjust unit and REST-layer tests to cover: OFFLINE non-immutable transforms allowed, REALTIME rejection + grandfathering, and offline-upsert comparison-column transform usage.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| pinot-spi/src/main/java/org/apache/pinot/spi/config/table/ingestion/IngestionConfig.java | Updates the JSON property description for transformConfigs to document OFFLINE vs REALTIME volatility policy and instability risks. |
| pinot-spi/src/main/java/org/apache/pinot/spi/annotations/ScalarFunction.java | Updates @ScalarFunction volatility documentation to reflect context-specific (OFFLINE vs REALTIME) transform policies. |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/TableConfigUtils.java | Changes validation so only REALTIME table-level ingestion transforms enforce IMMUTABLE volatility. |
| pinot-segment-local/src/test/java/org/apache/pinot/segment/local/utils/TableConfigUtilsTest.java | Updates/extends validation tests for OFFLINE acceptance, REALTIME rejection + grandfathering, offline-upsert transform validation, and post-partial-upsert volatility checks. |
| pinot-core/src/test/java/org/apache/pinot/core/util/SchemaUtilsTest.java | Adjusts the “grandfather existing non-deterministic transform” test to model REALTIME behavior post-policy change. |
| pinot-controller/src/test/java/org/apache/pinot/controller/api/TableConfigsRestletResourceTest.java | Updates REST tests to model legacy REALTIME transform grandfathering and adds OFFLINE non-immutable create/update coverage. |
| pinot-controller/src/test/java/org/apache/pinot/controller/api/PinotTableRestletResourceTest.java | Updates REST API tests to allow OFFLINE non-immutable transforms and keep REALTIME behavior unchanged (reject + legacy update path). |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #19244 +/- ##
============================================
+ Coverage 66.94% 66.96% +0.02%
Complexity 1423 1423
============================================
Files 3453 3453
Lines 218858 218868 +10
Branches 34787 34790 +3
============================================
+ Hits 146512 146567 +55
+ Misses 60621 60583 -38
+ Partials 11725 11718 -7
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:
|
Permit all scalar function volatility categories for table-level OFFLINE transform configs while retaining immutable-only validation for REALTIME, schema-level, and post-partial-upsert transforms.
52a541a to
e5d287d
Compare
Documents apache/pinot#19244, which allows OFFLINE table-level ingestion transforms to use registered scalar functions from any volatility category. The update distinguishes OFFLINE and REALTIME validation, preserves the schema-level and post-partial-upsert caveats, and adds an offline-upsert example that generates a missing comparison timestamp with `now()`. Validation: `git diff --check`. Co-authored-by: Xiang Fu <xiangfu@Xiang-mac-mtv-2.local>
|
Documentation follow-up: pinot-contrib/pinot-docs#983 (merged). |
Summary
Allow table-level
ingestionConfig.transformConfigson OFFLINE tables to use registered scalar functions from any volatility category. REALTIME table-level transforms continue to requireIMMUTABLEfunctions.Expression parsing and the existing transform validation remain unchanged. Schema-level transforms and
postPartialUpsertTransformConfigsalso retain their existing volatility checks.Motivation
Some OFFLINE upsert inputs, such as daily partial Parquet drops, do not contain a physical timestamp or row-version column. This lets ingestion populate a declared comparison column with a transform such as
now()without rewriting the input file first.Usage
Declare the generated column in the schema:
{ "dateTimeFieldSpecs": [ { "name": "ingestionTime", "dataType": "LONG", "format": "1:MILLISECONDS:EPOCH", "granularity": "1:MILLISECONDS" } ] }Use it as the OFFLINE upsert comparison column:
{ "upsertConfig": { "mode": "FULL", "comparisonColumns": ["ingestionTime"] }, "ingestionConfig": { "transformConfigs": [ { "columnName": "ingestionTime", "transformFunction": "now()" } ] } }The remaining OFFLINE upsert requirements, including primary-key partitioning and strict replica-group routing, are unchanged.
Scope
This is a validation-policy change only. It does not add a new SPI, segment format, serializer, or execution path. Non-immutable functions retain their existing ingestion execution semantics.
Validation
TableConfigUtilsTestSchemaUtilsTestPinotTableRestletResourceTestTableConfigsRestletResourceTest