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.
- {apache_iotdb-2.0.2.dist-info → apache_iotdb-2.0.4.dev0.dist-info}/METADATA +6 -6
- {apache_iotdb-2.0.2.dist-info → apache_iotdb-2.0.4.dev0.dist-info}/RECORD +34 -22
- {apache_iotdb-2.0.2.dist-info → apache_iotdb-2.0.4.dev0.dist-info}/WHEEL +1 -1
- iotdb/Session.py +158 -184
- iotdb/SessionPool.py +3 -1
- iotdb/template/MeasurementNode.py +1 -1
- iotdb/template/Template.py +3 -3
- iotdb/thrift/common/ttypes.py +18 -1
- iotdb/thrift/confignode/IConfigNodeRPCService.py +28290 -0
- iotdb/thrift/confignode/__init__.py +1 -0
- iotdb/thrift/confignode/constants.py +14 -0
- iotdb/thrift/confignode/ttypes.py +17249 -0
- iotdb/thrift/datanode/IDataNodeRPCService.py +17960 -0
- iotdb/thrift/datanode/MPPDataExchangeService.py +1071 -0
- iotdb/thrift/datanode/__init__.py +1 -0
- iotdb/thrift/datanode/constants.py +14 -0
- iotdb/thrift/datanode/ttypes.py +10920 -0
- iotdb/tsfile/utils/tsblock_serde.py +266 -0
- iotdb/utils/Field.py +30 -5
- iotdb/utils/NumpyTablet.py +1 -1
- iotdb/utils/SessionDataSet.py +43 -24
- iotdb/utils/Tablet.py +1 -1
- iotdb/utils/{IoTDBConnectionException.py → exception.py} +20 -0
- iotdb/utils/iotdb_rpc_dataset.py +406 -0
- iotdb/utils/rpc_utils.py +110 -0
- tests/integration/tablet_performance_comparison.py +3 -1
- tests/integration/test_new_data_types.py +6 -6
- tests/integration/test_tablemodel_query.py +476 -0
- iotdb/utils/IoTDBRpcDataSet.py +0 -463
- {apache_iotdb-2.0.2.dist-info → apache_iotdb-2.0.4.dev0.dist-info}/entry_points.txt +0 -0
- {apache_iotdb-2.0.2.dist-info → apache_iotdb-2.0.4.dev0.dist-info}/top_level.txt +0 -0
- /iotdb/tsfile/common/constant/{TsFileConstant.py → tsfile_constant.py} +0 -0
- /iotdb/tsfile/utils/{DateUtils.py → date_utils.py} +0 -0
- /iotdb/tsfile/utils/{Pair.py → pair.py} +0 -0
- /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
|
iotdb/utils/rpc_utils.py
ADDED
|
@@ -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(
|
|
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
|
-
|
|
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
|
-
|
|
139
|
-
|
|
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
|