This is an automated email from the ASF dual-hosted git repository.
hongzhigao pushed a commit to branch feature/python-new-datatypes
in repository https://gitbox.apache.org/repos/asf/tsfile.git
The following commit(s) were added to refs/heads/feature/python-new-datatypes
by this push:
new c234bb00 Feature/python new datatypes (#641)
c234bb00 is described below
commit c234bb0013198d8c2d118975721027ac9101e0d4
Author: Hongzhi Gao <[email protected]>
AuthorDate: Tue Nov 18 17:37:18 2025 +0800
Feature/python new datatypes (#641)
* [Python] new datatypes
* add cwrapper ut for python new datatypes
---
cpp/src/common/record.h | 18 ++---
cpp/src/common/row_record.h | 1 +
cpp/src/cwrapper/tsfile_cwrapper.cc | 13 ++++
cpp/src/cwrapper/tsfile_cwrapper.h | 5 ++
cpp/src/writer/tsfile_writer.cc | 4 +-
cpp/test/cwrapper/cwrapper_test.cc | 149 ++++++++++++++++++++++++++++++++----
python/setup.py | 2 +-
python/tests/test_write_and_read.py | 46 +++++++++--
python/tsfile/constants.py | 2 +-
python/tsfile/field.py | 14 +++-
python/tsfile/tsfile_cpp.pxd | 4 +
python/tsfile/tsfile_py_cpp.pyx | 14 +++-
python/tsfile/tsfile_reader.pyx | 12 +--
13 files changed, 232 insertions(+), 52 deletions(-)
diff --git a/cpp/src/common/record.h b/cpp/src/common/record.h
index 8c729f68..cbbebbc5 100644
--- a/cpp/src/common/record.h
+++ b/cpp/src/common/record.h
@@ -53,9 +53,8 @@ struct DataPoint {
int64_t i64_val_;
float float_val_;
double double_val_;
- common::String *str_val_;
} u_;
- TextType text_val_;
+ common::String text_val_;
DataPoint(const std::string &measurement_name, bool b)
: measurement_name_(measurement_name), text_val_() {
@@ -82,19 +81,12 @@ struct DataPoint {
u_.double_val_ = d;
}
- DataPoint(const std::string &measurement_name, common::String &str,
- common::PageArena &pa)
+ DataPoint(const std::string &measurement_name, common::String str)
: measurement_name_(measurement_name), text_val_() {
- char *p_buf = (char *)pa.alloc(sizeof(common::String));
- u_.str_val_ = new (p_buf) common::String();
- u_.str_val_->dup_from(str, pa);
+ text_val_.buf_ = str.buf_;
+ text_val_.len_ = str.len_;
}
- // DataPoint(const std::string &measurement_name, Text &text),
- // : measurement_name_(measurement_name),
- // data_type_(common::TEXT),
- // text_val_(text) {}
-
DataPoint(const std::string &measurement_name)
: isnull(true), measurement_name_(measurement_name) {}
void set_i32(int32_t i32) {
@@ -150,7 +142,7 @@ template <>
inline int TsRecord::add_point(const std::string &measurement_name,
common::String val) {
int ret = common::E_OK;
- points_.emplace_back(DataPoint(measurement_name, val, pa));
+ points_.emplace_back(DataPoint(measurement_name, val));
return ret;
}
diff --git a/cpp/src/common/row_record.h b/cpp/src/common/row_record.h
index 5ff5e232..713cabc8 100644
--- a/cpp/src/common/row_record.h
+++ b/cpp/src/common/row_record.h
@@ -103,6 +103,7 @@ struct Field {
switch (type_) {
case common::TSDataType::BOOLEAN:
return value_.bval_;
+ case common::TSDataType::DATE:
case common::TSDataType::INT32:
return value_.ival_;
case common::TSDataType::TIMESTAMP:
diff --git a/cpp/src/cwrapper/tsfile_cwrapper.cc
b/cpp/src/cwrapper/tsfile_cwrapper.cc
index 1b09db49..02a3b11c 100644
--- a/cpp/src/cwrapper/tsfile_cwrapper.cc
+++ b/cpp/src/cwrapper/tsfile_cwrapper.cc
@@ -280,6 +280,19 @@ TsRecord _ts_record_new(const char *device_id, Timestamp
timestamp,
return common::E_OK; \
}
+ERRNO _insert_data_into_ts_record_by_name_string(TsRecord data,
+ const char *measurement_name,
+ const char *value) {
+ auto *record = (storage::TsRecord *)data;
+ storage::DataPoint point(
+ measurement_name,
+ common::String(const_cast<char *>(value), strlen(value)));
+ if (record->points_.size() + 1 > record->points_.capacity())
+ return common::E_BUF_NOT_ENOUGH;
+ record->points_.push_back(point);
+ return common::E_OK;
+}
+
INSERT_DATA_INTO_TS_RECORD_BY_NAME_DEF(int32_t);
INSERT_DATA_INTO_TS_RECORD_BY_NAME_DEF(int64_t);
INSERT_DATA_INTO_TS_RECORD_BY_NAME_DEF(bool);
diff --git a/cpp/src/cwrapper/tsfile_cwrapper.h
b/cpp/src/cwrapper/tsfile_cwrapper.h
index 75dc0364..3c753395 100644
--- a/cpp/src/cwrapper/tsfile_cwrapper.h
+++ b/cpp/src/cwrapper/tsfile_cwrapper.h
@@ -35,6 +35,8 @@ typedef enum {
TS_DATATYPE_DOUBLE = 4,
TS_DATATYPE_TEXT = 5,
TS_DATATYPE_VECTOR = 6,
+ TS_DATATYPE_DATE = 9,
+ TS_DATATYPE_BLOB = 10,
TS_DATATYPE_STRING = 11,
TS_DATATYPE_NULL_TYPE = 254,
TS_DATATYPE_INVALID = 255
@@ -623,6 +625,9 @@ 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);
+ERRNO _insert_data_into_ts_record_by_name_string(TsRecord data,
+ const char* measurement_name,
+ const char* value);
// Write a tablet into a device.
ERRNO _tsfile_writer_write_tablet(TsFileWriter writer, Tablet tablet);
diff --git a/cpp/src/writer/tsfile_writer.cc b/cpp/src/writer/tsfile_writer.cc
index 3ae5cf28..20c747f9 100644
--- a/cpp/src/writer/tsfile_writer.cc
+++ b/cpp/src/writer/tsfile_writer.cc
@@ -657,7 +657,7 @@ int TsFileWriter::write_point(ChunkWriter *chunk_writer,
int64_t timestamp,
case common::BLOB:
case common::TEXT:
case common::STRING:
- return chunk_writer->write(timestamp, *point.u_.str_val_);
+ return chunk_writer->write(timestamp, point.text_val_);
default:
return E_INVALID_DATA_POINT;
}
@@ -689,7 +689,7 @@ int TsFileWriter::write_point_aligned(ValueChunkWriter
*value_chunk_writer,
case common::BLOB:
case common::TEXT:
case common::STRING:
- return value_chunk_writer->write(timestamp, point.u_.str_val_,
+ return value_chunk_writer->write(timestamp, point.text_val_,
isnull);
default:
return E_INVALID_DATA_POINT;
diff --git a/cpp/test/cwrapper/cwrapper_test.cc
b/cpp/test/cwrapper/cwrapper_test.cc
index 90a93fb4..0ddbbde8 100644
--- a/cpp/test/cwrapper/cwrapper_test.cc
+++ b/cpp/test/cwrapper/cwrapper_test.cc
@@ -19,6 +19,17 @@
#include <gtest/gtest.h>
#include <unistd.h>
#include <utils/db_utils.h>
+
+#include "common/row_record.h"
+#include "cwrapper/tsfile_cwrapper.h"
+#include "reader/result_set.h"
+#include "reader/tsfile_reader.h"
+#include "writer/tsfile_writer.h"
+
+namespace storage {
+class TsFileReader;
+}
+
extern "C" {
#include "cwrapper/errno_define_c.h"
#include "cwrapper/tsfile_cwrapper.h"
@@ -28,23 +39,127 @@ extern "C" {
#include "utils/errno_define.h"
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);
-// }
+class CWrapperTest : public testing::Test {
+ public:
+ static void ASSERT_OK(ERRNO code, const char* msg = "") {
+ ASSERT_EQ(code, RET_OK) << msg;
+ }
+};
+
+TEST_F(CWrapperTest, TestForPythonInterfaceInsert) {
+ ERRNO code = 0;
+ const int column_num = 10;
+ char* filename = "cwrapper_for_python.tsfile";
+ remove(filename); // Clean up any existing file
+
+ // Device and measurement definitions
+ char* device_id = "root.device1";
+ char* str_measurement_id = "str_measurement";
+ char* text_measurement_id = "text_measurement";
+ char* date_measurement_id = "date_measurement";
+
+ // Define time series schemas for different data types
+ timeseries_schema str_measurement;
+ str_measurement.timeseries_name = str_measurement_id;
+ str_measurement.compression = TS_COMPRESSION_UNCOMPRESSED;
+ str_measurement.data_type = TS_DATATYPE_STRING;
+ str_measurement.encoding = TS_ENCODING_PLAIN;
+
+ timeseries_schema text_measurement;
+ text_measurement.timeseries_name = text_measurement_id;
+ text_measurement.compression = TS_COMPRESSION_UNCOMPRESSED;
+ text_measurement.data_type = TS_DATATYPE_TEXT;
+ text_measurement.encoding = TS_ENCODING_PLAIN;
+
+ timeseries_schema date_measurement;
+ date_measurement.timeseries_name = date_measurement_id;
+ date_measurement.compression = TS_COMPRESSION_UNCOMPRESSED;
+ date_measurement.data_type = TS_DATATYPE_DATE;
+ date_measurement.encoding = TS_ENCODING_PLAIN;
+
+ // Create TsFile writer
+ auto* writer = (storage::TsFileWriter*)_tsfile_writer_new(
+ filename, 128 * 1024 * 1024, &code);
+ ASSERT_OK(code, "create writer failed");
+
+ // Register time series with the writer
+ ASSERT_OK(
+ _tsfile_writer_register_timeseries(writer, device_id,
&str_measurement),
+ "register timeseries failed");
+
+ ASSERT_OK(
+ _tsfile_writer_register_timeseries(writer, device_id,
&text_measurement),
+ "register timeseries failed");
+
+ ASSERT_OK(
+ _tsfile_writer_register_timeseries(writer, device_id,
&date_measurement),
+ "register timeseries failed");
+
+ // Create a new time series record
+ auto* record = (storage::TsRecord*)_ts_record_new(device_id, 0, 3);
+
+ // Insert string data
+ char* test_str = "test_string";
+ ASSERT_OK(_insert_data_into_ts_record_by_name_string(record,
str_measurement_id,
+ test_str),
+ "insert data failed");
+
+ // Insert text data
+ char* test_text = "test_text";
+ ASSERT_OK(_insert_data_into_ts_record_by_name_string(record,
text_measurement_id,
+ test_text),
+ "insert data failed");
+
+ // Insert date data - NOTE: There's a bug here, should use
date_measurement_id
+ int32_t test_date = 20251118;
+ ASSERT_OK(_insert_data_into_ts_record_by_name_int32_t(record,
date_measurement_id,
+ test_date),
+ "insert data failed");
+
+ // Write the record to file and close writer
+ ASSERT_OK(_tsfile_writer_write_ts_record(writer, record),
+ "write record failed");
+ ASSERT_OK(_tsfile_writer_flush(writer), "flush failed");
+ ASSERT_OK(_tsfile_writer_close(writer), "close writer failed");
+
+ // Create reader to verify the written data
+ auto* reader = (storage::TsFileReader*)tsfile_reader_new(filename, &code);
+ ASSERT_OK(code, "create reader failed");
+
+ // Query the data we just wrote
+ char* sensors[] = {str_measurement_id, text_measurement_id,
date_measurement_id};
+ auto* result = (storage::ResultSet*)_tsfile_reader_query_device(
+ reader, device_id, sensors, 3, 0, 100, &code);
+ ASSERT_OK(code, "query device failed");
+
+ // Verify the retrieved data matches what we inserted
+ bool has_next = false;
+ int row_count = 0;
+ while (!result->next(has_next) && has_next) {
+ // Verify timestamp
+ EXPECT_EQ(result->get_value<int64_t>(1), row_count);
+
+ // Verify string data
+ const common::String* str = result->get_value<common::String*>(2);
+ EXPECT_EQ(strlen(test_str), str->len_);
+ const char* ret_char =
tsfile_result_set_get_value_by_index_string(result, 2);
+ EXPECT_EQ(strcmp(test_str, ret_char), 0);
+
+ // Verify text data
+ const common::String* text = result->get_value<common::String*>(3);
+ EXPECT_EQ(strlen(test_text), text->len_);
+ const char* ret_text =
tsfile_result_set_get_value_by_index_string(result, 3);
+ EXPECT_EQ(strcmp(test_text, ret_text), 0);
+
+ // Verify date data
+ int32_t ret_date =
tsfile_result_set_get_value_by_index_int32_t(result, 4);
+ EXPECT_EQ(test_date, ret_date);
+
+ row_count++;
+ }
+
+ ASSERT_OK(reader->close(), "close reader failed");
+}
TEST_F(CWrapperTest, WriterFlushTabletAndReadData) {
ERRNO code = 0;
diff --git a/python/setup.py b/python/setup.py
index 329cc2aa..cd369981 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -25,7 +25,7 @@ from Cython.Build import cythonize
from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
-version = "2.1.0.dev0"
+version = "2.2.0.dev"
system = platform.system()
diff --git a/python/tests/test_write_and_read.py
b/python/tests/test_write_and_read.py
index e5c87ab9..69cc3d89 100644
--- a/python/tests/test_write_and_read.py
+++ b/python/tests/test_write_and_read.py
@@ -33,27 +33,48 @@ from tsfile.exceptions import TableNotExistError,
ColumnNotExistError, NotSuppor
def test_row_record_write_and_read():
try:
+ if os.path.exists("record_write_and_read.tsfile"):
+ os.remove("record_write_and_read.tsfile")
writer = TsFileWriter("record_write_and_read.tsfile")
- timeseries = TimeseriesSchema("level1", TSDataType.INT64)
- writer.register_timeseries("root.device1", timeseries)
+ writer.register_timeseries("root.device1", TimeseriesSchema("level1",
TSDataType.INT64))
writer.register_timeseries("root.device1", TimeseriesSchema("level2",
TSDataType.DOUBLE))
writer.register_timeseries("root.device1", TimeseriesSchema("level3",
TSDataType.INT32))
+ writer.register_timeseries("root.device1", TimeseriesSchema("level4",
TSDataType.STRING))
+ writer.register_timeseries("root.device1", TimeseriesSchema("level5",
TSDataType.TEXT))
+ writer.register_timeseries("root.device1", TimeseriesSchema("level6",
TSDataType.BLOB))
+ writer.register_timeseries("root.device1", TimeseriesSchema("level7",
TSDataType.DATE))
+
+ max_row_num = 10
- max_row_num = 1000
for i in range(max_row_num):
row = RowRecord("root.device1", i,
[Field("level1", i + 1, TSDataType.INT64),
Field("level2", i * 1.1, TSDataType.DOUBLE),
- Field("level3", i * 2, TSDataType.INT32)])
+ Field("level3", i * 2, TSDataType.INT32),
+ Field("level4", f"string_value_{i}",
TSDataType.STRING),
+ Field("level5", f"text_value_{i}",
TSDataType.TEXT),
+ Field("level6", f"blob_data_{i}".encode('utf-8'),
TSDataType.BLOB),
+ Field("level7", i, TSDataType.DATE)])
writer.write_row_record(row)
writer.close()
reader = TsFileReader("record_write_and_read.tsfile")
- result = reader.query_timeseries("root.device1", ["level1", "level2"],
10, 100)
- i = 10
+ result = reader.query_timeseries("root.device1", ["level1", "level2",
"level3", "level4", "level5", "level6","level7"], 0, 100)
+ row_num = 0
while result.next():
- print(result.get_value_by_index(1))
+ #print(result.get_value_by_index(0))
+ print(f"\n--- 记录 #{row_num} ---")
+ print(f"索引1的值: {result.get_value_by_index(1)}")
+ print(f"索引2的值: {result.get_value_by_index(2)}")
+ print(f"索引3的值: {result.get_value_by_index(3)}")
+ print(f"索引4的值: {result.get_value_by_index(4)}")
+ print(f"索引5的值: {result.get_value_by_index(5)}")
+ print(f"索引6的值: {result.get_value_by_index(6)}")
+ print(f"索引7的值: {result.get_value_by_index(7)}")
+ print(f"索引8的值: {result.get_value_by_index(8)}")
+ assert result.get_value_by_index(2) == row_num + 1
+ row_num += 1
print(reader.get_active_query_result())
result.close()
print(reader.get_active_query_result())
@@ -116,6 +137,8 @@ def test_table_writer_and_reader():
[ColumnSchema("device", TSDataType.STRING,
ColumnCategory.TAG),
ColumnSchema("value", TSDataType.DOUBLE,
ColumnCategory.FIELD)])
try:
+ if os.path.exists("table_write.tsfile"):
+ os.remove("table_write.tsfile")
with TsFileTableWriter("table_write.tsfile", table) as writer:
tablet = Tablet(["device", "value"],
[TSDataType.STRING, TSDataType.DOUBLE], 100)
@@ -305,3 +328,12 @@ def test_tsfile_to_df():
to_dataframe("table_write_to_df.tsfile", "test_table", ["device1"])
finally:
os.remove("table_write_to_df.tsfile")
+
+import os
+
+if __name__ == "__main__":
+ os.chdir(os.path.dirname(os.path.abspath(__file__)))
+ pytest.main([
+ "test_write_and_read.py::test_row_record_write_and_read",
+ "-s", "-v"
+ ])
\ No newline at end of file
diff --git a/python/tsfile/constants.py b/python/tsfile/constants.py
index 5eaa2470..7df8eab0 100644
--- a/python/tsfile/constants.py
+++ b/python/tsfile/constants.py
@@ -35,7 +35,7 @@ class TSDataType(IntEnum):
def to_py_type(self):
if self == TSDataType.BOOLEAN:
return bool
- elif self == TSDataType.INT32:
+ elif self == TSDataType.INT32 or self == TSDataType.DATE:
return int
elif self == TSDataType.INT64:
return int
diff --git a/python/tsfile/field.py b/python/tsfile/field.py
index ae46c628..26d02c5f 100644
--- a/python/tsfile/field.py
+++ b/python/tsfile/field.py
@@ -75,6 +75,7 @@ class Field(object):
if (
self.data_type != TSDataType.INT32
+ and self.data_type != TSDataType.DATE
and self.data_type != TSDataType.INT64
and self.data_type != TSDataType.FLOAT
and self.data_type != TSDataType.DOUBLE
@@ -178,10 +179,21 @@ class Field(object):
return str(self.value)
# BLOB
elif self.data_type == TSDataType.BLOB:
- return str(hex(int.from_bytes(self.value, byteorder="big")))
+ return self.value
else:
return str(self.get_object_value(self.data_type))
+ def get_bytes_value(self):
+ if self.value is None:
+ return None
+ if self.data_type is None:
+ raise NoneDataTypeException("None Data Type Exception!")
+
+ if self.data_type == TSDataType.BLOB:
+ return self.value
+ else:
+ raise TypeError("get_bytes_value() only supports BLOB data type")
+
def __str__(self):
return self.get_string_value()
diff --git a/python/tsfile/tsfile_cpp.pxd b/python/tsfile/tsfile_cpp.pxd
index 1b04051c..76262b5f 100644
--- a/python/tsfile/tsfile_cpp.pxd
+++ b/python/tsfile/tsfile_cpp.pxd
@@ -42,6 +42,8 @@ cdef extern from "./tsfile_cwrapper.h":
TS_DATATYPE_DOUBLE = 4
TS_DATATYPE_TEXT = 5
TS_DATATYPE_VECTOR = 6
+ TS_DATATYPE_DATE = 9
+ TS_DATATYPE_BLOB = 10
TS_DATATYPE_STRING = 11
TS_DATATYPE_NULL_TYPE = 254
TS_DATATYPE_INVALID = 255
@@ -159,6 +161,8 @@ cdef extern from "./tsfile_cwrapper.h":
ErrorCode _insert_data_into_ts_record_by_name_double(TsRecord data, const
char *measurement_name,
const double value);
ErrorCode _insert_data_into_ts_record_by_name_bool(TsRecord data, const
char *measurement_name, const bint value);
+ ErrorCode _insert_data_into_ts_record_by_name_string(TsRecord data, const
char *measurement_name, const char *value)
+ #ErrorCode _insert_data_into_ts_record_by_name_blob(record,
PyUnicode_AsUTF8(field.get_field_name()), field.get_bytes_value())
void _free_tsfile_ts_record(TsRecord * record);
diff --git a/python/tsfile/tsfile_py_cpp.pyx b/python/tsfile/tsfile_py_cpp.pyx
index e1743039..70c162bb 100644
--- a/python/tsfile/tsfile_py_cpp.pyx
+++ b/python/tsfile/tsfile_py_cpp.pyx
@@ -83,8 +83,10 @@ cdef dict TS_DATA_TYPE_MAP = {
TSDataTypePy.INT64: TSDataType.TS_DATATYPE_INT64,
TSDataTypePy.FLOAT: TSDataType.TS_DATATYPE_FLOAT,
TSDataTypePy.DOUBLE: TSDataType.TS_DATATYPE_DOUBLE,
+ TSDataTypePy.DATE: TSDataType.TS_DATATYPE_DATE,
TSDataTypePy.TEXT: TSDataType.TS_DATATYPE_TEXT,
- TSDataTypePy.STRING: TSDataType.TS_DATATYPE_STRING
+ TSDataTypePy.STRING: TSDataType.TS_DATATYPE_STRING,
+ TSDataTypePy.BLOB: TSDataType.TS_DATATYPE_BLOB
}
cdef dict TS_ENCODING_MAP = {
@@ -266,8 +268,8 @@ cdef Tablet to_c_tablet(object tablet):
if value[row] is not None:
tablet_add_value_by_index_double(ctablet, row, col,
value[row])
- # STRING
- elif data_type == TS_DATATYPE_STRING:
+ # STRING or TEXT
+ elif data_type == TS_DATATYPE_STRING or data_type == TS_DATATYPE_TEXT
or data_type == TS_DATATYPE_BLOB:
for row in range(max_row_num):
if value[row] is not None:
py_value = value[row]
@@ -293,7 +295,7 @@ cdef TsRecord to_c_record(object row_record):
data_type = to_c_data_type(field.get_data_type())
if data_type == TS_DATATYPE_BOOLEAN:
_insert_data_into_ts_record_by_name_bool(record,
PyUnicode_AsUTF8(field.get_field_name()), field.get_bool_value())
- elif data_type == TS_DATATYPE_INT32:
+ elif data_type == TS_DATATYPE_INT32 or data_type == TS_DATATYPE_DATE:
_insert_data_into_ts_record_by_name_int32_t(record,
PyUnicode_AsUTF8(field.get_field_name()), field.get_int_value())
elif data_type == TS_DATATYPE_INT64:
_insert_data_into_ts_record_by_name_int64_t(record,
PyUnicode_AsUTF8(field.get_field_name()), field.get_long_value())
@@ -301,6 +303,10 @@ cdef TsRecord to_c_record(object row_record):
_insert_data_into_ts_record_by_name_double(record,
PyUnicode_AsUTF8(field.get_field_name()), field.get_double_value())
elif data_type == TS_DATATYPE_FLOAT:
_insert_data_into_ts_record_by_name_float(record,
PyUnicode_AsUTF8(field.get_field_name()), field.get_float_value())
+ elif data_type == TS_DATATYPE_TEXT or data_type == TS_DATATYPE_STRING:
+ _insert_data_into_ts_record_by_name_string(record,
PyUnicode_AsUTF8(field.get_field_name()),
field.get_string_value().encode('utf-8'))
+ elif data_type == TS_DATATYPE_BLOB:
+ _insert_data_into_ts_record_by_name_string(record,
PyUnicode_AsUTF8(field.get_field_name()), field.get_string_value())
return record
diff --git a/python/tsfile/tsfile_reader.pyx b/python/tsfile/tsfile_reader.pyx
index e8d38d7d..7a488c4e 100644
--- a/python/tsfile/tsfile_reader.pyx
+++ b/python/tsfile/tsfile_reader.pyx
@@ -162,7 +162,7 @@ cdef class ResultSetPy:
return None
# data type in metadata is an array, id from 0.
data_type = self.metadata.get_data_type(index)
- if data_type == TSDataTypePy.INT32:
+ if data_type == TSDataTypePy.INT32 or data_type == TSDataTypePy.DATE:
return tsfile_result_set_get_value_by_index_int32_t(self.result,
index)
elif data_type == TSDataTypePy.INT64:
return tsfile_result_set_get_value_by_index_int64_t(self.result,
index)
@@ -172,14 +172,14 @@ cdef class ResultSetPy:
return tsfile_result_set_get_value_by_index_double(self.result,
index)
elif data_type == TSDataTypePy.BOOLEAN:
return tsfile_result_set_get_value_by_index_bool(self.result,
index)
- elif data_type == TSDataTypePy.STRING:
+ elif data_type == TSDataTypePy.STRING or data_type ==
TSDataTypePy.TEXT or data_type == TSDataTypePy.BLOB:
try:
string =
tsfile_result_set_get_value_by_index_string(self.result, index)
- py_str = string.decode('utf-8')
- return py_str
+ if string == NULL:
+ return None
+ return string.decode('utf-8')
finally:
- if string != NULL:
- free(string)
+ pass
def get_value_by_name(self, column_name : str):
"""