sqlspec 0.36.0__cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.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.
- ac8f31065839703b4e70__mypyc.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/__init__.py +140 -0
- sqlspec/__main__.py +12 -0
- sqlspec/__metadata__.py +14 -0
- sqlspec/_serialization.py +315 -0
- sqlspec/_typing.py +700 -0
- sqlspec/adapters/__init__.py +0 -0
- sqlspec/adapters/adbc/__init__.py +5 -0
- sqlspec/adapters/adbc/_typing.py +82 -0
- sqlspec/adapters/adbc/adk/__init__.py +5 -0
- sqlspec/adapters/adbc/adk/store.py +1273 -0
- sqlspec/adapters/adbc/config.py +295 -0
- sqlspec/adapters/adbc/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/adbc/core.py +735 -0
- sqlspec/adapters/adbc/data_dictionary.py +334 -0
- sqlspec/adapters/adbc/driver.py +529 -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 +502 -0
- sqlspec/adapters/adbc/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/adbc/type_converter.py +140 -0
- sqlspec/adapters/aiosqlite/__init__.py +25 -0
- sqlspec/adapters/aiosqlite/_typing.py +82 -0
- sqlspec/adapters/aiosqlite/adk/__init__.py +5 -0
- sqlspec/adapters/aiosqlite/adk/store.py +818 -0
- sqlspec/adapters/aiosqlite/config.py +334 -0
- sqlspec/adapters/aiosqlite/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/aiosqlite/core.py +315 -0
- sqlspec/adapters/aiosqlite/data_dictionary.py +208 -0
- sqlspec/adapters/aiosqlite/driver.py +313 -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.py +533 -0
- sqlspec/adapters/asyncmy/__init__.py +21 -0
- sqlspec/adapters/asyncmy/_typing.py +87 -0
- sqlspec/adapters/asyncmy/adk/__init__.py +5 -0
- sqlspec/adapters/asyncmy/adk/store.py +703 -0
- sqlspec/adapters/asyncmy/config.py +302 -0
- sqlspec/adapters/asyncmy/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/asyncmy/core.py +360 -0
- sqlspec/adapters/asyncmy/data_dictionary.py +124 -0
- sqlspec/adapters/asyncmy/driver.py +383 -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 +19 -0
- sqlspec/adapters/asyncpg/_typing.py +88 -0
- sqlspec/adapters/asyncpg/adk/__init__.py +5 -0
- sqlspec/adapters/asyncpg/adk/store.py +748 -0
- sqlspec/adapters/asyncpg/config.py +569 -0
- sqlspec/adapters/asyncpg/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/asyncpg/core.py +367 -0
- sqlspec/adapters/asyncpg/data_dictionary.py +162 -0
- sqlspec/adapters/asyncpg/driver.py +487 -0
- sqlspec/adapters/asyncpg/events/__init__.py +6 -0
- sqlspec/adapters/asyncpg/events/backend.py +286 -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 +14 -0
- sqlspec/adapters/bigquery/_typing.py +86 -0
- sqlspec/adapters/bigquery/adk/__init__.py +5 -0
- sqlspec/adapters/bigquery/adk/store.py +827 -0
- sqlspec/adapters/bigquery/config.py +353 -0
- sqlspec/adapters/bigquery/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/bigquery/core.py +715 -0
- sqlspec/adapters/bigquery/data_dictionary.py +128 -0
- sqlspec/adapters/bigquery/driver.py +548 -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.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/bigquery/type_converter.py +107 -0
- sqlspec/adapters/cockroach_asyncpg/__init__.py +24 -0
- sqlspec/adapters/cockroach_asyncpg/_typing.py +72 -0
- sqlspec/adapters/cockroach_asyncpg/adk/__init__.py +3 -0
- sqlspec/adapters/cockroach_asyncpg/adk/store.py +410 -0
- sqlspec/adapters/cockroach_asyncpg/config.py +238 -0
- sqlspec/adapters/cockroach_asyncpg/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/cockroach_asyncpg/core.py +55 -0
- sqlspec/adapters/cockroach_asyncpg/data_dictionary.py +107 -0
- sqlspec/adapters/cockroach_asyncpg/driver.py +144 -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 +38 -0
- sqlspec/adapters/cockroach_psycopg/_typing.py +129 -0
- sqlspec/adapters/cockroach_psycopg/adk/__init__.py +13 -0
- sqlspec/adapters/cockroach_psycopg/adk/store.py +868 -0
- sqlspec/adapters/cockroach_psycopg/config.py +484 -0
- sqlspec/adapters/cockroach_psycopg/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/cockroach_psycopg/core.py +63 -0
- sqlspec/adapters/cockroach_psycopg/data_dictionary.py +215 -0
- sqlspec/adapters/cockroach_psycopg/driver.py +284 -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 +325 -0
- sqlspec/adapters/duckdb/__init__.py +25 -0
- sqlspec/adapters/duckdb/_typing.py +81 -0
- sqlspec/adapters/duckdb/adk/__init__.py +14 -0
- sqlspec/adapters/duckdb/adk/store.py +850 -0
- sqlspec/adapters/duckdb/config.py +463 -0
- sqlspec/adapters/duckdb/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/duckdb/core.py +257 -0
- sqlspec/adapters/duckdb/data_dictionary.py +140 -0
- sqlspec/adapters/duckdb/driver.py +430 -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.py +293 -0
- sqlspec/adapters/duckdb/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/duckdb/type_converter.py +118 -0
- sqlspec/adapters/mock/__init__.py +72 -0
- sqlspec/adapters/mock/_typing.py +147 -0
- sqlspec/adapters/mock/config.py +483 -0
- sqlspec/adapters/mock/core.py +319 -0
- sqlspec/adapters/mock/data_dictionary.py +366 -0
- sqlspec/adapters/mock/driver.py +721 -0
- sqlspec/adapters/mysqlconnector/__init__.py +36 -0
- sqlspec/adapters/mysqlconnector/_typing.py +141 -0
- sqlspec/adapters/mysqlconnector/adk/__init__.py +15 -0
- sqlspec/adapters/mysqlconnector/adk/store.py +1060 -0
- sqlspec/adapters/mysqlconnector/config.py +394 -0
- sqlspec/adapters/mysqlconnector/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/mysqlconnector/core.py +303 -0
- sqlspec/adapters/mysqlconnector/data_dictionary.py +235 -0
- sqlspec/adapters/mysqlconnector/driver.py +483 -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 +60 -0
- sqlspec/adapters/oracledb/_numpy_handlers.py +141 -0
- sqlspec/adapters/oracledb/_typing.py +182 -0
- sqlspec/adapters/oracledb/_uuid_handlers.py +166 -0
- sqlspec/adapters/oracledb/adk/__init__.py +10 -0
- sqlspec/adapters/oracledb/adk/store.py +2369 -0
- sqlspec/adapters/oracledb/config.py +550 -0
- sqlspec/adapters/oracledb/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/oracledb/core.py +543 -0
- sqlspec/adapters/oracledb/data_dictionary.py +536 -0
- sqlspec/adapters/oracledb/driver.py +1229 -0
- sqlspec/adapters/oracledb/events/__init__.py +16 -0
- sqlspec/adapters/oracledb/events/backend.py +347 -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 +535 -0
- sqlspec/adapters/oracledb/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/oracledb/type_converter.py +211 -0
- sqlspec/adapters/psqlpy/__init__.py +17 -0
- sqlspec/adapters/psqlpy/_typing.py +79 -0
- sqlspec/adapters/psqlpy/adk/__init__.py +5 -0
- sqlspec/adapters/psqlpy/adk/store.py +766 -0
- sqlspec/adapters/psqlpy/config.py +304 -0
- sqlspec/adapters/psqlpy/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/psqlpy/core.py +480 -0
- sqlspec/adapters/psqlpy/data_dictionary.py +126 -0
- sqlspec/adapters/psqlpy/driver.py +438 -0
- sqlspec/adapters/psqlpy/events/__init__.py +6 -0
- sqlspec/adapters/psqlpy/events/backend.py +310 -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.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/psqlpy/type_converter.py +113 -0
- sqlspec/adapters/psycopg/__init__.py +32 -0
- sqlspec/adapters/psycopg/_typing.py +164 -0
- sqlspec/adapters/psycopg/adk/__init__.py +10 -0
- sqlspec/adapters/psycopg/adk/store.py +1387 -0
- sqlspec/adapters/psycopg/config.py +576 -0
- sqlspec/adapters/psycopg/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/psycopg/core.py +450 -0
- sqlspec/adapters/psycopg/data_dictionary.py +289 -0
- sqlspec/adapters/psycopg/driver.py +975 -0
- sqlspec/adapters/psycopg/events/__init__.py +20 -0
- sqlspec/adapters/psycopg/events/backend.py +458 -0
- sqlspec/adapters/psycopg/events/store.py +42 -0
- sqlspec/adapters/psycopg/litestar/__init__.py +5 -0
- sqlspec/adapters/psycopg/litestar/store.py +552 -0
- sqlspec/adapters/psycopg/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/psycopg/type_converter.py +93 -0
- sqlspec/adapters/pymysql/__init__.py +21 -0
- sqlspec/adapters/pymysql/_typing.py +71 -0
- sqlspec/adapters/pymysql/adk/__init__.py +5 -0
- sqlspec/adapters/pymysql/adk/store.py +540 -0
- sqlspec/adapters/pymysql/config.py +195 -0
- sqlspec/adapters/pymysql/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/pymysql/core.py +299 -0
- sqlspec/adapters/pymysql/data_dictionary.py +122 -0
- sqlspec/adapters/pymysql/driver.py +259 -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.py +137 -0
- sqlspec/adapters/spanner/__init__.py +40 -0
- sqlspec/adapters/spanner/_typing.py +86 -0
- sqlspec/adapters/spanner/adk/__init__.py +5 -0
- sqlspec/adapters/spanner/adk/store.py +732 -0
- sqlspec/adapters/spanner/config.py +352 -0
- sqlspec/adapters/spanner/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/spanner/core.py +188 -0
- sqlspec/adapters/spanner/data_dictionary.py +120 -0
- sqlspec/adapters/spanner/dialect/__init__.py +6 -0
- sqlspec/adapters/spanner/dialect/_spangres.py +57 -0
- sqlspec/adapters/spanner/dialect/_spanner.py +130 -0
- sqlspec/adapters/spanner/driver.py +373 -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.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/spanner/type_converter.py +331 -0
- sqlspec/adapters/sqlite/__init__.py +19 -0
- sqlspec/adapters/sqlite/_typing.py +80 -0
- sqlspec/adapters/sqlite/adk/__init__.py +5 -0
- sqlspec/adapters/sqlite/adk/store.py +958 -0
- sqlspec/adapters/sqlite/config.py +280 -0
- sqlspec/adapters/sqlite/core.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/sqlite/core.py +312 -0
- sqlspec/adapters/sqlite/data_dictionary.py +202 -0
- sqlspec/adapters/sqlite/driver.py +359 -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.py +198 -0
- sqlspec/adapters/sqlite/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/adapters/sqlite/type_converter.py +114 -0
- sqlspec/base.py +747 -0
- sqlspec/builder/__init__.py +179 -0
- sqlspec/builder/_base.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_base.py +1022 -0
- sqlspec/builder/_column.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_column.py +521 -0
- sqlspec/builder/_ddl.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_ddl.py +1642 -0
- sqlspec/builder/_delete.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_delete.py +95 -0
- sqlspec/builder/_dml.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_dml.py +365 -0
- sqlspec/builder/_explain.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_explain.py +579 -0
- sqlspec/builder/_expression_wrappers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_expression_wrappers.py +46 -0
- sqlspec/builder/_factory.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_factory.py +1697 -0
- sqlspec/builder/_insert.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_insert.py +328 -0
- sqlspec/builder/_join.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_join.py +499 -0
- sqlspec/builder/_merge.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_merge.py +821 -0
- sqlspec/builder/_parsing_utils.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_parsing_utils.py +297 -0
- sqlspec/builder/_select.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_select.py +1660 -0
- sqlspec/builder/_temporal.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_temporal.py +139 -0
- sqlspec/builder/_update.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/builder/_update.py +173 -0
- sqlspec/builder/_vector_expressions.py +267 -0
- sqlspec/cli.py +911 -0
- sqlspec/config.py +1755 -0
- sqlspec/core/__init__.py +374 -0
- sqlspec/core/_correlation.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/_correlation.py +176 -0
- sqlspec/core/cache.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/cache.py +1069 -0
- sqlspec/core/compiler.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/compiler.py +954 -0
- sqlspec/core/explain.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/explain.py +275 -0
- sqlspec/core/filters.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/filters.py +952 -0
- sqlspec/core/hashing.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/hashing.py +262 -0
- sqlspec/core/metrics.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/metrics.py +83 -0
- sqlspec/core/parameters/__init__.py +71 -0
- sqlspec/core/parameters/_alignment.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_alignment.py +270 -0
- sqlspec/core/parameters/_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_converter.py +543 -0
- sqlspec/core/parameters/_processor.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_processor.py +505 -0
- sqlspec/core/parameters/_registry.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_registry.py +206 -0
- sqlspec/core/parameters/_transformers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_transformers.py +292 -0
- sqlspec/core/parameters/_types.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_types.py +499 -0
- sqlspec/core/parameters/_validator.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/parameters/_validator.py +180 -0
- sqlspec/core/pipeline.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/pipeline.py +319 -0
- sqlspec/core/query_modifiers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/query_modifiers.py +437 -0
- sqlspec/core/result/__init__.py +23 -0
- sqlspec/core/result/_base.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/result/_base.py +1121 -0
- sqlspec/core/result/_io.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/result/_io.py +28 -0
- sqlspec/core/splitter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/splitter.py +966 -0
- sqlspec/core/stack.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/stack.py +163 -0
- sqlspec/core/statement.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/statement.py +1503 -0
- sqlspec/core/type_converter.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/core/type_converter.py +339 -0
- sqlspec/data_dictionary/__init__.py +22 -0
- sqlspec/data_dictionary/_loader.py +123 -0
- sqlspec/data_dictionary/_registry.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/_registry.py +74 -0
- sqlspec/data_dictionary/_types.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/_types.py +121 -0
- sqlspec/data_dictionary/dialects/__init__.py +21 -0
- sqlspec/data_dictionary/dialects/bigquery.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/bigquery.py +49 -0
- sqlspec/data_dictionary/dialects/cockroachdb.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/cockroachdb.py +43 -0
- sqlspec/data_dictionary/dialects/duckdb.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/duckdb.py +47 -0
- sqlspec/data_dictionary/dialects/mysql.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/mysql.py +42 -0
- sqlspec/data_dictionary/dialects/oracle.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/oracle.py +34 -0
- sqlspec/data_dictionary/dialects/postgres.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/postgres.py +46 -0
- sqlspec/data_dictionary/dialects/spanner.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/spanner.py +37 -0
- sqlspec/data_dictionary/dialects/sqlite.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/data_dictionary/dialects/sqlite.py +42 -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/driver/__init__.py +32 -0
- sqlspec/driver/_async.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/driver/_async.py +1737 -0
- sqlspec/driver/_common.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/driver/_common.py +1478 -0
- sqlspec/driver/_sql_helpers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/driver/_sql_helpers.py +148 -0
- sqlspec/driver/_storage_helpers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/driver/_storage_helpers.py +144 -0
- sqlspec/driver/_sync.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/driver/_sync.py +1710 -0
- sqlspec/exceptions.py +338 -0
- sqlspec/extensions/__init__.py +0 -0
- sqlspec/extensions/adk/__init__.py +70 -0
- sqlspec/extensions/adk/_types.py +51 -0
- sqlspec/extensions/adk/converters.py +172 -0
- sqlspec/extensions/adk/memory/__init__.py +69 -0
- sqlspec/extensions/adk/memory/_types.py +30 -0
- sqlspec/extensions/adk/memory/converters.py +149 -0
- sqlspec/extensions/adk/memory/service.py +217 -0
- sqlspec/extensions/adk/memory/store.py +569 -0
- sqlspec/extensions/adk/migrations/0001_create_adk_tables.py +246 -0
- sqlspec/extensions/adk/migrations/__init__.py +0 -0
- sqlspec/extensions/adk/service.py +225 -0
- sqlspec/extensions/adk/store.py +567 -0
- sqlspec/extensions/events/__init__.py +51 -0
- sqlspec/extensions/events/_channel.py +703 -0
- sqlspec/extensions/events/_hints.py +45 -0
- sqlspec/extensions/events/_models.py +23 -0
- sqlspec/extensions/events/_payload.py +69 -0
- sqlspec/extensions/events/_protocols.py +134 -0
- sqlspec/extensions/events/_queue.py +461 -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 +19 -0
- sqlspec/extensions/fastapi/extension.py +351 -0
- sqlspec/extensions/fastapi/providers.py +607 -0
- sqlspec/extensions/flask/__init__.py +37 -0
- sqlspec/extensions/flask/_state.py +76 -0
- sqlspec/extensions/flask/_utils.py +71 -0
- sqlspec/extensions/flask/extension.py +519 -0
- sqlspec/extensions/litestar/__init__.py +28 -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 +671 -0
- sqlspec/extensions/litestar/providers.py +526 -0
- sqlspec/extensions/litestar/store.py +296 -0
- sqlspec/extensions/otel/__init__.py +58 -0
- sqlspec/extensions/prometheus/__init__.py +113 -0
- sqlspec/extensions/starlette/__init__.py +19 -0
- sqlspec/extensions/starlette/_state.py +30 -0
- sqlspec/extensions/starlette/_utils.py +96 -0
- sqlspec/extensions/starlette/extension.py +346 -0
- sqlspec/extensions/starlette/middleware.py +235 -0
- sqlspec/loader.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/loader.py +702 -0
- sqlspec/migrations/__init__.py +36 -0
- sqlspec/migrations/base.py +731 -0
- sqlspec/migrations/commands.py +1232 -0
- sqlspec/migrations/context.py +157 -0
- sqlspec/migrations/fix.py +204 -0
- sqlspec/migrations/loaders.py +443 -0
- sqlspec/migrations/runner.py +1172 -0
- sqlspec/migrations/templates.py +234 -0
- sqlspec/migrations/tracker.py +611 -0
- sqlspec/migrations/utils.py +256 -0
- sqlspec/migrations/validation.py +207 -0
- sqlspec/migrations/version.py +446 -0
- sqlspec/observability/__init__.py +55 -0
- sqlspec/observability/_common.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_common.py +77 -0
- sqlspec/observability/_config.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_config.py +348 -0
- sqlspec/observability/_diagnostics.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_diagnostics.py +74 -0
- sqlspec/observability/_dispatcher.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_dispatcher.py +152 -0
- sqlspec/observability/_formatters/__init__.py +13 -0
- sqlspec/observability/_formatters/_aws.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_formatters/_aws.py +102 -0
- sqlspec/observability/_formatters/_azure.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_formatters/_azure.py +96 -0
- sqlspec/observability/_formatters/_base.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_formatters/_base.py +57 -0
- sqlspec/observability/_formatters/_gcp.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_formatters/_gcp.py +131 -0
- sqlspec/observability/_formatting.py +58 -0
- sqlspec/observability/_observer.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_observer.py +357 -0
- sqlspec/observability/_runtime.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_runtime.py +420 -0
- sqlspec/observability/_sampling.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_sampling.py +188 -0
- sqlspec/observability/_spans.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/observability/_spans.py +161 -0
- sqlspec/protocols.py +916 -0
- sqlspec/py.typed +0 -0
- sqlspec/storage/__init__.py +48 -0
- sqlspec/storage/_utils.py +104 -0
- sqlspec/storage/backends/__init__.py +1 -0
- sqlspec/storage/backends/base.py +253 -0
- sqlspec/storage/backends/fsspec.py +529 -0
- sqlspec/storage/backends/local.py +441 -0
- sqlspec/storage/backends/obstore.py +916 -0
- sqlspec/storage/errors.py +104 -0
- sqlspec/storage/pipeline.py +582 -0
- sqlspec/storage/registry.py +301 -0
- sqlspec/typing.py +395 -0
- sqlspec/utils/__init__.py +7 -0
- sqlspec/utils/arrow_helpers.py +318 -0
- sqlspec/utils/config_tools.py +332 -0
- sqlspec/utils/correlation.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/correlation.py +134 -0
- sqlspec/utils/deprecation.py +190 -0
- sqlspec/utils/fixtures.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/fixtures.py +258 -0
- sqlspec/utils/logging.py +222 -0
- sqlspec/utils/module_loader.py +306 -0
- sqlspec/utils/portal.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/portal.py +375 -0
- sqlspec/utils/schema.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/schema.py +485 -0
- sqlspec/utils/serializers.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/serializers.py +408 -0
- sqlspec/utils/singleton.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/singleton.py +41 -0
- sqlspec/utils/sync_tools.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/sync_tools.py +311 -0
- sqlspec/utils/text.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/text.py +108 -0
- sqlspec/utils/type_converters.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/type_converters.py +128 -0
- sqlspec/utils/type_guards.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/type_guards.py +1360 -0
- sqlspec/utils/uuids.cpython-310-aarch64-linux-gnu.so +0 -0
- sqlspec/utils/uuids.py +225 -0
- sqlspec-0.36.0.dist-info/METADATA +205 -0
- sqlspec-0.36.0.dist-info/RECORD +531 -0
- sqlspec-0.36.0.dist-info/WHEEL +7 -0
- sqlspec-0.36.0.dist-info/entry_points.txt +2 -0
- sqlspec-0.36.0.dist-info/licenses/LICENSE +21 -0
|
Binary file
|
sqlspec/core/hashing.py
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"""Statement hashing utilities for cache key generation.
|
|
2
|
+
|
|
3
|
+
Provides hashing functions for SQL statements, expressions, parameters,
|
|
4
|
+
filters, and AST sub-expressions.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import TYPE_CHECKING, Any
|
|
8
|
+
|
|
9
|
+
from sqlglot import exp
|
|
10
|
+
|
|
11
|
+
from sqlspec.core.parameters import TypedParameter
|
|
12
|
+
from sqlspec.utils.type_guards import is_expression, is_typed_parameter
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from collections.abc import Sequence
|
|
16
|
+
|
|
17
|
+
from sqlspec.core.filters import StatementFilter
|
|
18
|
+
from sqlspec.core.statement import SQL
|
|
19
|
+
|
|
20
|
+
__all__ = (
|
|
21
|
+
"hash_expression",
|
|
22
|
+
"hash_expression_node",
|
|
23
|
+
"hash_optimized_expression",
|
|
24
|
+
"hash_parameters",
|
|
25
|
+
"hash_sql_statement",
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def hash_expression(expr: "exp.Expression | None", _seen: "set[int] | None" = None) -> int:
|
|
30
|
+
"""Generate hash from AST structure.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
expr: SQLGlot Expression to hash
|
|
34
|
+
_seen: Set of seen object IDs to handle circular references
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Hash of the AST structure
|
|
38
|
+
"""
|
|
39
|
+
if expr is None:
|
|
40
|
+
return hash(None)
|
|
41
|
+
|
|
42
|
+
if _seen is None:
|
|
43
|
+
_seen = set()
|
|
44
|
+
|
|
45
|
+
expr_id = id(expr)
|
|
46
|
+
if expr_id in _seen:
|
|
47
|
+
return hash(expr_id)
|
|
48
|
+
|
|
49
|
+
_seen.add(expr_id)
|
|
50
|
+
|
|
51
|
+
components: list[Any] = [type(expr).__name__]
|
|
52
|
+
|
|
53
|
+
for key, value in sorted(expr.args.items()):
|
|
54
|
+
components.extend((key, _hash_value(value, _seen)))
|
|
55
|
+
|
|
56
|
+
return hash(tuple(components))
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _hash_value(value: Any, _seen: "set[int]") -> int:
|
|
60
|
+
"""Hash different value types.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
value: Value to hash (can be Expression, list, dict, or primitive)
|
|
64
|
+
_seen: Set of seen object IDs to handle circular references
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
Hash of the value
|
|
68
|
+
"""
|
|
69
|
+
if isinstance(value, exp.Expression):
|
|
70
|
+
return hash_expression(value, _seen)
|
|
71
|
+
if isinstance(value, list):
|
|
72
|
+
return hash(tuple(_hash_value(v, _seen) for v in value))
|
|
73
|
+
if isinstance(value, dict):
|
|
74
|
+
items = sorted((k, _hash_value(v, _seen)) for k, v in value.items())
|
|
75
|
+
return hash(tuple(items))
|
|
76
|
+
if isinstance(value, tuple):
|
|
77
|
+
return hash(tuple(_hash_value(v, _seen) for v in value))
|
|
78
|
+
|
|
79
|
+
return hash(value)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def hash_parameters(
|
|
83
|
+
positional_parameters: "list[Any] | None" = None,
|
|
84
|
+
named_parameters: "dict[str, Any] | None" = None,
|
|
85
|
+
original_parameters: Any | None = None,
|
|
86
|
+
) -> int:
|
|
87
|
+
"""Generate hash for SQL parameters.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
positional_parameters: List of positional parameters
|
|
91
|
+
named_parameters: Dictionary of named parameters
|
|
92
|
+
original_parameters: Original parameters (for execute_many)
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
Combined hash of all parameters
|
|
96
|
+
"""
|
|
97
|
+
param_hash = 0
|
|
98
|
+
|
|
99
|
+
if positional_parameters:
|
|
100
|
+
hashable_parameters: list[tuple[Any, Any]] = []
|
|
101
|
+
for param in positional_parameters:
|
|
102
|
+
if isinstance(param, TypedParameter):
|
|
103
|
+
if isinstance(param.value, (list, dict)):
|
|
104
|
+
hashable_parameters.append((repr(param.value), param.original_type))
|
|
105
|
+
else:
|
|
106
|
+
hashable_parameters.append((param.value, param.original_type))
|
|
107
|
+
elif isinstance(param, (list, dict)):
|
|
108
|
+
hashable_parameters.append((repr(param), "unhashable"))
|
|
109
|
+
else:
|
|
110
|
+
try:
|
|
111
|
+
hash(param)
|
|
112
|
+
hashable_parameters.append((param, "primitive"))
|
|
113
|
+
except TypeError:
|
|
114
|
+
hashable_parameters.append((repr(param), "unhashable_repr"))
|
|
115
|
+
|
|
116
|
+
param_hash ^= hash(tuple(hashable_parameters))
|
|
117
|
+
|
|
118
|
+
if named_parameters:
|
|
119
|
+
hashable_items: list[tuple[str, tuple[Any, Any]]] = []
|
|
120
|
+
for key, value in sorted(named_parameters.items()):
|
|
121
|
+
if is_typed_parameter(value):
|
|
122
|
+
if isinstance(value.value, (list, dict)):
|
|
123
|
+
hashable_items.append((key, (repr(value.value), value.original_type)))
|
|
124
|
+
else:
|
|
125
|
+
hashable_items.append((key, (value.value, value.original_type)))
|
|
126
|
+
elif isinstance(value, (list, dict)):
|
|
127
|
+
hashable_items.append((key, (repr(value), "unhashable")))
|
|
128
|
+
else:
|
|
129
|
+
hashable_items.append((key, (value, "primitive")))
|
|
130
|
+
param_hash ^= hash(tuple(hashable_items))
|
|
131
|
+
|
|
132
|
+
if original_parameters is not None:
|
|
133
|
+
if isinstance(original_parameters, list):
|
|
134
|
+
param_hash ^= hash(("original_count", len(original_parameters)))
|
|
135
|
+
if original_parameters:
|
|
136
|
+
sample_size = min(3, len(original_parameters))
|
|
137
|
+
sample_hash = hash(repr(original_parameters[:sample_size]))
|
|
138
|
+
param_hash ^= hash(("original_sample", sample_hash))
|
|
139
|
+
else:
|
|
140
|
+
param_hash ^= hash(("original", repr(original_parameters)))
|
|
141
|
+
|
|
142
|
+
return param_hash
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def _hash_filter_value(value: Any) -> int:
|
|
146
|
+
try:
|
|
147
|
+
return hash(value)
|
|
148
|
+
except TypeError:
|
|
149
|
+
return hash(repr(value))
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def hash_filters(filters: "Sequence[StatementFilter] | None" = None) -> int:
|
|
153
|
+
"""Generate hash for statement filters.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
filters: List of statement filters
|
|
157
|
+
|
|
158
|
+
Returns:
|
|
159
|
+
Hash of the filters
|
|
160
|
+
"""
|
|
161
|
+
if not filters:
|
|
162
|
+
return 0
|
|
163
|
+
|
|
164
|
+
return hash(tuple(f.get_cache_key() for f in filters))
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def hash_sql_statement(statement: "SQL") -> str:
|
|
168
|
+
"""Generate cache key for a SQL statement.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
statement: SQL statement object
|
|
172
|
+
|
|
173
|
+
Returns:
|
|
174
|
+
Cache key string
|
|
175
|
+
"""
|
|
176
|
+
stmt_expr = statement.statement_expression
|
|
177
|
+
expr_hash = hash_expression(stmt_expr) if is_expression(stmt_expr) else hash(statement.raw_sql)
|
|
178
|
+
|
|
179
|
+
param_hash = hash_parameters(
|
|
180
|
+
positional_parameters=statement.positional_parameters,
|
|
181
|
+
named_parameters=statement.named_parameters,
|
|
182
|
+
original_parameters=statement.original_parameters,
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
filter_hash = hash_filters(statement.filters)
|
|
186
|
+
|
|
187
|
+
state_components = [
|
|
188
|
+
expr_hash,
|
|
189
|
+
param_hash,
|
|
190
|
+
filter_hash,
|
|
191
|
+
hash(statement.dialect),
|
|
192
|
+
hash(statement.is_many),
|
|
193
|
+
hash(statement.is_script),
|
|
194
|
+
]
|
|
195
|
+
|
|
196
|
+
return f"sql:{hash(tuple(state_components))}"
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def hash_expression_node(node: exp.Expression, include_children: bool = True, dialect: str | None = None) -> str:
|
|
200
|
+
"""Generate cache key for an expression node.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
node: The expression node to hash
|
|
204
|
+
include_children: Whether to include child nodes in the hash
|
|
205
|
+
dialect: SQL dialect for context-aware hashing
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
Cache key string for the expression node
|
|
209
|
+
"""
|
|
210
|
+
if include_children:
|
|
211
|
+
node_hash = hash_expression(node)
|
|
212
|
+
else:
|
|
213
|
+
components: list[Any] = [type(node).__name__]
|
|
214
|
+
for key, value in sorted(node.args.items()):
|
|
215
|
+
if not isinstance(value, (list, exp.Expression)):
|
|
216
|
+
components.extend((key, hash(value)))
|
|
217
|
+
node_hash = hash(tuple(components))
|
|
218
|
+
|
|
219
|
+
dialect_part = f":{dialect}" if dialect else ""
|
|
220
|
+
return f"expr{dialect_part}:{node_hash}"
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def hash_optimized_expression(
|
|
224
|
+
expr: exp.Expression,
|
|
225
|
+
dialect: str,
|
|
226
|
+
schema: "dict[str, Any] | None" = None,
|
|
227
|
+
optimizer_settings: "dict[str, Any] | None" = None,
|
|
228
|
+
) -> str:
|
|
229
|
+
"""Generate cache key for optimized expressions.
|
|
230
|
+
|
|
231
|
+
Creates a key that includes expression structure, dialect, schema
|
|
232
|
+
context, and optimizer settings.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
expr: The unoptimized expression
|
|
236
|
+
dialect: Target SQL dialect
|
|
237
|
+
schema: Schema information
|
|
238
|
+
optimizer_settings: Additional optimizer configuration
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
Cache key string for the optimized expression
|
|
242
|
+
"""
|
|
243
|
+
|
|
244
|
+
expr_hash = hash_expression(expr)
|
|
245
|
+
|
|
246
|
+
schema_hash = 0
|
|
247
|
+
if schema:
|
|
248
|
+
schema_items = []
|
|
249
|
+
for table_name, table_schema in sorted(schema.items()):
|
|
250
|
+
if isinstance(table_schema, dict):
|
|
251
|
+
schema_items.append((table_name, len(table_schema)))
|
|
252
|
+
else:
|
|
253
|
+
schema_items.append((table_name, hash("unknown")))
|
|
254
|
+
schema_hash = hash(tuple(schema_items))
|
|
255
|
+
|
|
256
|
+
settings_hash = 0
|
|
257
|
+
if optimizer_settings:
|
|
258
|
+
settings_items = sorted(optimizer_settings.items())
|
|
259
|
+
settings_hash = hash(tuple(settings_items))
|
|
260
|
+
|
|
261
|
+
components = (expr_hash, dialect, schema_hash, settings_hash)
|
|
262
|
+
return f"opt:{hash(components)}"
|
|
Binary file
|
sqlspec/core/metrics.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""Telemetry helper objects for stack execution."""
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING: # pragma: no cover - imported for typing only
|
|
6
|
+
from sqlspec.observability import ObservabilityRuntime
|
|
7
|
+
|
|
8
|
+
__all__ = ("StackExecutionMetrics",)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class StackExecutionMetrics:
|
|
12
|
+
"""Capture telemetry facts about a stack execution."""
|
|
13
|
+
|
|
14
|
+
__slots__ = (
|
|
15
|
+
"adapter",
|
|
16
|
+
"continue_on_error",
|
|
17
|
+
"duration_s",
|
|
18
|
+
"error_count",
|
|
19
|
+
"error_type",
|
|
20
|
+
"forced_disable",
|
|
21
|
+
"native_pipeline",
|
|
22
|
+
"statement_count",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
adapter: str,
|
|
28
|
+
statement_count: int,
|
|
29
|
+
*,
|
|
30
|
+
continue_on_error: bool,
|
|
31
|
+
native_pipeline: bool,
|
|
32
|
+
forced_disable: bool,
|
|
33
|
+
) -> None:
|
|
34
|
+
self.adapter = adapter
|
|
35
|
+
self.statement_count = statement_count
|
|
36
|
+
self.continue_on_error = continue_on_error
|
|
37
|
+
self.native_pipeline = native_pipeline
|
|
38
|
+
self.forced_disable = forced_disable
|
|
39
|
+
self.duration_s = 0.0
|
|
40
|
+
self.error_type: str | None = None
|
|
41
|
+
self.error_count = 0
|
|
42
|
+
|
|
43
|
+
def record_duration(self, duration: float) -> None:
|
|
44
|
+
"""Record execution duration in seconds."""
|
|
45
|
+
|
|
46
|
+
self.duration_s = duration
|
|
47
|
+
|
|
48
|
+
def record_operation_error(self, error: Exception) -> None:
|
|
49
|
+
"""Record an operation error when continue-on-error is enabled."""
|
|
50
|
+
|
|
51
|
+
self.error_count += 1
|
|
52
|
+
if not self.continue_on_error and self.error_type is None:
|
|
53
|
+
self.error_type = type(error).__name__
|
|
54
|
+
|
|
55
|
+
def record_error(self, error: Exception) -> None:
|
|
56
|
+
"""Record a terminal error."""
|
|
57
|
+
|
|
58
|
+
self.error_type = type(error).__name__
|
|
59
|
+
self.error_count = max(self.error_count, 1)
|
|
60
|
+
|
|
61
|
+
def emit(self, runtime: "ObservabilityRuntime") -> None:
|
|
62
|
+
"""Emit collected metrics to the configured runtime."""
|
|
63
|
+
|
|
64
|
+
runtime.increment_metric("stack.execute.invocations")
|
|
65
|
+
runtime.increment_metric("stack.execute.statements", float(self.statement_count))
|
|
66
|
+
|
|
67
|
+
mode = "continue" if self.continue_on_error else "failfast"
|
|
68
|
+
runtime.increment_metric(f"stack.execute.mode.{mode}")
|
|
69
|
+
|
|
70
|
+
pipeline_label = "native" if self.native_pipeline else "sequential"
|
|
71
|
+
runtime.increment_metric(f"stack.execute.path.{pipeline_label}")
|
|
72
|
+
|
|
73
|
+
if self.forced_disable:
|
|
74
|
+
runtime.increment_metric("stack.execute.override.forced")
|
|
75
|
+
|
|
76
|
+
runtime.increment_metric("stack.execute.duration_ms", self.duration_s * 1000.0)
|
|
77
|
+
|
|
78
|
+
if self.error_type is not None:
|
|
79
|
+
runtime.increment_metric("stack.execute.errors")
|
|
80
|
+
runtime.increment_metric(f"stack.execute.errors.{self.error_type}")
|
|
81
|
+
|
|
82
|
+
if self.error_count and self.continue_on_error:
|
|
83
|
+
runtime.increment_metric("stack.execute.partial_errors", float(self.error_count))
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""Parameter processing public API."""
|
|
2
|
+
|
|
3
|
+
from sqlspec.core.parameters._alignment import (
|
|
4
|
+
EXECUTE_MANY_MIN_ROWS,
|
|
5
|
+
collect_null_parameter_ordinals,
|
|
6
|
+
looks_like_execute_many,
|
|
7
|
+
normalize_parameter_key,
|
|
8
|
+
validate_parameter_alignment,
|
|
9
|
+
)
|
|
10
|
+
from sqlspec.core.parameters._converter import ParameterConverter
|
|
11
|
+
from sqlspec.core.parameters._processor import ParameterProcessor, fingerprint_parameters
|
|
12
|
+
from sqlspec.core.parameters._registry import (
|
|
13
|
+
DRIVER_PARAMETER_PROFILES,
|
|
14
|
+
build_statement_config_from_profile,
|
|
15
|
+
get_driver_profile,
|
|
16
|
+
register_driver_profile,
|
|
17
|
+
)
|
|
18
|
+
from sqlspec.core.parameters._transformers import (
|
|
19
|
+
build_literal_inlining_transform,
|
|
20
|
+
build_null_pruning_transform,
|
|
21
|
+
replace_null_parameters_with_literals,
|
|
22
|
+
replace_placeholders_with_literals,
|
|
23
|
+
)
|
|
24
|
+
from sqlspec.core.parameters._types import (
|
|
25
|
+
DriverParameterProfile,
|
|
26
|
+
ParameterInfo,
|
|
27
|
+
ParameterMapping,
|
|
28
|
+
ParameterPayload,
|
|
29
|
+
ParameterProcessingResult,
|
|
30
|
+
ParameterProfile,
|
|
31
|
+
ParameterSequence,
|
|
32
|
+
ParameterStyle,
|
|
33
|
+
ParameterStyleConfig,
|
|
34
|
+
TypedParameter,
|
|
35
|
+
is_iterable_parameters,
|
|
36
|
+
wrap_with_type,
|
|
37
|
+
)
|
|
38
|
+
from sqlspec.core.parameters._validator import PARAMETER_REGEX, ParameterValidator
|
|
39
|
+
|
|
40
|
+
__all__ = (
|
|
41
|
+
"DRIVER_PARAMETER_PROFILES",
|
|
42
|
+
"EXECUTE_MANY_MIN_ROWS",
|
|
43
|
+
"PARAMETER_REGEX",
|
|
44
|
+
"DriverParameterProfile",
|
|
45
|
+
"ParameterConverter",
|
|
46
|
+
"ParameterInfo",
|
|
47
|
+
"ParameterMapping",
|
|
48
|
+
"ParameterPayload",
|
|
49
|
+
"ParameterProcessingResult",
|
|
50
|
+
"ParameterProcessor",
|
|
51
|
+
"ParameterProfile",
|
|
52
|
+
"ParameterSequence",
|
|
53
|
+
"ParameterStyle",
|
|
54
|
+
"ParameterStyleConfig",
|
|
55
|
+
"ParameterValidator",
|
|
56
|
+
"TypedParameter",
|
|
57
|
+
"build_literal_inlining_transform",
|
|
58
|
+
"build_null_pruning_transform",
|
|
59
|
+
"build_statement_config_from_profile",
|
|
60
|
+
"collect_null_parameter_ordinals",
|
|
61
|
+
"fingerprint_parameters",
|
|
62
|
+
"get_driver_profile",
|
|
63
|
+
"is_iterable_parameters",
|
|
64
|
+
"looks_like_execute_many",
|
|
65
|
+
"normalize_parameter_key",
|
|
66
|
+
"register_driver_profile",
|
|
67
|
+
"replace_null_parameters_with_literals",
|
|
68
|
+
"replace_placeholders_with_literals",
|
|
69
|
+
"validate_parameter_alignment",
|
|
70
|
+
"wrap_with_type",
|
|
71
|
+
)
|
|
Binary file
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"""Parameter alignment and validation helpers."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping, Sequence
|
|
4
|
+
from typing import Any, cast
|
|
5
|
+
|
|
6
|
+
import sqlspec.exceptions
|
|
7
|
+
from sqlspec.core.parameters._types import ParameterProfile, ParameterStyle
|
|
8
|
+
|
|
9
|
+
__all__ = (
|
|
10
|
+
"EXECUTE_MANY_MIN_ROWS",
|
|
11
|
+
"collect_null_parameter_ordinals",
|
|
12
|
+
"looks_like_execute_many",
|
|
13
|
+
"normalize_parameter_key",
|
|
14
|
+
"validate_parameter_alignment",
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
EXECUTE_MANY_MIN_ROWS: int = 2
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _is_sequence_like(value: Any) -> bool:
|
|
21
|
+
return isinstance(value, Sequence) and not isinstance(value, (str, bytes, bytearray))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def normalize_parameter_key(key: Any) -> "tuple[str, int | str]":
|
|
25
|
+
"""Normalize a parameter key into an ``(kind, value)`` tuple.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
key: Key supplied by the caller (index, name, or adapter-specific token).
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
Tuple identifying the key type and canonical value for alignment checks.
|
|
32
|
+
"""
|
|
33
|
+
if isinstance(key, str):
|
|
34
|
+
stripped_numeric = key.lstrip("$")
|
|
35
|
+
if stripped_numeric.isdigit():
|
|
36
|
+
return ("index", int(stripped_numeric) - 1)
|
|
37
|
+
if key.isdigit():
|
|
38
|
+
return ("index", int(key) - 1)
|
|
39
|
+
return ("named", key)
|
|
40
|
+
if isinstance(key, int):
|
|
41
|
+
if key > 0:
|
|
42
|
+
return ("index", key - 1)
|
|
43
|
+
return ("index", key)
|
|
44
|
+
return ("named", str(key))
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def looks_like_execute_many(parameters: Any) -> bool:
|
|
48
|
+
"""Return ``True`` when the payload resembles an ``execute_many`` structure.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
parameters: Potential parameter payload to inspect.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
``True`` if the payload appears to be a sequence of parameter sets.
|
|
55
|
+
"""
|
|
56
|
+
if not _is_sequence_like(parameters) or len(parameters) < EXECUTE_MANY_MIN_ROWS:
|
|
57
|
+
return False
|
|
58
|
+
return all(_is_sequence_like(entry) or isinstance(entry, Mapping) for entry in parameters)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def collect_null_parameter_ordinals(parameters: Any, profile: "ParameterProfile") -> "set[int]":
|
|
62
|
+
"""Identify placeholder ordinals whose provided values are ``None``.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
parameters: Parameter payload supplied by the caller.
|
|
66
|
+
profile: Metadata describing detected placeholders.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
Set of ordinal indices corresponding to ``None`` values.
|
|
70
|
+
"""
|
|
71
|
+
if parameters is None:
|
|
72
|
+
return set()
|
|
73
|
+
|
|
74
|
+
null_positions: set[int] = set()
|
|
75
|
+
|
|
76
|
+
if isinstance(parameters, Mapping):
|
|
77
|
+
name_lookup: dict[str, int] = {}
|
|
78
|
+
for parameter in profile.parameters:
|
|
79
|
+
if parameter.name:
|
|
80
|
+
name_lookup[parameter.name] = parameter.ordinal
|
|
81
|
+
stripped_name = parameter.name.lstrip("@")
|
|
82
|
+
name_lookup.setdefault(stripped_name, parameter.ordinal)
|
|
83
|
+
name_lookup.setdefault(f"@{stripped_name}", parameter.ordinal)
|
|
84
|
+
|
|
85
|
+
for key, value in parameters.items():
|
|
86
|
+
if value is not None:
|
|
87
|
+
continue
|
|
88
|
+
key_kind, normalized_key = normalize_parameter_key(key)
|
|
89
|
+
if key_kind == "index" and isinstance(normalized_key, int):
|
|
90
|
+
null_positions.add(normalized_key)
|
|
91
|
+
continue
|
|
92
|
+
if key_kind == "named":
|
|
93
|
+
ordinal = name_lookup.get(str(normalized_key))
|
|
94
|
+
if ordinal is not None:
|
|
95
|
+
null_positions.add(ordinal)
|
|
96
|
+
return null_positions
|
|
97
|
+
|
|
98
|
+
if isinstance(parameters, Sequence) and not isinstance(parameters, (str, bytes, bytearray)):
|
|
99
|
+
for index, value in enumerate(parameters):
|
|
100
|
+
if value is None:
|
|
101
|
+
null_positions.add(index)
|
|
102
|
+
return null_positions
|
|
103
|
+
|
|
104
|
+
return null_positions
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _collect_expected_identifiers(parameter_profile: "ParameterProfile") -> "set[tuple[str, int | str]]":
|
|
108
|
+
identifiers: set[tuple[str, int | str]] = set()
|
|
109
|
+
for parameter in parameter_profile.parameters:
|
|
110
|
+
style = parameter.style
|
|
111
|
+
name = parameter.name
|
|
112
|
+
if style in {
|
|
113
|
+
ParameterStyle.NAMED_COLON,
|
|
114
|
+
ParameterStyle.NAMED_AT,
|
|
115
|
+
ParameterStyle.NAMED_DOLLAR,
|
|
116
|
+
ParameterStyle.NAMED_PYFORMAT,
|
|
117
|
+
}:
|
|
118
|
+
identifiers.add(("named", name or f"param_{parameter.ordinal}"))
|
|
119
|
+
elif style in {ParameterStyle.NUMERIC, ParameterStyle.POSITIONAL_COLON}:
|
|
120
|
+
if name and name.isdigit():
|
|
121
|
+
identifiers.add(("index", int(name) - 1))
|
|
122
|
+
else:
|
|
123
|
+
identifiers.add(("index", parameter.ordinal))
|
|
124
|
+
else:
|
|
125
|
+
identifiers.add(("index", parameter.ordinal))
|
|
126
|
+
return identifiers
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _collect_actual_identifiers(parameters: Any) -> "tuple[set[tuple[str, int | str]], int]":
|
|
130
|
+
if parameters is None:
|
|
131
|
+
return set(), 0
|
|
132
|
+
if isinstance(parameters, Mapping):
|
|
133
|
+
mapping_identifiers = {normalize_parameter_key(key) for key in parameters}
|
|
134
|
+
return mapping_identifiers, len(parameters)
|
|
135
|
+
if looks_like_execute_many(parameters):
|
|
136
|
+
aggregated_identifiers: set[tuple[str, int | str]] = set()
|
|
137
|
+
for entry in parameters:
|
|
138
|
+
entry_identifiers, _ = _collect_actual_identifiers(entry)
|
|
139
|
+
aggregated_identifiers.update(entry_identifiers)
|
|
140
|
+
return aggregated_identifiers, len(aggregated_identifiers)
|
|
141
|
+
if _is_sequence_like(parameters):
|
|
142
|
+
identifiers = {("index", cast("int | str", index)) for index in range(len(parameters))}
|
|
143
|
+
return identifiers, len(parameters)
|
|
144
|
+
identifiers = {("index", cast("int | str", 0))}
|
|
145
|
+
return identifiers, 1
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _format_identifiers(identifiers: "set[tuple[str, int | str]]") -> str:
|
|
149
|
+
if not identifiers:
|
|
150
|
+
return "[]"
|
|
151
|
+
formatted: list[str] = []
|
|
152
|
+
for identifier in sorted(identifiers, key=_identifier_sort_key):
|
|
153
|
+
kind, value = identifier
|
|
154
|
+
if kind == "named":
|
|
155
|
+
formatted.append(str(value))
|
|
156
|
+
elif isinstance(value, int):
|
|
157
|
+
formatted.append(str(value + 1))
|
|
158
|
+
else:
|
|
159
|
+
formatted.append(str(value))
|
|
160
|
+
return "[" + ", ".join(formatted) + "]"
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _identifier_sort_key(item: "tuple[str, int | str]") -> "tuple[str, str]":
|
|
164
|
+
return item[0], str(item[1])
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def _normalize_index_identifiers(expected: "set[tuple[str, int | str]]", actual: "set[tuple[str, int | str]]") -> bool:
|
|
168
|
+
"""Allow positional payloads to satisfy generated param_N identifiers."""
|
|
169
|
+
|
|
170
|
+
if not expected or not actual:
|
|
171
|
+
return False
|
|
172
|
+
|
|
173
|
+
expected_named = {value for kind, value in expected if kind == "named"}
|
|
174
|
+
actual_indexes = {value for kind, value in actual if kind == "index"}
|
|
175
|
+
|
|
176
|
+
if not expected_named or not actual_indexes:
|
|
177
|
+
return False
|
|
178
|
+
|
|
179
|
+
normalized_expected: set[int] = set()
|
|
180
|
+
for name in expected_named:
|
|
181
|
+
if not isinstance(name, str) or not name.startswith("param_"):
|
|
182
|
+
return False
|
|
183
|
+
suffix = name[6:]
|
|
184
|
+
if not suffix.isdigit():
|
|
185
|
+
return False
|
|
186
|
+
normalized_expected.add(int(suffix))
|
|
187
|
+
|
|
188
|
+
if not normalized_expected:
|
|
189
|
+
return False
|
|
190
|
+
|
|
191
|
+
if not all(isinstance(index, int) for index in actual_indexes):
|
|
192
|
+
return False
|
|
193
|
+
|
|
194
|
+
normalized_actual = {int(index) for index in actual_indexes}
|
|
195
|
+
return normalized_actual == normalized_expected
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def _validate_single_parameter_set(
|
|
199
|
+
parameter_profile: "ParameterProfile", parameters: Any, batch_index: "int | None" = None
|
|
200
|
+
) -> None:
|
|
201
|
+
expected_identifiers = _collect_expected_identifiers(parameter_profile)
|
|
202
|
+
actual_identifiers, actual_count = _collect_actual_identifiers(parameters)
|
|
203
|
+
expected_count = len(expected_identifiers)
|
|
204
|
+
|
|
205
|
+
if expected_count == 0 and actual_count == 0:
|
|
206
|
+
return
|
|
207
|
+
|
|
208
|
+
prefix = "Parameter count mismatch"
|
|
209
|
+
if batch_index is not None:
|
|
210
|
+
prefix = f"{prefix} in batch {batch_index}"
|
|
211
|
+
|
|
212
|
+
if expected_count == 0 and actual_count > 0:
|
|
213
|
+
msg = f"{prefix}: statement does not accept parameters."
|
|
214
|
+
raise sqlspec.exceptions.SQLSpecError(msg)
|
|
215
|
+
|
|
216
|
+
if expected_count > 0 and actual_count == 0:
|
|
217
|
+
msg = f"{prefix}: expected {expected_count} parameters, received 0."
|
|
218
|
+
raise sqlspec.exceptions.SQLSpecError(msg)
|
|
219
|
+
|
|
220
|
+
if expected_count != actual_count:
|
|
221
|
+
msg = f"{prefix}: {actual_count} parameters provided but {expected_count} placeholders detected."
|
|
222
|
+
raise sqlspec.exceptions.SQLSpecError(msg)
|
|
223
|
+
|
|
224
|
+
identifiers_match = expected_identifiers == actual_identifiers or _normalize_index_identifiers(
|
|
225
|
+
expected_identifiers, actual_identifiers
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
if not identifiers_match:
|
|
229
|
+
msg = (
|
|
230
|
+
f"{prefix}: expected identifiers {_format_identifiers(expected_identifiers)}, "
|
|
231
|
+
f"received {_format_identifiers(actual_identifiers)}."
|
|
232
|
+
)
|
|
233
|
+
raise sqlspec.exceptions.SQLSpecError(msg)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def validate_parameter_alignment(
|
|
237
|
+
parameter_profile: "ParameterProfile | None", parameters: Any, *, is_many: bool = False
|
|
238
|
+
) -> None:
|
|
239
|
+
"""Ensure provided parameters align with detected placeholders.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
parameter_profile: Placeholder metadata extracted from the statement.
|
|
243
|
+
parameters: Parameter payload the adapter will execute with.
|
|
244
|
+
is_many: Whether the call explicitly targets ``execute_many``.
|
|
245
|
+
|
|
246
|
+
Raises:
|
|
247
|
+
SQLSpecError: If counts or identifiers differ between placeholders and payload.
|
|
248
|
+
"""
|
|
249
|
+
profile = parameter_profile or ParameterProfile.empty()
|
|
250
|
+
if profile.total_count == 0:
|
|
251
|
+
return
|
|
252
|
+
|
|
253
|
+
effective_is_many = is_many or looks_like_execute_many(parameters)
|
|
254
|
+
|
|
255
|
+
if effective_is_many:
|
|
256
|
+
if parameters is None:
|
|
257
|
+
if profile.total_count == 0:
|
|
258
|
+
return
|
|
259
|
+
msg = "Parameter count mismatch: expected parameter sets for execute_many."
|
|
260
|
+
raise sqlspec.exceptions.SQLSpecError(msg)
|
|
261
|
+
if not _is_sequence_like(parameters):
|
|
262
|
+
msg = "Parameter count mismatch: expected sequence of parameter sets for execute_many."
|
|
263
|
+
raise sqlspec.exceptions.SQLSpecError(msg)
|
|
264
|
+
if len(parameters) == 0:
|
|
265
|
+
return
|
|
266
|
+
for index, param_set in enumerate(parameters):
|
|
267
|
+
_validate_single_parameter_set(profile, param_set, batch_index=index)
|
|
268
|
+
return
|
|
269
|
+
|
|
270
|
+
_validate_single_parameter_set(profile, parameters)
|
|
Binary file
|