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.
Files changed (122) hide show
  1. matrixone/__init__.py +155 -0
  2. matrixone/account.py +723 -0
  3. matrixone/async_client.py +3913 -0
  4. matrixone/async_metadata_manager.py +311 -0
  5. matrixone/async_orm.py +123 -0
  6. matrixone/async_vector_index_manager.py +633 -0
  7. matrixone/base_client.py +208 -0
  8. matrixone/client.py +4672 -0
  9. matrixone/config.py +452 -0
  10. matrixone/connection_hooks.py +286 -0
  11. matrixone/exceptions.py +89 -0
  12. matrixone/logger.py +782 -0
  13. matrixone/metadata.py +820 -0
  14. matrixone/moctl.py +219 -0
  15. matrixone/orm.py +2277 -0
  16. matrixone/pitr.py +646 -0
  17. matrixone/pubsub.py +771 -0
  18. matrixone/restore.py +411 -0
  19. matrixone/search_vector_index.py +1176 -0
  20. matrixone/snapshot.py +550 -0
  21. matrixone/sql_builder.py +844 -0
  22. matrixone/sqlalchemy_ext/__init__.py +161 -0
  23. matrixone/sqlalchemy_ext/adapters.py +163 -0
  24. matrixone/sqlalchemy_ext/dialect.py +534 -0
  25. matrixone/sqlalchemy_ext/fulltext_index.py +895 -0
  26. matrixone/sqlalchemy_ext/fulltext_search.py +1686 -0
  27. matrixone/sqlalchemy_ext/hnsw_config.py +194 -0
  28. matrixone/sqlalchemy_ext/ivf_config.py +252 -0
  29. matrixone/sqlalchemy_ext/table_builder.py +351 -0
  30. matrixone/sqlalchemy_ext/vector_index.py +1721 -0
  31. matrixone/sqlalchemy_ext/vector_type.py +948 -0
  32. matrixone/version.py +580 -0
  33. matrixone_python_sdk-0.1.0.dist-info/METADATA +706 -0
  34. matrixone_python_sdk-0.1.0.dist-info/RECORD +122 -0
  35. matrixone_python_sdk-0.1.0.dist-info/WHEEL +5 -0
  36. matrixone_python_sdk-0.1.0.dist-info/entry_points.txt +5 -0
  37. matrixone_python_sdk-0.1.0.dist-info/licenses/LICENSE +200 -0
  38. matrixone_python_sdk-0.1.0.dist-info/top_level.txt +2 -0
  39. tests/__init__.py +19 -0
  40. tests/offline/__init__.py +20 -0
  41. tests/offline/conftest.py +77 -0
  42. tests/offline/test_account.py +703 -0
  43. tests/offline/test_async_client_query_comprehensive.py +1218 -0
  44. tests/offline/test_basic.py +54 -0
  45. tests/offline/test_case_sensitivity.py +227 -0
  46. tests/offline/test_connection_hooks_offline.py +287 -0
  47. tests/offline/test_dialect_schema_handling.py +609 -0
  48. tests/offline/test_explain_methods.py +346 -0
  49. tests/offline/test_filter_logical_in.py +237 -0
  50. tests/offline/test_fulltext_search_comprehensive.py +795 -0
  51. tests/offline/test_ivf_config.py +249 -0
  52. tests/offline/test_join_methods.py +281 -0
  53. tests/offline/test_join_sqlalchemy_compatibility.py +276 -0
  54. tests/offline/test_logical_in_method.py +237 -0
  55. tests/offline/test_matrixone_version_parsing.py +264 -0
  56. tests/offline/test_metadata_offline.py +557 -0
  57. tests/offline/test_moctl.py +300 -0
  58. tests/offline/test_moctl_simple.py +251 -0
  59. tests/offline/test_model_support_offline.py +359 -0
  60. tests/offline/test_model_support_simple.py +225 -0
  61. tests/offline/test_pinecone_filter_offline.py +377 -0
  62. tests/offline/test_pitr.py +585 -0
  63. tests/offline/test_pubsub.py +712 -0
  64. tests/offline/test_query_update.py +283 -0
  65. tests/offline/test_restore.py +445 -0
  66. tests/offline/test_snapshot_comprehensive.py +384 -0
  67. tests/offline/test_sql_escaping_edge_cases.py +551 -0
  68. tests/offline/test_sqlalchemy_integration.py +382 -0
  69. tests/offline/test_sqlalchemy_vector_integration.py +434 -0
  70. tests/offline/test_table_builder.py +198 -0
  71. tests/offline/test_unified_filter.py +398 -0
  72. tests/offline/test_unified_transaction.py +495 -0
  73. tests/offline/test_vector_index.py +238 -0
  74. tests/offline/test_vector_operations.py +688 -0
  75. tests/offline/test_vector_type.py +174 -0
  76. tests/offline/test_version_core.py +328 -0
  77. tests/offline/test_version_management.py +372 -0
  78. tests/offline/test_version_standalone.py +652 -0
  79. tests/online/__init__.py +20 -0
  80. tests/online/conftest.py +216 -0
  81. tests/online/test_account_management.py +194 -0
  82. tests/online/test_advanced_features.py +344 -0
  83. tests/online/test_async_client_interfaces.py +330 -0
  84. tests/online/test_async_client_online.py +285 -0
  85. tests/online/test_async_model_insert_online.py +293 -0
  86. tests/online/test_async_orm_online.py +300 -0
  87. tests/online/test_async_simple_query_online.py +802 -0
  88. tests/online/test_async_transaction_simple_query.py +300 -0
  89. tests/online/test_basic_connection.py +130 -0
  90. tests/online/test_client_online.py +238 -0
  91. tests/online/test_config.py +90 -0
  92. tests/online/test_config_validation.py +123 -0
  93. tests/online/test_connection_hooks_new_online.py +217 -0
  94. tests/online/test_dialect_schema_handling_online.py +331 -0
  95. tests/online/test_filter_logical_in_online.py +374 -0
  96. tests/online/test_fulltext_comprehensive.py +1773 -0
  97. tests/online/test_fulltext_label_online.py +433 -0
  98. tests/online/test_fulltext_search_online.py +842 -0
  99. tests/online/test_ivf_stats_online.py +506 -0
  100. tests/online/test_logger_integration.py +311 -0
  101. tests/online/test_matrixone_query_orm.py +540 -0
  102. tests/online/test_metadata_online.py +579 -0
  103. tests/online/test_model_insert_online.py +255 -0
  104. tests/online/test_mysql_driver_validation.py +213 -0
  105. tests/online/test_orm_advanced_features.py +2022 -0
  106. tests/online/test_orm_cte_integration.py +269 -0
  107. tests/online/test_orm_online.py +270 -0
  108. tests/online/test_pinecone_filter.py +708 -0
  109. tests/online/test_pubsub_operations.py +352 -0
  110. tests/online/test_query_methods.py +225 -0
  111. tests/online/test_query_update_online.py +433 -0
  112. tests/online/test_search_vector_index.py +557 -0
  113. tests/online/test_simple_fulltext_online.py +915 -0
  114. tests/online/test_snapshot_comprehensive.py +998 -0
  115. tests/online/test_sqlalchemy_engine_integration.py +336 -0
  116. tests/online/test_sqlalchemy_integration.py +425 -0
  117. tests/online/test_transaction_contexts.py +1219 -0
  118. tests/online/test_transaction_insert_methods.py +356 -0
  119. tests/online/test_transaction_query_methods.py +288 -0
  120. tests/online/test_unified_filter_online.py +529 -0
  121. tests/online/test_vector_comprehensive.py +706 -0
  122. tests/online/test_version_management.py +291 -0
@@ -0,0 +1,300 @@
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
+ Test MoCtlManager functionality
17
+ """
18
+
19
+ import unittest
20
+ from unittest.mock import Mock, patch
21
+ import json
22
+ import sys
23
+ import os
24
+
25
+ # Store original modules to restore later
26
+ _original_modules = {}
27
+
28
+
29
+ def setup_sqlalchemy_mocks():
30
+ """Setup SQLAlchemy mocks for this test class"""
31
+ global _original_modules
32
+ _original_modules['pymysql'] = sys.modules.get('pymysql')
33
+ _original_modules['sqlalchemy'] = sys.modules.get('sqlalchemy')
34
+ _original_modules['sqlalchemy.engine'] = sys.modules.get('sqlalchemy.engine')
35
+ _original_modules['sqlalchemy.orm'] = sys.modules.get('sqlalchemy.orm')
36
+
37
+ sys.modules['pymysql'] = Mock()
38
+ sys.modules['sqlalchemy'] = Mock()
39
+ sys.modules['sqlalchemy.engine'] = Mock()
40
+ sys.modules['sqlalchemy.engine'].Engine = Mock()
41
+ sys.modules['sqlalchemy.orm'] = Mock()
42
+ sys.modules['sqlalchemy.orm'].sessionmaker = Mock()
43
+ sys.modules['sqlalchemy.orm'].declarative_base = Mock()
44
+ sys.modules['sqlalchemy'].create_engine = Mock()
45
+ sys.modules['sqlalchemy'].text = Mock()
46
+ sys.modules['sqlalchemy'].Column = Mock()
47
+ sys.modules['sqlalchemy'].Integer = Mock()
48
+ sys.modules['sqlalchemy'].String = Mock()
49
+ sys.modules['sqlalchemy'].DateTime = Mock()
50
+
51
+
52
+ def teardown_sqlalchemy_mocks():
53
+ """Restore original modules"""
54
+ global _original_modules
55
+ for module_name, original_module in _original_modules.items():
56
+ if original_module is not None:
57
+ sys.modules[module_name] = original_module
58
+ elif module_name in sys.modules:
59
+ del sys.modules[module_name]
60
+
61
+
62
+ # Add the matrixone package to the path
63
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'matrixone'))
64
+
65
+ from matrixone.moctl import MoCtlManager, MoCtlError
66
+ from matrixone.client import Client
67
+
68
+
69
+ class TestMoCtlManager(unittest.TestCase):
70
+ """Test MoCtlManager functionality"""
71
+
72
+ @classmethod
73
+ def setUpClass(cls):
74
+ """Setup mocks for the entire test class"""
75
+ setup_sqlalchemy_mocks()
76
+
77
+ @classmethod
78
+ def tearDownClass(cls):
79
+ """Restore original modules after tests"""
80
+ teardown_sqlalchemy_mocks()
81
+
82
+ def setUp(self):
83
+ """Set up test fixtures"""
84
+ self.mock_client = Mock()
85
+ self.mock_client.execute = Mock()
86
+ self.moctl_manager = MoCtlManager(self.mock_client)
87
+
88
+ def test_init(self):
89
+ """Test MoCtlManager initialization"""
90
+ self.assertEqual(self.moctl_manager.client, self.mock_client)
91
+
92
+ def test_execute_moctl_success(self):
93
+ """Test successful mo_ctl execution"""
94
+ # Mock successful result
95
+ mock_result = Mock()
96
+ mock_result.rows = [('{"method": "Flush", "result": [{"returnStr": "OK"}]}',)]
97
+ self.mock_client.execute.return_value = mock_result
98
+
99
+ result = self.moctl_manager._execute_moctl('dn', 'flush', 'db1.t')
100
+
101
+ # Verify the SQL was called correctly
102
+ expected_sql = "SELECT mo_ctl('dn', 'flush', 'db1.t')"
103
+ self.mock_client.execute.assert_called_once_with(expected_sql)
104
+
105
+ # Verify the result was parsed correctly
106
+ self.assertEqual(result['method'], 'Flush')
107
+ self.assertEqual(result['result'][0]['returnStr'], 'OK')
108
+
109
+ def test_execute_moctl_no_params(self):
110
+ """Test mo_ctl execution without parameters"""
111
+ # Mock successful result
112
+ mock_result = Mock()
113
+ mock_result.rows = [('{"method": "Checkpoint", "result": [{"returnStr": "OK"}]}',)]
114
+ self.mock_client.execute.return_value = mock_result
115
+
116
+ result = self.moctl_manager._execute_moctl('dn', 'checkpoint', '')
117
+
118
+ # Verify the SQL was called correctly
119
+ expected_sql = "SELECT mo_ctl('dn', 'checkpoint', '')"
120
+ self.mock_client.execute.assert_called_once_with(expected_sql)
121
+
122
+ # Verify the result was parsed correctly
123
+ self.assertEqual(result['method'], 'Checkpoint')
124
+ self.assertEqual(result['result'][0]['returnStr'], 'OK')
125
+
126
+ def test_execute_moctl_failure(self):
127
+ """Test mo_ctl execution failure"""
128
+ # Mock failure result
129
+ mock_result = Mock()
130
+ mock_result.rows = [('{"method": "Flush", "result": [{"returnStr": "ERROR: Table not found"}]}',)]
131
+ self.mock_client.execute.return_value = mock_result
132
+
133
+ # Should raise MoCtlError
134
+ with self.assertRaises(MoCtlError) as context:
135
+ self.moctl_manager._execute_moctl('dn', 'flush', 'db1.nonexistent')
136
+
137
+ self.assertIn("mo_ctl operation failed", str(context.exception))
138
+
139
+ def test_execute_moctl_no_rows(self):
140
+ """Test mo_ctl execution with no rows returned"""
141
+ # Mock empty result
142
+ mock_result = Mock()
143
+ mock_result.rows = []
144
+ self.mock_client.execute.return_value = mock_result
145
+
146
+ # Should raise MoCtlError
147
+ with self.assertRaises(MoCtlError) as context:
148
+ self.moctl_manager._execute_moctl('dn', 'flush', 'db1.t')
149
+
150
+ self.assertIn("mo_ctl command returned no results", str(context.exception))
151
+
152
+ def test_execute_moctl_json_error(self):
153
+ """Test mo_ctl execution with invalid JSON"""
154
+ # Mock invalid JSON result
155
+ mock_result = Mock()
156
+ mock_result.rows = [('invalid json',)]
157
+ self.mock_client.execute.return_value = mock_result
158
+
159
+ # Should raise MoCtlError
160
+ with self.assertRaises(MoCtlError) as context:
161
+ self.moctl_manager._execute_moctl('dn', 'flush', 'db1.t')
162
+
163
+ self.assertIn("Failed to parse mo_ctl result", str(context.exception))
164
+
165
+ def test_execute_moctl_exception(self):
166
+ """Test mo_ctl execution with exception"""
167
+ # Mock exception
168
+ self.mock_client.execute.side_effect = Exception("Connection failed")
169
+
170
+ # Should raise MoCtlError
171
+ with self.assertRaises(MoCtlError) as context:
172
+ self.moctl_manager._execute_moctl('dn', 'flush', 'db1.t')
173
+
174
+ self.assertIn("mo_ctl operation failed", str(context.exception))
175
+
176
+ def test_flush_table(self):
177
+ """Test flush_table method"""
178
+ # Mock successful result
179
+ mock_result = Mock()
180
+ mock_result.rows = [('{"method": "Flush", "result": [{"returnStr": "OK"}]}',)]
181
+ self.mock_client.execute.return_value = mock_result
182
+
183
+ result = self.moctl_manager.flush_table('db1', 'users')
184
+
185
+ # Verify the SQL was called correctly
186
+ expected_sql = "SELECT mo_ctl('dn', 'flush', 'db1.users')"
187
+ self.mock_client.execute.assert_called_once_with(expected_sql)
188
+
189
+ # Verify the result
190
+ self.assertEqual(result['method'], 'Flush')
191
+ self.assertEqual(result['result'][0]['returnStr'], 'OK')
192
+
193
+ def test_increment_checkpoint(self):
194
+ """Test increment_checkpoint method"""
195
+ # Mock successful result
196
+ mock_result = Mock()
197
+ mock_result.rows = [('{"method": "Checkpoint", "result": [{"returnStr": "OK"}]}',)]
198
+ self.mock_client.execute.return_value = mock_result
199
+
200
+ result = self.moctl_manager.increment_checkpoint()
201
+
202
+ # Verify the SQL was called correctly
203
+ expected_sql = "SELECT mo_ctl('dn', 'checkpoint', '')"
204
+ self.mock_client.execute.assert_called_once_with(expected_sql)
205
+
206
+ # Verify the result
207
+ self.assertEqual(result['method'], 'Checkpoint')
208
+ self.assertEqual(result['result'][0]['returnStr'], 'OK')
209
+
210
+ def test_global_checkpoint(self):
211
+ """Test global_checkpoint method"""
212
+ # Mock successful result
213
+ mock_result = Mock()
214
+ mock_result.rows = [('{"method": "GlobalCheckpoint", "result": [{"returnStr": "OK"}]}',)]
215
+ self.mock_client.execute.return_value = mock_result
216
+
217
+ result = self.moctl_manager.global_checkpoint()
218
+
219
+ # Verify the SQL was called correctly
220
+ expected_sql = "SELECT mo_ctl('dn', 'globalcheckpoint', '')"
221
+ self.mock_client.execute.assert_called_once_with(expected_sql)
222
+
223
+ # Verify the result
224
+ self.assertEqual(result['method'], 'GlobalCheckpoint')
225
+ self.assertEqual(result['result'][0]['returnStr'], 'OK')
226
+
227
+
228
+ class TestMoCtlIntegration(unittest.TestCase):
229
+ """Test MoCtlManager integration with Client"""
230
+
231
+ @classmethod
232
+ def setUpClass(cls):
233
+ """Setup mocks for the entire test class"""
234
+ setup_sqlalchemy_mocks()
235
+
236
+ @classmethod
237
+ def tearDownClass(cls):
238
+ """Restore original modules after tests"""
239
+ teardown_sqlalchemy_mocks()
240
+
241
+ def setUp(self):
242
+ """Set up test fixtures"""
243
+ self.mock_client = Mock()
244
+ self.mock_client.execute = Mock()
245
+ self.moctl_manager = MoCtlManager(self.mock_client)
246
+
247
+ def test_flush_table_integration(self):
248
+ """Test flush_table integration"""
249
+ # Mock successful result
250
+ mock_result = Mock()
251
+ mock_result.rows = [('{"method": "Flush", "result": [{"returnStr": "OK"}]}',)]
252
+ self.mock_client.execute.return_value = mock_result
253
+
254
+ result = self.moctl_manager.flush_table('production', 'orders')
255
+
256
+ # Verify the SQL was called correctly
257
+ expected_sql = "SELECT mo_ctl('dn', 'flush', 'production.orders')"
258
+ self.mock_client.execute.assert_called_once_with(expected_sql)
259
+
260
+ # Verify the result
261
+ self.assertEqual(result['method'], 'Flush')
262
+ self.assertEqual(result['result'][0]['returnStr'], 'OK')
263
+
264
+ def test_increment_checkpoint_integration(self):
265
+ """Test increment_checkpoint integration"""
266
+ # Mock successful result
267
+ mock_result = Mock()
268
+ mock_result.rows = [('{"method": "Checkpoint", "result": [{"returnStr": "OK"}]}',)]
269
+ self.mock_client.execute.return_value = mock_result
270
+
271
+ result = self.moctl_manager.increment_checkpoint()
272
+
273
+ # Verify the SQL was called correctly
274
+ expected_sql = "SELECT mo_ctl('dn', 'checkpoint', '')"
275
+ self.mock_client.execute.assert_called_once_with(expected_sql)
276
+
277
+ # Verify the result
278
+ self.assertEqual(result['method'], 'Checkpoint')
279
+ self.assertEqual(result['result'][0]['returnStr'], 'OK')
280
+
281
+ def test_global_checkpoint_integration(self):
282
+ """Test global_checkpoint integration"""
283
+ # Mock successful result
284
+ mock_result = Mock()
285
+ mock_result.rows = [('{"method": "GlobalCheckpoint", "result": [{"returnStr": "OK"}]}',)]
286
+ self.mock_client.execute.return_value = mock_result
287
+
288
+ result = self.moctl_manager.global_checkpoint()
289
+
290
+ # Verify the SQL was called correctly
291
+ expected_sql = "SELECT mo_ctl('dn', 'globalcheckpoint', '')"
292
+ self.mock_client.execute.assert_called_once_with(expected_sql)
293
+
294
+ # Verify the result
295
+ self.assertEqual(result['method'], 'GlobalCheckpoint')
296
+ self.assertEqual(result['result'][0]['returnStr'], 'OK')
297
+
298
+
299
+ if __name__ == '__main__':
300
+ unittest.main()
@@ -0,0 +1,251 @@
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
+ Test MoCtlManager core functionality (flush_table, increment_checkpoint, global_checkpoint only)
17
+ """
18
+
19
+ import unittest
20
+ from unittest.mock import Mock, patch
21
+ import json
22
+ import sys
23
+ import os
24
+
25
+ # Store original modules to restore later
26
+ _original_modules = {}
27
+
28
+
29
+ def setup_sqlalchemy_mocks():
30
+ """Setup SQLAlchemy mocks for this test class"""
31
+ global _original_modules
32
+ _original_modules['pymysql'] = sys.modules.get('pymysql')
33
+ _original_modules['sqlalchemy'] = sys.modules.get('sqlalchemy')
34
+ _original_modules['sqlalchemy.engine'] = sys.modules.get('sqlalchemy.engine')
35
+ _original_modules['sqlalchemy.orm'] = sys.modules.get('sqlalchemy.orm')
36
+
37
+ sys.modules['pymysql'] = Mock()
38
+ sys.modules['sqlalchemy'] = Mock()
39
+ sys.modules['sqlalchemy.engine'] = Mock()
40
+ sys.modules['sqlalchemy.engine'].Engine = Mock()
41
+ sys.modules['sqlalchemy.orm'] = Mock()
42
+ sys.modules['sqlalchemy.orm'].sessionmaker = Mock()
43
+ sys.modules['sqlalchemy.orm'].declarative_base = Mock()
44
+ sys.modules['sqlalchemy'].create_engine = Mock()
45
+ sys.modules['sqlalchemy'].text = Mock()
46
+ sys.modules['sqlalchemy'].Column = Mock()
47
+ sys.modules['sqlalchemy'].Integer = Mock()
48
+ sys.modules['sqlalchemy'].String = Mock()
49
+ sys.modules['sqlalchemy'].DateTime = Mock()
50
+
51
+
52
+ def teardown_sqlalchemy_mocks():
53
+ """Restore original modules"""
54
+ global _original_modules
55
+ for module_name, original_module in _original_modules.items():
56
+ if original_module is not None:
57
+ sys.modules[module_name] = original_module
58
+ elif module_name in sys.modules:
59
+ del sys.modules[module_name]
60
+
61
+
62
+ # Add the matrixone package to the path
63
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'matrixone'))
64
+
65
+ from matrixone.moctl import MoCtlManager, MoCtlError
66
+ from matrixone.client import Client
67
+
68
+
69
+ class TestMoCtlManager(unittest.TestCase):
70
+ """Test MoCtlManager core functionality"""
71
+
72
+ @classmethod
73
+ def setUpClass(cls):
74
+ """Setup mocks for the entire test class"""
75
+ setup_sqlalchemy_mocks()
76
+
77
+ @classmethod
78
+ def tearDownClass(cls):
79
+ """Restore original modules after tests"""
80
+ teardown_sqlalchemy_mocks()
81
+
82
+ def setUp(self):
83
+ """Set up test fixtures"""
84
+ self.mock_client = Mock()
85
+ self.mock_client.execute = Mock()
86
+ self.moctl_manager = MoCtlManager(self.mock_client)
87
+
88
+ def test_init(self):
89
+ """Test MoCtlManager initialization"""
90
+ self.assertEqual(self.moctl_manager.client, self.mock_client)
91
+
92
+ def test_flush_table(self):
93
+ """Test flush_table method"""
94
+ # Mock successful result
95
+ mock_result = Mock()
96
+ mock_result.rows = [('{"method": "Flush", "result": [{"returnStr": "OK"}]}',)]
97
+ self.mock_client.execute.return_value = mock_result
98
+
99
+ result = self.moctl_manager.flush_table('db1', 'users')
100
+
101
+ # Verify the SQL was called correctly
102
+ expected_sql = "SELECT mo_ctl('dn', 'flush', 'db1.users')"
103
+ self.mock_client.execute.assert_called_once_with(expected_sql)
104
+
105
+ # Verify the result
106
+ self.assertEqual(result['method'], 'Flush')
107
+ self.assertEqual(result['result'][0]['returnStr'], 'OK')
108
+
109
+ def test_increment_checkpoint(self):
110
+ """Test increment_checkpoint method"""
111
+ # Mock successful result
112
+ mock_result = Mock()
113
+ mock_result.rows = [('{"method": "Checkpoint", "result": [{"returnStr": "OK"}]}',)]
114
+ self.mock_client.execute.return_value = mock_result
115
+
116
+ result = self.moctl_manager.increment_checkpoint()
117
+
118
+ # Verify the SQL was called correctly
119
+ expected_sql = "SELECT mo_ctl('dn', 'checkpoint', '')"
120
+ self.mock_client.execute.assert_called_once_with(expected_sql)
121
+
122
+ # Verify the result
123
+ self.assertEqual(result['method'], 'Checkpoint')
124
+ self.assertEqual(result['result'][0]['returnStr'], 'OK')
125
+
126
+ def test_global_checkpoint(self):
127
+ """Test global_checkpoint method"""
128
+ # Mock successful result
129
+ mock_result = Mock()
130
+ mock_result.rows = [('{"method": "GlobalCheckpoint", "result": [{"returnStr": "OK"}]}',)]
131
+ self.mock_client.execute.return_value = mock_result
132
+
133
+ result = self.moctl_manager.global_checkpoint()
134
+
135
+ # Verify the SQL was called correctly
136
+ expected_sql = "SELECT mo_ctl('dn', 'globalcheckpoint', '')"
137
+ self.mock_client.execute.assert_called_once_with(expected_sql)
138
+
139
+ # Verify the result
140
+ self.assertEqual(result['method'], 'GlobalCheckpoint')
141
+ self.assertEqual(result['result'][0]['returnStr'], 'OK')
142
+
143
+ def test_flush_table_failure(self):
144
+ """Test flush_table method with failure"""
145
+ # Mock failure result
146
+ mock_result = Mock()
147
+ mock_result.rows = [('{"method": "Flush", "result": [{"returnStr": "ERROR: Table not found"}]}',)]
148
+ self.mock_client.execute.return_value = mock_result
149
+
150
+ # Should raise MoCtlError
151
+ with self.assertRaises(MoCtlError):
152
+ self.moctl_manager.flush_table('db1', 'nonexistent')
153
+
154
+ def test_increment_checkpoint_failure(self):
155
+ """Test increment_checkpoint method with failure"""
156
+ # Mock failure result
157
+ mock_result = Mock()
158
+ mock_result.rows = [('{"method": "Checkpoint", "result": [{"returnStr": "ERROR: Checkpoint failed"}]}',)]
159
+ self.mock_client.execute.return_value = mock_result
160
+
161
+ # Should raise MoCtlError
162
+ with self.assertRaises(MoCtlError):
163
+ self.moctl_manager.increment_checkpoint()
164
+
165
+ def test_global_checkpoint_failure(self):
166
+ """Test global_checkpoint method with failure"""
167
+ # Mock failure result
168
+ mock_result = Mock()
169
+ mock_result.rows = [
170
+ ('{"method": "GlobalCheckpoint", "result": [{"returnStr": "ERROR: Global checkpoint failed"}]}',)
171
+ ]
172
+ self.mock_client.execute.return_value = mock_result
173
+
174
+ # Should raise MoCtlError
175
+ with self.assertRaises(MoCtlError):
176
+ self.moctl_manager.global_checkpoint()
177
+
178
+
179
+ class TestMoCtlIntegration(unittest.TestCase):
180
+ """Test MoCtlManager integration with Client"""
181
+
182
+ @classmethod
183
+ def setUpClass(cls):
184
+ """Setup mocks for the entire test class"""
185
+ setup_sqlalchemy_mocks()
186
+
187
+ @classmethod
188
+ def tearDownClass(cls):
189
+ """Restore original modules after tests"""
190
+ teardown_sqlalchemy_mocks()
191
+
192
+ def setUp(self):
193
+ """Set up test fixtures"""
194
+ self.mock_client = Mock()
195
+ self.mock_client.execute = Mock()
196
+ self.moctl_manager = MoCtlManager(self.mock_client)
197
+
198
+ def test_flush_table_integration(self):
199
+ """Test flush_table integration"""
200
+ # Mock successful result
201
+ mock_result = Mock()
202
+ mock_result.rows = [('{"method": "Flush", "result": [{"returnStr": "OK"}]}',)]
203
+ self.mock_client.execute.return_value = mock_result
204
+
205
+ result = self.moctl_manager.flush_table('production', 'orders')
206
+
207
+ # Verify the SQL was called correctly
208
+ expected_sql = "SELECT mo_ctl('dn', 'flush', 'production.orders')"
209
+ self.mock_client.execute.assert_called_once_with(expected_sql)
210
+
211
+ # Verify the result
212
+ self.assertEqual(result['method'], 'Flush')
213
+ self.assertEqual(result['result'][0]['returnStr'], 'OK')
214
+
215
+ def test_increment_checkpoint_integration(self):
216
+ """Test increment_checkpoint integration"""
217
+ # Mock successful result
218
+ mock_result = Mock()
219
+ mock_result.rows = [('{"method": "Checkpoint", "result": [{"returnStr": "OK"}]}',)]
220
+ self.mock_client.execute.return_value = mock_result
221
+
222
+ result = self.moctl_manager.increment_checkpoint()
223
+
224
+ # Verify the SQL was called correctly
225
+ expected_sql = "SELECT mo_ctl('dn', 'checkpoint', '')"
226
+ self.mock_client.execute.assert_called_once_with(expected_sql)
227
+
228
+ # Verify the result
229
+ self.assertEqual(result['method'], 'Checkpoint')
230
+ self.assertEqual(result['result'][0]['returnStr'], 'OK')
231
+
232
+ def test_global_checkpoint_integration(self):
233
+ """Test global_checkpoint integration"""
234
+ # Mock successful result
235
+ mock_result = Mock()
236
+ mock_result.rows = [('{"method": "GlobalCheckpoint", "result": [{"returnStr": "OK"}]}',)]
237
+ self.mock_client.execute.return_value = mock_result
238
+
239
+ result = self.moctl_manager.global_checkpoint()
240
+
241
+ # Verify the SQL was called correctly
242
+ expected_sql = "SELECT mo_ctl('dn', 'globalcheckpoint', '')"
243
+ self.mock_client.execute.assert_called_once_with(expected_sql)
244
+
245
+ # Verify the result
246
+ self.assertEqual(result['method'], 'GlobalCheckpoint')
247
+ self.assertEqual(result['result'][0]['returnStr'], 'OK')
248
+
249
+
250
+ if __name__ == '__main__':
251
+ unittest.main()