matrixone-python-sdk 0.1.0__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.
- matrixone/__init__.py +155 -0
- matrixone/account.py +723 -0
- matrixone/async_client.py +3913 -0
- matrixone/async_metadata_manager.py +311 -0
- matrixone/async_orm.py +123 -0
- matrixone/async_vector_index_manager.py +633 -0
- matrixone/base_client.py +208 -0
- matrixone/client.py +4672 -0
- matrixone/config.py +452 -0
- matrixone/connection_hooks.py +286 -0
- matrixone/exceptions.py +89 -0
- matrixone/logger.py +782 -0
- matrixone/metadata.py +820 -0
- matrixone/moctl.py +219 -0
- matrixone/orm.py +2277 -0
- matrixone/pitr.py +646 -0
- matrixone/pubsub.py +771 -0
- matrixone/restore.py +411 -0
- matrixone/search_vector_index.py +1176 -0
- matrixone/snapshot.py +550 -0
- matrixone/sql_builder.py +844 -0
- matrixone/sqlalchemy_ext/__init__.py +161 -0
- matrixone/sqlalchemy_ext/adapters.py +163 -0
- matrixone/sqlalchemy_ext/dialect.py +534 -0
- matrixone/sqlalchemy_ext/fulltext_index.py +895 -0
- matrixone/sqlalchemy_ext/fulltext_search.py +1686 -0
- matrixone/sqlalchemy_ext/hnsw_config.py +194 -0
- matrixone/sqlalchemy_ext/ivf_config.py +252 -0
- matrixone/sqlalchemy_ext/table_builder.py +351 -0
- matrixone/sqlalchemy_ext/vector_index.py +1721 -0
- matrixone/sqlalchemy_ext/vector_type.py +948 -0
- matrixone/version.py +580 -0
- matrixone_python_sdk-0.1.0.dist-info/METADATA +706 -0
- matrixone_python_sdk-0.1.0.dist-info/RECORD +122 -0
- matrixone_python_sdk-0.1.0.dist-info/WHEEL +5 -0
- matrixone_python_sdk-0.1.0.dist-info/entry_points.txt +5 -0
- matrixone_python_sdk-0.1.0.dist-info/licenses/LICENSE +200 -0
- matrixone_python_sdk-0.1.0.dist-info/top_level.txt +2 -0
- tests/__init__.py +19 -0
- tests/offline/__init__.py +20 -0
- tests/offline/conftest.py +77 -0
- tests/offline/test_account.py +703 -0
- tests/offline/test_async_client_query_comprehensive.py +1218 -0
- tests/offline/test_basic.py +54 -0
- tests/offline/test_case_sensitivity.py +227 -0
- tests/offline/test_connection_hooks_offline.py +287 -0
- tests/offline/test_dialect_schema_handling.py +609 -0
- tests/offline/test_explain_methods.py +346 -0
- tests/offline/test_filter_logical_in.py +237 -0
- tests/offline/test_fulltext_search_comprehensive.py +795 -0
- tests/offline/test_ivf_config.py +249 -0
- tests/offline/test_join_methods.py +281 -0
- tests/offline/test_join_sqlalchemy_compatibility.py +276 -0
- tests/offline/test_logical_in_method.py +237 -0
- tests/offline/test_matrixone_version_parsing.py +264 -0
- tests/offline/test_metadata_offline.py +557 -0
- tests/offline/test_moctl.py +300 -0
- tests/offline/test_moctl_simple.py +251 -0
- tests/offline/test_model_support_offline.py +359 -0
- tests/offline/test_model_support_simple.py +225 -0
- tests/offline/test_pinecone_filter_offline.py +377 -0
- tests/offline/test_pitr.py +585 -0
- tests/offline/test_pubsub.py +712 -0
- tests/offline/test_query_update.py +283 -0
- tests/offline/test_restore.py +445 -0
- tests/offline/test_snapshot_comprehensive.py +384 -0
- tests/offline/test_sql_escaping_edge_cases.py +551 -0
- tests/offline/test_sqlalchemy_integration.py +382 -0
- tests/offline/test_sqlalchemy_vector_integration.py +434 -0
- tests/offline/test_table_builder.py +198 -0
- tests/offline/test_unified_filter.py +398 -0
- tests/offline/test_unified_transaction.py +495 -0
- tests/offline/test_vector_index.py +238 -0
- tests/offline/test_vector_operations.py +688 -0
- tests/offline/test_vector_type.py +174 -0
- tests/offline/test_version_core.py +328 -0
- tests/offline/test_version_management.py +372 -0
- tests/offline/test_version_standalone.py +652 -0
- tests/online/__init__.py +20 -0
- tests/online/conftest.py +216 -0
- tests/online/test_account_management.py +194 -0
- tests/online/test_advanced_features.py +344 -0
- tests/online/test_async_client_interfaces.py +330 -0
- tests/online/test_async_client_online.py +285 -0
- tests/online/test_async_model_insert_online.py +293 -0
- tests/online/test_async_orm_online.py +300 -0
- tests/online/test_async_simple_query_online.py +802 -0
- tests/online/test_async_transaction_simple_query.py +300 -0
- tests/online/test_basic_connection.py +130 -0
- tests/online/test_client_online.py +238 -0
- tests/online/test_config.py +90 -0
- tests/online/test_config_validation.py +123 -0
- tests/online/test_connection_hooks_new_online.py +217 -0
- tests/online/test_dialect_schema_handling_online.py +331 -0
- tests/online/test_filter_logical_in_online.py +374 -0
- tests/online/test_fulltext_comprehensive.py +1773 -0
- tests/online/test_fulltext_label_online.py +433 -0
- tests/online/test_fulltext_search_online.py +842 -0
- tests/online/test_ivf_stats_online.py +506 -0
- tests/online/test_logger_integration.py +311 -0
- tests/online/test_matrixone_query_orm.py +540 -0
- tests/online/test_metadata_online.py +579 -0
- tests/online/test_model_insert_online.py +255 -0
- tests/online/test_mysql_driver_validation.py +213 -0
- tests/online/test_orm_advanced_features.py +2022 -0
- tests/online/test_orm_cte_integration.py +269 -0
- tests/online/test_orm_online.py +270 -0
- tests/online/test_pinecone_filter.py +708 -0
- tests/online/test_pubsub_operations.py +352 -0
- tests/online/test_query_methods.py +225 -0
- tests/online/test_query_update_online.py +433 -0
- tests/online/test_search_vector_index.py +557 -0
- tests/online/test_simple_fulltext_online.py +915 -0
- tests/online/test_snapshot_comprehensive.py +998 -0
- tests/online/test_sqlalchemy_engine_integration.py +336 -0
- tests/online/test_sqlalchemy_integration.py +425 -0
- tests/online/test_transaction_contexts.py +1219 -0
- tests/online/test_transaction_insert_methods.py +356 -0
- tests/online/test_transaction_query_methods.py +288 -0
- tests/online/test_unified_filter_online.py +529 -0
- tests/online/test_vector_comprehensive.py +706 -0
- tests/online/test_version_management.py +291 -0
matrixone/restore.py
ADDED
@@ -0,0 +1,411 @@
|
|
1
|
+
# Copyright 2021 - 2022 Matrix Origin
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
"""
|
16
|
+
MatrixOne Python SDK - Restore Manager
|
17
|
+
Provides restore functionality for MatrixOne snapshots
|
18
|
+
"""
|
19
|
+
|
20
|
+
from typing import Optional
|
21
|
+
|
22
|
+
from .exceptions import RestoreError
|
23
|
+
|
24
|
+
|
25
|
+
class RestoreManager:
|
26
|
+
"""
|
27
|
+
Manager for restore operations from snapshots in MatrixOne.
|
28
|
+
|
29
|
+
This class provides comprehensive restore functionality for recovering data
|
30
|
+
from snapshots. It supports restoring entire clusters, databases, or tables
|
31
|
+
from previously created snapshots, enabling data recovery and disaster
|
32
|
+
recovery scenarios.
|
33
|
+
|
34
|
+
Key Features:
|
35
|
+
|
36
|
+
- Restore entire clusters from snapshots
|
37
|
+
- Restore specific databases from snapshots
|
38
|
+
- Restore individual tables from snapshots
|
39
|
+
- Integration with snapshot management
|
40
|
+
- Transaction-aware restore operations
|
41
|
+
- Support for both full and incremental restores
|
42
|
+
|
43
|
+
Supported Restore Levels:
|
44
|
+
- CLUSTER: Full cluster restore from snapshot
|
45
|
+
- DATABASE: Database-level restore from snapshot
|
46
|
+
- TABLE: Table-level restore from snapshot
|
47
|
+
|
48
|
+
Usage Examples::
|
49
|
+
|
50
|
+
# Initialize restore manager
|
51
|
+
restore = client.restore
|
52
|
+
|
53
|
+
# Restore entire cluster from snapshot
|
54
|
+
success = restore.restore_cluster('daily_backup_snapshot')
|
55
|
+
|
56
|
+
# Restore database from snapshot
|
57
|
+
success = restore.restore_database(
|
58
|
+
snapshot_name='daily_backup',
|
59
|
+
target_database='restored_database'
|
60
|
+
)
|
61
|
+
|
62
|
+
# Restore table from snapshot
|
63
|
+
success = restore.restore_table(
|
64
|
+
snapshot_name='users_backup',
|
65
|
+
target_database='restored_database',
|
66
|
+
target_table='restored_users'
|
67
|
+
)
|
68
|
+
|
69
|
+
# List available snapshots for restore
|
70
|
+
snapshots = client.snapshots.list()
|
71
|
+
|
72
|
+
# Get restore status
|
73
|
+
status = restore.get_restore_status('restore_job_id')
|
74
|
+
|
75
|
+
Note: Restore operations require appropriate snapshots to be available. Restore operations may
|
76
|
+
take significant time depending on the amount of data being restored and the snapshot size.
|
77
|
+
"""
|
78
|
+
|
79
|
+
def __init__(self, client):
|
80
|
+
"""Initialize RestoreManager with client connection"""
|
81
|
+
self._client = client
|
82
|
+
|
83
|
+
def restore_cluster(self, snapshot_name: str) -> bool:
|
84
|
+
"""
|
85
|
+
Restore entire cluster from snapshot
|
86
|
+
|
87
|
+
Args::
|
88
|
+
|
89
|
+
snapshot_name: Name of the snapshot to restore from
|
90
|
+
|
91
|
+
Returns::
|
92
|
+
|
93
|
+
bool: True if restore was successful
|
94
|
+
|
95
|
+
Raises::
|
96
|
+
|
97
|
+
RestoreError: If restore operation fails
|
98
|
+
|
99
|
+
Example
|
100
|
+
|
101
|
+
>>> client = Client()
|
102
|
+
>>> client.connect(...)
|
103
|
+
>>> success = client.restore.restore_cluster("cluster_snapshot_1")
|
104
|
+
"""
|
105
|
+
try:
|
106
|
+
sql = f"RESTORE CLUSTER FROM SNAPSHOT {self._client._escape_identifier(snapshot_name)}"
|
107
|
+
result = self._client.execute(sql)
|
108
|
+
return result is not None
|
109
|
+
except Exception as e:
|
110
|
+
raise RestoreError(f"Failed to restore cluster from snapshot '{snapshot_name}': {e}") from None
|
111
|
+
|
112
|
+
def restore_tenant(self, snapshot_name: str, account_name: str, to_account: Optional[str] = None) -> bool:
|
113
|
+
"""
|
114
|
+
Restore tenant from snapshot
|
115
|
+
|
116
|
+
Args::
|
117
|
+
|
118
|
+
snapshot_name: Name of the snapshot to restore from
|
119
|
+
account_name: Name of the account to restore
|
120
|
+
to_account: Optional target account name (for cross-tenant restore)
|
121
|
+
|
122
|
+
Returns::
|
123
|
+
|
124
|
+
bool: True if restore was successful
|
125
|
+
|
126
|
+
Raises::
|
127
|
+
|
128
|
+
RestoreError: If restore operation fails
|
129
|
+
|
130
|
+
Example
|
131
|
+
|
132
|
+
>>> # Restore tenant to itself
|
133
|
+
>>> success = client.restore.restore_tenant("acc1_snap1", "acc1")
|
134
|
+
>>>
|
135
|
+
>>> # Restore tenant to new tenant
|
136
|
+
>>> success = client.restore.restore_tenant("acc1_snap1", "acc1", "acc2")
|
137
|
+
"""
|
138
|
+
try:
|
139
|
+
if to_account:
|
140
|
+
# Cross-tenant restore
|
141
|
+
sql = (
|
142
|
+
f"RESTORE ACCOUNT {self._client._escape_identifier(account_name)} "
|
143
|
+
f"FROM SNAPSHOT {self._client._escape_identifier(snapshot_name)} "
|
144
|
+
f"TO ACCOUNT {self._client._escape_identifier(to_account)}"
|
145
|
+
)
|
146
|
+
else:
|
147
|
+
# Restore to same tenant
|
148
|
+
sql = (
|
149
|
+
f"RESTORE ACCOUNT {self._client._escape_identifier(account_name)} "
|
150
|
+
f"FROM SNAPSHOT {self._client._escape_identifier(snapshot_name)}"
|
151
|
+
)
|
152
|
+
|
153
|
+
result = self._client.execute(sql)
|
154
|
+
return result is not None
|
155
|
+
except Exception as e:
|
156
|
+
raise RestoreError(f"Failed to restore tenant '{account_name}' from snapshot '{snapshot_name}': {e}") from None
|
157
|
+
|
158
|
+
def restore_database(
|
159
|
+
self,
|
160
|
+
snapshot_name: str,
|
161
|
+
account_name: str,
|
162
|
+
database_name: str,
|
163
|
+
to_account: Optional[str] = None,
|
164
|
+
) -> bool:
|
165
|
+
"""
|
166
|
+
Restore database from snapshot
|
167
|
+
|
168
|
+
Args::
|
169
|
+
|
170
|
+
snapshot_name: Name of the snapshot to restore from
|
171
|
+
account_name: Name of the account
|
172
|
+
database_name: Name of the database to restore
|
173
|
+
to_account: Optional target account name (for cross-tenant restore)
|
174
|
+
|
175
|
+
Returns::
|
176
|
+
|
177
|
+
bool: True if restore was successful
|
178
|
+
|
179
|
+
Raises::
|
180
|
+
|
181
|
+
RestoreError: If restore operation fails
|
182
|
+
|
183
|
+
Example
|
184
|
+
|
185
|
+
>>> success = client.restore.restore_database("acc1_db_snap1", "acc1", "db1")
|
186
|
+
"""
|
187
|
+
try:
|
188
|
+
if to_account:
|
189
|
+
# Cross-tenant restore
|
190
|
+
sql = (
|
191
|
+
f"RESTORE ACCOUNT {self._client._escape_identifier(account_name)} "
|
192
|
+
f"DATABASE {self._client._escape_identifier(database_name)} "
|
193
|
+
f"FROM SNAPSHOT {self._client._escape_identifier(snapshot_name)} "
|
194
|
+
f"TO ACCOUNT {self._client._escape_identifier(to_account)}"
|
195
|
+
)
|
196
|
+
else:
|
197
|
+
# Restore to same tenant
|
198
|
+
sql = (
|
199
|
+
f"RESTORE ACCOUNT {self._client._escape_identifier(account_name)} "
|
200
|
+
f"DATABASE {self._client._escape_identifier(database_name)} "
|
201
|
+
f"FROM SNAPSHOT {self._client._escape_identifier(snapshot_name)}"
|
202
|
+
)
|
203
|
+
|
204
|
+
result = self._client.execute(sql)
|
205
|
+
return result is not None
|
206
|
+
except Exception as e:
|
207
|
+
raise RestoreError(f"Failed to restore database '{database_name}' from snapshot '{snapshot_name}': {e}") from None
|
208
|
+
|
209
|
+
def restore_table(
|
210
|
+
self,
|
211
|
+
snapshot_name: str,
|
212
|
+
account_name: str,
|
213
|
+
database_name: str,
|
214
|
+
table_name: str,
|
215
|
+
to_account: Optional[str] = None,
|
216
|
+
) -> bool:
|
217
|
+
"""
|
218
|
+
Restore table from snapshot
|
219
|
+
|
220
|
+
Args::
|
221
|
+
|
222
|
+
snapshot_name: Name of the snapshot to restore from
|
223
|
+
account_name: Name of the account
|
224
|
+
database_name: Name of the database
|
225
|
+
table_name: Name of the table to restore
|
226
|
+
to_account: Optional target account name (for cross-tenant restore)
|
227
|
+
|
228
|
+
Returns::
|
229
|
+
|
230
|
+
bool: True if restore was successful
|
231
|
+
|
232
|
+
Raises::
|
233
|
+
|
234
|
+
RestoreError: If restore operation fails
|
235
|
+
|
236
|
+
Example
|
237
|
+
|
238
|
+
>>> success = client.restore.restore_table("acc1_tab_snap1", "acc1", "db1", "t1")
|
239
|
+
"""
|
240
|
+
try:
|
241
|
+
if to_account:
|
242
|
+
# Cross-tenant restore
|
243
|
+
sql = (
|
244
|
+
f"RESTORE ACCOUNT {self._client._escape_identifier(account_name)} "
|
245
|
+
f"DATABASE {self._client._escape_identifier(database_name)} "
|
246
|
+
f"TABLE {self._client._escape_identifier(table_name)} "
|
247
|
+
f"FROM SNAPSHOT {self._client._escape_identifier(snapshot_name)} "
|
248
|
+
f"TO ACCOUNT {self._client._escape_identifier(to_account)}"
|
249
|
+
)
|
250
|
+
else:
|
251
|
+
# Restore to same tenant
|
252
|
+
sql = (
|
253
|
+
f"RESTORE ACCOUNT {self._client._escape_identifier(account_name)} "
|
254
|
+
f"DATABASE {self._client._escape_identifier(database_name)} "
|
255
|
+
f"TABLE {self._client._escape_identifier(table_name)} "
|
256
|
+
f"FROM SNAPSHOT {self._client._escape_identifier(snapshot_name)}"
|
257
|
+
)
|
258
|
+
|
259
|
+
result = self._client.execute(sql)
|
260
|
+
return result is not None
|
261
|
+
except Exception as e:
|
262
|
+
raise RestoreError(f"Failed to restore table '{table_name}' from snapshot '{snapshot_name}': {e}") from None
|
263
|
+
|
264
|
+
def restore_with_executor(
|
265
|
+
self,
|
266
|
+
restore_type: str,
|
267
|
+
snapshot_name: str,
|
268
|
+
account_name: Optional[str] = None,
|
269
|
+
database_name: Optional[str] = None,
|
270
|
+
table_name: Optional[str] = None,
|
271
|
+
to_account: Optional[str] = None,
|
272
|
+
executor=None,
|
273
|
+
) -> bool:
|
274
|
+
"""
|
275
|
+
Restore with custom executor (for transaction support)
|
276
|
+
|
277
|
+
Args::
|
278
|
+
|
279
|
+
restore_type: Type of restore ('cluster', 'tenant', 'database', 'table')
|
280
|
+
snapshot_name: Name of the snapshot to restore from
|
281
|
+
account_name: Name of the account (required for tenant/database/table)
|
282
|
+
database_name: Name of the database (required for database/table)
|
283
|
+
table_name: Name of the table (required for table)
|
284
|
+
to_account: Optional target account name
|
285
|
+
executor: Custom executor (transaction wrapper)
|
286
|
+
|
287
|
+
Returns::
|
288
|
+
|
289
|
+
bool: True if restore was successful
|
290
|
+
"""
|
291
|
+
try:
|
292
|
+
if restore_type == "cluster":
|
293
|
+
sql = f"RESTORE CLUSTER FROM SNAPSHOT {self._client._escape_identifier(snapshot_name)}"
|
294
|
+
elif restore_type == "tenant":
|
295
|
+
if not account_name:
|
296
|
+
raise RestoreError("Account name is required for tenant restore") from None
|
297
|
+
if to_account:
|
298
|
+
sql = (
|
299
|
+
f"RESTORE ACCOUNT {self._client._escape_identifier(account_name)} "
|
300
|
+
f"FROM SNAPSHOT {self._client._escape_identifier(snapshot_name)} "
|
301
|
+
f"TO ACCOUNT {self._client._escape_identifier(to_account)}"
|
302
|
+
)
|
303
|
+
else:
|
304
|
+
sql = (
|
305
|
+
f"RESTORE ACCOUNT {self._client._escape_identifier(account_name)} "
|
306
|
+
f"FROM SNAPSHOT {self._client._escape_identifier(snapshot_name)}"
|
307
|
+
)
|
308
|
+
elif restore_type == "database":
|
309
|
+
if not account_name or not database_name:
|
310
|
+
raise RestoreError("Account name and database name are required for database restore") from None
|
311
|
+
if to_account:
|
312
|
+
sql = (
|
313
|
+
f"RESTORE ACCOUNT {self._client._escape_identifier(account_name)} "
|
314
|
+
f"DATABASE {self._client._escape_identifier(database_name)} "
|
315
|
+
f"FROM SNAPSHOT {self._client._escape_identifier(snapshot_name)} "
|
316
|
+
f"TO ACCOUNT {self._client._escape_identifier(to_account)}"
|
317
|
+
)
|
318
|
+
else:
|
319
|
+
sql = (
|
320
|
+
f"RESTORE ACCOUNT {self._client._escape_identifier(account_name)} "
|
321
|
+
f"DATABASE {self._client._escape_identifier(database_name)} "
|
322
|
+
f"FROM SNAPSHOT {self._client._escape_identifier(snapshot_name)}"
|
323
|
+
)
|
324
|
+
elif restore_type == "table":
|
325
|
+
if not all([account_name, database_name, table_name]):
|
326
|
+
raise RestoreError("Account name, database name, and table name are required for table restore") from None
|
327
|
+
if to_account:
|
328
|
+
sql = (
|
329
|
+
f"RESTORE ACCOUNT {self._client._escape_identifier(account_name)} "
|
330
|
+
f"DATABASE {self._client._escape_identifier(database_name)} "
|
331
|
+
f"TABLE {self._client._escape_identifier(table_name)} "
|
332
|
+
f"FROM SNAPSHOT {self._client._escape_identifier(snapshot_name)} "
|
333
|
+
f"TO ACCOUNT {self._client._escape_identifier(to_account)}"
|
334
|
+
)
|
335
|
+
else:
|
336
|
+
sql = (
|
337
|
+
f"RESTORE ACCOUNT {self._client._escape_identifier(account_name)} "
|
338
|
+
f"DATABASE {self._client._escape_identifier(database_name)} "
|
339
|
+
f"TABLE {self._client._escape_identifier(table_name)} "
|
340
|
+
f"FROM SNAPSHOT {self._client._escape_identifier(snapshot_name)}"
|
341
|
+
)
|
342
|
+
else:
|
343
|
+
raise RestoreError(f"Invalid restore type: {restore_type}") from None
|
344
|
+
|
345
|
+
if executor:
|
346
|
+
result = executor.execute(sql)
|
347
|
+
else:
|
348
|
+
result = self._client.execute(sql)
|
349
|
+
|
350
|
+
return result is not None
|
351
|
+
except Exception as e:
|
352
|
+
raise RestoreError(f"Failed to restore {restore_type} from snapshot '{snapshot_name}': {e}") from None
|
353
|
+
|
354
|
+
|
355
|
+
class TransactionRestoreManager(RestoreManager):
|
356
|
+
"""RestoreManager for use within transactions"""
|
357
|
+
|
358
|
+
def __init__(self, client, transaction_wrapper):
|
359
|
+
"""Initialize TransactionRestoreManager with client and transaction wrapper"""
|
360
|
+
super().__init__(client)
|
361
|
+
self._transaction_wrapper = transaction_wrapper
|
362
|
+
|
363
|
+
def restore_cluster(self, snapshot_name: str) -> bool:
|
364
|
+
"""Restore cluster within transaction"""
|
365
|
+
return self.restore_with_executor("cluster", snapshot_name, executor=self._transaction_wrapper)
|
366
|
+
|
367
|
+
def restore_tenant(self, snapshot_name: str, account_name: str, to_account: Optional[str] = None) -> bool:
|
368
|
+
"""Restore tenant within transaction"""
|
369
|
+
return self.restore_with_executor(
|
370
|
+
"tenant",
|
371
|
+
snapshot_name,
|
372
|
+
account_name,
|
373
|
+
to_account=to_account,
|
374
|
+
executor=self._transaction_wrapper,
|
375
|
+
)
|
376
|
+
|
377
|
+
def restore_database(
|
378
|
+
self,
|
379
|
+
snapshot_name: str,
|
380
|
+
account_name: str,
|
381
|
+
database_name: str,
|
382
|
+
to_account: Optional[str] = None,
|
383
|
+
) -> bool:
|
384
|
+
"""Restore database within transaction"""
|
385
|
+
return self.restore_with_executor(
|
386
|
+
"database",
|
387
|
+
snapshot_name,
|
388
|
+
account_name,
|
389
|
+
database_name,
|
390
|
+
to_account=to_account,
|
391
|
+
executor=self._transaction_wrapper,
|
392
|
+
)
|
393
|
+
|
394
|
+
def restore_table(
|
395
|
+
self,
|
396
|
+
snapshot_name: str,
|
397
|
+
account_name: str,
|
398
|
+
database_name: str,
|
399
|
+
table_name: str,
|
400
|
+
to_account: Optional[str] = None,
|
401
|
+
) -> bool:
|
402
|
+
"""Restore table within transaction"""
|
403
|
+
return self.restore_with_executor(
|
404
|
+
"table",
|
405
|
+
snapshot_name,
|
406
|
+
account_name,
|
407
|
+
database_name,
|
408
|
+
table_name,
|
409
|
+
to_account=to_account,
|
410
|
+
executor=self._transaction_wrapper,
|
411
|
+
)
|