polyglot-sql 0.3.7__tar.gz → 0.3.9__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.
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/Cargo.lock +5 -5
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/Cargo.toml +1 -1
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/PKG-INFO +1 -1
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/Cargo.toml +1 -1
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/mod.rs +193 -3
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/expressions.rs +15 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/generator.rs +54 -1
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/lineage.rs +10 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/parser.rs +88 -66
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/scope.rs +10 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/traversal.rs +6 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/fabric_regression.rs +36 -0
- polyglot_sql-0.3.9/crates/polyglot-sql/tests/fabric_tpch_regression.rs +580 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/transform_regression.rs +130 -2
- polyglot_sql-0.3.9/crates/polyglot-sql/tests/tsql_regression.rs +199 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/src/expr_types.rs +1 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/tests/test_parse.py +19 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/python/polyglot_sql/__init__.py +2 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/python/polyglot_sql/__init__.pyi +11 -10
- polyglot_sql-0.3.7/crates/polyglot-sql/tests/tsql_regression.rs +0 -85
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/README.md +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/README.md +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/benches/in_list.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/benches/parsing.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/benches/rust_parsing.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/benches/transpile.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/examples/basic_usage.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/examples/bench_json.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/ast_transforms.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/builder.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/athena.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/bigquery.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/clickhouse.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/cockroachdb.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/databricks.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/datafusion.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/doris.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/dremio.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/drill.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/druid.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/duckdb.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/dune.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/exasol.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/fabric.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/generic.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/hive.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/materialize.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/mysql.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/oracle.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/postgres.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/presto.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/redshift.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/risingwave.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/singlestore.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/snowflake.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/solr.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/spark.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/sqlite.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/starrocks.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/tableau.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/teradata.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/tidb.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/trino.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/dialects/tsql.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/diff.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/error.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/function_catalog.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/function_registry.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/helper.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/lib.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/optimizer/annotate_types.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/optimizer/canonicalize.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/optimizer/eliminate_ctes.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/optimizer/eliminate_joins.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/optimizer/isolate_table_selects.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/optimizer/mod.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/optimizer/normalize.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/optimizer/normalize_identifiers.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/optimizer/optimize_joins.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/optimizer/optimizer.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/optimizer/pushdown_predicates.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/optimizer/pushdown_projections.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/optimizer/qualify_columns.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/optimizer/qualify_tables.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/optimizer/simplify.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/optimizer/subquery.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/planner.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/resolver.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/schema.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/time.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/tokens.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/transforms.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/trie.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/validation/tests.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/src/validation.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/analyze_failures.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/clickhouse_regression.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/common/known_failures.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/common/mod.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/common/test_data.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/common/test_runner.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/custom_clickhouse_coverage.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/custom_clickhouse_parser.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/custom_dialect.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/custom_dialect_tests.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/custom_fixtures/datafusion/ddl.json +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/custom_fixtures/datafusion/dml.json +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/custom_fixtures/datafusion/functions.json +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/custom_fixtures/datafusion/identity.json +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/custom_fixtures/datafusion/operators.json +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/custom_fixtures/datafusion/select.json +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/custom_fixtures/datafusion/transpilation.json +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/custom_fixtures/datafusion/types.json +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/deep_nesting_regression.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/dialect_matrix.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/error_handling.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/identity_roundtrip.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/postgres_sqlite_regression.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/snowflake_regression_test.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/sqlglot_compat.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/sqlglot_dialect_identity.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/sqlglot_identity.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/sqlglot_identity_detailed.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/sqlglot_parser.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/sqlglot_pretty.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/sqlglot_transpilation.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/sqlglot_transpile.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql/tests/tpch_transpile_stack.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-function-catalogs/Cargo.toml +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-function-catalogs/README.md +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-function-catalogs/src/clickhouse.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-function-catalogs/src/duckdb.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-function-catalogs/src/lib.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-function-catalogs/tools/clickhouse/extract_functions.py +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-function-catalogs/tools/duckdb/extract_functions.py +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/Cargo.toml +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/README.md +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/docs/api.md +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/docs/index.md +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/mkdocs.yml +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/src/annotate_types.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/src/dialects.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/src/diff.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/src/errors.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/src/expr.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/src/format.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/src/generate.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/src/helpers.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/src/lib.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/src/lineage.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/src/optimize.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/src/parse.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/src/tokenize.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/src/transpile.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/src/types.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/src/validate.rs +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/tests/conftest.py +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/tests/test_compat.py +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/tests/test_dialects.py +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/tests/test_diff.py +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/tests/test_expression.py +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/tests/test_format.py +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/tests/test_generate.py +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/tests/test_lineage.py +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/tests/test_optimize.py +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/tests/test_transpile.py +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/tests/test_validate.py +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/crates/polyglot-sql-python/uv.lock +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/pyproject.toml +0 -0
- {polyglot_sql-0.3.7 → polyglot_sql-0.3.9}/python/polyglot_sql/py.typed +0 -0
|
@@ -605,7 +605,7 @@ dependencies = [
|
|
|
605
605
|
|
|
606
606
|
[[package]]
|
|
607
607
|
name = "polyglot-sql"
|
|
608
|
-
version = "0.3.
|
|
608
|
+
version = "0.3.9"
|
|
609
609
|
dependencies = [
|
|
610
610
|
"criterion",
|
|
611
611
|
"once_cell",
|
|
@@ -621,7 +621,7 @@ dependencies = [
|
|
|
621
621
|
|
|
622
622
|
[[package]]
|
|
623
623
|
name = "polyglot-sql-ffi"
|
|
624
|
-
version = "0.3.
|
|
624
|
+
version = "0.3.9"
|
|
625
625
|
dependencies = [
|
|
626
626
|
"cbindgen",
|
|
627
627
|
"polyglot-sql",
|
|
@@ -631,11 +631,11 @@ dependencies = [
|
|
|
631
631
|
|
|
632
632
|
[[package]]
|
|
633
633
|
name = "polyglot-sql-function-catalogs"
|
|
634
|
-
version = "0.3.
|
|
634
|
+
version = "0.3.9"
|
|
635
635
|
|
|
636
636
|
[[package]]
|
|
637
637
|
name = "polyglot-sql-python"
|
|
638
|
-
version = "0.3.
|
|
638
|
+
version = "0.3.9"
|
|
639
639
|
dependencies = [
|
|
640
640
|
"polyglot-sql",
|
|
641
641
|
"pyo3",
|
|
@@ -646,7 +646,7 @@ dependencies = [
|
|
|
646
646
|
|
|
647
647
|
[[package]]
|
|
648
648
|
name = "polyglot-sql-wasm"
|
|
649
|
-
version = "0.3.
|
|
649
|
+
version = "0.3.9"
|
|
650
650
|
dependencies = [
|
|
651
651
|
"console_error_panic_hook",
|
|
652
652
|
"js-sys",
|
|
@@ -83,7 +83,7 @@ thiserror = { workspace = true }
|
|
|
83
83
|
unicode-segmentation = { workspace = true }
|
|
84
84
|
stacker = { version = "0.1", optional = true }
|
|
85
85
|
ts-rs = { version = "12.0", features = ["serde-compat"], optional = true }
|
|
86
|
-
polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.3.
|
|
86
|
+
polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.3.9", optional = true, default-features = false }
|
|
87
87
|
|
|
88
88
|
[dev-dependencies]
|
|
89
89
|
pretty_assertions = "1.4"
|
|
@@ -158,7 +158,10 @@ pub use trino::TrinoDialect;
|
|
|
158
158
|
pub use tsql::TSQLDialect;
|
|
159
159
|
|
|
160
160
|
use crate::error::Result;
|
|
161
|
-
use crate::expressions::{
|
|
161
|
+
use crate::expressions::{
|
|
162
|
+
Expression, From, Function, FunctionBody, Identifier, Join, Null, OrderBy, OutputClause,
|
|
163
|
+
TableRef, With,
|
|
164
|
+
};
|
|
162
165
|
use crate::generator::{Generator, GeneratorConfig};
|
|
163
166
|
use crate::parser::Parser;
|
|
164
167
|
use crate::tokens::{Token, TokenType, Tokenizer, TokenizerConfig};
|
|
@@ -1661,6 +1664,122 @@ where
|
|
|
1661
1664
|
}
|
|
1662
1665
|
}
|
|
1663
1666
|
|
|
1667
|
+
fn transform_table_ref_recursive<F>(table: TableRef, transform_fn: &F) -> Result<TableRef>
|
|
1668
|
+
where
|
|
1669
|
+
F: Fn(Expression) -> Result<Expression>,
|
|
1670
|
+
{
|
|
1671
|
+
match transform_recursive(Expression::Table(Box::new(table)), transform_fn)? {
|
|
1672
|
+
Expression::Table(table) => Ok(*table),
|
|
1673
|
+
_ => Err(crate::error::Error::parse(
|
|
1674
|
+
"TableRef transformation returned non-table expression",
|
|
1675
|
+
0,
|
|
1676
|
+
0,
|
|
1677
|
+
0,
|
|
1678
|
+
0,
|
|
1679
|
+
)),
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
fn transform_from_recursive<F>(from: From, transform_fn: &F) -> Result<From>
|
|
1684
|
+
where
|
|
1685
|
+
F: Fn(Expression) -> Result<Expression>,
|
|
1686
|
+
{
|
|
1687
|
+
match transform_recursive(Expression::From(Box::new(from)), transform_fn)? {
|
|
1688
|
+
Expression::From(from) => Ok(*from),
|
|
1689
|
+
_ => Err(crate::error::Error::parse(
|
|
1690
|
+
"FROM transformation returned non-FROM expression",
|
|
1691
|
+
0,
|
|
1692
|
+
0,
|
|
1693
|
+
0,
|
|
1694
|
+
0,
|
|
1695
|
+
)),
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
fn transform_join_recursive<F>(mut join: Join, transform_fn: &F) -> Result<Join>
|
|
1700
|
+
where
|
|
1701
|
+
F: Fn(Expression) -> Result<Expression>,
|
|
1702
|
+
{
|
|
1703
|
+
join.this = transform_recursive(join.this, transform_fn)?;
|
|
1704
|
+
if let Some(on) = join.on.take() {
|
|
1705
|
+
join.on = Some(transform_recursive(on, transform_fn)?);
|
|
1706
|
+
}
|
|
1707
|
+
if let Some(match_condition) = join.match_condition.take() {
|
|
1708
|
+
join.match_condition = Some(transform_recursive(match_condition, transform_fn)?);
|
|
1709
|
+
}
|
|
1710
|
+
join.pivots = join
|
|
1711
|
+
.pivots
|
|
1712
|
+
.into_iter()
|
|
1713
|
+
.map(|pivot| transform_recursive(pivot, transform_fn))
|
|
1714
|
+
.collect::<Result<Vec<_>>>()?;
|
|
1715
|
+
|
|
1716
|
+
match transform_fn(Expression::Join(Box::new(join)))? {
|
|
1717
|
+
Expression::Join(join) => Ok(*join),
|
|
1718
|
+
_ => Err(crate::error::Error::parse(
|
|
1719
|
+
"Join transformation returned non-join expression",
|
|
1720
|
+
0,
|
|
1721
|
+
0,
|
|
1722
|
+
0,
|
|
1723
|
+
0,
|
|
1724
|
+
)),
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
fn transform_output_clause_recursive<F>(
|
|
1729
|
+
mut output: OutputClause,
|
|
1730
|
+
transform_fn: &F,
|
|
1731
|
+
) -> Result<OutputClause>
|
|
1732
|
+
where
|
|
1733
|
+
F: Fn(Expression) -> Result<Expression>,
|
|
1734
|
+
{
|
|
1735
|
+
output.columns = output
|
|
1736
|
+
.columns
|
|
1737
|
+
.into_iter()
|
|
1738
|
+
.map(|column| transform_recursive(column, transform_fn))
|
|
1739
|
+
.collect::<Result<Vec<_>>>()?;
|
|
1740
|
+
if let Some(into_table) = output.into_table.take() {
|
|
1741
|
+
output.into_table = Some(transform_recursive(into_table, transform_fn)?);
|
|
1742
|
+
}
|
|
1743
|
+
Ok(output)
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
fn transform_with_recursive<F>(mut with: With, transform_fn: &F) -> Result<With>
|
|
1747
|
+
where
|
|
1748
|
+
F: Fn(Expression) -> Result<Expression>,
|
|
1749
|
+
{
|
|
1750
|
+
with.ctes = with
|
|
1751
|
+
.ctes
|
|
1752
|
+
.into_iter()
|
|
1753
|
+
.map(|mut cte| {
|
|
1754
|
+
cte.this = transform_recursive(cte.this, transform_fn)?;
|
|
1755
|
+
Ok(cte)
|
|
1756
|
+
})
|
|
1757
|
+
.collect::<Result<Vec<_>>>()?;
|
|
1758
|
+
if let Some(search) = with.search.take() {
|
|
1759
|
+
with.search = Some(Box::new(transform_recursive(*search, transform_fn)?));
|
|
1760
|
+
}
|
|
1761
|
+
Ok(with)
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
fn transform_order_by_recursive<F>(mut order: OrderBy, transform_fn: &F) -> Result<OrderBy>
|
|
1765
|
+
where
|
|
1766
|
+
F: Fn(Expression) -> Result<Expression>,
|
|
1767
|
+
{
|
|
1768
|
+
order.expressions = order
|
|
1769
|
+
.expressions
|
|
1770
|
+
.into_iter()
|
|
1771
|
+
.map(|mut ordered| {
|
|
1772
|
+
let original = ordered.this.clone();
|
|
1773
|
+
ordered.this = transform_recursive(ordered.this, transform_fn).unwrap_or(original);
|
|
1774
|
+
match transform_fn(Expression::Ordered(Box::new(ordered.clone()))) {
|
|
1775
|
+
Ok(Expression::Ordered(transformed)) => Ok(*transformed),
|
|
1776
|
+
Ok(_) | Err(_) => Ok(ordered),
|
|
1777
|
+
}
|
|
1778
|
+
})
|
|
1779
|
+
.collect::<Result<Vec<_>>>()?;
|
|
1780
|
+
Ok(order)
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1664
1783
|
fn transform_recursive_reference<F>(expr: Expression, transform_fn: &F) -> Result<Expression>
|
|
1665
1784
|
where
|
|
1666
1785
|
F: Fn(Expression) -> Result<Expression>,
|
|
@@ -2377,6 +2496,17 @@ where
|
|
|
2377
2496
|
Expression::Insert(ins)
|
|
2378
2497
|
}
|
|
2379
2498
|
Expression::Update(mut upd) => {
|
|
2499
|
+
upd.table = transform_table_ref_recursive(upd.table, transform_fn)?;
|
|
2500
|
+
upd.extra_tables = upd
|
|
2501
|
+
.extra_tables
|
|
2502
|
+
.into_iter()
|
|
2503
|
+
.map(|table| transform_table_ref_recursive(table, transform_fn))
|
|
2504
|
+
.collect::<Result<Vec<_>>>()?;
|
|
2505
|
+
upd.table_joins = upd
|
|
2506
|
+
.table_joins
|
|
2507
|
+
.into_iter()
|
|
2508
|
+
.map(|join| transform_join_recursive(join, transform_fn))
|
|
2509
|
+
.collect::<Result<Vec<_>>>()?;
|
|
2380
2510
|
upd.set = upd
|
|
2381
2511
|
.set
|
|
2382
2512
|
.into_iter()
|
|
@@ -2385,17 +2515,75 @@ where
|
|
|
2385
2515
|
(id, new_val)
|
|
2386
2516
|
})
|
|
2387
2517
|
.collect();
|
|
2518
|
+
if let Some(from_clause) = upd.from_clause.take() {
|
|
2519
|
+
upd.from_clause = Some(transform_from_recursive(from_clause, transform_fn)?);
|
|
2520
|
+
}
|
|
2521
|
+
upd.from_joins = upd
|
|
2522
|
+
.from_joins
|
|
2523
|
+
.into_iter()
|
|
2524
|
+
.map(|join| transform_join_recursive(join, transform_fn))
|
|
2525
|
+
.collect::<Result<Vec<_>>>()?;
|
|
2388
2526
|
if let Some(mut where_clause) = upd.where_clause.take() {
|
|
2389
2527
|
where_clause.this = transform_recursive(where_clause.this, transform_fn)?;
|
|
2390
2528
|
upd.where_clause = Some(where_clause);
|
|
2391
2529
|
}
|
|
2530
|
+
upd.returning = upd
|
|
2531
|
+
.returning
|
|
2532
|
+
.into_iter()
|
|
2533
|
+
.map(|expr| transform_recursive(expr, transform_fn))
|
|
2534
|
+
.collect::<Result<Vec<_>>>()?;
|
|
2535
|
+
if let Some(output) = upd.output.take() {
|
|
2536
|
+
upd.output = Some(transform_output_clause_recursive(output, transform_fn)?);
|
|
2537
|
+
}
|
|
2538
|
+
if let Some(with) = upd.with.take() {
|
|
2539
|
+
upd.with = Some(transform_with_recursive(with, transform_fn)?);
|
|
2540
|
+
}
|
|
2541
|
+
if let Some(limit) = upd.limit.take() {
|
|
2542
|
+
upd.limit = Some(transform_recursive(limit, transform_fn)?);
|
|
2543
|
+
}
|
|
2544
|
+
if let Some(order_by) = upd.order_by.take() {
|
|
2545
|
+
upd.order_by = Some(transform_order_by_recursive(order_by, transform_fn)?);
|
|
2546
|
+
}
|
|
2392
2547
|
Expression::Update(upd)
|
|
2393
2548
|
}
|
|
2394
2549
|
Expression::Delete(mut del) => {
|
|
2550
|
+
del.table = transform_table_ref_recursive(del.table, transform_fn)?;
|
|
2551
|
+
del.using = del
|
|
2552
|
+
.using
|
|
2553
|
+
.into_iter()
|
|
2554
|
+
.map(|table| transform_table_ref_recursive(table, transform_fn))
|
|
2555
|
+
.collect::<Result<Vec<_>>>()?;
|
|
2395
2556
|
if let Some(mut where_clause) = del.where_clause.take() {
|
|
2396
2557
|
where_clause.this = transform_recursive(where_clause.this, transform_fn)?;
|
|
2397
2558
|
del.where_clause = Some(where_clause);
|
|
2398
2559
|
}
|
|
2560
|
+
if let Some(output) = del.output.take() {
|
|
2561
|
+
del.output = Some(transform_output_clause_recursive(output, transform_fn)?);
|
|
2562
|
+
}
|
|
2563
|
+
if let Some(with) = del.with.take() {
|
|
2564
|
+
del.with = Some(transform_with_recursive(with, transform_fn)?);
|
|
2565
|
+
}
|
|
2566
|
+
if let Some(limit) = del.limit.take() {
|
|
2567
|
+
del.limit = Some(transform_recursive(limit, transform_fn)?);
|
|
2568
|
+
}
|
|
2569
|
+
if let Some(order_by) = del.order_by.take() {
|
|
2570
|
+
del.order_by = Some(transform_order_by_recursive(order_by, transform_fn)?);
|
|
2571
|
+
}
|
|
2572
|
+
del.returning = del
|
|
2573
|
+
.returning
|
|
2574
|
+
.into_iter()
|
|
2575
|
+
.map(|expr| transform_recursive(expr, transform_fn))
|
|
2576
|
+
.collect::<Result<Vec<_>>>()?;
|
|
2577
|
+
del.tables = del
|
|
2578
|
+
.tables
|
|
2579
|
+
.into_iter()
|
|
2580
|
+
.map(|table| transform_table_ref_recursive(table, transform_fn))
|
|
2581
|
+
.collect::<Result<Vec<_>>>()?;
|
|
2582
|
+
del.joins = del
|
|
2583
|
+
.joins
|
|
2584
|
+
.into_iter()
|
|
2585
|
+
.map(|join| transform_join_recursive(join, transform_fn))
|
|
2586
|
+
.collect::<Result<Vec<_>>>()?;
|
|
2399
2587
|
Expression::Delete(del)
|
|
2400
2588
|
}
|
|
2401
2589
|
|
|
@@ -32060,7 +32248,7 @@ impl Dialect {
|
|
|
32060
32248
|
match unit.trim().to_ascii_uppercase().as_str() {
|
|
32061
32249
|
"YEAR" | "YEARS" => Some(IntervalUnit::Year),
|
|
32062
32250
|
"QUARTER" | "QUARTERS" => Some(IntervalUnit::Quarter),
|
|
32063
|
-
"MONTH" | "MONTHS" => Some(IntervalUnit::Month),
|
|
32251
|
+
"MONTH" | "MONTHS" | "MON" | "MONS" | "MM" => Some(IntervalUnit::Month),
|
|
32064
32252
|
"WEEK" | "WEEKS" | "ISOWEEK" => Some(IntervalUnit::Week),
|
|
32065
32253
|
"DAY" | "DAYS" => Some(IntervalUnit::Day),
|
|
32066
32254
|
"HOUR" | "HOURS" => Some(IntervalUnit::Hour),
|
|
@@ -36732,7 +36920,9 @@ impl Dialect {
|
|
|
36732
36920
|
match s {
|
|
36733
36921
|
"YEAR" | "YY" | "YYYY" => crate::expressions::IntervalUnit::Year,
|
|
36734
36922
|
"QUARTER" | "QQ" | "Q" => crate::expressions::IntervalUnit::Quarter,
|
|
36735
|
-
"MONTH" | "MM" | "M" =>
|
|
36923
|
+
"MONTH" | "MONTHS" | "MON" | "MONS" | "MM" | "M" => {
|
|
36924
|
+
crate::expressions::IntervalUnit::Month
|
|
36925
|
+
}
|
|
36736
36926
|
"WEEK" | "WK" | "WW" | "ISOWEEK" => crate::expressions::IntervalUnit::Week,
|
|
36737
36927
|
"DAY" | "DD" | "D" | "DY" => crate::expressions::IntervalUnit::Day,
|
|
36738
36928
|
"HOUR" | "HH" => crate::expressions::IntervalUnit::Hour,
|
|
@@ -114,6 +114,7 @@ pub enum Expression {
|
|
|
114
114
|
Copy(Box<CopyStmt>),
|
|
115
115
|
Put(Box<PutStmt>),
|
|
116
116
|
StageReference(Box<StageReference>),
|
|
117
|
+
TryCatch(Box<TryCatch>),
|
|
117
118
|
|
|
118
119
|
// Expressions
|
|
119
120
|
Alias(Box<Alias>),
|
|
@@ -1146,6 +1147,7 @@ impl Expression {
|
|
|
1146
1147
|
| Expression::Copy(_)
|
|
1147
1148
|
| Expression::Put(_)
|
|
1148
1149
|
| Expression::Merge(_)
|
|
1150
|
+
| Expression::TryCatch(_)
|
|
1149
1151
|
|
|
1150
1152
|
// DDL
|
|
1151
1153
|
| Expression::CreateTable(_)
|
|
@@ -2229,6 +2231,7 @@ impl Expression {
|
|
|
2229
2231
|
Expression::Describe(_) => "describe",
|
|
2230
2232
|
Expression::Show(_) => "show",
|
|
2231
2233
|
Expression::Command(_) => "command",
|
|
2234
|
+
Expression::TryCatch(_) => "try_catch",
|
|
2232
2235
|
Expression::Kill(_) => "kill",
|
|
2233
2236
|
Expression::Execute(_) => "execute",
|
|
2234
2237
|
Expression::Raw(_) => "raw",
|
|
@@ -6003,6 +6006,18 @@ pub struct Command {
|
|
|
6003
6006
|
pub this: String,
|
|
6004
6007
|
}
|
|
6005
6008
|
|
|
6009
|
+
/// T-SQL TRY/CATCH block.
|
|
6010
|
+
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
6011
|
+
#[cfg_attr(feature = "bindings", derive(TS))]
|
|
6012
|
+
pub struct TryCatch {
|
|
6013
|
+
/// Statements inside BEGIN TRY ... END TRY.
|
|
6014
|
+
#[serde(default)]
|
|
6015
|
+
pub try_body: Vec<Expression>,
|
|
6016
|
+
/// Statements inside BEGIN CATCH ... END CATCH, when present.
|
|
6017
|
+
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
6018
|
+
pub catch_body: Option<Vec<Expression>>,
|
|
6019
|
+
}
|
|
6020
|
+
|
|
6006
6021
|
/// EXEC/EXECUTE statement (TSQL stored procedure call)
|
|
6007
6022
|
/// Syntax: EXEC [schema.]procedure_name [@param=value, ...]
|
|
6008
6023
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
@@ -3342,6 +3342,7 @@ impl Generator {
|
|
|
3342
3342
|
Ok(())
|
|
3343
3343
|
}
|
|
3344
3344
|
Expression::CreateTask(task) => self.generate_create_task(task),
|
|
3345
|
+
Expression::TryCatch(try_catch) => self.generate_try_catch(try_catch),
|
|
3345
3346
|
Expression::Command(cmd) => {
|
|
3346
3347
|
self.write(&cmd.this);
|
|
3347
3348
|
Ok(())
|
|
@@ -14109,6 +14110,58 @@ impl Generator {
|
|
|
14109
14110
|
Ok(())
|
|
14110
14111
|
}
|
|
14111
14112
|
|
|
14113
|
+
fn generate_try_catch(&mut self, try_catch: &TryCatch) -> Result<()> {
|
|
14114
|
+
self.write_keyword("BEGIN TRY");
|
|
14115
|
+
self.generate_tsql_block_statements(&try_catch.try_body)?;
|
|
14116
|
+
self.write_keyword("END TRY");
|
|
14117
|
+
|
|
14118
|
+
if let Some(catch_body) = &try_catch.catch_body {
|
|
14119
|
+
if self.config.pretty {
|
|
14120
|
+
self.write_newline();
|
|
14121
|
+
self.write_indent();
|
|
14122
|
+
} else {
|
|
14123
|
+
self.write_space();
|
|
14124
|
+
}
|
|
14125
|
+
self.write_keyword("BEGIN CATCH");
|
|
14126
|
+
self.generate_tsql_block_statements(catch_body)?;
|
|
14127
|
+
self.write_keyword("END CATCH");
|
|
14128
|
+
}
|
|
14129
|
+
|
|
14130
|
+
Ok(())
|
|
14131
|
+
}
|
|
14132
|
+
|
|
14133
|
+
fn generate_tsql_block_statements(&mut self, statements: &[Expression]) -> Result<()> {
|
|
14134
|
+
if statements.is_empty() {
|
|
14135
|
+
self.write_space();
|
|
14136
|
+
return Ok(());
|
|
14137
|
+
}
|
|
14138
|
+
|
|
14139
|
+
if self.config.pretty {
|
|
14140
|
+
self.indent_level += 1;
|
|
14141
|
+
for stmt in statements {
|
|
14142
|
+
self.write_newline();
|
|
14143
|
+
self.write_indent();
|
|
14144
|
+
self.generate_expression(stmt)?;
|
|
14145
|
+
self.write(";");
|
|
14146
|
+
}
|
|
14147
|
+
self.indent_level -= 1;
|
|
14148
|
+
self.write_newline();
|
|
14149
|
+
self.write_indent();
|
|
14150
|
+
} else {
|
|
14151
|
+
self.write_space();
|
|
14152
|
+
for (i, stmt) in statements.iter().enumerate() {
|
|
14153
|
+
if i > 0 {
|
|
14154
|
+
self.write_space();
|
|
14155
|
+
}
|
|
14156
|
+
self.generate_expression(stmt)?;
|
|
14157
|
+
self.write(";");
|
|
14158
|
+
}
|
|
14159
|
+
self.write_space();
|
|
14160
|
+
}
|
|
14161
|
+
|
|
14162
|
+
Ok(())
|
|
14163
|
+
}
|
|
14164
|
+
|
|
14112
14165
|
fn generate_drop_type(&mut self, dt: &DropType) -> Result<()> {
|
|
14113
14166
|
self.write_keyword("DROP TYPE");
|
|
14114
14167
|
|
|
@@ -18528,7 +18581,7 @@ impl Generator {
|
|
|
18528
18581
|
};
|
|
18529
18582
|
match lower {
|
|
18530
18583
|
"day" | "days" | "d" => "DAY".to_string(),
|
|
18531
|
-
"month" | "months" | "mon" | "mm" => "MONTH".to_string(),
|
|
18584
|
+
"month" | "months" | "mon" | "mons" | "mm" => "MONTH".to_string(),
|
|
18532
18585
|
"year" | "years" | "y" | "yy" | "yyyy" => "YEAR".to_string(),
|
|
18533
18586
|
"week" | "weeks" | "w" | "wk" => "WEEK".to_string(),
|
|
18534
18587
|
"hour" | "hours" | "h" | "hh" => "HOUR".to_string(),
|
|
@@ -1658,6 +1658,16 @@ fn collect_column_refs(expr: &Expression, refs: &mut Vec<SimpleColumnRef>) {
|
|
|
1658
1658
|
Expression::NamedArgument(n) => {
|
|
1659
1659
|
stack.push(&n.value);
|
|
1660
1660
|
}
|
|
1661
|
+
Expression::TryCatch(t) => {
|
|
1662
|
+
for stmt in &t.try_body {
|
|
1663
|
+
stack.push(stmt);
|
|
1664
|
+
}
|
|
1665
|
+
if let Some(catch_body) = &t.catch_body {
|
|
1666
|
+
for stmt in catch_body {
|
|
1667
|
+
stack.push(stmt);
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1661
1671
|
Expression::BracedWildcard(e) | Expression::ReturnStmt(e) => {
|
|
1662
1672
|
stack.push(e);
|
|
1663
1673
|
}
|
|
@@ -21032,66 +21032,17 @@ impl Parser {
|
|
|
21032
21032
|
|
|
21033
21033
|
if !is_transaction {
|
|
21034
21034
|
// TSQL: BEGIN TRY ... END TRY [BEGIN CATCH ... END CATCH]
|
|
21035
|
-
//
|
|
21036
|
-
|
|
21037
|
-
|
|
21038
|
-
|
|
21039
|
-
if
|
|
21040
|
-
|
|
21041
|
-
self.
|
|
21042
|
-
|
|
21043
|
-
|
|
21044
|
-
(
|
|
21045
|
-
|
|
21046
|
-
// Collect tokens until matching END TRY / END CATCH
|
|
21047
|
-
while !self.is_at_end() {
|
|
21048
|
-
if self.check(TokenType::End)
|
|
21049
|
-
&& self.current + 1 < self.tokens.len()
|
|
21050
|
-
&& self.tokens[self.current + 1]
|
|
21051
|
-
.text
|
|
21052
|
-
.eq_ignore_ascii_case(block_kind)
|
|
21053
|
-
{
|
|
21054
|
-
tokens.push(("END".to_string(), TokenType::End));
|
|
21055
|
-
self.skip(); // consume END
|
|
21056
|
-
tokens.push((block_kind.to_string(), TokenType::Var));
|
|
21057
|
-
self.skip(); // consume TRY/CATCH
|
|
21058
|
-
break;
|
|
21059
|
-
}
|
|
21060
|
-
let token = self.advance();
|
|
21061
|
-
let text = if token.token_type == TokenType::String {
|
|
21062
|
-
format!("'{}'", token.text)
|
|
21063
|
-
} else if token.token_type == TokenType::QuotedIdentifier {
|
|
21064
|
-
format!("\"{}\"", token.text)
|
|
21065
|
-
} else {
|
|
21066
|
-
token.text.clone()
|
|
21067
|
-
};
|
|
21068
|
-
tokens.push((text, token.token_type));
|
|
21069
|
-
}
|
|
21070
|
-
let mut result = Expression::Command(Box::new(Command {
|
|
21071
|
-
this: self.join_command_tokens(tokens),
|
|
21072
|
-
}));
|
|
21073
|
-
|
|
21074
|
-
// If this was a TRY block, check for a following BEGIN CATCH block
|
|
21075
|
-
if is_try
|
|
21076
|
-
&& self.check(TokenType::Begin)
|
|
21077
|
-
&& self.current + 1 < self.tokens.len()
|
|
21078
|
-
&& self.tokens[self.current + 1]
|
|
21079
|
-
.text
|
|
21080
|
-
.eq_ignore_ascii_case("CATCH")
|
|
21081
|
-
{
|
|
21082
|
-
// Recursively parse the BEGIN CATCH block
|
|
21083
|
-
let catch_block = self.parse_transaction()?;
|
|
21084
|
-
// Combine TRY and CATCH into a single command
|
|
21085
|
-
if let (Expression::Command(try_cmd), Expression::Command(catch_cmd)) =
|
|
21086
|
-
(&result, &catch_block)
|
|
21087
|
-
{
|
|
21088
|
-
result = Expression::Command(Box::new(Command {
|
|
21089
|
-
this: format!("{} {}", try_cmd.this, catch_cmd.this),
|
|
21090
|
-
}));
|
|
21091
|
-
}
|
|
21092
|
-
}
|
|
21093
|
-
|
|
21094
|
-
return Ok(result);
|
|
21035
|
+
// Parse bodies into statement nodes so traversal can see table refs.
|
|
21036
|
+
if self.check_identifier("TRY") {
|
|
21037
|
+
return self.parse_tsql_try_catch();
|
|
21038
|
+
}
|
|
21039
|
+
if self.check_identifier("CATCH") {
|
|
21040
|
+
self.skip(); // consume CATCH
|
|
21041
|
+
let catch_body = self.parse_tsql_block_body("CATCH")?;
|
|
21042
|
+
return Ok(Expression::TryCatch(Box::new(TryCatch {
|
|
21043
|
+
try_body: Vec::new(),
|
|
21044
|
+
catch_body: Some(catch_body),
|
|
21045
|
+
})));
|
|
21095
21046
|
}
|
|
21096
21047
|
|
|
21097
21048
|
// This is a procedural BEGIN block - parse as Command
|
|
@@ -21190,6 +21141,79 @@ impl Parser {
|
|
|
21190
21141
|
})))
|
|
21191
21142
|
}
|
|
21192
21143
|
|
|
21144
|
+
fn parse_tsql_try_catch(&mut self) -> Result<Expression> {
|
|
21145
|
+
self.skip(); // consume TRY
|
|
21146
|
+
let try_body = self.parse_tsql_block_body("TRY")?;
|
|
21147
|
+
let catch_body = if self.check(TokenType::Begin)
|
|
21148
|
+
&& self.current + 1 < self.tokens.len()
|
|
21149
|
+
&& self.tokens[self.current + 1]
|
|
21150
|
+
.text
|
|
21151
|
+
.eq_ignore_ascii_case("CATCH")
|
|
21152
|
+
{
|
|
21153
|
+
self.skip(); // consume BEGIN
|
|
21154
|
+
self.skip(); // consume CATCH
|
|
21155
|
+
Some(self.parse_tsql_block_body("CATCH")?)
|
|
21156
|
+
} else {
|
|
21157
|
+
None
|
|
21158
|
+
};
|
|
21159
|
+
|
|
21160
|
+
Ok(Expression::TryCatch(Box::new(TryCatch {
|
|
21161
|
+
try_body,
|
|
21162
|
+
catch_body,
|
|
21163
|
+
})))
|
|
21164
|
+
}
|
|
21165
|
+
|
|
21166
|
+
fn parse_tsql_block_body(&mut self, block_kind: &str) -> Result<Vec<Expression>> {
|
|
21167
|
+
let tokens = self.collect_tsql_block_body_tokens(block_kind)?;
|
|
21168
|
+
if tokens.is_empty() {
|
|
21169
|
+
return Ok(Vec::new());
|
|
21170
|
+
}
|
|
21171
|
+
|
|
21172
|
+
let mut parser = Parser::with_config(tokens, self.config.clone());
|
|
21173
|
+
parser.parse()
|
|
21174
|
+
}
|
|
21175
|
+
|
|
21176
|
+
fn collect_tsql_block_body_tokens(&mut self, block_kind: &str) -> Result<Vec<Token>> {
|
|
21177
|
+
let mut tokens = Vec::new();
|
|
21178
|
+
let mut depth = 1usize;
|
|
21179
|
+
|
|
21180
|
+
while !self.is_at_end() {
|
|
21181
|
+
if self.check(TokenType::Begin)
|
|
21182
|
+
&& self.current + 1 < self.tokens.len()
|
|
21183
|
+
&& self.tokens[self.current + 1]
|
|
21184
|
+
.text
|
|
21185
|
+
.eq_ignore_ascii_case(block_kind)
|
|
21186
|
+
{
|
|
21187
|
+
depth += 1;
|
|
21188
|
+
tokens.push(self.advance());
|
|
21189
|
+
tokens.push(self.advance());
|
|
21190
|
+
continue;
|
|
21191
|
+
}
|
|
21192
|
+
|
|
21193
|
+
if self.check(TokenType::End)
|
|
21194
|
+
&& self.current + 1 < self.tokens.len()
|
|
21195
|
+
&& self.tokens[self.current + 1]
|
|
21196
|
+
.text
|
|
21197
|
+
.eq_ignore_ascii_case(block_kind)
|
|
21198
|
+
{
|
|
21199
|
+
depth -= 1;
|
|
21200
|
+
if depth == 0 {
|
|
21201
|
+
self.skip(); // consume END
|
|
21202
|
+
self.skip(); // consume TRY/CATCH
|
|
21203
|
+
return Ok(tokens);
|
|
21204
|
+
}
|
|
21205
|
+
|
|
21206
|
+
tokens.push(self.advance());
|
|
21207
|
+
tokens.push(self.advance());
|
|
21208
|
+
continue;
|
|
21209
|
+
}
|
|
21210
|
+
|
|
21211
|
+
tokens.push(self.advance());
|
|
21212
|
+
}
|
|
21213
|
+
|
|
21214
|
+
Err(self.parse_error(format!("Expected END {}", block_kind)))
|
|
21215
|
+
}
|
|
21216
|
+
|
|
21193
21217
|
/// Parse START TRANSACTION statement
|
|
21194
21218
|
/// START TRANSACTION [READ ONLY | READ WRITE] [, ISOLATION LEVEL ...]
|
|
21195
21219
|
fn parse_start_transaction(&mut self) -> Result<Expression> {
|
|
@@ -47359,12 +47383,10 @@ impl Parser {
|
|
|
47359
47383
|
} else {
|
|
47360
47384
|
break;
|
|
47361
47385
|
}
|
|
47362
|
-
// Accept comma
|
|
47363
|
-
|
|
47364
|
-
|
|
47365
|
-
|
|
47366
|
-
break;
|
|
47367
|
-
}
|
|
47386
|
+
// Accept comma-separated DECLARE items. Statement-level semicolons
|
|
47387
|
+
// are consumed by the top-level parser so batches like
|
|
47388
|
+
// `DECLARE @x INT; SELECT @x` keep their statement boundary.
|
|
47389
|
+
if self.match_token(TokenType::Comma) {
|
|
47368
47390
|
continue;
|
|
47369
47391
|
}
|
|
47370
47392
|
break;
|
|
@@ -1001,6 +1001,16 @@ impl<'a> WalkInScopeIter<'a> {
|
|
|
1001
1001
|
// Tables don't have child expressions to traverse within scope
|
|
1002
1002
|
// (joins are handled at the Select level)
|
|
1003
1003
|
}
|
|
1004
|
+
Expression::TryCatch(try_catch) => {
|
|
1005
|
+
for stmt in &try_catch.try_body {
|
|
1006
|
+
children.push(stmt);
|
|
1007
|
+
}
|
|
1008
|
+
if let Some(catch_body) = &try_catch.catch_body {
|
|
1009
|
+
for stmt in catch_body {
|
|
1010
|
+
children.push(stmt);
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1004
1014
|
Expression::Column(_) | Expression::Literal(_) | Expression::Identifier(_) => {
|
|
1005
1015
|
// Leaf nodes - no children
|
|
1006
1016
|
}
|
|
@@ -746,6 +746,12 @@ fn iter_children_lists(expr: &Expression) -> Vec<(&'static str, &[Expression])>
|
|
|
746
746
|
Expression::Tuple(t) => {
|
|
747
747
|
lists.push(("expressions", t.expressions.as_slice()));
|
|
748
748
|
}
|
|
749
|
+
Expression::TryCatch(try_catch) => {
|
|
750
|
+
lists.push(("try_body", try_catch.try_body.as_slice()));
|
|
751
|
+
if let Some(catch_body) = &try_catch.catch_body {
|
|
752
|
+
lists.push(("catch_body", catch_body.as_slice()));
|
|
753
|
+
}
|
|
754
|
+
}
|
|
749
755
|
// Values.expressions is Vec<Tuple>, handle specially
|
|
750
756
|
Expression::Coalesce(c) => {
|
|
751
757
|
lists.push(("expressions", c.expressions.as_slice()));
|