case IS_TRUE: case IS_NOT_FALSE: return toDruidFilters(Iterables.getOnlyElement(((RexCall) rexNode).getOperands()), rowType, druidQuery); case IS_NOT_TRUE: case IS_FALSE: final DruidJsonFilter simpleFilter = toDruidFilters(Iterables .getOnlyElement(((RexCall) rexNode).getOperands()), rowType, druidQuery); return simpleFilter != null ? new JsonCompositeFilter(Type.NOT, simpleFilter) final List<DruidJsonFilter> jsonFilters = new ArrayList<>(); for (final RexNode e : call.getOperands()) { final DruidJsonFilter druidFilter = toDruidFilters(e, rowType, druidQuery); if (druidFilter == null) { return null; final DruidJsonFilter simpleLeafFilter = toSimpleDruidFilter(rexNode, rowType, druidQuery); return simpleLeafFilter == null ? toDruidExpressionFilter(rexNode, rowType, druidQuery) : simpleLeafFilter;
@Nullable private static DruidJsonFilter toSimpleDruidFilter(RexNode e, RelDataType rowType, DruidQuery druidQuery) { switch (e.getKind()) { case EQUALS: case NOT_EQUALS: return toEqualityKindDruidFilter(e, rowType, druidQuery); case GREATER_THAN: case GREATER_THAN_OR_EQUAL: case LESS_THAN: case LESS_THAN_OR_EQUAL: return toBoundDruidFilter(e, rowType, druidQuery); case BETWEEN: return toBetweenDruidFilter(e, rowType, druidQuery); case IN: case NOT_IN: return toInKindDruidFilter(e, rowType, druidQuery); case IS_NULL: case IS_NOT_NULL: return toIsNullKindDruidFilter(e, rowType, druidQuery); default: return null; } }
for (RexNode rexNode : ((RexCall) e).getOperands()) { if (rexNode.getKind() == SqlKind.LITERAL) { String value = toDruidLiteral(rexNode, rowType, druidQuery); if (value == null) { return null; return new DruidJsonFilter.JsonInFilter(columnName, listBuilder.build(), extractionFunction); } else { return toNotDruidFilter( new DruidJsonFilter.JsonInFilter(columnName, listBuilder.build(), extractionFunction));
/** * Translates Filter rel to Druid Filter Json object if possible. * Currently Filter rel input has to be Druid Table scan * * @param filterRel input filter rel * @param druidQuery Druid query * * @return DruidJson Filter or null if can not translate one of filters */ @Nullable private static DruidJsonFilter computeFilter(@Nullable Filter filterRel, DruidQuery druidQuery) { if (filterRel == null) { return null; } final RexNode filter = filterRel.getCondition(); final RelDataType inputRowType = filterRel.getInput().getRowType(); if (filter != null) { return DruidJsonFilter.toDruidFilters(filter, inputRowType, druidQuery); } return null; }
matchNulls = new DruidJsonFilter.JsonExpressionFilter(aggExpression + " == null"); } else { matchNulls = DruidJsonFilter.getSelectorFilter(fieldName, null, null); aggregation = new JsonFilteredAggregation(DruidJsonFilter.toNotDruidFilter(matchNulls), new JsonAggregation("count", name, fieldName, aggExpression)); } else if (!aggCall.isDistinct()) { .toDruidFilters(filterNode, druidQuery.table.getRowType(), druidQuery); if (druidFilter == null) {
@Test public void testInFilter() throws IOException { final Fixture f = new Fixture(); final List<? extends RexNode> listRexNodes = ImmutableList.of(f.rexBuilder.makeInputRef(f.varcharRowType, 0), f.rexBuilder.makeExactLiteral(BigDecimal.valueOf(1)), f.rexBuilder.makeExactLiteral(BigDecimal.valueOf(5)), f.rexBuilder.makeLiteral("value1")); RexNode inRexNode = f.rexBuilder.makeCall(SqlStdOperatorTable.IN, listRexNodes); DruidJsonFilter returnValue = DruidJsonFilter .toDruidFilters(inRexNode, f.varcharRowType, druidQuery); Assert.assertNotNull("Filter is null", returnValue); JsonFactory jsonFactory = new JsonFactory(); final StringWriter sw = new StringWriter(); JsonGenerator jsonGenerator = jsonFactory.createGenerator(sw); returnValue.write(jsonGenerator); jsonGenerator.close(); Assert.assertThat(sw.toString(), is("{\"type\":\"in\",\"dimension\":\"dimensionName\"," + "\"values\":[\"1\",\"5\",\"value1\"]}")); }
final RexNode rhs = rexCall.getOperands().get(3); final String lhsLiteralValue = toDruidLiteral(lhs, rowType, query); final String rhsLiteralValue = toDruidLiteral(rhs, rowType, query); if (lhsLiteralValue == null || rhsLiteralValue == null) { return null;
@Nullable private static DruidJsonFilter toIsNullKindDruidFilter(RexNode rexNode, RelDataType rowType, DruidQuery druidQuery) { if (rexNode.getKind() != SqlKind.IS_NULL && rexNode.getKind() != SqlKind.IS_NOT_NULL) { throw new AssertionError( DruidQuery.format("Expecting IS_NULL or IS_NOT_NULL but got [%s]", rexNode.getKind())); } final RexCall rexCall = (RexCall) rexNode; final RexNode refNode = rexCall.getOperands().get(0); Pair<String, ExtractionFunction> druidColumn = DruidQuery .toDruidColumn(refNode, rowType, druidQuery); final String columnName = druidColumn.left; final ExtractionFunction extractionFunction = druidColumn.right; if (columnName == null) { return null; } if (rexNode.getKind() == SqlKind.IS_NOT_NULL) { return toNotDruidFilter(new JsonSelector(columnName, null, extractionFunction)); } return new JsonSelector(columnName, null, extractionFunction); }
if (havingFilter != null) { havingJsonFilter = DruidJsonFilter .toDruidFilters(havingFilter.getCondition(), havingFilter.getInput().getRowType(), this); } else { havingJsonFilter = null;
@Test public void testBetweenFilterStringCase() throws IOException { final Fixture f = new Fixture(); final List<RexNode> listRexNodes = ImmutableList.of(f.rexBuilder.makeLiteral(false), f.rexBuilder.makeInputRef(f.varcharRowType, 0), f.rexBuilder.makeLiteral("lower-bound"), f.rexBuilder.makeLiteral("upper-bound")); RelDataType relDataType = f.typeFactory.createSqlType(SqlTypeName.BOOLEAN); RexNode betweenRexNode = f.rexBuilder.makeCall(relDataType, SqlStdOperatorTable.BETWEEN, listRexNodes); DruidJsonFilter returnValue = DruidJsonFilter .toDruidFilters(betweenRexNode, f.varcharRowType, druidQuery); Assert.assertNotNull("Filter is null", returnValue); JsonFactory jsonFactory = new JsonFactory(); final StringWriter sw = new StringWriter(); JsonGenerator jsonGenerator = jsonFactory.createGenerator(sw); returnValue.write(jsonGenerator); jsonGenerator.close(); Assert.assertThat(sw.toString(), is("{\"type\":\"bound\",\"dimension\":\"dimensionName\",\"lower\":\"lower-bound\"," + "\"lowerStrict\":false,\"upper\":\"upper-bound\",\"upperStrict\":false," + "\"ordering\":\"lexicographic\"}")); }
final String literalValue = DruidJsonFilter.toDruidLiteral(rexLiteral, rowType, druidQuery); if (literalValue == null) {
final Filter filter = (Filter) r; final DruidJsonFilter druidJsonFilter = DruidJsonFilter .toDruidFilters(filter.getCondition(), filter.getInput().getRowType(), this); if (druidJsonFilter == null) { return litmus.fail("invalid filter [{}]", filter.getCondition());
final String literalValue = toDruidLiteral(rexLiteral, rowType, druidQuery); if (literalValue == null) { return partialFilter; return toNotDruidFilter(partialFilter);
for (RexNode e : RelOptUtil.conjunctions(cond)) { DruidJsonFilter druidJsonFilter = DruidJsonFilter .toDruidFilters(e, filter.getInput().getRowType(), query); if (druidJsonFilter != null) { validPreds.add(e);
@Override public void onMatch(RelOptRuleCall call) { final Filter filter = call.rel(0); final DruidQuery query = call.rel(1); if (!DruidQuery.isValidSignature(query.signature() + 'h')) { return; } final RexNode cond = filter.getCondition(); final DruidJsonFilter druidJsonFilter = DruidJsonFilter .toDruidFilters(cond, query.getTopNode().getRowType(), query); if (druidJsonFilter != null) { final RelNode newFilter = filter .copy(filter.getTraitSet(), Util.last(query.rels), filter.getCondition()); final DruidQuery newDruidQuery = DruidQuery.extendQuery(query, newFilter); call.transformTo(newDruidQuery); } } }