virtuoso-opensource icon indicating copy to clipboard operation
virtuoso-opensource copied to clipboard

SELECT query with VALUES, BIND, and EXISTS clauses doesn't always work

Open FerrariAndrea opened this issue 4 years ago • 7 comments

Hi, I need to use query like this:

SELECT ?x ?i {
VALUES (?g ?s ?p ?o ?i) { 
   (<g><s> <p> "literal" 0)
   (<g><s> <p> <o> 1)
}
BIND(EXISTS{ GRAPH ?g {?s ?p ?o} } AS ?x )}

This query should return ?x as boolean, which is true if the quad exists in the KB, and return ?i as integer used as an index.

The query seam has some problem, sometimes the result of ?x is not correct, I have found an example to show:

On a void KB we can populate it through this update: INSERT DATA { GRAPH <g> { <s> <p> <o>. <s1> <p1> <o1>. <s1> <p2> "literal"}}

Check KB: image

If we try the query now, it's work as well: image

The quads ?i=0 and ?i=2 exist on KB.

Now, if we remove the quads <g> <s> <p> <o> and <g> <s1> <p1> <o1> from the KB the query does not work anymore.

image

The same query, now return ?x=0 for ?i=0, but we know that the quads <s1> <p2> "literal" (?i=0) exist on KB, and so the ?x should be 1 and not 0 for ?i=0.

image

I m using: OpenLink Virtuoso Interactive SQL (Virtuoso) Version 07.20.3229 as of Aug 21 2019

Thanks for your help.

FerrariAndrea avatar Dec 16 '20 08:12 FerrariAndrea

Can you provide the text of the queries being run, rather than screenshots? Using the Virtuoso "isql" command line tool is also preferable as then you can simply copy and paste query and results as verbatim text ...

I would also suggest repeating your tests against the Virtuoso develop/7 branch with all the latest updates/fixes ...

HughWilliams avatar Dec 16 '20 13:12 HughWilliams

I don't find isql tool, I m using the web site 'http://localhost:8890/sparql/' to do this test, I hope the results as json goes well anyway.

SPARQL example to replicate the mistake:

  1. initial query for check KB state in graph (it is void)

    SELECT * { GRAPH <g> { ?s ?p ?o }}
    

    Json result:

    { "head": { "link": [], "vars": ["s", "p", "o"] },
    "results": { "distinct": false, "ordered": true, "bindings": [ ] } } 
    
  2. Update for popolate graph <g>

    INSERT DATA { GRAPH <g> { <s1> <p1> <o1> . <s2> <p2> "literal" .}}
    
  3. check state:

    SELECT * { GRAPH <g> { ?s ?p ?o }}
    

    Json result:

    { "head": { "link": [], "vars": ["s", "p", "o"] },
       "results": { "distinct": false, "ordered": true, "bindings": [
        { "s": { "type": "uri", "value": "s1" }	, "p": { "type": "uri", "value": "p1" }	, "o": { "type": "uri", "value": "o1" }},
        { "s": { "type": "uri", "value": "s2" }	, "p": { "type": "uri", "value": "p2" }	, "o": { "type": "literal", "value": "literal" }} ] } }
    
  4. if I request now the query, it has the right result

    SELECT ?x ?i {
    VALUES (?g ?s ?p ?o ?i) { 
       (<g><s1> <p1> <o1> 0)
       (<g><s2> <p2> "literal" 1)
       (<g><s3> <p3> "otherLiteral" 2)
       (<g><s4> <p4> <4> 3)
    }
    BIND(EXISTS{ GRAPH ?g {?s ?p ?o} } AS ?x )}
    

    Json result:

    { "head": { "link": [], "vars": ["x", "i"] },
      "results": { "distinct": false, "ordered": true, "bindings": [
        { "x": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "1" }	, "i": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "0" }},
        { "x": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "1" }	, "i": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "1" }},
        { "x": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "0" }	, "i": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "2" }},
        { "x": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "0" }	, "i": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "3" }} ] } }
    

the first 2 quad exist so ?x=1 (for ?i=0 and ?i=1), the third and fourth not exist so ?x=0 (for ?i=2 and ?i=3).

  1. now we remove the quad <g><s1> <p1> <o1>

    DELETE DATA { GRAPH <g> { <s1> <p1> <o1> }}
    
  2. query for check

    SELECT * { GRAPH <g> { ?s ?p ?o }}
    

    json result

    { "head": { "link": [], "vars": ["s", "p", "o"] },
      "results": { "distinct": false, "ordered": true, "bindings": [
        { "s": { "type": "uri", "value": "s2" }	, "p": { "type": "uri", "value": "p2" }	, "o": { "type": "literal", "value": "literal" }} ] } }
    
  3. if we do now the same query of step 4, the result is not correct:

    SELECT ?x ?i {
    VALUES (?g ?s ?p ?o ?i) { 
       (<g><s1> <p1> <o1> 0)
       (<g><s2> <p2> "literal" 1)
       (<g><s3> <p3> "otherLiteral" 2)
       (<g><s4> <p4> <4> 3)
    }
    BIND(EXISTS{ GRAPH ?g {?s ?p ?o} } AS ?x )}
    

    Json result

    { "head": { "link": [], "vars": ["x", "i"] },
      "results": { "distinct": false, "ordered": true, "bindings": [
        { "x": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "0" }	, "i": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "0" }},
        { "x": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "0" }	, "i": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "1" }},
        { "x": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "0" }	, "i": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "2" }},
        { "x": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "0" }	, "i": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "3" }} ] } }
    

how we can see, all 4 quad result with ?x=0 so all 4 quad fail the EXISTS clause, but we know that the second one (?i=1) exist, so ?x need be set as 1 for ?i=1.

  1. Now we can execute this query too:

    SELECT ?x ?i {
    VALUES (?g ?s ?p ?o ?i) { 
       (<g><s2> <p2> "literal" 1)
    }
    BIND(EXISTS{ GRAPH ?g {?s ?p ?o} } AS ?x )}
    

    And this returns the expected result:

    { "head": { "link": [], "vars": ["x", "i"] },
      "results": { "distinct": false, "ordered": true, "bindings": [
        { "x": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "1" }	, "i": { "type": "typed-literal", "datatype": "http://www.w3.org/2001/XMLSchema#integer", "value": "1" }} ] } }
    

?i=1 and ?x=1, so the EXISTS clause of the query now is passed for the quad ?i=1. I think it is not coherent behavior.

For now, to try this test on the branch develop/7 of Virtuoso, I have some difficulty to install and set it, I will try again later.

FerrariAndrea avatar Dec 17 '20 09:12 FerrariAndrea

I m using the docker version on Windows, and it does not want to update at the last one.

After removing the image with docker rmi ID i run these commands:

C:\Users\TSG>docker pull tenforce/virtuoso:virtuoso7.2.5
virtuoso7.2.5: Pulling from tenforce/virtuoso
f7277927d38a: Pull complete
8d3eac894db4: Pull complete
edf72af6d627: Pull complete
3e4f86211d23: Pull complete
67ab69da6680: Pull complete
b2d8833ed71b: Pull complete
264135e83a4f: Pull complete
a46e9545daf5: Pull complete
026597218a5a: Pull complete
Digest: sha256:de97286328aa0babb9e06e9626321d91363ba3f260529b9083d1fa02f36ad664
Status: Downloaded newer image for tenforce/virtuoso:virtuoso7.2.5
docker.io/tenforce/virtuoso:virtuoso7.2.5

C:\Users\TSG>docker images
REPOSITORY          TAG             IMAGE ID       CREATED         SIZE
tenforce/virtuoso   virtuoso7.2.5   dbf707c11d6d   16 months ago   246MB

But in the console of Virtuoso I see any way the older version:

Converting environment variables to ini file
Finished converting environment variables to ini file
Thu Dec 17 2020
09:43:52 OpenLink Virtuoso Universal Server
09:43:52 Version 07.20.3229-pthreads for Linux as of Aug 21 2019
09:43:52 uses parts of OpenSSL, PCRE, Html Tidy
09:43:52 Database version 3126
09:43:52 SQL Optimizer enabled (max 1000 layouts)
09:43:53 Compiler unit is timed at 0.000103 msec
09:43:54 Roll forward started
09:43:54 Roll forward complete
09:43:54 Checkpoint started
09:43:54 Checkpoint finished, log reused
09:43:54 HTTP/WebDAV server online at 8890
09:43:54 Server online at 1111 (pid 1)

Maybe is just the tag of the version which is wrong?

FerrariAndrea avatar Dec 17 '20 09:12 FerrariAndrea

The Virtuoso isql command line tool is a standard program shipped with every Virtuoso server or client installation.

'http://localhost:8890/sparql/' is not a web site; it is the Virtuoso default SPARQL endpoint for SPARQL query execution via HTTP.

Note, the "tenforce" docker image is not the official OpenLink Virtuoso docker image, which is available from here and has a much more recent develop/7 build, if docker is what you want to use ...

HughWilliams avatar Dec 29 '20 08:12 HughWilliams

Thx, Now i'm using plain version 1.1.3230 from OpenLink Software. I found the ISQL and I repeat all the SPARQL update and query of this topic. with the same results and same issues. ( I don t found any Copy buttons in ISQL, I just select and then copied the HTML )

  1. SPARQL SELECT * { GRAPH <g> { ?s ?p ?o }}
Query result:
--
sANY | pANY | oANY
No. of rows in result: 0
  1. SPARQL INSERT DATA { GRAPH { . "literal" .}}
Query result:
--
callret-0ANY
Insert into <g>, 2 (or less) triples -- done
No. of rows in result: 1
  1. SPARQL SELECT * { GRAPH <g> { ?s ?p ?o }}

--
Query result:sANYpANYoANY s1 p1 o1 s2 p2 literalNo. of rows in result: 2 | Query result: | sANY | pANY | oANY | s1 | p1 | o1 | s2 | p2 | literal | No. of rows in result: 2
Query result:
sANY | pANY | oANY
s1 | p1 | o1
s2 | p2 | literal
No. of rows in result: 2

   4) SPARQL SELECT ?x ?i { VALUES (?g ?s ?p ?o ?i) { (<g><s1> <p1> <o1> 0) (<g><s2> <p2> "literal" 1) (<g><s3> <p3> "otherLiteral" 2) (<g><s4> <p4> <4> 3) } BIND(EXISTS{ GRAPH ?g {?s ?p ?o} } AS ?x )}

--
Query result:xINTEGERiANY 1 0 1 1 0 2 0 3No. of rows in result: 4 | Query result: | xINTEGER | iANY | 1 | 0 | 1 | 1 | 0 | 2 | 0 | 3 | No. of rows in result: 4
Query result:
xINTEGER | iANY
1 | 0
1 | 1
0 | 2
0 | 3
No. of rows in result: 4
  1. SPARQL DELETE DATA { GRAPH <g> { <s1> <p1> <o1> }}
Query result:
--
callret-0ANY
Delete from <g>, 1 (or less) triples -- done
No. of rows in result: 1
  1. SPARQL SELECT * { GRAPH <g> { ?s ?p ?o }}
Query result:
s
ANY	p
ANY	o
ANY
 s2	 p2	 literal
No. of rows in result: 1

7)SPARQL SELECT ?x ?i { VALUES (?g ?s ?p ?o ?i) { (<g><s1> <p1> <o1> 0) (<g><s2> <p2> "literal" 1) (<g><s3> <p3> "otherLiteral" 2) (<g><s4> <p4> <4> 3) } BIND(EXISTS{ GRAPH ?g {?s ?p ?o} } AS ?x )}

--
Query result:xINTEGERiANY 0 0 0 1 0 2 0 3No. of rows in result: 4 | Query result: | xINTEGER | iANY | 0 | 0 | 0 | 1 | 0 | 2 | 0 | 3 | No. of rows in result: 4
Query result:
xINTEGER | iANY
0 | 0
0 | 1
0 | 2
0 | 3
No. of rows in result: 4

The last result is wrong, as you can see the quad <g><s2> <p2> "literal" exist at query N°6, but for the query N°7 the EXIST clause return "0" not "1" .

FerrariAndrea avatar Dec 29 '20 09:12 FerrariAndrea

You seem to now be using the Conductor iSQL UI interface which is not the "isql" command line tool, which requires you connect to the docker image hosting Virtuoso and physically run the isql command from the Linux shell ...

Anyway, step 2 in your response is missing most of the insert data and fails to run, so I used the "insert" query from your previous post to insert the 2 triples resulting in the following running from command line isql:

SQL> SPARQL SELECT * { GRAPH <g> {?s ?p ?o}};
s                                                                                 p                                                                                 o
LONG VARCHAR                                                                      LONG VARCHAR                                                                      LONG VARCHAR
_______________________________________________________________________________


0 Rows. -- 3 msec.
SQL> SPARQL SELECT * { GRAPH <g> {?s ?p ?o}};                                                                                                                                                    s                                                                                 p                                                                                 o
LONG VARCHAR                                                                      LONG VARCHAR                                                                      LONG VARCHAR
_______________________________________________________________________________

s2                                                                                p2                                                                                literal

1 Rows. -- 0 msec.
SQL> SPARQL INSERT DATA { GRAPH <g> { <s1> <p1> <o1> . <s2> <p2> "literal" .}};

Done. -- 7 msec.
SQL> SPARQL SELECT * { GRAPH <g> {?s ?p ?o}};
s                                                                                 p                                                                                 o
LONG VARCHAR                                                                      LONG VARCHAR                                                                      LONG VARCHAR
_______________________________________________________________________________

s2                                                                                p2                                                                                literal
s1                                                                                p1                                                                                o1

2 Rows. -- 1 msec.
SQL> SPARQL SELECT ?x ?i { VALUES (?g ?s ?p ?o ?i) { (<g><s1> <p1> <o1> 0) (<g><s2> <p2> "literal" 1) (<g><s3> <p3> "otherLiteral" 2) (<g><s4> <p4> <4> 3) } BIND(EXISTS{ GRAPH ?g {?s ?p ?o} } AS ?x )};
x           i
INTEGER     LONG VARCHAR
_______________________________________________________________________________

1           0
1           1
0           2
0           3

4 Rows. -- 6 msec.
SQL> SPARQL DELETE DATA { GRAPH <g> { <s1> <p1> <o1> }};                                                                                                                                         
Done. -- 2 msec.
SQL> SPARQL SELECT * { GRAPH <g> {?s ?p ?o}};                                                                                                                                                    s                                                                                 p                                                                                 o
LONG VARCHAR                                                                      LONG VARCHAR                                                                      LONG VARCHAR
_______________________________________________________________________________

s2                                                                                p2                                                                                literal

1 Rows. -- 0 msec.
SQL> SPARQL SELECT ?x ?i { VALUES (?g ?s ?p ?o ?i) { (<g><s1> <p1> <o1> 0) (<g><s2> <p2> "literal" 1) (<g><s3> <p3> "otherLiteral" 2) (<g><s4> <p4> <4> 3) } BIND(EXISTS{ GRAPH ?g {?s ?p ?o} } AS ?x )};
x           i
INTEGER     LONG VARCHAR
_______________________________________________________________________________

0           0
0           1
0           2
0           3

4 Rows. -- 1 msec.
SQL>

I presume for the last query above, the second row of the result set should have been 1 1, as the <g><s2> <p2> "literal" triple pattern still exists following the delete; please confirm?

HughWilliams avatar Dec 29 '20 18:12 HughWilliams

Thank you so much for your patience.

Yes, I confirm.

FerrariAndrea avatar Jan 02 '21 09:01 FerrariAndrea