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
@@ -0,0 +1,90 @@
|
|
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
|
+
Configuration for online tests
|
17
|
+
"""
|
18
|
+
|
19
|
+
import os
|
20
|
+
from typing import Optional, Tuple
|
21
|
+
|
22
|
+
|
23
|
+
class OnlineTestConfig:
|
24
|
+
"""Configuration for online tests"""
|
25
|
+
|
26
|
+
def __init__(self):
|
27
|
+
# Connection parameters
|
28
|
+
self.host = os.getenv('MATRIXONE_HOST', '127.0.0.1')
|
29
|
+
self.port = int(os.getenv('MATRIXONE_PORT', '6001'))
|
30
|
+
self.user = os.getenv('MATRIXONE_USER', 'root')
|
31
|
+
self.password = os.getenv('MATRIXONE_PASSWORD', '111')
|
32
|
+
self.database = os.getenv('MATRIXONE_DATABASE', 'test')
|
33
|
+
|
34
|
+
# Test database names (can be overridden for different test environments)
|
35
|
+
self.test_database = os.getenv('MATRIXONE_TEST_DATABASE', self.database)
|
36
|
+
self.sys_database = os.getenv('MATRIXONE_SYS_DATABASE', 'sys')
|
37
|
+
|
38
|
+
# Test account (for multi-tenant scenarios)
|
39
|
+
self.test_account = os.getenv('MATRIXONE_TEST_ACCOUNT', 'sys')
|
40
|
+
|
41
|
+
# Test table prefixes (to avoid conflicts)
|
42
|
+
self.table_prefix = os.getenv('MATRIXONE_TABLE_PREFIX', 'test_')
|
43
|
+
|
44
|
+
# Snapshot and backup settings
|
45
|
+
self.snapshot_prefix = os.getenv('MATRIXONE_SNAPSHOT_PREFIX', 'testsnapshot')
|
46
|
+
|
47
|
+
# Vector test settings
|
48
|
+
self.vector_dimensions = int(os.getenv('MATRIXONE_VECTOR_DIMENSIONS', '64'))
|
49
|
+
self.vector_test_data_size = int(os.getenv('MATRIXONE_VECTOR_TEST_SIZE', '100'))
|
50
|
+
|
51
|
+
def get_connection_params(self) -> Tuple[str, int, str, str, str]:
|
52
|
+
"""Get connection parameters as tuple"""
|
53
|
+
return self.host, self.port, self.user, self.password, self.database
|
54
|
+
|
55
|
+
def get_test_database(self) -> str:
|
56
|
+
"""Get test database name"""
|
57
|
+
return self.test_database
|
58
|
+
|
59
|
+
def get_sys_database(self) -> str:
|
60
|
+
"""Get system database name"""
|
61
|
+
return self.sys_database
|
62
|
+
|
63
|
+
def get_test_account(self) -> str:
|
64
|
+
"""Get test account name"""
|
65
|
+
return self.test_account
|
66
|
+
|
67
|
+
def get_table_name(self, base_name: str) -> str:
|
68
|
+
"""Get full table name with prefix"""
|
69
|
+
return f"{self.table_prefix}{base_name}"
|
70
|
+
|
71
|
+
def get_snapshot_name(self, base_name: str = None) -> str:
|
72
|
+
"""Get snapshot name with prefix"""
|
73
|
+
if base_name:
|
74
|
+
return f"{self.snapshot_prefix}_{base_name}"
|
75
|
+
return self.snapshot_prefix
|
76
|
+
|
77
|
+
def get_vector_dimensions(self) -> int:
|
78
|
+
"""Get vector dimensions for tests"""
|
79
|
+
return self.vector_dimensions
|
80
|
+
|
81
|
+
def get_vector_test_data_size(self) -> int:
|
82
|
+
"""Get vector test data size"""
|
83
|
+
return self.vector_test_data_size
|
84
|
+
|
85
|
+
def __str__(self):
|
86
|
+
return f"OnlineTestConfig(host={self.host}, port={self.port}, user={self.user}, database={self.database}, test_database={self.test_database})"
|
87
|
+
|
88
|
+
|
89
|
+
# Global configuration instance
|
90
|
+
online_config = OnlineTestConfig()
|
@@ -0,0 +1,123 @@
|
|
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 configuration validation for online tests
|
17
|
+
"""
|
18
|
+
|
19
|
+
import pytest
|
20
|
+
import os
|
21
|
+
from .test_config import online_config
|
22
|
+
|
23
|
+
|
24
|
+
class TestConfigValidation:
|
25
|
+
"""Test that the configuration system works correctly"""
|
26
|
+
|
27
|
+
def test_config_has_all_required_attributes(self):
|
28
|
+
"""Test that config has all required attributes"""
|
29
|
+
assert hasattr(online_config, 'host')
|
30
|
+
assert hasattr(online_config, 'port')
|
31
|
+
assert hasattr(online_config, 'user')
|
32
|
+
assert hasattr(online_config, 'password')
|
33
|
+
assert hasattr(online_config, 'database')
|
34
|
+
assert hasattr(online_config, 'test_database')
|
35
|
+
assert hasattr(online_config, 'sys_database')
|
36
|
+
assert hasattr(online_config, 'test_account')
|
37
|
+
assert hasattr(online_config, 'table_prefix')
|
38
|
+
assert hasattr(online_config, 'snapshot_prefix')
|
39
|
+
assert hasattr(online_config, 'vector_dimensions')
|
40
|
+
assert hasattr(online_config, 'vector_test_data_size')
|
41
|
+
|
42
|
+
def test_config_methods_work(self):
|
43
|
+
"""Test that config methods work correctly"""
|
44
|
+
# Test connection params
|
45
|
+
host, port, user, password, database = online_config.get_connection_params()
|
46
|
+
assert isinstance(host, str)
|
47
|
+
assert isinstance(port, int)
|
48
|
+
assert isinstance(user, str)
|
49
|
+
assert isinstance(password, str)
|
50
|
+
assert isinstance(database, str)
|
51
|
+
|
52
|
+
# Test database names
|
53
|
+
test_db = online_config.get_test_database()
|
54
|
+
sys_db = online_config.get_sys_database()
|
55
|
+
assert isinstance(test_db, str)
|
56
|
+
assert isinstance(sys_db, str)
|
57
|
+
|
58
|
+
# Test account
|
59
|
+
account = online_config.get_test_account()
|
60
|
+
assert isinstance(account, str)
|
61
|
+
|
62
|
+
# Test table name generation
|
63
|
+
table_name = online_config.get_table_name("test_table")
|
64
|
+
assert table_name == f"{online_config.table_prefix}test_table"
|
65
|
+
|
66
|
+
# Test snapshot name generation
|
67
|
+
snapshot_name = online_config.get_snapshot_name("test_snapshot")
|
68
|
+
assert snapshot_name == f"{online_config.snapshot_prefix}_test_snapshot"
|
69
|
+
|
70
|
+
# Test vector settings
|
71
|
+
dimensions = online_config.get_vector_dimensions()
|
72
|
+
data_size = online_config.get_vector_test_data_size()
|
73
|
+
assert isinstance(dimensions, int)
|
74
|
+
assert isinstance(data_size, int)
|
75
|
+
|
76
|
+
def test_config_respects_environment_variables(self):
|
77
|
+
"""Test that config respects environment variables"""
|
78
|
+
# Save original values
|
79
|
+
original_host = online_config.host
|
80
|
+
original_port = online_config.port
|
81
|
+
original_user = online_config.user
|
82
|
+
original_password = online_config.password
|
83
|
+
original_database = online_config.database
|
84
|
+
|
85
|
+
try:
|
86
|
+
# Set test environment variables
|
87
|
+
os.environ['MATRIXONE_HOST'] = 'test_host'
|
88
|
+
os.environ['MATRIXONE_PORT'] = '9999'
|
89
|
+
os.environ['MATRIXONE_USER'] = 'test_user'
|
90
|
+
os.environ['MATRIXONE_PASSWORD'] = 'test_password'
|
91
|
+
os.environ['MATRIXONE_DATABASE'] = 'test_db'
|
92
|
+
|
93
|
+
# Create new config instance to test env vars
|
94
|
+
from .test_config import OnlineTestConfig
|
95
|
+
|
96
|
+
test_config = OnlineTestConfig()
|
97
|
+
|
98
|
+
assert test_config.host == 'test_host'
|
99
|
+
assert test_config.port == 9999
|
100
|
+
assert test_config.user == 'test_user'
|
101
|
+
assert test_config.password == 'test_password'
|
102
|
+
assert test_config.database == 'test_db'
|
103
|
+
|
104
|
+
finally:
|
105
|
+
# Clean up environment variables
|
106
|
+
for key in [
|
107
|
+
'MATRIXONE_HOST',
|
108
|
+
'MATRIXONE_PORT',
|
109
|
+
'MATRIXONE_USER',
|
110
|
+
'MATRIXONE_PASSWORD',
|
111
|
+
'MATRIXONE_DATABASE',
|
112
|
+
]:
|
113
|
+
if key in os.environ:
|
114
|
+
del os.environ[key]
|
115
|
+
|
116
|
+
def test_config_string_representation(self):
|
117
|
+
"""Test config string representation"""
|
118
|
+
config_str = str(online_config)
|
119
|
+
assert 'OnlineTestConfig' in config_str
|
120
|
+
assert online_config.host in config_str
|
121
|
+
assert str(online_config.port) in config_str
|
122
|
+
assert online_config.user in config_str
|
123
|
+
assert online_config.database in config_str
|
@@ -0,0 +1,217 @@
|
|
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
|
+
#!/usr/bin/env python3
|
16
|
+
"""
|
17
|
+
Online tests for the new connection hooks functionality using SQLAlchemy events
|
18
|
+
"""
|
19
|
+
|
20
|
+
import pytest
|
21
|
+
from matrixone import Client, AsyncClient
|
22
|
+
from matrixone.connection_hooks import ConnectionAction, create_connection_hook
|
23
|
+
|
24
|
+
|
25
|
+
class TestNewConnectionHooksOnline:
|
26
|
+
"""Test the new connection hooks implementation with SQLAlchemy events"""
|
27
|
+
|
28
|
+
def test_sync_client_connection_hook_executes_on_each_connection(self, test_client):
|
29
|
+
"""Test that connection hook executes on each new connection"""
|
30
|
+
# Create a new client instance
|
31
|
+
client = Client()
|
32
|
+
|
33
|
+
# Track how many times the hook is called
|
34
|
+
hook_call_count = 0
|
35
|
+
|
36
|
+
def count_hook_calls(client):
|
37
|
+
nonlocal hook_call_count
|
38
|
+
hook_call_count += 1
|
39
|
+
print(f"Hook called {hook_call_count} times")
|
40
|
+
|
41
|
+
# Connect with the hook
|
42
|
+
client.connect(
|
43
|
+
host=test_client._connection_params['host'],
|
44
|
+
port=test_client._connection_params['port'],
|
45
|
+
user=test_client._connection_params['user'],
|
46
|
+
password=test_client._connection_params['password'],
|
47
|
+
database=test_client._connection_params['database'],
|
48
|
+
on_connect=count_hook_calls,
|
49
|
+
)
|
50
|
+
|
51
|
+
# The hook should be called once for the initial connection
|
52
|
+
assert hook_call_count >= 1
|
53
|
+
|
54
|
+
# Force a new connection by executing a query
|
55
|
+
# This should trigger the hook again
|
56
|
+
result = client.execute("SELECT 1")
|
57
|
+
assert len(result.rows) == 1
|
58
|
+
|
59
|
+
# The hook should be called again for the new connection
|
60
|
+
assert hook_call_count >= 2
|
61
|
+
|
62
|
+
# Clean up
|
63
|
+
client.disconnect()
|
64
|
+
|
65
|
+
def test_sync_client_with_predefined_actions(self, test_client):
|
66
|
+
"""Test sync client with predefined actions"""
|
67
|
+
client = Client()
|
68
|
+
|
69
|
+
# Connect with predefined actions
|
70
|
+
client.connect(
|
71
|
+
host=test_client._connection_params['host'],
|
72
|
+
port=test_client._connection_params['port'],
|
73
|
+
user=test_client._connection_params['user'],
|
74
|
+
password=test_client._connection_params['password'],
|
75
|
+
database=test_client._connection_params['database'],
|
76
|
+
on_connect=[ConnectionAction.ENABLE_FULLTEXT],
|
77
|
+
)
|
78
|
+
|
79
|
+
assert client.connected()
|
80
|
+
|
81
|
+
# Test that we can use fulltext operations
|
82
|
+
# (This would fail if fulltext wasn't enabled)
|
83
|
+
try:
|
84
|
+
# Create a simple table and test fulltext
|
85
|
+
client.execute("CREATE TABLE IF NOT EXISTS test_hook_table (id INT, content TEXT)")
|
86
|
+
client.execute("INSERT INTO test_hook_table VALUES (1, 'test content')")
|
87
|
+
|
88
|
+
# This should work if fulltext is enabled
|
89
|
+
result = (
|
90
|
+
client.query("test_hook_table.content")
|
91
|
+
.filter("MATCH(content) AGAINST('test' IN NATURAL LANGUAGE MODE)")
|
92
|
+
.execute()
|
93
|
+
)
|
94
|
+
|
95
|
+
# Clean up
|
96
|
+
client.execute("DROP TABLE IF EXISTS test_hook_table")
|
97
|
+
|
98
|
+
except Exception as e:
|
99
|
+
# If fulltext is not available, that's okay for this test
|
100
|
+
print(f"Fulltext test skipped: {e}")
|
101
|
+
|
102
|
+
# Clean up
|
103
|
+
client.disconnect()
|
104
|
+
|
105
|
+
@pytest.mark.asyncio
|
106
|
+
async def test_async_client_connection_hook_executes_on_each_connection(self, test_async_client):
|
107
|
+
"""Test that async connection hook executes on each new connection"""
|
108
|
+
# Create a new client instance
|
109
|
+
client = AsyncClient()
|
110
|
+
|
111
|
+
# Track how many times the hook is called
|
112
|
+
hook_call_count = 0
|
113
|
+
|
114
|
+
def count_hook_calls(client):
|
115
|
+
nonlocal hook_call_count
|
116
|
+
hook_call_count += 1
|
117
|
+
print(f"Async hook called {hook_call_count} times")
|
118
|
+
|
119
|
+
# Connect with the hook
|
120
|
+
await client.connect(
|
121
|
+
host=test_async_client._connection_params['host'],
|
122
|
+
port=test_async_client._connection_params['port'],
|
123
|
+
user=test_async_client._connection_params['user'],
|
124
|
+
password=test_async_client._connection_params['password'],
|
125
|
+
database=test_async_client._connection_params['database'],
|
126
|
+
on_connect=count_hook_calls,
|
127
|
+
)
|
128
|
+
|
129
|
+
# The hook should be called once for the initial connection
|
130
|
+
assert hook_call_count >= 1
|
131
|
+
|
132
|
+
# Force a new connection by executing a query
|
133
|
+
# This should trigger the hook again
|
134
|
+
result = await client.execute("SELECT 1")
|
135
|
+
assert len(result.rows) == 1
|
136
|
+
|
137
|
+
# The hook should be called again for the new connection
|
138
|
+
assert hook_call_count >= 2
|
139
|
+
|
140
|
+
# Clean up
|
141
|
+
await client.disconnect()
|
142
|
+
|
143
|
+
@pytest.mark.asyncio
|
144
|
+
async def test_async_client_with_predefined_actions(self, test_async_client):
|
145
|
+
"""Test async client with predefined actions"""
|
146
|
+
client = AsyncClient()
|
147
|
+
|
148
|
+
# Connect with predefined actions
|
149
|
+
await client.connect(
|
150
|
+
host=test_async_client._connection_params['host'],
|
151
|
+
port=test_async_client._connection_params['port'],
|
152
|
+
user=test_async_client._connection_params['user'],
|
153
|
+
password=test_async_client._connection_params['password'],
|
154
|
+
database=test_async_client._connection_params['database'],
|
155
|
+
on_connect=[ConnectionAction.ENABLE_FULLTEXT],
|
156
|
+
)
|
157
|
+
|
158
|
+
assert client.connected()
|
159
|
+
|
160
|
+
# Test that we can use fulltext operations
|
161
|
+
try:
|
162
|
+
# Create a simple table and test fulltext
|
163
|
+
await client.execute("CREATE TABLE IF NOT EXISTS test_async_hook_table (id INT, content TEXT)")
|
164
|
+
await client.execute("INSERT INTO test_async_hook_table VALUES (1, 'test content')")
|
165
|
+
|
166
|
+
# This should work if fulltext is enabled
|
167
|
+
result = (
|
168
|
+
await client.query("test_async_hook_table.content")
|
169
|
+
.filter("MATCH(content) AGAINST('test' IN NATURAL LANGUAGE MODE)")
|
170
|
+
.execute()
|
171
|
+
)
|
172
|
+
|
173
|
+
# Clean up
|
174
|
+
await client.execute("DROP TABLE IF EXISTS test_async_hook_table")
|
175
|
+
|
176
|
+
except Exception as e:
|
177
|
+
# If fulltext is not available, that's okay for this test
|
178
|
+
print(f"Async fulltext test skipped: {e}")
|
179
|
+
|
180
|
+
# Clean up
|
181
|
+
await client.disconnect()
|
182
|
+
|
183
|
+
def test_connection_hook_with_multiple_actions(self, test_client):
|
184
|
+
"""Test connection hook with multiple actions"""
|
185
|
+
client = Client()
|
186
|
+
|
187
|
+
# Track which actions were executed
|
188
|
+
executed_actions = []
|
189
|
+
|
190
|
+
def track_actions(client):
|
191
|
+
executed_actions.append("custom_hook")
|
192
|
+
|
193
|
+
# Create hook with multiple actions
|
194
|
+
hook = create_connection_hook(
|
195
|
+
actions=[ConnectionAction.ENABLE_FULLTEXT, ConnectionAction.ENABLE_IVF], custom_hook=track_actions
|
196
|
+
)
|
197
|
+
|
198
|
+
# Connect with the hook
|
199
|
+
client.connect(
|
200
|
+
host=test_client._connection_params['host'],
|
201
|
+
port=test_client._connection_params['port'],
|
202
|
+
user=test_client._connection_params['user'],
|
203
|
+
password=test_client._connection_params['password'],
|
204
|
+
database=test_client._connection_params['database'],
|
205
|
+
on_connect=hook,
|
206
|
+
)
|
207
|
+
|
208
|
+
assert client.connected()
|
209
|
+
|
210
|
+
# Force a new connection to trigger the hook
|
211
|
+
client.execute("SELECT 1")
|
212
|
+
|
213
|
+
# The custom hook should have been called
|
214
|
+
assert "custom_hook" in executed_actions
|
215
|
+
|
216
|
+
# Clean up
|
217
|
+
client.disconnect()
|