dtSpark 1.0.4__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.
- dtSpark/__init__.py +0 -0
- dtSpark/_description.txt +1 -0
- dtSpark/_full_name.txt +1 -0
- dtSpark/_licence.txt +21 -0
- dtSpark/_metadata.yaml +6 -0
- dtSpark/_name.txt +1 -0
- dtSpark/_version.txt +1 -0
- dtSpark/aws/__init__.py +7 -0
- dtSpark/aws/authentication.py +296 -0
- dtSpark/aws/bedrock.py +578 -0
- dtSpark/aws/costs.py +318 -0
- dtSpark/aws/pricing.py +580 -0
- dtSpark/cli_interface.py +2645 -0
- dtSpark/conversation_manager.py +3050 -0
- dtSpark/core/__init__.py +12 -0
- dtSpark/core/application.py +3355 -0
- dtSpark/core/context_compaction.py +735 -0
- dtSpark/daemon/__init__.py +104 -0
- dtSpark/daemon/__main__.py +10 -0
- dtSpark/daemon/action_monitor.py +213 -0
- dtSpark/daemon/daemon_app.py +730 -0
- dtSpark/daemon/daemon_manager.py +289 -0
- dtSpark/daemon/execution_coordinator.py +194 -0
- dtSpark/daemon/pid_file.py +169 -0
- dtSpark/database/__init__.py +482 -0
- dtSpark/database/autonomous_actions.py +1191 -0
- dtSpark/database/backends.py +329 -0
- dtSpark/database/connection.py +122 -0
- dtSpark/database/conversations.py +520 -0
- dtSpark/database/credential_prompt.py +218 -0
- dtSpark/database/files.py +205 -0
- dtSpark/database/mcp_ops.py +355 -0
- dtSpark/database/messages.py +161 -0
- dtSpark/database/schema.py +673 -0
- dtSpark/database/tool_permissions.py +186 -0
- dtSpark/database/usage.py +167 -0
- dtSpark/files/__init__.py +4 -0
- dtSpark/files/manager.py +322 -0
- dtSpark/launch.py +39 -0
- dtSpark/limits/__init__.py +10 -0
- dtSpark/limits/costs.py +296 -0
- dtSpark/limits/tokens.py +342 -0
- dtSpark/llm/__init__.py +17 -0
- dtSpark/llm/anthropic_direct.py +446 -0
- dtSpark/llm/base.py +146 -0
- dtSpark/llm/context_limits.py +438 -0
- dtSpark/llm/manager.py +177 -0
- dtSpark/llm/ollama.py +578 -0
- dtSpark/mcp_integration/__init__.py +5 -0
- dtSpark/mcp_integration/manager.py +653 -0
- dtSpark/mcp_integration/tool_selector.py +225 -0
- dtSpark/resources/config.yaml.template +631 -0
- dtSpark/safety/__init__.py +22 -0
- dtSpark/safety/llm_service.py +111 -0
- dtSpark/safety/patterns.py +229 -0
- dtSpark/safety/prompt_inspector.py +442 -0
- dtSpark/safety/violation_logger.py +346 -0
- dtSpark/scheduler/__init__.py +20 -0
- dtSpark/scheduler/creation_tools.py +599 -0
- dtSpark/scheduler/execution_queue.py +159 -0
- dtSpark/scheduler/executor.py +1152 -0
- dtSpark/scheduler/manager.py +395 -0
- dtSpark/tools/__init__.py +4 -0
- dtSpark/tools/builtin.py +833 -0
- dtSpark/web/__init__.py +20 -0
- dtSpark/web/auth.py +152 -0
- dtSpark/web/dependencies.py +37 -0
- dtSpark/web/endpoints/__init__.py +17 -0
- dtSpark/web/endpoints/autonomous_actions.py +1125 -0
- dtSpark/web/endpoints/chat.py +621 -0
- dtSpark/web/endpoints/conversations.py +353 -0
- dtSpark/web/endpoints/main_menu.py +547 -0
- dtSpark/web/endpoints/streaming.py +421 -0
- dtSpark/web/server.py +578 -0
- dtSpark/web/session.py +167 -0
- dtSpark/web/ssl_utils.py +195 -0
- dtSpark/web/static/css/dark-theme.css +427 -0
- dtSpark/web/static/js/actions.js +1101 -0
- dtSpark/web/static/js/chat.js +614 -0
- dtSpark/web/static/js/main.js +496 -0
- dtSpark/web/static/js/sse-client.js +242 -0
- dtSpark/web/templates/actions.html +408 -0
- dtSpark/web/templates/base.html +93 -0
- dtSpark/web/templates/chat.html +814 -0
- dtSpark/web/templates/conversations.html +350 -0
- dtSpark/web/templates/goodbye.html +81 -0
- dtSpark/web/templates/login.html +90 -0
- dtSpark/web/templates/main_menu.html +983 -0
- dtSpark/web/templates/new_conversation.html +191 -0
- dtSpark/web/web_interface.py +137 -0
- dtspark-1.0.4.dist-info/METADATA +187 -0
- dtspark-1.0.4.dist-info/RECORD +96 -0
- dtspark-1.0.4.dist-info/WHEEL +5 -0
- dtspark-1.0.4.dist-info/entry_points.txt +3 -0
- dtspark-1.0.4.dist-info/licenses/LICENSE +21 -0
- dtspark-1.0.4.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Database backend abstraction for multi-database support.
|
|
3
|
+
|
|
4
|
+
Supports:
|
|
5
|
+
- SQLite (default, local file-based)
|
|
6
|
+
- MySQL/MariaDB (remote database server)
|
|
7
|
+
- PostgreSQL (remote database server)
|
|
8
|
+
- Microsoft SQL Server (remote database server)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import logging
|
|
14
|
+
import sqlite3
|
|
15
|
+
import os
|
|
16
|
+
from abc import ABC, abstractmethod
|
|
17
|
+
from typing import Optional, Dict, Any, Union
|
|
18
|
+
from dataclasses import dataclass
|
|
19
|
+
|
|
20
|
+
from dtPyAppFramework.paths import ApplicationPaths
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class DatabaseCredentials:
|
|
24
|
+
"""Database connection credentials."""
|
|
25
|
+
host: Optional[str] = None
|
|
26
|
+
port: Optional[int] = None
|
|
27
|
+
database: Optional[str] = None
|
|
28
|
+
username: Optional[str] = None
|
|
29
|
+
password: Optional[str] = None
|
|
30
|
+
ssl: bool = False
|
|
31
|
+
driver: Optional[str] = None # For MSSQL
|
|
32
|
+
path: Optional[str] = None # For SQLite
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class DatabaseBackend(ABC):
|
|
36
|
+
"""Abstract base class for database backends."""
|
|
37
|
+
|
|
38
|
+
def __init__(self, credentials: DatabaseCredentials):
|
|
39
|
+
"""
|
|
40
|
+
Initialise database backend.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
credentials: Database connection credentials
|
|
44
|
+
"""
|
|
45
|
+
self.credentials = credentials
|
|
46
|
+
self.connection = None
|
|
47
|
+
|
|
48
|
+
@abstractmethod
|
|
49
|
+
def connect(self):
|
|
50
|
+
"""
|
|
51
|
+
Establish database connection.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
Database connection object
|
|
55
|
+
"""
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
@abstractmethod
|
|
59
|
+
def get_placeholder(self) -> str:
|
|
60
|
+
"""
|
|
61
|
+
Get SQL parameter placeholder for this database.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
Placeholder string (?, %s, etc.)
|
|
65
|
+
"""
|
|
66
|
+
pass
|
|
67
|
+
|
|
68
|
+
@abstractmethod
|
|
69
|
+
def get_autoincrement_syntax(self) -> str:
|
|
70
|
+
"""
|
|
71
|
+
Get auto-increment syntax for this database.
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
Auto-increment SQL syntax
|
|
75
|
+
"""
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
@abstractmethod
|
|
79
|
+
def supports_returning(self) -> bool:
|
|
80
|
+
"""
|
|
81
|
+
Check if database supports RETURNING clause.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
True if RETURNING is supported
|
|
85
|
+
"""
|
|
86
|
+
pass
|
|
87
|
+
|
|
88
|
+
def close(self):
|
|
89
|
+
"""Close database connection."""
|
|
90
|
+
if self.connection:
|
|
91
|
+
self.connection.close()
|
|
92
|
+
self.connection = None
|
|
93
|
+
|
|
94
|
+
def test_connection(self) -> bool:
|
|
95
|
+
"""
|
|
96
|
+
Test database connection.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
True if connection successful
|
|
100
|
+
"""
|
|
101
|
+
try:
|
|
102
|
+
conn = self.connect()
|
|
103
|
+
cursor = conn.cursor()
|
|
104
|
+
cursor.execute("SELECT 1")
|
|
105
|
+
cursor.close()
|
|
106
|
+
return True
|
|
107
|
+
except Exception as e:
|
|
108
|
+
logging.error(f"Database connection test failed: {e}")
|
|
109
|
+
return False
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class SQLiteBackend(DatabaseBackend):
|
|
113
|
+
"""SQLite database backend (local file-based)."""
|
|
114
|
+
|
|
115
|
+
def connect(self):
|
|
116
|
+
"""Establish SQLite connection."""
|
|
117
|
+
if self.connection is None:
|
|
118
|
+
self.connection = sqlite3.connect(
|
|
119
|
+
os.path.join(ApplicationPaths().usr_data_root_path, "conversations.db"),
|
|
120
|
+
check_same_thread=False
|
|
121
|
+
)
|
|
122
|
+
self.connection.row_factory = sqlite3.Row
|
|
123
|
+
return self.connection
|
|
124
|
+
|
|
125
|
+
def get_placeholder(self) -> str:
|
|
126
|
+
return "?"
|
|
127
|
+
|
|
128
|
+
def get_autoincrement_syntax(self) -> str:
|
|
129
|
+
return "AUTOINCREMENT"
|
|
130
|
+
|
|
131
|
+
def supports_returning(self) -> bool:
|
|
132
|
+
return False # SQLite < 3.35 doesn't support RETURNING
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class MySQLBackend(DatabaseBackend):
|
|
136
|
+
"""MySQL/MariaDB database backend."""
|
|
137
|
+
|
|
138
|
+
def connect(self):
|
|
139
|
+
"""Establish MySQL connection."""
|
|
140
|
+
try:
|
|
141
|
+
import mysql.connector
|
|
142
|
+
except ImportError:
|
|
143
|
+
raise ImportError(
|
|
144
|
+
"mysql-connector-python is required for MySQL support. "
|
|
145
|
+
"Install it with: pip install mysql-connector-python"
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
if self.connection is None:
|
|
149
|
+
connection_params = {
|
|
150
|
+
'host': self.credentials.host,
|
|
151
|
+
'port': self.credentials.port or 3306,
|
|
152
|
+
'database': self.credentials.database,
|
|
153
|
+
'user': self.credentials.username,
|
|
154
|
+
'password': self.credentials.password,
|
|
155
|
+
'autocommit': False
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if self.credentials.ssl:
|
|
159
|
+
connection_params['ssl_disabled'] = False
|
|
160
|
+
|
|
161
|
+
self.connection = mysql.connector.connect(**connection_params)
|
|
162
|
+
|
|
163
|
+
return self.connection
|
|
164
|
+
|
|
165
|
+
def get_placeholder(self) -> str:
|
|
166
|
+
return "%s"
|
|
167
|
+
|
|
168
|
+
def get_autoincrement_syntax(self) -> str:
|
|
169
|
+
return "AUTO_INCREMENT"
|
|
170
|
+
|
|
171
|
+
def supports_returning(self) -> bool:
|
|
172
|
+
return False # MySQL doesn't support RETURNING
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class PostgreSQLBackend(DatabaseBackend):
|
|
176
|
+
"""PostgreSQL database backend."""
|
|
177
|
+
|
|
178
|
+
def connect(self):
|
|
179
|
+
"""Establish PostgreSQL connection."""
|
|
180
|
+
try:
|
|
181
|
+
import psycopg2
|
|
182
|
+
import psycopg2.extras
|
|
183
|
+
except ImportError:
|
|
184
|
+
raise ImportError(
|
|
185
|
+
"psycopg2 is required for PostgreSQL support. "
|
|
186
|
+
"Install it with: pip install psycopg2-binary"
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
if self.connection is None:
|
|
190
|
+
connection_params = {
|
|
191
|
+
'host': self.credentials.host,
|
|
192
|
+
'port': self.credentials.port or 5432,
|
|
193
|
+
'database': self.credentials.database,
|
|
194
|
+
'user': self.credentials.username,
|
|
195
|
+
'password': self.credentials.password
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if self.credentials.ssl:
|
|
199
|
+
connection_params['sslmode'] = 'require'
|
|
200
|
+
|
|
201
|
+
self.connection = psycopg2.connect(**connection_params)
|
|
202
|
+
self.connection.autocommit = False
|
|
203
|
+
|
|
204
|
+
return self.connection
|
|
205
|
+
|
|
206
|
+
def get_placeholder(self) -> str:
|
|
207
|
+
return "%s"
|
|
208
|
+
|
|
209
|
+
def get_autoincrement_syntax(self) -> str:
|
|
210
|
+
return "SERIAL"
|
|
211
|
+
|
|
212
|
+
def supports_returning(self) -> bool:
|
|
213
|
+
return True
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
class MSSQLBackend(DatabaseBackend):
|
|
217
|
+
"""Microsoft SQL Server database backend."""
|
|
218
|
+
|
|
219
|
+
def connect(self):
|
|
220
|
+
"""Establish MSSQL connection."""
|
|
221
|
+
try:
|
|
222
|
+
import pyodbc
|
|
223
|
+
except ImportError:
|
|
224
|
+
raise ImportError(
|
|
225
|
+
"pyodbc is required for Microsoft SQL Server support. "
|
|
226
|
+
"Install it with: pip install pyodbc"
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
if self.connection is None:
|
|
230
|
+
driver = self.credentials.driver or "ODBC Driver 17 for SQL Server"
|
|
231
|
+
|
|
232
|
+
connection_string = (
|
|
233
|
+
f"DRIVER={{{driver}}};"
|
|
234
|
+
f"SERVER={self.credentials.host};"
|
|
235
|
+
f"DATABASE={self.credentials.database};"
|
|
236
|
+
f"UID={self.credentials.username};"
|
|
237
|
+
f"PWD={self.credentials.password};"
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
if self.credentials.port:
|
|
241
|
+
connection_string = connection_string.replace(
|
|
242
|
+
f"SERVER={self.credentials.host};",
|
|
243
|
+
f"SERVER={self.credentials.host},{self.credentials.port};"
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
if self.credentials.ssl:
|
|
247
|
+
connection_string += "Encrypt=yes;TrustServerCertificate=no;"
|
|
248
|
+
|
|
249
|
+
self.connection = pyodbc.connect(connection_string)
|
|
250
|
+
self.connection.autocommit = False
|
|
251
|
+
|
|
252
|
+
return self.connection
|
|
253
|
+
|
|
254
|
+
def get_placeholder(self) -> str:
|
|
255
|
+
return "?"
|
|
256
|
+
|
|
257
|
+
def get_autoincrement_syntax(self) -> str:
|
|
258
|
+
return "IDENTITY"
|
|
259
|
+
|
|
260
|
+
def supports_returning(self) -> bool:
|
|
261
|
+
return False # MSSQL uses OUTPUT clause instead
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def create_backend(db_type: str, credentials: DatabaseCredentials) -> DatabaseBackend:
|
|
265
|
+
"""
|
|
266
|
+
Factory function to create appropriate database backend.
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
db_type: Database type (sqlite, mysql, mariadb, postgresql, mssql)
|
|
270
|
+
credentials: Database connection credentials
|
|
271
|
+
|
|
272
|
+
Returns:
|
|
273
|
+
Appropriate DatabaseBackend instance
|
|
274
|
+
|
|
275
|
+
Raises:
|
|
276
|
+
ValueError: If database type is not supported
|
|
277
|
+
"""
|
|
278
|
+
db_type_lower = db_type.lower()
|
|
279
|
+
|
|
280
|
+
if db_type_lower == 'sqlite':
|
|
281
|
+
return SQLiteBackend(credentials)
|
|
282
|
+
elif db_type_lower in ('mysql', 'mariadb'):
|
|
283
|
+
return MySQLBackend(credentials)
|
|
284
|
+
elif db_type_lower == 'postgresql':
|
|
285
|
+
return PostgreSQLBackend(credentials)
|
|
286
|
+
elif db_type_lower in ('mssql', 'sqlserver', 'mssqlserver'):
|
|
287
|
+
return MSSQLBackend(credentials)
|
|
288
|
+
else:
|
|
289
|
+
raise ValueError(
|
|
290
|
+
f"Unsupported database type: {db_type}. "
|
|
291
|
+
f"Supported types: sqlite, mysql, mariadb, postgresql, mssql"
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def validate_credentials(db_type: str, credentials: DatabaseCredentials) -> tuple[bool, Optional[str]]:
|
|
296
|
+
"""
|
|
297
|
+
Validate database credentials for given database type.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
db_type: Database type
|
|
301
|
+
credentials: Database credentials
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
Tuple of (is_valid, error_message)
|
|
305
|
+
"""
|
|
306
|
+
db_type_lower = db_type.lower()
|
|
307
|
+
|
|
308
|
+
if db_type_lower == 'sqlite':
|
|
309
|
+
if not credentials.path:
|
|
310
|
+
return False, "SQLite database path is required"
|
|
311
|
+
return True, None
|
|
312
|
+
|
|
313
|
+
# Remote databases require connection details
|
|
314
|
+
required_fields = ['host', 'database', 'username', 'password']
|
|
315
|
+
|
|
316
|
+
missing = []
|
|
317
|
+
if not credentials.host:
|
|
318
|
+
missing.append('host')
|
|
319
|
+
if not credentials.database:
|
|
320
|
+
missing.append('database')
|
|
321
|
+
if not credentials.username:
|
|
322
|
+
missing.append('username')
|
|
323
|
+
if not credentials.password:
|
|
324
|
+
missing.append('password')
|
|
325
|
+
|
|
326
|
+
if missing:
|
|
327
|
+
return False, f"Missing required credentials: {', '.join(missing)}"
|
|
328
|
+
|
|
329
|
+
return True, None
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Database connection management module.
|
|
3
|
+
|
|
4
|
+
This module handles:
|
|
5
|
+
- Multi-database backend support (SQLite, MySQL, PostgreSQL, MSSQL)
|
|
6
|
+
- Database connection setup
|
|
7
|
+
- Connection lifecycle management
|
|
8
|
+
- Directory management for database files
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import sqlite3
|
|
14
|
+
import logging
|
|
15
|
+
import threading
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import Optional, Any
|
|
18
|
+
|
|
19
|
+
from .backends import (
|
|
20
|
+
DatabaseBackend,
|
|
21
|
+
DatabaseCredentials,
|
|
22
|
+
create_backend,
|
|
23
|
+
validate_credentials
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class DatabaseConnection:
|
|
28
|
+
"""Manages database connection lifecycle with multi-backend support."""
|
|
29
|
+
|
|
30
|
+
def __init__(self, db_type: str = 'sqlite', credentials: Optional[DatabaseCredentials] = None,
|
|
31
|
+
db_path: Optional[str] = None):
|
|
32
|
+
"""
|
|
33
|
+
Initialise the database connection.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
db_type: Database type (sqlite, mysql, mariadb, postgresql, mssql)
|
|
37
|
+
credentials: Database connection credentials
|
|
38
|
+
db_path: Path to SQLite database file (for backward compatibility)
|
|
39
|
+
"""
|
|
40
|
+
self.db_type = db_type.lower()
|
|
41
|
+
self._lock = threading.RLock() # Reentrant lock for thread-safe operations
|
|
42
|
+
|
|
43
|
+
# Handle backward compatibility with old SQLite-only constructor
|
|
44
|
+
if credentials is None and db_path:
|
|
45
|
+
credentials = DatabaseCredentials(path=db_path)
|
|
46
|
+
self.db_type = 'sqlite'
|
|
47
|
+
|
|
48
|
+
if credentials is None:
|
|
49
|
+
raise ValueError("Database credentials are required")
|
|
50
|
+
|
|
51
|
+
# Validate credentials
|
|
52
|
+
is_valid, error_msg = validate_credentials(self.db_type, credentials)
|
|
53
|
+
if not is_valid:
|
|
54
|
+
raise ValueError(f"Invalid database credentials: {error_msg}")
|
|
55
|
+
|
|
56
|
+
# Create appropriate backend
|
|
57
|
+
self.backend = create_backend(self.db_type, credentials)
|
|
58
|
+
|
|
59
|
+
# For SQLite, ensure directory exists
|
|
60
|
+
if self.db_type == 'sqlite':
|
|
61
|
+
self._ensure_database_directory(credentials.path)
|
|
62
|
+
|
|
63
|
+
# Establish connection
|
|
64
|
+
self.conn = self.backend.connect()
|
|
65
|
+
|
|
66
|
+
# Configure connection based on backend
|
|
67
|
+
self._configure_connection()
|
|
68
|
+
|
|
69
|
+
logging.info(f"Database connection established: type={self.db_type}")
|
|
70
|
+
|
|
71
|
+
def _ensure_database_directory(self, db_path: str):
|
|
72
|
+
"""
|
|
73
|
+
Ensure the directory for the database file exists (SQLite only).
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
db_path: Path to database file
|
|
77
|
+
"""
|
|
78
|
+
db_dir = Path(db_path).parent
|
|
79
|
+
db_dir.mkdir(parents=True, exist_ok=True)
|
|
80
|
+
|
|
81
|
+
def _configure_connection(self):
|
|
82
|
+
"""Configure connection based on database backend."""
|
|
83
|
+
if self.db_type == 'sqlite':
|
|
84
|
+
# Enable WAL (Write-Ahead Logging) mode for better concurrency
|
|
85
|
+
cursor = self.conn.execute("PRAGMA journal_mode=WAL")
|
|
86
|
+
journal_mode = cursor.fetchone()[0]
|
|
87
|
+
cursor.close()
|
|
88
|
+
logging.info(f"SQLite journal mode: {journal_mode}")
|
|
89
|
+
|
|
90
|
+
def get_connection(self) -> Any:
|
|
91
|
+
"""
|
|
92
|
+
Get the database connection.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
Database connection object
|
|
96
|
+
"""
|
|
97
|
+
return self.conn
|
|
98
|
+
|
|
99
|
+
def get_backend(self) -> DatabaseBackend:
|
|
100
|
+
"""
|
|
101
|
+
Get the database backend.
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
DatabaseBackend instance
|
|
105
|
+
"""
|
|
106
|
+
return self.backend
|
|
107
|
+
|
|
108
|
+
def close(self):
|
|
109
|
+
"""Close the database connection."""
|
|
110
|
+
if self.conn:
|
|
111
|
+
self.backend.close()
|
|
112
|
+
self.conn = None
|
|
113
|
+
logging.info(f"Database connection closed: type={self.db_type}")
|
|
114
|
+
|
|
115
|
+
def test_connection(self) -> bool:
|
|
116
|
+
"""
|
|
117
|
+
Test database connection.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
True if connection is working
|
|
121
|
+
"""
|
|
122
|
+
return self.backend.test_connection()
|