apache-iotdb 2.0.2__py3-none-any.whl → 2.0.4.dev0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. {apache_iotdb-2.0.2.dist-info → apache_iotdb-2.0.4.dev0.dist-info}/METADATA +6 -6
  2. {apache_iotdb-2.0.2.dist-info → apache_iotdb-2.0.4.dev0.dist-info}/RECORD +34 -22
  3. {apache_iotdb-2.0.2.dist-info → apache_iotdb-2.0.4.dev0.dist-info}/WHEEL +1 -1
  4. iotdb/Session.py +158 -184
  5. iotdb/SessionPool.py +3 -1
  6. iotdb/template/MeasurementNode.py +1 -1
  7. iotdb/template/Template.py +3 -3
  8. iotdb/thrift/common/ttypes.py +18 -1
  9. iotdb/thrift/confignode/IConfigNodeRPCService.py +28290 -0
  10. iotdb/thrift/confignode/__init__.py +1 -0
  11. iotdb/thrift/confignode/constants.py +14 -0
  12. iotdb/thrift/confignode/ttypes.py +17249 -0
  13. iotdb/thrift/datanode/IDataNodeRPCService.py +17960 -0
  14. iotdb/thrift/datanode/MPPDataExchangeService.py +1071 -0
  15. iotdb/thrift/datanode/__init__.py +1 -0
  16. iotdb/thrift/datanode/constants.py +14 -0
  17. iotdb/thrift/datanode/ttypes.py +10920 -0
  18. iotdb/tsfile/utils/tsblock_serde.py +266 -0
  19. iotdb/utils/Field.py +30 -5
  20. iotdb/utils/NumpyTablet.py +1 -1
  21. iotdb/utils/SessionDataSet.py +43 -24
  22. iotdb/utils/Tablet.py +1 -1
  23. iotdb/utils/{IoTDBConnectionException.py → exception.py} +20 -0
  24. iotdb/utils/iotdb_rpc_dataset.py +406 -0
  25. iotdb/utils/rpc_utils.py +110 -0
  26. tests/integration/tablet_performance_comparison.py +3 -1
  27. tests/integration/test_new_data_types.py +6 -6
  28. tests/integration/test_tablemodel_query.py +476 -0
  29. iotdb/utils/IoTDBRpcDataSet.py +0 -463
  30. {apache_iotdb-2.0.2.dist-info → apache_iotdb-2.0.4.dev0.dist-info}/entry_points.txt +0 -0
  31. {apache_iotdb-2.0.2.dist-info → apache_iotdb-2.0.4.dev0.dist-info}/top_level.txt +0 -0
  32. /iotdb/tsfile/common/constant/{TsFileConstant.py → tsfile_constant.py} +0 -0
  33. /iotdb/tsfile/utils/{DateUtils.py → date_utils.py} +0 -0
  34. /iotdb/tsfile/utils/{Pair.py → pair.py} +0 -0
  35. /iotdb/tsfile/utils/{ReadWriteIOUtils.py → read_write_io_utils.py} +0 -0
@@ -0,0 +1,406 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+ #
18
+
19
+ # for package
20
+ import logging
21
+
22
+ import numpy as np
23
+ import pandas as pd
24
+ from thrift.transport import TTransport
25
+
26
+ from iotdb.thrift.rpc.IClientRPCService import TSFetchResultsReq, TSCloseOperationReq
27
+ from iotdb.tsfile.utils.date_utils import parse_int_to_date
28
+ from iotdb.tsfile.utils.tsblock_serde import deserialize
29
+ from iotdb.utils.exception import IoTDBConnectionException
30
+ from iotdb.utils.IoTDBConstants import TSDataType
31
+ from iotdb.utils.rpc_utils import verify_success, convert_to_timestamp
32
+
33
+ logger = logging.getLogger("IoTDB")
34
+ TIMESTAMP_STR = "Time"
35
+
36
+
37
+ class IoTDBRpcDataSet(object):
38
+
39
+ def __init__(
40
+ self,
41
+ sql,
42
+ column_name_list,
43
+ column_type_list,
44
+ ignore_timestamp,
45
+ more_data,
46
+ query_id,
47
+ client,
48
+ statement_id,
49
+ session_id,
50
+ query_result,
51
+ fetch_size,
52
+ time_out,
53
+ zone_id,
54
+ time_precision,
55
+ column_index_2_tsblock_column_index_list,
56
+ ):
57
+ self.__statement_id = statement_id
58
+ self.__session_id = session_id
59
+ self.ignore_timestamp = ignore_timestamp
60
+ self.__sql = sql
61
+ self.__query_id = query_id
62
+ self.__client = client
63
+ self.__fetch_size = fetch_size
64
+ self.column_size = len(column_name_list)
65
+ self.__time_out = time_out
66
+ self.__more_data = more_data
67
+
68
+ self.__column_name_list = []
69
+ self.__column_type_list = []
70
+ self.column_ordinal_dict = {}
71
+ self.column_name_2_tsblock_column_index_dict = {}
72
+ column_start_index = 1
73
+
74
+ start_index_for_column_index_2_tsblock_column_index_list = 0
75
+ if not ignore_timestamp:
76
+ self.__column_name_list.append(TIMESTAMP_STR)
77
+ self.__column_type_list.append(TSDataType.INT64)
78
+ self.column_name_2_tsblock_column_index_dict[TIMESTAMP_STR] = -1
79
+ self.column_ordinal_dict[TIMESTAMP_STR] = 1
80
+ if column_index_2_tsblock_column_index_list is not None:
81
+ column_index_2_tsblock_column_index_list.insert(0, -1)
82
+ start_index_for_column_index_2_tsblock_column_index_list = 1
83
+ column_start_index += 1
84
+
85
+ if column_index_2_tsblock_column_index_list is None:
86
+ column_index_2_tsblock_column_index_list = []
87
+ if not ignore_timestamp:
88
+ start_index_for_column_index_2_tsblock_column_index_list = 1
89
+ column_index_2_tsblock_column_index_list.append(-1)
90
+ for i in range(len(column_name_list)):
91
+ column_index_2_tsblock_column_index_list.append(i)
92
+ ts_block_column_size = (
93
+ max(column_index_2_tsblock_column_index_list, default=0) + 1
94
+ )
95
+ self.__data_type_for_tsblock_column = [None] * ts_block_column_size
96
+ for i in range(len(column_name_list)):
97
+ name = column_name_list[i]
98
+ column_type = TSDataType[column_type_list[i]]
99
+ self.__column_name_list.append(name)
100
+ self.__column_type_list.append(column_type)
101
+ tsblock_column_index = column_index_2_tsblock_column_index_list[
102
+ start_index_for_column_index_2_tsblock_column_index_list + i
103
+ ]
104
+ if tsblock_column_index != -1:
105
+ self.__data_type_for_tsblock_column[tsblock_column_index] = column_type
106
+ if name not in self.column_name_2_tsblock_column_index_dict:
107
+ self.column_ordinal_dict[name] = i + column_start_index
108
+ self.column_name_2_tsblock_column_index_dict[name] = (
109
+ tsblock_column_index
110
+ )
111
+
112
+ self.__column_index_2_tsblock_column_index_list = (
113
+ column_index_2_tsblock_column_index_list
114
+ )
115
+ self.__query_result = query_result
116
+ self.__query_result_index = 0
117
+ self.__is_closed = False
118
+ self.__empty_resultSet = False
119
+ self.has_cached_data_frame = False
120
+ self.data_frame = None
121
+ self.__zone_id = zone_id
122
+ self.__time_precision = time_precision
123
+
124
+ def close(self):
125
+ if self.__is_closed:
126
+ return
127
+ if self.__client is not None:
128
+ try:
129
+ status = self.__client.closeOperation(
130
+ TSCloseOperationReq(
131
+ self.__session_id, self.__query_id, self.__statement_id
132
+ )
133
+ )
134
+ logger.debug(
135
+ "close session {}, message: {}".format(
136
+ self.__session_id, status.message
137
+ )
138
+ )
139
+ except TTransport.TException as e:
140
+ raise IoTDBConnectionException(
141
+ "close session {} failed because: ".format(self.__session_id), e
142
+ )
143
+
144
+ self.__is_closed = True
145
+ self.__client = None
146
+
147
+ def next(self):
148
+ if not self.has_cached_data_frame:
149
+ self.construct_one_data_frame()
150
+ if self.has_cached_data_frame:
151
+ return True
152
+ if self.__empty_resultSet:
153
+ return False
154
+ if self.__more_data and self.fetch_results():
155
+ self.construct_one_data_frame()
156
+ return True
157
+ return False
158
+
159
+ def construct_one_data_frame(self):
160
+ if self.has_cached_data_frame or self.__query_result is None:
161
+ return
162
+ result = {}
163
+ has_pd_series = []
164
+ for i in range(len(self.__column_index_2_tsblock_column_index_list)):
165
+ result[i] = []
166
+ has_pd_series.append(False)
167
+ total_length = 0
168
+ while self.__query_result_index < len(self.__query_result):
169
+ time_array, column_arrays, null_indicators, array_length = deserialize(
170
+ memoryview(self.__query_result[self.__query_result_index])
171
+ )
172
+ self.__query_result[self.__query_result_index] = None
173
+ self.__query_result_index += 1
174
+ if self.ignore_timestamp is None or self.ignore_timestamp is False:
175
+ result[0].append(time_array)
176
+ total_length += array_length
177
+ for i, location in enumerate(
178
+ self.__column_index_2_tsblock_column_index_list
179
+ ):
180
+ if location < 0:
181
+ continue
182
+ data_type = self.__data_type_for_tsblock_column[location]
183
+
184
+ column_array = column_arrays[location]
185
+ null_indicator = null_indicators[location]
186
+ if len(column_array) < array_length or (
187
+ data_type == 0 and null_indicator is not None
188
+ ):
189
+ tmp_array = np.full(array_length, None, dtype=object)
190
+ if null_indicator is not None:
191
+ indexes = [not v for v in null_indicator]
192
+ if data_type == 0:
193
+ tmp_array[indexes] = column_array[indexes]
194
+ elif len(column_array) != 0:
195
+ tmp_array[indexes] = column_array
196
+
197
+ # INT32, DATE
198
+ if data_type == 1 or data_type == 9:
199
+ tmp_array = pd.Series(tmp_array, dtype="Int32")
200
+ has_pd_series[i] = True
201
+ # INT64, TIMESTAMP
202
+ elif data_type == 2 or data_type == 8:
203
+ tmp_array = pd.Series(tmp_array, dtype="Int64")
204
+ has_pd_series[i] = True
205
+ # BOOLEAN
206
+ elif data_type == 0:
207
+ tmp_array = pd.Series(tmp_array, dtype="boolean")
208
+ has_pd_series[i] = True
209
+ # FLOAT, DOUBLE
210
+ elif data_type == 3 or data_type == 4:
211
+ tmp_array = pd.Series(tmp_array)
212
+ has_pd_series[i] = True
213
+ column_array = tmp_array
214
+
215
+ result[i].append(column_array)
216
+ for k, v in result.items():
217
+ if v is None or len(v) < 1 or v[0] is None:
218
+ result[k] = []
219
+ elif not has_pd_series[k]:
220
+ res = np.empty(total_length, dtype=v[0].dtype)
221
+ np.concatenate(v, axis=0, out=res)
222
+ result[k] = res
223
+ else:
224
+ v = [x if isinstance(x, pd.Series) else pd.Series(x) for x in v]
225
+ result[k] = pd.concat(v, ignore_index=True)
226
+
227
+ self.__query_result = None
228
+ self.data_frame = pd.DataFrame(result, dtype=object)
229
+ if not self.data_frame.empty:
230
+ self.has_cached_data_frame = True
231
+
232
+ def has_cached_result(self):
233
+ return self.has_cached_data_frame
234
+
235
+ def _has_next_result_set(self):
236
+ if (self.__query_result is not None) and (
237
+ len(self.__query_result) > self.__query_result_index
238
+ ):
239
+ return True
240
+ if self.__empty_resultSet:
241
+ return False
242
+ if self.__more_data and self.fetch_results():
243
+ return True
244
+ return False
245
+
246
+ def result_set_to_pandas(self):
247
+ result = {}
248
+ for i in range(len(self.__column_index_2_tsblock_column_index_list)):
249
+ result[i] = []
250
+ while self._has_next_result_set():
251
+ time_array, column_arrays, null_indicators, array_length = deserialize(
252
+ memoryview(self.__query_result[self.__query_result_index])
253
+ )
254
+ self.__query_result[self.__query_result_index] = None
255
+ self.__query_result_index += 1
256
+ if self.ignore_timestamp is None or self.ignore_timestamp is False:
257
+ if time_array.dtype.byteorder == ">" and len(time_array) > 0:
258
+ time_array = time_array.byteswap().view(
259
+ time_array.dtype.newbyteorder("<")
260
+ )
261
+ result[0].append(time_array)
262
+
263
+ for i, location in enumerate(
264
+ self.__column_index_2_tsblock_column_index_list
265
+ ):
266
+ if location < 0:
267
+ continue
268
+ data_type = self.__data_type_for_tsblock_column[location]
269
+ column_array = column_arrays[location]
270
+ # BOOLEAN, INT32, INT64, FLOAT, DOUBLE, BLOB
271
+ if data_type in (0, 1, 2, 3, 4, 10):
272
+ data_array = column_array
273
+ if (
274
+ data_type != 10
275
+ and len(data_array) > 0
276
+ and data_array.dtype.byteorder == ">"
277
+ ):
278
+ data_array = data_array.byteswap().view(
279
+ data_array.dtype.newbyteorder("<")
280
+ )
281
+ # TEXT, STRING
282
+ elif data_type in (5, 11):
283
+ data_array = np.array([x.decode("utf-8") for x in column_array])
284
+ # TIMESTAMP
285
+ elif data_type == 8:
286
+ data_array = pd.Series(
287
+ [
288
+ convert_to_timestamp(
289
+ x, self.__time_precision, self.__zone_id
290
+ )
291
+ for x in column_array
292
+ ],
293
+ dtype=object,
294
+ )
295
+ # DATE
296
+ elif data_type == 9:
297
+ data_array = pd.Series(column_array).apply(parse_int_to_date)
298
+ else:
299
+ raise RuntimeError("unsupported data type {}.".format(data_type))
300
+
301
+ null_indicator = null_indicators[location]
302
+ if len(data_array) < array_length or (
303
+ data_type == 0 and null_indicator is not None
304
+ ):
305
+ tmp_array = []
306
+ # BOOLEAN, INT32, INT64
307
+ if data_type == 0 or data_type == 1 or data_type == 2:
308
+ tmp_array = np.full(array_length, pd.NA, dtype=object)
309
+ # FLOAT, DOUBLE
310
+ elif data_type == 3 or data_type == 4:
311
+ tmp_array = np.full(
312
+ array_length, np.nan, dtype=data_type.np_dtype()
313
+ )
314
+ # TEXT, STRING, BLOB, DATE, TIMESTAMP
315
+ elif (
316
+ data_type == 5
317
+ or data_type == 11
318
+ or data_type == 10
319
+ or data_type == 9
320
+ or data_type == 8
321
+ ):
322
+ tmp_array = np.full(array_length, None, dtype=object)
323
+
324
+ if null_indicator is not None:
325
+ indexes = [not v for v in null_indicator]
326
+ if data_type == 0:
327
+ tmp_array[indexes] = data_array[indexes]
328
+ elif len(data_array) != 0:
329
+ tmp_array[indexes] = data_array
330
+
331
+ if data_type == 1:
332
+ tmp_array = pd.Series(tmp_array).astype("Int32")
333
+ elif data_type == 2:
334
+ tmp_array = pd.Series(tmp_array).astype("Int64")
335
+ elif data_type == 0:
336
+ tmp_array = pd.Series(tmp_array).astype("boolean")
337
+
338
+ data_array = tmp_array
339
+
340
+ result[i].append(data_array)
341
+
342
+ for k, v in result.items():
343
+ if v is None or len(v) < 1 or v[0] is None:
344
+ result[k] = []
345
+ elif v[0].dtype == "Int32":
346
+ v = [x if isinstance(x, pd.Series) else pd.Series(x) for x in v]
347
+ result[k] = pd.concat(v, ignore_index=True).astype("Int32")
348
+ elif v[0].dtype == "Int64":
349
+ v = [x if isinstance(x, pd.Series) else pd.Series(x) for x in v]
350
+ result[k] = pd.concat(v, ignore_index=True).astype("Int64")
351
+ elif v[0].dtype == bool:
352
+ result[k] = pd.Series(np.concatenate(v, axis=0)).astype("boolean")
353
+ else:
354
+ result[k] = np.concatenate(v, axis=0)
355
+
356
+ df = pd.DataFrame(result)
357
+ df.columns = self.__column_name_list
358
+ return df
359
+
360
+ def fetch_results(self):
361
+ if self.__is_closed:
362
+ raise IoTDBConnectionException("This DataSet is already closed")
363
+ request = TSFetchResultsReq(
364
+ self.__session_id,
365
+ self.__sql,
366
+ self.__fetch_size,
367
+ self.__query_id,
368
+ True,
369
+ self.__time_out,
370
+ self.__statement_id,
371
+ )
372
+ try:
373
+ resp = self.__client.fetchResultsV2(request)
374
+ verify_success(resp.status)
375
+ self.__more_data = resp.moreData
376
+ if not resp.hasResultSet:
377
+ self.__empty_resultSet = True
378
+ else:
379
+ self.__query_result = resp.queryResult
380
+ self.__query_result_index = 0
381
+ return resp.hasResultSet
382
+ except TTransport.TException as e:
383
+ raise IoTDBConnectionException(
384
+ "Cannot fetch result from server, because of network connection: ", e
385
+ )
386
+
387
+ def find_column_name_by_index(self, column_index):
388
+ if column_index <= 0:
389
+ raise Exception("Column index should start from 1")
390
+ if column_index > len(self.__column_name_list):
391
+ raise Exception(
392
+ "column index {} out of range {}".format(column_index, self.column_size)
393
+ )
394
+ return self.__column_name_list[column_index - 1]
395
+
396
+ def get_fetch_size(self):
397
+ return self.__fetch_size
398
+
399
+ def set_fetch_size(self, fetch_size):
400
+ self.__fetch_size = fetch_size
401
+
402
+ def get_column_names(self):
403
+ return self.__column_name_list
404
+
405
+ def get_column_types(self):
406
+ return self.__column_type_list
@@ -0,0 +1,110 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+ #
18
+ import logging
19
+
20
+ import pandas as pd
21
+ from pandas._libs import OutOfBoundsDatetime
22
+ from tzlocal import get_localzone_name
23
+
24
+ from iotdb.thrift.common.ttypes import TSStatus
25
+ from iotdb.utils.exception import RedirectException, StatementExecutionException
26
+
27
+ logger = logging.getLogger("IoTDB")
28
+
29
+ SUCCESS_STATUS = 200
30
+ MULTIPLE_ERROR = 302
31
+ REDIRECTION_RECOMMEND = 400
32
+
33
+
34
+ def verify_success(status: TSStatus):
35
+ """
36
+ verify success of operation
37
+ :param status: execution result status
38
+ """
39
+ if status.code == MULTIPLE_ERROR:
40
+ verify_success_by_list(status.subStatus)
41
+ return 0
42
+ if status.code == SUCCESS_STATUS or status.code == REDIRECTION_RECOMMEND:
43
+ return 0
44
+
45
+ raise StatementExecutionException(status)
46
+
47
+
48
+ def verify_success_by_list(status_list: list):
49
+ """
50
+ verify success of operation
51
+ :param status_list: execution result status
52
+ """
53
+ error_messages = [
54
+ status.message
55
+ for status in status_list
56
+ if status.code not in {SUCCESS_STATUS, REDIRECTION_RECOMMEND}
57
+ ]
58
+ if error_messages:
59
+ message = f"{MULTIPLE_ERROR}: {'; '.join(error_messages)}"
60
+ raise StatementExecutionException(message=message)
61
+
62
+
63
+ def verify_success_with_redirection(status: TSStatus):
64
+ verify_success(status)
65
+ if status.redirectNode is not None:
66
+ raise RedirectException(status.redirectNode)
67
+ return 0
68
+
69
+
70
+ def verify_success_with_redirection_for_multi_devices(status: TSStatus, devices: list):
71
+ verify_success(status)
72
+ if status.code == MULTIPLE_ERROR or status.code == REDIRECTION_RECOMMEND:
73
+ device_to_endpoint = {}
74
+ for i in range(len(status.subStatus)):
75
+ if status.subStatus[i].redirectNode is not None:
76
+ device_to_endpoint[devices[i]] = status.subStatus[i].redirectNode
77
+ raise RedirectException(device_to_endpoint)
78
+
79
+
80
+ def convert_to_timestamp(time: int, precision: str, timezone: str):
81
+ try:
82
+ return pd.Timestamp(time, unit=precision, tz=timezone)
83
+ except OutOfBoundsDatetime:
84
+ return pd.Timestamp(time, unit=precision).tz_localize(timezone)
85
+ except ValueError:
86
+ logger.warning(
87
+ f"Timezone string '{timezone}' cannot be recognized by pandas. "
88
+ f"Falling back to local timezone: '{get_localzone_name()}'."
89
+ )
90
+ return pd.Timestamp(time, unit=precision, tz=get_localzone_name())
91
+
92
+
93
+ unit_map = {
94
+ "ms": "milliseconds",
95
+ "us": "microseconds",
96
+ "ns": "nanoseconds",
97
+ }
98
+
99
+
100
+ def isoformat(ts: pd.Timestamp, unit: str):
101
+ if unit not in unit_map:
102
+ raise ValueError(f"Unsupported unit: {unit}")
103
+ try:
104
+ return ts.isoformat(timespec=unit_map[unit])
105
+ except ValueError:
106
+ logger.warning(
107
+ f"Timezone string '{unit_map[unit]}' cannot be recognized by old version pandas. "
108
+ f"Falling back to use auto timespec'."
109
+ )
110
+ return ts.isoformat()
@@ -113,7 +113,9 @@ def create_open_session():
113
113
  port_ = "6667"
114
114
  username_ = "root"
115
115
  password_ = "root"
116
- session = Session(ip, port_, username_, password_, fetch_size=1024, zone_id="UTC+8")
116
+ session = Session(
117
+ ip, port_, username_, password_, fetch_size=1024, zone_id="Asia/Shanghai"
118
+ )
117
119
  session.open(False)
118
120
  return session
119
121
 
@@ -18,6 +18,8 @@
18
18
  from datetime import date
19
19
 
20
20
  import numpy as np
21
+ import pandas as pd
22
+ from tzlocal import get_localzone_name
21
23
 
22
24
  from iotdb.Session import Session
23
25
  from iotdb.SessionPool import PoolConfig, create_session_pool
@@ -47,8 +49,7 @@ def session_test(use_session_pool=False):
47
49
  "root",
48
50
  None,
49
51
  1024,
50
- "Asia/Shanghai",
51
- 3,
52
+ max_retry=3,
52
53
  )
53
54
  session_pool = create_session_pool(pool_config, 1, 3000)
54
55
  session = session_pool.get_session()
@@ -134,10 +135,9 @@ def session_test(use_session_pool=False):
134
135
  assert row_record.get_fields()[0].get_date_value() == date(
135
136
  2024, 1, timestamp
136
137
  )
137
- assert (
138
- row_record.get_fields()[1].get_object_value(TSDataType.TIMESTAMP)
139
- == timestamp
140
- )
138
+ assert row_record.get_fields()[1].get_object_value(
139
+ TSDataType.TIMESTAMP
140
+ ) == pd.Timestamp(timestamp, unit="ms", tz=get_localzone_name())
141
141
  assert row_record.get_fields()[2].get_binary_value() == b"\x12\x34"
142
142
  assert row_record.get_fields()[3].get_string_value() == "test0" + str(
143
143
  timestamp