sqlty 0.1.0__tar.gz → 0.2.1__tar.gz
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.
- {sqlty-0.1.0 → sqlty-0.2.1}/PKG-INFO +8 -6
- {sqlty-0.1.0 → sqlty-0.2.1}/README.md +7 -5
- {sqlty-0.1.0 → sqlty-0.2.1}/pyproject.toml +2 -1
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/Cargo.lock +7 -4
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/Cargo.toml +2 -1
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-ext/Cargo.toml +2 -0
- sqlty-0.2.1/rust/crates/sqlty-ext/build.rs +51 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-ext/src/lib.rs +52 -21
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-python/src/checker.rs +187 -9
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-python/src/fixer.rs +3 -2
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-python/src/rules.rs +11 -2
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-python/src/tokens.rs +13 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/Cargo.toml +1 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/build.rs +3 -1
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/rules/README.md +96 -18
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/rules/common/aggregates.inference.toml +41 -1
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/common/conditional.inference.toml +17 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/common/datetime.inference.toml +25 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/rules/common/json.inference.toml +34 -2
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/common/math.inference.toml +17 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/common/strings.inference.toml +33 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/common/window.inference.toml +41 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/rules/compile.rs +387 -69
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/dialects.toml +6 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/mysql/aggregates.inference.toml +49 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/mysql/arithmetic.inference.toml +132 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/mysql/bits.inference.toml +10 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/mysql/comparison.inference.toml +28 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/mysql/conditional.inference.toml +19 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/mysql/datetime.inference.toml +136 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/mysql/encryption.inference.toml +46 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/mysql/json.inference.toml +102 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/mysql/math.inference.toml +84 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/mysql/misc.inference.toml +109 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/mysql/spatial.inference.toml +120 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/mysql/strings.inference.toml +228 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/mysql/system.inference.toml +118 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/admin.inference.toml +145 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/aggregates.inference.toml +178 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/rules/postgres/arithmetic.inference.toml +185 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/arrays.inference.toml +120 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/binary.inference.toml +46 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/comparison.inference.toml +20 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/rules/postgres/concat.inference.toml +20 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/conditional.inference.toml +10 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/datetime.inference.toml +127 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/enums.inference.toml +19 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/events.inference.toml +19 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/extensions.inference.toml +28 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/formatting.inference.toml +28 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/geometry.inference.toml +175 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/json.inference.toml +258 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/math.inference.toml +92 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/merge.inference.toml +10 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/network.inference.toml +64 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/ranges.inference.toml +136 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/rows.inference.toml +10 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/sequences.inference.toml +10 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/series.inference.toml +19 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/strings.inference.toml +101 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/system.inference.toml +353 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/textsearch.inference.toml +162 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/uuid.inference.toml +28 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/postgres/xml.inference.toml +55 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/sqlite/aggregates.inference.toml +29 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/sqlite/arithmetic.inference.toml +54 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/sqlite/bitwise.inference.toml +17 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/sqlite/datetime.inference.toml +28 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/sqlite/fts.inference.toml +37 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/sqlite/json.inference.toml +100 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/sqlite/math.inference.toml +38 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/sqlite/scalar.inference.toml +91 -0
- sqlty-0.2.1/rust/crates/sqlty-sql/rules/sqlite/strings.inference.toml +10 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/api.rs +11 -1
- sqlty-0.2.1/rust/crates/sqlty-sql/src/analyzer/dml.rs +797 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/explain.rs +6 -1
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/expr.rs +203 -76
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/functions.rs +153 -496
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/grouping.rs +80 -24
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/inference.rs +95 -12
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/json.rs +2 -1
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/literals.rs +7 -1
- sqlty-0.2.1/rust/crates/sqlty-sql/src/analyzer/merged_star.rs +178 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/mod.rs +18 -1
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/names.rs +4 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/narrowing.rs +100 -8
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/nullability.rs +416 -120
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/operators.rs +177 -5
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/params.rs +66 -1
- sqlty-0.2.1/rust/crates/sqlty-sql/src/analyzer/pg_record_functions.rs +599 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/preprocess.rs +128 -13
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/query.rs +214 -27
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/references.rs +21 -1
- sqlty-0.2.1/rust/crates/sqlty-sql/src/analyzer/registry.rs +264 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/resolve.rs +54 -19
- sqlty-0.2.1/rust/crates/sqlty-sql/src/analyzer/respell.rs +569 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/scope.rs +85 -17
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__dml__tests__returning_columns_in_queries.snap +11 -10
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__expr__tests__arrays_and_subscripts.snap +1 -1
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__expr__tests__composite_fields_and_json_access.snap +1 -2
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__expr__tests__literals_and_unary_operators.snap +2 -2
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__expr__tests__misc_expressions.snap +1 -1
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__expr__tests__mysql_and_sqlite_expressions.snap +5 -6
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__functions__tests__function_availability_differs_by_dialect.snap +1 -1
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__operators__tests__division_differs_between_postgres_and_mysql.snap +1 -2
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__dialects_name_and_type_the_same_query_differently.snap +3 -3
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__unsupported_query_forms_are_explained.snap +3 -2
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__values_lists.snap +23 -4
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__quoted_names_keep_their_case_in_postgres_only.snap +1 -1
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__star_over_unreadable_sources_names_the_reason.snap +8 -4
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__scope__tests__opaque_sources_explain_themselves.snap +5 -5
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__scope__tests__star_expansion_over_joins.snap +15 -6
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/sql_type.rs +5 -4
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/table_functions.rs +103 -32
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/tests.rs +2 -2
- sqlty-0.2.1/rust/crates/sqlty-sql/src/analyzer/text_names.rs +174 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/catalog/alter.rs +75 -11
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/catalog/columns.rs +46 -4
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/catalog/loader.rs +208 -20
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/catalog/mod.rs +79 -7
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/catalog/read.rs +162 -8
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/catalog/resolve.rs +52 -9
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/ddl.rs +325 -20
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/diagnostics.rs +6 -1
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/tests/inference_compiler.rs +180 -0
- sqlty-0.2.1/skills/sqlty/SKILL.md +81 -0
- sqlty-0.2.1/skills/sqlty-adopt/SKILL.md +125 -0
- sqlty-0.2.1/skills/sqlty-breaking/SKILL.md +130 -0
- sqlty-0.2.1/skills/sqlty-check/SKILL.md +144 -0
- sqlty-0.2.1/skills/sqlty-ci/SKILL.md +120 -0
- sqlty-0.2.1/skills/sqlty-rewrite/SKILL.md +134 -0
- sqlty-0.2.1/src/sqlty/_breaking.py +314 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_check.py +34 -4
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_cli.py +69 -24
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_core.pyi +2 -1
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_drivers.py +79 -16
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_helpers.py +17 -1
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_lint.py +15 -1
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_params.py +39 -6
- sqlty-0.2.1/src/sqlty/_snapshot.py +169 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_source.py +16 -4
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_type_extractor/ast_fields.py +55 -9
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_type_extractor/extract.py +59 -10
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/core.py +36 -30
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/insert-missing-column.md +9 -4
- sqlty-0.2.1/src/sqlty/rules/insert-value-count.md +58 -0
- sqlty-0.2.1/src/sqlty/rules/narrow-type.md +50 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/param-type-mismatch.md +10 -2
- sqlty-0.2.1/src/sqlty/rules/stale-type.md +56 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/ungrouped-column.md +3 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/unparsed-query.md +5 -3
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/unsupported-syntax.md +3 -3
- sqlty-0.1.0/rust/crates/sqlty-sql/rules/mysql/aggregates.inference.toml +0 -21
- sqlty-0.1.0/rust/crates/sqlty-sql/rules/mysql/arithmetic.inference.toml +0 -30
- sqlty-0.1.0/rust/crates/sqlty-sql/rules/mysql/comparison.inference.toml +0 -10
- sqlty-0.1.0/rust/crates/sqlty-sql/rules/mysql/json.inference.toml +0 -21
- sqlty-0.1.0/rust/crates/sqlty-sql/rules/mysql/strings.inference.toml +0 -51
- sqlty-0.1.0/rust/crates/sqlty-sql/rules/postgres/aggregates.inference.toml +0 -51
- sqlty-0.1.0/rust/crates/sqlty-sql/rules/postgres/json.inference.toml +0 -123
- sqlty-0.1.0/rust/crates/sqlty-sql/rules/sqlite/json.inference.toml +0 -28
- sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/dialect_functions.rs +0 -379
- sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/dml.rs +0 -388
- sqlty-0.1.0/rust/crates/sqlty-sql/src/analyzer/registry.rs +0 -439
- sqlty-0.1.0/src/sqlty/_breaking.py +0 -191
- sqlty-0.1.0/src/sqlty/_widening.py +0 -89
- sqlty-0.1.0/src/sqlty/rules/stale-type.md +0 -50
- sqlty-0.1.0/src/sqlty/skill/SKILL.md +0 -110
- {sqlty-0.1.0 → sqlty-0.2.1}/LICENSE +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-python/Cargo.toml +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-python/src/edit.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-python/src/lib.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-python/src/options.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-python/src/rewriter.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-python/src/scan.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-python/src/template.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/rules/common/arithmetic.inference.toml +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/rules/common/comparison.inference.toml +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/rules/common/concat.inference.toml +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/rules/mysql/concat.inference.toml +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/dialect.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/hashing.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/memo.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__expr__tests__case_expressions.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__expr__tests__casts.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__expr__tests__casts_without_a_schema_do_not_complain.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__functions__tests__aggregates_in_postgres.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__functions__tests__return_types_follow_the_argument.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__functions__tests__unknown_functions_are_untyped_and_explained.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__literals__tests__value_sets_flow_through_expressions.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__names__tests__column_names_follow_postgres_figure_colname.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__operators__tests__arithmetic_promotes_numbers_and_types_date_math.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__operators__tests__binary_operators_in_queries.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__operators__tests__common_type_follows_postgres_union_rules.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__column_names_come_from_the_first_branch.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__ctes.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__projection_forms.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__recursive_ctes_settle_nullability.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__set_operations_combine_nullability.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__set_operations_unify_types.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__query__tests__statements_that_are_not_queries_have_no_columns.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__ambiguous_names_are_reported_once_per_query.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__cte_columns_are_resolved_like_tables.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__names_are_not_judged_without_a_schema.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__nullability_comes_from_the_declaration.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__system_columns_exist_without_being_declared.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__unknown_names_say_what_is_missing.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__resolve__tests__unqualified_names_resolve_to_the_first_source_that_has_them.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__scope__tests__correlated_subqueries_see_the_outer_scope.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__scope__tests__derived_tables_ctes_and_views.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__scope__tests__nullability_follows_the_join_kind.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/snapshots/sqlty_sql__analyzer__scope__tests__table_names_fold_by_dialect.snap +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/star_expand.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/test_support.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/analyzer/typed.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/catalog/builtin_catalog.sql +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/catalog/names.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/json.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/lib.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/placeholders.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/src/values.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/rust/crates/sqlty-sql/tests/timing.rs +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/__init__.py +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/__main__.py +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_config.py +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_decode.py +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_gitignore.py +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_json_shape.py +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_json_types.py +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_psycopg.py +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_type_extractor/__init__.py +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_type_extractor/compat.py +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_type_extractor/generic.py +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_type_extractor/info.py +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_type_extractor/sandbox.py +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/_type_extractor/subtype.py +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/drivers/psycopg.py +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/magic.py +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/py.typed +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/ambiguous-column.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/column-count-mismatch.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/column-name-mismatch.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/column-type-mismatch.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/fstring-skipped.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/inline-sql-comment.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/json-shape-mismatch.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/literal-mismatch.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/mysql-sql-marker.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/nullable-mismatch.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/param-count-mismatch.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/redundant-literal.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/redundant-optional.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/select-star-no-schema.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/select-star.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/stale-rewrite.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/tstring-skipped.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/typeddict-inheritance.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/typeddict-key-mismatch.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/unchecked-query.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/unknown-column.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/unknown-function.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/unknown-table.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/unknown-type.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/untyped-query.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty/rules/unused-ignore.md +0 -0
- {sqlty-0.1.0 → sqlty-0.2.1}/src/sqlty_magic.pth +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlty
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Environment :: Console
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -111,13 +111,14 @@ CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT);
|
|
|
111
111
|
```python
|
|
112
112
|
from sqlty import SQL
|
|
113
113
|
|
|
114
|
-
# error: [
|
|
114
|
+
# error: [narrow-type] "SQL[tuple[int, str]] should be SQL[tuple[int, str | None]]"
|
|
115
115
|
query = SQL[tuple[int, str]]("--sql\nSELECT id, email FROM users")
|
|
116
116
|
```
|
|
117
117
|
|
|
118
118
|
`sqlty check --fix .` updates the type, and your type checker finds every
|
|
119
|
-
caller that now needs a `None` check. `
|
|
120
|
-
|
|
119
|
+
caller that now needs a `None` check. `narrow-type` is an error, so CI fails on
|
|
120
|
+
it; an annotation that is only wider than the rows, such as `str | None` for a
|
|
121
|
+
column made `NOT NULL`, is a `stale-type` warning
|
|
121
122
|
([CI](https://jirikuncar.github.io/sqlty/recipes/ci/)). For rolling deploys,
|
|
122
123
|
`sqlty breaking --against origin/main` exits 1 when old code breaks on the new
|
|
123
124
|
schema or new code on the old one
|
|
@@ -174,8 +175,9 @@ conn.execute("--sql\nSELECT emial FROM users")
|
|
|
174
175
|
asyncpg calls ([Parameters](https://jirikuncar.github.io/sqlty/guide/parameters/)).
|
|
175
176
|
These are the mistakes coding agents make: every problem is one
|
|
176
177
|
`file:line: [rule] message` line and a non-zero exit code they can act on, and
|
|
177
|
-
the [sqlty
|
|
178
|
-
them the conventions.
|
|
178
|
+
the [sqlty skills](https://jirikuncar.github.io/sqlty/recipes/agents/) teach
|
|
179
|
+
them the conventions. In Claude Code, `/plugin install sqlty --marketplace jirikuncar/sqlty`
|
|
180
|
+
installs them.
|
|
179
181
|
|
|
180
182
|
## Get started
|
|
181
183
|
|
|
@@ -78,13 +78,14 @@ CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT);
|
|
|
78
78
|
```python
|
|
79
79
|
from sqlty import SQL
|
|
80
80
|
|
|
81
|
-
# error: [
|
|
81
|
+
# error: [narrow-type] "SQL[tuple[int, str]] should be SQL[tuple[int, str | None]]"
|
|
82
82
|
query = SQL[tuple[int, str]]("--sql\nSELECT id, email FROM users")
|
|
83
83
|
```
|
|
84
84
|
|
|
85
85
|
`sqlty check --fix .` updates the type, and your type checker finds every
|
|
86
|
-
caller that now needs a `None` check. `
|
|
87
|
-
|
|
86
|
+
caller that now needs a `None` check. `narrow-type` is an error, so CI fails on
|
|
87
|
+
it; an annotation that is only wider than the rows, such as `str | None` for a
|
|
88
|
+
column made `NOT NULL`, is a `stale-type` warning
|
|
88
89
|
([CI](https://jirikuncar.github.io/sqlty/recipes/ci/)). For rolling deploys,
|
|
89
90
|
`sqlty breaking --against origin/main` exits 1 when old code breaks on the new
|
|
90
91
|
schema or new code on the old one
|
|
@@ -141,8 +142,9 @@ conn.execute("--sql\nSELECT emial FROM users")
|
|
|
141
142
|
asyncpg calls ([Parameters](https://jirikuncar.github.io/sqlty/guide/parameters/)).
|
|
142
143
|
These are the mistakes coding agents make: every problem is one
|
|
143
144
|
`file:line: [rule] message` line and a non-zero exit code they can act on, and
|
|
144
|
-
the [sqlty
|
|
145
|
-
them the conventions.
|
|
145
|
+
the [sqlty skills](https://jirikuncar.github.io/sqlty/recipes/agents/) teach
|
|
146
|
+
them the conventions. In Claude Code, `/plugin install sqlty --marketplace jirikuncar/sqlty`
|
|
147
|
+
installs them.
|
|
146
148
|
|
|
147
149
|
## Get started
|
|
148
150
|
|
|
@@ -61,7 +61,8 @@ manifest-path = "rust/crates/sqlty-ext/Cargo.toml"
|
|
|
61
61
|
# registers the lazy "sqlty" codec lookup (see docs/guide/magic-codec.md).
|
|
62
62
|
# The path is relative to the project root (maturin >= 1.12.1): the wheel gets
|
|
63
63
|
# it at the root (python-source prefix stripped), the sdist at src/.
|
|
64
|
-
|
|
64
|
+
# The Agent Skills are compiled into the extension, so only the sdist needs them.
|
|
65
|
+
include = ["src/sqlty_magic.pth", { path = "skills/**/*", format = "sdist" }]
|
|
65
66
|
|
|
66
67
|
[dependency-groups]
|
|
67
68
|
dev = [
|
|
@@ -614,7 +614,7 @@ dependencies = [
|
|
|
614
614
|
|
|
615
615
|
[[package]]
|
|
616
616
|
name = "sqlty-bench"
|
|
617
|
-
version = "0.1
|
|
617
|
+
version = "0.2.1"
|
|
618
618
|
dependencies = [
|
|
619
619
|
"criterion",
|
|
620
620
|
"sqlty-python",
|
|
@@ -623,17 +623,19 @@ dependencies = [
|
|
|
623
623
|
|
|
624
624
|
[[package]]
|
|
625
625
|
name = "sqlty-core"
|
|
626
|
-
version = "0.1
|
|
626
|
+
version = "0.2.1"
|
|
627
627
|
dependencies = [
|
|
628
628
|
"pyo3",
|
|
629
|
+
"recursive",
|
|
629
630
|
"sqlty-python",
|
|
630
631
|
"sqlty-sql",
|
|
632
|
+
"stacker",
|
|
631
633
|
"thiserror",
|
|
632
634
|
]
|
|
633
635
|
|
|
634
636
|
[[package]]
|
|
635
637
|
name = "sqlty-python"
|
|
636
|
-
version = "0.1
|
|
638
|
+
version = "0.2.1"
|
|
637
639
|
dependencies = [
|
|
638
640
|
"regex",
|
|
639
641
|
"sqlty-sql",
|
|
@@ -642,9 +644,10 @@ dependencies = [
|
|
|
642
644
|
|
|
643
645
|
[[package]]
|
|
644
646
|
name = "sqlty-sql"
|
|
645
|
-
version = "0.1
|
|
647
|
+
version = "0.2.1"
|
|
646
648
|
dependencies = [
|
|
647
649
|
"insta",
|
|
650
|
+
"recursive",
|
|
648
651
|
"regex",
|
|
649
652
|
"rustc-hash",
|
|
650
653
|
"serde",
|
|
@@ -3,7 +3,7 @@ resolver = "2"
|
|
|
3
3
|
members = ["crates/*"]
|
|
4
4
|
|
|
5
5
|
[workspace.package]
|
|
6
|
-
version = "0.1
|
|
6
|
+
version = "0.2.1"
|
|
7
7
|
edition = "2021"
|
|
8
8
|
description = "Rust engine of sqlty: SQL type inference and Python source rewriting"
|
|
9
9
|
license = "MIT"
|
|
@@ -15,6 +15,7 @@ rust-version = "1.88"
|
|
|
15
15
|
pyo3 = { version = "0.29", features = ["extension-module"] }
|
|
16
16
|
sqlparser = { version = "0.63", features = ["visitor"] }
|
|
17
17
|
regex = "1"
|
|
18
|
+
recursive = "0.1"
|
|
18
19
|
rustc-hash = "2"
|
|
19
20
|
thiserror = "2"
|
|
20
21
|
insta = "1.49"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//! Embeds the Agent Skills of `skills/` at the repository root, so `sqlty skill` prints the
|
|
2
|
+
//! ones of its own version wherever the wheel is installed.
|
|
3
|
+
|
|
4
|
+
use std::fmt::Write as _;
|
|
5
|
+
use std::path::{Path, PathBuf};
|
|
6
|
+
use std::{env, fs};
|
|
7
|
+
|
|
8
|
+
fn main() {
|
|
9
|
+
let root = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()).join("../../../skills");
|
|
10
|
+
let root = root
|
|
11
|
+
.canonicalize()
|
|
12
|
+
.unwrap_or_else(|e| panic!("{}: {e}", root.display()));
|
|
13
|
+
let mut files = Vec::new();
|
|
14
|
+
collect(&root, &mut files);
|
|
15
|
+
files.sort();
|
|
16
|
+
let mut out = String::from("pub(crate) static SKILLS: &[(&str, &str)] = &[\n");
|
|
17
|
+
for file in &files {
|
|
18
|
+
let relative = file
|
|
19
|
+
.strip_prefix(&root)
|
|
20
|
+
.unwrap()
|
|
21
|
+
.to_str()
|
|
22
|
+
.unwrap()
|
|
23
|
+
.replace('\\', "/");
|
|
24
|
+
writeln!(
|
|
25
|
+
out,
|
|
26
|
+
" ({relative:?}, include_str!({:?})),",
|
|
27
|
+
file.to_str().unwrap()
|
|
28
|
+
)
|
|
29
|
+
.unwrap();
|
|
30
|
+
}
|
|
31
|
+
out.push_str("];\n");
|
|
32
|
+
fs::write(
|
|
33
|
+
Path::new(&env::var("OUT_DIR").unwrap()).join("skills.rs"),
|
|
34
|
+
out,
|
|
35
|
+
)
|
|
36
|
+
.unwrap();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/// Every file under `dir`, and every directory for Cargo to watch.
|
|
40
|
+
fn collect(dir: &Path, files: &mut Vec<PathBuf>) {
|
|
41
|
+
println!("cargo:rerun-if-changed={}", dir.display());
|
|
42
|
+
for entry in fs::read_dir(dir).unwrap() {
|
|
43
|
+
let path = entry.unwrap().path();
|
|
44
|
+
if path.is_dir() {
|
|
45
|
+
collect(&path, files);
|
|
46
|
+
} else {
|
|
47
|
+
println!("cargo:rerun-if-changed={}", path.display());
|
|
48
|
+
files.push(path);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -52,6 +52,7 @@ type ParamTuple = (
|
|
|
52
52
|
Option<String>,
|
|
53
53
|
Option<bool>,
|
|
54
54
|
bool,
|
|
55
|
+
Option<String>,
|
|
55
56
|
);
|
|
56
57
|
|
|
57
58
|
/// A parsed schema and the tables and views it could not parse.
|
|
@@ -186,7 +187,7 @@ fn load_schema(
|
|
|
186
187
|
let dialect = dialect.0;
|
|
187
188
|
let overrides = analyzer::TypeOverrides::new(&types.unwrap_or_default(), dialect)
|
|
188
189
|
.map_err(PyValueError::new_err)?;
|
|
189
|
-
let loaded =
|
|
190
|
+
let loaded = detach(py, || {
|
|
190
191
|
let (schema, skipped) = if overrides.is_empty() {
|
|
191
192
|
analyzer::load_schema_with_skipped(schema_sql, dialect)
|
|
192
193
|
} else {
|
|
@@ -293,7 +294,28 @@ fn infer_type(
|
|
|
293
294
|
schema_sql: Option<SchemaArg>,
|
|
294
295
|
) -> Result<Option<String>, Error> {
|
|
295
296
|
let dialect = dialect.0;
|
|
296
|
-
Ok(
|
|
297
|
+
Ok(detach(py, || {
|
|
298
|
+
analyzer::infer_type(sql, dialect, schema(schema_sql, dialect).as_deref())
|
|
299
|
+
})?)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/// The stack the analyzer's recursion keeps free: it moves to a new stack of
|
|
303
|
+
/// [`STACK_SEGMENT`] when less is left, so an expression nested `MAX_DEPTH` (1000) levels
|
|
304
|
+
/// deep fits whatever thread calls it.
|
|
305
|
+
const STACK_RED_ZONE: usize = 2 << 20;
|
|
306
|
+
const STACK_SEGMENT: usize = 16 << 20;
|
|
307
|
+
|
|
308
|
+
/// Runs `f` without the GIL, with at least [`STACK_RED_ZONE`] of stack.
|
|
309
|
+
fn detach<T: Send, F: Send + FnOnce() -> T>(py: Python<'_>, f: F) -> T {
|
|
310
|
+
py.detach(|| stacker::maybe_grow(STACK_RED_ZONE, STACK_SEGMENT, f))
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
include!(concat!(env!("OUT_DIR"), "/skills.rs"));
|
|
314
|
+
|
|
315
|
+
/// The files of the Agent Skills, as `(path, text)` with paths like `sqlty/SKILL.md`.
|
|
316
|
+
#[pyfunction]
|
|
317
|
+
fn skills() -> Vec<(&'static str, &'static str)> {
|
|
318
|
+
SKILLS.to_vec()
|
|
297
319
|
}
|
|
298
320
|
|
|
299
321
|
/// Result columns of a query as `(name, python_type, sql_type)` tuples.
|
|
@@ -311,7 +333,7 @@ fn analyze_select(
|
|
|
311
333
|
schema_sql: Option<SchemaArg>,
|
|
312
334
|
) -> Result<Option<Vec<ColumnTuple>>, Error> {
|
|
313
335
|
let dialect = dialect.0;
|
|
314
|
-
let columns =
|
|
336
|
+
let columns = detach(py, || {
|
|
315
337
|
analyzer::analyze_select(sql, dialect, schema(schema_sql, dialect).as_deref())
|
|
316
338
|
})?;
|
|
317
339
|
Ok(columns.map(|columns| {
|
|
@@ -340,7 +362,7 @@ fn explain_select(
|
|
|
340
362
|
schema_sql: Option<SchemaArg>,
|
|
341
363
|
) -> Option<Vec<ColumnRulesTuple>> {
|
|
342
364
|
let dialect = dialect.0;
|
|
343
|
-
let columns =
|
|
365
|
+
let columns = detach(py, || {
|
|
344
366
|
analyzer::explain_select(sql, dialect, schema(schema_sql, dialect).as_deref())
|
|
345
367
|
})?;
|
|
346
368
|
let tuple = |rule: analyzer::RuleRef| (rule.id, rule.reference, rule.reasoning);
|
|
@@ -376,7 +398,7 @@ fn analyze_columns(
|
|
|
376
398
|
schema_sql: Option<SchemaArg>,
|
|
377
399
|
) -> Result<Option<Vec<NullableColumnTuple>>, Error> {
|
|
378
400
|
let dialect = dialect.0;
|
|
379
|
-
let columns =
|
|
401
|
+
let columns = detach(py, || {
|
|
380
402
|
analyzer::analyze_select(sql, dialect, schema(schema_sql, dialect).as_deref())
|
|
381
403
|
})?;
|
|
382
404
|
Ok(columns.map(|columns| {
|
|
@@ -439,7 +461,7 @@ fn analyze_params(
|
|
|
439
461
|
schema_sql: Option<SchemaArg>,
|
|
440
462
|
) -> Option<Vec<ParamTuple>> {
|
|
441
463
|
let dialect = dialect.0;
|
|
442
|
-
let params =
|
|
464
|
+
let params = detach(py, || {
|
|
443
465
|
analyzer::analyze_params(sql, dialect, schema(schema_sql, dialect).as_deref())
|
|
444
466
|
})?;
|
|
445
467
|
Some(
|
|
@@ -453,6 +475,7 @@ fn analyze_params(
|
|
|
453
475
|
param.sql_type,
|
|
454
476
|
nullable(param.nullability),
|
|
455
477
|
param.cast,
|
|
478
|
+
param.untyped_sql_type,
|
|
456
479
|
)
|
|
457
480
|
})
|
|
458
481
|
.collect(),
|
|
@@ -483,7 +506,8 @@ fn name_rules() -> Vec<&'static str> {
|
|
|
483
506
|
|
|
484
507
|
/// Why a query has untyped columns, or names what it cannot, as `(rule, message)` pairs:
|
|
485
508
|
/// `unknown-table`, `unknown-column`, `ambiguous-column`, `unknown-function`,
|
|
486
|
-
/// `unknown-type`, `unsupported-syntax`, `insert-missing-column` and
|
|
509
|
+
/// `unknown-type`, `unsupported-syntax`, `insert-missing-column`, `insert-value-count` and
|
|
510
|
+
/// `ungrouped-column`.
|
|
487
511
|
/// Tables, columns and
|
|
488
512
|
/// ambiguity are only judged with a schema.
|
|
489
513
|
///
|
|
@@ -498,7 +522,7 @@ fn query_diagnostics(
|
|
|
498
522
|
schema_sql: Option<SchemaArg>,
|
|
499
523
|
) -> Vec<(String, String)> {
|
|
500
524
|
let dialect = dialect.0;
|
|
501
|
-
|
|
525
|
+
detach(py, || {
|
|
502
526
|
analyzer::analyze_with_diagnostics(sql, dialect, schema(schema_sql, dialect).as_deref())
|
|
503
527
|
.1
|
|
504
528
|
.into_iter()
|
|
@@ -517,7 +541,7 @@ fn schema_skipped_tables(
|
|
|
517
541
|
dialect: DialectArg,
|
|
518
542
|
) -> Vec<String> {
|
|
519
543
|
let dialect = dialect.0;
|
|
520
|
-
|
|
544
|
+
detach(py, || skipped_objects(schema_sql, dialect, Some("table")))
|
|
521
545
|
.into_iter()
|
|
522
546
|
.map(|(_, name)| name)
|
|
523
547
|
.collect()
|
|
@@ -533,7 +557,7 @@ fn schema_skipped_objects(
|
|
|
533
557
|
dialect: DialectArg,
|
|
534
558
|
) -> Vec<(String, String)> {
|
|
535
559
|
let dialect = dialect.0;
|
|
536
|
-
|
|
560
|
+
detach(py, || skipped_objects(schema_sql, dialect, None))
|
|
537
561
|
}
|
|
538
562
|
|
|
539
563
|
fn skipped_objects<S: AsRef<str>>(
|
|
@@ -558,7 +582,7 @@ fn skipped_objects<S: AsRef<str>>(
|
|
|
558
582
|
#[pyo3(signature = (sql, *, dialect = DialectArg::POSTGRES))]
|
|
559
583
|
fn parse_error(py: Python<'_>, sql: &str, dialect: DialectArg) -> Option<String> {
|
|
560
584
|
let dialect = dialect.0;
|
|
561
|
-
|
|
585
|
+
detach(py, || analyzer::parse_error(sql, dialect))
|
|
562
586
|
}
|
|
563
587
|
|
|
564
588
|
/// Whether a query yields rows: a query, DML with RETURNING, or unparseable SQL.
|
|
@@ -568,7 +592,7 @@ fn parse_error(py: Python<'_>, sql: &str, dialect: DialectArg) -> Option<String>
|
|
|
568
592
|
#[pyo3(signature = (sql, *, dialect = DialectArg::POSTGRES))]
|
|
569
593
|
fn returns_rows(py: Python<'_>, sql: &str, dialect: DialectArg) -> bool {
|
|
570
594
|
let dialect = dialect.0;
|
|
571
|
-
|
|
595
|
+
detach(py, || analyzer::returns_rows(sql, dialect))
|
|
572
596
|
}
|
|
573
597
|
|
|
574
598
|
/// Rewrite Python source: "--sql\n..." -> SQL[T]("--sql\n...").
|
|
@@ -592,7 +616,7 @@ fn rewrite_source(
|
|
|
592
616
|
keep_lines: bool,
|
|
593
617
|
) -> Result<String, Error> {
|
|
594
618
|
let dialect = dialect.0;
|
|
595
|
-
|
|
619
|
+
detach(py, || {
|
|
596
620
|
let schema = schema_for(source, schema_sql, dialect);
|
|
597
621
|
let options = Options::new(dialect, schema.as_deref(), import_style, untyped)?;
|
|
598
622
|
Ok(rewriter::rewrite_source_with(source, &options, keep_lines))
|
|
@@ -608,7 +632,7 @@ fn rewrite_source(
|
|
|
608
632
|
#[pyfunction]
|
|
609
633
|
#[pyo3(signature = (source, *, import_style = None))]
|
|
610
634
|
fn strip_source(py: Python<'_>, source: &str, import_style: Option<&str>) -> Result<String, Error> {
|
|
611
|
-
|
|
635
|
+
detach(py, || {
|
|
612
636
|
let style = ImportStyle::parse(import_style)?;
|
|
613
637
|
Ok(rewriter::strip_source(source, &style))
|
|
614
638
|
})
|
|
@@ -638,7 +662,7 @@ fn fix_source(
|
|
|
638
662
|
suppressed: Option<rewriter::Suppressed>,
|
|
639
663
|
) -> Result<String, Error> {
|
|
640
664
|
let dialect = dialect.0;
|
|
641
|
-
|
|
665
|
+
detach(py, || {
|
|
642
666
|
let schema = schema_for(source, schema_sql, dialect);
|
|
643
667
|
let options = Options::new(dialect, schema.as_deref(), import_style, untyped)?;
|
|
644
668
|
let rules = RuleConfig::from_overrides(rules).map_err(ConfigError::from)?;
|
|
@@ -664,7 +688,9 @@ fn expand_star(
|
|
|
664
688
|
schema_sql: Option<SchemaArg>,
|
|
665
689
|
) -> Option<String> {
|
|
666
690
|
let dialect = dialect.0;
|
|
667
|
-
|
|
691
|
+
detach(py, || {
|
|
692
|
+
analyzer::expand_star(sql, dialect, schema(schema_sql, dialect).as_deref())
|
|
693
|
+
})
|
|
668
694
|
}
|
|
669
695
|
|
|
670
696
|
/// `(rule, message)` of `select-star` or `select-star-no-schema` for a query whose
|
|
@@ -682,8 +708,10 @@ fn select_star_finding(
|
|
|
682
708
|
has_schema: bool,
|
|
683
709
|
) -> Option<(&'static str, String)> {
|
|
684
710
|
let dialect = dialect.0;
|
|
685
|
-
|
|
686
|
-
|
|
711
|
+
detach(py, || {
|
|
712
|
+
checker::select_star_finding(sql, dialect, has_schema)
|
|
713
|
+
})
|
|
714
|
+
.map(|(rule, message)| (rule.name(), message))
|
|
687
715
|
}
|
|
688
716
|
|
|
689
717
|
/// A finding of `check_source`, which Python reads as a dict.
|
|
@@ -726,7 +754,7 @@ fn check_source(
|
|
|
726
754
|
any_calls: Vec<usize>,
|
|
727
755
|
) -> Result<Vec<DiagnosticOut>, Error> {
|
|
728
756
|
let dialect = dialect.0;
|
|
729
|
-
|
|
757
|
+
detach(py, || {
|
|
730
758
|
let schema = schema_for(source, schema_sql, dialect);
|
|
731
759
|
let options = Options::new(dialect, schema.as_deref(), import_style, untyped)?;
|
|
732
760
|
let rules = RuleConfig::from_overrides(rules).map_err(ConfigError::from)?;
|
|
@@ -756,7 +784,7 @@ fn wrapped_queries(
|
|
|
756
784
|
source: &str,
|
|
757
785
|
import_style: Option<&str>,
|
|
758
786
|
) -> Result<Vec<(usize, String, Option<String>)>, Error> {
|
|
759
|
-
|
|
787
|
+
detach(py, || {
|
|
760
788
|
let style = ImportStyle::parse(import_style)?;
|
|
761
789
|
Ok(checker::wrapped_queries(source, &style))
|
|
762
790
|
})
|
|
@@ -784,7 +812,7 @@ fn query_sites(
|
|
|
784
812
|
import_style: Option<&str>,
|
|
785
813
|
any_calls: Vec<usize>,
|
|
786
814
|
) -> Result<Vec<(usize, String, String)>, Error> {
|
|
787
|
-
|
|
815
|
+
detach(py, || {
|
|
788
816
|
let style = ImportStyle::parse(import_style)?;
|
|
789
817
|
Ok(checker::query_sites(source, &style, &any_calls)
|
|
790
818
|
.into_iter()
|
|
@@ -797,6 +825,8 @@ fn query_sites(
|
|
|
797
825
|
/// module runs without the GIL on free-threaded builds.
|
|
798
826
|
#[pymodule(gil_used = false)]
|
|
799
827
|
fn _core(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
828
|
+
recursive::set_minimum_stack_size(STACK_RED_ZONE);
|
|
829
|
+
recursive::set_stack_allocation_size(STACK_SEGMENT);
|
|
800
830
|
m.add_function(wrap_pyfunction!(infer_type, m)?)?;
|
|
801
831
|
m.add_function(wrap_pyfunction!(load_schema, m)?)?;
|
|
802
832
|
m.add_class::<SchemaHandle>()?;
|
|
@@ -821,6 +851,7 @@ fn _core(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
|
821
851
|
m.add_function(wrap_pyfunction!(check_source, m)?)?;
|
|
822
852
|
m.add_function(wrap_pyfunction!(wrapped_queries, m)?)?;
|
|
823
853
|
m.add_function(wrap_pyfunction!(query_sites, m)?)?;
|
|
854
|
+
m.add_function(wrap_pyfunction!(skills, m)?)?;
|
|
824
855
|
Ok(())
|
|
825
856
|
}
|
|
826
857
|
|