add tag filter eq
diff --git a/java/tsfile/src/main/codegen/dataModel/AllFilter.tdd b/java/tsfile/src/main/codegen/dataModel/AllFilter.tdd
index cb5815b..d8dcd64 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 77d394d..c4f1243 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 @@
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 @@
@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 @@
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 @@
@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 @@
@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 @@
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 @@
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 @@
@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 @@
@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 @@
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 @@
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 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 @@
@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 @@
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 @@
if(statistics.isEmpty()){
return false;
}
- return constant > (${filter.javaBoxName}) statistics.getMaxValue();
+ return constant > (${javaClassName}) statistics.getMaxValue();
</#if>
}
@@ -387,7 +393,7 @@
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 @@
@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 @@
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 @@
if(statistics.isEmpty()){
return false;
}
- return constant >= (${filter.javaBoxName}) statistics.getMaxValue();
+ return constant >= (${javaClassName}) statistics.getMaxValue();
</#if>
}
@@ -467,7 +473,7 @@
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 @@
@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 @@
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 @@
if(statistics.isEmpty()){
return false;
}
- return constant < (${filter.javaBoxName}) statistics.getMinValue();
+ return constant < (${javaClassName}) statistics.getMinValue();
</#if>
}
@@ -547,7 +553,7 @@
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 @@
@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 @@
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 @@
if(statistics.isEmpty()){
return false;
}
- return constant <= (${filter.javaBoxName}) statistics.getMinValue();
+ return constant <= (${javaClassName}) statistics.getMinValue();
</#if>
}
@@ -615,7 +621,7 @@
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 @@
@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 @@
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 @@
<#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 @@
@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 @@
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 @@
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 @@
<#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 @@
@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 @@
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 @@
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 @@
<#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 @@
<#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 @@
<#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 @@
<#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 @@
<#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 @@
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 @@
@Override
public boolean valueSatisfy(Object value){
- return candidates.contains((${filter.javaBoxName}) value);
+ return candidates.contains((${javaClassName}) value);
}
@Override
@@ -990,12 +996,12 @@
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 @@
} 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 @@
// 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 @@
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 @@
@Override
public boolean valueSatisfy(Object value){
- return !candidates.contains((${filter.javaBoxName}) value);
+ return !candidates.contains((${javaClassName}) value);
}
@Override
@@ -1203,7 +1209,7 @@
@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 @@
@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 @@
@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 @@
@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 e1fd9fe..d057484 100644
--- a/java/tsfile/src/main/codegen/templates/FilterTemplate.ftl
+++ b/java/tsfile/src/main/codegen/templates/FilterTemplate.ftl
@@ -66,6 +66,7 @@
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 @@
}
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 4445bf9..74c99ef 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.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 @@
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 @@
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 @@
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 3503e49..3f74178 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.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 @@
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 ae7fb9e..68e1953 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.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 @@
@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 cc48210..a5aac76 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 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 18d444d..a23ee31 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
@@ -75,6 +75,11 @@
}
@Override
+ public boolean satisfyString(long time, String value) {
+ return timeSatisfy(time);
+ }
+
+ @Override
public boolean satisfyRow(long time, Object[] values) {
// only use time to filter
return timeSatisfy(time);
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 e1ae98b..d715352 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
@@ -85,13 +85,18 @@
}
@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());
}
@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/filter/factory/TagFilterBuilder.java b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/factory/TagFilterBuilder.java
new file mode 100644
index 0000000..a315950
--- /dev/null
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/factory/TagFilterBuilder.java
@@ -0,0 +1,46 @@
+/*
+ * 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.tsfile.read.filter.factory;
+
+import org.apache.tsfile.annotations.TsFileApi;
+import org.apache.tsfile.file.metadata.TableSchema;
+import org.apache.tsfile.read.filter.basic.Filter;
+import org.apache.tsfile.read.filter.operator.TagFilterOperators.ValueEq;
+import org.apache.tsfile.write.schema.IMeasurementSchema;
+
+public class TagFilterBuilder {
+ private TableSchema tableSchema;
+
+ public TagFilterBuilder(TableSchema tableSchema) {
+ this.tableSchema = tableSchema;
+ }
+
+ @TsFileApi
+ 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 de0f338..8df4e50 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
@@ -78,6 +78,11 @@
}
@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 0091891..e02a369 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
@@ -91,6 +91,11 @@
}
@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 f0f1c2f..97a7875 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
@@ -78,6 +78,11 @@
}
@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 0f2d72b..2e5d070 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 @@
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 5e05077..8a585df 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.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 @@
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 0f3aade..1f12cc6 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 @@
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 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 a192a36..c50d1bf 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.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 @@
* @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 @@
String tableName,
List<String> columns,
ExpressionTree timeFilter,
- ExpressionTree idFilter,
+ Filter tagFilter,
ExpressionTree measurementFilter)
throws ReadProcessException {
TsFileMetadata fileMetadata = metadataQuerier.getWholeFileMetadata();
@@ -90,7 +91,7 @@
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 8ee4465..399cd32 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.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 @@
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 894353f..927ac89 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.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 @@
@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 @@
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 885e845..995f73f 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.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;
@@ -37,6 +38,11 @@
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;
@TsFileApi
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 6e38e51..e6b72e4 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 @@
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 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 @@
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 a9f8766..090d7f8 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 @@
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.IOException;
import java.nio.file.Files;
import java.util.Arrays;
+import java.util.Iterator;
public class ResultSetTest {
@@ -140,6 +143,135 @@
}
@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 =
new TableSchema(