<?xml version="1.0" encoding="UTF-8" ?>


<!--  RSS generated by JIRA #108 at Sat May 25 09:28:30 CEST 2013 -->

<rss version="0.92">






<channel>
    <title>openRDF.org Issue Tracker</title>
    <link>http://www.openrdf.org/issues</link>
    <description>This file is an XML representation of an issue</description>
    <language>en</language>
    <item>
        







<title>[SES-818] Incorrect TupleExpression created for &quot;SELECT (?s IN (?p,?o) AS ?x) ... &quot;.</title>
<link>http://www.openrdf.org/issues/browse/SES-818</link>

    
        <description>The incorrect TupleExpression is created for &amp;quot;SELECT (?s IN (?p,?o) AS ?x) ... &amp;quot;.  It produces the following AST tree.  You can see that Var(s), In, and Var(x) are all children of the ProjectionElem.  However, getAlias() assumes that the child at index 1 will be the alias when there are at least two children of the ProjectionElem.  That is In() rather than Var(x).   It seems likely that it would be easier if IN were treated as an infix operator such that the parse tree would be ProjectionElem(IN(s,p,o),x) and thus always have either one or two children which would make identifying the alias much easier. This might be done by a rewrite step.  Other solutions are of course possible, but if the expression in the &amp;quot;left&amp;quot; hand side of the AS has more than one node then getAlias() should return the last element rather than the 2nd element.&lt;br/&gt;
&lt;br/&gt;
&amp;gt; QueryContainer&lt;br/&gt;
&amp;gt; SelectQuery&lt;br/&gt;
&amp;gt;   Select&lt;br/&gt;
&amp;gt;    ProjectionElem&lt;br/&gt;
&amp;gt;     Var (s)&lt;br/&gt;
&amp;gt;     In&lt;br/&gt;
&amp;gt;      Var (p)&lt;br/&gt;
&amp;gt;      Var (o)&lt;br/&gt;
&amp;gt;     Var (x)&lt;br/&gt;
&lt;br/&gt;
public String getAlias() {&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (children.size()&amp;gt;= 2) {&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Node aliasNode = children.get(1);&lt;br/&gt;
&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (aliasNode instanceof ASTString) {&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return ((ASTString)aliasNode).getValue();&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else if (aliasNode instanceof ASTVar) {&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return ((ASTVar)aliasNode).getName();&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/&gt;
&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return null;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}</description>
    
    
        <environment>any</environment>
    
        <key id="12492">SES-818</key>
        <summary>Incorrect TupleExpression created for &quot;SELECT (?s IN (?p,?o) AS ?x) ... &quot;.</summary>
        <type id="1">Bug</type>
    
        <priority id="3">Major</priority>
    
        <status id="5">Resolved</status>
        
        <resolution id="1">Fixed</resolution>
        
    
        
        <assignee username="jeen">Jeen Broekstra</assignee>
        
    

    
        
        <reporter username="thompsonbry">Bryan Thompson</reporter>
        
    

        
        <created>Tue, 23 Aug 2011 00:58:27 +0200 (CEST)</created>
    <updated>Sun, 28 Aug 2011 23:41:19 +0200 (CEST)</updated>

    
        
        
            
            
                
                    <version>2.4.2</version>
                
            
        
    

    
        
        
            
            
                
                    <fixVersion>2.5.1</fixVersion>
                
            
        
    

    
        
        
            
            
                
                    <component>SPARQL</component>
                
            
        
    

    
    
        <due></due>
    
    
        <votes>0</votes>
    
    

    
    
        <comments>
            
            <comment author="thompsonbry" created="Tue, 23 Aug 2011 12:49:32 +0200 (CEST)" level="">Something related which I noticed is that the &amp;quot;AS&amp;quot; appears to disappear within a GROUP BY (?x AS ?y).  The ?x and ?y show as the children of a GroupBywithout the AS being represented by a dominating AS node.  You can see this would be the case by looking at the grammar.  I think that it might be more convenient to represent the { Expr AS Var } as an &amp;quot;AS&amp;quot; grammar production so it was always just a single AST node.  This would also solve the problem in the SELECT expressions since an AS would always be represented as a binary relation regardless of the number of nodes involved in the left hand side.&lt;br/&gt;
&lt;br/&gt;
void GroupCondition() :&lt;br/&gt;
{}&lt;br/&gt;
{&lt;br/&gt;
	FunctionCall()&lt;br/&gt;
|	BuiltInCall()&lt;br/&gt;
|	&amp;lt;LPAREN&amp;gt; Expression() [ &amp;lt;AS&amp;gt; Var() ] &amp;lt;RPAREN&amp;gt;  &amp;lt;==&lt;br/&gt;
|	Var()&lt;br/&gt;
}&lt;br/&gt;
</comment>
            
            <comment author="thompsonbry" created="Fri, 26 Aug 2011 20:59:58 +0200 (CEST)" level="">Jeen,&lt;br/&gt;
&lt;br/&gt;
This problem with IN and NOT IN was driving me nuts.  I modified the sparql.jjt grammar as follows:&lt;br/&gt;
&lt;br/&gt;
void RelationalExpression() #void :&lt;br/&gt;
{}&lt;br/&gt;
{&lt;br/&gt;
	NumericExpression()&lt;br/&gt;
	[&lt;br/&gt;
		&amp;lt;EQ&amp;gt; NumericExpression() {jjtThis.setOperator(CompareOp.EQ);} #Compare(2)&lt;br/&gt;
	|	&amp;lt;NE&amp;gt; NumericExpression() {jjtThis.setOperator(CompareOp.NE);} #Compare(2)&lt;br/&gt;
	|	&amp;lt;LT&amp;gt; NumericExpression() {jjtThis.setOperator(CompareOp.LT);} #Compare(2)&lt;br/&gt;
	|	&amp;lt;LE&amp;gt; NumericExpression() {jjtThis.setOperator(CompareOp.LE);} #Compare(2)&lt;br/&gt;
	|	&amp;lt;GE&amp;gt; NumericExpression() {jjtThis.setOperator(CompareOp.GE);} #Compare(2)&lt;br/&gt;
	|	&amp;lt;GT&amp;gt; NumericExpression() {jjtThis.setOperator(CompareOp.GT);} #Compare(2)&lt;br/&gt;
//	|	In() &lt;br/&gt;
//	|	NotIn()&lt;br/&gt;
	|	In()    #Infix(2)&lt;br/&gt;
	|	NotIn() #Infix(2)&lt;br/&gt;
	]&lt;br/&gt;
}&lt;br/&gt;
&lt;br/&gt;
This ensures that the IN() construction does not cause there to be more than one AST node in the value expression for the parent.&lt;br/&gt;
&lt;br/&gt;
I then added a production to handle the Infix operator:&lt;br/&gt;
&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/**&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;* Unwrap an {@link ASTInfix} node, returning the inner {@link FunctionNode}&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;* constructed for it.&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*/&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Override&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public FunctionNode visit(ASTInfix node, Object data) throws VisitorException {&lt;br/&gt;
&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;final Node left = node.jjtGetChild(0);&lt;br/&gt;
&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;final Node op = node.jjtGetChild(1);&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;op.jjtInsertChild(left, 0);&lt;br/&gt;
&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return (FunctionNode) op.jjtAccept(this, data);&lt;br/&gt;
&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/&gt;
&lt;br/&gt;
This fixes the problem for me.</comment>
            
            <comment author="jeen" created="Sun, 28 Aug 2011 23:39:36 +0200 (CEST)" level="">Thanks for the suggestions. I have added the Infix approach for the productions of In and Not In, which fixes the issues with this kind of operation appearing in the projection. The TupleExprBuilder now reads an Infix object by first visiting the leftArg and then injecting that arg immediately into the production for the rightArg, so the operator has both operands available, resulting in a ValueExpr (in this case, a OR-ed set of Compare objects). &lt;br/&gt;
&lt;br/&gt;
Have to run a few more quick tests before I commit, to see if I don&apos;t break any existing queries. </comment>
            
        </comments>
    
    

        



        <customfields>
        
            
        </customfields>
    </item>
</channel>


</rss>  