Compiled Cypher: a CALL subquery sees every outer variable, so an inner MATCH reusing an outer name joins to it instead of binding a new one
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
调研方向
Start with drivine/cypher/ast/clause.py:83 and drivine/cypher/cypher_reader.py:226, then trace _called_part and _call_writing in drivine/cypher/sql/sql_cypher_compiler.py. Port the listed cross-engine tests and the five statements in CompilerRefusalTest; done means CALL subqueries see only their imports while procedure calls retain access to the whole row.
由索引模型根据 Issue 内容生成。
描述
Port of liberation-data/drivine4j#410.
What happens here now. A compiled CALL { … } sees every variable of the row it is in, whatever it imports, so an inner MATCH that reuses an outer name joins to the outer variable instead of binding a new one:
MATCH (p:Person) CALL { MATCH (p:Movie) RETURN count(p) AS n } RETURN p.name, n
// Neo4j: 3 for each person Postgres, Oracle, SQLite: 0
MATCH (a:Person {name: 'Keanu'}) CALL { MATCH ()-[a:KNOWS]->() RETURN count(a) AS n } RETURN a.name, n
// Neo4j: Keanu, 2 here: refused as "a relationship variable bound before its pattern"
MATCH (a:N) CALL () { CREATE (a:N {made: true}) RETURN 1 AS x } RETURN x
// Neo4j: makes a new node for each row here: refused as bound already (without labels: joins the row's a and makes nothing)
Where:
drivine/cypher/ast/clause.py:83:Callkeeps no import list, anddrivine/cypher/cypher_reader.py:226drops the brackets ofCALL (a, b) { … },CALL () { … }andCALL (*) { … }.drivine/cypher/sql/sql_cypher_compiler.py:1496(_called_part): the inner query is_Select(select.scope), every variable of the row (line 1503),_imports_apartgets the whole scope (line 1504), and each clause is read withselect.scopeas its outer scope (line 1511), so a variable stays seen even after aWITHwithin the call that doesn't pass it on.drivine/cypher/sql/sql_cypher_compiler.py:2373(_call_writing):self._rows()binds every variable of the row, and_imported()(line 5957) drops a leading importingWITHwithout narrowing to what it names.
What the fix in drivine4j does (liberation-data/drivine4j#410):
- keeps the brackets in the AST (
imports,importsAll, from drivine4j#451); - works out what a CALL imports: its brackets' names, each with
(*), none with(); with no brackets, the variables its leadingWITHpasses on as they are, each withWITH *, and none where it has no leadingWITH; calledPart(_called_parthere) builds the call's query over the imported variables alone, givesimportsApartonly those, and reads its clauses with no outer scope, so an import aWITHin the call doesn't pass on is gone after it;callWriting(_call_writinghere) narrows the row's kinds to the imports before reading each row, and skips the leadingWITHonly where it passes on each import;- a procedure's
CALL db.labels() YIELD label WHERE …still sees the whole row, as itsWHEREmay read any variable around it (aprocedureflag on the call).
Every spec statement and TCK query compiled to the same SQL before and after on each store there.
Tests to port: drivine4j's CypherQueryCrossEngineTest "a CALL sees only the variables it imports, and a name it does not import is a new variable in it", CypherWriteCrossEngineTest "a CALL that writes sees only the variables it imports, so a CREATE of a name it does not import makes a new node", and the five #410 statements added to the accepted list in CompilerRefusalTest (two moved there from the refused list). Rows are Neo4j 2026.10's.
- 主要语言
- Python
- 星标
- 1
- 派生
- 0
- 平均合并
- 1 小时 29 分钟
- 30 天内合并 PR
- 136
环境准备
这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
liberation-data/drivine-python 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 78/100
liberation-data/drivine-python#250 ·
维护者通常 1 天内回复
-
bug
难度 1/5 1 小时以内 新手友好度 88/100
liberation-data/drivine-python#209 ·
维护者通常 1 天内回复
-
CI: three Oracle-only tests in test_cypher_compiled.py never run, as -k oracle doesn't select them未关闭
难度 1/5 1 小时以内 新手友好度 88/100
liberation-data/drivine-python#178 ·
维护者通常 1 天内回复
-
bug
难度 4/5 3-5 天 新手友好度 55/100
liberation-data/drivine-python#297 ·
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 55/100
liberation-data/drivine-python#295 ·
维护者通常 1 天内回复
查看 liberation-data/drivine-python 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 82/100
维护者通常 1 天内回复
-
namespace operations
难度 1/5 1 小时以内 新手友好度 65/100
EclipseFdn/open-vsx.org#15057 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 76/100
FinanceFlash/unvibecode#349 ·
-
Mission statement: why this is free, in the README, Why This Exists and the wiki Home可能已有人在做 @ChiefGyk3D 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 76/100
ChiefGyk3D/Clouds-Against-Humanity#348 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 74/100
vllm-project/vime#508 ·
维护者通常 4 天内回复