sqlspec 0.47.0__cp314-cp314-win_amd64.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.
- f68e0789eb443ecb1c2c__mypyc.cp314-win_amd64.pyd +0 -0
- sqlspec/__init__.py +167 -0
- sqlspec/__main__.py +12 -0
- sqlspec/__metadata__.py +14 -0
- sqlspec/_typing.py +714 -0
- sqlspec/adapters/__init__.py +0 -0
- sqlspec/adapters/adbc/__init__.py +13 -0
- sqlspec/adapters/adbc/_typing.py +106 -0
- sqlspec/adapters/adbc/adk/__init__.py +5 -0
- sqlspec/adapters/adbc/adk/store.py +1280 -0
- sqlspec/adapters/adbc/config.py +378 -0
- sqlspec/adapters/adbc/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/adbc/core.py +922 -0
- sqlspec/adapters/adbc/data_dictionary.py +339 -0
- sqlspec/adapters/adbc/driver.py +534 -0
- sqlspec/adapters/adbc/events/__init__.py +5 -0
- sqlspec/adapters/adbc/events/store.py +285 -0
- sqlspec/adapters/adbc/litestar/__init__.py +5 -0
- sqlspec/adapters/adbc/litestar/store.py +534 -0
- sqlspec/adapters/adbc/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/adbc/type_converter.py +142 -0
- sqlspec/adapters/aiomysql/__init__.py +21 -0
- sqlspec/adapters/aiomysql/_typing.py +137 -0
- sqlspec/adapters/aiomysql/adk/__init__.py +5 -0
- sqlspec/adapters/aiomysql/adk/store.py +678 -0
- sqlspec/adapters/aiomysql/config.py +305 -0
- sqlspec/adapters/aiomysql/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/aiomysql/core.py +536 -0
- sqlspec/adapters/aiomysql/data_dictionary.py +121 -0
- sqlspec/adapters/aiomysql/driver.py +386 -0
- sqlspec/adapters/aiomysql/events/__init__.py +5 -0
- sqlspec/adapters/aiomysql/events/store.py +104 -0
- sqlspec/adapters/aiomysql/litestar/__init__.py +5 -0
- sqlspec/adapters/aiomysql/litestar/store.py +314 -0
- sqlspec/adapters/aiosqlite/__init__.py +26 -0
- sqlspec/adapters/aiosqlite/_typing.py +109 -0
- sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/adk/store.py +829 -0
- sqlspec/adapters/aiosqlite/config.py +315 -0
- sqlspec/adapters/aiosqlite/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/aiosqlite/core.py +315 -0
- sqlspec/adapters/aiosqlite/data_dictionary.py +202 -0
- sqlspec/adapters/aiosqlite/driver.py +311 -0
- sqlspec/adapters/aiosqlite/events/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/events/store.py +20 -0
- sqlspec/adapters/aiosqlite/litestar/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/litestar/store.py +279 -0
- sqlspec/adapters/aiosqlite/pool.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/aiosqlite/pool.py +734 -0
- sqlspec/adapters/asyncmy/__init__.py +21 -0
- sqlspec/adapters/asyncmy/_typing.py +113 -0
- sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
- sqlspec/adapters/asyncmy/adk/store.py +644 -0
- sqlspec/adapters/asyncmy/config.py +307 -0
- sqlspec/adapters/asyncmy/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/asyncmy/core.py +538 -0
- sqlspec/adapters/asyncmy/data_dictionary.py +122 -0
- sqlspec/adapters/asyncmy/driver.py +391 -0
- sqlspec/adapters/asyncmy/events/__init__.py +5 -0
- sqlspec/adapters/asyncmy/events/store.py +104 -0
- sqlspec/adapters/asyncmy/litestar/__init__.py +5 -0
- sqlspec/adapters/asyncmy/litestar/store.py +296 -0
- sqlspec/adapters/asyncpg/__init__.py +26 -0
- sqlspec/adapters/asyncpg/_typing.py +103 -0
- sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
- sqlspec/adapters/asyncpg/adk/store.py +483 -0
- sqlspec/adapters/asyncpg/config.py +575 -0
- sqlspec/adapters/asyncpg/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/asyncpg/core.py +480 -0
- sqlspec/adapters/asyncpg/data_dictionary.py +157 -0
- sqlspec/adapters/asyncpg/driver.py +487 -0
- sqlspec/adapters/asyncpg/events/__init__.py +6 -0
- sqlspec/adapters/asyncpg/events/_hub.py +181 -0
- sqlspec/adapters/asyncpg/events/backend.py +210 -0
- sqlspec/adapters/asyncpg/events/store.py +40 -0
- sqlspec/adapters/asyncpg/litestar/__init__.py +5 -0
- sqlspec/adapters/asyncpg/litestar/store.py +251 -0
- sqlspec/adapters/bigquery/__init__.py +15 -0
- sqlspec/adapters/bigquery/_typing.py +108 -0
- sqlspec/adapters/bigquery/config.py +362 -0
- sqlspec/adapters/bigquery/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/bigquery/core.py +768 -0
- sqlspec/adapters/bigquery/data_dictionary.py +120 -0
- sqlspec/adapters/bigquery/driver.py +542 -0
- sqlspec/adapters/bigquery/events/__init__.py +5 -0
- sqlspec/adapters/bigquery/events/store.py +139 -0
- sqlspec/adapters/bigquery/litestar/__init__.py +5 -0
- sqlspec/adapters/bigquery/litestar/store.py +325 -0
- sqlspec/adapters/bigquery/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/bigquery/type_converter.py +107 -0
- sqlspec/adapters/cockroach_asyncpg/__init__.py +26 -0
- sqlspec/adapters/cockroach_asyncpg/_typing.py +73 -0
- sqlspec/adapters/cockroach_asyncpg/adk/__init__.py +3 -0
- sqlspec/adapters/cockroach_asyncpg/adk/store.py +465 -0
- sqlspec/adapters/cockroach_asyncpg/config.py +248 -0
- sqlspec/adapters/cockroach_asyncpg/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/cockroach_asyncpg/core.py +55 -0
- sqlspec/adapters/cockroach_asyncpg/data_dictionary.py +110 -0
- sqlspec/adapters/cockroach_asyncpg/driver.py +142 -0
- sqlspec/adapters/cockroach_asyncpg/events/__init__.py +3 -0
- sqlspec/adapters/cockroach_asyncpg/events/store.py +20 -0
- sqlspec/adapters/cockroach_asyncpg/litestar/__init__.py +3 -0
- sqlspec/adapters/cockroach_asyncpg/litestar/store.py +142 -0
- sqlspec/adapters/cockroach_psycopg/__init__.py +39 -0
- sqlspec/adapters/cockroach_psycopg/_typing.py +137 -0
- sqlspec/adapters/cockroach_psycopg/adk/__init__.py +13 -0
- sqlspec/adapters/cockroach_psycopg/adk/store.py +1039 -0
- sqlspec/adapters/cockroach_psycopg/config.py +511 -0
- sqlspec/adapters/cockroach_psycopg/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/cockroach_psycopg/core.py +63 -0
- sqlspec/adapters/cockroach_psycopg/data_dictionary.py +220 -0
- sqlspec/adapters/cockroach_psycopg/driver.py +273 -0
- sqlspec/adapters/cockroach_psycopg/events/__init__.py +6 -0
- sqlspec/adapters/cockroach_psycopg/events/store.py +34 -0
- sqlspec/adapters/cockroach_psycopg/litestar/__init__.py +3 -0
- sqlspec/adapters/cockroach_psycopg/litestar/store.py +327 -0
- sqlspec/adapters/duckdb/__init__.py +29 -0
- sqlspec/adapters/duckdb/_typing.py +104 -0
- sqlspec/adapters/duckdb/adk/__init__.py +14 -0
- sqlspec/adapters/duckdb/adk/store.py +935 -0
- sqlspec/adapters/duckdb/config.py +386 -0
- sqlspec/adapters/duckdb/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/duckdb/core.py +332 -0
- sqlspec/adapters/duckdb/data_dictionary.py +140 -0
- sqlspec/adapters/duckdb/driver.py +426 -0
- sqlspec/adapters/duckdb/events/__init__.py +5 -0
- sqlspec/adapters/duckdb/events/store.py +57 -0
- sqlspec/adapters/duckdb/litestar/__init__.py +5 -0
- sqlspec/adapters/duckdb/litestar/store.py +330 -0
- sqlspec/adapters/duckdb/pool.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/duckdb/pool.py +350 -0
- sqlspec/adapters/duckdb/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/duckdb/type_converter.py +118 -0
- sqlspec/adapters/mysqlconnector/__init__.py +39 -0
- sqlspec/adapters/mysqlconnector/_typing.py +186 -0
- sqlspec/adapters/mysqlconnector/adk/__init__.py +15 -0
- sqlspec/adapters/mysqlconnector/adk/store.py +1183 -0
- sqlspec/adapters/mysqlconnector/config.py +421 -0
- sqlspec/adapters/mysqlconnector/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/mysqlconnector/core.py +472 -0
- sqlspec/adapters/mysqlconnector/data_dictionary.py +230 -0
- sqlspec/adapters/mysqlconnector/driver.py +516 -0
- sqlspec/adapters/mysqlconnector/events/__init__.py +8 -0
- sqlspec/adapters/mysqlconnector/events/store.py +98 -0
- sqlspec/adapters/mysqlconnector/litestar/__init__.py +5 -0
- sqlspec/adapters/mysqlconnector/litestar/store.py +426 -0
- sqlspec/adapters/oracledb/__init__.py +39 -0
- sqlspec/adapters/oracledb/_json_handlers.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/oracledb/_json_handlers.py +196 -0
- sqlspec/adapters/oracledb/_param_types.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/oracledb/_param_types.py +46 -0
- sqlspec/adapters/oracledb/_typing.py +258 -0
- sqlspec/adapters/oracledb/_uuid_handlers.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/oracledb/_uuid_handlers.py +163 -0
- sqlspec/adapters/oracledb/_vector_handlers.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/oracledb/_vector_handlers.py +228 -0
- sqlspec/adapters/oracledb/adk/__init__.py +21 -0
- sqlspec/adapters/oracledb/adk/store.py +2453 -0
- sqlspec/adapters/oracledb/config.py +575 -0
- sqlspec/adapters/oracledb/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/oracledb/core.py +820 -0
- sqlspec/adapters/oracledb/data_dictionary.py +404 -0
- sqlspec/adapters/oracledb/driver.py +1277 -0
- sqlspec/adapters/oracledb/events/__init__.py +16 -0
- sqlspec/adapters/oracledb/events/_hub.py +345 -0
- sqlspec/adapters/oracledb/events/backend.py +300 -0
- sqlspec/adapters/oracledb/events/store.py +420 -0
- sqlspec/adapters/oracledb/litestar/__init__.py +5 -0
- sqlspec/adapters/oracledb/litestar/store.py +781 -0
- sqlspec/adapters/oracledb/migrations.py +539 -0
- sqlspec/adapters/oracledb/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/oracledb/type_converter.py +211 -0
- sqlspec/adapters/psqlpy/__init__.py +18 -0
- sqlspec/adapters/psqlpy/_typing.py +121 -0
- sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
- sqlspec/adapters/psqlpy/adk/store.py +591 -0
- sqlspec/adapters/psqlpy/config.py +376 -0
- sqlspec/adapters/psqlpy/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/psqlpy/core.py +694 -0
- sqlspec/adapters/psqlpy/data_dictionary.py +121 -0
- sqlspec/adapters/psqlpy/driver.py +411 -0
- sqlspec/adapters/psqlpy/events/__init__.py +6 -0
- sqlspec/adapters/psqlpy/events/_hub.py +204 -0
- sqlspec/adapters/psqlpy/events/backend.py +210 -0
- sqlspec/adapters/psqlpy/events/store.py +20 -0
- sqlspec/adapters/psqlpy/litestar/__init__.py +5 -0
- sqlspec/adapters/psqlpy/litestar/store.py +270 -0
- sqlspec/adapters/psqlpy/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/psqlpy/type_converter.py +113 -0
- sqlspec/adapters/psycopg/__init__.py +38 -0
- sqlspec/adapters/psycopg/_typing.py +218 -0
- sqlspec/adapters/psycopg/adk/__init__.py +10 -0
- sqlspec/adapters/psycopg/adk/store.py +1106 -0
- sqlspec/adapters/psycopg/config.py +695 -0
- sqlspec/adapters/psycopg/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/psycopg/core.py +520 -0
- sqlspec/adapters/psycopg/data_dictionary.py +278 -0
- sqlspec/adapters/psycopg/driver.py +1033 -0
- sqlspec/adapters/psycopg/events/__init__.py +20 -0
- sqlspec/adapters/psycopg/events/_hub.py +388 -0
- sqlspec/adapters/psycopg/events/backend.py +398 -0
- sqlspec/adapters/psycopg/events/store.py +42 -0
- sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
- sqlspec/adapters/psycopg/litestar/store.py +554 -0
- sqlspec/adapters/psycopg/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/psycopg/type_converter.py +93 -0
- sqlspec/adapters/pymysql/__init__.py +21 -0
- sqlspec/adapters/pymysql/_typing.py +92 -0
- sqlspec/adapters/pymysql/adk/__init__.py +5 -0
- sqlspec/adapters/pymysql/adk/store.py +657 -0
- sqlspec/adapters/pymysql/config.py +176 -0
- sqlspec/adapters/pymysql/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/pymysql/core.py +469 -0
- sqlspec/adapters/pymysql/data_dictionary.py +120 -0
- sqlspec/adapters/pymysql/driver.py +271 -0
- sqlspec/adapters/pymysql/events/__init__.py +5 -0
- sqlspec/adapters/pymysql/events/store.py +50 -0
- sqlspec/adapters/pymysql/litestar/__init__.py +5 -0
- sqlspec/adapters/pymysql/litestar/store.py +232 -0
- sqlspec/adapters/pymysql/pool.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/pymysql/pool.py +184 -0
- sqlspec/adapters/spanner/__init__.py +33 -0
- sqlspec/adapters/spanner/_typing.py +102 -0
- sqlspec/adapters/spanner/adk/__init__.py +5 -0
- sqlspec/adapters/spanner/adk/store.py +758 -0
- sqlspec/adapters/spanner/config.py +355 -0
- sqlspec/adapters/spanner/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/spanner/core.py +263 -0
- sqlspec/adapters/spanner/data_dictionary.py +120 -0
- sqlspec/adapters/spanner/driver.py +407 -0
- sqlspec/adapters/spanner/events/__init__.py +5 -0
- sqlspec/adapters/spanner/events/store.py +187 -0
- sqlspec/adapters/spanner/litestar/__init__.py +5 -0
- sqlspec/adapters/spanner/litestar/store.py +291 -0
- sqlspec/adapters/spanner/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/spanner/type_converter.py +342 -0
- sqlspec/adapters/sqlite/__init__.py +19 -0
- sqlspec/adapters/sqlite/_typing.py +123 -0
- sqlspec/adapters/sqlite/adk/__init__.py +5 -0
- sqlspec/adapters/sqlite/adk/store.py +992 -0
- sqlspec/adapters/sqlite/config.py +240 -0
- sqlspec/adapters/sqlite/core.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/sqlite/core.py +357 -0
- sqlspec/adapters/sqlite/data_dictionary.py +198 -0
- sqlspec/adapters/sqlite/driver.py +527 -0
- sqlspec/adapters/sqlite/events/__init__.py +5 -0
- sqlspec/adapters/sqlite/events/store.py +20 -0
- sqlspec/adapters/sqlite/litestar/__init__.py +5 -0
- sqlspec/adapters/sqlite/litestar/store.py +316 -0
- sqlspec/adapters/sqlite/pool.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/sqlite/pool.py +237 -0
- sqlspec/adapters/sqlite/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/adapters/sqlite/type_converter.py +114 -0
- sqlspec/base.py +832 -0
- sqlspec/builder/__init__.py +181 -0
- sqlspec/builder/_base.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_base.py +1071 -0
- sqlspec/builder/_column.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_column.py +521 -0
- sqlspec/builder/_ddl.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_ddl.py +1691 -0
- sqlspec/builder/_delete.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_delete.py +95 -0
- sqlspec/builder/_dml.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_dml.py +386 -0
- sqlspec/builder/_explain.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_explain.py +579 -0
- sqlspec/builder/_expression_wrappers.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_expression_wrappers.py +46 -0
- sqlspec/builder/_factory.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_factory.py +1884 -0
- sqlspec/builder/_insert.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_insert.py +405 -0
- sqlspec/builder/_join.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_join.py +489 -0
- sqlspec/builder/_merge.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_merge.py +823 -0
- sqlspec/builder/_parsing_utils.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_parsing_utils.py +295 -0
- sqlspec/builder/_select.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_select.py +1666 -0
- sqlspec/builder/_temporal.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_temporal.py +167 -0
- sqlspec/builder/_update.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_update.py +173 -0
- sqlspec/builder/_vector_distance.cp314-win_amd64.pyd +0 -0
- sqlspec/builder/_vector_distance.py +330 -0
- sqlspec/cli.py +1095 -0
- sqlspec/config.py +2383 -0
- sqlspec/core/__init__.py +372 -0
- sqlspec/core/_correlation.cp314-win_amd64.pyd +0 -0
- sqlspec/core/_correlation.py +176 -0
- sqlspec/core/_pagination.py +42 -0
- sqlspec/core/_pool.cp314-win_amd64.pyd +0 -0
- sqlspec/core/_pool.py +76 -0
- sqlspec/core/cache.cp314-win_amd64.pyd +0 -0
- sqlspec/core/cache.py +1085 -0
- sqlspec/core/compiler.cp314-win_amd64.pyd +0 -0
- sqlspec/core/compiler.py +1090 -0
- sqlspec/core/config_runtime.cp314-win_amd64.pyd +0 -0
- sqlspec/core/config_runtime.py +174 -0
- sqlspec/core/explain.cp314-win_amd64.pyd +0 -0
- sqlspec/core/explain.py +275 -0
- sqlspec/core/filters.cp314-win_amd64.pyd +0 -0
- sqlspec/core/filters.py +969 -0
- sqlspec/core/hashing.cp314-win_amd64.pyd +0 -0
- sqlspec/core/hashing.py +266 -0
- sqlspec/core/metrics.cp314-win_amd64.pyd +0 -0
- sqlspec/core/metrics.py +83 -0
- sqlspec/core/parameters/__init__.py +72 -0
- sqlspec/core/parameters/_alignment.cp314-win_amd64.pyd +0 -0
- sqlspec/core/parameters/_alignment.py +283 -0
- sqlspec/core/parameters/_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/core/parameters/_converter.py +554 -0
- sqlspec/core/parameters/_processor.cp314-win_amd64.pyd +0 -0
- sqlspec/core/parameters/_processor.py +1182 -0
- sqlspec/core/parameters/_registry.cp314-win_amd64.pyd +0 -0
- sqlspec/core/parameters/_registry.py +206 -0
- sqlspec/core/parameters/_transformers.cp314-win_amd64.pyd +0 -0
- sqlspec/core/parameters/_transformers.py +324 -0
- sqlspec/core/parameters/_types.cp314-win_amd64.pyd +0 -0
- sqlspec/core/parameters/_types.py +536 -0
- sqlspec/core/parameters/_validator.cp314-win_amd64.pyd +0 -0
- sqlspec/core/parameters/_validator.py +171 -0
- sqlspec/core/pipeline.cp314-win_amd64.pyd +0 -0
- sqlspec/core/pipeline.py +333 -0
- sqlspec/core/query_modifiers.cp314-win_amd64.pyd +0 -0
- sqlspec/core/query_modifiers.py +508 -0
- sqlspec/core/result/__init__.py +25 -0
- sqlspec/core/result/_base.cp314-win_amd64.pyd +0 -0
- sqlspec/core/result/_base.py +1232 -0
- sqlspec/core/result/_io.cp314-win_amd64.pyd +0 -0
- sqlspec/core/result/_io.py +28 -0
- sqlspec/core/splitter.cp314-win_amd64.pyd +0 -0
- sqlspec/core/splitter.py +1021 -0
- sqlspec/core/sqlcommenter.cp314-win_amd64.pyd +0 -0
- sqlspec/core/sqlcommenter.py +249 -0
- sqlspec/core/stack.cp314-win_amd64.pyd +0 -0
- sqlspec/core/stack.py +163 -0
- sqlspec/core/statement.cp314-win_amd64.pyd +0 -0
- sqlspec/core/statement.py +1865 -0
- sqlspec/core/type_converter.cp314-win_amd64.pyd +0 -0
- sqlspec/core/type_converter.py +340 -0
- sqlspec/data_dictionary/__init__.py +22 -0
- sqlspec/data_dictionary/_loader.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/_loader.py +138 -0
- sqlspec/data_dictionary/_registry.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/_registry.py +74 -0
- sqlspec/data_dictionary/_types.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/_types.py +121 -0
- sqlspec/data_dictionary/dialects/__init__.py +21 -0
- sqlspec/data_dictionary/dialects/bigquery.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/dialects/bigquery.py +81 -0
- sqlspec/data_dictionary/dialects/cockroachdb.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/dialects/cockroachdb.py +54 -0
- sqlspec/data_dictionary/dialects/duckdb.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/dialects/duckdb.py +47 -0
- sqlspec/data_dictionary/dialects/mysql.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/dialects/mysql.py +53 -0
- sqlspec/data_dictionary/dialects/oracle.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/dialects/oracle.py +197 -0
- sqlspec/data_dictionary/dialects/postgres.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/dialects/postgres.py +69 -0
- sqlspec/data_dictionary/dialects/spanner.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/dialects/spanner.py +37 -0
- sqlspec/data_dictionary/dialects/sqlite.cp314-win_amd64.pyd +0 -0
- sqlspec/data_dictionary/dialects/sqlite.py +59 -0
- sqlspec/data_dictionary/sql/.gitkeep +0 -0
- sqlspec/data_dictionary/sql/bigquery/columns.sql +23 -0
- sqlspec/data_dictionary/sql/bigquery/foreign_keys.sql +34 -0
- sqlspec/data_dictionary/sql/bigquery/indexes.sql +19 -0
- sqlspec/data_dictionary/sql/bigquery/tables.sql +33 -0
- sqlspec/data_dictionary/sql/bigquery/version.sql +3 -0
- sqlspec/data_dictionary/sql/cockroachdb/columns.sql +34 -0
- sqlspec/data_dictionary/sql/cockroachdb/foreign_keys.sql +40 -0
- sqlspec/data_dictionary/sql/cockroachdb/indexes.sql +32 -0
- sqlspec/data_dictionary/sql/cockroachdb/tables.sql +44 -0
- sqlspec/data_dictionary/sql/cockroachdb/version.sql +3 -0
- sqlspec/data_dictionary/sql/duckdb/columns.sql +23 -0
- sqlspec/data_dictionary/sql/duckdb/foreign_keys.sql +36 -0
- sqlspec/data_dictionary/sql/duckdb/indexes.sql +19 -0
- sqlspec/data_dictionary/sql/duckdb/tables.sql +38 -0
- sqlspec/data_dictionary/sql/duckdb/version.sql +3 -0
- sqlspec/data_dictionary/sql/mysql/columns.sql +23 -0
- sqlspec/data_dictionary/sql/mysql/foreign_keys.sql +28 -0
- sqlspec/data_dictionary/sql/mysql/indexes.sql +26 -0
- sqlspec/data_dictionary/sql/mysql/tables.sql +33 -0
- sqlspec/data_dictionary/sql/mysql/version.sql +3 -0
- sqlspec/data_dictionary/sql/oracle/columns.sql +23 -0
- sqlspec/data_dictionary/sql/oracle/foreign_keys.sql +48 -0
- sqlspec/data_dictionary/sql/oracle/indexes.sql +44 -0
- sqlspec/data_dictionary/sql/oracle/tables.sql +25 -0
- sqlspec/data_dictionary/sql/oracle/version.sql +20 -0
- sqlspec/data_dictionary/sql/postgres/columns.sql +34 -0
- sqlspec/data_dictionary/sql/postgres/foreign_keys.sql +40 -0
- sqlspec/data_dictionary/sql/postgres/indexes.sql +56 -0
- sqlspec/data_dictionary/sql/postgres/tables.sql +44 -0
- sqlspec/data_dictionary/sql/postgres/version.sql +3 -0
- sqlspec/data_dictionary/sql/spanner/columns.sql +23 -0
- sqlspec/data_dictionary/sql/spanner/foreign_keys.sql +70 -0
- sqlspec/data_dictionary/sql/spanner/indexes.sql +30 -0
- sqlspec/data_dictionary/sql/spanner/tables.sql +9 -0
- sqlspec/data_dictionary/sql/spanner/version.sql +3 -0
- sqlspec/data_dictionary/sql/sqlite/columns.sql +23 -0
- sqlspec/data_dictionary/sql/sqlite/foreign_keys.sql +22 -0
- sqlspec/data_dictionary/sql/sqlite/indexes.sql +7 -0
- sqlspec/data_dictionary/sql/sqlite/tables.sql +28 -0
- sqlspec/data_dictionary/sql/sqlite/version.sql +3 -0
- sqlspec/dialects/__init__.py +22 -0
- sqlspec/dialects/_compat.cp314-win_amd64.pyd +0 -0
- sqlspec/dialects/_compat.py +14 -0
- sqlspec/dialects/postgres/__init__.py +9 -0
- sqlspec/dialects/postgres/_generators.cp314-win_amd64.pyd +0 -0
- sqlspec/dialects/postgres/_generators.py +57 -0
- sqlspec/dialects/postgres/_operators.cp314-win_amd64.pyd +0 -0
- sqlspec/dialects/postgres/_operators.py +81 -0
- sqlspec/dialects/postgres/_paradedb.py +50 -0
- sqlspec/dialects/postgres/_pgvector.py +36 -0
- sqlspec/dialects/spanner/__init__.py +6 -0
- sqlspec/dialects/spanner/_generators.cp314-win_amd64.pyd +0 -0
- sqlspec/dialects/spanner/_generators.py +206 -0
- sqlspec/dialects/spanner/_spangres.py +77 -0
- sqlspec/dialects/spanner/_spanner.py +179 -0
- sqlspec/driver/__init__.py +49 -0
- sqlspec/driver/_async.cp314-win_amd64.pyd +0 -0
- sqlspec/driver/_async.py +1830 -0
- sqlspec/driver/_common.cp314-win_amd64.pyd +0 -0
- sqlspec/driver/_common.py +2292 -0
- sqlspec/driver/_exception_handler.cp314-win_amd64.pyd +0 -0
- sqlspec/driver/_exception_handler.py +108 -0
- sqlspec/driver/_query_cache.cp314-win_amd64.pyd +0 -0
- sqlspec/driver/_query_cache.py +96 -0
- sqlspec/driver/_sql_helpers.cp314-win_amd64.pyd +0 -0
- sqlspec/driver/_sql_helpers.py +139 -0
- sqlspec/driver/_storage_helpers.cp314-win_amd64.pyd +0 -0
- sqlspec/driver/_storage_helpers.py +153 -0
- sqlspec/driver/_sync.cp314-win_amd64.pyd +0 -0
- sqlspec/driver/_sync.py +1817 -0
- sqlspec/exceptions.cp314-win_amd64.pyd +0 -0
- sqlspec/exceptions.py +480 -0
- sqlspec/extensions/__init__.py +0 -0
- sqlspec/extensions/adk/__init__.py +84 -0
- sqlspec/extensions/adk/_config_utils.py +199 -0
- sqlspec/extensions/adk/_types.cp314-win_amd64.pyd +0 -0
- sqlspec/extensions/adk/_types.py +41 -0
- sqlspec/extensions/adk/artifact/__init__.py +57 -0
- sqlspec/extensions/adk/artifact/_types.cp314-win_amd64.pyd +0 -0
- sqlspec/extensions/adk/artifact/_types.py +32 -0
- sqlspec/extensions/adk/artifact/service.py +508 -0
- sqlspec/extensions/adk/artifact/store.py +361 -0
- sqlspec/extensions/adk/converters.py +212 -0
- sqlspec/extensions/adk/memory/__init__.py +69 -0
- sqlspec/extensions/adk/memory/_types.cp314-win_amd64.pyd +0 -0
- sqlspec/extensions/adk/memory/_types.py +30 -0
- sqlspec/extensions/adk/memory/converters.py +225 -0
- sqlspec/extensions/adk/memory/service.py +316 -0
- sqlspec/extensions/adk/memory/store.py +525 -0
- sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +184 -0
- sqlspec/extensions/adk/migrations/__init__.py +0 -0
- sqlspec/extensions/adk/service.py +279 -0
- sqlspec/extensions/adk/store.py +590 -0
- sqlspec/extensions/events/__init__.py +51 -0
- sqlspec/extensions/events/_channel.py +703 -0
- sqlspec/extensions/events/_hints.cp314-win_amd64.pyd +0 -0
- sqlspec/extensions/events/_hints.py +45 -0
- sqlspec/extensions/events/_models.py +23 -0
- sqlspec/extensions/events/_payload.cp314-win_amd64.pyd +0 -0
- sqlspec/extensions/events/_payload.py +69 -0
- sqlspec/extensions/events/_protocols.py +134 -0
- sqlspec/extensions/events/_queue.py +462 -0
- sqlspec/extensions/events/_store.py +209 -0
- sqlspec/extensions/events/migrations/0001_create_event_queue.py +59 -0
- sqlspec/extensions/events/migrations/__init__.py +3 -0
- sqlspec/extensions/fastapi/__init__.py +22 -0
- sqlspec/extensions/fastapi/extension.py +391 -0
- sqlspec/extensions/fastapi/providers.cp314-win_amd64.pyd +0 -0
- sqlspec/extensions/fastapi/providers.py +712 -0
- sqlspec/extensions/flask/__init__.py +38 -0
- sqlspec/extensions/flask/_state.py +87 -0
- sqlspec/extensions/flask/_utils.py +71 -0
- sqlspec/extensions/flask/extension.py +539 -0
- sqlspec/extensions/litestar/__init__.py +31 -0
- sqlspec/extensions/litestar/_utils.py +52 -0
- sqlspec/extensions/litestar/channels.py +165 -0
- sqlspec/extensions/litestar/cli.py +102 -0
- sqlspec/extensions/litestar/config.py +90 -0
- sqlspec/extensions/litestar/handlers.py +316 -0
- sqlspec/extensions/litestar/migrations/0001_create_session_table.py +137 -0
- sqlspec/extensions/litestar/migrations/__init__.py +3 -0
- sqlspec/extensions/litestar/plugin.py +1066 -0
- sqlspec/extensions/litestar/providers.cp314-win_amd64.pyd +0 -0
- sqlspec/extensions/litestar/providers.py +784 -0
- sqlspec/extensions/litestar/store.py +298 -0
- sqlspec/extensions/otel/__init__.py +58 -0
- sqlspec/extensions/prometheus/__init__.py +113 -0
- sqlspec/extensions/sanic/__init__.py +19 -0
- sqlspec/extensions/sanic/_state.py +43 -0
- sqlspec/extensions/sanic/_utils.py +127 -0
- sqlspec/extensions/sanic/extension.py +647 -0
- sqlspec/extensions/starlette/__init__.py +22 -0
- sqlspec/extensions/starlette/_state.py +42 -0
- sqlspec/extensions/starlette/_utils.py +96 -0
- sqlspec/extensions/starlette/extension.py +374 -0
- sqlspec/extensions/starlette/middleware.py +281 -0
- sqlspec/loader.cp314-win_amd64.pyd +0 -0
- sqlspec/loader.py +727 -0
- sqlspec/migrations/__init__.py +39 -0
- sqlspec/migrations/base.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/base.py +862 -0
- sqlspec/migrations/commands.py +2151 -0
- sqlspec/migrations/context.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/context.py +157 -0
- sqlspec/migrations/fix.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/fix.py +204 -0
- sqlspec/migrations/loaders.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/loaders.py +443 -0
- sqlspec/migrations/runner.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/runner.py +1195 -0
- sqlspec/migrations/squash.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/squash.py +490 -0
- sqlspec/migrations/templates.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/templates.py +234 -0
- sqlspec/migrations/tracker.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/tracker.py +792 -0
- sqlspec/migrations/utils.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/utils.py +256 -0
- sqlspec/migrations/validation.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/validation.py +359 -0
- sqlspec/migrations/version.cp314-win_amd64.pyd +0 -0
- sqlspec/migrations/version.py +446 -0
- sqlspec/observability/__init__.py +57 -0
- sqlspec/observability/_common.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_common.py +77 -0
- sqlspec/observability/_config.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_config.py +364 -0
- sqlspec/observability/_diagnostics.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_diagnostics.py +74 -0
- sqlspec/observability/_dispatcher.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_dispatcher.py +200 -0
- sqlspec/observability/_formatters/__init__.py +13 -0
- sqlspec/observability/_formatters/_aws.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_formatters/_aws.py +102 -0
- sqlspec/observability/_formatters/_azure.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_formatters/_azure.py +96 -0
- sqlspec/observability/_formatters/_base.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_formatters/_base.py +57 -0
- sqlspec/observability/_formatters/_gcp.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_formatters/_gcp.py +131 -0
- sqlspec/observability/_formatting.py +58 -0
- sqlspec/observability/_observer.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_observer.py +361 -0
- sqlspec/observability/_runtime.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_runtime.py +461 -0
- sqlspec/observability/_sampling.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_sampling.py +188 -0
- sqlspec/observability/_spans.cp314-win_amd64.pyd +0 -0
- sqlspec/observability/_spans.py +161 -0
- sqlspec/protocols.py +955 -0
- sqlspec/py.typed +0 -0
- sqlspec/service.py +433 -0
- sqlspec/storage/__init__.py +48 -0
- sqlspec/storage/_arrow_payload.py +68 -0
- sqlspec/storage/_paths.cp314-win_amd64.pyd +0 -0
- sqlspec/storage/_paths.py +58 -0
- sqlspec/storage/_utils.py +46 -0
- sqlspec/storage/backends/__init__.py +1 -0
- sqlspec/storage/backends/base.cp314-win_amd64.pyd +0 -0
- sqlspec/storage/backends/base.py +374 -0
- sqlspec/storage/backends/fsspec.py +574 -0
- sqlspec/storage/backends/local.py +468 -0
- sqlspec/storage/backends/obstore.py +956 -0
- sqlspec/storage/errors.cp314-win_amd64.pyd +0 -0
- sqlspec/storage/errors.py +102 -0
- sqlspec/storage/pipeline.cp314-win_amd64.pyd +0 -0
- sqlspec/storage/pipeline.py +628 -0
- sqlspec/storage/registry.cp314-win_amd64.pyd +0 -0
- sqlspec/storage/registry.py +329 -0
- sqlspec/typing.py +405 -0
- sqlspec/utils/__init__.py +7 -0
- sqlspec/utils/arrow_helpers.py +384 -0
- sqlspec/utils/config_tools.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/config_tools.py +314 -0
- sqlspec/utils/correlation.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/correlation.py +134 -0
- sqlspec/utils/deprecation.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/deprecation.py +157 -0
- sqlspec/utils/dispatch.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/dispatch.py +101 -0
- sqlspec/utils/fixtures.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/fixtures.py +260 -0
- sqlspec/utils/logging.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/logging.py +251 -0
- sqlspec/utils/module_loader.py +306 -0
- sqlspec/utils/portal.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/portal.py +377 -0
- sqlspec/utils/schema.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/schema.py +1040 -0
- sqlspec/utils/serializers/__init__.py +30 -0
- sqlspec/utils/serializers/_json.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/serializers/_json.py +415 -0
- sqlspec/utils/serializers/_numpy.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/serializers/_numpy.py +65 -0
- sqlspec/utils/serializers/_schema.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/serializers/_schema.py +285 -0
- sqlspec/utils/singleton.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/singleton.py +41 -0
- sqlspec/utils/sync_tools.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/sync_tools.py +316 -0
- sqlspec/utils/text.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/text.py +109 -0
- sqlspec/utils/type_converters.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/type_converters.py +216 -0
- sqlspec/utils/type_guards.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/type_guards.py +1508 -0
- sqlspec/utils/uuids.cp314-win_amd64.pyd +0 -0
- sqlspec/utils/uuids.py +241 -0
- sqlspec-0.47.0.dist-info/METADATA +202 -0
- sqlspec-0.47.0.dist-info/RECORD +621 -0
- sqlspec-0.47.0.dist-info/WHEEL +4 -0
- sqlspec-0.47.0.dist-info/entry_points.txt +6 -0
- sqlspec-0.47.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Events helpers for the Oracle adapter."""
|
|
2
|
+
|
|
3
|
+
from sqlspec.adapters.oracledb.events.backend import (
|
|
4
|
+
OracleAsyncAQEventBackend,
|
|
5
|
+
OracleSyncAQEventBackend,
|
|
6
|
+
create_event_backend,
|
|
7
|
+
)
|
|
8
|
+
from sqlspec.adapters.oracledb.events.store import OracleAsyncEventQueueStore, OracleSyncEventQueueStore
|
|
9
|
+
|
|
10
|
+
__all__ = (
|
|
11
|
+
"OracleAsyncAQEventBackend",
|
|
12
|
+
"OracleAsyncEventQueueStore",
|
|
13
|
+
"OracleSyncAQEventBackend",
|
|
14
|
+
"OracleSyncEventQueueStore",
|
|
15
|
+
"create_event_backend",
|
|
16
|
+
)
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
"""Persistent Oracle AQ queue-handle caches used by Oracle AQ event backends.
|
|
2
|
+
|
|
3
|
+
Eliminates per-iteration session + queue handle acquisition. The hub holds a
|
|
4
|
+
single dedicated connection per backend instance and caches one queue handle
|
|
5
|
+
per subscribed channel. Each dequeue uses the cached handle and honors the
|
|
6
|
+
caller's poll_interval (capped at the configured aq_wait_seconds ceiling).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# pyright: reportPrivateUsage=false
|
|
10
|
+
|
|
11
|
+
import asyncio
|
|
12
|
+
import contextlib
|
|
13
|
+
import logging
|
|
14
|
+
import threading
|
|
15
|
+
from math import ceil
|
|
16
|
+
from typing import TYPE_CHECKING, Any
|
|
17
|
+
|
|
18
|
+
from sqlspec.exceptions import EventChannelError, MissingDependencyError
|
|
19
|
+
from sqlspec.utils.logging import get_logger, log_with_context
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from sqlspec.adapters.oracledb.config import OracleAsyncConfig, OracleSyncConfig
|
|
23
|
+
|
|
24
|
+
logger = get_logger("sqlspec.adapters.oracledb.events.hub")
|
|
25
|
+
|
|
26
|
+
__all__ = ("OracleAsyncAQHub", "OracleSyncAQHub")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
_AQ_AVAILABLE = False
|
|
30
|
+
OracleDatabaseError: Any
|
|
31
|
+
|
|
32
|
+
try: # pragma: no cover - optional dependency path
|
|
33
|
+
from sqlspec.adapters.oracledb._typing import AQMSG_INVISIBLE as _AQMSG_INVISIBLE
|
|
34
|
+
from sqlspec.adapters.oracledb._typing import AQMSG_PAYLOAD_TYPE_JSON as _AQMSG_PAYLOAD_TYPE_JSON
|
|
35
|
+
from sqlspec.adapters.oracledb._typing import AQMSG_VISIBLE as _AQMSG_VISIBLE
|
|
36
|
+
from sqlspec.adapters.oracledb._typing import DB_TYPE_JSON as _DB_TYPE_JSON
|
|
37
|
+
from sqlspec.adapters.oracledb._typing import AQDequeueOptions as _AQDequeueOptions
|
|
38
|
+
from sqlspec.adapters.oracledb._typing import DatabaseError as _OracleDatabaseErrorImported
|
|
39
|
+
except ImportError: # pragma: no cover - optional dependency path
|
|
40
|
+
_AQDequeueOptions = None
|
|
41
|
+
_AQMSG_INVISIBLE = None
|
|
42
|
+
_AQMSG_PAYLOAD_TYPE_JSON = None
|
|
43
|
+
_AQMSG_VISIBLE = None
|
|
44
|
+
_DB_TYPE_JSON = None
|
|
45
|
+
OracleDatabaseError = None
|
|
46
|
+
else: # pragma: no cover - optional dependency path
|
|
47
|
+
_AQ_AVAILABLE = True
|
|
48
|
+
OracleDatabaseError = _OracleDatabaseErrorImported
|
|
49
|
+
|
|
50
|
+
AQDequeueOptions: Any = _AQDequeueOptions
|
|
51
|
+
AQMSG_INVISIBLE: "int | None" = _AQMSG_INVISIBLE
|
|
52
|
+
AQMSG_PAYLOAD_TYPE_JSON: Any = _AQMSG_PAYLOAD_TYPE_JSON
|
|
53
|
+
AQMSG_VISIBLE: "int | None" = _AQMSG_VISIBLE
|
|
54
|
+
DB_TYPE_JSON: Any = _DB_TYPE_JSON
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _resolve_payload_type() -> Any:
|
|
58
|
+
"""Pick the right driver constant for JSON payloads."""
|
|
59
|
+
if DB_TYPE_JSON is not None:
|
|
60
|
+
return DB_TYPE_JSON
|
|
61
|
+
return AQMSG_PAYLOAD_TYPE_JSON
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _resolve_options(visibility: "int | None", default_visibility: "int | None", wait_seconds: float) -> Any:
|
|
65
|
+
"""Build an AQDequeueOptions instance for the requested wait + visibility."""
|
|
66
|
+
if AQDequeueOptions is None: # pragma: no cover - optional dependency path
|
|
67
|
+
msg = "oracledb AQDequeueOptions"
|
|
68
|
+
raise MissingDependencyError(msg, install_package="oracledb")
|
|
69
|
+
options = AQDequeueOptions()
|
|
70
|
+
options.wait = 0 if wait_seconds <= 0 else ceil(wait_seconds)
|
|
71
|
+
if visibility is not None:
|
|
72
|
+
options.visibility = visibility
|
|
73
|
+
elif default_visibility is not None:
|
|
74
|
+
options.visibility = default_visibility
|
|
75
|
+
return options
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _channel_queue_name(template: str, channel: str) -> str:
|
|
79
|
+
"""Apply a queue-name template (supports ``{channel}`` substitution)."""
|
|
80
|
+
if isinstance(template, str) and "{" in template:
|
|
81
|
+
with contextlib.suppress(Exception):
|
|
82
|
+
return template.format(channel=channel.upper())
|
|
83
|
+
return template
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _resolve_wait_seconds(poll_interval: float, ceiling: int) -> float:
|
|
87
|
+
"""Cap the caller's poll_interval at the configured aq_wait_seconds ceiling."""
|
|
88
|
+
interval = max(float(poll_interval), 0.0)
|
|
89
|
+
if ceiling <= 0:
|
|
90
|
+
return interval
|
|
91
|
+
return min(interval, float(ceiling))
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class OracleSyncAQHub:
|
|
95
|
+
"""Per-channel persistent queue-handle cache for sync Oracle AQ."""
|
|
96
|
+
|
|
97
|
+
__slots__ = (
|
|
98
|
+
"_config",
|
|
99
|
+
"_default_visibility",
|
|
100
|
+
"_lock",
|
|
101
|
+
"_pool_destroying_registered",
|
|
102
|
+
"_queue_name_template",
|
|
103
|
+
"_queues",
|
|
104
|
+
"_session_cm",
|
|
105
|
+
"_session_driver",
|
|
106
|
+
"_shutting_down",
|
|
107
|
+
"_visibility",
|
|
108
|
+
"_wait_ceiling",
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
def __init__(
|
|
112
|
+
self,
|
|
113
|
+
config: "OracleSyncConfig",
|
|
114
|
+
*,
|
|
115
|
+
queue_name_template: str,
|
|
116
|
+
visibility: "int | None",
|
|
117
|
+
default_visibility: "int | None",
|
|
118
|
+
wait_ceiling: int,
|
|
119
|
+
) -> None:
|
|
120
|
+
self._config = config
|
|
121
|
+
self._queue_name_template = queue_name_template
|
|
122
|
+
self._visibility = visibility
|
|
123
|
+
self._default_visibility = default_visibility
|
|
124
|
+
self._wait_ceiling = wait_ceiling
|
|
125
|
+
self._lock = threading.Lock()
|
|
126
|
+
self._queues: dict[str, Any] = {}
|
|
127
|
+
self._session_cm: Any | None = None
|
|
128
|
+
self._session_driver: Any | None = None
|
|
129
|
+
self._shutting_down = False
|
|
130
|
+
self._pool_destroying_registered = False
|
|
131
|
+
|
|
132
|
+
def subscribe(self, channel: str) -> None:
|
|
133
|
+
with self._lock:
|
|
134
|
+
self._ensure_handle_locked(channel)
|
|
135
|
+
|
|
136
|
+
def dequeue(self, channel: str, poll_interval: float) -> "Any | None":
|
|
137
|
+
with self._lock:
|
|
138
|
+
if self._shutting_down:
|
|
139
|
+
return None
|
|
140
|
+
queue = self._ensure_handle_locked(channel)
|
|
141
|
+
driver = self._session_driver
|
|
142
|
+
if driver is None:
|
|
143
|
+
return None
|
|
144
|
+
wait_seconds = _resolve_wait_seconds(poll_interval, self._wait_ceiling)
|
|
145
|
+
options = _resolve_options(self._visibility, self._default_visibility, wait_seconds)
|
|
146
|
+
try:
|
|
147
|
+
message = queue.deqone(options=options)
|
|
148
|
+
except Exception as error: # pragma: no cover - driver surfaced runtime
|
|
149
|
+
if OracleDatabaseError is None or not isinstance(error, OracleDatabaseError):
|
|
150
|
+
raise
|
|
151
|
+
log_with_context(
|
|
152
|
+
logger,
|
|
153
|
+
logging.WARNING,
|
|
154
|
+
"event.receive",
|
|
155
|
+
adapter_name="oracledb",
|
|
156
|
+
backend_name="advanced_queue",
|
|
157
|
+
mode="sync",
|
|
158
|
+
error_type=type(error).__name__,
|
|
159
|
+
status="failed",
|
|
160
|
+
)
|
|
161
|
+
with contextlib.suppress(Exception):
|
|
162
|
+
driver.rollback()
|
|
163
|
+
return None
|
|
164
|
+
if message is None:
|
|
165
|
+
with contextlib.suppress(Exception):
|
|
166
|
+
driver.rollback()
|
|
167
|
+
return None
|
|
168
|
+
payload = message.payload
|
|
169
|
+
with contextlib.suppress(Exception):
|
|
170
|
+
driver.commit()
|
|
171
|
+
return payload
|
|
172
|
+
|
|
173
|
+
def shutdown(self) -> None:
|
|
174
|
+
with self._lock:
|
|
175
|
+
if self._shutting_down:
|
|
176
|
+
return
|
|
177
|
+
self._shutting_down = True
|
|
178
|
+
session_cm = self._session_cm
|
|
179
|
+
self._queues.clear()
|
|
180
|
+
self._session_cm = None
|
|
181
|
+
self._session_driver = None
|
|
182
|
+
if session_cm is not None:
|
|
183
|
+
with contextlib.suppress(Exception):
|
|
184
|
+
session_cm.__exit__(None, None, None)
|
|
185
|
+
self._shutting_down = False
|
|
186
|
+
|
|
187
|
+
def _ensure_handle_locked(self, channel: str) -> Any:
|
|
188
|
+
cached = self._queues.get(channel)
|
|
189
|
+
if cached is not None:
|
|
190
|
+
return cached
|
|
191
|
+
if not _AQ_AVAILABLE: # pragma: no cover - optional dependency path
|
|
192
|
+
msg = "oracledb"
|
|
193
|
+
raise MissingDependencyError(msg, install_package="oracledb")
|
|
194
|
+
driver = self._session_driver
|
|
195
|
+
if driver is None:
|
|
196
|
+
session_cm = self._config.provide_session()
|
|
197
|
+
driver = session_cm.__enter__()
|
|
198
|
+
self._session_cm = session_cm
|
|
199
|
+
self._session_driver = driver
|
|
200
|
+
self._register_pool_destroying()
|
|
201
|
+
connection = getattr(driver, "connection", None)
|
|
202
|
+
if connection is None:
|
|
203
|
+
msg = "Oracle driver does not expose a raw connection"
|
|
204
|
+
raise EventChannelError(msg)
|
|
205
|
+
queue_name = _channel_queue_name(self._queue_name_template, channel)
|
|
206
|
+
queue = connection.queue(queue_name, payload_type=_resolve_payload_type())
|
|
207
|
+
self._queues[channel] = queue
|
|
208
|
+
return queue
|
|
209
|
+
|
|
210
|
+
def _register_pool_destroying(self) -> None:
|
|
211
|
+
if self._pool_destroying_registered:
|
|
212
|
+
return
|
|
213
|
+
runtime = self._config.get_observability_runtime()
|
|
214
|
+
runtime.register_lifecycle_hook("on_pool_destroying", self._pool_destroying_hook)
|
|
215
|
+
self._pool_destroying_registered = True
|
|
216
|
+
|
|
217
|
+
def _pool_destroying_hook(self, _context: "dict[str, Any]") -> None:
|
|
218
|
+
self.shutdown()
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
class OracleAsyncAQHub:
|
|
222
|
+
"""Per-channel persistent queue-handle cache for async Oracle AQ."""
|
|
223
|
+
|
|
224
|
+
__slots__ = (
|
|
225
|
+
"_config",
|
|
226
|
+
"_default_visibility",
|
|
227
|
+
"_lock",
|
|
228
|
+
"_pool_destroying_registered",
|
|
229
|
+
"_queue_name_template",
|
|
230
|
+
"_queues",
|
|
231
|
+
"_session_cm",
|
|
232
|
+
"_session_driver",
|
|
233
|
+
"_shutting_down",
|
|
234
|
+
"_visibility",
|
|
235
|
+
"_wait_ceiling",
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
def __init__(
|
|
239
|
+
self,
|
|
240
|
+
config: "OracleAsyncConfig",
|
|
241
|
+
*,
|
|
242
|
+
queue_name_template: str,
|
|
243
|
+
visibility: "int | None",
|
|
244
|
+
default_visibility: "int | None",
|
|
245
|
+
wait_ceiling: int,
|
|
246
|
+
) -> None:
|
|
247
|
+
self._config = config
|
|
248
|
+
self._queue_name_template = queue_name_template
|
|
249
|
+
self._visibility = visibility
|
|
250
|
+
self._default_visibility = default_visibility
|
|
251
|
+
self._wait_ceiling = wait_ceiling
|
|
252
|
+
self._lock = asyncio.Lock()
|
|
253
|
+
self._queues: dict[str, Any] = {}
|
|
254
|
+
self._session_cm: Any | None = None
|
|
255
|
+
self._session_driver: Any | None = None
|
|
256
|
+
self._shutting_down = False
|
|
257
|
+
self._pool_destroying_registered = False
|
|
258
|
+
|
|
259
|
+
async def subscribe(self, channel: str) -> None:
|
|
260
|
+
async with self._lock:
|
|
261
|
+
await self._ensure_handle_locked(channel)
|
|
262
|
+
|
|
263
|
+
async def dequeue(self, channel: str, poll_interval: float) -> "Any | None":
|
|
264
|
+
async with self._lock:
|
|
265
|
+
if self._shutting_down:
|
|
266
|
+
return None
|
|
267
|
+
queue = await self._ensure_handle_locked(channel)
|
|
268
|
+
driver = self._session_driver
|
|
269
|
+
if driver is None:
|
|
270
|
+
return None
|
|
271
|
+
wait_seconds = _resolve_wait_seconds(poll_interval, self._wait_ceiling)
|
|
272
|
+
options = _resolve_options(self._visibility, self._default_visibility, wait_seconds)
|
|
273
|
+
try:
|
|
274
|
+
message = await queue.deqone(options=options)
|
|
275
|
+
except Exception as error: # pragma: no cover - driver surfaced runtime
|
|
276
|
+
if OracleDatabaseError is None or not isinstance(error, OracleDatabaseError):
|
|
277
|
+
raise
|
|
278
|
+
log_with_context(
|
|
279
|
+
logger,
|
|
280
|
+
logging.WARNING,
|
|
281
|
+
"event.receive",
|
|
282
|
+
adapter_name="oracledb",
|
|
283
|
+
backend_name="advanced_queue",
|
|
284
|
+
mode="async",
|
|
285
|
+
error_type=type(error).__name__,
|
|
286
|
+
status="failed",
|
|
287
|
+
)
|
|
288
|
+
with contextlib.suppress(Exception):
|
|
289
|
+
await driver.rollback()
|
|
290
|
+
return None
|
|
291
|
+
if message is None:
|
|
292
|
+
with contextlib.suppress(Exception):
|
|
293
|
+
await driver.rollback()
|
|
294
|
+
return None
|
|
295
|
+
payload = message.payload
|
|
296
|
+
with contextlib.suppress(Exception):
|
|
297
|
+
await driver.commit()
|
|
298
|
+
return payload
|
|
299
|
+
|
|
300
|
+
async def shutdown(self) -> None:
|
|
301
|
+
async with self._lock:
|
|
302
|
+
if self._shutting_down:
|
|
303
|
+
return
|
|
304
|
+
self._shutting_down = True
|
|
305
|
+
session_cm = self._session_cm
|
|
306
|
+
self._queues.clear()
|
|
307
|
+
self._session_cm = None
|
|
308
|
+
self._session_driver = None
|
|
309
|
+
if session_cm is not None:
|
|
310
|
+
with contextlib.suppress(Exception):
|
|
311
|
+
await session_cm.__aexit__(None, None, None)
|
|
312
|
+
self._shutting_down = False
|
|
313
|
+
|
|
314
|
+
async def _ensure_handle_locked(self, channel: str) -> Any:
|
|
315
|
+
cached = self._queues.get(channel)
|
|
316
|
+
if cached is not None:
|
|
317
|
+
return cached
|
|
318
|
+
if not _AQ_AVAILABLE: # pragma: no cover - optional dependency path
|
|
319
|
+
msg = "oracledb"
|
|
320
|
+
raise MissingDependencyError(msg, install_package="oracledb")
|
|
321
|
+
driver = self._session_driver
|
|
322
|
+
if driver is None:
|
|
323
|
+
session_cm = self._config.provide_session()
|
|
324
|
+
driver = await session_cm.__aenter__()
|
|
325
|
+
self._session_cm = session_cm
|
|
326
|
+
self._session_driver = driver
|
|
327
|
+
self._register_pool_destroying()
|
|
328
|
+
connection = getattr(driver, "connection", None)
|
|
329
|
+
if connection is None:
|
|
330
|
+
msg = "Oracle driver does not expose a raw connection"
|
|
331
|
+
raise EventChannelError(msg)
|
|
332
|
+
queue_name = _channel_queue_name(self._queue_name_template, channel)
|
|
333
|
+
queue = connection.queue(queue_name, payload_type=_resolve_payload_type())
|
|
334
|
+
self._queues[channel] = queue
|
|
335
|
+
return queue
|
|
336
|
+
|
|
337
|
+
def _register_pool_destroying(self) -> None:
|
|
338
|
+
if self._pool_destroying_registered:
|
|
339
|
+
return
|
|
340
|
+
runtime = self._config.get_observability_runtime()
|
|
341
|
+
runtime.register_lifecycle_hook("on_pool_destroying", self._pool_destroying_hook)
|
|
342
|
+
self._pool_destroying_registered = True
|
|
343
|
+
|
|
344
|
+
def _pool_destroying_hook(self, _context: "dict[str, Any]") -> "Any":
|
|
345
|
+
return self.shutdown()
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
"""Oracle Advanced Queuing backend for EventChannel."""
|
|
2
|
+
|
|
3
|
+
import contextlib
|
|
4
|
+
import logging
|
|
5
|
+
from datetime import datetime, timezone
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
|
+
|
|
8
|
+
from sqlspec.adapters.oracledb.events._hub import OracleAsyncAQHub, OracleSyncAQHub
|
|
9
|
+
from sqlspec.exceptions import ImproperConfigurationError, MissingDependencyError
|
|
10
|
+
from sqlspec.extensions.events import EventMessage, parse_event_timestamp
|
|
11
|
+
from sqlspec.utils.logging import get_logger, log_with_context
|
|
12
|
+
from sqlspec.utils.uuids import uuid4
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from sqlspec.adapters.oracledb.config import OracleAsyncConfig, OracleSyncConfig
|
|
16
|
+
|
|
17
|
+
_ORACLEDB_AVAILABLE = False
|
|
18
|
+
|
|
19
|
+
try: # pragma: no cover - optional dependency path
|
|
20
|
+
from sqlspec.adapters.oracledb._typing import AQMSG_INVISIBLE as _AQMSG_INVISIBLE
|
|
21
|
+
from sqlspec.adapters.oracledb._typing import AQMSG_PAYLOAD_TYPE_JSON as _AQMSG_PAYLOAD_TYPE_JSON
|
|
22
|
+
from sqlspec.adapters.oracledb._typing import AQMSG_VISIBLE as _AQMSG_VISIBLE
|
|
23
|
+
from sqlspec.adapters.oracledb._typing import DB_TYPE_JSON as _DB_TYPE_JSON
|
|
24
|
+
from sqlspec.adapters.oracledb._typing import AQDequeueOptions as _AQDequeueOptions
|
|
25
|
+
except ImportError: # pragma: no cover - optional dependency path
|
|
26
|
+
_AQDequeueOptions = None
|
|
27
|
+
_AQMSG_INVISIBLE = None
|
|
28
|
+
_AQMSG_PAYLOAD_TYPE_JSON = None
|
|
29
|
+
_AQMSG_VISIBLE = None
|
|
30
|
+
_DB_TYPE_JSON = None
|
|
31
|
+
else: # pragma: no cover - optional dependency path
|
|
32
|
+
_ORACLEDB_AVAILABLE = True
|
|
33
|
+
|
|
34
|
+
AQDequeueOptions: Any = _AQDequeueOptions
|
|
35
|
+
AQMSG_INVISIBLE: "int | None" = _AQMSG_INVISIBLE
|
|
36
|
+
AQMSG_PAYLOAD_TYPE_JSON: Any = _AQMSG_PAYLOAD_TYPE_JSON
|
|
37
|
+
AQMSG_VISIBLE: "int | None" = _AQMSG_VISIBLE
|
|
38
|
+
DB_TYPE_JSON: Any = _DB_TYPE_JSON
|
|
39
|
+
|
|
40
|
+
logger = get_logger("sqlspec.events.oracle")
|
|
41
|
+
|
|
42
|
+
__all__ = ("OracleAsyncAQEventBackend", "OracleSyncAQEventBackend", "create_event_backend")
|
|
43
|
+
|
|
44
|
+
_DEFAULT_QUEUE_NAME = "SQLSPEC_EVENTS_QUEUE"
|
|
45
|
+
_DEFAULT_VISIBILITY: "int | None"
|
|
46
|
+
_VISIBILITY_LOOKUP: "dict[str, int]"
|
|
47
|
+
|
|
48
|
+
if AQDequeueOptions is None:
|
|
49
|
+
_DEFAULT_VISIBILITY = None
|
|
50
|
+
_VISIBILITY_LOOKUP = {}
|
|
51
|
+
else:
|
|
52
|
+
_DEFAULT_VISIBILITY = AQMSG_VISIBLE
|
|
53
|
+
_VISIBILITY_LOOKUP = {}
|
|
54
|
+
if _DEFAULT_VISIBILITY is not None:
|
|
55
|
+
_VISIBILITY_LOOKUP["AQMSG_VISIBLE"] = _DEFAULT_VISIBILITY
|
|
56
|
+
if AQMSG_INVISIBLE is not None:
|
|
57
|
+
_VISIBILITY_LOOKUP["AQMSG_INVISIBLE"] = AQMSG_INVISIBLE
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _resolve_visibility_setting(value: Any) -> "int | None":
|
|
61
|
+
if value is None:
|
|
62
|
+
return None
|
|
63
|
+
if isinstance(value, int):
|
|
64
|
+
return value
|
|
65
|
+
if not isinstance(value, str):
|
|
66
|
+
msg = f"Invalid aq_visibility value: {value!r}. Expected int or AQMSG_* string."
|
|
67
|
+
raise ImproperConfigurationError(msg)
|
|
68
|
+
visibility = _VISIBILITY_LOOKUP.get(value)
|
|
69
|
+
if visibility is None:
|
|
70
|
+
msg = f"Invalid aq_visibility value: {value!r}. Expected one of: {sorted(_VISIBILITY_LOOKUP)}"
|
|
71
|
+
raise ImproperConfigurationError(msg)
|
|
72
|
+
return visibility
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class OracleSyncAQEventBackend:
|
|
76
|
+
"""Oracle AQ backend for sync Oracle adapters."""
|
|
77
|
+
|
|
78
|
+
__slots__ = ("_config", "_hub", "_queue_name", "_runtime", "_visibility", "_wait_seconds")
|
|
79
|
+
|
|
80
|
+
supports_sync = True
|
|
81
|
+
supports_async = False
|
|
82
|
+
backend_name = "advanced_queue"
|
|
83
|
+
|
|
84
|
+
def __init__(self, config: "OracleSyncConfig", settings: "dict[str, Any] | None" = None) -> None:
|
|
85
|
+
if "oracledb" not in type(config).__module__:
|
|
86
|
+
msg = "Oracle AQ backend requires an Oracle adapter"
|
|
87
|
+
raise ImproperConfigurationError(msg)
|
|
88
|
+
if config.is_async:
|
|
89
|
+
msg = "OracleSyncAQEventBackend requires a sync adapter"
|
|
90
|
+
raise ImproperConfigurationError(msg)
|
|
91
|
+
if not _ORACLEDB_AVAILABLE:
|
|
92
|
+
msg = "oracledb"
|
|
93
|
+
raise MissingDependencyError(msg, install_package="oracledb")
|
|
94
|
+
self._config = config
|
|
95
|
+
self._runtime = config.get_observability_runtime()
|
|
96
|
+
settings = settings or {}
|
|
97
|
+
self._queue_name = settings.get("aq_queue", _DEFAULT_QUEUE_NAME)
|
|
98
|
+
self._visibility: int | None = _resolve_visibility_setting(settings.get("aq_visibility"))
|
|
99
|
+
self._wait_seconds: int = int(settings.get("aq_wait_seconds", 5))
|
|
100
|
+
self._hub: OracleSyncAQHub | None = None
|
|
101
|
+
log_with_context(
|
|
102
|
+
logger,
|
|
103
|
+
logging.DEBUG,
|
|
104
|
+
"event.listen",
|
|
105
|
+
adapter_name="oracledb",
|
|
106
|
+
backend_name=self.backend_name,
|
|
107
|
+
mode="sync",
|
|
108
|
+
status="backend_ready",
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
def publish(self, channel: str, payload: "dict[str, Any]", metadata: "dict[str, Any] | None" = None) -> str:
|
|
112
|
+
event_id = uuid4().hex
|
|
113
|
+
envelope = _build_envelope(channel, event_id, payload, metadata)
|
|
114
|
+
session_cm = self._config.provide_session()
|
|
115
|
+
with session_cm as driver:
|
|
116
|
+
connection = driver.connection
|
|
117
|
+
if connection is None:
|
|
118
|
+
msg = "Oracle driver does not expose a raw connection"
|
|
119
|
+
raise ImproperConfigurationError(msg)
|
|
120
|
+
queue = _get_publish_queue(connection, channel, self._queue_name)
|
|
121
|
+
queue.enqone(payload=envelope)
|
|
122
|
+
driver.commit()
|
|
123
|
+
self._runtime.increment_metric("events.publish.native")
|
|
124
|
+
return event_id
|
|
125
|
+
|
|
126
|
+
def dequeue(self, channel: str, poll_interval: float) -> "EventMessage | None":
|
|
127
|
+
hub = self._ensure_hub()
|
|
128
|
+
payload = hub.dequeue(channel, poll_interval)
|
|
129
|
+
if payload is None:
|
|
130
|
+
return None
|
|
131
|
+
return _parse_message(channel, payload)
|
|
132
|
+
|
|
133
|
+
def ack(self, _event_id: str) -> None:
|
|
134
|
+
"""Acknowledge an event (no-op for Oracle AQ - committed at dequeue time)."""
|
|
135
|
+
self._runtime.increment_metric("events.ack")
|
|
136
|
+
|
|
137
|
+
def nack(self, _event_id: str) -> None:
|
|
138
|
+
"""Return an event to the queue (no-op for Oracle AQ)."""
|
|
139
|
+
|
|
140
|
+
def shutdown(self) -> None:
|
|
141
|
+
hub = self._hub
|
|
142
|
+
if hub is not None:
|
|
143
|
+
self._hub = None
|
|
144
|
+
hub.shutdown()
|
|
145
|
+
|
|
146
|
+
def _ensure_hub(self) -> OracleSyncAQHub:
|
|
147
|
+
if self._hub is None:
|
|
148
|
+
self._hub = OracleSyncAQHub(
|
|
149
|
+
self._config,
|
|
150
|
+
queue_name_template=self._queue_name,
|
|
151
|
+
visibility=self._visibility,
|
|
152
|
+
default_visibility=_DEFAULT_VISIBILITY,
|
|
153
|
+
wait_ceiling=self._wait_seconds,
|
|
154
|
+
)
|
|
155
|
+
return self._hub
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class OracleAsyncAQEventBackend:
|
|
159
|
+
"""Oracle AQ backend for async Oracle adapters."""
|
|
160
|
+
|
|
161
|
+
__slots__ = ("_config", "_hub", "_queue_name", "_runtime", "_visibility", "_wait_seconds")
|
|
162
|
+
|
|
163
|
+
supports_sync = False
|
|
164
|
+
supports_async = True
|
|
165
|
+
backend_name = "advanced_queue"
|
|
166
|
+
|
|
167
|
+
def __init__(self, config: "OracleAsyncConfig", settings: "dict[str, Any] | None" = None) -> None:
|
|
168
|
+
if "oracledb" not in type(config).__module__:
|
|
169
|
+
msg = "Oracle AQ backend requires an Oracle adapter"
|
|
170
|
+
raise ImproperConfigurationError(msg)
|
|
171
|
+
if not config.is_async:
|
|
172
|
+
msg = "OracleAsyncAQEventBackend requires an async adapter"
|
|
173
|
+
raise ImproperConfigurationError(msg)
|
|
174
|
+
if not _ORACLEDB_AVAILABLE:
|
|
175
|
+
msg = "oracledb"
|
|
176
|
+
raise MissingDependencyError(msg, install_package="oracledb")
|
|
177
|
+
self._config = config
|
|
178
|
+
self._runtime = config.get_observability_runtime()
|
|
179
|
+
settings = settings or {}
|
|
180
|
+
self._queue_name = settings.get("aq_queue", _DEFAULT_QUEUE_NAME)
|
|
181
|
+
self._visibility: int | None = _resolve_visibility_setting(settings.get("aq_visibility"))
|
|
182
|
+
self._wait_seconds: int = int(settings.get("aq_wait_seconds", 5))
|
|
183
|
+
self._hub: OracleAsyncAQHub | None = None
|
|
184
|
+
|
|
185
|
+
async def publish(self, channel: str, payload: "dict[str, Any]", metadata: "dict[str, Any] | None" = None) -> str:
|
|
186
|
+
event_id = uuid4().hex
|
|
187
|
+
envelope = _build_envelope(channel, event_id, payload, metadata)
|
|
188
|
+
session_cm = self._config.provide_session()
|
|
189
|
+
async with session_cm as driver:
|
|
190
|
+
connection = driver.connection
|
|
191
|
+
if connection is None:
|
|
192
|
+
msg = "Oracle driver does not expose a raw connection"
|
|
193
|
+
raise ImproperConfigurationError(msg)
|
|
194
|
+
queue = _get_publish_queue(connection, channel, self._queue_name)
|
|
195
|
+
await queue.enqone(payload=envelope)
|
|
196
|
+
await driver.commit()
|
|
197
|
+
self._runtime.increment_metric("events.publish.native")
|
|
198
|
+
return event_id
|
|
199
|
+
|
|
200
|
+
async def dequeue(self, channel: str, poll_interval: float) -> "EventMessage | None":
|
|
201
|
+
hub = self._ensure_hub()
|
|
202
|
+
payload = await hub.dequeue(channel, poll_interval)
|
|
203
|
+
if payload is None:
|
|
204
|
+
return None
|
|
205
|
+
return _parse_message(channel, payload)
|
|
206
|
+
|
|
207
|
+
async def ack(self, _event_id: str) -> None:
|
|
208
|
+
"""Acknowledge an event (no-op for Oracle AQ - committed at dequeue time)."""
|
|
209
|
+
self._runtime.increment_metric("events.ack")
|
|
210
|
+
|
|
211
|
+
async def nack(self, _event_id: str) -> None:
|
|
212
|
+
"""Return an event to the queue (no-op for Oracle AQ)."""
|
|
213
|
+
|
|
214
|
+
async def shutdown(self) -> None:
|
|
215
|
+
hub = self._hub
|
|
216
|
+
if hub is not None:
|
|
217
|
+
self._hub = None
|
|
218
|
+
await hub.shutdown()
|
|
219
|
+
|
|
220
|
+
def _ensure_hub(self) -> OracleAsyncAQHub:
|
|
221
|
+
if self._hub is None:
|
|
222
|
+
self._hub = OracleAsyncAQHub(
|
|
223
|
+
self._config,
|
|
224
|
+
queue_name_template=self._queue_name,
|
|
225
|
+
visibility=self._visibility,
|
|
226
|
+
default_visibility=_DEFAULT_VISIBILITY,
|
|
227
|
+
wait_ceiling=self._wait_seconds,
|
|
228
|
+
)
|
|
229
|
+
return self._hub
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def _get_publish_queue(connection: Any, channel: str, queue_name: str) -> Any:
|
|
233
|
+
"""Acquire a queue handle for a one-shot publish."""
|
|
234
|
+
if not _ORACLEDB_AVAILABLE:
|
|
235
|
+
msg = "oracledb"
|
|
236
|
+
raise MissingDependencyError(msg, install_package="oracledb")
|
|
237
|
+
if isinstance(queue_name, str) and "{" in queue_name:
|
|
238
|
+
with contextlib.suppress(Exception):
|
|
239
|
+
queue_name = queue_name.format(channel=channel.upper())
|
|
240
|
+
payload_type = DB_TYPE_JSON if DB_TYPE_JSON is not None else AQMSG_PAYLOAD_TYPE_JSON
|
|
241
|
+
return connection.queue(queue_name, payload_type=payload_type)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def _build_envelope(
|
|
245
|
+
channel: str, event_id: str, payload: "dict[str, Any]", metadata: "dict[str, Any] | None"
|
|
246
|
+
) -> "dict[str, Any]":
|
|
247
|
+
"""Build event envelope for Oracle AQ."""
|
|
248
|
+
return {
|
|
249
|
+
"channel": channel,
|
|
250
|
+
"event_id": event_id,
|
|
251
|
+
"payload": payload,
|
|
252
|
+
"metadata": metadata,
|
|
253
|
+
"published_at": datetime.now(timezone.utc).isoformat(),
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def _parse_message(channel: str, payload: Any) -> EventMessage:
|
|
258
|
+
"""Parse Oracle AQ message payload into EventMessage."""
|
|
259
|
+
if not isinstance(payload, dict):
|
|
260
|
+
payload = {"payload": payload}
|
|
261
|
+
payload_channel = payload.get("channel")
|
|
262
|
+
message_channel = payload_channel if isinstance(payload_channel, str) else channel
|
|
263
|
+
event_id = payload.get("event_id", uuid4().hex)
|
|
264
|
+
body = payload.get("payload")
|
|
265
|
+
if not isinstance(body, dict):
|
|
266
|
+
body = {"value": body}
|
|
267
|
+
metadata = payload.get("metadata")
|
|
268
|
+
if not (metadata is None or isinstance(metadata, dict)):
|
|
269
|
+
metadata = {"value": metadata}
|
|
270
|
+
timestamp = parse_event_timestamp(payload.get("published_at"))
|
|
271
|
+
return EventMessage(
|
|
272
|
+
event_id=event_id,
|
|
273
|
+
channel=message_channel,
|
|
274
|
+
payload=body,
|
|
275
|
+
metadata=metadata,
|
|
276
|
+
attempts=0,
|
|
277
|
+
available_at=timestamp,
|
|
278
|
+
lease_expires_at=None,
|
|
279
|
+
created_at=timestamp,
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def create_event_backend(
|
|
284
|
+
config: "OracleAsyncConfig | OracleSyncConfig", backend_name: str, extension_settings: "dict[str, Any]"
|
|
285
|
+
) -> "OracleSyncAQEventBackend | OracleAsyncAQEventBackend | None":
|
|
286
|
+
"""Factory used by EventChannel to create the Oracle AQ backend."""
|
|
287
|
+
is_async = config.is_async
|
|
288
|
+
match (backend_name, is_async):
|
|
289
|
+
case ("advanced_queue", False):
|
|
290
|
+
try:
|
|
291
|
+
return OracleSyncAQEventBackend(config, extension_settings) # type: ignore[arg-type]
|
|
292
|
+
except (ImproperConfigurationError, MissingDependencyError):
|
|
293
|
+
return None
|
|
294
|
+
case ("advanced_queue", True):
|
|
295
|
+
try:
|
|
296
|
+
return OracleAsyncAQEventBackend(config, extension_settings) # type: ignore[arg-type]
|
|
297
|
+
except (ImproperConfigurationError, MissingDependencyError):
|
|
298
|
+
return None
|
|
299
|
+
case _:
|
|
300
|
+
return None
|