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 1beaf27ca support C wrapper for tsfile v4. (#387)
1beaf27ca is described below

commit 1beaf27cacd4f1698bcd22e2f45d0003dfd48e50
Author: Colin Lee <[email protected]>
AuthorDate: Thu Feb 13 10:28:05 2025 +0800

    support C wrapper for tsfile v4. (#387)
    
    * add tmp code.
    
    * add cwrapper file.
    
    * add C tsfile.
    
    * add c v4.
    
    * fix tree.
    
    * remove useless func.
    
    * c wrapper v4.
    
    * fix some error.
    
    * add cwrapper test.
    
    * fix cwrapper.
    
    * add some uts.
    
    * fix cwrapper.
    
    * fix cwrapper v4.
    
    * fix cwrapper.
    
    * fix cmake .
    
    * fix comment.
    
    * fix cmake.
    
    * fix memory leak.
    
    * fix path laxer asan warning.
    
    * fix some isste.
    
    * fix cpp err.
    
    * fix remove lazy.
    
    ---------
    
    Co-authored-by: Jiang Tian <[email protected]>
---
 .github/workflows/unit-test-cpp-py.yml         |   2 +-
 cpp/CMakeLists.txt                             |   2 +-
 cpp/src/common/schema.h                        |   2 +-
 cpp/src/common/tablet.h                        |   1 +
 cpp/src/cwrapper/CMakeLists.txt                |   2 +-
 cpp/src/cwrapper/TsFile-cwrapper.cc            | 853 -------------------------
 cpp/src/cwrapper/TsFile-cwrapper.h             | 235 -------
 cpp/src/cwrapper/tsfile_cwrapper.cc            | 444 +++++++++++++
 cpp/src/cwrapper/tsfile_cwrapper.h             | 254 ++++++++
 cpp/src/cwrapper/tsfile_cwrapper_expression.cc | 207 ++++++
 cpp/src/cwrapper/tsfile_cwrapper_expression.h  | 101 +++
 cpp/src/reader/result_set.h                    |   9 +-
 cpp/src/reader/tsfile_reader.cc                |  30 +-
 cpp/src/reader/tsfile_reader.h                 |   1 +
 cpp/src/writer/tsfile_writer.cc                |   8 +-
 cpp/src/writer/tsfile_writer.h                 |   2 +-
 cpp/test/CMakeLists.txt                        |   2 +
 cpp/test/common/tsfile_common_test.cc          |   1 -
 cpp/test/cwrapper/cwrapper_test.cc             | 130 +++-
 19 files changed, 1156 insertions(+), 1130 deletions(-)

diff --git a/.github/workflows/unit-test-cpp-py.yml 
b/.github/workflows/unit-test-cpp-py.yml
index f4833e1f1..31c4f6907 100644
--- a/.github/workflows/unit-test-cpp-py.yml
+++ b/.github/workflows/unit-test-cpp-py.yml
@@ -78,7 +78,7 @@ jobs:
       - name: Build and test with Maven
         shell: bash
         run: |
-          ./mvnw${{ steps.platform_suffix.outputs.platform_suffix }} -P 
with-cpp,with-python clean verify
+          ./mvnw${{ steps.platform_suffix.outputs.platform_suffix }} -P 
with-cpp clean verify
 
       - name: Upload whl Artifact
         uses: actions/upload-artifact@v4
diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
index 8f402dd9a..e8bd08ac2 100755
--- a/cpp/CMakeLists.txt
+++ b/cpp/CMakeLists.txt
@@ -21,7 +21,7 @@ project(TsFile_CPP)
 
 cmake_policy(SET CMP0079 NEW)
 set(TsFile_CPP_VERSION 2.1.0.dev)
-set(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} -Wall -Werror")
+set(CMAKE_CXX_FLAGS "$ENV{CXXFLAGS} -Wall")
 if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=maybe-uninitialized")
 endif()
diff --git a/cpp/src/common/schema.h b/cpp/src/common/schema.h
index 50761199d..7fcda4e88 100644
--- a/cpp/src/common/schema.h
+++ b/cpp/src/common/schema.h
@@ -151,7 +151,7 @@ namespace storage {
         TimeChunkWriter *time_chunk_writer_ = nullptr;
     };
 
-    enum class ColumnCategory { TAG, FIELD };
+    enum class ColumnCategory { TAG = 0, FIELD = 1 };
 
     class TableSchema {
     public:
diff --git a/cpp/src/common/tablet.h b/cpp/src/common/tablet.h
index 647e2f673..b725ac075 100644
--- a/cpp/src/common/tablet.h
+++ b/cpp/src/common/tablet.h
@@ -98,6 +98,7 @@ class Tablet {
                        [](const std::string &name, common::TSDataType type) {
                            return MeasurementSchema(name, type);
                        });
+        schema_vec_ = 
std::make_shared<std::vector<MeasurementSchema>>(measurement_vec);
     }
 
     Tablet(const std::string &insert_target_name,
diff --git a/cpp/src/cwrapper/CMakeLists.txt b/cpp/src/cwrapper/CMakeLists.txt
index 345c66d3c..27fd9f3ed 100644
--- a/cpp/src/cwrapper/CMakeLists.txt
+++ b/cpp/src/cwrapper/CMakeLists.txt
@@ -18,5 +18,5 @@ under the License.
 ]]
 message("Running in cwrapper directory")
 set(CMAKE_POSITION_INDEPENDENT_CODE ON)
-aux_source_directory(. CWRAPPER_SRC_LIST)
+aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} CWRAPPER_SRC_LIST)
 add_library(cwrapper_obj OBJECT ${CWRAPPER_SRC_LIST})
\ No newline at end of file
diff --git a/cpp/src/cwrapper/TsFile-cwrapper.cc 
b/cpp/src/cwrapper/TsFile-cwrapper.cc
deleted file mode 100644
index 347608304..000000000
--- a/cpp/src/cwrapper/TsFile-cwrapper.cc
+++ /dev/null
@@ -1,853 +0,0 @@
-/*
- * 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.
- */
-
-#include "cwrapper/TsFile-cwrapper.h"
-
-#include <iomanip>
-
-#include "common/global.h"
-#include "reader/expression.h"
-#include "reader/filter/and_filter.h"
-#include "reader/filter/filter.h"
-#include "reader/filter/time_filter.h"
-#include "reader/filter/time_operator.h"
-#include "reader/result_set.h"
-#include "reader/tsfile_reader.h"
-#include "utils/errno_define.h"
-#include "writer/tsfile_writer.h"
-
-static bool is_init = false;
-
-#define INSERT_DATA_INTO_RECORD(record, column, value)               \
-    do {                                                             \
-        DataPoint point(column, value);                              \
-        if (record->points_.size() + 1 > record->points_.capacity()) \
-            return E_BUF_NOT_ENOUGH;                                 \
-        record->points_.push_back(point);                            \
-        return E_OK;                                                 \
-    } while (0)
-
-#define CONSTRUCT_EXP_INTERNAL(exp, column_name) \
-    do {                                         \
-        exp.column_name = column_name;           \
-        exp.operatype = oper;                    \
-        exp.children_length = 0;                 \
-    } while (0)
-
-#define INSERT_DATA_TABLET_STEP                                             \
-    do {                                                                    \
-        for (int i = 0; i < tablet->column_num; i++) {                      \
-            if (strcmp(tablet->column_schema[i]->name, column_name) == 0) { \
-                column_id = i;                                              \
-                break;                                                      \
-            }                                                               \
-        }                                                                   \
-        if (column_id == -1) {                                              \
-            return tablet;                                                  \
-        }                                                                   \
-        if (tablet->cur_num + 1 > tablet->max_capacity) {                   \
-            return tablet;                                                  \
-        }                                                                   \
-        tablet->times[line_id] = timestamp;                                 \
-    } while (0)
-#define TSDataType common::TSDataType
-#define TSEncoding common::TSEncoding
-#define CompressionType common::CompressionType
-#define TsFileReader storage::TsFileReader
-#define TsFileWriter storage::TsFileWriter
-#define E_OK common::E_OK
-#define TsRecord storage::TsRecord
-#define DataPoint storage::DataPoint
-#define E_BUF_NOT_ENOUGH common::E_BUF_NOT_ENOUGH
-
-TSDataType get_datatype(SchemaInfo schema_info) {
-    if (schema_info & TS_TYPE_BOOLEAN) {
-        return TSDataType::BOOLEAN;
-    } else if (schema_info & TS_TYPE_DOUBLE) {
-        return TSDataType::DOUBLE;
-    } else if (schema_info & TS_TYPE_FLOAT) {
-        return TSDataType::FLOAT;
-    } else if (schema_info & TS_TYPE_INT32) {
-        return TSDataType::INT32;
-    } else if (schema_info & TS_TYPE_INT64) {
-        return TSDataType::INT64;
-    } else if (schema_info & TS_TYPE_TEXT) {
-        return TSDataType::TEXT;
-    }
-    return TSDataType::INVALID_DATATYPE;
-}
-
-TSEncoding get_data_encoding(SchemaInfo schema_info) {
-    if (schema_info & TS_ENCODING_PLAIN) {
-        return TSEncoding::PLAIN;
-    } else if (schema_info & TS_ENCODING_TS_DIFF) {
-        return TSEncoding::DIFF;
-    } else if (schema_info & TS_ENCODING_BITMAP) {
-        return TSEncoding::BITMAP;
-    } else if (schema_info & TS_ENCODING_GORILLA) {
-        return TSEncoding::GORILLA;
-    }
-    return TSEncoding::PLAIN;
-}
-
-CompressionType get_data_compression(SchemaInfo schema_info) {
-    if (schema_info & TS_COMPRESS_UNCOMPRESS) {
-        return CompressionType::UNCOMPRESSED;
-    } else if (schema_info & TS_COMPRESS_LZ4) {
-        return CompressionType::LZ4;
-    }
-    return CompressionType::UNCOMPRESSED;
-}
-
-SchemaInfo get_schema_info(TSDataType type) {
-    switch (type) {
-        case TSDataType::BOOLEAN:
-            return TS_TYPE_BOOLEAN;
-        case TSDataType::DOUBLE:
-            return TS_TYPE_DOUBLE;
-        case TSDataType::FLOAT:
-            return TS_TYPE_FLOAT;
-        case TSDataType::INT32:
-            return TS_TYPE_INT32;
-        case TSDataType::INT64:
-            return TS_TYPE_INT64;
-        case TSDataType::TEXT:
-            return TS_TYPE_TEXT;
-        default:
-            return 0;
-    }
-}
-
-void init_tsfile_config() {
-    if (!is_init) {
-        common::init_config_value();
-        is_init = true;
-    }
-}
-
-CTsFileReader ts_reader_open(const char* pathname, ErrorCode* err_code) {
-    init_tsfile_config();
-    TsFileReader* reader = new TsFileReader();
-    int ret = reader->open(pathname);
-    if (ret != E_OK) {
-        std::cout << "open file failed" << std::endl;
-        *err_code = ret;
-        delete reader;
-        return nullptr;
-    }
-    return reader;
-}
-
-CTsFileWriter ts_writer_open(const char* pathname, ErrorCode* err_code) {
-    init_tsfile_config();
-    TsFileWriter* writer = new TsFileWriter();
-    int flags = O_WRONLY | O_CREAT | O_TRUNC;
-#ifdef _WIN32
-    flags |= O_BINARY;
-#endif
-    int ret = writer->open(pathname, flags, 0644);
-    if (ret != E_OK) {
-        delete writer;
-        *err_code = ret;
-        return nullptr;
-    }
-    return writer;
-}
-
-CTsFileWriter ts_writer_open_flag(const char* pathname, mode_t flag,
-                                  ErrorCode* err_code) {
-    init_tsfile_config();
-    TsFileWriter* writer = new TsFileWriter();
-    int ret = writer->open(pathname, O_CREAT | O_RDWR, flag);
-    if (ret != E_OK) {
-        delete writer;
-        *err_code = ret;
-        return nullptr;
-    }
-    return writer;
-}
-
-CTsFileWriter ts_writer_open_conf(const char* pathname, int flag,
-                                  ErrorCode* err_code, TsFileConf* conf) {
-    *err_code = common::E_INVALID_ARG;
-    return nullptr;
-}
-
-ErrorCode ts_writer_close(CTsFileWriter writer) {
-    TsFileWriter* w = (TsFileWriter*)writer;
-    int ret = w->close();
-    delete w;
-    return ret;
-}
-
-ErrorCode ts_reader_close(CTsFileReader reader) {
-    TsFileReader* ts_reader = (TsFileReader*)reader;
-    delete ts_reader;
-    return E_OK;
-}
-
-ErrorCode tsfile_register_table_column(CTsFileWriter writer,
-                                       const char* table_name,
-                                       ColumnSchema* schema) {
-    TsFileWriter* w = (TsFileWriter*)writer;
-
-    int ret = w->register_timeseries(
-        table_name, storage::MeasurementSchema(
-                        schema->name, get_datatype(schema->column_def),
-                        get_data_encoding(schema->column_def),
-                        get_data_compression(schema->column_def)));
-    return ret;
-}
-
-ErrorCode tsfile_register_table(CTsFileWriter writer,
-                                TableSchema* table_schema) {
-    TsFileWriter* w = (TsFileWriter*)writer;
-    for (int column_id = 0; column_id < table_schema->column_num; column_id++) 
{
-        ColumnSchema* schema = table_schema->column_schema[column_id];
-        ErrorCode ret = w->register_timeseries(
-            table_schema->table_name,
-            storage::MeasurementSchema(
-                schema->name, get_datatype(schema->column_def),
-                get_data_encoding(schema->column_def),
-                get_data_compression(schema->column_def)));
-        if (ret != E_OK) {
-            return ret;
-        }
-    }
-    return E_OK;
-}
-
-TsFileRowData create_tsfile_row(const char* table_name, int64_t timestamp,
-                                int column_length) {
-    TsRecord* record = new TsRecord(timestamp, table_name, column_length);
-    return record;
-}
-
-Tablet* create_tablet(const char* table_name, int max_capacity) {
-    Tablet* tablet = new Tablet();
-    tablet->table_name = strdup(table_name);
-    tablet->max_capacity = max_capacity;
-    tablet->times = (timestamp*)malloc(max_capacity * sizeof(int64_t));
-    return tablet;
-}
-
-int get_size_from_schema_info(SchemaInfo schema_info) {
-    if (schema_info & TS_TYPE_BOOLEAN) {
-        return sizeof(bool);
-    } else if (schema_info & TS_TYPE_DOUBLE) {
-        return sizeof(double);
-    } else if (schema_info & TS_TYPE_FLOAT) {
-        return sizeof(float);
-    } else if (schema_info & TS_TYPE_INT32) {
-        return sizeof(int32_t);
-    } else if (schema_info & TS_TYPE_INT64) {
-        return sizeof(int64_t);
-    } else if (schema_info & TS_TYPE_TEXT) {
-        return sizeof(char*);
-    }
-    return 0;
-}
-
-Tablet* add_column_to_tablet(Tablet* tablet, char* column_name,
-                             SchemaInfo column_def) {
-    tablet->column_num++;
-    tablet->column_schema = (ColumnSchema**)realloc(
-        tablet->column_schema, tablet->column_num * sizeof(ColumnSchema*));
-    tablet->bitmap =
-        (bool**)realloc(tablet->bitmap, tablet->column_num * sizeof(bool*));
-    tablet->bitmap[tablet->column_num - 1] =
-        (bool*)malloc(tablet->max_capacity * sizeof(bool));
-    std::memset(tablet->bitmap[tablet->column_num - 1], 0,
-                tablet->max_capacity * sizeof(bool));
-    ColumnSchema* schema = new ColumnSchema();
-    schema->name = column_name;
-    schema->column_def = column_def;
-    tablet->column_schema[tablet->column_num - 1] = schema;
-    tablet->value =
-        (void**)realloc(tablet->value, tablet->column_num * sizeof(void*));
-    tablet->value[tablet->column_num - 1] =
-        (void*)malloc(tablet->max_capacity * sizeof(int64_t));
-    return tablet;
-}
-
-Tablet* add_data_to_tablet_i64(Tablet* tablet, int line_id, int64_t timestamp,
-                               const char* column_name, int64_t value) {
-    int column_id = -1;
-    INSERT_DATA_TABLET_STEP;
-    memcpy((int64_t*)tablet->value[column_id] + line_id, &value,
-           sizeof(int64_t));
-    tablet->bitmap[column_id][line_id] = true;
-    line_id > tablet->cur_num ? tablet->cur_num = line_id : 0;
-    return tablet;
-}
-
-Tablet* add_data_to_tablet_i32(Tablet* tablet, int line_id, int64_t timestamp,
-                               const char* column_name, int32_t value) {
-    int column_id = -1;
-    INSERT_DATA_TABLET_STEP;
-    memcpy((int32_t*)tablet->value[column_id] + line_id, &value,
-           sizeof(int32_t));
-    tablet->bitmap[column_id][line_id] = true;
-    line_id > tablet->cur_num ? tablet->cur_num = line_id : 0;
-    return tablet;
-}
-
-Tablet* add_data_to_tablet_float(Tablet* tablet, int line_id, int64_t 
timestamp,
-                                 const char* column_name, float value) {
-    int column_id = -1;
-    INSERT_DATA_TABLET_STEP;
-    memcpy((float*)tablet->value[column_id] + line_id, &value, sizeof(float));
-    tablet->bitmap[column_id][line_id] = true;
-    line_id > tablet->cur_num ? tablet->cur_num = line_id : 0;
-    return tablet;
-}
-
-Tablet* add_data_to_tablet_double(Tablet* tablet, int line_id,
-                                  int64_t timestamp, const char* column_name,
-                                  double value) {
-    int column_id = -1;
-    INSERT_DATA_TABLET_STEP;
-    memcpy((double*)tablet->value[column_id] + line_id, &value, 
sizeof(double));
-    tablet->bitmap[column_id][line_id] = true;
-    line_id > tablet->cur_num ? tablet->cur_num = line_id : 0;
-    return tablet;
-}
-
-Tablet* add_data_to_tablet_bool(Tablet* tablet, int line_id, int64_t timestamp,
-                                const char* column_name, bool value) {
-    int column_id = -1;
-    INSERT_DATA_TABLET_STEP;
-    memcpy((bool*)tablet->value[column_id] + line_id, &value, sizeof(bool));
-    tablet->bitmap[column_id][line_id] = true;
-    line_id > tablet->cur_num ? tablet->cur_num = line_id : 0;
-    return tablet;
-}
-
-Tablet* add_data_to_tablet_char(Tablet* tablet, int line_id, int64_t timestamp,
-                                const char* column_name, char* value) {
-    int column_id = -1;
-    INSERT_DATA_TABLET_STEP;
-    memcpy((char*)tablet->value[column_id] + line_id, &value, sizeof(char*));
-    tablet->bitmap[column_id][line_id] = true;
-    line_id > tablet->cur_num ? tablet->cur_num = line_id : 0;
-    return tablet;
-}
-
-// Tablet* add_null_to_tablet(Tablet* tablet, int line_id, int64_t timestamp,
-// const char* column_num) {
-//     int column_id = -1;
-//     for (int i = 0; i < tablet->column_num; i++) {
-//         if (strcmp(tablet->column_schema[i]->name, column_num) == 0) {
-//             column_id = i;
-//             break;
-//         }
-//     }
-//     if (column_id == -1) {
-//         return tablet;
-//     }
-
-//     if (tablet->cur_num + 1 > tablet->max_capacity) {
-//         return tablet;
-//     }
-//     tablet->times[line_id] = timestamp;
-//     memcpy((int64_t*)tablet->value[column_id] + line_id, 0, 
sizeof(int64_t));
-//     line_id > tablet->cur_num ? tablet->cur_num = line_id : 0;
-//     return tablet;
-// }
-
-ErrorCode destory_tablet(Tablet* tablet) {
-    free(tablet->table_name);
-    tablet->table_name = nullptr;
-    free(tablet->times);
-    tablet->times = nullptr;
-    for (int i = 0; i < tablet->column_num; i++) {
-        free(tablet->column_schema[i]);
-        free(tablet->value[i]);
-        free(tablet->bitmap[i]);
-    }
-    free(tablet->bitmap);
-    free(tablet->column_schema);
-    free(tablet->value);
-    delete tablet;
-    return E_OK;
-}
-
-ErrorCode insert_data_into_tsfile_row_int32(TsFileRowData data, char* 
columname,
-                                            int32_t value) {
-    TsRecord* record = (TsRecord*)data;
-    INSERT_DATA_INTO_RECORD(record, columname, value);
-}
-
-ErrorCode insert_data_into_tsfile_row_boolean(TsFileRowData data,
-                                              char* columname, bool value) {
-    TsRecord* record = (TsRecord*)data;
-    INSERT_DATA_INTO_RECORD(record, columname, value);
-}
-
-ErrorCode insert_data_into_tsfile_row_int64(TsFileRowData data, char* 
columname,
-                                            int64_t value) {
-    TsRecord* record = (TsRecord*)data;
-    INSERT_DATA_INTO_RECORD(record, columname, value);
-}
-
-ErrorCode insert_data_into_tsfile_row_float(TsFileRowData data, char* 
columname,
-                                            float value) {
-    TsRecord* record = (TsRecord*)data;
-    INSERT_DATA_INTO_RECORD(record, columname, value);
-}
-
-ErrorCode insert_data_into_tsfile_row_double(TsFileRowData data,
-                                             char* columname, double value) {
-    TsRecord* record = (TsRecord*)data;
-    INSERT_DATA_INTO_RECORD(record, columname, value);
-}
-
-ErrorCode tsfile_write_row_data(CTsFileWriter writer, TsFileRowData data) {
-    TsFileWriter* w = (TsFileWriter*)writer;
-    TsRecord* record = (TsRecord*)data;
-    int ret = w->write_record(*record);
-    if (ret == E_OK) {
-        delete record;
-    }
-    return ret;
-}
-
-ErrorCode destory_tsfile_row(TsFileRowData data) {
-    TsRecord* record = (TsRecord*)data;
-    if (record != nullptr) {
-        delete record;
-        record = nullptr;
-    }
-    return E_OK;
-}
-
-ErrorCode tsfile_flush_data(CTsFileWriter writer) {
-    TsFileWriter* w = (TsFileWriter*)writer;
-    int ret = w->flush();
-    return ret;
-}
-
-Expression create_column_filter(const char* column_name, OperatorType oper,
-                                int32_t int32_value) {
-    Expression exp;
-    CONSTRUCT_EXP_INTERNAL(exp, column_name);
-    exp.const_condition.value_condition = int32_value;
-    exp.const_condition.type = TS_TYPE_INT32;
-    return exp;
-}
-
-Expression create_column_filter(const char* column_name, OperatorType oper,
-                                int64_t int64_value) {
-    Expression exp;
-    CONSTRUCT_EXP_INTERNAL(exp, column_name);
-    exp.const_condition.value_condition = int64_value;
-    exp.const_condition.type = TS_TYPE_INT64;
-    return exp;
-}
-Expression create_column_filter(const char* column_name, OperatorType oper,
-                                bool bool_value) {
-    Expression exp;
-    CONSTRUCT_EXP_INTERNAL(exp, column_name);
-    exp.const_condition.value_condition = bool_value ? 1 : 0;
-    exp.const_condition.type = TS_TYPE_BOOLEAN;
-    return exp;
-}
-Expression create_column_filter(const char* column_name, OperatorType oper,
-                                float float_value) {
-    Expression exp;
-    CONSTRUCT_EXP_INTERNAL(exp, column_name);
-    memcpy(&exp.const_condition.value_condition, &float_value, sizeof(float));
-    exp.const_condition.type = TS_TYPE_FLOAT;
-    return exp;
-}
-Expression create_column_filter(const char* column_name, OperatorType oper,
-                                double double_value) {
-    Expression exp;
-    CONSTRUCT_EXP_INTERNAL(exp, column_name);
-    exp.const_condition.value_condition = double_value;
-    exp.const_condition.type = TS_TYPE_DOUBLE;
-    return exp;
-}
-Expression create_column_filter(const char* column_name, OperatorType oper,
-                                const char* char_value) {
-    Expression exp;
-    CONSTRUCT_EXP_INTERNAL(exp, column_name);
-    exp.const_condition.value_condition = 
reinterpret_cast<int64_t>(char_value);
-    exp.const_condition.type = TS_TYPE_TEXT;
-    return exp;
-}
-
-TimeFilterExpression* create_andquery_timefilter() {
-    storage::Expression* exp = new storage::Expression(storage::AND_EXPR);
-    return (TimeFilterExpression*)exp;
-}
-
-TimeFilterExpression* create_time_filter(const char* table_name,
-                                         const char* column_name,
-                                         OperatorType oper, int64_t timestamp) 
{
-    std::string table_name_str(table_name);
-    std::string column_name_str(column_name);
-    storage::Path path(table_name_str, column_name_str);
-    storage::Filter* filter;
-    switch (oper) {
-        case GT:
-            filter = storage::TimeFilter::gt(timestamp);
-            break;
-        case LT:
-            filter = storage::TimeFilter::lt(timestamp);
-            break;
-        case EQ:
-            filter = storage::TimeFilter::eq(timestamp);
-            break;
-        case NOTEQ:
-            filter = storage::TimeFilter::not_eqt(timestamp);
-            break;
-        case GE:
-            filter = storage::TimeFilter::gt_eq(timestamp);
-            break;
-        case LE:
-            filter = storage::TimeFilter::lt_eq(timestamp);
-            break;
-        default:
-            filter = nullptr;
-            break;
-    }
-    storage::Expression* exp =
-        new storage::Expression(storage::SERIES_EXPR, path, filter);
-    return (TimeFilterExpression*)exp;
-}
-
-TimeFilterExpression* add_time_filter_to_and_query(
-    TimeFilterExpression* exp_and, TimeFilterExpression* exp) {
-    storage::Expression* and_exp = (storage::Expression*)exp_and;
-    storage::Expression* time_exp = (storage::Expression*)exp;
-    if (and_exp->left_ == nullptr) {
-        and_exp->left_ = time_exp;
-    } else if (and_exp->right_ == nullptr) {
-        and_exp->right_ = time_exp;
-    } else {
-        storage::Expression* new_exp =
-            new storage::Expression(storage::AND_EXPR);
-        new_exp->left_ = and_exp->right_;
-        and_exp->right_ = new_exp;
-        add_time_filter_to_and_query((TimeFilterExpression*)new_exp, exp);
-    }
-    return exp_and;
-}
-
-void destory_time_filter_query(TimeFilterExpression* expression) {
-    if (expression == nullptr) {
-        return;
-    }
-
-    destory_time_filter_query(
-        (TimeFilterExpression*)((storage::Expression*)expression)->left_);
-    destory_time_filter_query(
-        (TimeFilterExpression*)((storage::Expression*)expression)->right_);
-    storage::Expression* exp = (storage::Expression*)expression;
-    if (exp->type_ == storage::ExpressionType::SERIES_EXPR) {
-        delete exp->filter_;
-    } else {
-        delete exp;
-    }
-}
-
-Expression create_global_time_expression(OperatorType oper, int64_t timestamp) 
{
-    Expression exp;
-    exp.operatype = oper;
-    exp.expression_type = GLOBALTIME;
-    exp.const_condition.value_condition = timestamp;
-    exp.const_condition.type = TS_TYPE_INT64;
-    return exp;
-}
-
-Expression* and_filter_to_and_query(Expression* exp_and, Expression* exp) {
-    if (exp_and->children_length >= MAX_COLUMN_FILTER_NUM - 1) {
-        return nullptr;
-    }
-    exp_and->children[exp_and->children_length++] = exp;
-    return exp_and;
-}
-
-QueryDataRet ts_reader_query(CTsFileReader reader, const char* table_name,
-                             const char** columns_name, int column_num,
-                             TimeFilterExpression* expression) {
-    TsFileReader* r = (TsFileReader*)reader;
-    std::string table_name_str(table_name);
-    std::vector<storage::Path> selected_paths;
-    for (int i = 0; i < column_num; i++) {
-        std::string column_name(columns_name[i]);
-        selected_paths.push_back(storage::Path(table_name_str, column_name));
-    }
-
-    storage::ResultSet* qds = nullptr;
-    storage::QueryExpression* query_expression =
-        storage::QueryExpression::create(selected_paths,
-                                         (storage::Expression*)expression);
-    r->query(query_expression, qds);
-    QueryDataRet ret = (QueryDataRet)malloc(sizeof(struct query_data_ret));
-    ret->data = qds;
-    ret->column_names = (char**)malloc(column_num * sizeof(char*));
-    ret->column_num = column_num;
-    for (int i = 0; i < column_num; i++) {
-        ret->column_names[i] = strdup(columns_name[i]);
-    }
-    return ret;
-}
-
-QueryDataRet ts_reader_begin_end(CTsFileReader reader, const char* table_name,
-                                 char** columns_name, int column_num,
-                                 timestamp begin, timestamp end) {
-    TsFileReader* r = (TsFileReader*)reader;
-    std::string table_name_str(table_name);
-    std::vector<storage::Path> selected_paths;
-    for (int i = 0; i < column_num; i++) {
-        std::string column_name(columns_name[i]);
-        selected_paths.push_back(storage::Path(table_name_str, column_name));
-    }
-
-    storage::ResultSet* qds = nullptr;
-    storage::Filter* filter_low = nullptr;
-    storage::Filter* filter_high = nullptr;
-    storage::Expression* exp = nullptr;
-    storage::Filter* and_filter = nullptr;
-    if (begin != -1) {
-        filter_low = storage::TimeFilter::gt_eq(begin);
-    }
-    if (end != -1) {
-        filter_high = storage::TimeFilter::lt_eq(end);
-    }
-    if (filter_low != nullptr && filter_high != nullptr) {
-        and_filter = new storage::AndFilter(filter_low, filter_high);
-        exp = new storage::Expression(storage::GLOBALTIME_EXPR,
-                                      and_filter);  // exp never be deleted
-    } else if (filter_low != nullptr && filter_high == nullptr) {
-        exp = new storage::Expression(storage::GLOBALTIME_EXPR, filter_low);
-    } else if (filter_high != nullptr && filter_low == nullptr) {
-        exp = new storage::Expression(storage::GLOBALTIME_EXPR, filter_high);
-    }
-    storage::QueryExpression* query_expr =
-        storage::QueryExpression::create(selected_paths, exp);
-    r->query(query_expr, qds);
-    QueryDataRet ret = (QueryDataRet)malloc(sizeof(struct query_data_ret));
-    ret->data = qds;
-    ret->column_num = column_num;
-    ret->column_names = (char**)malloc(column_num * sizeof(char*));
-    for (int i = 0; i < column_num; i++) {
-        ret->column_names[i] = strdup(columns_name[i]);
-    }
-    return ret;
-}
-
-QueryDataRet ts_reader_read(CTsFileReader reader, const char* table_name,
-                            char** columns_name, int column_num) {
-    TsFileReader* r = (TsFileReader*)reader;
-    std::string table_name_str(table_name);
-    std::vector<storage::Path> selected_paths;
-    for (int i = 0; i < column_num; i++) {
-        std::string column_name(columns_name[i]);
-        selected_paths.push_back(storage::Path(table_name_str, column_name));
-    }
-    storage::ResultSet* qds = nullptr;
-    storage::QueryExpression* query_expr =
-        storage::QueryExpression::create(selected_paths, nullptr);
-    r->query(query_expr, qds);
-    QueryDataRet ret = (QueryDataRet)malloc(sizeof(struct query_data_ret));
-    ret->data = qds;
-    ret->column_names = (char**)malloc(column_num * sizeof(char*));
-    ret->column_num = column_num;
-    for (int i = 0; i < column_num; i++) {
-        ret->column_names[i] = strdup(columns_name[i]);
-    }
-    return ret;
-}
-
-ErrorCode destory_query_dataret(QueryDataRet data) {
-    storage::ResultSet* qds = (storage::ResultSet*)data->data;
-    delete qds;
-    for (int i = 0; i < data->column_num; i++) {
-        free(data->column_names[i]);
-    }
-    free(data->column_names);
-    free(data);
-    return E_OK;
-}
-
-DataResult* ts_next(QueryDataRet data, int expect_line_count) {
-    storage::ResultSet* qds = (storage::ResultSet*)data->data;
-    DataResult* result = create_tablet("result", expect_line_count);
-    storage::RowRecord* record;
-    bool init_tablet = false;
-    for (int i = 0; i < expect_line_count; i++) {
-        if (!qds->next()) {
-            break;
-        }
-        record = qds->get_row_record();
-        int column_num = record->get_fields()->size();
-        if (!init_tablet) {
-            for (int col = 0; col < column_num; col++) {
-                storage::Field* field = record->get_field(col);
-                result = add_column_to_tablet(result, data->column_names[col],
-                                              get_schema_info(field->type_));
-            }
-            init_tablet = true;
-        }
-        for (int col = 0; col < column_num; col++) {
-            storage::Field* field = record->get_field(col);
-            switch (field->type_) {
-                // all data will stored as 8 bytes
-                case TSDataType::BOOLEAN:
-                    result = add_data_to_tablet_bool(
-                        result, i, record->get_timestamp(),
-                        data->column_names[col], field->value_.bval_);
-                    break;
-                case TSDataType::INT32:
-                    result = add_data_to_tablet_i32(
-                        result, i, record->get_timestamp(),
-                        data->column_names[col], field->value_.ival_);
-                    break;
-                case TSDataType::INT64:
-                    result = add_data_to_tablet_i64(
-                        result, i, record->get_timestamp(),
-                        data->column_names[col], field->value_.lval_);
-                    break;
-                case TSDataType::FLOAT:
-                    result = add_data_to_tablet_float(
-                        result, i, record->get_timestamp(),
-                        data->column_names[col], field->value_.fval_);
-                    break;
-                case TSDataType::DOUBLE:
-                    result = add_data_to_tablet_double(
-                        result, i, record->get_timestamp(),
-                        data->column_names[col], field->value_.dval_);
-                    break;
-                case TSDataType::TEXT:
-                    result = add_data_to_tablet_char(
-                        result, i, record->get_timestamp(),
-                        data->column_names[col], field->value_.sval_);
-                    break;
-                case TSDataType::NULL_TYPE:
-                    // result = add_data_to_tablet(result, i ,
-                    // record->get_timestamp(),
-                    //                             data->column_names[col], 0);
-                    // skip null data
-                    break;
-                default:
-                    std::cout << field->type_ << std::endl;
-                    std::cout << "error here" << std::endl;
-                    return nullptr;
-            }
-        }
-    }
-    return result;
-}
-
-void print_data_result(DataResult* result) {
-    std::cout << std::left << std::setw(15) << "timestamp";
-    for (int i = 0; i < result->column_num; i++) {
-        std::cout << std::left << std::setw(15)
-                  << result->column_schema[i]->name;
-    }
-    std::cout << std::endl;
-    for (int i = 0; i < result->cur_num; i++) {
-        std::cout << std::left << std::setw(15);
-        std::cout << result->times[i];
-        for (int j = 0; j < result->column_num; j++) {
-            ColumnSchema* schema = result->column_schema[j];
-            double dval;
-            float fval;
-            std::cout << std::left << std::setw(15);
-            switch (get_datatype(schema->column_def)) {
-                case TSDataType::BOOLEAN:
-                    std::cout
-                        << ((*((int64_t*)result->value[j] + i)) > 0 ? "true"
-                                                                    : "false");
-                    break;
-                case TSDataType::INT32:
-                    std::cout << *((int64_t*)result->value[j] + i);
-                    break;
-                case TSDataType::INT64:
-                    std::cout << *((int64_t*)result->value[j] + i);
-                    break;
-                case TSDataType::FLOAT:
-                    memcpy(&fval, (int64_t*)result->value[j] + i,
-                           sizeof(float));
-                    std::cout << fval;
-                    break;
-                case TSDataType::DOUBLE:
-                    memcpy(&dval, (int64_t*)result->value[j] + i,
-                           sizeof(double));
-                    std::cout << dval;
-                    break;
-                default:
-                    std::cout << "";
-            }
-        }
-        std::cout << std::endl;
-    }
-}
-
-// }
-
-// storage::Expression construct_query(Expression* exp) {
-//   int column_num = exp->children_length;
-//   std::vector<storage::Path> paths;
-//   for (int i = 0; i < column_num; i++) {
-//     Expression* exp = exp->children[i];
-//     if (exp->expression_type != )
-//     if (exp->column_name != nullptr ) {
-//       std::string column_name = exp->column_name;
-
-//     } else if (column->expression_type == AND) {
-//       storage::Expression and_exp = construct_query(table_name,
-//       column);
-//       // add and_exp to the query
-//     }
-//     column++;
-//   }
-//   // construct the query using paths and other information
-//   // return the constructed query
-// }
-
-// storage::Filter get_filter(int operate_type, Constant condition) {
-//   switch(operate_type) {
-//     case GT:
-//       return storage::TimeFilter::gt();
-
-//   }
-
-// }
-
-// storage::Expression construct_query(const char* table_name,
-// Expression exp) {
-//   std::string table = table_name;
-//   int column_num = exp.children_length;
-//   std::vector<storage::Path> paths;
-//   paths.reserve(column_num);
-//   Expression* column = exp.children;
-//   for (int i = 0; i < column_num;i++) {
-//     if (column_num == 1) {
-//       std::string column_name = column->column_name;
-//       // select_list
-//       paths.push_back(storage::Path(table, column_name));
-//       int operate = column->operatype;
-//       Filter filter = get_filter(operate, column->const_condition);
-//     }
-//   }
-// }
diff --git a/cpp/src/cwrapper/TsFile-cwrapper.h 
b/cpp/src/cwrapper/TsFile-cwrapper.h
deleted file mode 100644
index 97ffedd0d..000000000
--- a/cpp/src/cwrapper/TsFile-cwrapper.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef CWRAPPER_TSFILE_CWRAPPER_H
-#define CWRAPPER_TSFILE_CWRAPPER_H
-
-#include <fcntl.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#ifdef _WIN32
-#include <sys/stat.h>
-#endif
-
-typedef long long SchemaInfo;
-typedef long long timestamp;
-typedef void* CTsFileReader;
-typedef void* CTsFileWriter;
-typedef void* TsFileRowData;
-typedef int ErrorCode;
-typedef void* TimeFilterExpression;
-
-// DATA TYPE
-#define TS_TYPE_INT32 1 << 8
-#define TS_TYPE_BOOLEAN 1 << 9
-#define TS_TYPE_FLOAT 1 << 10
-#define TS_TYPE_DOUBLE 1 << 11
-#define TS_TYPE_INT64 1 << 12
-#define TS_TYPE_TEXT 1 << 13
-
-// ENCODING TYPE
-#define TS_ENCODING_PLAIN 1 << 16
-#define TS_ENCODING_TS_DIFF 1 << 17
-#define TS_ENCODING_DICTIONARY 1 << 18
-#define TS_ENCODING_RLE 1 << 19
-#define TS_ENCODING_BITMAP 1 << 20
-#define TS_ENCODING_GORILLA_V1 1 << 21
-#define TS_ENCODING_REGULAR 1 << 22
-#define TS_ENCODING_GORILLA 1 << 23
-#define TS_ENCODING_ZIGZAG 1 << 24
-#define TS_ENCODING_FREQ 1 << 25
-
-// COMPRESS TYPE
-#define TS_COMPRESS_UNCOMPRESS 1LL << 32
-#define TS_COMPRESS_SNAPPY 1LL << 33
-#define TS_COMPRESS_GZIP 1LL << 34
-#define TS_COMPRESS_LZO 1LL << 35
-#define TS_COMPRESS_SDT 1LL << 36
-#define TS_COMPRESS_PAA 1LL << 37
-#define TS_COMPRESS_PLA 1LL << 38
-#define TS_COMPRESS_LZ4 1LL << 39
-
-#define MAX_COLUMN_FILTER_NUM 10
-
-typedef struct column_schema {
-    char* name;
-    SchemaInfo column_def;
-} ColumnSchema;
-
-typedef struct table_shcema {
-    char* table_name;
-    ColumnSchema** column_schema;
-    int column_num;
-} TableSchema;
-
-typedef enum operator_type {
-    LT,
-    LE,
-    EQ,
-    GT,
-    GE,
-    NOTEQ,
-} OperatorType;
-
-typedef enum expression_type {
-    OR,
-    AND,
-    GLOBALTIME,
-} ExpressionType;
-
-typedef struct constant {
-    int64_t value_condition;
-    int type;
-} Constant;
-
-typedef struct expression {
-    const char* column_name;
-    Constant const_condition;
-    ExpressionType expression_type;
-    OperatorType operatype;
-    struct expression* children[MAX_COLUMN_FILTER_NUM];
-    int children_length;
-} Expression;
-
-typedef struct tablet {
-    char* table_name;
-    ColumnSchema** column_schema;
-    int column_num;
-    timestamp* times;
-    bool** bitmap;
-    void** value;
-    int cur_num;
-    int max_capacity;
-} Tablet;
-
-typedef struct tsfile_conf {
-    int mem_threshold_kb;
-} TsFileConf;
-
-typedef Tablet DataResult;
-
-typedef void* QueryDataRetINTERNAL;
-typedef struct query_data_ret {
-    char** column_names;
-    int column_num;
-    QueryDataRetINTERNAL data;
-} * QueryDataRet;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-CTsFileReader ts_reader_open(const char* pathname, ErrorCode* err_code);
-CTsFileWriter ts_writer_open(const char* pathname, ErrorCode* err_code);
-CTsFileWriter ts_writer_open_flag(const char* pathname, mode_t flag,
-                                  ErrorCode* err_code);
-CTsFileWriter ts_writer_open_conf(const char* pathname, mode_t flag,
-                                  ErrorCode* err_code, TsFileConf* conf);
-
-ErrorCode ts_writer_close(CTsFileWriter writer);
-ErrorCode ts_reader_close(CTsFileReader reader);
-
-ErrorCode tsfile_register_table_column(CTsFileWriter writer,
-                                       const char* table_name,
-                                       ColumnSchema* schema);
-ErrorCode tsfile_register_table(CTsFileWriter writer,
-                                TableSchema* table_shcema);
-
-TsFileRowData create_tsfile_row(const char* tablename, int64_t timestamp,
-                                int column_length);
-
-ErrorCode insert_data_into_tsfile_row_int32(TsFileRowData data, char* 
columname,
-                                            int32_t value);
-ErrorCode insert_data_into_tsfile_row_boolean(TsFileRowData data,
-                                              char* columname, bool value);
-ErrorCode insert_data_into_tsfile_row_int64(TsFileRowData data, char* 
columname,
-                                            int64_t value);
-ErrorCode insert_data_into_tsfile_row_float(TsFileRowData data, char* 
columname,
-                                            float value);
-ErrorCode insert_data_into_tsfile_row_double(TsFileRowData data,
-                                             char* columname, double value);
-
-ErrorCode tsfile_write_row_data(CTsFileWriter writer, TsFileRowData data);
-ErrorCode destory_tsfile_row(TsFileRowData data);
-
-Tablet* create_tablet(const char* table_name, int max_capacity);
-Tablet* add_column_to_tablet(Tablet* tablet, char* column_name,
-                             SchemaInfo column_def);
-Tablet add_data_to_tablet(Tablet tablet, int line_id, int64_t timestamp,
-                          const char* column_name, int64_t value);
-
-ErrorCode destory_tablet(Tablet* tablet);
-
-ErrorCode tsfile_flush_data(CTsFileWriter writer);
-
-Expression create_column_filter_I32(const char* column_name, OperatorType oper,
-                                    int32_t int32_value);
-Expression create_column_filter_I64(const char* column_name, OperatorType oper,
-                                    int64_t int64_value);
-Expression create_column_filter_bval(const char* column_name, OperatorType 
oper,
-                                     bool bool_value);
-Expression create_column_filter_fval(const char* column_name, OperatorType 
oper,
-                                     float float_value);
-Expression create_column_filter_dval(const char* column_name, OperatorType 
oper,
-                                     double double_value);
-Expression create_column_filter_cval(const char* column_name, OperatorType 
oper,
-                                     const char* char_value);
-
-TimeFilterExpression* create_andquery_timefilter();
-
-TimeFilterExpression* create_time_filter(const char* table_name,
-                                         const char* column_name,
-                                         OperatorType oper, int64_t timestamp);
-
-TimeFilterExpression* add_time_filter_to_and_query(
-    TimeFilterExpression* exp_and, TimeFilterExpression* exp);
-
-void destory_time_filter_query(TimeFilterExpression* expression);
-
-Expression* create_time_expression(const char* column_name, OperatorType oper,
-                                   int64_t timestamp);
-
-Expression* add_and_filter_to_and_query(Expression* exp_and, Expression* exp);
-
-QueryDataRet ts_reader_query(CTsFileReader reader, const char* table_name,
-                             const char** columns, int colum_num,
-                             TimeFilterExpression* expression);
-
-QueryDataRet ts_reader_begin_end(CTsFileReader reader, const char* table_name,
-                                 char** columns, int colum_num, timestamp 
begin,
-                                 timestamp end);
-
-QueryDataRet ts_reader_read(CTsFileReader reader, const char* table_name,
-                            char** columns, int colum_num);
-
-ErrorCode destory_query_dataret(QueryDataRet query_data_set);
-
-DataResult* ts_next(QueryDataRet data, int expect_line_count);
-
-void print_data_result(DataResult* result);
-
-void clean_data_record(DataResult data_result);
-void clean_query_ret(QueryDataRet query_data_set);
-void clean_query_tree(Expression* expression);
-
-#ifdef __cplusplus
-}
-#endif
-#endif  // CWRAPPER_TSFILE_CWRAPPER_H
diff --git a/cpp/src/cwrapper/tsfile_cwrapper.cc 
b/cpp/src/cwrapper/tsfile_cwrapper.cc
new file mode 100644
index 000000000..9093378f6
--- /dev/null
+++ b/cpp/src/cwrapper/tsfile_cwrapper.cc
@@ -0,0 +1,444 @@
+/*
+ * 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.
+ */
+
+#include "cwrapper/tsfile_cwrapper.h"
+
+#include <reader/qds_without_timegenerator.h>
+
+#include "common/tablet.h"
+#include "reader/result_set.h"
+#include "reader/tsfile_reader.h"
+#include "writer/tsfile_writer.h"
+
+static bool is_init = false;
+
+Tablet tablet_new_with_device(const char *device_id, char **column_name_list,
+                              TSDataType *data_types, int column_num,
+                              int max_rows) {
+    std::vector<std::string> measurement_list;
+    std::vector<common::TSDataType> data_type_list;
+    for (int i = 0; i < column_num; i++) {
+        measurement_list.emplace_back(column_name_list[i]);
+        data_type_list.push_back(
+            static_cast<common::TSDataType>(*(data_types + i)));
+    }
+    auto *tablet = new storage::Tablet(device_id, &measurement_list,
+                                       &data_type_list, max_rows);
+    tablet->init();
+    return tablet;
+}
+
+Tablet tablet_new(const char **column_name_list, TSDataType *data_types,
+                  uint32_t column_num) {
+    std::vector<std::string> measurement_list;
+    std::vector<common::TSDataType> data_type_list;
+    for (int i = 0; i < column_num; i++) {
+        measurement_list.emplace_back(column_name_list[i]);
+        data_type_list.push_back(
+            static_cast<common::TSDataType>(*(data_types + i)));
+    }
+    auto *tablet = new storage::Tablet("", &measurement_list, &data_type_list);
+    return tablet;
+}
+
+uint32_t tablet_get_cur_row_size(Tablet tablet) {
+    return static_cast<storage::Tablet *>(tablet)->get_cur_row_size();
+}
+
+ERRNO tablet_add_timestamp(Tablet tablet, uint32_t row_index,
+                           timestamp timestamp) {
+    return static_cast<storage::Tablet *>(tablet)->add_timestamp(row_index,
+                                                                 timestamp);
+}
+
+#define TABLET_ADD_VALUE_BY_NAME_DEF(type)                                   \
+    ERRNO tablet_add_value_by_name_##type(Tablet tablet, uint32_t row_index, \
+                                          const char *column_name,           \
+                                          type value) {                      \
+        return static_cast<storage::Tablet *>(tablet)->add_value(            \
+            row_index, column_name, value);                                  \
+    }
+
+TABLET_ADD_VALUE_BY_NAME_DEF(int32_t);
+TABLET_ADD_VALUE_BY_NAME_DEF(int64_t);
+TABLET_ADD_VALUE_BY_NAME_DEF(float);
+TABLET_ADD_VALUE_BY_NAME_DEF(double);
+TABLET_ADD_VALUE_BY_NAME_DEF(bool);
+
+#define TABLE_ADD_VALUE_BY_INDEX_DEF(type)                                    \
+    ERRNO tablet_add_value_by_index_##type(Tablet tablet, uint32_t row_index, \
+                                           uint32_t column_index,             \
+                                           type value) {                      \
+        return static_cast<storage::Tablet *>(tablet)->add_value(             \
+            row_index, column_index, value);                                  \
+    }
+
+TABLE_ADD_VALUE_BY_INDEX_DEF(int32_t);
+TABLE_ADD_VALUE_BY_INDEX_DEF(int64_t);
+TABLE_ADD_VALUE_BY_INDEX_DEF(float);
+TABLE_ADD_VALUE_BY_INDEX_DEF(double);
+TABLE_ADD_VALUE_BY_INDEX_DEF(bool);
+
+void *tablet_get_value(Tablet tablet, uint32_t row_index, uint32_t 
schema_index,
+                       TSDataType *type) {
+    common::TSDataType data_type;
+    void *result = static_cast<storage::Tablet *>(tablet)->get_value(
+        row_index, schema_index, data_type);
+    *type = static_cast<TSDataType>(data_type);
+    return result;
+}
+
+// TsRecord API
+TsRecord ts_record_new(const char *device_id, timestamp timestamp,
+                       int timeseries_num) {
+    auto *record = new storage::TsRecord(timestamp, device_id, timeseries_num);
+    return record;
+}
+
+#define INSERT_DATA_INTO_TS_RECORD_BY_NAME_DEF(type)                 \
+    ERRNO insert_data_into_ts_record_by_name_##type(                  \
+        TsRecord data, const char *measurement_name, type value) {   \
+        auto *record = (storage::TsRecord *)data;                    \
+        storage::DataPoint point(measurement_name, value);           \
+        if (record->points_.size() + 1 > record->points_.capacity()) \
+            return common::E_BUF_NOT_ENOUGH;                         \
+        record->points_.push_back(point);                            \
+        return common::E_OK;                                         \
+    }
+
+INSERT_DATA_INTO_TS_RECORD_BY_NAME_DEF(int32_t);
+INSERT_DATA_INTO_TS_RECORD_BY_NAME_DEF(int64_t);
+INSERT_DATA_INTO_TS_RECORD_BY_NAME_DEF(bool);
+INSERT_DATA_INTO_TS_RECORD_BY_NAME_DEF(float);
+INSERT_DATA_INTO_TS_RECORD_BY_NAME_DEF(double);
+
+void init_tsfile_config() {
+    if (!is_init) {
+        common::init_config_value();
+        is_init = true;
+    }
+}
+
+TsFileReader tsfile_reader_new(const char *pathname, ERRNO *err_code) {
+    init_tsfile_config();
+    auto reader = new storage::TsFileReader();
+    int ret = reader->open(pathname);
+    if (ret != common::E_OK) {
+        *err_code = ret;
+        delete reader;
+        return nullptr;
+    }
+    return reader;
+}
+
+TsFileWriter tsfile_writer_new(const char *pathname, ERRNO *err_code) {
+    init_tsfile_config();
+    auto writer = new storage::TsFileWriter();
+    int flags = O_WRONLY | O_CREAT | O_TRUNC;
+#ifdef _WIN32
+    flags |= O_BINARY;
+#endif
+    int ret = writer->open(pathname, flags, 0644);
+    if (ret != common::E_OK) {
+        delete writer;
+        *err_code = ret;
+        return nullptr;
+    }
+    return writer;
+}
+
+TsFileWriter tsfile_writer_new_with_conf(const char *pathname,
+                                         const mode_t flag, ERRNO *err_code,
+                                         TsFileConf *conf) {
+    init_tsfile_config();
+    auto *writer = new storage::TsFileWriter();
+    const int ret = writer->open(pathname, O_CREAT | O_RDWR, flag);
+    if (ret != common::E_OK) {
+        delete writer;
+        *err_code = ret;
+        return nullptr;
+    }
+    return writer;
+}
+
+ERRNO tsfile_writer_close(TsFileWriter writer) {
+    auto *w = static_cast<storage::TsFileWriter *>(writer);
+    int ret = w->close();
+    delete w;
+    return ret;
+}
+
+ERRNO tsfile_reader_close(TsFileReader reader) {
+    auto *ts_reader = static_cast<storage::TsFileReader *>(reader);
+    delete ts_reader;
+    return common::E_OK;
+}
+
+ERRNO tsfile_writer_register_table(TsFileWriter writer, TableSchema *schema) {
+    std::vector<storage::MeasurementSchema *> measurement_schemas;
+    std::vector<storage::ColumnCategory> column_categories;
+    measurement_schemas.resize(schema->column_num);
+    for (int i = 0; i < schema->column_num; i++) {
+        ColumnSchema *cur_schema = schema->column_schemas + i;
+        measurement_schemas[i] = new storage::MeasurementSchema(
+            cur_schema->column_name,
+            static_cast<common::TSDataType>(cur_schema->data_type));
+        column_categories.push_back(
+            static_cast<storage::ColumnCategory>(cur_schema->column_category));
+    }
+    auto tsfile_writer = static_cast<storage::TsFileWriter *>(writer);
+    return 
tsfile_writer->register_table(std::make_shared<storage::TableSchema>(
+        schema->table_name, measurement_schemas, column_categories));
+}
+
+ERRNO tsfile_writer_register_timeseries(TsFileWriter writer,
+                                        const char *device_id,
+                                        const TimeseriesSchema *schema) {
+    auto *w = static_cast<storage::TsFileWriter *>(writer);
+
+    int ret = w->register_timeseries(
+        device_id,
+        storage::MeasurementSchema(
+            schema->timeseries_name,
+            static_cast<common::TSDataType>(schema->data_type),
+            static_cast<common::TSEncoding>(schema->encoding),
+            static_cast<common::CompressionType>(schema->compression)));
+    return ret;
+}
+
+ERRNO tsfile_writer_register_device(TsFileWriter writer,
+                                    const device_schema *device_schema) {
+    auto *w = static_cast<storage::TsFileWriter *>(writer);
+    for (int column_id = 0; column_id < device_schema->timeseries_num;
+         column_id++) {
+        TimeseriesSchema schema = device_schema->timeseries_schema[column_id];
+        const ERRNO ret = w->register_timeseries(
+            device_schema->device_name,
+            storage::MeasurementSchema(
+                schema.timeseries_name,
+                static_cast<common::TSDataType>(schema.data_type),
+                static_cast<common::TSEncoding>(schema.encoding),
+                static_cast<common::CompressionType>(schema.compression)));
+        if (ret != common::E_OK) {
+            return ret;
+        }
+    }
+    return common::E_OK;
+}
+
+ERRNO tsfile_writer_write_ts_record(TsFileWriter writer, TsRecord data) {
+    auto *w = static_cast<storage::TsFileWriter *>(writer);
+    const storage::TsRecord *record = static_cast<storage::TsRecord *>(data);
+    const int ret = w->write_record(*record);
+    return ret;
+}
+
+ERRNO tsfile_writer_write_tablet(TsFileWriter writer, Tablet tablet) {
+    auto *w = static_cast<storage::TsFileWriter *>(writer);
+    const auto *tbl = static_cast<storage::Tablet *>(tablet);
+    return w->write_tablet(*tbl);
+}
+
+ERRNO tsfile_writer_flush_data(TsFileWriter writer) {
+    auto *w = static_cast<storage::TsFileWriter *>(writer);
+    return w->flush();
+}
+
+// Query
+
+ResultSet tsfile_reader_query_table(TsFileReader reader, const char 
*table_name,
+char **columns, uint32_t column_num,
+                                    timestamp start_time, timestamp end_time) {
+    // TODO: Implement query table with tsfile reader.
+    return nullptr;
+}
+
+ResultSet tsfile_reader_query_device(TsFileReader reader, const char* 
device_name,
+    char** sensor_name, uint32_t sensor_num,
+                                   timestamp start_time, timestamp end_time) {
+    auto *r = static_cast<storage::TsFileReader *>(reader);
+    std::vector<std::string> selected_paths;
+    selected_paths.reserve(sensor_num);
+    for (int i = 0; i < sensor_num; i++) {
+        selected_paths.push_back(std::string(device_name) + "." + 
std::string(sensor_name[i]));
+    }
+    storage::ResultSet *qds = nullptr;
+    r->query(selected_paths, start_time, end_time, qds);
+    return qds;
+}
+
+bool tsfile_result_set_has_next(ResultSet result_set) {
+    auto *r = static_cast<storage::QDSWithoutTimeGenerator *>(result_set);
+    return r->next();
+}
+
+#define TSFILE_RESULT_SET_GET_VALUE_BY_NAME_DEF(type)                          
\
+    type tsfile_result_set_get_value_by_name_##type(ResultSet result_set,      
\
+                                                    const char *column_name) { 
\
+        auto *r = static_cast<storage::ResultSet *>(result_set);               
\
+        return r->get_value<type>(column_name);                                
\
+    }
+TSFILE_RESULT_SET_GET_VALUE_BY_NAME_DEF(bool);
+TSFILE_RESULT_SET_GET_VALUE_BY_NAME_DEF(int32_t);
+TSFILE_RESULT_SET_GET_VALUE_BY_NAME_DEF(int64_t);
+TSFILE_RESULT_SET_GET_VALUE_BY_NAME_DEF(float);
+TSFILE_RESULT_SET_GET_VALUE_BY_NAME_DEF(double);
+
+#define TSFILE_RESULT_SET_GET_VALUE_BY_INDEX_DEF(type)                        \
+    type tsfile_result_set_get_value_by_index_##type(ResultSet result_set,    \
+                                                     uint32_t column_index) { \
+        auto *r = static_cast<storage::ResultSet *>(result_set);              \
+        return r->get_value<type>(column_index);                              \
+    }
+
+TSFILE_RESULT_SET_GET_VALUE_BY_INDEX_DEF(int32_t);
+TSFILE_RESULT_SET_GET_VALUE_BY_INDEX_DEF(int64_t);
+TSFILE_RESULT_SET_GET_VALUE_BY_INDEX_DEF(float);
+TSFILE_RESULT_SET_GET_VALUE_BY_INDEX_DEF(double);
+TSFILE_RESULT_SET_GET_VALUE_BY_INDEX_DEF(bool);
+
+bool tsfile_result_set_is_null_by_name(ResultSet result_set,
+                                       const char *column_name) {
+    auto *r = static_cast<storage::ResultSet *>(result_set);
+    return r->is_null(column_name);
+}
+
+bool tsfile_result_set_is_null_by_index(const ResultSet result_set,
+                                        const uint32_t column_index) {
+    auto *r = static_cast<storage::ResultSet *>(result_set);
+    return r->is_null(column_index);
+}
+
+ResultSetMetaData tsfile_result_set_get_metadata(ResultSet result_set) {
+    auto *r = static_cast<storage::QDSWithoutTimeGenerator *>(result_set);
+    ResultSetMetaData meta_data;
+    storage::ResultSetMetadata *result_set_metadata = r->get_metadata();
+    meta_data.column_num = result_set_metadata->get_column_count();
+    meta_data.column_names =
+        static_cast<char **>(malloc(meta_data.column_num * sizeof(char *)));
+    meta_data.data_types = static_cast<TSDataType *>(
+        malloc(meta_data.column_num * sizeof(TSDataType)));
+    for (int i = 0; i < meta_data.column_num; i++) {
+        meta_data.column_names[i] =
+            strdup(result_set_metadata->get_column_name(i).c_str());
+        meta_data.data_types[i] =
+            static_cast<TSDataType>(result_set_metadata->get_column_type(i));
+    }
+    return meta_data;
+}
+
+char *tsfile_result_set_meta_get_column_name(ResultSetMetaData result_set,
+                                             uint32_t column_index) {
+    return result_set.column_names[column_index];
+}
+
+TSDataType tsfile_result_set_meta_get_data_type(ResultSetMetaData result_set,
+                                                uint32_t column_index) {
+    return result_set.data_types[column_index];
+}
+
+int tsfile_result_set_meta_get_column_num(ResultSetMetaData result_set) {
+    return result_set.column_num;
+}
+
+TableSchema tsfile_reader_get_table_schema(TsFileReader reader,
+                                           const char *table_name) {
+    // TODO: Implement get table schema with tsfile reader.
+    return TableSchema();
+}
+
+DeviceSchema tsfile_reader_get_device_schema(TsFileReader reader,
+                                                 const char *device_id) {
+    auto *r = static_cast<storage::TsFileReader *>(reader);
+    std::vector<storage::MeasurementSchema> measurement_schemas;
+    r->get_timeseries_schema(
+        std::make_shared<storage::StringArrayDeviceID>(device_id),
+        measurement_schemas);
+    DeviceSchema schema;
+    schema.device_name = strdup(device_id);
+    schema.timeseries_num = measurement_schemas.size();
+    schema.timeseries_schema = static_cast<TimeseriesSchema *>(
+        malloc(sizeof(TimeseriesSchema) * schema.timeseries_num));
+    for (uint32_t i = 0; i < schema.timeseries_num; i++) {
+        schema.timeseries_schema[i].timeseries_name =
+            strdup(measurement_schemas[i].measurement_name_.c_str());
+        schema.timeseries_schema[i].data_type =
+            static_cast<TSDataType>(measurement_schemas[i].data_type_);
+        schema.timeseries_schema[i].compression = static_cast<CompressionType>(
+            measurement_schemas[i].compression_type_);
+        schema.timeseries_schema[i].encoding =
+            static_cast<TSEncoding>(measurement_schemas[i].encoding_);
+    }
+    return schema;
+}
+
+TableSchema *tsfile_reader_get_all_table_schemas(TsFileReader reader,
+                                                 uint32_t *num) {
+    // TODO: Implement get all table schemas.
+    return nullptr;
+}
+
+// delete pointer
+void free_tsfile_ts_record(TsRecord* record) {
+    if (*record != nullptr) {
+        delete static_cast<storage::TsRecord *>(*record);
+    }
+    *record = nullptr;
+}
+
+void free_tablet(Tablet* tablet) {
+    if (*tablet != nullptr) {
+        delete static_cast<storage::Tablet *>(*tablet);
+    }
+    *tablet = nullptr;
+}
+
+void free_tsfile_result_set(ResultSet* result_set) {
+    if (*result_set != nullptr) {
+        delete static_cast<storage::ResultSet *>(*result_set);
+    }
+    *result_set = nullptr;
+}
+
+void free_result_set_meta_data(ResultSetMetaData result_set_meta_data) {
+    for (int i = 0; i < result_set_meta_data.column_num; i++) {
+        free(result_set_meta_data.column_names[i]);
+    }
+    free(result_set_meta_data.column_names);
+    free(result_set_meta_data.data_types);
+}
+
+void free_device_schema(DeviceSchema schema) {
+    free(schema.device_name);
+    for (int i = 0; i < schema.timeseries_num; i++) {
+        free_timeseries_schema(schema.timeseries_schema[i]);
+    }
+    free(schema.timeseries_schema);
+}
+void free_timeseries_schema(TimeseriesSchema schema) {
+    free(schema.timeseries_name);
+}
+void free_table_schema(TableSchema schema) {
+    free(schema.table_name);
+    for (int i = 0; i < schema.column_num; i++) {
+        free_column_schema(schema.column_schemas[i]);
+    }
+    free(schema.column_schemas);
+}
+void free_column_schema(ColumnSchema schema) { free(schema.column_name); }
\ No newline at end of file
diff --git a/cpp/src/cwrapper/tsfile_cwrapper.h 
b/cpp/src/cwrapper/tsfile_cwrapper.h
new file mode 100644
index 000000000..46cdabbcd
--- /dev/null
+++ b/cpp/src/cwrapper/tsfile_cwrapper.h
@@ -0,0 +1,254 @@
+/*
+ * 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.
+ */
+
+#ifndef SRC_CWRAPPER_TSFILE_CWRAPPER_H_
+#define SRC_CWRAPPER_TSFILE_CWRAPPER_H_
+
+#include <cstdint>
+#include <iostream>
+
+typedef enum {
+    TS_DATATYPE_BOOLEAN = 0,
+    TS_DATATYPE_INT32 = 1,
+    TS_DATATYPE_INT64 = 2,
+    TS_DATATYPE_FLOAT = 3,
+    TS_DATATYPE_DOUBLE = 4,
+    TS_DATATYPE_TEXT = 5,
+    TS_DATATYPE_VECTOR = 6,
+    TS_DATATYPE_NULL_TYPE = 254,
+    TS_DATATYPE_INVALID = 255
+} TSDataType;
+
+typedef enum {
+    TS_ENCODING_PLAIN = 0,
+    TS_ENCODING_DICTIONARY = 1,
+    TS_ENCODING_RLE = 2,
+    TS_ENCODING_DIFF = 3,
+    TS_ENCODING_TS_2DIFF = 4,
+    TS_ENCODING_BITMAP = 5,
+    TS_ENCODING_GORILLA_V1 = 6,
+    TS_ENCODING_REGULAR = 7,
+    TS_ENCODING_GORILLA = 8,
+    TS_ENCODING_ZIGZAG = 9,
+    TS_ENCODING_FREQ = 10,
+    TS_ENCODING_INVALID = 255
+} TSEncoding;
+
+typedef enum {
+    TS_COMPRESSION_UNCOMPRESSED = 0,
+    TS_COMPRESSION_SNAPPY = 1,
+    TS_COMPRESSION_GZIP = 2,
+    TS_COMPRESSION_LZO = 3,
+    TS_COMPRESSION_SDT = 4,
+    TS_COMPRESSION_PAA = 5,
+    TS_COMPRESSION_PLA = 6,
+    TS_COMPRESSION_LZ4 = 7,
+    TS_COMPRESSION_INVALID = 255
+} CompressionType;
+
+typedef enum column_category { TAG = 0, FIELD = 1 } ColumnCategory;
+
+typedef struct column_schema {
+    char* column_name;
+    TSDataType data_type;
+    ColumnCategory column_category;
+} ColumnSchema;
+
+typedef struct table_schema {
+    char* table_name;
+    ColumnSchema* column_schemas;
+    int column_num;
+} TableSchema;
+
+typedef struct timeseries_schema {
+    char* timeseries_name;
+    TSDataType data_type;
+    TSEncoding encoding;
+    CompressionType compression;
+} TimeseriesSchema;
+
+typedef struct device_schema {
+    char* device_name;
+    TimeseriesSchema* timeseries_schema;
+    int timeseries_num;
+} DeviceSchema;
+
+typedef struct result_set_meta_data {
+    char** column_names;
+    TSDataType* data_types;
+    int column_num;
+} ResultSetMetaData;
+
+typedef struct tsfile_conf {
+    int mem_threshold_kb;
+} TsFileConf;
+
+typedef void* TsFileReader;
+typedef void* TsFileWriter;
+
+// just reuse Tablet from c++
+typedef void* Tablet;
+typedef void* TsRecord;
+
+typedef void* ResultSet;
+
+typedef int32_t ERRNO;
+typedef int64_t timestamp;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*--------------------------Tablet API------------------------ */
+Tablet tablet_new_with_device(const char* device_id, char** column_name_list,
+                              TSDataType* data_types, int column_num,
+                              int max_rows);
+
+Tablet tablet_new(const char** column_name_list, TSDataType* data_types,
+                  int column_num);
+
+uint32_t tablet_get_cur_row_size(Tablet tablet);
+
+ERRNO tablet_add_timestamp(Tablet tablet, uint32_t row_index,
+                           timestamp timestamp);
+
+#define TABLET_ADD_VALUE_BY_NAME(type)                                        \
+    ERRNO tablet_add_value_by_name_##type(Tablet* tablet, uint32_t row_index, \
+                                          char* column_name, type value);
+
+TABLET_ADD_VALUE_BY_NAME(int32_t);
+TABLET_ADD_VALUE_BY_NAME(int64_t);
+TABLET_ADD_VALUE_BY_NAME(float);
+TABLET_ADD_VALUE_BY_NAME(double);
+TABLET_ADD_VALUE_BY_NAME(bool);
+
+#define TABLE_ADD_VALUE_BY_INDEX(type)                                        \
+    ERRNO tablet_add_value_by_index_##type(Tablet tablet, uint32_t row_index, \
+                                           uint32_t column_index, type value);
+
+TABLE_ADD_VALUE_BY_INDEX(int32_t);
+TABLE_ADD_VALUE_BY_INDEX(int64_t);
+TABLE_ADD_VALUE_BY_INDEX(float);
+TABLE_ADD_VALUE_BY_INDEX(double);
+TABLE_ADD_VALUE_BY_INDEX(bool);
+
+void* tablet_get_value(Tablet tablet, uint32_t row_index, uint32_t 
schema_index,
+                       TSDataType* type);
+
+/*--------------------------TsRecord API------------------------ */
+TsRecord ts_record_new(const char* device_id, timestamp timestamp,
+                       int timeseries_num);
+
+#define INSERT_DATA_INTO_TS_RECORD_BY_NAME(type)     \
+    ERRNO insert_data_into_ts_record_by_name_##type( \
+        TsRecord data, const char* measurement_name, type value);
+
+INSERT_DATA_INTO_TS_RECORD_BY_NAME(int32_t);
+INSERT_DATA_INTO_TS_RECORD_BY_NAME(int64_t);
+INSERT_DATA_INTO_TS_RECORD_BY_NAME(bool);
+INSERT_DATA_INTO_TS_RECORD_BY_NAME(float);
+INSERT_DATA_INTO_TS_RECORD_BY_NAME(double);
+
+/*--------------------------TsFile Reader and Writer------------------------ */
+TsFileReader tsfile_reader_new(const char* pathname, ERRNO* err_code);
+TsFileWriter tsfile_writer_new(const char* pathname, ERRNO* err_code);
+TsFileWriter tsfile_writer_new_with_conf(const char* pathname, mode_t flag,
+                                         ERRNO* err_code, TsFileConf* conf);
+
+ERRNO tsfile_writer_close(TsFileWriter writer);
+ERRNO tsfile_reader_close(TsFileReader reader);
+
+/*--------------------------TsFile Writer Register------------------------ */
+ERRNO tsfile_writer_register_table(TsFileWriter writer, TableSchema* schema);
+ERRNO tsfile_writer_register_timeseries(TsFileWriter writer,
+                                        const char* device_id,
+                                        const TimeseriesSchema* schema);
+ERRNO tsfile_writer_register_device(TsFileWriter writer,
+                                    const DeviceSchema* device_schema);
+
+/*-------------------TsFile Writer write and flush data------------------ */
+ERRNO tsfile_writer_write_tablet(TsFileWriter writer, Tablet tablet);
+ERRNO tsfile_writer_write_ts_record(TsFileWriter writer, TsRecord record);
+ERRNO tsfile_writer_flush_data(TsFileWriter writer);
+
+/*-------------------TsFile reader query data------------------ */
+ResultSet tsfile_reader_query_table(TsFileReader reader, const char* 
table_name,
+                                    char** columns, uint32_t column_num,
+                                    timestamp start_time, timestamp end_time);
+ResultSet tsfile_reader_query_device(TsFileReader reader,
+                                     const char* device_name,
+                                     char** sensor_name, uint32_t sensor_num,
+                                     timestamp start_time, timestamp end_time);
+bool tsfile_result_set_has_next(ResultSet result_set);
+
+#define TSFILE_RESULT_SET_GET_VALUE_BY_NAME(type)                         \
+    type tsfile_result_set_get_value_by_name_##type(ResultSet result_set, \
+                                                    const char* column_name)
+TSFILE_RESULT_SET_GET_VALUE_BY_NAME(bool);
+TSFILE_RESULT_SET_GET_VALUE_BY_NAME(int32_t);
+TSFILE_RESULT_SET_GET_VALUE_BY_NAME(int64_t);
+TSFILE_RESULT_SET_GET_VALUE_BY_NAME(float);
+TSFILE_RESULT_SET_GET_VALUE_BY_NAME(double);
+
+#define TSFILE_RESULT_SET_GET_VALUE_BY_INDEX(type)                         \
+    type tsfile_result_set_get_value_by_index_##type(ResultSet result_set, \
+                                                     uint32_t column_index);
+
+TSFILE_RESULT_SET_GET_VALUE_BY_INDEX(int32_t);
+TSFILE_RESULT_SET_GET_VALUE_BY_INDEX(int64_t);
+TSFILE_RESULT_SET_GET_VALUE_BY_INDEX(float);
+TSFILE_RESULT_SET_GET_VALUE_BY_INDEX(double);
+TSFILE_RESULT_SET_GET_VALUE_BY_INDEX(bool);
+
+bool tsfile_result_set_is_null_by_name(ResultSet result_set,
+                                       const char* column_name);
+
+bool tsfile_result_set_is_null_by_index(ResultSet result_set,
+                                        uint32_t column_index);
+
+ResultSetMetaData tsfile_result_set_get_metadata(ResultSet result_set);
+char* tsfile_result_set_meta_get_column_name(ResultSetMetaData result_set,
+                                             uint32_t column_index);
+TSDataType tsfile_result_set_meta_get_data_type(ResultSetMetaData result_set,
+                                                uint32_t column_index);
+int tsfile_result_set_meta_get_column_num(ResultSetMetaData result_set);
+
+// Desc table schema.
+TableSchema tsfile_reader_get_table_schema(TsFileReader reader,
+                                           const char* table_name);
+DeviceSchema tsfile_reader_get_device_schema(TsFileReader reader,
+                                             const char* device_id);
+
+TableSchema* tsfile_reader_get_all_table_schemas(TsFileReader reader,
+                                                 uint32_t* schema_num);
+
+// Close and free resource.
+void free_tsfile_ts_record(TsRecord* record);
+void free_tablet(Tablet* tablet);
+void free_tsfile_result_set(ResultSet* result_set);
+void free_result_set_meta_data(ResultSetMetaData result_set_meta_data);
+void free_device_schema(DeviceSchema schema);
+void free_timeseries_schema(TimeseriesSchema schema);
+void free_table_schema(TableSchema schema);
+void free_column_schema(ColumnSchema schema);
+
+#ifdef __cplusplus
+}
+#endif
+#endif  // SRC_CWRAPPER_TSFILE_CWRAPPER_H_
diff --git a/cpp/src/cwrapper/tsfile_cwrapper_expression.cc 
b/cpp/src/cwrapper/tsfile_cwrapper_expression.cc
new file mode 100644
index 000000000..338ff2c2e
--- /dev/null
+++ b/cpp/src/cwrapper/tsfile_cwrapper_expression.cc
@@ -0,0 +1,207 @@
+/*
+ * 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.
+ */
+//
+// #include "tsfile_cwrapper_expression.h"
+//
+// #include "common/global.h"
+// #include "reader/expression.h"
+// #include "reader/filter/filter.h"
+// #include "reader/filter/time_filter.h"
+// #include "reader/filter/time_operator.h"
+// #include "reader/result_set.h"
+// #include "reader/tsfile_reader.h"
+// #include "utils/errno_define.h"
+// #include "writer/tsfile_writer.h"
+//
+// #define E_OK common::E_OK
+//
+// #define CONSTRUCT_EXP_INTERNAL(exp, column_name) \
+//     do {                                         \
+//         exp.column_name = column_name;           \
+//         exp.operate_type = oper;                    \
+//         exp.children_length = 0;                 \
+//     } while (0)
+//
+// Expression create_column_filter(const char* column_name, OperatorType oper,
+//                                 int32_t int32_value) {
+//     Expression exp;
+//     CONSTRUCT_EXP_INTERNAL(exp, column_name);
+//     exp.const_condition.value_condition = int32_value;
+//     exp.const_condition.type = TSDataType::TS_DATATYPE_INT32;
+//     return exp;
+// }
+//
+// Expression create_column_filter(const char* column_name, OperatorType oper,
+//                                 int64_t int64_value) {
+//     Expression exp;
+//     CONSTRUCT_EXP_INTERNAL(exp, column_name);
+//     exp.const_condition.value_condition = int64_value;
+//     exp.const_condition.type = TSDataType::TS_DATATYPE_INT64;
+//     return exp;
+// }
+// Expression create_column_filter(const char* column_name, OperatorType oper,
+//                                 bool bool_value) {
+//     Expression exp;
+//     CONSTRUCT_EXP_INTERNAL(exp, column_name);
+//     exp.const_condition.value_condition = bool_value ? 1 : 0;
+//     exp.const_condition.type = TSDataType::TS_DATATYPE_BOOLEAN;
+//     return exp;
+// }
+// Expression create_column_filter(const char* column_name, OperatorType oper,
+//                                 float float_value) {
+//     Expression exp;
+//     CONSTRUCT_EXP_INTERNAL(exp, column_name);
+//     memcpy(&exp.const_condition.value_condition, &float_value, 
sizeof(float));
+//     exp.const_condition.type = TSDataType::TS_DATATYPE_FLOAT;
+//     return exp;
+// }
+// Expression create_column_filter(const char* column_name, OperatorType oper,
+//                                 double double_value) {
+//     Expression exp;
+//     CONSTRUCT_EXP_INTERNAL(exp, column_name);
+//     exp.const_condition.value_condition = double_value;
+//     exp.const_condition.type = TSDataType::TS_DATATYPE_DOUBLE;
+//     return exp;
+// }
+// Expression create_column_filter(const char* column_name, OperatorType oper,
+//                                 const char* char_value) {
+//     Expression exp;
+//     CONSTRUCT_EXP_INTERNAL(exp, column_name);
+//     exp.const_condition.value_condition = 
reinterpret_cast<int64_t>(char_value);
+//     exp.const_condition.type = TSDataType::TS_DATATYPE_TEXT;
+//     return exp;
+// }
+//
+// TimeFilterExpression* create_andquery_timefilter() {
+//     storage::Expression* exp = new storage::Expression(storage::AND_EXPR);
+//     return (TimeFilterExpression*)exp;
+// }
+//
+// TimeFilterExpression* create_time_filter(const char* table_name,
+//                                          const char* column_name,
+//                                          OperatorType oper, int64_t 
timestamp) {
+//     std::string table_name_str(table_name);
+//     std::string column_name_str(column_name);
+//     storage::Path path(table_name_str, column_name_str);
+//     storage::Filter* filter;
+//     switch (oper) {
+//         case GT:
+//             filter = storage::TimeFilter::gt(timestamp);
+//             break;
+//         case LT:
+//             filter = storage::TimeFilter::lt(timestamp);
+//             break;
+//         case EQ:
+//             filter = storage::TimeFilter::eq(timestamp);
+//             break;
+//         case NOTEQ:
+//             filter = storage::TimeFilter::not_eqt(timestamp);
+//             break;
+//         case GE:
+//             filter = storage::TimeFilter::gt_eq(timestamp);
+//             break;
+//         case LE:
+//             filter = storage::TimeFilter::lt_eq(timestamp);
+//             break;
+//         default:
+//             filter = nullptr;
+//             break;
+//     }
+//     storage::Expression* exp =
+//         new storage::Expression(storage::SERIES_EXPR, path, filter);
+//     return (TimeFilterExpression*)exp;
+// }
+//
+// TimeFilterExpression* add_time_filter_to_and_query(
+//     TimeFilterExpression* exp_and, TimeFilterExpression* exp) {
+//     storage::Expression* and_exp = (storage::Expression*)exp_and;
+//     storage::Expression* time_exp = (storage::Expression*)exp;
+//     if (and_exp->left_ == nullptr) {
+//         and_exp->left_ = time_exp;
+//     } else if (and_exp->right_ == nullptr) {
+//         and_exp->right_ = time_exp;
+//     } else {
+//         storage::Expression* new_exp =
+//             new storage::Expression(storage::AND_EXPR);
+//         new_exp->left_ = and_exp->right_;
+//         and_exp->right_ = new_exp;
+//         add_time_filter_to_and_query((TimeFilterExpression*)new_exp, exp);
+//     }
+//     return exp_and;
+// }
+//
+// void destory_time_filter_query(TimeFilterExpression* expression) {
+//     if (expression == nullptr) {
+//         return;
+//     }
+//
+//     destory_time_filter_query(
+//         (TimeFilterExpression*)((storage::Expression*)expression)->left_);
+//     destory_time_filter_query(
+//         (TimeFilterExpression*)((storage::Expression*)expression)->right_);
+//     storage::Expression* exp = (storage::Expression*)expression;
+//     if (exp->type_ == storage::ExpressionType::SERIES_EXPR) {
+//         delete exp->filter_;
+//     } else {
+//         delete exp;
+//     }
+// }
+//
+// Expression create_global_time_expression(OperatorType oper, int64_t 
timestamp) {
+//     Expression exp;
+//     exp.operate_type = oper;
+//     exp.expression_type = GLOBALTIME;
+//     exp.const_condition.value_condition = timestamp;
+//     exp.const_condition.type = TSDataType::TS_DATATYPE_INT64;
+//     return exp;
+// }
+//
+// Expression* and_filter_to_and_query(Expression* exp_and, Expression* exp) {
+//     if (exp_and->children_length >= MAX_COLUMN_FILTER_NUM - 1) {
+//         return nullptr;
+//     }
+//     exp_and->children[exp_and->children_length++] = exp;
+//     return exp_and;
+// }
+//
+// QueryDataRet ts_reader_query(TsFileReader reader, const char* table_name,
+//                              const char** columns_name, int column_num,
+//                              TimeFilterExpression* expression) {
+//     auto* r = (storage::TsFileReader*)reader;
+//     std::string table_name_str(table_name);
+//     std::vector<storage::Path> selected_paths;
+//     for (int i = 0; i < column_num; i++) {
+//         std::string column_name(columns_name[i]);
+//         selected_paths.push_back(storage::Path(table_name_str, 
column_name));
+//     }
+//
+//     storage::ResultSet* qds = nullptr;
+//     storage::QueryExpression* query_expression =
+//         storage::QueryExpression::create(selected_paths,
+//                                          (storage::Expression*)expression);
+//     r->query(query_expression, qds);
+//     QueryDataRet ret = (QueryDataRet)malloc(sizeof(struct query_data_ret));
+//     ret->data = qds;
+//     ret->column_names = (char**)malloc(column_num * sizeof(char*));
+//     ret->column_num = column_num;
+//     for (int i = 0; i < column_num; i++) {
+//         ret->column_names[i] = strdup(columns_name[i]);
+//     }
+//     return ret;
+// }
\ No newline at end of file
diff --git a/cpp/src/cwrapper/tsfile_cwrapper_expression.h 
b/cpp/src/cwrapper/tsfile_cwrapper_expression.h
new file mode 100644
index 000000000..4c593865f
--- /dev/null
+++ b/cpp/src/cwrapper/tsfile_cwrapper_expression.h
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+//
+//#ifndef CWRAPPER_TSFILE_CWRAPPER_H
+//#define CWRAPPER_TSFILE_CWRAPPER_H
+//
+//#include <fcntl.h>
+//#include <stdbool.h>
+//#include <stddef.h>
+//#include <stdint.h>
+//#ifdef _WIN32
+//#include <sys/stat.h>
+//#endif
+//
+//#include "tsfile_cwrapper.h"
+//
+//typedef void* TimeFilterExpression;
+//
+//#define MAX_COLUMN_FILTER_NUM 10
+//typedef enum operator_type {
+//    LT,
+//    LE,
+//    EQ,
+//    GT,
+//    GE,
+//    NOTEQ,
+//} OperatorType;
+//
+//typedef enum expression_type {
+//    OR,
+//    AND,
+//    GLOBALTIME,
+//} ExpressionType;
+//
+//typedef struct constant {
+//    int64_t value_condition;
+//    int type;
+//} Constant;
+//
+//typedef struct expression {
+//    const char* column_name;
+//    Constant const_condition;
+//    ExpressionType expression_type;
+//    OperatorType operate_type;
+//    struct expression* children[MAX_COLUMN_FILTER_NUM];
+//    int children_length;
+//} Expression;
+//
+//typedef void* QueryDataRetINTERNAL;
+//typedef struct query_data_ret {
+//    char** column_names;
+//    int column_num;
+//    QueryDataRetINTERNAL data;
+//}* QueryDataRet;
+//
+//#ifdef __cplusplus
+//extern "C" {
+//#endif
+//
+//TimeFilterExpression* create_query_and_time_filter();
+//
+//TimeFilterExpression* create_time_filter(const char* table_name,
+//                                         const char* column_name,
+//                                         OperatorType oper,
+//                                         timestamp timestamp);
+//
+//TimeFilterExpression* add_time_filter_to_and_query(
+//    TimeFilterExpression* exp_and, TimeFilterExpression* exp);
+//
+//void destroy_time_filter_query(TimeFilterExpression* expression);
+//
+//Expression* create_time_expression(const char* column_name, OperatorType 
oper,
+//                                   timestamp timestamp);
+//
+//Expression* add_and_filter_to_and_query(Expression* exp_and, Expression* 
exp);
+//
+//QueryDataRet ts_reader_query(TsFileReader reader, const char* table_name,
+//                             const char** columns, int colum_num,
+//                             TimeFilterExpression* expression);
+//
+//
+//#ifdef __cplusplus
+//}
+//#endif
+//#endif  // CWRAPPER_TSFILE_CWRAPPER_H
diff --git a/cpp/src/reader/result_set.h b/cpp/src/reader/result_set.h
index d4872a97f..894267997 100644
--- a/cpp/src/reader/result_set.h
+++ b/cpp/src/reader/result_set.h
@@ -39,6 +39,9 @@ class ResultSetMetadata {
         ASSERT(column_index >= 0 && column_index < column_names_.size());
         return column_names_[column_index];
     }
+    uint32_t get_column_count() {
+        return column_names_.size();
+    }
 
    private:
     std::vector<std::string> column_names_;
@@ -77,10 +80,10 @@ class ResultSet {
 };
 
 template <>
-inline common::String* ResultSet::get_value(const std::string& column_name) {
+inline common::String* ResultSet::get_value(const std::string& full_name) {
     RowRecord* row_record = get_row_record();
-    ASSERT(index_lookup_.count(column_name));
-    uint32_t index = index_lookup_[column_name];
+    ASSERT(index_lookup_.count(full_name));
+    uint32_t index = index_lookup_[full_name];
     ASSERT(index >= 0 && index < row_record->get_col_num());
     return row_record->get_field(index)->get_string_value();
 }
diff --git a/cpp/src/reader/tsfile_reader.cc b/cpp/src/reader/tsfile_reader.cc
index ef0aef60c..ce3f87137 100644
--- a/cpp/src/reader/tsfile_reader.cc
+++ b/cpp/src/reader/tsfile_reader.cc
@@ -26,9 +26,7 @@ using namespace common;
 using namespace storage;
 
 namespace storage {
-TsFileReader::TsFileReader()
-    : read_file_(nullptr), tsfile_executor_(nullptr) {
-}
+TsFileReader::TsFileReader() : read_file_(nullptr), tsfile_executor_(nullptr) 
{}
 
 TsFileReader::~TsFileReader() { close(); }
 
@@ -82,21 +80,23 @@ void 
TsFileReader::destroy_query_data_set(storage::ResultSet* qds) {
     tsfile_executor_->destroy_query_data_set(qds);
 }
 
-std::vector<std::shared_ptr<IDeviceID>> 
TsFileReader::get_all_devices(std::string table_name) {
+std::vector<std::shared_ptr<IDeviceID>> TsFileReader::get_all_devices(
+    std::string table_name) {
     TsFileMeta* tsfile_meta = tsfile_executor_->get_tsfile_meta();
     std::vector<std::shared_ptr<IDeviceID>> device_ids;
     if (tsfile_meta != nullptr) {
         PageArena pa;
         pa.init(512, MOD_TSFILE_READER);
-        auto index_node = 
tsfile_meta->table_metadata_index_node_map_[table_name];
+        auto index_node =
+            tsfile_meta->table_metadata_index_node_map_[table_name];
         get_all_devices(device_ids, index_node, pa);
     }
     return device_ids;
 }
 
-int TsFileReader::get_all_devices(std::vector<std::shared_ptr<IDeviceID>>& 
device_ids,
-                                  std::shared_ptr<MetaIndexNode> index_node,
-                                  PageArena& pa) {
+int TsFileReader::get_all_devices(
+    std::vector<std::shared_ptr<IDeviceID>>& device_ids,
+    std::shared_ptr<MetaIndexNode> index_node, PageArena& pa) {
     int ret = E_OK;
     if (index_node != nullptr) {
         if (index_node->node_type_ == LEAF_DEVICE) {
@@ -119,7 +119,7 @@ int 
TsFileReader::get_all_devices(std::vector<std::shared_ptr<IDeviceID>>& devic
                 if (IS_NULL(data_buf) || IS_NULL(m_idx_node_buf)) {
                     return E_OOM;
                 }
-                auto* top_node_ptr = new(m_idx_node_buf) MetaIndexNode(&pa);
+                auto* top_node_ptr = new (m_idx_node_buf) MetaIndexNode(&pa);
                 auto top_node = std::shared_ptr<MetaIndexNode>(
                     top_node_ptr, [](MetaIndexNode* ptr) {
                         if (ptr) {
@@ -128,9 +128,9 @@ int 
TsFileReader::get_all_devices(std::vector<std::shared_ptr<IDeviceID>>& devic
                     });
 
                 if (RET_FAIL(read_file_->read(start_offset, data_buf, 
read_size,
-                    ret_read_len))) {
-                } else if (RET_FAIL(top_node->device_deserialize_from(data_buf,
-                    read_size))) {
+                                              ret_read_len))) {
+                } else if (RET_FAIL(top_node->device_deserialize_from(
+                               data_buf, read_size))) {
                 } else {
                     ret = get_all_devices(device_ids, top_node, pa);
                 }
@@ -148,8 +148,8 @@ int TsFileReader::get_timeseries_schema(
     PageArena pa;
     pa.init(512, MOD_TSFILE_READER);
     if (RET_FAIL(tsfile_executor_->get_tsfile_io_reader()
-        ->get_device_timeseries_meta_without_chunk_meta(
-            device_id, timeseries_indexs, pa))) {
+                     ->get_device_timeseries_meta_without_chunk_meta(
+                         device_id, timeseries_indexs, pa))) {
     } else {
         for (auto timeseries_index : timeseries_indexs) {
             MeasurementSchema ms(
@@ -166,4 +166,4 @@ ResultSet* TsFileReader::read_timeseries(
     const std::vector<std::string>& measurement_name) {
     return nullptr;
 }
-} // namespace storage
+}  // namespace storage
diff --git a/cpp/src/reader/tsfile_reader.h b/cpp/src/reader/tsfile_reader.h
index c03e1a564..42ada98e0 100644
--- a/cpp/src/reader/tsfile_reader.h
+++ b/cpp/src/reader/tsfile_reader.h
@@ -52,6 +52,7 @@ class TsFileReader {
     int get_timeseries_schema(std::shared_ptr<IDeviceID> device_id,
                               std::vector<MeasurementSchema> &result);
 
+
    private:
     int get_all_devices(std::vector<std::shared_ptr<IDeviceID>> &device_ids,
                         std::shared_ptr<MetaIndexNode> index_node, 
common::PageArena &pa);
diff --git a/cpp/src/writer/tsfile_writer.cc b/cpp/src/writer/tsfile_writer.cc
index a8c8ecf7b..9480a9ccf 100644
--- a/cpp/src/writer/tsfile_writer.cc
+++ b/cpp/src/writer/tsfile_writer.cc
@@ -115,10 +115,14 @@ void TsFileWriter::set_generate_table_schema(bool 
generate_table_schema) {
     io_writer_->set_generate_table_schema(generate_table_schema);
 }
 
-void TsFileWriter::register_table(
+int TsFileWriter::register_table(
     const std::shared_ptr<TableSchema> &table_schema) {
-    if (!table_schema) return;
+    if (!table_schema) return E_INVALID_ARG;
+    if (table_schema_map_.find(table_schema->get_table_name()) != 
table_schema_map_.end()) {
+        return E_ALREADY_EXIST;
+    }
     table_schema_map_.emplace(table_schema->get_table_name(), table_schema);
+    return E_OK;
 }
 
 bool check_file_exist(const std::string &file_path) {
diff --git a/cpp/src/writer/tsfile_writer.h b/cpp/src/writer/tsfile_writer.h
index 1fdf7e5b7..22468f92d 100644
--- a/cpp/src/writer/tsfile_writer.h
+++ b/cpp/src/writer/tsfile_writer.h
@@ -65,7 +65,7 @@ class TsFileWriter {
     int register_aligned_timeseries(
         const std::string &device_id,
         const std::vector<MeasurementSchema *> &measurement_schemas);
-    void register_table(const std::shared_ptr<TableSchema> &table_schema);
+    int register_table(const std::shared_ptr<TableSchema> &table_schema);
     int write_record(const TsRecord &record);
     int write_tablet(const Tablet &tablet);
     int write_record_aligned(const TsRecord &record);
diff --git a/cpp/test/CMakeLists.txt b/cpp/test/CMakeLists.txt
index 77e31d6c0..a17b1e3c3 100644
--- a/cpp/test/CMakeLists.txt
+++ b/cpp/test/CMakeLists.txt
@@ -75,6 +75,7 @@ file(GLOB_RECURSE TEST_SRCS
         "compress/*_test.cc"
         "reader/*_test.cc"
         "writer/*_test.cc"
+        "cwrapper/*_test.cc"
         )
 if (${COV_ENABLED})
     message("Enable code cov...")
@@ -83,6 +84,7 @@ endif ()
 
 if(NOT WIN32)
 #enable address sanitizer default
+    set(ENV{ASAN_OPTIONS} "detect_container_overflow=0")
     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -g")
 endif()
 
diff --git a/cpp/test/common/tsfile_common_test.cc 
b/cpp/test/common/tsfile_common_test.cc
index 46e9f8d7e..40371ce6b 100644
--- a/cpp/test/common/tsfile_common_test.cc
+++ b/cpp/test/common/tsfile_common_test.cc
@@ -19,7 +19,6 @@
 #include "common/tsfile_common.h"
 
 #include <common/schema.h>
-#include <cwrapper/TsFile-cwrapper.h>
 #include <gtest/gtest.h>
 
 namespace storage {
diff --git a/cpp/test/cwrapper/cwrapper_test.cc 
b/cpp/test/cwrapper/cwrapper_test.cc
index 18335fdf2..ed834068d 100644
--- a/cpp/test/cwrapper/cwrapper_test.cc
+++ b/cpp/test/cwrapper/cwrapper_test.cc
@@ -18,30 +18,128 @@
  */
 #include <gtest/gtest.h>
 #include <unistd.h>
+extern "C" {
+#include "cwrapper/tsfile_cwrapper.h"
+}
 
-#include "cwrapper/TsFile-cwrapper.h"
 #include "utils/errno_define.h"
 
 using namespace common;
 
 namespace cwrapper {
-#define TSFILE_NAME "cwrapper.tsfile"
 class CWrapperTest : public testing::Test {};
 
-TEST_F(CWrapperTest, write_tsfile) {
-    ErrorCode code = 0;
-    CTsFileWriter writer = ts_writer_open(TSFILE_NAME, &code);
+TEST_F(CWrapperTest, RegisterTimeSeries) {
+    ERRNO code = 0;
+    char* temperature = strdup("temperature");
+    TimeseriesSchema ts_schema{temperature, TS_DATATYPE_INT32,
+                               TS_ENCODING_PLAIN, TS_COMPRESSION_UNCOMPRESSED};
+    TsFileWriter writer = 
tsfile_writer_new("cwrapper_register_timeseries.tsfile", &code);
+    ASSERT_EQ(code, 0);
+    code = tsfile_writer_register_timeseries(writer, "device1", &ts_schema);
+    ASSERT_EQ(code, 0);
+    free(temperature);
+    tsfile_writer_close(writer);
+}
+
+TEST_F(CWrapperTest, WriterFlushTabletAndReadData) {
+    ERRNO code = 0;
+    const int device_num = 50;
+    const int measurement_num = 50;
+    DeviceSchema device_schema[50];
+    TsFileWriter writer = 
tsfile_writer_new("cwrapper_write_flush_and_read.tsfile", &code);
     ASSERT_EQ(code, 0);
-    ASSERT_NE(writer, nullptr);
-    // open again
-    writer = ts_writer_open(TSFILE_NAME, &code);
-    ASSERT_EQ(code, E_ALREADY_EXIST);
-    ts_writer_close(writer);
-    ASSERT_EQ(writer, nullptr);
-    ASSERT_EQ(access(TSFILE_NAME, F_OK), 0);
-
-    writer = ts_writer_open(TSFILE_NAME, &code);
-    ASSERT_EQ(code, E_ALREADY_EXIST);
-    ASSERT_EQ(writer, nullptr);
+    for (int i = 0; i < device_num; i++) {
+        char* device_name = strdup(("device" + std::to_string(i)).c_str());
+        device_schema[i].device_name = device_name;
+        device_schema[i].timeseries_num = measurement_num;
+        device_schema[i].timeseries_schema = (TimeseriesSchema*)malloc(
+            sizeof(TimeseriesSchema) * measurement_num);
+        for (int j = 0; j < measurement_num; j++) {
+            TimeseriesSchema* schema = device_schema[i].timeseries_schema + j;
+            schema->timeseries_name =
+                strdup(("measurement" + std::to_string(j)).c_str());
+            schema->compression = TS_COMPRESSION_UNCOMPRESSED;
+            schema->data_type = TS_DATATYPE_INT64;
+            schema->encoding = TS_ENCODING_PLAIN;
+        }
+        code = tsfile_writer_register_device(writer, &device_schema[i]);
+        ASSERT_EQ(code, 0);
+        free_device_schema(device_schema[i]);
+    }
+    int max_rows = 100;
+    for (int i = 0; i < device_num; i++) {
+        char* device_name = strdup(("device" + std::to_string(i)).c_str());
+        char** measurements_name =
+            static_cast<char**>(malloc(measurement_num * sizeof(char*)));
+        TSDataType* data_types = static_cast<TSDataType*>(
+            malloc(sizeof(TSDataType) * measurement_num));
+        for (int j = 0; j < measurement_num; j++) {
+            measurements_name[j] =
+                strdup(("measurement" + std::to_string(j)).c_str());
+            data_types[j] = TS_DATATYPE_INT64;
+        }
+        Tablet tablet =
+            tablet_new_with_device(device_name, measurements_name, data_types,
+                                   measurement_num, max_rows);
+        free(device_name);
+        free(data_types);
+        for (int j = 0; j < measurement_num; j++) {
+            free(measurements_name[j]);
+        }
+        free(measurements_name);
+        for (int j = 0; j < measurement_num; j++) {
+            for (int row = 0; row < max_rows; row++) {
+                tablet_add_timestamp(tablet, row, 16225600 + row);
+            }
+            for (int row = 0; row < max_rows; row++) {
+                tablet_add_value_by_index_int64_t(
+                    tablet, row, j, static_cast<int64_t>(row + j));
+            }
+        }
+        code = tsfile_writer_write_tablet(writer, tablet);
+        ASSERT_EQ(code, 0);
+        free_tablet(&tablet);
+    }
+    ASSERT_EQ(tsfile_writer_flush_data(writer), 0);
+    ASSERT_EQ(tsfile_writer_close(writer), 0);
+
+    TsFileReader reader = 
tsfile_reader_new("cwrapper_write_flush_and_read.tsfile", &code);
+    ASSERT_EQ(code, 0);
+
+    char** sensor_list =
+        static_cast<char**>(malloc(measurement_num * sizeof(char*)));
+    for (int i = 0; i < measurement_num; i++) {
+        sensor_list[i] = strdup(("measurement" + std::to_string(i)).c_str());
+    }
+    ResultSet result_set =
+        tsfile_reader_query_device(reader,"device0", sensor_list, 
measurement_num, 16225600,
+                                 16225600 + max_rows - 1);
+
+    ResultSetMetaData metadata = tsfile_result_set_get_metadata(result_set);
+    ASSERT_EQ(metadata.column_num, measurement_num);
+    ASSERT_EQ(std::string(metadata.column_names[4]),
+              std::string("device0.measurement4"));
+    ASSERT_EQ(metadata.data_types[9], TS_DATATYPE_INT64);
+    for (int i = 0; i < measurement_num - 1; i++) {
+        ASSERT_TRUE(tsfile_result_set_has_next(result_set));
+        ASSERT_FALSE(tsfile_result_set_is_null_by_index(result_set, i));
+        ASSERT_EQ(tsfile_result_set_get_value_by_index_int64_t(result_set, i),
+                  i * 2);
+        ASSERT_EQ(tsfile_result_set_get_value_by_name_int64_t(
+                      result_set,
+                      std::string("measurement" + std::to_string(i)).c_str()),
+                  i * 2);
+    }
+    free_tsfile_result_set(&result_set);
+    free_result_set_meta_data(metadata);
+    for (int i = 0; i < measurement_num; i++) {
+        free(sensor_list[i]);
+    }
+    free(sensor_list);
+    tsfile_reader_close(reader);
+    // DeviceSchema schema = tsfile_reader_get_device_schema(reader,
+    // "device4"); ASSERT_EQ(schema.timeseries_num, 1);
+    // ASSERT_EQ(schema.timeseries_schema->name, std::string("measurement4"));
 }
 }  // namespace cwrapper
\ No newline at end of file

Reply via email to