data-flow-control 0.2.0__tar.gz → 0.2.2__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 (192) hide show
  1. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/Cargo.lock +3 -3
  2. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/Cargo.toml +1 -1
  3. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/PKG-INFO +1 -1
  4. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/columns.rs +197 -235
  5. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/mod.rs +1 -0
  6. data_flow_control-0.2.2/passant-core/src/rewriter/sink_columns.rs +396 -0
  7. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/sql/builders.rs +6 -2
  8. data_flow_control-0.2.2/passant-core/tests/kill_null_guard_regression.rs +64 -0
  9. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/pyproject.toml +1 -1
  10. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/LICENSE +0 -0
  11. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/Cargo.toml +0 -0
  12. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/benches/rewrite_perf.rs +0 -0
  13. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/aggregate_registry.rs +0 -0
  14. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/catalog/dimension.rs +0 -0
  15. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/catalog.rs +0 -0
  16. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/diagnostics.rs +0 -0
  17. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/explain.rs +0 -0
  18. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/full_push.rs +0 -0
  19. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/identifiers.rs +0 -0
  20. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/intern.rs +0 -0
  21. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/ir.rs +0 -0
  22. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/lib.rs +0 -0
  23. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/optimizer.rs +0 -0
  24. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/parser.rs +0 -0
  25. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/partial_push.rs +0 -0
  26. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/planner.rs +0 -0
  27. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/policy.rs +0 -0
  28. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/policy_compile.rs +0 -0
  29. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/policy_index.rs +0 -0
  30. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/policy_parser.rs +0 -0
  31. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/policy_pgn.pest +0 -0
  32. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/policy_store/branch.rs +0 -0
  33. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/policy_store/compiled.rs +0 -0
  34. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/policy_store/delete.rs +0 -0
  35. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/policy_store/indexes.rs +0 -0
  36. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/policy_store/memory.rs +0 -0
  37. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/policy_store/mod.rs +0 -0
  38. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/query_analysis.rs +0 -0
  39. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/resolution_placement.rs +0 -0
  40. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/resolution_registry.rs +0 -0
  41. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewrite_stats.rs +0 -0
  42. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewrite_strategy.rs +0 -0
  43. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/aggregates.rs +0 -0
  44. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/constraint_preprocess.rs +0 -0
  45. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/derived_policy.rs +0 -0
  46. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/dimensions.rs +0 -0
  47. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/exists.rs +0 -0
  48. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/expr.rs +0 -0
  49. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/helpers.rs +0 -0
  50. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/insert_output_policy.rs +0 -0
  51. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/joint_lineage/terminal_distinct.rs +0 -0
  52. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/joint_lineage/terminal_except.rs +0 -0
  53. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/joint_lineage/terminal_intersect.rs +0 -0
  54. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/joint_lineage.rs +0 -0
  55. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/limit.rs +0 -0
  56. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/output_scope.rs +0 -0
  57. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/plan/actions.rs +0 -0
  58. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/plan/applicability.rs +0 -0
  59. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/plan/dominance.rs +0 -0
  60. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/plan/mod.rs +0 -0
  61. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/plan/scope_plan.rs +0 -0
  62. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/plan/write_plan.rs +0 -0
  63. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/policy_expr.rs +0 -0
  64. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/projection.rs +0 -0
  65. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/resolution.rs +0 -0
  66. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/scope.rs +0 -0
  67. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/select.rs +0 -0
  68. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/types.rs +0 -0
  69. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/rewriter/write_path.rs +0 -0
  70. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/semiring.rs +0 -0
  71. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/source_set_index.rs +0 -0
  72. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/source_sets/analysis.rs +0 -0
  73. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/source_sets/annotations.rs +0 -0
  74. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/source_sets/branch.rs +0 -0
  75. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/source_sets/mod.rs +0 -0
  76. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/source_sets/rewrites.rs +0 -0
  77. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/source_sets/split.rs +0 -0
  78. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/sql/ast_stats.rs +0 -0
  79. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/sql/columns.rs +0 -0
  80. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/sql/dialect.rs +0 -0
  81. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/sql/expr.rs +0 -0
  82. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/sql/expr_key.rs +0 -0
  83. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/sql/mod.rs +0 -0
  84. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/sql/parse.rs +0 -0
  85. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/sql/render.rs +0 -0
  86. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/statement_tables.rs +0 -0
  87. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/src/threshold.rs +0 -0
  88. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/common/duckdb.rs +0 -0
  89. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/common/mod.rs +0 -0
  90. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/completion/conformance.rs +0 -0
  91. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/completion/main.rs +0 -0
  92. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/completion/partial_push.rs +0 -0
  93. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/completion/pgn.rs +0 -0
  94. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/completion/pgn_unique.rs +0 -0
  95. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/completion/policy_storage.rs +0 -0
  96. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/completion/rewrite_api_parity.rs +0 -0
  97. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/completion/semiring.rs +0 -0
  98. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/completion/source_sets.rs +0 -0
  99. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/completion/symmetric_self_join.rs +0 -0
  100. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/completion/threshold.rs +0 -0
  101. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/completion/unique_not_unique.rs +0 -0
  102. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/dialect.rs +0 -0
  103. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/execution/insert.rs +0 -0
  104. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/execution/kill.rs +0 -0
  105. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/execution/main.rs +0 -0
  106. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/execution/oracle.rs +0 -0
  107. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/execution/remove.rs +0 -0
  108. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/execution/update.rs +0 -0
  109. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/expected/duckdb/remove_scan.sql +0 -0
  110. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/expected/postgres/remove_scan.sql +0 -0
  111. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/expected/sqlite/remove_scan.sql +0 -0
  112. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/explain_strategy.rs +0 -0
  113. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/gaps/column_propagation.rs +0 -0
  114. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/gaps/dimensions.rs +0 -0
  115. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/gaps/exists_join.rs +0 -0
  116. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/gaps/having_where.rs +0 -0
  117. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/gaps/identifiers.rs +0 -0
  118. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/gaps/insert_shapes.rs +0 -0
  119. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/gaps/main.rs +0 -0
  120. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/gaps/multi_source.rs +0 -0
  121. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/gaps/operators.rs +0 -0
  122. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/gaps/query_shapes.rs +0 -0
  123. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/gaps/scalar_subquery.rs +0 -0
  124. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/indexed_candidate_differential.rs +0 -0
  125. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/insert_values_body.rs +0 -0
  126. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/paper_examples.rs +0 -0
  127. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/parser.rs +0 -0
  128. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/planner.rs +0 -0
  129. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/policy.rs +0 -0
  130. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/policy_dialect.rs +0 -0
  131. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/policy_store_memory.rs +0 -0
  132. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/rewrite/derived_policy.rs +0 -0
  133. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/rewrite/in_semijoin.rs +0 -0
  134. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/rewrite/insert.rs +0 -0
  135. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/rewrite/joins.rs +0 -0
  136. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/rewrite/main.rs +0 -0
  137. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/rewrite/meal_deduction.rs +0 -0
  138. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/rewrite/output.rs +0 -0
  139. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/rewrite/recursive.rs +0 -0
  140. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/rewrite/scan.rs +0 -0
  141. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/rewrite/update.rs +0 -0
  142. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/rewrite_candidate_regression.rs +0 -0
  143. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/rewrite_fast_paths.rs +0 -0
  144. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/rewrite_large_registry.rs +0 -0
  145. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/rewrite_stats_timings.rs +0 -0
  146. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/scan_ready_expr.rs +0 -0
  147. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/source_set_split_no_parse.rs +0 -0
  148. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/sql_builders.rs +0 -0
  149. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/sql_columns.rs +0 -0
  150. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-core/tests/ui_resolution.rs +0 -0
  151. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-py/Cargo.toml +0 -0
  152. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-py/src/bindings/catalog.rs +0 -0
  153. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-py/src/bindings/errors.rs +0 -0
  154. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-py/src/bindings/mod.rs +0 -0
  155. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-py/src/bindings/planner.rs +0 -0
  156. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-py/src/bindings/policy.rs +0 -0
  157. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-py/src/bindings/stats.rs +0 -0
  158. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/passant-py/src/lib.rs +0 -0
  159. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/__init__.py +0 -0
  160. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/_rust.py +0 -0
  161. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/adapters/__init__.py +0 -0
  162. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/adapters/_retry.py +0 -0
  163. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/adapters/base.py +0 -0
  164. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/adapters/clickhouse.py +0 -0
  165. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/adapters/datafusion.py +0 -0
  166. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/adapters/duckdb.py +0 -0
  167. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/adapters/kill.py +0 -0
  168. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/adapters/pg_catalog.py +0 -0
  169. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/adapters/postgres.py +0 -0
  170. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/adapters/registry.py +0 -0
  171. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/adapters/sqlite.py +0 -0
  172. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/adapters/umbra.py +0 -0
  173. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/aggregate_introspection.py +0 -0
  174. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/catalog.py +0 -0
  175. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/connection.py +0 -0
  176. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/dialect.py +0 -0
  177. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/errors.py +0 -0
  178. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/langchain/__init__.py +0 -0
  179. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/langchain/agent.py +0 -0
  180. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/langchain/call_tool_with_dataflow.py +0 -0
  181. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/langchain/database.py +0 -0
  182. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/langchain/middleware.py +0 -0
  183. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/langchain/schema.py +0 -0
  184. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/langchain/sql_validation.py +0 -0
  185. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/langchain/tool_spec.py +0 -0
  186. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/langchain/wrapper.py +0 -0
  187. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/options.py +0 -0
  188. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/planner.py +0 -0
  189. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/policy.py +0 -0
  190. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/tools/__init__.py +0 -0
  191. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/python/data_flow_control/tools/retry.py +0 -0
  192. {data_flow_control-0.2.0 → data_flow_control-0.2.2}/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.0"
1596
+ version = "0.2.2"
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.0"
1608
+ version = "0.2.2"
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.0"
1626
+ version = "0.2.2"
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.0"
6
+ version = "0.2.2"
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.0
3
+ Version: 0.2.2
4
4
  Requires-Dist: duckdb>=1.3.0
5
5
  Requires-Dist: numpy>=1.24.4
6
6
  Requires-Dist: sqlglot==28.3.0
@@ -2,8 +2,8 @@ use std::collections::{HashMap, HashSet};
2
2
 
3
3
  use sqlparser::ast::{Expr, FunctionArg, FunctionArgExpr, FunctionArguments, Ident};
4
4
 
5
- use crate::diagnostics::{ErrorKind, RewriteError};
6
- use crate::identifiers::{AliasByBase, ColumnName, QualifiedColumn, TableName};
5
+ use crate::diagnostics::RewriteError;
6
+ use crate::identifiers::{AliasByBase, ColumnName, QualifiedColumn};
7
7
 
8
8
  use super::helpers::OUTPUT_MARKER;
9
9
 
@@ -39,6 +39,14 @@ pub(crate) fn replace_source_alias_qualifiers(
39
39
  op,
40
40
  expr: Box::new(replace_source_alias_qualifiers(*expr, source_aliases)),
41
41
  },
42
+ Expr::IsNull(expr) => Expr::IsNull(Box::new(replace_source_alias_qualifiers(
43
+ *expr,
44
+ source_aliases,
45
+ ))),
46
+ Expr::IsNotNull(expr) => Expr::IsNotNull(Box::new(replace_source_alias_qualifiers(
47
+ *expr,
48
+ source_aliases,
49
+ ))),
42
50
  Expr::Case {
43
51
  operand,
44
52
  conditions,
@@ -88,10 +96,10 @@ pub(crate) fn apply_policy_sink_column_replacements(
88
96
  expr
89
97
  };
90
98
  if let Some(sink_alias) = sink_alias {
91
- expr = replace_sink_columns(expr, sink_alias, sink_expr_by_column);
99
+ expr = replace_sink_columns(expr, sink_alias, sink_expr_by_column)?;
92
100
  }
93
101
  if !(sink_overlaps_source && sink_alias.is_some()) {
94
- expr = replace_sink_columns(expr, sink, sink_expr_by_column);
102
+ expr = replace_sink_columns(expr, sink, sink_expr_by_column)?;
95
103
  }
96
104
  Ok(expr)
97
105
  }
@@ -116,59 +124,8 @@ pub(crate) fn replace_sink_columns(
116
124
  expr: Expr,
117
125
  sink: &str,
118
126
  sink_expr_by_column: &HashMap<String, Expr>,
119
- ) -> Expr {
120
- let sink_table = TableName::parse(sink);
121
- match expr {
122
- Expr::CompoundIdentifier(parts) if parts.len() >= 2 => {
123
- if let Some(column) = QualifiedColumn::from_compound_identifier(&parts)
124
- && sink_table.matches_name(column.table.as_str())
125
- {
126
- return sink_expr_by_column
127
- .get(&column.column.key())
128
- .cloned()
129
- .unwrap_or(Expr::CompoundIdentifier(parts));
130
- }
131
- Expr::CompoundIdentifier(parts)
132
- }
133
- Expr::BinaryOp { left, op, right } => Expr::BinaryOp {
134
- left: Box::new(replace_sink_columns(*left, sink, sink_expr_by_column)),
135
- op,
136
- right: Box::new(replace_sink_columns(*right, sink, sink_expr_by_column)),
137
- },
138
- Expr::Nested(expr) => Expr::Nested(Box::new(replace_sink_columns(
139
- *expr,
140
- sink,
141
- sink_expr_by_column,
142
- ))),
143
- Expr::UnaryOp { op, expr } => Expr::UnaryOp {
144
- op,
145
- expr: Box::new(replace_sink_columns(*expr, sink, sink_expr_by_column)),
146
- },
147
- Expr::Case {
148
- operand,
149
- conditions,
150
- results,
151
- else_result,
152
- } => Expr::Case {
153
- operand: operand
154
- .map(|expr| Box::new(replace_sink_columns(*expr, sink, sink_expr_by_column))),
155
- conditions: conditions
156
- .into_iter()
157
- .map(|expr| replace_sink_columns(expr, sink, sink_expr_by_column))
158
- .collect(),
159
- results: results
160
- .into_iter()
161
- .map(|expr| replace_sink_columns(expr, sink, sink_expr_by_column))
162
- .collect(),
163
- else_result: else_result
164
- .map(|expr| Box::new(replace_sink_columns(*expr, sink, sink_expr_by_column))),
165
- },
166
- Expr::Function(mut function) => {
167
- replace_sink_columns_in_function(&mut function, sink, sink_expr_by_column);
168
- Expr::Function(function)
169
- }
170
- other => other,
171
- }
127
+ ) -> Result<Expr, RewriteError> {
128
+ super::sink_columns::replace(expr, sink, sink_expr_by_column, None)
172
129
  }
173
130
 
174
131
  fn replace_sink_columns_strict(
@@ -177,125 +134,12 @@ fn replace_sink_columns_strict(
177
134
  sink_expr_by_column: &HashMap<String, Expr>,
178
135
  ambiguous_output_columns: &HashSet<String>,
179
136
  ) -> Result<Expr, RewriteError> {
180
- let sink_table = TableName::parse(sink);
181
- match expr {
182
- Expr::CompoundIdentifier(parts) if parts.len() >= 2 => {
183
- if let Some(column) = QualifiedColumn::from_compound_identifier(&parts)
184
- && sink_table.matches_name(column.table.as_str())
185
- {
186
- let key = column.column.key();
187
- if ambiguous_output_columns.contains(&key) {
188
- return Err(RewriteError::unsupported(
189
- ErrorKind::InvalidSinkColumn,
190
- format!(
191
- "ambiguous _OUTPUT_ column '{}': multiple projected expressions share this output name",
192
- column.column.as_str()
193
- ),
194
- ));
195
- }
196
- if let Some(replacement) = sink_expr_by_column.get(&key) {
197
- return Ok(replacement.clone());
198
- }
199
- return Err(RewriteError::catalog(
200
- ErrorKind::InvalidSinkColumn,
201
- format!(
202
- "{sink}.{} is not a projected output column",
203
- column.column.as_str()
204
- ),
205
- Some(sink.to_string()),
206
- Some(column.column.as_str().to_string()),
207
- ));
208
- }
209
- Ok(Expr::CompoundIdentifier(parts))
210
- }
211
- Expr::BinaryOp { left, op, right } => Ok(Expr::BinaryOp {
212
- left: Box::new(replace_sink_columns_strict(
213
- *left,
214
- sink,
215
- sink_expr_by_column,
216
- ambiguous_output_columns,
217
- )?),
218
- op,
219
- right: Box::new(replace_sink_columns_strict(
220
- *right,
221
- sink,
222
- sink_expr_by_column,
223
- ambiguous_output_columns,
224
- )?),
225
- }),
226
- Expr::Nested(expr) => Ok(Expr::Nested(Box::new(replace_sink_columns_strict(
227
- *expr,
228
- sink,
229
- sink_expr_by_column,
230
- ambiguous_output_columns,
231
- )?))),
232
- Expr::UnaryOp { op, expr } => Ok(Expr::UnaryOp {
233
- op,
234
- expr: Box::new(replace_sink_columns_strict(
235
- *expr,
236
- sink,
237
- sink_expr_by_column,
238
- ambiguous_output_columns,
239
- )?),
240
- }),
241
- Expr::Case {
242
- operand,
243
- conditions,
244
- results,
245
- else_result,
246
- } => Ok(Expr::Case {
247
- operand: match operand {
248
- Some(expr) => Some(Box::new(replace_sink_columns_strict(
249
- *expr,
250
- sink,
251
- sink_expr_by_column,
252
- ambiguous_output_columns,
253
- )?)),
254
- None => None,
255
- },
256
- conditions: conditions
257
- .into_iter()
258
- .map(|expr| {
259
- replace_sink_columns_strict(
260
- expr,
261
- sink,
262
- sink_expr_by_column,
263
- ambiguous_output_columns,
264
- )
265
- })
266
- .collect::<Result<Vec<_>, _>>()?,
267
- results: results
268
- .into_iter()
269
- .map(|expr| {
270
- replace_sink_columns_strict(
271
- expr,
272
- sink,
273
- sink_expr_by_column,
274
- ambiguous_output_columns,
275
- )
276
- })
277
- .collect::<Result<Vec<_>, _>>()?,
278
- else_result: match else_result {
279
- Some(expr) => Some(Box::new(replace_sink_columns_strict(
280
- *expr,
281
- sink,
282
- sink_expr_by_column,
283
- ambiguous_output_columns,
284
- )?)),
285
- None => None,
286
- },
287
- }),
288
- Expr::Function(mut function) => {
289
- replace_sink_columns_strict_in_function(
290
- &mut function,
291
- sink,
292
- sink_expr_by_column,
293
- ambiguous_output_columns,
294
- )?;
295
- Ok(Expr::Function(function))
296
- }
297
- other => Ok(other),
298
- }
137
+ super::sink_columns::replace(
138
+ expr,
139
+ sink,
140
+ sink_expr_by_column,
141
+ Some(ambiguous_output_columns),
142
+ )
299
143
  }
300
144
 
301
145
  pub(crate) fn collect_compound_columns_by_name(expr: &Expr, columns: &mut HashMap<String, Expr>) {
@@ -454,65 +298,6 @@ fn replace_source_alias_qualifiers_in_function(
454
298
  }
455
299
  }
456
300
 
457
- fn replace_sink_columns_in_function(
458
- function: &mut sqlparser::ast::Function,
459
- sink: &str,
460
- sink_expr_by_column: &HashMap<String, Expr>,
461
- ) {
462
- let FunctionArguments::List(args) = &mut function.args else {
463
- return;
464
- };
465
- for arg in &mut args.args {
466
- match arg {
467
- FunctionArg::Unnamed(FunctionArgExpr::Expr(expr))
468
- | FunctionArg::Named {
469
- arg: FunctionArgExpr::Expr(expr),
470
- ..
471
- }
472
- | FunctionArg::ExprNamed {
473
- arg: FunctionArgExpr::Expr(expr),
474
- ..
475
- } => {
476
- *expr = replace_sink_columns(expr.clone(), sink, sink_expr_by_column);
477
- }
478
- _ => {}
479
- }
480
- }
481
- }
482
-
483
- fn replace_sink_columns_strict_in_function(
484
- function: &mut sqlparser::ast::Function,
485
- sink: &str,
486
- sink_expr_by_column: &HashMap<String, Expr>,
487
- ambiguous_output_columns: &HashSet<String>,
488
- ) -> Result<(), RewriteError> {
489
- let FunctionArguments::List(args) = &mut function.args else {
490
- return Ok(());
491
- };
492
- for arg in &mut args.args {
493
- match arg {
494
- FunctionArg::Unnamed(FunctionArgExpr::Expr(expr))
495
- | FunctionArg::Named {
496
- arg: FunctionArgExpr::Expr(expr),
497
- ..
498
- }
499
- | FunctionArg::ExprNamed {
500
- arg: FunctionArgExpr::Expr(expr),
501
- ..
502
- } => {
503
- *expr = replace_sink_columns_strict(
504
- expr.clone(),
505
- sink,
506
- sink_expr_by_column,
507
- ambiguous_output_columns,
508
- )?;
509
- }
510
- _ => {}
511
- }
512
- }
513
- Ok(())
514
- }
515
-
516
301
  pub(crate) fn rewrite_column_qualifiers(expr: &mut Expr, alias_by_base: &AliasByBase) {
517
302
  match expr {
518
303
  Expr::CompoundIdentifier(parts) if parts.len() >= 2 => {
@@ -676,4 +461,181 @@ mod tests {
676
461
  );
677
462
  assert_eq!(expr.to_string(), "mt.\"OrderID\" > 1");
678
463
  }
464
+
465
+ #[test]
466
+ fn source_alias_replacement_descends_through_nested_null_tests() {
467
+ let aliases = HashMap::from([("src".to_string(), "receipts".to_string())]);
468
+ for (input, expected) in [
469
+ ("src.amount IS NULL", "receipts.amount IS NULL"),
470
+ ("src.amount IS NOT NULL", "receipts.amount IS NOT NULL"),
471
+ (
472
+ "NOT ((src.amount IS NULL) IS NOT NULL)",
473
+ "NOT ((receipts.amount IS NULL) IS NOT NULL)",
474
+ ),
475
+ (
476
+ "CASE WHEN src.amount IS NULL THEN src.id IS NOT NULL ELSE false END",
477
+ "CASE WHEN receipts.amount IS NULL THEN receipts.id IS NOT NULL ELSE false END",
478
+ ),
479
+ (
480
+ "coalesce(src.amount IS NOT NULL, false)",
481
+ "coalesce(receipts.amount IS NOT NULL, false)",
482
+ ),
483
+ ] {
484
+ assert_eq!(
485
+ replace_source_alias_qualifiers(parse_expr(input), &aliases),
486
+ parse_expr(expected),
487
+ "{input}"
488
+ );
489
+ }
490
+ }
491
+
492
+ #[test]
493
+ fn sink_replacement_descends_through_nested_null_tests() {
494
+ let columns = HashMap::from([("amount".to_string(), parse_expr("input.cost"))]);
495
+ for (input, expected) in [
496
+ ("reports.amount IS NULL", "input.cost IS NULL"),
497
+ ("reports.amount IS NOT NULL", "input.cost IS NOT NULL"),
498
+ (
499
+ "NOT ((reports.amount IS NOT NULL) IS NULL)",
500
+ "NOT ((input.cost IS NOT NULL) IS NULL)",
501
+ ),
502
+ (
503
+ "coalesce(reports.amount IS NULL, false)",
504
+ "coalesce(input.cost IS NULL, false)",
505
+ ),
506
+ ] {
507
+ assert_eq!(
508
+ replace_sink_columns(parse_expr(input), "reports", &columns).unwrap(),
509
+ parse_expr(expected),
510
+ "{input}"
511
+ );
512
+ }
513
+ }
514
+
515
+ #[test]
516
+ fn output_marker_replacement_descends_through_nested_null_tests() {
517
+ let columns = HashMap::from([("amount".to_string(), parse_expr("input.cost"))]);
518
+ for (input, expected) in [
519
+ ("_OUTPUT_.amount IS NULL", "input.cost IS NULL"),
520
+ ("_OUTPUT_.amount IS NOT NULL", "input.cost IS NOT NULL"),
521
+ (
522
+ "NOT ((_OUTPUT_.amount IS NULL) IS NOT NULL)",
523
+ "NOT ((input.cost IS NULL) IS NOT NULL)",
524
+ ),
525
+ (
526
+ "CASE WHEN _OUTPUT_.amount IS NULL THEN false ELSE _OUTPUT_.amount IS NOT NULL END",
527
+ "CASE WHEN input.cost IS NULL THEN false ELSE input.cost IS NOT NULL END",
528
+ ),
529
+ ] {
530
+ assert_eq!(
531
+ apply_output_marker_replacements(parse_expr(input), &columns, &HashSet::new())
532
+ .expect("valid output mapping"),
533
+ parse_expr(expected),
534
+ "{input}"
535
+ );
536
+ }
537
+ }
538
+
539
+ #[test]
540
+ fn nested_null_output_references_still_reject_ambiguity_and_missing_columns() {
541
+ let columns = HashMap::from([("amount".to_string(), parse_expr("input.cost"))]);
542
+ let ambiguous = HashSet::from(["amount".to_string()]);
543
+ for predicate in [
544
+ "_OUTPUT_.amount IS NULL",
545
+ "NOT ((_OUTPUT_.amount IS NOT NULL) IS NULL)",
546
+ ] {
547
+ let error =
548
+ apply_output_marker_replacements(parse_expr(predicate), &columns, &ambiguous)
549
+ .expect_err("ambiguous output must fail closed");
550
+ assert!(
551
+ error.to_string().contains("ambiguous _OUTPUT_ column"),
552
+ "{error}"
553
+ );
554
+ }
555
+ for predicate in [
556
+ "_OUTPUT_.missing IS NULL",
557
+ "NOT ((_OUTPUT_.missing IS NOT NULL) IS NULL)",
558
+ ] {
559
+ let error =
560
+ apply_output_marker_replacements(parse_expr(predicate), &columns, &HashSet::new())
561
+ .expect_err("missing output must fail closed");
562
+ assert!(
563
+ error.to_string().contains("not a projected output column"),
564
+ "{error}"
565
+ );
566
+ }
567
+ }
568
+
569
+ #[test]
570
+ fn null_replacements_preserve_unrelated_qualifiers() {
571
+ let columns = HashMap::from([("amount".to_string(), parse_expr("input.cost"))]);
572
+ let original = parse_expr("other.amount IS NULL OR other.amount IS NOT NULL");
573
+ assert_eq!(
574
+ replace_sink_columns(original.clone(), "reports", &columns).unwrap(),
575
+ original
576
+ );
577
+ assert_eq!(
578
+ apply_output_marker_replacements(original.clone(), &columns, &HashSet::new()).unwrap(),
579
+ original
580
+ );
581
+ }
582
+ #[test]
583
+ fn nested_output_references_preserve_strict_validation() {
584
+ let columns = HashMap::from([("amount".to_string(), parse_expr("input.cost"))]);
585
+ let ambiguous = HashSet::from(["amount".to_string()]);
586
+ let error = apply_output_marker_replacements(
587
+ parse_expr("EXISTS (SELECT 1 WHERE _OUTPUT_.amount > 0)"),
588
+ &columns,
589
+ &ambiguous,
590
+ )
591
+ .expect_err("nested ambiguous output must fail closed");
592
+ assert!(error.to_string().contains("ambiguous _OUTPUT_ column"));
593
+ let error = apply_output_marker_replacements(
594
+ parse_expr("EXISTS (SELECT 1 WHERE _OUTPUT_.missing > 0)"),
595
+ &columns,
596
+ &HashSet::new(),
597
+ )
598
+ .expect_err("nested missing output must fail closed");
599
+ assert!(error.to_string().contains("not a projected output column"));
600
+ }
601
+
602
+ #[test]
603
+ fn output_subquery_replaces_only_free_references() {
604
+ let columns = HashMap::from([("amount".to_string(), parse_expr("input.cost"))]);
605
+ let original =
606
+ parse_expr("EXISTS (SELECT 1 FROM lookup AS _OUTPUT_ WHERE _OUTPUT_.amount > 0)");
607
+ assert_eq!(
608
+ apply_output_marker_replacements(original.clone(), &columns, &HashSet::new()).unwrap(),
609
+ original
610
+ );
611
+ assert_eq!(
612
+ apply_output_marker_replacements(
613
+ parse_expr("EXISTS (SELECT 1 WHERE _OUTPUT_.amount > 0)"),
614
+ &columns,
615
+ &HashSet::new()
616
+ )
617
+ .unwrap(),
618
+ parse_expr("EXISTS (SELECT 1 WHERE input.cost > 0)")
619
+ );
620
+ }
621
+
622
+ #[test]
623
+ fn unrelated_complex_subquery_is_unchanged() {
624
+ let columns = HashMap::from([("amount".to_string(), parse_expr("1"))]);
625
+ let original =
626
+ parse_expr("EXISTS (SELECT 1 FROM sales PIVOT (sum(amount) FOR month IN ('JAN'))) ");
627
+ assert_eq!(
628
+ replace_sink_columns(original.clone(), "sink", &columns).unwrap(),
629
+ original
630
+ );
631
+ let relevant = parse_expr(
632
+ "EXISTS (SELECT sink.amount FROM sales PIVOT (sum(amount) FOR month IN ('JAN'))) ",
633
+ );
634
+ assert!(
635
+ replace_sink_columns(relevant, "sink", &columns)
636
+ .unwrap_err()
637
+ .to_string()
638
+ .contains("operator-specific scope")
639
+ );
640
+ }
679
641
  }
@@ -27,6 +27,7 @@ mod aggregates;
27
27
  pub(crate) use aggregates::decompose_composed_aggregates;
28
28
  mod columns;
29
29
  pub(crate) mod constraint_preprocess;
30
+ mod sink_columns;
30
31
  pub(crate) use constraint_preprocess::preprocess_policy_constraint;
31
32
  mod derived_policy;
32
33
  pub(crate) mod dimensions;