haruki-830 commented on code in PR #4474:
URL: https://github.com/apache/flink-cdc/pull/4474#discussion_r3621645536
##########
flink-cdc-runtime/src/main/java/org/apache/flink/cdc/runtime/parser/JaninoCompiler.java:
##########
@@ -322,6 +335,131 @@ private static Java.Rvalue generateUnaryOperation(
return new Java.UnaryOperation(Location.NOWHERE, operator, atom);
}
+ private static Java.Rvalue generateFunctionOperation(String functionName,
Java.Rvalue[] atoms) {
+ return new Java.MethodInvocation(Location.NOWHERE, null, functionName,
atoms);
+ }
+
+ private static Java.Rvalue generateLazyBinaryFunctionOperation(
+ Context context, SqlBasicCall sqlBasicCall, String functionName,
Java.Rvalue[] atoms) {
+ if (atoms.length != 2) {
+ throw new ParseException("Unrecognized expression: " +
sqlBasicCall.toString());
+ }
+ Java.Rvalue rightOperandSupplier =
+ new Java.AmbiguousName(
+ Location.NOWHERE,
+ new String[] {
+ "new java.util.function.Supplier<Boolean>() {
public Boolean get() { return "
+ + atoms[1]
+ + "; } }"
+ });
+ return generateFunctionOperation(
+ functionName, new Java.Rvalue[] {atoms[0],
rightOperandSupplier});
+ }
+
+ private static Java.Rvalue generateLogicalBinaryOperation(
+ Context context, SqlBasicCall sqlBasicCall, Java.Rvalue[] atoms,
boolean isAnd) {
+ if (atoms.length != 2) {
+ throw new ParseException("Unrecognized expression: " +
sqlBasicCall.toString());
+ }
+ boolean leftNullable = isExpressionNullable(context,
sqlBasicCall.getOperandList().get(0));
+ boolean rightNullable = isExpressionNullable(context,
sqlBasicCall.getOperandList().get(1));
+ if (!leftNullable && !rightNullable) {
+ return generateBinaryOperation(context, sqlBasicCall, atoms, isAnd
? "&&" : "||");
+ }
+ if (!leftNullable) {
+ return generateLeftNonNullableLogicalOperation(atoms, isAnd);
+ }
+ // TODO: This nullable-left path still relies on JIT escape analysis
to optimize
+ // per-evaluation Supplier allocation. Introduce statement-level
codegen
+ // (for example, GeneratedExpression/ScriptEvaluator) to avoid the
potential cost.
+ return generateLazyBinaryFunctionOperation(
+ context, sqlBasicCall, isAnd ? "and" : "or", atoms);
+ }
+
+ private static Java.Rvalue generateLeftNonNullableLogicalOperation(
+ Java.Rvalue[] atoms, boolean isAnd) {
+ if (isAnd) {
+ return new Java.ConditionalExpression(
+ Location.NOWHERE,
+ atoms[0],
+ atoms[1],
+ new Java.AmbiguousName(Location.NOWHERE, new String[]
{"Boolean.FALSE"}));
+ }
+ return new Java.ConditionalExpression(
+ Location.NOWHERE,
+ atoms[0],
+ new Java.AmbiguousName(Location.NOWHERE, new String[]
{"Boolean.TRUE"}),
+ atoms[1]);
+ }
+
+ private static boolean isExpressionNullable(Context context, SqlNode
sqlNode) {
+ if (sqlNode instanceof SqlIdentifier) {
+ return isIdentifierNullable(context, (SqlIdentifier) sqlNode);
+ }
+ if (sqlNode instanceof SqlLiteral) {
+ return ((SqlLiteral) sqlNode).getValue() == null;
+ }
+ if (sqlNode instanceof SqlBasicCall) {
+ return isBasicCallNullable(context, (SqlBasicCall) sqlNode);
+ }
+ return true;
+ }
Review Comment:
Thanks for the suggestion. I agree that deriving nullability from
Calcite/RelNode would be cleaner.
Since the current check only runs once during expression compilation and is
conservative for unknown expressions, I kept it local in this PR to avoid
expanding the scope. I think it would be better to revisit this in the
follow-up PR for statement-level Transform expression codegen.
--
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]