Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using the result of a SPARQL query with EXISTS and AS raises an exception #1472

Closed
ghost opened this issue Nov 18, 2021 · 10 comments · Fixed by #1794
Closed

Using the result of a SPARQL query with EXISTS and AS raises an exception #1472

ghost opened this issue Nov 18, 2021 · 10 comments · Fixed by #1794
Assignees
Labels
bug Something isn't working SPARQL

Comments

@ghost
Copy link

ghost commented Nov 18, 2021

import rdflib

QUERY = """
    SELECT * {
        BIND(
            EXISTS {
                <http://example.com/a>
                <http://example.com/b>
                <http://example.com/c>
            }
            AS ?exists
        )
    }
"""
graph = rdflib.Graph()
result = graph.query(QUERY)
for row in result:
    print(row)

ought to print

(rdflib.term.Literal('false', datatype=rdflib.term.URIRef('http://www.w3.org/2001/XMLSchema#boolean')),)

This result would agree with that of SPARQL playground. Instead, the following exception is raised.

Exception: What do I do with this CompValue? GroupGraphPatternSub_GroupGraphPatternSub_{'part': [TriplesBlock_{'triples': [[rdflib.term.URIRef('http://example.com/a'), rdflib.term.URIRef('http://example.com/b'), rdflib.term.URIRef('http://example.com/c')]], '_vars': set()}], '_vars': set()}

I observed this bug under the following conditions.

  • Ubuntu 20.04
  • Python 3.9.5
  • rdflib 6.0.2
@ghost ghost added the bug Something isn't working label Nov 18, 2021
@ghost
Copy link

ghost commented Nov 18, 2021

Technically it's “unhandled” (as indicated by the output) rather than a bug per se but the difference is moot.

FWIW, the RDFLib SPARQL test suite shows a basic use of EXISTS in the context of a FILTER (as opposed to a BIND):
SELECT ?l WHERE { GRAPH ex:g1 { ?a rdfs:label ?l } FILTER EXISTS { ?a a ?type }}
and the venerable SPARQL cheatsheet would seem to accord with this use pattern. Sorry can't be of more help.

@ghost
Copy link
Author

ghost commented Nov 19, 2021

@gjhiggins, FILTER EXISTS has a different meaning. Using EXISTS and BIND as I did conforms to W3C's grammar for SPARQL.

row symbol ::= expression
[60] Bind ::= 'BIND' '(' Expression 'AS' Var ')'
[110] Expression ::= ConditionalOrExpression
[111] ConditionalOrExpression ::= ConditionalAndExpression ( '||' ConditionalAndExpression )*
[112] ConditionalAndExpression ::= ValueLogical ( '&&' ValueLogical )*
[113] ValueLogical ::= RelationalExpression
[114] RelationalExpression ::= NumericExpression ( '=' NumericExpression | '!=' NumericExpression | '<' NumericExpression | '>' NumericExpression | '<=' NumericExpression | '>=' NumericExpression | 'IN' ExpressionList | 'NOT' 'IN' ExpressionList )?
[115] NumericExpression ::= AdditiveExpression
[116] AdditiveExpression ::= MultiplicativeExpression ( '+' MultiplicativeExpression | '-' MultiplicativeExpression | ( NumericLiteralPositive | NumericLiteralNegative ) ( ( '*' UnaryExpression ) | ( '/' UnaryExpression ) )* )*
[117] MultiplicativeExpression ::= UnaryExpression ( '*' UnaryExpression | '/' UnaryExpression )*
[118] UnaryExpression ::= '!' PrimaryExpression | '+' PrimaryExpression | '-' PrimaryExpression | PrimaryExpression
[119] PrimaryExpression ::= BrackettedExpression | BuiltInCall | iriOrFunction | RDFLiteral | NumericLiteral | BooleanLiteral | Var
[121] BuiltInCall ::= Aggregate | 'STR' '(' Expression ')' | 'LANG' '(' Expression ')' | 'LANGMATCHES' '(' Expression ',' Expression ')' | 'DATATYPE' '(' Expression ')' | 'BOUND' '(' Var ')' | 'IRI' '(' Expression ')' | 'URI' '(' Expression ')' | 'BNODE' ( '(' Expression ')' | NIL ) | 'RAND' NIL | 'ABS' '(' Expression ')' | 'CEIL' '(' Expression ')' | 'FLOOR' '(' Expression ')' | 'ROUND' '(' Expression ')' | 'CONCAT' ExpressionList | SubstringExpression | 'STRLEN' '(' Expression ')' | StrReplaceExpression | 'UCASE' '(' Expression ')' | 'LCASE' '(' Expression ')' | 'ENCODE_FOR_URI' '(' Expression ')' | 'CONTAINS' '(' Expression ',' Expression ')' | 'STRSTARTS' '(' Expression ',' Expression ')' | 'STRENDS' '(' Expression ',' Expression ')' | 'STRBEFORE' '(' Expression ',' Expression ')' | 'STRAFTER' '(' Expression ',' Expression ')' | 'YEAR' '(' Expression ')' | 'MONTH' '(' Expression ')' | 'DAY' '(' Expression ')' | 'HOURS' '(' Expression ')' | 'MINUTES' '(' Expression ')' | 'SECONDS' '(' Expression ')' | 'TIMEZONE' '(' Expression ')' | 'TZ' '(' Expression ')' | 'NOW' NIL | 'UUID' NIL | 'STRUUID' NIL | 'MD5' '(' Expression ')' | 'SHA1' '(' Expression ')' | 'SHA256' '(' Expression ')' | 'SHA384' '(' Expression ')' | 'SHA512' '(' Expression ')' | 'COALESCE' ExpressionList | 'IF' '(' Expression ',' Expression ',' Expression ')' | 'STRLANG' '(' Expression ',' Expression ')' | 'STRDT' '(' Expression ',' Expression ')' | 'sameTerm' '(' Expression ',' Expression ')' | 'isIRI' '(' Expression ')' | 'isURI' '(' Expression ')' | 'isBLANK' '(' Expression ')' | 'isLITERAL' '(' Expression ')' | 'isNUMERIC' '(' Expression ')' | RegexExpression | ExistsFunc | NotExistsFunc
[125] ExistsFunc ::= 'EXISTS' GroupGraphPattern

@ghost
Copy link

ghost commented Nov 19, 2021

I didn't mean to imply that you were wrong and I'm sorry if I gave that impression. The TL;DR on this is basically “Thanks for drawing our attention to this, it will get added to the maintenance TODO list but I couldn't even venture a guess as to when it might get fixed, hope you can find a workaround in the interim.” Thanks for posting the spec, that's useful.

@ghost
Copy link
Author

ghost commented Nov 19, 2021

@gjhiggins, thank you.

@ghost
Copy link
Author

ghost commented Nov 19, 2021

Trying to work around the bug, I have found another manifestation thereof.

import rdflib

QUERY = """
    SELECT (
        EXISTS {
            <http://example.com/a>
            <http://example.com/b>
            <http://example.com/c>
        }
        AS ?exists
    )
    {}
"""
graph = rdflib.Graph()
result = graph.query(QUERY)
for row in result:
    print(row)

ought to print

(rdflib.term.Literal('false', datatype=rdflib.term.URIRef('http://www.w3.org/2001/XMLSchema#boolean')),)

Instead the following exception is raised.

Exception: What do I do with this CompValue? GroupGraphPatternSub_GroupGraphPatternSub_{'part': [TriplesBlock_{'triples': [[rdflib.term.URIRef('http://example.com/a'), PathAlternative_{'part': [PathSequence_{'part': [PathElt_{'part': rdflib.term.URIRef('http://example.com/b'), '_vars': set()}], '_vars': set()}], '_vars': set()}, rdflib.term.URIRef('http://example.com/c')]], '_vars': set()}], '_vars': set()}

@ghost
Copy link

ghost commented Nov 19, 2021

Thanks for helping to clarify the scope of the issue. The Exception makes sense given that RDFLib only recognises EXISTS in a FILTER context.

@amediantsev
Copy link

amediantsev commented Dec 2, 2021

@gjhiggins Hi. I encountered the same problem in my work. I want to ask, maybe could you recommend some temporary workaround. Also, could you share if you have some progress on that?
Thanks a lot.

@ghost ghost added the SPARQL label Dec 23, 2021
@mgberg
Copy link
Contributor

mgberg commented Jan 10, 2022

I'm also running into this issue. Hoping there will be a fix in the somewhat near future.

@aucampia aucampia self-assigned this Jan 25, 2022
@aucampia aucampia closed this as completed Feb 2, 2022
@aucampia aucampia reopened this Feb 2, 2022
@ghost ghost changed the title Using a SPARQL result raises an exception when it ought not to Using the result of a SPARQL query with EXISTS raises an exception Feb 8, 2022
@ghost ghost changed the title Using the result of a SPARQL query with EXISTS raises an exception Using the result of a SPARQL query with EXISTS and AS raises an exception Feb 8, 2022
aucampia added a commit to aucampia/rdflib that referenced this issue Apr 9, 2022
This patch fixes an issue with `BIND( EXISTS ... )` in SPARQL,
for example:

```sparql
SELECT * WHERE {
    BIND(
	EXISTS {
	    <http://example.com/a>
	    <http://example.com/b>
	    <http://example.com/c>
	}
	AS ?bound
    )
}
```

The graph pattern of `EXISTS` needs to be translated for it to operate
correctly during evaluation, but this was not happening. This patch
corrects that so that the graph pattern is translated as part of
translating `BIND`.

This patch also adds a bunch of tests for EXISTS to ensure there is no
regression and that various EXISTS cases function correctly.

Fixes RDFLib#1472
aucampia added a commit to aucampia/rdflib that referenced this issue Apr 9, 2022
This patch fixes an issue with `BIND( EXISTS ... )` in SPARQL,
for example:

```sparql
SELECT * WHERE {
    BIND(
	EXISTS {
	    <http://example.com/a>
	    <http://example.com/b>
	    <http://example.com/c>
	}
	AS ?bound
    )
}
```

The graph pattern of `EXISTS` needs to be translated for it to operate
correctly during evaluation, but this was not happening. This patch
corrects that so that the graph pattern is translated as part of
translating `BIND`.

This patch also adds a bunch of tests for EXISTS to ensure there is no
regression and that various EXISTS cases function correctly.

Fixes RDFLib#1472
@aucampia
Copy link
Member

aucampia commented Apr 9, 2022

@mgberg @JDawson-Camlin @amediantsev PR to fix this is here: #1794 - please review if you feel comfortable doing so.

aucampia added a commit to aucampia/rdflib that referenced this issue Apr 13, 2022
This patch fixes an issue with `BIND( EXISTS ... )` in SPARQL,
for example:

```sparql
SELECT * WHERE {
    BIND(
	EXISTS {
	    <http://example.com/a>
	    <http://example.com/b>
	    <http://example.com/c>
	}
	AS ?bound
    )
}
```

The graph pattern of `EXISTS` needs to be translated for it to operate
correctly during evaluation, but this was not happening. This patch
corrects that so that the graph pattern is translated as part of
translating `BIND`.

This patch also adds a bunch of tests for EXISTS to ensure there is no
regression and that various EXISTS cases function correctly.

Fixes RDFLib#1472
aucampia added a commit to aucampia/rdflib that referenced this issue Apr 15, 2022
This patch fixes an issue with `BIND( EXISTS ... )` in SPARQL,
for example:

```sparql
SELECT * WHERE {
    BIND(
	EXISTS {
	    <http://example.com/a>
	    <http://example.com/b>
	    <http://example.com/c>
	}
	AS ?bound
    )
}
```

The graph pattern of `EXISTS` needs to be translated for it to operate
correctly during evaluation, but this was not happening. This patch
corrects that so that the graph pattern is translated as part of
translating `BIND`.

This patch also adds a bunch of tests for EXISTS to ensure there is no
regression and that various EXISTS cases function correctly.

Fixes RDFLib#1472
@ghost
Copy link
Author

ghost commented Sep 16, 2022

@mgberg @JDawson-Camlin @amediantsev PR to fix this is here: #1794 - please review if you feel comfortable doing so.

@aucampia, the PR fixes the first manifestation of the bug, but not the second.

import rdflib

QUERY = """
    SELECT (
        EXISTS {
            <http://example.com/a>
            <http://example.com/b>
            <http://example.com/c>
        }
        AS ?exists
    )
    {}
"""
graph = rdflib.Graph()
result = graph.query(QUERY)
for row in result:
    print(row)

ought to print

(rdflib.term.Literal('false', datatype=rdflib.term.URIRef('http://www.w3.org/2001/XMLSchema#boolean')),)

Instead the following exception is raised.

Exception: What do I do with this CompValue? GroupGraphPatternSub_GroupGraphPatternSub_{'part': [TriplesBlock_{'triples': [[rdflib.term.URIRef('http://example.com/a'), PathAlternative_{'part': [PathSequence_{'part': [PathElt_{'part': rdflib.term.URIRef('http://example.com/b'), '_vars': set()}], '_vars': set()}], '_vars': set()}, rdflib.term.URIRef('http://example.com/c')]], '_vars': set()}], '_vars': set()}

This issue ought to be reopened.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working SPARQL
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants