1 | /* | |
2 | * Copyright OpenSearch Contributors | |
3 | * SPDX-License-Identifier: Apache-2.0 | |
4 | */ | |
5 | ||
6 | ||
7 | package org.opensearch.sql.planner.physical; | |
8 | ||
9 | import com.google.common.collect.ImmutableMap; | |
10 | import com.google.common.collect.ImmutableMap.Builder; | |
11 | import java.util.Collections; | |
12 | import java.util.List; | |
13 | import java.util.Optional; | |
14 | import java.util.stream.Collectors; | |
15 | import lombok.EqualsAndHashCode; | |
16 | import lombok.Getter; | |
17 | import lombok.RequiredArgsConstructor; | |
18 | import lombok.ToString; | |
19 | import org.opensearch.sql.data.model.ExprTupleValue; | |
20 | import org.opensearch.sql.data.model.ExprValue; | |
21 | import org.opensearch.sql.data.model.ExprValueUtils; | |
22 | import org.opensearch.sql.executor.ExecutionEngine; | |
23 | import org.opensearch.sql.expression.NamedExpression; | |
24 | import org.opensearch.sql.expression.parse.ParseExpression; | |
25 | ||
26 | /** | |
27 | * Project the fields specified in {@link ProjectOperator#projectList} from input. | |
28 | */ | |
29 | @ToString | |
30 | @EqualsAndHashCode(callSuper = false) | |
31 | @RequiredArgsConstructor | |
32 | public class ProjectOperator extends PhysicalPlan { | |
33 | @Getter | |
34 | private final PhysicalPlan input; | |
35 | @Getter | |
36 | private final List<NamedExpression> projectList; | |
37 | @Getter | |
38 | private final List<NamedExpression> namedParseExpressions; | |
39 | ||
40 | @Override | |
41 | public <R, C> R accept(PhysicalPlanNodeVisitor<R, C> visitor, C context) { | |
42 |
1
1. accept : replaced return value with null for org/opensearch/sql/planner/physical/ProjectOperator::accept → KILLED |
return visitor.visitProject(this, context); |
43 | } | |
44 | ||
45 | @Override | |
46 | public List<PhysicalPlan> getChild() { | |
47 |
1
1. getChild : replaced return value with Collections.emptyList for org/opensearch/sql/planner/physical/ProjectOperator::getChild → KILLED |
return Collections.singletonList(input); |
48 | } | |
49 | ||
50 | @Override | |
51 | public boolean hasNext() { | |
52 |
2
1. hasNext : replaced boolean return with true for org/opensearch/sql/planner/physical/ProjectOperator::hasNext → TIMED_OUT 2. hasNext : replaced boolean return with false for org/opensearch/sql/planner/physical/ProjectOperator::hasNext → KILLED |
return input.hasNext(); |
53 | } | |
54 | ||
55 | @Override | |
56 | public ExprValue next() { | |
57 | ExprValue inputValue = input.next(); | |
58 | ImmutableMap.Builder<String, ExprValue> mapBuilder = new Builder<>(); | |
59 | ||
60 | // ParseExpression will always override NamedExpression when identifier conflicts | |
61 | // TODO needs a better implementation, see https://github.com/opensearch-project/sql/issues/458 | |
62 | for (NamedExpression expr : projectList) { | |
63 | ExprValue exprValue = expr.valueOf(inputValue.bindingTuples()); | |
64 | Optional<NamedExpression> optionalParseExpression = namedParseExpressions.stream() | |
65 |
2
1. lambda$next$0 : replaced boolean return with false for org/opensearch/sql/planner/physical/ProjectOperator::lambda$next$0 → KILLED 2. lambda$next$0 : replaced boolean return with true for org/opensearch/sql/planner/physical/ProjectOperator::lambda$next$0 → KILLED |
.filter(parseExpr -> parseExpr.getNameOrAlias().equals(expr.getNameOrAlias())) |
66 | .findFirst(); | |
67 |
1
1. next : negated conditional → KILLED |
if (optionalParseExpression.isEmpty()) { |
68 | mapBuilder.put(expr.getNameOrAlias(), exprValue); | |
69 | continue; | |
70 | } | |
71 | ||
72 | NamedExpression parseExpression = optionalParseExpression.get(); | |
73 | ExprValue sourceFieldValue = inputValue.bindingTuples() | |
74 | .resolve(((ParseExpression) parseExpression.getDelegated()).getSourceField()); | |
75 |
1
1. next : negated conditional → KILLED |
if (sourceFieldValue.isMissing()) { |
76 | // source field will be missing after stats command, read from inputValue if it exists | |
77 | // otherwise do nothing since it should not appear as a field | |
78 | ExprValue tupleValue = | |
79 | ExprValueUtils.getTupleValue(inputValue).get(parseExpression.getNameOrAlias()); | |
80 |
1
1. next : negated conditional → KILLED |
if (tupleValue != null) { |
81 | mapBuilder.put(parseExpression.getNameOrAlias(), tupleValue); | |
82 | } | |
83 | } else { | |
84 | ExprValue parsedValue = parseExpression.valueOf(inputValue.bindingTuples()); | |
85 | mapBuilder.put(parseExpression.getNameOrAlias(), parsedValue); | |
86 | } | |
87 | } | |
88 |
1
1. next : replaced return value with null for org/opensearch/sql/planner/physical/ProjectOperator::next → KILLED |
return ExprTupleValue.fromExprValueMap(mapBuilder.build()); |
89 | } | |
90 | ||
91 | @Override | |
92 | public ExecutionEngine.Schema schema() { | |
93 |
1
1. schema : replaced return value with null for org/opensearch/sql/planner/physical/ProjectOperator::schema → KILLED |
return new ExecutionEngine.Schema(getProjectList().stream() |
94 |
1
1. lambda$schema$1 : replaced return value with null for org/opensearch/sql/planner/physical/ProjectOperator::lambda$schema$1 → KILLED |
.map(expr -> new ExecutionEngine.Schema.Column(expr.getName(), |
95 | expr.getAlias(), expr.type())).collect(Collectors.toList())); | |
96 | } | |
97 | } | |
Mutations | ||
42 |
1.1 |
|
47 |
1.1 |
|
52 |
1.1 2.2 |
|
65 |
1.1 2.2 |
|
67 |
1.1 |
|
75 |
1.1 |
|
80 |
1.1 |
|
88 |
1.1 |
|
93 |
1.1 |
|
94 |
1.1 |