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 static org.opensearch.sql.data.type.ExprCoreType.STRUCT; | |
10 | import static org.opensearch.sql.expression.env.Environment.extendEnv; | |
11 | ||
12 | import com.google.common.collect.ImmutableMap; | |
13 | import com.google.common.collect.ImmutableMap.Builder; | |
14 | import java.util.Collections; | |
15 | import java.util.LinkedHashMap; | |
16 | import java.util.List; | |
17 | import java.util.Map; | |
18 | import java.util.Map.Entry; | |
19 | import lombok.EqualsAndHashCode; | |
20 | import lombok.Getter; | |
21 | import lombok.RequiredArgsConstructor; | |
22 | import lombok.ToString; | |
23 | import org.apache.commons.lang3.tuple.Pair; | |
24 | import org.opensearch.sql.data.model.ExprTupleValue; | |
25 | import org.opensearch.sql.data.model.ExprValue; | |
26 | import org.opensearch.sql.data.model.ExprValueUtils; | |
27 | import org.opensearch.sql.expression.Expression; | |
28 | import org.opensearch.sql.expression.ReferenceExpression; | |
29 | import org.opensearch.sql.expression.env.Environment; | |
30 | ||
31 | /** | |
32 | * The eval operator evaluate the {@link EvalOperator#expressionList} and put the result into to | |
33 | * output. If the field name doesn't exist in the input, a new field will be append to the output. | |
34 | * If the field name exist in the input, a new value will be put into to output. | |
35 | * | |
36 | * <p>The {@link EvalOperator#expressionList} are evaluated from left to right. It means you can | |
37 | * reference previous evaluated field. | |
38 | * e.g. fields velocity = distance/time, doubleVelocity = 2 * velocity | |
39 | */ | |
40 | @ToString | |
41 | @EqualsAndHashCode(callSuper = false) | |
42 | @RequiredArgsConstructor | |
43 | public class EvalOperator extends PhysicalPlan { | |
44 | @Getter | |
45 | private final PhysicalPlan input; | |
46 | @Getter | |
47 | private final List<Pair<ReferenceExpression, Expression>> expressionList; | |
48 | ||
49 | @Override | |
50 | public <R, C> R accept(PhysicalPlanNodeVisitor<R, C> visitor, C context) { | |
51 |
1
1. accept : replaced return value with null for org/opensearch/sql/planner/physical/EvalOperator::accept → KILLED |
return visitor.visitEval(this, context); |
52 | } | |
53 | ||
54 | @Override | |
55 | public List<PhysicalPlan> getChild() { | |
56 |
1
1. getChild : replaced return value with Collections.emptyList for org/opensearch/sql/planner/physical/EvalOperator::getChild → KILLED |
return Collections.singletonList(input); |
57 | } | |
58 | ||
59 | @Override | |
60 | public boolean hasNext() { | |
61 |
2
1. hasNext : replaced boolean return with true for org/opensearch/sql/planner/physical/EvalOperator::hasNext → TIMED_OUT 2. hasNext : replaced boolean return with false for org/opensearch/sql/planner/physical/EvalOperator::hasNext → KILLED |
return input.hasNext(); |
62 | } | |
63 | ||
64 | @Override | |
65 | public ExprValue next() { | |
66 | ExprValue inputValue = input.next(); | |
67 | Map<String, ExprValue> evalMap = eval(inputValue.bindingTuples()); | |
68 | ||
69 |
1
1. next : negated conditional → KILLED |
if (STRUCT == inputValue.type()) { |
70 | ImmutableMap.Builder<String, ExprValue> resultBuilder = new Builder<>(); | |
71 | Map<String, ExprValue> tupleValue = ExprValueUtils.getTupleValue(inputValue); | |
72 | for (Entry<String, ExprValue> valueEntry : tupleValue.entrySet()) { | |
73 |
1
1. next : negated conditional → KILLED |
if (evalMap.containsKey(valueEntry.getKey())) { |
74 | resultBuilder.put(valueEntry.getKey(), evalMap.get(valueEntry.getKey())); | |
75 | evalMap.remove(valueEntry.getKey()); | |
76 | } else { | |
77 | resultBuilder.put(valueEntry); | |
78 | } | |
79 | } | |
80 | resultBuilder.putAll(evalMap); | |
81 |
1
1. next : replaced return value with null for org/opensearch/sql/planner/physical/EvalOperator::next → KILLED |
return ExprTupleValue.fromExprValueMap(resultBuilder.build()); |
82 | } else { | |
83 |
1
1. next : replaced return value with null for org/opensearch/sql/planner/physical/EvalOperator::next → KILLED |
return inputValue; |
84 | } | |
85 | } | |
86 | ||
87 | /** | |
88 | * Evaluate the expression in the {@link EvalOperator#expressionList} with {@link Environment}. | |
89 | * @param env {@link Environment} | |
90 | * @return The mapping of reference and {@link ExprValue} for each expression. | |
91 | */ | |
92 | private Map<String, ExprValue> eval(Environment<Expression, ExprValue> env) { | |
93 | Map<String, ExprValue> evalResultMap = new LinkedHashMap<>(); | |
94 | for (Pair<ReferenceExpression, Expression> pair : expressionList) { | |
95 | ReferenceExpression var = pair.getKey(); | |
96 | ExprValue value = pair.getValue().valueOf(env); | |
97 | env = extendEnv(env, var, value); | |
98 | evalResultMap.put(var.toString(), value); | |
99 | } | |
100 |
1
1. eval : replaced return value with Collections.emptyMap for org/opensearch/sql/planner/physical/EvalOperator::eval → KILLED |
return evalResultMap; |
101 | } | |
102 | } | |
Mutations | ||
51 |
1.1 |
|
56 |
1.1 |
|
61 |
1.1 2.2 |
|
69 |
1.1 |
|
73 |
1.1 |
|
81 |
1.1 |
|
83 |
1.1 |
|
100 |
1.1 |