apache-iotdb 1.3.3__tar.gz → 2.0.1b0__tar.gz
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-1.3.3 → apache_iotdb-2.0.1b0}/PKG-INFO +5 -5
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/README.md +2 -2
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/apache_iotdb.egg-info/PKG-INFO +5 -5
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/apache_iotdb.egg-info/SOURCES.txt +11 -6
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/apache_iotdb.egg-info/requires.txt +1 -1
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/Session.py +221 -22
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/SessionPool.py +11 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/sqlalchemy/IoTDBDialect.py +11 -4
- apache_iotdb-2.0.1b0/iotdb/table_session.py +147 -0
- apache_iotdb-2.0.1b0/iotdb/table_session_pool.py +116 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/thrift/common/ttypes.py +54 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/thrift/rpc/IClientRPCService.py +12 -12
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/thrift/rpc/ttypes.py +601 -493
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/utils/Field.py +0 -1
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/utils/IoTDBRpcDataSet.py +4 -1
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/utils/NumpyTablet.py +39 -14
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/utils/Tablet.py +50 -14
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/pyproject.toml +3 -3
- {apache_iotdb-1.3.3/iotdb/dbapi/tests → apache_iotdb-2.0.1b0/tests/integration/dbapi}/test_connection.py +1 -1
- {apache_iotdb-1.3.3/iotdb/dbapi/tests → apache_iotdb-2.0.1b0/tests/integration/dbapi}/test_cursor.py +1 -1
- {apache_iotdb-1.3.3/iotdb/sqlalchemy/tests → apache_iotdb-2.0.1b0/tests/integration/sqlalchemy}/test_dialect.py +28 -15
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/tests/integration/test_aligned_timeseries.py +1 -1
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/tests/integration/test_dataframe.py +1 -1
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/tests/integration/test_delete_data.py +1 -1
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/tests/integration/test_new_data_types.py +1 -1
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/tests/integration/test_one_device.py +1 -1
- apache_iotdb-2.0.1b0/tests/integration/test_relational_session.py +128 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/tests/integration/test_session.py +82 -20
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/tests/integration/test_session_pool.py +1 -1
- apache_iotdb-2.0.1b0/tests/integration/test_tablemodel_insert.py +1592 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/tests/integration/test_tablet.py +1 -1
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/tests/integration/test_todf.py +1 -1
- apache_iotdb-2.0.1b0/tests/integration/test_treemodel_insert.py +6027 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/apache_iotdb.egg-info/dependency_links.txt +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/apache_iotdb.egg-info/entry_points.txt +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/apache_iotdb.egg-info/top_level.txt +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/__init__.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/dbapi/Connection.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/dbapi/Cursor.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/dbapi/Exceptions.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/dbapi/__init__.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/sqlalchemy/IoTDBIdentifierPreparer.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/sqlalchemy/IoTDBSQLCompiler.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/sqlalchemy/IoTDBTypeCompiler.py +0 -0
- {apache_iotdb-1.3.3/iotdb/dbapi/tests → apache_iotdb-2.0.1b0/iotdb/sqlalchemy}/__init__.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/template/MeasurementNode.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/template/Template.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/template/TemplateNode.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/template/TemplateQueryType.py +0 -0
- {apache_iotdb-1.3.3/iotdb/sqlalchemy → apache_iotdb-2.0.1b0/iotdb/template}/__init__.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/thrift/__init__.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/thrift/common/__init__.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/thrift/common/constants.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/thrift/rpc/__init__.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/thrift/rpc/constants.py +0 -0
- {apache_iotdb-1.3.3/iotdb/sqlalchemy/tests → apache_iotdb-2.0.1b0/iotdb/tsfile}/__init__.py +0 -0
- {apache_iotdb-1.3.3/iotdb/template → apache_iotdb-2.0.1b0/iotdb/tsfile/common}/__init__.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/tsfile/common/constant/TsFileConstant.py +0 -0
- {apache_iotdb-1.3.3/iotdb/tsfile → apache_iotdb-2.0.1b0/iotdb/tsfile/common/constant}/__init__.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/tsfile/utils/DateUtils.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/tsfile/utils/Pair.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/tsfile/utils/ReadWriteIOUtils.py +0 -0
- {apache_iotdb-1.3.3/iotdb/tsfile/common → apache_iotdb-2.0.1b0/iotdb/tsfile/utils}/__init__.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/utils/BitMap.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/utils/IoTDBConnectionException.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/utils/IoTDBConstants.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/utils/RowRecord.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/iotdb/utils/SessionDataSet.py +0 -0
- {apache_iotdb-1.3.3/iotdb/tsfile/common/constant → apache_iotdb-2.0.1b0/iotdb/utils}/__init__.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/setup.cfg +0 -0
- {apache_iotdb-1.3.3/iotdb/tsfile/utils → apache_iotdb-2.0.1b0/tests}/__init__.py +0 -0
- {apache_iotdb-1.3.3/iotdb/utils → apache_iotdb-2.0.1b0/tests/integration}/__init__.py +0 -0
- {apache_iotdb-1.3.3/tests → apache_iotdb-2.0.1b0/tests/integration/dbapi}/__init__.py +0 -0
- /apache_iotdb-1.3.3/iotdb/IoTDBContainer.py → /apache_iotdb-2.0.1b0/tests/integration/iotdb_container.py +0 -0
- {apache_iotdb-1.3.3/tests/integration → apache_iotdb-2.0.1b0/tests/integration/sqlalchemy}/__init__.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/tests/integration/tablet_performance_comparison.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/tests/unit/__init__.py +0 -0
- {apache_iotdb-1.3.3 → apache_iotdb-2.0.1b0}/tests/unit/test_numpy_tablet.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: apache-iotdb
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.1b0
|
|
4
4
|
Summary: Apache IoTDB client API
|
|
5
5
|
Author-email: Apache IoTDB <dev@iotdb.apache.org>
|
|
6
6
|
License: Apache License, Version 2.0
|
|
@@ -17,7 +17,7 @@ Description-Content-Type: text/markdown
|
|
|
17
17
|
Requires-Dist: thrift>=0.14.1
|
|
18
18
|
Requires-Dist: pandas>=1.0.0
|
|
19
19
|
Requires-Dist: numpy>=1.0.0
|
|
20
|
-
Requires-Dist: sqlalchemy
|
|
20
|
+
Requires-Dist: sqlalchemy>=1.4
|
|
21
21
|
Requires-Dist: sqlalchemy-utils>=0.37.8
|
|
22
22
|
|
|
23
23
|
<!--
|
|
@@ -69,9 +69,9 @@ You have to install thrift (>=0.14.1) before using the package.
|
|
|
69
69
|
|
|
70
70
|
First, download the latest package: `pip3 install apache-iotdb`
|
|
71
71
|
|
|
72
|
-
You can get an example of using the package to read and write data at here: [Example](https://github.com/apache/iotdb/blob/master/client-py/SessionExample.py)
|
|
72
|
+
You can get an example of using the package to read and write data at here: [Example](https://github.com/apache/iotdb/blob/master/iotdb-client/client-py/SessionExample.py)
|
|
73
73
|
|
|
74
|
-
An example of aligned timeseries: [Aligned Timeseries Session Example](https://github.com/apache/iotdb/blob/master/client-py/SessionAlignedTimeseriesExample.py)
|
|
74
|
+
An example of aligned timeseries: [Aligned Timeseries Session Example](https://github.com/apache/iotdb/blob/master/iotdb-client/client-py/SessionAlignedTimeseriesExample.py)
|
|
75
75
|
|
|
76
76
|
(you need to add `import iotdb` in the head of the file)
|
|
77
77
|
|
|
@@ -47,9 +47,9 @@ You have to install thrift (>=0.14.1) before using the package.
|
|
|
47
47
|
|
|
48
48
|
First, download the latest package: `pip3 install apache-iotdb`
|
|
49
49
|
|
|
50
|
-
You can get an example of using the package to read and write data at here: [Example](https://github.com/apache/iotdb/blob/master/client-py/SessionExample.py)
|
|
50
|
+
You can get an example of using the package to read and write data at here: [Example](https://github.com/apache/iotdb/blob/master/iotdb-client/client-py/SessionExample.py)
|
|
51
51
|
|
|
52
|
-
An example of aligned timeseries: [Aligned Timeseries Session Example](https://github.com/apache/iotdb/blob/master/client-py/SessionAlignedTimeseriesExample.py)
|
|
52
|
+
An example of aligned timeseries: [Aligned Timeseries Session Example](https://github.com/apache/iotdb/blob/master/iotdb-client/client-py/SessionAlignedTimeseriesExample.py)
|
|
53
53
|
|
|
54
54
|
(you need to add `import iotdb` in the head of the file)
|
|
55
55
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: apache-iotdb
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.1b0
|
|
4
4
|
Summary: Apache IoTDB client API
|
|
5
5
|
Author-email: Apache IoTDB <dev@iotdb.apache.org>
|
|
6
6
|
License: Apache License, Version 2.0
|
|
@@ -17,7 +17,7 @@ Description-Content-Type: text/markdown
|
|
|
17
17
|
Requires-Dist: thrift>=0.14.1
|
|
18
18
|
Requires-Dist: pandas>=1.0.0
|
|
19
19
|
Requires-Dist: numpy>=1.0.0
|
|
20
|
-
Requires-Dist: sqlalchemy
|
|
20
|
+
Requires-Dist: sqlalchemy>=1.4
|
|
21
21
|
Requires-Dist: sqlalchemy-utils>=0.37.8
|
|
22
22
|
|
|
23
23
|
<!--
|
|
@@ -69,9 +69,9 @@ You have to install thrift (>=0.14.1) before using the package.
|
|
|
69
69
|
|
|
70
70
|
First, download the latest package: `pip3 install apache-iotdb`
|
|
71
71
|
|
|
72
|
-
You can get an example of using the package to read and write data at here: [Example](https://github.com/apache/iotdb/blob/master/client-py/SessionExample.py)
|
|
72
|
+
You can get an example of using the package to read and write data at here: [Example](https://github.com/apache/iotdb/blob/master/iotdb-client/client-py/SessionExample.py)
|
|
73
73
|
|
|
74
|
-
An example of aligned timeseries: [Aligned Timeseries Session Example](https://github.com/apache/iotdb/blob/master/client-py/SessionAlignedTimeseriesExample.py)
|
|
74
|
+
An example of aligned timeseries: [Aligned Timeseries Session Example](https://github.com/apache/iotdb/blob/master/iotdb-client/client-py/SessionAlignedTimeseriesExample.py)
|
|
75
75
|
|
|
76
76
|
(you need to add `import iotdb` in the head of the file)
|
|
77
77
|
|
|
@@ -6,24 +6,20 @@ apache_iotdb.egg-info/dependency_links.txt
|
|
|
6
6
|
apache_iotdb.egg-info/entry_points.txt
|
|
7
7
|
apache_iotdb.egg-info/requires.txt
|
|
8
8
|
apache_iotdb.egg-info/top_level.txt
|
|
9
|
-
iotdb/IoTDBContainer.py
|
|
10
9
|
iotdb/Session.py
|
|
11
10
|
iotdb/SessionPool.py
|
|
12
11
|
iotdb/__init__.py
|
|
12
|
+
iotdb/table_session.py
|
|
13
|
+
iotdb/table_session_pool.py
|
|
13
14
|
iotdb/dbapi/Connection.py
|
|
14
15
|
iotdb/dbapi/Cursor.py
|
|
15
16
|
iotdb/dbapi/Exceptions.py
|
|
16
17
|
iotdb/dbapi/__init__.py
|
|
17
|
-
iotdb/dbapi/tests/__init__.py
|
|
18
|
-
iotdb/dbapi/tests/test_connection.py
|
|
19
|
-
iotdb/dbapi/tests/test_cursor.py
|
|
20
18
|
iotdb/sqlalchemy/IoTDBDialect.py
|
|
21
19
|
iotdb/sqlalchemy/IoTDBIdentifierPreparer.py
|
|
22
20
|
iotdb/sqlalchemy/IoTDBSQLCompiler.py
|
|
23
21
|
iotdb/sqlalchemy/IoTDBTypeCompiler.py
|
|
24
22
|
iotdb/sqlalchemy/__init__.py
|
|
25
|
-
iotdb/sqlalchemy/tests/__init__.py
|
|
26
|
-
iotdb/sqlalchemy/tests/test_dialect.py
|
|
27
23
|
iotdb/template/MeasurementNode.py
|
|
28
24
|
iotdb/template/Template.py
|
|
29
25
|
iotdb/template/TemplateNode.py
|
|
@@ -57,15 +53,24 @@ iotdb/utils/Tablet.py
|
|
|
57
53
|
iotdb/utils/__init__.py
|
|
58
54
|
tests/__init__.py
|
|
59
55
|
tests/integration/__init__.py
|
|
56
|
+
tests/integration/iotdb_container.py
|
|
60
57
|
tests/integration/tablet_performance_comparison.py
|
|
61
58
|
tests/integration/test_aligned_timeseries.py
|
|
62
59
|
tests/integration/test_dataframe.py
|
|
63
60
|
tests/integration/test_delete_data.py
|
|
64
61
|
tests/integration/test_new_data_types.py
|
|
65
62
|
tests/integration/test_one_device.py
|
|
63
|
+
tests/integration/test_relational_session.py
|
|
66
64
|
tests/integration/test_session.py
|
|
67
65
|
tests/integration/test_session_pool.py
|
|
66
|
+
tests/integration/test_tablemodel_insert.py
|
|
68
67
|
tests/integration/test_tablet.py
|
|
69
68
|
tests/integration/test_todf.py
|
|
69
|
+
tests/integration/test_treemodel_insert.py
|
|
70
|
+
tests/integration/dbapi/__init__.py
|
|
71
|
+
tests/integration/dbapi/test_connection.py
|
|
72
|
+
tests/integration/dbapi/test_cursor.py
|
|
73
|
+
tests/integration/sqlalchemy/__init__.py
|
|
74
|
+
tests/integration/sqlalchemy/test_dialect.py
|
|
70
75
|
tests/unit/__init__.py
|
|
71
76
|
tests/unit/test_numpy_tablet.py
|
|
@@ -69,11 +69,12 @@ class Session(object):
|
|
|
69
69
|
SUCCESS_STATUS = 200
|
|
70
70
|
MULTIPLE_ERROR = 302
|
|
71
71
|
REDIRECTION_RECOMMEND = 400
|
|
72
|
-
DEFAULT_FETCH_SIZE =
|
|
72
|
+
DEFAULT_FETCH_SIZE = 5000
|
|
73
73
|
DEFAULT_USER = "root"
|
|
74
74
|
DEFAULT_PASSWORD = "root"
|
|
75
75
|
DEFAULT_ZONE_ID = time.strftime("%z")
|
|
76
76
|
RETRY_NUM = 3
|
|
77
|
+
SQL_DIALECT = "tree"
|
|
77
78
|
|
|
78
79
|
def __init__(
|
|
79
80
|
self,
|
|
@@ -104,6 +105,8 @@ class Session(object):
|
|
|
104
105
|
self.__enable_redirection = enable_redirection
|
|
105
106
|
self.__device_id_to_endpoint = None
|
|
106
107
|
self.__endpoint_to_connection = None
|
|
108
|
+
self.sql_dialect = self.SQL_DIALECT
|
|
109
|
+
self.database = None
|
|
107
110
|
|
|
108
111
|
@classmethod
|
|
109
112
|
def init_from_node_urls(
|
|
@@ -118,7 +121,13 @@ class Session(object):
|
|
|
118
121
|
if node_urls is None:
|
|
119
122
|
raise RuntimeError("node urls is empty")
|
|
120
123
|
session = Session(
|
|
121
|
-
None,
|
|
124
|
+
None,
|
|
125
|
+
None,
|
|
126
|
+
user,
|
|
127
|
+
password,
|
|
128
|
+
fetch_size,
|
|
129
|
+
zone_id,
|
|
130
|
+
enable_redirection,
|
|
122
131
|
)
|
|
123
132
|
session.__hosts = []
|
|
124
133
|
session.__ports = []
|
|
@@ -181,12 +190,15 @@ class Session(object):
|
|
|
181
190
|
else:
|
|
182
191
|
client = Client(TBinaryProtocol.TBinaryProtocolAccelerated(transport))
|
|
183
192
|
|
|
193
|
+
configuration = {"version": "V_1_0", "sql_dialect": self.sql_dialect}
|
|
194
|
+
if self.database is not None:
|
|
195
|
+
configuration["db"] = self.database
|
|
184
196
|
open_req = TSOpenSessionReq(
|
|
185
197
|
client_protocol=self.protocol_version,
|
|
186
198
|
username=self.__user,
|
|
187
199
|
password=self.__password,
|
|
188
200
|
zoneId=self.__zone_id,
|
|
189
|
-
configuration=
|
|
201
|
+
configuration=configuration,
|
|
190
202
|
)
|
|
191
203
|
|
|
192
204
|
try:
|
|
@@ -498,6 +510,15 @@ class Session(object):
|
|
|
498
510
|
string_values = [string_values]
|
|
499
511
|
if type(measurements) == str:
|
|
500
512
|
measurements = [measurements]
|
|
513
|
+
if self.__has_none_value(string_values):
|
|
514
|
+
filtered_measurements, filtered_values = zip(
|
|
515
|
+
*[(m, v) for m, v in zip(measurements, string_values) if v is not None]
|
|
516
|
+
)
|
|
517
|
+
measurements = list(filtered_measurements)
|
|
518
|
+
values = list(filtered_values)
|
|
519
|
+
if len(measurements) == 0 or len(values) == 0:
|
|
520
|
+
logger.info("All inserting values are none!")
|
|
521
|
+
return
|
|
501
522
|
request = self.gen_insert_str_record_req(
|
|
502
523
|
device_id, timestamp, measurements, string_values
|
|
503
524
|
)
|
|
@@ -529,6 +550,15 @@ class Session(object):
|
|
|
529
550
|
string_values = [string_values]
|
|
530
551
|
if type(measurements) == str:
|
|
531
552
|
measurements = [measurements]
|
|
553
|
+
if self.__has_none_value(string_values):
|
|
554
|
+
filtered_measurements, filtered_values = zip(
|
|
555
|
+
*[(m, v) for m, v in zip(measurements, string_values) if v is not None]
|
|
556
|
+
)
|
|
557
|
+
measurements = list(filtered_measurements)
|
|
558
|
+
values = list(filtered_values)
|
|
559
|
+
if len(measurements) == 0 or len(values) == 0:
|
|
560
|
+
logger.info("All inserting values are none!")
|
|
561
|
+
return
|
|
532
562
|
request = self.gen_insert_str_record_req(
|
|
533
563
|
device_id, timestamp, measurements, string_values, True
|
|
534
564
|
)
|
|
@@ -564,6 +594,20 @@ class Session(object):
|
|
|
564
594
|
:param data_types: List of TSDataType, indicate the data type for each sensor
|
|
565
595
|
:param values: List, values to be inserted, for each sensor
|
|
566
596
|
"""
|
|
597
|
+
if self.__has_none_value(values):
|
|
598
|
+
filtered_measurements, filtered_data_types, filtered_values = zip(
|
|
599
|
+
*[
|
|
600
|
+
(m, d, v)
|
|
601
|
+
for m, d, v in zip(measurements, data_types, values)
|
|
602
|
+
if v is not None
|
|
603
|
+
]
|
|
604
|
+
)
|
|
605
|
+
measurements = list(filtered_measurements)
|
|
606
|
+
data_types = list(filtered_data_types)
|
|
607
|
+
values = list(filtered_values)
|
|
608
|
+
if len(measurements) == 0 or len(data_types) == 0 or len(values) == 0:
|
|
609
|
+
logger.info("All inserting values are none!")
|
|
610
|
+
return
|
|
567
611
|
request = self.gen_insert_record_req(
|
|
568
612
|
device_id, timestamp, measurements, data_types, values
|
|
569
613
|
)
|
|
@@ -597,6 +641,19 @@ class Session(object):
|
|
|
597
641
|
:param types_lst: 2-D List of TSDataType, each element of outer list indicates sensor data types of a device
|
|
598
642
|
:param values_lst: 2-D List, values to be inserted, for each device
|
|
599
643
|
"""
|
|
644
|
+
if self.__has_none_value(values_lst):
|
|
645
|
+
(
|
|
646
|
+
device_ids,
|
|
647
|
+
times,
|
|
648
|
+
measurements_lst,
|
|
649
|
+
types_lst,
|
|
650
|
+
values_lst,
|
|
651
|
+
) = self.__filter_lists_by_values(
|
|
652
|
+
device_ids, times, measurements_lst, types_lst, values_lst
|
|
653
|
+
)
|
|
654
|
+
if len(device_ids) == 0:
|
|
655
|
+
logger.info("All inserting values are none!")
|
|
656
|
+
return
|
|
600
657
|
if self.__enable_redirection:
|
|
601
658
|
request_group = {}
|
|
602
659
|
for i in range(len(device_ids)):
|
|
@@ -666,6 +723,20 @@ class Session(object):
|
|
|
666
723
|
:param data_types: List of TSDataType, indicate the data type for each sensor
|
|
667
724
|
:param values: List, values to be inserted, for each sensor
|
|
668
725
|
"""
|
|
726
|
+
if self.__has_none_value(values):
|
|
727
|
+
filtered_measurements, filtered_data_types, filtered_values = zip(
|
|
728
|
+
*[
|
|
729
|
+
(m, d, v)
|
|
730
|
+
for m, d, v in zip(measurements, data_types, values)
|
|
731
|
+
if v is not None
|
|
732
|
+
]
|
|
733
|
+
)
|
|
734
|
+
measurements = list(filtered_measurements)
|
|
735
|
+
data_types = list(filtered_data_types)
|
|
736
|
+
values = list(filtered_values)
|
|
737
|
+
if len(measurements) == 0 or len(data_types) == 0 or len(values) == 0:
|
|
738
|
+
logger.info("All inserting values are none!")
|
|
739
|
+
return
|
|
669
740
|
request = self.gen_insert_record_req(
|
|
670
741
|
device_id, timestamp, measurements, data_types, values, True
|
|
671
742
|
)
|
|
@@ -699,6 +770,19 @@ class Session(object):
|
|
|
699
770
|
:param types_lst: 2-D List of TSDataType, each element of outer list indicates sensor data types of a device
|
|
700
771
|
:param values_lst: 2-D List, values to be inserted, for each device
|
|
701
772
|
"""
|
|
773
|
+
if self.__has_none_value(values_lst):
|
|
774
|
+
(
|
|
775
|
+
device_ids,
|
|
776
|
+
times,
|
|
777
|
+
measurements_lst,
|
|
778
|
+
types_lst,
|
|
779
|
+
values_lst,
|
|
780
|
+
) = self.__filter_lists_by_values(
|
|
781
|
+
device_ids, times, measurements_lst, types_lst, values_lst
|
|
782
|
+
)
|
|
783
|
+
if len(device_ids) == 0:
|
|
784
|
+
logger.info("All inserting values are none!")
|
|
785
|
+
return
|
|
702
786
|
if self.__enable_redirection:
|
|
703
787
|
request_group = {}
|
|
704
788
|
for i in range(len(device_ids)):
|
|
@@ -891,13 +975,15 @@ class Session(object):
|
|
|
891
975
|
"""
|
|
892
976
|
request = self.gen_insert_tablet_req(tablet)
|
|
893
977
|
try:
|
|
894
|
-
connection = self.get_connection(tablet.
|
|
978
|
+
connection = self.get_connection(tablet.get_insert_target_name())
|
|
895
979
|
request.sessionId = connection.session_id
|
|
896
980
|
return Session.verify_success_with_redirection(
|
|
897
981
|
connection.client.insertTablet(request)
|
|
898
982
|
)
|
|
899
983
|
except RedirectException as e:
|
|
900
|
-
return self.handle_redirection(
|
|
984
|
+
return self.handle_redirection(
|
|
985
|
+
tablet.get_insert_target_name(), e.redirect_node
|
|
986
|
+
)
|
|
901
987
|
except TTransport.TException as e:
|
|
902
988
|
if self.reconnect():
|
|
903
989
|
try:
|
|
@@ -916,14 +1002,14 @@ class Session(object):
|
|
|
916
1002
|
if self.__enable_redirection:
|
|
917
1003
|
request_group = {}
|
|
918
1004
|
for i in range(len(tablet_lst)):
|
|
919
|
-
connection = self.get_connection(tablet_lst[i].
|
|
1005
|
+
connection = self.get_connection(tablet_lst[i].get_insert_target_name())
|
|
920
1006
|
request = request_group.setdefault(
|
|
921
1007
|
connection.client,
|
|
922
1008
|
TSInsertTabletsReq(
|
|
923
1009
|
connection.session_id, [], [], [], [], [], [], False
|
|
924
1010
|
),
|
|
925
1011
|
)
|
|
926
|
-
request.prefixPaths.append(tablet_lst[i].
|
|
1012
|
+
request.prefixPaths.append(tablet_lst[i].get_insert_target_name())
|
|
927
1013
|
request.timestampsList.append(tablet_lst[i].get_binary_timestamps())
|
|
928
1014
|
request.measurementsList.append(tablet_lst[i].get_measurements())
|
|
929
1015
|
request.valuesList.append(tablet_lst[i].get_binary_values())
|
|
@@ -982,13 +1068,15 @@ class Session(object):
|
|
|
982
1068
|
"""
|
|
983
1069
|
request = self.gen_insert_tablet_req(tablet, True)
|
|
984
1070
|
try:
|
|
985
|
-
connection = self.get_connection(tablet.
|
|
1071
|
+
connection = self.get_connection(tablet.get_insert_target_name())
|
|
986
1072
|
request.sessionId = connection.session_id
|
|
987
1073
|
return Session.verify_success_with_redirection(
|
|
988
1074
|
connection.client.insertTablet(request)
|
|
989
1075
|
)
|
|
990
1076
|
except RedirectException as e:
|
|
991
|
-
return self.handle_redirection(
|
|
1077
|
+
return self.handle_redirection(
|
|
1078
|
+
tablet.get_insert_target_name(), e.redirect_node
|
|
1079
|
+
)
|
|
992
1080
|
except TTransport.TException as e:
|
|
993
1081
|
if self.reconnect():
|
|
994
1082
|
try:
|
|
@@ -1007,14 +1095,14 @@ class Session(object):
|
|
|
1007
1095
|
if self.__enable_redirection:
|
|
1008
1096
|
request_group = {}
|
|
1009
1097
|
for i in range(len(tablet_lst)):
|
|
1010
|
-
connection = self.get_connection(tablet_lst[i].
|
|
1098
|
+
connection = self.get_connection(tablet_lst[i].get_insert_target_name())
|
|
1011
1099
|
request = request_group.setdefault(
|
|
1012
1100
|
connection.client,
|
|
1013
1101
|
TSInsertTabletsReq(
|
|
1014
1102
|
connection.session_id, [], [], [], [], [], [], True
|
|
1015
1103
|
),
|
|
1016
1104
|
)
|
|
1017
|
-
request.prefixPaths.append(tablet_lst[i].
|
|
1105
|
+
request.prefixPaths.append(tablet_lst[i].get_insert_target_name())
|
|
1018
1106
|
request.timestampsList.append(tablet_lst[i].get_binary_timestamps())
|
|
1019
1107
|
request.measurementsList.append(tablet_lst[i].get_measurements())
|
|
1020
1108
|
request.valuesList.append(tablet_lst[i].get_binary_values())
|
|
@@ -1059,6 +1147,36 @@ class Session(object):
|
|
|
1059
1147
|
self.connection_error_msg()
|
|
1060
1148
|
) from None
|
|
1061
1149
|
|
|
1150
|
+
def insert_relational_tablet(self, tablet):
|
|
1151
|
+
"""
|
|
1152
|
+
insert one tablet, for example three column in the table1 can form a tablet:
|
|
1153
|
+
timestamps, id1, attr1, m1
|
|
1154
|
+
1, id:1, attr:1, 1.0
|
|
1155
|
+
2, id:1, attr:1, 2.0
|
|
1156
|
+
3, id:2, attr:2, 3.0
|
|
1157
|
+
:param tablet: a tablet specified above
|
|
1158
|
+
"""
|
|
1159
|
+
request = self.gen_insert_relational_tablet_req(tablet)
|
|
1160
|
+
try:
|
|
1161
|
+
connection = self.get_connection(tablet.get_insert_target_name())
|
|
1162
|
+
request.sessionId = connection.session_id
|
|
1163
|
+
return Session.verify_success_with_redirection(
|
|
1164
|
+
connection.client.insertTablet(request)
|
|
1165
|
+
)
|
|
1166
|
+
except RedirectException as e:
|
|
1167
|
+
return self.handle_redirection(
|
|
1168
|
+
tablet.get_insert_target_name(), e.redirect_node
|
|
1169
|
+
)
|
|
1170
|
+
except TTransport.TException as e:
|
|
1171
|
+
if self.reconnect():
|
|
1172
|
+
try:
|
|
1173
|
+
request.sessionId = self.__session_id
|
|
1174
|
+
return Session.verify_success(self.__client.insertTablet(request))
|
|
1175
|
+
except TTransport.TException as e1:
|
|
1176
|
+
raise IoTDBConnectionException(e1) from None
|
|
1177
|
+
else:
|
|
1178
|
+
raise IoTDBConnectionException(self.connection_error_msg()) from None
|
|
1179
|
+
|
|
1062
1180
|
def insert_records_of_one_device(
|
|
1063
1181
|
self, device_id, times_list, measurements_list, types_list, values_list
|
|
1064
1182
|
):
|
|
@@ -1275,13 +1393,27 @@ class Session(object):
|
|
|
1275
1393
|
def gen_insert_tablet_req(self, tablet, is_aligned=False):
|
|
1276
1394
|
return TSInsertTabletReq(
|
|
1277
1395
|
self.__session_id,
|
|
1278
|
-
tablet.
|
|
1396
|
+
tablet.get_insert_target_name(),
|
|
1397
|
+
tablet.get_measurements(),
|
|
1398
|
+
tablet.get_binary_values(),
|
|
1399
|
+
tablet.get_binary_timestamps(),
|
|
1400
|
+
tablet.get_data_types(),
|
|
1401
|
+
tablet.get_row_number(),
|
|
1402
|
+
is_aligned,
|
|
1403
|
+
)
|
|
1404
|
+
|
|
1405
|
+
def gen_insert_relational_tablet_req(self, tablet, is_aligned=False):
|
|
1406
|
+
return TSInsertTabletReq(
|
|
1407
|
+
self.__session_id,
|
|
1408
|
+
tablet.get_insert_target_name(),
|
|
1279
1409
|
tablet.get_measurements(),
|
|
1280
1410
|
tablet.get_binary_values(),
|
|
1281
1411
|
tablet.get_binary_timestamps(),
|
|
1282
1412
|
tablet.get_data_types(),
|
|
1283
1413
|
tablet.get_row_number(),
|
|
1284
1414
|
is_aligned,
|
|
1415
|
+
True,
|
|
1416
|
+
tablet.get_column_categories(),
|
|
1285
1417
|
)
|
|
1286
1418
|
|
|
1287
1419
|
def gen_insert_tablets_req(self, tablet_lst, is_aligned=False):
|
|
@@ -1292,7 +1424,7 @@ class Session(object):
|
|
|
1292
1424
|
type_lst = []
|
|
1293
1425
|
size_lst = []
|
|
1294
1426
|
for tablet in tablet_lst:
|
|
1295
|
-
device_id_lst.append(tablet.
|
|
1427
|
+
device_id_lst.append(tablet.get_insert_target_name())
|
|
1296
1428
|
measurements_lst.append(tablet.get_measurements())
|
|
1297
1429
|
values_lst.append(tablet.get_binary_values())
|
|
1298
1430
|
timestamps_lst.append(tablet.get_binary_timestamps())
|
|
@@ -1365,6 +1497,18 @@ class Session(object):
|
|
|
1365
1497
|
else:
|
|
1366
1498
|
raise IoTDBConnectionException(self.connection_error_msg()) from None
|
|
1367
1499
|
|
|
1500
|
+
previous_db = self.database
|
|
1501
|
+
if resp.database is not None:
|
|
1502
|
+
self.database = resp.database
|
|
1503
|
+
if previous_db != self.database and self.__endpoint_to_connection is not None:
|
|
1504
|
+
iterator = iter(self.__endpoint_to_connection.items())
|
|
1505
|
+
for entry in list(iterator):
|
|
1506
|
+
endpoint, connection = entry
|
|
1507
|
+
if connection != self.__default_connection:
|
|
1508
|
+
try:
|
|
1509
|
+
connection.change_database(sql)
|
|
1510
|
+
except Exception as e:
|
|
1511
|
+
self.__endpoint_to_connection.pop(endpoint)
|
|
1368
1512
|
return Session.verify_success(resp.status)
|
|
1369
1513
|
|
|
1370
1514
|
def execute_statement(self, sql: str, timeout=0):
|
|
@@ -1526,7 +1670,7 @@ class Session(object):
|
|
|
1526
1670
|
):
|
|
1527
1671
|
return 0
|
|
1528
1672
|
|
|
1529
|
-
raise RuntimeError(
|
|
1673
|
+
raise RuntimeError(f"{status.code}: {status.message}")
|
|
1530
1674
|
|
|
1531
1675
|
@staticmethod
|
|
1532
1676
|
def verify_success_by_list(status_list: list):
|
|
@@ -1534,14 +1678,15 @@ class Session(object):
|
|
|
1534
1678
|
verify success of operation
|
|
1535
1679
|
:param status_list: execution result status
|
|
1536
1680
|
"""
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1681
|
+
error_messages = [
|
|
1682
|
+
status.message
|
|
1683
|
+
for status in status_list
|
|
1684
|
+
if status.code
|
|
1685
|
+
not in {Session.SUCCESS_STATUS, Session.REDIRECTION_RECOMMEND}
|
|
1686
|
+
]
|
|
1687
|
+
if error_messages:
|
|
1688
|
+
message = f"{Session.MULTIPLE_ERROR}: {'; '.join(error_messages)}"
|
|
1689
|
+
raise RuntimeError(message)
|
|
1545
1690
|
|
|
1546
1691
|
@staticmethod
|
|
1547
1692
|
def verify_success_with_redirection(status: TSStatus):
|
|
@@ -1842,6 +1987,49 @@ class Session(object):
|
|
|
1842
1987
|
)
|
|
1843
1988
|
return request
|
|
1844
1989
|
|
|
1990
|
+
def __has_none_value(self, values_list) -> bool:
|
|
1991
|
+
for item in values_list:
|
|
1992
|
+
if isinstance(item, list):
|
|
1993
|
+
if self.__has_none_value(item):
|
|
1994
|
+
return True
|
|
1995
|
+
elif item is None:
|
|
1996
|
+
return True
|
|
1997
|
+
return False
|
|
1998
|
+
|
|
1999
|
+
@staticmethod
|
|
2000
|
+
def __filter_lists_by_values(
|
|
2001
|
+
device_lst, time_lst, measurements_lst, types_lst, values_lst
|
|
2002
|
+
):
|
|
2003
|
+
filtered_devices = []
|
|
2004
|
+
filtered_times = []
|
|
2005
|
+
filtered_measurements = []
|
|
2006
|
+
filtered_types = []
|
|
2007
|
+
filtered_values = []
|
|
2008
|
+
|
|
2009
|
+
for device, time_, measurements, types, values in zip(
|
|
2010
|
+
device_lst, time_lst, measurements_lst, types_lst, values_lst
|
|
2011
|
+
):
|
|
2012
|
+
filtered_row = [
|
|
2013
|
+
(m, t, v)
|
|
2014
|
+
for m, t, v in zip(measurements, types, values)
|
|
2015
|
+
if v is not None
|
|
2016
|
+
]
|
|
2017
|
+
if filtered_row:
|
|
2018
|
+
f_measurements, f_types, f_values = zip(*filtered_row)
|
|
2019
|
+
filtered_measurements.append(list(f_measurements))
|
|
2020
|
+
filtered_types.append(list(f_types))
|
|
2021
|
+
filtered_values.append(list(f_values))
|
|
2022
|
+
filtered_devices.append(device)
|
|
2023
|
+
filtered_times.append(time_)
|
|
2024
|
+
|
|
2025
|
+
return (
|
|
2026
|
+
filtered_devices,
|
|
2027
|
+
filtered_times,
|
|
2028
|
+
filtered_measurements,
|
|
2029
|
+
filtered_types,
|
|
2030
|
+
filtered_values,
|
|
2031
|
+
)
|
|
2032
|
+
|
|
1845
2033
|
def create_schema_template(self, template: Template):
|
|
1846
2034
|
warnings.warn(
|
|
1847
2035
|
"The APIs about template are deprecated and will be removed in future versions. Use sql instead.",
|
|
@@ -2253,6 +2441,17 @@ class SessionConnection(object):
|
|
|
2253
2441
|
self.session_id = session_id
|
|
2254
2442
|
self.statement_id = statement_id
|
|
2255
2443
|
|
|
2444
|
+
def change_database(self, sql):
|
|
2445
|
+
try:
|
|
2446
|
+
self.client.executeUpdateStatement(
|
|
2447
|
+
TSExecuteStatementReq(self.session_id, sql, self.statement_id)
|
|
2448
|
+
)
|
|
2449
|
+
except TTransport.TException as e:
|
|
2450
|
+
raise IoTDBConnectionException(
|
|
2451
|
+
"failed to change database",
|
|
2452
|
+
e,
|
|
2453
|
+
) from None
|
|
2454
|
+
|
|
2256
2455
|
def close_connection(self, req):
|
|
2257
2456
|
try:
|
|
2258
2457
|
self.client.closeSession(req)
|
|
@@ -27,6 +27,7 @@ DEFAULT_MULTIPIE = 5
|
|
|
27
27
|
DEFAULT_FETCH_SIZE = 5000
|
|
28
28
|
DEFAULT_MAX_RETRY = 3
|
|
29
29
|
DEFAULT_TIME_ZONE = "UTC+8"
|
|
30
|
+
SQL_DIALECT = "tree"
|
|
30
31
|
logger = logging.getLogger("IoTDB")
|
|
31
32
|
|
|
32
33
|
|
|
@@ -42,6 +43,7 @@ class PoolConfig(object):
|
|
|
42
43
|
time_zone: str = DEFAULT_TIME_ZONE,
|
|
43
44
|
max_retry: int = DEFAULT_MAX_RETRY,
|
|
44
45
|
enable_compression: bool = False,
|
|
46
|
+
enable_redirection: bool = True,
|
|
45
47
|
):
|
|
46
48
|
self.host = host
|
|
47
49
|
self.port = port
|
|
@@ -58,6 +60,7 @@ class PoolConfig(object):
|
|
|
58
60
|
self.time_zone = time_zone
|
|
59
61
|
self.max_retry = max_retry
|
|
60
62
|
self.enable_compression = enable_compression
|
|
63
|
+
self.enable_redirection = enable_redirection
|
|
61
64
|
|
|
62
65
|
|
|
63
66
|
class SessionPool(object):
|
|
@@ -71,6 +74,8 @@ class SessionPool(object):
|
|
|
71
74
|
self.__queue = Queue(max_pool_size)
|
|
72
75
|
self.__lock = Lock()
|
|
73
76
|
self.__closed = False
|
|
77
|
+
self.sql_dialect = SQL_DIALECT
|
|
78
|
+
self.database = None
|
|
74
79
|
|
|
75
80
|
def __construct_session(self) -> Session:
|
|
76
81
|
if len(self.__pool_config.node_urls) > 0:
|
|
@@ -80,7 +85,10 @@ class SessionPool(object):
|
|
|
80
85
|
self.__pool_config.password,
|
|
81
86
|
self.__pool_config.fetch_size,
|
|
82
87
|
self.__pool_config.time_zone,
|
|
88
|
+
enable_redirection=self.__pool_config.enable_redirection,
|
|
83
89
|
)
|
|
90
|
+
session.sql_dialect = self.sql_dialect
|
|
91
|
+
session.database = self.database
|
|
84
92
|
|
|
85
93
|
else:
|
|
86
94
|
session = Session(
|
|
@@ -90,7 +98,10 @@ class SessionPool(object):
|
|
|
90
98
|
self.__pool_config.password,
|
|
91
99
|
self.__pool_config.fetch_size,
|
|
92
100
|
self.__pool_config.time_zone,
|
|
101
|
+
enable_redirection=self.__pool_config.enable_redirection,
|
|
93
102
|
)
|
|
103
|
+
session.sql_dialect = self.sql_dialect
|
|
104
|
+
session.database = self.database
|
|
94
105
|
|
|
95
106
|
session.open(self.__pool_config.enable_compression)
|
|
96
107
|
return session
|
|
@@ -18,13 +18,14 @@
|
|
|
18
18
|
|
|
19
19
|
from sqlalchemy import types, util
|
|
20
20
|
from sqlalchemy.engine import default
|
|
21
|
+
from sqlalchemy.sql import text
|
|
21
22
|
from sqlalchemy.sql.sqltypes import String
|
|
22
23
|
|
|
23
24
|
from iotdb import dbapi
|
|
24
25
|
|
|
26
|
+
from .IoTDBIdentifierPreparer import IoTDBIdentifierPreparer
|
|
25
27
|
from .IoTDBSQLCompiler import IoTDBSQLCompiler
|
|
26
28
|
from .IoTDBTypeCompiler import IoTDBTypeCompiler
|
|
27
|
-
from .IoTDBIdentifierPreparer import IoTDBIdentifierPreparer
|
|
28
29
|
|
|
29
30
|
TYPES_MAP = {
|
|
30
31
|
"BOOLEAN": types.Boolean,
|
|
@@ -68,6 +69,10 @@ class IoTDBDialect(default.DefaultDialect):
|
|
|
68
69
|
opts.update({"sqlalchemy_mode": True})
|
|
69
70
|
return [[], opts]
|
|
70
71
|
|
|
72
|
+
@classmethod
|
|
73
|
+
def import_dbapi(cls):
|
|
74
|
+
return dbapi
|
|
75
|
+
|
|
71
76
|
@classmethod
|
|
72
77
|
def dbapi(cls):
|
|
73
78
|
return dbapi
|
|
@@ -79,17 +84,19 @@ class IoTDBDialect(default.DefaultDialect):
|
|
|
79
84
|
return table_name in self.get_table_names(connection, schema=schema)
|
|
80
85
|
|
|
81
86
|
def get_schema_names(self, connection, **kw):
|
|
82
|
-
cursor = connection.execute("SHOW DATABASES")
|
|
87
|
+
cursor = connection.execute(text("SHOW DATABASES"))
|
|
83
88
|
return [row[0] for row in cursor.fetchall()]
|
|
84
89
|
|
|
85
90
|
def get_table_names(self, connection, schema=None, **kw):
|
|
86
91
|
cursor = connection.execute(
|
|
87
|
-
"SHOW DEVICES %s.**" % (schema or self.default_schema_name)
|
|
92
|
+
text("SHOW DEVICES %s.**" % (schema or self.default_schema_name))
|
|
88
93
|
)
|
|
89
94
|
return [row[0].replace(schema + ".", "", 1) for row in cursor.fetchall()]
|
|
90
95
|
|
|
91
96
|
def get_columns(self, connection, table_name, schema=None, **kw):
|
|
92
|
-
cursor = connection.execute(
|
|
97
|
+
cursor = connection.execute(
|
|
98
|
+
text("SHOW TIMESERIES %s.%s.*" % (schema, table_name))
|
|
99
|
+
)
|
|
93
100
|
columns = [self._general_time_column_info()]
|
|
94
101
|
for row in cursor.fetchall():
|
|
95
102
|
columns.append(self._create_column_info(row, schema, table_name))
|