data-flow-control 0.2.2__tar.gz → 0.2.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 (193) hide show
  1. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/Cargo.lock +3 -3
  2. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/Cargo.toml +1 -1
  3. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/PKG-INFO +1 -1
  4. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/aggregate_registry.rs +10 -0
  5. data_flow_control-0.2.3/passant-core/src/rewriter/joint_lineage/grouped_projection.rs +245 -0
  6. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/joint_lineage.rs +13 -0
  7. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/pyproject.toml +1 -1
  8. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/LICENSE +0 -0
  9. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/Cargo.toml +0 -0
  10. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/benches/rewrite_perf.rs +0 -0
  11. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/catalog/dimension.rs +0 -0
  12. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/catalog.rs +0 -0
  13. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/diagnostics.rs +0 -0
  14. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/explain.rs +0 -0
  15. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/full_push.rs +0 -0
  16. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/identifiers.rs +0 -0
  17. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/intern.rs +0 -0
  18. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/ir.rs +0 -0
  19. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/lib.rs +0 -0
  20. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/optimizer.rs +0 -0
  21. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/parser.rs +0 -0
  22. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/partial_push.rs +0 -0
  23. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/planner.rs +0 -0
  24. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/policy.rs +0 -0
  25. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/policy_compile.rs +0 -0
  26. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/policy_index.rs +0 -0
  27. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/policy_parser.rs +0 -0
  28. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/policy_pgn.pest +0 -0
  29. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/policy_store/branch.rs +0 -0
  30. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/policy_store/compiled.rs +0 -0
  31. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/policy_store/delete.rs +0 -0
  32. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/policy_store/indexes.rs +0 -0
  33. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/policy_store/memory.rs +0 -0
  34. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/policy_store/mod.rs +0 -0
  35. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/query_analysis.rs +0 -0
  36. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/resolution_placement.rs +0 -0
  37. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/resolution_registry.rs +0 -0
  38. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewrite_stats.rs +0 -0
  39. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewrite_strategy.rs +0 -0
  40. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/aggregates.rs +0 -0
  41. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/columns.rs +0 -0
  42. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/constraint_preprocess.rs +0 -0
  43. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/derived_policy.rs +0 -0
  44. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/dimensions.rs +0 -0
  45. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/exists.rs +0 -0
  46. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/expr.rs +0 -0
  47. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/helpers.rs +0 -0
  48. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/insert_output_policy.rs +0 -0
  49. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/joint_lineage/terminal_distinct.rs +0 -0
  50. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/joint_lineage/terminal_except.rs +0 -0
  51. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/joint_lineage/terminal_intersect.rs +0 -0
  52. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/limit.rs +0 -0
  53. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/mod.rs +0 -0
  54. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/output_scope.rs +0 -0
  55. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/plan/actions.rs +0 -0
  56. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/plan/applicability.rs +0 -0
  57. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/plan/dominance.rs +0 -0
  58. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/plan/mod.rs +0 -0
  59. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/plan/scope_plan.rs +0 -0
  60. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/plan/write_plan.rs +0 -0
  61. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/policy_expr.rs +0 -0
  62. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/projection.rs +0 -0
  63. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/resolution.rs +0 -0
  64. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/scope.rs +0 -0
  65. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/select.rs +0 -0
  66. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/sink_columns.rs +0 -0
  67. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/types.rs +0 -0
  68. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/rewriter/write_path.rs +0 -0
  69. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/semiring.rs +0 -0
  70. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/source_set_index.rs +0 -0
  71. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/source_sets/analysis.rs +0 -0
  72. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/source_sets/annotations.rs +0 -0
  73. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/source_sets/branch.rs +0 -0
  74. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/source_sets/mod.rs +0 -0
  75. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/source_sets/rewrites.rs +0 -0
  76. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/source_sets/split.rs +0 -0
  77. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/sql/ast_stats.rs +0 -0
  78. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/sql/builders.rs +0 -0
  79. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/sql/columns.rs +0 -0
  80. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/sql/dialect.rs +0 -0
  81. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/sql/expr.rs +0 -0
  82. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/sql/expr_key.rs +0 -0
  83. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/sql/mod.rs +0 -0
  84. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/sql/parse.rs +0 -0
  85. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/sql/render.rs +0 -0
  86. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/statement_tables.rs +0 -0
  87. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/src/threshold.rs +0 -0
  88. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/common/duckdb.rs +0 -0
  89. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/common/mod.rs +0 -0
  90. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/completion/conformance.rs +0 -0
  91. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/completion/main.rs +0 -0
  92. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/completion/partial_push.rs +0 -0
  93. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/completion/pgn.rs +0 -0
  94. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/completion/pgn_unique.rs +0 -0
  95. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/completion/policy_storage.rs +0 -0
  96. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/completion/rewrite_api_parity.rs +0 -0
  97. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/completion/semiring.rs +0 -0
  98. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/completion/source_sets.rs +0 -0
  99. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/completion/symmetric_self_join.rs +0 -0
  100. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/completion/threshold.rs +0 -0
  101. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/completion/unique_not_unique.rs +0 -0
  102. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/dialect.rs +0 -0
  103. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/execution/insert.rs +0 -0
  104. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/execution/kill.rs +0 -0
  105. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/execution/main.rs +0 -0
  106. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/execution/oracle.rs +0 -0
  107. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/execution/remove.rs +0 -0
  108. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/execution/update.rs +0 -0
  109. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/expected/duckdb/remove_scan.sql +0 -0
  110. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/expected/postgres/remove_scan.sql +0 -0
  111. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/expected/sqlite/remove_scan.sql +0 -0
  112. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/explain_strategy.rs +0 -0
  113. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/gaps/column_propagation.rs +0 -0
  114. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/gaps/dimensions.rs +0 -0
  115. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/gaps/exists_join.rs +0 -0
  116. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/gaps/having_where.rs +0 -0
  117. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/gaps/identifiers.rs +0 -0
  118. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/gaps/insert_shapes.rs +0 -0
  119. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/gaps/main.rs +0 -0
  120. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/gaps/multi_source.rs +0 -0
  121. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/gaps/operators.rs +0 -0
  122. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/gaps/query_shapes.rs +0 -0
  123. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/gaps/scalar_subquery.rs +0 -0
  124. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/indexed_candidate_differential.rs +0 -0
  125. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/insert_values_body.rs +0 -0
  126. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/kill_null_guard_regression.rs +0 -0
  127. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/paper_examples.rs +0 -0
  128. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/parser.rs +0 -0
  129. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/planner.rs +0 -0
  130. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/policy.rs +0 -0
  131. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/policy_dialect.rs +0 -0
  132. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/policy_store_memory.rs +0 -0
  133. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/rewrite/derived_policy.rs +0 -0
  134. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/rewrite/in_semijoin.rs +0 -0
  135. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/rewrite/insert.rs +0 -0
  136. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/rewrite/joins.rs +0 -0
  137. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/rewrite/main.rs +0 -0
  138. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/rewrite/meal_deduction.rs +0 -0
  139. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/rewrite/output.rs +0 -0
  140. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/rewrite/recursive.rs +0 -0
  141. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/rewrite/scan.rs +0 -0
  142. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/rewrite/update.rs +0 -0
  143. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/rewrite_candidate_regression.rs +0 -0
  144. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/rewrite_fast_paths.rs +0 -0
  145. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/rewrite_large_registry.rs +0 -0
  146. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/rewrite_stats_timings.rs +0 -0
  147. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/scan_ready_expr.rs +0 -0
  148. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/source_set_split_no_parse.rs +0 -0
  149. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/sql_builders.rs +0 -0
  150. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/sql_columns.rs +0 -0
  151. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-core/tests/ui_resolution.rs +0 -0
  152. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-py/Cargo.toml +0 -0
  153. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-py/src/bindings/catalog.rs +0 -0
  154. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-py/src/bindings/errors.rs +0 -0
  155. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-py/src/bindings/mod.rs +0 -0
  156. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-py/src/bindings/planner.rs +0 -0
  157. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-py/src/bindings/policy.rs +0 -0
  158. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-py/src/bindings/stats.rs +0 -0
  159. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/passant-py/src/lib.rs +0 -0
  160. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/__init__.py +0 -0
  161. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/_rust.py +0 -0
  162. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/adapters/__init__.py +0 -0
  163. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/adapters/_retry.py +0 -0
  164. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/adapters/base.py +0 -0
  165. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/adapters/clickhouse.py +0 -0
  166. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/adapters/datafusion.py +0 -0
  167. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/adapters/duckdb.py +0 -0
  168. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/adapters/kill.py +0 -0
  169. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/adapters/pg_catalog.py +0 -0
  170. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/adapters/postgres.py +0 -0
  171. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/adapters/registry.py +0 -0
  172. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/adapters/sqlite.py +0 -0
  173. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/adapters/umbra.py +0 -0
  174. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/aggregate_introspection.py +0 -0
  175. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/catalog.py +0 -0
  176. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/connection.py +0 -0
  177. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/dialect.py +0 -0
  178. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/errors.py +0 -0
  179. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/langchain/__init__.py +0 -0
  180. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/langchain/agent.py +0 -0
  181. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/langchain/call_tool_with_dataflow.py +0 -0
  182. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/langchain/database.py +0 -0
  183. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/langchain/middleware.py +0 -0
  184. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/langchain/schema.py +0 -0
  185. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/langchain/sql_validation.py +0 -0
  186. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/langchain/tool_spec.py +0 -0
  187. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/langchain/wrapper.py +0 -0
  188. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/options.py +0 -0
  189. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/planner.py +0 -0
  190. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/policy.py +0 -0
  191. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/tools/__init__.py +0 -0
  192. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/tools/retry.py +0 -0
  193. {data_flow_control-0.2.2 → data_flow_control-0.2.3}/python/data_flow_control/ui.py +0 -0
@@ -1593,7 +1593,7 @@ dependencies = [
1593
1593
 
1594
1594
  [[package]]
1595
1595
  name = "passant-cli"
1596
- version = "0.2.2"
1596
+ version = "0.2.3"
1597
1597
  dependencies = [
1598
1598
  "anyhow",
1599
1599
  "assert_cmd",
@@ -1605,7 +1605,7 @@ dependencies = [
1605
1605
 
1606
1606
  [[package]]
1607
1607
  name = "passant-core"
1608
- version = "0.2.2"
1608
+ version = "0.2.3"
1609
1609
  dependencies = [
1610
1610
  "anyhow",
1611
1611
  "criterion",
@@ -1623,7 +1623,7 @@ dependencies = [
1623
1623
 
1624
1624
  [[package]]
1625
1625
  name = "passant-py"
1626
- version = "0.2.2"
1626
+ version = "0.2.3"
1627
1627
  dependencies = [
1628
1628
  "passant-core",
1629
1629
  "pyo3",
@@ -3,7 +3,7 @@ members = ["passant-core", "passant-py"]
3
3
  resolver = "2"
4
4
 
5
5
  [workspace.package]
6
- version = "0.2.2"
6
+ version = "0.2.3"
7
7
  edition = "2024"
8
8
  license = "MIT"
9
9
  authors = ["Charlie Summers"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: data-flow-control
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Requires-Dist: duckdb>=1.3.0
5
5
  Requires-Dist: numpy>=1.24.4
6
6
  Requires-Dist: sqlglot==28.3.0
@@ -184,6 +184,7 @@ impl AggregateRegistry {
184
184
  self.expr_contains_aggregate(left) || self.expr_contains_aggregate(right)
185
185
  }
186
186
  Expr::Nested(expr)
187
+ | Expr::Cast { expr, .. }
187
188
  | Expr::UnaryOp { expr, .. }
188
189
  | Expr::IsFalse(expr)
189
190
  | Expr::IsNotFalse(expr)
@@ -624,6 +625,15 @@ mod tests {
624
625
  assert!(registry.expr_contains_aggregate(&expr));
625
626
  }
626
627
 
628
+ #[test]
629
+ fn expr_contains_aggregate_inside_cast() {
630
+ let registry = AggregateRegistry::for_dialect(SqlDialect::DuckDb);
631
+ let expr = crate::sql::parse_projection_expr("CAST(list(c.id) AS VARCHAR)").unwrap();
632
+ assert!(registry.expr_contains_aggregate(&expr));
633
+ let scalar = crate::sql::parse_projection_expr("CAST(c.id AS VARCHAR)").unwrap();
634
+ assert!(!registry.expr_contains_aggregate(&scalar));
635
+ }
636
+
627
637
  #[test]
628
638
  fn lookup_schema_qualified_introspected_aggregate() {
629
639
  let registry = AggregateRegistry::for_dialect(SqlDialect::Postgres).merge_introspected(&[
@@ -0,0 +1,245 @@
1
+ //! Flatten pure projection wrappers over one grouped input before policy placement.
2
+ //! This keeps source aggregates at their contributor boundary and exposes the final
3
+ //! sink expressions to the ordinary grouped INSERT planner. Unsupported wrappers
4
+ //! retain the existing fail-closed lineage path.
5
+ use super::*;
6
+ use crate::aggregate_registry::AggregateRegistry;
7
+
8
+ pub(super) fn flatten(query: &mut Query, registry: &AggregateRegistry) -> bool {
9
+ let Some(select) = grouped_projection(query, registry) else {
10
+ return false;
11
+ };
12
+ if let SetExpr::Select(original) = query.body.as_ref()
13
+ && select.as_ref() == original.as_ref()
14
+ {
15
+ return false;
16
+ }
17
+ *query.body = SetExpr::Select(select);
18
+ true
19
+ }
20
+
21
+ fn grouped_projection(query: &Query, registry: &AggregateRegistry) -> Option<Box<Select>> {
22
+ // Moving ORDER/LIMIT or CTE boundaries can change the contributing rows.
23
+ let mut shape = query.clone();
24
+ *shape.body = SetExpr::Select(Box::new(crate::sql::empty_select()));
25
+ if shape != crate::sql::query_from_select(crate::sql::empty_select()) {
26
+ return None;
27
+ }
28
+ let SetExpr::Select(select) = query.body.as_ref() else {
29
+ return None;
30
+ };
31
+ if select_is_aggregation(select, registry) {
32
+ // Keep only a global aggregate's FROM/WHERE. Output aliases in a
33
+ // retained clause can change binding when its projection is replaced.
34
+ let mut shape = select.as_ref().clone();
35
+ shape.select_token = crate::sql::empty_select().select_token;
36
+ shape.projection.clear();
37
+ shape.from.clear();
38
+ shape.selection = None;
39
+ if shape != crate::sql::empty_select() || !safe_projection(&select.projection) {
40
+ return None;
41
+ }
42
+ let aliases: HashSet<_> = select
43
+ .projection
44
+ .iter()
45
+ .filter_map(|item| {
46
+ if let SelectItem::ExprWithAlias { alias, .. } = item {
47
+ Some(alias.value.to_ascii_lowercase())
48
+ } else {
49
+ None
50
+ }
51
+ })
52
+ .collect();
53
+ let mut retained = select.as_ref().clone();
54
+ retained.projection.clear();
55
+ let alias_reference = visit_expressions(&retained, |expr| {
56
+ if let Expr::Identifier(id) = expr
57
+ && aliases.contains(&id.value.to_ascii_lowercase())
58
+ {
59
+ return ControlFlow::Break(());
60
+ }
61
+ ControlFlow::Continue(())
62
+ });
63
+ return alias_reference.is_continue().then(|| select.clone());
64
+ }
65
+ let mut shape = select.as_ref().clone();
66
+ shape.select_token = crate::sql::empty_select().select_token;
67
+ shape.projection.clear();
68
+ shape.from.clear();
69
+ if shape != crate::sql::empty_select() || select.from.len() != 1 {
70
+ return None;
71
+ }
72
+ let table = &select.from[0];
73
+ if !table.joins.is_empty() || !safe_projection(&select.projection) {
74
+ return None;
75
+ }
76
+ let TableFactor::Derived {
77
+ lateral: false,
78
+ subquery,
79
+ alias: Some(alias),
80
+ } = &table.relation
81
+ else {
82
+ return None;
83
+ };
84
+ if !alias.columns.is_empty() {
85
+ return None;
86
+ }
87
+ let mut inner = grouped_projection(subquery, registry)?;
88
+ let mut columns = HashMap::new();
89
+ for item in &inner.projection {
90
+ let (expr, name) = super::super::expr::projection_expr_and_name(item)?;
91
+ let name = name.or_else(|| super::super::expr::projected_column_name(expr))?;
92
+ if columns
93
+ .insert(name.to_ascii_lowercase(), expr.clone())
94
+ .is_some()
95
+ {
96
+ return None;
97
+ }
98
+ }
99
+ let mut projection = select.projection.clone();
100
+ for item in &mut projection {
101
+ // Preserve public names before substituting their defining expressions.
102
+ if let SelectItem::UnnamedExpr(expr) = item {
103
+ let alias = match expr {
104
+ Expr::Identifier(id) => id.clone(),
105
+ Expr::CompoundIdentifier(parts) => parts.last()?.clone(),
106
+ _ => return None,
107
+ };
108
+ *item = SelectItem::ExprWithAlias {
109
+ expr: expr.clone(),
110
+ alias,
111
+ };
112
+ }
113
+ let result = visit_expressions_mut(item, |expr| {
114
+ let name = match expr {
115
+ Expr::Identifier(name) => Some(name.value.to_ascii_lowercase()),
116
+ Expr::CompoundIdentifier(parts)
117
+ if parts.len() == 2
118
+ && parts[0].value.eq_ignore_ascii_case(&alias.name.value) =>
119
+ {
120
+ Some(parts[1].value.to_ascii_lowercase())
121
+ }
122
+ Expr::CompoundIdentifier(_) => return ControlFlow::Break(()),
123
+ _ => None,
124
+ };
125
+ if let Some(name) = name {
126
+ let Some(replacement) = columns.get(&name) else {
127
+ return ControlFlow::Break(());
128
+ };
129
+ *expr = replacement.clone();
130
+ }
131
+ ControlFlow::Continue(())
132
+ });
133
+ if result.is_break() {
134
+ return None;
135
+ }
136
+ }
137
+ inner.projection = projection;
138
+ // An unused global aggregate still determines cardinality; do not erase it.
139
+ select_is_aggregation(&inner, registry).then_some(inner)
140
+ }
141
+
142
+ fn safe_projection(items: &[SelectItem]) -> bool {
143
+ // Expansion can repeat expressions. Do not duplicate volatile or unknown
144
+ // functions, windows, or subqueries. These deterministic functions cover the
145
+ // typed JSON sink adapter without altering the underlying grouped query.
146
+ items.iter().all(|item| {
147
+ visit_expressions(item, |expr| {
148
+ match expr {
149
+ Expr::Function(function) => {
150
+ if function.over.is_some()
151
+ || !matches!(
152
+ function.name.to_string().to_ascii_lowercase().as_str(),
153
+ "json_object"
154
+ | "json_type"
155
+ | "regexp_full_match"
156
+ | "list"
157
+ | "array_agg"
158
+ | "min"
159
+ | "max"
160
+ | "sum"
161
+ | "count"
162
+ | "bool_and"
163
+ | "bool_or"
164
+ | "coalesce"
165
+ )
166
+ {
167
+ return ControlFlow::Break(());
168
+ }
169
+ }
170
+ Expr::Subquery(_) | Expr::Exists { .. } | Expr::InSubquery { .. } => {
171
+ return ControlFlow::Break(());
172
+ }
173
+ _ => {}
174
+ }
175
+ ControlFlow::Continue(())
176
+ })
177
+ .is_continue()
178
+ })
179
+ }
180
+
181
+ #[cfg(test)]
182
+ mod tests {
183
+ use super::*;
184
+ use crate::sql::SqlDialect;
185
+
186
+ fn query(sql: &str) -> Query {
187
+ let sqlparser::ast::Statement::Query(query) = crate::parser::parse_query(sql).unwrap()
188
+ else {
189
+ panic!("expected query");
190
+ };
191
+ *query
192
+ }
193
+
194
+ #[test]
195
+ fn flatten_pure_projection_keeps_global_aggregate() {
196
+ let mut q = query(
197
+ "SELECT v.body AS body FROM (SELECT CAST(list(id) AS VARCHAR) AS body FROM cases) AS v",
198
+ );
199
+ assert!(flatten(
200
+ &mut q,
201
+ &AggregateRegistry::for_dialect(SqlDialect::DuckDb)
202
+ ));
203
+ assert_eq!(
204
+ q.to_string(),
205
+ "SELECT CAST(list(id) AS VARCHAR) AS body FROM cases"
206
+ );
207
+ }
208
+
209
+ #[test]
210
+ fn preserve_quoted_output_alias() {
211
+ let mut q = query(
212
+ "SELECT v.\"to\" FROM (SELECT CAST(list(id) AS VARCHAR) AS \"to\" FROM cases) AS v",
213
+ );
214
+ assert!(flatten(
215
+ &mut q,
216
+ &AggregateRegistry::for_dialect(SqlDialect::DuckDb)
217
+ ));
218
+ assert_eq!(
219
+ q.to_string(),
220
+ "SELECT CAST(list(id) AS VARCHAR) AS \"to\" FROM cases"
221
+ );
222
+ }
223
+
224
+ #[test]
225
+ fn preserve_cardinality_and_unsupported_boundaries() {
226
+ for sql in [
227
+ "SELECT 1 AS x FROM (SELECT count(*) AS n FROM cases) AS v",
228
+ "SELECT v.body AS body FROM (SELECT CAST(list(id) AS VARCHAR) AS body FROM cases) AS v WHERE v.body IS NOT NULL",
229
+ "SELECT random() AS x, v.body AS body FROM (SELECT CAST(list(id) AS VARCHAR) AS body FROM cases) AS v",
230
+ "SELECT v.body AS body FROM (SELECT category, CAST(list(id) AS VARCHAR) AS body FROM cases GROUP BY 1) AS v",
231
+ "SELECT v.body AS body FROM (SELECT CAST(list(id) AS VARCHAR) AS body FROM cases HAVING body IS NOT NULL) AS v",
232
+ "SELECT v.body AS body FROM (SELECT CAST(list(id) AS VARCHAR) AS body FROM cases LIMIT 1) AS v",
233
+ "SELECT v.body AS body FROM (SELECT 'Discrimination' AS selected_category, CAST(list(id) AS VARCHAR) AS body FROM cases WHERE category=selected_category) AS v",
234
+ "SELECT v.body AS body FROM (SELECT CAST(list(id) AS VARCHAR) AS body FROM cases QUALIFY row_number() OVER () = 1) AS v",
235
+ ] {
236
+ let mut q = query(sql);
237
+ let original = q.clone();
238
+ assert!(
239
+ !flatten(&mut q, &AggregateRegistry::for_dialect(SqlDialect::DuckDb)),
240
+ "{sql}"
241
+ );
242
+ assert_eq!(q, original);
243
+ }
244
+ }
245
+ }
@@ -1,6 +1,7 @@
1
1
  //! Inherited policy demands and synthesized lineage for the joint endpoint.
2
2
  //! Each original query is entered once and synthesized once. CTE references bind
3
3
  //! memoized schemas; generated policy wrappers never enter this traversal.
4
+ mod grouped_projection;
4
5
  mod terminal_distinct;
5
6
  mod terminal_except;
6
7
  mod terminal_intersect;
@@ -95,6 +96,18 @@ pub(crate) fn rewrite_joint_root(
95
96
  if applicable.is_empty() {
96
97
  return Ok(false);
97
98
  }
99
+ if context.sink.is_some()
100
+ && grouped_projection::flatten(query, &rewriter.aggregate_registry)
101
+ && let SetExpr::Select(select) = query.body.as_ref()
102
+ {
103
+ for (column, item) in context.sink_output_columns.iter().zip(&select.projection) {
104
+ if let Some((expr, _)) = super::expr::projection_expr_and_name(item) {
105
+ context
106
+ .sink_expr_by_column
107
+ .insert(column.value.to_ascii_lowercase(), expr.clone());
108
+ }
109
+ }
110
+ }
98
111
  let strictly_applicable: Vec<_> = applicable
99
112
  .iter()
100
113
  .copied()
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "data-flow-control"
3
- version = "0.2.2"
3
+ version = "0.2.3"
4
4
  description = "Rust-backed Data Flow Control rewrite engine"
5
5
  license = "MIT"
6
6
  license-files = ["LICENSE"]