memorisdk 1.0.1__py3-none-any.whl → 2.0.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.
Potentially problematic release.
This version of memorisdk might be problematic. Click here for more details.
- memori/__init__.py +24 -8
- memori/agents/conscious_agent.py +252 -414
- memori/agents/memory_agent.py +487 -224
- memori/agents/retrieval_agent.py +416 -60
- memori/config/memory_manager.py +323 -0
- memori/core/conversation.py +393 -0
- memori/core/database.py +386 -371
- memori/core/memory.py +1676 -534
- memori/core/providers.py +217 -0
- memori/database/adapters/__init__.py +10 -0
- memori/database/adapters/mysql_adapter.py +331 -0
- memori/database/adapters/postgresql_adapter.py +291 -0
- memori/database/adapters/sqlite_adapter.py +229 -0
- memori/database/auto_creator.py +320 -0
- memori/database/connection_utils.py +207 -0
- memori/database/connectors/base_connector.py +283 -0
- memori/database/connectors/mysql_connector.py +240 -18
- memori/database/connectors/postgres_connector.py +277 -4
- memori/database/connectors/sqlite_connector.py +178 -3
- memori/database/models.py +400 -0
- memori/database/queries/base_queries.py +1 -1
- memori/database/queries/memory_queries.py +91 -2
- memori/database/query_translator.py +222 -0
- memori/database/schema_generators/__init__.py +7 -0
- memori/database/schema_generators/mysql_schema_generator.py +215 -0
- memori/database/search/__init__.py +8 -0
- memori/database/search/mysql_search_adapter.py +255 -0
- memori/database/search/sqlite_search_adapter.py +180 -0
- memori/database/search_service.py +548 -0
- memori/database/sqlalchemy_manager.py +839 -0
- memori/integrations/__init__.py +36 -11
- memori/integrations/litellm_integration.py +340 -6
- memori/integrations/openai_integration.py +506 -240
- memori/utils/input_validator.py +395 -0
- memori/utils/pydantic_models.py +138 -36
- memori/utils/query_builder.py +530 -0
- memori/utils/security_audit.py +594 -0
- memori/utils/security_integration.py +339 -0
- memori/utils/transaction_manager.py +547 -0
- {memorisdk-1.0.1.dist-info → memorisdk-2.0.0.dist-info}/METADATA +144 -34
- memorisdk-2.0.0.dist-info/RECORD +67 -0
- memorisdk-1.0.1.dist-info/RECORD +0 -44
- memorisdk-1.0.1.dist-info/entry_points.txt +0 -2
- {memorisdk-1.0.1.dist-info → memorisdk-2.0.0.dist-info}/WHEEL +0 -0
- {memorisdk-1.0.1.dist-info → memorisdk-2.0.0.dist-info}/licenses/LICENSE +0 -0
- {memorisdk-1.0.1.dist-info → memorisdk-2.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Cross-database query parameter translator for Memori v2.0
|
|
3
|
+
|
|
4
|
+
This module provides database-agnostic parameter translation to handle
|
|
5
|
+
differences between SQLite, PostgreSQL, and MySQL, particularly for
|
|
6
|
+
boolean values and other database-specific syntax.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Any, Dict, Union
|
|
10
|
+
|
|
11
|
+
from loguru import logger
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class QueryParameterTranslator:
|
|
15
|
+
"""
|
|
16
|
+
Translates query parameters to be compatible with different database engines.
|
|
17
|
+
|
|
18
|
+
Handles cross-database compatibility issues like:
|
|
19
|
+
- Boolean values (SQLite: 0/1, PostgreSQL: TRUE/FALSE, MySQL: 0/1)
|
|
20
|
+
- Date/time formats
|
|
21
|
+
- Case sensitivity
|
|
22
|
+
- Data type constraints
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, database_type: str):
|
|
26
|
+
"""
|
|
27
|
+
Initialize translator for specific database type.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
database_type: Database engine name ('sqlite', 'postgresql', 'mysql')
|
|
31
|
+
"""
|
|
32
|
+
self.database_type = database_type.lower()
|
|
33
|
+
logger.debug(f"QueryParameterTranslator initialized for {self.database_type}")
|
|
34
|
+
|
|
35
|
+
def translate_parameters(self, parameters: Dict[str, Any]) -> Dict[str, Any]:
|
|
36
|
+
"""
|
|
37
|
+
Translate parameters to be compatible with the target database.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
parameters: Dictionary of query parameters
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Dictionary with translated parameters
|
|
44
|
+
"""
|
|
45
|
+
if not parameters:
|
|
46
|
+
return parameters
|
|
47
|
+
|
|
48
|
+
translated = {}
|
|
49
|
+
|
|
50
|
+
for key, value in parameters.items():
|
|
51
|
+
translated[key] = self._translate_value(value, key)
|
|
52
|
+
|
|
53
|
+
return translated
|
|
54
|
+
|
|
55
|
+
def _translate_value(self, value: Any, parameter_name: str = None) -> Any:
|
|
56
|
+
"""Translate a single parameter value based on database type."""
|
|
57
|
+
|
|
58
|
+
# Handle boolean values
|
|
59
|
+
if isinstance(value, bool):
|
|
60
|
+
return self._translate_boolean(value)
|
|
61
|
+
|
|
62
|
+
# Handle integer boolean representations (0, 1)
|
|
63
|
+
if isinstance(value, int) and value in (0, 1):
|
|
64
|
+
# Check if this looks like a boolean context based on parameter name
|
|
65
|
+
if self._is_likely_boolean_context(value, parameter_name):
|
|
66
|
+
return self._translate_boolean(bool(value))
|
|
67
|
+
|
|
68
|
+
# Handle None values
|
|
69
|
+
if value is None:
|
|
70
|
+
return None
|
|
71
|
+
|
|
72
|
+
# Handle lists/arrays
|
|
73
|
+
if isinstance(value, (list, tuple)):
|
|
74
|
+
return [self._translate_value(item) for item in value]
|
|
75
|
+
|
|
76
|
+
# Handle dictionaries
|
|
77
|
+
if isinstance(value, dict):
|
|
78
|
+
return {k: self._translate_value(v, k) for k, v in value.items()}
|
|
79
|
+
|
|
80
|
+
# Return other values unchanged
|
|
81
|
+
return value
|
|
82
|
+
|
|
83
|
+
def _translate_boolean(self, value: bool) -> Union[bool, int]:
|
|
84
|
+
"""
|
|
85
|
+
Translate boolean values for database compatibility.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
value: Boolean value to translate
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
Database-appropriate boolean representation
|
|
92
|
+
"""
|
|
93
|
+
if self.database_type == "postgresql":
|
|
94
|
+
# PostgreSQL uses TRUE/FALSE
|
|
95
|
+
return value # SQLAlchemy handles the TRUE/FALSE conversion
|
|
96
|
+
|
|
97
|
+
elif self.database_type in ("sqlite", "mysql"):
|
|
98
|
+
# SQLite and MySQL use 0/1 for booleans
|
|
99
|
+
return int(value)
|
|
100
|
+
|
|
101
|
+
else:
|
|
102
|
+
# Default: return as-is and let SQLAlchemy handle it
|
|
103
|
+
logger.warning(
|
|
104
|
+
f"Unknown database type {self.database_type}, using default boolean handling"
|
|
105
|
+
)
|
|
106
|
+
return value
|
|
107
|
+
|
|
108
|
+
def _is_likely_boolean_context(
|
|
109
|
+
self, value: int, parameter_name: str = None
|
|
110
|
+
) -> bool:
|
|
111
|
+
"""
|
|
112
|
+
Heuristic to determine if an integer (0 or 1) is meant to be a boolean.
|
|
113
|
+
|
|
114
|
+
This is used to detect integer parameters that should be treated as booleans
|
|
115
|
+
for cross-database compatibility.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
value: Integer value (should be 0 or 1)
|
|
119
|
+
parameter_name: Name of the parameter (for context)
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
True if this looks like a boolean context
|
|
123
|
+
"""
|
|
124
|
+
# Must be 0 or 1 to be considered
|
|
125
|
+
if value not in (0, 1):
|
|
126
|
+
return False
|
|
127
|
+
|
|
128
|
+
# Use parameter name patterns to identify boolean fields
|
|
129
|
+
if parameter_name:
|
|
130
|
+
boolean_patterns = [
|
|
131
|
+
"active",
|
|
132
|
+
"enabled",
|
|
133
|
+
"disabled",
|
|
134
|
+
"processed",
|
|
135
|
+
"eligible",
|
|
136
|
+
"is_",
|
|
137
|
+
"has_",
|
|
138
|
+
"can_",
|
|
139
|
+
"should_",
|
|
140
|
+
"allow_",
|
|
141
|
+
"visible",
|
|
142
|
+
"hidden",
|
|
143
|
+
"conscious_processed",
|
|
144
|
+
"processed_for_duplicates",
|
|
145
|
+
"promotion_eligible",
|
|
146
|
+
"is_user_context",
|
|
147
|
+
"is_preference",
|
|
148
|
+
"is_skill_knowledge",
|
|
149
|
+
"is_current_project",
|
|
150
|
+
"is_permanent_context",
|
|
151
|
+
]
|
|
152
|
+
|
|
153
|
+
param_lower = parameter_name.lower()
|
|
154
|
+
for pattern in boolean_patterns:
|
|
155
|
+
if pattern in param_lower:
|
|
156
|
+
return True
|
|
157
|
+
|
|
158
|
+
# Default to treating 0/1 as potential booleans if no parameter name context
|
|
159
|
+
return True
|
|
160
|
+
|
|
161
|
+
def translate_query_with_parameters(
|
|
162
|
+
self, query: str, parameters: Dict[str, Any]
|
|
163
|
+
) -> tuple[str, Dict[str, Any]]:
|
|
164
|
+
"""
|
|
165
|
+
Translate both query and parameters for database compatibility.
|
|
166
|
+
|
|
167
|
+
Currently focuses on parameter translation, but could be extended
|
|
168
|
+
to handle query syntax differences if needed.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
query: SQL query string
|
|
172
|
+
parameters: Query parameters
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
Tuple of (translated_query, translated_parameters)
|
|
176
|
+
"""
|
|
177
|
+
# For now, we only translate parameters
|
|
178
|
+
# Query translation could be added here if needed for other compatibility issues
|
|
179
|
+
translated_params = self.translate_parameters(parameters)
|
|
180
|
+
|
|
181
|
+
return query, translated_params
|
|
182
|
+
|
|
183
|
+
def get_boolean_true(self) -> Union[bool, int]:
|
|
184
|
+
"""Get database-appropriate TRUE value."""
|
|
185
|
+
return self._translate_boolean(True)
|
|
186
|
+
|
|
187
|
+
def get_boolean_false(self) -> Union[bool, int]:
|
|
188
|
+
"""Get database-appropriate FALSE value."""
|
|
189
|
+
return self._translate_boolean(False)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
# Convenience functions for common boolean translations
|
|
193
|
+
def get_db_boolean(value: bool, database_type: str) -> Union[bool, int]:
|
|
194
|
+
"""
|
|
195
|
+
Get database-appropriate boolean value.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
value: Boolean value
|
|
199
|
+
database_type: Database engine name
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
Database-appropriate boolean representation
|
|
203
|
+
"""
|
|
204
|
+
translator = QueryParameterTranslator(database_type)
|
|
205
|
+
return translator._translate_boolean(value)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def translate_query_params(
|
|
209
|
+
parameters: Dict[str, Any], database_type: str
|
|
210
|
+
) -> Dict[str, Any]:
|
|
211
|
+
"""
|
|
212
|
+
Convenience function to translate query parameters.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
parameters: Query parameters
|
|
216
|
+
database_type: Database engine name
|
|
217
|
+
|
|
218
|
+
Returns:
|
|
219
|
+
Translated parameters
|
|
220
|
+
"""
|
|
221
|
+
translator = QueryParameterTranslator(database_type)
|
|
222
|
+
return translator.translate_parameters(parameters)
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MySQL schema generator for Memori v2.0
|
|
3
|
+
Converts SQLite schema to MySQL-compatible schema with FULLTEXT search
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Dict, List
|
|
7
|
+
|
|
8
|
+
from ..connectors.base_connector import BaseSchemaGenerator, DatabaseType
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class MySQLSchemaGenerator(BaseSchemaGenerator):
|
|
12
|
+
"""MySQL-specific schema generator"""
|
|
13
|
+
|
|
14
|
+
def __init__(self):
|
|
15
|
+
super().__init__(DatabaseType.MYSQL)
|
|
16
|
+
|
|
17
|
+
def get_data_type_mappings(self) -> Dict[str, str]:
|
|
18
|
+
"""Get MySQL-specific data type mappings from SQLite"""
|
|
19
|
+
return {
|
|
20
|
+
"TEXT": "TEXT",
|
|
21
|
+
"INTEGER": "INT",
|
|
22
|
+
"REAL": "DECIMAL(10,2)",
|
|
23
|
+
"BOOLEAN": "BOOLEAN",
|
|
24
|
+
"TIMESTAMP": "TIMESTAMP",
|
|
25
|
+
"AUTOINCREMENT": "AUTO_INCREMENT",
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
def generate_core_schema(self) -> str:
|
|
29
|
+
"""Generate core tables schema for MySQL"""
|
|
30
|
+
return """
|
|
31
|
+
-- Chat History Table
|
|
32
|
+
CREATE TABLE IF NOT EXISTS chat_history (
|
|
33
|
+
chat_id VARCHAR(255) PRIMARY KEY,
|
|
34
|
+
user_input TEXT NOT NULL,
|
|
35
|
+
ai_output TEXT NOT NULL,
|
|
36
|
+
model VARCHAR(255) NOT NULL,
|
|
37
|
+
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
38
|
+
session_id VARCHAR(255) NOT NULL,
|
|
39
|
+
namespace VARCHAR(255) NOT NULL DEFAULT 'default',
|
|
40
|
+
tokens_used INT DEFAULT 0,
|
|
41
|
+
metadata JSON
|
|
42
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
43
|
+
|
|
44
|
+
-- Short-term Memory Table
|
|
45
|
+
CREATE TABLE IF NOT EXISTS short_term_memory (
|
|
46
|
+
memory_id VARCHAR(255) PRIMARY KEY,
|
|
47
|
+
chat_id VARCHAR(255),
|
|
48
|
+
processed_data JSON NOT NULL,
|
|
49
|
+
importance_score DECIMAL(3,2) NOT NULL DEFAULT 0.5,
|
|
50
|
+
category_primary VARCHAR(255) NOT NULL,
|
|
51
|
+
retention_type VARCHAR(50) NOT NULL DEFAULT 'short_term',
|
|
52
|
+
namespace VARCHAR(255) NOT NULL DEFAULT 'default',
|
|
53
|
+
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
54
|
+
expires_at TIMESTAMP NULL,
|
|
55
|
+
access_count INT DEFAULT 0,
|
|
56
|
+
last_accessed TIMESTAMP NULL,
|
|
57
|
+
searchable_content TEXT NOT NULL,
|
|
58
|
+
summary TEXT NOT NULL,
|
|
59
|
+
is_permanent_context BOOLEAN DEFAULT FALSE,
|
|
60
|
+
INDEX idx_chat_id (chat_id),
|
|
61
|
+
FOREIGN KEY (chat_id) REFERENCES chat_history (chat_id) ON DELETE SET NULL
|
|
62
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
63
|
+
|
|
64
|
+
-- Long-term Memory Table
|
|
65
|
+
CREATE TABLE IF NOT EXISTS long_term_memory (
|
|
66
|
+
memory_id VARCHAR(255) PRIMARY KEY,
|
|
67
|
+
original_chat_id VARCHAR(255),
|
|
68
|
+
processed_data JSON NOT NULL,
|
|
69
|
+
importance_score DECIMAL(3,2) NOT NULL DEFAULT 0.5,
|
|
70
|
+
category_primary VARCHAR(255) NOT NULL,
|
|
71
|
+
retention_type VARCHAR(50) NOT NULL DEFAULT 'long_term',
|
|
72
|
+
namespace VARCHAR(255) NOT NULL DEFAULT 'default',
|
|
73
|
+
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
74
|
+
access_count INT DEFAULT 0,
|
|
75
|
+
last_accessed TIMESTAMP NULL,
|
|
76
|
+
searchable_content TEXT NOT NULL,
|
|
77
|
+
summary TEXT NOT NULL,
|
|
78
|
+
novelty_score DECIMAL(3,2) DEFAULT 0.5,
|
|
79
|
+
relevance_score DECIMAL(3,2) DEFAULT 0.5,
|
|
80
|
+
actionability_score DECIMAL(3,2) DEFAULT 0.5,
|
|
81
|
+
|
|
82
|
+
-- Enhanced Classification Fields
|
|
83
|
+
classification VARCHAR(50) NOT NULL DEFAULT 'conversational',
|
|
84
|
+
memory_importance VARCHAR(20) NOT NULL DEFAULT 'medium',
|
|
85
|
+
topic VARCHAR(255),
|
|
86
|
+
entities_json JSON DEFAULT (JSON_ARRAY()),
|
|
87
|
+
keywords_json JSON DEFAULT (JSON_ARRAY()),
|
|
88
|
+
|
|
89
|
+
-- Conscious Context Flags
|
|
90
|
+
is_user_context BOOLEAN DEFAULT FALSE,
|
|
91
|
+
is_preference BOOLEAN DEFAULT FALSE,
|
|
92
|
+
is_skill_knowledge BOOLEAN DEFAULT FALSE,
|
|
93
|
+
is_current_project BOOLEAN DEFAULT FALSE,
|
|
94
|
+
promotion_eligible BOOLEAN DEFAULT FALSE,
|
|
95
|
+
|
|
96
|
+
-- Memory Management
|
|
97
|
+
duplicate_of VARCHAR(255),
|
|
98
|
+
supersedes_json JSON DEFAULT (JSON_ARRAY()),
|
|
99
|
+
related_memories_json JSON DEFAULT (JSON_ARRAY()),
|
|
100
|
+
|
|
101
|
+
-- Technical Metadata
|
|
102
|
+
confidence_score DECIMAL(3,2) DEFAULT 0.8,
|
|
103
|
+
extraction_timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
104
|
+
classification_reason TEXT,
|
|
105
|
+
|
|
106
|
+
-- Processing Status
|
|
107
|
+
processed_for_duplicates BOOLEAN DEFAULT FALSE,
|
|
108
|
+
conscious_processed BOOLEAN DEFAULT FALSE
|
|
109
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
def generate_indexes(self) -> str:
|
|
113
|
+
"""Generate MySQL-specific indexes"""
|
|
114
|
+
return """
|
|
115
|
+
-- Chat History Indexes
|
|
116
|
+
CREATE INDEX idx_chat_namespace_session ON chat_history(namespace, session_id);
|
|
117
|
+
CREATE INDEX idx_chat_timestamp ON chat_history(timestamp);
|
|
118
|
+
CREATE INDEX idx_chat_model ON chat_history(model);
|
|
119
|
+
|
|
120
|
+
-- Short-term Memory Indexes
|
|
121
|
+
CREATE INDEX idx_short_term_namespace ON short_term_memory(namespace);
|
|
122
|
+
CREATE INDEX idx_short_term_category ON short_term_memory(category_primary);
|
|
123
|
+
CREATE INDEX idx_short_term_importance ON short_term_memory(importance_score);
|
|
124
|
+
CREATE INDEX idx_short_term_expires ON short_term_memory(expires_at);
|
|
125
|
+
CREATE INDEX idx_short_term_created ON short_term_memory(created_at);
|
|
126
|
+
CREATE INDEX idx_short_term_access ON short_term_memory(access_count, last_accessed);
|
|
127
|
+
CREATE INDEX idx_short_term_permanent ON short_term_memory(is_permanent_context);
|
|
128
|
+
|
|
129
|
+
-- Long-term Memory Indexes
|
|
130
|
+
CREATE INDEX idx_long_term_namespace ON long_term_memory(namespace);
|
|
131
|
+
CREATE INDEX idx_long_term_category ON long_term_memory(category_primary);
|
|
132
|
+
CREATE INDEX idx_long_term_importance ON long_term_memory(importance_score);
|
|
133
|
+
CREATE INDEX idx_long_term_created ON long_term_memory(created_at);
|
|
134
|
+
CREATE INDEX idx_long_term_access ON long_term_memory(access_count, last_accessed);
|
|
135
|
+
CREATE INDEX idx_long_term_scores ON long_term_memory(novelty_score, relevance_score, actionability_score);
|
|
136
|
+
|
|
137
|
+
-- Enhanced Classification Indexes
|
|
138
|
+
CREATE INDEX idx_long_term_classification ON long_term_memory(classification);
|
|
139
|
+
CREATE INDEX idx_long_term_memory_importance ON long_term_memory(memory_importance);
|
|
140
|
+
CREATE INDEX idx_long_term_topic ON long_term_memory(topic);
|
|
141
|
+
CREATE INDEX idx_long_term_conscious_flags ON long_term_memory(is_user_context, is_preference, is_skill_knowledge, promotion_eligible);
|
|
142
|
+
CREATE INDEX idx_long_term_conscious_processed ON long_term_memory(conscious_processed);
|
|
143
|
+
CREATE INDEX idx_long_term_duplicates ON long_term_memory(processed_for_duplicates);
|
|
144
|
+
CREATE INDEX idx_long_term_confidence ON long_term_memory(confidence_score);
|
|
145
|
+
|
|
146
|
+
-- Composite indexes for search optimization
|
|
147
|
+
CREATE INDEX idx_short_term_namespace_category_importance ON short_term_memory(namespace, category_primary, importance_score);
|
|
148
|
+
CREATE INDEX idx_long_term_namespace_category_importance ON long_term_memory(namespace, category_primary, importance_score);
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
def generate_search_setup(self) -> str:
|
|
152
|
+
"""Generate MySQL FULLTEXT search setup"""
|
|
153
|
+
return """
|
|
154
|
+
-- MySQL FULLTEXT Search Indexes
|
|
155
|
+
-- These replace SQLite's FTS5 virtual table with MySQL's native FULLTEXT indexes
|
|
156
|
+
|
|
157
|
+
-- FULLTEXT index for short-term memory
|
|
158
|
+
ALTER TABLE short_term_memory ADD FULLTEXT INDEX ft_short_term_search (searchable_content, summary);
|
|
159
|
+
|
|
160
|
+
-- FULLTEXT index for long-term memory
|
|
161
|
+
ALTER TABLE long_term_memory ADD FULLTEXT INDEX ft_long_term_search (searchable_content, summary);
|
|
162
|
+
|
|
163
|
+
-- Additional FULLTEXT indexes for enhanced search capabilities
|
|
164
|
+
ALTER TABLE long_term_memory ADD FULLTEXT INDEX ft_long_term_topic (topic);
|
|
165
|
+
|
|
166
|
+
-- Note: MySQL FULLTEXT indexes are maintained automatically
|
|
167
|
+
-- No triggers needed like SQLite FTS5
|
|
168
|
+
"""
|
|
169
|
+
|
|
170
|
+
def generate_mysql_specific_optimizations(self) -> str:
|
|
171
|
+
"""Generate MySQL-specific optimizations"""
|
|
172
|
+
return """
|
|
173
|
+
-- MySQL-specific optimizations
|
|
174
|
+
|
|
175
|
+
-- Set InnoDB buffer pool size (if you have permission)
|
|
176
|
+
-- SET GLOBAL innodb_buffer_pool_size = 268435456; -- 256MB
|
|
177
|
+
|
|
178
|
+
-- Optimize FULLTEXT search settings
|
|
179
|
+
-- SET GLOBAL ft_min_word_len = 3;
|
|
180
|
+
-- SET GLOBAL ft_boolean_syntax = ' +-><()~*:""&|';
|
|
181
|
+
|
|
182
|
+
-- Enable query cache (MySQL 5.7 and below)
|
|
183
|
+
-- SET GLOBAL query_cache_type = ON;
|
|
184
|
+
-- SET GLOBAL query_cache_size = 67108864; -- 64MB
|
|
185
|
+
"""
|
|
186
|
+
|
|
187
|
+
def generate_full_schema(self) -> str:
|
|
188
|
+
"""Generate complete MySQL schema"""
|
|
189
|
+
schema_parts = [
|
|
190
|
+
"-- Memori v2.0 MySQL Schema",
|
|
191
|
+
"-- Generated schema for cross-database compatibility",
|
|
192
|
+
"",
|
|
193
|
+
"-- Set MySQL session variables for optimal performance",
|
|
194
|
+
"SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO';",
|
|
195
|
+
"SET SESSION innodb_lock_wait_timeout = 30;",
|
|
196
|
+
"",
|
|
197
|
+
self.generate_core_schema(),
|
|
198
|
+
"",
|
|
199
|
+
self.generate_indexes(),
|
|
200
|
+
"",
|
|
201
|
+
self.generate_search_setup(),
|
|
202
|
+
"",
|
|
203
|
+
"-- Schema generation completed",
|
|
204
|
+
]
|
|
205
|
+
return "\n".join(schema_parts)
|
|
206
|
+
|
|
207
|
+
def get_migration_queries(self) -> List[str]:
|
|
208
|
+
"""Get queries to migrate from SQLite to MySQL"""
|
|
209
|
+
return [
|
|
210
|
+
# Note: These would be used for data migration from SQLite to MySQL
|
|
211
|
+
# Data migration is complex and would require specialized tooling
|
|
212
|
+
"-- Data migration queries would go here",
|
|
213
|
+
"-- This requires extracting data from SQLite and inserting into MySQL",
|
|
214
|
+
"-- with proper data type conversions and character encoding handling",
|
|
215
|
+
]
|