-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature] [Refactoring] Create LiteralContext to hold type and value of literal and Boolean literal eval support #9389
Conversation
61yao
commented
Sep 13, 2022
- Pass the literal for boolean as the correct type from thrift.
- Only boolean literal and some numerical types are supported.
- This naturally fixes the the boolean literal eval because we have query rewrite for this.
pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
Outdated
Show resolved
Hide resolved
pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
Outdated
Show resolved
Hide resolved
pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
Outdated
Show resolved
Hide resolved
pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
Outdated
Show resolved
Hide resolved
} | ||
|
||
public Type getType() { | ||
return _type; | ||
} | ||
|
||
public String getLiteral() { | ||
return _value; | ||
@Nullable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(minor) Not sure if we want to put @Nullable
here. We usually call it after checking the type, and this annotation can potentially cause warning in IDE. If we decide to use @Nullable
here, we should probably also annotate getIdentifier()
and getFunction()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check and get seems a better idea. yes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the annotation.
I feel the best way is to have LiteralContext, IdentifierContext and Function Context inherit from ExpressionContext, so we don't need to check and call get... it is also more clear which value field is set. but this needs a bit more refactoring.
pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
Outdated
Show resolved
Hide resolved
pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
Show resolved
Hide resolved
pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
Outdated
Show resolved
Hide resolved
b51baa1
to
ed8140a
Compare
Codecov Report
@@ Coverage Diff @@
## master #9389 +/- ##
=============================================
+ Coverage 25.97% 69.90% +43.92%
- Complexity 44 5213 +5169
=============================================
Files 1915 1928 +13
Lines 102376 102783 +407
Branches 15554 15597 +43
=============================================
+ Hits 26592 71850 +45258
+ Misses 73096 25848 -47248
- Partials 2688 5085 +2397
Flags with carried forward coverage won't be shown. Click here to find out more.
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
...rc/main/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunction.java
Show resolved
Hide resolved
pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
Show resolved
Hide resolved
...pache/pinot/core/query/aggregation/function/DistinctCountThetaSketchAggregationFunction.java
Show resolved
Hide resolved
pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
Show resolved
Hide resolved
private static Class<?> convertDataTypeToJavaType(FieldSpec.DataType dataType) { | ||
switch (dataType) { | ||
case INT: | ||
return Integer.class; | ||
case LONG: | ||
return Long.class; | ||
case BOOLEAN: | ||
return Boolean.class; | ||
case FLOAT: | ||
return Float.class; | ||
case DOUBLE: | ||
return Double.class; | ||
case STRING: | ||
return String.class; | ||
default: | ||
throw new UnsupportedOperationException("Unsupported dataType:" + dataType); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the purpose of this. we have PinotDataType for this right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO we should focus on having Literal store DataType
and Value
. all conversion logics should be outside of LiteralContext
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is used to check whether the constructor for LiteralContext is valid to prevent bad usage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm I don't think this check is needed - as there's no need to convert to a java class.
- a simple immutable list of supported FieldTypes are sufficient.
- even if that I don't think it is necessary since it indeed and store the date type and value without a problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, what if people try to store a literal context with the wrong type, we should throw an exception right?
pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
Outdated
Show resolved
Hide resolved
private static String getStringValue(ExpressionContext expressionContext) { | ||
if (expressionContext.getType() != ExpressionContext.Type.LITERAL) { | ||
if(expressionContext.getType() != ExpressionContext.Type.LITERAL){ | ||
throw new BadQueryRequestException( | ||
"Pinot does not support column or function on the right-hand side of the predicate"); | ||
} | ||
return expressionContext.getLiteral(); | ||
return expressionContext.getLiteralString(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a new function
getLiteralContext(ExpressionContext expressionContext) {
// ...
}
and make
@Deprecated
getStringValue() {
LiteralContext literalContext = getLiteralContext(...);
return literalContext.getDataType().convertToString(literalContext.getValue());
}
later we make all the usage of getStringValue() go to getLiteralContext
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can do this when we deprecate getLiteralString?
// TODO: Support null literal and other types. | ||
switch (node.getTypeName()) { | ||
case BOOLEAN: | ||
literal.setBoolValue(node.booleanValue()); | ||
break; | ||
default: | ||
literal.setStringValue(StringUtils.replace(node.toValue(), "''", "'")); | ||
break; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO this can be added later. since @Jackie-Jiang might have some idea regarding bool <-> string casting with or w/o dictionary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure how this is related to casting? Can you clarify?
pinot-core/src/main/java/org/apache/pinot/core/data/table/TableResizer.java
Show resolved
Hide resolved
...rc/main/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunction.java
Show resolved
Hide resolved
...c/main/java/org/apache/pinot/core/query/aggregation/function/AggregationFunctionFactory.java
Show resolved
Hide resolved
pinot-common/src/main/java/org/apache/pinot/common/request/context/LiteralContext.java
Show resolved
Hide resolved
|
||
public LiteralContext(Literal literal) { | ||
_type = convertThriftTypeToDataType(literal.getSetField()); | ||
_value = literal.getFieldValue(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we also need to convert the value to match the data type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you meant we do a conversion here? do you mean we have one member data for each type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in the thrift definition file it is already a union of corresponding types right? do we need additional conversion?
pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
Outdated
Show resolved
Hide resolved
pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
Outdated
Show resolved
Hide resolved
pinot-common/src/main/java/org/apache/pinot/common/request/context/LiteralContext.java
Show resolved
Hide resolved
pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
Outdated
Show resolved
Hide resolved
pinot-common/src/main/java/org/apache/pinot/common/request/context/LiteralContext.java
Outdated
Show resolved
Hide resolved
pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good to me otherwise. please also fix tests
pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
Outdated
Show resolved
Hide resolved
pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
Outdated
Show resolved
Hide resolved
pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
Outdated
Show resolved
Hide resolved
pinot-common/src/main/java/org/apache/pinot/common/request/context/LiteralContext.java
Show resolved
Hide resolved
return '\'' + "" + '\''; | ||
} | ||
// TODO: print out the type. | ||
if(_type == FieldSpec.DataType.STRING || _type == FieldSpec.DataType.BYTES) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the value for BYTES
type? If it is byte[]
, toString()
won't work
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good question. try testing with ST_POINT(0, 0)
and see what's the literal BYTES constructed.
but I think since we don't want to worry about these non-directly constructable literal types we can add a TODO and address later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, the type can never be bytes. So I removed it.
for ST_POINT(0, 0), it will be passed in as string for literal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
the failure looks real in compatibility regression test
plz kindly take a look |
@walterddr I fixed the test and it should work now, but somehow the tests don't run anymore |
I trigered the run |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good. I will add the comment in the commit message to handle the quote/unquote issue for the literal toString