• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

apache / iotdb / #9919

25 Aug 2023 07:08AM UTC coverage: 47.802% (+0.007%) from 47.795%
#9919

push

travis_ci

web-flow
Remove some useless configs (#10950)

80023 of 167404 relevant lines covered (47.8%)

0.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

44.79
/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/ExpressionUtils.java
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one
3
 * or more contributor license agreements.  See the NOTICE file
4
 * distributed with this work for additional information
5
 * regarding copyright ownership.  The ASF licenses this file
6
 * to you under the Apache License, Version 2.0 (the
7
 * "License"); you may not use this file except in compliance
8
 * with the License.  You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied.  See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19

20
package org.apache.iotdb.db.queryengine.plan.analyze;
21

22
import org.apache.iotdb.commons.path.PartialPath;
23
import org.apache.iotdb.db.queryengine.plan.expression.Expression;
24
import org.apache.iotdb.db.queryengine.plan.expression.ExpressionType;
25
import org.apache.iotdb.db.queryengine.plan.expression.UnknownExpressionTypeException;
26
import org.apache.iotdb.db.queryengine.plan.expression.binary.AdditionExpression;
27
import org.apache.iotdb.db.queryengine.plan.expression.binary.BinaryExpression;
28
import org.apache.iotdb.db.queryengine.plan.expression.binary.DivisionExpression;
29
import org.apache.iotdb.db.queryengine.plan.expression.binary.EqualToExpression;
30
import org.apache.iotdb.db.queryengine.plan.expression.binary.GreaterEqualExpression;
31
import org.apache.iotdb.db.queryengine.plan.expression.binary.GreaterThanExpression;
32
import org.apache.iotdb.db.queryengine.plan.expression.binary.LessEqualExpression;
33
import org.apache.iotdb.db.queryengine.plan.expression.binary.LessThanExpression;
34
import org.apache.iotdb.db.queryengine.plan.expression.binary.LogicAndExpression;
35
import org.apache.iotdb.db.queryengine.plan.expression.binary.LogicOrExpression;
36
import org.apache.iotdb.db.queryengine.plan.expression.binary.ModuloExpression;
37
import org.apache.iotdb.db.queryengine.plan.expression.binary.MultiplicationExpression;
38
import org.apache.iotdb.db.queryengine.plan.expression.binary.NonEqualExpression;
39
import org.apache.iotdb.db.queryengine.plan.expression.binary.SubtractionExpression;
40
import org.apache.iotdb.db.queryengine.plan.expression.binary.WhenThenExpression;
41
import org.apache.iotdb.db.queryengine.plan.expression.leaf.ConstantOperand;
42
import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimeSeriesOperand;
43
import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimestampOperand;
44
import org.apache.iotdb.db.queryengine.plan.expression.multi.FunctionExpression;
45
import org.apache.iotdb.db.queryengine.plan.expression.other.CaseWhenThenExpression;
46
import org.apache.iotdb.db.queryengine.plan.expression.ternary.BetweenExpression;
47
import org.apache.iotdb.db.queryengine.plan.expression.ternary.TernaryExpression;
48
import org.apache.iotdb.db.queryengine.plan.expression.unary.InExpression;
49
import org.apache.iotdb.db.queryengine.plan.expression.unary.IsNullExpression;
50
import org.apache.iotdb.db.queryengine.plan.expression.unary.LikeExpression;
51
import org.apache.iotdb.db.queryengine.plan.expression.unary.LogicNotExpression;
52
import org.apache.iotdb.db.queryengine.plan.expression.unary.NegationExpression;
53
import org.apache.iotdb.db.queryengine.plan.expression.unary.RegularExpression;
54
import org.apache.iotdb.db.queryengine.plan.expression.unary.UnaryExpression;
55
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
56
import org.apache.iotdb.tsfile.read.filter.TimeFilter;
57
import org.apache.iotdb.tsfile.read.filter.basic.Filter;
58
import org.apache.iotdb.tsfile.utils.Pair;
59

60
import java.util.ArrayList;
61
import java.util.List;
62
import java.util.stream.Collectors;
63

64
public class ExpressionUtils {
65

66
  private ExpressionUtils() {
67
    // util class
68
  }
69

70
  public static List<Expression> reconstructTimeSeriesOperands(
71
      TimeSeriesOperand rawExpression, List<? extends PartialPath> actualPaths) {
72
    List<Expression> resultExpressions = new ArrayList<>();
1✔
73
    for (PartialPath actualPath : actualPaths) {
1✔
74
      resultExpressions.add(reconstructTimeSeriesOperand(rawExpression, actualPath));
1✔
75
    }
1✔
76
    return resultExpressions;
1✔
77
  }
78

79
  public static Expression reconstructTimeSeriesOperand(
80
      TimeSeriesOperand rawExpression, PartialPath actualPath) {
81
    Expression resultExpression = new TimeSeriesOperand(actualPath);
1✔
82
    return cloneCommonFields(rawExpression, resultExpression);
1✔
83
  }
84

85
  public static List<Expression> reconstructFunctionExpressions(
86
      FunctionExpression expression, List<List<Expression>> childExpressionsList) {
87
    List<Expression> resultExpressions = new ArrayList<>();
1✔
88
    for (List<Expression> functionExpressions : childExpressionsList) {
1✔
89
      resultExpressions.add(reconstructFunctionExpression(expression, functionExpressions));
1✔
90
    }
1✔
91
    return resultExpressions;
1✔
92
  }
93

94
  public static Expression reconstructFunctionExpression(
95
      FunctionExpression rawExpression, List<Expression> childExpressions) {
96
    Expression resultExpression =
1✔
97
        new FunctionExpression(
98
            rawExpression.getFunctionName(),
1✔
99
            rawExpression.getFunctionAttributes(),
1✔
100
            childExpressions,
101
            rawExpression.getCountTimeExpressions());
1✔
102
    return cloneCommonFields(rawExpression, resultExpression);
1✔
103
  }
104

105
  public static List<Expression> reconstructUnaryExpressions(
106
      UnaryExpression expression, List<Expression> childExpressions) {
107
    List<Expression> resultExpressions = new ArrayList<>();
×
108
    for (Expression childExpression : childExpressions) {
×
109
      resultExpressions.add(reconstructUnaryExpression(expression, childExpression));
×
110
    }
×
111
    return resultExpressions;
×
112
  }
113

114
  public static Expression reconstructCaseWhenThenExpression(
115
      CaseWhenThenExpression rawExpression, List<Expression> childExpressions) {
116
    Expression resultExpression =
×
117
        new CaseWhenThenExpression(
118
            childExpressions // transform to List<WhenThenExpression>
119
                .subList(0, childExpressions.size() - 1).stream()
×
120
                .map(WhenThenExpression.class::cast)
×
121
                .collect(Collectors.toList()),
×
122
            childExpressions.get(childExpressions.size() - 1));
×
123
    return cloneCommonFields(rawExpression, resultExpression);
×
124
  }
125

126
  public static Expression reconstructUnaryExpression(
127
      UnaryExpression rawExpression, Expression childExpression) {
128
    Expression resultExpression;
129
    switch (rawExpression.getExpressionType()) {
×
130
      case IS_NULL:
131
        resultExpression =
×
132
            new IsNullExpression(childExpression, ((IsNullExpression) rawExpression).isNot());
×
133
        break;
×
134
      case IN:
135
        resultExpression =
×
136
            new InExpression(
137
                childExpression,
138
                ((InExpression) rawExpression).isNotIn(),
×
139
                ((InExpression) rawExpression).getValues());
×
140
        break;
×
141
      case LIKE:
142
        resultExpression =
×
143
            new LikeExpression(
144
                childExpression,
145
                ((LikeExpression) rawExpression).getPatternString(),
×
146
                ((LikeExpression) rawExpression).getPattern());
×
147
        break;
×
148
      case LOGIC_NOT:
149
        resultExpression = new LogicNotExpression(childExpression);
×
150
        break;
×
151
      case NEGATION:
152
        resultExpression = new NegationExpression(childExpression);
×
153
        break;
×
154
      case REGEXP:
155
        resultExpression =
×
156
            new RegularExpression(
157
                childExpression,
158
                ((RegularExpression) rawExpression).getPatternString(),
×
159
                ((RegularExpression) rawExpression).getPattern());
×
160
        break;
×
161
      default:
162
        throw new UnknownExpressionTypeException(rawExpression.getExpressionType());
×
163
    }
164
    return cloneCommonFields(rawExpression, resultExpression);
×
165
  }
166

167
  public static List<Expression> reconstructBinaryExpressions(
168
      BinaryExpression expression,
169
      List<Expression> leftExpressions,
170
      List<Expression> rightExpressions) {
171
    List<Expression> resultExpressions = new ArrayList<>();
1✔
172
    for (Expression le : leftExpressions) {
1✔
173
      for (Expression re : rightExpressions) {
1✔
174
        resultExpressions.add(reconstructBinaryExpression(expression, le, re));
1✔
175
      }
1✔
176
    }
1✔
177
    return resultExpressions;
1✔
178
  }
179

180
  public static Expression reconstructBinaryExpression(
181
      Expression rawExpression, Expression leftExpression, Expression rightExpression) {
182
    Expression resultExpression;
183
    switch (rawExpression.getExpressionType()) {
1✔
184
      case ADDITION:
185
        resultExpression = new AdditionExpression(leftExpression, rightExpression);
1✔
186
        break;
1✔
187
      case SUBTRACTION:
188
        resultExpression = new SubtractionExpression(leftExpression, rightExpression);
1✔
189
        break;
1✔
190
      case MULTIPLICATION:
191
        resultExpression = new MultiplicationExpression(leftExpression, rightExpression);
1✔
192
        break;
1✔
193
      case DIVISION:
194
        resultExpression = new DivisionExpression(leftExpression, rightExpression);
1✔
195
        break;
1✔
196
      case MODULO:
197
        resultExpression = new ModuloExpression(leftExpression, rightExpression);
1✔
198
        break;
1✔
199
      case LESS_THAN:
200
        resultExpression = new LessThanExpression(leftExpression, rightExpression);
1✔
201
        break;
1✔
202
      case LESS_EQUAL:
203
        resultExpression = new LessEqualExpression(leftExpression, rightExpression);
1✔
204
        break;
1✔
205
      case GREATER_THAN:
206
        resultExpression = new GreaterThanExpression(leftExpression, rightExpression);
1✔
207
        break;
1✔
208
      case GREATER_EQUAL:
209
        resultExpression = new GreaterEqualExpression(leftExpression, rightExpression);
1✔
210
        break;
1✔
211
      case EQUAL_TO:
212
        resultExpression = new EqualToExpression(leftExpression, rightExpression);
×
213
        break;
×
214
      case NON_EQUAL:
215
        resultExpression = new NonEqualExpression(leftExpression, rightExpression);
1✔
216
        break;
1✔
217
      case LOGIC_AND:
218
        resultExpression = new LogicAndExpression(leftExpression, rightExpression);
1✔
219
        break;
1✔
220
      case LOGIC_OR:
221
        resultExpression = new LogicOrExpression(leftExpression, rightExpression);
1✔
222
        break;
1✔
223
      case WHEN_THEN:
224
        resultExpression = new WhenThenExpression(leftExpression, rightExpression);
×
225
        break;
×
226
      default:
227
        throw new IllegalArgumentException(
×
228
            "unsupported rawExpression type: " + rawExpression.getExpressionType());
×
229
    }
230
    return cloneCommonFields(rawExpression, resultExpression);
1✔
231
  }
232

233
  public static List<Expression> reconstructTernaryExpressions(
234
      TernaryExpression expression,
235
      List<Expression> firstExpressions,
236
      List<Expression> secondExpressions,
237
      List<Expression> thirdExpressions) {
238
    List<Expression> resultExpressions = new ArrayList<>();
×
239
    for (Expression fe : firstExpressions) {
×
240
      for (Expression se : secondExpressions)
×
241
        for (Expression te : thirdExpressions) {
×
242
          resultExpressions.add(reconstructTernaryExpression(expression, fe, se, te));
×
243
        }
×
244
    }
×
245
    return resultExpressions;
×
246
  }
247

248
  public static Expression reconstructTernaryExpression(
249
      TernaryExpression rawExpression,
250
      Expression firstExpression,
251
      Expression secondExpression,
252
      Expression thirdExpression) {
253
    Expression resultExpression;
254
    if (rawExpression.getExpressionType() == ExpressionType.BETWEEN) {
×
255
      resultExpression =
×
256
          new BetweenExpression(
257
              firstExpression,
258
              secondExpression,
259
              thirdExpression,
260
              ((BetweenExpression) rawExpression).isNotBetween());
×
261
    } else {
262
      throw new UnknownExpressionTypeException(rawExpression.getExpressionType());
×
263
    }
264
    return cloneCommonFields(rawExpression, resultExpression);
×
265
  }
266

267
  private static Expression cloneCommonFields(
268
      Expression rawExpression, Expression resultExpression) {
269
    resultExpression.setViewPath(rawExpression.getViewPath());
1✔
270
    return resultExpression;
1✔
271
  }
272

273
  /**
274
   * Make cartesian product. Attention, in this implementation, the way to handle the empty set is
275
   * to ignore it instead of making the result an empty set.
276
   *
277
   * @param dimensionValue source data
278
   * @param resultList final results
279
   * @param layer the depth of recursive, dimensionValue[layer] will be processed this time, should
280
   *     always be 0 while call from outside
281
   * @param currentList intermediate result, should always be empty while call from outside
282
   * @param <T> any type
283
   */
284
  public static <T> void cartesianProduct(
285
      List<List<T>> dimensionValue, List<List<T>> resultList, int layer, List<T> currentList) {
286
    if (layer < dimensionValue.size() - 1) {
1✔
287
      if (dimensionValue.get(layer).isEmpty()) {
×
288
        cartesianProduct(dimensionValue, resultList, layer + 1, currentList);
×
289
      } else {
290
        for (int i = 0; i < dimensionValue.get(layer).size(); i++) {
×
291
          List<T> list = new ArrayList<>(currentList);
×
292
          list.add(dimensionValue.get(layer).get(i));
×
293
          cartesianProduct(dimensionValue, resultList, layer + 1, list);
×
294
        }
295
      }
296
    } else if (layer == dimensionValue.size() - 1) {
1✔
297
      if (dimensionValue.get(layer).isEmpty()) {
1✔
298
        resultList.add(currentList);
×
299
      } else {
300
        for (int i = 0; i < dimensionValue.get(layer).size(); i++) {
1✔
301
          List<T> list = new ArrayList<>(currentList);
1✔
302
          list.add(dimensionValue.get(layer).get(i));
1✔
303
          resultList.add(list);
1✔
304
        }
305
      }
306
    }
307
  }
1✔
308

309
  public static Filter constructTimeFilter(
310
      ExpressionType expressionType, Expression timeExpression, Expression valueExpression) {
311
    if (timeExpression instanceof TimestampOperand
1✔
312
        && valueExpression instanceof ConstantOperand
313
        && ((ConstantOperand) valueExpression).getDataType() == TSDataType.INT64) {
1✔
314
      long value = Long.parseLong(((ConstantOperand) valueExpression).getValueString());
1✔
315
      switch (expressionType) {
1✔
316
        case LESS_THAN:
317
          return TimeFilter.lt(value);
1✔
318
        case LESS_EQUAL:
319
          return TimeFilter.ltEq(value);
×
320
        case GREATER_THAN:
321
          return TimeFilter.gt(value);
1✔
322
        case GREATER_EQUAL:
323
          return TimeFilter.gtEq(value);
1✔
324
        case EQUAL_TO:
325
          return TimeFilter.eq(value);
×
326
        case NON_EQUAL:
327
          return TimeFilter.notEq(value);
×
328
        default:
329
          throw new UnknownExpressionTypeException(expressionType);
×
330
      }
331
    }
332
    return null;
1✔
333
  }
334

335
  public static Pair<Filter, Boolean> getPairFromBetweenTimeFirst(
336
      Expression firstExpression, Expression secondExpression, boolean not) {
337
    if (firstExpression instanceof ConstantOperand
×
338
        && secondExpression instanceof ConstantOperand
339
        && ((ConstantOperand) firstExpression).getDataType() == TSDataType.INT64
×
340
        && ((ConstantOperand) secondExpression).getDataType() == TSDataType.INT64) {
×
341
      long value1 = Long.parseLong(((ConstantOperand) firstExpression).getValueString());
×
342
      long value2 = Long.parseLong(((ConstantOperand) secondExpression).getValueString());
×
343
      return new Pair<>(
×
344
          not ? TimeFilter.notBetween(value1, value2) : TimeFilter.between(value1, value2), false);
×
345
    } else {
346
      return new Pair<>(null, true);
×
347
    }
348
  }
349

350
  public static Pair<Filter, Boolean> getPairFromBetweenTimeSecond(
351
      BetweenExpression predicate, Expression expression) {
352
    if (predicate.isNotBetween()) {
×
353
      return new Pair<>(
×
354
          TimeFilter.gt(Long.parseLong(((ConstantOperand) expression).getValueString())), false);
×
355

356
    } else {
357
      return new Pair<>(
×
358
          TimeFilter.ltEq(Long.parseLong(((ConstantOperand) expression).getValueString())), false);
×
359
    }
360
  }
361

362
  public static Pair<Filter, Boolean> getPairFromBetweenTimeThird(
363
      BetweenExpression predicate, Expression expression) {
364
    if (predicate.isNotBetween()) {
×
365
      return new Pair<>(
×
366
          TimeFilter.lt(Long.parseLong(((ConstantOperand) expression).getValueString())), false);
×
367

368
    } else {
369
      return new Pair<>(
×
370
          TimeFilter.gtEq(Long.parseLong(((ConstantOperand) expression).getValueString())), false);
×
371
    }
372
  }
373

374
  public static boolean checkConstantSatisfy(
375
      Expression firstExpression, Expression secondExpression) {
376
    return firstExpression.isConstantOperand()
×
377
        && secondExpression.isConstantOperand()
×
378
        && ((ConstantOperand) firstExpression).getDataType() == TSDataType.INT64
×
379
        && ((ConstantOperand) secondExpression).getDataType() == TSDataType.INT64
×
380
        && (Long.parseLong(((ConstantOperand) firstExpression).getValueString())
×
381
            <= Long.parseLong(((ConstantOperand) secondExpression).getValueString()));
×
382
  }
383

384
  public static Expression constructQueryFilter(List<Expression> expressions) {
385
    if (expressions.size() == 1) {
1✔
386
      return expressions.get(0);
1✔
387
    }
388
    return ExpressionUtils.constructBinaryFilterTreeWithAnd(expressions);
1✔
389
  }
390

391
  private static Expression constructBinaryFilterTreeWithAnd(List<Expression> expressions) {
392
    // TODO: consider AVL tree
393
    if (expressions.size() == 2) {
1✔
394
      return new LogicAndExpression(expressions.get(0), expressions.get(1));
1✔
395
    } else {
396
      return new LogicAndExpression(
×
397
          expressions.get(0),
×
398
          constructBinaryFilterTreeWithAnd(expressions.subList(1, expressions.size())));
×
399
    }
400
  }
401
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc