@@ -251,6 +251,15 @@ private static SqlOperandTypeChecker extractTypeCheckerFromUDF(
251251 return (udfOperandMetadata == null ) ? null : udfOperandMetadata .getInnerTypeChecker ();
252252 }
253253
254+ /**
255+ * Wrap a SqlOperator into a FunctionImp with a composite type checker.
256+ *
257+ * @param operator the SqlOperator to wrap
258+ * @param typeChecker the CompositeOperandTypeChecker to use for type checking
259+ * @param checkCompositionType if true, the type checker will check whether the composition type
260+ * of the type checker is OR.
261+ * @return a FunctionImp that resolves to the operator and has the specified type checker
262+ */
254263 private static FunctionImp wrapWithCompositeTypeChecker (
255264 SqlOperator operator ,
256265 CompositeOperandTypeChecker typeChecker ,
@@ -388,7 +397,6 @@ void populate() {
388397 registerOperator (IS_NULL , SqlStdOperatorTable .IS_NULL );
389398 registerOperator (IFNULL , SqlStdOperatorTable .COALESCE );
390399 registerOperator (COALESCE , SqlStdOperatorTable .COALESCE );
391- registerOperator (INTERNAL_ITEM , SqlStdOperatorTable .ITEM );
392400
393401 // Register library operator
394402 registerOperator (REGEXP , SqlLibraryOperators .REGEXP );
@@ -544,6 +552,17 @@ void populate() {
544552 (CompositeOperandTypeChecker )
545553 OperandTypes .STRING_INTEGER .or (OperandTypes .STRING_INTEGER_INTEGER ),
546554 false ));
555+ // SqlStdOperatorTable.ITEM.getOperandTypeChecker() checks only the first operand instead of
556+ // all operands. Therefore, we wrap it with a custom CompositeOperandTypeChecker to check both
557+ // operands.
558+ register (
559+ INTERNAL_ITEM ,
560+ wrapWithCompositeTypeChecker (
561+ SqlStdOperatorTable .ITEM ,
562+ (CompositeOperandTypeChecker )
563+ OperandTypes .family (SqlTypeFamily .ARRAY , SqlTypeFamily .INTEGER )
564+ .or (OperandTypes .family (SqlTypeFamily .MAP , SqlTypeFamily .ANY )),
565+ false ));
547566 register (
548567 LOG ,
549568 createFunctionImpWithTypeChecker (
0 commit comments