}
@Override
protected BasicOperator generateJoin(final InnerNodePlan inp, final Root root, final BasicOperator left, final BasicOperator right, final Collection<Variable> sortCriterium, final Map<TriplePattern, Map<Variable, VarBucket>> selectivity){
Join join;
Operator last;
if (this.RDF3XSORT) {
if (sortCriterium.size() == 0 || equalCriterium(sortCriterium, inp.getOrder())) {
join = new MergeJoinWithoutSorting();
join.setEstimatedCardinality(inp.getCardinality());
last = join;
} else {
join = new MergeJoinWithoutSorting();
join.setEstimatedCardinality(inp.getCardinality());
if (!sortCriterium.equals(inp.getJoinPartner())) {
// insert necessary sort operator
last = FastSort.createInstance(root, inp.getTriplePatterns(), sortCriterium);
join.setEstimatedCardinality(inp.getCardinality());
last.setPrecedingOperator(join);
join.setSucceedingOperator(new OperatorIDTuple(last, 0));
this.moveToLeft(inp.getTriplePatterns(), root);
} else {
last = join;
}
}
if (left instanceof RDF3XIndexScan) {
((RDF3XIndexScan) left).setCollationOrder(inp.getJoinPartner());
}
if (right instanceof RDF3XIndexScan) {
((RDF3XIndexScan) right).setCollationOrder(inp.getJoinPartner());
}
} else {
if (inp.getJoinType() == JoinType.MERGEJOIN) {
if (this.NARYMERGEJOIN) {
throw new UnsupportedOperationException("Deprecated");
// combine existing n-ary merge joins with the one which will be newly created
// int number;
// if (left instanceof NAryMergeJoinWithoutSorting) {
// number = ((NAryMergeJoinWithoutSorting) left).getNumberOfOperands();
// } else {
// number = 1;
// }
// if (right instanceof NAryMergeJoinWithoutSorting) {
// number += ((NAryMergeJoinWithoutSorting) right).getNumberOfOperands();
// } else {
// number += 1;
// }
// // determine minima and maxima...
// Bindings min = Bindings.createNewInstance();
// for (final Variable v : inp.getJoinPartner()) {
// if (inp.getSelectivity() == null) {
// min = null;
// break;
// }
// final VarBucket vb = inp.getSelectivity().get(v);
// if (vb == null) {
// min = null;
// break;
// }
// min.add(v, vb.minimum);
// }
// Bindings max = Bindings.createNewInstance();
// for (final Variable v : inp.getJoinPartner()) {
// if (inp.getSelectivity() == null) {
// max = null;
// break;
// }
// final VarBucket vb = inp.getSelectivity().get(v);
// if (vb == null) {
// max = null;
// break;
// }
// max.add(v, vb.maximum);
// }
// join = new NAryMergeJoinWithoutSorting(number, min, max);
// final BasicOperator[] bos = new BasicOperator[number];
//
// int index2 = 0;
// if (left instanceof NAryMergeJoinWithoutSorting) {
// for (final BasicOperator bo : left
// .getPrecedingOperators()) {
// bos[index2++] = bo;
// join.addPrecedingOperator(bo);
// }
// } else {
// bos[index2++] = left;
// join.addPrecedingOperator(left);
// }
// if (right instanceof NAryMergeJoinWithoutSorting) {
// for (final BasicOperator bo : right
// .getPrecedingOperators()) {
// bos[index2++] = bo;
// join.addPrecedingOperator(bo);
// }
// } else {
// bos[index2++] = right;
// join.addPrecedingOperator(right);
// }
// if (min != null){
// Arrays.sort(bos, new Comparator<Object>() {
// @Override
// public int compare(final Object o1, final Object o2) {
// final double sel1 = selectivity.get(
// ((BasicIndexScan) o1).getTriplePattern().iterator().next()).values().iterator().next().getSumDistinctLiterals();
// final double sel2 = selectivity.get(
// ((BasicIndexScan) o2).getTriplePattern().iterator().next()).values().iterator().next().getSumDistinctLiterals();
// if (sel1 < sel2){
// return -1;
// } else if (sel2 < sel1){
// return 1;
// } else {
// return 0;
// }
// }
// });
// }
// for (int i = 0; i < bos.length; i++) {
// bos[i].setSucceedingOperator(new OperatorIDTuple(join, i));
// }
} else {
join = new MergeJoinWithoutSorting();
}
join.setEstimatedCardinality(inp.getCardinality());
last = join;
if (left instanceof RDF3XIndexScan) {
((RDF3XIndexScan) left).setCollationOrder(inp.getJoinPartner());
}
if (right instanceof RDF3XIndexScan) {
((RDF3XIndexScan) right).setCollationOrder(inp.getJoinPartner());
}
} else {
join = new Join();
join.setEstimatedCardinality(inp.getCardinality());
last = join;
}
}
// optimize the order of executions of the left and right operand...
if (!(inp.getLeft() instanceof InnerNodePlan && ((InnerNodePlan) inp.getLeft()).getJoinType() == JoinType.DEFAULT)
&& (inp.getRight() instanceof InnerNodePlan && ((InnerNodePlan) inp.getRight()).getJoinType() == JoinType.DEFAULT)
|| (inp.getLeft() instanceof LeafNodePlan && inp.getRight() instanceof InnerNodePlan)) {
this.moveToLeft(inp.getRight().getTriplePatterns(), root);
} else if (!(inp.getRight() instanceof InnerNodePlan && ((InnerNodePlan) inp.getRight()).getJoinType() == JoinType.DEFAULT)
&& (inp.getLeft() instanceof InnerNodePlan && ((InnerNodePlan) inp.getLeft()).getJoinType() == JoinType.DEFAULT)
|| (inp.getRight() instanceof LeafNodePlan && inp.getLeft() instanceof InnerNodePlan)) {
this.moveToLeft(inp.getLeft().getTriplePatterns(), root);
} else if (inp.getLeft().getCost() > inp.getRight().getCost()) {
log.debug("Card. of joins with estimated lower cost vs. est. higher cost: {} <-> {}",
inp.getRight().getCardinality(), inp.getLeft().getCardinality());
log.debug("Cost of joins with estimated lower cost vs. est. higher cost: {} <-> {}",
inp.getRight().getCost(), inp.getLeft().getCost());
this.moveToLeft(inp.getRight().getTriplePatterns(), root);
} else {
log.debug("Card. of joins with estimated lower cost vs. est. higher cost: {} <-> {}",
inp.getLeft().getCardinality(), inp.getRight().getCardinality());
log.debug("Cost of joins with estimated lower cost vs. est. higher cost: {} <-> {}",
inp.getLeft().getCost(), inp.getRight().getCost());
this.moveToLeft(inp.getLeft().getTriplePatterns(), root);
}
join.setIntersectionVariables(inp.getJoinPartner());
final HashSet<Variable> unionVars = new HashSet<Variable>();
for(final TriplePattern tp: inp.getTriplePatterns()){
unionVars.addAll(tp.getVariables());
}
join.setUnionVariables(unionVars);
if (!last.equals(join)) {
final LinkedList<Variable> llv = new LinkedList<Variable>();
llv.addAll(join.getUnionVariables());
last.setIntersectionVariables(llv);
last.setUnionVariables(llv);
}
if (!(join instanceof NAryMergeJoinWithoutSorting)) {
left.setSucceedingOperator(new OperatorIDTuple(join, 0));
right.setSucceedingOperator(new OperatorIDTuple(join, 1));
join.addPrecedingOperator(left);