Skip to content

Commit 77d49a1

Browse files
committed
Experiment: support type checking for built-in operators by accessing composition field of CompositeOperandTypeChecker via relection. May cause fatal errors if IllegalAccessException is thrown.
Signed-off-by: Yuanchun Shen <yuanchu@amazon.com>
1 parent d34857f commit 77d49a1

2 files changed

Lines changed: 43 additions & 0 deletions

File tree

core/src/main/java/org/opensearch/sql/expression/function/PPLFuncImpTable.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,15 @@
3838
import org.apache.calcite.sql.type.SqlTypeName;
3939
import org.apache.calcite.sql.validate.SqlUserDefinedFunction;
4040
import org.apache.commons.lang3.function.TriFunction;
41+
import org.apache.logging.log4j.LogManager;
42+
import org.apache.logging.log4j.Logger;
4143
import org.checkerframework.checker.nullness.qual.Nullable;
4244
import org.opensearch.sql.calcite.utils.OpenSearchTypeFactory;
4345
import org.opensearch.sql.exception.ExpressionEvaluationException;
4446
import org.opensearch.sql.executor.QueryType;
4547

4648
public class PPLFuncImpTable {
49+
private static final Logger logger = LogManager.getLogger(PPLFuncImpTable.class);
4750

4851
public interface FunctionImp {
4952
RexNode resolve(RexBuilder builder, RexNode... args);
@@ -186,7 +189,24 @@ void registerOperator(BuiltinFunctionName functionName, SqlOperator operator) {
186189
register(functionName, createCompositeFunctionImp(operator, compositeTypeChecker));
187190
} else if (typeChecker instanceof ImplicitCastOperandTypeChecker implicitCastTypeChecker) {
188191
register(functionName, createImplicitCastFunctionImp(operator, implicitCastTypeChecker));
192+
} else if (typeChecker instanceof CompositeOperandTypeChecker compositeTypeChecker) {
193+
try {
194+
// If compositeTypeChecker contains operand checkers other than family type checkers or
195+
// other than OR compositions, this will throw an IllegalArgumentException.
196+
register(functionName, createCompositeFunctionImp(operator, compositeTypeChecker));
197+
} catch (IllegalArgumentException e) {
198+
// register without type checker
199+
logger.debug(
200+
"Cannot create composite type checker for function: {}. Will skip its type checking",
201+
functionName);
202+
register(
203+
functionName,
204+
(RexBuilder builder, RexNode... node) -> builder.makeCall(operator, node));
205+
}
189206
} else {
207+
logger.debug(
208+
"Cannot create type checker for function: {}. Will skip its type checking",
209+
functionName);
190210
register(
191211
functionName,
192212
(RexBuilder builder, RexNode... node) -> builder.makeCall(operator, node));

core/src/main/java/org/opensearch/sql/expression/function/PPLTypeChecker.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package org.opensearch.sql.expression.function;
77

8+
import java.lang.reflect.Field;
89
import java.util.ArrayList;
910
import java.util.List;
1011
import java.util.stream.Collectors;
@@ -16,6 +17,7 @@
1617
import org.apache.calcite.sql.type.SqlOperandTypeChecker;
1718
import org.apache.calcite.sql.type.SqlTypeFamily;
1819
import org.apache.calcite.sql.type.SqlTypeName;
20+
import org.apache.logging.log4j.LogManager;
1921
import org.opensearch.sql.calcite.utils.UserDefinedFunctionUtils;
2022

2123
/**
@@ -228,6 +230,27 @@ static PPLFamilyTypeCheckerWrapper wrapFamily(ImplicitCastOperandTypeChecker typ
228230
* @throws IllegalArgumentException if any rule is not an {@link ImplicitCastOperandTypeChecker}
229231
*/
230232
static PPLCompositeTypeChecker wrapComposite(CompositeOperandTypeChecker typeChecker) {
233+
try {
234+
Field compositionField = CompositeOperandTypeChecker.class.getDeclaredField("composition");
235+
compositionField.setAccessible(true);
236+
CompositeOperandTypeChecker.Composition composition =
237+
(CompositeOperandTypeChecker.Composition) compositionField.get(typeChecker);
238+
if (composition != CompositeOperandTypeChecker.Composition.OR) {
239+
throw new IllegalArgumentException(
240+
String.format(
241+
"Currently only OR compositions of ImplicitCastOperandTypeChecker are supported,"
242+
+ " but got %s composition",
243+
composition.name()));
244+
}
245+
} catch (IllegalAccessException e) {
246+
LogManager.getLogger(PPLTypeChecker.class).error(e);
247+
} catch (NoSuchFieldException e) {
248+
LogManager.getLogger(PPLTypeChecker.class)
249+
.error(
250+
"Failed to access the composition field of CompositeOperandTypeChecker. "
251+
+ "This may indicate a change in the Calcite library.");
252+
}
253+
231254
for (SqlOperandTypeChecker rule : typeChecker.getRules()) {
232255
if (!(rule instanceof ImplicitCastOperandTypeChecker)) {
233256
throw new IllegalArgumentException(

0 commit comments

Comments
 (0)