You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@lucene.apache.org by "Trejkaz (JIRA)" <ji...@apache.org> on 2015/11/02 04:04:27 UTC

[jira] [Commented] (LUCENE-6865) BooleanQuery2ModifierNodeProcessor breaks the query node hierarchy

    [ https://issues.apache.org/jira/browse/LUCENE-6865?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14984675#comment-14984675 ] 

Trejkaz commented on LUCENE-6865:
---------------------------------

Tried updating to 5.3, looks like backwards compatibility was broken in the 5.3 release, and we depend on elasticsearch as well, meaning we can't update even if we update all our own code to 5.3.


> BooleanQuery2ModifierNodeProcessor breaks the query node hierarchy
> ------------------------------------------------------------------
>
>                 Key: LUCENE-6865
>                 URL: https://issues.apache.org/jira/browse/LUCENE-6865
>             Project: Lucene - Core
>          Issue Type: Bug
>            Reporter: Trejkaz
>
> We discovered that one of our own implementations of QueryNodeProcessor was seeing node.getParent() returning null for nodes other than the root of the query tree.
> I put a diagnostic processor around every processor which runs and found that BooleanQuery2ModifierNodeProcessor (and possibly others, although it isn't clear) are mysteriously setting some of the node references to null.
> Example query tree before:
> {noformat}
> GroupQueryNode, parent = null
>   WithinQueryNode, parent = GroupQueryNode
>     QuotedFieldQueryNode, parent = WithinQueryNode
>     GroupQueryNode, parent = WithinQueryNode
>       AndQueryNode, parent = GroupQueryNode
>         GroupQueryNode, parent = AndQueryNode
>           OrQueryNode, parent = GroupQueryNode
>             QuotedFieldQueryNode, parent = OrQueryNode
>             QuotedFieldQueryNode, parent = OrQueryNode
>         GroupQueryNode, parent = AndQueryNode
>           OrQueryNode, parent = GroupQueryNode
>             QuotedFieldQueryNode, parent = OrQueryNode
>             QuotedFieldQueryNode, parent = OrQueryNode
> {noformat}
> And after BooleanQuery2ModifierNodeProcessor.process():
> {noformat}
> GroupQueryNode, parent = null
>   WithinQueryNode, parent = GroupQueryNode
>     QuotedFieldQueryNode, parent = WithinQueryNode
>     GroupQueryNode, parent = WithinQueryNode
>       AndQueryNode, parent = GroupQueryNode
>         BooleanModifierNode, parent = AndQueryNode
>           GroupQueryNode, parent = null
>             OrQueryNode, parent = GroupQueryNode
>               QuotedFieldQueryNode, parent = OrQueryNode
>               QuotedFieldQueryNode, parent = OrQueryNode
>         BooleanModifierNode, parent = AndQueryNode
>           GroupQueryNode, parent = null
>             OrQueryNode, parent = GroupQueryNode
>               QuotedFieldQueryNode, parent = OrQueryNode
>               QuotedFieldQueryNode, parent = OrQueryNode
> {noformat}
> Looking at QueryNodeImpl, there is a lot of fiddly logic in there. Removing children can trigger setting the parent to null, but setting the parent can also trigger the child removing itself, so it's near impossible to figure out why this could be happening, but I'm closing in on it at least. My initial suspicion is that cloneTree() is responsible, because ironically the number of failures of this sort _increase_ if I try to use cloneTree to defend against mutability bugs.
> The fix I have come up with is to clone the whole API but making QueryNode immutable. This removes the ability for processors to mess with nodes that don't belong to them, but also obviates the need for a parent reference in the first place, which I think is the entire source of the problem - keeping the parent and child in sync correctly is obviously going to be hard, and indeed we find that there is at least one bug of this sort lurking in there.
> But even if we rewrite it, I figured I would report the issue so that maybe it can be fixed for others.
> Code to use for diagnostics:
> {code}
> import java.util.List;
> import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
> import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
> import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
> import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessor;
> public class DiagnosticQueryNodeProcessor implements QueryNodeProcessor
> {
>     private final QueryNodeProcessor delegate;
>     public TreeFixingQueryNodeProcessor(QueryNodeProcessor delegate)
>     {
>         this.delegate = delegate;
>     }
>     @Override
>     public QueryConfigHandler getQueryConfigHandler()
>     {
>         return delegate.getQueryConfigHandler();
>     }
>     @Override
>     public void setQueryConfigHandler(QueryConfigHandler queryConfigHandler)
>     {
>         delegate.setQueryConfigHandler(queryConfigHandler);
>     }
>     @Override
>     public QueryNode process(QueryNode queryNode) throws QueryNodeException
>     {
>         System.out.println("Before " + delegate.getClass().getSimpleName() + ".process():");
>         dumpTree(queryNode);
>         queryNode = delegate.process(queryNode);
>         System.out.println("After " + delegate.getClass().getSimpleName() + ".process():");
>         dumpTree(queryNode);
>         return queryNode;
>     }
>     private void dumpTree(QueryNode queryNode)
>     {
>         dumpTree(queryNode, "");
>     }
>     private void dumpTree(QueryNode queryNode, String prefix)
>     {
>         System.out.println(prefix + queryNode.getClass().getSimpleName() +
>                            ", parent = " + (queryNode.getParent() == null ? "null" : queryNode.getParent().getClass().getSimpleName()));
>         List<QueryNode> children = queryNode.getChildren();
>         if (children != null)
>         {
>             String childPrefix = "  " + prefix;
>             for (QueryNode child : children)
>             {
>                 dumpTree(child, childPrefix);
>             }
>         }
>     }
> }
> {code}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@lucene.apache.org
For additional commands, e-mail: dev-help@lucene.apache.org