Skip to content

Commit de35dbb

Browse files
committed
Refactor calcite adapter create with utility methods
Signed-off-by: Chen Dai <daichen@amazon.com>
1 parent 4c15604 commit de35dbb

3 files changed

Lines changed: 47 additions & 35 deletions

File tree

api/src/main/java/org/opensearch/sql/api/function/UnifiedFunction.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
* functions, enabling functions to be implemented once and used across multiple execution engines
1414
* without engine-specific code duplication.
1515
*
16-
* <p>Types are represented as SQL type name strings (e.g., "VARCHAR", "INTEGER", "ARRAY&lt;T&gt;",
17-
* "STRUCT&lt;...&gt;") for engine-agnostic serialization.
16+
* <p>Note: types are represented as engine-agnostic SQL type name strings (e.g., {@code "VARCHAR"},
17+
* {@code "INTEGER"}, {@code "ARRAY<T>"}, {@code "STRUCT<...>"}) to avoid introducing a dedicated
18+
* {@code UnifiedType} abstraction until it’s needed.
1819
*
1920
* @see java.io.Serializable
2021
*/
@@ -23,29 +24,29 @@ public interface UnifiedFunction extends Serializable {
2324
/**
2425
* Returns the name of the function.
2526
*
26-
* @return the function name.
27+
* @return the function name
2728
*/
2829
String getFunctionName();
2930

3031
/**
3132
* Returns the unified type names expected for the input arguments.
3233
*
33-
* @return list of SQL type names for input arguments.
34+
* @return list of unified type names for input arguments
3435
*/
3536
List<String> getInputTypes();
3637

3738
/**
3839
* Returns the unified type name of the function result.
3940
*
40-
* @return unified type name of the function result.
41+
* @return unified type name of the function result
4142
*/
4243
String getReturnType();
4344

4445
/**
4546
* Evaluates the function with the provided input values.
4647
*
47-
* @param inputs argument values evaluated by the caller.
48-
* @return the evaluated result, may be null depending on the function implementation.
48+
* @param inputs argument values evaluated by the caller
49+
* @return the evaluated result, may be null depending on the function implementation
4950
*/
5051
Object eval(List<Object> inputs);
5152
}

api/src/main/java/org/opensearch/sql/api/function/UnifiedFunctionCalciteAdapter.java

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -60,47 +60,59 @@ public class UnifiedFunctionCalciteAdapter implements UnifiedFunction {
6060
*/
6161
private final String compiledCode;
6262

63+
@Override
64+
public Object eval(List<Object> inputs) {
65+
RexExecutable rexExecutor = new RexExecutable(compiledCode, functionName);
66+
DataContext dataContext = DataContexts.of(Map.of(INPUT_RECORD_KEY, inputs.toArray()));
67+
rexExecutor.setDataContext(dataContext);
68+
69+
Object[] results = rexExecutor.execute();
70+
return (results == null || results.length == 0) ? null : results[0];
71+
}
72+
6373
/**
6474
* Creates Calcite RexNode adapter for a unified function.
6575
*
66-
* <p>Note this method pre-compiles the resolved function expression and stores the generated
76+
* <p>Note: this method pre-compiles the resolved function expression and stores the generated
6777
* source code as a string. This avoids serializing {@link RexNode} instances and simplifies
6878
* distribution across execution engines. If performance or security concerns arise, we can change
6979
* this internal implementation.
7080
*
7181
* @param rexBuilder RexBuilder for creating expressions
72-
* @param functionName function name (e.g., "UPPER", "CONCAT", "ABS")
73-
* @param inputTypeNames function argument types as SQL type names (e.g., "VARCHAR", "INTEGER")
82+
* @param functionName function name
83+
* @param inputTypes function argument types
7484
* @return configured adapter instance
7585
*/
7686
public static UnifiedFunctionCalciteAdapter create(
77-
RexBuilder rexBuilder, String functionName, List<String> inputTypeNames) {
78-
RelDataTypeFactory typeFactory = rexBuilder.getTypeFactory();
79-
RelDataTypeFactory.Builder rowTypeBuilder = typeFactory.builder();
80-
RexNode[] inputRefs = new RexNode[inputTypeNames.size()];
81-
for (int i = 0; i < inputTypeNames.size(); i++) {
82-
SqlTypeName sqlType = SqlTypeName.valueOf(inputTypeNames.get(i));
83-
RelDataType relType = typeFactory.createSqlType(sqlType);
84-
rowTypeBuilder.add("_" + i, relType);
85-
inputRefs[i] = rexBuilder.makeInputRef(relType, i);
86-
}
87-
88-
RelDataType inputRowType = rowTypeBuilder.build();
87+
RexBuilder rexBuilder, String functionName, List<String> inputTypes) {
88+
RexNode[] inputRefs = makeInputRefs(rexBuilder, inputTypes);
8989
RexNode resolved = PPLFuncImpTable.INSTANCE.resolve(rexBuilder, functionName, inputRefs);
90+
RelDataType inputRowType = buildInputRowType(rexBuilder, inputTypes);
9091
RexExecutable executable =
9192
RexExecutorImpl.getExecutable(rexBuilder, List.of(resolved), inputRowType);
92-
String returnTypeName = resolved.getType().getSqlTypeName().getName();
93+
String returnType = resolved.getType().getSqlTypeName().getName();
94+
9395
return new UnifiedFunctionCalciteAdapter(
94-
functionName, returnTypeName, List.copyOf(inputTypeNames), executable.getSource());
96+
functionName, returnType, List.copyOf(inputTypes), executable.getSource());
9597
}
9698

97-
@Override
98-
public Object eval(List<Object> inputs) {
99-
RexExecutable rexExecutor = new RexExecutable(compiledCode, functionName);
100-
DataContext dataContext = DataContexts.of(Map.of(INPUT_RECORD_KEY, inputs.toArray()));
101-
rexExecutor.setDataContext(dataContext);
99+
private static RelDataType buildInputRowType(RexBuilder rexBuilder, List<String> inputTypes) {
100+
RelDataTypeFactory typeFactory = rexBuilder.getTypeFactory();
101+
RelDataTypeFactory.Builder builder = typeFactory.builder();
102+
for (int i = 0; i < inputTypes.size(); i++) {
103+
RelDataType relType = typeFactory.createSqlType(SqlTypeName.valueOf(inputTypes.get(i)));
104+
builder.add("_" + i, relType);
105+
}
106+
return builder.build();
107+
}
102108

103-
Object[] results = rexExecutor.execute();
104-
return (results == null || results.length == 0) ? null : results[0];
109+
private static RexNode[] makeInputRefs(RexBuilder rexBuilder, List<String> inputTypes) {
110+
RelDataTypeFactory typeFactory = rexBuilder.getTypeFactory();
111+
RexNode[] inputRefs = new RexNode[inputTypes.size()];
112+
for (int i = 0; i < inputTypes.size(); i++) {
113+
RelDataType relType = typeFactory.createSqlType(SqlTypeName.valueOf(inputTypes.get(i)));
114+
inputRefs[i] = rexBuilder.makeInputRef(relType, i);
115+
}
116+
return inputRefs;
105117
}
106118
}

api/src/main/java/org/opensearch/sql/api/function/UnifiedFunctionRepository.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,8 @@ public List<UnifiedFunctionDescriptor> loadFunctions() {
3636
operator -> {
3737
String functionName = operator.getName();
3838
UnifiedFunctionBuilder builder =
39-
inputTypeNames ->
40-
UnifiedFunctionCalciteAdapter.create(
41-
rexBuilder, functionName, inputTypeNames);
39+
inputTypes ->
40+
UnifiedFunctionCalciteAdapter.create(rexBuilder, functionName, inputTypes);
4241
return new UnifiedFunctionDescriptor(functionName, builder);
4342
})
4443
.collect(Collectors.toList());
@@ -73,7 +72,7 @@ public interface UnifiedFunctionBuilder extends Serializable {
7372
/**
7473
* Builds a {@link UnifiedFunction} instance for the specified input types.
7574
*
76-
* @param inputTypes SQL type names for function arguments (e.g., ["VARCHAR", "INTEGER"])
75+
* @param inputTypes Unified type names for function arguments
7776
* @return a UnifiedFunction instance configured for the specified input types
7877
*/
7978
UnifiedFunction build(List<String> inputTypes);

0 commit comments

Comments
 (0)