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 0f1ab168 Example c cpp (#418)
0f1ab168 is described below

commit 0f1ab1683b7baa82c4539b5840414f6988f2a868
Author: Colin Lee <[email protected]>
AuthorDate: Fri Feb 28 09:23:17 2025 +0800

    Example c cpp (#418)
    
    * examples.
    
    tmpc ode.
    
    tmp code.
    
    fix issue.
    
    * add example.
    
    * fix some c issues.
    
    * fix some error.
    
    * fix c
    
    * fix some error.
    
    * fix some issue.
    
    * fix file.
    
    * fix some example issue.
    
    * Fix windows.
    
    * fix code style.
    
    * fix tmp code.
    
    * fix error.
    
    * remove file.
---
 cpp/examples/CMakeLists.txt                        |  21 +-
 cpp/examples/README.md                             |  79 +++
 cpp/examples/build.sh                              |   2 +-
 cpp/examples/c_examples/c_examples.c               | 133 -----
 cpp/examples/c_examples/c_examples.h               |  15 +-
 cpp/examples/c_examples/demo_read.c                | 110 ++++
 cpp/examples/c_examples/demo_write.c               |  96 ++++
 cpp/examples/cpp_examples/cpp_examples.h           |  11 +
 cpp/examples/cpp_examples/demo_read.cpp            | 128 ++---
 cpp/examples/cpp_examples/demo_write.cpp           | 125 ++---
 cpp/examples/examples.cc                           |   2 +
 cpp/examples/test_cpp.tsfile                       | Bin 0 -> 447 bytes
 cpp/src/common/db_common.h                         |   2 +
 cpp/src/common/schema.h                            |   6 +-
 cpp/src/common/tablet.cc                           | 120 +++--
 cpp/src/cwrapper/errno_define.h                    |  77 +++
 cpp/src/cwrapper/tsfile_cwrapper.cc                | 585 +++++++++++++--------
 cpp/src/cwrapper/tsfile_cwrapper.h                 | 358 +++++++++++--
 .../reader/block/single_device_tsblock_reader.cc   |   7 +-
 cpp/src/reader/table_result_set.cc                 |   1 +
 cpp/src/utils/db_utils.h                           |   8 +
 cpp/src/writer/tsfile_table_writer.h               |   1 +
 cpp/src/writer/tsfile_writer.cc                    | 104 ++--
 cpp/src/writer/tsfile_writer.h                     |  53 +-
 cpp/test/cwrapper/cwrapper_test.cc                 | 242 +++++----
 25 files changed, 1525 insertions(+), 761 deletions(-)

diff --git a/cpp/examples/CMakeLists.txt b/cpp/examples/CMakeLists.txt
index 4b433c96..75b92692 100644
--- a/cpp/examples/CMakeLists.txt
+++ b/cpp/examples/CMakeLists.txt
@@ -20,13 +20,32 @@ cmake_minimum_required(VERSION 3.10)
 project(examples)
 message("Running in exampes directory")
 
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+
+# TsFile include dir
 set(SDK_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/../src/)
 message("SDK_INCLUDE_DIR: ${SDK_INCLUDE_DIR}")
+
+# TsFile shared object dir
 set(SDK_LIB_DIR_RELEASE ${PROJECT_SOURCE_DIR}/../build/Release/lib)
 message("SDK_LIB_DIR_RELEASE: ${SDK_LIB_DIR_RELEASE}")
 
+set(SDK_LIB_DIR_DEBUG ${PROJECT_SOURCE_DIR}/../build/Debug/lib)
+message("SDK_LIB_DIR_DEBUG: ${SDK_LIB_DIR_DEBUG}")
+include_directories(${PROJECT_SOURCE_DIR}/../third_party/antlr4-cpp-runtime-4/runtime/src)
+
+set(BUILD_TYPE "Debug")
 include_directories(${SDK_INCLUDE_DIR})
-find_library(my_tsfile_lib NAMES tsfile PATHS ${SDK_LIB_DIR_RELEASE} 
NO_DEFAULT_PATH REQUIRED)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g")
+set(CMAKE_CXX_FLAGS_DEBUG" ${CMAKE_CXX_FLAGS} -O0 -g")
+
+# Find libtsfile in SDK_LIB_RIR
+if (BUILD_TYPE STREQUAL "Release")
+    find_library(my_tsfile_lib NAMES tsfile PATHS ${SDK_LIB_DIR_RELEASE} 
NO_DEFAULT_PATH REQUIRED)
+elseif(BUILD_TYPE STREQUAL "Debug")
+    find_library(my_tsfile_lib NAMES tsfile PATHS ${SDK_LIB_DIR_DEBUG} 
NO_DEFAULT_PATH REQUIRED)
+endif ()
 
 add_subdirectory(cpp_examples)
 add_subdirectory(c_examples)
diff --git a/cpp/examples/README.md b/cpp/examples/README.md
new file mode 100644
index 00000000..7b20d5f4
--- /dev/null
+++ b/cpp/examples/README.md
@@ -0,0 +1,79 @@
+<!--
+
+​    Licensed to the Apache Software Foundation (ASF) under one
+​    or more contributor license agreements.  See the NOTICE file
+​    distributed with this work for additional information
+​    regarding copyright ownership.  The ASF licenses this file
+​    to you under the Apache License, Version 2.0 (the
+​    "License"); you may not use this file except in compliance
+​    with the License.  You may obtain a copy of the License at
+
+​        http://www.apache.org/licenses/LICENSE-2.0
+
+​    Unless required by applicable law or agreed to in writing,
+​    software distributed under the License is distributed on an
+​    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+​    KIND, either express or implied.  See the License for the
+​    specific language governing permissions and limitations
+​    under the License.
+
+-->
+
+# TsFile Reader/Writer Integration Guide
+
+## 1. Building TSFile Shared Library
+
+Build Methods (Choose either approach)
+
+### Method 1: Maven Build
+Execute from the project root directory:
+
+```BASH
+mvn package -P with-cpp clean verify
+```
+Output location: cpp/target/build/lib
+
+If maven is not installed, may use 'mvnw' in linux/macos or 'mvnw.cmd' in win 
instead"
+
+### Method 2: Script Build
+Run the build script:
+
+```BASH
+bash build.sh
+```
+Output location: cpp/build/Release/lib
+
+## Project Configuration
+### CMake Integration
+
+Add to your CMakeLists.txt:
+
+```CMAKE
+find_library(TSFILE_LIB NAMES tsfile PATHS ${SDK_LIB} REQUIRED)
+target_link_libraries(your_target ${TSFILE_LIB})
+```
+
+Note: Set ${SDK_LIB} to your TSFile library directory.
+
+## 3. Implementation Examples
+   
+### Directory Structure
+```TEXT
+   ├── CMakeLists.txt
+   ├── c_examples/
+   │   ├── demo_write.c    # C write implementation
+   │   └── demo_read.c     # C read implementation
+   ├── cpp_examples/
+   │   ├── demo_write.cpp  # C++ write implementation
+   │   └── demo_read.cpp   # C++ read implementation
+   └── examples.cc         # Combined use cases
+```
+
+### Code References
+Writing TSFiles:\
+C: c_examples/demo_write.c\
+C++: cpp_examples/demo_write.cpp
+
+Reading TSFiles:\
+C: c_examples/demo_read.c\
+C++: cpp_examples/demo_read.cpp
\ No newline at end of file
diff --git a/cpp/examples/build.sh b/cpp/examples/build.sh
index bf4a3c45..36cf44ae 100644
--- a/cpp/examples/build.sh
+++ b/cpp/examples/build.sh
@@ -28,5 +28,5 @@ else
 fi
 
 
-cmake ../../ -DUSE_CPP11=$use_cpp11
+cmake ../../ -DBUILD_TYPE=$build_type
 make
\ No newline at end of file
diff --git a/cpp/examples/c_examples/c_examples.c 
b/cpp/examples/c_examples/c_examples.c
deleted file mode 100644
index 8e5f8d2d..00000000
--- a/cpp/examples/c_examples/c_examples.c
+++ /dev/null
@@ -1,133 +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 "c_examples.h"
-
-#include <fcntl.h>
-#include <malloc.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#define HANDLE_ERROR(err_no)                  \
-    do {                                      \
-        if (err_no != 0) {                    \
-            printf("get err no: %d", err_no); \
-            return err_no;                    \
-        }                                     \
-    } while (0)
-
-ErrorCode write_tsfile() {
-    ErrorCode err_code;
-    CTsFileWriter writer;
-    if (access("c_rw.tsfile", 0) == 0) {
-        if (remove("test.tsfile") != 0) {
-            printf("Failed to delete test.tsfile file\n");
-            return -1;
-        }
-    }
-    writer = ts_writer_open("c_rw.tsfile", &err_code);
-    if (NULL == writer) {
-        return err_code;
-    }
-    ColumnSchema columnSchema;
-    columnSchema.name = "temperature";
-    columnSchema.column_def = TS_TYPE_INT32;
-    err_code =
-        tsfile_register_table_column(writer, "test_table", &columnSchema);
-    HANDLE_ERROR(err_code);
-    TableSchema tableSchema;
-    tableSchema.column_num = 3;
-    tableSchema.table_name = "test_table";
-    tableSchema.column_schema =
-        (ColumnSchema **)malloc(tableSchema.column_num * sizeof(TableSchema 
*));
-    tableSchema.column_schema[0] = (ColumnSchema 
*)malloc(sizeof(ColumnSchema));
-    tableSchema.column_schema[0]->column_def = TS_TYPE_DOUBLE;
-    tableSchema.column_schema[0]->name = "level";
-    tableSchema.column_schema[1] = (ColumnSchema 
*)malloc(sizeof(ColumnSchema));
-    tableSchema.column_schema[1]->column_def = TS_TYPE_BOOLEAN;
-    tableSchema.column_schema[1]->name = "up";
-    tableSchema.column_schema[2] = (ColumnSchema 
*)malloc(sizeof(ColumnSchema));
-    tableSchema.column_schema[2]->column_def = TS_TYPE_FLOAT;
-    tableSchema.column_schema[2]->name = "humi";
-    err_code = tsfile_register_table(writer, &tableSchema);
-    free(tableSchema.column_schema[0]);
-    free(tableSchema.column_schema[1]);
-    free(tableSchema.column_schema[2]);
-    free(tableSchema.column_schema);
-    HANDLE_ERROR(err_code);
-    printf("register table success\n");
-    TsFileRowData rowData = create_tsfile_row("test_table", 1, 4);
-    insert_data_into_tsfile_row_double(rowData, "level", 10);
-    insert_data_into_tsfile_row_float(rowData, "humi", 10.0f);
-    insert_data_into_tsfile_row_boolean(rowData, "up", true);
-    insert_data_into_tsfile_row_int32(rowData, "temperature", 10);
-    err_code = tsfile_write_row_data(writer, rowData);
-
-    rowData = create_tsfile_row("test_table", 2, 4);
-    insert_data_into_tsfile_row_double(rowData, "level", 12);
-    err_code = tsfile_write_row_data(writer, rowData);
-
-    for (int ind = 10; ind < 2000; ind++) {
-        rowData = create_tsfile_row("test_table", ind, 4);
-        insert_data_into_tsfile_row_double(rowData, "level", 12 + ind);
-        insert_data_into_tsfile_row_float(rowData, "humi", 12.0f + ind);
-        insert_data_into_tsfile_row_boolean(rowData, "up", true);
-        insert_data_into_tsfile_row_int32(rowData, "temperature", 12 + ind);
-        err_code = tsfile_write_row_data(writer, rowData);
-    }
-    printf("writer row data success\n");
-    HANDLE_ERROR(err_code);
-    HANDLE_ERROR(tsfile_flush_data(writer));
-    printf("flush data success\n");
-    HANDLE_ERROR(ts_writer_close(writer));
-    printf("close writer success\n");
-    return 0;
-}
-
-ErrorCode read_tsfile() {
-    ErrorCode err_code;
-    CTsFileReader reader;
-    reader = ts_reader_open("c_rw.tsfile", &err_code);
-    if (NULL == reader) {
-        return err_code;
-    }
-    const char *columns[] = {"temperature", "level", "up", "humi"};
-    //  TimeFilterExpression* exp = create_andquery_timefilter();
-    //  TimeFilterExpression* time_filter = create_time_filter("test_table",
-    //  "temperature", GT, 11); TimeFilterExpression* time_filter2 =
-    //  create_time_filter("test_table", "humi", GT, 10); TimeFilterExpression*
-    //  time_filter3 = create_time_filter("test_table", "level", LE, 20);
-    //  add_time_filter_to_and_query(exp, time_filter);
-    //  add_time_filter_to_and_query(exp, time_filter2);
-    //  add_time_filter_to_and_query(exp, time_filter3);
-
-    QueryDataRet ret = ts_reader_query(reader, "test_table", columns, 4, NULL);
-    printf("query success\n");
-    DataResult *result = ts_next(ret, 20);
-    if (result == NULL) {
-        printf("get result failed\n");
-        return -1;
-    }
-    print_data_result(result);
-    //  destory_time_filter_query(exp);
-    HANDLE_ERROR(destory_query_dataret(ret));
-    HANDLE_ERROR(destory_tablet(result));
-    return 0;
-}
diff --git a/cpp/examples/c_examples/c_examples.h 
b/cpp/examples/c_examples/c_examples.h
index 3f63803f..ba674778 100644
--- a/cpp/examples/c_examples/c_examples.h
+++ b/cpp/examples/c_examples/c_examples.h
@@ -17,15 +17,22 @@
  * under the License.
  */
 
-#include "cwrapper/TsFile-cwrapper.h"
+#include "cwrapper/errno_define.h"
+#include "cwrapper/tsfile_cwrapper.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
+ERRNO write_tsfile();
+ERRNO read_tsfile();
 
-ErrorCode write_tsfile();
-ErrorCode read_tsfile();
-
+#define HANDLE_ERROR(err_no)                  \
+    do {                                      \
+        if (err_no != 0) {                    \
+            printf("get err no: %d", err_no); \
+            return err_no;                    \
+        }                                     \
+    } while (0)
 #ifdef __cplusplus
 }
 #endif
diff --git a/cpp/examples/c_examples/demo_read.c 
b/cpp/examples/c_examples/demo_read.c
new file mode 100644
index 00000000..1636adbd
--- /dev/null
+++ b/cpp/examples/c_examples/demo_read.c
@@ -0,0 +1,110 @@
+/*
+ * 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 <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "c_examples.h"
+
+// This example shows you how to read tsfile.
+ERRNO read_tsfile() {
+
+    ERRNO code = 0;
+    char* table_name = "table1";
+
+    // Create tsfile reader with specify tsfile's path
+    TsFileReader reader = tsfile_reader_new("test_c.tsfile", &code);
+    HANDLE_ERROR(code);
+
+    ResultSet ret = tsfile_query_table(
+        reader, table_name, (char*[]){"id1", "id2", "s1"}, 3, 0, 10, &code);
+    HANDLE_ERROR(code);
+
+    if (ret == NULL) {
+        HANDLE_ERROR(RET_INVALID_QUERY);
+    }
+
+    // Get query result metadata: column name and datatype
+    ResultSetMetaData metadata = tsfile_result_set_get_metadata(ret);
+    int column_num = metadata.column_num;
+
+    for (int i = 0; i < column_num; i++) {
+        printf("column:%s, datatype:%d\n", metadata.column_names[i],
+               metadata.data_types[i]);
+    }
+
+    // Get data by column name or index.
+    while (tsfile_result_set_next(ret, &code) && code == RET_OK) {
+        // Timestamp at column 1 and column index begin from 1.
+        Timestamp timestamp =
+            tsfile_result_set_get_value_by_index_int64_t(ret, 1);
+        printf("%ld ", timestamp);
+        for (int i = 1; i < column_num; i++) {
+            if (tsfile_result_set_is_null_by_index(ret, i)) {
+                printf(" null ");
+            } else {
+                switch (metadata.data_types[i]) {
+                    case TS_DATATYPE_BOOLEAN:
+                        printf("%d", tsfile_result_set_get_value_by_index_bool(
+                                         ret, i));
+                        break;
+                    case TS_DATATYPE_INT32:
+                        printf("%d",
+                               
tsfile_result_set_get_value_by_index_int32_t(ret,
+                                                                            
i));
+                        break;
+                    case TS_DATATYPE_INT64:
+                        printf("%ld",
+                               
tsfile_result_set_get_value_by_index_int64_t(ret,
+                                                                            
i));
+                        break;
+                    case TS_DATATYPE_FLOAT:
+                        printf("%f", 
tsfile_result_set_get_value_by_index_float(
+                                         ret, i));
+                        break;
+                    case TS_DATATYPE_DOUBLE:
+                        printf("%lf",
+                               tsfile_result_set_get_value_by_index_double(ret,
+                                                                           i));
+                        break;
+                    case TS_DATATYPE_STRING:
+                        printf("%s",
+                               tsfile_result_set_get_value_by_index_string(ret,
+                                                                           i));
+                        break;
+                    default:
+                        printf("unknown_type");
+                        break;
+                }
+            }
+        }
+    }
+
+    // Free query meta data
+    free_result_set_meta_data(metadata);
+
+    // Free query handler.
+    free_tsfile_result_set(&ret);
+
+    // Close tsfile reader.
+    tsfile_reader_close(reader);
+
+    return 0;
+}
diff --git a/cpp/examples/c_examples/demo_write.c 
b/cpp/examples/c_examples/demo_write.c
new file mode 100644
index 00000000..78c134dc
--- /dev/null
+++ b/cpp/examples/c_examples/demo_write.c
@@ -0,0 +1,96 @@
+/*
+ * 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 <malloc.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "c_examples.h"
+
+// This example shows you how to write tsfile.
+ERRNO write_tsfile() {
+    ERRNO code = 0;
+    char* table_name = "table1";
+
+    // Create table schema to describe a table in a tsfile.
+    TableSchema table_schema;
+    table_schema.table_name = strdup(table_name);
+    table_schema.column_num = 3;
+    table_schema.column_schemas =
+        (ColumnSchema*)malloc(sizeof(ColumnSchema) * 3);
+    table_schema.column_schemas[0] =
+        ColumnSchema{.column_name = strdup("id1"),
+                     .data_type = TS_DATATYPE_STRING,
+                     .compression = TS_COMPRESSION_UNCOMPRESSED,
+                     .encoding = TS_ENCODING_PLAIN,
+                     .column_category = TAG};
+    table_schema.column_schemas[1] =
+        ColumnSchema{.column_name = strdup("id2"),
+                     .data_type = TS_DATATYPE_STRING,
+                     .compression = TS_COMPRESSION_UNCOMPRESSED,
+                     .encoding = TS_ENCODING_PLAIN,
+                     .column_category = TAG};
+    table_schema.column_schemas[2] =
+        ColumnSchema{.column_name = strdup("s1"),
+                     .data_type = TS_DATATYPE_INT32,
+                     .compression = TS_COMPRESSION_UNCOMPRESSED,
+                     .encoding = TS_ENCODING_PLAIN,
+                     .column_category = FIELD};
+
+    // Create a file with specify path to write tsfile.
+    WriteFile file = write_file_new("test_c.tsfile", &code);
+    HANDLE_ERROR(code);
+
+    // Create tsfile writer with specify table schema.
+    TsFileWriter writer = tsfile_writer_new(file, &table_schema, &code);
+    HANDLE_ERROR(code);
+
+    // Create tablet to insert data.
+    Tablet tablet =
+        tablet_new((char*[]){"id1", "id2", "s1"},
+                   (TSDataType[]){TS_DATATYPE_STRING, TS_DATATYPE_STRING,
+                                  TS_DATATYPE_INT32},
+                   3, 5);
+
+    for (int row = 0; row < 5; row++) {
+        Timestamp timestamp = row;
+        tablet_add_timestamp(tablet, row, timestamp);
+        tablet_add_value_by_name_string(tablet, row, "id1", "id_field_1");
+        tablet_add_value_by_name_string(tablet, row, "id2", "id_field_2");
+        tablet_add_value_by_name_int32_t(tablet, row, "s1", row);
+    }
+
+    // Write tablet data.
+    HANDLE_ERROR(tsfile_writer_write(writer, tablet));
+
+    // Free tablet.
+    free_tablet(&tablet);
+
+    // Free table schema we used before.
+    free_table_schema(table_schema);
+
+    // Close writer.
+    HANDLE_ERROR(tsfile_writer_close(writer));
+
+    // Close write file after closing writer.
+    free_write_file(&file);
+
+    return 0;
+}
\ No newline at end of file
diff --git a/cpp/examples/cpp_examples/cpp_examples.h 
b/cpp/examples/cpp_examples/cpp_examples.h
index b2e52aad..b0512e9a 100644
--- a/cpp/examples/cpp_examples/cpp_examples.h
+++ b/cpp/examples/cpp_examples/cpp_examples.h
@@ -22,12 +22,23 @@
 #include "common/record.h"
 #include "common/row_record.h"
 #include "common/schema.h"
+#include "common/tablet.h"
+#include "file/write_file.h"
 #include "reader/expression.h"
 #include "reader/filter/filter.h"
 #include "reader/qds_with_timegenerator.h"
 #include "reader/qds_without_timegenerator.h"
 #include "reader/tsfile_reader.h"
+#include "writer/tsfile_table_writer.h"
 #include "writer/tsfile_writer.h"
 
+#define HANDLE_ERROR(err_no)                  \
+    do {                                      \
+        if (err_no != 0) {                    \
+            printf("get err no: %d", err_no); \
+            return err_no;                    \
+        }                                     \
+    } while (0)
+
 int demo_read();
 int demo_write();
diff --git a/cpp/examples/cpp_examples/demo_read.cpp 
b/cpp/examples/cpp_examples/demo_read.cpp
index 8fab33f9..4961fb04 100644
--- a/cpp/examples/cpp_examples/demo_read.cpp
+++ b/cpp/examples/cpp_examples/demo_read.cpp
@@ -20,78 +20,82 @@
 #include <string>
 #include <vector>
 
+#include "../c_examples/c_examples.h"
 #include "cpp_examples.h"
 
-std::string field_to_string(storage::Field *value) {
-    if (value->type_ == common::TEXT) {
-        return std::string(value->value_.sval_);
-    } else {
-        std::stringstream ss;
-        switch (value->type_) {
-            case common::BOOLEAN:
-                ss << (value->value_.bval_ ? "true" : "false");
-                break;
-            case common::INT32:
-                ss << value->value_.ival_;
-                break;
-            case common::INT64:
-                ss << value->value_.lval_;
-                break;
-            case common::FLOAT:
-                ss << value->value_.fval_;
-                break;
-            case common::DOUBLE:
-                ss << value->value_.dval_;
-                break;
-            case common::NULL_TYPE:
-                ss << "NULL";
-                break;
-            default:
-                ASSERT(false);
-                break;
-        }
-        return ss.str();
-    }
-}
+using namespace storage;
 
 int demo_read() {
-    std::cout << "begin to read tsfile from demo_ts.tsfile" << std::endl;
-    std::string device_name = "root.db001.dev001";
-    std::string measurement_name = "m001";
-    storage::Path p1(device_name, measurement_name);
-    std::vector<storage::Path> select_list;
-    select_list.push_back(p1);
-    storage::QueryExpression *query_expr =
-        storage::QueryExpression::create(select_list, nullptr);
 
-    common::init_config_value();
+    int code = 0;
+    libtsfile_init();
+    std::string table_name = "table1";
+
+    // Create tsfile reader and open tsfile with specify path.
     storage::TsFileReader reader;
-    int ret = reader.open("cpp_rw.tsfile");
+    reader.open("test_cpp.tsfile");
+
+    // Query data with tsfile reader.
+    storage::ResultSet* temp_ret = nullptr;
+    std::vector<std::string> columns;
+    columns.emplace_back("id1");
+    columns.emplace_back("id2");
+    columns.emplace_back("s1");
 
-    std::cout << "begin to query expr" << std::endl;
-    ASSERT(ret == 0);
-    storage::ResultSet *qds = nullptr;
-    ret = reader.query(query_expr, qds);
+    // Column vector contains the columns you want to select.
+    HANDLE_ERROR(reader.query(table_name, columns, 0, 100, temp_ret));
 
-    storage::RowRecord *record;
-    std::cout << "begin to dump data from tsfile ---" << std::endl;
-    int row_cout = 0;
-    do {
-        if (qds->next()) {
-            std::cout << "dump QDS :  " << record->get_timestamp() << ",";
-            record = qds->get_row_record();
-            if (record) {
-                int size = record->get_fields()->size();
-                for (int i = 0; i < size; ++i) {
-                    std::cout << field_to_string(record->get_field(i)) << ",";
+    // Get query handler.
+    auto ret = dynamic_cast<storage::TableResultSet*>(temp_ret);
+
+    // Metadata in query handler.
+    auto metadata = ret->get_metadata();
+    int column_num = metadata->get_column_count();
+    for (int i = 0; i < column_num; i++) {
+        std::cout << "column name: " << metadata->get_column_name(i)
+                  << std::endl;
+        std::cout << "column type: " << metadata->get_column_type(i)
+                  << std::endl;
+    }
+
+    // Check and get next data.
+    bool has_next = false;
+    while ((code = ret->next(has_next)) == common::E_OK && has_next) {
+        // Timestamp at column 1 and column index begin from 1.
+        Timestamp timestamp = ret->get_value<Timestamp>(1);
+        for (int i = 0; i < column_num; i++) {
+            if (ret->is_null(i)) {
+                std::cout << "null" << std::endl;
+            } else {
+                switch (metadata->get_column_type(i)) {
+                    case common::BOOLEAN:
+                        std::cout << ret->get_value<bool>(i) << std::endl;
+                        break;
+                    case common::INT32:
+                        std::cout << ret->get_value<int32_t>(i) << std::endl;
+                        break;
+                    case common::INT64:
+                        std::cout << ret->get_value<int64_t>(i) << std::endl;
+                        break;
+                    case common::FLOAT:
+                        std::cout << ret->get_value<float>(i) << std::endl;
+                        break;
+                    case common::DOUBLE:
+                        std::cout << ret->get_value<double>(i) << std::endl;
+                        break;
+                    case common::STRING:
+                        std::cout << ret->get_value<common::String*>(i)
+                                  << std::endl;
+                        break;
+                    default:;
                 }
-                std::cout << std::endl;
-                row_cout++;
             }
-        } else {
-            break;
         }
-    } while (true);
+    }
+
+    // Close query result set.
+    ret->close();
 
-    return (0);
+    // Close reader.
+    reader.close();
 }
diff --git a/cpp/examples/cpp_examples/demo_write.cpp 
b/cpp/examples/cpp_examples/demo_write.cpp
index 17c5cb6b..594309b7 100644
--- a/cpp/examples/cpp_examples/demo_write.cpp
+++ b/cpp/examples/cpp_examples/demo_write.cpp
@@ -17,7 +17,9 @@
  * under the License.
  */
 
+#include <cwrapper/tsfile_cwrapper.h>
 #include <time.h>
+#include <writer/tsfile_table_writer.h>
 
 #include <iostream>
 #include <random>
@@ -27,88 +29,65 @@
 
 using namespace storage;
 
-long getNowTime() { return time(nullptr); }
-
-static std::string generate_random_string(int length) {
-    std::random_device rd;
-    std::mt19937 gen(rd());
-    std::uniform_int_distribution<> dis(0, 61);
-
-    const std::string chars =
-        "0123456789"
-        "abcdefghijklmnopqrstuvwxyz"
-        "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
-    std::string random_string;
-
-    for (int i = 0; i < length; ++i) {
-        random_string += chars[dis(gen)];
-    }
-
-    return random_string;
-}
-
 int demo_write() {
-    TsFileWriter* tsfile_writer_ = new TsFileWriter();
+    int code = 0;
     libtsfile_init();
-    std::string file_name_ = std::string("tsfile_writer_test_") +
-                             generate_random_string(10) +
-                             std::string(".tsfile");
+
+    std::string table_name = "table1";
+
+    // Create a file with specify path to write tsfile.
+    storage::WriteFile file;
     int flags = O_WRONLY | O_CREAT | O_TRUNC;
 #ifdef _WIN32
     flags |= O_BINARY;
 #endif
     mode_t mode = 0666;
-    tsfile_writer_->open(file_name_, flags, mode);
-    remove(file_name_.c_str());
-    const int device_num = 50;
-    const int measurement_num = 50;
-    std::vector<MeasurementSchema> schema_vec[50];
-    for (int i = 0; i < device_num; i++) {
-        std::string device_name = "test_device" + std::to_string(i);
-        schema_vec[i].reserve(measurement_num);
-        for (int j = 0; j < measurement_num; j++) {
-            std::string measure_name = "measurement" + std::to_string(j);
-            schema_vec[i].emplace_back(
-                MeasurementSchema(measure_name, common::TSDataType::INT32,
-                                  common::TSEncoding::PLAIN,
-                                  common::CompressionType::UNCOMPRESSED));
-            tsfile_writer_->register_timeseries(device_name, schema_vec[i][j]);
-        }
-    }
+    file.create("test_cpp.tsfile", flags, mode);
 
-    std::cout << "input tablet size" << std::endl;
-    int tablet_size;
-    std::cin >> tablet_size;
-
-    int max_rows = 100000;
-    int cur_row = 0;
-    long start = getNowTime();
-    for (; cur_row < max_rows;) {
-        if (cur_row + tablet_size > max_rows) {
-            tablet_size = max_rows - cur_row;
-        }
-        for (int i = 0; i < device_num; i++) {
-            std::string device_name = "test_device" + std::to_string(i);
-            Tablet tablet(device_name, &schema_vec[i], tablet_size);
-            tablet.init();
-            for (int row = 0; row < tablet_size; row++) {
-                tablet.set_timestamp(row, 16225600 + cur_row + row);
-            }
-            for (int j = 0; j < measurement_num; j++) {
-                for (int row = 0; row < tablet_size; row++) {
-                    tablet.set_value(row, j, row + cur_row);
-                }
-            }
-            tsfile_writer_->write_tablet(tablet);
-            tsfile_writer_->flush();
-        }
-        cur_row += tablet_size;
-        std::cout << "finish writing " << cur_row << " rows" << std::endl;
+    // Create table schema to describe a table in a tsfile.
+    auto* schema = new storage::TableSchema(
+        table_name,
+        {
+            common::ColumnSchema("id1", common::STRING, common::UNCOMPRESSED,
+                                 common::PLAIN, common::ColumnCategory::TAG),
+            common::ColumnSchema("id2", common::STRING, common::UNCOMPRESSED,
+                                 common::PLAIN, common::ColumnCategory::TAG),
+            common::ColumnSchema("s1", common::INT64, common::UNCOMPRESSED,
+                                 common::PLAIN, common::ColumnCategory::FIELD),
+        });
+
+
+
+    // Create a file with specify path to write tsfile.
+    auto* writer = new TsFileTableWriter(&file, schema);
+
+    // Create tablet to insert data.
+    storage::Tablet tablet = storage::Tablet(
+        table_name, {"id1", "id2", "s1"},
+        {common::STRING, common::STRING, common::INT64},
+        {common::ColumnCategory::TAG, common::ColumnCategory::TAG,
+         common::ColumnCategory::FIELD},
+        10);
+
+
+    for (int row = 0; row < 5; row++) {
+        long timestamp = row;
+        tablet.add_timestamp(row, timestamp);
+        tablet.add_value(row, "id1", "id1_filed_1");
+        tablet.add_value(row, "id2", "id1_filed_2");
+        tablet.add_value(row, "s1", static_cast<int64_t>(row));
     }
 
-    tsfile_writer_->close();
-    long end = getNowTime();
-    printf("interval waitForResults is %ld \n", end - start);
+    // Write tablet data.
+    HANDLE_ERROR(writer->write_table(tablet));
+
+    // Flush data
+    HANDLE_ERROR(writer->flush());
+
+    // Close writer.
+    HANDLE_ERROR(writer->close());
+
+    delete writer;
+
     return 0;
 }
diff --git a/cpp/examples/examples.cc b/cpp/examples/examples.cc
index 845d3f78..edbd819a 100644
--- a/cpp/examples/examples.cc
+++ b/cpp/examples/examples.cc
@@ -22,8 +22,10 @@
 
 int main() {
     // C++ examples
+    // std::cout << "begin write and read tsfile by cpp" << std::endl;
     demo_write();
     demo_read();
+    std::cout << "begin write and read tsfile by c" << std::endl;
     // C examples
     write_tsfile();
     read_tsfile();
diff --git a/cpp/examples/test_cpp.tsfile b/cpp/examples/test_cpp.tsfile
new file mode 100644
index 00000000..e8410db8
Binary files /dev/null and b/cpp/examples/test_cpp.tsfile differ
diff --git a/cpp/src/common/db_common.h b/cpp/src/common/db_common.h
index 572b998b..b06c8fe4 100644
--- a/cpp/src/common/db_common.h
+++ b/cpp/src/common/db_common.h
@@ -134,6 +134,8 @@ FORCE_INLINE CompressionType 
get_default_compression_for_type(TSDataType type) {
         return UNCOMPRESSED;
     } else if (type == common::TEXT) {
         return UNCOMPRESSED;
+    } else if (type == common::STRING) {
+        return UNCOMPRESSED;
     } else {
         ASSERT(false);
     }
diff --git a/cpp/src/common/schema.h b/cpp/src/common/schema.h
index 15822041..3a67b7fa 100644
--- a/cpp/src/common/schema.h
+++ b/cpp/src/common/schema.h
@@ -184,7 +184,7 @@ class TableSchema {
      * in the table.
      */
     TableSchema(const std::string &table_name,
-                const std::vector<common::ColumnSchema> &column_schemas) {
+                const std::vector<common::ColumnSchema> 
&column_schemas):table_name_(table_name) {
         to_lowercase_inplace(table_name_);
         for (const common::ColumnSchema &column_schema : column_schemas) {
             column_schemas_.emplace_back(std::make_shared<MeasurementSchema>(
@@ -280,6 +280,10 @@ class TableSchema {
         return ret;
     }
 
+    int32_t get_columns_num() const {
+        return column_schemas_.size();
+    }
+
     int find_column_index(const std::string &column_name) {
         std::string lower_case_column_name = to_lower(column_name);
         auto it = column_pos_index_.find(lower_case_column_name);
diff --git a/cpp/src/common/tablet.cc b/cpp/src/common/tablet.cc
index 181e9920..54f39df5 100644
--- a/cpp/src/common/tablet.cc
+++ b/cpp/src/common/tablet.cc
@@ -43,33 +43,40 @@ int Tablet::init() {
         }
     }
     ASSERT(schema_map_.size() == schema_count);
-    value_matrix_ = (ValueMatrixEntry *)malloc(sizeof(ValueMatrixEntry) * 
schema_count);
+    value_matrix_ =
+        (ValueMatrixEntry *)malloc(sizeof(ValueMatrixEntry) * schema_count);
     for (size_t c = 0; c < schema_count; ++c) {
         const MeasurementSchema &schema = schema_vec_->at(c);
 
         switch (schema.data_type_) {
             case BOOLEAN:
-                value_matrix_[c].bool_data = (bool 
*)malloc(get_data_type_size(schema.data_type_) * max_row_num_);
+                value_matrix_[c].bool_data = (bool *)malloc(
+                    get_data_type_size(schema.data_type_) * max_row_num_);
                 break;
             case INT32:
-                value_matrix_[c].int32_data = (int32_t 
*)malloc(get_data_type_size(schema.data_type_) * max_row_num_);
+                value_matrix_[c].int32_data = (int32_t *)malloc(
+                    get_data_type_size(schema.data_type_) * max_row_num_);
                 break;
             case INT64:
-                value_matrix_[c].int64_data = (int64_t 
*)malloc(get_data_type_size(schema.data_type_) * max_row_num_);
+                value_matrix_[c].int64_data = (int64_t *)malloc(
+                    get_data_type_size(schema.data_type_) * max_row_num_);
                 break;
             case FLOAT:
-                value_matrix_[c].float_data = (float 
*)malloc(get_data_type_size(schema.data_type_) * max_row_num_);
+                value_matrix_[c].float_data = (float *)malloc(
+                    get_data_type_size(schema.data_type_) * max_row_num_);
                 break;
             case DOUBLE:
-                value_matrix_[c].double_data = (double 
*)malloc(get_data_type_size(schema.data_type_) * max_row_num_);
+                value_matrix_[c].double_data = (double *)malloc(
+                    get_data_type_size(schema.data_type_) * max_row_num_);
                 break;
             case STRING: {
-                value_matrix_[c].string_data = (common::String 
*)malloc(sizeof(String) * max_row_num_);
+                value_matrix_[c].string_data =
+                    (common::String *)malloc(sizeof(String) * max_row_num_);
                 break;
             }
             default:
                 ASSERT(false);
-            return E_INVALID_ARG;
+                return E_INVALID_ARG;
         }
     }
 
@@ -92,24 +99,24 @@ void Tablet::destroy() {
             switch (schema.data_type_) {
                 case INT32:
                     free(value_matrix_[c].int32_data);
-                break;
+                    break;
                 case INT64:
                     free(value_matrix_[c].int64_data);
-                break;
+                    break;
                 case FLOAT:
                     free(value_matrix_[c].float_data);
-                break;
+                    break;
                 case DOUBLE:
                     free(value_matrix_[c].double_data);
-                break;
+                    break;
                 case BOOLEAN:
                     free(value_matrix_[c].bool_data);
-                break;
+                    break;
                 case STRING:
                     free(value_matrix_[c].string_data);
-                break;
+                    break;
                 default:
-                        break;
+                    break;
             }
         }
         free(value_matrix_);
@@ -133,11 +140,12 @@ int Tablet::add_timestamp(uint32_t row_index, int64_t 
timestamp) {
     return E_OK;
 }
 
-void* Tablet::get_value(int row_index, uint32_t schema_index, 
common::TSDataType& data_type) const {
+void *Tablet::get_value(int row_index, uint32_t schema_index,
+                        common::TSDataType &data_type) const {
     if (UNLIKELY(schema_index >= schema_vec_->size())) {
         return nullptr;
     }
-    const MeasurementSchema& schema = schema_vec_->at(schema_index);
+    const MeasurementSchema &schema = schema_vec_->at(schema_index);
 
     ValueMatrixEntry column_values = value_matrix_[schema_index];
     data_type = schema.data_type_;
@@ -146,23 +154,23 @@ void* Tablet::get_value(int row_index, uint32_t 
schema_index, common::TSDataType
     }
     switch (schema.data_type_) {
         case BOOLEAN: {
-            bool* bool_values = column_values.bool_data;
+            bool *bool_values = column_values.bool_data;
             return &bool_values[row_index];
         }
         case INT32: {
-            int32_t* int32_values = column_values.int32_data;
+            int32_t *int32_values = column_values.int32_data;
             return &int32_values[row_index];
         }
         case INT64: {
-            int64_t* int64_values = column_values.int64_data;
+            int64_t *int64_values = column_values.int64_data;
             return &int64_values[row_index];
         }
         case FLOAT: {
-            float* float_values = column_values.float_data;
+            float *float_values = column_values.float_data;
             return &float_values[row_index];
         }
         case DOUBLE: {
-            double* double_values = column_values.double_data;
+            double *double_values = column_values.double_data;
             return &double_values[row_index];
         }
         case STRING: {
@@ -175,8 +183,10 @@ void* Tablet::get_value(int row_index, uint32_t 
schema_index, common::TSDataType
 }
 
 template <>
-void Tablet::process_val(uint32_t row_index, uint32_t schema_index, 
common::String val) {
-    value_matrix_[schema_index].string_data[row_index].dup_from(val, 
page_arena_);
+void Tablet::process_val(uint32_t row_index, uint32_t schema_index,
+                         common::String val) {
+    value_matrix_[schema_index].string_data[row_index].dup_from(val,
+                                                                page_arena_);
     bitmaps_[schema_index].clear(row_index); /* mark as non-null */
 }
 
@@ -184,20 +194,25 @@ template <typename T>
 void Tablet::process_val(uint32_t row_index, uint32_t schema_index, T val) {
     switch (schema_vec_->at(schema_index).data_type_) {
         case common::BOOLEAN:
-            (value_matrix_[schema_index].bool_data)[row_index] = 
static_cast<bool>(val);
-        break;
+            (value_matrix_[schema_index].bool_data)[row_index] =
+                static_cast<bool>(val);
+            break;
         case common::INT32:
-            value_matrix_[schema_index].int32_data[row_index] = 
static_cast<int32_t>(val);
-        break;
+            value_matrix_[schema_index].int32_data[row_index] =
+                static_cast<int32_t>(val);
+            break;
         case common::INT64:
-            value_matrix_[schema_index].int64_data[row_index] = 
static_cast<int64_t>(val);
-        break;
+            value_matrix_[schema_index].int64_data[row_index] =
+                static_cast<int64_t>(val);
+            break;
         case common::FLOAT:
-            value_matrix_[schema_index].float_data[row_index] = 
static_cast<float>(val);
-        break;
+            value_matrix_[schema_index].float_data[row_index] =
+                static_cast<float>(val);
+            break;
         case common::DOUBLE:
-            value_matrix_[schema_index].double_data[row_index] = 
static_cast<double>(val);
-        break;
+            value_matrix_[schema_index].double_data[row_index] =
+                static_cast<double>(val);
+            break;
         default:
             ASSERT(false);
     }
@@ -216,13 +231,13 @@ int Tablet::add_value(uint32_t row_index, uint32_t 
schema_index, T val) {
             if (GetDataTypeFromTemplateType<T>() == common::INT32 &&
                 schema.data_type_ == common::INT64) {
                 process_val(row_index, schema_index, 
static_cast<int64_t>(val));
-                } else if (GetDataTypeFromTemplateType<T>() == common::FLOAT &&
-                           schema.data_type_ == common::DOUBLE) {
-                    process_val(row_index, schema_index, 
static_cast<double>(val));
-                           } else {
-                               ASSERT(false);
-                               return E_TYPE_NOT_MATCH;
-                           }
+            } else if (GetDataTypeFromTemplateType<T>() == common::FLOAT &&
+                       schema.data_type_ == common::DOUBLE) {
+                process_val(row_index, schema_index, static_cast<double>(val));
+            } else {
+                ASSERT(false);
+                return E_TYPE_NOT_MATCH;
+            }
         } else {
             process_val(row_index, schema_index, val);
         }
@@ -231,7 +246,8 @@ int Tablet::add_value(uint32_t row_index, uint32_t 
schema_index, T val) {
 }
 
 template <>
-int Tablet::add_value(uint32_t row_index, uint32_t schema_index, 
common::String val) {
+int Tablet::add_value(uint32_t row_index, uint32_t schema_index,
+                      common::String val) {
     int ret = common::E_OK;
     if (UNLIKELY(schema_index >= schema_vec_->size())) {
         ASSERT(false);
@@ -255,6 +271,13 @@ int Tablet::add_value(uint32_t row_index, const 
std::string &measurement_name,
     return ret;
 }
 
+template<>
+int Tablet::add_value(uint32_t row_index,
+                               const std::string &measurement_name,
+                               const char *val) {
+    add_value(row_index, measurement_name, String(val));
+}
+
 template int Tablet::add_value(uint32_t row_index, uint32_t schema_index,
                                bool val);
 template int Tablet::add_value(uint32_t row_index, uint32_t schema_index,
@@ -279,10 +302,11 @@ template int Tablet::add_value(uint32_t row_index,
 template int Tablet::add_value(uint32_t row_index,
                                const std::string &measurement_name, double 
val);
 template int Tablet::add_value(uint32_t row_index,
-                               const std::string &measurement_name,
-                               String val);
+                               const std::string &measurement_name, String 
val);
+
 
-void Tablet::set_column_categories(const std::vector<ColumnCategory>& 
column_categories) {
+void Tablet::set_column_categories(
+    const std::vector<ColumnCategory> &column_categories) {
     column_categories_ = column_categories;
     id_column_indexes_.clear();
     for (size_t i = 0; i < column_categories_.size(); i++) {
@@ -298,15 +322,15 @@ std::shared_ptr<IDeviceID> Tablet::get_device_id(int i) 
const {
     id_array.push_back(insert_target_name_);
     for (auto id_column_idx : id_column_indexes_) {
         common::TSDataType data_type = INVALID_DATATYPE;
-        void* value_ptr = get_value(i, id_column_idx, data_type);
+        void *value_ptr = get_value(i, id_column_idx, data_type);
         common::String str;
         switch (data_type) {
             case STRING:
-                str = *static_cast<common::String*>(value_ptr);
+                str = *static_cast<common::String *>(value_ptr);
                 id_array.push_back(str.to_std_string());
                 break;
             default:
-                break ;
+                break;
         }
     }
     return std::make_shared<StringArrayDeviceID>(id_array);
diff --git a/cpp/src/cwrapper/errno_define.h b/cpp/src/cwrapper/errno_define.h
new file mode 100644
index 00000000..cf7ad1f4
--- /dev/null
+++ b/cpp/src/cwrapper/errno_define.h
@@ -0,0 +1,77 @@
+/*
+* 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_ERRNO_DEFINRET_H
+#define CWRAPPER_ERRNO_DEFINRET_H
+
+#define RET_OK 0
+#define RET_OOM 1
+#define RET_NOT_EXIST 2
+#define RET_ALREADY_EXIST 3
+#define RET_INVALID_ARG 4
+#define RET_OUT_OF_RANGE 5
+#define RET_PARTIAL_READ 6
+#define RET_NET_BIND_ERR 7
+#define RET_NET_SOCKET_ERR 8
+#define RET_NET_EPOLL_ERR 9
+#define RET_NET_EPOLL_WAIT_ERR 10
+#define RET_NET_RECV_ERR 11
+#define RET_NET_ACCEPT_ERR 12
+#define RET_NET_FCNTL_ERR 13
+#define RET_NET_LISTEN_ERR 14
+#define RET_NET_SEND_ERR 15
+#define RET_PIPRET_ERR 16
+#define RET_THREAD_CREATRET_ERR 17
+#define RET_MUTEX_ERR 18
+#define RET_COND_ERR 19
+#define RET_OVERFLOW 20
+#define RET_NO_MORRET_DATA 21
+#define RET_OUT_OF_ORDER 22
+#define RET_TSBLOCK_TYPRET_NOT_SUPPORTED 23
+#define RET_TSBLOCK_DATA_INCONSISTENCY 24
+#define RET_DDL_UNKNOWN_TYPE 25
+#define RET_TYPRET_NOT_SUPPORTED 26
+#define RET_TYPRET_NOT_MATCH 27
+#define RET_FILRET_OPEN_ERR 28
+#define RET_FILRET_CLOSRET_ERR 29
+#define RET_FILRET_WRITRET_ERR 30
+#define RET_FILRET_READ_ERR 31
+#define RET_FILRET_SYNC_ERR 32
+#define RET_TSFILRET_WRITER_META_ERR 33
+#define RET_FILRET_STAT_ERR 34
+#define RET_TSFILRET_CORRUPTED 35
+#define RET_BUF_NOT_ENOUGH 36
+#define RET_INVALID_PATH 37
+#define RET_NOT_MATCH 38
+#define RET_JSON_INVALID 39
+#define RET_NOT_SUPPORT 40
+#define RET_PARSER_ERR 41
+#define RET_ANALYZRET_ERR 42
+#define RET_INVALID_DATA_POINT 43
+#define RET_DEVICRET_NOT_EXIST 44
+#define RET_MEASUREMENT_NOT_EXIST 45
+#define RET_INVALID_QUERY 46
+#define RET_SDK_QUERY_OPTIMIZRET_ERR 47
+#define RET_COMPRESS_ERR 48
+#define RET_TABLRET_NOT_EXIST 49
+#define RET_COLUMN_NOT_EXIST 50
+#define RET_UNSUPPORTED_ORDER 51
+#define RET_INVALID_NODRET_TYPE 52
+
+#endif  /* CWRAPPER_ERRNO_DEFINRET_H */
\ No newline at end of file
diff --git a/cpp/src/cwrapper/tsfile_cwrapper.cc 
b/cpp/src/cwrapper/tsfile_cwrapper.cc
index c6c52a16..dbd85b52 100644
--- a/cpp/src/cwrapper/tsfile_cwrapper.cc
+++ b/cpp/src/cwrapper/tsfile_cwrapper.cc
@@ -19,32 +19,105 @@
 
 #include "cwrapper/tsfile_cwrapper.h"
 
+#include <file/write_file.h>
 #include <reader/qds_without_timegenerator.h>
+#include <unistd.h>
+#include <writer/tsfile_table_writer.h>
 
 #include "common/tablet.h"
 #include "reader/result_set.h"
 #include "reader/tsfile_reader.h"
 #include "writer/tsfile_writer.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 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)));
+void init_tsfile_config() {
+    if (!is_init) {
+        common::init_config_value();
+        is_init = true;
+    }
+}
+
+WriteFile write_file_new(const char *pathname, ERRNO *err_code) {
+    int ret;
+    init_tsfile_config();
+
+    if (access(pathname, F_OK) == 0) {
+        *err_code = common::E_ALREADY_EXIST;
+        return nullptr;
+    }
+
+    int flags = O_RDWR | O_CREAT | O_TRUNC;
+#ifdef _WIN32
+    flags |= O_BINARY;
+#endif
+    mode_t mode = 0666;
+    storage::WriteFile *file = new storage::WriteFile;
+    ret = file->create(pathname, flags, mode);
+    *err_code = ret;
+    return file;
+}
+
+TsFileWriter tsfile_writer_new(WriteFile file, TableSchema *schema,
+                               ERRNO *err_code) {
+    init_tsfile_config();
+    std::vector<common::ColumnSchema> column_schemas;
+    for (int i = 0; i < schema->column_num; i++) {
+        ColumnSchema cur_schema = schema->column_schemas[i];
+        column_schemas.emplace_back(common::ColumnSchema(
+            cur_schema.column_name,
+            static_cast<common::TSDataType>(cur_schema.data_type),
+            static_cast<common::CompressionType>(cur_schema.compression),
+            static_cast<common::TSEncoding>(cur_schema.encoding),
+            static_cast<common::ColumnCategory>(cur_schema.column_category)));
+    }
+
+    // There is no need to free table_schema.
+    storage::TableSchema *table_schema =
+        new storage::TableSchema(schema->table_name, column_schemas);
+    *err_code = common::E_OK;
+    return new storage::TsFileTableWriter(
+        static_cast<storage::WriteFile *>(file), table_schema);
+}
+
+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;
     }
-    auto *tablet = new storage::Tablet(device_id, &measurement_list,
-                                       &data_type_list, max_rows);
-    return tablet;
+    return reader;
+}
+
+ERRNO tsfile_writer_close(TsFileWriter writer) {
+    auto *w = static_cast<storage::TsFileTableWriter *>(writer);
+    int ret = w->flush();
+    if (ret != common::E_OK) {
+        return ret;
+    }
+    ret = w->close();
+    if (ret != common::E_OK) {
+        return ret;
+    }
+    delete w;
+    return ret;
 }
 
-Tablet tablet_new(const char **column_name_list, TSDataType *data_types,
-                  uint32_t column_num) {
+ERRNO tsfile_reader_close(TsFileReader reader) {
+    auto *ts_reader = static_cast<storage::TsFileReader *>(reader);
+    delete ts_reader;
+    return common::E_OK;
+}
+
+Tablet tablet_new(char **column_name_list, TSDataType *data_types,
+                  uint32_t column_num, uint32_t max_rows) {
     std::vector<std::string> measurement_list;
     std::vector<common::TSDataType> data_type_list;
     for (uint32_t i = 0; i < column_num; i++) {
@@ -52,8 +125,7 @@ Tablet tablet_new(const char **column_name_list, TSDataType 
*data_types,
         data_type_list.push_back(
             static_cast<common::TSDataType>(*(data_types + i)));
     }
-    auto *tablet = new storage::Tablet("", &measurement_list, &data_type_list);
-    return tablet;
+    return new storage::Tablet(measurement_list, data_type_list, max_rows);
 }
 
 uint32_t tablet_get_cur_row_size(Tablet tablet) {
@@ -61,7 +133,7 @@ uint32_t tablet_get_cur_row_size(Tablet tablet) {
 }
 
 ERRNO tablet_add_timestamp(Tablet tablet, uint32_t row_index,
-                           timestamp timestamp) {
+                           Timestamp timestamp) {
     return static_cast<storage::Tablet *>(tablet)->add_timestamp(row_index,
                                                                  timestamp);
 }
@@ -69,57 +141,62 @@ ERRNO tablet_add_timestamp(Tablet tablet, uint32_t 
row_index,
 #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) {                      \
+                                          const 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);
 
+ERRNO tablet_add_value_by_name_string(Tablet tablet, uint32_t row_index,
+                                      const char *column_name,
+                                      const char *value) {
+    return static_cast<storage::Tablet *>(tablet)->add_value(
+        row_index, column_name, common::String(value));
+}
+
 #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) {                      \
+                                           const type value) {                \
         return static_cast<storage::Tablet *>(tablet)->add_value(             \
             row_index, column_index, value);                                  \
     }
 
+ERRNO tablet_add_value_by_index_string(Tablet tablet, uint32_t row_index,
+                                       uint32_t column_index,
+                                       const char *value) {
+    return static_cast<storage::Tablet *>(tablet)->add_value(
+        row_index, column_index, common::String(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;
+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;                                         \
-    }
+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);
@@ -127,184 +204,174 @@ 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;
+                                     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;
 }
-
-ERRNO tsfile_writer_close(TsFileWriter writer) {
-    auto *w = static_cast<storage::TsFileWriter *>(writer);
-    int ret = w->close();
-    delete w;
-    return ret;
+return writer;
 }
 
-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<common::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<common::ColumnCategory>(cur_schema->column_category));
 }
-
-ERRNO tsfile_writer_register_table(TsFileWriter writer, TableSchema *schema) {
-    std::vector<storage::MeasurementSchema *> measurement_schemas;
-    std::vector<common::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<common::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));
+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);
+                                    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;
+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;
-        }
+                                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;
+}
+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;
+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);
+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();
+*/
+ERRNO tsfile_writer_write(TsFileWriter writer, Tablet tablet) {
+    auto *w = static_cast<storage::TsFileTableWriter *>(writer);
+    auto *tbl = static_cast<storage::Tablet *>(tablet);
+    return w->write_table(*tbl);
 }
 
-// Query
+// ERRNO tsfile_writer_flush_data(TsFileWriter writer) {
+//     auto *w = static_cast<storage::TsFileWriter *>(writer);
+//     return w->flush();
+// }
 
-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;
-}
+// Query
 
-ResultSet tsfile_reader_query_device(TsFileReader reader, const char* 
device_name,
-    char** sensor_name, uint32_t sensor_num,
-                                   timestamp start_time, timestamp end_time) {
+ResultSet tsfile_query_table(TsFileReader reader, const char *table_name,
+                             char **columns, uint32_t column_num,
+                             Timestamp start_time, Timestamp end_time,
+                             ERRNO *err_code) {
     auto *r = static_cast<storage::TsFileReader *>(reader);
-    std::vector<std::string> selected_paths;
-    selected_paths.reserve(sensor_num);
-    for (uint32_t i = 0; i < sensor_num; i++) {
-        selected_paths.push_back(std::string(device_name) + "." + 
std::string(sensor_name[i]));
+    storage::ResultSet *table_result_set = nullptr;
+    std::vector<std::string> column_names;
+    for (uint32_t i = 0; i < column_num; i++) {
+        column_names.emplace_back(columns[i]);
+    }
+    *err_code = r->query(table_name, column_names, start_time, end_time,
+                         table_result_set);
+    return table_result_set;
+}
+
+// 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 (uint32_t 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_next(ResultSet result_set, ERRNO *err_code) {
+    auto *r = static_cast<storage::TableResultSet *>(result_set);
+    bool has_next = true;
+    int ret = common::E_OK;
+    ret = r->next(has_next);
+    *err_code = ret;
+    if (ret != common::E_OK) {
+        return false;
     }
-    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);
-    bool has_next = false;
-    r->next(has_next);
     return has_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);               
\
+        auto *r = static_cast<storage::TableResultSet *>(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);
+char *tsfile_result_set_get_value_by_name_string(ResultSet result_set,
+                                                 const char *column_name) {
+    auto *r = static_cast<storage::TableResultSet *>(result_set);
+    common::String *ret = r->get_value<common::String *>(column_name);
+    // Caller should free return's char* 's space.
+    char *dup = (char *)malloc(ret->len_ + 1);
+    if (dup) {
+        memcpy(dup, ret->buf_, ret->len_);
+        dup[ret->len_] = '\0';
+    }
+    return dup;
+}
 
 #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);              \
+        auto *r = static_cast<storage::TableResultSet *>(result_set);         \
         return r->get_value<type>(column_index);                              \
     }
 
@@ -314,22 +381,40 @@ 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);
 
+char *tsfile_result_set_get_value_by_index_string(ResultSet result_set,
+                                                  uint32_t column_index) {
+    auto *r = static_cast<storage::TableResultSet *>(result_set);
+    common::String *ret = r->get_value<common::String *>(column_index);
+    // Caller should free return's char* 's space.
+    char *dup = (char *)malloc(ret->len_ + 1);
+    if (dup) {
+        memcpy(dup, ret->buf_, ret->len_);
+        dup[ret->len_] = '\0';
+    }
+    return dup;
+}
+
 bool tsfile_result_set_is_null_by_name(ResultSet result_set,
                                        const char *column_name) {
-    auto *r = static_cast<storage::ResultSet *>(result_set);
+    auto *r = static_cast<storage::TableResultSet *>(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);
+    auto *r = static_cast<storage::TableResultSet *>(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);
+    auto *r = static_cast<storage::TableResultSet *>(result_set);
+    if (result_set == NULL) {
+        return ResultSetMetaData();
+    }
+
     ResultSetMetaData meta_data;
-    std::shared_ptr<storage::ResultSetMetadata> result_set_metadata = 
r->get_metadata();
+    std::shared_ptr<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 *)));
@@ -344,73 +429,127 @@ ResultSetMetaData 
tsfile_result_set_get_metadata(ResultSet result_set) {
     return meta_data;
 }
 
-char *tsfile_result_set_meta_get_column_name(ResultSetMetaData result_set,
-                                             uint32_t column_index) {
+char *tsfile_result_set_metadata_get_column_name(ResultSetMetaData result_set,
+                                                 uint32_t column_index) {
+    if (column_index >= result_set.column_num) {
+        return nullptr;
+    }
     return result_set.column_names[column_index];
 }
 
-TSDataType tsfile_result_set_meta_get_data_type(ResultSetMetaData result_set,
-                                                uint32_t column_index) {
+TSDataType tsfile_result_set_metadata_get_data_type(
+    ResultSetMetaData result_set, uint32_t column_index) {
+    if (column_index >= result_set.column_num) {
+        return TS_DATATYPE_INVALID;
+    }
     return result_set.data_types[column_index];
 }
 
-int tsfile_result_set_meta_get_column_num(ResultSetMetaData result_set) {
+int tsfile_result_set_metadata_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 (int 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_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 (int 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_);
+    auto table_shcema = r->get_table_schema(table_name);
+    TableSchema ret_schema;
+    ret_schema.table_name = strdup(table_shcema->get_table_name().c_str());
+    int column_num = table_shcema->get_columns_num();
+    ret_schema.column_num = column_num;
+    ret_schema.column_schemas = 
static_cast<ColumnSchema*>(malloc(sizeof(ColumnSchema) * column_num));
+    for (int i = 0; i < column_num; i++) {
+        auto column_schema = table_shcema->get_measurement_schemas()[i];
+        ret_schema.column_schemas[i].column_name = 
strdup(column_schema->measurement_name_.c_str());
+        ret_schema.column_schemas[i].data_type = 
static_cast<TSDataType>(column_schema->data_type_);
+        ret_schema.column_schemas[i].compression = 
static_cast<CompressionType>(column_schema->compression_type_);
+        ret_schema.column_schemas[i].encoding = 
static_cast<TSEncoding>(column_schema->encoding_);
+        ret_schema.column_schemas[i].column_category = 
static_cast<ColumnCategory>(table_shcema->get_column_categories()[i]);
     }
-    return schema;
+    return ret_schema;
 }
 
 TableSchema *tsfile_reader_get_all_table_schemas(TsFileReader reader,
-                                                 uint32_t *num) {
-    // TODO: Implement get all table schemas.
-    return nullptr;
+                                                 uint32_t *size) {
+    auto *r = static_cast<storage::TsFileReader *>(reader);
+    auto table_schemas = r->get_all_table_schemas();
+    size_t table_num = table_schemas.size();
+    TableSchema *ret =
+        static_cast<TableSchema *>(malloc(sizeof(TableSchema) * table_num));
+    for (size_t i = 0; i < table_schemas.size(); i++) {
+        ret[i].table_name = strdup(table_schemas[i]->get_table_name().c_str());
+        int column_num = table_schemas[i]->get_columns_num();
+        ret[i].column_num = column_num;
+        ret[i].column_schemas = static_cast<ColumnSchema *>(
+            malloc(column_num * sizeof(ColumnSchema)));
+        auto column_schemas = table_schemas[i]->get_measurement_schemas();
+        for (int j = 0; j < column_num; j++) {
+            ret[i].column_schemas[j].column_name =
+                strdup(column_schemas[j]->measurement_name_.c_str());
+            ret[i].column_schemas[j].data_type =
+                static_cast<TSDataType>(column_schemas[j]->data_type_);
+            ret[i].column_schemas[j].encoding =
+                static_cast<TSEncoding>(column_schemas[j]->encoding_);
+            ret[i].column_schemas[j].compression = 
static_cast<CompressionType>(
+                column_schemas[j]->compression_type_);
+            ret[i].column_schemas[j].column_category =
+                static_cast<ColumnCategory>(
+                    table_schemas[i]->get_column_categories()[j]);
+        }
+    }
+    *size = table_num;
+    return ret;
 }
 
 // delete pointer
-void free_tsfile_ts_record(TsRecord* record) {
+void free_tsfile_ts_record(TsRecord *record) {
     if (*record != nullptr) {
         delete static_cast<storage::TsRecord *>(*record);
     }
     *record = nullptr;
 }
 
-void free_tablet(Tablet* tablet) {
+void free_tablet(Tablet *tablet) {
     if (*tablet != nullptr) {
         delete static_cast<storage::Tablet *>(*tablet);
     }
     *tablet = nullptr;
 }
 
-void free_tsfile_result_set(ResultSet* result_set) {
+void free_tsfile_result_set(ResultSet *result_set) {
     if (*result_set != nullptr) {
         delete static_cast<storage::ResultSet *>(*result_set);
     }
@@ -442,4 +581,14 @@ void free_table_schema(TableSchema schema) {
     }
     free(schema.column_schemas);
 }
-void free_column_schema(ColumnSchema schema) { free(schema.column_name); }
\ No newline at end of file
+void free_column_schema(ColumnSchema schema) { free(schema.column_name); }
+
+void free_write_file(WriteFile *write_file) {
+    auto f = static_cast<storage::WriteFile *>(*write_file);
+    delete f;
+    *write_file = nullptr;
+}
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/cpp/src/cwrapper/tsfile_cwrapper.h 
b/cpp/src/cwrapper/tsfile_cwrapper.h
index 46cdabbc..af1c9c29 100644
--- a/cpp/src/cwrapper/tsfile_cwrapper.h
+++ b/cpp/src/cwrapper/tsfile_cwrapper.h
@@ -19,9 +19,13 @@
 
 #ifndef SRC_CWRAPPER_TSFILE_CWRAPPER_H_
 #define SRC_CWRAPPER_TSFILE_CWRAPPER_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-#include <cstdint>
-#include <iostream>
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/stat.h>
 
 typedef enum {
     TS_DATATYPE_BOOLEAN = 0,
@@ -31,6 +35,7 @@ typedef enum {
     TS_DATATYPE_DOUBLE = 4,
     TS_DATATYPE_TEXT = 5,
     TS_DATATYPE_VECTOR = 6,
+    TS_DATATYPE_STRING = 11,
     TS_DATATYPE_NULL_TYPE = 254,
     TS_DATATYPE_INVALID = 255
 } TSDataType;
@@ -67,6 +72,8 @@ typedef enum column_category { TAG = 0, FIELD = 1 } 
ColumnCategory;
 typedef struct column_schema {
     char* column_name;
     TSDataType data_type;
+    CompressionType compression;
+    TSEncoding encoding;
     ColumnCategory column_category;
 } ColumnSchema;
 
@@ -99,6 +106,8 @@ typedef struct tsfile_conf {
     int mem_threshold_kb;
 } TsFileConf;
 
+typedef void* WriteFile;
+
 typedef void* TsFileReader;
 typedef void* TsFileWriter;
 
@@ -109,38 +118,148 @@ typedef void* TsRecord;
 typedef void* ResultSet;
 
 typedef int32_t ERRNO;
-typedef int64_t timestamp;
+typedef int64_t Timestamp;
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+/*--------------------------TsFile Reader and Writer------------------------ */
+
+/**
+ * @brief Creates a file for writing.
+ *
+ * @param pathname     Target file path to create.
+ * @param err_code     [out] E_OK(0), or check error code in errno_define.h.
+ *
+ * @return WriteFile Valid handle on success.
+ *
+ * @note Call free_write_file() to release resources.
+ * @note Before call free_write_file(), make sure TsFileWriter has been closed.
+ */
+
+WriteFile write_file_new(const char* pathname, ERRNO* err_code);
+
+/**
+ * @brief Creates a TsFileWriter for writing a TsFile.
+ *
+ * @param file     Target file where the table data will be written.
+ * @param schema       Table schema definition.
+ *                     - Ownership: Should be free it by Caller.
+ * @param err_code     [out] E_OK(0), or check error code in errno_define.h.
+ *
+ * @return TsFileWriter Valid handle on success, NULL on failure.
+ *
+ * @note Call tsfile_writer_close() to release resources.
+ */
+TsFileWriter tsfile_writer_new(WriteFile file, TableSchema* schema,
+                               ERRNO* err_code);
+
+/**
+ * @brief Creates a TsFileReader for reading a TsFile.
+ *
+ * @param pathname     Source TsFiles path. Must be a valid path.
+ * @param err_code     E_OK(0), or check error code in errno_define.h.
+ * @return TsFileReader Valid handle on success, NULL on failure.
+ *
+ * @note Call tsfile_reader_close() to release resources.
+ */
+
+TsFileReader tsfile_reader_new(const char* pathname, ERRNO* err_code);
+
+/**
+ * @brief Releases resources associated with a TsFileWriter.
+ *
+ * @param writer [in] Writer handle obtained from tsfile_writer_new().
+ *                    After call: handle becomes invalid and must not be 
reused.
+ * @return ERRNO - E_OK(0) on success, check error code in errno_define.h.
+ */
+ERRNO tsfile_writer_close(TsFileWriter writer);
+
+/**
+ * @brief Releases resources associated with a TsFileReader.
+ *
+ * @param reader [in] Reader handle obtained from tsfile_reader_new().
+ *                    After call:
+ *                      Handle becomes invalid and must not be reused.
+ *                      Result_set obtained by this handle becomes invalid.
+ * @return ERRNO - E_OK(0) on success, or check error code in errno_define.h.
+ */
+ERRNO tsfile_reader_close(TsFileReader reader);
 
 /*--------------------------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);
+/**
+ * @brief Creates a Tablet for batch data.
+ *
+ * @param column_name_list [in] Column names array. Size=column_num.
+ * @param data_types [in] Data types array. Size=column_num.
+ * @param column_num [in] Number of columns. Must be ≥1.
+ * @param max_rows [in] Pre-allocated row capacity. Must be ≥1.
+ * @return Tablet Valid handle.
+ * @note Call free_tablet() to release resources.
+ */
+Tablet tablet_new(char** column_name_list, TSDataType* data_types,
+                  uint32_t column_num, uint32_t max_rows);
 
+/**
+ * @brief Gets current row count in the Tablet.
+ *
+ * @param tablet [in] Valid Tablet handle.
+ * @return uint32_t Row count (0 to max_rows-1).
+ */
 uint32_t tablet_get_cur_row_size(Tablet tablet);
 
+/**
+ * @brief Assigns timestamp to a row in the Tablet.
+ *
+ * @param tablet [in] Valid Tablet handle.
+ * @param row_index [in] Target row (0 ≤ index < max_rows).
+ * @param timestamp [in] Timestamp with int64_t type.
+ * @return ERRNO - E_OK(0)/E_OUT_OF_RANGE(5) or check errno_define.h.
+ */
 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);
+                           Timestamp timestamp);
 
+/**
+ * @brief Adds a value to a Tablet row by column name (generic types).
+ *
+ * @param tablet [in] Valid Tablet handle.
+ * @param row_index [in] Target row (0 ≤ index < max_rows).
+ * @param column_name [in] Existing column name from Tablet schema.
+ * @param value [in] Value to add. Type must match column schema.
+ * @return ERRNO - E_OK(0) or check errno_define.h.
+ *
+ * @note Generated for types: int32_t, int64_t, float, double, bool
+ */
+#define TABLET_ADD_VALUE_BY_NAME(type)                                       \
+    ERRNO tablet_add_value_by_name_##type(Tablet tablet, uint32_t row_index, \
+                                          const char* column_name,           \
+                                          const 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);
 
+/**
+ * @brief Adds a string value to a Tablet row by column name.
+ *
+ * @param value [in] Null-terminated string. Ownership remains with caller.
+ * @return ERRNO.
+ */
+ERRNO tablet_add_value_by_name_string(Tablet tablet, uint32_t row_index,
+                                      const char* column_name,
+                                      const char* value);
+
+/**
+ * @brief Adds a value to a Tablet row by column index (generic types).
+ *
+ * @param column_index [in] Column position (0 ≤ index < column_num).
+ * @return ERRNO - E_OK(0) or check errno_define.h.
+ *
+ * @note Generated for types: int32_t, int64_t, float, double, 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);
+                                           uint32_t column_index,             \
+                                           const type value);
 
 TABLE_ADD_VALUE_BY_INDEX(int32_t);
 TABLE_ADD_VALUE_BY_INDEX(int64_t);
@@ -148,55 +267,98 @@ 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);
+/**
+ * @brief Adds a string value to a Tablet row by column index.
+ *
+ * @param value [in] Null-terminated string. Copied internally.
+ */
+ERRNO tablet_add_value_by_index_string(Tablet tablet, uint32_t row_index,
+                                       uint32_t column_index,
+                                       const char* value);
 
 /*--------------------------TsRecord API------------------------ */
-TsRecord ts_record_new(const char* device_id, timestamp timestamp,
-                       int timeseries_num);
+/*
+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);
+   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);
+                                       const char* device_id,
+                                       const TimeseriesSchema* schema);
 ERRNO tsfile_writer_register_device(TsFileWriter writer,
-                                    const DeviceSchema* device_schema);
+                                   const DeviceSchema* device_schema);
+                                   */
+
+/*-------------------TsFile Writer write data------------------ */
+
+/**
+ * @brief Writes data from a Tablet to the TsFile.
+ *
+ * @param writer [in] Valid TsFileWriter handle. Must be initialized.
+ * @param tablet [in] Tablet containing data. Should be freed after successful
+ * write.
+ * @return ERRNO - E_OK(0), or check error code in errno_define.h.
+ *
+ */
 
-/*-------------------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);
+ERRNO tsfile_writer_write(TsFileWriter writer, Tablet tablet);
+// 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);
 
+/**
+ * @brief Queries time series data from a specific table within time range.
+ *
+ * @param reader [in] Valid TsFileReader handle from tsfile_reader_new().
+ * @param table_name [in] Target table name. Must exist in the TS file.
+ * @param columns [in] Array of column names to fetch.
+ * @param column_num [in] Number of columns in array.
+ * @param start_time [in] Start timestamp.
+ * @param end_time [in] End timestamp. Must ≥ start_time.
+ * @return ResultSet Query results handle. Must be freed with
+ * free_tsfile_result_set().
+ */
+ResultSet tsfile_query_table(TsFileReader reader, const char* table_name,
+                             char** columns, uint32_t column_num,
+                             Timestamp start_time, Timestamp end_time,
+                             ERRNO* err_code);
+// ResultSet tsfile_reader_query_device(TsFileReader reader,
+//                                      const char* device_name,
+//                                      char** sensor_name, uint32_t 
sensor_num,
+//                                      Timestamp start_time, Timestamp
+//                                      end_time);
+
+/**
+ * @brief Check and fetch the next row in the ResultSet.
+ *
+ * @param result_set [in] Valid ResultSet handle.
+ * @return bool - true: Row available, false: End of data or error.
+ */
+bool tsfile_result_set_next(ResultSet result_set, ERRNO* error_code);
+
+/**
+ * @brief Gets value from current row by column name (generic types).
+ *
+ * @param result_set [in] Valid ResultSet with active row (after next()=true).
+ * @param column_name [in] Existing column name in result schema.
+ * @return type-value, return type-specific value.
+ * @note Generated for: bool, int32_t, int64_t, float, double
+ */
 #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)
@@ -206,6 +368,24 @@ 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);
 
+/**
+ * @brief Gets string value from current row by column name.
+ *
+ * @return char* - String pointer. Caller must free this ptr after usage.
+ */
+char* tsfile_result_set_get_value_by_name_string(ResultSet result_set,
+                                                 const char* column_name);
+
+/**
+ * @brief Gets value from current row by column_index[0 <= column_index <<
+ * column_num] (generic types).
+ *
+ * @param result_set [in] Valid ResultSet with active row (after next()=true).
+ * @param column_name [in] Existing column index in result schema.
+ * @return type-value, return type-specific value.
+ * @note Generated for: bool, int32_t, int64_t, float, 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);
@@ -216,27 +396,90 @@ TSFILE_RESULT_SET_GET_VALUE_BY_INDEX(float);
 TSFILE_RESULT_SET_GET_VALUE_BY_INDEX(double);
 TSFILE_RESULT_SET_GET_VALUE_BY_INDEX(bool);
 
+/**
+ * @brief Gets string value from current row by column index.
+ *
+ * @return char* - String pointer. Caller must free this ptr after usage.
+ */
+char* tsfile_result_set_get_value_by_index_string(ResultSet result_set,
+                                                  uint32_t column_index);
+
+/**
+ * @brief Checks if the current row's column value is NULL by column name.
+ *
+ * @param result_set [in] Valid ResultSet with active row (after next()=true).
+ * @param column_name [in] Existing column name in result schema.
+ * @return bool - true: Value is NULL or column not found, false: Valid value.
+ */
 bool tsfile_result_set_is_null_by_name(ResultSet result_set,
                                        const char* column_name);
 
+/**
+ * @brief Checks if the current row's column value is NULL by column index.
+ *
+ * @param column_index [in] Column position (0 ≤ index < result_column_count).
+ * @return bool - true: Value is NULL or index out of range, false: Valid 
value.
+ */
 bool tsfile_result_set_is_null_by_index(ResultSet result_set,
                                         uint32_t column_index);
 
+/*-------------------TsFile reader query metadata------------------ */
+
+/**
+ * @brief Retrieves metadata describing the ResultSet's schema.
+ *
+ * @param result_set [in] Valid ResultSet handle.
+ * @return ResultSetMetaData Metadata handle. Caller should free the
+ * ResultSetMataData after usage.
+ * @note Before calling this func, check if result_set is NULL, which means
+ * the query may be not correct.
+ */
 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);
+
+/**
+ * @brief Gets column name by index from metadata.
+ *
+ * @param column_index [in] Column position (0 ≤ index < column_num).
+ * @return const char* Read-only string. NULL if index invalid.
+ */
+char* tsfile_result_set_metadata_get_column_name(ResultSetMetaData result_set,
+                                                 uint32_t column_index);
+
+/**
+ * @brief Gets column data type by index from metadata.
+ *
+ * @return TSDataType Returns TS_DATATYPE_INVALID(255) if index invalid.
+ */
+TSDataType tsfile_result_set_metadata_get_data_type(
+    ResultSetMetaData result_set, uint32_t column_index);
+
+/**
+ * @brief Gets total number of columns in the result schema.
+ *
+ * @return column num in result set metadata.
+ */
+int tsfile_result_set_metadata_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);
+// DeviceSchema tsfile_reader_get_device_schema(TsFileReader reader,
+//                                              const char* device_id);
 
+/**
+ * @brief Gets specific table's schema in the tsfile.
+ *
+ * @return TableSchema, contains table and column info.
+ * @note Caller should call free_table_schema to free the tableschema.
+ */
+TableSchema tsfile_reader_get_table_schema(TsFileReader reader,
+                                       const char* table_name);
+/**
+ * @brief Gets all table schema in the tsfile.
+ *
+ * @return TableSchema, contains table and column info.
+ * @note Caller should call free_table_schema and free to free the ptr.
+ */
 TableSchema* tsfile_reader_get_all_table_schemas(TsFileReader reader,
-                                                 uint32_t* schema_num);
+                                                 uint32_t* size);
 
 // Close and free resource.
 void free_tsfile_ts_record(TsRecord* record);
@@ -247,6 +490,7 @@ void free_device_schema(DeviceSchema schema);
 void free_timeseries_schema(TimeseriesSchema schema);
 void free_table_schema(TableSchema schema);
 void free_column_schema(ColumnSchema schema);
+void free_write_file(WriteFile* write_file);
 
 #ifdef __cplusplus
 }
diff --git a/cpp/src/reader/block/single_device_tsblock_reader.cc 
b/cpp/src/reader/block/single_device_tsblock_reader.cc
index ecda84e2..7c39a416 100644
--- a/cpp/src/reader/block/single_device_tsblock_reader.cc
+++ b/cpp/src/reader/block/single_device_tsblock_reader.cc
@@ -191,8 +191,9 @@ int SingleDeviceTsBlockReader::fill_ids() {
             common::String device_id(
                 device_query_task_->get_device_id()->get_segments().at(
                     id_column_context.pos_in_device_id_));
-            if (RET_FAIL(col_appenders_[pos + 1]->fill((char*)&device_id, 
sizeof(device_id),
-                                      current_block_->get_row_count()))) {
+            if (RET_FAIL(col_appenders_[pos + 1]->fill(
+                    (char*)&device_id, sizeof(device_id),
+                    current_block_->get_row_count()))) {
                 return ret;
             }
         }
@@ -234,7 +235,7 @@ void SingleDeviceTsBlockReader::construct_column_context(
     const ITimeseriesIndex* time_series_index, Filter* time_filter) {
     if (time_series_index == nullptr ||
         (time_series_index->get_data_type() != common::TSDataType::VECTOR &&
-        time_series_index->get_chunk_meta_list()->empty())) {
+         time_series_index->get_chunk_meta_list()->empty())) {
     } else if (time_series_index->get_data_type() == common::VECTOR) {
         const AlignedTimeseriesIndex* aligned_time_series_index =
             dynamic_cast<const AlignedTimeseriesIndex*>(time_series_index);
diff --git a/cpp/src/reader/table_result_set.cc 
b/cpp/src/reader/table_result_set.cc
index b0db3f82..6cf6d7e3 100644
--- a/cpp/src/reader/table_result_set.cc
+++ b/cpp/src/reader/table_result_set.cc
@@ -54,6 +54,7 @@ int TableResultSet::next(bool &has_next) {
     if (row_iterator_ == nullptr || !row_iterator_->has_next()) {
         has_next = false;
     }
+
     if (has_next && IS_SUCC(ret)) {
         uint32_t len = 0;
         bool null = false;
diff --git a/cpp/src/utils/db_utils.h b/cpp/src/utils/db_utils.h
index 8f5f5620..508d3a29 100644
--- a/cpp/src/utils/db_utils.h
+++ b/cpp/src/utils/db_utils.h
@@ -281,6 +281,14 @@ struct ColumnSchema {
           encoding_(encoding),
           column_category_(column_category) {}
 
+    ColumnSchema(std::string column_name, TSDataType data_type,
+             ColumnCategory column_category = ColumnCategory::FIELD)
+    : column_name_(std::move(column_name)),
+      data_type_(data_type),
+      compression_(get_default_compression_for_type(data_type)),
+      encoding_(get_default_encoding_for_type(data_type)),
+      column_category_(column_category) {}
+
     const std::string &get_column_name() const { return column_name_; }
     const TSDataType &get_data_type() const { return data_type_; }
     const ColumnCategory &get_column_category() const {
diff --git a/cpp/src/writer/tsfile_table_writer.h 
b/cpp/src/writer/tsfile_table_writer.h
index 4abe28ca..15b81485 100644
--- a/cpp/src/writer/tsfile_table_writer.h
+++ b/cpp/src/writer/tsfile_table_writer.h
@@ -60,6 +60,7 @@ class TsFileTableWriter {
         tsfile_writer_->register_table(table_schema_ptr);
         exclusive_table_name_ = table_schema->get_table_name();
     }
+
     ~TsFileTableWriter();
     /**
      * Registers a table schema with the writer.
diff --git a/cpp/src/writer/tsfile_writer.cc b/cpp/src/writer/tsfile_writer.cc
index 4cf81339..8f88ec03 100644
--- a/cpp/src/writer/tsfile_writer.cc
+++ b/cpp/src/writer/tsfile_writer.cc
@@ -281,6 +281,29 @@ struct MeasurementNamesFromTablet {
     }
 };
 
+int TsFileWriter::do_check_and_prepare_tablet(Tablet &tablet) {
+    if (tablet.column_categories_.empty()) {
+        auto &schema_map = io_writer_->get_schema()->table_schema_map_;
+        auto table_schema_it = schema_map.find(tablet.get_table_name());
+        auto table_schema = table_schema_it->second;
+        uint32_t column_cnt = tablet.get_column_count();
+        for (uint32_t i = 0; i < column_cnt; i++) {
+            auto &col_name = tablet.get_column_name(i);
+            int col_index = table_schema->find_column_index(col_name);
+            if (col_index == -1) {
+                return E_COLUMN_NOT_EXIST;
+            }
+            const common::ColumnCategory column_category =
+                table_schema->get_column_categories()[col_index];
+            tablet.column_categories_.emplace_back(column_category);
+            if (column_category == ColumnCategory::TAG) {
+                tablet.id_column_indexes_.push_back(i);
+            }
+        }
+    }
+    return common::E_OK;
+}
+
 template <typename MeasurementNamesGetter>
 int TsFileWriter::do_check_schema(std::shared_ptr<IDeviceID> device_id,
                                   MeasurementNamesGetter &measurement_names,
@@ -387,8 +410,7 @@ int TsFileWriter::do_check_schema_aligned(
 }
 
 int TsFileWriter::do_check_schema_table(
-    std::shared_ptr<IDeviceID> device_id,
-    Tablet &tablet,
+    std::shared_ptr<IDeviceID> device_id, Tablet &tablet,
     storage::TimeChunkWriter *&time_chunk_writer,
     common::SimpleVector<storage::ValueChunkWriter *> &value_chunk_writers) {
     int ret = E_OK;
@@ -405,7 +427,6 @@ int TsFileWriter::do_check_schema_table(
 
     if (UNLIKELY(dev_it == schemas_.end()) ||
         IS_NULL(device_schema = dev_it->second)) {
-
         device_schema = new MeasurementSchemaGroup;
         device_schema->is_aligned_ = true;
         device_schema->time_chunk_writer_ = new TimeChunkWriter();
@@ -413,34 +434,29 @@ int TsFileWriter::do_check_schema_table(
             "", g_config_value_.time_encoding_type_,
             g_config_value_.time_compress_type_);
 
-        for (uint32_t i = 0; i < 
table_schema->get_measurement_schemas().size(); ++i) {
-            if (table_schema->get_column_categories().at(i) == 
common::ColumnCategory::FIELD) {
-                auto table_column_schema = 
table_schema->get_measurement_schemas().at(i);
-                auto device_column_schema = new 
MeasurementSchema(table_column_schema->measurement_name_,
-                        table_column_schema->data_type_, 
table_column_schema->encoding_,
-                        table_column_schema->compression_type_);
+        for (uint32_t i = 0; i < 
table_schema->get_measurement_schemas().size();
+             ++i) {
+            if (table_schema->get_column_categories().at(i) ==
+                common::ColumnCategory::FIELD) {
+                auto table_column_schema =
+                    table_schema->get_measurement_schemas().at(i);
+                auto device_column_schema = new MeasurementSchema(
+                    table_column_schema->measurement_name_,
+                    table_column_schema->data_type_,
+                    table_column_schema->encoding_,
+                    table_column_schema->compression_type_);
                 if (!table_column_schema->props_.empty()) {
                     device_column_schema->props_ = table_column_schema->props_;
                 }
-                
device_schema->measurement_schema_map_[device_column_schema->measurement_name_] 
= device_column_schema;
+                device_schema->measurement_schema_map_
+                    [device_column_schema->measurement_name_] =
+                    device_column_schema;
             }
         }
         schemas_[device_id] = device_schema;
     }
 
     uint32_t column_cnt = tablet.get_column_count();
-    if (tablet.column_categories_.empty()) {
-        for (uint32_t i = 0; i < column_cnt; i++) {
-            auto& col_name = tablet.get_column_name(i);
-            int col_index = table_schema->find_column_index(col_name);
-            if (col_index == -1) {
-                return E_COLUMN_NOT_EXIST;
-            }
-            const common::ColumnCategory column_category = 
table_schema->get_column_categories()[col_index];
-            tablet.column_categories_.emplace_back(column_category);
-        }
-    }
-
     time_chunk_writer = device_schema->time_chunk_writer_;
     MeasurementSchemaMap &msm = device_schema->measurement_schema_map_;
 
@@ -495,19 +511,23 @@ int64_t TsFileWriter::calculate_mem_size_for_all_group() {
             if (!chunk_group->is_aligned_) {
                 ChunkWriter *&chunk_writer = m_schema->chunk_writer_;
                 if (chunk_writer != nullptr) {
-                    mem_total_size += 
chunk_writer->estimate_max_series_mem_size();
+                    mem_total_size +=
+                        chunk_writer->estimate_max_series_mem_size();
                 }
             } else {
                 ValueChunkWriter *&chunk_writer = 
m_schema->value_chunk_writer_;
                 if (chunk_writer != nullptr) {
-                    mem_total_size += 
chunk_writer->estimate_max_series_mem_size();
+                    mem_total_size +=
+                        chunk_writer->estimate_max_series_mem_size();
                 }
             }
         }
         if (chunk_group->is_aligned_) {
-            TimeChunkWriter *&time_chunk_writer = 
chunk_group->time_chunk_writer_;
+            TimeChunkWriter *&time_chunk_writer =
+                chunk_group->time_chunk_writer_;
             if (time_chunk_writer != nullptr) {
-                mem_total_size += 
time_chunk_writer->estimate_max_series_mem_size();
+                mem_total_size +=
+                    time_chunk_writer->estimate_max_series_mem_size();
             }
         }
     }
@@ -685,9 +705,13 @@ int TsFileWriter::write_table(Tablet &tablet) {
     if (io_writer_->get_schema()->table_schema_map_.find(
             tablet.insert_target_name_) ==
         io_writer_->get_schema()->table_schema_map_.end()) {
-        ret = E_DEVICE_NOT_EXIST;
+        ret = E_TABLE_NOT_EXIST;
+        return ret;
+    }
+    if (RET_FAIL(do_check_and_prepare_tablet(tablet))) {
         return ret;
     }
+
     auto device_id_end_index_pairs = split_tablet_by_device(tablet);
     int start_idx = 0;
     for (auto &device_id_end_index_pair : device_id_end_index_pairs) {
@@ -696,18 +720,20 @@ int TsFileWriter::write_table(Tablet &tablet) {
         if (table_aligned_) {
             SimpleVector<ValueChunkWriter *> value_chunk_writers;
             TimeChunkWriter *time_chunk_writer = nullptr;
-            if (RET_FAIL(do_check_schema_table(
-                    device_id,
-                    tablet, time_chunk_writer, value_chunk_writers))) {
+            if (RET_FAIL(do_check_schema_table(device_id, tablet,
+                                               time_chunk_writer,
+                                               value_chunk_writers))) {
                 return ret;
-                    }
+            }
             for (uint32_t i = 0; i < tablet.get_cur_row_size(); i++) {
                 time_chunk_writer->write(tablet.timestamps_[i]);
             }
             uint32_t field_col_count = 0;
             for (uint32_t i = 0; i < tablet.get_column_count(); ++i) {
-                if (tablet.column_categories_[i] == 
common::ColumnCategory::FIELD) {
-                    ValueChunkWriter *value_chunk_writer = 
value_chunk_writers[field_col_count];
+                if (tablet.column_categories_[i] ==
+                    common::ColumnCategory::FIELD) {
+                    ValueChunkWriter *value_chunk_writer =
+                        value_chunk_writers[field_col_count];
                     if (IS_NULL(value_chunk_writer)) {
                         continue;
                     }
@@ -719,9 +745,9 @@ int TsFileWriter::write_table(Tablet &tablet) {
             MeasurementNamesFromTablet mnames_getter(tablet);
             SimpleVector<ChunkWriter *> chunk_writers;
             if (RET_FAIL(
-                do_check_schema(device_id, mnames_getter, chunk_writers))) {
+                    do_check_schema(device_id, mnames_getter, chunk_writers))) 
{
                 return ret;
-                }
+            }
             ASSERT(chunk_writers.size() == tablet.get_column_count());
             for (uint32_t c = 0; c < chunk_writers.size(); c++) {
                 ChunkWriter *chunk_writer = chunk_writers[c];
@@ -795,8 +821,9 @@ int TsFileWriter::write_column(ChunkWriter *chunk_writer, 
const Tablet &tablet,
     return ret;
 }
 
-int TsFileWriter::time_write_column(TimeChunkWriter *time_chunk_writer, const 
Tablet &tablet, uint32_t start_idx,
-                               uint32_t end_idx) {
+int TsFileWriter::time_write_column(TimeChunkWriter *time_chunk_writer,
+                                    const Tablet &tablet, uint32_t start_idx,
+                                    uint32_t end_idx) {
     int64_t *timestamps = tablet.timestamps_;
     int ret = E_OK;
     if (IS_NULL(time_chunk_writer) || IS_NULL(timestamps)) {
@@ -811,7 +838,8 @@ int TsFileWriter::time_write_column(TimeChunkWriter 
*time_chunk_writer, const Ta
 }
 
 int TsFileWriter::value_write_column(ValueChunkWriter *value_chunk_writer,
-                                     const Tablet &tablet, int col_idx, 
uint32_t start_idx, uint32_t end_idx) {
+                                     const Tablet &tablet, int col_idx,
+                                     uint32_t start_idx, uint32_t end_idx) {
     int ret = E_OK;
 
     TSDataType data_type = tablet.schema_vec_->at(col_idx).data_type_;
diff --git a/cpp/src/writer/tsfile_writer.h b/cpp/src/writer/tsfile_writer.h
index 67a74c30..3b155dba 100644
--- a/cpp/src/writer/tsfile_writer.h
+++ b/cpp/src/writer/tsfile_writer.h
@@ -110,34 +110,35 @@ class TsFileWriter {
 
     int write_typed_column(storage::ChunkWriter *chunk_writer,
                            int64_t *timestamps, bool *col_values,
-                           common::BitMap &col_notnull_bitmap, uint32_t 
start_idx,
-                           uint32_t end_idx);
+                           common::BitMap &col_notnull_bitmap,
+                           uint32_t start_idx, uint32_t end_idx);
     int write_typed_column(storage::ChunkWriter *chunk_writer,
                            int64_t *timestamps, int32_t *col_values,
-                           common::BitMap &col_notnull_bitmap, uint32_t 
start_idx,
-                           uint32_t end_idx);
+                           common::BitMap &col_notnull_bitmap,
+                           uint32_t start_idx, uint32_t end_idx);
     int write_typed_column(storage::ChunkWriter *chunk_writer,
                            int64_t *timestamps, int64_t *col_values,
-                           common::BitMap &col_notnull_bitmap, uint32_t 
start_idx,
-                           uint32_t end_idx);
+                           common::BitMap &col_notnull_bitmap,
+                           uint32_t start_idx, uint32_t end_idx);
     int write_typed_column(storage::ChunkWriter *chunk_writer,
                            int64_t *timestamps, float *col_values,
-                           common::BitMap &col_notnull_bitmap, uint32_t 
start_idx,
-                           uint32_t end_idx);
+                           common::BitMap &col_notnull_bitmap,
+                           uint32_t start_idx, uint32_t end_idx);
     int write_typed_column(storage::ChunkWriter *chunk_writer,
                            int64_t *timestamps, double *col_values,
-                           common::BitMap &col_notnull_bitmap, uint32_t 
start_idx,
-                           uint32_t end_idx);
-    int write_typed_column(ChunkWriter*chunk_writer, int64_t*timestamps,
-                           common::String*col_values, 
common::BitMap&col_notnull_bitmap,
-                           uint32_t start_idx,
-                           uint32_t end_idx);
+                           common::BitMap &col_notnull_bitmap,
+                           uint32_t start_idx, uint32_t end_idx);
+    int write_typed_column(ChunkWriter *chunk_writer, int64_t *timestamps,
+                           common::String *col_values,
+                           common::BitMap &col_notnull_bitmap,
+                           uint32_t start_idx, uint32_t end_idx);
 
     template <typename MeasurementNamesGetter>
     int do_check_schema(
         std::shared_ptr<IDeviceID> device_id,
         MeasurementNamesGetter &measurement_names,
         common::SimpleVector<storage::ChunkWriter *> &chunk_writers);
+
     template <typename MeasurementNamesGetter>
     int do_check_schema_aligned(
         std::shared_ptr<IDeviceID> device_id,
@@ -145,14 +146,17 @@ class TsFileWriter {
         storage::TimeChunkWriter *&time_chunk_writer,
         common::SimpleVector<storage::ValueChunkWriter *> 
&value_chunk_writers);
     int do_check_schema_table(
-      std::shared_ptr<IDeviceID> device_id,
-      Tablet &tablet,
-      storage::TimeChunkWriter *&time_chunk_writer,
-      common::SimpleVector<storage::ValueChunkWriter *> &value_chunk_writers);
+        std::shared_ptr<IDeviceID> device_id, Tablet &tablet,
+        storage::TimeChunkWriter *&time_chunk_writer,
+        common::SimpleVector<storage::ValueChunkWriter *> 
&value_chunk_writers);
+
+    int do_check_and_prepare_tablet(Tablet &tablet);
     // std::vector<storage::ChunkWriter*> &chunk_writers);
     int write_column(storage::ChunkWriter *chunk_writer, const Tablet &,
-                     int col_idx, uint32_t start_idx = 0, uint32_t end_idx = 
UINT32_MAX);
-    int time_write_column(TimeChunkWriter* time_chunk_writer, const Tablet& 
tablet, uint32_t start_idx = 0,
+                     int col_idx, uint32_t start_idx = 0,
+                     uint32_t end_idx = UINT32_MAX);
+    int time_write_column(TimeChunkWriter *time_chunk_writer,
+                          const Tablet &tablet, uint32_t start_idx = 0,
                           uint32_t end_idx = UINT32_MAX);
     int register_timeseries(const std::string &device_path,
                             MeasurementSchema *measurement_schema,
@@ -184,7 +188,11 @@ class TsFileWriter {
     int write_typed_column(ValueChunkWriter *value_chunk_writer,
                            int64_t *timestamps, double *col_values,
                            common::BitMap &col_notnull_bitmap,
-                           uint32_t row_count);int 
write_typed_column(ValueChunkWriter*value_chunk_writer, int64_t*timestamps, 
common::String*col_values, common::BitMap&col_notnull_bitmap, int32_t 
row_count);
+                           uint32_t row_count);
+    int write_typed_column(ValueChunkWriter *value_chunk_writer,
+                           int64_t *timestamps, common::String *col_values,
+                           common::BitMap &col_notnull_bitmap,
+                           int32_t row_count);
 
     int write_typed_column(ValueChunkWriter *value_chunk_writer,
                            int64_t *timestamps, float *col_values,
@@ -203,7 +211,8 @@ class TsFileWriter {
 
     int value_write_column(ValueChunkWriter *value_chunk_writer,
                            const Tablet &tablet, int col_idx,
-                           uint32_t start_idx = 0, uint32_t end_idx = 
UINT32_MAX);
+                           uint32_t start_idx = 0,
+                           uint32_t end_idx = UINT32_MAX);
 };
 
 }  // end namespace storage
diff --git a/cpp/test/cwrapper/cwrapper_test.cc 
b/cpp/test/cwrapper/cwrapper_test.cc
index 394063a0..224257e2 100644
--- a/cpp/test/cwrapper/cwrapper_test.cc
+++ b/cpp/test/cwrapper/cwrapper_test.cc
@@ -18,130 +18,172 @@
  */
 #include <gtest/gtest.h>
 #include <unistd.h>
+#include <utils/db_utils.h>
 extern "C" {
+#include "cwrapper/errno_define.h"
 #include "cwrapper/tsfile_cwrapper.h"
 }
 
+#include "common/tablet.h"
 #include "utils/errno_define.h"
 
-using namespace common;
-
 namespace cwrapper {
 class CWrapperTest : public testing::Test {};
 
-TEST_F(CWrapperTest, RegisterTimeSeries) {
-    ERRNO code = 0;
-    char* temperature = strdup("temperature");
-    TimeseriesSchema ts_schema{temperature, TS_DATATYPE_INT32,
-                               TS_ENCODING_PLAIN, TS_COMPRESSION_UNCOMPRESSED};
-    remove("cwrapper_register_timeseries.tsfile");
-    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, RegisterTimeSeries) {
+//     ERRNO code = 0;
+//     char* temperature = strdup("temperature");
+//     TimeseriesSchema ts_schema{temperature, TS_DATATYPE_INT32,
+//                                TS_ENCODING_PLAIN,
+//                                TS_COMPRESSION_UNCOMPRESSED};
+//     remove("cwrapper_register_timeseries.tsfile");
+//     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];
+    const int column_num = 10;
     remove("cwrapper_write_flush_and_read.tsfile");
-    TsFileWriter writer = 
tsfile_writer_new("cwrapper_write_flush_and_read.tsfile", &code);
-    ASSERT_EQ(code, 0);
-    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]);
+    TableSchema schema;
+    schema.table_name = strdup("testtable0");
+    int id_schema_num = 5;
+    int field_schema_num = 5;
+    schema.column_num = column_num;
+    schema.column_schemas =
+        static_cast<ColumnSchema*>(malloc(column_num * sizeof(ColumnSchema)));
+    for (int i = 0; i < id_schema_num; i++) {
+        schema.column_schemas[i] =
+            ColumnSchema{strdup(std::string("id" + std::to_string(i)).c_str()),
+                         TS_DATATYPE_STRING, TS_COMPRESSION_UNCOMPRESSED,
+                         TS_ENCODING_PLAIN, TAG};
     }
-    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));
+    for (int i = 0; i < field_schema_num; i++) {
+        schema.column_schemas[i + id_schema_num] =
+            ColumnSchema{strdup(std::string("s" + std::to_string(i)).c_str()),
+                         TS_DATATYPE_INT64, TS_COMPRESSION_UNCOMPRESSED,
+                         TS_ENCODING_PLAIN, FIELD};
+    }
+    WriteFile file =
+        write_file_new("cwrapper_write_flush_and_read.tsfile", &code);
+    TsFileWriter writer = tsfile_writer_new(file, &schema, &code);
+    ASSERT_EQ(code, RET_OK);
+
+    char** column_names =
+        static_cast<char**>(malloc(column_num * sizeof(char*)));
+    TSDataType* data_types =
+        static_cast<TSDataType*>(malloc(sizeof(TSDataType) * column_num));
+    for (int i = 0; i < id_schema_num; i++) {
+        column_names[i] = strdup(std::string("id" + 
std::to_string(i)).c_str());
+        data_types[i] = TS_DATATYPE_STRING;
+    }
+
+    for (int i = 0; i < field_schema_num; i++) {
+        column_names[i + id_schema_num] =
+            strdup(std::string("s" + std::to_string(i)).c_str());
+        data_types[i + id_schema_num] = TS_DATATYPE_INT64;
+    }
+
+    Tablet tablet = tablet_new(column_names, data_types, column_num, 10);
+
+    int num_timestamp = 10;
+    char* literal = new char[std::strlen("device_id") + 1];
+    std::strcpy(literal, "device_id");
+
+    for (int l = 0; l < num_timestamp; l++) {
+        tablet_add_timestamp(tablet, l, l);
+        for (int i = 0; i < schema.column_num; i++) {
+            switch (schema.column_schemas[i].data_type) {
+                case TS_DATATYPE_STRING:
+                    tablet_add_value_by_name_string(
+                        tablet, l, schema.column_schemas[i].column_name,
+                        literal);
+                    break;
+                case TS_DATATYPE_INT64:
+                    tablet_add_value_by_name_int64_t(
+                        tablet, l, schema.column_schemas[i].column_name, l);
+                    break;
+                default:
+                    break;
             }
         }
-        code = tsfile_writer_write_tablet(writer, tablet);
-        ASSERT_EQ(code, 0);
-        free_tablet(&tablet);
     }
-    ASSERT_EQ(tsfile_writer_flush_data(writer), 0);
+    delete[] literal;
+    code = tsfile_writer_write(writer, tablet);
+    ASSERT_EQ(code, RET_OK);
     ASSERT_EQ(tsfile_writer_close(writer), 0);
 
-    TsFileReader reader = 
tsfile_reader_new("cwrapper_write_flush_and_read.tsfile", &code);
+
+    TsFileReader reader =
+        tsfile_reader_new("cwrapper_write_flush_and_read.tsfile", &code);
     ASSERT_EQ(code, 0);
+    ResultSet result_set = tsfile_query_table(reader, schema.table_name,
+                                              column_names, 10, 0, 100, &code);
 
-    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());
+    int row = 0;
+    while (tsfile_result_set_next(result_set, &code) && code == RET_OK) {
+        for (int i = 0; i < schema.column_num; i++) {
+            char* ret = nullptr;
+            switch (schema.column_schemas[i].data_type) {
+                case TS_DATATYPE_STRING:
+                    ret = tsfile_result_set_get_value_by_name_string(
+                        result_set, schema.column_schemas[i].column_name);
+                    ASSERT_EQ(std::string("device_id"), std::string(ret));
+                    free(ret);
+                    break;
+                case TS_DATATYPE_INT64:
+                    ASSERT_EQ(row, tsfile_result_set_get_value_by_name_int64_t(
+                                       result_set,
+                                       schema.column_schemas[i].column_name));
+                    break;
+                default:
+                    break;
+            }
+        }
+        for (int i = 7; i <= 11; i++) {
+            ASSERT_EQ(row, tsfile_result_set_get_value_by_index_int64_t(
+                               result_set, i));
+        }
+        row++;
     }
-    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 + 
1),
-                  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);
+    ASSERT_EQ(row, num_timestamp);
+    uint32_t size;
+    TableSchema* all_schema =
+        tsfile_reader_get_all_table_schemas(reader, &size);
+    ASSERT_EQ(1, size);
+    ASSERT_EQ(std::string(all_schema[0].table_name),
+              std::string(schema.table_name));
+    ASSERT_EQ(all_schema[0].column_num, schema.column_num);
+    int count_int64_t = 0;
+    int count_string = 0;
+    for (int i = 0; i < column_num; i++) {
+        if (all_schema[0].column_schemas[i].data_type == TS_DATATYPE_INT64) {
+            count_int64_t++;
+        } else if (all_schema[0].column_schemas[i].data_type ==
+                   TS_DATATYPE_STRING) {
+            count_string++;
+        }
     }
+
+    ASSERT_EQ(5, count_int64_t);
+    ASSERT_EQ(5, count_string);
+    free_tablet(&tablet);
+    tsfile_reader_close(reader);
     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_table_schema(schema);
+    free_table_schema(*all_schema);
+    free(all_schema);
+    for (int i = 0; i < column_num; i++) {
+        free(column_names[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"));
+    free(column_names);
+    free(data_types);
+    free_write_file(&file);
+
 }
 }  // namespace cwrapper
\ No newline at end of file

Reply via email to