sunholo 0.123.3__py3-none-any.whl → 0.123.5__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.
- sunholo/database/alloydb_client.py +64 -62
- {sunholo-0.123.3.dist-info → sunholo-0.123.5.dist-info}/METADATA +1 -1
- {sunholo-0.123.3.dist-info → sunholo-0.123.5.dist-info}/RECORD +7 -7
- {sunholo-0.123.3.dist-info → sunholo-0.123.5.dist-info}/WHEEL +0 -0
- {sunholo-0.123.3.dist-info → sunholo-0.123.5.dist-info}/entry_points.txt +0 -0
- {sunholo-0.123.3.dist-info → sunholo-0.123.5.dist-info}/licenses/LICENSE.txt +0 -0
- {sunholo-0.123.3.dist-info → sunholo-0.123.5.dist-info}/top_level.txt +0 -0
@@ -14,7 +14,6 @@ from .uuid import generate_uuid_from_object_id
|
|
14
14
|
from ..custom_logging import log
|
15
15
|
from ..utils import ConfigManager
|
16
16
|
from ..components import get_embeddings
|
17
|
-
|
18
17
|
class AlloyDBClient:
|
19
18
|
"""
|
20
19
|
A class to manage interactions with an AlloyDB instance.
|
@@ -228,22 +227,31 @@ class AlloyDBClient:
|
|
228
227
|
def _execute_sql_langchain(self, sql_statement):
|
229
228
|
return self.engine._fetch(query = sql_statement)
|
230
229
|
|
231
|
-
def _execute_sql_pg8000(self, sql_statement):
|
232
|
-
"""
|
230
|
+
def _execute_sql_pg8000(self, sql_statement, params=None):
|
231
|
+
"""
|
232
|
+
Executes a given SQL statement with error handling.
|
233
233
|
|
234
|
-
|
235
|
-
|
234
|
+
Args:
|
235
|
+
sql_statement (str): The SQL statement to execute.
|
236
|
+
params (dict or list, optional): Parameters for the SQL statement.
|
237
|
+
|
238
|
+
Returns:
|
239
|
+
The result of the execution, if any.
|
236
240
|
"""
|
237
241
|
sql_ = sqlalchemy.text(sql_statement)
|
238
242
|
result = None
|
239
243
|
with self.engine.connect() as conn:
|
240
244
|
try:
|
241
245
|
log.info(f"Executing SQL statement: {sql_}")
|
242
|
-
|
246
|
+
if params:
|
247
|
+
result = conn.execute(sql_, params)
|
248
|
+
else:
|
249
|
+
result = conn.execute(sql_)
|
243
250
|
except DatabaseError as e:
|
244
251
|
if "already exists" in str(e):
|
245
252
|
log.warning(f"Error ignored: {str(e)}. Assuming object already exists.")
|
246
253
|
else:
|
254
|
+
log.error(f"Database error: {e}, SQL: {sql_statement}, Params: {params}")
|
247
255
|
raise
|
248
256
|
finally:
|
249
257
|
conn.close()
|
@@ -253,6 +261,7 @@ class AlloyDBClient:
|
|
253
261
|
async def execute_sql_async(self, sql_statement):
|
254
262
|
log.info(f"Executing async SQL statement: {sql_statement}")
|
255
263
|
if self.engine_type == "pg8000":
|
264
|
+
# dont use async???
|
256
265
|
result = await self._execute_sql_async_pg8000(sql_statement)
|
257
266
|
elif self.engine_type == "langchain":
|
258
267
|
result = await self._execute_sql_async_langchain(sql_statement)
|
@@ -275,14 +284,14 @@ class AlloyDBClient:
|
|
275
284
|
sql_ = sqlalchemy.text(sql_statement)
|
276
285
|
result = None
|
277
286
|
|
278
|
-
#
|
279
|
-
conn =
|
287
|
+
# IMPORTANT: Don't use await here, the engine.connect() is synchronous
|
288
|
+
conn = self.engine.connect()
|
280
289
|
try:
|
281
290
|
log.info(f"Executing SQL statement asynchronously: {sql_}")
|
282
291
|
if values:
|
283
|
-
result =
|
292
|
+
result = conn.execute(sql_, values)
|
284
293
|
else:
|
285
|
-
result =
|
294
|
+
result = conn.execute(sql_)
|
286
295
|
|
287
296
|
# Explicitly commit transaction
|
288
297
|
await conn.commit()
|
@@ -293,7 +302,7 @@ class AlloyDBClient:
|
|
293
302
|
raise
|
294
303
|
finally:
|
295
304
|
# Close connection only here, not inside the context manager
|
296
|
-
|
305
|
+
conn.close()
|
297
306
|
|
298
307
|
return result
|
299
308
|
|
@@ -512,42 +521,6 @@ class AlloyDBClient:
|
|
512
521
|
|
513
522
|
self.grant_table_permissions(vectorstore_id, users)
|
514
523
|
|
515
|
-
async def _execute_sql_async_pg8000(self, sql_statement, values=None):
|
516
|
-
"""Executes a given SQL statement asynchronously with error handling."""
|
517
|
-
sql_ = sqlalchemy.text(sql_statement)
|
518
|
-
result = None
|
519
|
-
async with self.engine.connect() as conn:
|
520
|
-
try:
|
521
|
-
log.info(f"Executing SQL statement asynchronously: {sql_}")
|
522
|
-
if values:
|
523
|
-
result = await conn.execute(sql_, values)
|
524
|
-
else:
|
525
|
-
result = await conn.execute(sql_)
|
526
|
-
except DatabaseError as e:
|
527
|
-
if "already exists" in str(e):
|
528
|
-
log.warning(f"Error ignored: {str(e)}. Assuming object already exists.")
|
529
|
-
else:
|
530
|
-
raise
|
531
|
-
finally:
|
532
|
-
await conn.close()
|
533
|
-
|
534
|
-
return result
|
535
|
-
|
536
|
-
async def _execute_sql_async_langchain(self, sql_statement, values=None):
|
537
|
-
"""Execute SQL asynchronously using langchain engine"""
|
538
|
-
if values:
|
539
|
-
# Implement parameterized queries for langchain engine
|
540
|
-
# This would need to be adjusted based on how langchain engine handles parameters
|
541
|
-
log.warning("Parameterized queries may not be fully supported with langchain engine")
|
542
|
-
# For now, attempt a basic string substitution (not ideal for production)
|
543
|
-
for value in values:
|
544
|
-
if isinstance(value, str):
|
545
|
-
sql_statement = sql_statement.replace("%s", f"'{value}'", 1)
|
546
|
-
else:
|
547
|
-
sql_statement = sql_statement.replace("%s", str(value), 1)
|
548
|
-
|
549
|
-
return await self.engine._afetch(query=sql_statement)
|
550
|
-
|
551
524
|
async def check_connection(self):
|
552
525
|
"""
|
553
526
|
Checks if the database connection is still valid.
|
@@ -556,9 +529,16 @@ class AlloyDBClient:
|
|
556
529
|
bool: True if connection is valid, False otherwise
|
557
530
|
"""
|
558
531
|
try:
|
559
|
-
#
|
560
|
-
|
561
|
-
|
532
|
+
# For pg8000 engine, use synchronous connection
|
533
|
+
if self.engine_type == "pg8000":
|
534
|
+
# Use direct synchronous query
|
535
|
+
with self.engine.connect() as conn:
|
536
|
+
conn.execute(sqlalchemy.text("SELECT 1"))
|
537
|
+
return True
|
538
|
+
else:
|
539
|
+
# For langchain, use async connection
|
540
|
+
await self._execute_sql_async_langchain("SELECT 1")
|
541
|
+
return True
|
562
542
|
except Exception as e:
|
563
543
|
log.warning(f"Database connection check failed: {e}")
|
564
544
|
return False
|
@@ -650,15 +630,24 @@ class AlloyDBClient:
|
|
650
630
|
)
|
651
631
|
'''
|
652
632
|
|
653
|
-
# Execute SQL to create table
|
654
|
-
|
633
|
+
# Execute SQL to create table based on engine type
|
634
|
+
if self.engine_type == "pg8000":
|
635
|
+
# Use the synchronous method for pg8000
|
636
|
+
result = self._execute_sql_pg8000(sql)
|
637
|
+
else:
|
638
|
+
# Use the async method for langchain
|
639
|
+
result = await self._execute_sql_async_langchain(sql)
|
640
|
+
|
655
641
|
log.info(f"Created or ensured table {table_name} exists")
|
656
642
|
|
657
643
|
# Grant permissions if users are provided
|
658
644
|
if users:
|
659
645
|
for user in users:
|
660
646
|
grant_sql = f'GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE "{table_name}" TO "{user}";'
|
661
|
-
|
647
|
+
if self.engine_type == "pg8000":
|
648
|
+
self.execute_sql(grant_sql)
|
649
|
+
else:
|
650
|
+
await self._execute_sql_async_langchain(grant_sql)
|
662
651
|
|
663
652
|
return result
|
664
653
|
|
@@ -683,15 +672,22 @@ class AlloyDBClient:
|
|
683
672
|
insert_data["extraction_backend"] = metadata.get("extraction_backend", "unknown")
|
684
673
|
insert_data["extraction_model"] = metadata.get("extraction_model", "unknown")
|
685
674
|
|
686
|
-
# Prepare column names and
|
675
|
+
# Prepare column names and values for SQL
|
687
676
|
columns = [f'"{key}"' for key in insert_data.keys()]
|
688
|
-
placeholders = []
|
689
|
-
values = []
|
690
677
|
|
691
|
-
# Process values
|
692
|
-
|
693
|
-
|
694
|
-
|
678
|
+
# Process values
|
679
|
+
processed_values = {}
|
680
|
+
for i, (key, value) in enumerate(insert_data.items()):
|
681
|
+
# Create a unique parameter name
|
682
|
+
param_name = f"param_{i}"
|
683
|
+
# For JSON values, convert to string
|
684
|
+
if isinstance(value, (dict, list)):
|
685
|
+
processed_values[param_name] = json.dumps(value)
|
686
|
+
else:
|
687
|
+
processed_values[param_name] = value
|
688
|
+
|
689
|
+
# Create placeholders using named parameters
|
690
|
+
placeholders = [f":{param_name}" for param_name in processed_values.keys()]
|
695
691
|
|
696
692
|
# Create SQL statement for insertion
|
697
693
|
columns_str = ", ".join(columns)
|
@@ -703,8 +699,14 @@ class AlloyDBClient:
|
|
703
699
|
RETURNING id
|
704
700
|
'''
|
705
701
|
|
706
|
-
# Execute SQL to insert data
|
707
|
-
|
702
|
+
# Execute SQL to insert data based on engine type
|
703
|
+
if self.engine_type == "pg8000":
|
704
|
+
# Use the synchronous method for pg8000 with properly formatted parameters
|
705
|
+
result = self._execute_sql_pg8000(sql, processed_values)
|
706
|
+
else:
|
707
|
+
# Use the async method for langchain
|
708
|
+
result = await self._execute_sql_async_langchain(sql, processed_values)
|
709
|
+
|
708
710
|
log.info(f"Inserted data into table {table_name}")
|
709
711
|
|
710
712
|
return result
|
@@ -60,7 +60,7 @@ sunholo/components/retriever.py,sha256=Wmchv3huAM4w7DIS-a5Lp9Hi7M8pE6vZdxgseiT9S
|
|
60
60
|
sunholo/components/vectorstore.py,sha256=k7GS1Y5c6ZGXSDAJvyCes6dTjhDAi0fjGbVLqpyfzBc,5918
|
61
61
|
sunholo/database/__init__.py,sha256=bpB5Nk21kwqYj-qdVnvNgXjLsbflnH4g-San7OHMqR4,283
|
62
62
|
sunholo/database/alloydb.py,sha256=x1zUMB-EVWbE2Zvp4nAs2Z-tB_kOZmS45H2lwVHdYnk,11678
|
63
|
-
sunholo/database/alloydb_client.py,sha256=
|
63
|
+
sunholo/database/alloydb_client.py,sha256=OCAi7Gopry7tiOOdjka-cldghFpxl6IXWWGEANmFVII,27414
|
64
64
|
sunholo/database/database.py,sha256=VqhZdkXUNdvWn8sUcUV3YNby1JDVf7IykPVXWBtxo9U,7361
|
65
65
|
sunholo/database/lancedb.py,sha256=DyfZntiFKBlVPaFooNN1Z6Pl-LAs4nxWKKuq8GBqN58,715
|
66
66
|
sunholo/database/static_dbs.py,sha256=8cvcMwUK6c32AS2e_WguKXWMkFf5iN3g9WHzsh0C07Q,442
|
@@ -168,9 +168,9 @@ sunholo/vertex/init.py,sha256=1OQwcPBKZYBTDPdyU7IM4X4OmiXLdsNV30C-fee2scQ,2875
|
|
168
168
|
sunholo/vertex/memory_tools.py,sha256=tBZxqVZ4InTmdBvLlOYwoSEWu4-kGquc-gxDwZCC4FA,7667
|
169
169
|
sunholo/vertex/safety.py,sha256=S9PgQT1O_BQAkcqauWncRJaydiP8Q_Jzmu9gxYfy1VA,2482
|
170
170
|
sunholo/vertex/type_dict_to_json.py,sha256=uTzL4o9tJRao4u-gJOFcACgWGkBOtqACmb6ihvCErL8,4694
|
171
|
-
sunholo-0.123.
|
172
|
-
sunholo-0.123.
|
173
|
-
sunholo-0.123.
|
174
|
-
sunholo-0.123.
|
175
|
-
sunholo-0.123.
|
176
|
-
sunholo-0.123.
|
171
|
+
sunholo-0.123.5.dist-info/licenses/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
|
172
|
+
sunholo-0.123.5.dist-info/METADATA,sha256=ahlMOD2O68Y-qNXEM0UmWYJt_6dZyPvjXxdDcB71T8Y,10001
|
173
|
+
sunholo-0.123.5.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
174
|
+
sunholo-0.123.5.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
|
175
|
+
sunholo-0.123.5.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
|
176
|
+
sunholo-0.123.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|