Пример #1
0
 @Nullable
 private Function rewriteAndValidateFields(Function function, Context context) {
   if (function.arguments().size() == 2) {
     Symbol left = function.arguments().get(0);
     Symbol right = function.arguments().get(1);
     if (left.symbolType() == SymbolType.REFERENCE && right.symbolType().isValueSymbol()) {
       Reference ref = (Reference) left;
       if (ref.info().ident().columnIdent().equals(DocSysColumns.ID)) {
         function.setArgument(
             0,
             new Reference(DocSysColumns.forTable(ref.ident().tableIdent(), DocSysColumns.UID)));
         function.setArgument(
             1,
             Literal.newLiteral(
                 Uid.createUid(
                     Constants.DEFAULT_MAPPING_TYPE, ValueSymbolVisitor.STRING.process(right))));
       } else {
         String unsupportedMessage =
             context.unsupportedMessage(ref.info().ident().columnIdent().name());
         if (unsupportedMessage != null) {
           throw new UnsupportedFeatureException(unsupportedMessage);
         }
       }
     }
   }
   return function;
 }
Пример #2
0
      @Override
      public Query apply(Function input, Context context) {
        assert input != null;
        assert input.arguments().size() == 1;
        BooleanQuery query = new BooleanQuery();

        query.add(process(input.arguments().get(0), context), BooleanClause.Occur.MUST_NOT);
        query.add(Queries.newMatchAllQuery(), BooleanClause.Occur.MUST);

        return query;
      }
Пример #3
0
      @Nullable
      protected Tuple<Reference, Literal> prepare(Function input) {
        assert input != null;
        assert input.arguments().size() == 2;

        Symbol left = input.arguments().get(0);
        Symbol right = input.arguments().get(1);

        if (!(left instanceof Reference) || !(right.symbolType().isValueSymbol())) {
          return null;
        }
        assert right.symbolType() == SymbolType.LITERAL;
        return new Tuple<>((Reference) left, (Literal) right);
      }
Пример #4
0
      @Override
      public Query apply(Function input, Context context) throws IOException {
        List<Symbol> arguments = input.arguments();
        assert arguments.size() == 4 : "invalid number of arguments";
        assert Symbol.isLiteral(arguments.get(0), DataTypes.OBJECT);
        assert Symbol.isLiteral(arguments.get(1), DataTypes.STRING);
        assert Symbol.isLiteral(arguments.get(2), DataTypes.STRING);
        assert Symbol.isLiteral(arguments.get(3), DataTypes.OBJECT);

        @SuppressWarnings("unchecked")
        Map<String, Object> fields = (Map) ((Literal) arguments.get(0)).value();
        BytesRef queryString = (BytesRef) ((Literal) arguments.get(1)).value();
        BytesRef matchType = (BytesRef) ((Literal) arguments.get(2)).value();
        Map options = (Map) ((Literal) arguments.get(3)).value();

        checkArgument(queryString != null, "cannot use NULL as query term in match predicate");

        MatchQueryBuilder queryBuilder;
        if (fields.size() == 1) {
          queryBuilder =
              new MatchQueryBuilder(context.mapperService, context.indexCache, matchType, options);
        } else {
          queryBuilder =
              new MultiMatchQueryBuilder(
                  context.mapperService, context.indexCache, matchType, options);
        }
        return queryBuilder.query(fields, queryString);
      }
Пример #5
0
    @Override
    public Query visitFunction(Function function, Context context) {
      assert function != null;
      if (fieldIgnored(function, context)) {
        return Queries.newMatchAllQuery();
      }
      function = rewriteAndValidateFields(function, context);

      FunctionToQuery toQuery = functions.get(function.info().ident().name());
      if (toQuery == null) {
        return genericFunctionQuery(function, context);
      }

      Query query;
      try {
        query = toQuery.apply(function, context);
      } catch (IOException e) {
        throw ExceptionsHelper.convertToRuntime(e);
      } catch (UnsupportedOperationException e) {
        return genericFunctionQuery(function, context);
      }
      if (query == null) {
        query = queryFromInnerFunction(function, context);
        if (query == null) {
          return genericFunctionQuery(function, context);
        }
      }
      return query;
    }
Пример #6
0
 @Override
 public Query apply(Function input, Context context) {
   assert input != null;
   BooleanQuery query = new BooleanQuery();
   for (Symbol symbol : input.arguments()) {
     query.add(process(symbol, context), BooleanClause.Occur.MUST);
   }
   return query;
 }
Пример #7
0
      @Override
      public Query apply(Function input, Context context) {
        assert input != null;
        assert input.arguments().size() == 1;
        Symbol arg = input.arguments().get(0);
        if (arg.symbolType() != SymbolType.REFERENCE) {
          return null;
        }
        Reference reference = (Reference) arg;

        String columnName = reference.info().ident().columnIdent().fqn();
        QueryBuilderHelper builderHelper = QueryBuilderHelper.forType(reference.valueType());
        BooleanFilter boolFilter = new BooleanFilter();
        boolFilter.add(
            builderHelper.rangeFilter(columnName, null, null, true, true),
            BooleanClause.Occur.MUST_NOT);
        return new FilteredQuery(Queries.newMatchAllQuery(), boolFilter);
      }
Пример #8
0
 @Override
 public Query apply(Function input, Context context) {
   assert input != null;
   BooleanQuery query = new BooleanQuery();
   query.setMinimumNumberShouldMatch(1);
   for (Symbol symbol : input.arguments()) {
     query.add(process(symbol, context), BooleanClause.Occur.SHOULD);
   }
   return query;
 }
Пример #9
0
 @Override
 public Query apply(Function function, Context context) throws IOException {
   Symbol left = function.arguments().get(0);
   Symbol collectionSymbol = function.arguments().get(1);
   Preconditions.checkArgument(
       DataTypes.isCollectionType(collectionSymbol.valueType()),
       "invalid argument for ANY expression");
   if (left.symbolType().isValueSymbol()) {
     // 1 = any (array_col) - simple eq
     assert collectionSymbol.symbolType().isReference()
         : "no reference found in ANY expression";
     return applyArrayReference((Reference) collectionSymbol, (Literal) left, context);
   } else if (collectionSymbol.symbolType().isValueSymbol()) {
     assert left.symbolType().isReference() : "no reference found in ANY expression";
     return applyArrayLiteral((Reference) left, (Literal) collectionSymbol, context);
   } else {
     // should never get here - 2 literal arguments must have been normalized away yet
     return null;
   }
 }
Пример #10
0
    private boolean fieldIgnored(Function function, Context context) {
      if (function.arguments().size() != 2) {
        return false;
      }

      Symbol left = function.arguments().get(0);
      Symbol right = function.arguments().get(1);
      if (left.symbolType() == SymbolType.REFERENCE && right.symbolType().isValueSymbol()) {
        String columnName = ((Reference) left).info().ident().columnIdent().name();
        if (Context.FILTERED_FIELDS.contains(columnName)) {
          context.filteredFieldValues.put(columnName, ((Input) right).value());
          return true;
        }
        String unsupportedMessage = Context.UNSUPPORTED_FIELDS.get(columnName);
        if (unsupportedMessage != null) {
          throw new UnsupportedFeatureException(unsupportedMessage);
        }
      }
      return false;
    }
Пример #11
0
    RefLiteralPair(Function function) {
      assert function.arguments().size() == 2 : "function requires 2 arguments";
      Symbol left = function.arguments().get(0);
      Symbol right = function.arguments().get(1);

      if (left instanceof Reference) {
        reference = (Reference) left;
      } else if (right instanceof Reference) {
        reference = (Reference) right;
      } else {
        reference = null;
      }

      if (left.symbolType().isValueSymbol()) {
        input = (Input) left;
      } else if (right.symbolType().isValueSymbol()) {
        input = (Input) right;
      } else {
        input = null;
      }
    }
Пример #12
0
    FunctionLiteralPair(Function outerFunction) {
      assert outerFunction.arguments().size() == 2 : "function requires 2 arguments";
      Symbol left = outerFunction.arguments().get(0);
      Symbol right = outerFunction.arguments().get(1);

      functionName = outerFunction.info().ident().name();

      if (left instanceof Function) {
        function = (Function) left;
      } else if (right instanceof Function) {
        function = (Function) right;
      } else {
        function = null;
      }

      if (left.symbolType().isValueSymbol()) {
        input = (Input) left;
      } else if (right.symbolType().isValueSymbol()) {
        input = (Input) right;
      } else {
        input = null;
      }
    }
Пример #13
0
    private static Filter genericFunctionFilter(Function function, Context context) {
      if (function.valueType() != DataTypes.BOOLEAN) {
        raiseUnsupported(function);
      }
      // avoid field-cache
      // reason1: analyzed columns or columns with index off wouldn't work
      //   substr(n, 1, 1) in the case of n => analyzed would throw an error because n would be an
      // array
      // reason2: would have to load each value into the field cache
      function = (Function) DocReferenceConverter.convertIf(function);

      final CollectInputSymbolVisitor.Context ctx =
          context.inputSymbolVisitor.extractImplementations(function);
      assert ctx.topLevelInputs().size() == 1;
      @SuppressWarnings("unchecked")
      final Input<Boolean> condition = (Input<Boolean>) ctx.topLevelInputs().get(0);
      @SuppressWarnings("unchecked")
      final List<LuceneCollectorExpression> expressions = ctx.docLevelExpressions();
      final CollectorContext collectorContext =
          new CollectorContext(
              context.mapperService,
              context.fieldDataService,
              new CollectorFieldsVisitor(expressions.size()));

      for (LuceneCollectorExpression expression : expressions) {
        expression.startCollect(collectorContext);
      }
      return new Filter() {
        @Override
        public DocIdSet getDocIdSet(AtomicReaderContext context, Bits acceptDocs)
            throws IOException {
          for (LuceneCollectorExpression expression : expressions) {
            expression.setNextReader(context.reader().getContext());
          }
          return BitsFilteredDocIdSet.wrap(
              new FunctionDocSet(
                  context.reader(),
                  collectorContext.visitor(),
                  condition,
                  expressions,
                  context.reader().maxDoc(),
                  acceptDocs),
              acceptDocs);
        }
      };
    }
Пример #14
0
 private Query queryFromInnerFunction(Function function, Context context) {
   for (Symbol symbol : function.arguments()) {
     if (symbol.symbolType() == SymbolType.FUNCTION) {
       String functionName = ((Function) symbol).info().ident().name();
       InnerFunctionToQuery functionToQuery = innerFunctions.get(functionName);
       if (functionToQuery != null) {
         try {
           Query query = functionToQuery.apply(function, (Function) symbol, context);
           if (query != null) {
             return query;
           }
         } catch (IOException e) {
           throw ExceptionsHelper.convertToRuntime(e);
         }
       }
     }
   }
   return null;
 }
Пример #15
0
      /**
       * @param parent the outer function. E.g. in the case of
       *     <pre>where distance(p1, POINT (10 20)) > 20</pre>
       *     this would be
       *     <pre>gt( \<inner function\>,  20)</pre>
       *
       * @param inner has to be the distance function
       */
      @Override
      public Query apply(Function parent, Function inner, Context context) {
        assert inner.info().ident().name().equals(DistanceFunction.NAME);

        RefLiteralPair distanceRefLiteral = new RefLiteralPair(inner);
        if (!distanceRefLiteral.isValid()) {
          // can't use distance filter without literal, fallback to genericFunction
          return null;
        }
        FunctionLiteralPair functionLiteralPair = new FunctionLiteralPair(parent);
        if (!functionLiteralPair.isValid()) {
          // must be something like eq(distance(..), non-literal) - fallback to genericFunction
          return null;
        }
        Double distance = DataTypes.DOUBLE.value(functionLiteralPair.input().value());

        String fieldName = distanceRefLiteral.reference().info().ident().columnIdent().fqn();
        FieldMapper mapper = getGeoPointFieldMapper(fieldName, context.mapperService);
        GeoPointFieldMapper geoMapper = ((GeoPointFieldMapper) mapper);
        IndexGeoPointFieldData fieldData = context.fieldDataService.getForField(mapper);

        Input geoPointInput = distanceRefLiteral.input();
        Double[] pointValue = (Double[]) geoPointInput.value();
        double lat = pointValue[1];
        double lon = pointValue[0];

        String parentName = functionLiteralPair.functionName();

        Double from = null;
        Double to = null;
        boolean includeLower = false;
        boolean includeUpper = false;

        switch (parentName) {
          case EqOperator.NAME:
            includeLower = true;
            includeUpper = true;
            from = distance;
            to = distance;
            break;
          case LteOperator.NAME:
            includeUpper = true;
            to = distance;
            break;
          case LtOperator.NAME:
            to = distance;
            break;
          case GteOperator.NAME:
            from = distance;
            includeLower = true;
            break;
          case GtOperator.NAME:
            from = distance;
            break;
          default:
            // invalid operator? give up
            return null;
        }
        GeoPoint geoPoint = new GeoPoint(lat, lon);
        Filter filter =
            new GeoDistanceRangeFilter(
                geoPoint,
                from,
                to,
                includeLower,
                includeUpper,
                GEO_DISTANCE,
                geoMapper,
                fieldData,
                optimizeBox);
        return new FilteredQuery(
            Queries.newMatchAllQuery(), context.indexCache.filter().cache(filter));
      }