thoth-dbmanager 0.4.1__py3-none-any.whl → 0.4.2__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.
- thoth_dbmanager/adapters/qdrant.py +189 -0
- thoth_dbmanager/plugins/qdrant.py +41 -0
- {thoth_dbmanager-0.4.1.dist-info → thoth_dbmanager-0.4.2.dist-info}/METADATA +4 -1
- {thoth_dbmanager-0.4.1.dist-info → thoth_dbmanager-0.4.2.dist-info}/RECORD +7 -5
- {thoth_dbmanager-0.4.1.dist-info → thoth_dbmanager-0.4.2.dist-info}/WHEEL +0 -0
- {thoth_dbmanager-0.4.1.dist-info → thoth_dbmanager-0.4.2.dist-info}/licenses/LICENSE +0 -0
- {thoth_dbmanager-0.4.1.dist-info → thoth_dbmanager-0.4.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,189 @@
|
|
1
|
+
"""
|
2
|
+
Qdrant adapter for Thoth SQL Database Manager.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import Any, Dict, List, Optional, Union
|
6
|
+
from ..core.interfaces import DbAdapter
|
7
|
+
|
8
|
+
|
9
|
+
class QdrantAdapter(DbAdapter):
|
10
|
+
"""
|
11
|
+
Qdrant vector database adapter implementation.
|
12
|
+
"""
|
13
|
+
|
14
|
+
def __init__(self, **kwargs):
|
15
|
+
"""Initialize Qdrant adapter with connection parameters."""
|
16
|
+
super().__init__()
|
17
|
+
self.host = kwargs.get('host', 'localhost')
|
18
|
+
self.port = kwargs.get('port', 6333)
|
19
|
+
self.api_key = kwargs.get('api_key')
|
20
|
+
self.collection_name = kwargs.get('collection_name', 'thoth_documents')
|
21
|
+
self._client = None
|
22
|
+
|
23
|
+
def connect(self) -> bool:
|
24
|
+
"""Establish connection to Qdrant."""
|
25
|
+
try:
|
26
|
+
# Import qdrant_client here to avoid dependency issues
|
27
|
+
from qdrant_client import QdrantClient
|
28
|
+
|
29
|
+
if self.api_key:
|
30
|
+
self._client = QdrantClient(
|
31
|
+
host=self.host,
|
32
|
+
port=self.port,
|
33
|
+
api_key=self.api_key
|
34
|
+
)
|
35
|
+
else:
|
36
|
+
self._client = QdrantClient(
|
37
|
+
host=self.host,
|
38
|
+
port=self.port
|
39
|
+
)
|
40
|
+
|
41
|
+
# Test connection
|
42
|
+
self._client.get_collections()
|
43
|
+
return True
|
44
|
+
except Exception as e:
|
45
|
+
print(f"Failed to connect to Qdrant: {e}")
|
46
|
+
return False
|
47
|
+
|
48
|
+
def disconnect(self) -> None:
|
49
|
+
"""Disconnect from Qdrant."""
|
50
|
+
if self._client:
|
51
|
+
self._client.close()
|
52
|
+
self._client = None
|
53
|
+
|
54
|
+
def execute_query(self, query: str, params: Optional[Dict] = None,
|
55
|
+
fetch: Union[str, int] = "all", timeout: int = 60) -> Any:
|
56
|
+
"""
|
57
|
+
Execute a query against Qdrant.
|
58
|
+
Note: Qdrant doesn't use SQL, so this adapts the interface.
|
59
|
+
"""
|
60
|
+
if not self._client:
|
61
|
+
raise RuntimeError("Not connected to Qdrant")
|
62
|
+
|
63
|
+
# This is a placeholder - adapt based on your specific needs
|
64
|
+
# Qdrant uses vector search, not SQL queries
|
65
|
+
return {"message": "Qdrant uses vector search, not SQL queries"}
|
66
|
+
|
67
|
+
def get_tables(self) -> List[Dict[str, str]]:
|
68
|
+
"""Get collections (equivalent to tables in Qdrant)."""
|
69
|
+
if not self._client:
|
70
|
+
raise RuntimeError("Not connected to Qdrant")
|
71
|
+
|
72
|
+
try:
|
73
|
+
collections = self._client.get_collections()
|
74
|
+
return [
|
75
|
+
{
|
76
|
+
"table_name": collection.name,
|
77
|
+
"table_type": "COLLECTION"
|
78
|
+
}
|
79
|
+
for collection in collections.collections
|
80
|
+
]
|
81
|
+
except Exception as e:
|
82
|
+
print(f"Error getting collections: {e}")
|
83
|
+
return []
|
84
|
+
|
85
|
+
def get_columns(self, table_name: str) -> List[Dict[str, Any]]:
|
86
|
+
"""Get collection info (equivalent to columns in Qdrant)."""
|
87
|
+
if not self._client:
|
88
|
+
raise RuntimeError("Not connected to Qdrant")
|
89
|
+
|
90
|
+
try:
|
91
|
+
collection_info = self._client.get_collection(table_name)
|
92
|
+
return [
|
93
|
+
{
|
94
|
+
"column_name": "id",
|
95
|
+
"data_type": "UUID",
|
96
|
+
"is_nullable": False
|
97
|
+
},
|
98
|
+
{
|
99
|
+
"column_name": "vector",
|
100
|
+
"data_type": f"VECTOR({collection_info.config.params.vectors.size})",
|
101
|
+
"is_nullable": False
|
102
|
+
},
|
103
|
+
{
|
104
|
+
"column_name": "payload",
|
105
|
+
"data_type": "JSON",
|
106
|
+
"is_nullable": True
|
107
|
+
}
|
108
|
+
]
|
109
|
+
except Exception as e:
|
110
|
+
print(f"Error getting collection info: {e}")
|
111
|
+
return []
|
112
|
+
|
113
|
+
def get_foreign_keys(self) -> List[Dict[str, str]]:
|
114
|
+
"""Get foreign keys (not applicable for Qdrant)."""
|
115
|
+
return []
|
116
|
+
|
117
|
+
def get_unique_values(self) -> Dict[str, Dict[str, List[str]]]:
|
118
|
+
"""Get unique values from collections."""
|
119
|
+
if not self._client:
|
120
|
+
raise RuntimeError("Not connected to Qdrant")
|
121
|
+
|
122
|
+
# This is a simplified implementation
|
123
|
+
# In practice, you'd need to scroll through points and extract unique payload values
|
124
|
+
return {}
|
125
|
+
|
126
|
+
def add_documentation(self, doc_type: str, content: Dict[str, Any]) -> str:
|
127
|
+
"""Add documentation to Qdrant collection."""
|
128
|
+
if not self._client:
|
129
|
+
raise RuntimeError("Not connected to Qdrant")
|
130
|
+
|
131
|
+
try:
|
132
|
+
from qdrant_client.models import PointStruct
|
133
|
+
import uuid
|
134
|
+
|
135
|
+
# Generate a unique ID for the document
|
136
|
+
doc_id = str(uuid.uuid4())
|
137
|
+
|
138
|
+
# Create a point with the documentation content
|
139
|
+
point = PointStruct(
|
140
|
+
id=doc_id,
|
141
|
+
vector=content.get('vector', [0.0] * 384), # Default vector size
|
142
|
+
payload={
|
143
|
+
"doc_type": doc_type,
|
144
|
+
"content": content
|
145
|
+
}
|
146
|
+
)
|
147
|
+
|
148
|
+
# Upsert the point
|
149
|
+
self._client.upsert(
|
150
|
+
collection_name=self.collection_name,
|
151
|
+
points=[point]
|
152
|
+
)
|
153
|
+
|
154
|
+
return doc_id
|
155
|
+
except Exception as e:
|
156
|
+
print(f"Error adding documentation: {e}")
|
157
|
+
raise
|
158
|
+
|
159
|
+
def delete_collection(self, collection_name: str) -> bool:
|
160
|
+
"""Delete a collection from Qdrant."""
|
161
|
+
if not self._client:
|
162
|
+
raise RuntimeError("Not connected to Qdrant")
|
163
|
+
|
164
|
+
try:
|
165
|
+
self._client.delete_collection(collection_name)
|
166
|
+
return True
|
167
|
+
except Exception as e:
|
168
|
+
print(f"Error deleting collection: {e}")
|
169
|
+
return False
|
170
|
+
|
171
|
+
def create_collection(self, collection_name: str, vector_size: int = 384) -> bool:
|
172
|
+
"""Create a new collection in Qdrant."""
|
173
|
+
if not self._client:
|
174
|
+
raise RuntimeError("Not connected to Qdrant")
|
175
|
+
|
176
|
+
try:
|
177
|
+
from qdrant_client.models import VectorParams, Distance
|
178
|
+
|
179
|
+
self._client.create_collection(
|
180
|
+
collection_name=collection_name,
|
181
|
+
vectors_config=VectorParams(
|
182
|
+
size=vector_size,
|
183
|
+
distance=Distance.COSINE
|
184
|
+
)
|
185
|
+
)
|
186
|
+
return True
|
187
|
+
except Exception as e:
|
188
|
+
print(f"Error creating collection: {e}")
|
189
|
+
return False
|
@@ -0,0 +1,41 @@
|
|
1
|
+
"""
|
2
|
+
Qdrant plugin for Thoth SQL Database Manager.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import List
|
6
|
+
from ..core.interfaces import DbPlugin
|
7
|
+
from ..adapters.qdrant import QdrantAdapter
|
8
|
+
|
9
|
+
|
10
|
+
class QdrantPlugin(DbPlugin):
|
11
|
+
"""Plugin for Qdrant vector database."""
|
12
|
+
|
13
|
+
plugin_name = "qdrant"
|
14
|
+
plugin_version = "1.0.0"
|
15
|
+
supported_db_types = ["qdrant"]
|
16
|
+
required_dependencies = ["qdrant-client"]
|
17
|
+
|
18
|
+
def create_adapter(self, **kwargs) -> QdrantAdapter:
|
19
|
+
"""Create and return a QdrantAdapter instance."""
|
20
|
+
return QdrantAdapter(**kwargs)
|
21
|
+
|
22
|
+
def validate_connection_params(self, **kwargs) -> bool:
|
23
|
+
"""Validate Qdrant connection parameters."""
|
24
|
+
required_params = ['host']
|
25
|
+
|
26
|
+
for param in required_params:
|
27
|
+
if param not in kwargs:
|
28
|
+
return False
|
29
|
+
|
30
|
+
# Validate host format
|
31
|
+
host = kwargs.get('host')
|
32
|
+
if not isinstance(host, str) or not host.strip():
|
33
|
+
return False
|
34
|
+
|
35
|
+
# Validate port if provided
|
36
|
+
port = kwargs.get('port')
|
37
|
+
if port is not None:
|
38
|
+
if not isinstance(port, int) or port <= 0 or port > 65535:
|
39
|
+
return False
|
40
|
+
|
41
|
+
return True
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: thoth_dbmanager
|
3
|
-
Version: 0.4.
|
3
|
+
Version: 0.4.2
|
4
4
|
Summary: A Python library for managing SQL databases with support for multiple database types, LSH-based similarity search, and a modern plugin architecture.
|
5
5
|
Author-email: Marco Pancotti <mp@tylconsulting.it>
|
6
6
|
License: MIT
|
@@ -45,6 +45,8 @@ Requires-Dist: supabase>=2.0.0; extra == "supabase"
|
|
45
45
|
Requires-Dist: postgrest-py>=0.16.0; extra == "supabase"
|
46
46
|
Requires-Dist: gotrue-py>=2.0.0; extra == "supabase"
|
47
47
|
Provides-Extra: sqlite
|
48
|
+
Provides-Extra: qdrant
|
49
|
+
Requires-Dist: qdrant-client>=1.7.0; extra == "qdrant"
|
48
50
|
Provides-Extra: all
|
49
51
|
Requires-Dist: psycopg2-binary>=2.9.0; extra == "all"
|
50
52
|
Requires-Dist: mysql-connector-python>=8.0.0; extra == "all"
|
@@ -55,6 +57,7 @@ Requires-Dist: informixdb>=2.2.0; extra == "all"
|
|
55
57
|
Requires-Dist: supabase>=2.0.0; extra == "all"
|
56
58
|
Requires-Dist: postgrest-py>=0.16.0; extra == "all"
|
57
59
|
Requires-Dist: gotrue-py>=2.0.0; extra == "all"
|
60
|
+
Requires-Dist: qdrant-client>=1.7.0; extra == "all"
|
58
61
|
Provides-Extra: dev
|
59
62
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
60
63
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
@@ -7,6 +7,7 @@ thoth_dbmanager/adapters/mariadb.py,sha256=LTsf0gORiwqZkd6WtKcOsYLHyDgysxdqNesBs
|
|
7
7
|
thoth_dbmanager/adapters/mysql.py,sha256=TrFbxoMMNWbmUcgkKQYOIfsstmMUmuLlGB7R4ZFEIYI,5698
|
8
8
|
thoth_dbmanager/adapters/oracle.py,sha256=JSrsgohjz5PbVc8nI188MZ4QGBQls4ieNmwWfAKA7II,21468
|
9
9
|
thoth_dbmanager/adapters/postgresql.py,sha256=qxdlxOV7Nvn8U4Lhat50w87Z2S8AzBfmLfEwKfz7dis,17299
|
10
|
+
thoth_dbmanager/adapters/qdrant.py,sha256=sL8ldUbAczENb01MmcrkJBKw0dieWPAG2aj97jznj3k,6557
|
10
11
|
thoth_dbmanager/adapters/sqlite.py,sha256=RTDszgnAtkE14LKFeoe9lBHgsqXqkmDk6jDCTmVpnoM,14659
|
11
12
|
thoth_dbmanager/adapters/sqlserver.py,sha256=V555kUH54Fb1Atow0BfvbSHmoSwGnrB_RJGn718VQSI,23880
|
12
13
|
thoth_dbmanager/adapters/supabase.py,sha256=bl2C6LpOpykPF3vIbdNRDk43aXLADzSk0wQuwTcEHZA,10348
|
@@ -29,11 +30,12 @@ thoth_dbmanager/plugins/mariadb.py,sha256=ElYa4Rexwrofcjcs0UQKan8fZpbU6-n9zghYR9
|
|
29
30
|
thoth_dbmanager/plugins/mysql.py,sha256=mbDsIDV2H_BWYANU4JHMsUkxLQICuGtjKTTPbig2Ngs,16546
|
30
31
|
thoth_dbmanager/plugins/oracle.py,sha256=k4Yxvz5MdsH3Sfty9lxbhr8igSnHvGbGujz3bLpNcHo,5230
|
31
32
|
thoth_dbmanager/plugins/postgresql.py,sha256=GF6k4K0t7-Y08THWJzS0eWJkrQ1e4GfoKIcanC0Z5Ng,5401
|
33
|
+
thoth_dbmanager/plugins/qdrant.py,sha256=XWmc4K6ILiwvB1BhyJBBtA7ohRzQmk1MiZ1N7S-YF78,1199
|
32
34
|
thoth_dbmanager/plugins/sqlite.py,sha256=esgJqDp2aSu4a32WnmynfFyY9JfW5W8VjNTkaA-hZhM,6402
|
33
35
|
thoth_dbmanager/plugins/sqlserver.py,sha256=mMb3F5FmSWV02FZwj-Ult-2TjuyeVA4Fl1iME1dbgLU,5289
|
34
36
|
thoth_dbmanager/plugins/supabase.py,sha256=mWlaGAdpywx4-pU4Ffpmn24ze8sg0sM5kc6bFDoeYRg,8645
|
35
|
-
thoth_dbmanager-0.4.
|
36
|
-
thoth_dbmanager-0.4.
|
37
|
-
thoth_dbmanager-0.4.
|
38
|
-
thoth_dbmanager-0.4.
|
39
|
-
thoth_dbmanager-0.4.
|
37
|
+
thoth_dbmanager-0.4.2.dist-info/licenses/LICENSE,sha256=81-BOzGgwtY1XdYfkwMQB87AkOGXI9OMq0kjNcZA4UE,1071
|
38
|
+
thoth_dbmanager-0.4.2.dist-info/METADATA,sha256=iMFzfRMoh0BqUahLBLt2Pny1oA7L6F1tB7iF8W4D9no,12183
|
39
|
+
thoth_dbmanager-0.4.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
40
|
+
thoth_dbmanager-0.4.2.dist-info/top_level.txt,sha256=b9ttxm9RUc0KUCASEKRx6FqoREYJ1-KZWSpNuaM0uQ4,16
|
41
|
+
thoth_dbmanager-0.4.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|