Skip to content

Commit 69d24da

Browse files
committed
Preserve UDT element type for list(ip|binary) aggregates
1 parent ea39ffd commit 69d24da

2 files changed

Lines changed: 48 additions & 8 deletions

File tree

core/src/main/java/org/opensearch/sql/executor/analytics/AnalyticsExecutionEngine.java

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.opensearch.sql.calcite.CalcitePlanContext;
2727
import org.opensearch.sql.calcite.utils.OpenSearchTypeFactory;
2828
import org.opensearch.sql.common.response.ResponseListener;
29+
import org.opensearch.sql.data.model.ExprCollectionValue;
2930
import org.opensearch.sql.data.model.ExprTupleValue;
3031
import org.opensearch.sql.data.model.ExprValue;
3132
import org.opensearch.sql.data.model.ExprValueUtils;
@@ -215,6 +216,8 @@ private List<ExprValue> convertRows(Iterable<Object[]> rows, List<RelDataTypeFie
215216
* IpFieldMapper}'s {@code valueFetcher} output).
216217
* <li>{@link BinaryType} + {@code byte[]} &rarr; base64-encoded string (matches the OpenSearch
217218
* {@code binary} field wire format).
219+
* <li>{@code ARRAY<IpType>} / {@code ARRAY<BinaryType>} + {@code List<byte[]>} &rarr; element-wise
220+
* UDT-aware conversion for {@code list(ip|binary)} aggregates.
218221
* <li>Anything else &rarr; existing {@link ExprValueUtils#fromObjectValue} path.
219222
* </ul>
220223
*
@@ -224,19 +227,55 @@ private List<ExprValue> convertRows(Iterable<Object[]> rows, List<RelDataTypeFie
224227
private static ExprValue toExprValue(Object value, RelDataType type) {
225228
if (value instanceof byte[] bytes) {
226229
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-
}
230+
return ipBytesToExprValue(bytes);
233231
} else if (type instanceof BinaryType) {
234-
return ExprValueUtils.stringValue(Base64.getEncoder().encodeToString(bytes));
232+
return binaryBytesToExprValue(bytes);
233+
}
234+
}
235+
if (value instanceof List<?> list) {
236+
RelDataType component = type.getComponentType();
237+
if (component instanceof IpType) {
238+
List<ExprValue> elems = new ArrayList<>(list.size());
239+
for (Object elem : list) {
240+
if (elem == null) {
241+
elems.add(ExprValueUtils.nullValue());
242+
} else if (elem instanceof byte[] eb) {
243+
elems.add(ipBytesToExprValue(eb));
244+
} else {
245+
elems.add(ExprValueUtils.fromObjectValue(elem));
246+
}
247+
}
248+
return new ExprCollectionValue(elems);
249+
} else if (component instanceof BinaryType) {
250+
List<ExprValue> elems = new ArrayList<>(list.size());
251+
for (Object elem : list) {
252+
if (elem == null) {
253+
elems.add(ExprValueUtils.nullValue());
254+
} else if (elem instanceof byte[] eb) {
255+
elems.add(binaryBytesToExprValue(eb));
256+
} else {
257+
elems.add(ExprValueUtils.fromObjectValue(elem));
258+
}
259+
}
260+
return new ExprCollectionValue(elems);
235261
}
236262
}
237263
return ExprValueUtils.fromObjectValue(value);
238264
}
239265

266+
private static ExprValue ipBytesToExprValue(byte[] bytes) {
267+
try {
268+
return ExprValueUtils.stringValue(
269+
InetAddresses.toAddrString(InetAddress.getByAddress(bytes)));
270+
} catch (UnknownHostException e) {
271+
throw new IllegalStateException("invalid IP buffer length: " + bytes.length, e);
272+
}
273+
}
274+
275+
private static ExprValue binaryBytesToExprValue(byte[] bytes) {
276+
return ExprValueUtils.stringValue(Base64.getEncoder().encodeToString(bytes));
277+
}
278+
240279
private Schema buildSchema(List<RelDataTypeField> fields) {
241280
List<Schema.Column> columns = new ArrayList<>();
242281
for (RelDataTypeField field : fields) {

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,9 +499,10 @@ public class PPLBuiltinOperators extends ReflectiveSqlOperatorTable {
499499
"pattern",
500500
ReturnTypes.explicit(UserDefinedFunctionUtils.nullablePatternAggList),
501501
null);
502+
// ARG0_ARRAY preserves UDT element type so AnalyticsExecutionEngine can render IP/binary byte[].
502503
public static final SqlAggFunction LIST =
503504
createUserDefinedAggFunction(
504-
ListAggFunction.class, "LIST", PPLReturnTypes.STRING_ARRAY, PPLOperandTypes.ANY_SCALAR);
505+
ListAggFunction.class, "LIST", PPLReturnTypes.ARG0_ARRAY, PPLOperandTypes.ANY_SCALAR);
505506
public static final SqlAggFunction VALUES =
506507
createUserDefinedAggFunction(
507508
ValuesAggFunction.class,

0 commit comments

Comments
 (0)