matrixone-python-sdk 0.1.11__tar.gz → 0.1.13__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.
Files changed (96) hide show
  1. {matrixone_python_sdk-0.1.11/matrixone_python_sdk.egg-info → matrixone_python_sdk-0.1.13}/PKG-INFO +11 -1
  2. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/README_USER.md +10 -0
  3. matrixone_python_sdk-0.1.13/examples/example_32_branch_operations.py +475 -0
  4. matrixone_python_sdk-0.1.13/examples/example_33_ivf_rank_search.py +403 -0
  5. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/__init__.py +9 -0
  6. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/async_client.py +41 -13
  7. matrixone_python_sdk-0.1.13/matrixone/branch.py +872 -0
  8. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/cli_tools.py +2 -2
  9. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/client.py +58 -17
  10. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/clone.py +4 -4
  11. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/exceptions.py +4 -0
  12. matrixone_python_sdk-0.1.13/matrixone/ivf_rank.py +127 -0
  13. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/pitr.py +16 -16
  14. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/restore.py +8 -8
  15. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/session.py +4 -0
  16. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/snapshot.py +6 -6
  17. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/sqlalchemy_ext/dialect.py +23 -20
  18. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/sqlalchemy_ext/fulltext_index.py +36 -0
  19. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/vector_manager.py +256 -2
  20. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/version.py +12 -2
  21. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13/matrixone_python_sdk.egg-info}/PKG-INFO +11 -1
  22. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone_python_sdk.egg-info/SOURCES.txt +4 -0
  23. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/pyproject.toml +1 -1
  24. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/LICENSE +0 -0
  25. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/MANIFEST.in +0 -0
  26. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/README.md +0 -0
  27. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_01_basic_connection.py +0 -0
  28. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_02_account_management.py +0 -0
  29. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_03_async_operations.py +0 -0
  30. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_04_transaction_management.py +0 -0
  31. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_05_snapshot_restore.py +0 -0
  32. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_06_sqlalchemy_integration.py +0 -0
  33. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_07_advanced_features.py +0 -0
  34. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_08_pubsub_operations.py +0 -0
  35. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_09_logger_integration.py +0 -0
  36. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_10_version_management.py +0 -0
  37. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_11_matrixone_version_demo.py +0 -0
  38. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_12_vector_basics.py +0 -0
  39. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_13_vector_indexes.py +0 -0
  40. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_14_vector_search.py +0 -0
  41. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_15_vector_advanced.py +0 -0
  42. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_18_snapshot_orm.py +0 -0
  43. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_19_sqlalchemy_style_orm.py +0 -0
  44. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_20_sqlalchemy_engine_integration.py +0 -0
  45. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_21_advanced_orm_features.py +0 -0
  46. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_22_unified_sql_builder.py +0 -0
  47. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_23_load_data_operations.py +0 -0
  48. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_24_query_update.py +0 -0
  49. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_25_metadata_operations.py +0 -0
  50. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_26_stage_operations.py +0 -0
  51. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_27_export_operations.py +0 -0
  52. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_28_sqlalchemy_select.py +0 -0
  53. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_29_complex_queries.py +0 -0
  54. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_30_with_snapshot_method.py +0 -0
  55. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_31_cdc_operations.py +0 -0
  56. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_connection_hooks.py +0 -0
  57. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_dynamic_logging.py +0 -0
  58. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/examples/example_ivf_stats_complete.py +0 -0
  59. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/account.py +0 -0
  60. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/async_orm.py +0 -0
  61. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/base_client.py +0 -0
  62. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/cdc.py +0 -0
  63. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/config.py +0 -0
  64. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/connection_hooks.py +0 -0
  65. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/export.py +0 -0
  66. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/fulltext_manager.py +0 -0
  67. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/index_utils.py +0 -0
  68. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/load_data.py +0 -0
  69. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/logger.py +0 -0
  70. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/metadata.py +0 -0
  71. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/moctl.py +0 -0
  72. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/orm.py +0 -0
  73. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/pubsub.py +0 -0
  74. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/search_vector_index.py +0 -0
  75. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/sql_builder.py +0 -0
  76. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/sqlalchemy_ext/__init__.py +0 -0
  77. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/sqlalchemy_ext/fulltext_search.py +0 -0
  78. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/sqlalchemy_ext/hnsw_config.py +0 -0
  79. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/sqlalchemy_ext/ivf_config.py +0 -0
  80. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/sqlalchemy_ext/json_functions.py +0 -0
  81. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/sqlalchemy_ext/json_type.py +0 -0
  82. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/sqlalchemy_ext/snapshot.py +0 -0
  83. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/sqlalchemy_ext/table_builder.py +0 -0
  84. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/sqlalchemy_ext/vector_index.py +0 -0
  85. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/sqlalchemy_ext/vector_type.py +0 -0
  86. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/sqlalchemy_select.py +0 -0
  87. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone/stage.py +0 -0
  88. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone_python_sdk.egg-info/dependency_links.txt +0 -0
  89. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone_python_sdk.egg-info/entry_points.txt +0 -0
  90. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone_python_sdk.egg-info/not-zip-safe +0 -0
  91. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone_python_sdk.egg-info/requires.txt +0 -0
  92. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/matrixone_python_sdk.egg-info/top_level.txt +0 -0
  93. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/mo_diag.py +0 -0
  94. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/requirements.txt +0 -0
  95. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/setup.cfg +0 -0
  96. {matrixone_python_sdk-0.1.11 → matrixone_python_sdk-0.1.13}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matrixone-python-sdk
3
- Version: 0.1.11
3
+ Version: 0.1.13
4
4
  Summary: A comprehensive Python SDK for MatrixOne database operations with vector search, fulltext search, and advanced features
5
5
  Home-page: https://github.com/matrixorigin/matrixone
6
6
  Author: MatrixOne Team
@@ -87,6 +87,9 @@ A comprehensive, high-level Python SDK for MatrixOne that provides SQLAlchemy-li
87
87
  - 📋 [Best Practices](https://matrixone.readthedocs.io/en/latest/best_practices.html)
88
88
  - 📖 [API Reference](https://matrixone.readthedocs.io/en/latest/api/index.html)
89
89
 
90
+ **For Developers:**
91
+ - 🛠️ [MatrixOne Development Guide](../../etc/DEV_README.md) - Complete guide for setting up MatrixOne locally, multi-CN clusters, monitoring, and all `make dev-*` commands
92
+
90
93
  ---
91
94
 
92
95
  ## ✨ Features
@@ -205,6 +208,13 @@ class User(Base):
205
208
 
206
209
  ## Quick Start
207
210
 
211
+ > **💡 Need to set up MatrixOne server?**
212
+ > If you don't have MatrixOne running yet, check out the [MatrixOne Development Guide](../../etc/DEV_README.md) for instructions on:
213
+ > - Starting a standalone MatrixOne instance
214
+ > - Setting up a multi-CN cluster with Docker Compose
215
+ > - Enabling monitoring and metrics
216
+ > - All `make dev-*` commands
217
+
208
218
  ### Basic Usage
209
219
 
210
220
  ```python
@@ -19,6 +19,9 @@ A comprehensive, high-level Python SDK for MatrixOne that provides SQLAlchemy-li
19
19
  - 📋 [Best Practices](https://matrixone.readthedocs.io/en/latest/best_practices.html)
20
20
  - 📖 [API Reference](https://matrixone.readthedocs.io/en/latest/api/index.html)
21
21
 
22
+ **For Developers:**
23
+ - 🛠️ [MatrixOne Development Guide](../../etc/DEV_README.md) - Complete guide for setting up MatrixOne locally, multi-CN clusters, monitoring, and all `make dev-*` commands
24
+
22
25
  ---
23
26
 
24
27
  ## ✨ Features
@@ -137,6 +140,13 @@ class User(Base):
137
140
 
138
141
  ## Quick Start
139
142
 
143
+ > **💡 Need to set up MatrixOne server?**
144
+ > If you don't have MatrixOne running yet, check out the [MatrixOne Development Guide](../../etc/DEV_README.md) for instructions on:
145
+ > - Starting a standalone MatrixOne instance
146
+ > - Setting up a multi-CN cluster with Docker Compose
147
+ > - Enabling monitoring and metrics
148
+ > - All `make dev-*` commands
149
+
140
150
  ### Basic Usage
141
151
 
142
152
  ```python
@@ -0,0 +1,475 @@
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
+ Example 32: Branch Operations - Git-Style Version Control for Data
19
+
20
+ This example demonstrates Git-style branch operations with real-world scenarios:
21
+ 1. Basic API - Simple string-based operations
22
+ 2. ORM Model Support - SQLAlchemy model integration
23
+ 3. Development Workflow - Create dev branch, test, merge
24
+ 4. Safe Data Migration - Snapshot-based testing before applying
25
+ 5. A/B Testing - Compare different data transformations
26
+ 6. Multi-Team Development - Independent branches with conflict resolution
27
+ 7. Database-Level Branching - Schema changes across entire databases
28
+ 8. Async Operations - Non-blocking branch operations
29
+
30
+ This example demonstrates the complete branch functionality of MatrixOne.
31
+ """
32
+
33
+ import asyncio
34
+ import time
35
+ from matrixone import Client, AsyncClient
36
+ from matrixone.orm import declarative_base
37
+ from sqlalchemy import Column, Integer, String, Numeric
38
+ from matrixone.logger import create_default_logger
39
+ from matrixone.config import get_connection_params, print_config
40
+
41
+ Base = declarative_base()
42
+
43
+ class Product(Base):
44
+ __tablename__ = 'products'
45
+ id = Column(Integer, primary_key=True)
46
+ name = Column(String(100))
47
+ price = Column(Numeric(10, 2))
48
+
49
+
50
+ class BranchOperationsDemo:
51
+ """Demonstrates branch operations with comprehensive testing."""
52
+
53
+ def __init__(self):
54
+ self.logger = create_default_logger(sql_log_mode="auto")
55
+ self.results = {
56
+ 'tests_run': 0,
57
+ 'tests_passed': 0,
58
+ 'tests_failed': 0,
59
+ 'unexpected_results': [],
60
+ }
61
+
62
+ def test_basic_api(self):
63
+ """Test 1: Basic API - Simple string-based operations"""
64
+ print("\n=== Test 1: Basic API ===")
65
+ self.results['tests_run'] += 1
66
+
67
+ try:
68
+ host, port, user, password, database = get_connection_params()
69
+ client = Client(logger=self.logger, sql_log_mode="full")
70
+ client.connect(host=host, port=port, user=user, password=password, database=database)
71
+
72
+ # Create and delete
73
+ client.execute("DROP TABLE IF EXISTS users")
74
+ client.execute("CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(50))")
75
+ client.execute("INSERT INTO users VALUES (1, 'Alice')")
76
+
77
+ client.branch.create('users_branch', 'users')
78
+ client.branch.delete('users_branch')
79
+ client.execute("DROP TABLE users")
80
+
81
+ self.logger.info("✅ Basic API test passed")
82
+ self.results['tests_passed'] += 1
83
+ client.disconnect()
84
+
85
+ except Exception as e:
86
+ self.logger.error(f"❌ Basic API test failed: {e}")
87
+ self.results['tests_failed'] += 1
88
+ self.results['unexpected_results'].append({'test': 'basic_api', 'error': str(e)})
89
+
90
+ def test_orm_model_support(self):
91
+ """Test 2: ORM Model Support - SQLAlchemy model integration"""
92
+ print("\n=== Test 2: ORM Model Support ===")
93
+ self.results['tests_run'] += 1
94
+
95
+ try:
96
+ host, port, user, password, database = get_connection_params()
97
+ client = Client(logger=self.logger, sql_log_mode="full")
98
+ client.connect(host=host, port=port, user=user, password=password, database=database)
99
+
100
+ client.execute("DROP TABLE IF EXISTS products")
101
+ client.execute("DROP TABLE IF EXISTS products_branch")
102
+
103
+ client.create_table(Product)
104
+ client.insert(Product, {'id': 1, 'name': 'Laptop', 'price': 999.99})
105
+
106
+ client.branch.create('products_branch', Product)
107
+ client.branch.delete('products_branch')
108
+ client.drop_table(Product)
109
+
110
+ self.logger.info("✅ ORM model support test passed")
111
+ self.results['tests_passed'] += 1
112
+ client.disconnect()
113
+
114
+ except Exception as e:
115
+ self.logger.error(f"❌ ORM model support test failed: {e}")
116
+ self.results['tests_failed'] += 1
117
+ self.results['unexpected_results'].append({'test': 'orm_model_support', 'error': str(e)})
118
+
119
+ def test_dev_workflow(self):
120
+ """Test 3: Development Workflow - Create dev branch, test, merge"""
121
+ print("\n=== Test 3: Development Workflow ===")
122
+ self.results['tests_run'] += 1
123
+
124
+ try:
125
+ host, port, user, password, database = get_connection_params()
126
+ client = Client(logger=self.logger, sql_log_mode="full")
127
+ client.connect(host=host, port=port, user=user, password=password, database=database)
128
+
129
+ # Cleanup first
130
+ client.execute("DROP TABLE IF EXISTS users_dev")
131
+ client.execute("DROP TABLE IF EXISTS users_prod")
132
+
133
+ # Setup production
134
+ client.execute("""
135
+ CREATE TABLE users_prod (
136
+ id INT PRIMARY KEY,
137
+ name VARCHAR(100),
138
+ email VARCHAR(100),
139
+ status VARCHAR(20)
140
+ )
141
+ """)
142
+ client.execute("INSERT INTO users_prod VALUES (1, 'Alice', 'alice@example.com', 'active')")
143
+ client.execute("INSERT INTO users_prod VALUES (2, 'Bob', 'bob@example.com', 'active')")
144
+
145
+ # Create dev branch
146
+ client.branch.create('users_dev', 'users_prod')
147
+
148
+ # Make changes in dev (data only, not schema)
149
+ client.execute("INSERT INTO users_dev VALUES (3, 'Charlie', 'charlie@example.com', 'active')")
150
+
151
+ # Compare
152
+ diffs = client.branch.diff('users_dev', 'users_prod')
153
+
154
+ # Merge
155
+ client.branch.merge('users_dev', 'users_prod', on_conflict='accept')
156
+ result = client.execute("SELECT COUNT(*) FROM users_prod")
157
+ count = result.rows[0][0]
158
+
159
+ client.execute("DROP TABLE users_dev")
160
+ client.execute("DROP TABLE users_prod")
161
+
162
+ self.logger.info(f"✅ Development workflow test passed (merged {count} users)")
163
+ self.results['tests_passed'] += 1
164
+ client.disconnect()
165
+
166
+ except Exception as e:
167
+ self.logger.error(f"❌ Development workflow test failed: {e}")
168
+ self.results['tests_failed'] += 1
169
+ self.results['unexpected_results'].append({'test': 'dev_workflow', 'error': str(e)})
170
+
171
+ def test_safe_migration(self):
172
+ """Test 4: Safe Data Migration - Snapshot-based testing before applying"""
173
+ print("\n=== Test 4: Safe Data Migration ===")
174
+ self.results['tests_run'] += 1
175
+
176
+ try:
177
+ host, port, user, password, database = get_connection_params()
178
+ client = Client(logger=self.logger, sql_log_mode="full")
179
+ client.connect(host=host, port=port, user=user, password=password, database=database)
180
+
181
+ # Setup
182
+ client.execute("DROP TABLE IF EXISTS orders")
183
+ client.execute("""
184
+ CREATE TABLE orders (
185
+ id INT PRIMARY KEY,
186
+ customer_id INT,
187
+ amount DECIMAL(10,2),
188
+ status VARCHAR(20)
189
+ )
190
+ """)
191
+ client.execute("INSERT INTO orders VALUES (1, 101, 100.00, 'pending')")
192
+ client.execute("INSERT INTO orders VALUES (2, 102, 200.00, 'completed')")
193
+
194
+ # Create snapshot
195
+ snap_name = f"orders_backup_{int(time.time())}"
196
+ client.execute(f"CREATE SNAPSHOT {snap_name} FOR TABLE test orders")
197
+
198
+ # Create branch from snapshot
199
+ client.branch.create('orders_test', 'orders', snapshot=snap_name)
200
+
201
+ # Test migration
202
+ client.execute("UPDATE orders_test SET status = 'processing' WHERE status = 'pending'")
203
+ result = client.execute("SELECT COUNT(*) FROM orders_test WHERE status = 'processing'")
204
+ migrated = result.rows[0][0]
205
+
206
+ # Apply to production
207
+ client.execute("UPDATE orders SET status = 'processing' WHERE status = 'pending'")
208
+
209
+ client.execute("DROP TABLE orders_test")
210
+ client.execute("DROP TABLE orders")
211
+ client.execute(f"DROP SNAPSHOT {snap_name}")
212
+
213
+ self.logger.info(f"✅ Safe migration test passed ({migrated} orders updated)")
214
+ self.results['tests_passed'] += 1
215
+ client.disconnect()
216
+
217
+ except Exception as e:
218
+ self.logger.error(f"❌ Safe migration test failed: {e}")
219
+ self.results['tests_failed'] += 1
220
+ self.results['unexpected_results'].append({'test': 'safe_migration', 'error': str(e)})
221
+
222
+ def test_ab_testing(self):
223
+ """Test 5: A/B Testing - Compare different data transformations"""
224
+ print("\n=== Test 5: A/B Testing ===")
225
+ self.results['tests_run'] += 1
226
+
227
+ try:
228
+ host, port, user, password, database = get_connection_params()
229
+ client = Client(logger=self.logger, sql_log_mode="full")
230
+ client.connect(host=host, port=port, user=user, password=password, database=database)
231
+
232
+ # Setup
233
+ client.execute("DROP TABLE IF EXISTS products")
234
+ client.execute("""
235
+ CREATE TABLE products (
236
+ id INT PRIMARY KEY,
237
+ name VARCHAR(100),
238
+ price DECIMAL(10,2)
239
+ )
240
+ """)
241
+ client.execute("INSERT INTO products VALUES (1, 'Laptop', 1000.00)")
242
+ client.execute("INSERT INTO products VALUES (2, 'Mouse', 50.00)")
243
+ client.execute("INSERT INTO products VALUES (3, 'Desk', 300.00)")
244
+
245
+ # Branch A: 10% discount
246
+ client.branch.create('products_a', 'products')
247
+ client.execute("UPDATE products_a SET price = price * 0.9")
248
+ result = client.execute("SELECT AVG(price) FROM products_a")
249
+ avg_a = float(result.rows[0][0])
250
+
251
+ # Branch B: 15% discount
252
+ client.branch.create('products_b', 'products')
253
+ client.execute("UPDATE products_b SET price = price * 0.85")
254
+ result = client.execute("SELECT AVG(price) FROM products_b")
255
+ avg_b = float(result.rows[0][0])
256
+
257
+ # Merge winner
258
+ client.branch.merge('products_b', 'products', on_conflict='accept')
259
+
260
+ client.execute("DROP TABLE products_a")
261
+ client.execute("DROP TABLE products_b")
262
+ client.execute("DROP TABLE products")
263
+
264
+ self.logger.info(f"✅ A/B testing test passed (A: ${avg_a:.2f}, B: ${avg_b:.2f})")
265
+ self.results['tests_passed'] += 1
266
+ client.disconnect()
267
+
268
+ except Exception as e:
269
+ self.logger.error(f"❌ A/B testing test failed: {e}")
270
+ self.results['tests_failed'] += 1
271
+ self.results['unexpected_results'].append({'test': 'ab_testing', 'error': str(e)})
272
+
273
+ def test_multi_team(self):
274
+ """Test 6: Multi-Team Development - Independent branches with conflict resolution"""
275
+ print("\n=== Test 6: Multi-Team Development ===")
276
+ self.results['tests_run'] += 1
277
+
278
+ try:
279
+ host, port, user, password, database = get_connection_params()
280
+ client = Client(logger=self.logger, sql_log_mode="full")
281
+ client.connect(host=host, port=port, user=user, password=password, database=database)
282
+
283
+ # Setup
284
+ client.execute("DROP TABLE IF EXISTS inventory")
285
+ client.execute("""
286
+ CREATE TABLE inventory (
287
+ id INT PRIMARY KEY,
288
+ item VARCHAR(100),
289
+ quantity INT,
290
+ warehouse VARCHAR(50)
291
+ )
292
+ """)
293
+ client.execute("INSERT INTO inventory VALUES (1, 'Widget A', 100, 'Warehouse 1')")
294
+ client.execute("INSERT INTO inventory VALUES (2, 'Widget B', 50, 'Warehouse 2')")
295
+
296
+ # Team A: Update warehouse
297
+ client.branch.create('inventory_team_a', 'inventory')
298
+ client.execute("UPDATE inventory_team_a SET warehouse = 'Warehouse 1' WHERE id = 1")
299
+
300
+ # Team B: Update quantities
301
+ client.branch.create('inventory_team_b', 'inventory')
302
+ client.execute("UPDATE inventory_team_b SET quantity = 150 WHERE id = 1")
303
+
304
+ # Merge both
305
+ client.branch.merge('inventory_team_a', 'inventory', on_conflict='accept')
306
+ client.branch.merge('inventory_team_b', 'inventory', on_conflict='accept')
307
+
308
+ client.execute("DROP TABLE inventory_team_a")
309
+ client.execute("DROP TABLE inventory_team_b")
310
+ client.execute("DROP TABLE inventory")
311
+
312
+ self.logger.info("✅ Multi-team development test passed")
313
+ self.results['tests_passed'] += 1
314
+ client.disconnect()
315
+
316
+ except Exception as e:
317
+ self.logger.error(f"❌ Multi-team development test failed: {e}")
318
+ self.results['tests_failed'] += 1
319
+ self.results['unexpected_results'].append({'test': 'multi_team', 'error': str(e)})
320
+
321
+ def test_database_branching(self):
322
+ """Test 7: Database-Level Branching - Schema changes across entire databases"""
323
+ print("\n=== Test 7: Database-Level Branching ===")
324
+ self.results['tests_run'] += 1
325
+
326
+ try:
327
+ host, port, user, password, database = get_connection_params()
328
+ client = Client(logger=self.logger, sql_log_mode="full")
329
+ client.connect(host=host, port=port, user=user, password=password, database=database)
330
+
331
+ prod_db = f"shop_prod_{int(time.time())}"
332
+ dev_db = f"shop_dev_{int(time.time())}"
333
+
334
+ # Setup production database
335
+ client.execute(f"DROP DATABASE IF EXISTS {prod_db}")
336
+ client.execute(f"CREATE DATABASE {prod_db}")
337
+ client.execute(f"USE {prod_db}")
338
+ client.execute("""
339
+ CREATE TABLE customers (
340
+ id INT PRIMARY KEY,
341
+ name VARCHAR(100)
342
+ )
343
+ """)
344
+ client.execute("""
345
+ CREATE TABLE orders (
346
+ id INT PRIMARY KEY,
347
+ customer_id INT,
348
+ amount DECIMAL(10,2)
349
+ )
350
+ """)
351
+ client.execute("INSERT INTO customers VALUES (1, 'Alice')")
352
+ client.execute("INSERT INTO orders VALUES (1, 1, 100.00)")
353
+
354
+ # Create dev database branch
355
+ client.branch.create(dev_db, prod_db, database=True)
356
+
357
+ # Test schema changes
358
+ client.execute(f"USE {dev_db}")
359
+ client.execute("ALTER TABLE customers ADD COLUMN email VARCHAR(100)")
360
+ client.execute("ALTER TABLE orders ADD COLUMN status VARCHAR(20)")
361
+ result = client.execute("DESCRIBE customers")
362
+ columns = len(result.rows)
363
+
364
+ # Cleanup
365
+ client.execute(f"USE test")
366
+ client.execute(f"DROP DATABASE {prod_db}")
367
+ client.execute(f"DROP DATABASE {dev_db}")
368
+
369
+ self.logger.info(f"✅ Database-level branching test passed ({columns} columns)")
370
+ self.results['tests_passed'] += 1
371
+ client.disconnect()
372
+
373
+ except Exception as e:
374
+ self.logger.error(f"❌ Database-level branching test failed: {e}")
375
+ self.results['tests_failed'] += 1
376
+ self.results['unexpected_results'].append({'test': 'database_branching', 'error': str(e)})
377
+
378
+ async def test_async_operations(self):
379
+ """Test 8: Async Operations - Non-blocking branch operations"""
380
+ print("\n=== Test 8: Async Operations ===")
381
+ self.results['tests_run'] += 1
382
+
383
+ try:
384
+ host, port, user, password, database = get_connection_params()
385
+ async_client = AsyncClient(logger=self.logger, sql_log_mode="full")
386
+ await async_client.connect(host=host, port=port, user=user, password=password, database=database)
387
+
388
+ # Create table
389
+ await async_client.execute("DROP TABLE IF EXISTS async_test")
390
+ await async_client.execute("CREATE TABLE async_test (id INT PRIMARY KEY)")
391
+ await async_client.execute("INSERT INTO async_test VALUES (1)")
392
+
393
+ # Async branch operations
394
+ await async_client.branch.create('async_test_branch', 'async_test')
395
+ diffs = await async_client.branch.diff('async_test_branch', 'async_test')
396
+ await async_client.branch.delete('async_test_branch')
397
+
398
+ await async_client.execute("DROP TABLE async_test")
399
+ await async_client.disconnect()
400
+
401
+ self.logger.info("✅ Async operations test passed")
402
+ self.results['tests_passed'] += 1
403
+
404
+ except Exception as e:
405
+ self.logger.error(f"❌ Async operations test failed: {e}")
406
+ self.results['tests_failed'] += 1
407
+ self.results['unexpected_results'].append({'test': 'async_operations', 'error': str(e)})
408
+
409
+ def generate_summary_report(self):
410
+ """Generate comprehensive summary report."""
411
+ print("\n" + "="*80)
412
+ print("Branch Operations Demo - Summary Report")
413
+ print("="*80)
414
+
415
+ total_tests = self.results['tests_run']
416
+ passed_tests = self.results['tests_passed']
417
+ failed_tests = self.results['tests_failed']
418
+ unexpected_results = self.results['unexpected_results']
419
+
420
+ print(f"Total Tests Run: {total_tests}")
421
+ print(f"Tests Passed: {passed_tests}")
422
+ print(f"Tests Failed: {failed_tests}")
423
+ print(f"Success Rate: {(passed_tests/total_tests*100):.1f}%" if total_tests > 0 else "N/A")
424
+
425
+ if unexpected_results:
426
+ print(f"\nUnexpected Results ({len(unexpected_results)}):")
427
+ for i, result in enumerate(unexpected_results, 1):
428
+ print(f" {i}. Test: {result['test']}")
429
+ print(f" Error: {result['error']}")
430
+ else:
431
+ print("\n✓ No unexpected results - all tests behaved as expected")
432
+
433
+ return self.results
434
+
435
+ def run_all_tests(self):
436
+ """Run all tests"""
437
+ print("\n" + "="*80)
438
+ print("MatrixOne Branch Operations - Complete Examples")
439
+ print("="*80)
440
+ print_config()
441
+
442
+ self.test_basic_api()
443
+ self.test_orm_model_support()
444
+ self.test_dev_workflow()
445
+ self.test_safe_migration()
446
+ self.test_ab_testing()
447
+ self.test_multi_team()
448
+ self.test_database_branching()
449
+ asyncio.run(self.test_async_operations())
450
+
451
+ results = self.generate_summary_report()
452
+
453
+ print("\n" + "="*80)
454
+ print("Key Features Demonstrated:")
455
+ print("="*80)
456
+ print("1. ✓ Simple API: create(), delete(), diff(), merge()")
457
+ print("2. ✓ ORM Model Support: Works with SQLAlchemy models")
458
+ print("3. ✓ Development Workflow: Isolate, test, merge changes")
459
+ print("4. ✓ Safe Migration: Snapshot-based testing")
460
+ print("5. ✓ A/B Testing: Compare different data transformations")
461
+ print("6. ✓ Multi-Team: Independent branches with conflict resolution")
462
+ print("7. ✓ Database Branching: Schema changes across entire databases")
463
+ print("8. ✓ Async Support: Non-blocking operations")
464
+
465
+ return results
466
+
467
+
468
+ def main():
469
+ """Main entry point"""
470
+ demo = BranchOperationsDemo()
471
+ demo.run_all_tests()
472
+
473
+
474
+ if __name__ == '__main__':
475
+ main()