CaseClause.java

1
/*
2
 * Copyright OpenSearch Contributors
3
 * SPDX-License-Identifier: Apache-2.0
4
 */
5
6
7
package org.opensearch.sql.expression.conditional.cases;
8
9
import static org.opensearch.sql.data.type.ExprCoreType.UNDEFINED;
10
11
import com.google.common.collect.ImmutableList;
12
import java.util.List;
13
import java.util.stream.Collectors;
14
import lombok.EqualsAndHashCode;
15
import lombok.Getter;
16
import lombok.ToString;
17
import org.opensearch.sql.data.model.ExprNullValue;
18
import org.opensearch.sql.data.model.ExprValue;
19
import org.opensearch.sql.data.type.ExprType;
20
import org.opensearch.sql.expression.Expression;
21
import org.opensearch.sql.expression.ExpressionNodeVisitor;
22
import org.opensearch.sql.expression.FunctionExpression;
23
import org.opensearch.sql.expression.env.Environment;
24
import org.opensearch.sql.expression.function.FunctionName;
25
26
/**
27
 * A CASE clause is very different from a regular function. Functions have well-defined signature,
28
 * though CASE clause is more like a function implementation which requires type check "manually".
29
 */
30
@EqualsAndHashCode(callSuper = false)
31
@Getter
32
@ToString
33
public class CaseClause extends FunctionExpression {
34
35
  /**
36
   * List of WHEN clauses.
37
   */
38
  private final List<WhenClause> whenClauses;
39
40
  /**
41
   * Default result if none of WHEN conditions match.
42
   */
43
  private final Expression defaultResult;
44
45
  /**
46
   * Initialize case clause.
47
   */
48
  public CaseClause(List<WhenClause> whenClauses, Expression defaultResult) {
49
    super(FunctionName.of("case"), concatArgs(whenClauses, defaultResult));
50
    this.whenClauses = whenClauses;
51
    this.defaultResult = defaultResult;
52
  }
53
54
  @Override
55
  public ExprValue valueOf(Environment<Expression, ExprValue> valueEnv) {
56
    for (WhenClause when : whenClauses) {
57 1 1. valueOf : negated conditional → KILLED
      if (when.isTrue(valueEnv)) {
58 1 1. valueOf : replaced return value with null for org/opensearch/sql/expression/conditional/cases/CaseClause::valueOf → KILLED
        return when.valueOf(valueEnv);
59
      }
60
    }
61 2 1. valueOf : negated conditional → KILLED
2. valueOf : replaced return value with null for org/opensearch/sql/expression/conditional/cases/CaseClause::valueOf → KILLED
    return (defaultResult == null) ? ExprNullValue.of() : defaultResult.valueOf(valueEnv);
62
  }
63
64
  @Override
65
  public ExprType type() {
66
    List<ExprType> types = allResultTypes();
67
68
    // Return undefined if all WHEN/ELSE return NULL
69 2 1. type : negated conditional → KILLED
2. type : replaced return value with null for org/opensearch/sql/expression/conditional/cases/CaseClause::type → KILLED
    return types.isEmpty() ? UNDEFINED : types.get(0);
70
  }
71
72
  @Override
73
  public <T, C> T accept(ExpressionNodeVisitor<T, C> visitor, C context) {
74 1 1. accept : replaced return value with null for org/opensearch/sql/expression/conditional/cases/CaseClause::accept → KILLED
    return visitor.visitCase(this, context);
75
  }
76
77
  /**
78
   * Get types of each result in WHEN clause and ELSE clause.
79
   * Exclude UNKNOWN type from NULL literal which means NULL in THEN or ELSE clause
80
   * is not included in result.
81
   * @return all result types. Use list so caller can generate friendly error message.
82
   */
83
  public List<ExprType> allResultTypes() {
84
    List<ExprType> types = whenClauses.stream()
85
                                      .map(WhenClause::type)
86
                                      .collect(Collectors.toList());
87 1 1. allResultTypes : negated conditional → KILLED
    if (defaultResult != null) {
88
      types.add(defaultResult.type());
89
    }
90
91 2 1. lambda$allResultTypes$0 : negated conditional → KILLED
2. lambda$allResultTypes$0 : replaced boolean return with true for org/opensearch/sql/expression/conditional/cases/CaseClause::lambda$allResultTypes$0 → KILLED
    types.removeIf(type -> (type == UNDEFINED));
92 1 1. allResultTypes : replaced return value with Collections.emptyList for org/opensearch/sql/expression/conditional/cases/CaseClause::allResultTypes → KILLED
    return types;
93
  }
94
95
  private static List<Expression> concatArgs(List<WhenClause> whenClauses,
96
                                             Expression defaultResult) {
97
    ImmutableList.Builder<Expression> args = ImmutableList.builder();
98 1 1. concatArgs : removed call to java/util/List::forEach → SURVIVED
    whenClauses.forEach(args::add);
99
100 1 1. concatArgs : negated conditional → KILLED
    if (defaultResult != null) {
101
      args.add(defaultResult);
102
    }
103 1 1. concatArgs : replaced return value with Collections.emptyList for org/opensearch/sql/expression/conditional/cases/CaseClause::concatArgs → SURVIVED
    return args.build();
104
  }
105
106
}

Mutations

57

1.1
Location : valueOf
Killed by : org.opensearch.sql.expression.conditional.cases.CaseClauseTest.[engine:junit-jupiter]/[class:org.opensearch.sql.expression.conditional.cases.CaseClauseTest]/[method:should_return_default_result_if_none_matched_and_no_default()]
negated conditional → KILLED

58

1.1
Location : valueOf
Killed by : org.opensearch.sql.expression.conditional.cases.CaseClauseTest.[engine:junit-jupiter]/[class:org.opensearch.sql.expression.conditional.cases.CaseClauseTest]/[method:should_return_when_clause_result_if_matched()]
replaced return value with null for org/opensearch/sql/expression/conditional/cases/CaseClause::valueOf → KILLED

61

1.1
Location : valueOf
Killed by : org.opensearch.sql.expression.conditional.cases.CaseClauseTest.[engine:junit-jupiter]/[class:org.opensearch.sql.expression.conditional.cases.CaseClauseTest]/[method:should_return_default_result_if_none_matched_and_no_default()]
negated conditional → KILLED

2.2
Location : valueOf
Killed by : org.opensearch.sql.expression.conditional.cases.CaseClauseTest.[engine:junit-jupiter]/[class:org.opensearch.sql.expression.conditional.cases.CaseClauseTest]/[method:should_return_default_result_if_none_matched_and_no_default()]
replaced return value with null for org/opensearch/sql/expression/conditional/cases/CaseClause::valueOf → KILLED

69

1.1
Location : type
Killed by : org.opensearch.sql.expression.conditional.cases.CaseClauseTest.[engine:junit-jupiter]/[class:org.opensearch.sql.expression.conditional.cases.CaseClauseTest]/[method:should_use_type_of_when_clause()]
negated conditional → KILLED

2.2
Location : type
Killed by : org.opensearch.sql.expression.conditional.cases.CaseClauseTest.[engine:junit-jupiter]/[class:org.opensearch.sql.expression.conditional.cases.CaseClauseTest]/[method:should_use_type_of_when_clause()]
replaced return value with null for org/opensearch/sql/expression/conditional/cases/CaseClause::type → KILLED

74

1.1
Location : accept
Killed by : org.opensearch.sql.analysis.ExpressionReferenceOptimizerTest.[engine:junit-jupiter]/[class:org.opensearch.sql.analysis.ExpressionReferenceOptimizerTest]/[method:case_clause_should_be_replaced()]
replaced return value with null for org/opensearch/sql/expression/conditional/cases/CaseClause::accept → KILLED

87

1.1
Location : allResultTypes
Killed by : org.opensearch.sql.expression.conditional.cases.CaseClauseTest.[engine:junit-jupiter]/[class:org.opensearch.sql.expression.conditional.cases.CaseClauseTest]/[method:should_use_type_of_when_clause()]
negated conditional → KILLED

91

1.1
Location : lambda$allResultTypes$0
Killed by : org.opensearch.sql.expression.conditional.cases.CaseClauseTest.[engine:junit-jupiter]/[class:org.opensearch.sql.expression.conditional.cases.CaseClauseTest]/[method:should_use_type_of_when_clause()]
negated conditional → KILLED

2.2
Location : lambda$allResultTypes$0
Killed by : org.opensearch.sql.expression.conditional.cases.CaseClauseTest.[engine:junit-jupiter]/[class:org.opensearch.sql.expression.conditional.cases.CaseClauseTest]/[method:should_use_type_of_when_clause()]
replaced boolean return with true for org/opensearch/sql/expression/conditional/cases/CaseClause::lambda$allResultTypes$0 → KILLED

92

1.1
Location : allResultTypes
Killed by : org.opensearch.sql.expression.conditional.cases.CaseClauseTest.[engine:junit-jupiter]/[class:org.opensearch.sql.expression.conditional.cases.CaseClauseTest]/[method:should_use_type_of_when_clause()]
replaced return value with Collections.emptyList for org/opensearch/sql/expression/conditional/cases/CaseClause::allResultTypes → KILLED

98

1.1
Location : concatArgs
Killed by : none
removed call to java/util/List::forEach → SURVIVED

100

1.1
Location : concatArgs
Killed by : org.opensearch.sql.expression.conditional.cases.CaseClauseTest.[engine:junit-jupiter]/[class:org.opensearch.sql.expression.conditional.cases.CaseClauseTest]/[method:should_use_type_of_when_clause()]
negated conditional → KILLED

103

1.1
Location : concatArgs
Killed by : none
replaced return value with Collections.emptyList for org/opensearch/sql/expression/conditional/cases/CaseClause::concatArgs → SURVIVED

Active mutators

Tests examined


Report generated by PIT 1.9.0