1 | /* | |
2 | * Copyright OpenSearch Contributors | |
3 | * SPDX-License-Identifier: Apache-2.0 | |
4 | */ | |
5 | ||
6 | ||
7 | package org.opensearch.sql.expression; | |
8 | ||
9 | import static org.opensearch.sql.utils.ExpressionUtils.PATH_SEP; | |
10 | ||
11 | import java.util.Arrays; | |
12 | import java.util.List; | |
13 | import lombok.EqualsAndHashCode; | |
14 | import lombok.Getter; | |
15 | import lombok.RequiredArgsConstructor; | |
16 | import org.opensearch.sql.data.model.ExprTupleValue; | |
17 | import org.opensearch.sql.data.model.ExprValue; | |
18 | import org.opensearch.sql.data.type.ExprType; | |
19 | import org.opensearch.sql.expression.env.Environment; | |
20 | ||
21 | @EqualsAndHashCode | |
22 | @RequiredArgsConstructor | |
23 | public class ReferenceExpression implements Expression { | |
24 | @Getter | |
25 | private final String attr; | |
26 | ||
27 | @Getter | |
28 | private final List<String> paths; | |
29 | ||
30 | private final ExprType type; | |
31 | ||
32 | /** | |
33 | * Constructor of ReferenceExpression. | |
34 | * @param ref the field name. e.g. addr.state/addr. | |
35 | * @param type type. | |
36 | */ | |
37 | public ReferenceExpression(String ref, ExprType type) { | |
38 | this.attr = ref; | |
39 | // Todo. the define of paths need to be redefined after adding multiple index/variable support. | |
40 | this.paths = Arrays.asList(ref.split("\\.")); | |
41 | this.type = type; | |
42 | } | |
43 | ||
44 | @Override | |
45 | public ExprValue valueOf(Environment<Expression, ExprValue> env) { | |
46 |
1
1. valueOf : replaced return value with null for org/opensearch/sql/expression/ReferenceExpression::valueOf → KILLED |
return env.resolve(this); |
47 | } | |
48 | ||
49 | @Override | |
50 | public ExprType type() { | |
51 |
1
1. type : replaced return value with null for org/opensearch/sql/expression/ReferenceExpression::type → KILLED |
return type; |
52 | } | |
53 | ||
54 | @Override | |
55 | public <T, C> T accept(ExpressionNodeVisitor<T, C> visitor, C context) { | |
56 |
1
1. accept : replaced return value with null for org/opensearch/sql/expression/ReferenceExpression::accept → KILLED |
return visitor.visitReference(this, context); |
57 | } | |
58 | ||
59 | @Override | |
60 | public String toString() { | |
61 |
1
1. toString : replaced return value with "" for org/opensearch/sql/expression/ReferenceExpression::toString → KILLED |
return attr; |
62 | } | |
63 | ||
64 | /** | |
65 | * Resolve the ExprValue from {@link ExprTupleValue} using paths. | |
66 | * Considering the following sample data. | |
67 | * { | |
68 | * "name": "bob smith" | |
69 | * "project.year": 1990, | |
70 | * "project": { | |
71 | * "year": "2020" | |
72 | * } | |
73 | * "address": { | |
74 | * "state": "WA", | |
75 | * "city": "seattle", | |
76 | * "project.year": 1990 | |
77 | * } | |
78 | * "address.local": { | |
79 | * "state": "WA", | |
80 | * } | |
81 | * } | |
82 | * The paths could be | |
83 | * 1. top level, e.g. "name", which will be resolved as "bob smith" | |
84 | * 2. multiple paths, e.g. "name.address.state", which will be resolved as "WA" | |
85 | * 3. special case, the "." is the path separator, but it is possible that the path include | |
86 | * ".", for handling this use case, we define the resolve rule as bellow, e.g. "project.year" is | |
87 | * resolved as 1990 instead of 2020. Note. This logic only applied top level none object field. | |
88 | * e.g. "address.local.state" been resolved to Missing. but "address.project.year" could been | |
89 | * resolved as 1990. | |
90 | * | |
91 | * <p>Resolve Rule | |
92 | * 1. Resolve the full name by combine the paths("x"."y"."z") as whole ("x.y.z"). | |
93 | * 2. Resolve the path recursively through ExprValue. | |
94 | * | |
95 | * @param value {@link ExprTupleValue}. | |
96 | * @return {@link ExprTupleValue}. | |
97 | */ | |
98 | public ExprValue resolve(ExprTupleValue value) { | |
99 |
1
1. resolve : replaced return value with null for org/opensearch/sql/expression/ReferenceExpression::resolve → KILLED |
return resolve(value, paths); |
100 | } | |
101 | ||
102 | private ExprValue resolve(ExprValue value, List<String> paths) { | |
103 | final ExprValue wholePathValue = value.keyValue(String.join(PATH_SEP, paths)); | |
104 |
2
1. resolve : negated conditional → KILLED 2. resolve : negated conditional → KILLED |
if (!wholePathValue.isMissing() || paths.size() == 1) { |
105 |
1
1. resolve : replaced return value with null for org/opensearch/sql/expression/ReferenceExpression::resolve → KILLED |
return wholePathValue; |
106 | } else { | |
107 |
1
1. resolve : replaced return value with null for org/opensearch/sql/expression/ReferenceExpression::resolve → KILLED |
return resolve(value.keyValue(paths.get(0)), paths.subList(1, paths.size())); |
108 | } | |
109 | } | |
110 | } | |
Mutations | ||
46 |
1.1 |
|
51 |
1.1 |
|
56 |
1.1 |
|
61 |
1.1 |
|
99 |
1.1 |
|
104 |
1.1 2.2 |
|
105 |
1.1 |
|
107 |
1.1 |