diff options
| author | Rob B <73846016+robons@users.noreply.github.com> | 2023-01-29 15:50:07 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-01-29 16:50:07 +0100 |
| commit | c5c16dfafaf32dc46a06381a774822eb9be8cfbc (patch) | |
| tree | db8b55f88e5aeae4c35f0c721973331152a7b1aa /rdflib | |
| parent | fbb8279f0127e45cfa7741a9054de86284b795e7 (diff) | |
| download | rdflib-c5c16dfafaf32dc46a06381a774822eb9be8cfbc.tar.gz | |
fix: bug with `SELECT *` inside `SELECT *` (#2190)
Fixing use of `SELECT *` in sub-select within `SELECT *` parent query as discovered in https://github.com/RDFLib/rdflib/issues/1722.
Now when an instance of `SELECT *` is encountered, the query tree/plan builder now correctly considers the projected variables of any sub-select statements when deciding which variables should be projected out.
Fixes <https://github.com/RDFLib/rdflib/issues/1722>.
Diffstat (limited to 'rdflib')
| -rw-r--r-- | rdflib/plugins/sparql/algebra.py | 23 | ||||
| -rw-r--r-- | rdflib/plugins/sparql/evaluate.py | 1 |
2 files changed, 23 insertions, 1 deletions
diff --git a/rdflib/plugins/sparql/algebra.py b/rdflib/plugins/sparql/algebra.py index d538920e..923957b2 100644 --- a/rdflib/plugins/sparql/algebra.py +++ b/rdflib/plugins/sparql/algebra.py @@ -511,6 +511,7 @@ def _findVars(x, res: Set[Variable]) -> Optional[CompValue]: # type: ignore[ret elif x.name == "SubSelect": if x.projection: res.update(v.var or v.evar for v in x.projection) + return x @@ -637,6 +638,7 @@ def translate(q: CompValue) -> Tuple[CompValue, List[Variable]]: traverse(q.where, functools.partial(_findVars, res=VS)) # all query types have a where part + # depth-first recursive generation of mapped query tree M = translateGroupGraphPattern(q.where) aggregate = False @@ -679,6 +681,12 @@ def translate(q: CompValue) -> Tuple[CompValue, List[Variable]]: if not q.projection: # select * + + # Find the first child projection in each branch of the mapped query tree, + # then include the variables it projects out in our projected variables. + for child_projection in _find_first_child_projections(M): + VS |= set(child_projection.PV) + PV = list(VS) else: PV = list() @@ -731,6 +739,21 @@ def translate(q: CompValue) -> Tuple[CompValue, List[Variable]]: return M, PV +def _find_first_child_projections(M: CompValue) -> Iterable[CompValue]: + """ + Recursively find the first child instance of a Projection operation in each of + the branches of the query execution plan/tree. + """ + + for child_op in M.values(): + if isinstance(child_op, CompValue): + if child_op.name == "Project": + yield child_op + else: + for child_projection in _find_first_child_projections(child_op): + yield child_projection + + # type error: Missing return statement def simplify(n: Any) -> Optional[CompValue]: # type: ignore[return] """Remove joins to empty BGPs""" diff --git a/rdflib/plugins/sparql/evaluate.py b/rdflib/plugins/sparql/evaluate.py index 1ac1e6ef..aafd0fe7 100644 --- a/rdflib/plugins/sparql/evaluate.py +++ b/rdflib/plugins/sparql/evaluate.py @@ -543,7 +543,6 @@ def evalDistinct( def evalProject(ctx: QueryContext, project: CompValue): res = evalPart(ctx, project.p) - return (row.project(project.PV) for row in res) |
