示例#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) 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);
      }
示例#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) {
        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);
      }
示例#5
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;
 }
示例#6
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;
    }
示例#7
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;
      }
    }
示例#8
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;
      }
    }
示例#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 PlannedAnalyzedRelation normalSelect(
        QueriedTable table,
        WhereClause whereClause,
        TableRelation tableRelation,
        ConsumerContext context) {
      QuerySpec querySpec = table.querySpec();
      TableInfo tableInfo = tableRelation.tableInfo();

      List<Symbol> outputSymbols;
      if (tableInfo.schemaInfo().systemSchema()) {
        outputSymbols = tableRelation.resolve(querySpec.outputs());
      } else {
        outputSymbols = new ArrayList<>(querySpec.outputs().size());
        for (Symbol symbol : querySpec.outputs()) {
          outputSymbols.add(
              DocReferenceConverter.convertIfPossible(tableRelation.resolve(symbol), tableInfo));
        }
      }
      CollectNode collectNode;
      MergeNode mergeNode = null;
      OrderBy orderBy = querySpec.orderBy();
      if (context.rootRelation() != table) {
        // insert directly from shards
        assert !querySpec.isLimited()
            : "insert from sub query with limit or order by is not supported. "
                + "Analyzer should have thrown an exception already.";

        ImmutableList<Projection> projections = ImmutableList.<Projection>of();
        collectNode =
            PlanNodeBuilder.collect(
                context.plannerContext().jobId(),
                tableInfo,
                context.plannerContext(),
                whereClause,
                outputSymbols,
                projections);
      } else if (querySpec.isLimited() || orderBy != null) {
        /**
         * select id, name, order by id, date
         *
         * <p>toCollect: [id, name, date] // includes order by symbols, that aren't already selected
         * allOutputs: [in(0), in(1), in(2)] // for topN projection on shards/collectNode
         * orderByInputs: [in(0), in(2)] // for topN projection on shards/collectNode AND handler
         * finalOutputs: [in(0), in(1)] // for topN output on handler -> changes output to what
         * should be returned.
         */
        List<Symbol> toCollect;
        List<Symbol> orderByInputColumns = null;
        if (orderBy != null) {
          List<Symbol> orderBySymbols = tableRelation.resolve(orderBy.orderBySymbols());
          toCollect = new ArrayList<>(outputSymbols.size() + orderBySymbols.size());
          toCollect.addAll(outputSymbols);
          // note: can only de-dup order by symbols due to non-deterministic functions like select
          // random(), random()
          for (Symbol orderBySymbol : orderBySymbols) {
            if (!toCollect.contains(orderBySymbol)) {
              toCollect.add(orderBySymbol);
            }
          }
          orderByInputColumns = new ArrayList<>();
          for (Symbol symbol : orderBySymbols) {
            orderByInputColumns.add(new InputColumn(toCollect.indexOf(symbol), symbol.valueType()));
          }
        } else {
          toCollect = new ArrayList<>(outputSymbols.size());
          toCollect.addAll(outputSymbols);
        }

        List<Symbol> allOutputs = new ArrayList<>(toCollect.size()); // outputs from collector
        for (int i = 0; i < toCollect.size(); i++) {
          allOutputs.add(new InputColumn(i, toCollect.get(i).valueType()));
        }
        List<Symbol> finalOutputs =
            new ArrayList<>(outputSymbols.size()); // final outputs on handler after sort
        for (int i = 0; i < outputSymbols.size(); i++) {
          finalOutputs.add(new InputColumn(i, outputSymbols.get(i).valueType()));
        }

        // if we have an offset we have to get as much docs from every node as we have offset+limit
        // otherwise results will be wrong
        TopNProjection tnp;
        int limit = firstNonNull(querySpec.limit(), Constants.DEFAULT_SELECT_LIMIT);
        if (orderBy == null) {
          tnp = new TopNProjection(querySpec.offset() + limit, 0);
        } else {
          tnp =
              new TopNProjection(
                  querySpec.offset() + limit,
                  0,
                  orderByInputColumns,
                  orderBy.reverseFlags(),
                  orderBy.nullsFirst());
        }
        tnp.outputs(allOutputs);
        collectNode =
            PlanNodeBuilder.collect(
                context.plannerContext().jobId(),
                tableInfo,
                context.plannerContext(),
                whereClause,
                toCollect,
                ImmutableList.<Projection>of(tnp));

        // MERGE
        tnp = new TopNProjection(limit, querySpec.offset());
        tnp.outputs(finalOutputs);
        if (orderBy == null) {
          // no sorting needed
          mergeNode =
              PlanNodeBuilder.localMerge(
                  context.plannerContext().jobId(),
                  ImmutableList.<Projection>of(tnp),
                  collectNode,
                  context.plannerContext());
        } else {
          // no order by needed in TopN as we already sorted on collector
          // and we merge sorted with SortedBucketMerger
          mergeNode =
              PlanNodeBuilder.sortedLocalMerge(
                  context.plannerContext().jobId(),
                  ImmutableList.<Projection>of(tnp),
                  orderBy,
                  allOutputs,
                  orderByInputColumns,
                  collectNode,
                  context.plannerContext());
        }
      } else {
        collectNode =
            PlanNodeBuilder.collect(
                context.plannerContext().jobId(),
                tableInfo,
                context.plannerContext(),
                whereClause,
                outputSymbols,
                ImmutableList.<Projection>of());
        mergeNode =
            PlanNodeBuilder.localMerge(
                context.plannerContext().jobId(),
                ImmutableList.<Projection>of(),
                collectNode,
                context.plannerContext());
      }
      return new QueryAndFetch(collectNode, mergeNode, context.plannerContext().jobId());
    }