xiangfu0 commented on code in PR #17652:
URL: https://github.com/apache/pinot/pull/17652#discussion_r2776884079


##########
pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/TruncateDecimalTransformFunction.java:
##########
@@ -98,7 +98,8 @@ public double[] transformToDoubleValuesSV(ValueBlock 
valueBlock) {
       }
     } else {
       for (int i = 0; i < length; i++) {
-        _doubleValuesSV[i] = Math.signum(leftValues[i]) * 
Math.floor(Math.abs(leftValues[i]));
+        // Keep behavior consistent with truncate(value, 0), including 
canonical +0.0 for values truncated to zero.
+        _doubleValuesSV[i] = BigDecimal.valueOf(leftValues[i]).setScale(0, 
RoundingMode.DOWN).doubleValue();

Review Comment:
   Good catch. Updated no-scale truncate path to preserve non-finite values 
(`NaN`, `+/-Infinity`) and only apply truncation/zero-normalization for finite 
numbers. This avoids the runtime regression while keeping deterministic 
signed-zero behavior.



##########
pinot-controller/src/test/java/org/apache/pinot/controller/api/PinotTableRestletResourceTest.java:
##########
@@ -1197,18 +1197,21 @@ public void testTableTasksCleanupWithNonActiveTasks()
     String taskName = 
taskInfo.values().iterator().next().getScheduledTaskNames().get(0);
     waitForTaskState(taskName, TaskState.IN_PROGRESS);
 
-    // stop the task queue to abort the task
+    // Stop the task queue to abort the task. Keep it stopped until table 
deletion is complete to avoid
+    // task transition races while cleanup deletes Helix job metadata.
     sendPutRequest(DEFAULT_INSTANCE.getControllerRequestURLBuilder()
         
.forStopMinionTaskQueue(MinionConstants.SegmentGenerationAndPushTask.TASK_TYPE));
     waitForTaskState(taskName, TaskState.STOPPED);
-    // resume the task queue again to avoid affecting other tests
-    sendPutRequest(DEFAULT_INSTANCE.getControllerRequestURLBuilder()
-        
.forResumeMinionTaskQueue(MinionConstants.SegmentGenerationAndPushTask.TASK_TYPE));
-
-    // Delete table - should succeed and clean up tasks
-    String deleteResponse = sendDeleteRequest(
-        
DEFAULT_INSTANCE.getControllerRequestURLBuilder().forTableDelete(tableName));
-    assertEquals(deleteResponse, "{\"status\":\"Tables: [" + tableName + 
"_OFFLINE] deleted\"}");
+    try {
+      // Delete table - should succeed and clean up tasks
+      String deleteResponse = sendDeleteRequest(
+          
DEFAULT_INSTANCE.getControllerRequestURLBuilder().forTableDelete(tableName));
+      assertEquals(deleteResponse, "{\"status\":\"Tables: [" + tableName + 
"_OFFLINE] deleted\"}");
+    } finally {
+      // Resume queue to avoid affecting other tests.
+      sendPutRequest(DEFAULT_INSTANCE.getControllerRequestURLBuilder()
+          
.forResumeMinionTaskQueue(MinionConstants.SegmentGenerationAndPushTask.TASK_TYPE));
+    }

Review Comment:
   Agreed. Widened the `try/finally` so `waitForTaskState(..., STOPPED)` is 
inside the guarded block. Once stop is issued, queue resume now always executes 
via `finally`, even on wait timeout/failure.



##########
pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/TruncateDecimalTransformFunction.java:
##########
@@ -98,7 +98,8 @@ public double[] transformToDoubleValuesSV(ValueBlock 
valueBlock) {
       }
     } else {
       for (int i = 0; i < length; i++) {
-        _doubleValuesSV[i] = Math.signum(leftValues[i]) * 
Math.floor(Math.abs(leftValues[i]));
+        // Keep behavior consistent with truncate(value, 0), including 
canonical +0.0 for values truncated to zero.
+        _doubleValuesSV[i] = BigDecimal.valueOf(leftValues[i]).setScale(0, 
RoundingMode.DOWN).doubleValue();

Review Comment:
   Applied. Replaced per-row `BigDecimal` allocation in the no-scale branch 
with math-based truncation (`floor`/`ceil`) plus explicit zero normalization 
(`-0.0` -> `+0.0`). This keeps the hot path allocation-free and deterministic.



##########
pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/TruncateDecimalTransformFunctionTest.java:
##########
@@ -62,6 +62,15 @@ public void testTruncateDecimalTransformFunction() {
       expectedValues[i] = truncate(_doubleSVValues[i], 0);
     }
     testTransformFunction(transformFunction, expectedValues);
+
+    // Regression for signed-zero handling: truncate(value) should match 
truncate(value, 0).
+    expression = RequestContextUtils.getExpression("truncate(-0.4)");
+    transformFunction = TransformFunctionFactory.get(expression, 
_dataSourceMap);
+    Assert.assertTrue(transformFunction instanceof 
TruncateDecimalTransformFunction);
+    for (int i = 0; i < NUM_ROWS; i++) {
+      expectedValues[i] = 0.0d;
+    }

Review Comment:
   Updated to `Arrays.fill(expectedValues, 0.0d)` for clarity and conciseness.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to