This is an automated email from the ASF dual-hosted git repository.
jackietien pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/tsfile.git
The following commit(s) were added to refs/heads/develop by this push:
new 0de0fd4c Support new data type: STRING, BLOB, TIMESTAMP, DATE
0de0fd4c is described below
commit 0de0fd4cf6e0ae29d6cfe9ac507b7283f163a809
Author: Chen YZ <[email protected]>
AuthorDate: Thu May 16 16:34:20 2024 +0800
Support new data type: STRING, BLOB, TIMESTAMP, DATE
---
.../java/org/apache/tsfile/enums/TSDataType.java | 35 ++-
.../org/apache/tsfile/utils/TsPrimitiveType.java | 8 +
.../apache/tsfile/encoding/decoder/Decoder.java | 16 ++
.../tsfile/encoding/encoder/PlainEncoder.java | 4 +
.../tsfile/encoding/encoder/TSEncodingBuilder.java | 16 ++
.../file/metadata/statistics/BlobStatistics.java | 120 ++++++++++
.../metadata/statistics/DateStatistics.java} | 30 +--
.../file/metadata/statistics/Statistics.java | 16 ++
.../file/metadata/statistics/StringStatistics.java | 246 +++++++++++++++++++++
.../metadata/statistics/TimestampStatistics.java} | 30 +--
.../apache/tsfile/read/TsFileSequenceReader.java | 12 +
.../org/apache/tsfile/read/common/BatchData.java | 24 ++
.../tsfile/read/common/DescReadWriteBatchData.java | 12 +
.../java/org/apache/tsfile/read/common/Field.java | 31 +++
.../apache/tsfile/read/common/block/TsBlock.java | 4 +
.../tsfile/read/common/block/TsBlockBuilder.java | 8 +
.../block/column/Int32ArrayColumnEncoder.java | 98 ++++----
.../block/column/Int64ArrayColumnEncoder.java | 81 +++----
.../read/common/block/column/NullColumn.java | 4 +
.../tsfile/read/common/type/TypeFactory.java | 4 +
.../read/filter/operator/ValueFilterOperators.java | 1 +
.../query/dataset/DataSetWithoutTimeGenerator.java | 4 +
.../apache/tsfile/read/reader/page/PageReader.java | 8 +
.../tsfile/read/reader/page/ValuePageReader.java | 24 ++
.../java/org/apache/tsfile/utils/BytesUtils.java | 10 +
.../java/org/apache/tsfile/utils/DateUtils.java | 79 +++++++
.../apache/tsfile/utils/TsFileGeneratorUtils.java | 4 +
.../write/chunk/AlignedChunkGroupWriterImpl.java | 12 +
.../tsfile/write/chunk/AlignedChunkWriterImpl.java | 8 +
.../chunk/NonAlignedChunkGroupWriterImpl.java | 4 +
.../org/apache/tsfile/write/record/Tablet.java | 61 +++++
.../tsfile/write/record/datapoint/DataPoint.java | 4 +
.../org/apache/tsfile/utils/DateUtilsTest.java | 114 ++++++++++
.../java/org/apache/tsfile/utils/RecordUtils.java | 4 +
34 files changed, 1001 insertions(+), 135 deletions(-)
diff --git a/java/common/src/main/java/org/apache/tsfile/enums/TSDataType.java
b/java/common/src/main/java/org/apache/tsfile/enums/TSDataType.java
index efb8fa02..226c2e09 100644
--- a/java/common/src/main/java/org/apache/tsfile/enums/TSDataType.java
+++ b/java/common/src/main/java/org/apache/tsfile/enums/TSDataType.java
@@ -50,7 +50,20 @@ public enum TSDataType {
VECTOR((byte) 6),
/** UNKNOWN. */
- UNKNOWN((byte) 7);
+ UNKNOWN((byte) 7),
+
+ /** TIMESTAMP. */
+ TIMESTAMP((byte) 8),
+
+ /** DATE. */
+ DATE((byte) 9),
+
+ /** BLOB. */
+ BLOB((byte) 10),
+
+ /** STRING */
+ STRING((byte) 11);
+ ;
private final byte type;
@@ -90,6 +103,14 @@ public enum TSDataType {
return TSDataType.VECTOR;
case 7:
return TSDataType.UNKNOWN;
+ case 8:
+ return TSDataType.TIMESTAMP;
+ case 9:
+ return TSDataType.DATE;
+ case 10:
+ return TSDataType.BLOB;
+ case 11:
+ return TSDataType.STRING;
default:
throw new IllegalArgumentException("Invalid input: " + type);
}
@@ -125,12 +146,16 @@ public enum TSDataType {
return 1;
case INT32:
case FLOAT:
+ case DATE:
return 4;
// For text: return the size of reference here
case TEXT:
case INT64:
case DOUBLE:
case VECTOR:
+ case BLOB:
+ case STRING:
+ case TIMESTAMP:
return 8;
default:
throw new UnSupportedDataTypeException(this.toString());
@@ -160,6 +185,10 @@ public enum TSDataType {
case DOUBLE:
return true;
// For text: return the size of reference here
+ case BLOB:
+ case TIMESTAMP:
+ case DATE:
+ case STRING:
case BOOLEAN:
case TEXT:
case VECTOR:
@@ -183,8 +212,12 @@ public enum TSDataType {
case DOUBLE:
case TEXT:
case BOOLEAN:
+ case TIMESTAMP:
+ case DATE:
+ case STRING:
return true;
case VECTOR:
+ case BLOB:
return false;
default:
throw new UnSupportedDataTypeException(this.toString());
diff --git
a/java/common/src/main/java/org/apache/tsfile/utils/TsPrimitiveType.java
b/java/common/src/main/java/org/apache/tsfile/utils/TsPrimitiveType.java
index 62e2b1eb..50a74436 100644
--- a/java/common/src/main/java/org/apache/tsfile/utils/TsPrimitiveType.java
+++ b/java/common/src/main/java/org/apache/tsfile/utils/TsPrimitiveType.java
@@ -36,14 +36,18 @@ public abstract class TsPrimitiveType implements
Serializable {
case BOOLEAN:
return new TsPrimitiveType.TsBoolean();
case INT32:
+ case DATE:
return new TsPrimitiveType.TsInt();
case INT64:
+ case TIMESTAMP:
return new TsPrimitiveType.TsLong();
case FLOAT:
return new TsPrimitiveType.TsFloat();
case DOUBLE:
return new TsPrimitiveType.TsDouble();
case TEXT:
+ case BLOB:
+ case STRING:
return new TsPrimitiveType.TsBinary();
case VECTOR:
return new TsPrimitiveType.TsVector();
@@ -63,14 +67,18 @@ public abstract class TsPrimitiveType implements
Serializable {
case BOOLEAN:
return new TsPrimitiveType.TsBoolean((boolean) v);
case INT32:
+ case DATE:
return new TsPrimitiveType.TsInt((int) v);
case INT64:
+ case TIMESTAMP:
return new TsPrimitiveType.TsLong((long) v);
case FLOAT:
return new TsPrimitiveType.TsFloat((float) v);
case DOUBLE:
return new TsPrimitiveType.TsDouble((double) v);
case TEXT:
+ case BLOB:
+ case STRING:
return new TsPrimitiveType.TsBinary((Binary) v);
case VECTOR:
return new TsPrimitiveType.TsVector((TsPrimitiveType[]) v);
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/encoding/decoder/Decoder.java
b/java/tsfile/src/main/java/org/apache/tsfile/encoding/decoder/Decoder.java
index f1404ae1..36c3d826 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/encoding/decoder/Decoder.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/encoding/decoder/Decoder.java
@@ -54,9 +54,11 @@ public abstract class Decoder {
switch (dataType) {
case BOOLEAN:
case INT32:
+ case DATE:
return new IntRleDecoder();
case INT64:
case VECTOR:
+ case TIMESTAMP:
return new LongRleDecoder();
case FLOAT:
case DOUBLE:
@@ -67,9 +69,11 @@ public abstract class Decoder {
case TS_2DIFF:
switch (dataType) {
case INT32:
+ case DATE:
return new DeltaBinaryDecoder.IntDeltaDecoder();
case INT64:
case VECTOR:
+ case TIMESTAMP:
return new DeltaBinaryDecoder.LongDeltaDecoder();
case FLOAT:
case DOUBLE:
@@ -89,9 +93,11 @@ public abstract class Decoder {
case REGULAR:
switch (dataType) {
case INT32:
+ case DATE:
return new RegularDataDecoder.IntRegularDecoder();
case INT64:
case VECTOR:
+ case TIMESTAMP:
return new RegularDataDecoder.LongRegularDecoder();
default:
throw new TsFileDecodingException(String.format(ERROR_MSG,
encoding, dataType));
@@ -103,9 +109,11 @@ public abstract class Decoder {
case DOUBLE:
return new DoublePrecisionDecoderV2();
case INT32:
+ case DATE:
return new IntGorillaDecoder();
case INT64:
case VECTOR:
+ case TIMESTAMP:
return new LongGorillaDecoder();
default:
throw new TsFileDecodingException(String.format(ERROR_MSG,
encoding, dataType));
@@ -115,8 +123,10 @@ public abstract class Decoder {
case ZIGZAG:
switch (dataType) {
case INT32:
+ case DATE:
return new IntZigzagDecoder();
case INT64:
+ case TIMESTAMP:
return new LongZigzagDecoder();
default:
throw new TsFileDecodingException(String.format(ERROR_MSG,
encoding, dataType));
@@ -128,9 +138,11 @@ public abstract class Decoder {
case DOUBLE:
return new DoublePrecisionChimpDecoder();
case INT32:
+ case DATE:
return new IntChimpDecoder();
case INT64:
case VECTOR:
+ case TIMESTAMP:
return new LongChimpDecoder();
default:
throw new TsFileDecodingException(String.format(ERROR_MSG,
encoding, dataType));
@@ -138,8 +150,10 @@ public abstract class Decoder {
case SPRINTZ:
switch (dataType) {
case INT32:
+ case DATE:
return new IntSprintzDecoder();
case INT64:
+ case TIMESTAMP:
return new LongSprintzDecoder();
case FLOAT:
return new FloatSprintzDecoder();
@@ -151,8 +165,10 @@ public abstract class Decoder {
case RLBE:
switch (dataType) {
case INT32:
+ case DATE:
return new IntRLBEDecoder();
case INT64:
+ case TIMESTAMP:
return new LongRLBEDecoder();
case FLOAT:
return new FloatRLBEDecoder();
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/encoding/encoder/PlainEncoder.java
b/java/tsfile/src/main/java/org/apache/tsfile/encoding/encoder/PlainEncoder.java
index e93f1f08..09c28cbe 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/encoding/encoder/PlainEncoder.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/encoding/encoder/PlainEncoder.java
@@ -116,14 +116,18 @@ public class PlainEncoder extends Encoder {
case BOOLEAN:
return 1;
case INT32:
+ case DATE:
return 4;
case INT64:
+ case TIMESTAMP:
return 8;
case FLOAT:
return 4;
case DOUBLE:
return 8;
case TEXT:
+ case STRING:
+ case BLOB:
// refer to encode(Binary,ByteArrayOutputStream)
return 4 + TSFileConfig.BYTE_SIZE_PER_CHAR * maxStringLength;
default:
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/encoding/encoder/TSEncodingBuilder.java
b/java/tsfile/src/main/java/org/apache/tsfile/encoding/encoder/TSEncodingBuilder.java
index 65ef569b..232ddd3c 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/encoding/encoder/TSEncodingBuilder.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/encoding/encoder/TSEncodingBuilder.java
@@ -142,9 +142,11 @@ public abstract class TSEncodingBuilder {
public Encoder getEncoder(TSDataType type) {
switch (type) {
case INT32:
+ case DATE:
case BOOLEAN:
return new IntRleEncoder();
case INT64:
+ case TIMESTAMP:
return new LongRleEncoder();
case FLOAT:
case DOUBLE:
@@ -196,8 +198,10 @@ public abstract class TSEncodingBuilder {
public Encoder getEncoder(TSDataType type) {
switch (type) {
case INT32:
+ case DATE:
return new DeltaBinaryEncoder.IntDeltaEncoder();
case INT64:
+ case TIMESTAMP:
return new DeltaBinaryEncoder.LongDeltaEncoder();
case FLOAT:
case DOUBLE:
@@ -268,8 +272,10 @@ public abstract class TSEncodingBuilder {
public Encoder getEncoder(TSDataType type) {
switch (type) {
case INT32:
+ case DATE:
return new RegularDataEncoder.IntRegularEncoder();
case INT64:
+ case TIMESTAMP:
return new RegularDataEncoder.LongRegularEncoder();
default:
throw new UnSupportedDataTypeException("REGULAR doesn't support data
type: " + type);
@@ -293,8 +299,10 @@ public abstract class TSEncodingBuilder {
case DOUBLE:
return new DoublePrecisionEncoderV2();
case INT32:
+ case DATE:
return new IntGorillaEncoder();
case INT64:
+ case TIMESTAMP:
return new LongGorillaEncoder();
default:
throw new UnSupportedDataTypeException("GORILLA doesn't support data
type: " + type);
@@ -312,8 +320,10 @@ public abstract class TSEncodingBuilder {
public Encoder getEncoder(TSDataType type) {
switch (type) {
case INT32:
+ case DATE:
return new IntSprintzEncoder();
case INT64:
+ case TIMESTAMP:
return new LongSprintzEncoder();
case FLOAT:
return new FloatSprintzEncoder();
@@ -335,8 +345,10 @@ public abstract class TSEncodingBuilder {
public Encoder getEncoder(TSDataType type) {
switch (type) {
case INT32:
+ case DATE:
return new IntRLBE();
case INT64:
+ case TIMESTAMP:
return new LongRLBE();
case FLOAT:
return new FloatRLBE();
@@ -375,8 +387,10 @@ public abstract class TSEncodingBuilder {
public Encoder getEncoder(TSDataType type) {
switch (type) {
case INT32:
+ case DATE:
return new IntZigzagEncoder();
case INT64:
+ case TIMESTAMP:
return new LongZigzagEncoder();
default:
throw new UnSupportedDataTypeException("ZIGZAG doesn't support data
type: " + type);
@@ -400,8 +414,10 @@ public abstract class TSEncodingBuilder {
case DOUBLE:
return new DoublePrecisionChimpEncoder();
case INT32:
+ case DATE:
return new IntChimpEncoder();
case INT64:
+ case TIMESTAMP:
return new LongChimpEncoder();
default:
throw new UnSupportedDataTypeException("CHIMP doesn't support data
type: " + type);
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/BlobStatistics.java
b/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/BlobStatistics.java
new file mode 100644
index 00000000..c0f3d2bc
--- /dev/null
+++
b/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/BlobStatistics.java
@@ -0,0 +1,120 @@
+/*
+ * 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.file.metadata.statistics;
+
+import org.apache.tsfile.enums.TSDataType;
+import org.apache.tsfile.exception.filter.StatisticsClassException;
+import org.apache.tsfile.utils.Binary;
+import org.apache.tsfile.utils.RamUsageEstimator;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+public class BlobStatistics extends Statistics<Binary> {
+
+ public static final long INSTANCE_SIZE =
+ RamUsageEstimator.shallowSizeOfInstance(BlobStatistics.class);
+
+ // no statistics for blob data type
+
+ @Override
+ public TSDataType getType() {
+ return TSDataType.BLOB;
+ }
+
+ /** The output of this method should be identical to the method
"serializeStats(outputStream)". */
+ @Override
+ public int getStatsSize() {
+ return 0;
+ }
+
+ @Override
+ public long getRetainedSizeInBytes() {
+ return INSTANCE_SIZE;
+ }
+
+ @Override
+ int serializeStats(OutputStream outputStream) throws IOException {
+ return 0;
+ }
+
+ public void updateStats(Binary value) {
+ // do nothing
+ }
+
+ @Override
+ public void deserialize(InputStream inputStream) throws IOException {
+ // do nothing
+ }
+
+ @Override
+ public void deserialize(ByteBuffer byteBuffer) {
+ // do nothing
+ }
+
+ @Override
+ public Binary getMinValue() {
+ throw new StatisticsClassException(
+ String.format(STATS_UNSUPPORTED_MSG, TSDataType.BLOB, "min"));
+ }
+
+ @Override
+ public Binary getMaxValue() {
+ throw new StatisticsClassException(
+ String.format(STATS_UNSUPPORTED_MSG, TSDataType.BLOB, "max"));
+ }
+
+ @Override
+ public Binary getFirstValue() {
+ throw new StatisticsClassException(
+ String.format(STATS_UNSUPPORTED_MSG, TSDataType.BLOB, "first"));
+ }
+
+ @Override
+ public Binary getLastValue() {
+ throw new StatisticsClassException(
+ String.format(STATS_UNSUPPORTED_MSG, TSDataType.BLOB, "last"));
+ }
+
+ @Override
+ public double getSumDoubleValue() {
+ throw new StatisticsClassException(
+ String.format(STATS_UNSUPPORTED_MSG, TSDataType.BLOB, "sum"));
+ }
+
+ @Override
+ public long getSumLongValue() {
+
+ throw new StatisticsClassException(
+ String.format(STATS_UNSUPPORTED_MSG, TSDataType.BLOB, "sum"));
+ }
+
+ @Override
+ protected void mergeStatisticsValue(Statistics<Binary> stats) {
+ // do nothing
+ }
+
+ @Override
+ public String toString() {
+ return "BlobStatistics{}";
+ }
+}
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/type/TypeFactory.java
b/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/DateStatistics.java
similarity index 54%
copy from
java/tsfile/src/main/java/org/apache/tsfile/read/common/type/TypeFactory.java
copy to
java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/DateStatistics.java
index 62282280..d79e31fd 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/type/TypeFactory.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/DateStatistics.java
@@ -17,33 +17,13 @@
* under the License.
*/
-package org.apache.tsfile.read.common.type;
+package org.apache.tsfile.file.metadata.statistics;
import org.apache.tsfile.enums.TSDataType;
-public class TypeFactory {
-
- private TypeFactory() {
- // forbidding instantiation
- }
-
- public static Type getType(TSDataType tsDataType) {
- switch (tsDataType) {
- case INT32:
- return IntType.getInstance();
- case INT64:
- return LongType.getInstance();
- case FLOAT:
- return FloatType.getInstance();
- case DOUBLE:
- return DoubleType.getInstance();
- case BOOLEAN:
- return BooleanType.getInstance();
- case TEXT:
- return BinaryType.getInstance();
- default:
- throw new UnsupportedOperationException(
- String.format("Invalid TSDataType for TypeFactory: %s",
tsDataType));
- }
+public class DateStatistics extends IntegerStatistics {
+ @Override
+ public TSDataType getType() {
+ return TSDataType.DATE;
}
}
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/Statistics.java
b/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/Statistics.java
index 4f92b455..addec426 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/Statistics.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/Statistics.java
@@ -85,6 +85,14 @@ public abstract class Statistics<T extends Serializable> {
return new FloatStatistics();
case VECTOR:
return new TimeStatistics();
+ case DATE:
+ return new DateStatistics();
+ case TIMESTAMP:
+ return new TimestampStatistics();
+ case STRING:
+ return new StringStatistics();
+ case BLOB:
+ return new BlobStatistics();
default:
throw new UnknownColumnTypeException(type.toString());
}
@@ -106,6 +114,14 @@ public abstract class Statistics<T extends Serializable> {
return FloatStatistics.INSTANCE_SIZE;
case VECTOR:
return TimeStatistics.INSTANCE_SIZE;
+ case DATE:
+ return DateStatistics.INSTANCE_SIZE;
+ case TIMESTAMP:
+ return TimestampStatistics.INSTANCE_SIZE;
+ case STRING:
+ return StringStatistics.INSTANCE_SIZE;
+ case BLOB:
+ return BlobStatistics.INSTANCE_SIZE;
default:
throw new UnknownColumnTypeException(type.toString());
}
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/StringStatistics.java
b/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/StringStatistics.java
new file mode 100644
index 00000000..de6cccc3
--- /dev/null
+++
b/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/StringStatistics.java
@@ -0,0 +1,246 @@
+/*
+ * 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.file.metadata.statistics;
+
+import org.apache.tsfile.common.conf.TSFileConfig;
+import org.apache.tsfile.enums.TSDataType;
+import org.apache.tsfile.exception.filter.StatisticsClassException;
+import org.apache.tsfile.utils.Binary;
+import org.apache.tsfile.utils.RamUsageEstimator;
+import org.apache.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.Objects;
+
+import static org.apache.tsfile.utils.RamUsageEstimator.sizeOfCharArray;
+
+public class StringStatistics extends Statistics<Binary> {
+ public static final long INSTANCE_SIZE =
+ RamUsageEstimator.shallowSizeOfInstance(StringStatistics.class)
+ + 4 * RamUsageEstimator.shallowSizeOfInstance(Binary.class);
+
+ private static final Binary EMPTY_VALUE = new Binary("",
TSFileConfig.STRING_CHARSET);
+
+ private Binary firstValue = EMPTY_VALUE;
+ private Binary lastValue = EMPTY_VALUE;
+ private Binary minValue = EMPTY_VALUE;
+ private Binary maxValue = EMPTY_VALUE;
+
+ @Override
+ public TSDataType getType() {
+ return TSDataType.BLOB;
+ }
+
+ /** The output of this method should be identical to the method
"serializeStats(outputStream)". */
+ @Override
+ public int getStatsSize() {
+ return 4 * 4
+ + firstValue.getValues().length
+ + lastValue.getValues().length
+ + minValue.getValues().length
+ + maxValue.getValues().length;
+ }
+
+ @Override
+ public long getRetainedSizeInBytes() {
+ return INSTANCE_SIZE
+ + sizeOfCharArray(firstValue.getLength())
+ + sizeOfCharArray(lastValue.getLength())
+ + sizeOfCharArray(minValue.getLength())
+ + sizeOfCharArray(maxValue.getLength());
+ }
+
+ public void initializeStats(Binary first, Binary last, Binary min, Binary
max) {
+ this.firstValue = first;
+ this.lastValue = last;
+ this.minValue = min;
+ this.maxValue = max;
+ }
+
+ private void updateStats(Binary minValue, Binary maxValue, Binary lastValue)
{
+ if (this.minValue.compareTo(minValue) > 0) {
+ this.minValue = minValue;
+ }
+ if (this.maxValue.compareTo(maxValue) < 0) {
+ this.maxValue = maxValue;
+ }
+ this.lastValue = lastValue;
+ }
+
+ private void updateStats(
+ Binary firstValue,
+ Binary lastValue,
+ Binary minValue,
+ Binary maxValue,
+ long startTime,
+ long endTime) {
+ // only if endTime greater or equals to the current endTime need we update
the last value
+ // only if startTime less or equals to the current startTime need we
update the first value
+ // otherwise, just ignore
+ if (this.minValue.compareTo(minValue) > 0) {
+ this.minValue = minValue;
+ }
+ if (this.maxValue.compareTo(maxValue) < 0) {
+ this.maxValue = maxValue;
+ }
+ if (startTime <= this.getStartTime()) {
+ this.firstValue = firstValue;
+ }
+ if (endTime >= this.getEndTime()) {
+ this.lastValue = lastValue;
+ }
+ }
+
+ @Override
+ public Binary getMinValue() {
+ return minValue;
+ }
+
+ @Override
+ public Binary getMaxValue() {
+ return maxValue;
+ }
+
+ @Override
+ public Binary getFirstValue() {
+ return firstValue;
+ }
+
+ @Override
+ public Binary getLastValue() {
+ return lastValue;
+ }
+
+ @Override
+ public double getSumDoubleValue() {
+ throw new StatisticsClassException(
+ String.format(STATS_UNSUPPORTED_MSG, TSDataType.STRING, "double sum"));
+ }
+
+ @Override
+ public long getSumLongValue() {
+ throw new StatisticsClassException(
+ String.format(STATS_UNSUPPORTED_MSG, TSDataType.STRING, "long sum"));
+ }
+
+ @Override
+ protected void mergeStatisticsValue(Statistics<Binary> stats) {
+ StringStatistics stringStats = (StringStatistics) stats;
+ if (isEmpty) {
+ initializeStats(
+ stringStats.getFirstValue(),
+ stringStats.getLastValue(),
+ stringStats.getMinValue(),
+ stringStats.getMaxValue());
+ isEmpty = false;
+ } else {
+ updateStats(
+ stringStats.getFirstValue(),
+ stringStats.getLastValue(),
+ stringStats.getMinValue(),
+ stringStats.getMaxValue(),
+ stats.getStartTime(),
+ stats.getEndTime());
+ }
+ }
+
+ @Override
+ void updateStats(Binary value) {
+ if (isEmpty) {
+ initializeStats(value, value, value, value);
+ isEmpty = false;
+ } else {
+ updateStats(value, value, value);
+ }
+ }
+
+ @Override
+ void updateStats(Binary[] values, int batchSize) {
+ for (int i = 0; i < batchSize; i++) {
+ updateStats(values[i]);
+ }
+ }
+
+ @Override
+ public int serializeStats(OutputStream outputStream) throws IOException {
+ int byteLen = 0;
+ byteLen += ReadWriteIOUtils.write(firstValue, outputStream);
+ byteLen += ReadWriteIOUtils.write(lastValue, outputStream);
+ byteLen += ReadWriteIOUtils.write(minValue, outputStream);
+ byteLen += ReadWriteIOUtils.write(maxValue, outputStream);
+ return byteLen;
+ }
+
+ @Override
+ public void deserialize(InputStream inputStream) throws IOException {
+ this.firstValue = ReadWriteIOUtils.readBinary(inputStream);
+ this.lastValue = ReadWriteIOUtils.readBinary(inputStream);
+ this.minValue = ReadWriteIOUtils.readBinary(inputStream);
+ this.maxValue = ReadWriteIOUtils.readBinary(inputStream);
+ }
+
+ @Override
+ public void deserialize(ByteBuffer byteBuffer) {
+ this.firstValue = ReadWriteIOUtils.readBinary(byteBuffer);
+ this.lastValue = ReadWriteIOUtils.readBinary(byteBuffer);
+ this.minValue = ReadWriteIOUtils.readBinary(byteBuffer);
+ this.maxValue = ReadWriteIOUtils.readBinary(byteBuffer);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+ StringStatistics that = (StringStatistics) o;
+ return firstValue.equals(that.firstValue)
+ && lastValue.equals(that.lastValue)
+ && minValue.equals(that.minValue)
+ && maxValue.equals(that.maxValue);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), firstValue, lastValue, minValue,
maxValue);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()
+ + " [firstValue:"
+ + firstValue
+ + ", lastValue:"
+ + lastValue
+ + ", minValue:"
+ + minValue
+ + ", maxValue:"
+ + maxValue
+ + "]";
+ }
+}
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/type/TypeFactory.java
b/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/TimestampStatistics.java
similarity index 54%
copy from
java/tsfile/src/main/java/org/apache/tsfile/read/common/type/TypeFactory.java
copy to
java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/TimestampStatistics.java
index 62282280..8c634d12 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/type/TypeFactory.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/file/metadata/statistics/TimestampStatistics.java
@@ -17,33 +17,13 @@
* under the License.
*/
-package org.apache.tsfile.read.common.type;
+package org.apache.tsfile.file.metadata.statistics;
import org.apache.tsfile.enums.TSDataType;
-public class TypeFactory {
-
- private TypeFactory() {
- // forbidding instantiation
- }
-
- public static Type getType(TSDataType tsDataType) {
- switch (tsDataType) {
- case INT32:
- return IntType.getInstance();
- case INT64:
- return LongType.getInstance();
- case FLOAT:
- return FloatType.getInstance();
- case DOUBLE:
- return DoubleType.getInstance();
- case BOOLEAN:
- return BooleanType.getInstance();
- case TEXT:
- return BinaryType.getInstance();
- default:
- throw new UnsupportedOperationException(
- String.format("Invalid TSDataType for TypeFactory: %s",
tsDataType));
- }
+public class TimestampStatistics extends LongStatistics {
+ @Override
+ public TSDataType getType() {
+ return TSDataType.TIMESTAMP;
}
}
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/TsFileSequenceReader.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/TsFileSequenceReader.java
index a15c9890..4c8ce31d 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/TsFileSequenceReader.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/TsFileSequenceReader.java
@@ -1839,9 +1839,11 @@ public class TsFileSequenceReader implements
AutoCloseable {
long timeStamp = timeBatch.get(0)[i];
switch (dataType) {
case INT32:
+ case DATE:
chunkStatistics.update(timeStamp, value.getInt());
break;
case INT64:
+ case TIMESTAMP:
chunkStatistics.update(timeStamp, value.getLong());
break;
case FLOAT:
@@ -1854,6 +1856,8 @@ public class TsFileSequenceReader implements
AutoCloseable {
chunkStatistics.update(timeStamp,
value.getBoolean());
break;
case TEXT:
+ case BLOB:
+ case STRING:
chunkStatistics.update(timeStamp, value.getBinary());
break;
default:
@@ -1874,9 +1878,11 @@ public class TsFileSequenceReader implements
AutoCloseable {
while (batchData.hasCurrent()) {
switch (dataType) {
case INT32:
+ case DATE:
chunkStatistics.update(batchData.currentTime(),
batchData.getInt());
break;
case INT64:
+ case TIMESTAMP:
chunkStatistics.update(batchData.currentTime(),
batchData.getLong());
break;
case FLOAT:
@@ -1889,6 +1895,8 @@ public class TsFileSequenceReader implements
AutoCloseable {
chunkStatistics.update(batchData.currentTime(),
batchData.getBoolean());
break;
case TEXT:
+ case BLOB:
+ case STRING:
chunkStatistics.update(batchData.currentTime(),
batchData.getBinary());
break;
default:
@@ -2086,9 +2094,11 @@ public class TsFileSequenceReader implements
AutoCloseable {
while (batchData.hasCurrent()) {
switch (dataType) {
case INT32:
+ case DATE:
chunkStatistics.update(batchData.currentTime(),
batchData.getInt());
break;
case INT64:
+ case TIMESTAMP:
chunkStatistics.update(batchData.currentTime(),
batchData.getLong());
break;
case FLOAT:
@@ -2101,6 +2111,8 @@ public class TsFileSequenceReader implements
AutoCloseable {
chunkStatistics.update(batchData.currentTime(),
batchData.getBoolean());
break;
case TEXT:
+ case BLOB:
+ case STRING:
chunkStatistics.update(batchData.currentTime(),
batchData.getBinary());
break;
default:
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/BatchData.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/common/BatchData.java
index bd89bcc7..504f7a9c 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/common/BatchData.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/common/BatchData.java
@@ -130,8 +130,10 @@ public class BatchData {
public Object currentValue() {
switch (dataType) {
case INT32:
+ case DATE:
return getInt();
case INT64:
+ case TIMESTAMP:
return getLong();
case FLOAT:
return getFloat();
@@ -140,6 +142,8 @@ public class BatchData {
case BOOLEAN:
return getBoolean();
case TEXT:
+ case BLOB:
+ case STRING:
return getBinary();
case VECTOR:
return getVector();
@@ -151,8 +155,10 @@ public class BatchData {
public TsPrimitiveType currentTsPrimitiveType() {
switch (dataType) {
case INT32:
+ case DATE:
return new TsInt(getInt());
case INT64:
+ case TIMESTAMP:
return new TsLong(getLong());
case FLOAT:
return new TsFloat(getFloat());
@@ -161,6 +167,8 @@ public class BatchData {
case BOOLEAN:
return new TsBoolean(getBoolean());
case TEXT:
+ case BLOB:
+ case STRING:
return new TsBinary(getBinary());
case VECTOR:
return new TsVector(getVector());
@@ -203,10 +211,12 @@ public class BatchData {
booleanRet.add(new boolean[capacity]);
break;
case INT32:
+ case DATE:
intRet = new ArrayList<>();
intRet.add(new int[capacity]);
break;
case INT64:
+ case TIMESTAMP:
longRet = new ArrayList<>();
longRet.add(new long[capacity]);
break;
@@ -219,6 +229,8 @@ public class BatchData {
doubleRet.add(new double[capacity]);
break;
case TEXT:
+ case BLOB:
+ case STRING:
binaryRet = new ArrayList<>();
binaryRet.add(new Binary[capacity]);
break;
@@ -547,9 +559,11 @@ public class BatchData {
putBoolean(t, (boolean) v);
break;
case INT32:
+ case DATE:
putInt(t, (int) v);
break;
case INT64:
+ case TIMESTAMP:
putLong(t, (long) v);
break;
case FLOAT:
@@ -559,6 +573,8 @@ public class BatchData {
putDouble(t, (double) v);
break;
case TEXT:
+ case BLOB:
+ case STRING:
putBinary(t, (Binary) v);
break;
case VECTOR:
@@ -681,6 +697,8 @@ public class BatchData {
}
break;
case TEXT:
+ case BLOB:
+ case STRING:
for (int i = 0; i < length(); i++) {
outputStream.writeLong(getTimeByIndex(i));
Binary binary = getBinaryByIndex(i);
@@ -689,12 +707,14 @@ public class BatchData {
}
break;
case INT64:
+ case TIMESTAMP:
for (int i = 0; i < length(); i++) {
outputStream.writeLong(getTimeByIndex(i));
outputStream.writeLong(getLongByIndex(i));
}
break;
case INT32:
+ case DATE:
for (int i = 0; i < length(); i++) {
outputStream.writeLong(getTimeByIndex(i));
outputStream.writeInt(getIntByIndex(i));
@@ -722,14 +742,18 @@ public class BatchData {
outputStream.writeFloat(value.getFloat());
break;
case TEXT:
+ case BLOB:
+ case STRING:
Binary binary = value.getBinary();
outputStream.writeInt(binary.getLength());
outputStream.write(binary.getValues());
break;
case INT64:
+ case TIMESTAMP:
outputStream.writeLong(value.getLong());
break;
case INT32:
+ case DATE:
outputStream.writeInt(value.getInt());
break;
default:
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/DescReadWriteBatchData.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/common/DescReadWriteBatchData.java
index 9b168f29..1fd65740 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/DescReadWriteBatchData.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/common/DescReadWriteBatchData.java
@@ -55,10 +55,12 @@ public class DescReadWriteBatchData extends
DescReadBatchData {
booleanRet.add(new boolean[capacity]);
break;
case INT32:
+ case DATE:
intRet = new LinkedList<>();
intRet.add(new int[capacity]);
break;
case INT64:
+ case TIMESTAMP:
longRet = new LinkedList<>();
longRet.add(new long[capacity]);
break;
@@ -71,6 +73,8 @@ public class DescReadWriteBatchData extends DescReadBatchData
{
doubleRet.add(new double[capacity]);
break;
case TEXT:
+ case BLOB:
+ case STRING:
binaryRet = new LinkedList<>();
binaryRet.add(new Binary[capacity]);
break;
@@ -434,6 +438,8 @@ public class DescReadWriteBatchData extends
DescReadBatchData {
}
break;
case TEXT:
+ case BLOB:
+ case STRING:
for (int i = length() - 1; i >= 0; i--) {
outputStream.writeLong(getTimeByIndex(i));
Binary binary = getBinaryByIndex(i);
@@ -442,12 +448,14 @@ public class DescReadWriteBatchData extends
DescReadBatchData {
}
break;
case INT64:
+ case TIMESTAMP:
for (int i = length() - 1; i >= 0; i--) {
outputStream.writeLong(getTimeByIndex(i));
outputStream.writeLong(getLongByIndex(i));
}
break;
case INT32:
+ case DATE:
for (int i = length() - 1; i >= 0; i--) {
outputStream.writeLong(getTimeByIndex(i));
outputStream.writeInt(getIntByIndex(i));
@@ -475,14 +483,18 @@ public class DescReadWriteBatchData extends
DescReadBatchData {
outputStream.writeFloat(value.getFloat());
break;
case TEXT:
+ case BLOB:
+ case STRING:
Binary binary = value.getBinary();
outputStream.writeInt(binary.getLength());
outputStream.write(binary.getValues());
break;
case INT64:
+ case TIMESTAMP:
outputStream.writeLong(value.getLong());
break;
case INT32:
+ case DATE:
outputStream.writeInt(value.getInt());
break;
default:
diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/common/Field.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/common/Field.java
index 32feae4a..aaa2f2f9 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/common/Field.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/common/Field.java
@@ -22,9 +22,12 @@ package org.apache.tsfile.read.common;
import org.apache.tsfile.enums.TSDataType;
import org.apache.tsfile.exception.NullFieldException;
import org.apache.tsfile.utils.Binary;
+import org.apache.tsfile.utils.DateUtils;
import org.apache.tsfile.utils.TsPrimitiveType;
import org.apache.tsfile.write.UnSupportedDataTypeException;
+import java.time.LocalDate;
+
/**
* Field is component of one {@code RowRecord} which stores a value in
specific data type. The value
* type of Field is primitive(int long, float, double, binary, boolean).
@@ -54,15 +57,19 @@ public class Field {
out.setFloatV(field.getFloatV());
break;
case INT64:
+ case TIMESTAMP:
out.setLongV(field.getLongV());
break;
case INT32:
+ case DATE:
out.setIntV(field.getIntV());
break;
case BOOLEAN:
out.setBoolV(field.getBoolV());
break;
case TEXT:
+ case BLOB:
+ case STRING:
out.setBinaryV(field.getBinaryV());
break;
default:
@@ -143,6 +150,13 @@ public class Field {
this.binaryV = binaryV;
}
+ public LocalDate getDateV() {
+ if (dataType == null) {
+ throw new NullFieldException();
+ }
+ return DateUtils.parseIntToLocalDate(intV);
+ }
+
/**
* get field value and convert to string.
*
@@ -156,14 +170,18 @@ public class Field {
case BOOLEAN:
return String.valueOf(boolV);
case INT32:
+ case DATE:
return String.valueOf(intV);
case INT64:
+ case TIMESTAMP:
return String.valueOf(longV);
case FLOAT:
return String.valueOf(floatV);
case DOUBLE:
return String.valueOf(doubleV);
case TEXT:
+ case BLOB:
+ case STRING:
return binaryV.toString();
default:
throw new UnSupportedDataTypeException(dataType.toString());
@@ -185,12 +203,17 @@ public class Field {
case FLOAT:
return getFloatV();
case INT64:
+ case TIMESTAMP:
return getLongV();
case INT32:
return getIntV();
+ case DATE:
+ return getDateV();
case BOOLEAN:
return getBoolV();
case TEXT:
+ case BLOB:
+ case STRING:
return getBinaryV();
default:
throw new UnSupportedDataTypeException(dataType.toString());
@@ -204,9 +227,11 @@ public class Field {
Field field = new Field(dataType);
switch (dataType) {
case INT32:
+ case DATE:
field.setIntV((int) value);
break;
case INT64:
+ case TIMESTAMP:
field.setLongV((long) value);
break;
case FLOAT:
@@ -219,6 +244,8 @@ public class Field {
field.setBoolV((boolean) value);
break;
case TEXT:
+ case BLOB:
+ case STRING:
field.setBinaryV((Binary) value);
break;
default:
@@ -233,9 +260,11 @@ public class Field {
field.setBoolV(value.getBoolean());
break;
case INT32:
+ case DATE:
field.setIntV(value.getInt());
break;
case INT64:
+ case TIMESTAMP:
field.setLongV(value.getLong());
break;
case FLOAT:
@@ -245,6 +274,8 @@ public class Field {
field.setDoubleV(value.getDouble());
break;
case TEXT:
+ case BLOB:
+ case STRING:
field.setBinaryV(value.getBinary());
break;
default:
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/TsBlock.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/TsBlock.java
index d6b7ca3d..da3e0568 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/TsBlock.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/TsBlock.java
@@ -523,11 +523,13 @@ public class TsBlock {
sourceTsBlock.getValueColumns()[i].getBoolean(sourceIndex);
break;
case INT32:
+ case DATE:
valueColumns[i].isNull()[updateIdx] = false;
valueColumns[i].getInts()[updateIdx] =
sourceTsBlock.getValueColumns()[i].getInt(sourceIndex);
break;
case INT64:
+ case TIMESTAMP:
valueColumns[i].isNull()[updateIdx] = false;
valueColumns[i].getLongs()[updateIdx] =
sourceTsBlock.getValueColumns()[i].getLong(sourceIndex);
@@ -543,6 +545,8 @@ public class TsBlock {
sourceTsBlock.getValueColumns()[i].getDouble(sourceIndex);
break;
case TEXT:
+ case BLOB:
+ case STRING:
valueColumns[i].isNull()[updateIdx] = false;
valueColumns[i].getBinaries()[updateIdx] =
sourceTsBlock.getValueColumns()[i].getBinary(sourceIndex);
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/TsBlockBuilder.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/TsBlockBuilder.java
index 872372b7..568c222c 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/TsBlockBuilder.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/TsBlockBuilder.java
@@ -113,11 +113,13 @@ public class TsBlockBuilder {
tsBlockBuilderStatus.createColumnBuilderStatus(),
initialExpectedEntries);
break;
case INT32:
+ case DATE:
valueColumnBuilders[i] =
new IntColumnBuilder(
tsBlockBuilderStatus.createColumnBuilderStatus(),
initialExpectedEntries);
break;
case INT64:
+ case TIMESTAMP:
valueColumnBuilders[i] =
new LongColumnBuilder(
tsBlockBuilderStatus.createColumnBuilderStatus(),
initialExpectedEntries);
@@ -133,6 +135,8 @@ public class TsBlockBuilder {
tsBlockBuilderStatus.createColumnBuilderStatus(),
initialExpectedEntries);
break;
case TEXT:
+ case BLOB:
+ case STRING:
valueColumnBuilders[i] =
new BinaryColumnBuilder(
tsBlockBuilderStatus.createColumnBuilderStatus(),
initialExpectedEntries);
@@ -181,11 +185,13 @@ public class TsBlockBuilder {
tsBlockBuilderStatus.createColumnBuilderStatus(),
initialExpectedEntries);
break;
case INT32:
+ case DATE:
valueColumnBuilders[i] =
new IntColumnBuilder(
tsBlockBuilderStatus.createColumnBuilderStatus(),
initialExpectedEntries);
break;
case INT64:
+ case TIMESTAMP:
valueColumnBuilders[i] =
new LongColumnBuilder(
tsBlockBuilderStatus.createColumnBuilderStatus(),
initialExpectedEntries);
@@ -201,6 +207,8 @@ public class TsBlockBuilder {
tsBlockBuilderStatus.createColumnBuilderStatus(),
initialExpectedEntries);
break;
case TEXT:
+ case BLOB:
+ case STRING:
valueColumnBuilders[i] =
new BinaryColumnBuilder(
tsBlockBuilderStatus.createColumnBuilderStatus(),
initialExpectedEntries);
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/Int32ArrayColumnEncoder.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/Int32ArrayColumnEncoder.java
index 748a054c..cc727fb7 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/Int32ArrayColumnEncoder.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/Int32ArrayColumnEncoder.java
@@ -40,36 +40,38 @@ public class Int32ArrayColumnEncoder implements
ColumnEncoder {
boolean[] nullIndicators = ColumnEncoder.deserializeNullIndicators(input,
positionCount);
- if (TSDataType.INT32.equals(dataType)) {
- int[] values = new int[positionCount];
- if (nullIndicators == null) {
- for (int i = 0; i < positionCount; i++) {
- values[i] = input.getInt();
- }
- } else {
- for (int i = 0; i < positionCount; i++) {
- if (!nullIndicators[i]) {
- values[i] = input.getInt();
+ switch (dataType) {
+ case INT32:
+ case DATE:
+ int[] intValues = new int[positionCount];
+ if (nullIndicators == null) {
+ for (int i = 0; i < positionCount; i++) {
+ intValues[i] = input.getInt();
+ }
+ } else {
+ for (int i = 0; i < positionCount; i++) {
+ if (!nullIndicators[i]) {
+ intValues[i] = input.getInt();
+ }
}
}
- }
- return new IntColumn(0, positionCount, nullIndicators, values);
- } else if (TSDataType.FLOAT.equals(dataType)) {
- float[] values = new float[positionCount];
- if (nullIndicators == null) {
- for (int i = 0; i < positionCount; i++) {
- values[i] = Float.intBitsToFloat(input.getInt());
- }
- } else {
- for (int i = 0; i < positionCount; i++) {
- if (!nullIndicators[i]) {
- values[i] = Float.intBitsToFloat(input.getInt());
+ return new IntColumn(0, positionCount, nullIndicators, intValues);
+ case FLOAT:
+ float[] floatValues = new float[positionCount];
+ if (nullIndicators == null) {
+ for (int i = 0; i < positionCount; i++) {
+ floatValues[i] = Float.intBitsToFloat(input.getInt());
+ }
+ } else {
+ for (int i = 0; i < positionCount; i++) {
+ if (!nullIndicators[i]) {
+ floatValues[i] = Float.intBitsToFloat(input.getInt());
+ }
}
}
- }
- return new FloatColumn(0, positionCount, nullIndicators, values);
- } else {
- throw new IllegalArgumentException("Invalid data type: " + dataType);
+ return new FloatColumn(0, positionCount, nullIndicators, floatValues);
+ default:
+ throw new IllegalArgumentException("Invalid data type: " + dataType);
}
}
@@ -80,32 +82,36 @@ public class Int32ArrayColumnEncoder implements
ColumnEncoder {
TSDataType dataType = column.getDataType();
int positionCount = column.getPositionCount();
- if (TSDataType.INT32.equals(dataType)) {
- if (column.mayHaveNull()) {
- for (int i = 0; i < positionCount; i++) {
- if (!column.isNull(i)) {
+ switch (dataType) {
+ case INT32:
+ case DATE:
+ if (column.mayHaveNull()) {
+ for (int i = 0; i < positionCount; i++) {
+ if (!column.isNull(i)) {
+ output.writeInt(column.getInt(i));
+ }
+ }
+ } else {
+ for (int i = 0; i < positionCount; i++) {
output.writeInt(column.getInt(i));
}
}
- } else {
- for (int i = 0; i < positionCount; i++) {
- output.writeInt(column.getInt(i));
- }
- }
- } else if (TSDataType.FLOAT.equals(dataType)) {
- if (column.mayHaveNull()) {
- for (int i = 0; i < positionCount; i++) {
- if (!column.isNull(i)) {
+ break;
+ case FLOAT:
+ if (column.mayHaveNull()) {
+ for (int i = 0; i < positionCount; i++) {
+ if (!column.isNull(i)) {
+ output.writeInt(Float.floatToIntBits(column.getFloat(i)));
+ }
+ }
+ } else {
+ for (int i = 0; i < positionCount; i++) {
output.writeInt(Float.floatToIntBits(column.getFloat(i)));
}
}
- } else {
- for (int i = 0; i < positionCount; i++) {
- output.writeInt(Float.floatToIntBits(column.getFloat(i)));
- }
- }
- } else {
- throw new IllegalArgumentException("Invalid data type: " + dataType);
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid data type: " + dataType);
}
}
}
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/Int64ArrayColumnEncoder.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/Int64ArrayColumnEncoder.java
index 51490f06..58cfbebf 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/Int64ArrayColumnEncoder.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/Int64ArrayColumnEncoder.java
@@ -61,37 +61,38 @@ public class Int64ArrayColumnEncoder implements
ColumnEncoder {
// +---------------+-----------------+-------------+
boolean[] nullIndicators = ColumnEncoder.deserializeNullIndicators(input,
positionCount);
-
- if (TSDataType.INT64.equals(dataType)) {
- long[] values = new long[positionCount];
- if (nullIndicators == null) {
- for (int i = 0; i < positionCount; i++) {
- values[i] = input.getLong();
- }
- } else {
- for (int i = 0; i < positionCount; i++) {
- if (!nullIndicators[i]) {
+ switch (dataType) {
+ case INT64:
+ case TIMESTAMP:
+ long[] values = new long[positionCount];
+ if (nullIndicators == null) {
+ for (int i = 0; i < positionCount; i++) {
values[i] = input.getLong();
}
+ } else {
+ for (int i = 0; i < positionCount; i++) {
+ if (!nullIndicators[i]) {
+ values[i] = input.getLong();
+ }
+ }
}
- }
- return new LongColumn(0, positionCount, nullIndicators, values);
- } else if (TSDataType.DOUBLE.equals(dataType)) {
- double[] values = new double[positionCount];
- if (nullIndicators == null) {
- for (int i = 0; i < positionCount; i++) {
- values[i] = Double.longBitsToDouble(input.getLong());
- }
- } else {
- for (int i = 0; i < positionCount; i++) {
- if (!nullIndicators[i]) {
- values[i] = Double.longBitsToDouble(input.getLong());
+ return new LongColumn(0, positionCount, nullIndicators, values);
+ case DOUBLE:
+ double[] doubleValues = new double[positionCount];
+ if (nullIndicators == null) {
+ for (int i = 0; i < positionCount; i++) {
+ doubleValues[i] = Double.longBitsToDouble(input.getLong());
+ }
+ } else {
+ for (int i = 0; i < positionCount; i++) {
+ if (!nullIndicators[i]) {
+ doubleValues[i] = Double.longBitsToDouble(input.getLong());
+ }
}
}
- }
- return new DoubleColumn(0, positionCount, nullIndicators, values);
- } else {
- throw new IllegalArgumentException("Invalid data type: " + dataType);
+ return new DoubleColumn(0, positionCount, nullIndicators,
doubleValues);
+ default:
+ throw new IllegalArgumentException("Invalid data type: " + dataType);
}
}
@@ -102,20 +103,24 @@ public class Int64ArrayColumnEncoder implements
ColumnEncoder {
TSDataType dataType = column.getDataType();
int positionCount = column.getPositionCount();
- if (TSDataType.INT64.equals(dataType)) {
- for (int i = 0; i < positionCount; i++) {
- if (!column.isNull(i)) {
- output.writeLong(column.getLong(i));
+ switch (dataType) {
+ case INT64:
+ case TIMESTAMP:
+ for (int i = 0; i < positionCount; i++) {
+ if (!column.isNull(i)) {
+ output.writeLong(column.getLong(i));
+ }
}
- }
- } else if (TSDataType.DOUBLE.equals(dataType)) {
- for (int i = 0; i < positionCount; i++) {
- if (!column.isNull(i)) {
- output.writeLong(Double.doubleToLongBits(column.getDouble(i)));
+ break;
+ case DOUBLE:
+ for (int i = 0; i < positionCount; i++) {
+ if (!column.isNull(i)) {
+ output.writeLong(Double.doubleToLongBits(column.getDouble(i)));
+ }
}
- }
- } else {
- throw new IllegalArgumentException("Invalid data type: " + dataType);
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid data type: " + dataType);
}
}
}
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/NullColumn.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/NullColumn.java
index be21cfa6..f95cdb00 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/NullColumn.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/common/block/column/NullColumn.java
@@ -108,14 +108,18 @@ public class NullColumn implements Column {
case BOOLEAN:
return new
RunLengthEncodedColumn(BooleanColumnBuilder.NULL_VALUE_BLOCK, positionCount);
case INT32:
+ case DATE:
return new RunLengthEncodedColumn(IntColumnBuilder.NULL_VALUE_BLOCK,
positionCount);
case INT64:
+ case TIMESTAMP:
return new RunLengthEncodedColumn(LongColumnBuilder.NULL_VALUE_BLOCK,
positionCount);
case FLOAT:
return new RunLengthEncodedColumn(FloatColumnBuilder.NULL_VALUE_BLOCK,
positionCount);
case DOUBLE:
return new
RunLengthEncodedColumn(DoubleColumnBuilder.NULL_VALUE_BLOCK, positionCount);
case TEXT:
+ case BLOB:
+ case STRING:
return new
RunLengthEncodedColumn(BinaryColumnBuilder.NULL_VALUE_BLOCK, positionCount);
default:
throw new IllegalArgumentException("Unknown data type: " + dataType);
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/type/TypeFactory.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/common/type/TypeFactory.java
index 62282280..72946ee8 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/common/type/TypeFactory.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/common/type/TypeFactory.java
@@ -30,8 +30,10 @@ public class TypeFactory {
public static Type getType(TSDataType tsDataType) {
switch (tsDataType) {
case INT32:
+ case DATE:
return IntType.getInstance();
case INT64:
+ case TIMESTAMP:
return LongType.getInstance();
case FLOAT:
return FloatType.getInstance();
@@ -40,6 +42,8 @@ public class TypeFactory {
case BOOLEAN:
return BooleanType.getInstance();
case TEXT:
+ case BLOB:
+ case STRING:
return BinaryType.getInstance();
default:
throw new UnsupportedOperationException(
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/ValueFilterOperators.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/ValueFilterOperators.java
index 3cc7e8ad..c2b7284c 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/ValueFilterOperators.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/filter/operator/ValueFilterOperators.java
@@ -557,6 +557,7 @@ public final class ValueFilterOperators {
private static boolean statisticsNotAvailable(Statistics<?> statistics) {
return statistics.getType() == TSDataType.TEXT
|| statistics.getType() == TSDataType.BOOLEAN
+ || statistics.getType() == TSDataType.BLOB
|| statistics.isEmpty();
}
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/query/dataset/DataSetWithoutTimeGenerator.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/query/dataset/DataSetWithoutTimeGenerator.java
index cdd50d9b..02f8ffd4 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/query/dataset/DataSetWithoutTimeGenerator.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/query/dataset/DataSetWithoutTimeGenerator.java
@@ -163,9 +163,11 @@ public class DataSetWithoutTimeGenerator extends
QueryDataSet {
field.setBoolV(col.getBoolean());
break;
case INT32:
+ case DATE:
field.setIntV(col.getInt());
break;
case INT64:
+ case TIMESTAMP:
field.setLongV(col.getLong());
break;
case FLOAT:
@@ -175,6 +177,8 @@ public class DataSetWithoutTimeGenerator extends
QueryDataSet {
field.setDoubleV(col.getDouble());
break;
case TEXT:
+ case BLOB:
+ case STRING:
field.setBinaryV(col.getBinary());
break;
case VECTOR:
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/PageReader.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/PageReader.java
index d4208f31..bbf0b49c 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/PageReader.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/PageReader.java
@@ -134,12 +134,14 @@ public class PageReader implements IPageReader {
}
break;
case INT32:
+ case DATE:
int anInt = valueDecoder.readInt(valueBuffer);
if (!isDeleted(timestamp) && (allSatisfy ||
recordFilter.satisfy(timestamp, anInt))) {
pageData.putInt(timestamp, anInt);
}
break;
case INT64:
+ case TIMESTAMP:
long aLong = valueDecoder.readLong(valueBuffer);
if (!isDeleted(timestamp) && (allSatisfy ||
recordFilter.satisfy(timestamp, aLong))) {
pageData.putLong(timestamp, aLong);
@@ -158,6 +160,8 @@ public class PageReader implements IPageReader {
}
break;
case TEXT:
+ case BLOB:
+ case STRING:
Binary aBinary = valueDecoder.readBinary(valueBuffer);
if (!isDeleted(timestamp) && (allSatisfy ||
recordFilter.satisfy(timestamp, aBinary))) {
pageData.putBinary(timestamp, aBinary);
@@ -206,6 +210,7 @@ public class PageReader implements IPageReader {
}
break;
case INT32:
+ case DATE:
while (timeDecoder.hasNext(timeBuffer)) {
long timestamp = timeDecoder.readLong(timeBuffer);
int anInt = valueDecoder.readInt(valueBuffer);
@@ -227,6 +232,7 @@ public class PageReader implements IPageReader {
}
break;
case INT64:
+ case TIMESTAMP:
while (timeDecoder.hasNext(timeBuffer)) {
long timestamp = timeDecoder.readLong(timeBuffer);
long aLong = valueDecoder.readLong(valueBuffer);
@@ -290,6 +296,8 @@ public class PageReader implements IPageReader {
}
break;
case TEXT:
+ case BLOB:
+ case STRING:
while (timeDecoder.hasNext(timeBuffer)) {
long timestamp = timeDecoder.readLong(timeBuffer);
Binary aBinary = valueDecoder.readBinary(valueBuffer);
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/ValuePageReader.java
b/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/ValuePageReader.java
index 833df288..8bf13791 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/ValuePageReader.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/ValuePageReader.java
@@ -101,12 +101,14 @@ public class ValuePageReader {
}
break;
case INT32:
+ case DATE:
int anInt = valueDecoder.readInt(valueBuffer);
if (!isDeleted(timestamp) && (filter == null ||
filter.satisfy(timestamp, anInt))) {
pageData.putInt(timestamp, anInt);
}
break;
case INT64:
+ case TIMESTAMP:
long aLong = valueDecoder.readLong(valueBuffer);
if (!isDeleted(timestamp) && (filter == null ||
filter.satisfy(timestamp, aLong))) {
pageData.putLong(timestamp, aLong);
@@ -125,6 +127,8 @@ public class ValuePageReader {
}
break;
case TEXT:
+ case BLOB:
+ case STRING:
Binary aBinary = valueDecoder.readBinary(valueBuffer);
if (!isDeleted(timestamp) && (filter == null ||
filter.satisfy(timestamp, aBinary))) {
pageData.putBinary(timestamp, aBinary);
@@ -150,12 +154,14 @@ public class ValuePageReader {
}
break;
case INT32:
+ case DATE:
int anInt = valueDecoder.readInt(valueBuffer);
if (!isDeleted(timestamp)) {
resultValue = new TsPrimitiveType.TsInt(anInt);
}
break;
case INT64:
+ case TIMESTAMP:
long aLong = valueDecoder.readLong(valueBuffer);
if (!isDeleted(timestamp)) {
resultValue = new TsPrimitiveType.TsLong(aLong);
@@ -174,6 +180,8 @@ public class ValuePageReader {
}
break;
case TEXT:
+ case BLOB:
+ case STRING:
Binary aBinary = valueDecoder.readBinary(valueBuffer);
if (!isDeleted(timestamp)) {
resultValue = new TsPrimitiveType.TsBinary(aBinary);
@@ -207,12 +215,14 @@ public class ValuePageReader {
}
break;
case INT32:
+ case DATE:
int anInt = valueDecoder.readInt(valueBuffer);
if (!isDeleted(timeBatch[i])) {
valueBatch[i] = new TsPrimitiveType.TsInt(anInt);
}
break;
case INT64:
+ case TIMESTAMP:
long aLong = valueDecoder.readLong(valueBuffer);
if (!isDeleted(timeBatch[i])) {
valueBatch[i] = new TsPrimitiveType.TsLong(aLong);
@@ -231,6 +241,8 @@ public class ValuePageReader {
}
break;
case TEXT:
+ case BLOB:
+ case STRING:
Binary aBinary = valueDecoder.readBinary(valueBuffer);
if (!isDeleted(timeBatch[i])) {
valueBatch[i] = new TsPrimitiveType.TsBinary(aBinary);
@@ -275,6 +287,7 @@ public class ValuePageReader {
}
break;
case INT32:
+ case DATE:
int anInt = valueDecoder.readInt(valueBuffer);
if (keepCurrentRow[i]) {
if (isDeleted[i]) {
@@ -285,6 +298,7 @@ public class ValuePageReader {
}
break;
case INT64:
+ case TIMESTAMP:
long aLong = valueDecoder.readLong(valueBuffer);
if (keepCurrentRow[i]) {
if (isDeleted[i]) {
@@ -315,6 +329,8 @@ public class ValuePageReader {
}
break;
case TEXT:
+ case BLOB:
+ case STRING:
Binary aBinary = valueDecoder.readBinary(valueBuffer);
if (keepCurrentRow[i]) {
if (isDeleted[i]) {
@@ -355,12 +371,14 @@ public class ValuePageReader {
}
break;
case INT32:
+ case DATE:
int anInt = valueDecoder.readInt(valueBuffer);
if (keepCurrentRow[i]) {
columnBuilder.writeInt(anInt);
}
break;
case INT64:
+ case TIMESTAMP:
long aLong = valueDecoder.readLong(valueBuffer);
if (keepCurrentRow[i]) {
columnBuilder.writeLong(aLong);
@@ -379,6 +397,8 @@ public class ValuePageReader {
}
break;
case TEXT:
+ case BLOB:
+ case STRING:
Binary aBinary = valueDecoder.readBinary(valueBuffer);
if (keepCurrentRow[i]) {
columnBuilder.writeBinary(aBinary);
@@ -417,6 +437,7 @@ public class ValuePageReader {
}
break;
case INT32:
+ case DATE:
// skip useless data
for (int i = 0; i < readStartIndex; i++) {
if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) {
@@ -435,6 +456,7 @@ public class ValuePageReader {
}
break;
case INT64:
+ case TIMESTAMP:
// skip useless data
for (int i = 0; i < readStartIndex; i++) {
if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) {
@@ -489,6 +511,8 @@ public class ValuePageReader {
}
break;
case TEXT:
+ case BLOB:
+ case STRING:
// skip useless data
for (int i = 0; i < readStartIndex; i++) {
if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) {
diff --git a/java/tsfile/src/main/java/org/apache/tsfile/utils/BytesUtils.java
b/java/tsfile/src/main/java/org/apache/tsfile/utils/BytesUtils.java
index 40862a5d..f38a0da1 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/utils/BytesUtils.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/utils/BytesUtils.java
@@ -931,4 +931,14 @@ public class BytesUtils {
public static Binary valueOf(String value) {
return new Binary(stringToBytes(value));
}
+
+ public static String parseBlobByteArrayToString(byte[] input) {
+ StringBuilder hexString = new StringBuilder("0x");
+ if (input != null) {
+ for (byte b : input) {
+ hexString.append(String.format("%02x", b));
+ }
+ }
+ return hexString.toString();
+ }
}
diff --git a/java/tsfile/src/main/java/org/apache/tsfile/utils/DateUtils.java
b/java/tsfile/src/main/java/org/apache/tsfile/utils/DateUtils.java
new file mode 100644
index 00000000..3caa46c2
--- /dev/null
+++ b/java/tsfile/src/main/java/org/apache/tsfile/utils/DateUtils.java
@@ -0,0 +1,79 @@
+/*
+ * 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.utils;
+
+import java.sql.Date;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+
+public class DateUtils {
+ private static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+ public static String formatDate(int date) {
+ return date / 10000
+ + "-"
+ + String.format("%02d", (date / 100) % 100)
+ + "-"
+ + String.format("%02d", date % 100);
+ }
+
+ public static Integer parseDateExpressionToInt(String dateExpression) {
+ if (dateExpression == null || dateExpression.isEmpty()) {
+ throw new DateTimeParseException("Date expression is null or empty.",
"", 0);
+ }
+ LocalDate date;
+ try {
+ date = LocalDate.parse(dateExpression, DATE_FORMATTER);
+ } catch (DateTimeParseException e) {
+ throw new DateTimeParseException(
+ "Invalid date format. Please use YYYY-MM-DD format.",
dateExpression, 0);
+ }
+ if (date.getYear() < 1000) {
+ throw new DateTimeParseException("Year must be between 1000 and 9999.",
dateExpression, 0);
+ }
+ return date.getYear() * 10000 + date.getMonthValue() * 100 +
date.getDayOfMonth();
+ }
+
+ public static Integer parseDateExpressionToInt(LocalDate localDate) {
+ if (localDate == null) {
+ throw new DateTimeParseException("Date expression is null or empty.",
"", 0);
+ }
+ if (localDate.getYear() < 1000) {
+ throw new DateTimeParseException(
+ "Year must be between 1000 and 9999.",
localDate.format(DATE_FORMATTER), 0);
+ }
+ return localDate.getYear() * 10000
+ + localDate.getMonthValue() * 100
+ + localDate.getDayOfMonth();
+ }
+
+ public static Date parseIntToDate(int date) {
+ return new Date(date / 10000 - 1900, (date / 100) % 100 - 1, date % 100);
+ }
+
+ public static LocalDate parseIntToLocalDate(int date) {
+ try {
+ return LocalDate.of(date / 10000, (date / 100) % 100, date % 100);
+ } catch (Exception e) {
+ throw new DateTimeParseException("Invalid date format.", "", 0);
+ }
+ }
+}
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/utils/TsFileGeneratorUtils.java
b/java/tsfile/src/main/java/org/apache/tsfile/utils/TsFileGeneratorUtils.java
index 71633a99..ba1b5e31 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/utils/TsFileGeneratorUtils.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/utils/TsFileGeneratorUtils.java
@@ -70,9 +70,11 @@ public class TsFileGeneratorUtils {
DataPoint dPoint;
switch (schema.getType()) {
case INT64:
+ case TIMESTAMP:
dPoint = new LongDataPoint(schema.getMeasurementId(), startValue);
break;
case INT32:
+ case DATE:
dPoint = new IntDataPoint(schema.getMeasurementId(), (int)
startValue);
break;
case DOUBLE:
@@ -85,6 +87,8 @@ public class TsFileGeneratorUtils {
dPoint = new BooleanDataPoint(schema.getMeasurementId(), true);
break;
case TEXT:
+ case BLOB:
+ case STRING:
default:
dPoint =
new StringDataPoint(
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/write/chunk/AlignedChunkGroupWriterImpl.java
b/java/tsfile/src/main/java/org/apache/tsfile/write/chunk/AlignedChunkGroupWriterImpl.java
index 1d596881..f0e4055a 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/write/chunk/AlignedChunkGroupWriterImpl.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/write/chunk/AlignedChunkGroupWriterImpl.java
@@ -120,9 +120,11 @@ public class AlignedChunkGroupWriterImpl implements
IChunkGroupWriter {
valueChunkWriter.write(time, (boolean) point.getValue(), isNull);
break;
case INT32:
+ case DATE:
valueChunkWriter.write(time, (int) point.getValue(), isNull);
break;
case INT64:
+ case TIMESTAMP:
valueChunkWriter.write(time, (long) point.getValue(), isNull);
break;
case FLOAT:
@@ -132,6 +134,8 @@ public class AlignedChunkGroupWriterImpl implements
IChunkGroupWriter {
valueChunkWriter.write(time, (double) point.getValue(), isNull);
break;
case TEXT:
+ case BLOB:
+ case STRING:
valueChunkWriter.write(time, (Binary) point.getValue(), isNull);
break;
default:
@@ -180,9 +184,11 @@ public class AlignedChunkGroupWriterImpl implements
IChunkGroupWriter {
valueChunkWriter.write(time, ((boolean[])
tablet.values[columnIndex])[row], isNull);
break;
case INT32:
+ case DATE:
valueChunkWriter.write(time, ((int[])
tablet.values[columnIndex])[row], isNull);
break;
case INT64:
+ case TIMESTAMP:
valueChunkWriter.write(time, ((long[])
tablet.values[columnIndex])[row], isNull);
break;
case FLOAT:
@@ -192,6 +198,8 @@ public class AlignedChunkGroupWriterImpl implements
IChunkGroupWriter {
valueChunkWriter.write(time, ((double[])
tablet.values[columnIndex])[row], isNull);
break;
case TEXT:
+ case BLOB:
+ case STRING:
valueChunkWriter.write(time, ((Binary[])
tablet.values[columnIndex])[row], isNull);
break;
default:
@@ -266,9 +274,11 @@ public class AlignedChunkGroupWriterImpl implements
IChunkGroupWriter {
valueChunkWriter.write(-1, false, true);
break;
case INT32:
+ case DATE:
valueChunkWriter.write(-1, 0, true);
break;
case INT64:
+ case TIMESTAMP:
valueChunkWriter.write(-1, 0L, true);
break;
case FLOAT:
@@ -278,6 +288,8 @@ public class AlignedChunkGroupWriterImpl implements
IChunkGroupWriter {
valueChunkWriter.write(-1, 0.0d, true);
break;
case TEXT:
+ case BLOB:
+ case STRING:
valueChunkWriter.write(-1, null, true);
break;
default:
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/write/chunk/AlignedChunkWriterImpl.java
b/java/tsfile/src/main/java/org/apache/tsfile/write/chunk/AlignedChunkWriterImpl.java
index 656b7852..d5fddb83 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/write/chunk/AlignedChunkWriterImpl.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/write/chunk/AlignedChunkWriterImpl.java
@@ -198,9 +198,11 @@ public class AlignedChunkWriterImpl implements
IChunkWriter {
ValueChunkWriter writer = valueChunkWriterList.get(valueIndex++);
switch (writer.getDataType()) {
case INT64:
+ case TIMESTAMP:
writer.write(time, point != null ? point.getLong() : Long.MAX_VALUE,
point == null);
break;
case INT32:
+ case DATE:
writer.write(time, point != null ? point.getInt() :
Integer.MAX_VALUE, point == null);
break;
case FLOAT:
@@ -213,6 +215,8 @@ public class AlignedChunkWriterImpl implements IChunkWriter
{
writer.write(time, point != null ? point.getBoolean() : false, point
== null);
break;
case TEXT:
+ case BLOB:
+ case STRING:
writer.write(
time,
point != null ? point.getBinary() : new
Binary("".getBytes(StandardCharsets.UTF_8)),
@@ -255,6 +259,8 @@ public class AlignedChunkWriterImpl implements IChunkWriter
{
TSDataType tsDataType = chunkWriter.getDataType();
switch (tsDataType) {
case TEXT:
+ case BLOB:
+ case STRING:
chunkWriter.write(times, column.getBinaries(), column.isNull(),
batchSize, arrayOffset);
break;
case DOUBLE:
@@ -264,9 +270,11 @@ public class AlignedChunkWriterImpl implements
IChunkWriter {
chunkWriter.write(times, column.getBooleans(), column.isNull(),
batchSize, arrayOffset);
break;
case INT64:
+ case TIMESTAMP:
chunkWriter.write(times, column.getLongs(), column.isNull(),
batchSize, arrayOffset);
break;
case INT32:
+ case DATE:
chunkWriter.write(times, column.getInts(), column.isNull(),
batchSize, arrayOffset);
break;
case FLOAT:
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/write/chunk/NonAlignedChunkGroupWriterImpl.java
b/java/tsfile/src/main/java/org/apache/tsfile/write/chunk/NonAlignedChunkGroupWriterImpl.java
index 9df9b14d..42485ac7 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/write/chunk/NonAlignedChunkGroupWriterImpl.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/write/chunk/NonAlignedChunkGroupWriterImpl.java
@@ -109,9 +109,11 @@ public class NonAlignedChunkGroupWriterImpl implements
IChunkGroupWriter {
pointCount++;
switch (tsDataType) {
case INT32:
+ case DATE:
chunkWriters.get(measurementId).write(time, ((int[])
tablet.values[column])[row]);
break;
case INT64:
+ case TIMESTAMP:
chunkWriters.get(measurementId).write(time, ((long[])
tablet.values[column])[row]);
break;
case FLOAT:
@@ -124,6 +126,8 @@ public class NonAlignedChunkGroupWriterImpl implements
IChunkGroupWriter {
chunkWriters.get(measurementId).write(time, ((boolean[])
tablet.values[column])[row]);
break;
case TEXT:
+ case BLOB:
+ case STRING:
chunkWriters.get(measurementId).write(time, ((Binary[])
tablet.values[column])[row]);
break;
default:
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/write/record/Tablet.java
b/java/tsfile/src/main/java/org/apache/tsfile/write/record/Tablet.java
index 61ab2e41..bd18fb2b 100644
--- a/java/tsfile/src/main/java/org/apache/tsfile/write/record/Tablet.java
+++ b/java/tsfile/src/main/java/org/apache/tsfile/write/record/Tablet.java
@@ -24,6 +24,7 @@ import org.apache.tsfile.enums.TSDataType;
import org.apache.tsfile.utils.Binary;
import org.apache.tsfile.utils.BitMap;
import org.apache.tsfile.utils.BytesUtils;
+import org.apache.tsfile.utils.DateUtils;
import org.apache.tsfile.utils.PublicBAOS;
import org.apache.tsfile.utils.ReadWriteIOUtils;
import org.apache.tsfile.write.UnSupportedDataTypeException;
@@ -32,6 +33,7 @@ import org.apache.tsfile.write.schema.MeasurementSchema;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -187,6 +189,7 @@ public class Tablet {
}
switch (dataType) {
case TEXT:
+ case STRING:
{
Binary[] sensor = (Binary[]) values[indexOfSchema];
if (value instanceof Binary) {
@@ -199,6 +202,12 @@ public class Tablet {
}
break;
}
+ case BLOB:
+ {
+ Binary[] sensor = (Binary[]) values[indexOfSchema];
+ sensor[rowIndex] = value != null ? (Binary) value :
Binary.EMPTY_VALUE;
+ break;
+ }
case FLOAT:
{
float[] sensor = (float[]) values[indexOfSchema];
@@ -211,7 +220,14 @@ public class Tablet {
sensor[rowIndex] = value != null ? (int) value : Integer.MIN_VALUE;
break;
}
+ case DATE:
+ {
+ LocalDate[] sensor = (LocalDate[]) values[indexOfSchema];
+ sensor[rowIndex] = (LocalDate) value;
+ break;
+ }
case INT64:
+ case TIMESTAMP:
{
long[] sensor = (long[]) values[indexOfSchema];
sensor[rowIndex] = value != null ? (long) value : Long.MIN_VALUE;
@@ -280,6 +296,7 @@ public class Tablet {
valueColumn = new int[maxRowNumber];
break;
case INT64:
+ case TIMESTAMP:
valueColumn = new long[maxRowNumber];
break;
case FLOAT:
@@ -292,8 +309,13 @@ public class Tablet {
valueColumn = new boolean[maxRowNumber];
break;
case TEXT:
+ case STRING:
+ case BLOB:
valueColumn = new Binary[maxRowNumber];
break;
+ case DATE:
+ valueColumn = new LocalDate[maxRowNumber];
+ break;
default:
throw new
UnSupportedDataTypeException(String.format(NOT_SUPPORT_DATATYPE, dataType));
}
@@ -333,13 +355,17 @@ public class Tablet {
break;
case INT32:
case FLOAT:
+ case DATE:
valueOccupation += rowSize * 4;
break;
case INT64:
case DOUBLE:
+ case TIMESTAMP:
valueOccupation += rowSize * 8;
break;
case TEXT:
+ case BLOB:
+ case STRING:
valueOccupation += rowSize * 4;
Binary[] binaries = (Binary[]) values[columnIndex];
for (int rowIndex = 0; rowIndex < rowSize; rowIndex++) {
@@ -435,7 +461,14 @@ public class Tablet {
ReadWriteIOUtils.write(intValues[j], stream);
}
break;
+ case DATE:
+ LocalDate[] dateValues = (LocalDate[]) column;
+ for (int j = 0; j < rowSize; j++) {
+
ReadWriteIOUtils.write(DateUtils.parseDateExpressionToInt(dateValues[j]),
stream);
+ }
+ break;
case INT64:
+ case TIMESTAMP:
long[] longValues = (long[]) column;
for (int j = 0; j < rowSize; j++) {
ReadWriteIOUtils.write(longValues[j], stream);
@@ -460,6 +493,8 @@ public class Tablet {
}
break;
case TEXT:
+ case BLOB:
+ case STRING:
Binary[] binaryValues = (Binary[]) column;
for (int j = 0; j < rowSize; j++) {
ReadWriteIOUtils.write(BytesUtils.boolToByte(binaryValues[j] !=
null), stream);
@@ -565,7 +600,16 @@ public class Tablet {
}
values[i] = intValues;
break;
+ case DATE:
+ LocalDate[] dateValues = new LocalDate[rowSize];
+ for (int index = 0; index < rowSize; index++) {
+ dateValues[index] =
+
DateUtils.parseIntToLocalDate(ReadWriteIOUtils.readInt(byteBuffer));
+ }
+ values[i] = dateValues;
+ break;
case INT64:
+ case TIMESTAMP:
long[] longValues = new long[rowSize];
for (int index = 0; index < rowSize; index++) {
longValues[index] = ReadWriteIOUtils.readLong(byteBuffer);
@@ -587,6 +631,8 @@ public class Tablet {
values[i] = doubleValues;
break;
case TEXT:
+ case BLOB:
+ case STRING:
Binary[] binaryValues = new Binary[rowSize];
for (int index = 0; index < rowSize; index++) {
boolean isNotNull =
BytesUtils.byteToBool(ReadWriteIOUtils.readByte(byteBuffer));
@@ -678,7 +724,20 @@ public class Tablet {
}
}
break;
+ case DATE:
+ LocalDate[] thisDateValues = (LocalDate[]) values[i];
+ LocalDate[] thatDateValues = (LocalDate[]) thatValues[i];
+ if (thisDateValues.length < rowSize || thatDateValues.length <
rowSize) {
+ return false;
+ }
+ for (int j = 0; j < rowSize; j++) {
+ if (!thisDateValues[j].equals(thatDateValues[j])) {
+ return false;
+ }
+ }
+ break;
case INT64:
+ case TIMESTAMP:
long[] thisLongValues = (long[]) values[i];
long[] thatLongValues = (long[]) thatValues[i];
if (thisLongValues.length < rowSize || thatLongValues.length <
rowSize) {
@@ -727,6 +786,8 @@ public class Tablet {
}
break;
case TEXT:
+ case BLOB:
+ case STRING:
Binary[] thisBinaryValues = (Binary[]) values[i];
Binary[] thatBinaryValues = (Binary[]) thatValues[i];
if (thisBinaryValues.length < rowSize || thatBinaryValues.length <
rowSize) {
diff --git
a/java/tsfile/src/main/java/org/apache/tsfile/write/record/datapoint/DataPoint.java
b/java/tsfile/src/main/java/org/apache/tsfile/write/record/datapoint/DataPoint.java
index 6bfa1b69..6f5e4a08 100644
---
a/java/tsfile/src/main/java/org/apache/tsfile/write/record/datapoint/DataPoint.java
+++
b/java/tsfile/src/main/java/org/apache/tsfile/write/record/datapoint/DataPoint.java
@@ -64,9 +64,11 @@ public abstract class DataPoint {
try {
switch (dataType) {
case INT32:
+ case DATE:
dataPoint = new IntDataPoint(measurementId, Integer.parseInt(value));
break;
case INT64:
+ case TIMESTAMP:
dataPoint = new LongDataPoint(measurementId, Long.parseLong(value));
break;
case FLOAT:
@@ -79,6 +81,8 @@ public abstract class DataPoint {
dataPoint = new BooleanDataPoint(measurementId,
Boolean.parseBoolean(value));
break;
case TEXT:
+ case BLOB:
+ case STRING:
dataPoint =
new StringDataPoint(measurementId, new Binary(value,
TSFileConfig.STRING_CHARSET));
break;
diff --git
a/java/tsfile/src/test/java/org/apache/tsfile/utils/DateUtilsTest.java
b/java/tsfile/src/test/java/org/apache/tsfile/utils/DateUtilsTest.java
new file mode 100644
index 00000000..6154a3a9
--- /dev/null
+++ b/java/tsfile/src/test/java/org/apache/tsfile/utils/DateUtilsTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.utils;
+
+import org.junit.Test;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeParseException;
+import java.util.Date;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+public class DateUtilsTest {
+
+ @Test
+ public void testFormatDate() {
+ int date = 20230514;
+ String formattedDate = DateUtils.formatDate(date);
+ assertEquals("2023-05-14", formattedDate);
+ }
+
+ @Test
+ public void testParseDateExpressionToInt_ValidDate() {
+ String dateExpression = "2023-05-14";
+ int dateInt = DateUtils.parseDateExpressionToInt(dateExpression);
+ assertEquals(20230514, dateInt);
+ }
+
+ @Test
+ public void testParseDateExpressionToInt_InvalidDate() {
+ String dateExpression = "2023-14-05";
+ assertThrows(
+ DateTimeParseException.class,
+ () -> {
+ DateUtils.parseDateExpressionToInt(dateExpression);
+ });
+ }
+
+ @Test
+ public void testParseDateExpressionToInt_NullOrEmpty() {
+ assertThrows(
+ DateTimeParseException.class,
+ () -> {
+ DateUtils.parseDateExpressionToInt((String) null);
+ });
+ assertThrows(
+ DateTimeParseException.class,
+ () -> {
+ DateUtils.parseDateExpressionToInt("");
+ });
+ }
+
+ @Test
+ public void testParseDateExpressionToInt_ValidLocalDate() {
+ LocalDate localDate = LocalDate.of(2023, 5, 14);
+ int dateInt = DateUtils.parseDateExpressionToInt(localDate);
+ assertEquals(20230514, dateInt);
+ }
+
+ @Test
+ public void testParseDateExpressionToInt_NullLocalDate() {
+ assertThrows(
+ DateTimeParseException.class,
+ () -> {
+ DateUtils.parseDateExpressionToInt((LocalDate) null);
+ });
+ }
+
+ @Test
+ public void testParseIntToDate() {
+ int date = 20230514;
+ Date parsedDate = DateUtils.parseIntToDate(date);
+ assertEquals(2023 - 1900, parsedDate.getYear());
+ assertEquals(4, parsedDate.getMonth()); // Date month is 0-based
+ assertEquals(14, parsedDate.getDate());
+ }
+
+ @Test
+ public void testParseIntToLocalDate() {
+ int date = 20230514;
+ LocalDate localDate = DateUtils.parseIntToLocalDate(date);
+ assertEquals(2023, localDate.getYear());
+ assertEquals(5, localDate.getMonthValue());
+ assertEquals(14, localDate.getDayOfMonth());
+ }
+
+ @Test
+ public void testParseIntToLocalDate_InvalidDate() {
+ int date = 20231405;
+ assertThrows(
+ DateTimeParseException.class,
+ () -> {
+ DateUtils.parseIntToLocalDate(date);
+ });
+ }
+}
diff --git a/java/tsfile/src/test/java/org/apache/tsfile/utils/RecordUtils.java
b/java/tsfile/src/test/java/org/apache/tsfile/utils/RecordUtils.java
index 53fc4ffe..41e72110 100644
--- a/java/tsfile/src/test/java/org/apache/tsfile/utils/RecordUtils.java
+++ b/java/tsfile/src/test/java/org/apache/tsfile/utils/RecordUtils.java
@@ -85,9 +85,11 @@ public class RecordUtils {
try {
switch (type) {
case INT32:
+ case DATE:
ret.addTuple(new IntDataPoint(measurementId,
Integer.parseInt(value)));
break;
case INT64:
+ case TIMESTAMP:
ret.addTuple(new LongDataPoint(measurementId,
Long.parseLong(value)));
break;
case FLOAT:
@@ -100,6 +102,8 @@ public class RecordUtils {
ret.addTuple(new BooleanDataPoint(measurementId,
Boolean.parseBoolean(value)));
break;
case TEXT:
+ case BLOB:
+ case STRING:
ret.addTuple(new StringDataPoint(measurementId,
BytesUtils.valueOf(items[i + 1])));
break;
default: