Details

      Description

      SELECT *
      {
      OPTIONAL {
      OPTIONAL {
      BIND (3 as ?x)
      }
      BIND (4 as ?x)
      }
      }

      should evaluate as 3, but currently evaluates as 4

        Activity

        Hide
        jeremycarroll jeremycarroll added a comment -

        Replying to jeremycarroll:
        > SELECT *
        > {
        > OPTIONAL {
        > OPTIONAL {
        > BIND (3 as ?x)
        > }
        > BIND (4 as ?x)
        > }
        > }
        >
        > should evaluate as unbound, but currently evaluates as 4

        Show
        jeremycarroll jeremycarroll added a comment - Replying to jeremycarroll : > SELECT * > { > OPTIONAL { > OPTIONAL { > BIND (3 as ?x) > } > BIND (4 as ?x) > } > } > > should evaluate as unbound, but currently evaluates as 4
        Hide
        jeremycarroll jeremycarroll added a comment -

        should evaluate as unbound not 3!

        Show
        jeremycarroll jeremycarroll added a comment - should evaluate as unbound not 3!
        Hide
        jeremycarroll jeremycarroll added a comment -

        Here is an example that is still small but closer to what I am actually experiencing.
        First we have a graph of four triples:

        INSERT {
          
          GRAPH <eg:a>
             { <eg:a> <eg:a> 1, 2, 3, 4 }
          }
        
        WHERE {
          
          }
        

        then I query with this:

        SELECT *
        FROM <eg:a>
        WITH
        { SELECT *
          WHERE
          {  <eg:a> <eg:a> ?x
              { <eg:a> <eg:a> ?y }
              UNION 
              { <eg:a> <eg:a> ?z }
          } LIMIT 19
        } AS %sub
        WITH
        { SELECT *
          WHERE
          {  
             INCLUDE %sub
             OPTIONAL { BIND ( 5 as ?z) }
             OPTIONAL { BIND ( 5 as ?y) }
          } 
        } AS %bound
        WHERE
        {
          INCLUDE %bound
          OPTIONAL {   <eg:a>?pz  ?z 
                   
                   }
          OPTIONAL {
                       <eg:a> ?py  ?y 
                   
                   }
        }
        
        

        I am consistently getting 31 results, not the expected 19, and some incorrectly have neither ?y nor ?z being 5

        Show
        jeremycarroll jeremycarroll added a comment - Here is an example that is still small but closer to what I am actually experiencing. First we have a graph of four triples: INSERT { GRAPH <eg:a> { <eg:a> <eg:a> 1, 2, 3, 4 } } WHERE { } then I query with this: SELECT * FROM <eg:a> WITH { SELECT * WHERE { <eg:a> <eg:a> ?x { <eg:a> <eg:a> ?y } UNION { <eg:a> <eg:a> ?z } } LIMIT 19 } AS %sub WITH { SELECT * WHERE { INCLUDE %sub OPTIONAL { BIND ( 5 as ?z) } OPTIONAL { BIND ( 5 as ?y) } } } AS %bound WHERE { INCLUDE %bound OPTIONAL { <eg:a>?pz ?z } OPTIONAL { <eg:a> ?py ?y } } I am consistently getting 31 results, not the expected 19, and some incorrectly have neither ?y nor ?z being 5
        Hide
        jeremycarroll jeremycarroll added a comment -

        To articulate the assumptions in the query:

        SELECT *
        FROM <eg:a>
        WITH
        { SELECT *
          WHERE
          {  <eg:a> <eg:a> ?x
              { <eg:a> <eg:a> ?y }
              UNION 
              { <eg:a> <eg:a> ?z }
        # we have 19 results, each with ?x one of 1,2,3 or 4, and either ?y is unbound and ?z is in 1,2,3,4 or ?z is unbound and ?y is 1,2,3,4 
        # we randomly have 19 of the 32 possible results
          } LIMIT 19
        } AS %sub
        WITH
        { SELECT *
          WHERE
          {  
             INCLUDE %sub
             OPTIONAL { BIND ( 5 as ?z) }
             OPTIONAL { BIND ( 5 as ?y) }
        # we have 19 results, each with ?x one of 1,2,3 or 4, and either ?y is 5 and ?z is in 1,2,3,4 or ?z is 5 and ?y is 1,2,3,4 
        # we randomly have 19 of the 32 possible results
          } 
        } AS %bound
        WHERE
        {
          INCLUDE %bound
        # if ?z is not 5 bind ?pz to <eg:a>
          OPTIONAL {   <eg:a>?pz  ?z 
                   
                   }
        
        # if ?y is not 5 bind ?py to <eg:a>
          OPTIONAL {
                       <eg:a> ?py  ?y 
                   
                   }
        }
        
        Show
        jeremycarroll jeremycarroll added a comment - To articulate the assumptions in the query: SELECT * FROM <eg:a> WITH { SELECT * WHERE { <eg:a> <eg:a> ?x { <eg:a> <eg:a> ?y } UNION { <eg:a> <eg:a> ?z } # we have 19 results, each with ?x one of 1,2,3 or 4, and either ?y is unbound and ?z is in 1,2,3,4 or ?z is unbound and ?y is 1,2,3,4 # we randomly have 19 of the 32 possible results } LIMIT 19 } AS %sub WITH { SELECT * WHERE { INCLUDE %sub OPTIONAL { BIND ( 5 as ?z) } OPTIONAL { BIND ( 5 as ?y) } # we have 19 results, each with ?x one of 1,2,3 or 4, and either ?y is 5 and ?z is in 1,2,3,4 or ?z is 5 and ?y is 1,2,3,4 # we randomly have 19 of the 32 possible results } } AS %bound WHERE { INCLUDE %bound # if ?z is not 5 bind ?pz to <eg:a> OPTIONAL { <eg:a>?pz ?z } # if ?y is not 5 bind ?py to <eg:a> OPTIONAL { <eg:a> ?py ?y } }
        Hide
        jeremycarroll jeremycarroll added a comment -

        Here is a reduced version of previous example:

        SELECT *
        FROM <eg:a>
        WITH
        { SELECT *
          WHERE
          {  { BIND ( 4 as ?y )
              }
              UNION 
              {  BIND ( 4 as ?z )
              }
          } LIMIT 2
        } AS %sub
        WITH
        { SELECT *
          WHERE
          {  
             INCLUDE %sub
             OPTIONAL { BIND ( 5 as ?z) }
             OPTIONAL { BIND ( 5 as ?y) }
          } 
        } AS %bound
        WHERE
        {
          
          INCLUDE %bound
          OPTIONAL {  
                BIND ( 4 as ?z )
                   }
          OPTIONAL {
                BIND ( 4 as ?y )
                   }
        }
        

        reducing the LIMIT to 1 everything behaves correctly; with limit of 2 we get three answers including the incorrect ?y = ?z= 4

        Show
        jeremycarroll jeremycarroll added a comment - Here is a reduced version of previous example: SELECT * FROM <eg:a> WITH { SELECT * WHERE { { BIND ( 4 as ?y ) } UNION { BIND ( 4 as ?z ) } } LIMIT 2 } AS %sub WITH { SELECT * WHERE { INCLUDE %sub OPTIONAL { BIND ( 5 as ?z) } OPTIONAL { BIND ( 5 as ?y) } } } AS %bound WHERE { INCLUDE %bound OPTIONAL { BIND ( 4 as ?z ) } OPTIONAL { BIND ( 4 as ?y ) } } reducing the LIMIT to 1 everything behaves correctly; with limit of 2 we get three answers including the incorrect ?y = ?z= 4
        Hide
        jeremycarroll jeremycarroll added a comment -

        Further simplification to:

        WHERE
        {
          { BIND ( 4 as ?y )
          }
              UNION 
          {  BIND ( 4 as ?z )
          }
          OPTIONAL { BIND ( 5 as ?z) }
          OPTIONAL { BIND ( 5 as ?y) }
        }
        

        again gives three results rather than two

        Show
        jeremycarroll jeremycarroll added a comment - Further simplification to: WHERE { { BIND ( 4 as ?y ) } UNION { BIND ( 4 as ?z ) } OPTIONAL { BIND ( 5 as ?z) } OPTIONAL { BIND ( 5 as ?y) } } again gives three results rather than two
        Hide
        jeremycarroll jeremycarroll added a comment -

        The optimized AST for the last example is:
        {{

        { Optimized AST WITH \{ bq. QueryType: SELECT bq. SELECT VarNode(y) VarNode(z) JoinGroupNode \{ UnionNode [joinVars=[]] [projectInVars=[]] \{ JoinGroupNode [joinVars=[]] [projectInVars=[]] \{ ( ConstantNode(XSDInteger(4)) AS VarNode(y) ) }

        JOIN ON ()
        JoinGroupNode [joinVars=[]] [projectInVars=[]] {
        ( ConstantNode(XSDInteger(4)) AS VarNode(z) )
        } JOIN ON ()
        } JOIN ON ()
        }
        } AS --nsr-1 JOIN ON () DEPENDS ON ()
        WITH {

        QueryType: SELECT

        SELECT VarNode VarNode(z)

        JoinGroupNode {
        INCLUDE --nsr-1 JOIN ON ()
        JoinGroupNode [optional] [joinVars=[]] [projectInVars=[z]] {
        ( ConstantNode(XSDInteger(5)) AS VarNode(z) )
        } JOIN ON ()
        }
        } AS -nsr-2 JOIN ON () DEPENDS ON (-nsr-1)
        WITH {

        QueryType: SELECT

        SELECT VarNode VarNode(z)

        JoinGroupNode {
        INCLUDE --nsr-1 JOIN ON ()
        JoinGroupNode [optional] [joinVars=[]] [projectInVars=[y]] {
        ( ConstantNode(XSDInteger(5)) AS VarNode )
        } JOIN ON ()
        }
        } AS -nsr-3 JOIN ON () DEPENDS ON (-nsr-1)
        QueryType: SELECT
        includeInferred=true
        SELECT VarNode VarNode(z)

        JoinGroupNode {

        INCLUDE --nsr-2 JOIN ON ()
        INCLUDE --nsr-3 JOIN ON ()
        }
        }}
        which is incorrect!
        - that AST does indeed have 4 and 4 as an answer, so an optimizer step was incorrect

        Show
        jeremycarroll jeremycarroll added a comment - The optimized AST for the last example is: {{ { Optimized AST WITH \{ bq. QueryType: SELECT bq. SELECT VarNode(y) VarNode(z) JoinGroupNode \{ UnionNode [joinVars=[]] [projectInVars=[]] \{ JoinGroupNode [joinVars=[]] [projectInVars=[]] \{ ( ConstantNode(XSDInteger(4)) AS VarNode(y) ) } JOIN ON () JoinGroupNode [joinVars=[]] [projectInVars=[]] { ( ConstantNode(XSDInteger(4)) AS VarNode(z) ) } JOIN ON () } JOIN ON () } } AS --nsr-1 JOIN ON () DEPENDS ON () WITH { QueryType: SELECT SELECT VarNode VarNode(z) JoinGroupNode { INCLUDE --nsr-1 JOIN ON () JoinGroupNode [optional] [joinVars=[]] [projectInVars= [z] ] { ( ConstantNode(XSDInteger(5)) AS VarNode(z) ) } JOIN ON () } } AS - nsr-2 JOIN ON () DEPENDS ON ( -nsr-1) WITH { QueryType: SELECT SELECT VarNode VarNode(z) JoinGroupNode { INCLUDE --nsr-1 JOIN ON () JoinGroupNode [optional] [joinVars=[]] [projectInVars= [y] ] { ( ConstantNode(XSDInteger(5)) AS VarNode ) } JOIN ON () } } AS - nsr-3 JOIN ON () DEPENDS ON ( -nsr-1) QueryType: SELECT includeInferred=true SELECT VarNode VarNode(z) JoinGroupNode { INCLUDE --nsr-2 JOIN ON () INCLUDE --nsr-3 JOIN ON () } }} which is incorrect! - that AST does indeed have 4 and 4 as an answer, so an optimizer step was incorrect
        Hide
        jeremycarroll jeremycarroll added a comment -

        The issue is in the complex optional optimizer
        - the following step is unsound

        QueryType: SELECT
        includeInferred=true
        SELECT VarNode(y) VarNode(z)
          JoinGroupNode {
            UnionNode {
              JoinGroupNode {
                ( ConstantNode(XSDInteger(4)) AS VarNode(y) )
              }
              JoinGroupNode {
                ( ConstantNode(XSDInteger(4)) AS VarNode(z) )
              }
            }
            JoinGroupNode [optional] {
              ( ConstantNode(XSDInteger(5)) AS VarNode(z) )
            }
            JoinGroupNode [optional] {
              ( ConstantNode(XSDInteger(5)) AS VarNode(y) )
            }
          }
        INFO : 24034      com.bigdata.rdf.sail.webapp.BigdataRDFContext.queryService2 com.bigdata.rdf.sparql.ast.optimizers.ASTOptimizerList.optimize(ASTOptimizerList.java:102): Applying: com.bigdata.rdf.sparql.ast.optimizers.ASTComplexOptionalOptimizer@1d23ee10
        DEBUG: 24038      com.bigdata.rdf.sail.webapp.BigdataRDFContext.queryService2 com.bigdata.rdf.sparql.ast.optimizers.ASTOptimizerList.optimize(ASTOptimizerList.java:110): Rewritten AST:
        
        WITH {
          QueryType: SELECT
          SELECT VarNode(y) VarNode(z)
            JoinGroupNode {
              UnionNode {
                JoinGroupNode {
                  ( ConstantNode(XSDInteger(4)) AS VarNode(y) )
                }
                JoinGroupNode {
                  ( ConstantNode(XSDInteger(4)) AS VarNode(z) )
                }
              }
            }
        } AS --nsr-1
        WITH {
          QueryType: SELECT
          SELECT VarNode(y) VarNode(z)
            JoinGroupNode {
              INCLUDE --nsr-1
              JoinGroupNode [optional] {
                ( ConstantNode(XSDInteger(5)) AS VarNode(z) )
              }
            }
        } AS --nsr-2
        WITH {
          QueryType: SELECT
          SELECT VarNode(y) VarNode(z)
            JoinGroupNode {
              INCLUDE --nsr-1
              JoinGroupNode [optional] {
                ( ConstantNode(XSDInteger(5)) AS VarNode(y) )
              }
            }
        } AS --nsr-3
        QueryType: SELECT
        includeInferred=true
        SELECT VarNode(y) VarNode(z)
          JoinGroupNode {
            INCLUDE --nsr-2
            INCLUDE --nsr-3
          }
        
        
        Show
        jeremycarroll jeremycarroll added a comment - The issue is in the complex optional optimizer - the following step is unsound QueryType: SELECT includeInferred=true SELECT VarNode(y) VarNode(z) JoinGroupNode { UnionNode { JoinGroupNode { ( ConstantNode(XSDInteger(4)) AS VarNode(y) ) } JoinGroupNode { ( ConstantNode(XSDInteger(4)) AS VarNode(z) ) } } JoinGroupNode [optional] { ( ConstantNode(XSDInteger(5)) AS VarNode(z) ) } JoinGroupNode [optional] { ( ConstantNode(XSDInteger(5)) AS VarNode(y) ) } } INFO : 24034 com.bigdata.rdf.sail.webapp.BigdataRDFContext.queryService2 com.bigdata.rdf.sparql.ast.optimizers.ASTOptimizerList.optimize(ASTOptimizerList.java:102): Applying: com.bigdata.rdf.sparql.ast.optimizers.ASTComplexOptionalOptimizer@1d23ee10 DEBUG: 24038 com.bigdata.rdf.sail.webapp.BigdataRDFContext.queryService2 com.bigdata.rdf.sparql.ast.optimizers.ASTOptimizerList.optimize(ASTOptimizerList.java:110): Rewritten AST: WITH { QueryType: SELECT SELECT VarNode(y) VarNode(z) JoinGroupNode { UnionNode { JoinGroupNode { ( ConstantNode(XSDInteger(4)) AS VarNode(y) ) } JoinGroupNode { ( ConstantNode(XSDInteger(4)) AS VarNode(z) ) } } } } AS --nsr-1 WITH { QueryType: SELECT SELECT VarNode(y) VarNode(z) JoinGroupNode { INCLUDE --nsr-1 JoinGroupNode [optional] { ( ConstantNode(XSDInteger(5)) AS VarNode(z) ) } } } AS --nsr-2 WITH { QueryType: SELECT SELECT VarNode(y) VarNode(z) JoinGroupNode { INCLUDE --nsr-1 JoinGroupNode [optional] { ( ConstantNode(XSDInteger(5)) AS VarNode(y) ) } } } AS --nsr-3 QueryType: SELECT includeInferred=true SELECT VarNode(y) VarNode(z) JoinGroupNode { INCLUDE --nsr-2 INCLUDE --nsr-3 }
        Hide
        jeremycarroll jeremycarroll added a comment -

        Looking at ticket 397 http://trac.bigdata.com/ticket/397 suggests that the problem is that the flow of optionally
        bound variables from one optional group to the next is not respected.
        That the analysis should include this flow seems to be implicit in the comment:

             *      FIXME We should not be lifting the simple optional into the first
             *      named subquery. In is independent of the other optionals (they do
             *      not use the variable which is bound by the simple optional).
             *      Therefore it should be left in place in step (1) and then lifted out
             *      in step (2) into its own named subquery in support of a more
             *      efficient MERGE JOIN pattern.
        

        but the overall flow should include such analysis so that it is not that we take an initial subquery with all the non-optional bits
        and then feed that into each of the optional subs queries; rather, for each complex optional in turn, we feed in those previous subqueries with shared variables that may have been bound

        Show
        jeremycarroll jeremycarroll added a comment - Looking at ticket 397 http://trac.bigdata.com/ticket/397 suggests that the problem is that the flow of optionally bound variables from one optional group to the next is not respected. That the analysis should include this flow seems to be implicit in the comment: * FIXME We should not be lifting the simple optional into the first * named subquery. In is independent of the other optionals (they do * not use the variable which is bound by the simple optional). * Therefore it should be left in place in step (1) and then lifted out * in step (2) into its own named subquery in support of a more * efficient MERGE JOIN pattern. but the overall flow should include such analysis so that it is not that we take an initial subquery with all the non-optional bits and then feed that into each of the optional subs queries; rather, for each complex optional in turn, we feed in those previous subqueries with shared variables that may have been bound
        Hide
        jeremycarroll jeremycarroll added a comment -

        The last example query is correctly executed as:

        SELECT *
        WITH {
          SELECT *
          WHERE
        {
          { BIND ( 4 as ?y )
              }
              UNION 
              {  BIND ( 4 as ?z )
              }
          
          
          }} as %Main 
        WITH {
          SELECT *
          WHERE
        {
          INCLUDE %Main
             OPTIONAL { BIND ( 5 as ?z) }
          
          }} as %Sub1
        WHERE
        {
          INCLUDE %Sub1
             OPTIONAL { BIND ( 5 as ?y) }
        }
        
        Show
        jeremycarroll jeremycarroll added a comment - The last example query is correctly executed as: SELECT * WITH { SELECT * WHERE { { BIND ( 4 as ?y ) } UNION { BIND ( 4 as ?z ) } }} as %Main WITH { SELECT * WHERE { INCLUDE %Main OPTIONAL { BIND ( 5 as ?z) } }} as %Sub1 WHERE { INCLUDE %Sub1 OPTIONAL { BIND ( 5 as ?y) } }
        Hide
        jeremycarroll jeremycarroll added a comment -

        The first query is not the same defect ?.
        The problem is here, with ASTJoinOrderByTypeOptimizer being unsound.

        SELECT VarNode(x)
          JoinGroupNode {
            JoinGroupNode [optional] {
              JoinGroupNode [optional] {
                ( ConstantNode(XSDInteger(3)) AS VarNode(x) )
              }
              ( ConstantNode(XSDInteger(4)) AS VarNode(x) )
            }
          }
        INFO : 1813457      com.bigdata.rdf.sail.webapp.BigdataRDFContext.queryService3 com.bigdata.rdf.sparql.ast.optimizers.ASTOptimizerList.optimize(ASTOptimizerList.java:102): Applying: com.bigdata.rdf.sparql.ast.optimizers.ASTJoinOrderByTypeOptimizer@36a98198
        DEBUG: 1813457      com.bigdata.rdf.sail.webapp.BigdataRDFContext.queryService2 com.bigdata.rdf.sparql.ast.optimizers.ASTOptimizerList.optimize(ASTOptimizerList.java:110): Rewritten AST:
        
        QueryType: SELECT
        includeInferred=true
        SELECT VarNode(x)
          JoinGroupNode {
            JoinGroupNode [optional] {
              ( ConstantNode(XSDInteger(4)) AS VarNode(x) )
              JoinGroupNode [optional] {
                ( ConstantNode(XSDInteger(3)) AS VarNode(x) )
              }
            }
          }
        
        Show
        jeremycarroll jeremycarroll added a comment - The first query is not the same defect ?. The problem is here, with ASTJoinOrderByTypeOptimizer being unsound. SELECT VarNode(x) JoinGroupNode { JoinGroupNode [optional] { JoinGroupNode [optional] { ( ConstantNode(XSDInteger(3)) AS VarNode(x) ) } ( ConstantNode(XSDInteger(4)) AS VarNode(x) ) } } INFO : 1813457 com.bigdata.rdf.sail.webapp.BigdataRDFContext.queryService3 com.bigdata.rdf.sparql.ast.optimizers.ASTOptimizerList.optimize(ASTOptimizerList.java:102): Applying: com.bigdata.rdf.sparql.ast.optimizers.ASTJoinOrderByTypeOptimizer@36a98198 DEBUG: 1813457 com.bigdata.rdf.sail.webapp.BigdataRDFContext.queryService2 com.bigdata.rdf.sparql.ast.optimizers.ASTOptimizerList.optimize(ASTOptimizerList.java:110): Rewritten AST: QueryType: SELECT includeInferred=true SELECT VarNode(x) JoinGroupNode { JoinGroupNode [optional] { ( ConstantNode(XSDInteger(4)) AS VarNode(x) ) JoinGroupNode [optional] { ( ConstantNode(XSDInteger(3)) AS VarNode(x) ) } } }
        Hide
        jeremycarroll jeremycarroll added a comment -

        The file ASTJoinOrderByTypeOptimizer.java concedes:

             *   TODO: the placement of OPTIONALS should really be more complicated than this.
             *   e.g. consider interaction with SERVICE calls etc.
             *   Optional joins:
             *   10. Simple optionals & optional subgroups
        
        Show
        jeremycarroll jeremycarroll added a comment - The file ASTJoinOrderByTypeOptimizer.java concedes: * TODO: the placement of OPTIONALS should really be more complicated than this. * e.g. consider interaction with SERVICE calls etc. * Optional joins: * 10. Simple optionals & optional subgroups
        Hide
        jeremycarroll jeremycarroll added a comment -
        SELECT * 
        {
        OPTIONAL {
        OPTIONAL {
        BIND (3 as ?x)
        }
          BIND (5 as ?z)
         <eg:a> <eg:a> ?x .
          hint:Prior hint:runLast true .
        }
        }
        

        is close to a work-around for the first case

        Show
        jeremycarroll jeremycarroll added a comment - SELECT * { OPTIONAL { OPTIONAL { BIND (3 as ?x) } BIND (5 as ?z) <eg:a> <eg:a> ?x . hint:Prior hint:runLast true . } } is close to a work-around for the first case
        Hide
        jeremycarroll jeremycarroll added a comment -
        SELECT * 
        {
        OPTIONAL {
        OPTIONAL {
        BIND (3 as ?x)
        }
          BIND (4 as ?x).
          hint:Group hint:optimizer "None" .
        }
        }
        

        is a work around to the original problem

        Show
        jeremycarroll jeremycarroll added a comment - SELECT * { OPTIONAL { OPTIONAL { BIND (3 as ?x) } BIND (4 as ?x). hint:Group hint:optimizer "None" . } } is a work around to the original problem
        Hide
        bryanthompson bryanthompson added a comment -

        Jeremy,

        This looks like an issue with the static optimizer freely reordering the OPTIONALs. I believe that you have looked at this code in some depth before. Can you please take a look at suggest a patch for Mike to review?

        Thanks,
        Bryan

        Show
        bryanthompson bryanthompson added a comment - Jeremy, This looks like an issue with the static optimizer freely reordering the OPTIONALs. I believe that you have looked at this code in some depth before. Can you please take a look at suggest a patch for Mike to review? Thanks, Bryan
        Hide
        michaelschmidt michaelschmidt added a comment -

        Actually, there were two orthogonal problems discussed in the ticket:

        1. Comments 3 to 8 are discussion a problem related to the ASTComplexOptionalOptimizer, which is disabled meanwhile. These queries work fine now, giving the correct multiplicities and results. Added a test case, see ticket BLZG-882 for more details.

        2. The original query mentioned in the desciption. Imho, the result for this query is correct, { ?x -> 4}, see the argumentation below:

        First of note that (I believe that) this query is invalid according to the SPARQL standard: http://www.w3.org/TR/sparql11-query/, 18.2.1 says that "In BIND (expr AS v) requires that the variable v is not in-scope from the preceeding elements in the group graph pattern in which it is used.". However, there's no problem evaluating it according to the W3C semantics, which applies here as well.

        To see why I believe that { ?x -> 4 } is is correct, look at the following as a replacement for the second version:

        # DATA:
        <http://s> <http:/is3> "3" .
        <http://s> <http:/is4> "4" .
        
        # QUERY:
        SELECT * WHERE
        {
          <http://s> <http:/is4> ?x .
          OPTIONAL {
            <http://s> <http:/is3> ?x .
          }
        }
        

        The result, "4", is pretty obvious (that's what blazegraph returns here). The result actually does not change when adding another OPTIONAL around:

        SELECT * WHERE
        {
          OPTIONAL {
            <http://s> <http:/is4> ?x .
            OPTIONAL {
              <http://s> <http:/is3> ?x .
            }
          }
        }
        

        The additional OPTIONAL constitutes just a join of the empty (universal) solution set with the solution of the previous query, thus exactly the solution of the previous query.

        Bridging to the example provided in the bug: I don?t see why BIND should be treated differently here than binding triple patterns. Imho, the syntactic restriction imposed by the W3C standard is unnecessarily strict (though there are cases where such restrictions are needed, consider for instance the pattern ?BIND(?x AS ?y) BIND(?y AS ?x)? with mutual (unresolvable) dependencies.

        Note that there are also no "bottom-up" issues here, both queries are perfectly well designed, so we can safely evaluate top-down or bottom-up, as we like.

        Test cases from this ticket have been added, see pull request in branch ticket_933.

        Show
        michaelschmidt michaelschmidt added a comment - Actually, there were two orthogonal problems discussed in the ticket: 1. Comments 3 to 8 are discussion a problem related to the ASTComplexOptionalOptimizer, which is disabled meanwhile. These queries work fine now, giving the correct multiplicities and results. Added a test case, see ticket BLZG-882 for more details. 2. The original query mentioned in the desciption. Imho, the result for this query is correct, { ?x -> 4}, see the argumentation below: First of note that (I believe that) this query is invalid according to the SPARQL standard: http://www.w3.org/TR/sparql11-query/ , 18.2.1 says that "In BIND (expr AS v) requires that the variable v is not in-scope from the preceeding elements in the group graph pattern in which it is used.". However, there's no problem evaluating it according to the W3C semantics, which applies here as well. To see why I believe that { ?x -> 4 } is is correct, look at the following as a replacement for the second version: # DATA: <http://s> <http:/is3> "3" . <http://s> <http:/is4> "4" . # QUERY: SELECT * WHERE { <http://s> <http:/is4> ?x . OPTIONAL { <http://s> <http:/is3> ?x . } } The result, "4", is pretty obvious (that's what blazegraph returns here). The result actually does not change when adding another OPTIONAL around: SELECT * WHERE { OPTIONAL { <http://s> <http:/is4> ?x . OPTIONAL { <http://s> <http:/is3> ?x . } } } The additional OPTIONAL constitutes just a join of the empty (universal) solution set with the solution of the previous query, thus exactly the solution of the previous query. Bridging to the example provided in the bug: I don?t see why BIND should be treated differently here than binding triple patterns. Imho, the syntactic restriction imposed by the W3C standard is unnecessarily strict (though there are cases where such restrictions are needed, consider for instance the pattern ?BIND(?x AS ?y) BIND(?y AS ?x)? with mutual (unresolvable) dependencies. Note that there are also no "bottom-up" issues here, both queries are perfectly well designed, so we can safely evaluate top-down or bottom-up, as we like. Test cases from this ticket have been added, see pull request in branch ticket_933.

          People

          • Assignee:
            jeremycarroll jeremycarroll
            Reporter:
            jeremycarroll jeremycarroll
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: