This is an automated email from the ASF dual-hosted git repository.
jiangtian 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 af2a7ee4 Fix tag empty error and disorder timestamp. (#489)
af2a7ee4 is described below
commit af2a7ee472dfcdc3e807f5c9fcfe19cff4e513b2
Author: Colin Lee <[email protected]>
AuthorDate: Thu Jun 19 09:47:48 2025 +0800
Fix tag empty error and disorder timestamp. (#489)
* add timestamp check.
* fix read error when tag is empty.
* fix tag empty error.
* add no_str_to_read.
* fix fmt.
* fix memory leak.
* use std::string tag in path.
* fix memory leak.
* fix memory leak.
* fix err in win.
* fix.
---
cpp/src/common/allocator/byte_stream.h | 49 ++++
cpp/src/common/allocator/my_string.h | 8 +-
cpp/src/common/constant/tsfile_constant.h | 6 +
cpp/src/common/device_id.h | 164 ++++++++-----
cpp/src/common/row_record.h | 5 +-
cpp/src/common/statistic.h | 5 +
cpp/src/common/tablet.cc | 22 +-
cpp/src/common/tsblock/tsblock.cc | 8 +-
cpp/src/common/tsblock/tsblock.h | 9 +
.../common/tsblock/vector/variable_length_vector.h | 1 +
cpp/src/common/tsfile_common.h | 31 ++-
cpp/src/file/tsfile_io_writer.cc | 1 -
cpp/src/reader/aligned_chunk_reader.cc | 3 +-
.../reader/block/single_device_tsblock_reader.cc | 22 +-
cpp/src/reader/chunk_reader.cc | 2 +-
cpp/src/reader/device_meta_iterator.cc | 1 -
cpp/src/reader/qds_with_timegenerator.cc | 4 +-
cpp/src/reader/qds_without_timegenerator.cc | 4 +-
cpp/src/reader/table_result_set.cc | 8 +-
cpp/src/utils/db_utils.h | 80 -------
cpp/src/utils/storage_utils.h | 4 +-
cpp/src/writer/time_page_writer.h | 4 +
cpp/src/writer/tsfile_writer.cc | 4 +-
cpp/test/common/device_id_test.cc | 59 +++++
cpp/test/common/row_record_test.cc | 6 +-
.../reader/table_view/tsfile_reader_table_test.cc | 12 +-
cpp/test/reader/tsfile_reader_test.cc | 4 +-
cpp/test/utils/db_utils_test.cc | 50 ----
.../writer/table_view/tsfile_writer_table_test.cc | 265 ++++++++++++++++++++-
cpp/test/writer/time_chunk_writer_test.cc | 5 -
cpp/test/writer/tsfile_writer_test.cc | 12 +-
31 files changed, 587 insertions(+), 271 deletions(-)
diff --git a/cpp/src/common/allocator/byte_stream.h
b/cpp/src/common/allocator/byte_stream.h
index 78366345..47c5148f 100644
--- a/cpp/src/common/allocator/byte_stream.h
+++ b/cpp/src/common/allocator/byte_stream.h
@@ -20,6 +20,7 @@
#ifndef COMMON_ALLOCATOR_BYTE_STREAM_H
#define COMMON_ALLOCATOR_BYTE_STREAM_H
+#include <common/constant/tsfile_constant.h>
#include <stdio.h>
#include <stdlib.h>
@@ -1047,6 +1048,54 @@ class SerializationUtil {
}
return ret;
}
+
+ // If the str is nullptr, NO_STR_TO_READ will be added instead.
+ FORCE_INLINE static int write_var_char_ptr(const std::string *str,
+ ByteStream &out) {
+ int ret = common::E_OK;
+ if (str == nullptr) {
+ write_var_int(storage::NO_STR_TO_READ, out);
+ return ret;
+ }
+ size_t str_len = str->length();
+ if (RET_FAIL(write_var_int(str_len, out))) {
+ return ret;
+ } else if (RET_FAIL(out.write_buf(str->c_str(), str_len))) {
+ return ret;
+ }
+ return ret;
+ }
+
+ // If `str` is not a nullptr after calling `read_var_char_ptr`, it
+ // indicates that memory has been allocated and must be freed.
+ FORCE_INLINE static int read_var_char_ptr(std::string *&str,
+ ByteStream &in) {
+ int ret = common::E_OK;
+ int32_t len = 0;
+ int32_t read_len = 0;
+ if (RET_FAIL(read_var_int(len, in))) {
+ return ret;
+ } else {
+ if (len == storage::NO_STR_TO_READ) {
+ str = nullptr;
+ return ret;
+ } else {
+ char *tmp_buf = static_cast<char *>(malloc(len));
+ if (RET_FAIL(in.read_buf(tmp_buf, len, read_len))) {
+ free(tmp_buf);
+ return ret;
+ } else if (len != read_len) {
+ free(tmp_buf);
+ ret = E_BUF_NOT_ENOUGH;
+ } else {
+ str = new std::string(tmp_buf, len);
+ free(tmp_buf);
+ }
+ }
+ }
+ return ret;
+ }
+
FORCE_INLINE static int read_var_str(std::string &str, ByteStream &in) {
int ret = common::E_OK;
int32_t len = 0;
diff --git a/cpp/src/common/allocator/my_string.h
b/cpp/src/common/allocator/my_string.h
index 9f5d8a5a..1f7bf00a 100644
--- a/cpp/src/common/allocator/my_string.h
+++ b/cpp/src/common/allocator/my_string.h
@@ -35,11 +35,12 @@ struct String {
String() : buf_(nullptr), len_(0) {}
String(char *buf, uint32_t len) : buf_(buf), len_(len) {}
- String(const std::string& str, common::PageArena& pa) : buf_(nullptr),
len_(0) {
+ String(const std::string &str, common::PageArena &pa)
+ : buf_(nullptr), len_(0) {
dup_from(str, pa);
}
- String(const std::string& str) {
- buf_ = (char*)str.c_str();
+ String(const std::string &str) {
+ buf_ = (char *)str.c_str();
len_ = str.size();
}
FORCE_INLINE bool is_null() const { return buf_ == nullptr && len_ == 0; }
@@ -67,6 +68,7 @@ struct String {
FORCE_INLINE int dup_from(const String &str, common::PageArena &pa) {
len_ = str.len_;
if (UNLIKELY(len_ == 0)) {
+ buf_ = nullptr;
return common::E_OK;
}
buf_ = pa.alloc(len_);
diff --git a/cpp/src/common/constant/tsfile_constant.h
b/cpp/src/common/constant/tsfile_constant.h
index af5d70f7..e1f4fd34 100644
--- a/cpp/src/common/constant/tsfile_constant.h
+++ b/cpp/src/common/constant/tsfile_constant.h
@@ -16,6 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
+
+#ifndef COMMON_CONSTANT_TSFILE_CONSTANT_H_
+#define COMMON_CONSTANT_TSFILE_CONSTANT_H_
#include <string>
#include <regex>
@@ -38,8 +41,11 @@ namespace storage
static const unsigned char VALUE_COLUMN_MASK = 0x40;
static const std::string TIME_COLUMN_ID = "";
+ static const int NO_STR_TO_READ = -1;
static const std::regex
IDENTIFIER_PATTERN("([a-zA-Z0-9_\\u2E80-\\u9FFF]+)");
static const std::regex
NODE_NAME_PATTERN("(\\*{0,2}[a-zA-Z0-9_\\u2E80-\\u9FFF]+\\*{0,2})");
static const int DEFAULT_SEGMENT_NUM_FOR_TABLE_NAME = 3;
} // namespace storage
+
+#endif
diff --git a/cpp/src/common/device_id.h b/cpp/src/common/device_id.h
index 021cb6aa..b3a173db 100644
--- a/cpp/src/common/device_id.h
+++ b/cpp/src/common/device_id.h
@@ -35,25 +35,25 @@
namespace storage {
class IDeviceID {
-public:
+ public:
virtual ~IDeviceID() = default;
virtual int serialize(common::ByteStream& write_stream) { return 0; }
virtual int deserialize(common::ByteStream& read_stream) { return 0; }
virtual std::string get_table_name() { return ""; }
virtual int segment_num() { return 0; }
- virtual const std::vector<std::string>& get_segments() const {
+ virtual const std::vector<std::string*>& get_segments() const {
return empty_segments_;
}
virtual std::string get_device_name() const { return ""; };
- virtual bool operator<(const IDeviceID& other) { return 0; }
+ virtual bool operator<(const IDeviceID& other) { return false; }
virtual bool operator==(const IDeviceID& other) { return false; }
virtual bool operator!=(const IDeviceID& other) { return false; }
-protected:
+ protected:
IDeviceID() : empty_segments_() {}
-private:
- const std::vector<std::string> empty_segments_;
+ private:
+ const std::vector<std::string*> empty_segments_;
};
struct IDeviceIDComparator {
@@ -64,23 +64,51 @@ struct IDeviceIDComparator {
};
class StringArrayDeviceID : public IDeviceID {
-public:
+ public:
explicit StringArrayDeviceID(const std::vector<std::string>& segments)
: segments_(formalize(segments)) {}
- explicit StringArrayDeviceID(const std::string& device_id_string)
- : segments_(split_device_id_string(device_id_string)) {}
+ explicit StringArrayDeviceID(const std::string& device_id_string) {
+ auto segments = split_device_id_string(device_id_string);
+ segments_.reserve(segments.size());
+ for (const auto& segment : segments) {
+ segments_.push_back(new std::string(segment));
+ }
+ }
+
+ explicit StringArrayDeviceID(const std::vector<std::string*>& segments) {
+ segments_.reserve(segments.size());
+ for (const auto& segment : segments) {
+ segments_.push_back(segment == nullptr ? nullptr
+ : new
std::string(*segment));
+ }
+ }
explicit StringArrayDeviceID() : segments_() {}
- ~StringArrayDeviceID() override = default;
+ ~StringArrayDeviceID() override {
+ for (const auto& segment : segments_) {
+ delete segment;
+ }
+ }
std::string get_device_name() const override {
- return segments_.empty() ? "" :
std::accumulate(std::next(segments_.begin()), segments_.end(),
- segments_.front(),
- [](std::string a, const std::string& b) {
- return std::move(a) + "." + b;
- });
+ if (segments_.empty()) {
+ return "";
+ }
+
+ std::string result(*segments_.front());
+ for (auto it = std::next(segments_.begin()); it != segments_.end();
+ ++it) {
+ result += '.';
+ if (*it != nullptr) {
+ result += **it;
+ } else {
+ result += "null";
+ }
+ }
+
+ return result;
};
int serialize(common::ByteStream& write_stream) override {
@@ -88,12 +116,12 @@ public:
if (RET_FAIL(common::SerializationUtil::write_var_uint(segment_num(),
write_stream)))
{
return ret;
- }
+ }
for (const auto& segment : segments_) {
- if (RET_FAIL(common::SerializationUtil::write_var_str(segment,
- write_stream))) {
+ if (RET_FAIL(common::SerializationUtil::write_var_char_ptr(
+ segment, write_stream))) {
return ret;
- }
+ }
}
return ret;
}
@@ -101,13 +129,23 @@ public:
int deserialize(common::ByteStream& read_stream) override {
int ret = common::E_OK;
uint32_t num_segments;
- if (RET_FAIL(common::SerializationUtil::read_var_uint(num_segments,
read_stream))) {
+ if (RET_FAIL(common::SerializationUtil::read_var_uint(num_segments,
+ read_stream))) {
return ret;
}
+
+ for (auto& segment : segments_) {
+ if (segment != nullptr) {
+ delete segment;
+ }
+ }
+
segments_.clear();
for (uint32_t i = 0; i < num_segments; ++i) {
- std::string segment;
- if (RET_FAIL(common::SerializationUtil::read_var_str(segment,
read_stream))) {
+ std::string* segment;
+ if (RET_FAIL(common::SerializationUtil::read_var_char_ptr(
+ segment, read_stream))) {
+ delete segment;
return ret;
}
segments_.push_back(segment);
@@ -116,52 +154,69 @@ public:
}
std::string get_table_name() override {
- return segments_.empty() ? "" : segments_[0];
+ return segments_.empty() ? "" : *segments_[0];
}
int segment_num() override { return static_cast<int>(segments_.size()); }
- const std::vector<std::string>& get_segments() const override {
+ const std::vector<std::string*>& get_segments() const override {
return segments_;
}
- virtual bool operator<(const IDeviceID& other) override {
+ bool operator<(const IDeviceID& other) override {
auto other_segments = other.get_segments();
- return std::lexicographical_compare(segments_.begin(), segments_.end(),
- other_segments.begin(),
- other_segments.end());
+ return std::lexicographical_compare(
+ segments_.begin(), segments_.end(), other_segments.begin(),
+ other_segments.end(),
+ [](const std::string* a, const std::string* b) {
+ if (a == nullptr && b == nullptr) return false; // equal
+ if (a == nullptr) return true; // nullptr < any string
+ if (b == nullptr) return false; // any string > nullptr
+ return *a < *b;
+ });
}
bool operator==(const IDeviceID& other) override {
auto other_segments = other.get_segments();
return (segments_.size() == other_segments.size()) &&
std::equal(segments_.begin(), segments_.end(),
- other_segments.begin());
+ other_segments.begin(),
+ [](const std::string* a, const std::string* b) {
+ if (a == nullptr && b == nullptr) return true;
+ if (a == nullptr || b == nullptr) return false;
+ return *a == *b;
+ });
}
bool operator!=(const IDeviceID& other) override {
return !(*this == other);
}
-private:
- std::vector<std::string> segments_;
+ private:
+ std::vector<std::string*> segments_;
- std::vector<std::string> formalize(
+ static std::vector<std::string*> formalize(
const std::vector<std::string>& segments) {
auto it =
std::find_if(segments.rbegin(), segments.rend(),
[](const std::string& seg) { return !seg.empty(); });
- return std::vector<std::string>(segments.begin(), it.base());
+ std::vector<std::string> validate_segments(segments.begin(),
it.base());
+ std::vector<std::string*> result;
+ result.reserve(validate_segments.size());
+ for (const auto& segment : validate_segments) {
+ result.emplace_back(new std::string(segment));
+ }
+ return result;
}
- std::vector<std::string> split_device_id_string(
+ static std::vector<std::string> split_device_id_string(
const std::string& device_id_string) {
auto splits =
storage::PathNodesGenerator::invokeParser(device_id_string);
return split_device_id_string(splits);
}
- std::vector<std::string> split_device_id_string(
+ static std::vector<std::string> split_device_id_string(
const std::vector<std::string>& splits) {
size_t segment_cnt = splits.size();
std::vector<std::string> final_segments;
@@ -173,8 +228,9 @@ private:
if (segment_cnt == 1) {
// "root" -> {"root"}
final_segments.push_back(splits[0]);
- } else if (segment_cnt < static_cast<size_t>(
- storage::DEFAULT_SEGMENT_NUM_FOR_TABLE_NAME + 1)) {
+ } else if (segment_cnt <
+ static_cast<size_t>(
+ storage::DEFAULT_SEGMENT_NUM_FOR_TABLE_NAME + 1)) {
// "root.a" -> {"root", "a"}
// "root.a.b" -> {"root.a", "b"}
std::string table_name = std::accumulate(
@@ -184,26 +240,26 @@ private:
});
final_segments.push_back(table_name);
final_segments.push_back(splits.back());
- } else {
- // "root.a.b.c" -> {"root.a.b", "c"}
- // "root.a.b.c.d" -> {"root.a.b", "c", "d"}
- std::string table_name = std::accumulate(
- splits.begin(),
- splits.begin() +
storage::DEFAULT_SEGMENT_NUM_FOR_TABLE_NAME,
- std::string(), [](const std::string& a, const std::string&
b) {
- return a.empty() ? b : a + storage::PATH_SEPARATOR + b;
- });
-
- final_segments.emplace_back(std::move(table_name));
- final_segments.insert(
- final_segments.end(),
- splits.begin() +
storage::DEFAULT_SEGMENT_NUM_FOR_TABLE_NAME,
- splits.end());
- }
+ } else {
+ // "root.a.b.c" -> {"root.a.b", "c"}
+ // "root.a.b.c.d" -> {"root.a.b", "c", "d"}
+ std::string table_name = std::accumulate(
+ splits.begin(),
+ splits.begin() + storage::DEFAULT_SEGMENT_NUM_FOR_TABLE_NAME,
+ std::string(), [](const std::string& a, const std::string& b) {
+ return a.empty() ? b : a + storage::PATH_SEPARATOR + b;
+ });
+
+ final_segments.emplace_back(std::move(table_name));
+ final_segments.insert(
+ final_segments.end(),
+ splits.begin() + storage::DEFAULT_SEGMENT_NUM_FOR_TABLE_NAME,
+ splits.end());
+ }
return final_segments;
}
};
-}
+} // namespace storage
#endif
\ No newline at end of file
diff --git a/cpp/src/common/row_record.h b/cpp/src/common/row_record.h
index 2e449a5f..902913eb 100644
--- a/cpp/src/common/row_record.h
+++ b/cpp/src/common/row_record.h
@@ -55,8 +55,7 @@ struct Field {
is_type(common::NULL_TYPE);
}
- template <class T>
- FORCE_INLINE void set_value(common::TSDataType type, T val,
+ void set_value(common::TSDataType type, void* val, size_t len,
common::PageArena &pa) {
if (val == nullptr) {
type_ = common::NULL_TYPE;
@@ -86,7 +85,7 @@ struct Field {
}
case common::STRING: {
value_.strval_ = new common::String();
- value_.strval_->dup_from(*(common::String *)val, pa);
+ value_.strval_->dup_from(std::string(static_cast<char*>(val),
len), pa);
break;
}
// case common::TEXT: {
diff --git a/cpp/src/common/statistic.h b/cpp/src/common/statistic.h
index 8eb866e2..7590a6e0 100644
--- a/cpp/src/common/statistic.h
+++ b/cpp/src/common/statistic.h
@@ -164,6 +164,11 @@ class Statistic {
ASSERT(false);
return 0;
}
+
+ int get_count() const { return count_; }
+
+ int64_t get_end_time() const { return end_time_; }
+
virtual int deserialize_from(common::ByteStream &in) {
int ret = common::E_OK;
if (RET_FAIL(common::SerializationUtil::read_var_uint(
diff --git a/cpp/src/common/tablet.cc b/cpp/src/common/tablet.cc
index 8bc801cf..08671793 100644
--- a/cpp/src/common/tablet.cc
+++ b/cpp/src/common/tablet.cc
@@ -334,22 +334,36 @@ void Tablet::set_column_categories(
}
std::shared_ptr<IDeviceID> Tablet::get_device_id(int i) const {
- std::vector<std::string> id_array;
- id_array.push_back(insert_target_name_);
+ std::vector<std::string *> id_array;
+ id_array.push_back(new std::string(insert_target_name_));
for (auto id_column_idx : id_column_indexes_) {
common::TSDataType data_type = INVALID_DATATYPE;
void *value_ptr = get_value(i, id_column_idx, data_type);
+ if (value_ptr == nullptr) {
+ id_array.push_back(nullptr);
+ continue;
+ }
common::String str;
switch (data_type) {
case STRING:
str = *static_cast<common::String *>(value_ptr);
- id_array.push_back(str.to_std_string());
+ if (str.buf_ == nullptr || str.len_ == 0) {
+ id_array.push_back(new std::string());
+ } else {
+ id_array.push_back(new std::string(str.buf_, str.len_));
+ }
break;
default:
break;
}
}
- return std::make_shared<StringArrayDeviceID>(id_array);
+ auto res = std::make_shared<StringArrayDeviceID>(id_array);
+ for (auto &id : id_array) {
+ if (id != nullptr) {
+ delete id;
+ }
+ }
+ return res;
}
} // end namespace storage
\ No newline at end of file
diff --git a/cpp/src/common/tsblock/tsblock.cc
b/cpp/src/common/tsblock/tsblock.cc
index f290e3f6..8b93a501 100644
--- a/cpp/src/common/tsblock/tsblock.cc
+++ b/cpp/src/common/tsblock/tsblock.cc
@@ -72,24 +72,24 @@ void TsBlock::write_data(ByteStream *__restrict byte_stream,
switch (type) {
case common::INT64: {
int64_t ival = *reinterpret_cast<int64_t *>(val);
- strval = to_string(ival);
+ strval = std::to_string(ival);
break;
}
case common::INT32: {
int32_t ival = *reinterpret_cast<int32_t *>(val);
- strval = to_string(ival);
+ strval = std::to_string(ival);
break;
}
case common::FLOAT: {
float ival = *reinterpret_cast<float *>(
val); // cppcheck-suppress invalidPointerCast
- strval = to_string(ival);
+ strval = std::to_string(ival);
break;
}
case common::DOUBLE: {
double ival = *reinterpret_cast<double *>(
val); // cppcheck-suppress invalidPointerCast
- strval = to_string(ival);
+ strval = std::to_string(ival);
break;
}
case common::BOOLEAN: {
diff --git a/cpp/src/common/tsblock/tsblock.h b/cpp/src/common/tsblock/tsblock.h
index 47f110cc..4316e8f6 100644
--- a/cpp/src/common/tsblock/tsblock.h
+++ b/cpp/src/common/tsblock/tsblock.h
@@ -202,6 +202,15 @@ class ColAppender {
FORCE_INLINE uint32_t get_col_row_count() { return column_row_count_; }
FORCE_INLINE uint32_t get_column_index() { return column_index_; }
+ FORCE_INLINE int fill_null(uint32_t end_index) {
+ while (column_row_count_ < end_index) {
+ if (!add_row()) {
+ return E_INVALID_ARG;
+ }
+ append_null();
+ }
+ return E_OK;
+ }
FORCE_INLINE int fill(const char *value, uint32_t len,
uint32_t end_index) {
while (column_row_count_ < end_index) {
diff --git a/cpp/src/common/tsblock/vector/variable_length_vector.h
b/cpp/src/common/tsblock/vector/variable_length_vector.h
index bec599ac..23ebb75d 100644
--- a/cpp/src/common/tsblock/vector/variable_length_vector.h
+++ b/cpp/src/common/tsblock/vector/variable_length_vector.h
@@ -61,6 +61,7 @@ class VariableLengthVector : public Vector {
*null = nulls_.test(rowid);
} else {
*null = false;
+ *len = 0;
}
if (LIKELY(!(*null))) {
char *result = values_.read(offset_, len);
diff --git a/cpp/src/common/tsfile_common.h b/cpp/src/common/tsfile_common.h
index 878fc4d2..f20632ee 100644
--- a/cpp/src/common/tsfile_common.h
+++ b/cpp/src/common/tsfile_common.h
@@ -621,10 +621,10 @@ class TSMIterator {
common::String &ret_measurement_name,
TimeseriesIndex &ret_ts_index);
-private:
- common::SimpleList<ChunkGroupMeta *> &chunk_group_meta_list_;
- common::SimpleList<ChunkGroupMeta *>::Iterator chunk_group_meta_iter_;
- common::SimpleList<ChunkMeta *>::Iterator chunk_meta_iter_;
+ private:
+ common::SimpleList<ChunkGroupMeta *> &chunk_group_meta_list_;
+ common::SimpleList<ChunkGroupMeta *>::Iterator chunk_group_meta_iter_;
+ common::SimpleList<ChunkMeta *>::Iterator chunk_meta_iter_;
// timeseries measurenemnt chunk meta info
// map <device_name, <measurement_name, vector<chunk_meta>>>
@@ -651,10 +651,10 @@ struct IComparable {
virtual int compare(const IComparable &other) {
if (this->operator<(other)) {
return -1;
- } else if (this->operator>(other)) {
- return 1;
- } else {
+ } else if (this->operator==(other)) {
return 0;
+ } else {
+ return 1;
}
}
virtual std::string to_string() const = 0;
@@ -670,24 +670,21 @@ struct DeviceIDComparable : IComparable {
const auto *other_device =
dynamic_cast<const DeviceIDComparable *>(&other);
if (!other_device) throw std::runtime_error("Incompatible comparison");
- return device_id_->get_device_name() <
- other_device->device_id_->get_device_name();
+ return *device_id_ < *other_device->device_id_;
}
bool operator>(const IComparable &other) const override {
const auto *other_device =
dynamic_cast<const DeviceIDComparable *>(&other);
if (!other_device) throw std::runtime_error("Incompatible comparison");
- return device_id_->get_device_name() >
- other_device->device_id_->get_device_name();
+ return *device_id_ != *other_device->device_id_ && !(*device_id_ <
*other_device->device_id_);
}
bool operator==(const IComparable &other) const override {
const auto *other_device =
dynamic_cast<const DeviceIDComparable *>(&other);
if (!other_device) throw std::runtime_error("Incompatible comparison");
- return device_id_->get_device_name() ==
- other_device->device_id_->get_device_name();
+ return *device_id_ == *other_device->device_id_;
}
std::string to_string() const override {
@@ -908,10 +905,10 @@ struct MetaIndexNode {
}
}
- int binary_search_children(std::shared_ptr<IComparable> key,
- bool exact_search,
- std::shared_ptr<IMetaIndexEntry>
&ret_index_entry,
- int64_t &ret_end_offset);
+ int binary_search_children(
+ std::shared_ptr<IComparable> key, bool exact_search,
+ std::shared_ptr<IMetaIndexEntry> &ret_index_entry,
+ int64_t &ret_end_offset);
int serialize_to(common::ByteStream &out) {
int ret = common::E_OK;
diff --git a/cpp/src/file/tsfile_io_writer.cc b/cpp/src/file/tsfile_io_writer.cc
index af4c29dc..4d19b12e 100644
--- a/cpp/src/file/tsfile_io_writer.cc
+++ b/cpp/src/file/tsfile_io_writer.cc
@@ -409,7 +409,6 @@ int TsFileIOWriter::write_file_index() {
// Time column also need add to bloom filter.
ret = filter.add_path_entry(tmp_device_name, measurement_name);
-
if (RET_FAIL(ts_index.serialize_to(write_stream_))) {
} else {
#if DEBUG_SE
diff --git a/cpp/src/reader/aligned_chunk_reader.cc
b/cpp/src/reader/aligned_chunk_reader.cc
index 06af8699..230661f3 100644
--- a/cpp/src/reader/aligned_chunk_reader.cc
+++ b/cpp/src/reader/aligned_chunk_reader.cc
@@ -209,7 +209,6 @@ int AlignedChunkReader::get_next_page(TsBlock *ret_tsblock,
int ret = E_OK;
Filter *filter =
(oneshoot_filter != nullptr ? oneshoot_filter : time_filter_);
-
if (prev_time_page_not_finish() && prev_value_page_not_finish()) {
ret = decode_time_value_buf_into_tsblock(ret_tsblock, oneshoot_filter);
return ret;
@@ -550,7 +549,7 @@ int AlignedChunkReader::decode_time_value_buf_into_tsblock(
continue;
\
} else {
\
/*std::cout << "decoder: time=" << time << ", value=" << value
\
- * << std::endl;*/
\
+ * << std::endl;*/ \
row_appender.append(0, (char *)&time, sizeof(time));
\
row_appender.append(1, (char *)&value, sizeof(value));
\
}
\
diff --git a/cpp/src/reader/block/single_device_tsblock_reader.cc
b/cpp/src/reader/block/single_device_tsblock_reader.cc
index ec8059f9..90a642b2 100644
--- a/cpp/src/reader/block/single_device_tsblock_reader.cc
+++ b/cpp/src/reader/block/single_device_tsblock_reader.cc
@@ -67,9 +67,6 @@ int SingleDeviceTsBlockReader::init(DeviceQueryTask*
device_query_task,
device_query_task->get_device_id(),
device_query_task->get_column_mapping()->get_measurement_columns(),
time_series_indexs, pa_);
- for (auto measurement_column :
- device_query_task->get_column_mapping()->get_measurement_columns()) {
- }
for (const auto& time_series_index : time_series_indexs) {
construct_column_context(time_series_index, time_filter);
}
@@ -104,9 +101,11 @@ int SingleDeviceTsBlockReader::has_next(bool& has_next) {
has_next = false;
return common::E_OK;
}
+
for (auto col_appender : col_appenders_) {
col_appender->reset();
}
+
current_block_->reset();
bool next_time_set = false;
@@ -199,11 +198,20 @@ int SingleDeviceTsBlockReader::fill_ids() {
for (const auto& entry : id_column_contexts_) {
const auto& id_column_context = entry.second;
for (int32_t pos : id_column_context.pos_in_result_) {
- common::String device_id(
- device_query_task_->get_device_id()->get_segments().at(
- id_column_context.pos_in_device_id_));
+ std::string* device_tag = nullptr;
+ device_tag =
device_query_task_->get_device_id()->get_segments().at(
+ id_column_context.pos_in_device_id_);
+ if (device_tag == nullptr) {
+ ret = col_appenders_[pos + 1]->fill_null(
+ current_block_->get_row_count());
+ if (ret != common::E_OK) {
+ return ret;
+ }
+ continue;
+ }
+
if (RET_FAIL(col_appenders_[pos + 1]->fill(
- (char*)&device_id, sizeof(device_id),
+ device_tag->c_str(), device_tag->length(),
current_block_->get_row_count()))) {
return ret;
}
diff --git a/cpp/src/reader/chunk_reader.cc b/cpp/src/reader/chunk_reader.cc
index f1e395da..afe7740a 100644
--- a/cpp/src/reader/chunk_reader.cc
+++ b/cpp/src/reader/chunk_reader.cc
@@ -437,7 +437,7 @@ int
ChunkReader::STRING_DECODE_TYPED_TV_INTO_TSBLOCK(ByteStream &time_in,
continue;
} else {
row_appender.append(0, (char *)&time, sizeof(time));
- row_appender.append(1, (char *)&value, sizeof(value));
+ row_appender.append(1, value.buf_, value.len_);
}
}
return ret;
diff --git a/cpp/src/reader/device_meta_iterator.cc
b/cpp/src/reader/device_meta_iterator.cc
index d4512263..e3c61dc8 100644
--- a/cpp/src/reader/device_meta_iterator.cc
+++ b/cpp/src/reader/device_meta_iterator.cc
@@ -28,7 +28,6 @@ bool DeviceMetaIterator::has_next() {
if (load_results() != common::E_OK) {
return false;
}
-
return !result_cache_.empty();
}
diff --git a/cpp/src/reader/qds_with_timegenerator.cc
b/cpp/src/reader/qds_with_timegenerator.cc
index fd0e1292..c93eb5c0 100644
--- a/cpp/src/reader/qds_with_timegenerator.cc
+++ b/cpp/src/reader/qds_with_timegenerator.cc
@@ -357,7 +357,7 @@ int QDSWithTimeGenerator::next(bool &has_next) {
return E_OK;
}
row_record_->set_timestamp(timestamp);
- row_record_->get_field(0)->set_value(TSDataType::INT64, ×tamp, pa_);
+ row_record_->get_field(0)->set_value(TSDataType::INT64, ×tamp,
sizeof(timestamp), pa_);
#if DEBUG_SE
std::cout << "QDSWithTimeGenerator::get_next: timestamp=" << timestamp
<< ", will generate row at this timestamp." << std::endl;
@@ -366,7 +366,7 @@ int QDSWithTimeGenerator::next(bool &has_next) {
for (size_t i = 0; i < value_at_vec_.size(); i++) {
ValueAt &va = value_at_vec_[i];
void *val_obj_ptr = va.at(timestamp);
- row_record_->get_field(i + 1)->set_value(va.data_type_, val_obj_ptr,
+ row_record_->get_field(i + 1)->set_value(va.data_type_, val_obj_ptr,
get_len(va.data_type_),
pa_);
}
diff --git a/cpp/src/reader/qds_without_timegenerator.cc
b/cpp/src/reader/qds_without_timegenerator.cc
index 805c9c4d..b2323da8 100644
--- a/cpp/src/reader/qds_without_timegenerator.cc
+++ b/cpp/src/reader/qds_without_timegenerator.cc
@@ -117,7 +117,7 @@ int QDSWithoutTimeGenerator::next(bool &has_next) {
}
int64_t time = heap_time_.begin()->first;
row_record_->set_timestamp(time);
- row_record_->get_field(0)->set_value(INT64, &time, pa_);
+ row_record_->get_field(0)->set_value(INT64, &time, get_len(INT64), pa_);
uint32_t count = heap_time_.count(time);
std::multimap<int64_t, uint32_t>::iterator iter = heap_time_.find(time);
@@ -125,7 +125,7 @@ int QDSWithoutTimeGenerator::next(bool &has_next) {
uint32_t len = 0;
row_record_->get_field(iter->second + 1)
->set_value(value_iters_[iter->second]->get_data_type(),
- value_iters_[iter->second]->read(&len), pa_);
+ value_iters_[iter->second]->read(&len), len, pa_);
value_iters_[iter->second]->next();
if (!time_iters_[iter->second]->end()) {
int64_t timev = *(int64_t
*)(time_iters_[iter->second]->read(&len));
diff --git a/cpp/src/reader/table_result_set.cc
b/cpp/src/reader/table_result_set.cc
index bbadc44a..396913e9 100644
--- a/cpp/src/reader/table_result_set.cc
+++ b/cpp/src/reader/table_result_set.cc
@@ -70,9 +70,11 @@ int TableResultSet::next(bool& has_next) {
bool null = false;
row_record_->reset();
for (uint32_t i = 0; i < row_iterator_->get_column_count(); ++i) {
- row_record_->get_field(i)->set_value(
- row_iterator_->get_data_type(i),
- row_iterator_->read(i, &len, &null), pa_);
+ const auto value = row_iterator_->read(i, &len, &null);
+ if (!null) {
+
row_record_->get_field(i)->set_value(row_iterator_->get_data_type(i),
+ value, len, pa_);
+ }
}
row_iterator_->next();
}
diff --git a/cpp/src/utils/db_utils.h b/cpp/src/utils/db_utils.h
index 4b5aca9b..592bb0ed 100644
--- a/cpp/src/utils/db_utils.h
+++ b/cpp/src/utils/db_utils.h
@@ -150,86 +150,6 @@ struct TsID {
}
};
-struct DeviceID {
- NodeID db_nid_;
- NodeID device_nid_;
-
- DeviceID() : db_nid_(0), device_nid_(0) {}
- DeviceID(const NodeID db_nid, const NodeID device_nid)
- : db_nid_(db_nid), device_nid_(device_nid) {}
- explicit DeviceID(const TsID &ts_id)
- : db_nid_(ts_id.db_nid_), device_nid_(ts_id.device_nid_) {}
-
- FORCE_INLINE bool operator==(const DeviceID &other) const {
- return db_nid_ == other.db_nid_ && device_nid_ == other.device_nid_;
- }
- FORCE_INLINE bool operator!=(const DeviceID &other) const {
- return db_nid_ != other.db_nid_ || device_nid_ != other.device_nid_;
- }
- FORCE_INLINE void from(const TsID &ts_id) {
- db_nid_ = ts_id.db_nid_;
- device_nid_ = ts_id.device_nid_;
- }
- FORCE_INLINE bool operator<(const DeviceID &that) const {
- int32_t this_i32 = (((int32_t)db_nid_) << 16) | (device_nid_);
- int32_t that_i32 = (((int32_t)that.db_nid_) << 16) |
(that.device_nid_);
- return this_i32 < that_i32;
- }
-};
-
-#define INVALID_TTL (-1)
-
-// describe single database
-struct DatabaseDesc {
- int64_t ttl_;
- std::string db_name_;
- TsID ts_id_;
-
- DatabaseDesc() : ttl_(INVALID_TTL), db_name_(""), ts_id_() {}
- DatabaseDesc(uint64_t ttl, const std::string &name, const TsID &ts_id)
- : ttl_(ttl), db_name_(name), ts_id_(ts_id) {}
-};
-
-enum WALFlushPolicy {
- WAL_DISABLED = 0,
- WAL_ASYNC = 1,
- WAL_FLUSH = 2,
- WAL_SYNC = 3,
-};
-
-template <typename T>
-std::string to_string(const T &val) {
- // todo: There may be a better way to avoid the memory problem of
- // ostringstream
- std::ostringstream oss;
- oss << val;
- return oss.str();
-}
-
-// TODO rename to DatabaseIdTTL
-struct DatabaseIdTTL {
- NodeID db_nid_;
- int64_t ttl_;
- DatabaseIdTTL() {}
- DatabaseIdTTL(NodeID db_nid, int64_t ttl) : db_nid_(db_nid), ttl_(ttl) {}
- DatabaseIdTTL(const DatabaseIdTTL &other)
- : db_nid_(other.db_nid_), ttl_(other.ttl_) {}
- DatabaseIdTTL &operator=(const DatabaseIdTTL &other) {
- this->db_nid_ = other.db_nid_;
- this->ttl_ = other.ttl_;
- return *this;
- }
- bool operator==(const DatabaseIdTTL &other) {
- if (db_nid_ != other.db_nid_ || ttl_ != other.ttl_) {
- return false;
- }
- return true;
- }
- friend std::ostream &operator<<(std::ostream &out, DatabaseIdTTL &di) {
- out << "(" << di.db_nid_ << ", " << di.ttl_ << ") ";
- return out;
- }
-};
/**
* @brief Represents the schema information for a single measurement.
diff --git a/cpp/src/utils/storage_utils.h b/cpp/src/utils/storage_utils.h
index 698a7303..a152a57e 100644
--- a/cpp/src/utils/storage_utils.h
+++ b/cpp/src/utils/storage_utils.h
@@ -75,12 +75,12 @@ FORCE_INLINE std::string get_file_path_from_file_id(
return oss.str();
}
-static void to_lowercase_inplace(std::string &str) {
+FORCE_INLINE static void to_lowercase_inplace(std::string &str) {
std::transform(
str.begin(), str.end(), str.begin(),
[](unsigned char c) -> unsigned char { return std::tolower(c); });
}
-static std::string to_lower(const std::string &str) {
+FORCE_INLINE static std::string to_lower(const std::string &str) {
std::string result;
std::transform(
str.begin(), str.end(), std::back_inserter(result),
diff --git a/cpp/src/writer/time_page_writer.h
b/cpp/src/writer/time_page_writer.h
index bc5b8212..bbf70165 100644
--- a/cpp/src/writer/time_page_writer.h
+++ b/cpp/src/writer/time_page_writer.h
@@ -73,6 +73,10 @@ class TimePageWriter {
FORCE_INLINE int write(int64_t timestamp) {
int ret = common::E_OK;
+ if (statistic_->count_ != 0 && is_inited_ &&
+ timestamp <= statistic_->end_time_) {
+ return common::E_OUT_OF_ORDER;
+ }
if (RET_FAIL(time_encoder_->encode(timestamp, time_out_stream_))) {
} else {
statistic_->update(timestamp);
diff --git a/cpp/src/writer/tsfile_writer.cc b/cpp/src/writer/tsfile_writer.cc
index 0f47756d..dcf6608b 100644
--- a/cpp/src/writer/tsfile_writer.cc
+++ b/cpp/src/writer/tsfile_writer.cc
@@ -751,7 +751,9 @@ int TsFileWriter::write_table(Tablet &tablet) {
return ret;
}
for (int i = start_idx; i < end_idx; i++) {
- time_chunk_writer->write(tablet.timestamps_[i]);
+ if (RET_FAIL(time_chunk_writer->write(tablet.timestamps_[i])))
{
+ return ret;
+ }
}
uint32_t field_col_count = 0;
for (uint32_t i = 0; i < tablet.get_column_count(); ++i) {
diff --git a/cpp/test/common/device_id_test.cc
b/cpp/test/common/device_id_test.cc
new file mode 100644
index 00000000..64a294c4
--- /dev/null
+++ b/cpp/test/common/device_id_test.cc
@@ -0,0 +1,59 @@
+/*
+ * 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 a
+ *
+ * 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.
+ */
+
+#include "common/device_id.h"
+
+#include <gtest/gtest.h>
+#include "common/tablet.h"
+
+namespace storage {
+using namespace ::common;
+TEST(DeviceIdTest, NormalTest) {
+ std::string device_id_string = "root.db.tb.device1";
+ StringArrayDeviceID device_id = StringArrayDeviceID(device_id_string);
+ ASSERT_EQ("root.db.tb.device1", device_id.get_device_name());
+}
+
+TEST(DeviceIdTest, TabletDeviceId) {
+ std::vector<TSDataType> measurement_types{
+ TSDataType::STRING, TSDataType::STRING, TSDataType::STRING,
TSDataType::INT32};
+ std::vector<ColumnCategory> column_categories{ColumnCategory::TAG,
ColumnCategory::TAG, ColumnCategory::TAG, ColumnCategory::FIELD};
+ std::vector<std::string> measurement_names{"tag1", "tag2",
+ "tag3", "value"};
+
+ Tablet tablet("test_device0", measurement_names, measurement_types,
column_categories);
+ tablet.add_timestamp(0, 1);
+ tablet.add_value(0, 0, "t1");
+ tablet.add_value(0, 1, "t2");
+ tablet.add_value(0, 2, "t3");
+ tablet.add_value(1, 0, "");
+ tablet.add_value(1, 1, "t2");
+ tablet.add_value(1, 2, "t3");
+ tablet.add_value(2, 1, "t2");
+ tablet.add_value(2, 2, "t3");
+ auto device_id = std::make_shared<StringArrayDeviceID>(
+ std::vector<std::string>({"test_device0", "t1", "t2", "t3"}));
+ auto device_id2 = tablet.get_device_id(0);
+ ASSERT_TRUE(*device_id2 == *device_id);
+
+ ASSERT_EQ("test_device0..t2.t3",
tablet.get_device_id(1)->get_device_name());
+ ASSERT_EQ("test_device0.null.t2.t3",
tablet.get_device_id(2)->get_device_name());
+
+}
+}
diff --git a/cpp/test/common/row_record_test.cc
b/cpp/test/common/row_record_test.cc
index fd6e41f0..b753dbf5 100644
--- a/cpp/test/common/row_record_test.cc
+++ b/cpp/test/common/row_record_test.cc
@@ -22,6 +22,8 @@
#include <vector>
+#include "common/tsblock/tuple_desc.h"
+
namespace storage {
TEST(FieldTest, DefaultConstructor) {
@@ -62,12 +64,12 @@ TEST(FieldTest, SetValue) {
Field field;
common::PageArena pa; // dosen't matter
int32_t i32_val = 123;
- field.set_value(common::INT32, &i32_val, pa);
+ field.set_value(common::INT32, &i32_val, common::get_len(common::INT32),
pa);
EXPECT_EQ(field.type_, common::INT32);
EXPECT_EQ(field.value_.ival_, 123);
double d_val = 3.14;
- field.set_value(common::DOUBLE, &d_val, pa);
+ field.set_value(common::DOUBLE, &d_val, common::get_len(common::DOUBLE),
pa);
EXPECT_EQ(field.type_, common::DOUBLE);
EXPECT_DOUBLE_EQ(field.value_.dval_, 3.14);
}
diff --git a/cpp/test/reader/table_view/tsfile_reader_table_test.cc
b/cpp/test/reader/table_view/tsfile_reader_table_test.cc
index d2f4a8a3..2bdc74b2 100644
--- a/cpp/test/reader/table_view/tsfile_reader_table_test.cc
+++ b/cpp/test/reader/table_view/tsfile_reader_table_test.cc
@@ -80,17 +80,17 @@ class TsFileTableReaderTest : public ::testing::Test {
int measurement_schema_num = 5;
for (int i = 0; i < id_schema_num; i++) {
measurement_schemas.emplace_back(new MeasurementSchema(
- "id" + to_string(i), TSDataType::STRING, TSEncoding::PLAIN,
+ "id" + std::to_string(i), TSDataType::STRING,
TSEncoding::PLAIN,
CompressionType::UNCOMPRESSED));
column_categories.emplace_back(ColumnCategory::TAG);
}
for (int i = 0; i < measurement_schema_num; i++) {
measurement_schemas.emplace_back(new MeasurementSchema(
- "s" + to_string(i), TSDataType::INT64, TSEncoding::PLAIN,
+ "s" + std::to_string(i), TSDataType::INT64, TSEncoding::PLAIN,
CompressionType::UNCOMPRESSED));
column_categories.emplace_back(ColumnCategory::FIELD);
}
- return new TableSchema("testTable" + to_string(table_num),
+ return new TableSchema("testTable" + std::to_string(table_num),
measurement_schemas, column_categories);
}
@@ -254,12 +254,12 @@ TEST_F(TsFileTableReaderTest, TableModelResultMetadata) {
ASSERT_EQ(result_set_metadata->get_column_type(1), INT64);
for (int i = 2; i <= 6; i++) {
ASSERT_EQ(result_set_metadata->get_column_name(i),
- "id" + to_string(i - 2));
+ "id" + std::to_string(i - 2));
ASSERT_EQ(result_set_metadata->get_column_type(i), TSDataType::STRING);
}
for (int i = 7; i <= 11; i++) {
ASSERT_EQ(result_set_metadata->get_column_name(i),
- "s" + to_string(i - 7));
+ "s" + std::to_string(i - 7));
ASSERT_EQ(result_set_metadata->get_column_type(i), TSDataType::INT64);
}
reader.destroy_query_data_set(table_result_set);
@@ -296,7 +296,7 @@ TEST_F(TsFileTableReaderTest, TableModelGetSchema) {
ASSERT_EQ(table_schemas.size(), 10);
for (int i = 0; i < 10; i++) {
ASSERT_EQ(table_schemas[i]->get_table_name(),
- "testtable" + to_string(i));
+ "testtable" + std::to_string(i));
for (int j = 0; j < 5; j++) {
ASSERT_EQ(table_schemas[i]->get_data_types()[j],
TSDataType::STRING);
diff --git a/cpp/test/reader/tsfile_reader_test.cc
b/cpp/test/reader/tsfile_reader_test.cc
index a52eec7a..0b360eb4 100644
--- a/cpp/test/reader/tsfile_reader_test.cc
+++ b/cpp/test/reader/tsfile_reader_test.cc
@@ -160,13 +160,13 @@ TEST_F(TsFileReaderTest, GetAllDevice) {
for (size_t i = 0; i < 1024; i++) {
tsfile_writer_->register_timeseries(
- "device.ln" + to_string(i),
+ "device.ln" + std::to_string(i),
storage::MeasurementSchema(measurement_name, data_type, encoding,
compression_type));
}
for (size_t i = 0; i < 1024; i++) {
- TsRecord record(1622505600000, "device.ln" + to_string(i));
+ TsRecord record(1622505600000, "device.ln" + std::to_string(i));
record.add_point(measurement_name, (int32_t)0);
ASSERT_EQ(tsfile_writer_->write_record(record), E_OK);
}
diff --git a/cpp/test/utils/db_utils_test.cc b/cpp/test/utils/db_utils_test.cc
index ae0e8376..fb455eea 100644
--- a/cpp/test/utils/db_utils_test.cc
+++ b/cpp/test/utils/db_utils_test.cc
@@ -117,56 +117,6 @@ TEST(TsIDTest, OperatorLess) {
EXPECT_FALSE(ts_id2 < ts_id1);
}
-TEST(DeviceIDTest, Constructor) {
- DeviceID device_id;
- EXPECT_EQ(device_id.db_nid_, 0);
- EXPECT_EQ(device_id.device_nid_, 0);
-}
-
-TEST(DeviceIDTest, ParameterizedConstructor) {
- DeviceID device_id(1, 2);
- EXPECT_EQ(device_id.db_nid_, 1);
- EXPECT_EQ(device_id.device_nid_, 2);
-}
-
-TEST(DeviceIDTest, TsIDConstructor) {
- TsID ts_id(1, 2, 3);
- DeviceID device_id(ts_id);
- EXPECT_EQ(device_id.db_nid_, 1);
- EXPECT_EQ(device_id.device_nid_, 2);
-}
-
-TEST(DeviceIDTest, OperatorEqual) {
- DeviceID device_id1(1, 2);
- DeviceID device_id2(1, 2);
- EXPECT_TRUE(device_id1 == device_id2);
- device_id2.db_nid_ = 3;
- EXPECT_FALSE(device_id1 == device_id2);
-}
-
-TEST(DeviceIDTest, OperatorNotEqual) {
- DeviceID device_id1(1, 2);
- DeviceID device_id2(1, 2);
- EXPECT_FALSE(device_id1 != device_id2);
- device_id2.db_nid_ = 3;
- EXPECT_TRUE(device_id1 != device_id2);
-}
-
-TEST(DatabaseDescTest, Constructor) {
- DatabaseDesc db_desc;
- EXPECT_EQ(db_desc.ttl_, INVALID_TTL);
- EXPECT_EQ(db_desc.db_name_, "");
- EXPECT_EQ(db_desc.ts_id_.db_nid_, 0);
-}
-
-TEST(DatabaseDescTest, ParameterizedConstructor) {
- TsID ts_id(1, 2, 3);
- DatabaseDesc db_desc(1000, "test_db", ts_id);
- EXPECT_EQ(db_desc.ttl_, 1000);
- EXPECT_EQ(db_desc.db_name_, "test_db");
- EXPECT_EQ(db_desc.ts_id_, ts_id);
-}
-
TEST(ColumnSchemaTest, Constructor) {
ColumnSchema col_schema;
EXPECT_EQ(col_schema.data_type_, INVALID_DATATYPE);
diff --git a/cpp/test/writer/table_view/tsfile_writer_table_test.cc
b/cpp/test/writer/table_view/tsfile_writer_table_test.cc
index a13c20be..44636078 100644
--- a/cpp/test/writer/table_view/tsfile_writer_table_test.cc
+++ b/cpp/test/writer/table_view/tsfile_writer_table_test.cc
@@ -37,7 +37,7 @@ class TsFileWriterTableTest : public ::testing::Test {
libtsfile_init();
file_name_ = std::string("tsfile_writer_table_test_") +
generate_random_string(10) + std::string(".tsfile");
- remove(file_name_.c_str());
+ int ret = remove(file_name_.c_str());
int flags = O_WRONLY | O_CREAT | O_TRUNC;
#ifdef _WIN32
flags |= O_BINARY;
@@ -45,7 +45,10 @@ class TsFileWriterTableTest : public ::testing::Test {
mode_t mode = 0666;
write_file_.create(file_name_, flags, mode);
}
- void TearDown() override { remove(file_name_.c_str()); }
+ void TearDown() override {
+ int ret = remove(file_name_.c_str());
+ ASSERT_EQ(ret, 0);
+ }
std::string file_name_;
WriteFile write_file_;
@@ -76,17 +79,17 @@ class TsFileWriterTableTest : public ::testing::Test {
int measurement_schema_num = 5;
for (int i = 0; i < id_schema_num; i++) {
measurement_schemas.emplace_back(new MeasurementSchema(
- "id" + to_string(i), TSDataType::STRING, TSEncoding::PLAIN,
+ "id" + std::to_string(i), TSDataType::STRING,
TSEncoding::PLAIN,
CompressionType::UNCOMPRESSED));
column_categories.emplace_back(ColumnCategory::TAG);
}
for (int i = 0; i < measurement_schema_num; i++) {
measurement_schemas.emplace_back(new MeasurementSchema(
- "s" + to_string(i), TSDataType::INT64, TSEncoding::PLAIN,
+ "s" + std::to_string(i), TSDataType::INT64, TSEncoding::PLAIN,
CompressionType::UNCOMPRESSED));
column_categories.emplace_back(ColumnCategory::FIELD);
}
- return new TableSchema("testTable" + to_string(table_num),
+ return new TableSchema("testTable" + std::to_string(table_num),
measurement_schemas, column_categories);
}
@@ -187,6 +190,56 @@ TEST_F(TsFileWriterTableTest, WithoutTagAndMultiPage) {
delete table_schema;
}
+TEST_F(TsFileWriterTableTest, WriteDisorderTest) {
+ auto table_schema = gen_table_schema(0);
+ auto tsfile_table_writer_ =
+ std::make_shared<TsFileTableWriter>(&write_file_, table_schema);
+
+ int device_num = 1;
+ int num_timestamp_per_device = 10;
+ int offset = 0;
+ storage::Tablet tablet(table_schema->get_measurement_names(),
+ table_schema->get_data_types(),
+ device_num * num_timestamp_per_device);
+
+ char* literal = new char[std::strlen("device_id") + 1];
+ std::strcpy(literal, "device_id");
+ String literal_str(literal, std::strlen("device_id"));
+ for (int i = 0; i < device_num; i++) {
+ for (int l = 0; l < num_timestamp_per_device; l++) {
+ int row_index = i * num_timestamp_per_device + l;
+ // disordered timestamp.
+ tablet.add_timestamp(row_index, l > num_timestamp_per_device / 2
+ ? l - num_timestamp_per_device
+ : offset + l);
+ auto column_schemas = table_schema->get_measurement_schemas();
+ for (const auto& column_schema : column_schemas) {
+ switch (column_schema->data_type_) {
+ case TSDataType::INT64:
+ tablet.add_value(row_index,
+ column_schema->measurement_name_,
+ static_cast<int64_t>(i));
+ break;
+ case TSDataType::STRING:
+ tablet.add_value(row_index,
+ column_schema->measurement_name_,
+ literal_str);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ delete[] literal;
+
+ ASSERT_EQ(tsfile_table_writer_->write_table(tablet),
+ common::E_OUT_OF_ORDER);
+ ASSERT_EQ(tsfile_table_writer_->flush(), common::E_OK);
+ ASSERT_EQ(tsfile_table_writer_->close(), common::E_OK);
+ delete table_schema;
+}
+
TEST_F(TsFileWriterTableTest, WriteTableTestMultiFlush) {
auto table_schema = gen_table_schema(0);
auto tsfile_table_writer_ = std::make_shared<TsFileTableWriter>(
@@ -250,6 +303,62 @@ TEST_F(TsFileWriterTableTest, WriterWithMemoryThreshold) {
delete table_schema;
}
+TEST_F(TsFileWriterTableTest, EmptyTagWrite) {
+ std::vector<MeasurementSchema*> measurement_schemas;
+ std::vector<ColumnCategory> column_categories;
+ measurement_schemas.resize(3);
+ measurement_schemas[0] = new MeasurementSchema("device1", STRING);
+ measurement_schemas[1] = new MeasurementSchema("device2", STRING);
+ measurement_schemas[2] = new MeasurementSchema("value", DOUBLE);
+ column_categories.emplace_back(ColumnCategory::TAG);
+ column_categories.emplace_back(ColumnCategory::TAG);
+ column_categories.emplace_back(ColumnCategory::FIELD);
+ TableSchema* table_schema =
+ new TableSchema("test_table", measurement_schemas, column_categories);
+ auto tsfile_table_writer =
+ std::make_shared<TsFileTableWriter>(&write_file_, table_schema);
+ Tablet tablet = Tablet(table_schema->get_measurement_names(),
+ table_schema->get_data_types());
+ tablet.set_table_name("test_table");
+ for (int i = 0; i < 100; i++) {
+ tablet.add_timestamp(i, static_cast<int64_t>(i));
+ tablet.add_value(i, "device1",
+ std::string("device" + std::to_string(i)).c_str());
+ tablet.add_value(i, "device2", "");
+ tablet.add_value(i, "value", i * 1.1);
+ }
+ tsfile_table_writer->write_table(tablet);
+ tsfile_table_writer->flush();
+ tsfile_table_writer->close();
+
+ TsFileReader reader = TsFileReader();
+ reader.open(write_file_.get_file_path());
+ ResultSet* ret = nullptr;
+ int ret_value =
+ reader.query("test_table", {"device1", "device2", "value"}, 0, 50,
ret);
+ ASSERT_EQ(common::E_OK, ret_value);
+
+ ASSERT_EQ(ret_value, 0);
+ auto* table_result_set = (TableResultSet*)ret;
+ bool has_next = false;
+ int cur_line = 0;
+ while (IS_SUCC(table_result_set->next(has_next)) && has_next) {
+ cur_line++;
+ int64_t timestamp = table_result_set->get_value<int64_t>("time");
+ ASSERT_EQ(table_result_set->get_value<common::String*>("device1")
+ ->to_std_string(),
+ "device" + std::to_string(timestamp));
+ ASSERT_EQ(table_result_set->get_value<double>("value"),
+ timestamp * 1.1);
+ }
+ ASSERT_EQ(cur_line, 51);
+ table_result_set->close();
+ reader.destroy_query_data_set(table_result_set);
+
+ reader.close();
+ delete table_schema;
+}
+
TEST_F(TsFileWriterTableTest, WritehDataTypeMisMatch) {
auto table_schema = gen_table_schema(0);
auto tsfile_table_writer_ = std::make_shared<TsFileTableWriter>(
@@ -263,9 +372,6 @@ TEST_F(TsFileWriterTableTest, WritehDataTypeMisMatch) {
storage::Tablet tablet(table_schema->get_measurement_names(), datatypes,
device_num * num_timestamp_per_device);
- char* literal = new char[std::strlen("device_id") + 1];
- std::strcpy(literal, "device_id");
- String literal_str(literal, std::strlen("device_id"));
for (int i = 0; i < device_num; i++) {
for (int l = 0; l < num_timestamp_per_device; l++) {
int row_index = i * num_timestamp_per_device + l;
@@ -284,9 +390,9 @@ TEST_F(TsFileWriterTableTest, WritehDataTypeMisMatch) {
static_cast<int32_t>(i));
break;
case TSDataType::STRING:
- tablet.add_value(row_index,
-
column_schemas[idx]->measurement_name_,
- literal_str);
+ tablet.add_value(
+ row_index, column_schemas[idx]->measurement_name_,
+ std::string("device" + std::to_string(i)).c_str());
break;
default:
break;
@@ -294,7 +400,6 @@ TEST_F(TsFileWriterTableTest, WritehDataTypeMisMatch) {
}
}
}
- delete[] literal;
delete table_schema;
ASSERT_EQ(E_TYPE_NOT_MATCH, tsfile_table_writer_->write_table(tablet));
@@ -341,7 +446,7 @@ TEST_F(TsFileWriterTableTest, WriteAndReadSimple) {
int64_t timestamp = table_result_set->get_value<int64_t>("time");
ASSERT_EQ(table_result_set->get_value<common::String*>("device")
->to_std_string(),
- "device" + to_string(timestamp));
+ "device" + std::to_string(timestamp));
ASSERT_EQ(table_result_set->get_value<double>("value"),
timestamp * 1.1);
}
@@ -388,5 +493,139 @@ TEST_F(TsFileWriterTableTest, DuplicateColumnName) {
ASSERT_EQ(E_INVALID_ARG, tsfile_table_writer->write_table(tablet));
ASSERT_EQ(E_INVALID_ARG, tsfile_table_writer->register_table(
std::make_shared<TableSchema>(*table_schema)));
+ tsfile_table_writer->close();
+ delete table_schema;
+}
+
+TEST_F(TsFileWriterTableTest, WriteWithNullAndEmptyTag) {
+ std::vector<MeasurementSchema*> measurement_schemas;
+ std::vector<ColumnCategory> column_categories;
+ for (int i = 0; i < 3; i++) {
+ measurement_schemas.emplace_back(new MeasurementSchema(
+ "id" + std::to_string(i), TSDataType::STRING));
+ column_categories.emplace_back(ColumnCategory::TAG);
+ }
+ measurement_schemas.emplace_back(new MeasurementSchema("value", DOUBLE));
+ column_categories.emplace_back(ColumnCategory::FIELD);
+ auto table_schema =
+ new TableSchema("testTable", measurement_schemas, column_categories);
+ auto tsfile_table_writer =
+ std::make_shared<TsFileTableWriter>(&write_file_, table_schema);
+ int time = 0;
+ Tablet tablet = Tablet(table_schema->get_measurement_names(),
+ table_schema->get_data_types(), 10);
+
+ for (int i = 0; i < 10; i++) {
+ tablet.add_timestamp(i, static_cast<int64_t>(time++));
+ tablet.add_value(i, 0, "tag1");
+ tablet.add_value(i, 1, "tag2");
+ tablet.add_value(i, 2, "tag3");
+ tablet.add_value(i, 3, 100.0f);
+ }
+
+ tsfile_table_writer->write_table(tablet);
+ Tablet tablet2 = Tablet(table_schema->get_measurement_names(),
+ table_schema->get_data_types(), 10);
+
+ for (int i = 0; i < 10; i++) {
+ tablet2.add_timestamp(i, static_cast<int64_t>(time++));
+ tablet2.add_value(i, 0, i % 2 == 0 ? "" : "tag4");
+ tablet2.add_value(i, 1, i % 2 == 1 ? "" : "tag5");
+ tablet2.add_value(i, 2, i % 3 == 0 ? "" : "tag6");
+ tablet2.add_value(i, 3, 101.0f);
+ }
+ tsfile_table_writer->write_table(tablet2);
+
+ Tablet tablet3 = Tablet(table_schema->get_measurement_names(),
+ table_schema->get_data_types(), 10);
+ for (int i = 0; i < 10; i++) {
+ tablet3.add_timestamp(i, static_cast<int64_t>(time++));
+ tablet3.add_value(i, 0, "tag7");
+ if (i % 2 == 0) {
+ tablet3.add_value(i, 1, "tag8\0ta");
+ } else {
+ tablet3.add_value(i, 2, "tag9");
+ }
+ tablet3.add_value(i, 3, 102.0f);
+ }
+
+ tsfile_table_writer->write_table(tablet3);
+ tsfile_table_writer->flush();
+ tsfile_table_writer->close();
+
delete table_schema;
+
+ auto reader = TsFileReader();
+ reader.open(write_file_.get_file_path());
+ ResultSet* ret = nullptr;
+ int ret_value =
+ reader.query("testTable", {"id0", "id1", "id2", "value"}, 0, 50, ret);
+ ASSERT_EQ(common::E_OK, ret_value);
+
+ auto table_result_set = (TableResultSet*)ret;
+ bool has_next = false;
+ int cur_line = 0;
+ auto schema = table_result_set->get_metadata();
+ while (IS_SUCC(table_result_set->next(has_next)) && has_next) {
+ int64_t timestamp = table_result_set->get_value<int64_t>(1);
+ switch (timestamp) {
+ case 0: {
+ // All tag fields have valid values.
+ ASSERT_EQ(common::String(std::string("tag1")),
+ *table_result_set->get_value<common::String*>(2));
+ ASSERT_EQ(common::String(std::string("tag2")),
+ *table_result_set->get_value<common::String*>(3));
+ ASSERT_EQ(common::String(std::string("tag3")),
+ *table_result_set->get_value<common::String*>(4));
+ ASSERT_EQ(100.0f, table_result_set->get_value<double>(5));
+ break;
+ }
+ case 10: {
+ // The first and last tag fields are empty strings.
+ ASSERT_EQ(common::String(std::string("")),
+ *table_result_set->get_value<common::String*>(2));
+ ASSERT_EQ(common::String(std::string("tag5")),
+ *table_result_set->get_value<common::String*>(3));
+ ASSERT_EQ(common::String(std::string("")),
+ *table_result_set->get_value<common::String*>(4));
+ ASSERT_EQ(101.0f, table_result_set->get_value<double>(5));
+ break;
+ }
+ case 11: {
+ // The middle tag field is an empty string.
+ ASSERT_EQ(common::String(std::string("tag4")),
+ *table_result_set->get_value<common::String*>(2));
+ ASSERT_EQ(common::String(std::string("")),
+ *table_result_set->get_value<common::String*>(3));
+ ASSERT_EQ(common::String(std::string("tag6")),
+ *table_result_set->get_value<common::String*>(4));
+ ASSERT_EQ(101.0f, table_result_set->get_value<double>(5));
+ break;
+ }
+ case 20: {
+ // The last tag field is null.
+ ASSERT_EQ(common::String(std::string("tag7")),
+ *table_result_set->get_value<common::String*>(2));
+ ASSERT_EQ(common::String(std::string("tag8\0ta")),
+ *table_result_set->get_value<common::String*>(3));
+ ASSERT_TRUE(table_result_set->is_null(4));
+ ASSERT_EQ(102.0f, table_result_set->get_value<double>(5));
+ break;
+ }
+ case 21: {
+ // The middle tag field is null.
+ ASSERT_EQ(common::String(std::string("tag7")),
+ *table_result_set->get_value<common::String*>(2));
+ ASSERT_EQ(common::String(std::string("tag9")),
+ *table_result_set->get_value<common::String*>(4));
+ ASSERT_TRUE(table_result_set->is_null(3));
+ ASSERT_EQ(102.0f, table_result_set->get_value<double>(5));
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ reader.destroy_query_data_set(table_result_set);
+ ASSERT_EQ(reader.close(), common::E_OK);
}
\ No newline at end of file
diff --git a/cpp/test/writer/time_chunk_writer_test.cc
b/cpp/test/writer/time_chunk_writer_test.cc
index 1f1910c4..df79ab28 100644
--- a/cpp/test/writer/time_chunk_writer_test.cc
+++ b/cpp/test/writer/time_chunk_writer_test.cc
@@ -52,11 +52,6 @@ TEST_F(TimeChunkWriterTest, InitWithParameters) {
writer.destroy();
}
-TEST_F(TimeChunkWriterTest, WriteBoolean) {
- EXPECT_EQ(time_chunk_writer.write(true), E_OK);
- EXPECT_EQ(time_chunk_writer.write(false), E_OK);
-}
-
TEST_F(TimeChunkWriterTest, WriteLargeDataSet) {
for (int i = 0; i < 10000; ++i) {
time_chunk_writer.write(i);
diff --git a/cpp/test/writer/tsfile_writer_test.cc
b/cpp/test/writer/tsfile_writer_test.cc
index 6f58f0cb..d8c0d414 100644
--- a/cpp/test/writer/tsfile_writer_test.cc
+++ b/cpp/test/writer/tsfile_writer_test.cc
@@ -706,7 +706,7 @@ TEST_F(TsFileWriterTest, WriteAlignedTimeseries) {
std::string device_name = "device";
std::vector<std::string> measurement_names;
for (int i = 0; i < measurement_num; i++) {
- measurement_names.emplace_back("temperature" + to_string(i));
+ measurement_names.emplace_back("temperature" + std::to_string(i));
}
common::TSDataType data_type = common::TSDataType::INT32;
@@ -735,7 +735,7 @@ TEST_F(TsFileWriterTest, WriteAlignedTimeseries) {
std::vector<storage::Path> select_list;
for (int i = 0; i < measurement_num; ++i) {
- std::string measurement_name = "temperature" + to_string(i);
+ std::string measurement_name = "temperature" + std::to_string(i);
storage::Path path(device_name, measurement_name);
select_list.push_back(path);
}
@@ -776,7 +776,7 @@ TEST_F(TsFileWriterTest, WriteAlignedMultiFlush) {
std::string device_name = "device";
std::vector<std::string> measurement_names;
for (int i = 0; i < measurement_num; i++) {
- measurement_names.emplace_back("temperature" + to_string(i));
+ measurement_names.emplace_back("temperature" + std::to_string(i));
}
common::TSDataType data_type = common::TSDataType::INT32;
@@ -805,7 +805,7 @@ TEST_F(TsFileWriterTest, WriteAlignedMultiFlush) {
std::vector<storage::Path> select_list;
for (int i = 0; i < measurement_num; ++i) {
- std::string measurement_name = "temperature" + to_string(i);
+ std::string measurement_name = "temperature" + std::to_string(i);
storage::Path path(device_name, measurement_name);
select_list.push_back(path);
}
@@ -846,7 +846,7 @@ TEST_F(TsFileWriterTest, WriteAlignedPartialData) {
std::string device_name = "device";
std::vector<std::string> measurement_names;
for (int i = 0; i < measurement_num; i++) {
- measurement_names.emplace_back("temperature" + to_string(i));
+ measurement_names.emplace_back("temperature" + std::to_string(i));
}
common::TSDataType data_type = common::TSDataType::INT32;
@@ -874,7 +874,7 @@ TEST_F(TsFileWriterTest, WriteAlignedPartialData) {
std::vector<storage::Path> select_list;
for (int i = 0; i < measurement_num; ++i) {
- std::string measurement_name = "temperature" + to_string(i);
+ std::string measurement_name = "temperature" + std::to_string(i);
storage::Path path(device_name, measurement_name);
select_list.push_back(path);
}