/** Returns the simplest expression matching this */ private String toExpression(Limit from, Limit to, int hitLimit) { if (from.equals(to) && hitLimit == 0) return from.number().toString(); String expression = from.toRangeStart() + ";" + to.toRangeEnd(); if (hitLimit == 0) return expression; // Insert ;hitLimit at the end inside the brackets return expression.substring(0, expression.length()-1) + ";" + hitLimit + expression.substring(expression.length()-1); }
public boolean isSmallerOrEqualTo(Limit other) { double thisNumber = this.number().doubleValue(); double otherNumber = other.number().doubleValue(); if (thisNumber == otherNumber) { if ( ! other.isInclusive()) return false; return true; } return thisNumber < otherNumber; }
/** Returns true if these two ranges overlap */ public boolean overlaps(Range other) { if (other.from.isSmallerOrEqualTo(this.to) && other.to.isLargerOrEqualTo(this.from)) return true; if (other.to.isLargerOrEqualTo(this.from) && other.from.isSmallerOrEqualTo(this.to)) return true; return false; }
@Override boolean serialize(StringBuilder destination, Item item) { IntItem intItem = (IntItem) item; if (intItem.getFromLimit().number().equals(intItem.getToLimit().number())) { destination.append(normalizeIndexName(intItem.getIndexName())).append(" = "); annotatedNumberImage(intItem, intItem.getFromLimit().number().toString(), destination); } else if (intItem.getFromLimit().isInfinite()) { destination.append(normalizeIndexName(intItem.getIndexName())); destination.append(intItem.getToLimit().isInclusive() ? " <= " : " < "); annotatedNumberImage(intItem, intItem.getToLimit().number().toString(), destination); } else if (intItem.getToLimit().isInfinite()) { destination.append(normalizeIndexName(intItem.getIndexName())); destination.append(intItem.getFromLimit().isInclusive() ? " >= " : " > "); annotatedNumberImage(intItem, intItem.getFromLimit().number().toString(), destination); } else { serializeAsRange(destination, intItem); } return false; }
/** * Creates an int item from arguments. * This will return an instance of the RankItem subclass if either <code>hitLimit</code> or both <code>from</code> * and <code>to</code> is set to a value other than defaults (respectively 0, double negative and positive infinity). * And different from each other. * * @param indexName the index this searches * @param from the lower limit (inclusive) on hits * @param to the higher limit (inclusive) on hits * @param hitLimit the number of hits to match, or 0 to return all */ public static IntItem from(String indexName, Limit from, Limit to, int hitLimit) { if (hitLimit == 0 && (from.equals(Limit.NEGATIVE_INFINITY) || to.equals(Limit.POSITIVE_INFINITY) || from.equals(to))) return new IntItem(from, to, indexName); else { return new RangeItem(from, to, hitLimit, indexName, false); } }
String toRangeStart() { return (inclusive ? "[" : "<" ) + (isInfinite() ? "" : number.toString()); }
/** Returns the smaller of this and the given limit */ public Limit min(Limit other) { return this.isSmallerOrEqualTo(other) ? this : other; }
/** Returns the larger of this and the given limit */ public Limit max(Limit other) { return this.isLargerOrEqualTo(other) ? this : other; }
/** Returns the upper limit of this range, which may be positive infinity */ public final Number getTo() { return getToLimit().number(); }
@Override public boolean equals(Object object) { if ( ! super.equals(object)) return false; IntItem other = (IntItem) object; // Ensured by superclass if ( ! getFromLimit().equals(other.getFromLimit())) return false; if ( ! getToLimit().equals(other.getToLimit())) return false; if ( getHitLimit() != other.getHitLimit()) return false; return true; }
String toRangeEnd() { return (isInfinite() ? "" : number.toString()) + (inclusive ? "]" : ">" ); }
public boolean isLargerOrEqualTo(Limit other) { double thisNumber = this.number().doubleValue(); double otherNumber = other.number().doubleValue(); if (thisNumber == otherNumber) { if ( ! other.isInclusive()) return false; return true; } return thisNumber > otherNumber; }
/** Returns the lower limit of this range, which may be negative infinity */ public final Number getFrom() { return getFromLimit().number(); }
private boolean optimizeAnd(AndItem and, IndexFacts.Session indexFacts) { // Find consolidated ranges by collecting a list of compatible ranges List<FieldRange> fieldRanges = null; for (Iterator<Item> i = and.getItemIterator(); i.hasNext(); ) { Item item = i.next(); if ( ! (item instanceof IntItem)) continue; IntItem intItem = (IntItem)item; if (intItem.getHitLimit() != 0) continue; // each such op gets a different partial set: Cannot be optimized if (intItem.getFromLimit().equals(intItem.getToLimit())) continue; // don't optimize searches for single numbers if (indexFacts.getIndex(intItem.getIndexName()).isMultivalue()) continue; // May match different values in each range if (fieldRanges == null) fieldRanges = new ArrayList<>(); Optional<FieldRange> compatibleRange = findCompatibleRange(intItem, fieldRanges); if (compatibleRange.isPresent()) compatibleRange.get().addRange(intItem); else fieldRanges.add(new FieldRange(intItem)); i.remove(); } // Add consolidated ranges if (fieldRanges == null) return false; boolean optimized = false; for (FieldRange fieldRange : fieldRanges) { and.addItem(fieldRange.toItem()); optimized |= fieldRange.isOptimization(); } return optimized; }
private void serializeAsRange(StringBuilder destination, IntItem intItem) { String annotations = leafAnnotations(intItem); boolean leftOpen = !intItem.getFromLimit().isInclusive(); boolean rightOpen = !intItem.getToLimit().isInclusive(); String boundsAnnotation = ""; int initLen; .append(", ").append(intItem.getFromLimit().number()) .append(", ").append(intItem.getToLimit().number()) .append(")");