final Integer[] minArray = new Integer[hmvi.size()];
final Integer[] maxArray = new Integer[hmvi.size()];
final Iterator<Bindings> itbSize = qrSize.oneTimeIterator();
while (itbSize.hasNext()) {
final Bindings b = itbSize.next();
for (final Variable v : b.getVariableSet()) {
final LazyLiteral ll = (LazyLiteral) b.get(v);
final int pos = hmvi.get(v);
if (minArray[pos] == null || minArray[pos] > ll.getCode()) {
minArray[pos] = ll.getCode();
}
if (maxArray[pos] == null || maxArray[pos] < ll.getCode()) {
maxArray[pos] = ll.getCode();
}
}
size++;
for (int i = 0; i < minArray.length; i++) {
if (minArray[i] != null) {
tp.addMinMaxLazyLiteral(i, minArray[i], maxArray[i]);
}
}
}
} else {
int maxId = 1;
if (qrSize instanceof IdIteratorQueryResult) {
maxId = ((IdIteratorQueryResult) qrSize).getMaxId();
}
final int[][] min = new int[maxId][];
final int[][] max = new int[maxId][];
size = qrSize.oneTimeSize();
for (int id = 0; id < maxId; id++) {
if (min[id] != null) {
for (int i = 0; i < min[id].length; i++) {
tp.addMinMaxPresortingNumbers(i, min[id].length,
id, min[id][i], max[id][i]);
}
}
}
}
qrSize.release();
if (size == 0) {
System.out.println("No result for " + tp);
return null;
}
// System.out.println("(Statistics) " + tp + ", " + size
// + " triples retrieved");
tp.setCardinality(size);
for (final Variable v : joinPartnersTP) {
if (intermediate != null && intermediate.containsKey(v)) {
boolean flag = true;
final Literal min = minima.get(v);
if (intermediate.get(v) == null
|| min != null
&& (intermediate.get(v).minimum == null || !min
.equals(intermediate.get(v).minimum))) {
flag = false;
}
final Literal max = maxima.get(v);
if (max != null
&& (intermediate.get(v).maximum == null || !max
.equals(intermediate.get(v).maximum))) {
flag = false;
}
if (flag) {
result.put(v, intermediate.get(v));
continue;
}
}
// get result of triple pattern in the correct sorted way!
final Collection<Variable> cv = new LinkedList<Variable>();
cv.add(v);
if (this instanceof RDF3XIndexScan) {
((RDF3XIndexScan) this).setCollationOrder(CollationOrder.getCollationOrder(tp, cv));
}
QueryResult qr = this.join(this.root.dataset);
if (this instanceof MemoryIndexScan) {
// additional sorting phase according to variable v needed
// for memory index approach!
final DBMergeSortedBag<Bindings> sort = new DBMergeSortedBag<Bindings>(
new SortConfiguration(), new Comparator<Bindings>() {
@Override
public int compare(final Bindings arg0, final Bindings arg1) {
return arg0.get(v).compareToNotNecessarilySPARQLSpecificationConform(arg1.get(v));
}
}, Bindings.class);
final Iterator<Bindings> itb = qr.oneTimeIterator();
while (itb.hasNext()) {
sort.add(itb.next());
}
qr = QueryResult.createInstance(sort.iterator());
}
if (qr == null) {
return result;
}
if (size == 0) {
qr.release();
return result;
}
final double bucketSize = (double) size / MaxNumberBuckets;
final Iterator<Bindings> ib = qr.oneTimeIterator();
final VarBucket vb = new VarBucket();
vb.minimum = minima.get(v);
vb.maximum = maxima.get(v);
Entry currentEntry = new Entry();
Literal lastLiteral = null;
while (ib.hasNext()) {
final Bindings b = ib.next();
final Literal next = b.get(v);
if (lastLiteral == null
|| lastLiteral
.compareToNotNecessarilySPARQLSpecificationConform(next) != 0) {
currentEntry.distinctLiterals += 1.0;
lastLiteral = next;
}
currentEntry.selectivity += 1.0;
if (currentEntry.selectivity >= bucketSize) {
currentEntry.literal = b.get(v);
if (ib.hasNext()) {
Bindings b2 = ib.next();
while (ib.hasNext()
&& b2
.get(v)
.compareToNotNecessarilySPARQLSpecificationConform(
currentEntry.literal) == 0) {
currentEntry.selectivity += 1.0;
b2 = ib.next();
}
vb.selectivityOfInterval.add(currentEntry);
currentEntry = new Entry();
currentEntry.distinctLiterals = 1.0;
currentEntry.selectivity = 1.0;
if (!ib.hasNext()
&& b2
.get(v)
.compareToNotNecessarilySPARQLSpecificationConform(
next) != 0) {
currentEntry.literal = b2.get(v);
vb.selectivityOfInterval.add(currentEntry);
}
} else {
vb.selectivityOfInterval.add(currentEntry);
}