@Override
  public void handle(
      final AST2BOpContext context,
      final QueryRoot queryRoot,
      final QueryHintScope scope,
      final ASTBase op,
      final Boolean value) {

    if (scope == QueryHintScope.Query) {

      context.mergeJoin = value;

      return;
    }

    throw new QueryHintException(scope, op, getName(), value);
  }
  private void liftSparql11Subquery(
      final AST2BOpContext context, final StaticAnalysis sa, final SubqueryRoot subqueryRoot) {

    final IGroupNode<?> parent = subqueryRoot.getParent();

    final String newName = "-subSelect-" + context.nextId();

    final NamedSubqueryInclude include = new NamedSubqueryInclude(newName);

    /**
     * Set query hints from the parent join group.
     *
     * @see <a href="http://sourceforge.net/apps/trac/bigdata/ticket/791" > Clean up query hints
     *     </a>
     */
    include.setQueryHints((Properties) parent.getProperty(ASTBase.Annotations.QUERY_HINTS));

    /**
     * Copy across attached join filters.
     *
     * @see <a href="https://sourceforge.net/apps/trac/bigdata/ticket/796" >Filter assigned to
     *     sub-query by query generator is dropped from evaluation</a>
     */
    include.setAttachedJoinFilters(subqueryRoot.getAttachedJoinFilters());

    /*
     * Note: A SubqueryRoot normally starts out as the sole child of a
     * JoinGroupNode. However, other rewrites may have written out that
     * JoinGroupNode and it does not appear to be present for an ASK
     * subquery.
     *
     * Therefore, when the parent of the SubqueryRoot is a JoinGroupNode
     * having the SubqueryRoot as its only child, we use the parent's parent
     * in order to replace the JoinGroupNode when we lift out the
     * SubqueryRoot. Otherwise we use the parent since there is no wrapping
     * JoinGroupNode (or if there is, it has some other stuff in there as
     * well).
     *
     * BLZG-1542 -> there is an additional thing we need to take care of:
     *              whenever the parent node is an OPTIONAL or MINUS, we
     *              must not remove it, otherwise we would just "drop" an
     *              OPTIONAL or MINUS, thus changing the query's semantics
     *
     */

    if ((parent instanceof JoinGroupNode)
        && !((JoinGroupNode) parent).isOptional()
        && !((JoinGroupNode) parent).isMinus()
        && ((BOp) parent).arity() == 1
        && parent.getParent() != null
        && !((IGroupNode<?>) parent.getParent() instanceof UnionNode)) {

      final IGroupNode<IGroupMemberNode> pp = parent.getParent();

      // Replace the sub-select with the include.
      if (((ASTBase) pp).replaceWith((BOp) parent, include) == 0) throw new AssertionError();

    } else {

      // Replace the sub-select with the include.
      if (((ASTBase) parent).replaceWith((BOp) subqueryRoot, include) == 0)
        throw new AssertionError();
    }

    final NamedSubqueryRoot nsr = new NamedSubqueryRoot(subqueryRoot.getQueryType(), newName);

    /**
     * Copy across query hints from the original subquery.
     *
     * @see <a href="http://sourceforge.net/apps/trac/bigdata/ticket/791" > Clean up query hints
     *     </a>
     */
    nsr.setQueryHints(subqueryRoot.getQueryHints());

    nsr.setConstruct(subqueryRoot.getConstruct());
    nsr.setGroupBy(subqueryRoot.getGroupBy());
    nsr.setHaving(subqueryRoot.getHaving());
    nsr.setOrderBy(subqueryRoot.getOrderBy());
    nsr.setProjection(subqueryRoot.getProjection());
    nsr.setSlice(subqueryRoot.getSlice());
    nsr.setWhereClause(subqueryRoot.getWhereClause());
    nsr.setBindingsClause(subqueryRoot.getBindingsClause());

    sa.getQueryRoot().getNamedSubqueriesNotNull().add(nsr);
  }