|
122 | 122 | rewrite_temporal_constructors_in_expr, |
123 | 123 | ) |
124 | 124 | from graphistry.compute.gfql.same_path_types import WhereComparison, col, compare |
125 | | -# #1295 / #1260 S2 — bounded reentry helpers extracted to focused subpackage. |
126 | | -# These are re-exported here to keep existing imports |
127 | | -# (``from graphistry.compute.gfql.cypher.lowering import _reentry_hidden_column_name``) |
128 | | -# working unchanged across the codebase. The moved modules import this module |
129 | | -# lazily inside function bodies for the few helpers (``_unsupported``, |
130 | | -# ``_render_expr_node``, etc.) they still need from lowering.py. |
| 125 | +# Reentry helpers moved to focused subpackages and are re-exported here for compatibility. |
131 | 126 | from graphistry.compute.gfql.cypher.reentry.naming import ( |
132 | 127 | _is_hidden_reentry_property, |
133 | 128 | _reentry_hidden_column_name, |
@@ -5637,12 +5632,7 @@ def _is_variable_length_relationship_pattern(relationship: RelationshipPattern) |
5637 | 5632 |
|
5638 | 5633 |
|
5639 | 5634 | def _reject_nonterminal_variable_length_relationship_patterns(query: CypherQuery) -> None: # noqa: ARG001 |
5640 | | - """No-op: variable-length rels in connected patterns are now supported. |
5641 | | -
|
5642 | | - The lowering sets ``prune_to_endpoints=True`` on non-terminal |
5643 | | - variable-length edges so the next hop starts from the correct |
5644 | | - wavefront endpoints only. See #1001 for reentry-match follow-up. |
5645 | | - """ |
| 5635 | + """No-op: variable-length relationships in connected patterns are supported.""" |
5646 | 5636 |
|
5647 | 5637 |
|
5648 | 5638 | def _variable_length_relationship_aliases( |
@@ -6231,9 +6221,19 @@ def lower_match_query( |
6231 | 6221 | row_where: Optional[ExpressionText] = None |
6232 | 6222 | row_where_predicates: List[str] = list(dynamic_row_where_predicates) |
6233 | 6223 | if query.where is not None: |
6234 | | - where_expr_upper = boolean_expr_to_text(query.where.expr_tree).upper() if query.where.expr_tree is not None else "" |
6235 | | - if _cartesian_node_only_patterns(merged_match) is not None and query.where.expr_tree is not None and _where_expr_tree_pattern_predicates(query.where.expr_tree) and (" OR " in where_expr_upper or " XOR " in where_expr_upper): |
6236 | | - raise _unsupported_at_span("Cypher WHERE pattern predicates mixed with OR/XOR are not yet supported for cartesian MATCH patterns", field="where", value=where_expr_upper, span=query.where.span) |
| 6224 | + if _cartesian_node_only_patterns(merged_match) is not None and query.where.expr_tree is not None: |
| 6225 | + where_expr_upper = boolean_expr_to_text(query.where.expr_tree).upper() |
| 6226 | + stack: List[BooleanExpr] = [query.where.expr_tree] |
| 6227 | + while stack: |
| 6228 | + cur = stack.pop() |
| 6229 | + left = cast(Optional[BooleanExpr], cur.left) |
| 6230 | + right = cast(Optional[BooleanExpr], cur.right) |
| 6231 | + if cur.op in {"or", "xor"} and ((left is not None and _where_expr_tree_pattern_predicates(left)) or (right is not None and _where_expr_tree_pattern_predicates(right))): |
| 6232 | + raise _unsupported_at_span("Cypher WHERE pattern predicates mixed with OR/XOR are not yet supported for cartesian MATCH patterns", field="where", value=where_expr_upper, span=query.where.span) |
| 6233 | + if left is not None: |
| 6234 | + stack.append(left) |
| 6235 | + if right is not None: |
| 6236 | + stack.append(right) |
6237 | 6237 | where_expr, where_pattern_row_filters = _rewrite_where_expr_patterns_to_markers( |
6238 | 6238 | where=query.where, |
6239 | 6239 | alias_targets=alias_targets, |
|
0 commit comments