use of org.apache.druid.query.filter.OrDimFilter in project druid by druid-io.
the class MoveTimeFiltersToIntervals method extractConvertibleTimeBounds.
/**
* Extract bound filters on __time that can be converted to query-level "intervals".
*
* @return pair of new dimFilter + RangeSet of __time that should be ANDed together. Either can be null but not both.
*/
private static Pair<DimFilter, RangeSet<Long>> extractConvertibleTimeBounds(final DimFilter filter) {
if (filter instanceof AndDimFilter) {
final List<DimFilter> children = ((AndDimFilter) filter).getFields();
final List<DimFilter> newChildren = new ArrayList<>();
final List<RangeSet<Long>> rangeSets = new ArrayList<>();
for (DimFilter child : children) {
final Pair<DimFilter, RangeSet<Long>> pair = extractConvertibleTimeBounds(child);
if (pair.lhs != null) {
newChildren.add(pair.lhs);
}
if (pair.rhs != null) {
rangeSets.add(pair.rhs);
}
}
final DimFilter newFilter;
if (newChildren.size() == 0) {
newFilter = null;
} else if (newChildren.size() == 1) {
newFilter = newChildren.get(0);
} else {
newFilter = new AndDimFilter(newChildren);
}
return Pair.of(newFilter, rangeSets.isEmpty() ? null : RangeSets.intersectRangeSets(rangeSets));
} else if (filter instanceof OrDimFilter) {
final List<DimFilter> children = ((OrDimFilter) filter).getFields();
final List<RangeSet<Long>> rangeSets = new ArrayList<>();
boolean allCompletelyConverted = true;
boolean allHadIntervals = true;
for (DimFilter child : children) {
final Pair<DimFilter, RangeSet<Long>> pair = extractConvertibleTimeBounds(child);
if (pair.lhs != null) {
allCompletelyConverted = false;
}
if (pair.rhs != null) {
rangeSets.add(pair.rhs);
} else {
allHadIntervals = false;
}
}
if (allCompletelyConverted) {
return Pair.of(null, RangeSets.unionRangeSets(rangeSets));
} else {
return Pair.of(filter, allHadIntervals ? RangeSets.unionRangeSets(rangeSets) : null);
}
} else if (filter instanceof NotDimFilter) {
final DimFilter child = ((NotDimFilter) filter).getField();
final Pair<DimFilter, RangeSet<Long>> pair = extractConvertibleTimeBounds(child);
if (pair.rhs != null && pair.lhs == null) {
return Pair.of(null, pair.rhs.complement());
} else {
return Pair.of(filter, null);
}
} else if (filter instanceof BoundDimFilter) {
final BoundDimFilter bound = (BoundDimFilter) filter;
if (BoundRefKey.from(bound).equals(TIME_BOUND_REF_KEY)) {
return Pair.of(null, RangeSets.of(toLongRange(Bounds.toRange(bound))));
} else {
return Pair.of(filter, null);
}
} else {
return Pair.of(filter, null);
}
}
use of org.apache.druid.query.filter.OrDimFilter in project druid by druid-io.
the class CombineAndSimplifyBounds method process.
@Override
public DimFilter process(DimFilter filter) {
if (filter instanceof FalseDimFilter) {
// we might sometimes come into here with just a false from optimizing impossible conditions
return filter;
} else if (filter instanceof AndDimFilter) {
final List<DimFilter> children = getAndFilterChildren((AndDimFilter) filter);
final DimFilter one = doSimplifyAnd(children);
final DimFilter two = negate(doSimplifyOr(negateAll(children)));
return computeCost(one) <= computeCost(two) ? one : two;
} else if (filter instanceof OrDimFilter) {
final List<DimFilter> children = getOrFilterChildren((OrDimFilter) filter);
final DimFilter one = doSimplifyOr(children);
final DimFilter two = negate(doSimplifyAnd(negateAll(children)));
return computeCost(one) <= computeCost(two) ? one : two;
} else if (filter instanceof NotDimFilter) {
final DimFilter field = ((NotDimFilter) filter).getField();
final DimFilter candidate;
if (field instanceof OrDimFilter) {
candidate = doSimplifyAnd(negateAll(getOrFilterChildren((OrDimFilter) field)));
} else if (field instanceof AndDimFilter) {
candidate = doSimplifyOr(negateAll(getAndFilterChildren((AndDimFilter) field)));
} else {
candidate = negate(field);
}
return computeCost(filter) <= computeCost(candidate) ? filter : candidate;
} else {
return filter;
}
}
use of org.apache.druid.query.filter.OrDimFilter in project druid by druid-io.
the class ConvertSelectorsToIns method process.
@Override
public DimFilter process(DimFilter filter) {
if (filter instanceof OrDimFilter) {
// Copy children list
final List<DimFilter> children = Lists.newArrayList(((OrDimFilter) filter).getFields());
// Group filters by dimension and extractionFn.
final Map<BoundRefKey, List<SelectorDimFilter>> selectors = new HashMap<>();
for (DimFilter child : children) {
if (child instanceof SelectorDimFilter) {
final SelectorDimFilter selector = (SelectorDimFilter) child;
final BoundRefKey boundRefKey = BoundRefKey.from(selector, RowSignatures.getNaturalStringComparator(sourceRowSignature, SimpleExtraction.of(selector.getDimension(), selector.getExtractionFn())));
List<SelectorDimFilter> filterList = selectors.computeIfAbsent(boundRefKey, k -> new ArrayList<>());
filterList.add(selector);
}
}
// Emit IN filters for each group of size > 1.
for (Map.Entry<BoundRefKey, List<SelectorDimFilter>> entry : selectors.entrySet()) {
final List<SelectorDimFilter> filterList = entry.getValue();
if (filterList.size() > 1) {
// We found a simplification. Remove the old filters and add new ones.
final Set<String> values = Sets.newHashSetWithExpectedSize(filterList.size());
for (final SelectorDimFilter selector : filterList) {
values.add(selector.getValue());
if (!children.remove(selector)) {
// Don't expect this to happen, but include it as a sanity check.
throw new ISE("Tried to remove selector but couldn't");
}
}
children.add(new InDimFilter(entry.getKey().getDimension(), values, entry.getKey().getExtractionFn(), null));
}
}
if (!children.equals(((OrDimFilter) filter).getFields())) {
return children.size() == 1 ? children.get(0) : new OrDimFilter(children);
} else {
return filter;
}
} else {
return filter;
}
}
use of org.apache.druid.query.filter.OrDimFilter in project hive by apache.
the class DruidStorageHandlerUtils method toDruidFilter.
@Nullable
private static DimFilter toDruidFilter(ExprNodeDesc filterExpr, Configuration configuration, List<VirtualColumn> virtualColumns, boolean resolveDynamicValues) {
if (filterExpr == null) {
return null;
}
Class<? extends GenericUDF> genericUDFClass = getGenericUDFClassFromExprDesc(filterExpr);
if (FunctionRegistry.isOpAnd(filterExpr)) {
Iterator<ExprNodeDesc> iterator = filterExpr.getChildren().iterator();
List<DimFilter> delegates = Lists.newArrayList();
while (iterator.hasNext()) {
DimFilter filter = toDruidFilter(iterator.next(), configuration, virtualColumns, resolveDynamicValues);
if (filter != null) {
delegates.add(filter);
}
}
if (!delegates.isEmpty()) {
return new AndDimFilter(delegates);
}
}
if (FunctionRegistry.isOpOr(filterExpr)) {
Iterator<ExprNodeDesc> iterator = filterExpr.getChildren().iterator();
List<DimFilter> delegates = Lists.newArrayList();
while (iterator.hasNext()) {
DimFilter filter = toDruidFilter(iterator.next(), configuration, virtualColumns, resolveDynamicValues);
if (filter != null) {
delegates.add(filter);
}
}
if (!delegates.isEmpty()) {
return new OrDimFilter(delegates);
}
} else if (GenericUDFBetween.class == genericUDFClass) {
List<ExprNodeDesc> child = filterExpr.getChildren();
String col = extractColName(child.get(1), virtualColumns);
if (col != null) {
try {
StringComparator comparator = stringTypeInfos.contains(child.get(1).getTypeInfo()) ? StringComparators.LEXICOGRAPHIC : StringComparators.NUMERIC;
String lower = evaluate(child.get(2), configuration, resolveDynamicValues);
String upper = evaluate(child.get(3), configuration, resolveDynamicValues);
return new BoundDimFilter(col, lower, upper, false, false, null, null, comparator);
} catch (HiveException e) {
throw new RuntimeException(e);
}
}
} else if (GenericUDFInBloomFilter.class == genericUDFClass) {
List<ExprNodeDesc> child = filterExpr.getChildren();
String col = extractColName(child.get(0), virtualColumns);
if (col != null) {
try {
BloomKFilter bloomFilter = evaluateBloomFilter(child.get(1), configuration, resolveDynamicValues);
return new BloomDimFilter(col, BloomKFilterHolder.fromBloomKFilter(bloomFilter), null);
} catch (HiveException | IOException e) {
throw new RuntimeException(e);
}
}
}
return null;
}
Aggregations