This is an automated email from the ASF dual-hosted git repository.
jiangtian pushed a commit to branch new_java_interfaces
in repository https://gitbox.apache.org/repos/asf/tsfile.git
The following commit(s) were added to refs/heads/new_java_interfaces by this
push:
new bd1efe38 add tag filter eq
bd1efe38 is described below
commit bd1efe38616f01c2eaf13d09bff11721b87b3c9a
Author: Tian Jiang <[email protected]>
AuthorDate: Thu Apr 24 14:22:22 2025 +0800
add tag filter eq
---
.../src/main/codegen/dataModel/AllFilter.tdd | 5 +
.../codegen/templates/FilterOperatorsTemplate.ftl | 168 +++++++++++----------
.../src/main/codegen/templates/FilterTemplate.ftl | 7 +
.../tsfile/read/controller/DeviceMetaIterator.java | 12 +-
.../tsfile/read/controller/IMetadataQuerier.java | 4 +-
.../read/controller/MetadataQuerierByFileImpl.java | 6 +-
.../apache/tsfile/read/filter/basic/Filter.java | 2 +
.../tsfile/read/filter/basic/TimeFilter.java | 5 +
.../tsfile/read/filter/basic/ValueFilter.java | 7 +-
.../factory/TagFilterBuilder.java} | 39 +++--
.../apache/tsfile/read/filter/operator/And.java | 5 +
.../apache/tsfile/read/filter/operator/Not.java | 5 +
.../org/apache/tsfile/read/filter/operator/Or.java | 5 +
.../tsfile/read/query/dataset/ResultSet.java | 7 +-
.../tsfile/read/query/dataset/TableResultSet.java | 96 +++++++++++-
.../tsfile/read/query/dataset/TreeResultSet.java | 7 +
.../read/query/executor/TableQueryExecutor.java | 7 +-
.../query/executor/task/DeviceTaskIterator.java | 6 +-
.../tsfile/read/v4/DeviceTableModelReader.java | 12 +-
.../org/apache/tsfile/read/v4/ITsFileReader.java | 6 +
.../org/apache/tsfile/utils/ReadWriteIOUtils.java | 23 +++
.../apache/tsfile/read/query/ResultSetTest.java | 132 ++++++++++++++++
22 files changed, 444 insertions(+), 122 deletions(-)
diff --git a/java/tsfile/src/main/codegen/dataModel/AllFilter.tdd
b/java/tsfile/src/main/codegen/dataModel/AllFilter.tdd
index cb5815bc..d8dcd64e 100644
--- a/java/tsfile/src/main/codegen/dataModel/AllFilter.tdd
+++ b/java/tsfile/src/main/codegen/dataModel/AllFilter.tdd
@@ -52,6 +52,11 @@
"dataType": "Binary",
"javaBoxName": "String",
"classSerializeName": "STRING"
+ },
+ {
+ "dataType": "String",
+ "javaBoxName": "Tag",
+ "classSerializeName": "TAG"
}
]
}
\ No newline at end of file
diff --git a/java/tsfile/src/main/codegen/templates/FilterOperatorsTemplate.ftl
b/java/tsfile/src/main/codegen/templates/FilterOperatorsTemplate.ftl
index 77d394d1..c4f1243b 100644
--- a/java/tsfile/src/main/codegen/templates/FilterOperatorsTemplate.ftl
+++ b/java/tsfile/src/main/codegen/templates/FilterOperatorsTemplate.ftl
@@ -2,6 +2,12 @@
<#list filters as filter>
<#assign className = "${filter.javaBoxName}FilterOperators">
<#assign filterName = "${filter.javaBoxName}Filter">
+ <#if filter.javaBoxName == "Tag">
+ <#assign javaClassName = "String">
+ <#else>
+ <#assign javaClassName = "${filter.javaBoxName}">
+ </#if>
+
<@pp.changeOutputFile
name="/org/apache/tsfile/read/filter/operator/${className}.java" />
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -71,7 +77,7 @@ public final class ${className} {
protected ValueColumnCompareFilter(int measurementIndex,
${filter.dataType} constant) {
super(measurementIndex);
- <#if filter.dataType == "Binary">
+ <#if filter.dataType == "Binary" || filter.dataType == "String">
this.constant = Objects.requireNonNull(constant,
CONSTANT_CANNOT_BE_NULL_MSG);
<#else>
this.constant = constant;
@@ -81,7 +87,7 @@ public final class ${className} {
@SuppressWarnings("unchecked")
protected ValueColumnCompareFilter(ByteBuffer buffer) {
super(buffer);
- <#if filter.dataType == "Binary">
+ <#if filter.dataType == "Binary" || filter.dataType == "String">
this.constant =
Objects.requireNonNull(ReadWriteIOUtils.read${filter.dataType?cap_first}(buffer),
CONSTANT_CANNOT_BE_NULL_MSG);
<#else>
this.constant =
ReadWriteIOUtils.read${filter.dataType?cap_first}(buffer);
@@ -106,7 +112,7 @@ public final class ${className} {
return false;
}
ValueColumnCompareFilter that = (ValueColumnCompareFilter) o;
- <#if filter.dataType == "Binary">
+ <#if filter.dataType == "Binary" || filter.dataType == "String">
return Objects.equals(constant,that.constant);
<#else>
return constant == that.constant;
@@ -142,7 +148,7 @@ public final class ${className} {
@Override
public boolean valueSatisfy(${filter.dataType} value) {
- <#if filter.dataType == "Binary">
+ <#if filter.dataType == "Binary" || filter.dataType == "String">
return constant.equals(value);
<#else>
return constant == value;
@@ -152,8 +158,8 @@ public final class ${className} {
@Override
@SuppressWarnings("unchecked")
public boolean canSkip(Statistics<? extends Serializable> statistics) {
- <#if filter.dataType == "boolean" || filter.dataType == "Binary">
- <#if filter.javaBoxName == "String">
+ <#if filter.dataType == "boolean" || filter.dataType == "Binary" ||
filter.dataType == "String">
+ <#if filter.javaBoxName == "String" || filter.javaBoxName == "Tag">
if(statistics.isEmpty()){
return false;
}
@@ -167,15 +173,15 @@ public final class ${className} {
if(statistics.isEmpty()){
return false;
}
- return constant < (${filter.javaBoxName}) statistics.getMinValue()
- || constant > (${filter.javaBoxName}) statistics.getMaxValue();
+ return constant < (${javaClassName}) statistics.getMinValue()
+ || constant > (${javaClassName}) statistics.getMaxValue();
</#if>
}
@Override
@SuppressWarnings("unchecked")
public boolean allSatisfy(Statistics<? extends Serializable> statistics) {
- <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+ <#if filter.dataType == "boolean" || filter.dataType == "Binary" ||
filter.dataType == "String">
<#if filter.javaBoxName == "String">
if(statistics.isEmpty()){
return false;
@@ -190,8 +196,8 @@ public final class ${className} {
if(statistics.isEmpty()){
return false;
}
- return constant == (${filter.javaBoxName}) statistics.getMinValue()
- && constant == (${filter.javaBoxName}) statistics.getMaxValue();
+ return constant == (${javaClassName}) statistics.getMinValue()
+ && constant == (${javaClassName}) statistics.getMaxValue();
</#if>
}
@@ -223,7 +229,7 @@ public final class ${className} {
@Override
public boolean valueSatisfy(${filter.dataType} value) {
- <#if filter.dataType == "Binary">
+ <#if filter.dataType == "Binary" || filter.dataType == "String">
return !constant.equals(value);
<#else>
return constant != value;
@@ -233,7 +239,7 @@ public final class ${className} {
@Override
@SuppressWarnings("unchecked")
public boolean canSkip(Statistics<? extends Serializable> statistics) {
- <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+ <#if filter.dataType == "boolean" || filter.dataType == "Binary" ||
filter.dataType == "String">
<#if filter.javaBoxName == "String">
if(statistics.isEmpty()){
return false;
@@ -249,15 +255,15 @@ public final class ${className} {
return false;
}
// drop if this is a column where min = max = value
- return constant == (${filter.javaBoxName}) statistics.getMinValue()
- && constant == (${filter.javaBoxName}) statistics.getMaxValue();
+ return constant == (${javaClassName}) statistics.getMinValue()
+ && constant == (${javaClassName}) statistics.getMaxValue();
</#if>
}
@Override
@SuppressWarnings("unchecked")
public boolean allSatisfy(Statistics<? extends Serializable> statistics) {
- <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+ <#if filter.dataType == "boolean" || filter.dataType == "Binary" ||
filter.dataType == "String">
<#if filter.javaBoxName == "String">
if(statistics.isEmpty()){
return false;
@@ -271,8 +277,8 @@ public final class ${className} {
if(statistics.isEmpty()){
return false;
}
- return constant < (${filter.javaBoxName}) statistics.getMinValue()
- || constant > (${filter.javaBoxName}) statistics.getMaxValue();
+ return constant < (${javaClassName}) statistics.getMinValue()
+ || constant > (${javaClassName}) statistics.getMaxValue();
</#if>
}
@@ -307,7 +313,7 @@ public final class ${className} {
public boolean valueSatisfy(${filter.dataType} value) {
<#if filter.dataType == "boolean">
return Boolean.compare(constant,value) > 0;
- <#elseif filter.dataType == "Binary">
+ <#elseif filter.dataType == "Binary" || filter.dataType == "String">
return constant.compareTo(value) > 0;
<#else>
return constant > value;
@@ -317,7 +323,7 @@ public final class ${className} {
@Override
@SuppressWarnings("unchecked")
public boolean canSkip(Statistics<? extends Serializable> statistics) {
- <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+ <#if filter.dataType == "boolean" || filter.dataType == "Binary" ||
filter.dataType == "String">
<#if filter.javaBoxName == "String">
if(statistics.isEmpty()){
return false;
@@ -332,14 +338,14 @@ public final class ${className} {
return false;
}
// drop if value <= min
- return constant <= (${filter.javaBoxName}) statistics.getMinValue();
+ return constant <= (${javaClassName}) statistics.getMinValue();
</#if>
}
@Override
@SuppressWarnings("unchecked")
public boolean allSatisfy(Statistics<? extends Serializable> statistics) {
- <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+ <#if filter.dataType == "boolean" || filter.dataType == "Binary" ||
filter.dataType == "String">
<#if filter.javaBoxName == "String">
if(statistics.isEmpty()){
return false;
@@ -352,7 +358,7 @@ public final class ${className} {
if(statistics.isEmpty()){
return false;
}
- return constant > (${filter.javaBoxName}) statistics.getMaxValue();
+ return constant > (${javaClassName}) statistics.getMaxValue();
</#if>
}
@@ -387,7 +393,7 @@ public final class ${className} {
public boolean valueSatisfy(${filter.dataType} value) {
<#if filter.dataType == "boolean">
return Boolean.compare(constant,value) >= 0;
- <#elseif filter.dataType == "Binary">
+ <#elseif filter.dataType == "Binary" || filter.dataType == "String">
return constant.compareTo(value) >= 0;
<#else>
return constant >= value;
@@ -397,7 +403,7 @@ public final class ${className} {
@Override
@SuppressWarnings("unchecked")
public boolean canSkip(Statistics<? extends Serializable> statistics) {
- <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+ <#if filter.dataType == "boolean" || filter.dataType == "Binary" ||
filter.dataType == "String">
<#if filter.javaBoxName == "String">
if(statistics.isEmpty()){
return false;
@@ -412,14 +418,14 @@ public final class ${className} {
return false;
}
// drop if value < min
- return constant < (${filter.javaBoxName}) statistics.getMinValue();
+ return constant < (${javaClassName}) statistics.getMinValue();
</#if>
}
@Override
@SuppressWarnings("unchecked")
public boolean allSatisfy(Statistics<? extends Serializable> statistics) {
- <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+ <#if filter.dataType == "boolean" || filter.dataType == "Binary" ||
filter.dataType == "String">
<#if filter.javaBoxName == "String">
if(statistics.isEmpty()){
return false;
@@ -432,7 +438,7 @@ public final class ${className} {
if(statistics.isEmpty()){
return false;
}
- return constant >= (${filter.javaBoxName}) statistics.getMaxValue();
+ return constant >= (${javaClassName}) statistics.getMaxValue();
</#if>
}
@@ -467,7 +473,7 @@ public final class ${className} {
public boolean valueSatisfy(${filter.dataType} value) {
<#if filter.dataType == "boolean">
return Boolean.compare(constant,value) < 0;
- <#elseif filter.dataType == "Binary">
+ <#elseif filter.dataType == "Binary" || filter.dataType == "String">
return constant.compareTo(value) < 0;
<#else>
return constant < value;
@@ -477,7 +483,7 @@ public final class ${className} {
@Override
@SuppressWarnings("unchecked")
public boolean canSkip(Statistics<? extends Serializable> statistics) {
- <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+ <#if filter.dataType == "boolean" || filter.dataType == "Binary" ||
filter.dataType == "String">
<#if filter.javaBoxName == "String">
if(statistics.isEmpty()){
return false;
@@ -492,14 +498,14 @@ public final class ${className} {
return false;
}
// drop if value >= max
- return constant >= (${filter.javaBoxName}) statistics.getMaxValue();
+ return constant >= (${javaClassName}) statistics.getMaxValue();
</#if>
}
@Override
@SuppressWarnings("unchecked")
public boolean allSatisfy(Statistics<? extends Serializable> statistics) {
- <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+ <#if filter.dataType == "boolean" || filter.dataType == "Binary" ||
filter.dataType == "String">
<#if filter.javaBoxName == "String">
if(statistics.isEmpty()){
return false;
@@ -512,7 +518,7 @@ public final class ${className} {
if(statistics.isEmpty()){
return false;
}
- return constant < (${filter.javaBoxName}) statistics.getMinValue();
+ return constant < (${javaClassName}) statistics.getMinValue();
</#if>
}
@@ -547,7 +553,7 @@ public final class ${className} {
public boolean valueSatisfy(${filter.dataType} value) {
<#if filter.dataType == "boolean">
return Boolean.compare(constant,value) <= 0;
- <#elseif filter.dataType == "Binary">
+ <#elseif filter.dataType == "Binary" || filter.dataType == "String">
return constant.compareTo(value) <= 0;
<#else>
return constant <= value;
@@ -557,7 +563,7 @@ public final class ${className} {
@Override
@SuppressWarnings("unchecked")
public boolean canSkip(Statistics<? extends Serializable> statistics) {
- <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+ <#if filter.dataType == "boolean" || filter.dataType == "Binary" ||
filter.dataType == "String">
<#if filter.javaBoxName == "String">
if(statistics.isEmpty()){
return false;
@@ -572,14 +578,14 @@ public final class ${className} {
return false;
}
// drop if value > max
- return constant > (${filter.javaBoxName}) statistics.getMaxValue();
+ return constant > (${javaClassName}) statistics.getMaxValue();
</#if>
}
@Override
@SuppressWarnings("unchecked")
public boolean allSatisfy(Statistics<? extends Serializable> statistics) {
- <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+ <#if filter.dataType == "boolean" || filter.dataType == "Binary" ||
filter.dataType == "String">
<#if filter.javaBoxName == "String">
if(statistics.isEmpty()){
return false;
@@ -592,7 +598,7 @@ public final class ${className} {
if(statistics.isEmpty()){
return false;
}
- return constant <= (${filter.javaBoxName}) statistics.getMinValue();
+ return constant <= (${javaClassName}) statistics.getMinValue();
</#if>
}
@@ -615,7 +621,7 @@ public final class ${className} {
protected ValueColumnRangeFilter(int measurementIndex, ${filter.dataType}
min, ${filter.dataType} max) {
super(measurementIndex);
- <#if filter.dataType == "Binary">
+ <#if filter.dataType == "Binary" || filter.dataType == "String">
this.min = Objects.requireNonNull(min,"min cannot be null");
this.max = Objects.requireNonNull(max,"max cannot be null");
<#else>
@@ -627,7 +633,7 @@ public final class ${className} {
@SuppressWarnings("unchecked")
protected ValueColumnRangeFilter(ByteBuffer buffer) {
super(buffer);
- <#if filter.dataType == "Binary">
+ <#if filter.dataType == "Binary" || filter.dataType == "String">
this.min =
Objects.requireNonNull(ReadWriteIOUtils.read${filter.dataType?cap_first}(buffer),"min
cannot be null");
this.max =
Objects.requireNonNull(ReadWriteIOUtils.read${filter.dataType?cap_first}(buffer),"max
cannot be null");
<#else>
@@ -655,7 +661,7 @@ public final class ${className} {
return false;
}
ValueColumnRangeFilter that = (ValueColumnRangeFilter) o;
- <#if filter.dataType == "Binary">
+ <#if filter.dataType == "Binary" || filter.dataType == "String">
return min.equals(that.min) && max.equals(that.max);
<#else>
return min == that.min && max == that.max;
@@ -696,7 +702,7 @@ public final class ${className} {
<#if filter.dataType == "boolean">
return Boolean.compare(min,value) <= 0
&& Boolean.compare(max,value) >= 0;
- <#elseif filter.dataType == "Binary">
+ <#elseif filter.dataType == "Binary" || filter.dataType == "String">
return min.compareTo(value) <= 0
&& max.compareTo(value) >= 0;
<#else>
@@ -707,7 +713,7 @@ public final class ${className} {
@Override
@SuppressWarnings("unchecked")
public boolean canSkip(Statistics<? extends Serializable> statistics) {
- <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+ <#if filter.dataType == "boolean" || filter.dataType == "Binary" ||
filter.dataType == "String">
<#if filter.javaBoxName == "String">
if(statistics.isEmpty()){
return false;
@@ -722,15 +728,15 @@ public final class ${className} {
if(statistics.isEmpty()){
return false;
}
- return (${filter.javaBoxName}) statistics.getMaxValue() < min
- || (${filter.javaBoxName}) statistics.getMinValue() > max;
+ return (${javaClassName}) statistics.getMaxValue() < min
+ || (${javaClassName}) statistics.getMinValue() > max;
</#if>
}
@Override
@SuppressWarnings("unchecked")
public boolean allSatisfy(Statistics<? extends Serializable> statistics) {
- <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+ <#if filter.dataType == "boolean" || filter.dataType == "Binary" ||
filter.dataType == "String">
<#if filter.javaBoxName == "String">
if(statistics.isEmpty()){
return false;
@@ -744,8 +750,8 @@ public final class ${className} {
if(statistics.isEmpty()){
return false;
}
- return (${filter.javaBoxName}) statistics.getMinValue() >= min
- && (${filter.javaBoxName}) statistics.getMaxValue() <= max;
+ return (${javaClassName}) statistics.getMinValue() >= min
+ && (${javaClassName}) statistics.getMaxValue() <= max;
</#if>
}
@@ -781,7 +787,7 @@ public final class ${className} {
<#if filter.dataType == "boolean">
return Boolean.compare(min,value) > 0
|| Boolean.compare(max,value) < 0;
- <#elseif filter.dataType == "Binary">
+ <#elseif filter.dataType == "Binary" || filter.dataType == "String">
return min.compareTo(value) > 0 || max.compareTo(value) < 0;
<#else>
return min > value || max < value;
@@ -791,7 +797,7 @@ public final class ${className} {
@Override
@SuppressWarnings("unchecked")
public boolean canSkip(Statistics<? extends Serializable> statistics) {
- <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+ <#if filter.dataType == "boolean" || filter.dataType == "Binary" ||
filter.dataType == "String">
<#if filter.javaBoxName == "String">
if(statistics.isEmpty()){
return false;
@@ -806,15 +812,15 @@ public final class ${className} {
if(statistics.isEmpty()){
return false;
}
- return (${filter.javaBoxName}) statistics.getMinValue() >= min
- && (${filter.javaBoxName}) statistics.getMaxValue() <= max;
+ return (${javaClassName}) statistics.getMinValue() >= min
+ && (${javaClassName}) statistics.getMaxValue() <= max;
</#if>
}
@Override
@SuppressWarnings("unchecked")
public boolean allSatisfy(Statistics<? extends Serializable> statistics) {
- <#if filter.dataType == "boolean" || filter.dataType == "Binary">
+ <#if filter.dataType == "boolean" || filter.dataType == "Binary" ||
filter.dataType == "String">
<#if filter.javaBoxName == "String">
if(statistics.isEmpty()){
return false;
@@ -828,8 +834,8 @@ public final class ${className} {
if(statistics.isEmpty()){
return false;
}
- return (${filter.javaBoxName}) statistics.getMinValue() > max
- || (${filter.javaBoxName}) statistics.getMaxValue() < min;
+ return (${javaClassName}) statistics.getMinValue() > max
+ || (${javaClassName}) statistics.getMaxValue() < min;
</#if>
}
@@ -850,7 +856,7 @@ public final class ${className} {
<#if filter.javaBoxName == "String">
protected final Set<${filter.dataType}> candidates;
<#else>
- protected final Set<${filter.javaBoxName}> candidates;
+ protected final Set<${javaClassName}> candidates;
</#if>
protected final ${filter.dataType} candidatesMin;
@@ -859,7 +865,7 @@ public final class ${className} {
<#if filter.javaBoxName == "String">
protected ValueColumnSetFilter(int measurementIndex,
Set<${filter.dataType}> candidates) {
<#else>
- protected ValueColumnSetFilter(int measurementIndex,
Set<${filter.javaBoxName}> candidates) {
+ protected ValueColumnSetFilter(int measurementIndex, Set<${javaClassName}>
candidates) {
</#if>
super(measurementIndex);
this.candidates = candidates;
@@ -867,18 +873,18 @@ public final class ${className} {
<#if filter.javaBoxName == "String">
Set<${filter.dataType}> filteredSet =
candidates.stream().filter(Objects::nonNull).collect(Collectors.toSet());
<#else>
- Set<${filter.javaBoxName}> filteredSet =
candidates.stream().filter(Objects::nonNull).collect(Collectors.toSet());
+ Set<${javaClassName}> filteredSet =
candidates.stream().filter(Objects::nonNull).collect(Collectors.toSet());
</#if>
<#if filter.dataType == "boolean">
// BooleanStatistics is not available
this.candidatesMin = false;
this.candidatesMax = false;
- <#elseif filter.dataType == "Binary">
+ <#elseif filter.dataType == "Binary" || filter.dataType == "String">
this.candidatesMin = !filteredSet.isEmpty() ?
Collections.min(filteredSet) : null;
this.candidatesMax = !filteredSet.isEmpty() ?
Collections.max(filteredSet) : null;
<#else>
- this.candidatesMin = !filteredSet.isEmpty() ?
Collections.min(filteredSet) : ${filter.javaBoxName}.MIN_VALUE;
- this.candidatesMax = !filteredSet.isEmpty() ?
Collections.max(filteredSet) : ${filter.javaBoxName}.MAX_VALUE;
+ this.candidatesMin = !filteredSet.isEmpty() ?
Collections.min(filteredSet) : ${javaClassName}.MIN_VALUE;
+ this.candidatesMax = !filteredSet.isEmpty() ?
Collections.max(filteredSet) : ${javaClassName}.MAX_VALUE;
</#if>
}
@@ -888,18 +894,18 @@ public final class ${className} {
<#if filter.javaBoxName == "String">
this.candidates = ReadWriteIOUtils.read${filter.dataType}Set(buffer);
<#else>
- this.candidates = ReadWriteIOUtils.read${filter.javaBoxName}Set(buffer);
+ this.candidates = ReadWriteIOUtils.read${javaClassName}Set(buffer);
</#if>
<#if filter.dataType == "boolean">
// BooleanStatistics is not available
this.candidatesMin = false;
this.candidatesMax = false;
- <#elseif filter.dataType == "Binary">
+ <#elseif filter.dataType == "Binary" || filter.dataType == "String">
this.candidatesMin = !candidates.isEmpty() ? Collections.min(candidates)
: null;
this.candidatesMax = !candidates.isEmpty() ? Collections.max(candidates)
: null;
<#else>
- this.candidatesMin = !candidates.isEmpty() ? Collections.min(candidates)
: ${filter.javaBoxName}.MAX_VALUE;
- this.candidatesMax = !candidates.isEmpty() ? Collections.max(candidates)
: ${filter.javaBoxName}.MAX_VALUE;
+ this.candidatesMin = !candidates.isEmpty() ? Collections.min(candidates)
: ${javaClassName}.MAX_VALUE;
+ this.candidatesMax = !candidates.isEmpty() ? Collections.max(candidates)
: ${javaClassName}.MAX_VALUE;
</#if>
if(hasNull){
this.candidates.add(null);
@@ -913,7 +919,7 @@ public final class ${className} {
<#if filter.javaBoxName == "String">
ReadWriteIOUtils.write${filter.dataType}Set(candidates, outputStream);
<#else>
- ReadWriteIOUtils.write${filter.javaBoxName}Set(candidates, outputStream);
+ ReadWriteIOUtils.write${javaClassName}Set(candidates, outputStream);
</#if>
}
@@ -951,7 +957,7 @@ public final class ${className} {
super(measurementIndex, candidates);
}
<#else>
- public ValueIn(int measurementIndex, Set<${filter.javaBoxName}>
candidates) {
+ public ValueIn(int measurementIndex, Set<${javaClassName}> candidates) {
super(measurementIndex, candidates);
}
</#if>
@@ -962,7 +968,7 @@ public final class ${className} {
@Override
public boolean valueSatisfy(Object value){
- return candidates.contains((${filter.javaBoxName}) value);
+ return candidates.contains((${javaClassName}) value);
}
@Override
@@ -990,12 +996,12 @@ public final class ${className} {
if (statistics.isPresent()) {
Statistics<? extends Serializable> stat = statistics.get();
- <#if filter.dataType == "Binary" && filter.javaBoxName == "String">
+ <#if (filter.dataType == "Binary" && filter.javaBoxName == "String")
|| (filter.dataType == "String" && filter.javaBoxName == "Tag")>
${filter.dataType} valuesMin = (${filter.dataType}) stat.getMinValue();
${filter.dataType} valuesMax = (${filter.dataType}) stat.getMaxValue();
<#else>
- ${filter.javaBoxName} valuesMin = (${filter.javaBoxName})
stat.getMinValue();
- ${filter.javaBoxName} valuesMax = (${filter.javaBoxName})
stat.getMaxValue();
+ ${javaClassName} valuesMin = (${javaClassName}) stat.getMinValue();
+ ${javaClassName} valuesMax = (${javaClassName}) stat.getMaxValue();
</#if>
// All values are same
if (valuesMin.equals(valuesMax)) {
@@ -1003,7 +1009,7 @@ public final class ${className} {
} else {
if (!candidates.isEmpty()) {
// All values are less than min, or greater than max
- <#if filter.dataType == "Binary" && filter.javaBoxName == "String">
+ <#if (filter.dataType == "Binary" && filter.javaBoxName ==
"String") || (filter.dataType == "String" && filter.javaBoxName == "Tag")>
return candidatesMin.compareTo(valuesMax) > 0
|| candidatesMax.compareTo(valuesMin) < 0;
<#else>
@@ -1044,12 +1050,12 @@ public final class ${className} {
// All values are same
if (statistics.isPresent()) {
Statistics<? extends Serializable> stat = statistics.get();
- <#if filter.dataType == "Binary" && filter.javaBoxName == "String">
+ <#if (filter.dataType == "Binary" && filter.javaBoxName == "String")
|| (filter.dataType == "String" && filter.javaBoxName == "Tag")>
${filter.dataType} valuesMin = (${filter.dataType}) stat.getMinValue();
${filter.dataType} valuesMax = (${filter.dataType}) stat.getMaxValue();
<#else>
- ${filter.javaBoxName} valuesMin = (${filter.javaBoxName})
stat.getMinValue();
- ${filter.javaBoxName} valuesMax = (${filter.javaBoxName})
stat.getMaxValue();
+ ${javaClassName} valuesMin = (${javaClassName}) stat.getMinValue();
+ ${javaClassName} valuesMax = (${javaClassName}) stat.getMaxValue();
</#if>
// All values are same
if (valuesMin.equals(valuesMax)) {
@@ -1095,7 +1101,7 @@ public final class ${className} {
super(measurementIndex, candidates);
}
<#else>
- public ValueNotIn(int measurementIndex, Set<${filter.javaBoxName}>
candidates) {
+ public ValueNotIn(int measurementIndex, Set<${javaClassName}> candidates) {
super(measurementIndex, candidates);
}
</#if>
@@ -1106,7 +1112,7 @@ public final class ${className} {
@Override
public boolean valueSatisfy(Object value){
- return !candidates.contains((${filter.javaBoxName}) value);
+ return !candidates.contains((${javaClassName}) value);
}
@Override
@@ -1203,7 +1209,7 @@ public final class ${className} {
@Override
public boolean valueSatisfy(${filter.dataType} value) {
- <#if filter.dataType == "Binary">
+ <#if filter.dataType == "Binary" || filter.dataType == "String">
return pattern.matcher(new MatcherInput(value.toString(), new
AccessCount())).find();
<#else>
return pattern.matcher(new MatcherInput(String.valueOf(value), new
AccessCount())).find();
@@ -1248,7 +1254,7 @@ public final class ${className} {
@Override
public boolean valueSatisfy(${filter.dataType} value) {
- <#if filter.dataType == "Binary">
+ <#if filter.dataType == "Binary" || filter.dataType == "String">
return !pattern.matcher(new MatcherInput(value.toString(), new
AccessCount())).find();
<#else>
return !pattern.matcher(new MatcherInput(String.valueOf(value), new
AccessCount())).find();
@@ -1353,7 +1359,7 @@ public final class ${className} {
@Override
public boolean valueSatisfy(${filter.dataType} value) {
- <#if filter.dataType == "Binary">
+ <#if filter.dataType == "Binary" || filter.dataType == "String">
return pattern.getMatcher().match(value.toString().getBytes());
<#else>
return pattern.getMatcher().match(String.valueOf(value).getBytes());
@@ -1398,7 +1404,7 @@ public final class ${className} {
@Override
public boolean valueSatisfy(${filter.dataType} value) {
- <#if filter.dataType == "Binary">
+ <#if filter.dataType == "Binary" || filter.dataType == "String">
return !pattern.getMatcher().match(value.toString().getBytes());
<#else>
return !pattern.getMatcher().match(String.valueOf(value).getBytes());
diff --git a/java/tsfile/src/main/codegen/templates/FilterTemplate.ftl
b/java/tsfile/src/main/codegen/templates/FilterTemplate.ftl
index e1fd9fef..d0574842 100644
--- a/java/tsfile/src/main/codegen/templates/FilterTemplate.ftl
+++ b/java/tsfile/src/main/codegen/templates/FilterTemplate.ftl
@@ -66,6 +66,7 @@ public abstract class ${className} extends ValueFilter {
protected abstract boolean valueSatisfy(${filter.dataType} value);
+ <#if filter.javaBoxName != "Tag">
@Override
public boolean[] satisfyTsBlock(boolean[] selection, TsBlock tsBlock) {
Column valueColumn = tsBlock.getValueColumns()[measurementIndex];
@@ -83,6 +84,12 @@ public abstract class ${className} extends ValueFilter {
}
return satisfyInfo;
}
+ <#else >
+ @Override
+ public boolean[] satisfyTsBlock(boolean[] selection, TsBlock tsBlock) {
+ throw new IllegalArgumentException("TagFilter cannot be applied to
TsBlock");
+ }
+ </#if>
@Override
public void serialize(DataOutputStream outputStream) throws IOException {
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/controller/DeviceMetaIterator.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/controller/DeviceMetaIterator.java
index 4445bf9b..74c99efa 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/controller/DeviceMetaIterator.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/controller/DeviceMetaIterator.java
@@ -24,7 +24,7 @@ import org.apache.tsfile.file.metadata.IDeviceID;
import org.apache.tsfile.file.metadata.MetadataIndexNode;
import org.apache.tsfile.file.metadata.enums.MetadataIndexNodeType;
import org.apache.tsfile.read.TsFileSequenceReader;
-import org.apache.tsfile.read.expression.ExpressionTree;
+import org.apache.tsfile.read.filter.basic.Filter;
import org.apache.tsfile.utils.Pair;
import org.slf4j.Logger;
@@ -43,15 +43,15 @@ public class DeviceMetaIterator implements
Iterator<Pair<IDeviceID, MetadataInde
private final TsFileSequenceReader tsFileSequenceReader;
private final Queue<MetadataIndexNode> metadataIndexNodes = new
ArrayDeque<>();
private final Queue<Pair<IDeviceID, MetadataIndexNode>> resultCache = new
ArrayDeque<>();
- private final ExpressionTree idFilter;
+ private final Filter tagFilter;
public DeviceMetaIterator(
TsFileSequenceReader tsFileSequenceReader,
MetadataIndexNode metadataIndexNode,
- ExpressionTree idFilter) {
+ Filter tagFilter) {
this.tsFileSequenceReader = tsFileSequenceReader;
this.metadataIndexNodes.add(metadataIndexNode);
- this.idFilter = idFilter;
+ this.tagFilter = tagFilter;
}
@Override
@@ -74,7 +74,8 @@ public class DeviceMetaIterator implements
Iterator<Pair<IDeviceID, MetadataInde
for (int i = 0; i < leafChildren.size(); i++) {
IMetadataIndexEntry child = leafChildren.get(i);
final IDeviceID deviceID = ((DeviceMetadataIndexEntry)
child).getDeviceID();
- if (idFilter != null && !idFilter.satisfy(deviceID)) {
+ // time is only a placeholder here
+ if (tagFilter != null && !tagFilter.satisfyRow(0,
deviceID.getSegments())) {
continue;
}
@@ -114,6 +115,7 @@ public class DeviceMetaIterator implements
Iterator<Pair<IDeviceID, MetadataInde
if (!resultCache.isEmpty()) {
return;
}
+ break;
case INTERNAL_DEVICE:
loadInternalNode(currentNode);
break;
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/controller/IMetadataQuerier.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/controller/IMetadataQuerier.java
index 3503e49e..3f74178d 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/controller/IMetadataQuerier.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/controller/IMetadataQuerier.java
@@ -28,7 +28,7 @@ import org.apache.tsfile.file.metadata.TableSchema;
import org.apache.tsfile.file.metadata.TsFileMetadata;
import org.apache.tsfile.read.common.Path;
import org.apache.tsfile.read.common.TimeRange;
-import org.apache.tsfile.read.expression.ExpressionTree;
+import org.apache.tsfile.read.filter.basic.Filter;
import org.apache.tsfile.utils.Pair;
import java.io.IOException;
@@ -87,5 +87,5 @@ public interface IMetadataQuerier {
void clear();
Iterator<Pair<IDeviceID, MetadataIndexNode>> deviceIterator(
- MetadataIndexNode root, ExpressionTree idFilter);
+ MetadataIndexNode root, Filter idFilter);
}
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/controller/MetadataQuerierByFileImpl.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/controller/MetadataQuerierByFileImpl.java
index ae7fb9ee..68e19530 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/controller/MetadataQuerierByFileImpl.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/controller/MetadataQuerierByFileImpl.java
@@ -34,7 +34,7 @@ import org.apache.tsfile.read.TsFileSequenceReader;
import org.apache.tsfile.read.TsFileSequenceReader.LocateStatus;
import org.apache.tsfile.read.common.Path;
import org.apache.tsfile.read.common.TimeRange;
-import org.apache.tsfile.read.expression.ExpressionTree;
+import org.apache.tsfile.read.filter.basic.Filter;
import org.apache.tsfile.utils.Pair;
import java.io.IOException;
@@ -306,7 +306,7 @@ public class MetadataQuerierByFileImpl implements
IMetadataQuerier {
@Override
public Iterator<Pair<IDeviceID, MetadataIndexNode>> deviceIterator(
- MetadataIndexNode root, ExpressionTree idFilter) {
- return new DeviceMetaIterator(tsFileReader, root, idFilter);
+ MetadataIndexNode root, Filter tagFilter) {
+ return new DeviceMetaIterator(tsFileReader, root, tagFilter);
}
}
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/Filter.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/Filter.java
index cc48210d..a5aac76c 100755
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/Filter.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/Filter.java
@@ -77,6 +77,8 @@ public abstract class Filter {
public abstract boolean satisfyBinary(long time, Binary value);
+ public abstract boolean satisfyString(long time, String value);
+
/**
* To examine whether the row(with time and values) is satisfied with the
filter.
*
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/TimeFilter.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/TimeFilter.java
index 18d444d7..a23ee31a 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/TimeFilter.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/TimeFilter.java
@@ -74,6 +74,11 @@ public abstract class TimeFilter extends Filter {
return timeSatisfy(time);
}
+ @Override
+ public boolean satisfyString(long time, String value) {
+ return timeSatisfy(time);
+ }
+
@Override
public boolean satisfyRow(long time, Object[] values) {
// only use time to filter
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/ValueFilter.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/ValueFilter.java
index e1ae98bb..d715352f 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/ValueFilter.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/basic/ValueFilter.java
@@ -84,6 +84,11 @@ public abstract class ValueFilter extends Filter {
throw new UnSupportedDataTypeException(getClass().getName());
}
+ @Override
+ public boolean satisfyString(long time, String value) {
+ throw new UnSupportedDataTypeException(getClass().getName());
+ }
+
@Override
public boolean satisfyBinary(long time, Binary value) {
throw new UnSupportedDataTypeException(getClass().getName());
@@ -91,7 +96,7 @@ public abstract class ValueFilter extends Filter {
@Override
public boolean satisfyRow(long time, Object[] values) {
- return satisfy(time, values[measurementIndex]);
+ return satisfy(time, measurementIndex < values.length ?
values[measurementIndex] : null);
}
@Override
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/v4/ITsFileReader.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/factory/TagFilterBuilder.java
similarity index 53%
copy from java/tsfile/src/main/java/org/apache/tsfile/read/v4/ITsFileReader.java
copy to
java/tsfile/src/main/java/org/apache/tsfile/read/filter/factory/TagFilterBuilder.java
index 885e8452..a3159509 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/v4/ITsFileReader.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/factory/TagFilterBuilder.java
@@ -17,31 +17,30 @@
* under the License.
*/
-package org.apache.tsfile.read.v4;
+package org.apache.tsfile.read.filter.factory;
import org.apache.tsfile.annotations.TsFileApi;
-import org.apache.tsfile.exception.read.ReadProcessException;
-import org.apache.tsfile.exception.write.NoMeasurementException;
-import org.apache.tsfile.exception.write.NoTableException;
import org.apache.tsfile.file.metadata.TableSchema;
-import org.apache.tsfile.read.query.dataset.ResultSet;
+import org.apache.tsfile.read.filter.basic.Filter;
+import org.apache.tsfile.read.filter.operator.TagFilterOperators.ValueEq;
+import org.apache.tsfile.write.schema.IMeasurementSchema;
-import java.io.IOException;
-import java.util.List;
-import java.util.Optional;
+public class TagFilterBuilder {
+ private TableSchema tableSchema;
-public interface ITsFileReader extends AutoCloseable {
+ public TagFilterBuilder(TableSchema tableSchema) {
+ this.tableSchema = tableSchema;
+ }
@TsFileApi
- ResultSet query(String tableName, List<String> columnNames, long startTime,
long endTime)
- throws ReadProcessException, IOException, NoTableException,
NoMeasurementException;
-
- @TsFileApi
- Optional<TableSchema> getTableSchemas(String tableName) throws IOException;
-
- @TsFileApi
- List<TableSchema> getAllTableSchema() throws IOException;
-
- @TsFileApi
- void close();
+ public Filter eq(String columnName, Object value) {
+ int idColumnOrder = tableSchema.findIdColumnOrder(columnName);
+ if (idColumnOrder == -1) {
+ throw new IllegalArgumentException("Column '" + columnName + "' is not a
tag column");
+ }
+ IMeasurementSchema columnSchema = tableSchema.findColumnSchema(columnName);
+
+ // +1 for table name
+ return new ValueEq(idColumnOrder + 1, (String) value);
+ }
}
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/And.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/And.java
index de0f3381..8df4e509 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/And.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/And.java
@@ -77,6 +77,11 @@ public class And extends BinaryLogicalFilter {
return left.satisfyBinary(time, value) && right.satisfyBinary(time, value);
}
+ @Override
+ public boolean satisfyString(long time, String value) {
+ return left.satisfyString(time, value) && right.satisfyString(time, value);
+ }
+
@Override
public boolean satisfyRow(long time, Object[] values) {
return left.satisfyRow(time, values) && right.satisfyRow(time, values);
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/Not.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/Not.java
index 00918915..e02a3697 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/Not.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/Not.java
@@ -90,6 +90,11 @@ public class Not extends Filter {
return !filter.satisfyRow(time, values);
}
+ @Override
+ public boolean satisfyString(long time, String value) {
+ return !filter.satisfyString(time, value);
+ }
+
@Override
public boolean satisfyBooleanRow(long time, boolean[] values) {
return !filter.satisfyBooleanRow(time, values);
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/Or.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/Or.java
index f0f1c2f1..97a78758 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/Or.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/Or.java
@@ -77,6 +77,11 @@ public class Or extends BinaryLogicalFilter {
return left.satisfyBinary(time, value) || right.satisfyBinary(time, value);
}
+ @Override
+ public boolean satisfyString(long time, String value) {
+ return left.satisfyString(time, value) || right.satisfyString(time, value);
+ }
+
@Override
public boolean satisfyRow(long time, Object[] values) {
return left.satisfyRow(time, values) || right.satisfyRow(time, values);
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/query/dataset/ResultSet.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/query/dataset/ResultSet.java
index 0f2d72bf..2e5d0706 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/query/dataset/ResultSet.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/query/dataset/ResultSet.java
@@ -20,9 +20,11 @@
package org.apache.tsfile.read.query.dataset;
import org.apache.tsfile.annotations.TsFileApi;
+import org.apache.tsfile.write.record.TSRecord;
import java.io.IOException;
import java.time.LocalDate;
+import java.util.Iterator;
public interface ResultSet extends AutoCloseable {
@@ -87,5 +89,8 @@ public interface ResultSet extends AutoCloseable {
boolean isNull(int columnIndex);
@TsFileApi
- public abstract void close();
+ void close();
+
+ @TsFileApi
+ Iterator<TSRecord> recordIterator();
}
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/query/dataset/TableResultSet.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/query/dataset/TableResultSet.java
index 5e050774..8a585df8 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/query/dataset/TableResultSet.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/query/dataset/TableResultSet.java
@@ -26,27 +26,36 @@ import org.apache.tsfile.read.common.RowRecord;
import org.apache.tsfile.read.common.block.TsBlock;
import org.apache.tsfile.read.reader.IPointReader;
import org.apache.tsfile.read.reader.block.TsBlockReader;
+import org.apache.tsfile.write.record.TSRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
+import java.util.Iterator;
import java.util.List;
+import java.util.NoSuchElementException;
public class TableResultSet extends AbstractResultSet {
+
private static final Logger LOG =
LoggerFactory.getLogger(TableResultSet.class);
private TsBlockReader tsBlockReader;
private IPointReader tsBlockPointReader;
private List<String> columnNameList;
private List<TSDataType> dataTypeList;
+ private String tableName;
public TableResultSet(
- TsBlockReader tsBlockReader, List<String> columnNameList,
List<TSDataType> dataTypeList) {
+ TsBlockReader tsBlockReader,
+ List<String> columnNameList,
+ List<TSDataType> dataTypeList,
+ String tableName) {
super(columnNameList, dataTypeList);
this.tsBlockReader = tsBlockReader;
this.columnNameList = columnNameList;
this.dataTypeList = dataTypeList;
+ this.tableName = tableName;
}
@Override
@@ -85,4 +94,89 @@ public class TableResultSet extends AbstractResultSet {
LOG.error("Failed to close tsBlockReader");
}
}
+
+ @Override
+ public Iterator<TSRecord> recordIterator() {
+ return new RecordIterator();
+ }
+
+ private class RecordIterator implements Iterator<TSRecord> {
+
+ private TSRecord cachedRecord = null;
+ private boolean exhausted = false;
+
+ @Override
+ public boolean hasNext() {
+ if (cachedRecord != null) {
+ return true;
+ }
+ if (exhausted) {
+ return false;
+ }
+
+ try {
+ return cacheNextRecord();
+ } catch (IOException e) {
+ throw new NoSuchElementException(e.toString());
+ }
+ }
+
+ private boolean cacheNextRecord() throws IOException {
+ boolean next = TableResultSet.this.next();
+ if (!next) {
+ exhausted = true;
+ return false;
+ }
+
+ cachedRecord = new TSRecord(tableName, getLong("Time"));
+ for (int i = 0; i < columnNameList.size(); i++) {
+ Field field = currentRow.getFields().get(i);
+ if (field != null) {
+ switch (field.getDataType()) {
+ case INT32:
+ case DATE:
+ cachedRecord.addPoint(columnNameList.get(i), field.getIntV());
+ break;
+ case INT64:
+ case TIMESTAMP:
+ cachedRecord.addPoint(columnNameList.get(i), field.getLongV());
+ break;
+ case FLOAT:
+ cachedRecord.addPoint(columnNameList.get(i), field.getFloatV());
+ break;
+ case DOUBLE:
+ cachedRecord.addPoint(columnNameList.get(i), field.getDoubleV());
+ break;
+ case STRING:
+ case TEXT:
+ cachedRecord.addPoint(columnNameList.get(i),
field.getStringValue());
+ break;
+ case BLOB:
+ cachedRecord.addPoint(columnNameList.get(i),
field.getBinaryV().getValues());
+ break;
+ case BOOLEAN:
+ cachedRecord.addPoint(columnNameList.get(i), field.getBoolV());
+ break;
+ case VECTOR:
+ case UNKNOWN:
+ default:
+ break;
+ }
+ } else {
+ cachedRecord.dataPointList.add(null);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public TSRecord next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ TSRecord ret = cachedRecord;
+ cachedRecord = null;
+ return ret;
+ }
+ }
}
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/query/dataset/TreeResultSet.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/query/dataset/TreeResultSet.java
index 0f3aade6..1f12cc62 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/query/dataset/TreeResultSet.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/query/dataset/TreeResultSet.java
@@ -21,8 +21,10 @@ package org.apache.tsfile.read.query.dataset;
import org.apache.tsfile.annotations.TsFileApi;
import org.apache.tsfile.read.common.Path;
+import org.apache.tsfile.write.record.TSRecord;
import java.io.IOException;
+import java.util.Iterator;
import java.util.stream.Collectors;
public class TreeResultSet extends AbstractResultSet {
@@ -51,4 +53,9 @@ public class TreeResultSet extends AbstractResultSet {
public void close() {
// nothing to be done
}
+
+ @Override
+ public Iterator<TSRecord> recordIterator() {
+ return null;
+ }
}
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/query/executor/TableQueryExecutor.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/query/executor/TableQueryExecutor.java
index a192a360..c50d1bf1 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/query/executor/TableQueryExecutor.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/query/executor/TableQueryExecutor.java
@@ -29,6 +29,7 @@ import org.apache.tsfile.file.metadata.TsFileMetadata;
import org.apache.tsfile.read.controller.IChunkLoader;
import org.apache.tsfile.read.controller.IMetadataQuerier;
import org.apache.tsfile.read.expression.ExpressionTree;
+import org.apache.tsfile.read.filter.basic.Filter;
import org.apache.tsfile.read.query.executor.task.DeviceTaskIterator;
import org.apache.tsfile.read.reader.block.DeviceOrderedTsBlockReader;
import org.apache.tsfile.read.reader.block.TsBlockReader;
@@ -62,7 +63,7 @@ public class TableQueryExecutor {
* @param tableName table to query
* @param columns columns to query (ID or MEASUREMENT)
* @param timeFilter time predicate
- * @param idFilter id predicate
+ * @param tagFilter id predicate
* @param measurementFilter measurement predicate
* @return an iterator of TsBlocks
* @throws ReadProcessException if the read process fails
@@ -71,7 +72,7 @@ public class TableQueryExecutor {
String tableName,
List<String> columns,
ExpressionTree timeFilter,
- ExpressionTree idFilter,
+ Filter tagFilter,
ExpressionTree measurementFilter)
throws ReadProcessException {
TsFileMetadata fileMetadata = metadataQuerier.getWholeFileMetadata();
@@ -90,7 +91,7 @@ public class TableQueryExecutor {
DeviceTaskIterator deviceTaskIterator =
new DeviceTaskIterator(
- columns, tableRoot, columnMapping, metadataQuerier, idFilter,
tableSchema);
+ columns, tableRoot, columnMapping, metadataQuerier, tagFilter,
tableSchema);
switch (tableQueryOrdering) {
case DEVICE:
return new DeviceOrderedTsBlockReader(
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/query/executor/task/DeviceTaskIterator.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/query/executor/task/DeviceTaskIterator.java
index 8ee44650..399cd32c 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/query/executor/task/DeviceTaskIterator.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/query/executor/task/DeviceTaskIterator.java
@@ -23,7 +23,7 @@ import org.apache.tsfile.file.metadata.IDeviceID;
import org.apache.tsfile.file.metadata.MetadataIndexNode;
import org.apache.tsfile.file.metadata.TableSchema;
import org.apache.tsfile.read.controller.IMetadataQuerier;
-import org.apache.tsfile.read.expression.ExpressionTree;
+import org.apache.tsfile.read.filter.basic.Filter;
import org.apache.tsfile.read.query.executor.TableQueryExecutor.ColumnMapping;
import org.apache.tsfile.utils.Pair;
@@ -41,11 +41,11 @@ public class DeviceTaskIterator implements
Iterator<DeviceQueryTask> {
MetadataIndexNode indexRoot,
ColumnMapping columnMapping,
IMetadataQuerier metadataQuerier,
- ExpressionTree idFilter,
+ Filter tagFilter,
TableSchema tableSchema) {
this.columnNames = columnNames;
this.columnMapping = columnMapping;
- this.deviceMetaIterator = metadataQuerier.deviceIterator(indexRoot,
idFilter);
+ this.deviceMetaIterator = metadataQuerier.deviceIterator(indexRoot,
tagFilter);
this.tableSchema = tableSchema;
}
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/v4/DeviceTableModelReader.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/v4/DeviceTableModelReader.java
index 894353fa..927ac895 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/v4/DeviceTableModelReader.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/v4/DeviceTableModelReader.java
@@ -31,6 +31,7 @@ import org.apache.tsfile.read.controller.IChunkLoader;
import org.apache.tsfile.read.controller.IMetadataQuerier;
import org.apache.tsfile.read.controller.MetadataQuerierByFileImpl;
import org.apache.tsfile.read.expression.ExpressionTree;
+import org.apache.tsfile.read.filter.basic.Filter;
import org.apache.tsfile.read.query.dataset.ResultSet;
import org.apache.tsfile.read.query.dataset.TableResultSet;
import org.apache.tsfile.read.query.executor.TableQueryExecutor;
@@ -79,6 +80,13 @@ public class DeviceTableModelReader implements ITsFileReader
{
@TsFileApi
public ResultSet query(String tableName, List<String> columnNames, long
startTime, long endTime)
throws IOException, NoTableException, NoMeasurementException,
ReadProcessException {
+ return query(tableName, columnNames, startTime, endTime, null);
+ }
+
+ @Override
+ public ResultSet query(
+ String tableName, List<String> columnNames, long startTime, long
endTime, Filter tagFilter)
+ throws ReadProcessException, IOException, NoTableException,
NoMeasurementException {
String lowerCaseTableName = tableName.toLowerCase();
TableSchema tableSchema =
fileReader.getTableSchemaMap().get(lowerCaseTableName);
if (tableSchema == null) {
@@ -100,9 +108,9 @@ public class DeviceTableModelReader implements
ITsFileReader {
lowerCaseTableName,
lowerCaseColumnNames,
new ExpressionTree.TimeBetweenAnd(startTime, endTime),
- null,
+ tagFilter,
null);
- return new TableResultSet(tsBlockReader, columnNames, dataTypeList);
+ return new TableResultSet(tsBlockReader, columnNames, dataTypeList,
tableName);
}
@Override
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/v4/ITsFileReader.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/v4/ITsFileReader.java
index 885e8452..995f73f6 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/v4/ITsFileReader.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/v4/ITsFileReader.java
@@ -24,6 +24,7 @@ import org.apache.tsfile.exception.read.ReadProcessException;
import org.apache.tsfile.exception.write.NoMeasurementException;
import org.apache.tsfile.exception.write.NoTableException;
import org.apache.tsfile.file.metadata.TableSchema;
+import org.apache.tsfile.read.filter.basic.Filter;
import org.apache.tsfile.read.query.dataset.ResultSet;
import java.io.IOException;
@@ -36,6 +37,11 @@ public interface ITsFileReader extends AutoCloseable {
ResultSet query(String tableName, List<String> columnNames, long startTime,
long endTime)
throws ReadProcessException, IOException, NoTableException,
NoMeasurementException;
+ @TsFileApi
+ ResultSet query(
+ String tableName, List<String> columnNames, long startTime, long
endTime, Filter tagFilter)
+ throws ReadProcessException, IOException, NoTableException,
NoMeasurementException;
+
@TsFileApi
Optional<TableSchema> getTableSchemas(String tableName) throws IOException;
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/utils/ReadWriteIOUtils.java
b/java/tsfile/src/main/java/org/apache/tsfile/utils/ReadWriteIOUtils.java
index 6e38e513..e6b72e40 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/utils/ReadWriteIOUtils.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/utils/ReadWriteIOUtils.java
@@ -997,6 +997,18 @@ public class ReadWriteIOUtils {
return set;
}
+ public static Set<String> readStringSet(ByteBuffer buffer) {
+ int size = readInt(buffer);
+ if (size <= 0) {
+ return Collections.emptySet();
+ }
+ Set<String> set = new HashSet<>();
+ for (int i = 0; i < size; i++) {
+ set.add(readString(buffer));
+ }
+ return set;
+ }
+
// read object set with self define length
public static <T> Set<T> readObjectSet(ByteBuffer buffer) {
int size = readInt(buffer);
@@ -1082,6 +1094,16 @@ public class ReadWriteIOUtils {
}
}
+ public static void writeStringSet(Set<String> set, DataOutputStream
outputStream)
+ throws IOException {
+ write(set.contains(null) ? set.size() - 1 : set.size(), outputStream);
+ for (String e : set) {
+ if (e != null) {
+ write(e, outputStream);
+ }
+ }
+ }
+
public static CompressionType readCompressionType(InputStream inputStream)
throws IOException {
byte n = readByte(inputStream);
return CompressionType.deserialize(n);
@@ -1145,6 +1167,7 @@ public class ReadWriteIOUtils {
BINARY,
BOOLEAN,
STRING,
+ TAG,
NULL
}
diff --git
a/java/tsfile/src/test/java/org/apache/tsfile/read/query/ResultSetTest.java
b/java/tsfile/src/test/java/org/apache/tsfile/read/query/ResultSetTest.java
index a9f8766b..090d7f80 100644
--- a/java/tsfile/src/test/java/org/apache/tsfile/read/query/ResultSetTest.java
+++ b/java/tsfile/src/test/java/org/apache/tsfile/read/query/ResultSetTest.java
@@ -22,10 +22,12 @@ package org.apache.tsfile.read.query;
import org.apache.tsfile.enums.ColumnCategory;
import org.apache.tsfile.enums.TSDataType;
import org.apache.tsfile.file.metadata.TableSchema;
+import org.apache.tsfile.read.filter.factory.TagFilterBuilder;
import org.apache.tsfile.read.query.dataset.ResultSet;
import org.apache.tsfile.read.query.dataset.ResultSetMetadata;
import org.apache.tsfile.read.v4.DeviceTableModelReader;
import org.apache.tsfile.utils.TsFileGeneratorForTest;
+import org.apache.tsfile.write.record.TSRecord;
import org.apache.tsfile.write.record.Tablet;
import org.apache.tsfile.write.schema.MeasurementSchema;
import org.apache.tsfile.write.v4.ITsFileWriter;
@@ -40,6 +42,7 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Arrays;
+import java.util.Iterator;
public class ResultSetTest {
@@ -139,6 +142,135 @@ public class ResultSetTest {
}
}
+ @Test
+ public void testQueryTableWithTagFilter() throws Exception {
+ TableSchema tableSchema =
+ new TableSchema(
+ "t1",
+ Arrays.asList(
+ new MeasurementSchema("id1", TSDataType.STRING),
+ new MeasurementSchema("id2", TSDataType.STRING),
+ new MeasurementSchema("s1", TSDataType.BOOLEAN),
+ new MeasurementSchema("s2", TSDataType.BOOLEAN)),
+ Arrays.asList(
+ ColumnCategory.TAG,
+ ColumnCategory.TAG,
+ ColumnCategory.FIELD,
+ ColumnCategory.FIELD));
+ Tablet tablet =
+ new Tablet(
+ Arrays.asList("id1", "id2", "s1", "s2"),
+ Arrays.asList(
+ TSDataType.STRING, TSDataType.STRING, TSDataType.BOOLEAN,
TSDataType.BOOLEAN),
+ 1024);
+ tablet.addTimestamp(0, 0);
+ tablet.addValue("id1", 0, "id_field1");
+ tablet.addValue("id2", 0, "id_field2");
+ tablet.addValue("s1", 0, true);
+ tablet.addValue("s2", 0, false);
+
+ tablet.addTimestamp(1, 1);
+ tablet.addValue("id1", 1, "id_field1_2");
+ tablet.addValue("s2", 1, true);
+
+ tablet.addTimestamp(2, 2);
+
+ try (ITsFileWriter writer =
+ new
TsFileWriterBuilder().file(tsfile).tableSchema(tableSchema).build()) {
+ writer.write(tablet);
+ }
+
+ // eq
+ TagFilterBuilder filterBuilder = new TagFilterBuilder(tableSchema);
+ try (DeviceTableModelReader tsFileReader = new
DeviceTableModelReader(tsfile);
+ ResultSet resultSet =
+ tsFileReader.query(
+ "T1",
+ Arrays.asList("ID1", "ID2", "S2", "S1"),
+ 0,
+ 2,
+ filterBuilder.eq("ID1", "id_field1"))) {
+
+ Assert.assertTrue(resultSet.next());
+ Assert.assertEquals(0, resultSet.getLong(1));
+ Assert.assertEquals("id_field1", resultSet.getString(2));
+ Assert.assertEquals("id_field2", resultSet.getString(3));
+ Assert.assertFalse(resultSet.getBoolean(4));
+ Assert.assertTrue(resultSet.getBoolean(5));
+ }
+ }
+
+ @Test
+ public void testQueryTableByIterator() throws Exception {
+ TableSchema tableSchema =
+ new TableSchema(
+ "t1",
+ Arrays.asList(
+ new MeasurementSchema("id1", TSDataType.STRING),
+ new MeasurementSchema("id2", TSDataType.STRING),
+ new MeasurementSchema("s1", TSDataType.BOOLEAN),
+ new MeasurementSchema("s2", TSDataType.BOOLEAN)),
+ Arrays.asList(
+ ColumnCategory.TAG,
+ ColumnCategory.TAG,
+ ColumnCategory.FIELD,
+ ColumnCategory.FIELD));
+ Tablet tablet =
+ new Tablet(
+ Arrays.asList("id1", "id2", "s1", "s2"),
+ Arrays.asList(
+ TSDataType.STRING, TSDataType.STRING, TSDataType.BOOLEAN,
TSDataType.BOOLEAN),
+ 1024);
+ tablet.addTimestamp(0, 0);
+ tablet.addValue("id1", 0, "id_field1");
+ tablet.addValue("id2", 0, "id_field2");
+ tablet.addValue("s1", 0, true);
+ tablet.addValue("s2", 0, false);
+
+ tablet.addTimestamp(1, 1);
+ tablet.addValue("id1", 1, "id_field1_2");
+ tablet.addValue("s2", 1, true);
+
+ tablet.addTimestamp(2, 2);
+
+ try (ITsFileWriter writer =
+ new
TsFileWriterBuilder().file(tsfile).tableSchema(tableSchema).build()) {
+ writer.write(tablet);
+ }
+
+ try (DeviceTableModelReader tsFileReader = new
DeviceTableModelReader(tsfile);
+ ResultSet resultSet =
+ tsFileReader.query("T1", Arrays.asList("ID1", "ID2", "S2", "S1"),
0, 2); ) {
+ Iterator<TSRecord> tsRecordIterator = resultSet.recordIterator();
+
+ Assert.assertTrue(tsRecordIterator.hasNext());
+ TSRecord tsRecord = tsRecordIterator.next();
+ Assert.assertEquals(2, tsRecord.time);
+ Assert.assertNull(tsRecord.dataPointList.get(0));
+ Assert.assertNull(tsRecord.dataPointList.get(1));
+ Assert.assertNull(tsRecord.dataPointList.get(2));
+ Assert.assertNull(tsRecord.dataPointList.get(3));
+
+ Assert.assertTrue(tsRecordIterator.hasNext());
+ tsRecord = tsRecordIterator.next();
+ Assert.assertEquals(0, tsRecord.time);
+ Assert.assertEquals("id_field1",
tsRecord.dataPointList.get(0).getValue().toString());
+ Assert.assertEquals("id_field2",
tsRecord.dataPointList.get(1).getValue().toString());
+ Assert.assertFalse((Boolean) tsRecord.dataPointList.get(2).getValue());
+ Assert.assertTrue((Boolean) tsRecord.dataPointList.get(3).getValue());
+
+ Assert.assertTrue(tsRecordIterator.hasNext());
+ tsRecord = tsRecordIterator.next();
+ Assert.assertEquals(1, tsRecord.time);
+ Assert.assertEquals("id_field1_2",
tsRecord.dataPointList.get(0).getValue().toString());
+ Assert.assertNull(tsRecord.dataPointList.get(1));
+ Assert.assertTrue((Boolean) tsRecord.dataPointList.get(2).getValue());
+ Assert.assertNull(tsRecord.dataPointList.get(3));
+
+ Assert.assertFalse(tsRecordIterator.hasNext());
+ }
+ }
+
@Test
public void testQueryWithMaxValue() throws Exception {
TableSchema tableSchema =