66package org .opensearch .sql .expression .function ;
77
88import static org .apache .calcite .sql .SqlJsonConstructorNullClause .NULL_ON_NULL ;
9- import static org .opensearch .sql .calcite .utils .CalciteToolsHelper .STDDEV_POP_NULLABLE ;
10- import static org .opensearch .sql .calcite .utils .CalciteToolsHelper .STDDEV_SAMP_NULLABLE ;
11- import static org .opensearch .sql .calcite .utils .CalciteToolsHelper .VAR_POP_NULLABLE ;
12- import static org .opensearch .sql .calcite .utils .CalciteToolsHelper .VAR_SAMP_NULLABLE ;
139import static org .opensearch .sql .calcite .utils .OpenSearchTypeFactory .TYPE_FACTORY ;
1410import static org .opensearch .sql .calcite .utils .OpenSearchTypeFactory .getLegacyTypeName ;
15- import static org .opensearch .sql .calcite .utils .UserDefinedFunctionUtils .createAggregateFunction ;
1611import static org .opensearch .sql .expression .function .BuiltinFunctionName .ABS ;
1712import static org .opensearch .sql .expression .function .BuiltinFunctionName .ACOS ;
1813import static org .opensearch .sql .expression .function .BuiltinFunctionName .ADD ;
246241import org .apache .calcite .sql .type .CompositeOperandTypeChecker ;
247242import org .apache .calcite .sql .type .ImplicitCastOperandTypeChecker ;
248243import org .apache .calcite .sql .type .OperandTypes ;
249- import org .apache .calcite .sql .type .ReturnTypes ;
250244import org .apache .calcite .sql .type .SameOperandTypeChecker ;
251245import org .apache .calcite .sql .type .SqlOperandTypeChecker ;
252246import org .apache .calcite .sql .type .SqlTypeFamily ;
258252import org .apache .logging .log4j .LogManager ;
259253import org .apache .logging .log4j .Logger ;
260254import org .opensearch .sql .calcite .CalcitePlanContext ;
261- import org .opensearch .sql .calcite .udf .udaf .LogPatternAggFunction ;
262- import org .opensearch .sql .calcite .udf .udaf .PercentileApproxFunction ;
263- import org .opensearch .sql .calcite .udf .udaf .TakeAggFunction ;
264255import org .opensearch .sql .calcite .utils .OpenSearchTypeFactory ;
265256import org .opensearch .sql .calcite .utils .PlanUtils ;
266257import org .opensearch .sql .calcite .utils .UserDefinedFunctionUtils ;
@@ -631,6 +622,30 @@ private static PPLTypeChecker wrapSqlOperandTypeChecker(
631622 return pplTypeChecker ;
632623 }
633624
625+ /**
626+ * Extracts the underlying {@link SqlOperandTypeChecker} from a {@link SqlOperator}.
627+ *
628+ * <p>For user-defined functions (UDFs) and user-defined aggregate functions (UDAFs), the {@link
629+ * SqlOperandTypeChecker} is typically wrapped in a {@link UDFOperandMetadata}, which contains the
630+ * actual type checker used for operand validation. Most of these wrapped type checkers are
631+ * defined in {@link org.opensearch.sql.calcite.utils.PPLOperandTypes}. This method retrieves the
632+ * inner type checker from {@link UDFOperandMetadata} if present.
633+ *
634+ * <p>For Calcite's built-in operators, its type checker is returned directly.
635+ *
636+ * @param operator the {@link SqlOperator}, which may be a Calcite built-in operator, a
637+ * user-defined function, or a user-defined aggregation function
638+ * @return the underlying {@link SqlOperandTypeChecker} instance, or {@code null} if not available
639+ */
640+ private static SqlOperandTypeChecker extractTypeCheckerFromUDF (SqlOperator operator ) {
641+ SqlOperandTypeChecker typeChecker = operator .getOperandTypeChecker ();
642+ if (typeChecker instanceof UDFOperandMetadata ) {
643+ UDFOperandMetadata udfOperandMetadata = (UDFOperandMetadata ) typeChecker ;
644+ return udfOperandMetadata .getInnerTypeChecker ();
645+ }
646+ return typeChecker ;
647+ }
648+
634649 @ SuppressWarnings ({"UnusedReturnValue" , "SameParameterValue" })
635650 private abstract static class AbstractBuilder {
636651
@@ -652,13 +667,7 @@ abstract void register(
652667 */
653668 public void registerOperator (BuiltinFunctionName functionName , SqlOperator ... operators ) {
654669 for (SqlOperator operator : operators ) {
655- SqlOperandTypeChecker typeChecker ;
656- if (operator instanceof SqlUserDefinedFunction udfOperator ) {
657- typeChecker = extractTypeCheckerFromUDF (udfOperator );
658- } else {
659- typeChecker = operator .getOperandTypeChecker ();
660- }
661-
670+ SqlOperandTypeChecker typeChecker = extractTypeCheckerFromUDF (operator );
662671 PPLTypeChecker pplTypeChecker =
663672 wrapSqlOperandTypeChecker (
664673 typeChecker , operator .getName (), operator instanceof SqlUserDefinedFunction );
@@ -669,13 +678,6 @@ public void registerOperator(BuiltinFunctionName functionName, SqlOperator... op
669678 }
670679 }
671680
672- private static SqlOperandTypeChecker extractTypeCheckerFromUDF (
673- SqlUserDefinedFunction udfOperator ) {
674- UDFOperandMetadata udfOperandMetadata =
675- (UDFOperandMetadata ) udfOperator .getOperandTypeChecker ();
676- return (udfOperandMetadata == null ) ? null : udfOperandMetadata .getInnerTypeChecker ();
677- }
678-
679681 void populate () {
680682 // register operators for comparison
681683 registerOperator (NOTEQUAL , PPLBuiltinOperators .NOT_EQUALS_IP , SqlStdOperatorTable .NOT_EQUALS );
@@ -1094,19 +1096,30 @@ void register(
10941096 }
10951097
10961098 void registerOperator (BuiltinFunctionName functionName , SqlAggFunction aggFunction ) {
1099+ SqlOperandTypeChecker innerTypeChecker = extractTypeCheckerFromUDF (aggFunction );
10971100 PPLTypeChecker typeChecker =
1098- wrapSqlOperandTypeChecker (aggFunction . getOperandTypeChecker () , functionName .name (), true );
1101+ wrapSqlOperandTypeChecker (innerTypeChecker , functionName .name (), true );
10991102 AggHandler handler =
1100- (distinct , field , argList , ctx ) ->
1101- UserDefinedFunctionUtils .makeAggregateCall (
1102- aggFunction , List .of (field ), argList , ctx .relBuilder );
1103+ (distinct , field , argList , ctx ) -> {
1104+ List <RexNode > newArgList =
1105+ argList .stream ().map (PlanUtils ::derefMapCall ).collect (Collectors .toList ());
1106+ return UserDefinedFunctionUtils .makeAggregateCall (
1107+ aggFunction , List .of (field ), newArgList , ctx .relBuilder );
1108+ };
11031109 register (functionName , handler , typeChecker );
11041110 }
11051111
11061112 void populate () {
11071113 registerOperator (MAX , SqlStdOperatorTable .MAX );
11081114 registerOperator (MIN , SqlStdOperatorTable .MIN );
11091115 registerOperator (SUM , SqlStdOperatorTable .SUM );
1116+ registerOperator (VARSAMP , PPLBuiltinOperators .VAR_SAMP_NULLABLE );
1117+ registerOperator (VARPOP , PPLBuiltinOperators .VAR_POP_NULLABLE );
1118+ registerOperator (STDDEV_SAMP , PPLBuiltinOperators .STDDEV_SAMP_NULLABLE );
1119+ registerOperator (STDDEV_POP , PPLBuiltinOperators .STDDEV_POP_NULLABLE );
1120+ registerOperator (TAKE , PPLBuiltinOperators .TAKE );
1121+ registerOperator (PERCENTILE_APPROX , PPLBuiltinOperators .PERCENTILE_APPROX );
1122+ registerOperator (INTERNAL_PATTERN , PPLBuiltinOperators .INTERNAL_PATTERN );
11101123
11111124 register (
11121125 AVG ,
@@ -1121,84 +1134,6 @@ void populate() {
11211134 distinct , null , field == null ? ImmutableList .of () : ImmutableList .of (field )),
11221135 wrapSqlOperandTypeChecker (
11231136 SqlStdOperatorTable .COUNT .getOperandTypeChecker (), COUNT .name (), false ));
1124-
1125- register (
1126- VARSAMP ,
1127- (distinct , field , argList , ctx ) -> ctx .relBuilder .aggregateCall (VAR_SAMP_NULLABLE , field ),
1128- wrapSqlOperandTypeChecker (
1129- SqlStdOperatorTable .VAR_SAMP .getOperandTypeChecker (), VARSAMP .name (), false ));
1130-
1131- register (
1132- VARPOP ,
1133- (distinct , field , argList , ctx ) -> ctx .relBuilder .aggregateCall (VAR_POP_NULLABLE , field ),
1134- wrapSqlOperandTypeChecker (
1135- SqlStdOperatorTable .VAR_POP .getOperandTypeChecker (), VARPOP .name (), false ));
1136-
1137- register (
1138- STDDEV_SAMP ,
1139- (distinct , field , argList , ctx ) ->
1140- ctx .relBuilder .aggregateCall (STDDEV_SAMP_NULLABLE , field ),
1141- wrapSqlOperandTypeChecker (
1142- SqlStdOperatorTable .STDDEV_SAMP .getOperandTypeChecker (), STDDEV_SAMP .name (), false ));
1143-
1144- register (
1145- STDDEV_POP ,
1146- (distinct , field , argList , ctx ) ->
1147- ctx .relBuilder .aggregateCall (STDDEV_POP_NULLABLE , field ),
1148- wrapSqlOperandTypeChecker (
1149- SqlStdOperatorTable .STDDEV_POP .getOperandTypeChecker (), STDDEV_POP .name (), false ));
1150-
1151- register (
1152- TAKE ,
1153- (distinct , field , argList , ctx ) -> {
1154- List <RexNode > newArgList =
1155- argList .stream ().map (PlanUtils ::derefMapCall ).collect (Collectors .toList ());
1156- return createAggregateFunction (
1157- TakeAggFunction .class ,
1158- "TAKE" ,
1159- UserDefinedFunctionUtils .getReturnTypeInferenceForArray (),
1160- List .of (field ),
1161- newArgList ,
1162- ctx .relBuilder );
1163- },
1164- PPLTypeChecker .wrapComposite (
1165- (CompositeOperandTypeChecker )
1166- OperandTypes .ANY .or (
1167- OperandTypes .family (SqlTypeFamily .ANY , SqlTypeFamily .INTEGER )),
1168- false ));
1169-
1170- register (
1171- PERCENTILE_APPROX ,
1172- (distinct , field , argList , ctx ) -> {
1173- List <RexNode > newArgList =
1174- argList .stream ().map (PlanUtils ::derefMapCall ).collect (Collectors .toList ());
1175- newArgList .add (ctx .rexBuilder .makeFlag (field .getType ().getSqlTypeName ()));
1176- return createAggregateFunction (
1177- PercentileApproxFunction .class ,
1178- "percentile_approx" ,
1179- ReturnTypes .ARG0_FORCE_NULLABLE ,
1180- List .of (field ),
1181- newArgList ,
1182- ctx .relBuilder );
1183- },
1184- PPLTypeChecker .wrapComposite (
1185- (CompositeOperandTypeChecker )
1186- OperandTypes .NUMERIC_NUMERIC .or (
1187- OperandTypes .family (
1188- SqlTypeFamily .NUMERIC , SqlTypeFamily .NUMERIC , SqlTypeFamily .NUMERIC )),
1189- false ));
1190-
1191- register (
1192- INTERNAL_PATTERN ,
1193- (distinct , field , argList , ctx ) ->
1194- createAggregateFunction (
1195- LogPatternAggFunction .class ,
1196- "pattern" ,
1197- ReturnTypes .explicit (UserDefinedFunctionUtils .nullablePatternAggList ),
1198- List .of (field ),
1199- argList ,
1200- ctx .relBuilder ),
1201- null );
12021137 }
12031138 }
12041139}
0 commit comments