thoth-dbmanager 0.4.13__py3-none-any.whl → 0.5.1__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.
@@ -1,4 +1,3 @@
1
- import pickle
2
1
  import logging
3
2
  from abc import ABC, abstractmethod
4
3
  from pathlib import Path
@@ -7,20 +6,15 @@ from typing import Any, Dict, List, Optional, Union, ClassVar, Type, TypeVar
7
6
 
8
7
  from .lsh.manager import LshManager
9
8
  from .core.factory import ThothDbFactory
10
- from .core.interfaces import DbPlugin
11
-
12
- # Import plugins to register them
13
- from .plugins.postgresql import PostgreSQLPlugin
14
- from .plugins.sqlite import SQLitePlugin
15
9
 
16
10
  T = TypeVar('T', bound='ThothDbManager')
17
11
 
18
12
  class ThothDbManager(ABC):
19
13
  """
20
- This class provides methods for interacting with a database.
21
- It follows a singleton pattern for each unique set of connection parameters.
14
+ Modern database manager interface using plugin architecture.
22
15
 
23
- This class now serves as a compatibility layer over the new plugin architecture.
16
+ This class provides a unified interface for database operations
17
+ across multiple database types through the plugin system.
24
18
  """
25
19
  _instances: ClassVar[Dict[tuple, Any]] = {}
26
20
  _lock: ClassVar[Lock] = Lock()
@@ -28,10 +22,7 @@ class ThothDbManager(ABC):
28
22
  @classmethod
29
23
  def get_instance(cls: Type[T], db_type: str, **kwargs) -> T:
30
24
  """
31
- Get or create a singleton instance based on the database type.
32
- This acts as a factory for different database manager implementations.
33
-
34
- Now uses the new plugin architecture while maintaining backward compatibility.
25
+ Get or create a singleton instance using the plugin architecture.
35
26
 
36
27
  Args:
37
28
  db_type (str): The type of database (e.g., 'postgresql', 'sqlite', 'mysql').
@@ -43,40 +34,13 @@ class ThothDbManager(ABC):
43
34
  Raises:
44
35
  ValueError: If the database type is unsupported or required parameters are missing.
45
36
  """
46
- # Try new plugin architecture first
47
- try:
48
- if db_type in ["postgresql", "sqlite"]: # Currently supported by new architecture
49
- # Extract required parameters
50
- db_root_path = kwargs.get('db_root_path')
51
- db_mode = kwargs.get('db_mode', 'dev')
52
-
53
- if not db_root_path:
54
- raise ValueError("db_root_path is required")
55
-
56
- # Remove extracted parameters from kwargs to avoid duplicate parameter errors
57
- kwargs_clean = kwargs.copy()
58
- kwargs_clean.pop('db_root_path', None)
59
- kwargs_clean.pop('db_mode', None)
60
-
61
- # Create plugin instance using factory
62
- plugin = ThothDbFactory.create_manager(db_type, db_root_path, db_mode, **kwargs_clean)
63
-
64
- # Wrap plugin in compatibility adapter
65
- return ThothDbManagerAdapter(plugin)
66
-
67
- except Exception as e:
68
- logging.warning(f"Failed to use new plugin architecture for {db_type}: {e}. Falling back to legacy implementation.")
37
+ # Import all plugins to ensure they're registered
38
+ from . import plugins
69
39
 
70
- # Use unified plugin system for all database types
71
40
  try:
72
- # Import all plugins to ensure they're registered
73
- from . import plugins
74
-
75
41
  # Create plugin instance using factory
76
42
  plugin = ThothDbFactory.create_manager(db_type, **kwargs)
77
-
78
- # Wrap plugin in compatibility adapter
79
- return ThothDbManagerAdapter(plugin)
43
+ return plugin
80
44
 
81
45
  except Exception as e:
82
46
  logging.error(f"Failed to create {db_type} manager: {e}")
@@ -103,11 +67,6 @@ class ThothDbManager(ABC):
103
67
  self.db_id = None
104
68
  self.db_directory_path = None
105
69
 
106
- # LSH related attributes (for backward compatibility)
107
- self.lsh = None
108
- self.minhashes = None
109
- self.vector_db = None
110
-
111
70
  # New LSH manager (lazy initialization)
112
71
  self._lsh_manager = None
113
72
 
@@ -245,44 +204,6 @@ class ThothDbManager(ABC):
245
204
  """
246
205
  pass
247
206
 
248
- def set_lsh(self) -> str:
249
- """
250
- Sets the LSH and minhashes attributes by loading from storage.
251
-
252
- This method maintains backward compatibility while using the new LSH manager.
253
- """
254
- with self._lock:
255
- if self.lsh is None:
256
- try:
257
- # Use the new LSH manager
258
- if self.lsh_manager and self.lsh_manager.load_lsh():
259
- # Set backward compatibility attributes
260
- self.lsh = self.lsh_manager.lsh
261
- self.minhashes = self.lsh_manager.minhashes
262
- return "success"
263
- else:
264
- # Fallback to old method for compatibility
265
- lsh_path = self.db_directory_path / "preprocessed" / f"{self.db_id}_lsh.pkl"
266
- minhashes_path = self.db_directory_path / "preprocessed" / f"{self.db_id}_minhashes.pkl"
267
-
268
- if not lsh_path.exists() or not minhashes_path.exists():
269
- raise FileNotFoundError(f"LSH or MinHashes file not found for {self.db_id}")
270
-
271
- with lsh_path.open("rb") as file:
272
- self.lsh = pickle.load(file)
273
- with minhashes_path.open("rb") as file:
274
- self.minhashes = pickle.load(file)
275
- return "success"
276
- except Exception as e:
277
- logging.error(f"Error loading LSH: {str(e)}")
278
- self.lsh = "error"
279
- self.minhashes = "error"
280
- return "error"
281
- elif self.lsh == "error":
282
- return "error"
283
- else:
284
- return "success"
285
-
286
207
  def query_lsh(self,
287
208
  keyword: str,
288
209
  signature_size: int = 30,
@@ -303,7 +224,6 @@ class ThothDbManager(ABC):
303
224
  - inner key is column name
304
225
  - value is list of similar strings
305
226
  """
306
- # Try using the new LSH manager first
307
227
  if self.lsh_manager:
308
228
  try:
309
229
  return self.lsh_manager.query(
@@ -313,148 +233,20 @@ class ThothDbManager(ABC):
313
233
  top_n=top_n
314
234
  )
315
235
  except Exception as e:
316
- logging.warning(f"LSH manager query failed, falling back to old method: {e}")
317
-
318
- # Fallback to old method for backward compatibility
319
- lsh_status = self.set_lsh()
320
- if lsh_status == "success":
321
- # Import here to avoid circular imports
322
- from .helpers.search import _query_lsh
323
- return _query_lsh(self.lsh, self.minhashes, keyword, signature_size, n_gram, top_n)
236
+ logging.error(f"LSH manager query failed: {e}")
237
+ raise Exception(f"Error querying LSH for {self.db_id}: {e}")
324
238
  else:
325
- raise Exception(f"Error loading LSH for {self.db_id}")
326
-
239
+ raise Exception(f"LSH manager not initialized for {self.db_id}")
327
240
 
328
- class ThothDbManagerAdapter(ThothDbManager):
329
- """
330
- Adapter class that wraps the new plugin architecture to provide backward compatibility
331
- with the original ThothDbManager interface.
332
- """
333
-
334
- def __init__(self, plugin: DbPlugin):
241
+ def health_check(self) -> bool:
335
242
  """
336
- Initialize the adapter with a plugin instance.
243
+ Check if database connection is healthy.
337
244
 
338
- Args:
339
- plugin: Database plugin instance
245
+ Returns:
246
+ bool: True if connection is healthy, False otherwise
340
247
  """
341
- self.plugin = plugin
342
-
343
- # Copy plugin attributes for backward compatibility
344
- self.db_root_path = plugin.db_root_path
345
- self.db_mode = plugin.db_mode
346
- self.db_type = plugin.supported_db_types[0] if plugin.supported_db_types else "unknown"
347
- self.db_id = getattr(plugin, 'db_id', None)
348
- self.db_directory_path = getattr(plugin, 'db_directory_path', None)
349
- self.schema = getattr(plugin, 'schema', "")
350
-
351
- # Engine and connection (delegated to adapter)
352
- self.engine = getattr(plugin.adapter, 'engine', None) if plugin.adapter else None
353
-
354
- # LSH related attributes (for backward compatibility)
355
- self.lsh = None
356
- self.minhashes = None
357
- self.vector_db = None
358
-
359
- # Flag to track initialization
360
- self._initialized = plugin._initialized
361
-
362
- @property
363
- def lsh_manager(self):
364
- """Access LSH manager through plugin"""
365
- return getattr(self.plugin, 'lsh_manager', None)
366
-
367
- def execute_sql(self, sql: str, params: Optional[Dict] = None, fetch: Union[str, int] = "all", timeout: int = 60) -> Any:
368
- """Execute SQL queries through plugin"""
369
- return self.plugin.execute_sql(sql, params, fetch, timeout)
370
-
371
- def get_unique_values(self) -> Dict[str, Dict[str, List[str]]]:
372
- """Get unique values through plugin"""
373
- return self.plugin.get_unique_values()
374
-
375
- def get_tables(self) -> List[Dict[str, str]]:
376
- """Get tables through plugin"""
377
- return self.plugin.get_tables()
378
-
379
- def get_columns(self, table_name: str) -> List[Dict[str, Any]]:
380
- """Get columns through plugin"""
381
- return self.plugin.get_columns(table_name)
382
-
383
- def get_foreign_keys(self) -> List[Dict[str, str]]:
384
- """Get foreign keys through plugin"""
385
- return self.plugin.get_foreign_keys()
386
-
387
- def set_lsh(self) -> str:
388
- """Set LSH through plugin"""
389
- if hasattr(self.plugin, 'set_lsh'):
390
- result = self.plugin.set_lsh()
391
-
392
- # Update backward compatibility attributes
393
- if result == "success" and self.lsh_manager:
394
- self.lsh = getattr(self.lsh_manager, 'lsh', None)
395
- self.minhashes = getattr(self.lsh_manager, 'minhashes', None)
396
-
397
- return result
398
- else:
399
- # Fallback to original implementation
400
- return super().set_lsh()
401
-
402
- def query_lsh(self, keyword: str, signature_size: int = 30, n_gram: int = 3, top_n: int = 10) -> Dict[str, Dict[str, List[str]]]:
403
- """Query LSH through plugin"""
404
- if hasattr(self.plugin, 'query_lsh'):
405
- return self.plugin.query_lsh(keyword, signature_size, n_gram, top_n)
406
- else:
407
- # Fallback to original implementation
408
- return super().query_lsh(keyword, signature_size, n_gram, top_n)
409
-
410
- # Document-based methods (new functionality)
411
- def get_tables_as_documents(self):
412
- """Get tables as document objects"""
413
- if self.plugin.adapter:
414
- return self.plugin.adapter.get_tables_as_documents()
415
- return []
416
-
417
- def get_columns_as_documents(self, table_name: str):
418
- """Get columns as document objects"""
419
- if self.plugin.adapter:
420
- return self.plugin.adapter.get_columns_as_documents(table_name)
421
- return []
422
-
423
- def get_foreign_keys_as_documents(self):
424
- """Get foreign keys as document objects"""
425
- if self.plugin.adapter:
426
- return self.plugin.adapter.get_foreign_keys_as_documents()
427
- return []
428
-
429
- def get_schemas_as_documents(self):
430
- """Get schemas as document objects"""
431
- if self.plugin.adapter:
432
- return self.plugin.adapter.get_schemas_as_documents()
433
- return []
434
-
435
- def get_indexes_as_documents(self, table_name: Optional[str] = None):
436
- """Get indexes as document objects"""
437
- if self.plugin.adapter:
438
- return self.plugin.adapter.get_indexes_as_documents(table_name)
439
- return []
440
-
441
- def get_connection_info(self) -> Dict[str, Any]:
442
- """Get connection information"""
443
- if hasattr(self.plugin, 'get_connection_info'):
444
- return self.plugin.get_connection_info()
445
- return {}
446
-
447
- def health_check(self) -> bool:
448
- """Check database health"""
449
- if self.plugin.adapter:
450
- return self.plugin.adapter.health_check()
451
- return False
452
-
453
- def get_example_data(self, table_name: str, number_of_rows: int = 30) -> Dict[str, List[Any]]:
454
- """Get example data through plugin"""
455
- if hasattr(self.plugin, 'get_example_data'):
456
- return self.plugin.get_example_data(table_name, number_of_rows)
457
- elif self.plugin.adapter:
458
- return self.plugin.adapter.get_example_data(table_name, number_of_rows)
459
- else:
460
- raise RuntimeError("Plugin not initialized or doesn't support get_example_data")
248
+ try:
249
+ self.execute_sql("SELECT 1", fetch="one")
250
+ return True
251
+ except Exception:
252
+ return False
@@ -5,7 +5,7 @@ This package provides database-agnostic operations, LSH similarity search,
5
5
  and an extensible plugin architecture for managing SQL databases.
6
6
  """
7
7
 
8
- # Core classes - always available
8
+ # Core classes
9
9
  from .ThothDbManager import ThothDbManager
10
10
  from .core.factory import ThothDbFactory
11
11
  from .core.interfaces import DbPlugin, DbAdapter
@@ -24,7 +24,7 @@ from .documents import (
24
24
  create_document
25
25
  )
26
26
 
27
- # Export LSH functionality for backward compatibility
27
+ # LSH functionality
28
28
  from .lsh.factory import make_db_lsh
29
29
  from .lsh import LshManager, LshFactory
30
30
 
@@ -36,50 +36,13 @@ from .dynamic_imports import (
36
36
  get_available_databases,
37
37
  import_database_components,
38
38
  DatabaseImportError,
39
- # Convenience functions
40
- import_postgresql,
41
- import_mysql,
42
- import_sqlite,
43
- import_sqlserver,
44
- import_oracle,
45
- import_mariadb,
46
- import_supabase,
47
39
  )
48
40
 
49
- # Legacy API - will be dynamically imported when accessed
50
- def __getattr__(name: str):
51
- """Dynamic attribute access for database managers."""
52
- if name == 'ThothPgManager':
53
- return import_manager('postgresql')
54
- elif name == 'ThothSqliteManager':
55
- return import_manager('sqlite')
56
- elif name == 'ThothMySqlManager':
57
- return import_manager('mysql')
58
- elif name == 'ThothMariaDbManager':
59
- return import_manager('mariadb')
60
- elif name == 'ThothSqlServerManager':
61
- return import_manager('sqlserver')
62
- elif name == 'ThothOracleManager':
63
- return import_manager('oracle')
64
- elif name == 'ThothSupabaseManager':
65
- return import_manager('supabase')
66
-
67
- raise AttributeError(f"module 'thoth_dbmanager' has no attribute '{name}'")
68
-
69
- # Public API
41
+ # Public API - Modern Plugin Architecture Only
70
42
  __all__ = [
71
- # Legacy API
43
+ # Core API
72
44
  "ThothDbManager",
73
- "ThothPgManager",
74
- "ThothSqliteManager",
75
- "ThothMySqlManager",
76
- "ThothMariaDbManager",
77
- "ThothSqlServerManager",
78
- "ThothOracleManager",
79
- "ThothSupabaseManager",
80
-
81
- # New architecture
82
- "ThothDbFactory",
45
+ "ThothDbFactory",
83
46
  "DbPluginRegistry",
84
47
  "DbPlugin",
85
48
  "DbAdapter",
@@ -87,7 +50,7 @@ __all__ = [
87
50
  # Document models
88
51
  "BaseThothDbDocument",
89
52
  "TableDocument",
90
- "ColumnDocument",
53
+ "ColumnDocument",
91
54
  "QueryDocument",
92
55
  "SchemaDocument",
93
56
  "ForeignKeyDocument",
@@ -95,24 +58,6 @@ __all__ = [
95
58
  "ThothDbType",
96
59
  "create_document",
97
60
 
98
- # Plugins
99
- "PostgreSQLPlugin",
100
- "SQLitePlugin",
101
- "MySQLPlugin",
102
- "MariaDBPlugin",
103
- "SQLServerPlugin",
104
- "OraclePlugin",
105
- "SupabasePlugin",
106
-
107
- # Adapters
108
- "PostgreSQLAdapter",
109
- "SQLiteAdapter",
110
- "MySQLAdapter",
111
- "MariaDBAdapter",
112
- "SQLServerAdapter",
113
- "OracleAdapter",
114
- "SupabaseAdapter",
115
-
116
61
  # LSH functionality
117
62
  "make_db_lsh",
118
63
  "LshManager",
@@ -120,11 +65,11 @@ __all__ = [
120
65
 
121
66
  # Dynamic import system
122
67
  "import_manager",
123
- "import_adapter",
68
+ "import_adapter",
124
69
  "import_plugin",
125
70
  "get_available_databases",
126
71
  "import_database_components",
127
72
  "DatabaseImportError",
128
73
  ]
129
74
 
130
- __version__ = "0.4.3"
75
+ __version__ = "0.5.0"
@@ -4,18 +4,12 @@ Database adapters for Thoth SQL Database Manager.
4
4
 
5
5
  from .postgresql import PostgreSQLAdapter
6
6
  from .sqlite import SQLiteAdapter
7
- from .supabase import SupabaseAdapter
8
- from .mysql import MySQLAdapter
9
7
  from .mariadb import MariaDBAdapter
10
8
  from .sqlserver import SQLServerAdapter
11
- from .oracle import OracleAdapter
12
9
 
13
10
  __all__ = [
14
11
  "PostgreSQLAdapter",
15
12
  "SQLiteAdapter",
16
- "SupabaseAdapter",
17
- "MySQLAdapter",
18
13
  "MariaDBAdapter",
19
14
  "SQLServerAdapter",
20
- "OracleAdapter",
21
15
  ]
@@ -124,18 +124,10 @@ class ThothDbFactory:
124
124
  "required": ["host", "port", "database", "user", "password"],
125
125
  "optional": ["schema", "sslmode", "connect_timeout"]
126
126
  },
127
- "supabase": {
128
- "required": ["host", "port", "database", "user", "password"],
129
- "optional": ["schema", "sslmode", "connect_timeout", "project_url", "api_key", "use_rest_api"]
130
- },
131
127
  "sqlite": {
132
128
  "required": ["database_path"],
133
129
  "optional": ["timeout", "check_same_thread"]
134
130
  },
135
- "mysql": {
136
- "required": ["host", "port", "database", "user", "password"],
137
- "optional": ["charset", "autocommit", "connect_timeout"]
138
- },
139
131
  "mariadb": {
140
132
  "required": ["host", "port", "database", "user", "password"],
141
133
  "optional": ["charset", "autocommit", "connect_timeout"]
@@ -143,14 +135,6 @@ class ThothDbFactory:
143
135
  "sqlserver": {
144
136
  "required": ["server", "database", "user", "password"],
145
137
  "optional": ["driver", "trusted_connection", "timeout"]
146
- },
147
- "oracle": {
148
- "required": ["host", "port", "service_name", "user", "password"],
149
- "optional": ["encoding", "nencoding", "threaded"]
150
- },
151
- "informix": {
152
- "required": ["server", "database", "host", "user", "password"],
153
- "optional": ["protocol", "service", "timeout"]
154
138
  }
155
139
  }
156
140
 
@@ -10,11 +10,8 @@ import warnings
10
10
  # Mapping of database names to their required packages
11
11
  DATABASE_DEPENDENCIES = {
12
12
  'postgresql': ['psycopg2'],
13
- 'mysql': ['mysql.connector'],
14
13
  'mariadb': ['mariadb'],
15
14
  'sqlserver': ['pyodbc'],
16
- 'oracle': ['cx_Oracle'],
17
- 'supabase': ['supabase', 'postgrest', 'gotrue'],
18
15
  'sqlite': [], # Built into Python
19
16
  }
20
17
 
@@ -23,22 +20,16 @@ DATABASE_DEPENDENCIES = {
23
20
  # Mapping of database names to their adapter classes
24
21
  DATABASE_ADAPTERS = {
25
22
  'postgresql': 'thoth_dbmanager.adapters.postgresql.PostgreSQLAdapter',
26
- 'mysql': 'thoth_dbmanager.adapters.mysql.MySQLAdapter',
27
23
  'mariadb': 'thoth_dbmanager.adapters.mariadb.MariaDBAdapter',
28
24
  'sqlserver': 'thoth_dbmanager.adapters.sqlserver.SQLServerAdapter',
29
- 'oracle': 'thoth_dbmanager.adapters.oracle.OracleAdapter',
30
- 'supabase': 'thoth_dbmanager.adapters.supabase.SupabaseAdapter',
31
25
  'sqlite': 'thoth_dbmanager.adapters.sqlite.SQLiteAdapter',
32
26
  }
33
27
 
34
28
  # Mapping of database names to their plugin classes
35
29
  DATABASE_PLUGINS = {
36
30
  'postgresql': 'thoth_dbmanager.plugins.postgresql.PostgreSQLPlugin',
37
- 'mysql': 'thoth_dbmanager.plugins.mysql.MySQLPlugin',
38
31
  'mariadb': 'thoth_dbmanager.plugins.mariadb.MariaDBPlugin',
39
32
  'sqlserver': 'thoth_dbmanager.plugins.sqlserver.SQLServerPlugin',
40
- 'oracle': 'thoth_dbmanager.plugins.oracle.OraclePlugin',
41
- 'supabase': 'thoth_dbmanager.plugins.supabase.SupabasePlugin',
42
33
  'sqlite': 'thoth_dbmanager.plugins.sqlite.SQLitePlugin',
43
34
  }
44
35
 
@@ -4,7 +4,7 @@ import re
4
4
  from typing import Dict, List, Optional
5
5
  from pathlib import Path
6
6
 
7
- from dbmanager.helpers.schema import DatabaseSchema
7
+ from thoth_dbmanager.helpers.schema import DatabaseSchema
8
8
 
9
9
 
10
10
  class MultiDbGenerator:
@@ -5,19 +5,13 @@ Database plugins for Thoth SQL Database Manager.
5
5
  # Import all plugins to ensure they are registered
6
6
  from .postgresql import PostgreSQLPlugin
7
7
  from .sqlite import SQLitePlugin
8
- from .supabase import SupabasePlugin
9
- from .mysql import MySQLPlugin
10
8
  from .mariadb import MariaDBPlugin
11
9
  from .sqlserver import SQLServerPlugin
12
- from .oracle import OraclePlugin
13
10
 
14
11
  # This ensures all plugins are registered when the module is imported
15
12
  __all__ = [
16
13
  "PostgreSQLPlugin",
17
14
  "SQLitePlugin",
18
- "SupabasePlugin",
19
- "MySQLPlugin",
20
15
  "MariaDBPlugin",
21
16
  "SQLServerPlugin",
22
- "OraclePlugin",
23
17
  ]
@@ -218,3 +218,10 @@ class SQLitePlugin(DbPlugin):
218
218
  return self.adapter.get_example_data(table_name, number_of_rows)
219
219
  else:
220
220
  raise RuntimeError("Plugin not initialized")
221
+
222
+ def health_check(self) -> bool:
223
+ """Check database connection health"""
224
+ if self.adapter:
225
+ return self.adapter.health_check()
226
+ else:
227
+ return False