data-flow-control 0.2.0__tar.gz → 0.2.1__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 (191) hide show
  1. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/Cargo.lock +3 -3
  2. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/Cargo.toml +1 -1
  3. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/PKG-INFO +1 -1
  4. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/columns.rs +148 -0
  5. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/sql/builders.rs +6 -2
  6. data_flow_control-0.2.1/passant-core/tests/kill_null_guard_regression.rs +64 -0
  7. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/pyproject.toml +1 -1
  8. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/LICENSE +0 -0
  9. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/Cargo.toml +0 -0
  10. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/benches/rewrite_perf.rs +0 -0
  11. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/aggregate_registry.rs +0 -0
  12. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/catalog/dimension.rs +0 -0
  13. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/catalog.rs +0 -0
  14. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/diagnostics.rs +0 -0
  15. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/explain.rs +0 -0
  16. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/full_push.rs +0 -0
  17. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/identifiers.rs +0 -0
  18. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/intern.rs +0 -0
  19. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/ir.rs +0 -0
  20. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/lib.rs +0 -0
  21. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/optimizer.rs +0 -0
  22. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/parser.rs +0 -0
  23. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/partial_push.rs +0 -0
  24. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/planner.rs +0 -0
  25. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/policy.rs +0 -0
  26. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/policy_compile.rs +0 -0
  27. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/policy_index.rs +0 -0
  28. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/policy_parser.rs +0 -0
  29. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/policy_pgn.pest +0 -0
  30. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/policy_store/branch.rs +0 -0
  31. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/policy_store/compiled.rs +0 -0
  32. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/policy_store/delete.rs +0 -0
  33. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/policy_store/indexes.rs +0 -0
  34. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/policy_store/memory.rs +0 -0
  35. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/policy_store/mod.rs +0 -0
  36. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/query_analysis.rs +0 -0
  37. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/resolution_placement.rs +0 -0
  38. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/resolution_registry.rs +0 -0
  39. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewrite_stats.rs +0 -0
  40. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewrite_strategy.rs +0 -0
  41. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/aggregates.rs +0 -0
  42. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/constraint_preprocess.rs +0 -0
  43. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/derived_policy.rs +0 -0
  44. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/dimensions.rs +0 -0
  45. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/exists.rs +0 -0
  46. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/expr.rs +0 -0
  47. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/helpers.rs +0 -0
  48. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/insert_output_policy.rs +0 -0
  49. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/joint_lineage/terminal_distinct.rs +0 -0
  50. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/joint_lineage/terminal_except.rs +0 -0
  51. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/joint_lineage/terminal_intersect.rs +0 -0
  52. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/joint_lineage.rs +0 -0
  53. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/limit.rs +0 -0
  54. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/mod.rs +0 -0
  55. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/output_scope.rs +0 -0
  56. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/plan/actions.rs +0 -0
  57. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/plan/applicability.rs +0 -0
  58. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/plan/dominance.rs +0 -0
  59. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/plan/mod.rs +0 -0
  60. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/plan/scope_plan.rs +0 -0
  61. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/plan/write_plan.rs +0 -0
  62. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/policy_expr.rs +0 -0
  63. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/projection.rs +0 -0
  64. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/resolution.rs +0 -0
  65. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/scope.rs +0 -0
  66. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/select.rs +0 -0
  67. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/types.rs +0 -0
  68. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/rewriter/write_path.rs +0 -0
  69. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/semiring.rs +0 -0
  70. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/source_set_index.rs +0 -0
  71. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/source_sets/analysis.rs +0 -0
  72. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/source_sets/annotations.rs +0 -0
  73. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/source_sets/branch.rs +0 -0
  74. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/source_sets/mod.rs +0 -0
  75. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/source_sets/rewrites.rs +0 -0
  76. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/source_sets/split.rs +0 -0
  77. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/sql/ast_stats.rs +0 -0
  78. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/sql/columns.rs +0 -0
  79. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/sql/dialect.rs +0 -0
  80. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/sql/expr.rs +0 -0
  81. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/sql/expr_key.rs +0 -0
  82. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/sql/mod.rs +0 -0
  83. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/sql/parse.rs +0 -0
  84. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/sql/render.rs +0 -0
  85. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/statement_tables.rs +0 -0
  86. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/src/threshold.rs +0 -0
  87. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/common/duckdb.rs +0 -0
  88. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/common/mod.rs +0 -0
  89. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/completion/conformance.rs +0 -0
  90. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/completion/main.rs +0 -0
  91. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/completion/partial_push.rs +0 -0
  92. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/completion/pgn.rs +0 -0
  93. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/completion/pgn_unique.rs +0 -0
  94. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/completion/policy_storage.rs +0 -0
  95. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/completion/rewrite_api_parity.rs +0 -0
  96. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/completion/semiring.rs +0 -0
  97. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/completion/source_sets.rs +0 -0
  98. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/completion/symmetric_self_join.rs +0 -0
  99. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/completion/threshold.rs +0 -0
  100. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/completion/unique_not_unique.rs +0 -0
  101. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/dialect.rs +0 -0
  102. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/execution/insert.rs +0 -0
  103. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/execution/kill.rs +0 -0
  104. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/execution/main.rs +0 -0
  105. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/execution/oracle.rs +0 -0
  106. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/execution/remove.rs +0 -0
  107. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/execution/update.rs +0 -0
  108. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/expected/duckdb/remove_scan.sql +0 -0
  109. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/expected/postgres/remove_scan.sql +0 -0
  110. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/expected/sqlite/remove_scan.sql +0 -0
  111. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/explain_strategy.rs +0 -0
  112. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/gaps/column_propagation.rs +0 -0
  113. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/gaps/dimensions.rs +0 -0
  114. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/gaps/exists_join.rs +0 -0
  115. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/gaps/having_where.rs +0 -0
  116. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/gaps/identifiers.rs +0 -0
  117. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/gaps/insert_shapes.rs +0 -0
  118. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/gaps/main.rs +0 -0
  119. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/gaps/multi_source.rs +0 -0
  120. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/gaps/operators.rs +0 -0
  121. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/gaps/query_shapes.rs +0 -0
  122. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/gaps/scalar_subquery.rs +0 -0
  123. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/indexed_candidate_differential.rs +0 -0
  124. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/insert_values_body.rs +0 -0
  125. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/paper_examples.rs +0 -0
  126. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/parser.rs +0 -0
  127. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/planner.rs +0 -0
  128. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/policy.rs +0 -0
  129. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/policy_dialect.rs +0 -0
  130. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/policy_store_memory.rs +0 -0
  131. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/rewrite/derived_policy.rs +0 -0
  132. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/rewrite/in_semijoin.rs +0 -0
  133. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/rewrite/insert.rs +0 -0
  134. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/rewrite/joins.rs +0 -0
  135. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/rewrite/main.rs +0 -0
  136. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/rewrite/meal_deduction.rs +0 -0
  137. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/rewrite/output.rs +0 -0
  138. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/rewrite/recursive.rs +0 -0
  139. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/rewrite/scan.rs +0 -0
  140. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/rewrite/update.rs +0 -0
  141. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/rewrite_candidate_regression.rs +0 -0
  142. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/rewrite_fast_paths.rs +0 -0
  143. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/rewrite_large_registry.rs +0 -0
  144. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/rewrite_stats_timings.rs +0 -0
  145. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/scan_ready_expr.rs +0 -0
  146. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/source_set_split_no_parse.rs +0 -0
  147. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/sql_builders.rs +0 -0
  148. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/sql_columns.rs +0 -0
  149. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-core/tests/ui_resolution.rs +0 -0
  150. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-py/Cargo.toml +0 -0
  151. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-py/src/bindings/catalog.rs +0 -0
  152. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-py/src/bindings/errors.rs +0 -0
  153. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-py/src/bindings/mod.rs +0 -0
  154. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-py/src/bindings/planner.rs +0 -0
  155. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-py/src/bindings/policy.rs +0 -0
  156. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-py/src/bindings/stats.rs +0 -0
  157. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/passant-py/src/lib.rs +0 -0
  158. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/__init__.py +0 -0
  159. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/_rust.py +0 -0
  160. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/adapters/__init__.py +0 -0
  161. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/adapters/_retry.py +0 -0
  162. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/adapters/base.py +0 -0
  163. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/adapters/clickhouse.py +0 -0
  164. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/adapters/datafusion.py +0 -0
  165. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/adapters/duckdb.py +0 -0
  166. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/adapters/kill.py +0 -0
  167. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/adapters/pg_catalog.py +0 -0
  168. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/adapters/postgres.py +0 -0
  169. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/adapters/registry.py +0 -0
  170. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/adapters/sqlite.py +0 -0
  171. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/adapters/umbra.py +0 -0
  172. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/aggregate_introspection.py +0 -0
  173. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/catalog.py +0 -0
  174. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/connection.py +0 -0
  175. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/dialect.py +0 -0
  176. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/errors.py +0 -0
  177. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/langchain/__init__.py +0 -0
  178. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/langchain/agent.py +0 -0
  179. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/langchain/call_tool_with_dataflow.py +0 -0
  180. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/langchain/database.py +0 -0
  181. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/langchain/middleware.py +0 -0
  182. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/langchain/schema.py +0 -0
  183. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/langchain/sql_validation.py +0 -0
  184. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/langchain/tool_spec.py +0 -0
  185. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/langchain/wrapper.py +0 -0
  186. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/options.py +0 -0
  187. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/planner.py +0 -0
  188. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/policy.py +0 -0
  189. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/tools/__init__.py +0 -0
  190. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/python/data_flow_control/tools/retry.py +0 -0
  191. {data_flow_control-0.2.0 → data_flow_control-0.2.1}/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.1"
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.1"
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.1"
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.1"
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.1
4
4
  Requires-Dist: duckdb>=1.3.0
5
5
  Requires-Dist: numpy>=1.24.4
6
6
  Requires-Dist: sqlglot==28.3.0
@@ -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,
@@ -144,6 +152,16 @@ pub(crate) fn replace_sink_columns(
144
152
  op,
145
153
  expr: Box::new(replace_sink_columns(*expr, sink, sink_expr_by_column)),
146
154
  },
155
+ Expr::IsNull(expr) => Expr::IsNull(Box::new(replace_sink_columns(
156
+ *expr,
157
+ sink,
158
+ sink_expr_by_column,
159
+ ))),
160
+ Expr::IsNotNull(expr) => Expr::IsNotNull(Box::new(replace_sink_columns(
161
+ *expr,
162
+ sink,
163
+ sink_expr_by_column,
164
+ ))),
147
165
  Expr::Case {
148
166
  operand,
149
167
  conditions,
@@ -238,6 +256,18 @@ fn replace_sink_columns_strict(
238
256
  ambiguous_output_columns,
239
257
  )?),
240
258
  }),
259
+ Expr::IsNull(expr) => Ok(Expr::IsNull(Box::new(replace_sink_columns_strict(
260
+ *expr,
261
+ sink,
262
+ sink_expr_by_column,
263
+ ambiguous_output_columns,
264
+ )?))),
265
+ Expr::IsNotNull(expr) => Ok(Expr::IsNotNull(Box::new(replace_sink_columns_strict(
266
+ *expr,
267
+ sink,
268
+ sink_expr_by_column,
269
+ ambiguous_output_columns,
270
+ )?))),
241
271
  Expr::Case {
242
272
  operand,
243
273
  conditions,
@@ -676,4 +706,122 @@ mod tests {
676
706
  );
677
707
  assert_eq!(expr.to_string(), "mt.\"OrderID\" > 1");
678
708
  }
709
+
710
+ #[test]
711
+ fn source_alias_replacement_descends_through_nested_null_tests() {
712
+ let aliases = HashMap::from([("src".to_string(), "receipts".to_string())]);
713
+ for (input, expected) in [
714
+ ("src.amount IS NULL", "receipts.amount IS NULL"),
715
+ ("src.amount IS NOT NULL", "receipts.amount IS NOT NULL"),
716
+ (
717
+ "NOT ((src.amount IS NULL) IS NOT NULL)",
718
+ "NOT ((receipts.amount IS NULL) IS NOT NULL)",
719
+ ),
720
+ (
721
+ "CASE WHEN src.amount IS NULL THEN src.id IS NOT NULL ELSE false END",
722
+ "CASE WHEN receipts.amount IS NULL THEN receipts.id IS NOT NULL ELSE false END",
723
+ ),
724
+ (
725
+ "coalesce(src.amount IS NOT NULL, false)",
726
+ "coalesce(receipts.amount IS NOT NULL, false)",
727
+ ),
728
+ ] {
729
+ assert_eq!(
730
+ replace_source_alias_qualifiers(parse_expr(input), &aliases),
731
+ parse_expr(expected),
732
+ "{input}"
733
+ );
734
+ }
735
+ }
736
+
737
+ #[test]
738
+ fn sink_replacement_descends_through_nested_null_tests() {
739
+ let columns = HashMap::from([("amount".to_string(), parse_expr("input.cost"))]);
740
+ for (input, expected) in [
741
+ ("reports.amount IS NULL", "input.cost IS NULL"),
742
+ ("reports.amount IS NOT NULL", "input.cost IS NOT NULL"),
743
+ (
744
+ "NOT ((reports.amount IS NOT NULL) IS NULL)",
745
+ "NOT ((input.cost IS NOT NULL) IS NULL)",
746
+ ),
747
+ (
748
+ "coalesce(reports.amount IS NULL, false)",
749
+ "coalesce(input.cost IS NULL, false)",
750
+ ),
751
+ ] {
752
+ assert_eq!(
753
+ replace_sink_columns(parse_expr(input), "reports", &columns),
754
+ parse_expr(expected),
755
+ "{input}"
756
+ );
757
+ }
758
+ }
759
+
760
+ #[test]
761
+ fn output_marker_replacement_descends_through_nested_null_tests() {
762
+ let columns = HashMap::from([("amount".to_string(), parse_expr("input.cost"))]);
763
+ for (input, expected) in [
764
+ ("_OUTPUT_.amount IS NULL", "input.cost IS NULL"),
765
+ ("_OUTPUT_.amount IS NOT NULL", "input.cost IS NOT NULL"),
766
+ (
767
+ "NOT ((_OUTPUT_.amount IS NULL) IS NOT NULL)",
768
+ "NOT ((input.cost IS NULL) IS NOT NULL)",
769
+ ),
770
+ (
771
+ "CASE WHEN _OUTPUT_.amount IS NULL THEN false ELSE _OUTPUT_.amount IS NOT NULL END",
772
+ "CASE WHEN input.cost IS NULL THEN false ELSE input.cost IS NOT NULL END",
773
+ ),
774
+ ] {
775
+ assert_eq!(
776
+ apply_output_marker_replacements(parse_expr(input), &columns, &HashSet::new())
777
+ .expect("valid output mapping"),
778
+ parse_expr(expected),
779
+ "{input}"
780
+ );
781
+ }
782
+ }
783
+
784
+ #[test]
785
+ fn nested_null_output_references_still_reject_ambiguity_and_missing_columns() {
786
+ let columns = HashMap::from([("amount".to_string(), parse_expr("input.cost"))]);
787
+ let ambiguous = HashSet::from(["amount".to_string()]);
788
+ for predicate in [
789
+ "_OUTPUT_.amount IS NULL",
790
+ "NOT ((_OUTPUT_.amount IS NOT NULL) IS NULL)",
791
+ ] {
792
+ let error =
793
+ apply_output_marker_replacements(parse_expr(predicate), &columns, &ambiguous)
794
+ .expect_err("ambiguous output must fail closed");
795
+ assert!(
796
+ error.to_string().contains("ambiguous _OUTPUT_ column"),
797
+ "{error}"
798
+ );
799
+ }
800
+ for predicate in [
801
+ "_OUTPUT_.missing IS NULL",
802
+ "NOT ((_OUTPUT_.missing IS NOT NULL) IS NULL)",
803
+ ] {
804
+ let error =
805
+ apply_output_marker_replacements(parse_expr(predicate), &columns, &HashSet::new())
806
+ .expect_err("missing output must fail closed");
807
+ assert!(
808
+ error.to_string().contains("not a projected output column"),
809
+ "{error}"
810
+ );
811
+ }
812
+ }
813
+
814
+ #[test]
815
+ fn null_replacements_preserve_unrelated_qualifiers() {
816
+ let columns = HashMap::from([("amount".to_string(), parse_expr("input.cost"))]);
817
+ let original = parse_expr("other.amount IS NULL OR other.amount IS NOT NULL");
818
+ assert_eq!(
819
+ replace_sink_columns(original.clone(), "reports", &columns),
820
+ original
821
+ );
822
+ assert_eq!(
823
+ apply_output_marker_replacements(original.clone(), &columns, &HashSet::new()).unwrap(),
824
+ original
825
+ );
826
+ }
679
827
  }
@@ -385,7 +385,7 @@ pub fn passant_kill_pass_filter(pass_expr: Expr) -> Expr {
385
385
  }
386
386
  }
387
387
 
388
- /// Tuple-resolution KILL filter: relation-level abort guard plus per-row pass filter.
388
+ /// Tuple-resolution KILL filter: relation-level abort guard plus legacy NULL filtering.
389
389
  ///
390
390
  /// DuckDB may invoke `passant_kill()` from the legacy per-row `pass OR CASE …` pattern even
391
391
  /// when every row passes; aggregating violations first avoids that.
@@ -413,7 +413,11 @@ pub fn passant_kill_tuple_filter(relation: &str, pass_column: &str) -> Expr {
413
413
  ),
414
414
  relation,
415
415
  );
416
- and_exprs(vec![violation_guard, pass_col]).expect("kill tuple filter is non-empty")
416
+ // Do not filter FALSE rows here: a constant FALSE filter can let the optimizer
417
+ // discard the entire candidate relation without evaluating the abort guard.
418
+ // Keep NULL filtering to preserve KILL's existing three-valued behavior.
419
+ and_exprs(vec![violation_guard, Expr::IsNotNull(Box::new(pass_col))])
420
+ .expect("kill tuple filter is non-empty")
417
421
  }
418
422
 
419
423
  pub fn string_concat(left: Expr, right: Expr) -> Expr {
@@ -0,0 +1,64 @@
1
+ //! FALSE must reach the relation-level abort; NULL retains legacy filtering.
2
+ #[path = "common/duckdb.rs"]
3
+ mod fixture;
4
+
5
+ use passant_core::sql::{passant_kill_tuple_filter, qualified_column};
6
+ use sqlparser::ast::{BinaryOperator, Expr};
7
+
8
+ #[test]
9
+ fn kill_tuple_guard_filters_only_null_not_false_candidates() {
10
+ let guard = passant_kill_tuple_filter("candidates", "pass");
11
+ let Expr::BinaryOp {
12
+ left,
13
+ op: BinaryOperator::And,
14
+ right,
15
+ } = &guard
16
+ else {
17
+ panic!("expected aggregate abort guard AND null filter: {guard}");
18
+ };
19
+ assert!(matches!(left.as_ref(), Expr::Subquery(_)), "{guard}");
20
+ assert_eq!(
21
+ right.as_ref(),
22
+ &Expr::IsNotNull(Box::new(qualified_column("candidates", "pass")))
23
+ );
24
+ let abort = left.to_string();
25
+ assert!(
26
+ abort.contains("max(CASE WHEN NOT candidates.pass THEN 1 ELSE 0 END)"),
27
+ "{abort}"
28
+ );
29
+ assert_eq!(abort.matches("passant_kill()").count(), 1);
30
+ }
31
+
32
+ #[test]
33
+ fn constant_false_kill_aborts_insert_without_changing_existing_rows() {
34
+ let db = fixture::TestDb::new();
35
+ db.exec("CREATE TABLE target(id INTEGER); INSERT INTO target VALUES (99)");
36
+ let guard = passant_kill_tuple_filter("candidates", "pass");
37
+ let sql = format!(
38
+ "INSERT INTO target WITH candidates AS (SELECT false AS pass) SELECT 7 FROM candidates WHERE {guard}"
39
+ );
40
+ let error = db
41
+ .conn
42
+ .execute_batch(&sql)
43
+ .expect_err("constant FALSE must not optimize away KILL");
44
+ assert!(
45
+ error
46
+ .to_string()
47
+ .contains("KILLing due to dfc policy violation"),
48
+ "{error}"
49
+ );
50
+ assert_eq!(db.fetchall_i64("SELECT id FROM target"), vec![99]);
51
+ }
52
+
53
+ #[test]
54
+ fn kill_null_candidates_keep_legacy_null_filtering() {
55
+ let db = fixture::TestDb::new();
56
+ let guard = passant_kill_tuple_filter("candidates", "pass");
57
+ let sql = format!(
58
+ "WITH candidates AS (SELECT NULL::BOOLEAN AS pass) SELECT 7 FROM candidates WHERE {guard}"
59
+ );
60
+ assert!(db.fetchall_i64(&sql).is_empty());
61
+ let sql =
62
+ format!("WITH candidates AS (SELECT true AS pass) SELECT 7 FROM candidates WHERE {guard}");
63
+ assert_eq!(db.fetchall_i64(&sql), vec![7]);
64
+ }
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "data-flow-control"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  description = "Rust-backed Data Flow Control rewrite engine"
5
5
  license = "MIT"
6
6
  license-files = ["LICENSE"]