.getPrecedingOperators().get(0),
basicOperator.getUnionVariables())) {
operatorMustReceiveSortedData(root, basicOperator
.getPrecedingOperators().get(0),
basicOperator.getUnionVariables());
final BasicOperator newOperator = new SortedDataDistinct();
newOperator.cloneFrom(basicOperator);
basicOperator.replaceWith(newOperator);
return newOperator;
}
} else if (basicOperator.getClass() == Join.class) {
// root.deleteParents();
// root.setParents();
// root.detectCycles();
// root.sendMessage(new BoundVariablesMessage());
// check if MergeJoinWithoutSorting can be used
boolean flag = true;
if (basicOperator.getIntersectionVariables().size() > 0) {
for (final BasicOperator bo : basicOperator
.getPrecedingOperators()) {
flag = flag
&& operatorCanReceiveSortedData(
bo,
basicOperator
.getIntersectionVariables());
}
} else {
flag = false;
}
if (flag) {
final LinkedList<BasicOperator> llbo = new LinkedList<BasicOperator>();
llbo.addAll(basicOperator.getPrecedingOperators());
for (final BasicOperator bo : llbo) {
operatorMustReceiveSortedData(root, bo,
basicOperator
.getIntersectionVariables());
}
final BasicOperator newOperator = new MergeJoinWithoutSorting();
newOperator.cloneFrom(basicOperator);
basicOperator.replaceWith(newOperator);
return newOperator;
} else {
// do not insert SIP operator in cycles!
if(!(basicOperator.getCycleOperands()!=null && basicOperator.getCycleOperands().size()>0)){
// insert SIP operator for joins other than
// MergeJoinWithoutSorting!
int min = -1;
int minIndex = -1;
int i = 0;
for (final BasicOperator bo : basicOperator
.getPrecedingOperators()) {
final List<TriplePattern> listTps = determineTriplePatterns(
basicOperator,
new LinkedList<TriplePattern>(),
new HashSet<BasicOperator>());
if (listTps.size() > 0) {
final TriplePattern tp = listTps.get(0);
int current = 0;
for (final OperatorIDTuple oid : root
.getSucceedingOperators()) {
if (oid.getOperator() instanceof BasicIndexScan) {
if (((BasicIndexScan) oid.getOperator())
.getTriplePattern()
.contains(tp)) {
if (min == -1 || min > current) {
min = current;
minIndex = i;
}
}
}
current++;
}
}
i++;
}
if (minIndex > -1) {
final BasicOperator bo = basicOperator.getPrecedingOperators().get(minIndex);
if (bo != null && bo.getSucceedingOperators().size()==1) {
if (!this.severalTimesQueryResults(bo, new HashSet<BasicOperator>())) {
List<TriplePattern> tpsOfOthers = null;
for (final BasicOperator others : basicOperator
.getPrecedingOperators()) {
if (!others.equals(bo)) {
if (tpsOfOthers == null) {
tpsOfOthers = determineTriplePatterns(
others,
new LinkedList<TriplePattern>(),
new HashSet<BasicOperator>());
} else {
tpsOfOthers
.addAll(determineTriplePatterns(
others,
new LinkedList<TriplePattern>(),
new HashSet<BasicOperator>()));
}
}
}
this.tpsOfSucceedingJoins(basicOperator, tpsOfOthers);
if (tpsOfOthers != null) {
final SIPFilterOperator sip_op = (replacements
.get(Join.class) == HashMapIndexJoin.class) ? new SIPFilterOperatorIterator(
tpsOfOthers,
basicOperator
.getIntersectionVariables())
: new SIPFilterOperator(tpsOfOthers, basicOperator.getIntersectionVariables());
final List<Variable> intersectionVariables = new LinkedList<Variable>();
final List<Variable> unionVariables = new LinkedList<Variable>();
intersectionVariables.addAll(bo.getIntersectionVariables());
unionVariables.addAll(bo.getUnionVariables());
sip_op.setIntersectionVariables(intersectionVariables);
sip_op.setUnionVariables(unionVariables);
sip_op.addSucceedingOperators(bo.getSucceedingOperators());
sip_op.setPrecedingOperator(bo);
bo.setSucceedingOperator(new OperatorIDTuple(sip_op, 0));
basicOperator.removePrecedingOperator(bo);
basicOperator.addPrecedingOperator(sip_op);
}
}
}
}
}
}
} else if (basicOperator.getClass() == Optional.class) {
// root.deleteParents();
// root.setParents();
// root.detectCycles();
// root.sendMessage(new BoundVariablesMessage());
// check if MergeWithoutSortingOptional can be used
boolean flag = true;
if (basicOperator.getIntersectionVariables().size() > 0) {
for (final BasicOperator bo : basicOperator
.getPrecedingOperators()) {
flag = flag
&& operatorCanReceiveSortedData(
bo,
basicOperator
.getIntersectionVariables());
}
} else {
flag = false;
}
if (flag) {
final LinkedList<BasicOperator> llbo = new LinkedList<BasicOperator>();
llbo.addAll(basicOperator.getPrecedingOperators());
for (final BasicOperator bo : llbo) {
operatorMustReceiveSortedData(root, bo,
basicOperator.getIntersectionVariables());
}
final BasicOperator newOperator = new MergeWithoutSortingOptional();
newOperator.cloneFrom(basicOperator);
basicOperator.replaceWith(newOperator);
return newOperator;
}
} else if (basicOperator instanceof FastSort) {
if (basicOperator.getPrecedingOperators().size() == 1
&& !(basicOperator.getPrecedingOperators().get(0) instanceof SIPFilterOperator)
&& basicOperator.getSucceedingOperators().size() == 1) {
if (basicOperator.getSucceedingOperators().get(0)
.getOperator() instanceof Join) {
final Join join = (Join) basicOperator
.getSucceedingOperators().get(0)
.getOperator();
int min = -1;
int minIndex = -1;
int i = 0;
for (final BasicOperator bo : join
.getPrecedingOperators()) {
final TriplePattern tp = determineTriplePatterns(
join,
new LinkedList<TriplePattern>(),
new HashSet<BasicOperator>())
.get(0);
int current = 0;
for (final OperatorIDTuple oid : root
.getSucceedingOperators()) {
if (oid.getOperator() instanceof BasicIndexScan) {
if (((BasicIndexScan) oid.getOperator())
.getTriplePattern()
.contains(tp)) {
if (min == -1 || min > current) {
min = current;
minIndex = i;
}
}
}
current++;
}
i++;
}
final BasicOperator bo = join.getPrecedingOperators().get(minIndex);
if (bo != null
&& bo instanceof FastSort
&& bo.getPrecedingOperators().size() == 1
&& !(bo.getPrecedingOperators().get(0) instanceof SIPFilterOperator)) {
if (!this.severalTimesQueryResults(bo,
new HashSet<BasicOperator>())) {
List<TriplePattern> tpsOfOthers = null;
for (final BasicOperator others : join
.getPrecedingOperators()) {
if (!others.equals(bo)) {
if (tpsOfOthers == null) {
tpsOfOthers = determineTriplePatterns(
others,
new LinkedList<TriplePattern>(),
new HashSet<BasicOperator>());
} else {
tpsOfOthers
.addAll(determineTriplePatterns(
others,
new LinkedList<TriplePattern>(),
new HashSet<BasicOperator>()));
}
}
}
this.tpsOfSucceedingJoins(join, tpsOfOthers);
final SIPFilterOperator sip_op =
// (replacements
// .get(Join.class) ==
// HashMapIndexJoin.class) ?
new SIPFilterOperatorIterator(
tpsOfOthers,
join.getIntersectionVariables())
// : new
// SIPFilterOperator(tpsOfOthers,join
// .getIntersectionVariables())
;
final List<Variable> intersectionVariables = new LinkedList<Variable>();
final List<Variable> unionVariables = new LinkedList<Variable>();
intersectionVariables.addAll(bo.getIntersectionVariables());
unionVariables.addAll(bo.getUnionVariables());
sip_op.setIntersectionVariables(intersectionVariables);
sip_op.setUnionVariables(unionVariables);
if (bo instanceof FastSort) {
final BasicOperator bo2 = bo
.getPrecedingOperators()
.get(0);
sip_op.addSucceedingOperators(bo2
.getSucceedingOperators());
sip_op.setPrecedingOperator(bo2);
bo2
.setSucceedingOperator(new OperatorIDTuple(
sip_op, 0));
bo.removePrecedingOperator(bo2);
bo.addPrecedingOperator(sip_op);
} else {
sip_op.addSucceedingOperators(bo.getSucceedingOperators());
sip_op.setPrecedingOperator(bo);
bo.setSucceedingOperator(new OperatorIDTuple(sip_op, 0));
join.removePrecedingOperator(bo);
join.addPrecedingOperator(sip_op);
}
}
}
}
}
} else if (basicOperator instanceof Sort) {
BasicOperator sortlimit = basicOperator;
if (basicOperator.getPrecedingOperators().size() == 1) {
final BasicOperator prec = basicOperator
.getPrecedingOperators().get(0);
if (prec instanceof SortLimit) {
sortlimit = prec;
}
}
final Collection<Variable> sortCriterium = ((Sort) basicOperator)
.getSortCriterium();
boolean flag;
if (sortCriterium != null
&& (LiteralFactory.getMapType() != LiteralFactory.MapType.LAZYLITERAL)
&& (LiteralFactory.getMapType() != LiteralFactory.MapType.LAZYLITERALWITHOUTINITIALPREFIXCODEMAP)) {
flag = true;
for (final BasicOperator bo : sortlimit
.getPrecedingOperators()) {
flag = flag
&& operatorCanReceiveSortedData(bo,
sortCriterium);
}
} else {
flag = false;
}
if (flag) {
final LinkedList<BasicOperator> llbo = new LinkedList<BasicOperator>();
llbo.addAll(sortlimit.getPrecedingOperators());
for (final BasicOperator bo : llbo) {
bo.removeSucceedingOperator(sortlimit);
bo.addSucceedingOperators(basicOperator
.getSucceedingOperators());
for (final OperatorIDTuple oID : basicOperator
.getSucceedingOperators()) {
oID.getOperator().removePrecedingOperator(
basicOperator);
oID.getOperator().addPrecedingOperator(bo);
}
operatorMustReceiveSortedData(root, bo,
sortCriterium);
}
return null;
}
}
}
} catch(final CyclesDuringDeterminationofTriplePatternsException e){
}
final Class<? extends BasicOperator> newClass = replacements
.get(basicOperator.getClass());
BasicOperator newOperator = basicOperator;
if (newClass != null) {
try {
newOperator = newClass.newInstance();
} catch (final Exception ex) {
ex.printStackTrace();
System.err.println(ex);
}
newOperator.cloneFrom(basicOperator);
basicOperator.replaceWith(newOperator);
if (basicOperator.getClass() == Join.class
&& newOperator instanceof MergeJoinWithoutSortingSeveralIterations) {
// Insert necessary sort operators here...
final LinkedList<BasicOperator> llbo = new LinkedList<BasicOperator>();
llbo.addAll(newOperator.getPrecedingOperators());
for (final BasicOperator bo : llbo) {
final List<Variable> sortCriterium = new LinkedList<Variable>();
sortCriterium.addAll(basicOperator
.getIntersectionVariables());
if (!(root instanceof PatternMatcher)
&& !(root instanceof Stream)
&& operatorCanReceiveSortedData(
bo,
basicOperator
.getIntersectionVariables())) {
operatorMustReceiveSortedData(root, bo,
basicOperator
.getIntersectionVariables());
} else {
final ImmediateSort immediateSort = new ImmediateSort(
sortCriterium);
final List<Variable> vars = new LinkedList<Variable>();
vars.addAll(basicOperator
.getIntersectionVariables());
immediateSort.setUnionVariables(vars);
immediateSort.setIntersectionVariables(vars);
immediateSort.addPrecedingOperator(bo);
immediateSort
.addSucceedingOperator(new OperatorIDTuple(
newOperator, bo
.getOperatorIDTuple(
newOperator)
.getId()));
bo.getOperatorIDTuple(newOperator).setOperator(
immediateSort);
newOperator.removePrecedingOperator(bo);
}
}
}
}
return newOperator;
}
private void tpsOfSucceedingJoins(final BasicOperator bo,
List<TriplePattern> tpsOfOthers) throws CyclesDuringDeterminationofTriplePatternsException {
if (bo.getSucceedingOperators().size() == 1) {
final BasicOperator sbo = bo.getSucceedingOperators()
.get(0).getOperator();
if (sbo instanceof Join) {
if (sbo.getPrecedingOperators().size() == 2) {
for (final BasicOperator op : sbo
.getPrecedingOperators()) {
if (!op.equals(bo)) {
if (tpsOfOthers == null) {
tpsOfOthers = determineTriplePatterns(
op,
new LinkedList<TriplePattern>(),
new HashSet<BasicOperator>());
} else {
tpsOfOthers
.addAll(determineTriplePatterns(
op,
new LinkedList<TriplePattern>(),
new HashSet<BasicOperator>()));
}
}
}
}
this.tpsOfSucceedingJoins(sbo, tpsOfOthers);
}
}
}
private boolean severalTimesQueryResults(
final BasicOperator basicOperator,
final Set<BasicOperator> alreadyVisited) {
if (alreadyVisited.contains(basicOperator)) {
// loop detected!
return true;
}
alreadyVisited.add(basicOperator);
if (basicOperator instanceof Union) {
if (!(basicOperator instanceof MergeUnion)) {
return true;
}
} else if (basicOperator instanceof BasicIndexScan) {
return false;
} else {
if (basicOperator.getPrecedingOperators() != null) {
for (final BasicOperator predecessor : basicOperator
.getPrecedingOperators()) {
if (this.severalTimesQueryResults(predecessor,
alreadyVisited)) {
return true;
}
}
}
}
return false;
}
};
final BasicOperator newRoot = (BasicOperator) op.visit(sogv);
// now replace any merge joins and merge optionals with maybe their
// parallel versions...
final SimpleOperatorGraphVisitor sogvMergeJoinsAndOptionals = new SimpleOperatorGraphVisitor() {
@Override
public Object visit(final BasicOperator basicOperator) {
final Class<? extends BasicOperator> newClass = replacementsMergeJoinAndMergeOptional
.get(basicOperator.getClass());
BasicOperator newOperator = basicOperator;
if (newClass != null) {
try {
newOperator = newClass.newInstance();
} catch (final Exception ex) {
ex.printStackTrace();
System.err.println(ex);
}
newOperator.cloneFrom(basicOperator);
basicOperator.replaceWith(newOperator);
}
return newOperator;
}
};