1 | /* | |
2 | * Copyright OpenSearch Contributors | |
3 | * SPDX-License-Identifier: Apache-2.0 | |
4 | */ | |
5 | ||
6 | package org.opensearch.sql.expression; | |
7 | ||
8 | import java.util.LinkedHashMap; | |
9 | import java.util.List; | |
10 | import java.util.regex.Matcher; | |
11 | import java.util.regex.Pattern; | |
12 | import java.util.stream.Collectors; | |
13 | import lombok.Getter; | |
14 | import org.opensearch.sql.common.utils.StringUtils; | |
15 | import org.opensearch.sql.data.model.ExprTupleValue; | |
16 | import org.opensearch.sql.data.model.ExprValue; | |
17 | import org.opensearch.sql.data.model.ExprValueUtils; | |
18 | import org.opensearch.sql.data.type.ExprCoreType; | |
19 | import org.opensearch.sql.data.type.ExprType; | |
20 | import org.opensearch.sql.expression.env.Environment; | |
21 | import org.opensearch.sql.expression.function.BuiltinFunctionName; | |
22 | ||
23 | /** | |
24 | * Highlight Expression. | |
25 | */ | |
26 | @Getter | |
27 | public class HighlightExpression extends FunctionExpression { | |
28 | private final Expression highlightField; | |
29 | private final ExprType type; | |
30 | ||
31 | /** | |
32 | * HighlightExpression Constructor. | |
33 | * @param highlightField : Highlight field for expression. | |
34 | */ | |
35 | public HighlightExpression(Expression highlightField) { | |
36 | super(BuiltinFunctionName.HIGHLIGHT.getName(), List.of(highlightField)); | |
37 | this.highlightField = highlightField; | |
38 |
1
1. <init> : negated conditional → KILLED |
this.type = this.highlightField.toString().contains("*") |
39 | ? ExprCoreType.STRUCT : ExprCoreType.ARRAY; | |
40 | } | |
41 | ||
42 | /** | |
43 | * Return collection value matching highlight field. | |
44 | * @param valueEnv : Dataset to parse value from. | |
45 | * @return : collection value of highlight fields. | |
46 | */ | |
47 | @Override | |
48 | public ExprValue valueOf(Environment<Expression, ExprValue> valueEnv) { | |
49 | String refName = "_highlight"; | |
50 | // Not a wilcard expression | |
51 |
1
1. valueOf : negated conditional → KILLED |
if (this.type == ExprCoreType.ARRAY) { |
52 | refName += "." + StringUtils.unquoteText(getHighlightField().toString()); | |
53 | } | |
54 | ExprValue value = valueEnv.resolve(DSL.ref(refName, ExprCoreType.STRING)); | |
55 | ||
56 | // In the event of multiple returned highlights and wildcard being | |
57 | // used in conjunction with other highlight calls, we need to ensure | |
58 | // only wildcard regex matching is mapped to wildcard call. | |
59 |
2
1. valueOf : negated conditional → KILLED 2. valueOf : negated conditional → KILLED |
if (this.type == ExprCoreType.STRUCT && value.type() == ExprCoreType.STRUCT) { |
60 | value = new ExprTupleValue( | |
61 | new LinkedHashMap<String, ExprValue>(value.tupleValue() | |
62 | .entrySet() | |
63 | .stream() | |
64 |
2
1. lambda$valueOf$0 : replaced boolean return with false for org/opensearch/sql/expression/HighlightExpression::lambda$valueOf$0 → KILLED 2. lambda$valueOf$0 : replaced boolean return with true for org/opensearch/sql/expression/HighlightExpression::lambda$valueOf$0 → KILLED |
.filter(s -> matchesHighlightRegex(s.getKey(), |
65 | StringUtils.unquoteText(highlightField.toString()))) | |
66 | .collect(Collectors.toMap( | |
67 |
1
1. lambda$valueOf$1 : replaced return value with "" for org/opensearch/sql/expression/HighlightExpression::lambda$valueOf$1 → SURVIVED |
e -> e.getKey(), |
68 |
1
1. lambda$valueOf$2 : replaced return value with null for org/opensearch/sql/expression/HighlightExpression::lambda$valueOf$2 → KILLED |
e -> e.getValue())))); |
69 |
1
1. valueOf : negated conditional → KILLED |
if (value.tupleValue().isEmpty()) { |
70 | value = ExprValueUtils.missingValue(); | |
71 | } | |
72 | } | |
73 | ||
74 |
1
1. valueOf : replaced return value with null for org/opensearch/sql/expression/HighlightExpression::valueOf → KILLED |
return value; |
75 | } | |
76 | ||
77 | /** | |
78 | * Get type for HighlightExpression. | |
79 | * @return : Expression type. | |
80 | */ | |
81 | @Override | |
82 | public ExprType type() { | |
83 |
1
1. type : replaced return value with null for org/opensearch/sql/expression/HighlightExpression::type → KILLED |
return this.type; |
84 | } | |
85 | ||
86 | @Override | |
87 | public <T, C> T accept(ExpressionNodeVisitor<T, C> visitor, C context) { | |
88 |
1
1. accept : replaced return value with null for org/opensearch/sql/expression/HighlightExpression::accept → KILLED |
return visitor.visitHighlight(this, context); |
89 | } | |
90 | ||
91 | /** | |
92 | * Check if field matches the wildcard pattern used in highlight query. | |
93 | * @param field Highlight selected field for query | |
94 | * @param pattern Wildcard regex to match field against | |
95 | * @return True if field matches wildcard pattern | |
96 | */ | |
97 | private boolean matchesHighlightRegex(String field, String pattern) { | |
98 | Pattern p = Pattern.compile(pattern.replace("*", ".*")); | |
99 | Matcher matcher = p.matcher(field); | |
100 |
2
1. matchesHighlightRegex : replaced boolean return with false for org/opensearch/sql/expression/HighlightExpression::matchesHighlightRegex → KILLED 2. matchesHighlightRegex : replaced boolean return with true for org/opensearch/sql/expression/HighlightExpression::matchesHighlightRegex → KILLED |
return matcher.matches(); |
101 | } | |
102 | } | |
Mutations | ||
38 |
1.1 |
|
51 |
1.1 |
|
59 |
1.1 2.2 |
|
64 |
1.1 2.2 |
|
67 |
1.1 |
|
68 |
1.1 |
|
69 |
1.1 |
|
74 |
1.1 |
|
83 |
1.1 |
|
88 |
1.1 |
|
100 |
1.1 2.2 |