diff --git a/core/src/main/java/org/opensearch/sql/planner/physical/ProjectOperator.java b/core/src/main/java/org/opensearch/sql/planner/physical/ProjectOperator.java index 496e4e6ddb..57cba826ee 100644 --- a/core/src/main/java/org/opensearch/sql/planner/physical/ProjectOperator.java +++ b/core/src/main/java/org/opensearch/sql/planner/physical/ProjectOperator.java @@ -8,6 +8,8 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; + +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -19,6 +21,7 @@ import org.opensearch.sql.data.model.ExprTupleValue; import org.opensearch.sql.data.model.ExprValue; import org.opensearch.sql.data.model.ExprValueUtils; +import org.opensearch.sql.data.type.ExprCoreType; import org.opensearch.sql.executor.ExecutionEngine; import org.opensearch.sql.expression.NamedExpression; import org.opensearch.sql.expression.parse.ParseExpression; @@ -56,6 +59,7 @@ public boolean hasNext() { public ExprValue next() { ExprValue inputValue = input.next(); ImmutableMap.Builder mapBuilder = new Builder<>(); + ExprValue result = ExprValueUtils.collectionValue(new ArrayList<>()); // ParseExpression will always override NamedExpression when identifier conflicts // TODO needs a better implementation, see https://github.com/opensearch-project/sql/issues/458 @@ -65,7 +69,16 @@ public ExprValue next() { .filter(parseExpr -> parseExpr.getNameOrAlias().equals(expr.getNameOrAlias())) .findFirst(); if (optionalParseExpression.isEmpty()) { - mapBuilder.put(expr.getNameOrAlias(), exprValue); + if (exprValue.type().equals(ExprCoreType.ARRAY)) { + for (ExprValue exprVal : exprValue.collectionValue()) { + mapBuilder.put(expr.getNameOrAlias(), exprVal); + result.collectionValue().add(ExprTupleValue.fromExprValueMap(mapBuilder.build())); + mapBuilder = new Builder<>(); + } + } + else { + mapBuilder.put(expr.getNameOrAlias(), exprValue); + } continue; } @@ -85,6 +98,8 @@ public ExprValue next() { mapBuilder.put(parseExpression.getNameOrAlias(), parsedValue); } } + if (result.collectionValue().size() > 0) + return result; return ExprTupleValue.fromExprValueMap(mapBuilder.build()); } diff --git a/opensearch/src/main/java/org/opensearch/sql/opensearch/executor/OpenSearchExecutionEngine.java b/opensearch/src/main/java/org/opensearch/sql/opensearch/executor/OpenSearchExecutionEngine.java index 9a136a3bec..5dc10234e0 100644 --- a/opensearch/src/main/java/org/opensearch/sql/opensearch/executor/OpenSearchExecutionEngine.java +++ b/opensearch/src/main/java/org/opensearch/sql/opensearch/executor/OpenSearchExecutionEngine.java @@ -12,6 +12,7 @@ import lombok.RequiredArgsConstructor; import org.opensearch.sql.common.response.ResponseListener; import org.opensearch.sql.data.model.ExprValue; +import org.opensearch.sql.data.type.ExprCoreType; import org.opensearch.sql.executor.ExecutionContext; import org.opensearch.sql.executor.ExecutionEngine; import org.opensearch.sql.executor.Explain; @@ -46,7 +47,13 @@ public void execute(PhysicalPlan physicalPlan, ExecutionContext context, plan.open(); while (plan.hasNext()) { - result.add(plan.next()); + ExprValue nextPlan = plan.next(); + + if (nextPlan.type().equals(ExprCoreType.ARRAY)) + for (ExprValue value: nextPlan.collectionValue()) + result.add(value); + else + result.add(nextPlan); } QueryResponse response = new QueryResponse(physicalPlan.schema(), result);