Search in sources :

Example 1 with IndexFunction

use of com.cinchapi.ccl.type.function.IndexFunction in project concourse by cinchapi.

the class Stores method find.

/**
 * Find the records that contain values that are stored for {@code key} and
 * satisfy {@code operator} in relation to the specified {@code values} at
 * {@code timestamp}.
 * <p>
 * If the {@code key} is primitive, the store lookup is usually a simple
 * {@link Store#find(String, Operator, TObject[]) find}. However, if the key
 * is a navigation key, this method will process it by
 * {@link #browse(Store, String) browsing} the destination values and
 * checking the operator validity of each if and only if the {@code store}
 * is an {@link AtomicOperation} or {@link AtomicSupport supports} starting
 * one.
 * </p>
 *
 * @param store
 * @param timestamp
 * @param key
 * @param operator
 * @param values
 * @return the records that satisfy the query
 */
public static Set<Long> find(Store store, long timestamp, String key, Operator operator, TObject... values) {
    for (int i = 0; i < values.length; ++i) {
        TObject value = values[i];
        if (value.getType() == Type.FUNCTION) {
            Function function = (Function) Convert.thriftToJava(value);
            TemporalFunction func = (TemporalFunction) function;
            String method = Calculations.alias(function.operation());
            ArrayBuilder<Object> args = ArrayBuilder.builder();
            method += "Key";
            args.add(function.key());
            if (function instanceof KeyRecordsFunction || function instanceof KeyConditionFunction) {
                method += "Records";
                Collection<Long> records = function instanceof KeyRecordsFunction ? ((KeyRecordsFunction) function).source() : Finder.instance().visit(((KeyConditionFunction) function).source(), store);
                args.add(records);
            } else if (!(function instanceof IndexFunction)) {
                throw new IllegalStateException("Invalid function value");
            }
            method += "Atomic";
            args.add(func.timestamp());
            args.add(store);
            values[i] = Convert.javaToThrift(Reflection.callStatic(Operations.class, method, args.build()));
        }
    }
    if (Keys.isNavigationKey(key)) {
        Map<TObject, Set<Long>> index = timestamp == Time.NONE ? browse(store, key) : browse(store, key, timestamp);
        Set<Long> records = index.entrySet().stream().filter(e -> e.getKey().is(operator, values)).map(e -> e.getValue()).flatMap(Set::stream).collect(Collectors.toCollection(LinkedHashSet::new));
        return records;
    } else if (Keys.isFunctionKey(key)) {
        Set<Long> records = Sets.newLinkedHashSet();
        for (long record : store.getAllRecords()) {
            Set<TObject> aggregate = select(store, key, record, timestamp);
            for (TObject tobject : aggregate) {
                if (tobject.is(operator, values)) {
                    records.add(record);
                    break;
                }
            }
        }
        return records;
    } else {
        return timestamp == Time.NONE ? store.find(key, operator, values) : store.find(timestamp, key, operator, values);
    }
}
Also used : Function(com.cinchapi.ccl.type.Function) ArrayBuilder(com.cinchapi.common.base.ArrayBuilder) Source(com.cinchapi.concourse.server.ops.Strategy.Source) Store(com.cinchapi.concourse.server.storage.Store) AbstractSet(java.util.AbstractSet) AdHocIterator(com.cinchapi.common.base.AdHocIterator) HashMap(java.util.HashMap) IndexFunction(com.cinchapi.ccl.type.function.IndexFunction) Constants(com.cinchapi.concourse.Constants) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) Calculations(com.cinchapi.concourse.server.calculate.Calculations) Reflection(com.cinchapi.common.reflect.Reflection) AtomicSupport(com.cinchapi.concourse.server.storage.AtomicSupport) ImmutableList(com.google.common.collect.ImmutableList) TObject(com.cinchapi.concourse.thrift.TObject) Convert(com.cinchapi.concourse.util.Convert) Keys(com.cinchapi.concourse.validate.Keys) TemporalFunction(com.cinchapi.ccl.type.function.TemporalFunction) Map(java.util.Map) Link(com.cinchapi.concourse.Link) LinkedHashSet(java.util.LinkedHashSet) Nullable(javax.annotation.Nullable) KeyType(com.cinchapi.concourse.validate.Keys.KeyType) Time(com.cinchapi.concourse.time.Time) ImmutableSet(com.google.common.collect.ImmutableSet) Iterator(java.util.Iterator) ImmutableMap(com.google.common.collect.ImmutableMap) Collection(java.util.Collection) Set(java.util.Set) KeyConditionFunction(com.cinchapi.ccl.type.function.KeyConditionFunction) MoreObjects(com.google.common.base.MoreObjects) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) AtomicOperation(com.cinchapi.concourse.server.storage.AtomicOperation) Operator(com.cinchapi.concourse.thrift.Operator) ForwardingMap(com.google.common.collect.ForwardingMap) Finder(com.cinchapi.concourse.server.query.Finder) Key(com.cinchapi.concourse.validate.Keys.Key) Type(com.cinchapi.concourse.thrift.Type) Queue(java.util.Queue) ArrayDeque(java.util.ArrayDeque) KeyValue(com.cinchapi.concourse.util.KeyValue) KeyRecordsFunction(com.cinchapi.ccl.type.function.KeyRecordsFunction) TObject(com.cinchapi.concourse.thrift.TObject) AbstractSet(java.util.AbstractSet) LinkedHashSet(java.util.LinkedHashSet) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) KeyRecordsFunction(com.cinchapi.ccl.type.function.KeyRecordsFunction) TemporalFunction(com.cinchapi.ccl.type.function.TemporalFunction) Function(com.cinchapi.ccl.type.Function) IndexFunction(com.cinchapi.ccl.type.function.IndexFunction) TemporalFunction(com.cinchapi.ccl.type.function.TemporalFunction) KeyConditionFunction(com.cinchapi.ccl.type.function.KeyConditionFunction) KeyRecordsFunction(com.cinchapi.ccl.type.function.KeyRecordsFunction) IndexFunction(com.cinchapi.ccl.type.function.IndexFunction) TObject(com.cinchapi.concourse.thrift.TObject) KeyConditionFunction(com.cinchapi.ccl.type.function.KeyConditionFunction)

Example 2 with IndexFunction

use of com.cinchapi.ccl.type.function.IndexFunction in project concourse by cinchapi.

the class ConvertTest method testConvertStringToIndexFunction.

@Test
public void testConvertStringToIndexFunction() {
    IndexFunction expected = new IndexFunction("average", "age");
    Object actual = Convert.stringToJava("average(age)");
    Assert.assertEquals(expected, actual);
}
Also used : IndexFunction(com.cinchapi.ccl.type.function.IndexFunction) TObject(com.cinchapi.concourse.thrift.TObject) Test(org.junit.Test)

Example 3 with IndexFunction

use of com.cinchapi.ccl.type.function.IndexFunction in project concourse by cinchapi.

the class Convert method javaToThrift.

/**
 * Return the Thrift Object that represents {@code object}.
 *
 * @param object
 * @return the TObject
 */
public static TObject javaToThrift(Object object) {
    if (object == null) {
        return TObject.NULL;
    } else {
        ByteBuffer bytes;
        Type type = null;
        if (object instanceof Boolean) {
            bytes = ByteBuffer.allocate(1);
            bytes.put((boolean) object ? (byte) 1 : (byte) 0);
            type = Type.BOOLEAN;
        } else if (object instanceof Double) {
            bytes = ByteBuffer.allocate(8);
            bytes.putDouble((double) object);
            type = Type.DOUBLE;
        } else if (object instanceof Float) {
            bytes = ByteBuffer.allocate(4);
            bytes.putFloat((float) object);
            type = Type.FLOAT;
        } else if (object instanceof Link) {
            bytes = ByteBuffer.allocate(8);
            bytes.putLong(((Link) object).longValue());
            type = Type.LINK;
        } else if (object instanceof Long) {
            bytes = ByteBuffer.allocate(8);
            bytes.putLong((long) object);
            type = Type.LONG;
        } else if (object instanceof Integer) {
            bytes = ByteBuffer.allocate(4);
            bytes.putInt((int) object);
            type = Type.INTEGER;
        } else if (object instanceof BigDecimal) {
            bytes = ByteBuffer.allocate(8);
            bytes.putDouble((double) ((BigDecimal) object).doubleValue());
            type = Type.DOUBLE;
        } else if (object instanceof Tag) {
            bytes = ByteBuffer.wrap(object.toString().getBytes(StandardCharsets.UTF_8));
            type = Type.TAG;
        } else if (object instanceof Timestamp) {
            try {
                bytes = ByteBuffer.allocate(8);
                bytes.putLong(((Timestamp) object).getMicros());
                type = Type.TIMESTAMP;
            } catch (IllegalStateException e) {
                throw new UnsupportedOperationException("Cannot convert string based Timestamp to a TObject");
            }
        } else if (object instanceof Function) {
            type = Type.FUNCTION;
            Function function = (Function) object;
            byte[] nameBytes = function.operation().getBytes(StandardCharsets.UTF_8);
            byte[] keyBytes = function.key().getBytes(StandardCharsets.UTF_8);
            if (function instanceof IndexFunction) {
                /*
                     * Schema:
                     * | type (1) | timestamp(8) | nameLength (4) | name
                     * (nameLength) | key |
                     */
                bytes = ByteBuffer.allocate(1 + 8 + 4 + nameBytes.length + keyBytes.length);
                bytes.put((byte) FunctionType.INDEX.ordinal());
                bytes.putLong(((TemporalFunction) function).timestamp());
                bytes.putInt(nameBytes.length);
                bytes.put(nameBytes);
                bytes.put(keyBytes);
            } else if (function instanceof KeyRecordsFunction) {
                /*
                     * Schema:
                     * | type (1) | timestamp(8) | nameLength (4) | name
                     * (nameLength) | keyLength (4) | key (keyLength) | records
                     * (8 each) |
                     */
                KeyRecordsFunction func = (KeyRecordsFunction) function;
                bytes = ByteBuffer.allocate(1 + 8 + 4 + nameBytes.length + 4 + keyBytes.length + 8 * func.source().size());
                bytes.put((byte) FunctionType.KEY_RECORDS.ordinal());
                bytes.putLong(((TemporalFunction) function).timestamp());
                bytes.putInt(nameBytes.length);
                bytes.put(nameBytes);
                bytes.putInt(keyBytes.length);
                bytes.put(keyBytes);
                for (long record : func.source()) {
                    bytes.putLong(record);
                }
            } else if (function instanceof KeyConditionFunction) {
                /*
                     * Schema:
                     * | type (1) | timestamp(8) | nameLength (4) | name
                     * (nameLength) | keyLength (4) | key (keyLength) |
                     * condition |
                     */
                KeyConditionFunction func = (KeyConditionFunction) function;
                String condition = ConcourseCompiler.get().tokenize(func.source()).stream().map(Symbol::toString).collect(Collectors.joining(" "));
                bytes = ByteBuffer.allocate(1 + 9 + 4 + nameBytes.length + 4 + keyBytes.length + condition.length());
                bytes.put((byte) FunctionType.KEY_CONDITION.ordinal());
                bytes.putLong(((TemporalFunction) function).timestamp());
                bytes.putInt(nameBytes.length);
                bytes.put(nameBytes);
                bytes.putInt(keyBytes.length);
                bytes.put(keyBytes);
                bytes.put(condition.getBytes(StandardCharsets.UTF_8));
            } else {
                throw new UnsupportedOperationException("Cannot convert the following function to a TObject: " + function);
            }
        } else {
            bytes = ByteBuffer.wrap(object.toString().getBytes(StandardCharsets.UTF_8));
            type = Type.STRING;
        }
        bytes.rewind();
        return new TObject(bytes, type).setJavaFormat(object);
    }
}
Also used : TObject(com.cinchapi.concourse.thrift.TObject) KeyRecordsFunction(com.cinchapi.ccl.type.function.KeyRecordsFunction) FunctionValueSymbol(com.cinchapi.ccl.grammar.FunctionValueSymbol) Symbol(com.cinchapi.ccl.grammar.Symbol) ByteBuffer(java.nio.ByteBuffer) Timestamp(com.cinchapi.concourse.Timestamp) BigDecimal(java.math.BigDecimal) TemporalFunction(com.cinchapi.ccl.type.function.TemporalFunction) IndexFunction(com.cinchapi.ccl.type.function.IndexFunction) TemporalFunction(com.cinchapi.ccl.type.function.TemporalFunction) KeyRecordsFunction(com.cinchapi.ccl.type.function.KeyRecordsFunction) Function(com.cinchapi.ccl.type.Function) KeyConditionFunction(com.cinchapi.ccl.type.function.KeyConditionFunction) Type(com.cinchapi.concourse.thrift.Type) IndexFunction(com.cinchapi.ccl.type.function.IndexFunction) Tag(com.cinchapi.concourse.Tag) KeyConditionFunction(com.cinchapi.ccl.type.function.KeyConditionFunction) Link(com.cinchapi.concourse.Link)

Example 4 with IndexFunction

use of com.cinchapi.ccl.type.function.IndexFunction in project concourse by cinchapi.

the class Convert method thriftToJava.

/**
 * Return the Java Object that represents {@code object}.
 *
 * @param object
 * @return the Object
 */
public static Object thriftToJava(TObject object) {
    Preconditions.checkState(object.getType() != null, "Cannot read value because it has been " + "created with a newer version of Concourse " + "Server. Please upgrade this client.");
    Object java = object.getJavaFormat();
    if (java == null) {
        ByteBuffer buffer = object.bufferForData();
        switch(object.getType()) {
            case BOOLEAN:
                java = ByteBuffers.getBoolean(buffer);
                break;
            case DOUBLE:
                java = buffer.getDouble();
                break;
            case FLOAT:
                java = buffer.getFloat();
                break;
            case INTEGER:
                java = buffer.getInt();
                break;
            case LINK:
                java = Link.to(buffer.getLong());
                break;
            case LONG:
                java = buffer.getLong();
                break;
            case TAG:
                java = ByteBuffers.getUtf8String(buffer);
                break;
            case TIMESTAMP:
                java = Timestamp.fromMicros(buffer.getLong());
                break;
            case FUNCTION:
                FunctionType type = Enums.parseIgnoreCase(FunctionType.class, buffer.get());
                long timestamp = buffer.getLong();
                int nameLength = buffer.getInt();
                String name = ByteBuffers.getUtf8String(ByteBuffers.get(buffer, nameLength));
                int keyLength;
                String key;
                switch(type) {
                    case INDEX:
                        key = ByteBuffers.getUtf8String(buffer);
                        java = new IndexFunction(name, key, timestamp);
                        break;
                    case KEY_RECORDS:
                        keyLength = buffer.getInt();
                        key = ByteBuffers.getUtf8String(ByteBuffers.get(buffer, keyLength));
                        ArrayBuilder<Long> ab = ArrayBuilder.builder();
                        while (buffer.hasRemaining()) {
                            long record = buffer.getLong();
                            ab.add(record);
                        }
                        java = new KeyRecordsFunction(timestamp, name, key, ab.build());
                        break;
                    case KEY_CONDITION:
                        keyLength = buffer.getInt();
                        key = ByteBuffers.getUtf8String(ByteBuffers.get(buffer, keyLength));
                        String condition = ByteBuffers.getUtf8String(buffer);
                        ConditionTree tree = (ConditionTree) ConcourseCompiler.get().parse(condition);
                        java = new KeyConditionFunction(name, key, tree, timestamp);
                        break;
                }
                break;
            case NULL:
                java = null;
                break;
            default:
                java = ByteBuffers.getUtf8String(buffer);
                break;
        }
        buffer.rewind();
    }
    return java;
}
Also used : IndexFunction(com.cinchapi.ccl.type.function.IndexFunction) KeyRecordsFunction(com.cinchapi.ccl.type.function.KeyRecordsFunction) ConditionTree(com.cinchapi.ccl.syntax.ConditionTree) TObject(com.cinchapi.concourse.thrift.TObject) KeyConditionFunction(com.cinchapi.ccl.type.function.KeyConditionFunction) ByteBuffer(java.nio.ByteBuffer)

Example 5 with IndexFunction

use of com.cinchapi.ccl.type.function.IndexFunction in project concourse by cinchapi.

the class CclFunctionsTest method testFindKeyOperatorIndexFunctionObjectEvaluationValue.

@Test
public void testFindKeyOperatorIndexFunctionObjectEvaluationValue() {
    setupDatabaseKey(client);
    Number avgAge = client.calculate().average("age");
    Set<Long> expected = client.find("age", Operator.GREATER_THAN, avgAge);
    Set<Long> actual = client.find("age", Operator.GREATER_THAN, new IndexFunction("avg", "age"));
    Assert.assertEquals(expected, actual);
}
Also used : IndexFunction(com.cinchapi.ccl.type.function.IndexFunction) ConcourseIntegrationTest(com.cinchapi.concourse.test.ConcourseIntegrationTest) Test(org.junit.Test)

Aggregations

IndexFunction (com.cinchapi.ccl.type.function.IndexFunction)6 TObject (com.cinchapi.concourse.thrift.TObject)4 KeyConditionFunction (com.cinchapi.ccl.type.function.KeyConditionFunction)3 KeyRecordsFunction (com.cinchapi.ccl.type.function.KeyRecordsFunction)3 Function (com.cinchapi.ccl.type.Function)2 TemporalFunction (com.cinchapi.ccl.type.function.TemporalFunction)2 Link (com.cinchapi.concourse.Link)2 Type (com.cinchapi.concourse.thrift.Type)2 ByteBuffer (java.nio.ByteBuffer)2 Test (org.junit.Test)2 FunctionValueSymbol (com.cinchapi.ccl.grammar.FunctionValueSymbol)1 Symbol (com.cinchapi.ccl.grammar.Symbol)1 ConditionTree (com.cinchapi.ccl.syntax.ConditionTree)1 AdHocIterator (com.cinchapi.common.base.AdHocIterator)1 ArrayBuilder (com.cinchapi.common.base.ArrayBuilder)1 Reflection (com.cinchapi.common.reflect.Reflection)1 Constants (com.cinchapi.concourse.Constants)1 Tag (com.cinchapi.concourse.Tag)1 Timestamp (com.cinchapi.concourse.Timestamp)1 Calculations (com.cinchapi.concourse.server.calculate.Calculations)1