private void validateFilterPushDown(GTInfo info) { if (!hasFilterPushDown()) return; Set<TblColRef> filterColumns = Sets.newHashSet(); TupleFilter.collectColumns(filterPushDown, filterColumns); for (TblColRef col : filterColumns) { // filter columns must belong to the table info.validateColRef(col); // filter columns must be returned to satisfy upper layer evaluation (calcite) columns = columns.set(col.getColumnDesc().getZeroBasedIndex()); } // un-evaluatable filter must be removed if (!TupleFilter.isEvaluableRecursively(filterPushDown)) { Set<TblColRef> unevaluableColumns = Sets.newHashSet(); filterPushDown = GTUtil.convertFilterUnevaluatable(filterPushDown, info, unevaluableColumns); // columns in un-evaluatable filter must be returned without loss so upper layer can do final // evaluation if (hasAggregation()) { for (TblColRef col : unevaluableColumns) { aggrGroupBy = aggrGroupBy.set(col.getColumnDesc().getZeroBasedIndex()); } } } }
private CompareTupleFilter mergeToInClause(TupleFilter filter) { List<? extends TupleFilter> children = filter.getChildren(); TblColRef inColumn = null; List<String> inValues = new LinkedList<String>(); for (TupleFilter child : children) { if (child.getOperator() == FilterOperatorEnum.EQ) { CompareTupleFilter compFilter = (CompareTupleFilter) child; TblColRef column = compFilter.getColumn(); if (inColumn == null) { inColumn = column; } if (column == null || !column.equals(inColumn)) { return null; } inValues.addAll(compFilter.getValues()); } else { return null; } } children.clear(); CompareTupleFilter inFilter = new CompareTupleFilter(FilterOperatorEnum.IN); inFilter.addChild(new ColumnTupleFilter(inColumn)); inFilter.addChild(new ConstantTupleFilter(inValues)); return inFilter; }
private void collectColumnsRecursively(TupleFilter filter, Set<TblColRef> collector) { if (filter instanceof ColumnTupleFilter) { collector.add(((ColumnTupleFilter) filter).getColumn()); } for (TupleFilter child : filter.getChildren()) { collectColumnsRecursively(child, collector); } }
@Override public TupleFilter visitCall(RexCall call) { TupleFilter filter = null; SqlOperator op = call.getOperator(); switch (op.getKind()) { case AND: filter = new LogicalTupleFilter(FilterOperatorEnum.AND); break; case OR: filter = new LogicalTupleFilter(FilterOperatorEnum.OR); break; case NOT: filter = new LogicalTupleFilter(FilterOperatorEnum.NOT); break; case EQUALS: filter = new CompareTupleFilter(FilterOperatorEnum.EQ); break; case GREATER_THAN: filter = new CompareTupleFilter(FilterOperatorEnum.GT); break; case LESS_THAN: filter = new CompareTupleFilter(FilterOperatorEnum.LT); break; case GREATER_THAN_OR_EQUAL: filter = new CompareTupleFilter(FilterOperatorEnum.GTE); break; case LESS_THAN_OR_EQUAL: filter = new CompareTupleFilter(FilterOperatorEnum.LTE); break; case NOT_EQUALS: filter = new CompareTupleFilter(FilterOperatorEnum.NEQ); break; case IS_NULL: filter = new CompareTupleFilter(FilterOperatorEnum.ISNULL); break; case IS_NOT_NULL: filter = new CompareTupleFilter(FilterOperatorEnum.ISNOTNULL); break; case CAST: case REINTERPRET: // NOTE: use child directly break; case CASE: filter = new CaseTupleFilter(); break; case OTHER: if (op.getName().equalsIgnoreCase("extract_date")) { filter = new ExtractTupleFilter(FilterOperatorEnum.EXTRACT); } else { throw new UnsupportedOperationException(op.getName()); } break; default: throw new UnsupportedOperationException(op.getName()); } for (RexNode operand : call.operands) { TupleFilter childFilter = operand.accept(this); if (filter == null) { filter = childFilter; } else { filter.addChild(childFilter); } } if (op.getKind() == SqlKind.OR) { CompareTupleFilter inFilter = mergeToInClause(filter); if (inFilter != null) { filter = inFilter; } } return filter; }