All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.apple.foundationdb.record.query.expressions.Query Maven / Gradle / Ivy

There is a newer version: 2.8.110.0
Show newest version
/*
 * Query.java
 *
 * This source file is part of the FoundationDB open source project
 *
 * Copyright 2015-2018 Apple Inc. and the FoundationDB project authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.apple.foundationdb.record.query.expressions;

import com.apple.foundationdb.annotation.API;
import com.apple.foundationdb.record.FunctionNames;
import com.apple.foundationdb.record.metadata.IndexRecordFunction;
import com.apple.foundationdb.record.metadata.Key;
import com.apple.foundationdb.record.metadata.MetaDataException;
import com.apple.foundationdb.record.metadata.StoreRecordFunction;
import com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression;
import com.apple.foundationdb.record.metadata.expressions.KeyExpression;
import com.apple.foundationdb.record.metadata.expressions.QueryableKeyExpression;
import com.apple.foundationdb.record.provider.foundationdb.FDBRecordVersion;
import com.apple.foundationdb.record.provider.foundationdb.leaderboard.TimeWindowForFunction;
import com.apple.foundationdb.record.provider.foundationdb.leaderboard.TimeWindowRecordFunction;
import com.apple.foundationdb.tuple.Tuple;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Holder class for creating querying expressions.
 */
@API(API.Status.STABLE)
public class Query {

    /**
     * Creates a new Field context. This has a variety of methods for asserting about the value of the associated field.
     * Usable for any type field.
     * @param name the name of the field
     * @return a new Field ready for matching
     */
    @Nonnull
    public static Field field(@Nonnull String name) {
        return new Field(name);
    }

    /**
     * Check that a set of components all evaluate to true for a given record.
     * @param first the first assertion
     * @param second the second assertion
     * @param operands any other assertions
     * @return a new component that will return the record if all the children match
     */
    @Nonnull
    public static QueryComponent and(@Nonnull QueryComponent first, @Nonnull QueryComponent second,
                                     @Nonnull QueryComponent... operands) {
        return AndComponent.from(toList(first, second, operands));
    }

    /**
     * Check that a set of components all evaluate to true for a given record.
     * @param operands assertions
     * @return a new component that will return the record if all the children match
     */
    @Nonnull
    public static QueryComponent and(@Nonnull List operands) {
        return AndComponent.from(operands);
    }


    /**
     * Check that any of a set of components evaluate to true for a given record.
     * @param first the first assertion
     * @param second the second assertion
     * @param operands any other assertions
     * @return a new component that will return the record if any of the children match
     */
    @Nonnull
    public static QueryComponent or(@Nonnull QueryComponent first, @Nonnull QueryComponent second, @Nonnull QueryComponent... operands) {
        return OrComponent.from(toList(first, second, operands));
    }

    /**
     * Check that a set of components all evaluate to true for a given record.
     * @param operands assertions
     * @return a new component that will return the record if any of the children match
     */
    @Nonnull
    public static QueryComponent or(@Nonnull List operands) {
        return OrComponent.from(operands);
    }

    /**
     * Negate a component test.
     * @param operand assertion to be negated
     * @return a new component that will return the record if the child does not match
     */
    @Nonnull
    public static QueryComponent not(@Nonnull QueryComponent operand) {
        return new NotComponent(operand);
    }

    /**
     * A record function that can be used to determine or compare the rank value for a record.
     * @param operand the argument to rank
     * @return a record function that evaluates the rank of the operand
     */
    @Nonnull
    public static QueryRecordFunction rank(@Nonnull GroupingKeyExpression operand) {
        return new QueryRecordFunction<>(new IndexRecordFunction<>(FunctionNames.RANK, operand, null));
    }

    /**
     * A record function that can be used to determine or compare the rank value for a record.
     * @param fieldName the argument to rank
     * @return a record function that evaluates the rank of the operand
     */
    @Nonnull
    public static QueryRecordFunction rank(@Nonnull String fieldName) {
        return rank(Key.Expressions.field(fieldName).ungrouped());
    }

    /**
     * A record function that can be used to determine or compare the rank value for a record for a time window.
     * @param timeWindow the time window for which to get the rank
     * @param operand the argument to rank
     * @return a record function that evaluates to the rank of the operand
     */
    @Nonnull
    public static QueryRecordFunction timeWindowRank(@Nonnull TimeWindowForFunction timeWindow, @Nonnull GroupingKeyExpression operand) {
        return new QueryRecordFunction<>(new TimeWindowRecordFunction<>(FunctionNames.TIME_WINDOW_RANK, operand, null, timeWindow));
    }

    /**
     * A record function that can be used to determine or compare the rank value for a record for a time window.
     * @param type the type of time window
     * @param timestamp the target timestamp
     * @param typeParameter the name of the time window type parameter if it is a parameter
     * @param timestampParameter the name of the timestamp parameter if it is a parameter
     * @param operand the argument to rank
     * @return a record function that evaluates to the rank of the operand
     */
    @Nonnull
    public static QueryRecordFunction timeWindowRank(int type, long timestamp, @Nullable String typeParameter, @Nullable String timestampParameter, @Nonnull GroupingKeyExpression operand) {
        return timeWindowRank(new TimeWindowForFunction(type, timestamp, typeParameter, timestampParameter), operand);
    }

    /**
     * A record function that can be used to determine or compare the rank value for a record for a time window.
     * @param type the type of time window
     * @param timestamp the target timestamp
     * @param operand the argument to rank
     * @return a record function that evaluates to the rank of the operand
     */
    @Nonnull
    public static QueryRecordFunction timeWindowRank(int type, long timestamp, @Nonnull GroupingKeyExpression operand) {
        return timeWindowRank(type, timestamp, null, null, operand);
    }

    /**
     * A record function that can be used to determine or compare the rank value for a record for a time window.
     * @param typeParameter the name of the time window type parameter
     * @param timestampParameter the name of the timestamp parameter
     * @param operand the argument to rank
     * @return a record function that evaluates to the rank of the operand
     */
    @Nonnull
    public static QueryRecordFunction timeWindowRank(@Nonnull String typeParameter, @Nonnull String timestampParameter, @Nonnull GroupingKeyExpression operand) {
        return timeWindowRank(0, 0, typeParameter, timestampParameter, operand);
    }

    /**
     * A record function that can be used to determine or compare the rank value for a record for a time window and the score entry that determined that rank.
     *
     * The result of evaluation will be {@code null} if the record has no entry within the specified time window or else a {@code Tuple}
     * of rank, value, timestamp, and any other values in the specified operand's items.
     * @param timeWindow the time window for which to get the rank
     * @param operand the argument to rank
     * @return a record function that evaluates to a {@code Tuple} of the rank and the corresponding entry
     */
    @Nonnull
    public static QueryRecordFunction timeWindowRankAndEntry(@Nonnull TimeWindowForFunction timeWindow, @Nonnull GroupingKeyExpression operand) {
        return new QueryRecordFunction<>(new TimeWindowRecordFunction<>(FunctionNames.TIME_WINDOW_RANK_AND_ENTRY, operand, null, timeWindow));
    }

    /**
     * A record function that can be used to determine or compare the rank value for a record for a time window and the score entry that determined that rank.
     *
     * The result of evaluation will be {@code null} if the record has no entry within the specified time window or else a {@code Tuple}
     * of rank, value, timestamp, and any other values in the specified operand's items.
     * @param type the type of time window
     * @param timestamp the target timestamp
     * @param typeParameter the name of the time window type parameter if it is a parameter
     * @param timestampParameter the name of the timestamp parameter if it is a parameter
     * @param operand the argument to rank
     * @return a record function that evaluates to the rank of the operand
     */
    @Nonnull
    public static QueryRecordFunction timeWindowRankAndEntry(int type, long timestamp, @Nullable String typeParameter, @Nullable String timestampParameter, @Nonnull GroupingKeyExpression operand) {
        return timeWindowRankAndEntry(new TimeWindowForFunction(type, timestamp, typeParameter, timestampParameter), operand);
    }

    /**
     * A record function that can be used to determine or compare the rank value for a record for a time window and the score entry that determined that rank.
     *
     * The result of evaluation will be {@code null} if the record has no entry within the specified time window or else a {@code Tuple}
     * of rank, value, timestamp, and any other values in the specified operand's items.
     * @param type the type of time window
     * @param timestamp the target timestamp
     * @param operand the argument to rank
     * @return a record function that evaluates to the rank of the operand
     */
    @Nonnull
    public static QueryRecordFunction timeWindowRankAndEntry(int type, long timestamp, @Nonnull GroupingKeyExpression operand) {
        return timeWindowRankAndEntry(type, timestamp, null, null, operand);
    }

    /**
     * A record function that can be used to determine or compare the rank value for a record for a time window and the score entry that determined that rank.
     *
     * The result of evaluation will be {@code null} if the record has no entry within the specified time window or else a {@code Tuple}
     * of rank, value, timestamp, and any other values in the specified operand's items.
     * @param typeParameter the name of the time window type parameter
     * @param timestampParameter the name of the timestamp parameter
     * @param operand the argument to rank
     * @return a record function that evaluates to the rank of the operand
     */
    @Nonnull
    public static QueryRecordFunction timeWindowRankAndEntry(@Nonnull String typeParameter, @Nonnull String timestampParameter, @Nonnull GroupingKeyExpression operand) {
        return timeWindowRankAndEntry(0, 0, typeParameter, timestampParameter, operand);
    }

    /**
     * A record function that can be used to determine the version of a record.
     * @return a record function that evaluates the version of the record
     */
    @Nonnull
    public static QueryRecordFunction version() {
        return new QueryRecordFunction<>(new StoreRecordFunction<>(FunctionNames.VERSION));
    }

    /**
     * Build query components using a key expression.
     * @param keyExpression the key expression to compare with values
     * @return a {@code QueryKeyExpression} for matching
     */
    @Nonnull
    @API(API.Status.EXPERIMENTAL)
    public static QueryKeyExpression keyExpression(@Nonnull KeyExpression keyExpression) {
        if (!(keyExpression instanceof QueryableKeyExpression)) {
            throw new MetaDataException("query key expression must be queryable");
        }
        return new QueryKeyExpression((QueryableKeyExpression)keyExpression);
    }

    /**
     * Exception thrown when a query expression is not valid in some context.
     */
    @SuppressWarnings("serial")
    public static class InvalidExpressionException extends IllegalStateException {
        public InvalidExpressionException(String message) {
            super(message);
        }
    }

    private static List toList(@Nonnull QueryComponent first, @Nonnull QueryComponent second,
                                               @Nonnull QueryComponent... operands) {
        List children = new ArrayList<>(operands.length + 2);
        children.add(first);
        children.add(second);
        Collections.addAll(children, operands);
        return children;
    }

    public static boolean isSingleFieldComparison(@Nonnull QueryComponent component) {
        return component instanceof FieldWithComparison ||
               (component instanceof NestedField &&
                ((NestedField)component).getChild() instanceof FieldWithComparison);
    }

    private Query() {
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy