Fix single-node labeled pattern expressions not filtering by label (#2443)#2444
Open
gregfelice wants to merge 1 commit into
Open
Fix single-node labeled pattern expressions not filtering by label (#2443)#2444gregfelice wants to merge 1 commit into
gregfelice wants to merge 1 commit into
Conversation
…pache#2443) A single-node labeled pattern used as a boolean expression -- e.g. `WHERE (a:Person)`, `WHERE EXISTS((a:Person))` -- was accepted but did not test the bound vertex's label. It desugars to an EXISTS sub-pattern, and make_path_join_quals() returned early for vertex-only patterns (list_length(entities) < 3), emitting no quals. With no edge to carry a correlation, the sub-pattern referenced nothing from the enclosing query, so the planner produced an uncorrelated one-time InitPlan that was trivially true whenever any vertex of that label existed -- the predicate matched every outer row. Emit an explicit label-id filter for a vertex-only pattern whose vertex carries a non-default label and whose variable is declared in an ancestor parse state (i.e. a correlated reference). make_qual() builds a name-based id reference that resolves to the outer variable, so the filter both correlates the sub-pattern to that variable and enforces the label. Freshly scanned, non-correlated vertices (no ancestor binding) are untouched, so plain MATCH (a:Person) and "does any X exist" EXISTS checks are unaffected. Add regression coverage in pattern_expression: WHERE (a:Person), WHERE NOT (a:Person), and EXISTS((a:Company)) against a graph with a non-Person vertex. All 41 regression tests pass.
464ed50 to
9c2c441
Compare
Contributor
Author
|
Ready for review.
Fixes #2443. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A single-node labeled pattern used as a boolean expression — e.g.
WHERE (a:Person)orWHERE EXISTS((a:Person))— is accepted but does not test the bound vertex's label. It evaluates as trivially true, so the predicate matches every row.Repro (on
master):Root cause
A single-node pattern expression desugars to an
EXISTSsub-pattern.make_path_join_quals()returns early for vertex-only patterns (list_length(entities) < 3), emitting no quals. With no edge to carry a correlation, the sub-pattern references nothing from the enclosing query, so the planner produces an uncorrelated one-time InitPlan that is true whenever any vertex of that label exists — independent of the outer row.Relationship patterns are unaffected: the edge-driven join (
start_id = a.id) correlates them to the outer variable, which is whyWHERE (a)-[:R]->(b)works correctly.EXPLAINbefore the fix — uncorrelatedInitPlanwith aOne-Time Filter:After the fix — correlated
SubPlanreferencing the outera_1:Fix
In
make_path_join_quals(), for a vertex-only pattern whose vertex carries a non-default label and whose variable is declared in an ancestor parse state (a correlated reference), emit an explicit label-id filter.make_qual()builds a name-based id reference that resolves to the outer variable, so the filter both correlates the sub-pattern to that variable and enforces the label.Freshly scanned, non-correlated vertices (no ancestor binding) are untouched, so
MATCH (a:Person)and "does any X exist"EXISTSchecks behave exactly as before.Testing
Added regression coverage to
pattern_expressionagainst a graph containing a non-Personvertex:WHERE (a:Person)→ only the:PersonverticesWHERE NOT (a:Person)→ only the non-PersonvertexWHERE EXISTS((a:Company))→ only the:CompanyvertexAll 41 regression tests pass (
make installcheck).Note
RETURN (a:Label)in a projection on an unlabeled bound variable still errors with "multiple labels for variable" — that is a separate, pre-existing guard, orthogonal to this fix, and is intentionally left unchanged.Fixes #2443