polyglot-sql 0.10.0__tar.gz → 0.11.0__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.10.0 → polyglot_sql-0.11.0}/Cargo.lock +6 -6
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/Cargo.toml +1 -1
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/PKG-INFO +21 -1
- {polyglot_sql-0.10.0/crates/polyglot-sql-python → polyglot_sql-0.11.0}/README.md +20 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/Cargo.toml +2 -2
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/README.md +4 -4
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/benches/performance_hotspots.rs +1 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/bigquery.rs +1 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/clickhouse.rs +1 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/duckdb.rs +2 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/expressions.rs +13 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/generator.rs +91 -48
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/guard.rs +48 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/lineage.rs +24 -6
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/optimizer/annotate_types.rs +171 -37
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/optimizer/qualify_columns.rs +333 -104
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/parser.rs +1780 -774
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/resolver.rs +46 -4
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/scope.rs +9 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/tokens.rs +14 -5
- polyglot_sql-0.11.0/crates/polyglot-sql/tests/data_type_api.rs +251 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/deep_nesting_regression.rs +141 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/query_analysis.rs +106 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-function-catalogs/README.md +1 -1
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0/crates/polyglot-sql-python}/README.md +20 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/transpile.rs +33 -1
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/tests/test_generate.py +33 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/tests/test_query_analysis.py +23 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/tests/test_transpile.py +36 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/python/polyglot_sql/__init__.py +18 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/python/polyglot_sql/__init__.pyi +14 -1
- polyglot_sql-0.10.0/crates/polyglot-sql/tests/data_type_api.rs +0 -86
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/benches/allocation_hotspots.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/benches/ast_traversal.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/benches/in_list.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/benches/lineage.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/benches/parsing.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/benches/rust_parsing.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/benches/transpile.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/examples/basic_usage.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/examples/bench_json.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/ast_children.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/ast_json.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/ast_mutation.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/ast_transforms.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/builder/mod.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/builder/plan.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/athena.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/cockroachdb.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/databricks.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/datafusion.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/doris.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/dremio.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/drill.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/druid.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/dune.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/exasol.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/fabric.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/generic.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/hive.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/materialize.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/mod.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/mysql.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/normalization/aggregates.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/normalization/collections.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/normalization/json.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/normalization/mod.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/normalization/operators.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/normalization/postgres_interval.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/normalization/scalar.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/normalization/statements.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/normalization/temporal.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/normalization/types.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/oracle.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/postgres.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/presto.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/redshift.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/risingwave.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/singlestore.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/snowflake.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/solr.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/spark.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/sqlite.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/starrocks.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/tableau.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/teradata.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/tidb.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/trino.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/dialects/tsql.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/diff.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/error.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/format_tokens.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/function_catalog.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/function_registry.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/helper.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/lib.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/openlineage.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/optimizer/canonicalize.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/optimizer/eliminate_ctes.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/optimizer/eliminate_joins.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/optimizer/isolate_table_selects.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/optimizer/mod.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/optimizer/normalize.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/optimizer/normalize_identifiers.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/optimizer/optimize_joins.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/optimizer/optimizer.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/optimizer/pushdown_predicates.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/optimizer/pushdown_projections.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/optimizer/qualify_tables.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/optimizer/simplify.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/optimizer/subquery.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/planner.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/query_analysis/column_uses.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/query_analysis.rs +3 -3
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/schema.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/set_operation.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/time.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/transforms.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/traversal.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/trie.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/validation/tests.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/src/validation.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/analyze_failures.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/clickhouse_regression.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/common/known_failures.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/common/mod.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/common/test_data.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/common/test_runner.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/create_view_security_comment_regression.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/custom_clickhouse_coverage.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/custom_clickhouse_parser.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/custom_dialect.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/custom_dialect_tests.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/custom_fixtures/datafusion/ddl.json +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/custom_fixtures/datafusion/dml.json +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/custom_fixtures/datafusion/functions.json +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/custom_fixtures/datafusion/identity.json +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/custom_fixtures/datafusion/operators.json +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/custom_fixtures/datafusion/select.json +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/custom_fixtures/datafusion/transpilation.json +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/custom_fixtures/datafusion/types.json +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/dialect_matrix.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/error_handling.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/fabric_regression.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/fabric_tpch_regression.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/identity_roundtrip.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/oracle_data_types_regression.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/postgres_explain_options.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/postgres_regexp_clickhouse.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/postgres_sqlite_regression.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/query_analysis_regression.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/snowflake_regression_test.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/sqlglot_compat.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/sqlglot_dialect_identity.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/sqlglot_identity.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/sqlglot_identity_detailed.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/sqlglot_parser.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/sqlglot_pretty.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/sqlglot_transpilation.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/sqlglot_transpile.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/tpch_transpile_stack.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/transform_regression.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql/tests/tsql_regression.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-ast-derive/Cargo.toml +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-ast-derive/src/lib.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-function-catalogs/Cargo.toml +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-function-catalogs/src/clickhouse.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-function-catalogs/src/duckdb.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-function-catalogs/src/lib.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-function-catalogs/tools/clickhouse/extract_functions.py +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-function-catalogs/tools/duckdb/extract_functions.py +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/Cargo.toml +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/docs/api.md +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/docs/index.md +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/mkdocs.yml +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/annotate_types.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/builders.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/dialects.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/diff.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/errors.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/expr.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/expr_types.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/format.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/generate.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/helpers.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/lib.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/lineage.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/openlineage.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/optimize.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/parse.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/query_analysis.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/tokenize.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/transforms.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/types.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/src/validate.rs +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/tests/conftest.py +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/tests/test_builders.py +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/tests/test_compat.py +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/tests/test_dialects.py +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/tests/test_diff.py +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/tests/test_expression.py +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/tests/test_format.py +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/tests/test_lineage.py +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/tests/test_optimize.py +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/tests/test_parse.py +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/tests/test_transforms.py +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/tests/test_validate.py +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/crates/polyglot-sql-python/uv.lock +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/pyproject.toml +0 -0
- {polyglot_sql-0.10.0 → polyglot_sql-0.11.0}/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.
|
|
608
|
+
version = "0.11.0"
|
|
609
609
|
dependencies = [
|
|
610
610
|
"criterion",
|
|
611
611
|
"once_cell",
|
|
@@ -623,7 +623,7 @@ dependencies = [
|
|
|
623
623
|
|
|
624
624
|
[[package]]
|
|
625
625
|
name = "polyglot-sql-ast-derive"
|
|
626
|
-
version = "0.
|
|
626
|
+
version = "0.11.0"
|
|
627
627
|
dependencies = [
|
|
628
628
|
"proc-macro2",
|
|
629
629
|
"quote",
|
|
@@ -632,7 +632,7 @@ dependencies = [
|
|
|
632
632
|
|
|
633
633
|
[[package]]
|
|
634
634
|
name = "polyglot-sql-ffi"
|
|
635
|
-
version = "0.
|
|
635
|
+
version = "0.11.0"
|
|
636
636
|
dependencies = [
|
|
637
637
|
"cbindgen",
|
|
638
638
|
"polyglot-sql",
|
|
@@ -642,11 +642,11 @@ dependencies = [
|
|
|
642
642
|
|
|
643
643
|
[[package]]
|
|
644
644
|
name = "polyglot-sql-function-catalogs"
|
|
645
|
-
version = "0.
|
|
645
|
+
version = "0.11.0"
|
|
646
646
|
|
|
647
647
|
[[package]]
|
|
648
648
|
name = "polyglot-sql-python"
|
|
649
|
-
version = "0.
|
|
649
|
+
version = "0.11.0"
|
|
650
650
|
dependencies = [
|
|
651
651
|
"polyglot-sql",
|
|
652
652
|
"pyo3",
|
|
@@ -657,7 +657,7 @@ dependencies = [
|
|
|
657
657
|
|
|
658
658
|
[[package]]
|
|
659
659
|
name = "polyglot-sql-wasm"
|
|
660
|
-
version = "0.
|
|
660
|
+
version = "0.11.0"
|
|
661
661
|
dependencies = [
|
|
662
662
|
"console_error_panic_hook",
|
|
663
663
|
"js-sys",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: polyglot-sql
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.0
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -110,6 +110,26 @@ polyglot_sql.generate(ast)
|
|
|
110
110
|
# ["SELECT id FROM a UNION ALL SELECT id FROM b ORDER BY id LIMIT 100 OFFSET 10"]
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
+
### Complexity Guard Options
|
|
114
|
+
|
|
115
|
+
`transpile` also accepts `complexity_guard`, a `ComplexityGuardOptions` typed dictionary
|
|
116
|
+
using the shared camelCase keys: `maxParserDepth`, `maxInputBytes`, `maxTokens`,
|
|
117
|
+
`maxAstNodes`, `maxAstDepth`, `maxParenthesisDepth`, and `maxFunctionCallDepth`.
|
|
118
|
+
Omit the argument, pass `None`, or omit a key to use its default. A field-level `None`
|
|
119
|
+
disables that check; a nonnegative integer overrides it. For example:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
polyglot_sql.transpile(sql, complexity_guard={"maxParserDepth": 128})
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Parser depth defaults to 1024 logical levels on native targets (32 on WASM) and is
|
|
126
|
+
checked during parsing, before an AST exists. Zero rejects parsing descents.
|
|
127
|
+
Other checks remain independent.
|
|
128
|
+
Raising or disabling limits can permit stack exhaustion and process termination,
|
|
129
|
+
even for trusted generated SQL. Increasing a limit does not increase stack space;
|
|
130
|
+
these limits are not general time/memory budgets. Application owners should control
|
|
131
|
+
overrides. Parsing APIs without guard options inherit the default protection.
|
|
132
|
+
|
|
113
133
|
### Format Guard Behavior
|
|
114
134
|
|
|
115
135
|
`format_sql` uses Rust core formatting guards with default limits:
|
|
@@ -83,6 +83,26 @@ polyglot_sql.generate(ast)
|
|
|
83
83
|
# ["SELECT id FROM a UNION ALL SELECT id FROM b ORDER BY id LIMIT 100 OFFSET 10"]
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
+
### Complexity Guard Options
|
|
87
|
+
|
|
88
|
+
`transpile` also accepts `complexity_guard`, a `ComplexityGuardOptions` typed dictionary
|
|
89
|
+
using the shared camelCase keys: `maxParserDepth`, `maxInputBytes`, `maxTokens`,
|
|
90
|
+
`maxAstNodes`, `maxAstDepth`, `maxParenthesisDepth`, and `maxFunctionCallDepth`.
|
|
91
|
+
Omit the argument, pass `None`, or omit a key to use its default. A field-level `None`
|
|
92
|
+
disables that check; a nonnegative integer overrides it. For example:
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
polyglot_sql.transpile(sql, complexity_guard={"maxParserDepth": 128})
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Parser depth defaults to 1024 logical levels on native targets (32 on WASM) and is
|
|
99
|
+
checked during parsing, before an AST exists. Zero rejects parsing descents.
|
|
100
|
+
Other checks remain independent.
|
|
101
|
+
Raising or disabling limits can permit stack exhaustion and process termination,
|
|
102
|
+
even for trusted generated SQL. Increasing a limit does not increase stack space;
|
|
103
|
+
these limits are not general time/memory budgets. Application owners should control
|
|
104
|
+
overrides. Parsing APIs without guard options inherit the default protection.
|
|
105
|
+
|
|
86
106
|
### Format Guard Behavior
|
|
87
107
|
|
|
88
108
|
`format_sql` uses Rust core formatting guards with default limits:
|
|
@@ -100,14 +100,14 @@ function-catalog-all-dialects = [
|
|
|
100
100
|
]
|
|
101
101
|
|
|
102
102
|
[dependencies]
|
|
103
|
-
polyglot-sql-ast-derive = { path = "../polyglot-sql-ast-derive", version = "0.
|
|
103
|
+
polyglot-sql-ast-derive = { path = "../polyglot-sql-ast-derive", version = "0.11.0" }
|
|
104
104
|
serde = { workspace = true }
|
|
105
105
|
serde_json = { workspace = true }
|
|
106
106
|
thiserror = { workspace = true }
|
|
107
107
|
unicode-segmentation = { workspace = true }
|
|
108
108
|
stacker = { version = "0.1", optional = true }
|
|
109
109
|
ts-rs = { version = "12.0", features = ["serde-compat"], optional = true }
|
|
110
|
-
polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.
|
|
110
|
+
polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.11.0", optional = true, default-features = false }
|
|
111
111
|
|
|
112
112
|
[dev-dependencies]
|
|
113
113
|
pretty_assertions = "1.4"
|
|
@@ -25,12 +25,12 @@ By default, `polyglot-sql` enables the full public API. Parser-only consumers ca
|
|
|
25
25
|
disable default features and opt into only the dialect parsers they need:
|
|
26
26
|
|
|
27
27
|
```toml
|
|
28
|
-
polyglot-sql = { version = "0.
|
|
28
|
+
polyglot-sql = { version = "0.11.0", default-features = false }
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
```toml
|
|
32
32
|
polyglot-sql = {
|
|
33
|
-
version = "0.
|
|
33
|
+
version = "0.11.0",
|
|
34
34
|
default-features = false,
|
|
35
35
|
features = ["dialect-clickhouse"],
|
|
36
36
|
}
|
|
@@ -44,14 +44,14 @@ Examples:
|
|
|
44
44
|
```toml
|
|
45
45
|
# Parse and generate SQL for one dialect.
|
|
46
46
|
polyglot-sql = {
|
|
47
|
-
version = "0.
|
|
47
|
+
version = "0.11.0",
|
|
48
48
|
default-features = false,
|
|
49
49
|
features = ["generate", "dialect-clickhouse"],
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
# Cross-dialect transpilation.
|
|
53
53
|
polyglot-sql = {
|
|
54
|
-
version = "0.
|
|
54
|
+
version = "0.11.0",
|
|
55
55
|
default-features = false,
|
|
56
56
|
features = ["transpile", "dialect-clickhouse", "dialect-postgresql"],
|
|
57
57
|
}
|
|
@@ -34,6 +34,7 @@ impl DialectImpl for BigQueryDialect {
|
|
|
34
34
|
// Remove double quote from identifiers (it's in the default config)
|
|
35
35
|
config.identifiers.remove(&'"');
|
|
36
36
|
config.identifiers.insert('`', '`');
|
|
37
|
+
config.identifier_backslash_escapes = true;
|
|
37
38
|
// BigQuery supports double quotes for strings (in addition to single quotes)
|
|
38
39
|
config.quotes.insert("\"".to_string(), "\"".to_string());
|
|
39
40
|
// BigQuery supports triple-quoted strings
|
|
@@ -28,6 +28,7 @@ impl DialectImpl for ClickHouseDialect {
|
|
|
28
28
|
// ClickHouse uses double quotes and backticks for identifiers
|
|
29
29
|
config.identifiers.insert('"', '"');
|
|
30
30
|
config.identifiers.insert('`', '`');
|
|
31
|
+
config.identifier_backslash_escapes = true;
|
|
31
32
|
// ClickHouse supports nested comments
|
|
32
33
|
config.nested_comments = true;
|
|
33
34
|
// ClickHouse allows identifiers to start with digits
|
|
@@ -97,6 +97,8 @@ impl DialectImpl for DuckDBDialect {
|
|
|
97
97
|
let mut config = TokenizerConfig::default();
|
|
98
98
|
// DuckDB uses double quotes for identifiers
|
|
99
99
|
config.identifiers.insert('"', '"');
|
|
100
|
+
// A leading escaped double quote belongs to the identifier, not a triple-quoted string.
|
|
101
|
+
config.quotes.remove("\"\"\"");
|
|
100
102
|
// DuckDB supports nested comments
|
|
101
103
|
config.nested_comments = true;
|
|
102
104
|
// DuckDB allows underscores as digit separators in numeric literals
|
|
@@ -3373,6 +3373,16 @@ impl Identifier {
|
|
|
3373
3373
|
self.name.is_empty()
|
|
3374
3374
|
}
|
|
3375
3375
|
|
|
3376
|
+
/// Preserve quoting in the legacy string representation of named type fields.
|
|
3377
|
+
/// Always use SQL-standard delimiters internally, independent of the source dialect.
|
|
3378
|
+
pub(crate) fn to_type_field_name(&self) -> String {
|
|
3379
|
+
if self.quoted {
|
|
3380
|
+
format!("\"{}\"", self.name.replace('"', "\"\""))
|
|
3381
|
+
} else {
|
|
3382
|
+
self.name.clone()
|
|
3383
|
+
}
|
|
3384
|
+
}
|
|
3385
|
+
|
|
3376
3386
|
/// Set the source span on this identifier
|
|
3377
3387
|
pub fn with_span(mut self, span: Span) -> Self {
|
|
3378
3388
|
self.span = Some(span);
|
|
@@ -5740,6 +5750,9 @@ pub enum WindowFrameBound {
|
|
|
5740
5750
|
#[derive(polyglot_sql_ast_derive::AstNode, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
5741
5751
|
#[cfg_attr(feature = "bindings", derive(TS))]
|
|
5742
5752
|
pub struct StructField {
|
|
5753
|
+
/// A raw field name, or a delimited identifier for compatibility with parsed ASTs.
|
|
5754
|
+
/// Parsed quoted names use double quotes with doubled internal quotes. An empty
|
|
5755
|
+
/// string denotes an anonymous field. Generation selects the target dialect's quotes.
|
|
5743
5756
|
pub name: String,
|
|
5744
5757
|
pub data_type: DataType,
|
|
5745
5758
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
|
@@ -16621,22 +16621,7 @@ impl Generator {
|
|
|
16621
16621
|
} else {
|
|
16622
16622
|
quote_style
|
|
16623
16623
|
};
|
|
16624
|
-
|
|
16625
|
-
let escaped_name = if quote_style.start == quote_style.end {
|
|
16626
|
-
output_name.replace(
|
|
16627
|
-
quote_style.end,
|
|
16628
|
-
&format!("{}{}", quote_style.end, quote_style.end),
|
|
16629
|
-
)
|
|
16630
|
-
} else {
|
|
16631
|
-
output_name.replace(
|
|
16632
|
-
quote_style.end,
|
|
16633
|
-
&format!("{}{}", quote_style.end, quote_style.end),
|
|
16634
|
-
)
|
|
16635
|
-
};
|
|
16636
|
-
self.write(&format!(
|
|
16637
|
-
"{}{}{}",
|
|
16638
|
-
quote_style.start, escaped_name, quote_style.end
|
|
16639
|
-
));
|
|
16624
|
+
self.write_quoted_identifier(&output_name, *quote_style);
|
|
16640
16625
|
} else {
|
|
16641
16626
|
self.write(&output_name);
|
|
16642
16627
|
}
|
|
@@ -16746,24 +16731,8 @@ impl Generator {
|
|
|
16746
16731
|
};
|
|
16747
16732
|
|
|
16748
16733
|
if needs_quoting {
|
|
16749
|
-
|
|
16750
|
-
|
|
16751
|
-
// Same start/end char (e.g., " or `) - double the quote char
|
|
16752
|
-
output_name.replace(
|
|
16753
|
-
quote_style.end,
|
|
16754
|
-
&format!("{}{}", quote_style.end, quote_style.end),
|
|
16755
|
-
)
|
|
16756
|
-
} else {
|
|
16757
|
-
// Different start/end (e.g., [ and ]) - escape only the end char
|
|
16758
|
-
output_name.replace(
|
|
16759
|
-
quote_style.end,
|
|
16760
|
-
&format!("{}{}", quote_style.end, quote_style.end),
|
|
16761
|
-
)
|
|
16762
|
-
};
|
|
16763
|
-
self.write(&format!(
|
|
16764
|
-
"{}{}{}{}",
|
|
16765
|
-
quote_style.start, escaped_name, quote_style.end, suffix
|
|
16766
|
-
));
|
|
16734
|
+
self.write_quoted_identifier(&output_name, *quote_style);
|
|
16735
|
+
self.write(&suffix);
|
|
16767
16736
|
} else {
|
|
16768
16737
|
self.write(&output_name);
|
|
16769
16738
|
}
|
|
@@ -16776,6 +16745,78 @@ impl Generator {
|
|
|
16776
16745
|
Ok(())
|
|
16777
16746
|
}
|
|
16778
16747
|
|
|
16748
|
+
/// Write an identifier using the target dialect's delimiters and escape rules.
|
|
16749
|
+
fn write_quoted_identifier(&mut self, name: &str, quote_style: IdentifierQuoteStyle) {
|
|
16750
|
+
let backslash_escapes = matches!(
|
|
16751
|
+
self.config.dialect,
|
|
16752
|
+
Some(DialectType::BigQuery | DialectType::ClickHouse)
|
|
16753
|
+
);
|
|
16754
|
+
self.output.push(quote_style.start);
|
|
16755
|
+
for c in name.chars() {
|
|
16756
|
+
if backslash_escapes {
|
|
16757
|
+
let escape = match c {
|
|
16758
|
+
'\\' => Some("\\\\"),
|
|
16759
|
+
'\n' => Some("\\n"),
|
|
16760
|
+
'\r' => Some("\\r"),
|
|
16761
|
+
'\t' => Some("\\t"),
|
|
16762
|
+
'\0' => Some("\\x00"),
|
|
16763
|
+
_ => None,
|
|
16764
|
+
};
|
|
16765
|
+
if let Some(escape) = escape {
|
|
16766
|
+
self.write(escape);
|
|
16767
|
+
continue;
|
|
16768
|
+
}
|
|
16769
|
+
if c == quote_style.end && self.config.dialect == Some(DialectType::BigQuery) {
|
|
16770
|
+
self.output.push('\\');
|
|
16771
|
+
self.output.push(c);
|
|
16772
|
+
continue;
|
|
16773
|
+
}
|
|
16774
|
+
}
|
|
16775
|
+
self.output.push(c);
|
|
16776
|
+
if c == quote_style.end {
|
|
16777
|
+
self.output.push(c);
|
|
16778
|
+
}
|
|
16779
|
+
}
|
|
16780
|
+
self.output.push(quote_style.end);
|
|
16781
|
+
}
|
|
16782
|
+
|
|
16783
|
+
/// Named type fields are single identifiers, never SQL fragments or index columns.
|
|
16784
|
+
/// Keep the public string shape while accepting legacy delimited field names.
|
|
16785
|
+
fn generate_type_field_name(&mut self, field_name: &str) {
|
|
16786
|
+
let mut name = Cow::Borrowed(field_name);
|
|
16787
|
+
let mut quoted = false;
|
|
16788
|
+
for (start, end) in [('"', '"'), ('`', '`'), ('[', ']')] {
|
|
16789
|
+
if let Some(inner) = field_name
|
|
16790
|
+
.strip_prefix(start)
|
|
16791
|
+
.and_then(|s| s.strip_suffix(end))
|
|
16792
|
+
{
|
|
16793
|
+
name = Cow::Owned(inner.replace(&format!("{end}{end}"), &end.to_string()));
|
|
16794
|
+
quoted = true;
|
|
16795
|
+
break;
|
|
16796
|
+
}
|
|
16797
|
+
}
|
|
16798
|
+
|
|
16799
|
+
let needs_quoting = quoted
|
|
16800
|
+
|| !Self::is_safe_unquoted_identifier(&name)
|
|
16801
|
+
|| self.is_reserved_keyword(&name)
|
|
16802
|
+
|| self.config.always_quote_identifiers;
|
|
16803
|
+
if self.config.normalize_identifiers && !quoted {
|
|
16804
|
+
name = Cow::Owned(name.to_ascii_lowercase());
|
|
16805
|
+
}
|
|
16806
|
+
if !needs_quoting {
|
|
16807
|
+
self.write(&name);
|
|
16808
|
+
return;
|
|
16809
|
+
}
|
|
16810
|
+
|
|
16811
|
+
let quote_style =
|
|
16812
|
+
if self.config.dialect == Some(DialectType::Athena) && self.athena_hive_context {
|
|
16813
|
+
IdentifierQuoteStyle::BACKTICK
|
|
16814
|
+
} else {
|
|
16815
|
+
self.config.identifier_quote_style
|
|
16816
|
+
};
|
|
16817
|
+
self.write_quoted_identifier(&name, quote_style);
|
|
16818
|
+
}
|
|
16819
|
+
|
|
16779
16820
|
fn generate_column(&mut self, col: &Column) -> Result<()> {
|
|
16780
16821
|
use crate::dialects::DialectType;
|
|
16781
16822
|
|
|
@@ -26846,7 +26887,7 @@ impl Generator {
|
|
|
26846
26887
|
if i > 0 {
|
|
26847
26888
|
self.write(", ");
|
|
26848
26889
|
}
|
|
26849
|
-
self.
|
|
26890
|
+
self.generate_type_field_name(name);
|
|
26850
26891
|
self.write(" ");
|
|
26851
26892
|
self.generate_data_type(dt)?;
|
|
26852
26893
|
if *not_null {
|
|
@@ -26870,7 +26911,7 @@ impl Generator {
|
|
|
26870
26911
|
self.write(", ");
|
|
26871
26912
|
}
|
|
26872
26913
|
if !field.name.is_empty() {
|
|
26873
|
-
self.
|
|
26914
|
+
self.generate_type_field_name(&field.name);
|
|
26874
26915
|
self.write(" ");
|
|
26875
26916
|
}
|
|
26876
26917
|
self.generate_data_type(&field.data_type)?;
|
|
@@ -26885,7 +26926,7 @@ impl Generator {
|
|
|
26885
26926
|
self.write(", ");
|
|
26886
26927
|
}
|
|
26887
26928
|
if !field.name.is_empty() {
|
|
26888
|
-
self.
|
|
26929
|
+
self.generate_type_field_name(&field.name);
|
|
26889
26930
|
self.write(" ");
|
|
26890
26931
|
}
|
|
26891
26932
|
self.generate_data_type(&field.data_type)?;
|
|
@@ -26900,7 +26941,7 @@ impl Generator {
|
|
|
26900
26941
|
self.write(", ");
|
|
26901
26942
|
}
|
|
26902
26943
|
if !field.name.is_empty() {
|
|
26903
|
-
self.
|
|
26944
|
+
self.generate_type_field_name(&field.name);
|
|
26904
26945
|
self.write(" ");
|
|
26905
26946
|
}
|
|
26906
26947
|
self.generate_data_type(&field.data_type)?;
|
|
@@ -26915,7 +26956,7 @@ impl Generator {
|
|
|
26915
26956
|
self.write(", ");
|
|
26916
26957
|
}
|
|
26917
26958
|
if !field.name.is_empty() {
|
|
26918
|
-
self.
|
|
26959
|
+
self.generate_type_field_name(&field.name);
|
|
26919
26960
|
self.write(" ");
|
|
26920
26961
|
}
|
|
26921
26962
|
self.generate_data_type(&field.data_type)?;
|
|
@@ -26930,7 +26971,7 @@ impl Generator {
|
|
|
26930
26971
|
self.write(", ");
|
|
26931
26972
|
}
|
|
26932
26973
|
if !field.name.is_empty() {
|
|
26933
|
-
self.
|
|
26974
|
+
self.generate_type_field_name(&field.name);
|
|
26934
26975
|
self.write(" ");
|
|
26935
26976
|
}
|
|
26936
26977
|
self.generate_data_type(&field.data_type)?;
|
|
@@ -26938,12 +26979,14 @@ impl Generator {
|
|
|
26938
26979
|
self.write(")");
|
|
26939
26980
|
}
|
|
26940
26981
|
_ => {
|
|
26941
|
-
// Hive/Spark
|
|
26982
|
+
// BigQuery and Hive/Spark use angle brackets even for types
|
|
26983
|
+
// parsed from a parenthesized source dialect.
|
|
26942
26984
|
let force_angle_brackets = matches!(
|
|
26943
26985
|
self.config.dialect,
|
|
26944
26986
|
Some(DialectType::Hive)
|
|
26945
26987
|
| Some(DialectType::Spark)
|
|
26946
26988
|
| Some(DialectType::Databricks)
|
|
26989
|
+
| Some(DialectType::BigQuery)
|
|
26947
26990
|
);
|
|
26948
26991
|
if *nested && !force_angle_brackets {
|
|
26949
26992
|
self.write_keyword("STRUCT(");
|
|
@@ -26952,7 +26995,7 @@ impl Generator {
|
|
|
26952
26995
|
self.write(", ");
|
|
26953
26996
|
}
|
|
26954
26997
|
if !field.name.is_empty() {
|
|
26955
|
-
self.
|
|
26998
|
+
self.generate_type_field_name(&field.name);
|
|
26956
26999
|
self.write(" ");
|
|
26957
27000
|
}
|
|
26958
27001
|
self.generate_data_type(&field.data_type)?;
|
|
@@ -26966,7 +27009,7 @@ impl Generator {
|
|
|
26966
27009
|
}
|
|
26967
27010
|
if !field.name.is_empty() {
|
|
26968
27011
|
// Named field: name TYPE (with configurable separator for Hive)
|
|
26969
|
-
self.
|
|
27012
|
+
self.generate_type_field_name(&field.name);
|
|
26970
27013
|
self.write(self.config.struct_field_sep);
|
|
26971
27014
|
}
|
|
26972
27015
|
// For anonymous fields, just output the type
|
|
@@ -27034,7 +27077,7 @@ impl Generator {
|
|
|
27034
27077
|
self.write(", ");
|
|
27035
27078
|
}
|
|
27036
27079
|
if !name.is_empty() {
|
|
27037
|
-
self.
|
|
27080
|
+
self.generate_type_field_name(name);
|
|
27038
27081
|
self.write(" ");
|
|
27039
27082
|
}
|
|
27040
27083
|
self.generate_data_type(dt)?;
|
|
@@ -33275,7 +33318,7 @@ impl Generator {
|
|
|
33275
33318
|
if key.is_empty() {
|
|
33276
33319
|
// Bracket notation at start of segment (e.g., already formatted)
|
|
33277
33320
|
self.write(segment);
|
|
33278
|
-
} else if Self::
|
|
33321
|
+
} else if Self::is_safe_unquoted_identifier(key) {
|
|
33279
33322
|
self.write(key);
|
|
33280
33323
|
self.write(subscript);
|
|
33281
33324
|
} else {
|
|
@@ -33284,7 +33327,7 @@ impl Generator {
|
|
|
33284
33327
|
self.write("\"]");
|
|
33285
33328
|
self.write(subscript);
|
|
33286
33329
|
}
|
|
33287
|
-
} else if Self::
|
|
33330
|
+
} else if Self::is_safe_unquoted_identifier(segment) {
|
|
33288
33331
|
self.write(segment);
|
|
33289
33332
|
} else {
|
|
33290
33333
|
self.write("[\"");
|
|
@@ -33294,9 +33337,9 @@ impl Generator {
|
|
|
33294
33337
|
}
|
|
33295
33338
|
}
|
|
33296
33339
|
|
|
33297
|
-
/// Check if a
|
|
33340
|
+
/// Check if a name can be emitted as a conservative unquoted identifier.
|
|
33298
33341
|
/// Matches Python sqlglot's SAFE_IDENTIFIER_RE: ^[_a-zA-Z]\w*$
|
|
33299
|
-
fn
|
|
33342
|
+
fn is_safe_unquoted_identifier(key: &str) -> bool {
|
|
33300
33343
|
if key.is_empty() {
|
|
33301
33344
|
return false;
|
|
33302
33345
|
}
|
|
@@ -11,6 +11,21 @@ const DEFAULT_MAX_AST_NODES: usize = 1_000_000;
|
|
|
11
11
|
const DEFAULT_MAX_AST_DEPTH: usize = 512;
|
|
12
12
|
const DEFAULT_MAX_PARENTHESES_DEPTH: usize = 512;
|
|
13
13
|
const DEFAULT_MAX_FUNCTION_CALL_DEPTH: usize = 64;
|
|
14
|
+
// WASM has no stacker support, and grammar frames differ substantially in size.
|
|
15
|
+
// Keep its default conservative; an explicit option still replaces this value.
|
|
16
|
+
#[cfg(target_arch = "wasm32")]
|
|
17
|
+
const DEFAULT_MAX_PARSER_DEPTH: usize = 32;
|
|
18
|
+
#[cfg(not(target_arch = "wasm32"))]
|
|
19
|
+
const DEFAULT_MAX_PARSER_DEPTH: usize = 1_024;
|
|
20
|
+
|
|
21
|
+
fn default_max_parser_depth() -> Option<usize> {
|
|
22
|
+
Some(DEFAULT_MAX_PARSER_DEPTH)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/// Resource exhaustion must not be treated as a speculative syntax mismatch.
|
|
26
|
+
pub(crate) fn is_guard_error(error: &Error) -> bool {
|
|
27
|
+
matches!(error, Error::Parse { message, .. } if message.starts_with("E_GUARD_"))
|
|
28
|
+
}
|
|
14
29
|
|
|
15
30
|
fn default_max_input_bytes() -> Option<usize> {
|
|
16
31
|
Some(DEFAULT_MAX_INPUT_BYTES)
|
|
@@ -43,6 +58,11 @@ fn default_max_function_call_depth() -> Option<usize> {
|
|
|
43
58
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
|
44
59
|
#[serde(rename_all = "camelCase")]
|
|
45
60
|
pub struct ComplexityGuardOptions {
|
|
61
|
+
/// Maximum logical nesting during parsing, before an AST exists.
|
|
62
|
+
/// Defaults to 32 on WASM and 1024 on native targets.
|
|
63
|
+
/// Raising this limit or disabling it with `None` can permit stack exhaustion.
|
|
64
|
+
#[serde(default = "default_max_parser_depth")]
|
|
65
|
+
pub max_parser_depth: Option<usize>,
|
|
46
66
|
/// Maximum allowed SQL input size in bytes.
|
|
47
67
|
/// `None` disables this check.
|
|
48
68
|
#[serde(default = "default_max_input_bytes")]
|
|
@@ -120,6 +140,7 @@ impl TokenGuardStats {
|
|
|
120
140
|
impl Default for ComplexityGuardOptions {
|
|
121
141
|
fn default() -> Self {
|
|
122
142
|
Self {
|
|
143
|
+
max_parser_depth: default_max_parser_depth(),
|
|
123
144
|
max_input_bytes: default_max_input_bytes(),
|
|
124
145
|
max_tokens: default_max_tokens(),
|
|
125
146
|
max_ast_nodes: default_max_ast_nodes(),
|
|
@@ -372,6 +393,33 @@ mod token_guard_tests {
|
|
|
372
393
|
use crate::tokens::Tokenizer;
|
|
373
394
|
use std::sync::Arc;
|
|
374
395
|
|
|
396
|
+
#[test]
|
|
397
|
+
fn parser_depth_json_contract() {
|
|
398
|
+
let omitted: ComplexityGuardOptions = serde_json::from_str("{}").unwrap();
|
|
399
|
+
assert_eq!(omitted.max_parser_depth, Some(DEFAULT_MAX_PARSER_DEPTH));
|
|
400
|
+
assert_eq!(
|
|
401
|
+
omitted.max_parser_depth,
|
|
402
|
+
ComplexityGuardOptions::default().max_parser_depth
|
|
403
|
+
);
|
|
404
|
+
for limit in [Some(0), Some(1), Some(2048), None] {
|
|
405
|
+
let guard = ComplexityGuardOptions {
|
|
406
|
+
max_parser_depth: limit,
|
|
407
|
+
..Default::default()
|
|
408
|
+
};
|
|
409
|
+
let json = serde_json::to_string(&guard).unwrap();
|
|
410
|
+
assert_eq!(
|
|
411
|
+
serde_json::from_str::<ComplexityGuardOptions>(&json).unwrap(),
|
|
412
|
+
guard
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
for value in ["-1", "1.5", "true", "\"10\""] {
|
|
416
|
+
assert!(serde_json::from_str::<ComplexityGuardOptions>(&format!(
|
|
417
|
+
"{{\"maxParserDepth\":{value}}}"
|
|
418
|
+
))
|
|
419
|
+
.is_err());
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
375
423
|
#[test]
|
|
376
424
|
fn collected_parser_stats_match_full_token_guard_pass() {
|
|
377
425
|
let sql: Arc<str> = Arc::from("SELECT outer(inner((value))), other(1, 2) FROM t");
|
|
@@ -476,8 +476,8 @@ fn normalize_cte_name(ident: &Identifier) -> String {
|
|
|
476
476
|
}
|
|
477
477
|
|
|
478
478
|
/// Expand SELECT * in CTEs by walking CTE definitions in order and propagating
|
|
479
|
-
/// resolved column lists. This handles
|
|
480
|
-
///
|
|
479
|
+
/// resolved column lists. This also handles chained CTEs in schema-free lineage
|
|
480
|
+
/// and analysis paths, where full column qualification is not performed.
|
|
481
481
|
///
|
|
482
482
|
/// When `schema` is provided, stars from external tables (not CTEs) are also resolved
|
|
483
483
|
/// by looking up column names in the schema. This enables correct expansion of patterns
|
|
@@ -1211,14 +1211,26 @@ fn to_node_inner(
|
|
|
1211
1211
|
// 0. Unwrap CTE scope — CTE scope expressions are Expression::Cte(...)
|
|
1212
1212
|
// but we need the inner query (SELECT/UNION) for column lookup.
|
|
1213
1213
|
let effective_expr = effective_scope_expression(scope_expr);
|
|
1214
|
+
// A CTE's explicit output names replace its projection names by ordinal.
|
|
1215
|
+
// Resolve that boundary before unwrapping, including unnamed expressions.
|
|
1216
|
+
let alias_ordinal = match (scope_expr, &column) {
|
|
1217
|
+
(Expression::Cte(cte), ColumnRef::Name(name)) if !cte.columns.is_empty() => {
|
|
1218
|
+
cte.columns.iter().position(|alias| {
|
|
1219
|
+
normalize_column_name(&alias.name, dialect) == normalize_column_name(name, dialect)
|
|
1220
|
+
})
|
|
1221
|
+
}
|
|
1222
|
+
_ => None,
|
|
1223
|
+
};
|
|
1224
|
+
let lookup_column = alias_ordinal.map(ColumnRef::Index);
|
|
1225
|
+
let lookup_column = lookup_column.as_ref().unwrap_or(&column);
|
|
1214
1226
|
|
|
1215
1227
|
// 1. Set operations (UNION / INTERSECT / EXCEPT)
|
|
1216
1228
|
if matches!(
|
|
1217
1229
|
effective_expr,
|
|
1218
1230
|
Expression::Union(_) | Expression::Intersect(_) | Expression::Except(_)
|
|
1219
1231
|
) {
|
|
1220
|
-
|
|
1221
|
-
|
|
1232
|
+
let mut node = handle_set_operation(
|
|
1233
|
+
lookup_column,
|
|
1222
1234
|
context,
|
|
1223
1235
|
scope_id,
|
|
1224
1236
|
effective_expr,
|
|
@@ -1230,11 +1242,17 @@ fn to_node_inner(
|
|
|
1230
1242
|
trim_selects,
|
|
1231
1243
|
&descendant_cte_scopes,
|
|
1232
1244
|
depth,
|
|
1233
|
-
)
|
|
1245
|
+
)?;
|
|
1246
|
+
if alias_ordinal.is_some() {
|
|
1247
|
+
if let ColumnRef::Name(name) = &column {
|
|
1248
|
+
node.name = (*name).to_string();
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
return Ok(node);
|
|
1234
1252
|
}
|
|
1235
1253
|
|
|
1236
1254
|
// 2. Find the select expression for this column
|
|
1237
|
-
let select_expr = find_select_expr(effective_expr,
|
|
1255
|
+
let select_expr = find_select_expr(effective_expr, lookup_column, dialect)?;
|
|
1238
1256
|
let column_name = resolve_column_name(&column, &select_expr);
|
|
1239
1257
|
|
|
1240
1258
|
// 3. Trim source if requested
|