singlestoredb 1.8.0__cp38-abi3-win32.whl → 1.9.0__cp38-abi3-win32.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.
Potentially problematic release.
This version of singlestoredb might be problematic. Click here for more details.
- _singlestoredb_accel.pyd +0 -0
- singlestoredb/__init__.py +2 -2
- singlestoredb/config.py +6 -0
- singlestoredb/connection.py +11 -0
- singlestoredb/fusion/handler.py +3 -0
- singlestoredb/fusion/handlers/export.py +6 -14
- singlestoredb/fusion/handlers/files.py +690 -0
- singlestoredb/fusion/handlers/stage.py +103 -91
- singlestoredb/fusion/handlers/utils.py +148 -0
- singlestoredb/management/__init__.py +1 -0
- singlestoredb/management/export.py +20 -184
- singlestoredb/management/files.py +1038 -0
- singlestoredb/management/workspace.py +162 -349
- singlestoredb/mysql/connection.py +9 -1
- singlestoredb/tests/test.ipynb +18 -0
- singlestoredb/tests/test2.ipynb +18 -0
- singlestoredb/tests/test_management.py +273 -1
- {singlestoredb-1.8.0.dist-info → singlestoredb-1.9.0.dist-info}/METADATA +1 -1
- {singlestoredb-1.8.0.dist-info → singlestoredb-1.9.0.dist-info}/RECORD +25 -19
- {singlestoredb-1.8.0.dist-info → singlestoredb-1.9.0.dist-info}/top_level.txt +1 -0
- sqlx/__init__.py +4 -0
- sqlx/magic.py +113 -0
- {singlestoredb-1.8.0.dist-info → singlestoredb-1.9.0.dist-info}/LICENSE +0 -0
- {singlestoredb-1.8.0.dist-info → singlestoredb-1.9.0.dist-info}/WHEEL +0 -0
- {singlestoredb-1.8.0.dist-info → singlestoredb-1.9.0.dist-info}/entry_points.txt +0 -0
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
"""SingleStoreDB export service."""
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
import
|
|
5
|
+
import copy
|
|
6
|
+
import json
|
|
7
7
|
from typing import Any
|
|
8
8
|
from typing import Dict
|
|
9
9
|
from typing import List
|
|
10
10
|
from typing import Optional
|
|
11
|
+
from typing import Union
|
|
11
12
|
|
|
12
13
|
from .. import ManagementError
|
|
13
14
|
from .utils import vars_to_str
|
|
@@ -15,172 +16,13 @@ from .workspace import WorkspaceGroup
|
|
|
15
16
|
from .workspace import WorkspaceManager
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
class Link(object):
|
|
19
|
-
"""Generic storage base class."""
|
|
20
|
-
scheme: str = 'unknown'
|
|
21
|
-
|
|
22
|
-
def __str__(self) -> str:
|
|
23
|
-
"""Return string representation."""
|
|
24
|
-
return vars_to_str(self)
|
|
25
|
-
|
|
26
|
-
def __repr__(self) -> str:
|
|
27
|
-
"""Return string representation."""
|
|
28
|
-
return str(self)
|
|
29
|
-
|
|
30
|
-
@abc.abstractmethod
|
|
31
|
-
def to_storage_location(self) -> Dict[str, Any]:
|
|
32
|
-
raise NotImplementedError
|
|
33
|
-
|
|
34
|
-
@classmethod
|
|
35
|
-
def from_config_and_creds(
|
|
36
|
-
cls,
|
|
37
|
-
scheme: str,
|
|
38
|
-
config: Dict[str, Any],
|
|
39
|
-
credentials: Dict[str, Any],
|
|
40
|
-
manager: 'WorkspaceManager',
|
|
41
|
-
) -> 'Link':
|
|
42
|
-
out_cls = None
|
|
43
|
-
for c in cls.__subclasses__():
|
|
44
|
-
if c.scheme == scheme.upper():
|
|
45
|
-
out_cls = c
|
|
46
|
-
break
|
|
47
|
-
|
|
48
|
-
if out_cls is None:
|
|
49
|
-
raise TypeError(f'No link class found for given information: {scheme}')
|
|
50
|
-
|
|
51
|
-
return out_cls.from_config_and_creds(scheme, config, credentials, manager)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
class S3Link(Link):
|
|
55
|
-
"""S3 link."""
|
|
56
|
-
|
|
57
|
-
scheme: str = 'S3'
|
|
58
|
-
region: str
|
|
59
|
-
storage_base_url: str
|
|
60
|
-
|
|
61
|
-
def __init__(self, region: str, storage_base_url: str):
|
|
62
|
-
self.region = region
|
|
63
|
-
self.storage_base_url = storage_base_url
|
|
64
|
-
self._manager: Optional[WorkspaceManager] = None
|
|
65
|
-
|
|
66
|
-
def to_storage_location(self) -> Dict[str, Any]:
|
|
67
|
-
return dict(
|
|
68
|
-
storageBaseURL=self.storage_base_url,
|
|
69
|
-
storageRegion=self.region,
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
@classmethod
|
|
73
|
-
def from_config_and_creds(
|
|
74
|
-
cls,
|
|
75
|
-
scheme: str,
|
|
76
|
-
config: Dict[str, Any],
|
|
77
|
-
credentials: Dict[str, Any],
|
|
78
|
-
manager: 'WorkspaceManager',
|
|
79
|
-
) -> 'S3Link':
|
|
80
|
-
assert scheme.upper() == cls.scheme
|
|
81
|
-
|
|
82
|
-
params: Dict[str, Any] = {}
|
|
83
|
-
params.update(config)
|
|
84
|
-
params.update(credentials)
|
|
85
|
-
|
|
86
|
-
assert params.get('region'), 'region is required'
|
|
87
|
-
assert params.get('endpoint_url'), 'endpoint_url is required'
|
|
88
|
-
|
|
89
|
-
out = cls(params['region'], params['endpoint_url'])
|
|
90
|
-
out._manager = manager
|
|
91
|
-
return out
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
class Catalog(object):
|
|
95
|
-
"""Generic catalog base class."""
|
|
96
|
-
|
|
97
|
-
catalog_type: str = 'UNKNOWN'
|
|
98
|
-
table_format: str = 'UNKNOWN'
|
|
99
|
-
|
|
100
|
-
def __str__(self) -> str:
|
|
101
|
-
"""Return string representation."""
|
|
102
|
-
return vars_to_str(self)
|
|
103
|
-
|
|
104
|
-
def __repr__(self) -> str:
|
|
105
|
-
"""Return string representation."""
|
|
106
|
-
return str(self)
|
|
107
|
-
|
|
108
|
-
@classmethod
|
|
109
|
-
def from_config_and_creds(
|
|
110
|
-
cls,
|
|
111
|
-
config: Dict[str, Any],
|
|
112
|
-
credentials: Dict[str, Any],
|
|
113
|
-
manager: 'WorkspaceManager',
|
|
114
|
-
) -> 'Catalog':
|
|
115
|
-
catalog_type = config['type'].upper()
|
|
116
|
-
table_format = config['table_format'].upper()
|
|
117
|
-
|
|
118
|
-
out_cls = None
|
|
119
|
-
for c in cls.__subclasses__():
|
|
120
|
-
if c.catalog_type == catalog_type and c.table_format == table_format:
|
|
121
|
-
out_cls = c
|
|
122
|
-
break
|
|
123
|
-
|
|
124
|
-
if out_cls is None:
|
|
125
|
-
raise TypeError(f'No catalog class found for given information: {config}')
|
|
126
|
-
|
|
127
|
-
return out_cls.from_config_and_creds(config, credentials, manager)
|
|
128
|
-
|
|
129
|
-
@abc.abstractmethod
|
|
130
|
-
def to_catalog_info(self) -> Dict[str, Any]:
|
|
131
|
-
"""Return a catalog info dictionary."""
|
|
132
|
-
raise NotImplementedError
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
class IcebergGlueCatalog(Catalog):
|
|
136
|
-
"""Iceberg glue catalog."""
|
|
137
|
-
|
|
138
|
-
table_format = 'ICEBERG'
|
|
139
|
-
catalog_type = 'GLUE'
|
|
140
|
-
|
|
141
|
-
region: str
|
|
142
|
-
catalog_id: str
|
|
143
|
-
|
|
144
|
-
def __init__(self, region: str, catalog_id: str):
|
|
145
|
-
self.region = region
|
|
146
|
-
self.catalog_id = catalog_id
|
|
147
|
-
self._manager: Optional[WorkspaceManager] = None
|
|
148
|
-
|
|
149
|
-
@classmethod
|
|
150
|
-
def from_config_and_creds(
|
|
151
|
-
cls,
|
|
152
|
-
config: Dict[str, Any],
|
|
153
|
-
credentials: Dict[str, Any],
|
|
154
|
-
manager: 'WorkspaceManager',
|
|
155
|
-
) -> 'IcebergGlueCatalog':
|
|
156
|
-
params = {}
|
|
157
|
-
params.update(config)
|
|
158
|
-
params.update(credentials)
|
|
159
|
-
|
|
160
|
-
out = cls(
|
|
161
|
-
region=params['region'],
|
|
162
|
-
catalog_id=params['id'],
|
|
163
|
-
)
|
|
164
|
-
out._manager = manager
|
|
165
|
-
return out
|
|
166
|
-
|
|
167
|
-
def to_catalog_info(self) -> Dict[str, Any]:
|
|
168
|
-
"""Return a catalog info dictionary."""
|
|
169
|
-
return dict(
|
|
170
|
-
catalogSource=self.catalog_type,
|
|
171
|
-
tableFormat=self.table_format,
|
|
172
|
-
glueRegion=self.region,
|
|
173
|
-
glueCatalogID=self.catalog_id,
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
|
|
177
19
|
class ExportService(object):
|
|
178
20
|
"""Export service."""
|
|
179
21
|
|
|
180
22
|
database: str
|
|
181
23
|
table: str
|
|
182
|
-
|
|
183
|
-
|
|
24
|
+
catalog_info: Dict[str, Any]
|
|
25
|
+
storage_info: Dict[str, Any]
|
|
184
26
|
columns: Optional[List[str]]
|
|
185
27
|
|
|
186
28
|
def __init__(
|
|
@@ -188,8 +30,8 @@ class ExportService(object):
|
|
|
188
30
|
workspace_group: WorkspaceGroup,
|
|
189
31
|
database: str,
|
|
190
32
|
table: str,
|
|
191
|
-
|
|
192
|
-
|
|
33
|
+
catalog_info: Union[str, Dict[str, Any]],
|
|
34
|
+
storage_info: Union[str, Dict[str, Any]],
|
|
193
35
|
columns: Optional[List[str]],
|
|
194
36
|
):
|
|
195
37
|
#: Workspace group
|
|
@@ -205,10 +47,16 @@ class ExportService(object):
|
|
|
205
47
|
self.columns = columns
|
|
206
48
|
|
|
207
49
|
#: Catalog
|
|
208
|
-
|
|
50
|
+
if isinstance(catalog_info, str):
|
|
51
|
+
self.catalog_info = json.loads(catalog_info)
|
|
52
|
+
else:
|
|
53
|
+
self.catalog_info = copy.copy(catalog_info)
|
|
209
54
|
|
|
210
55
|
#: Storage
|
|
211
|
-
|
|
56
|
+
if isinstance(storage_info, str):
|
|
57
|
+
self.storage_info = json.loads(storage_info)
|
|
58
|
+
else:
|
|
59
|
+
self.storage_info = copy.copy(storage_info)
|
|
212
60
|
|
|
213
61
|
self._manager: Optional[WorkspaceManager] = workspace_group._manager
|
|
214
62
|
|
|
@@ -227,21 +75,12 @@ class ExportService(object):
|
|
|
227
75
|
msg='No workspace manager is associated with this object.',
|
|
228
76
|
)
|
|
229
77
|
|
|
230
|
-
if not isinstance(self.catalog, IcebergGlueCatalog):
|
|
231
|
-
raise TypeError('Only Iceberg Glue catalog is supported at this time.')
|
|
232
|
-
|
|
233
|
-
if not isinstance(self.storage_link, S3Link):
|
|
234
|
-
raise TypeError('Only S3 links are supported at this time.')
|
|
235
|
-
|
|
236
78
|
out = self._manager._post(
|
|
237
79
|
f'workspaceGroups/{self.workspace_group.id}/'
|
|
238
80
|
'egress/createEgressClusterIdentity',
|
|
239
81
|
json=dict(
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
)[1],
|
|
243
|
-
glueRegion=self.catalog.region,
|
|
244
|
-
glueCatalogID=self.catalog.catalog_id,
|
|
82
|
+
catalogInfo=self.catalog_info,
|
|
83
|
+
storageInfo=self.storage_info,
|
|
245
84
|
),
|
|
246
85
|
)
|
|
247
86
|
|
|
@@ -254,16 +93,13 @@ class ExportService(object):
|
|
|
254
93
|
msg='No workspace manager is associated with this object.',
|
|
255
94
|
)
|
|
256
95
|
|
|
257
|
-
if not isinstance(self.storage_link, S3Link):
|
|
258
|
-
raise TypeError('Only S3 links are supported at this time.')
|
|
259
|
-
|
|
260
96
|
out = self._manager._post(
|
|
261
97
|
f'workspaceGroups/{self.workspace_group.id}/egress/startTableEgress',
|
|
262
98
|
json=dict(
|
|
263
99
|
databaseName=self.database,
|
|
264
100
|
tableName=self.table,
|
|
265
|
-
|
|
266
|
-
catalogInfo=self.
|
|
101
|
+
storageInfo=self.storage_info,
|
|
102
|
+
catalogInfo=self.catalog_info,
|
|
267
103
|
),
|
|
268
104
|
)
|
|
269
105
|
|
|
@@ -286,7 +122,7 @@ class ExportStatus(object):
|
|
|
286
122
|
msg='No workspace manager is associated with this object.',
|
|
287
123
|
)
|
|
288
124
|
|
|
289
|
-
out = self._manager.
|
|
125
|
+
out = self._manager._get(
|
|
290
126
|
f'workspaceGroups/{self.workspace_group.id}/egress/tableEgressStatus',
|
|
291
127
|
json=dict(egressID=self.export_id),
|
|
292
128
|
)
|