polyglot-sql 0.4.2__tar.gz → 0.4.3__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.
Files changed (175) hide show
  1. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/Cargo.lock +5 -5
  2. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/Cargo.toml +1 -1
  3. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/PKG-INFO +1 -1
  4. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/Cargo.toml +1 -1
  5. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/mod.rs +25 -0
  6. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/expressions.rs +24 -0
  7. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/generator.rs +36 -0
  8. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/lineage.rs +70 -1
  9. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/openlineage.rs +48 -0
  10. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/parser.rs +67 -0
  11. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/scope.rs +18 -0
  12. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/tokens.rs +3 -0
  13. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/traversal.rs +12 -0
  14. polyglot_sql-0.4.3/crates/polyglot-sql/tests/issue210_regression_test.rs +80 -0
  15. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/expr_types.rs +1 -0
  16. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/tests/test_lineage.py +6 -0
  17. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/tests/test_parse.py +20 -0
  18. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/python/polyglot_sql/__init__.py +3 -0
  19. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/python/polyglot_sql/__init__.pyi +1 -0
  20. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/README.md +0 -0
  21. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/README.md +0 -0
  22. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/benches/in_list.rs +0 -0
  23. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/benches/parsing.rs +0 -0
  24. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/benches/rust_parsing.rs +0 -0
  25. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/benches/transpile.rs +0 -0
  26. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/examples/basic_usage.rs +0 -0
  27. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/examples/bench_json.rs +0 -0
  28. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/ast_transforms.rs +0 -0
  29. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/builder.rs +0 -0
  30. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/athena.rs +0 -0
  31. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/bigquery.rs +0 -0
  32. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/clickhouse.rs +0 -0
  33. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/cockroachdb.rs +0 -0
  34. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/databricks.rs +0 -0
  35. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/datafusion.rs +0 -0
  36. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/doris.rs +0 -0
  37. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/dremio.rs +0 -0
  38. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/drill.rs +0 -0
  39. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/druid.rs +0 -0
  40. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/duckdb.rs +0 -0
  41. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/dune.rs +0 -0
  42. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/exasol.rs +0 -0
  43. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/fabric.rs +0 -0
  44. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/generic.rs +0 -0
  45. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/hive.rs +0 -0
  46. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/materialize.rs +0 -0
  47. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/mysql.rs +0 -0
  48. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/oracle.rs +0 -0
  49. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/postgres.rs +0 -0
  50. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/presto.rs +0 -0
  51. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/redshift.rs +0 -0
  52. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/risingwave.rs +0 -0
  53. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/singlestore.rs +0 -0
  54. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/snowflake.rs +0 -0
  55. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/solr.rs +0 -0
  56. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/spark.rs +0 -0
  57. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/sqlite.rs +0 -0
  58. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/starrocks.rs +0 -0
  59. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/tableau.rs +0 -0
  60. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/teradata.rs +0 -0
  61. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/tidb.rs +0 -0
  62. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/trino.rs +0 -0
  63. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/dialects/tsql.rs +0 -0
  64. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/diff.rs +0 -0
  65. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/error.rs +0 -0
  66. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/function_catalog.rs +0 -0
  67. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/function_registry.rs +0 -0
  68. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/helper.rs +0 -0
  69. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/lib.rs +0 -0
  70. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/optimizer/annotate_types.rs +0 -0
  71. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/optimizer/canonicalize.rs +0 -0
  72. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/optimizer/eliminate_ctes.rs +0 -0
  73. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/optimizer/eliminate_joins.rs +0 -0
  74. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/optimizer/isolate_table_selects.rs +0 -0
  75. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/optimizer/mod.rs +0 -0
  76. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/optimizer/normalize.rs +0 -0
  77. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/optimizer/normalize_identifiers.rs +0 -0
  78. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/optimizer/optimize_joins.rs +0 -0
  79. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/optimizer/optimizer.rs +0 -0
  80. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/optimizer/pushdown_predicates.rs +0 -0
  81. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/optimizer/pushdown_projections.rs +0 -0
  82. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/optimizer/qualify_columns.rs +0 -0
  83. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/optimizer/qualify_tables.rs +0 -0
  84. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/optimizer/simplify.rs +0 -0
  85. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/optimizer/subquery.rs +0 -0
  86. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/planner.rs +0 -0
  87. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/resolver.rs +0 -0
  88. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/schema.rs +0 -0
  89. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/time.rs +0 -0
  90. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/transforms.rs +0 -0
  91. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/trie.rs +0 -0
  92. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/validation/tests.rs +0 -0
  93. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/src/validation.rs +0 -0
  94. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/analyze_failures.rs +0 -0
  95. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/clickhouse_regression.rs +0 -0
  96. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/common/known_failures.rs +0 -0
  97. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/common/mod.rs +0 -0
  98. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/common/test_data.rs +0 -0
  99. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/common/test_runner.rs +0 -0
  100. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/custom_clickhouse_coverage.rs +0 -0
  101. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/custom_clickhouse_parser.rs +0 -0
  102. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/custom_dialect.rs +0 -0
  103. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/custom_dialect_tests.rs +0 -0
  104. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/ddl.json +0 -0
  105. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/dml.json +0 -0
  106. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/functions.json +0 -0
  107. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/identity.json +0 -0
  108. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/operators.json +0 -0
  109. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/select.json +0 -0
  110. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/transpilation.json +0 -0
  111. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/custom_fixtures/datafusion/types.json +0 -0
  112. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/deep_nesting_regression.rs +0 -0
  113. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/dialect_matrix.rs +0 -0
  114. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/error_handling.rs +0 -0
  115. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/fabric_regression.rs +0 -0
  116. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/fabric_tpch_regression.rs +0 -0
  117. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/identity_roundtrip.rs +0 -0
  118. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/issue201_regression_test.rs +0 -0
  119. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/postgres_sqlite_regression.rs +0 -0
  120. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/snowflake_regression_test.rs +0 -0
  121. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/sqlglot_compat.rs +0 -0
  122. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/sqlglot_dialect_identity.rs +0 -0
  123. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/sqlglot_identity.rs +0 -0
  124. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/sqlglot_identity_detailed.rs +0 -0
  125. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/sqlglot_parser.rs +0 -0
  126. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/sqlglot_pretty.rs +0 -0
  127. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/sqlglot_transpilation.rs +0 -0
  128. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/sqlglot_transpile.rs +0 -0
  129. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/tpch_transpile_stack.rs +0 -0
  130. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/transform_regression.rs +0 -0
  131. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql/tests/tsql_regression.rs +0 -0
  132. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-function-catalogs/Cargo.toml +0 -0
  133. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-function-catalogs/README.md +0 -0
  134. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-function-catalogs/src/clickhouse.rs +0 -0
  135. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-function-catalogs/src/duckdb.rs +0 -0
  136. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-function-catalogs/src/lib.rs +0 -0
  137. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-function-catalogs/tools/clickhouse/extract_functions.py +0 -0
  138. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-function-catalogs/tools/duckdb/extract_functions.py +0 -0
  139. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/Cargo.toml +0 -0
  140. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/README.md +0 -0
  141. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/docs/api.md +0 -0
  142. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/docs/index.md +0 -0
  143. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/mkdocs.yml +0 -0
  144. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/annotate_types.rs +0 -0
  145. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/dialects.rs +0 -0
  146. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/diff.rs +0 -0
  147. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/errors.rs +0 -0
  148. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/expr.rs +0 -0
  149. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/format.rs +0 -0
  150. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/generate.rs +0 -0
  151. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/helpers.rs +0 -0
  152. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/lib.rs +0 -0
  153. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/lineage.rs +0 -0
  154. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/openlineage.rs +0 -0
  155. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/optimize.rs +0 -0
  156. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/parse.rs +0 -0
  157. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/tokenize.rs +0 -0
  158. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/transforms.rs +0 -0
  159. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/transpile.rs +0 -0
  160. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/types.rs +0 -0
  161. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/src/validate.rs +0 -0
  162. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/tests/conftest.py +0 -0
  163. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/tests/test_compat.py +0 -0
  164. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/tests/test_dialects.py +0 -0
  165. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/tests/test_diff.py +0 -0
  166. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/tests/test_expression.py +0 -0
  167. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/tests/test_format.py +0 -0
  168. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/tests/test_generate.py +0 -0
  169. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/tests/test_optimize.py +0 -0
  170. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/tests/test_transforms.py +0 -0
  171. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/tests/test_transpile.py +0 -0
  172. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/tests/test_validate.py +0 -0
  173. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/crates/polyglot-sql-python/uv.lock +0 -0
  174. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/pyproject.toml +0 -0
  175. {polyglot_sql-0.4.2 → polyglot_sql-0.4.3}/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.4.2"
608
+ version = "0.4.3"
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.4.2"
624
+ version = "0.4.3"
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.4.2"
634
+ version = "0.4.3"
635
635
 
636
636
  [[package]]
637
637
  name = "polyglot-sql-python"
638
- version = "0.4.2"
638
+ version = "0.4.3"
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.4.2"
649
+ version = "0.4.3"
650
650
  dependencies = [
651
651
  "console_error_panic_hook",
652
652
  "js-sys",
@@ -6,7 +6,7 @@ exclude = [
6
6
  ]
7
7
 
8
8
  [workspace.package]
9
- version = "0.4.2"
9
+ version = "0.4.3"
10
10
  edition = "2021"
11
11
  license = "MIT"
12
12
  authors = ["polyglot contributors"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: polyglot-sql
3
- Version: 0.4.2
3
+ Version: 0.4.3
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -106,7 +106,7 @@ thiserror = { workspace = true }
106
106
  unicode-segmentation = { workspace = true }
107
107
  stacker = { version = "0.1", optional = true }
108
108
  ts-rs = { version = "12.0", features = ["serde-compat"], optional = true }
109
- polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.4.2", optional = true, default-features = false }
109
+ polyglot-sql-function-catalogs = { path = "../polyglot-sql-function-catalogs", version = "0.4.3", optional = true, default-features = false }
110
110
 
111
111
  [dev-dependencies]
112
112
  pretty_assertions = "1.4"
@@ -2918,6 +2918,31 @@ where
2918
2918
  Expression::CreateTask(ct)
2919
2919
  }
2920
2920
 
2921
+ // Prepare: recurse into the prepared statement body
2922
+ Expression::Prepare(mut prepare) => {
2923
+ prepare.statement = transform_recursive(prepare.statement, transform_fn)?;
2924
+ Expression::Prepare(prepare)
2925
+ }
2926
+
2927
+ // Execute: recurse into procedure/prepared name and argument values
2928
+ Expression::Execute(mut execute) => {
2929
+ execute.this = transform_recursive(execute.this, transform_fn)?;
2930
+ execute.arguments = execute
2931
+ .arguments
2932
+ .into_iter()
2933
+ .map(|argument| transform_recursive(argument, transform_fn))
2934
+ .collect::<Result<Vec<_>>>()?;
2935
+ execute.parameters = execute
2936
+ .parameters
2937
+ .into_iter()
2938
+ .map(|mut parameter| {
2939
+ parameter.value = transform_recursive(parameter.value, transform_fn)?;
2940
+ Ok(parameter)
2941
+ })
2942
+ .collect::<Result<Vec<_>>>()?;
2943
+ Expression::Execute(execute)
2944
+ }
2945
+
2921
2946
  // CreateProcedure: recurse into body expressions
2922
2947
  Expression::CreateProcedure(mut cp) => {
2923
2948
  if let Some(body) = cp.body.take() {
@@ -587,6 +587,8 @@ pub enum Expression {
587
587
  // Transaction and other commands
588
588
  Command(Box<Command>),
589
589
  Kill(Box<Kill>),
590
+ /// PREPARE statement (PostgreSQL/generic prepared statement definition)
591
+ Prepare(Box<PrepareStatement>),
590
592
  /// EXEC/EXECUTE statement (TSQL stored procedure call)
591
593
  Execute(Box<ExecuteStatement>),
592
594
 
@@ -1197,6 +1199,7 @@ impl Expression {
1197
1199
  | Expression::Describe(_)
1198
1200
  | Expression::Show(_)
1199
1201
  | Expression::Kill(_)
1202
+ | Expression::Prepare(_)
1200
1203
  | Expression::Execute(_)
1201
1204
  | Expression::Declare(_)
1202
1205
  | Expression::Refresh(_)
@@ -2235,6 +2238,7 @@ impl Expression {
2235
2238
  Expression::Command(_) => "command",
2236
2239
  Expression::TryCatch(_) => "try_catch",
2237
2240
  Expression::Kill(_) => "kill",
2241
+ Expression::Prepare(_) => "prepare",
2238
2242
  Expression::Execute(_) => "execute",
2239
2243
  Expression::Raw(_) => "raw",
2240
2244
  Expression::CreateTask(_) => "create_task",
@@ -6008,6 +6012,20 @@ pub struct Command {
6008
6012
  pub this: String,
6009
6013
  }
6010
6014
 
6015
+ /// PREPARE statement (PostgreSQL/generic prepared statement definition)
6016
+ /// Syntax: PREPARE name [(type, ...)] AS statement
6017
+ #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
6018
+ #[cfg_attr(feature = "bindings", derive(TS))]
6019
+ pub struct PrepareStatement {
6020
+ /// The prepared statement name.
6021
+ pub name: Identifier,
6022
+ /// Optional PostgreSQL parameter type list.
6023
+ #[serde(default, skip_serializing_if = "Vec::is_empty")]
6024
+ pub parameter_types: Vec<DataType>,
6025
+ /// The statement to execute when the prepared statement is invoked.
6026
+ pub statement: Expression,
6027
+ }
6028
+
6011
6029
  /// T-SQL TRY/CATCH block.
6012
6030
  #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
6013
6031
  #[cfg_attr(feature = "bindings", derive(TS))]
@@ -6030,6 +6048,12 @@ pub struct ExecuteStatement {
6030
6048
  /// Named parameters: @param=value pairs
6031
6049
  #[serde(default)]
6032
6050
  pub parameters: Vec<ExecuteParameter>,
6051
+ /// Positional prepared statement arguments, used by PostgreSQL EXECUTE name(...).
6052
+ #[serde(default, skip_serializing_if = "Vec::is_empty")]
6053
+ pub arguments: Vec<Expression>,
6054
+ /// Whether this statement represents PostgreSQL-style prepared statement execution.
6055
+ #[serde(default, skip_serializing_if = "std::ops::Not::not")]
6056
+ pub prepared: bool,
6033
6057
  /// Trailing clause text (e.g. WITH RESULT SETS ((...)))
6034
6058
  #[serde(default, skip_serializing_if = "Option::is_none")]
6035
6059
  pub suffix: Option<String>,
@@ -3357,10 +3357,24 @@ impl Generator {
3357
3357
  self.generate_expression(&kill.this)?;
3358
3358
  Ok(())
3359
3359
  }
3360
+ Expression::Prepare(prepare) => self.generate_prepare(prepare),
3360
3361
  Expression::Execute(exec) => {
3361
3362
  self.write_keyword("EXECUTE");
3362
3363
  self.write_space();
3363
3364
  self.generate_expression(&exec.this)?;
3365
+ if exec.prepared {
3366
+ if !exec.arguments.is_empty() {
3367
+ self.write("(");
3368
+ for (i, argument) in exec.arguments.iter().enumerate() {
3369
+ if i > 0 {
3370
+ self.write(", ");
3371
+ }
3372
+ self.generate_expression(argument)?;
3373
+ }
3374
+ self.write(")");
3375
+ }
3376
+ return Ok(());
3377
+ }
3364
3378
  for (i, param) in exec.parameters.iter().enumerate() {
3365
3379
  if i == 0 {
3366
3380
  self.write_space();
@@ -15616,6 +15630,28 @@ impl Generator {
15616
15630
  Ok(())
15617
15631
  }
15618
15632
 
15633
+ fn generate_prepare(&mut self, prepare: &PrepareStatement) -> Result<()> {
15634
+ self.write_keyword("PREPARE");
15635
+ self.write_space();
15636
+ self.generate_identifier(&prepare.name)?;
15637
+
15638
+ if !prepare.parameter_types.is_empty() {
15639
+ self.write(" (");
15640
+ for (i, data_type) in prepare.parameter_types.iter().enumerate() {
15641
+ if i > 0 {
15642
+ self.write(", ");
15643
+ }
15644
+ self.generate_data_type(data_type)?;
15645
+ }
15646
+ self.write(")");
15647
+ }
15648
+
15649
+ self.write_space();
15650
+ self.write_keyword("AS");
15651
+ self.write_space();
15652
+ self.generate_expression(&prepare.statement)
15653
+ }
15654
+
15619
15655
  /// Generate a pseudocolumn (Oracle ROWNUM, ROWID, LEVEL, etc.)
15620
15656
  /// Pseudocolumns should NEVER be quoted, as quoting breaks them in Oracle
15621
15657
  fn generate_pseudocolumn(&mut self, pc: &Pseudocolumn) -> Result<()> {
@@ -120,7 +120,8 @@ pub fn lineage(
120
120
  trim_selects: bool,
121
121
  ) -> Result<LineageNode> {
122
122
  // Fast path: skip clone when there are no CTEs to expand
123
- let has_with = matches!(sql, Expression::Select(s) if s.with.is_some());
123
+ let effective_sql = lineage_effective_expression(sql);
124
+ let has_with = matches!(effective_sql, Expression::Select(s) if s.with.is_some());
124
125
  if !has_with {
125
126
  return lineage_from_expression(column, sql, dialect, trim_selects);
126
127
  }
@@ -181,6 +182,7 @@ fn lineage_from_expression(
181
182
  dialect: Option<DialectType>,
182
183
  trim_selects: bool,
183
184
  ) -> Result<LineageNode> {
185
+ let sql = lineage_effective_expression(sql);
184
186
  let scope = build_scope(sql);
185
187
  to_node(
186
188
  ColumnRef::Name(column),
@@ -193,6 +195,13 @@ fn lineage_from_expression(
193
195
  )
194
196
  }
195
197
 
198
+ fn lineage_effective_expression(sql: &Expression) -> &Expression {
199
+ match sql {
200
+ Expression::Prepare(prepare) => &prepare.statement,
201
+ _ => sql,
202
+ }
203
+ }
204
+
196
205
  // ---------------------------------------------------------------------------
197
206
  // CTE star expansion
198
207
  // ---------------------------------------------------------------------------
@@ -222,6 +231,11 @@ fn normalize_cte_name(ident: &Identifier) -> String {
222
231
  /// case-insensitively (lowercased), while quoted names preserve their original case.
223
232
  /// This matches sqlglot's `normalize_identifiers` behavior.
224
233
  pub fn expand_cte_stars(expr: &mut Expression, schema: Option<&dyn Schema>) {
234
+ if let Expression::Prepare(prepare) = expr {
235
+ expand_cte_stars(&mut prepare.statement, schema);
236
+ return;
237
+ }
238
+
225
239
  let select = match expr {
226
240
  Expression::Select(s) => s,
227
241
  _ => return,
@@ -480,6 +494,14 @@ fn get_select_sources(select: &Select) -> Vec<SourceInfo> {
480
494
  let mut sources = Vec::new();
481
495
 
482
496
  fn extract_source(expr: &Expression) -> Option<SourceInfo> {
497
+ fn virtual_source_info(alias: &Identifier) -> SourceInfo {
498
+ SourceInfo {
499
+ alias: alias.name.clone(),
500
+ normalized: normalize_cte_name(alias),
501
+ fq_name: alias.name.clone(),
502
+ }
503
+ }
504
+
483
505
  match expr {
484
506
  Expression::Table(t) => {
485
507
  let normalized = normalize_cte_name(&t.name);
@@ -513,6 +535,10 @@ fn get_select_sources(select: &Select) -> Vec<SourceInfo> {
513
535
  fq_name,
514
536
  })
515
537
  }
538
+ Expression::Unnest(u) => u.alias.as_ref().map(virtual_source_info),
539
+ Expression::Alias(a) if matches!(&a.this, Expression::Unnest(_)) => {
540
+ Some(virtual_source_info(&a.alias))
541
+ }
516
542
  Expression::Paren(p) => extract_source(&p.this),
517
543
  _ => None,
518
544
  }
@@ -971,6 +997,10 @@ fn source_names_from_from_join(scope: &Scope) -> Vec<String> {
971
997
  Expression::Subquery(subquery) => {
972
998
  subquery.alias.as_ref().map(|alias| alias.name.clone())
973
999
  }
1000
+ Expression::Unnest(unnest) => unnest.alias.as_ref().map(|alias| alias.name.clone()),
1001
+ Expression::Alias(alias) if matches!(&alias.this, Expression::Unnest(_)) => {
1002
+ Some(alias.alias.name.clone())
1003
+ }
974
1004
  Expression::Paren(paren) => source_name(&paren.this),
975
1005
  _ => None,
976
1006
  }
@@ -2486,6 +2516,45 @@ mod tests {
2486
2516
  assert_eq!(node.name, "name");
2487
2517
  }
2488
2518
 
2519
+ #[test]
2520
+ fn test_lineage_bigquery_unnest_alias_source_issue_209() {
2521
+ let expr = parse_one(
2522
+ r#"
2523
+ SELECT date_val AS week_start
2524
+ FROM UNNEST(GENERATE_DATE_ARRAY('2024-01-01', '2024-12-31', INTERVAL 1 WEEK)) AS date_val
2525
+ "#,
2526
+ DialectType::BigQuery,
2527
+ )
2528
+ .expect("parse");
2529
+
2530
+ let node = lineage("week_start", &expr, Some(DialectType::BigQuery), false)
2531
+ .expect("lineage should resolve UNNEST alias as a source");
2532
+ let child = node
2533
+ .downstream
2534
+ .first()
2535
+ .expect("week_start should have downstream lineage");
2536
+
2537
+ assert_eq!(child.name, "date_val.date_val");
2538
+ assert_eq!(child.source_name, "date_val");
2539
+
2540
+ let Expression::Column(column) = &child.expression else {
2541
+ panic!(
2542
+ "expected downstream column expression, got {:?}",
2543
+ child.expression
2544
+ );
2545
+ };
2546
+ assert_eq!(column.name.name, "date_val");
2547
+ assert_eq!(
2548
+ column.table.as_ref().map(|table| table.name.as_str()),
2549
+ Some("date_val")
2550
+ );
2551
+ assert!(
2552
+ matches!(&child.source, Expression::Alias(alias) if matches!(&alias.this, Expression::Unnest(_)) && alias.alias.name == "date_val"),
2553
+ "expected UNNEST source expression, got {:?}",
2554
+ child.source
2555
+ );
2556
+ }
2557
+
2489
2558
  #[test]
2490
2559
  fn test_lineage_with_schema_snowflake_datediff_date_part_issue_61() {
2491
2560
  let expr = parse_one(
@@ -363,6 +363,7 @@ fn analyze_statement(
363
363
  warnings: &mut Vec<OpenLineageWarning>,
364
364
  ) -> Result<StatementAnalysis> {
365
365
  match expr {
366
+ Expression::Prepare(prepare) => analyze_statement(&prepare.statement, options, warnings),
366
367
  Expression::Select(select) => {
367
368
  let output = if let Some(into) = &select.into {
368
369
  dataset_from_expression(&into.this, options)?
@@ -914,6 +915,7 @@ fn collect_source_table(expr: &Expression, result: &mut Vec<(String, String)>) {
914
915
 
915
916
  fn leftmost_select(expr: &Expression) -> Option<&Select> {
916
917
  match expr {
918
+ Expression::Prepare(prepare) => leftmost_select(&prepare.statement),
917
919
  Expression::Select(select) => Some(select),
918
920
  Expression::Union(union) => leftmost_select(&union.left),
919
921
  Expression::Intersect(intersect) => leftmost_select(&intersect.left),
@@ -1103,6 +1105,19 @@ mod tests {
1103
1105
  assert_eq!(field.input_fields[0].transformations[0].subtype, "IDENTITY");
1104
1106
  }
1105
1107
 
1108
+ #[test]
1109
+ fn emits_column_lineage_for_prepared_statement_body() {
1110
+ let result = openlineage_column_lineage(
1111
+ "PREPARE leak AS SELECT id FROM sensitive_table WHERE id = $1",
1112
+ &options(),
1113
+ )
1114
+ .expect("lineage");
1115
+ let field = result.facet.fields.get("id").expect("field id");
1116
+ assert_eq!(field.input_fields.len(), 1);
1117
+ assert_eq!(field.input_fields[0].name, "sensitive_table");
1118
+ assert_eq!(field.input_fields[0].field, "id");
1119
+ }
1120
+
1106
1121
  #[test]
1107
1122
  fn resolves_input_dataset_behind_table_alias() {
1108
1123
  let result = openlineage_column_lineage("SELECT o.total FROM orders o", &options())
@@ -1165,6 +1180,39 @@ SELECT json_data FROM transform_cte
1165
1180
  );
1166
1181
  }
1167
1182
 
1183
+ #[test]
1184
+ fn emits_bigquery_unnest_alias_column_lineage_issue209() {
1185
+ let mut opts = options();
1186
+ opts.dialect = DialectType::BigQuery;
1187
+ opts.dataset_namespace = Some("bigquery://warehouse".to_string());
1188
+ opts.output_dataset = Some(OpenLineageDatasetId::new(
1189
+ "bigquery://warehouse",
1190
+ "calendar",
1191
+ ));
1192
+
1193
+ let result = openlineage_column_lineage(
1194
+ r#"
1195
+ SELECT date_val AS week_start
1196
+ FROM UNNEST(GENERATE_DATE_ARRAY('2024-01-01', '2024-12-31', INTERVAL 1 WEEK)) AS date_val
1197
+ "#,
1198
+ &opts,
1199
+ )
1200
+ .expect("lineage");
1201
+ let field = result.facet.fields.get("week_start").expect("week_start");
1202
+
1203
+ assert_eq!(field.input_fields.len(), 1);
1204
+ assert_eq!(field.input_fields[0].name, "date_val");
1205
+ assert_eq!(field.input_fields[0].field, "date_val");
1206
+ assert!(
1207
+ result
1208
+ .warnings
1209
+ .iter()
1210
+ .all(|warning| warning.code != "W_EMPTY_FIELD_LINEAGE"),
1211
+ "did not expect empty-lineage warning, got {:?}",
1212
+ result.warnings
1213
+ );
1214
+ }
1215
+
1168
1216
  #[test]
1169
1217
  fn emits_aggregation_column_lineage() {
1170
1218
  let result =
@@ -1136,6 +1136,7 @@ impl Parser {
1136
1136
  self.fallback_to_command(statement_start)
1137
1137
  }
1138
1138
  TokenType::Kill => self.parse_kill(),
1139
+ TokenType::Prepare => self.parse_prepare(),
1139
1140
  TokenType::Execute => {
1140
1141
  // ClickHouse: EXECUTE AS username statement → parse as command
1141
1142
  if matches!(
@@ -23658,6 +23659,48 @@ impl Parser {
23658
23659
  Ok(Expression::Kill(Box::new(Kill { this, kind })))
23659
23660
  }
23660
23661
 
23662
+ /// Parse PREPARE statement (PostgreSQL/generic prepared statement definition)
23663
+ /// PREPARE name [(type, ...)] AS statement
23664
+ fn parse_prepare(&mut self) -> Result<Expression> {
23665
+ self.expect(TokenType::Prepare)?;
23666
+
23667
+ let name = self.expect_identifier_or_keyword_with_quoted()?;
23668
+
23669
+ let mut parameter_types = Vec::new();
23670
+ if self.match_token(TokenType::LParen) {
23671
+ if !self.check(TokenType::RParen) {
23672
+ loop {
23673
+ parameter_types.push(self.parse_data_type()?);
23674
+ if !self.match_token(TokenType::Comma) {
23675
+ break;
23676
+ }
23677
+ }
23678
+ }
23679
+ self.expect(TokenType::RParen)?;
23680
+ }
23681
+
23682
+ self.expect(TokenType::As)?;
23683
+ let statement = self.parse_statement()?;
23684
+
23685
+ Ok(Expression::Prepare(Box::new(PrepareStatement {
23686
+ name,
23687
+ parameter_types,
23688
+ statement,
23689
+ })))
23690
+ }
23691
+
23692
+ fn is_postgres_prepared_execute_dialect(&self) -> bool {
23693
+ matches!(
23694
+ self.config.dialect,
23695
+ None | Some(crate::dialects::DialectType::Generic)
23696
+ | Some(crate::dialects::DialectType::PostgreSQL)
23697
+ | Some(crate::dialects::DialectType::Redshift)
23698
+ | Some(crate::dialects::DialectType::Materialize)
23699
+ | Some(crate::dialects::DialectType::RisingWave)
23700
+ | Some(crate::dialects::DialectType::CockroachDB)
23701
+ )
23702
+ }
23703
+
23661
23704
  /// Parse EXEC/EXECUTE statement (TSQL stored procedure call)
23662
23705
  /// EXEC [schema.]procedure_name [@param=value, ...]
23663
23706
  fn parse_execute(&mut self) -> Result<Expression> {
@@ -23680,6 +23723,28 @@ impl Parser {
23680
23723
  Expression::Table(Box::new(proc_name))
23681
23724
  };
23682
23725
 
23726
+ if self.is_postgres_prepared_execute_dialect() && self.check(TokenType::LParen) {
23727
+ let arguments = self.parse_wrapped_csv_expressions()?;
23728
+ return Ok(Expression::Execute(Box::new(ExecuteStatement {
23729
+ this,
23730
+ parameters: Vec::new(),
23731
+ arguments,
23732
+ prepared: true,
23733
+ suffix: None,
23734
+ })));
23735
+ }
23736
+ if self.is_postgres_prepared_execute_dialect()
23737
+ && (self.check(TokenType::Semicolon) || self.is_at_end())
23738
+ {
23739
+ return Ok(Expression::Execute(Box::new(ExecuteStatement {
23740
+ this,
23741
+ parameters: Vec::new(),
23742
+ arguments: Vec::new(),
23743
+ prepared: true,
23744
+ suffix: None,
23745
+ })));
23746
+ }
23747
+
23683
23748
  // Parse optional parameters: @param=value [OUTPUT], ...
23684
23749
  let mut parameters = Vec::new();
23685
23750
 
@@ -23743,6 +23808,8 @@ impl Parser {
23743
23808
  Ok(Expression::Execute(Box::new(ExecuteStatement {
23744
23809
  this,
23745
23810
  parameters,
23811
+ arguments: Vec::new(),
23812
+ prepared: false,
23746
23813
  suffix,
23747
23814
  })))
23748
23815
  }
@@ -533,6 +533,9 @@ fn collect_columns(expr: &Expression, columns: &mut Vec<ColumnRef>) {
533
533
  Expression::Exists(_) | Expression::Subquery(_) => {
534
534
  // These create their own scopes - don't collect from here
535
535
  }
536
+ Expression::Prepare(prepare) => {
537
+ collect_columns(&prepare.statement, columns);
538
+ }
536
539
  _ => {
537
540
  // For other expressions, we might need to add more cases
538
541
  }
@@ -551,6 +554,9 @@ pub fn build_scope(expression: &Expression) -> Scope {
551
554
 
552
555
  fn build_scope_impl(expression: &Expression, current_scope: &mut Scope) {
553
556
  match expression {
557
+ Expression::Prepare(prepare) => {
558
+ build_scope_impl(&prepare.statement, current_scope);
559
+ }
554
560
  Expression::Select(select) => {
555
561
  // Process CTEs first
556
562
  if let Some(with) = &select.with {
@@ -674,6 +680,14 @@ fn add_table_to_scope(expr: &Expression, scope: &mut Scope) {
674
680
  scope.add_source(name.clone(), expr.clone(), true);
675
681
  scope.derived_table_scopes.push(derived_scope);
676
682
  }
683
+ Expression::Unnest(unnest) => {
684
+ if let Some(alias) = &unnest.alias {
685
+ scope.add_source(alias.name.clone(), expr.clone(), false);
686
+ }
687
+ }
688
+ Expression::Alias(alias) if matches!(&alias.this, Expression::Unnest(_)) => {
689
+ scope.add_source(alias.alias.name.clone(), expr.clone(), false);
690
+ }
677
691
  Expression::Paren(paren) => {
678
692
  add_table_to_scope(&paren.this, scope);
679
693
  }
@@ -848,6 +862,9 @@ impl<'a> WalkInScopeIter<'a> {
848
862
  let mut children = Vec::new();
849
863
 
850
864
  match expr {
865
+ Expression::Prepare(prepare) => {
866
+ children.push(&prepare.statement);
867
+ }
851
868
  Expression::Select(select) => {
852
869
  // Walk SELECT expressions
853
870
  for e in &select.expressions {
@@ -1117,6 +1134,7 @@ pub fn traverse_scope(expression: &Expression) -> Vec<Scope> {
1117
1134
  | Expression::Union(_)
1118
1135
  | Expression::Intersect(_)
1119
1136
  | Expression::Except(_)
1137
+ | Expression::Prepare(_)
1120
1138
  | Expression::CreateTable(_) => {
1121
1139
  let root = build_scope(expression);
1122
1140
  root.traverse().into_iter().cloned().collect()
@@ -377,6 +377,7 @@ pub enum TokenType {
377
377
  Command,
378
378
  Comment,
379
379
  Commit,
380
+ Prepare,
380
381
  Preserve,
381
382
  Connect,
382
383
  ConnectBy,
@@ -898,6 +899,7 @@ impl TokenType {
898
899
  | TokenType::Qualify
899
900
  | TokenType::Returning
900
901
  | TokenType::Language
902
+ | TokenType::Prepare
901
903
  | TokenType::Preserve
902
904
  | TokenType::Savepoint
903
905
  | TokenType::Rollback
@@ -1171,6 +1173,7 @@ static DEFAULT_KEYWORDS: LazyLock<HashMap<String, TokenType>> = LazyLock::new(||
1171
1173
  keywords.insert("COMMIT".to_string(), TokenType::Commit);
1172
1174
  keywords.insert("BEGIN".to_string(), TokenType::Begin);
1173
1175
  keywords.insert("DESCRIBE".to_string(), TokenType::Describe);
1176
+ keywords.insert("PREPARE".to_string(), TokenType::Prepare);
1174
1177
  keywords.insert("PRESERVE".to_string(), TokenType::Preserve);
1175
1178
  keywords.insert("TRANSACTION".to_string(), TokenType::Transaction);
1176
1179
  keywords.insert("SAVEPOINT".to_string(), TokenType::Savepoint);
@@ -701,6 +701,18 @@ fn iter_children(expr: &Expression) -> Vec<(&'static str, &Expression)> {
701
701
  Expression::CreateTask(ct) => {
702
702
  children.push(("body", &ct.body));
703
703
  }
704
+ Expression::Prepare(prepare) => {
705
+ children.push(("statement", &prepare.statement));
706
+ }
707
+ Expression::Execute(exec) => {
708
+ children.push(("this", &exec.this));
709
+ for argument in &exec.arguments {
710
+ children.push(("argument", argument));
711
+ }
712
+ for parameter in &exec.parameters {
713
+ children.push(("parameter", &parameter.value));
714
+ }
715
+ }
704
716
  Expression::Analyze(a) => {
705
717
  if let Some(this) = &a.this {
706
718
  children.push(("this", this));