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,374 @@
1
+ #!/usr/bin/env python3
2
+
3
+ # Copyright 2021 - 2022 Matrix Origin
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ """
18
+ Online Test: filter(logical_in(...)) syntax for enhanced IN functionality
19
+
20
+ This test verifies that the filter(logical_in(...)) syntax works correctly with actual
21
+ database connections, including FulltextFilter objects, lists, and SQLAlchemy expressions.
22
+ """
23
+
24
+ import pytest
25
+ import sys
26
+ import os
27
+ from datetime import datetime
28
+
29
+ # Add the current directory to Python path
30
+ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
31
+
32
+ from matrixone import Client
33
+ from sqlalchemy import Column, Integer, String, DateTime, func
34
+ from matrixone.orm import declarative_base, logical_in
35
+ from matrixone.sqlalchemy_ext.fulltext_search import boolean_match
36
+
37
+ try:
38
+ from .test_config import online_config
39
+ except ImportError:
40
+ # Fallback for when running as standalone script
41
+ import test_config
42
+
43
+ online_config = test_config.online_config
44
+
45
+ # Create SQLAlchemy models
46
+ Base = declarative_base()
47
+
48
+
49
+ class User(Base):
50
+ __tablename__ = 'test_users_logical_in'
51
+ id = Column(Integer, primary_key=True)
52
+ name = Column(String(50))
53
+ age = Column(Integer)
54
+ city = Column(String(50))
55
+ department = Column(String(50))
56
+ salary = Column(Integer)
57
+ created_at = Column(DateTime)
58
+
59
+
60
+ class Article(Base):
61
+ __tablename__ = 'test_articles_logical_in'
62
+ id = Column(Integer, primary_key=True)
63
+ title = Column(String(100))
64
+ content = Column(String(500))
65
+ author = Column(String(50))
66
+ created_at = Column(DateTime)
67
+
68
+
69
+ class TestFilterLogicalInOnline:
70
+ """Online test class for filter(logical_in(...)) syntax functionality"""
71
+
72
+ @pytest.fixture(autouse=True)
73
+ def setup_and_cleanup(self):
74
+ """Set up test data and clean up after tests"""
75
+ # Setup - use real database connection
76
+ host, port, user, password, database = online_config.get_connection_params()
77
+ self.client = Client()
78
+ self.client.connect(host=host, port=port, user=user, password=password, database=database)
79
+
80
+ # Create tables
81
+ self.client.create_table(
82
+ "test_users_logical_in",
83
+ {
84
+ "id": "int",
85
+ "name": "varchar(50)",
86
+ "age": "int",
87
+ "city": "varchar(50)",
88
+ "department": "varchar(50)",
89
+ "salary": "int",
90
+ "created_at": "datetime",
91
+ },
92
+ primary_key="id",
93
+ )
94
+ self.client.create_table(
95
+ "test_articles_logical_in",
96
+ {
97
+ "id": "int",
98
+ "title": "varchar(100)",
99
+ "content": "varchar(500)",
100
+ "author": "varchar(50)",
101
+ "created_at": "datetime",
102
+ },
103
+ primary_key="id",
104
+ )
105
+
106
+ # Insert test data
107
+ self._insert_test_data()
108
+
109
+ yield
110
+
111
+ # Cleanup
112
+ try:
113
+ self.client.drop_table("test_users_logical_in")
114
+ self.client.drop_table("test_articles_logical_in")
115
+ except:
116
+ pass # Ignore cleanup errors
117
+ finally:
118
+ # Disconnect from database
119
+ try:
120
+ self.client.close()
121
+ except:
122
+ pass
123
+
124
+ def _insert_test_data(self):
125
+ """Insert test data for online tests"""
126
+ # Insert users
127
+ users_data = [
128
+ {"name": "张三", "age": 25, "city": "北京", "department": "Engineering", "salary": 80000},
129
+ {"name": "李四", "age": 30, "city": "上海", "department": "Sales", "salary": 70000},
130
+ {"name": "王五", "age": 35, "city": "广州", "department": "Engineering", "salary": 90000},
131
+ {"name": "赵六", "age": 28, "city": "深圳", "department": "Marketing", "salary": 75000},
132
+ {"name": "钱七", "age": 32, "city": "北京", "department": "Sales", "salary": 85000},
133
+ {"name": "孙八", "age": 27, "city": "上海", "department": "Engineering", "salary": 80000},
134
+ ]
135
+
136
+ for user_data in users_data:
137
+ self.client.insert("test_users_logical_in", user_data)
138
+
139
+ # Insert articles
140
+ articles_data = [
141
+ {"title": "Python编程入门", "content": "Python是一种高级编程语言,适合初学者学习", "author": "张三"},
142
+ {"title": "Java开发指南", "content": "Java是企业级应用开发的首选语言", "author": "李四"},
143
+ {"title": "Python数据分析", "content": "使用Python进行数据分析和机器学习", "author": "王五"},
144
+ {"title": "JavaScript前端开发", "content": "JavaScript是现代前端开发的核心技术", "author": "赵六"},
145
+ {"title": "Python Web开发", "content": "使用Python和Django进行Web应用开发", "author": "张三"},
146
+ {"title": "数据库设计原理", "content": "关系型数据库的设计和优化技巧", "author": "钱七"},
147
+ ]
148
+
149
+ for article_data in articles_data:
150
+ self.client.insert("test_articles_logical_in", article_data)
151
+
152
+ def test_filter_logical_in_with_list_values_online(self):
153
+ """Test filter(logical_in(...)) with list of values - online"""
154
+ # Test with city list
155
+ query = self.client.query(User).filter(logical_in("city", ["北京", "上海"]))
156
+ results = query.all()
157
+
158
+ # Should have 4 users: 张三(北京), 李四(上海), 钱七(北京), 孙八(上海)
159
+ assert len(results) == 4
160
+
161
+ cities = [user.city for user in results]
162
+ assert "北京" in cities
163
+ assert "上海" in cities
164
+ assert "广州" not in cities
165
+ assert "深圳" not in cities
166
+
167
+ def test_filter_logical_in_with_department_list_online(self):
168
+ """Test filter(logical_in(...)) with department list - online"""
169
+ query = self.client.query(User).filter(logical_in("department", ["Engineering", "Sales"]))
170
+ results = query.all()
171
+
172
+ # Should have 5 users: 张三(Engineering), 李四(Sales), 王五(Engineering), 钱七(Sales), 孙八(Engineering)
173
+ assert len(results) == 5
174
+
175
+ departments = [user.department for user in results]
176
+ assert "Engineering" in departments
177
+ assert "Sales" in departments
178
+ assert "Marketing" not in departments
179
+
180
+ def test_filter_logical_in_with_age_range_online(self):
181
+ """Test filter(logical_in(...)) with age range - online"""
182
+ query = self.client.query(User).filter(logical_in("age", [25, 30, 35]))
183
+ results = query.all()
184
+
185
+ # Should have 3 users: 张三(25), 李四(30), 王五(35)
186
+ assert len(results) == 3
187
+
188
+ ages = [user.age for user in results]
189
+ assert 25 in ages
190
+ assert 30 in ages
191
+ assert 35 in ages
192
+ assert 28 not in ages
193
+ assert 32 not in ages
194
+ assert 27 not in ages
195
+
196
+ def test_filter_logical_in_with_salary_range_online(self):
197
+ """Test filter(logical_in(...)) with salary range - online"""
198
+ query = self.client.query(User).filter(logical_in("salary", [80000, 90000]))
199
+ results = query.all()
200
+
201
+ # Should have 3 users: 张三(80000), 王五(90000), 孙八(80000)
202
+ assert len(results) == 3
203
+
204
+ salaries = [user.salary for user in results]
205
+ assert 80000 in salaries
206
+ assert 90000 in salaries
207
+ assert 70000 not in salaries
208
+ assert 75000 not in salaries
209
+ assert 85000 not in salaries
210
+
211
+ def test_filter_logical_in_with_author_list_online(self):
212
+ """Test filter(logical_in(...)) with author list - online"""
213
+ query = self.client.query(Article).filter(logical_in("author", ["张三", "李四"]))
214
+ results = query.all()
215
+
216
+ # Should have 3 articles: 张三的2篇文章 + 李四的1篇文章
217
+ assert len(results) == 3
218
+
219
+ authors = [article.author for article in results]
220
+ assert "张三" in authors
221
+ assert "李四" in authors
222
+ assert "王五" not in authors
223
+ assert "赵六" not in authors
224
+ assert "钱七" not in authors
225
+
226
+ def test_filter_logical_in_combined_with_other_conditions_online(self):
227
+ """Test filter(logical_in(...)) combined with other conditions - online"""
228
+ query = (
229
+ self.client.query(User)
230
+ .filter(logical_in("city", ["北京", "上海"]))
231
+ .filter(logical_in("department", ["Engineering", "Sales"]))
232
+ .filter("age > ?", 25)
233
+ )
234
+
235
+ results = query.all()
236
+
237
+ # Should return 3 users: 李四(上海, Sales, 30), 钱七(北京, Sales, 32), 孙八(上海, Engineering, 27)
238
+ assert len(results) == 3
239
+
240
+ for user in results:
241
+ assert user.city in ["北京", "上海"]
242
+ assert user.department in ["Engineering", "Sales"]
243
+ assert user.age > 25
244
+
245
+ def test_filter_logical_in_with_empty_list_online(self):
246
+ """Test filter(logical_in(...)) with empty list - online"""
247
+ query = self.client.query(User).filter(logical_in("id", []))
248
+ results = query.all()
249
+
250
+ assert len(results) == 0 # Empty list should return no results
251
+
252
+ def test_filter_logical_in_with_single_value_online(self):
253
+ """Test filter(logical_in(...)) with single value - online"""
254
+ query = self.client.query(User).filter(logical_in("id", 1))
255
+ results = query.all()
256
+
257
+ assert len(results) == 1
258
+ assert results[0].id == 1
259
+ assert results[0].name == "张三"
260
+
261
+ def test_filter_logical_in_with_tuple_values_online(self):
262
+ """Test filter(logical_in(...)) with tuple values - online"""
263
+ query = self.client.query(User).filter(logical_in("id", (1, 2, 3)))
264
+ results = query.all()
265
+
266
+ assert len(results) == 3
267
+
268
+ ids = [user.id for user in results]
269
+ assert 1 in ids
270
+ assert 2 in ids
271
+ assert 3 in ids
272
+ assert 4 not in ids
273
+ assert 5 not in ids
274
+ assert 6 not in ids
275
+
276
+ def test_filter_logical_in_method_chaining_online(self):
277
+ """Test filter(logical_in(...)) with method chaining - online"""
278
+ query = (
279
+ self.client.query(User)
280
+ .filter(logical_in("city", ["北京", "上海"]))
281
+ .filter(logical_in("department", ["Engineering", "Sales"]))
282
+ .filter("age > ?", 25)
283
+ .order_by("name")
284
+ .limit(10)
285
+ )
286
+
287
+ results = query.all()
288
+
289
+ # Should return 3 users: 李四(上海, Sales, 30), 钱七(北京, Sales, 32), 孙八(上海, Engineering, 27)
290
+ assert len(results) == 3
291
+
292
+ # Results should be ordered by name
293
+ names = [user.name for user in results]
294
+ assert names == sorted(names)
295
+
296
+ def test_filter_logical_in_with_aggregate_functions_online(self):
297
+ """Test filter(logical_in(...)) with aggregate functions - online"""
298
+ # Test with count function
299
+ query = (
300
+ self.client.query(User)
301
+ .select(User.department, func.count(User.id))
302
+ .filter(logical_in("city", ["北京", "上海", "广州"]))
303
+ .group_by(User.department)
304
+ .having(func.count(User.id) > 1)
305
+ )
306
+
307
+ results = query.all()
308
+
309
+ # Should return departments with more than 1 user in the specified cities
310
+ assert len(results) >= 0 # May vary based on data
311
+
312
+ for result in results:
313
+ assert result.count > 1
314
+
315
+ def test_filter_logical_in_performance_online(self):
316
+ """Test filter(logical_in(...)) performance with complex queries - online"""
317
+ query = (
318
+ self.client.query(User)
319
+ .select(User.department, func.count(User.id))
320
+ .filter(logical_in("city", ["北京", "上海", "广州", "深圳"]))
321
+ .filter(logical_in("department", ["Engineering", "Sales", "Marketing"]))
322
+ .filter("age > ?", 25)
323
+ .group_by(User.department)
324
+ .having(func.count(User.id) > 0)
325
+ .order_by(func.count(User.id).desc())
326
+ .limit(20)
327
+ )
328
+
329
+ results = query.all()
330
+
331
+ # Should return aggregated results
332
+ assert len(results) >= 0
333
+
334
+ # Results should be ordered by count descending
335
+ if len(results) > 1:
336
+ counts = [result.count for result in results]
337
+ assert counts == sorted(counts, reverse=True)
338
+
339
+ def test_filter_logical_in_with_article_search_online(self):
340
+ """Test filter(logical_in(...)) with article search - online"""
341
+ # Search for articles by specific authors
342
+ query = self.client.query(Article).filter(logical_in("author", ["张三", "王五"]))
343
+ results = query.all()
344
+
345
+ assert len(results) == 3 # 张三的2篇文章 + 王五的1篇文章
346
+
347
+ authors = [article.author for article in results]
348
+ assert "张三" in authors
349
+ assert "王五" in authors
350
+ assert "李四" not in authors
351
+ assert "赵六" not in authors
352
+ assert "钱七" not in authors
353
+
354
+ def test_filter_logical_in_with_mixed_conditions_online(self):
355
+ """Test filter(logical_in(...)) with mixed conditions - online"""
356
+ query = (
357
+ self.client.query(Article)
358
+ .filter(logical_in("author", ["张三", "李四", "王五"]))
359
+ .filter("title LIKE ?", "%Python%")
360
+ )
361
+
362
+ results = query.all()
363
+
364
+ # Should return Python-related articles by specified authors
365
+ assert len(results) >= 0
366
+
367
+ for article in results:
368
+ assert article.author in ["张三", "李四", "王五"]
369
+ assert "Python" in article.title
370
+
371
+
372
+ if __name__ == "__main__":
373
+ # Run tests if executed directly
374
+ pytest.main([__file__, "-v"])