sqlspec 0.64.0__py3-none-any.whl → 0.65.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.
- sqlspec/_typing.py +2 -0
- sqlspec/adapters/adbc/_typing.py +1 -2
- sqlspec/adapters/adbc/adk/store.py +130 -59
- sqlspec/adapters/adbc/config.py +7 -0
- sqlspec/adapters/adbc/core.py +42 -14
- sqlspec/adapters/adbc/driver.py +10 -4
- sqlspec/adapters/aiomysql/_typing.py +2 -0
- sqlspec/adapters/aiomysql/adk/store.py +7 -4
- sqlspec/adapters/aiomysql/config.py +38 -11
- sqlspec/adapters/aiomysql/core.py +45 -520
- sqlspec/adapters/aiomysql/data_dictionary.py +4 -290
- sqlspec/adapters/aiomysql/driver.py +16 -14
- sqlspec/adapters/aiosqlite/__init__.py +2 -0
- sqlspec/adapters/aiosqlite/_typing.py +1 -2
- sqlspec/adapters/aiosqlite/adk/store.py +105 -76
- sqlspec/adapters/aiosqlite/config.py +27 -61
- sqlspec/adapters/aiosqlite/core.py +155 -16
- sqlspec/adapters/aiosqlite/data_dictionary.py +0 -1
- sqlspec/adapters/aiosqlite/driver.py +82 -38
- sqlspec/adapters/aiosqlite/events/store.py +4 -3
- sqlspec/adapters/aiosqlite/litestar/store.py +16 -13
- sqlspec/adapters/aiosqlite/pool.py +80 -77
- sqlspec/adapters/arrow_odbc/_typing.py +1 -2
- sqlspec/adapters/arrow_odbc/adk/store.py +511 -168
- sqlspec/adapters/arrow_odbc/config.py +15 -2
- sqlspec/adapters/arrow_odbc/core.py +229 -19
- sqlspec/adapters/arrow_odbc/data_dictionary.py +10 -9
- sqlspec/adapters/arrow_odbc/driver.py +210 -85
- sqlspec/adapters/arrow_odbc/events/store.py +43 -18
- sqlspec/adapters/arrow_odbc/litestar/store.py +222 -54
- sqlspec/adapters/arrow_odbc/type_converter.py +9 -0
- sqlspec/adapters/asyncmy/_typing.py +2 -2
- sqlspec/adapters/asyncmy/adk/store.py +7 -4
- sqlspec/adapters/asyncmy/config.py +30 -11
- sqlspec/adapters/asyncmy/core.py +46 -536
- sqlspec/adapters/asyncmy/data_dictionary.py +4 -290
- sqlspec/adapters/asyncmy/driver.py +10 -10
- sqlspec/adapters/asyncpg/_typing.py +3 -5
- sqlspec/adapters/asyncpg/adk/store.py +13 -5
- sqlspec/adapters/asyncpg/config.py +32 -13
- sqlspec/adapters/asyncpg/core.py +26 -12
- sqlspec/adapters/asyncpg/driver.py +26 -12
- sqlspec/adapters/asyncpg/litestar/store.py +17 -10
- sqlspec/adapters/bigquery/_typing.py +9 -15
- sqlspec/adapters/bigquery/config.py +24 -7
- sqlspec/adapters/bigquery/core.py +16 -26
- sqlspec/adapters/bigquery/driver.py +80 -58
- sqlspec/adapters/bigquery/litestar/store.py +19 -5
- sqlspec/adapters/cockroach_asyncpg/_typing.py +3 -5
- sqlspec/adapters/cockroach_asyncpg/config.py +4 -2
- sqlspec/adapters/cockroach_asyncpg/core.py +27 -0
- sqlspec/adapters/cockroach_psycopg/_typing.py +3 -5
- sqlspec/adapters/cockroach_psycopg/adk/store.py +36 -9
- sqlspec/adapters/cockroach_psycopg/config.py +6 -29
- sqlspec/adapters/cockroach_psycopg/core.py +46 -0
- sqlspec/adapters/cockroach_psycopg/driver.py +16 -5
- sqlspec/adapters/db2/__init__.py +31 -0
- sqlspec/adapters/db2/_typing.py +311 -0
- sqlspec/adapters/db2/adk/__init__.py +10 -0
- sqlspec/adapters/db2/adk/store.py +1334 -0
- sqlspec/adapters/db2/config.py +460 -0
- sqlspec/adapters/db2/core.py +753 -0
- sqlspec/adapters/db2/data_dictionary.py +478 -0
- sqlspec/adapters/db2/driver.py +674 -0
- sqlspec/adapters/db2/events/__init__.py +6 -0
- sqlspec/adapters/db2/events/config.py +9 -0
- sqlspec/adapters/db2/events/store.py +67 -0
- sqlspec/adapters/db2/litestar/__init__.py +6 -0
- sqlspec/adapters/db2/litestar/config.py +12 -0
- sqlspec/adapters/db2/litestar/store.py +465 -0
- sqlspec/adapters/db2/migrations.py +191 -0
- sqlspec/adapters/db2/pool.py +564 -0
- sqlspec/adapters/duckdb/_typing.py +1 -2
- sqlspec/adapters/duckdb/adk/store.py +30 -15
- sqlspec/adapters/duckdb/config.py +23 -42
- sqlspec/adapters/duckdb/core.py +26 -2
- sqlspec/adapters/duckdb/driver.py +38 -29
- sqlspec/adapters/duckdb/litestar/store.py +3 -3
- sqlspec/adapters/mssql_python/adk/store.py +39 -17
- sqlspec/adapters/mssql_python/config.py +1 -0
- sqlspec/adapters/mssql_python/core.py +55 -17
- sqlspec/adapters/mssql_python/data_dictionary.py +1 -41
- sqlspec/adapters/mssql_python/driver.py +93 -15
- sqlspec/adapters/mssql_python/events/store.py +5 -24
- sqlspec/adapters/mssql_python/litestar/store.py +18 -47
- sqlspec/adapters/mssql_python/pool.py +3 -2
- sqlspec/adapters/mysql_common.py +502 -0
- sqlspec/adapters/mysqlconnector/_typing.py +6 -0
- sqlspec/adapters/mysqlconnector/adk/store.py +14 -8
- sqlspec/adapters/mysqlconnector/config.py +92 -20
- sqlspec/adapters/mysqlconnector/core.py +56 -461
- sqlspec/adapters/mysqlconnector/data_dictionary.py +6 -549
- sqlspec/adapters/mysqlconnector/driver.py +23 -16
- sqlspec/adapters/oracledb/__init__.py +7 -2
- sqlspec/adapters/oracledb/_json_handlers.py +46 -16
- sqlspec/adapters/oracledb/_storage.py +6 -4
- sqlspec/adapters/oracledb/adk/store.py +237 -268
- sqlspec/adapters/oracledb/config.py +34 -32
- sqlspec/adapters/oracledb/core.py +88 -87
- sqlspec/adapters/oracledb/driver.py +36 -13
- sqlspec/adapters/oracledb/events/store.py +10 -10
- sqlspec/adapters/oracledb/litestar/store.py +121 -202
- sqlspec/adapters/oracledb/migrations.py +1 -5
- sqlspec/adapters/oracledb/type_converter.py +10 -7
- sqlspec/adapters/psqlpy/_typing.py +2 -1
- sqlspec/adapters/psqlpy/adk/store.py +73 -39
- sqlspec/adapters/psqlpy/config.py +22 -12
- sqlspec/adapters/psqlpy/core.py +11 -5
- sqlspec/adapters/psqlpy/litestar/store.py +20 -18
- sqlspec/adapters/psqlpy/type_converter.py +17 -3
- sqlspec/adapters/psycopg/_typing.py +5 -2
- sqlspec/adapters/psycopg/adk/store.py +60 -18
- sqlspec/adapters/psycopg/config.py +40 -16
- sqlspec/adapters/psycopg/driver.py +36 -40
- sqlspec/adapters/psycopg/type_converter.py +2 -6
- sqlspec/adapters/pymssql/adk/store.py +18 -25
- sqlspec/adapters/pymssql/config.py +3 -0
- sqlspec/adapters/pymssql/core.py +31 -16
- sqlspec/adapters/pymssql/data_dictionary.py +1 -41
- sqlspec/adapters/pymssql/driver.py +4 -3
- sqlspec/adapters/pymssql/events/store.py +5 -24
- sqlspec/adapters/pymssql/litestar/store.py +18 -47
- sqlspec/adapters/pymssql/pool.py +2 -6
- sqlspec/adapters/pymysql/_typing.py +12 -25
- sqlspec/adapters/pymysql/adk/store.py +7 -4
- sqlspec/adapters/pymysql/config.py +3 -5
- sqlspec/adapters/pymysql/core.py +44 -464
- sqlspec/adapters/pymysql/data_dictionary.py +5 -289
- sqlspec/adapters/pymysql/driver.py +13 -8
- sqlspec/adapters/pymysql/litestar/store.py +1 -6
- sqlspec/adapters/pymysql/pool.py +16 -8
- sqlspec/adapters/spanner/adk/store.py +25 -22
- sqlspec/adapters/spanner/config.py +22 -10
- sqlspec/adapters/spanner/core.py +2 -7
- sqlspec/adapters/spanner/data_dictionary.py +132 -18
- sqlspec/adapters/spanner/driver.py +56 -18
- sqlspec/adapters/spanner/type_converter.py +43 -21
- sqlspec/adapters/sqlite/__init__.py +2 -0
- sqlspec/adapters/sqlite/_typing.py +1 -2
- sqlspec/adapters/sqlite/adk/store.py +78 -75
- sqlspec/adapters/sqlite/config.py +28 -63
- sqlspec/adapters/sqlite/core.py +103 -28
- sqlspec/adapters/sqlite/data_dictionary.py +0 -2
- sqlspec/adapters/sqlite/driver.py +88 -45
- sqlspec/adapters/sqlite/events/store.py +4 -3
- sqlspec/adapters/sqlite/litestar/store.py +12 -12
- sqlspec/adapters/sqlite/pool.py +74 -80
- sqlspec/builder/_base.py +67 -52
- sqlspec/builder/_ddl.py +25 -10
- sqlspec/builder/_dml.py +18 -7
- sqlspec/builder/_factory.py +3 -3
- sqlspec/builder/_merge.py +104 -4
- sqlspec/builder/_parsing_utils.py +37 -2
- sqlspec/builder/_select.py +1 -1
- sqlspec/core/query_modifiers.py +2 -2
- sqlspec/core/splitter.py +9 -0
- sqlspec/core/statement.py +8 -9
- sqlspec/data_dictionary/_registry.py +3 -0
- sqlspec/data_dictionary/_types.py +9 -1
- sqlspec/data_dictionary/dialects/__init__.py +2 -0
- sqlspec/data_dictionary/dialects/db2/__init__.py +31 -0
- sqlspec/data_dictionary/dialects/db2/config.py +172 -0
- sqlspec/data_dictionary/dialects/db2/sql/columns.sql +66 -0
- sqlspec/data_dictionary/dialects/db2/sql/constraints.sql +49 -0
- sqlspec/data_dictionary/dialects/db2/sql/foreign_keys.sql +43 -0
- sqlspec/data_dictionary/dialects/db2/sql/indexes.sql +39 -0
- sqlspec/data_dictionary/dialects/db2/sql/objects.sql +53 -0
- sqlspec/data_dictionary/dialects/db2/sql/schemas.sql +17 -0
- sqlspec/data_dictionary/dialects/db2/sql/tables.sql +87 -0
- sqlspec/data_dictionary/dialects/db2/sql/version.sql +8 -0
- sqlspec/data_dictionary/dialects/db2/sql/views.sql +15 -0
- sqlspec/data_dictionary/dialects/mssql/__init__.py +2 -0
- sqlspec/data_dictionary/dialects/mssql/config.py +41 -1
- sqlspec/data_dictionary/dialects/mysql/__init__.py +3 -0
- sqlspec/data_dictionary/dialects/mysql/dictionary.py +583 -0
- sqlspec/data_dictionary/dialects/spanner/config.py +2 -0
- sqlspec/data_dictionary/dialects/spanner/sql/foreign_keys.sql +23 -2
- sqlspec/data_dictionary/dialects/spanner/sql/googlesql/columns.sql +39 -16
- sqlspec/data_dictionary/dialects/spanner/sql/googlesql/constraints.sql +32 -0
- sqlspec/data_dictionary/dialects/spanner/sql/googlesql/foreign_keys.sql +91 -0
- sqlspec/data_dictionary/dialects/spanner/sql/googlesql/indexes.sql +36 -3
- sqlspec/data_dictionary/dialects/spanner/sql/googlesql/tables.sql +23 -8
- sqlspec/data_dictionary/dialects/spanner/sql/postgresql/change_streams.sql +28 -0
- sqlspec/data_dictionary/dialects/spanner/sql/postgresql/columns.sql +34 -0
- sqlspec/data_dictionary/dialects/spanner/sql/postgresql/constraints.sql +63 -0
- sqlspec/data_dictionary/dialects/spanner/sql/postgresql/foreign_keys.sql +91 -0
- sqlspec/data_dictionary/dialects/spanner/sql/postgresql/indexes.sql +52 -0
- sqlspec/data_dictionary/dialects/spanner/sql/postgresql/sequences.sql +14 -0
- sqlspec/data_dictionary/dialects/spanner/sql/postgresql/system.sql +27 -0
- sqlspec/data_dictionary/dialects/spanner/sql/postgresql/tables.sql +22 -0
- sqlspec/dialects/__init__.py +3 -1
- sqlspec/dialects/db2/__init__.py +110 -0
- sqlspec/dialects/db2/_generators.py +352 -0
- sqlspec/dialects/db2/_parsers.py +558 -0
- sqlspec/dialects/db2/_transforms.py +164 -0
- sqlspec/dialects/spanner/_expressions.py +78 -0
- sqlspec/dialects/spanner/_generators.py +481 -22
- sqlspec/dialects/spanner/_parsers.py +393 -57
- sqlspec/dialects/spanner/_spangres.py +19 -22
- sqlspec/dialects/spanner/_spanner.py +27 -23
- sqlspec/driver/_common.py +7 -7
- sqlspec/extensions/adk/memory/converters.py +8 -8
- sqlspec/extensions/adk/memory/service.py +99 -3
- sqlspec/extensions/adk/service.py +9 -11
- sqlspec/extensions/events/_queue.py +3 -1
- sqlspec/extensions/events/primitives.py +11 -2
- sqlspec/migrations/base.py +61 -59
- sqlspec/migrations/schema.py +56 -24
- sqlspec/migrations/tracker.py +3 -6
- sqlspec/observability/_common.py +1 -0
- sqlspec/protocols.py +1 -0
- sqlspec/typing.py +2 -0
- sqlspec/utils/fixtures.py +284 -114
- sqlspec/utils/text.py +1 -1
- {sqlspec-0.64.0.dist-info → sqlspec-0.65.0.dist-info}/METADATA +3 -1
- {sqlspec-0.64.0.dist-info → sqlspec-0.65.0.dist-info}/RECORD +219 -176
- {sqlspec-0.64.0.dist-info → sqlspec-0.65.0.dist-info}/WHEEL +1 -1
- {sqlspec-0.64.0.dist-info → sqlspec-0.65.0.dist-info}/entry_points.txt +1 -0
- {sqlspec-0.64.0.dist-info → sqlspec-0.65.0.dist-info}/licenses/LICENSE +0 -0
sqlspec/_typing.py
CHANGED
|
@@ -50,6 +50,7 @@ __all__ = (
|
|
|
50
50
|
"CATTRS_INSTALLED",
|
|
51
51
|
"CLOUD_SQL_CONNECTOR_INSTALLED",
|
|
52
52
|
"FSSPEC_INSTALLED",
|
|
53
|
+
"IBM_DB_INSTALLED",
|
|
53
54
|
"LITESTAR_INSTALLED",
|
|
54
55
|
"MSGSPEC_INSTALLED",
|
|
55
56
|
"NANOID_INSTALLED",
|
|
@@ -666,6 +667,7 @@ ATTRS_INSTALLED = dependency_flag("attrs")
|
|
|
666
667
|
CATTRS_INSTALLED = dependency_flag("cattrs")
|
|
667
668
|
CLOUD_SQL_CONNECTOR_INSTALLED = dependency_flag("google.cloud.sql.connector")
|
|
668
669
|
FSSPEC_INSTALLED = dependency_flag("fsspec")
|
|
670
|
+
IBM_DB_INSTALLED = dependency_flag("ibm_db")
|
|
669
671
|
LITESTAR_INSTALLED = dependency_flag("litestar")
|
|
670
672
|
MSGSPEC_INSTALLED = dependency_flag("msgspec")
|
|
671
673
|
NUMPY_INSTALLED = dependency_flag("numpy")
|
sqlspec/adapters/adbc/_typing.py
CHANGED
|
@@ -31,8 +31,7 @@ if TYPE_CHECKING:
|
|
|
31
31
|
AdbcConnection: TypeAlias = _AdbcConnection
|
|
32
32
|
AdbcRawCursor: TypeAlias = _AdbcRawCursor
|
|
33
33
|
AdbcNativeError: TypeAlias = _AdbcNativeError
|
|
34
|
-
|
|
35
|
-
if not TYPE_CHECKING:
|
|
34
|
+
else:
|
|
36
35
|
AdbcConnection = _AdbcConnection
|
|
37
36
|
AdbcRawCursor = _AdbcRawCursor
|
|
38
37
|
AdbcNativeError = _AdbcNativeError
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
"""ADBC ADK store for Google Agent Development Kit session/event storage."""
|
|
2
2
|
|
|
3
3
|
import contextlib
|
|
4
|
-
import re
|
|
5
4
|
from datetime import datetime, timedelta, timezone
|
|
5
|
+
from functools import lru_cache
|
|
6
6
|
from typing import TYPE_CHECKING, Any, Final, Literal
|
|
7
7
|
|
|
8
|
+
from sqlspec.adapters.adbc.core import (
|
|
9
|
+
driver_kind_from_driver_name,
|
|
10
|
+
is_shared_object_driver,
|
|
11
|
+
resolve_dialect_from_config,
|
|
12
|
+
)
|
|
13
|
+
from sqlspec.core.parameters._validator import PARAMETER_REGEX
|
|
8
14
|
from sqlspec.extensions.adk import BaseSyncADKStore, StoredEvent, StoredSession, normalize_session_list_options
|
|
9
15
|
from sqlspec.extensions.adk.memory.store import BaseSyncADKMemoryStore
|
|
10
16
|
from sqlspec.utils.logging import get_logger
|
|
@@ -36,6 +42,21 @@ ADBC_TABLE_NOT_FOUND_PATTERNS: Final = (
|
|
|
36
42
|
)
|
|
37
43
|
|
|
38
44
|
|
|
45
|
+
@lru_cache(maxsize=256)
|
|
46
|
+
def _postgresql_store_sql(sql: str) -> str:
|
|
47
|
+
"""Cache positional SQL conversion without changing quoted or commented text."""
|
|
48
|
+
segments: list[str] = []
|
|
49
|
+
last_end = 0
|
|
50
|
+
index = 0
|
|
51
|
+
for match in PARAMETER_REGEX.finditer(sql):
|
|
52
|
+
if match.lastgroup == "qmark":
|
|
53
|
+
index += 1
|
|
54
|
+
segments.extend((sql[last_end : match.start()], f"${index}"))
|
|
55
|
+
last_end = match.end()
|
|
56
|
+
segments.append(sql[last_end:])
|
|
57
|
+
return "".join(segments)
|
|
58
|
+
|
|
59
|
+
|
|
39
60
|
class AdbcADKStore(BaseSyncADKStore["AdbcConfig"]):
|
|
40
61
|
"""ADBC synchronous ADK store for Arrow Database Connectivity.
|
|
41
62
|
|
|
@@ -192,15 +213,28 @@ class AdbcADKStore(BaseSyncADKStore["AdbcConfig"]):
|
|
|
192
213
|
Returns:
|
|
193
214
|
Dialect identifier for DDL generation.
|
|
194
215
|
"""
|
|
195
|
-
driver_name = self._config.connection_config.get("driver_name", "")
|
|
196
|
-
|
|
197
|
-
|
|
216
|
+
driver_name = self._config.connection_config.get("driver_name", "")
|
|
217
|
+
if (
|
|
218
|
+
isinstance(driver_name, str)
|
|
219
|
+
and driver_name
|
|
220
|
+
and driver_kind_from_driver_name(driver_name) is None
|
|
221
|
+
and not is_shared_object_driver(driver_name)
|
|
222
|
+
):
|
|
223
|
+
logger.warning(
|
|
224
|
+
"Unknown ADBC driver: %s. Using generic SQL dialect. "
|
|
225
|
+
"Consider using a direct adapter for better performance.",
|
|
226
|
+
driver_name,
|
|
227
|
+
)
|
|
228
|
+
return DIALECT_GENERIC
|
|
229
|
+
|
|
230
|
+
resolved = resolve_dialect_from_config(self._config.connection_config)
|
|
231
|
+
if resolved == "postgres":
|
|
198
232
|
return DIALECT_POSTGRESQL
|
|
199
|
-
if "sqlite"
|
|
233
|
+
if resolved == "sqlite":
|
|
200
234
|
return DIALECT_SQLITE
|
|
201
|
-
if "duckdb"
|
|
235
|
+
if resolved == "duckdb":
|
|
202
236
|
return DIALECT_DUCKDB
|
|
203
|
-
if "snowflake"
|
|
237
|
+
if resolved == "snowflake":
|
|
204
238
|
return DIALECT_SNOWFLAKE
|
|
205
239
|
|
|
206
240
|
logger.warning(
|
|
@@ -605,14 +639,7 @@ class AdbcADKStore(BaseSyncADKStore["AdbcConfig"]):
|
|
|
605
639
|
"""Return SQL with dialect-appropriate positional placeholders."""
|
|
606
640
|
if self._dialect != DIALECT_POSTGRESQL:
|
|
607
641
|
return sql
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
def replace_placeholder(_match: Any) -> str:
|
|
611
|
-
nonlocal index
|
|
612
|
-
index += 1
|
|
613
|
-
return f"${index}"
|
|
614
|
-
|
|
615
|
-
return re.sub(r"\?", replace_placeholder, sql)
|
|
642
|
+
return _postgresql_store_sql(sql)
|
|
616
643
|
|
|
617
644
|
def _execute(self, cursor: Any, sql: str, params: "tuple[Any, ...] | list[Any]") -> Any:
|
|
618
645
|
"""Execute parameterized SQL using the current ADBC dialect's placeholder style."""
|
|
@@ -961,37 +988,41 @@ class AdbcADKStore(BaseSyncADKStore["AdbcConfig"]):
|
|
|
961
988
|
with self._config.provide_connection() as conn:
|
|
962
989
|
cursor = conn.cursor()
|
|
963
990
|
try:
|
|
964
|
-
self._execute(
|
|
965
|
-
cursor,
|
|
966
|
-
insert_sql,
|
|
967
|
-
(
|
|
968
|
-
event_record["id"],
|
|
969
|
-
event_record["app_name"],
|
|
970
|
-
event_record["user_id"],
|
|
971
|
-
event_record["session_id"],
|
|
972
|
-
event_record["invocation_id"],
|
|
973
|
-
event_record["timestamp"],
|
|
974
|
-
event_data,
|
|
975
|
-
),
|
|
976
|
-
)
|
|
977
991
|
self._execute(cursor, update_sql, (state_json, app_name, user_id, session_id))
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
cursor,
|
|
982
|
-
insert_app_state_sql,
|
|
983
|
-
(app_name, self._serialize_state(app_state), datetime.now(timezone.utc)),
|
|
984
|
-
)
|
|
985
|
-
if user_state is not None:
|
|
986
|
-
self._execute(cursor, delete_user_state_sql, (app_name, user_id))
|
|
992
|
+
self._execute(cursor, select_sql, (app_name, user_id, session_id))
|
|
993
|
+
row = cursor.fetchone()
|
|
994
|
+
if row is not None:
|
|
987
995
|
self._execute(
|
|
988
996
|
cursor,
|
|
989
|
-
|
|
990
|
-
(
|
|
997
|
+
insert_sql,
|
|
998
|
+
(
|
|
999
|
+
event_record["id"],
|
|
1000
|
+
event_record["app_name"],
|
|
1001
|
+
event_record["user_id"],
|
|
1002
|
+
event_record["session_id"],
|
|
1003
|
+
event_record["invocation_id"],
|
|
1004
|
+
event_record["timestamp"],
|
|
1005
|
+
event_data,
|
|
1006
|
+
),
|
|
991
1007
|
)
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1008
|
+
if app_state is not None:
|
|
1009
|
+
self._execute(cursor, delete_app_state_sql, (app_name,))
|
|
1010
|
+
self._execute(
|
|
1011
|
+
cursor,
|
|
1012
|
+
insert_app_state_sql,
|
|
1013
|
+
(app_name, self._serialize_state(app_state), datetime.now(timezone.utc)),
|
|
1014
|
+
)
|
|
1015
|
+
if user_state is not None:
|
|
1016
|
+
self._execute(cursor, delete_user_state_sql, (app_name, user_id))
|
|
1017
|
+
self._execute(
|
|
1018
|
+
cursor,
|
|
1019
|
+
insert_user_state_sql,
|
|
1020
|
+
(app_name, user_id, self._serialize_state(user_state), datetime.now(timezone.utc)),
|
|
1021
|
+
)
|
|
1022
|
+
conn.commit()
|
|
1023
|
+
else:
|
|
1024
|
+
with contextlib.suppress(Exception):
|
|
1025
|
+
conn.rollback()
|
|
995
1026
|
except Exception:
|
|
996
1027
|
with contextlib.suppress(Exception):
|
|
997
1028
|
conn.rollback()
|
|
@@ -1277,6 +1308,9 @@ class AdbcADKMemoryStore(BaseSyncADKMemoryStore["AdbcConfig"]):
|
|
|
1277
1308
|
|
|
1278
1309
|
def create_tables(self) -> None:
|
|
1279
1310
|
"""Create tables if they don't exist."""
|
|
1311
|
+
if not self._enabled:
|
|
1312
|
+
return
|
|
1313
|
+
|
|
1280
1314
|
if not self.create_schema_enabled:
|
|
1281
1315
|
self.reconcile_schema()
|
|
1282
1316
|
return
|
|
@@ -1308,18 +1342,43 @@ class AdbcADKMemoryStore(BaseSyncADKMemoryStore["AdbcConfig"]):
|
|
|
1308
1342
|
return self._delete_entries_older_than(days, app_name, scope)
|
|
1309
1343
|
|
|
1310
1344
|
def _detect_dialect(self) -> str:
|
|
1311
|
-
driver_name = self._config.connection_config.get("driver_name", "")
|
|
1312
|
-
if
|
|
1345
|
+
driver_name = self._config.connection_config.get("driver_name", "")
|
|
1346
|
+
if (
|
|
1347
|
+
isinstance(driver_name, str)
|
|
1348
|
+
and driver_name
|
|
1349
|
+
and driver_kind_from_driver_name(driver_name) is None
|
|
1350
|
+
and not is_shared_object_driver(driver_name)
|
|
1351
|
+
):
|
|
1352
|
+
logger.warning("Unknown ADBC driver: %s. Using generic SQL dialect.", driver_name)
|
|
1353
|
+
return DIALECT_GENERIC
|
|
1354
|
+
|
|
1355
|
+
resolved = resolve_dialect_from_config(self._config.connection_config)
|
|
1356
|
+
if resolved == "postgres":
|
|
1313
1357
|
return DIALECT_POSTGRESQL
|
|
1314
|
-
if "sqlite"
|
|
1358
|
+
if resolved == "sqlite":
|
|
1315
1359
|
return DIALECT_SQLITE
|
|
1316
|
-
if "duckdb"
|
|
1360
|
+
if resolved == "duckdb":
|
|
1317
1361
|
return DIALECT_DUCKDB
|
|
1318
|
-
if "snowflake"
|
|
1362
|
+
if resolved == "snowflake":
|
|
1319
1363
|
return DIALECT_SNOWFLAKE
|
|
1320
1364
|
logger.warning("Unknown ADBC driver: %s. Using generic SQL dialect.", driver_name)
|
|
1321
1365
|
return DIALECT_GENERIC
|
|
1322
1366
|
|
|
1367
|
+
def _format_sql(self, sql: str) -> str:
|
|
1368
|
+
"""Return SQL with dialect-appropriate positional placeholders."""
|
|
1369
|
+
if self._dialect != DIALECT_POSTGRESQL:
|
|
1370
|
+
return sql
|
|
1371
|
+
return _postgresql_store_sql(sql)
|
|
1372
|
+
|
|
1373
|
+
def _execute(self, cursor: Any, sql: str, params: "tuple[Any, ...] | list[Any]") -> Any:
|
|
1374
|
+
"""Execute parameterized SQL using the current ADBC dialect's placeholder style."""
|
|
1375
|
+
return cursor.execute(self._format_sql(sql), params)
|
|
1376
|
+
|
|
1377
|
+
def _json_placeholder(self) -> str:
|
|
1378
|
+
if self._dialect == DIALECT_POSTGRESQL:
|
|
1379
|
+
return "?::jsonb"
|
|
1380
|
+
return "?"
|
|
1381
|
+
|
|
1323
1382
|
def _serialize_json_field(self, value: Any) -> "str | None":
|
|
1324
1383
|
if value is None:
|
|
1325
1384
|
return None
|
|
@@ -1484,6 +1543,7 @@ class AdbcADKMemoryStore(BaseSyncADKMemoryStore["AdbcConfig"]):
|
|
|
1484
1543
|
|
|
1485
1544
|
inserted_count = 0
|
|
1486
1545
|
use_returning = self._dialect in {DIALECT_SQLITE, DIALECT_POSTGRESQL, DIALECT_DUCKDB}
|
|
1546
|
+
json_placeholder = self._json_placeholder()
|
|
1487
1547
|
|
|
1488
1548
|
if self._owner_id_column_name:
|
|
1489
1549
|
if use_returning:
|
|
@@ -1493,7 +1553,7 @@ class AdbcADKMemoryStore(BaseSyncADKMemoryStore["AdbcConfig"]):
|
|
|
1493
1553
|
{self._owner_id_column_name}, timestamp, content_json, content_text,
|
|
1494
1554
|
metadata_json, inserted_at
|
|
1495
1555
|
) VALUES (
|
|
1496
|
-
?, ?, ?, ?, ?, ?, ?, ?, ?,
|
|
1556
|
+
?, ?, ?, ?, ?, ?, ?, ?, ?, {json_placeholder}, ?, {json_placeholder}, ?
|
|
1497
1557
|
) ON CONFLICT(event_id) DO NOTHING RETURNING 1
|
|
1498
1558
|
"""
|
|
1499
1559
|
else:
|
|
@@ -1503,7 +1563,7 @@ class AdbcADKMemoryStore(BaseSyncADKMemoryStore["AdbcConfig"]):
|
|
|
1503
1563
|
{self._owner_id_column_name}, timestamp, content_json, content_text,
|
|
1504
1564
|
metadata_json, inserted_at
|
|
1505
1565
|
) VALUES (
|
|
1506
|
-
?, ?, ?, ?, ?, ?, ?, ?, ?,
|
|
1566
|
+
?, ?, ?, ?, ?, ?, ?, ?, ?, {json_placeholder}, ?, {json_placeholder}, ?
|
|
1507
1567
|
)
|
|
1508
1568
|
"""
|
|
1509
1569
|
elif use_returning:
|
|
@@ -1512,7 +1572,7 @@ class AdbcADKMemoryStore(BaseSyncADKMemoryStore["AdbcConfig"]):
|
|
|
1512
1572
|
id, session_id, app_name, user_id, scope, event_id, author,
|
|
1513
1573
|
timestamp, content_json, content_text, metadata_json, inserted_at
|
|
1514
1574
|
) VALUES (
|
|
1515
|
-
?, ?, ?, ?, ?, ?, ?, ?,
|
|
1575
|
+
?, ?, ?, ?, ?, ?, ?, ?, {json_placeholder}, ?, {json_placeholder}, ?
|
|
1516
1576
|
) ON CONFLICT(event_id) DO NOTHING RETURNING 1
|
|
1517
1577
|
"""
|
|
1518
1578
|
else:
|
|
@@ -1521,7 +1581,7 @@ class AdbcADKMemoryStore(BaseSyncADKMemoryStore["AdbcConfig"]):
|
|
|
1521
1581
|
id, session_id, app_name, user_id, scope, event_id, author,
|
|
1522
1582
|
timestamp, content_json, content_text, metadata_json, inserted_at
|
|
1523
1583
|
) VALUES (
|
|
1524
|
-
?, ?, ?, ?, ?, ?, ?, ?,
|
|
1584
|
+
?, ?, ?, ?, ?, ?, ?, ?, {json_placeholder}, ?, {json_placeholder}, ?
|
|
1525
1585
|
)
|
|
1526
1586
|
"""
|
|
1527
1587
|
|
|
@@ -1530,7 +1590,7 @@ class AdbcADKMemoryStore(BaseSyncADKMemoryStore["AdbcConfig"]):
|
|
|
1530
1590
|
try:
|
|
1531
1591
|
for entry in entries:
|
|
1532
1592
|
content_json = self._serialize_json_field(entry["content_json"])
|
|
1533
|
-
metadata_json = self._serialize_json_field(entry
|
|
1593
|
+
metadata_json = self._serialize_json_field(entry.get("metadata_json"))
|
|
1534
1594
|
params: tuple[Any, ...]
|
|
1535
1595
|
if self._owner_id_column_name:
|
|
1536
1596
|
params = (
|
|
@@ -1540,7 +1600,7 @@ class AdbcADKMemoryStore(BaseSyncADKMemoryStore["AdbcConfig"]):
|
|
|
1540
1600
|
entry["user_id"],
|
|
1541
1601
|
entry.get("scope", "user"),
|
|
1542
1602
|
entry["event_id"],
|
|
1543
|
-
entry
|
|
1603
|
+
entry.get("author"),
|
|
1544
1604
|
owner_id,
|
|
1545
1605
|
self._encode_timestamp(entry["timestamp"]),
|
|
1546
1606
|
content_json,
|
|
@@ -1556,7 +1616,7 @@ class AdbcADKMemoryStore(BaseSyncADKMemoryStore["AdbcConfig"]):
|
|
|
1556
1616
|
entry["user_id"],
|
|
1557
1617
|
entry.get("scope", "user"),
|
|
1558
1618
|
entry["event_id"],
|
|
1559
|
-
entry
|
|
1619
|
+
entry.get("author"),
|
|
1560
1620
|
self._encode_timestamp(entry["timestamp"]),
|
|
1561
1621
|
content_json,
|
|
1562
1622
|
entry["content_text"],
|
|
@@ -1564,12 +1624,12 @@ class AdbcADKMemoryStore(BaseSyncADKMemoryStore["AdbcConfig"]):
|
|
|
1564
1624
|
self._encode_timestamp(entry["inserted_at"]),
|
|
1565
1625
|
)
|
|
1566
1626
|
if use_returning:
|
|
1567
|
-
|
|
1627
|
+
self._execute(cursor, sql, params)
|
|
1568
1628
|
if cursor.fetchone():
|
|
1569
1629
|
inserted_count += 1
|
|
1570
1630
|
else:
|
|
1571
1631
|
try:
|
|
1572
|
-
|
|
1632
|
+
self._execute(cursor, sql, params)
|
|
1573
1633
|
inserted_count += 1
|
|
1574
1634
|
except Exception as exc:
|
|
1575
1635
|
exc_str = str(exc).lower()
|
|
@@ -1594,6 +1654,9 @@ class AdbcADKMemoryStore(BaseSyncADKMemoryStore["AdbcConfig"]):
|
|
|
1594
1654
|
msg = "Memory store is disabled"
|
|
1595
1655
|
raise RuntimeError(msg)
|
|
1596
1656
|
|
|
1657
|
+
if not query or not query.strip():
|
|
1658
|
+
return []
|
|
1659
|
+
|
|
1597
1660
|
if self._use_fts:
|
|
1598
1661
|
logger.warning("ADBC memory store does not support FTS, falling back to simple search")
|
|
1599
1662
|
|
|
@@ -1615,7 +1678,7 @@ class AdbcADKMemoryStore(BaseSyncADKMemoryStore["AdbcConfig"]):
|
|
|
1615
1678
|
with self._config.provide_connection() as conn:
|
|
1616
1679
|
cursor = conn.cursor()
|
|
1617
1680
|
try:
|
|
1618
|
-
|
|
1681
|
+
self._execute(cursor, sql, (*scope_params, pattern, effective_limit))
|
|
1619
1682
|
rows = cursor.fetchall()
|
|
1620
1683
|
finally:
|
|
1621
1684
|
cursor.close()
|
|
@@ -1628,6 +1691,10 @@ class AdbcADKMemoryStore(BaseSyncADKMemoryStore["AdbcConfig"]):
|
|
|
1628
1691
|
return self._rows_to_records(rows)
|
|
1629
1692
|
|
|
1630
1693
|
def _delete_entries_by_session(self, session_id: str) -> int:
|
|
1694
|
+
if not self._enabled:
|
|
1695
|
+
msg = "Memory store is disabled"
|
|
1696
|
+
raise RuntimeError(msg)
|
|
1697
|
+
|
|
1631
1698
|
use_returning = self._dialect in {DIALECT_SQLITE, DIALECT_POSTGRESQL, DIALECT_DUCKDB}
|
|
1632
1699
|
if use_returning:
|
|
1633
1700
|
sql = f"DELETE FROM {self._memory_table} WHERE session_id = ? RETURNING 1"
|
|
@@ -1636,7 +1703,7 @@ class AdbcADKMemoryStore(BaseSyncADKMemoryStore["AdbcConfig"]):
|
|
|
1636
1703
|
with self._config.provide_connection() as conn:
|
|
1637
1704
|
cursor = conn.cursor()
|
|
1638
1705
|
try:
|
|
1639
|
-
|
|
1706
|
+
self._execute(cursor, sql, (session_id,))
|
|
1640
1707
|
if use_returning:
|
|
1641
1708
|
deleted_rows = cursor.fetchall()
|
|
1642
1709
|
conn.commit()
|
|
@@ -1647,6 +1714,10 @@ class AdbcADKMemoryStore(BaseSyncADKMemoryStore["AdbcConfig"]):
|
|
|
1647
1714
|
cursor.close()
|
|
1648
1715
|
|
|
1649
1716
|
def _delete_entries_older_than(self, days: int, app_name: "str | None" = None, scope: "str | None" = None) -> int:
|
|
1717
|
+
if not self._enabled:
|
|
1718
|
+
msg = "Memory store is disabled"
|
|
1719
|
+
raise RuntimeError(msg)
|
|
1720
|
+
|
|
1650
1721
|
cutoff = self._encode_timestamp(datetime.now(timezone.utc) - timedelta(days=days))
|
|
1651
1722
|
use_returning = self._dialect in {DIALECT_SQLITE, DIALECT_POSTGRESQL, DIALECT_DUCKDB}
|
|
1652
1723
|
clauses = ["inserted_at < ?"]
|
|
@@ -1665,7 +1736,7 @@ class AdbcADKMemoryStore(BaseSyncADKMemoryStore["AdbcConfig"]):
|
|
|
1665
1736
|
with self._config.provide_connection() as conn:
|
|
1666
1737
|
cursor = conn.cursor()
|
|
1667
1738
|
try:
|
|
1668
|
-
|
|
1739
|
+
self._execute(cursor, sql, tuple(params))
|
|
1669
1740
|
if use_returning:
|
|
1670
1741
|
deleted_rows = cursor.fetchall()
|
|
1671
1742
|
conn.commit()
|
sqlspec/adapters/adbc/config.py
CHANGED
|
@@ -76,8 +76,15 @@ class AdbcConnectionParams(TypedDict):
|
|
|
76
76
|
role: NotRequired[str]
|
|
77
77
|
authorization_header: NotRequired[str]
|
|
78
78
|
grpc_options: NotRequired[dict[str, Any]]
|
|
79
|
+
grpc_max_message_size: NotRequired[int]
|
|
80
|
+
fetch_timeout: NotRequired[float]
|
|
79
81
|
gizmosql_backend: NotRequired[str]
|
|
80
82
|
tls_skip_verify: NotRequired[bool]
|
|
83
|
+
tls_root_certs: NotRequired[str]
|
|
84
|
+
mtls_cert_chain: NotRequired[str]
|
|
85
|
+
mtls_private_key: NotRequired[str]
|
|
86
|
+
with_cookie_middleware: NotRequired[bool]
|
|
87
|
+
headers: NotRequired[dict[str, str]]
|
|
81
88
|
extra: NotRequired[dict[str, Any]]
|
|
82
89
|
|
|
83
90
|
|
sqlspec/adapters/adbc/core.py
CHANGED
|
@@ -11,6 +11,7 @@ import sqlglot
|
|
|
11
11
|
from sqlglot import exp
|
|
12
12
|
from sqlglot.errors import ParseError
|
|
13
13
|
|
|
14
|
+
import sqlspec.adapters.adbc._typing as _adbc_typing
|
|
14
15
|
from sqlspec.adapters.adbc.type_converter import get_adbc_type_converter
|
|
15
16
|
from sqlspec.core import (
|
|
16
17
|
DriverParameterProfile,
|
|
@@ -181,6 +182,14 @@ _DRIVER_MANAGER_CONNECT: Final[str] = "adbc_driver_manager.dbapi.connect"
|
|
|
181
182
|
_FLIGHTSQL_DB_KWARGS_FIELDS: "tuple[str, ...]" = ("username", "password")
|
|
182
183
|
_FLIGHTSQL_TLS_SKIP_VERIFY_KEY: Final[str] = "adbc.flight.sql.client_option.tls_skip_verify"
|
|
183
184
|
_FLIGHTSQL_AUTHORIZATION_HEADER_KEY: Final[str] = "adbc.flight.sql.authorization_header"
|
|
185
|
+
_FLIGHTSQL_WITH_MAX_MSG_SIZE_KEY: Final[str] = "adbc.flight.sql.client_option.with_max_msg_size"
|
|
186
|
+
_FLIGHTSQL_TIMEOUT_QUERY_KEY: Final[str] = "adbc.flight.sql.rpc.timeout_seconds.query"
|
|
187
|
+
_FLIGHTSQL_TIMEOUT_FETCH_KEY: Final[str] = "adbc.flight.sql.rpc.timeout_seconds.fetch"
|
|
188
|
+
_FLIGHTSQL_TLS_ROOT_CERTS_KEY: Final[str] = "adbc.flight.sql.client_option.tls_root_certs"
|
|
189
|
+
_FLIGHTSQL_MTLS_CERT_CHAIN_KEY: Final[str] = "adbc.flight.sql.client_option.mtls_cert_chain"
|
|
190
|
+
_FLIGHTSQL_MTLS_PRIVATE_KEY_KEY: Final[str] = "adbc.flight.sql.client_option.mtls_private_key"
|
|
191
|
+
_FLIGHTSQL_WITH_COOKIE_MIDDLEWARE_KEY: Final[str] = "adbc.flight.sql.rpc.with_cookie_middleware"
|
|
192
|
+
_FLIGHTSQL_RPC_CALL_HEADER_PREFIX: Final[str] = "adbc.flight.sql.rpc.call_header."
|
|
184
193
|
_SQLSTATE_CLASS_CODE_LEN = 2
|
|
185
194
|
_SQLSTATE_DESCRIPTIONS: dict[str, str] = {
|
|
186
195
|
"23": "integrity constraint violation",
|
|
@@ -685,7 +694,6 @@ def create_mapped_exception(error: Any, *, logger: Any | None = None) -> SQLSpec
|
|
|
685
694
|
sqlstate = sqlstate_attr if sqlstate_attr is not None else None
|
|
686
695
|
|
|
687
696
|
if sqlstate:
|
|
688
|
-
# Use centralized SQLSTATE mapping for specific codes
|
|
689
697
|
if sqlstate == "23505":
|
|
690
698
|
return _create_adbc_error(error, UniqueViolationError, "unique constraint violation")
|
|
691
699
|
if sqlstate == "23503":
|
|
@@ -695,7 +703,6 @@ def create_mapped_exception(error: Any, *, logger: Any | None = None) -> SQLSpec
|
|
|
695
703
|
if sqlstate == "23514":
|
|
696
704
|
return _create_adbc_error(error, CheckViolationError, "check constraint violation")
|
|
697
705
|
|
|
698
|
-
# Deadlock and serialization errors
|
|
699
706
|
if sqlstate == "40P01":
|
|
700
707
|
return _create_adbc_error(error, DeadlockError, "deadlock detected")
|
|
701
708
|
if sqlstate == "40001":
|
|
@@ -705,25 +712,20 @@ def create_mapped_exception(error: Any, *, logger: Any | None = None) -> SQLSpec
|
|
|
705
712
|
termination_class = _classify_timeout_or_cancellation(str(error)) or OperationalError
|
|
706
713
|
return _create_adbc_error(error, termination_class, "query terminated")
|
|
707
714
|
|
|
708
|
-
# Permission errors
|
|
709
715
|
if sqlstate == "42501":
|
|
710
716
|
return _create_adbc_error(error, PermissionDeniedError, "insufficient privilege")
|
|
711
717
|
if sqlstate == "28000":
|
|
712
718
|
return _create_adbc_error(error, PermissionDeniedError, "invalid authorization")
|
|
713
719
|
|
|
714
|
-
# Use centralized mapping for SQLSTATE class prefixes
|
|
715
720
|
exc_class = map_sqlstate_to_exception(sqlstate)
|
|
716
721
|
if exc_class is not None and exc_class is not SQLSpecError:
|
|
717
722
|
description = _get_sqlstate_description(sqlstate)
|
|
718
723
|
return _create_adbc_error(error, exc_class, description)
|
|
719
724
|
|
|
720
|
-
# Fallback for unmapped SQLSTATE codes
|
|
721
725
|
return _create_adbc_error(error, SQLSpecError, "database error")
|
|
722
726
|
|
|
723
|
-
# Message-based fallback when no SQLSTATE is available
|
|
724
727
|
error_msg = str(error).lower()
|
|
725
728
|
|
|
726
|
-
# Constraint violations
|
|
727
729
|
if "unique" in error_msg or "duplicate" in error_msg:
|
|
728
730
|
return _create_adbc_error(error, UniqueViolationError, "unique constraint violation")
|
|
729
731
|
if "foreign key" in error_msg:
|
|
@@ -735,7 +737,6 @@ def create_mapped_exception(error: Any, *, logger: Any | None = None) -> SQLSpec
|
|
|
735
737
|
if "constraint" in error_msg:
|
|
736
738
|
return _create_adbc_error(error, IntegrityError, "integrity constraint violation")
|
|
737
739
|
|
|
738
|
-
# Deadlock/lock patterns
|
|
739
740
|
if "deadlock" in error_msg:
|
|
740
741
|
return _create_adbc_error(error, DeadlockError, "deadlock detected")
|
|
741
742
|
if "serialization" in error_msg or "concurrent update" in error_msg:
|
|
@@ -744,15 +745,12 @@ def create_mapped_exception(error: Any, *, logger: Any | None = None) -> SQLSpec
|
|
|
744
745
|
if message_class := _classify_timeout_or_cancellation(error_msg):
|
|
745
746
|
return _create_adbc_error(error, message_class, "query terminated")
|
|
746
747
|
|
|
747
|
-
# Permission patterns
|
|
748
748
|
if "permission" in error_msg or "denied" in error_msg or "unauthorized" in error_msg:
|
|
749
749
|
return _create_adbc_error(error, PermissionDeniedError, "permission denied")
|
|
750
750
|
|
|
751
|
-
# Syntax errors
|
|
752
751
|
if "syntax" in error_msg:
|
|
753
752
|
return _create_adbc_error(error, SQLParsingError, "SQL parsing error")
|
|
754
753
|
|
|
755
|
-
# Connection errors
|
|
756
754
|
if "connection" in error_msg or "connect" in error_msg:
|
|
757
755
|
return _create_adbc_error(error, DatabaseConnectionError, "connection error")
|
|
758
756
|
|
|
@@ -1154,7 +1152,7 @@ def _rewrite_postgres_uuid_placeholders(
|
|
|
1154
1152
|
|
|
1155
1153
|
for expression in expressions:
|
|
1156
1154
|
expression.transform(wrap_parameter, copy=False)
|
|
1157
|
-
rewritten = "; ".join(expression.sql(dialect=dialect) for expression in expressions)
|
|
1155
|
+
rewritten = "; ".join(expression.sql(dialect=dialect, copy=False) for expression in expressions)
|
|
1158
1156
|
return rewritten, effective_scalars, effective_arrays
|
|
1159
1157
|
|
|
1160
1158
|
|
|
@@ -1388,10 +1386,10 @@ def _prepare_batch_with_casts(
|
|
|
1388
1386
|
|
|
1389
1387
|
def _resolve_flightsql_db_kwargs_keys() -> "tuple[str, str]":
|
|
1390
1388
|
try:
|
|
1391
|
-
|
|
1389
|
+
database_options = _adbc_typing.AdbcFlightSqlDatabaseOptions
|
|
1392
1390
|
except ImportError:
|
|
1393
1391
|
return _FLIGHTSQL_TLS_SKIP_VERIFY_KEY, _FLIGHTSQL_AUTHORIZATION_HEADER_KEY
|
|
1394
|
-
return
|
|
1392
|
+
return database_options.TLS_SKIP_VERIFY.value, database_options.AUTHORIZATION_HEADER.value
|
|
1395
1393
|
|
|
1396
1394
|
|
|
1397
1395
|
def _lift_flightsql_db_kwargs(config: "dict[str, Any]") -> None:
|
|
@@ -1412,6 +1410,36 @@ def _lift_flightsql_db_kwargs(config: "dict[str, Any]") -> None:
|
|
|
1412
1410
|
if "authorization_header" in config:
|
|
1413
1411
|
db_kwargs_dict.setdefault(authorization_header_key, config.pop("authorization_header"))
|
|
1414
1412
|
|
|
1413
|
+
if "grpc_max_message_size" in config:
|
|
1414
|
+
db_kwargs_dict.setdefault(_FLIGHTSQL_WITH_MAX_MSG_SIZE_KEY, str(config.pop("grpc_max_message_size")))
|
|
1415
|
+
|
|
1416
|
+
if "query_timeout" in config:
|
|
1417
|
+
db_kwargs_dict.setdefault(_FLIGHTSQL_TIMEOUT_QUERY_KEY, str(config.pop("query_timeout")))
|
|
1418
|
+
|
|
1419
|
+
if "fetch_timeout" in config:
|
|
1420
|
+
db_kwargs_dict.setdefault(_FLIGHTSQL_TIMEOUT_FETCH_KEY, str(config.pop("fetch_timeout")))
|
|
1421
|
+
|
|
1422
|
+
if "tls_root_certs" in config:
|
|
1423
|
+
db_kwargs_dict.setdefault(_FLIGHTSQL_TLS_ROOT_CERTS_KEY, str(config.pop("tls_root_certs")))
|
|
1424
|
+
|
|
1425
|
+
if "mtls_cert_chain" in config:
|
|
1426
|
+
db_kwargs_dict.setdefault(_FLIGHTSQL_MTLS_CERT_CHAIN_KEY, str(config.pop("mtls_cert_chain")))
|
|
1427
|
+
|
|
1428
|
+
if "mtls_private_key" in config:
|
|
1429
|
+
db_kwargs_dict.setdefault(_FLIGHTSQL_MTLS_PRIVATE_KEY_KEY, str(config.pop("mtls_private_key")))
|
|
1430
|
+
|
|
1431
|
+
if "with_cookie_middleware" in config:
|
|
1432
|
+
val = config.pop("with_cookie_middleware")
|
|
1433
|
+
db_kwargs_dict.setdefault(
|
|
1434
|
+
_FLIGHTSQL_WITH_COOKIE_MIDDLEWARE_KEY, str(val).lower() if isinstance(val, bool) else str(val)
|
|
1435
|
+
)
|
|
1436
|
+
|
|
1437
|
+
if "headers" in config:
|
|
1438
|
+
headers = config.pop("headers")
|
|
1439
|
+
if isinstance(headers, dict):
|
|
1440
|
+
for hdr_key, hdr_val in headers.items():
|
|
1441
|
+
db_kwargs_dict.setdefault(f"{_FLIGHTSQL_RPC_CALL_HEADER_PREFIX}{hdr_key}", str(hdr_val))
|
|
1442
|
+
|
|
1415
1443
|
config.pop("gizmosql_backend", None)
|
|
1416
1444
|
if db_kwargs_dict:
|
|
1417
1445
|
config["db_kwargs"] = db_kwargs_dict
|
sqlspec/adapters/adbc/driver.py
CHANGED
|
@@ -257,7 +257,6 @@ class AdbcDriver(SyncDriverAdapterBase):
|
|
|
257
257
|
|
|
258
258
|
try:
|
|
259
259
|
if not prepared_parameters:
|
|
260
|
-
cursor._rowcount = 0 # pyright: ignore[reportPrivateUsage]
|
|
261
260
|
row_count = 0
|
|
262
261
|
elif isinstance(prepared_parameters, (list, tuple)) and prepared_parameters:
|
|
263
262
|
parameter_count = len(prepared_parameters)
|
|
@@ -496,7 +495,8 @@ class AdbcDriver(SyncDriverAdapterBase):
|
|
|
496
495
|
cursor = cursor_manager.__enter__()
|
|
497
496
|
try:
|
|
498
497
|
sql, driver_params = self._compiled_sql(prepared_statement, config)
|
|
499
|
-
|
|
498
|
+
execute_parameters = normalize_postgres_empty_parameters(self._dialect_name, driver_params)
|
|
499
|
+
cursor.execute(sql, parameters=execute_parameters)
|
|
500
500
|
fetch_record_batch = getattr(cursor, "fetch_record_batch", None)
|
|
501
501
|
if fetch_record_batch is None:
|
|
502
502
|
arrow_table = cursor.fetch_arrow_table()
|
|
@@ -512,6 +512,7 @@ class AdbcDriver(SyncDriverAdapterBase):
|
|
|
512
512
|
else:
|
|
513
513
|
reader = fetch_record_batch()
|
|
514
514
|
except Exception:
|
|
515
|
+
handle_postgres_rollback(self._dialect_name, cursor, logger)
|
|
515
516
|
cursor_manager.__exit__(None, None, None)
|
|
516
517
|
cursor = None
|
|
517
518
|
raise
|
|
@@ -537,8 +538,13 @@ class AdbcDriver(SyncDriverAdapterBase):
|
|
|
537
538
|
raise DatabaseConnectionError(msg)
|
|
538
539
|
|
|
539
540
|
sql, driver_params = self._compiled_sql(prepared_statement, config)
|
|
540
|
-
|
|
541
|
-
|
|
541
|
+
execute_parameters = normalize_postgres_empty_parameters(self._dialect_name, driver_params)
|
|
542
|
+
try:
|
|
543
|
+
cursor.execute(sql, parameters=execute_parameters)
|
|
544
|
+
arrow_table = cursor.fetch_arrow_table()
|
|
545
|
+
except Exception:
|
|
546
|
+
handle_postgres_rollback(self._dialect_name, cursor, logger)
|
|
547
|
+
raise
|
|
542
548
|
|
|
543
549
|
arrow_result = build_arrow_result_from_table(
|
|
544
550
|
prepared_statement,
|
|
@@ -579,12 +579,12 @@ class AiomysqlADKMemoryStore(BaseAsyncADKMemoryStore["AiomysqlConfig"]):
|
|
|
579
579
|
entry["user_id"],
|
|
580
580
|
entry.get("scope", "user"),
|
|
581
581
|
entry["event_id"],
|
|
582
|
-
entry
|
|
582
|
+
entry.get("author"),
|
|
583
583
|
owner_id,
|
|
584
584
|
entry["timestamp"],
|
|
585
585
|
to_json(entry["content_json"]),
|
|
586
586
|
entry["content_text"],
|
|
587
|
-
to_json(entry["metadata_json"]),
|
|
587
|
+
to_json(entry["metadata_json"]) if entry.get("metadata_json") is not None else None,
|
|
588
588
|
entry["inserted_at"],
|
|
589
589
|
)
|
|
590
590
|
else:
|
|
@@ -595,11 +595,11 @@ class AiomysqlADKMemoryStore(BaseAsyncADKMemoryStore["AiomysqlConfig"]):
|
|
|
595
595
|
entry["user_id"],
|
|
596
596
|
entry.get("scope", "user"),
|
|
597
597
|
entry["event_id"],
|
|
598
|
-
entry
|
|
598
|
+
entry.get("author"),
|
|
599
599
|
entry["timestamp"],
|
|
600
600
|
to_json(entry["content_json"]),
|
|
601
601
|
entry["content_text"],
|
|
602
|
-
to_json(entry["metadata_json"]),
|
|
602
|
+
to_json(entry["metadata_json"]) if entry.get("metadata_json") is not None else None,
|
|
603
603
|
entry["inserted_at"],
|
|
604
604
|
)
|
|
605
605
|
await cursor.execute(sql, params)
|
|
@@ -655,6 +655,9 @@ class AiomysqlADKMemoryStore(BaseAsyncADKMemoryStore["AiomysqlConfig"]):
|
|
|
655
655
|
records: list[StoredMemory] = []
|
|
656
656
|
for row in rows:
|
|
657
657
|
rec = cast("StoredMemory", dict(zip(columns, row, strict=False)))
|
|
658
|
+
rec["content_json"] = _json_dict(rec.get("content_json"))
|
|
659
|
+
metadata_val = rec.get("metadata_json")
|
|
660
|
+
rec["metadata_json"] = _json_dict(metadata_val) if metadata_val is not None else None
|
|
658
661
|
rec["embedding"] = None
|
|
659
662
|
records.append(rec)
|
|
660
663
|
return records
|