You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by lt...@apache.org on 2020/02/03 13:27:42 UTC
[incubator-iotdb] branch add_in_operation created (now 6b6bfe4)
This is an automated email from the ASF dual-hosted git repository.
lta pushed a change to branch add_in_operation
in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git.
at 6b6bfe4 add IN operation
This branch includes the following new commits:
new 6b6bfe4 add IN operation
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
[incubator-iotdb] 01/01: add IN operation
Posted by lt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
lta pushed a commit to branch add_in_operation
in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git
commit 6b6bfe49a56e1c42d14ae3b521716cc742a3b158
Author: lta <li...@163.com>
AuthorDate: Mon Feb 3 21:27:18 2020 +0800
add IN operation
---
.../org/apache/iotdb/db/qp/strategy/SqlBase.g4 | 6 +
.../apache/iotdb/db/qp/constant/SQLConstant.java | 3 +
.../org/apache/iotdb/db/qp/logical/Operator.java | 2 +-
.../db/qp/logical/crud/BasicFunctionOperator.java | 32 +---
.../iotdb/db/qp/logical/crud/FilterOperator.java | 28 +--
.../iotdb/db/qp/logical/crud/FunctionOperator.java | 17 ++
.../iotdb/db/qp/logical/crud/InOperator.java | 213 +++++++++++++++++++++
.../iotdb/db/qp/strategy/LogicalGenerator.java | 68 +++++--
.../iotdb/db/qp/strategy/PhysicalGenerator.java | 4 +-
.../qp/strategy/optimizer/ConcatPathOptimizer.java | 6 +-
.../optimizer/MergeSingleFilterOptimizer.java | 14 +-
.../qp/strategy/optimizer/RemoveNotOptimizer.java | 3 +-
.../iotdb/db/integration/IoTDBQueryDemoIT.java | 93 ++++++++-
.../apache/iotdb/db/qp/plan/PhysicalPlanTest.java | 50 +++++
.../iotdb/tsfile/read/filter/TimeFilter.java | 13 ++
.../iotdb/tsfile/read/filter/ValueFilter.java | 13 ++
.../tsfile/read/filter/factory/FilterFactory.java | 2 -
.../read/filter/factory/FilterSerializeId.java | 2 +-
.../iotdb/tsfile/read/filter/operator/Eq.java | 4 +-
.../read/filter/operator/{Eq.java => In.java} | 90 +++++----
20 files changed, 546 insertions(+), 117 deletions(-)
diff --git a/server/src/main/antlr4/org/apache/iotdb/db/qp/strategy/SqlBase.g4 b/server/src/main/antlr4/org/apache/iotdb/db/qp/strategy/SqlBase.g4
index 4e2e47f..ab0e68e 100644
--- a/server/src/main/antlr4/org/apache/iotdb/db/qp/strategy/SqlBase.g4
+++ b/server/src/main/antlr4/org/apache/iotdb/db/qp/strategy/SqlBase.g4
@@ -137,9 +137,13 @@ andExpression
predicate
: (suffixPath | prefixPath) comparisonOperator constant
+ | (suffixPath | prefixPath) inClause
| OPERATOR_NOT? LR_BRACKET orExpression RR_BRACKET
;
+inClause
+ : OPERATOR_NOT? OPERATOR_IN LR_BRACKET constant (COMMA constant)* RR_BRACKET
+ ;
fromClause
: FROM prefixPath (COMMA prefixPath)*
@@ -746,6 +750,8 @@ OPERATOR_LTE : '<=';
OPERATOR_NEQ : '!=' | '<>';
+OPERATOR_IN : 'IN' | 'in' | 'In' | 'iN';
+
OPERATOR_AND
: A N D
| '&'
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/constant/SQLConstant.java b/server/src/main/java/org/apache/iotdb/db/qp/constant/SQLConstant.java
index 9a89fcc..b62287d 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/constant/SQLConstant.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/constant/SQLConstant.java
@@ -78,6 +78,7 @@ public class SQLConstant {
public static final int GREATERTHANOREQUALTO = SqlBaseLexer.OPERATOR_GTE;
public static final int GREATERTHAN = SqlBaseLexer.OPERATOR_GT;
public static final int EQUAL_NS = SqlBaseLexer.OPERATOR_NEQ;
+ public static final int IN = SqlBaseLexer.OPERATOR_IN;
public static final int TOK_SELECT = 21;
public static final int TOK_FROM = 22;
@@ -165,6 +166,7 @@ public class SQLConstant {
tokenNames.put(LESSTHAN, "lessthan");
tokenNames.put(GREATERTHANOREQUALTO, "greaterthan_or_equalto");
tokenNames.put(GREATERTHAN, "greaterthan");
+ tokenNames.put(IN, "in");
tokenNames.put(TOK_SELECT, "TOK_SELECT");
tokenNames.put(TOK_FROM, "TOK_FROM");
@@ -207,6 +209,7 @@ public class SQLConstant {
static {
reverseWords.put(KW_AND, KW_OR);
+ reverseWords.put(IN, IN);
reverseWords.put(KW_OR, KW_AND);
reverseWords.put(EQUAL, NOTEQUAL);
reverseWords.put(NOTEQUAL, EQUAL);
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/Operator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/Operator.java
index 50d87bc..2dfd9ad 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/logical/Operator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/Operator.java
@@ -67,7 +67,7 @@ public abstract class Operator {
*/
public enum OperatorType {
SFW, JOIN, UNION, FILTER, GROUPBY, ORDERBY, LIMIT, SELECT, SEQTABLESCAN, HASHTABLESCAN,
- MERGEJOIN, FILEREAD, NULL, TABLESCAN, UPDATE, INSERT, BATCHINSERT, DELETE, BASIC_FUNC, QUERY, MERGEQUERY,
+ MERGEJOIN, FILEREAD, NULL, TABLESCAN, UPDATE, INSERT, BATCHINSERT, DELETE, BASIC_FUNC, IN, QUERY, MERGEQUERY,
AGGREGATION, AUTHOR, FROM, FUNC, LOADDATA, METADATA, PROPERTY, INDEX, INDEXQUERY, FILL,
SET_STORAGE_GROUP, CREATE_TIMESERIES, DELETE_TIMESERIES, CREATE_USER, DELETE_USER, MODIFY_PASSWORD,
GRANT_USER_PRIVILEGE, REVOKE_USER_PRIVILEGE, GRANT_USER_ROLE, REVOKE_USER_ROLE, CREATE_ROLE,
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/BasicFunctionOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/BasicFunctionOperator.java
index 2fce08a..fe1d05f 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/BasicFunctionOperator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/BasicFunctionOperator.java
@@ -39,7 +39,6 @@ import org.slf4j.LoggerFactory;
*/
public class BasicFunctionOperator extends FunctionOperator {
- protected Path path;
protected String value;
private Logger logger = LoggerFactory.getLogger(BasicFunctionOperator.class);
private BasicOperatorType funcToken;
@@ -57,44 +56,19 @@ public class BasicFunctionOperator extends FunctionOperator {
super(tokenIntType);
operatorType = Operator.OperatorType.BASIC_FUNC;
funcToken = BasicOperatorType.getBasicOpBySymbol(tokenIntType);
- this.path = this.singlePath = path;
+ this.path = path;
this.value = value;
isLeaf = true;
isSingle = true;
}
- /**
- * get path.
- *
- * @return path
- */
- public String getPath() {
- return path.toString();
- }
-
public String getValue() {
return value;
}
- /**
- * set reversed token.
- *
- * @throws LogicalOperatorException Logical Operator Exception
- */
- public void setReversedTokenIntType() throws LogicalOperatorException {
- int intType = SQLConstant.reverseWords.get(tokenIntType);
- setTokenIntType(intType);
- funcToken = BasicOperatorType.getBasicOpBySymbol(intType);
- }
-
- @Override
- public Path getSinglePath() {
- return singlePath;
- }
-
@Override
- public void setSinglePath(Path singlePath) {
- this.path = this.singlePath = singlePath;
+ protected void reverseFunc(){
+ funcToken = BasicOperatorType.getBasicOpBySymbol(getTokenIntType());
}
@Override
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FilterOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FilterOperator.java
index b1f1903..a36522a 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FilterOperator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FilterOperator.java
@@ -55,7 +55,7 @@ public class FilterOperator extends Operator implements Comparable<FilterOperato
// isSingle being true means all recursive children of this filter belong to one seriesPath.
protected boolean isSingle = false;
// if isSingle = false, singlePath must be null
- protected Path singlePath = null;
+ protected Path path = null;
public FilterOperator(int tokenType) {
super(tokenType);
@@ -94,12 +94,12 @@ public class FilterOperator extends Operator implements Comparable<FilterOperato
this.isSingle = b;
}
- public Path getSinglePath() {
- return singlePath;
+ public Path getPath() {
+ return path;
}
- public void setSinglePath(Path path) {
- this.singlePath = path;
+ public void setPath(Path path) {
+ this.path = path;
}
public boolean addChildOperator(FilterOperator op) {
@@ -114,7 +114,7 @@ public class FilterOperator extends Operator implements Comparable<FilterOperato
* @return QueryFilter in TsFile
*/
public IExpression transformToExpression(IQueryProcessExecutor executor)
- throws QueryProcessException, LogicalOperatorException {
+ throws QueryProcessException {
if (isSingle) {
Pair<IUnaryExpression, String> ret = transformToSingleQueryFilter(executor);
return ret.left;
@@ -192,16 +192,16 @@ public class FilterOperator extends Operator implements Comparable<FilterOperato
*/
@Override
public int compareTo(FilterOperator fil) {
- if (singlePath == null && fil.singlePath == null) {
+ if (path == null && fil.path == null) {
return 0;
}
- if (singlePath == null) {
+ if (path == null) {
return 1;
}
- if (fil.singlePath == null) {
+ if (fil.path == null) {
return -1;
}
- return fil.singlePath.toString().compareTo(singlePath.toString());
+ return fil.path.toString().compareTo(path.toString());
}
@Override
@@ -239,7 +239,7 @@ public class FilterOperator extends Operator implements Comparable<FilterOperato
}
sc.addTail(this.tokenName);
if (isSingle) {
- sc.addTail("[single:", getSinglePath().toString(), "]");
+ sc.addTail("[single:", getPath().toString(), "]");
}
sc.addTail("\n");
for (FilterOperator filter : childOperators) {
@@ -253,7 +253,7 @@ public class FilterOperator extends Operator implements Comparable<FilterOperato
StringContainer sc = new StringContainer();
sc.addTail("[", this.tokenName);
if (isSingle) {
- sc.addTail("[single:", getSinglePath().toString(), "]");
+ sc.addTail("[single:", getPath().toString(), "]");
}
sc.addTail(" ");
for (FilterOperator filter : childOperators) {
@@ -269,8 +269,8 @@ public class FilterOperator extends Operator implements Comparable<FilterOperato
ret.tokenSymbol = tokenSymbol;
ret.isLeaf = isLeaf;
ret.isSingle = isSingle;
- if (singlePath != null) {
- ret.singlePath = singlePath.clone();
+ if (path != null) {
+ ret.path = path.clone();
}
for (FilterOperator filterOperator : this.childOperators) {
ret.addChildOperator(filterOperator.clone());
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FunctionOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FunctionOperator.java
index 64039bd..87b492b 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FunctionOperator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FunctionOperator.java
@@ -18,6 +18,8 @@
*/
package org.apache.iotdb.db.qp.logical.crud;
+import org.apache.iotdb.db.exception.query.LogicalOperatorException;
+import org.apache.iotdb.db.qp.constant.SQLConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,6 +39,21 @@ public class FunctionOperator extends FilterOperator {
operatorType = OperatorType.FUNC;
}
+ /**
+ * set reversed token.
+ *
+ * @throws LogicalOperatorException Logical Operator Exception
+ */
+ public void setReversedTokenIntType() throws LogicalOperatorException {
+ int intType = SQLConstant.reverseWords.get(tokenIntType);
+ setTokenIntType(intType);
+ reverseFunc();
+ }
+
+ protected void reverseFunc(){
+
+ }
+
@Override
public boolean addChildOperator(FilterOperator op) {
logger.error("cannot add child to leaf FilterOperator, now it's FunctionOperator");
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/InOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/InOperator.java
new file mode 100644
index 0000000..f86c719
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/InOperator.java
@@ -0,0 +1,213 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.iotdb.db.qp.logical.crud;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.LogicalOperatorException;
+import org.apache.iotdb.db.exception.runtime.SQLParserException;
+import org.apache.iotdb.db.qp.executor.IQueryProcessExecutor;
+import org.apache.iotdb.db.qp.logical.Operator;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.read.common.Path;
+import org.apache.iotdb.tsfile.read.expression.IUnaryExpression;
+import org.apache.iotdb.tsfile.read.expression.impl.GlobalTimeExpression;
+import org.apache.iotdb.tsfile.read.expression.impl.SingleSeriesExpression;
+import org.apache.iotdb.tsfile.read.filter.TimeFilter;
+import org.apache.iotdb.tsfile.read.filter.ValueFilter;
+import org.apache.iotdb.tsfile.read.filter.basic.Filter;
+import org.apache.iotdb.tsfile.utils.Binary;
+import org.apache.iotdb.tsfile.utils.Pair;
+import org.apache.iotdb.tsfile.utils.StringContainer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * operator 'in' 'not in'
+ */
+public class InOperator extends FunctionOperator {
+
+ private boolean not;
+ protected Set<String> values;
+ private String valueToString;
+ private Logger logger = LoggerFactory.getLogger(InOperator.class);
+
+ /**
+ * In Operator Constructor.
+ *
+ * @param tokenIntType token in Int Type
+ * @param path path
+ * @param value value
+ * @throws LogicalOperatorException Logical Operator Exception
+ */
+ public InOperator(int tokenIntType, Path path, boolean not, Set<String> values)
+ throws SQLParserException {
+ super(tokenIntType);
+ operatorType = Operator.OperatorType.IN;
+ this.path = path;
+ this.values = values;
+ this.not = not;
+ List<String> valuesList = new ArrayList<>(values);
+ Collections.sort(valuesList);
+ this.valueToString = valuesList.toString();
+ isLeaf = true;
+ isSingle = true;
+ }
+
+ public Set<String> getValues() {
+ return values;
+ }
+
+ @Override
+ protected void reverseFunc(){
+ not = !not;
+ }
+
+ @Override
+ protected Pair<IUnaryExpression, String> transformToSingleQueryFilter(
+ IQueryProcessExecutor executor) throws LogicalOperatorException, PathException {
+ TSDataType type = executor.getSeriesType(path);
+ if (type == null) {
+ throw new PathException(
+ "given seriesPath:{" + path.getFullPath() + "} don't exist in metadata");
+ }
+ IUnaryExpression ret;
+
+ switch (type) {
+ case INT32:
+ Set<Integer> integerValues = new HashSet<>();
+ for (String val : values) {
+ integerValues.add(Integer.valueOf(val));
+ }
+ ret = In.getUnaryExpression(path, integerValues, not, valueToString);
+ break;
+ case INT64:
+ Set<Long> longValues = new HashSet<>();
+ for (String val : values) {
+ longValues.add(Long.valueOf(val));
+ }
+ ret = In.getUnaryExpression(path, longValues, not, valueToString);
+ break;
+ case BOOLEAN:
+ Set<Boolean> booleanValues = new HashSet<>();
+ for (String val : values) {
+ booleanValues.add(Boolean.valueOf(val));
+ }
+ ret = In.getUnaryExpression(path, booleanValues, not, valueToString);
+ break;
+ case FLOAT:
+ Set<Float> floatValues = new HashSet<>();
+ for (String val : values) {
+ floatValues.add(Float.parseFloat(val));
+ }
+ ret = In.getUnaryExpression(path, floatValues, not, valueToString);
+ break;
+ case DOUBLE:
+ Set<Double> doubleValues = new HashSet<>();
+ for (String val : values) {
+ doubleValues.add(Double.parseDouble(val));
+ }
+ ret = In.getUnaryExpression(path, doubleValues, not, valueToString);
+ break;
+ case TEXT:
+ Set<Binary> binaryValues = new HashSet<>();
+ for (String val : values) {
+ binaryValues.add(
+ (val.startsWith("'") && val.endsWith("'")) || (val.startsWith("\"") && val
+ .endsWith("\"")) ? new Binary(val.substring(1, val.length() - 1))
+ : new Binary(val));
+ }
+ ret = In.getUnaryExpression(path, binaryValues, not, valueToString);
+ break;
+ default:
+ throw new LogicalOperatorException(type.toString(), "");
+ }
+
+ return new Pair<>(ret, path.getFullPath());
+ }
+
+ @Override
+ public String showTree(int spaceNum) {
+ StringContainer sc = new StringContainer();
+ for (int i = 0; i < spaceNum; i++) {
+ sc.addTail(" ");
+ }
+ sc.addTail(path.toString(), this.tokenSymbol, not, valueToString, ", single\n");
+ return sc.toString();
+ }
+
+ @Override
+ public InOperator clone() {
+ InOperator ret;
+ try {
+ ret = new InOperator(this.tokenIntType, path.clone(), not, new HashSet<>(values));
+ } catch (SQLParserException e) {
+ logger.error("error clone:", e);
+ return null;
+ }
+ ret.tokenSymbol = tokenSymbol;
+ ret.isLeaf = isLeaf;
+ ret.isSingle = isSingle;
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ return "[" + path.getFullPath() + tokenSymbol + not + valueToString + "]";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ InOperator that = (InOperator) o;
+ return Objects.equals(path, that.path) && Objects.equals(valueToString, that.valueToString)
+ && not == that.not;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), path, not, valueToString);
+ }
+
+ private static class In {
+
+ public static <T extends Comparable<T>> IUnaryExpression getUnaryExpression(Path path,
+ Set<T> values, boolean not, String valueToString) {
+ if (path.equals("time")) {
+ return new GlobalTimeExpression(TimeFilter.in((Set<Long>) values, not, valueToString));
+ } else {
+ return new SingleSeriesExpression(path, ValueFilter.in(values, not, valueToString));
+ }
+ }
+
+ public <T extends Comparable<T>> Filter getValueFilter(T value) {
+ return ValueFilter.notEq(value);
+ }
+ }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java b/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java
index 509912e..349d2ed 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java
@@ -23,8 +23,10 @@ import java.time.ZoneId;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.apache.iotdb.db.conf.IoTDBDescriptor;
import org.apache.iotdb.db.exception.runtime.SQLParserException;
@@ -35,6 +37,7 @@ import org.apache.iotdb.db.qp.logical.crud.BasicFunctionOperator;
import org.apache.iotdb.db.qp.logical.crud.DeleteDataOperator;
import org.apache.iotdb.db.qp.logical.crud.FilterOperator;
import org.apache.iotdb.db.qp.logical.crud.FromOperator;
+import org.apache.iotdb.db.qp.logical.crud.InOperator;
import org.apache.iotdb.db.qp.logical.crud.InsertOperator;
import org.apache.iotdb.db.qp.logical.crud.QueryOperator;
import org.apache.iotdb.db.qp.logical.crud.SelectOperator;
@@ -88,6 +91,7 @@ import org.apache.iotdb.db.qp.strategy.SqlBaseParser.GrantUserContext;
import org.apache.iotdb.db.qp.strategy.SqlBaseParser.GrantWatermarkEmbeddingContext;
import org.apache.iotdb.db.qp.strategy.SqlBaseParser.GroupByClauseContext;
import org.apache.iotdb.db.qp.strategy.SqlBaseParser.GroupByDeviceClauseContext;
+import org.apache.iotdb.db.qp.strategy.SqlBaseParser.InClauseContext;
import org.apache.iotdb.db.qp.strategy.SqlBaseParser.InsertColumnSpecContext;
import org.apache.iotdb.db.qp.strategy.SqlBaseParser.InsertStatementContext;
import org.apache.iotdb.db.qp.strategy.SqlBaseParser.InsertValuesSpecContext;
@@ -181,7 +185,7 @@ public class LogicalGenerator extends SqlBaseBaseListener {
@Override
public void enterCountTimeseries(CountTimeseriesContext ctx) {
super.enterCountTimeseries(ctx);
- if(ctx.INT() != null) {
+ if (ctx.INT() != null) {
initializedOperator = new CountOperator(SQLConstant.TOK_COUNT_NODE_TIMESERIES,
parsePrefixPath(ctx.prefixPath()), Integer.parseInt(ctx.INT().getText()));
} else {
@@ -200,20 +204,24 @@ public class LogicalGenerator extends SqlBaseBaseListener {
@Override
public void enterShowDevices(ShowDevicesContext ctx) {
super.enterShowDevices(ctx);
- if(ctx.prefixPath() != null) {
- initializedOperator = new ShowDevicesOperator(SQLConstant.TOK_DEVICES, parsePrefixPath(ctx.prefixPath()));
+ if (ctx.prefixPath() != null) {
+ initializedOperator = new ShowDevicesOperator(SQLConstant.TOK_DEVICES,
+ parsePrefixPath(ctx.prefixPath()));
} else {
- initializedOperator = new ShowDevicesOperator(SQLConstant.TOK_DEVICES, new Path(SQLConstant.ROOT));
+ initializedOperator = new ShowDevicesOperator(SQLConstant.TOK_DEVICES,
+ new Path(SQLConstant.ROOT));
}
}
@Override
public void enterShowChildPaths(ShowChildPathsContext ctx) {
super.enterShowChildPaths(ctx);
- if(ctx.prefixPath()!= null) {
- initializedOperator = new ShowChildPathsOperator(SQLConstant.TOK_CHILD_PATHS, parsePrefixPath(ctx.prefixPath()));
+ if (ctx.prefixPath() != null) {
+ initializedOperator = new ShowChildPathsOperator(SQLConstant.TOK_CHILD_PATHS,
+ parsePrefixPath(ctx.prefixPath()));
} else {
- initializedOperator = new ShowChildPathsOperator(SQLConstant.TOK_CHILD_PATHS, new Path(SQLConstant.ROOT));
+ initializedOperator = new ShowChildPathsOperator(SQLConstant.TOK_CHILD_PATHS,
+ new Path(SQLConstant.ROOT));
}
}
@@ -284,11 +292,12 @@ public class LogicalGenerator extends SqlBaseBaseListener {
@Override
public void enterShowTimeseries(ShowTimeseriesContext ctx) {
super.enterShowTimeseries(ctx);
- if(ctx.prefixPath() != null) {
+ if (ctx.prefixPath() != null) {
initializedOperator = new ShowTimeSeriesOperator(SQLConstant.TOK_TIMESERIES,
parsePrefixPath(ctx.prefixPath()));
} else {
- initializedOperator = new ShowTimeSeriesOperator(SQLConstant.TOK_TIMESERIES, new Path("root"));
+ initializedOperator = new ShowTimeSeriesOperator(SQLConstant.TOK_TIMESERIES,
+ new Path("root"));
}
}
@@ -384,7 +393,7 @@ public class LogicalGenerator extends SqlBaseBaseListener {
super.enterAlterUser(ctx);
AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_UPDATE_USER,
AuthorOperator.AuthorType.UPDATE_USER);
- if(ctx.ID() != null) {
+ if (ctx.ID() != null) {
authorOperator.setUserName(ctx.ID().getText());
} else {
authorOperator.setUserName(ctx.ROOT().getText());
@@ -1167,28 +1176,49 @@ public class LogicalGenerator extends SqlBaseBaseListener {
return parseOrExpression(ctx.orExpression());
} else {
Path path = null;
- BasicFunctionOperator basic = null;
if (ctx.prefixPath() != null) {
path = parsePrefixPath(ctx.prefixPath());
}
if (ctx.suffixPath() != null) {
path = parseSuffixPath(ctx.suffixPath());
}
- if (ctx.constant().dateExpression() != null) {
+ if (ctx.inClause() != null) {
+ return parseInOperator(ctx.inClause(), path);
+ } else {
+ return parseBasicFunctionOperator(ctx, path);
+ }
+ }
+ }
+
+ private FilterOperator parseInOperator(InClauseContext ctx, Path path) {
+ Set<String> values = new HashSet<>();
+ boolean not = ctx.OPERATOR_NOT() != null;
+ for (ConstantContext constant : ctx.constant()) {
+ if (constant.dateExpression() != null) {
if (!path.equals(SQLConstant.RESERVED_TIME)) {
throw new SQLParserException(path.toString(), "Date can only be used to time");
}
- basic = new BasicFunctionOperator(ctx.comparisonOperator().type.getType(), path,
- Long.toString(parseDateExpression(ctx.constant().dateExpression())));
+ values.add(Long.toString(parseDateExpression(constant.dateExpression())));
} else {
- basic = new BasicFunctionOperator(ctx.comparisonOperator().type.getType(), path,
- ctx.constant().getText());
+ values.add(constant.getText());
}
- if (!isNotWhereClause && !isAndWhereClause && !isOrWhereClause) {
- return basic;
+ }
+ return new InOperator(ctx.OPERATOR_IN().getSymbol().getType(), path, not, values);
+ }
+
+ private FilterOperator parseBasicFunctionOperator(PredicateContext ctx, Path path) {
+ BasicFunctionOperator basic;
+ if (ctx.constant().dateExpression() != null) {
+ if (!path.equals(SQLConstant.RESERVED_TIME)) {
+ throw new SQLParserException(path.toString(), "Date can only be used to time");
}
- return basic;
+ basic = new BasicFunctionOperator(ctx.comparisonOperator().type.getType(), path,
+ Long.toString(parseDateExpression(ctx.constant().dateExpression())));
+ } else {
+ basic = new BasicFunctionOperator(ctx.comparisonOperator().type.getType(), path,
+ ctx.constant().getText());
}
+ return basic;
}
private Path parseSuffixPath(SuffixPathContext ctx) {
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java b/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
index 8b4d8f6..8b11890 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
@@ -392,7 +392,7 @@ public class PhysicalGenerator {
return operator;
}
BasicFunctionOperator basicOperator = (BasicFunctionOperator) operator;
- Path filterPath = basicOperator.getSinglePath();
+ Path filterPath = basicOperator.getPath();
// do nothing in the cases of "where time > 5" or "where root.d1.s1 > 5"
if (SQLConstant.isReservedPath(filterPath) || filterPath.startWith(SQLConstant.ROOT)) {
@@ -400,7 +400,7 @@ public class PhysicalGenerator {
}
Path concatPath = filterPath.addPrefixPath(filterPath, prefix);
- basicOperator.setSinglePath(concatPath);
+ basicOperator.setPath(concatPath);
return basicOperator;
}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java b/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java
index 81e3041..6d5e7f9 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java
@@ -216,8 +216,8 @@ public class ConcatPathOptimizer implements ILogicalOptimizer {
operator.setChildren(newFilterList);
return operator;
}
- BasicFunctionOperator basicOperator = (BasicFunctionOperator) operator;
- Path filterPath = basicOperator.getSinglePath();
+ FunctionOperator functionOperator = (FunctionOperator) operator;
+ Path filterPath = functionOperator.getPath();
// do nothing in the cases of "where time > 5" or "where root.d1.s1 > 5"
if (SQLConstant.isReservedPath(filterPath) || filterPath.startWith(SQLConstant.ROOT)) {
return operator;
@@ -228,7 +228,7 @@ public class ConcatPathOptimizer implements ILogicalOptimizer {
if (noStarPaths.size() == 1) {
// Transform "select s1 from root.car.* where s1 > 10" to
// "select s1 from root.car.* where root.car.*.s1 > 10"
- basicOperator.setSinglePath(noStarPaths.get(0));
+ functionOperator.setPath(noStarPaths.get(0));
return operator;
} else {
// Transform "select s1 from root.car.d1, root.car.d2 where s1 > 10" to
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/MergeSingleFilterOptimizer.java b/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/MergeSingleFilterOptimizer.java
index d2e3046..298eaa9 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/MergeSingleFilterOptimizer.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/MergeSingleFilterOptimizer.java
@@ -57,7 +57,7 @@ public class MergeSingleFilterOptimizer implements IFilterOptimizer {
*/
private Path mergeSamePathFilter(FilterOperator filter) throws LogicalOptimizeException {
if (filter.isLeaf()) {
- return filter.getSinglePath();
+ return filter.getPath();
}
List<FilterOperator> children = filter.getChildren();
checkInnerFilterLen(children);
@@ -73,14 +73,14 @@ public class MergeSingleFilterOptimizer implements IFilterOptimizer {
}
if (childPath != null) {
filter.setIsSingle(true);
- filter.setSinglePath(childPath);
+ filter.setPath(childPath);
return childPath;
}
// sort paths of BasicFunction by their single seriesPath. We don't sort children on non-leaf
// layer.
if (!children.isEmpty() && allIsBasic(children)) {
- children.sort(Comparator.comparing(o -> o.getSinglePath().getFullPath()));
+ children.sort(Comparator.comparing(o -> o.getPath().getFullPath()));
}
List<FilterOperator> ret = new ArrayList<>();
int firstNonSingleIndex = mergeSingleFilters(ret, filter);
@@ -96,7 +96,7 @@ public class MergeSingleFilterOptimizer implements IFilterOptimizer {
Path childPath = null;
int firstNonSingleIndex;
for (firstNonSingleIndex = 0; firstNonSingleIndex < children.size(); firstNonSingleIndex++) {
- tempPath = children.get(firstNonSingleIndex).getSinglePath();
+ tempPath = children.get(firstNonSingleIndex).getPath();
// sorted by seriesPath, all non-single filters are in the end
if (tempPath == null) {
break;
@@ -124,7 +124,7 @@ public class MergeSingleFilterOptimizer implements IFilterOptimizer {
} else {
// add a new inner node
FilterOperator newFilter = new FilterOperator(filter.getTokenIntType(), true);
- newFilter.setSinglePath(childPath);
+ newFilter.setPath(childPath);
newFilter.setChildren(tempExtrNode);
ret.add(newFilter);
tempExtrNode = new ArrayList<>();
@@ -140,7 +140,7 @@ public class MergeSingleFilterOptimizer implements IFilterOptimizer {
} else {
// add a new inner node
FilterOperator newFil = new FilterOperator(filter.getTokenIntType(), true);
- newFil.setSinglePath(childPath);
+ newFil.setPath(childPath);
newFil.setChildren(tempExtrNode);
ret.add(newFil);
}
@@ -157,7 +157,7 @@ public class MergeSingleFilterOptimizer implements IFilterOptimizer {
if (ret.size() == 1) {
// all children have same seriesPath, which means this filter node is a single node
filter.setIsSingle(true);
- filter.setSinglePath(childPath);
+ filter.setPath(childPath);
filter.setChildren(ret.get(0).getChildren());
return childPath;
} else {
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/RemoveNotOptimizer.java b/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/RemoveNotOptimizer.java
index 9b1fde7..5b85bcf 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/RemoveNotOptimizer.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/RemoveNotOptimizer.java
@@ -28,6 +28,7 @@ import org.apache.iotdb.db.exception.query.LogicalOptimizeException;
import org.apache.iotdb.db.qp.constant.SQLConstant;
import org.apache.iotdb.db.qp.logical.crud.BasicFunctionOperator;
import org.apache.iotdb.db.qp.logical.crud.FilterOperator;
+import org.apache.iotdb.db.qp.logical.crud.FunctionOperator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -78,7 +79,7 @@ public class RemoveNotOptimizer implements IFilterOptimizer {
int tokenInt = filter.getTokenIntType();
if (filter.isLeaf()) {
try {
- ((BasicFunctionOperator) filter).setReversedTokenIntType();
+ ((FunctionOperator)filter).setReversedTokenIntType();
} catch (LogicalOperatorException e) {
logger.error("meet error while converting BasicFunction.", e);
throw new LogicalOperatorException(
diff --git a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBQueryDemoIT.java b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBQueryDemoIT.java
index 77191a6..de7832a 100644
--- a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBQueryDemoIT.java
+++ b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBQueryDemoIT.java
@@ -233,7 +233,6 @@ public class IoTDBQueryDemoIT {
for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
builder.append(resultSet.getString(i)).append(",");
}
- System.out.println(builder.toString());
Assert.assertEquals(retArray[cnt], builder.toString());
cnt++;
}
@@ -251,7 +250,6 @@ public class IoTDBQueryDemoIT {
for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
header.append(resultSetMetaData.getColumnName(i)).append(",");
}
- System.out.println(header.toString());
Assert.assertEquals(
"Time,root.ln.wf01.wt01.status,root.ln.wf01.wt01.temperature,"
+ "root.ln.wf02.wt02.hardware,root.ln.wf02.wt02.status,root.sgcc.wf03.wt01.status,"
@@ -270,7 +268,96 @@ public class IoTDBQueryDemoIT {
for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
builder.append(resultSet.getString(i)).append(",");
}
- System.out.println(builder.toString());
+ Assert.assertEquals(retArray[cnt], builder.toString());
+ cnt++;
+ }
+ Assert.assertEquals(5, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void InTest() throws ClassNotFoundException {
+ String[] retArray = new String[]{
+ "1509465780000,false,20.18,v1,false,false,20.18,",
+ "1509465840000,false,21.13,v1,false,false,21.13,",
+ "1509465900000,false,22.72,v1,false,false,22.72,",
+ "1509465960000,false,20.71,v1,false,false,20.71,",
+ "1509466020000,false,21.45,v1,false,false,21.45,",
+ };
+
+ Class.forName(Config.JDBC_DRIVER_NAME);
+ try (Connection connection = DriverManager
+ .getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root");
+ Statement statement = connection.createStatement()) {
+
+ // test 1: fetchSize < limitNumber
+ statement.setFetchSize(4);
+ Assert.assertEquals(4, statement.getFetchSize());
+ boolean hasResultSet = statement.execute("select * from root where time in (1509465780000, 1509465840000, 1509465900000, 1509465960000, 1509466020000)");
+ Assert.assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+ StringBuilder header = new StringBuilder();
+ for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
+ header.append(resultSetMetaData.getColumnName(i)).append(",");
+ }
+ Assert.assertEquals(
+ "Time,root.ln.wf01.wt01.status,root.ln.wf01.wt01.temperature,"
+ + "root.ln.wf02.wt02.hardware,root.ln.wf02.wt02.status,root.sgcc.wf03.wt01.status,"
+ + "root.sgcc.wf03.wt01.temperature,", header.toString());
+ Assert.assertEquals(Types.TIMESTAMP, resultSetMetaData.getColumnType(1));
+ Assert.assertEquals(Types.BOOLEAN, resultSetMetaData.getColumnType(2));
+ Assert.assertEquals(Types.FLOAT, resultSetMetaData.getColumnType(3));
+ Assert.assertEquals(Types.VARCHAR, resultSetMetaData.getColumnType(4));
+ Assert.assertEquals(Types.BOOLEAN, resultSetMetaData.getColumnType(5));
+ Assert.assertEquals(Types.BOOLEAN, resultSetMetaData.getColumnType(6));
+ Assert.assertEquals(Types.FLOAT, resultSetMetaData.getColumnType(7));
+
+ int cnt = 0;
+ while (resultSet.next()) {
+ StringBuilder builder = new StringBuilder();
+ for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
+ builder.append(resultSet.getString(i)).append(",");
+ }
+ Assert.assertEquals(retArray[cnt], builder.toString());
+ cnt++;
+ }
+ Assert.assertEquals(5, cnt);
+ }
+
+ // test 1: fetchSize > limitNumber
+ statement.setFetchSize(10000);
+ Assert.assertEquals(10000, statement.getFetchSize());
+ hasResultSet = statement.execute("select * from root where time>10 limit 5 offset 3");
+ Assert.assertTrue(hasResultSet);
+ try (ResultSet resultSet = statement.getResultSet()) {
+ ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+ StringBuilder header = new StringBuilder();
+ for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
+ header.append(resultSetMetaData.getColumnName(i)).append(",");
+ }
+ Assert.assertEquals(
+ "Time,root.ln.wf01.wt01.status,root.ln.wf01.wt01.temperature,"
+ + "root.ln.wf02.wt02.hardware,root.ln.wf02.wt02.status,root.sgcc.wf03.wt01.status,"
+ + "root.sgcc.wf03.wt01.temperature,", header.toString());
+ Assert.assertEquals(Types.TIMESTAMP, resultSetMetaData.getColumnType(1));
+ Assert.assertEquals(Types.BOOLEAN, resultSetMetaData.getColumnType(2));
+ Assert.assertEquals(Types.FLOAT, resultSetMetaData.getColumnType(3));
+ Assert.assertEquals(Types.VARCHAR, resultSetMetaData.getColumnType(4));
+ Assert.assertEquals(Types.BOOLEAN, resultSetMetaData.getColumnType(5));
+ Assert.assertEquals(Types.BOOLEAN, resultSetMetaData.getColumnType(6));
+ Assert.assertEquals(Types.FLOAT, resultSetMetaData.getColumnType(7));
+
+ int cnt = 0;
+ while (resultSet.next()) {
+ StringBuilder builder = new StringBuilder();
+ for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
+ builder.append(resultSet.getString(i)).append(",");
+ }
Assert.assertEquals(retArray[cnt], builder.toString());
cnt++;
}
diff --git a/server/src/test/java/org/apache/iotdb/db/qp/plan/PhysicalPlanTest.java b/server/src/test/java/org/apache/iotdb/db/qp/plan/PhysicalPlanTest.java
index 9f38f50..f6f3ce2 100644
--- a/server/src/test/java/org/apache/iotdb/db/qp/plan/PhysicalPlanTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/qp/plan/PhysicalPlanTest.java
@@ -23,6 +23,11 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
import org.apache.iotdb.db.exception.StartupException;
import org.apache.iotdb.db.exception.metadata.MetadataException;
import org.apache.iotdb.db.exception.query.QueryProcessException;
@@ -510,6 +515,51 @@ public class PhysicalPlanTest {
}
@Test
+ public void testInOperator() throws QueryProcessException {
+ String sqlStr = "SELECT s1 FROM root.vehicle.d1 WHERE s1 in (25, 30, 40)";
+ PhysicalPlan plan = processor.parseSQLToPhysicalPlan(sqlStr);
+ IExpression queryFilter = ((QueryPlan) plan).getExpression();
+ List<String> valuesList = new ArrayList<>();
+ valuesList.add("25");
+ valuesList.add("30");
+ valuesList.add("40");
+ Collections.sort(valuesList);
+ Set<Float> values = new HashSet<>();
+ values.add(25.0f);
+ values.add(30.0f);
+ values.add(40.0f);
+ IExpression expect = new SingleSeriesExpression(new Path("root.vehicle.d1.s1"),
+ ValueFilter.in(values, false, valuesList.toString()));
+ assertEquals(expect.toString(), queryFilter.toString());
+ }
+
+ @Test
+ public void testNotInOperator() throws QueryProcessException {
+ String sqlStr = "SELECT s1 FROM root.vehicle.d1 WHERE s1 not in (25, 30, 40)";
+ PhysicalPlan plan = processor.parseSQLToPhysicalPlan(sqlStr);
+ IExpression queryFilter = ((QueryPlan) plan).getExpression();
+ List<String> valuesList = new ArrayList<>();
+ valuesList.add("25");
+ valuesList.add("30");
+ valuesList.add("40");
+ Collections.sort(valuesList);
+ Set<Float> values = new HashSet<>();
+ values.add(25.0f);
+ values.add(30.0f);
+ values.add(40.0f);
+ IExpression expect = new SingleSeriesExpression(new Path("root.vehicle.d1.s1"),
+ ValueFilter.in(values, true, valuesList.toString()));
+ assertEquals(expect.toString(), queryFilter.toString());
+
+ sqlStr = "SELECT s1 FROM root.vehicle.d1 WHERE not(s1 not in (25, 30, 40))";
+ plan = processor.parseSQLToPhysicalPlan(sqlStr);
+ queryFilter = ((QueryPlan) plan).getExpression();
+ expect = new SingleSeriesExpression(new Path("root.vehicle.d1.s1"),
+ ValueFilter.in(values, false, valuesList.toString()));
+ assertEquals(expect.toString(), queryFilter.toString());
+ }
+
+ @Test
public void testGrantWatermarkEmbedding()
throws QueryProcessException, MetadataException {
String sqlStr = "GRANT WATERMARK_EMBEDDING to a,b";
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/TimeFilter.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/TimeFilter.java
index d2a663a..007c813 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/TimeFilter.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/TimeFilter.java
@@ -18,11 +18,13 @@
*/
package org.apache.iotdb.tsfile.read.filter;
+import java.util.Set;
import org.apache.iotdb.tsfile.read.filter.basic.Filter;
import org.apache.iotdb.tsfile.read.filter.factory.FilterType;
import org.apache.iotdb.tsfile.read.filter.operator.Eq;
import org.apache.iotdb.tsfile.read.filter.operator.Gt;
import org.apache.iotdb.tsfile.read.filter.operator.GtEq;
+import org.apache.iotdb.tsfile.read.filter.operator.In;
import org.apache.iotdb.tsfile.read.filter.operator.Lt;
import org.apache.iotdb.tsfile.read.filter.operator.LtEq;
import org.apache.iotdb.tsfile.read.filter.operator.NotEq;
@@ -58,6 +60,17 @@ public class TimeFilter {
return new TimeNotEq(value);
}
+ public static TimeIn in(Set<Long> values, boolean not, String valueToString) {
+ return new TimeIn(values, not, valueToString);
+ }
+
+ public static class TimeIn extends In {
+
+ private TimeIn(Set<Long> values, boolean not, String valueToString) {
+ super(values, FilterType.TIME_FILTER,not, valueToString);
+ }
+ }
+
public static class TimeEq extends Eq {
private TimeEq(long value) {
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/ValueFilter.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/ValueFilter.java
index 18b1285..fa0c7c4 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/ValueFilter.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/ValueFilter.java
@@ -18,11 +18,13 @@
*/
package org.apache.iotdb.tsfile.read.filter;
+import java.util.Set;
import org.apache.iotdb.tsfile.read.filter.basic.Filter;
import org.apache.iotdb.tsfile.read.filter.factory.FilterType;
import org.apache.iotdb.tsfile.read.filter.operator.Eq;
import org.apache.iotdb.tsfile.read.filter.operator.Gt;
import org.apache.iotdb.tsfile.read.filter.operator.GtEq;
+import org.apache.iotdb.tsfile.read.filter.operator.In;
import org.apache.iotdb.tsfile.read.filter.operator.Lt;
import org.apache.iotdb.tsfile.read.filter.operator.LtEq;
import org.apache.iotdb.tsfile.read.filter.operator.NotEq;
@@ -50,6 +52,10 @@ public class ValueFilter {
return new ValueLtEq(value);
}
+ public static <T extends Comparable<T>> ValueIn<T> in(Set<T> values, boolean not, String valueToString){
+ return new ValueIn(values, not, valueToString);
+ }
+
public static ValueNotFilter not(Filter filter) {
return new ValueNotFilter(filter);
}
@@ -58,6 +64,13 @@ public class ValueFilter {
return new ValueNotEq(value);
}
+ public static class ValueIn<T extends Comparable<T>> extends In<T> {
+
+ private ValueIn(Set<T> values, boolean not, String valueToString) {
+ super(values, FilterType.VALUE_FILTER, not, valueToString);
+ }
+ }
+
public static class ValueEq<T extends Comparable<T>> extends Eq<T> {
private ValueEq(T value) {
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/factory/FilterFactory.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/factory/FilterFactory.java
index 7781e42..07f849a 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/factory/FilterFactory.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/factory/FilterFactory.java
@@ -30,8 +30,6 @@ import org.apache.iotdb.tsfile.read.filter.operator.LtEq;
import org.apache.iotdb.tsfile.read.filter.operator.NotEq;
import org.apache.iotdb.tsfile.read.filter.operator.NotFilter;
import org.apache.iotdb.tsfile.read.filter.operator.OrFilter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
public class FilterFactory {
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/factory/FilterSerializeId.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/factory/FilterSerializeId.java
index 1b20251..a76f1fa 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/factory/FilterSerializeId.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/factory/FilterSerializeId.java
@@ -20,5 +20,5 @@
package org.apache.iotdb.tsfile.read.filter.factory;
public enum FilterSerializeId {
- AND, EQ, GROUP_BY, GT, GTEQ, LT, LTEQ, NEQ, NOT, OR
+ AND, EQ, GROUP_BY, GT, GTEQ, LT, LTEQ, NEQ, NOT, OR, IN
}
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/Eq.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/Eq.java
index 9a6cc0e..931d046 100755
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/Eq.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/Eq.java
@@ -18,7 +18,6 @@
*/
package org.apache.iotdb.tsfile.read.filter.operator;
-import java.util.Objects;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.file.metadata.statistics.Statistics;
import org.apache.iotdb.tsfile.read.filter.basic.Filter;
@@ -45,7 +44,8 @@ public class Eq<T extends Comparable<T>> extends UnaryFilter<T> {
@Override
public boolean satisfy(Statistics statistics) {
if (filterType == FilterType.TIME_FILTER) {
- return ((Long) value) >= statistics.getStartTime() && ((Long) value) <= statistics.getEndTime();
+ return ((Long) value) >= statistics.getStartTime() && ((Long) value) <= statistics
+ .getEndTime();
} else {
if (statistics.getType() == TSDataType.TEXT || statistics.getType() == TSDataType.BOOLEAN) {
return true;
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/Eq.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/In.java
old mode 100755
new mode 100644
similarity index 50%
copy from tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/Eq.java
copy to tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/In.java
index 9a6cc0e..eb2c4c8
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/Eq.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/In.java
@@ -18,81 +18,105 @@
*/
package org.apache.iotdb.tsfile.read.filter.operator;
-import java.util.Objects;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.HashSet;
+import java.util.Set;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.file.metadata.statistics.Statistics;
import org.apache.iotdb.tsfile.read.filter.basic.Filter;
-import org.apache.iotdb.tsfile.read.filter.basic.UnaryFilter;
import org.apache.iotdb.tsfile.read.filter.factory.FilterSerializeId;
import org.apache.iotdb.tsfile.read.filter.factory.FilterType;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
/**
- * Equals.
+ * in clause.
*
* @param <T> comparable data type
*/
-public class Eq<T extends Comparable<T>> extends UnaryFilter<T> {
+public class In<T extends Comparable<T>> implements Filter {
- private static final long serialVersionUID = -6668083116644568248L;
+ private static final long serialVersionUID = 8572705136773595399L;
- public Eq() {
+ private Set<T> values;
+
+ private boolean not;
+
+ private String valueToString;
+
+ private FilterType filterType;
+
+ public In() {
}
- public Eq(T value, FilterType filterType) {
- super(value, filterType);
+ public In(Set<T> values, FilterType filterType, boolean not, String valueToString) {
+ this.values = values;
+ this.filterType = filterType;
+ this.not = not;
+ this.valueToString = valueToString;
}
@Override
public boolean satisfy(Statistics statistics) {
- if (filterType == FilterType.TIME_FILTER) {
- return ((Long) value) >= statistics.getStartTime() && ((Long) value) <= statistics.getEndTime();
- } else {
- if (statistics.getType() == TSDataType.TEXT || statistics.getType() == TSDataType.BOOLEAN) {
- return true;
- }
- return value.compareTo((T) statistics.getMinValue()) >= 0
- && value.compareTo((T) statistics.getMaxValue()) <= 0;
- }
+ return true;
}
@Override
public boolean satisfy(long time, Object value) {
Object v = filterType == FilterType.TIME_FILTER ? time : value;
- return this.value.equals(v);
+ return this.values.contains(v) != not;
}
@Override
public boolean satisfyStartEndTime(long startTime, long endTime) {
- if (filterType == FilterType.TIME_FILTER) {
- long time = (Long) value;
- return time <= endTime && time >= startTime;
- } else {
- return true;
- }
+ return true;
}
@Override
public boolean containStartEndTime(long startTime, long endTime) {
- if (filterType == FilterType.TIME_FILTER) {
- long time = (Long) value;
- return time == startTime && time == endTime;
- } else {
- return true;
- }
+ return true;
}
@Override
public Filter clone() {
- return new Eq(value, filterType);
+ return new In(values, filterType, not, valueToString);
+ }
+
+ @Override
+ public void serialize(DataOutputStream outputStream) {
+ try {
+ outputStream.write(getSerializeId().ordinal());
+ outputStream.write(filterType.ordinal());
+ ReadWriteIOUtils.write(not, outputStream);
+ ReadWriteIOUtils.write(valueToString, outputStream);
+ outputStream.write(values.size());
+ for (T value : values) {
+ ReadWriteIOUtils.writeObject(value, outputStream);
+ }
+ } catch (IOException ignored) {
+ // ignored
+ }
+ }
+
+ @Override
+ public void deserialize(ByteBuffer buffer) {
+ filterType = FilterType.values()[buffer.get()];
+ not = ReadWriteIOUtils.readBool(buffer);
+ valueToString = ReadWriteIOUtils.readString(buffer);
+ values = new HashSet<>();
+ for (int i = 0; i < buffer.get(); i++) {
+ values.add((T) ReadWriteIOUtils.readObject(buffer));
+ }
}
@Override
public String toString() {
- return getFilterType() + " == " + value;
+ return filterType + " < " + "reverse: " + not + ", " + valueToString;
}
@Override
public FilterSerializeId getSerializeId() {
- return FilterSerializeId.EQ;
+ return FilterSerializeId.IN;
}
}