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


##########
pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/CaseTransformFunction.java:
##########
@@ -872,6 +886,22 @@ protected byte[][] 
transformToBytesValuesSVUsingValueAndNull(ValueBlock valueBlo
     return _bytesValuesSV;
   }
 
+  private byte[][] getBytesValues(TransformFunction transformFunction, 
ValueBlock valueBlock) {
+    if (_resultMetadata.getDataType() != DataType.UUID || !(transformFunction 
instanceof LiteralTransformFunction)) {

Review Comment:
   Because BOOLEAN and TIMESTAMP literals keep their type and a UUID literal 
does not.
   
   `LiteralTransformFunction` delegates to `LiteralContext`, which holds the 
literal's `DataType`. A BOOLEAN literal is `DataType.BOOLEAN`, so 
`getIntLiteral()` → `getIntValue()` converts correctly; likewise TIMESTAMP → 
`getLongValue()`. For UUID there is no UUID literal: `CAST('550e8400-...' AS 
UUID)` is folded by `CompileTimeFunctionsInvoker` into a plain **STRING** 
literal, so `LiteralContext._type` is STRING and `getBytesLiteral()` → 
`getBytesValue()` hex-decodes it, which fails or silently produces the wrong 
bytes.
   
   So this is compensating in the consumer for type information lost at the 
literal — the same root cause as the RHS constant-folding discussion earlier in 
this PR.
   
   The principled fix is to carry the UUID type on the literal so 
`LiteralContext` reports `DataType.UUID` and `getBytesValue()` parses 
canonically; then this method disappears and `CASE` needs no UUID branch at 
all. That means touching literal typing in the planner/rewriter, which is 
squarely part 6/7 territory rather than this PR. Happy to do it there and 
delete this — or here if you would rather it not land in this shape.
   



##########
pinot-core/src/main/java/org/apache/pinot/core/query/reduce/filter/PredicateRowMatcher.java:
##########
@@ -78,6 +79,8 @@ public boolean isMatch(Object[] row) {
         return _predicateEvaluator.applySV((String) value);
       case BYTES:
         return _predicateEvaluator.applySV((byte[]) value);
+      case UUID:
+        return _predicateEvaluator.applySV(UuidUtils.toBytes(value));

Review Comment:
   I could not establish that it is, which is why the polymorphic helper is 
there rather than a cast.
   
   `UuidUtils.toBytes(Object)` accepts `java.util.UUID`, `String`, `byte[]` and 
`ByteArray`. The value here comes from `ColumnValueExtractor.extract`, which is 
just `row[_index]` off a reduce-path row, and `PredicateRowMatcher` is reached 
from `HavingFilterHandler` and `GapfillFilterHandler`. Depending on how the row 
was produced, a UUID column can be the internal `ByteArray` (what 
`ColumnDataType.UUID#toInternal` yields) or the external `java.util.UUID` 
(`toExternal`), so I did not want to commit to `(UUID) value` without being 
able to show it always holds.
   
   If you know the reduce path normalises to one of these before it reaches the 
matcher, I will make it a direct cast to match the other branches. I would also 
note there is no test exercising a UUID column through HAVING, so this line is 
currently unverified either way — worth adding once the expected type is 
settled.
   



-- 
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