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:43 UTC
[incubator-iotdb] 01/01: add IN operation
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;
}
}