[DATA-2616] Disallow non-deterministic ingestion transforms#18932
[DATA-2616] Disallow non-deterministic ingestion transforms#18932xiangfu0 wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR tightens ingestion-time transform validation by rejecting non-deterministic scalar functions (e.g., now(), ago(), rand() without seed) when building/validating ingestion transform evaluators, while keeping the existing default (non-ingestion) expression evaluator behavior permissive. It also marks now()/ago()/agoMV() as non-deterministic so they are no longer eligible for compile-time evaluation and will fail fast in ingestion contexts.
Changes:
- Add a “deterministic-only” evaluator mode (
FunctionEvaluatorFactory.getDeterministicExpressionEvaluator(...)) and enforce it for ingestion transforms (table ingestion transforms, schema transform functions during ingestion, default-column derived column creation, and expression transformer construction). - Mark time-based functions (
now(),ago(),agoMV()) as non-deterministic via@ScalarFunction(isDeterministic = false), and rely on determinism metadata (FunctionInfo#isDeterministic) for both compile-time folding and deterministic-only evaluation. - Expand/adjust unit tests to validate determinism behavior and updated SQL compilation outcomes.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| pinot-segment-local/src/test/java/org/apache/pinot/segment/local/utils/TableConfigUtilsTest.java | Adds assertions that ingestion and post-partial-upsert transforms reject non-deterministic functions. |
| pinot-segment-local/src/test/java/org/apache/pinot/segment/local/utils/SchemaUtilsTest.java | Adds schema validation tests ensuring non-deterministic schema transform functions are rejected. |
| pinot-segment-local/src/test/java/org/apache/pinot/segment/local/recordtransformer/ExpressionTransformerTest.java | Verifies ExpressionTransformer construction fails fast for non-deterministic transform functions. |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/TableConfigUtils.java | Switches ingestion transform validation to deterministic-only expression evaluator. |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/SchemaUtils.java | Uses deterministic-only evaluator when validating schema transform functions’ arguments. |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/loader/defaultcolumn/BaseDefaultColumnHandler.java | Ensures derived-column transforms used during segment loading are deterministic-only. |
| pinot-segment-local/src/main/java/org/apache/pinot/segment/local/recordtransformer/ExpressionTransformer.java | Builds ingestion transform evaluators using deterministic-only evaluation. |
| pinot-core/src/test/java/org/apache/pinot/core/function/FunctionRegistryTest.java | Adds determinism assertions for now, ago, and rand overloads. |
| pinot-common/src/test/java/org/apache/pinot/sql/parsers/CalciteSqlCompilerTest.java | Updates SQL compiler expectations so non-deterministic functions are not folded into literals. |
| pinot-common/src/test/java/org/apache/pinot/common/evaluator/InbuiltFunctionEvaluatorTest.java | Tests deterministic-only mode rejection of non-deterministic functions (including nested usage). |
| pinot-common/src/main/java/org/apache/pinot/common/function/scalar/DateTimeFunctions.java | Marks now, ago, agoMV as non-deterministic via annotation metadata. |
| pinot-common/src/main/java/org/apache/pinot/common/evaluator/InbuiltFunctionEvaluator.java | Adds deterministic-only enforcement using FunctionInfo.isDeterministic(). |
| pinot-common/src/main/java/org/apache/pinot/common/evaluator/FunctionEvaluatorFactory.java | Adds deterministic-only factory methods and threads the “allowNonDeterministic” flag into evaluator construction. |
6a548a3 to
e35c9d9
Compare
Jackie-Jiang
left a comment
There was a problem hiding this comment.
This will break existing tables right?
Should we just reject non-deterministic functions during table config validation?
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #18932 +/- ##
=========================================
Coverage 64.98% 64.99%
+ Complexity 1398 1392 -6
=========================================
Files 3399 3399
Lines 212770 212815 +45
Branches 33558 33566 +8
=========================================
+ Hits 138274 138322 +48
+ Misses 63363 63357 -6
- Partials 11133 11136 +3
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:
|
e35c9d9 to
c8da017
Compare
xiangfu0
left a comment
There was a problem hiding this comment.
Found one high-confidence compatibility issue; see inline comment.
c8da017 to
0485e90
Compare
|
Updated per review: the PR now rejects non-deterministic functions only for new or changed ingestion I also removed the For the runtime compatibility test feedback, I renamed the test to make the legacy-compatibility scope explicit and added a 1s wall-clock tolerance. |
0485e90 to
e3f611d
Compare
xiangfu0
left a comment
There was a problem hiding this comment.
Found one high-confidence compatibility issue; see inline comment.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
pinot-segment-local/src/main/java/org/apache/pinot/segment/local/utils/TableConfigUtils.java:732
getDeterministicExpressionEvaluator()can throw for both syntactically invalid expressions and for disallowed non-deterministic functions. Wrapping both cases under "Invalid transform function" is misleading for the non-deterministic rejection path and makes it harder to understand why a previously-valid expression is now rejected.
} catch (Exception e) {
throw new IllegalStateException(
"Invalid transform function '" + transformFunction + "' for column '" + columnName + "', exception: "
+ e.getMessage(), e);
79816a2 to
7bc1145
Compare
Reject non-deterministic built-in functions during table config validation for new or changed ingestion transform configs and post-partial-upsert transform configs. Keep runtime expression evaluation permissive, and allow unchanged legacy transform configs during table updates so existing tables continue ingesting and can receive unrelated config edits.
7bc1145 to
65a9fd1
Compare
Summary
Tests