@@ -215,6 +215,8 @@ private List<ExprValue> convertRows(Iterable<Object[]> rows, List<RelDataTypeFie
215215 * IpFieldMapper}'s {@code valueFetcher} output).
216216 * <li>{@link BinaryType} + {@code byte[]} → base64-encoded string (matches the OpenSearch
217217 * {@code binary} field wire format).
218+ * <li>{@code ARRAY<IpType>} / {@code ARRAY<BinaryType>} + {@code List<byte[]>} → element-wise
219+ * UDT-aware conversion for {@code list(ip|binary)} aggregates.
218220 * <li>Anything else → existing {@link ExprValueUtils#fromObjectValue} path.
219221 * </ul>
220222 *
@@ -224,19 +226,55 @@ private List<ExprValue> convertRows(Iterable<Object[]> rows, List<RelDataTypeFie
224226 private static ExprValue toExprValue (Object value , RelDataType type ) {
225227 if (value instanceof byte [] bytes ) {
226228 if (type instanceof IpType ) {
227- try {
228- return ExprValueUtils .stringValue (
229- InetAddresses .toAddrString (InetAddress .getByAddress (bytes )));
230- } catch (UnknownHostException e ) {
231- throw new IllegalStateException ("invalid IP buffer length: " + bytes .length , e );
232- }
229+ return ipBytesToExprValue (bytes );
233230 } else if (type instanceof BinaryType ) {
234- return ExprValueUtils .stringValue (Base64 .getEncoder ().encodeToString (bytes ));
231+ return binaryBytesToExprValue (bytes );
232+ }
233+ }
234+ if (value instanceof List <?> list ) {
235+ RelDataType component = type .getComponentType ();
236+ if (component instanceof IpType ) {
237+ List <ExprValue > elems = new ArrayList <>(list .size ());
238+ for (Object elem : list ) {
239+ if (elem == null ) {
240+ elems .add (ExprValueUtils .nullValue ());
241+ } else if (elem instanceof byte [] eb ) {
242+ elems .add (ipBytesToExprValue (eb ));
243+ } else {
244+ elems .add (ExprValueUtils .fromObjectValue (elem ));
245+ }
246+ }
247+ return new org .opensearch .sql .data .model .ExprCollectionValue (elems );
248+ } else if (component instanceof BinaryType ) {
249+ List <ExprValue > elems = new ArrayList <>(list .size ());
250+ for (Object elem : list ) {
251+ if (elem == null ) {
252+ elems .add (ExprValueUtils .nullValue ());
253+ } else if (elem instanceof byte [] eb ) {
254+ elems .add (binaryBytesToExprValue (eb ));
255+ } else {
256+ elems .add (ExprValueUtils .fromObjectValue (elem ));
257+ }
258+ }
259+ return new org .opensearch .sql .data .model .ExprCollectionValue (elems );
235260 }
236261 }
237262 return ExprValueUtils .fromObjectValue (value );
238263 }
239264
265+ private static ExprValue ipBytesToExprValue (byte [] bytes ) {
266+ try {
267+ return ExprValueUtils .stringValue (
268+ InetAddresses .toAddrString (InetAddress .getByAddress (bytes )));
269+ } catch (UnknownHostException e ) {
270+ throw new IllegalStateException ("invalid IP buffer length: " + bytes .length , e );
271+ }
272+ }
273+
274+ private static ExprValue binaryBytesToExprValue (byte [] bytes ) {
275+ return ExprValueUtils .stringValue (Base64 .getEncoder ().encodeToString (bytes ));
276+ }
277+
240278 private Schema buildSchema (List <RelDataTypeField > fields ) {
241279 List <Schema .Column > columns = new ArrayList <>();
242280 for (RelDataTypeField field : fields ) {
0 commit comments