static protected PipelineOp convertRTOJoinGraph(PipelineOp left,final JoinGroupNode joinGroup,final Set<IVariable<?>> doneSet,final AST2BOpContext ctx,final AtomicInteger start){
  final Set<IVariable<?>> doneSetIn=Collections.unmodifiableSet(doneSet);
  if (onlySimpleJoins && ctx.isQuads()) {
    return left;
  }
  final int arity=joinGroup.arity();
  final JoinGroupNode rtoJoinGroup=new JoinGroupNode();
  rtoJoinGroup.setQueryHints(joinGroup.getQueryHints());
  @SuppressWarnings("rawtypes") final LinkedList<Predicate> preds=new LinkedList<Predicate>();
  final List<IConstraint> constraints=new LinkedList<IConstraint>();
  int naccepted=0;
{
    final Set<IVariable<?>> doneSetTmp=new LinkedHashSet<IVariable<?>>(doneSet);
    for (int i=start.get(); i < arity; i++) {
      final IGroupMemberNode child=(IGroupMemberNode)joinGroup.get(i);
      if (child instanceof StatementPatternNode) {
        StatementPatternNode sp=(StatementPatternNode)child;
        final boolean optional=sp.isOptional();
        if (onlyRequiredJoins && optional) {
          break;
        }
        final List<IConstraint> attachedConstraints=getJoinConstraints(sp);
        @SuppressWarnings("rawtypes") final Map<IConstraint,Set<IVariable<IV>>> needsMaterialization=new LinkedHashMap<IConstraint,Set<IVariable<IV>>>();
        getJoinConstraints(attachedConstraints,needsMaterialization);
        if (onlySimpleJoins && !needsMaterialization.isEmpty()) {
          break;
        }
        sp=(StatementPatternNode)sp.clone();
        rtoJoinGroup.addChild(sp);
        naccepted++;
        final Predicate<?> pred=AST2BOpUtility.toPredicate(sp,ctx);
        preds.add(pred);
        sp.setProperty(Annotations.PREDICATE_ID,pred.getId());
        if (attachedConstraints != null) {
          constraints.addAll(attachedConstraints);
        }
      }
 else {
        if (onlySPs)         break;
        throw new UnsupportedOperationException();
      }
    }
    if (naccepted < RTO_MIN_JOINS) {
      return left;
    }
    doneSet.addAll(doneSetTmp);
  }
  final SampleType sampleType=joinGroup.getProperty(QueryHints.RTO_SAMPLE_TYPE,QueryHints.DEFAULT_RTO_SAMPLE_TYPE);
  final int limit=joinGroup.getProperty(QueryHints.RTO_LIMIT,QueryHints.DEFAULT_RTO_LIMIT);
  final int nedges=joinGroup.getProperty(QueryHints.RTO_NEDGES,QueryHints.DEFAULT_RTO_NEDGES);
  left=new JoinGraph(leftOrEmpty(left),new NV(BOp.Annotations.BOP_ID,ctx.nextId()),new NV(BOp.Annotations.EVALUATION_CONTEXT,BOpEvaluationContext.CONTROLLER),new NV(BOp.Annotations.CONTROLLER,true),new NV(JoinGraph.Annotations.VERTICES,preds.toArray(new Predicate[preds.size()])),new NV(JoinGraph.Annotations.CONSTRAINTS,constraints.toArray(new IConstraint[constraints.size()])),new NV(JoinGraph.Annotations.JOIN_GROUP,rtoJoinGroup),new NV(JoinGraph.Annotations.LIMIT,limit),new NV(JoinGraph.Annotations.NEDGES,nedges),new NV(JoinGraph.Annotations.SAMPLE_TYPE,sampleType.name()),new NV(JoinGraph.Annotations.DONE_SET,doneSetIn),new NV(JoinGraph.Annotations.NT,new NT(ctx.getNamespace(),ctx.getTimestamp())));
  start.addAndGet(naccepted);
  return left;
}

static protected PipelineOp convertRTOJoinGraph ( PipelineOp left , final JoinGroupNode joinGroup , final Set < IVariable < ? > > doneSet , final AST2BOpContext ctx , final AtomicInteger start ) { final Set < IVariable < ? > > doneSetIn = Collections . unmodifiableSet ( doneSet ) ; if ( onlySimpleJoins && ctx . isQuads ( ) ) { return left ; } final int arity = joinGroup . arity ( ) ; final JoinGroupNode rtoJoinGroup = new JoinGroupNode ( ) ; rtoJoinGroup . setQueryHints ( joinGroup . getQueryHints ( ) ) ; @ SuppressWarnings ( "rawtypes" ) final LinkedList < Predicate > preds = new LinkedList < Predicate > ( ) ; final List < IConstraint > constraints = new LinkedList < IConstraint > ( ) ; int naccepted = 0 ; { final Set < IVariable < ? > > doneSetTmp = new LinkedHashSet < IVariable < ? > > ( doneSet ) ; for ( int i = start . get ( ) ; i < arity ; i ++ ) { final IGroupMemberNode child = ( IGroupMemberNode ) joinGroup . get ( i ) ; if ( child instanceof StatementPatternNode ) { StatementPatternNode sp = ( StatementPatternNode ) child ; final boolean optional = sp . isOptional ( ) ; if ( onlyRequiredJoins && optional ) { break ; } final List < IConstraint > attachedConstraints = getJoinConstraints ( sp ) ; @ SuppressWarnings ( "rawtypes" ) final Map < IConstraint , Set < IVariable < IV > > > needsMaterialization = new LinkedHashMap < IConstraint , Set < IVariable < IV > > > ( ) ; getJoinConstraints ( attachedConstraints , needsMaterialization ) ; if ( onlySimpleJoins && ! needsMaterialization . isEmpty ( ) ) { break ; } sp = ( StatementPatternNode ) sp . clone ( ) ; rtoJoinGroup . addChild ( sp ) ; naccepted ++ ; final Predicate < ? > pred = AST2BOpUtility . toPredicate ( sp , ctx ) ; preds . add ( pred ) ; sp . setProperty ( Annotations . PREDICATE_ID , pred . getId ( ) ) ; if ( attachedConstraints != null ) { constraints . addAll ( attachedConstraints ) ; } } else { if ( onlySPs ) break ; throw new UnsupportedOperationException ( ) ; } } if ( naccepted < RTO_MIN_JOINS ) { return left ; } doneSet . addAll ( doneSetTmp ) ; } final SampleType sampleType = joinGroup . getProperty ( QueryHints . RTO_SAMPLE_TYPE , QueryHints . DEFAULT_RTO_SAMPLE_TYPE ) ; final int limit = joinGroup . getProperty ( QueryHints . RTO_LIMIT , QueryHints . DEFAULT_RTO_LIMIT ) ; final int nedges = joinGroup . getProperty ( QueryHints . RTO_NEDGES , QueryHints . DEFAULT_RTO_NEDGES ) ; left = new JoinGraph ( leftOrEmpty ( left ) , new NV ( BOp . Annotations . BOP_ID , ctx . nextId ( ) ) , new NV ( BOp . Annotations . EVALUATION_CONTEXT , BOpEvaluationContext . CONTROLLER ) , new NV ( BOp . Annotations . CONTROLLER , true ) , new NV ( JoinGraph . Annotations . VERTICES , preds . toArray ( new Predicate [ preds . size ( ) ] ) ) , new NV ( JoinGraph . Annotations . CONSTRAINTS , constraints . toArray ( new IConstraint [ constraints . size ( ) ] ) ) , new NV ( JoinGraph . Annotations . JOIN_GROUP , rtoJoinGroup ) , new NV ( JoinGraph . Annotations . LIMIT , limit ) , new NV ( JoinGraph . Annotations . NEDGES , nedges ) , new NV ( JoinGraph . Annotations . SAMPLE_TYPE , sampleType . name ( ) ) , new NV ( JoinGraph . Annotations . DONE_SET , doneSetIn ) , new NV ( JoinGraph . Annotations . NT , new NT ( ctx . getNamespace ( ) , ctx . getTimestamp ( ) ) ) ) ; start . addAndGet ( naccepted ) ; return left ; }
inspect the remainder of the join group . if we can isolate a join graph and filters , then we will push them down into an rto joingroup . since the joins have already been ordered by the static optimizer , we can accept them in sequence along with any attachable filters and ( if we get at least 3 predicates ) push them down into an rto join group . < p > note : two predicates in a join group is not enough for the rto to provide a different join ordering . both the static optimizer and the rto will always choose the ap with the smaller cardinality to run first . if there are only 2 predicates , then the other predicate will run second . you need at least three predicates before the rto could provide a different answer .
