Search in sources :

Example 1 with Literal

use of io.crate.expression.symbol.Literal in project crate by crate.

the class WhereClauseAnalyzer method resolvePartitions.

public static PartitionResult resolvePartitions(Symbol query, DocTableInfo tableInfo, CoordinatorTxnCtx coordinatorTxnCtx, NodeContext nodeCtx) {
    assert tableInfo.isPartitioned() : "table must be partitioned in order to resolve partitions";
    assert !tableInfo.partitions().isEmpty() : "table must have at least one partition";
    PartitionReferenceResolver partitionReferenceResolver = preparePartitionResolver(tableInfo.partitionedByColumns());
    EvaluatingNormalizer normalizer = new EvaluatingNormalizer(nodeCtx, RowGranularity.PARTITION, partitionReferenceResolver, null);
    Symbol normalized;
    Map<Symbol, List<Literal>> queryPartitionMap = new HashMap<>();
    for (PartitionName partitionName : tableInfo.partitions()) {
        for (PartitionExpression partitionExpression : partitionReferenceResolver.expressions()) {
            partitionExpression.setNextRow(partitionName);
        }
        normalized = normalizer.normalize(query, coordinatorTxnCtx);
        assert normalized != null : "normalizing a query must not return null";
        if (normalized.equals(query)) {
            // no partition columns inside the where clause
            return new PartitionResult(query, Collections.emptyList());
        }
        boolean canMatch = WhereClause.canMatch(normalized);
        if (canMatch) {
            List<Literal> partitions = queryPartitionMap.get(normalized);
            if (partitions == null) {
                partitions = new ArrayList<>();
                queryPartitionMap.put(normalized, partitions);
            }
            partitions.add(Literal.of(partitionName.asIndexName()));
        }
    }
    if (queryPartitionMap.size() == 1) {
        Map.Entry<Symbol, List<Literal>> entry = Iterables.getOnlyElement(queryPartitionMap.entrySet());
        return new PartitionResult(entry.getKey(), Lists2.map(entry.getValue(), literal -> nullOrString(literal.value())));
    } else if (queryPartitionMap.size() > 0) {
        PartitionResult partitionResult = tieBreakPartitionQueries(normalizer, queryPartitionMap, coordinatorTxnCtx);
        return partitionResult == null ? // the query will then be evaluated correctly within each partition to see whether it matches or not
        new PartitionResult(query, Lists2.map(tableInfo.partitions(), PartitionName::asIndexName)) : partitionResult;
    } else {
        return new PartitionResult(Literal.BOOLEAN_FALSE, Collections.emptyList());
    }
}
Also used : Tuple(io.crate.common.collections.Tuple) ScalarsAndRefsToTrue(io.crate.analyze.ScalarsAndRefsToTrue) HashMap(java.util.HashMap) EvaluatingNormalizer(io.crate.expression.eval.EvaluatingNormalizer) PartitionName(io.crate.metadata.PartitionName) ArrayList(java.util.ArrayList) Map(java.util.Map) StringUtils.nullOrString(io.crate.common.StringUtils.nullOrString) Nullable(javax.annotation.Nullable) DocTableInfo(io.crate.metadata.doc.DocTableInfo) NodeContext(io.crate.metadata.NodeContext) WhereClause(io.crate.analyze.WhereClause) PartitionReferenceResolver(io.crate.metadata.PartitionReferenceResolver) Reference(io.crate.metadata.Reference) Iterables(io.crate.common.collections.Iterables) Lists2(io.crate.common.collections.Lists2) List(java.util.List) RowGranularity(io.crate.metadata.RowGranularity) DocTableRelation(io.crate.analyze.relations.DocTableRelation) Literal(io.crate.expression.symbol.Literal) Symbol(io.crate.expression.symbol.Symbol) AbstractTableRelation(io.crate.analyze.relations.AbstractTableRelation) PartitionExpression(io.crate.expression.reference.partitioned.PartitionExpression) Collections(java.util.Collections) CoordinatorTxnCtx(io.crate.metadata.CoordinatorTxnCtx) EvaluatingNormalizer(io.crate.expression.eval.EvaluatingNormalizer) HashMap(java.util.HashMap) Symbol(io.crate.expression.symbol.Symbol) PartitionName(io.crate.metadata.PartitionName) PartitionExpression(io.crate.expression.reference.partitioned.PartitionExpression) Literal(io.crate.expression.symbol.Literal) ArrayList(java.util.ArrayList) List(java.util.List) PartitionReferenceResolver(io.crate.metadata.PartitionReferenceResolver) HashMap(java.util.HashMap) Map(java.util.Map)

Example 2 with Literal

use of io.crate.expression.symbol.Literal in project crate by crate.

the class InputColumns method tryCreateSubscriptOnRoot.

@Nullable
private static Symbol tryCreateSubscriptOnRoot(Symbol symbol, ColumnIdent column, HashMap<Symbol, InputColumn> inputs) {
    if (column.isTopLevel()) {
        return null;
    }
    ColumnIdent root = column.getRoot();
    InputColumn rootIC = lookupValueByColumn(inputs, root);
    if (rootIC == null) {
        return symbol;
    }
    DataType<?> returnType = symbol.valueType();
    List<String> path = column.path();
    List<Symbol> arguments = mapTail(rootIC, path, Literal::of);
    return new Function(SubscriptObjectFunction.SIGNATURE, arguments, returnType);
}
Also used : ColumnIdent(io.crate.metadata.ColumnIdent) SubscriptObjectFunction(io.crate.expression.scalar.SubscriptObjectFunction) Function(io.crate.expression.symbol.Function) WindowFunction(io.crate.expression.symbol.WindowFunction) InputColumn(io.crate.expression.symbol.InputColumn) AliasSymbol(io.crate.expression.symbol.AliasSymbol) ParameterSymbol(io.crate.expression.symbol.ParameterSymbol) SelectSymbol(io.crate.expression.symbol.SelectSymbol) ScopedSymbol(io.crate.expression.symbol.ScopedSymbol) Symbol(io.crate.expression.symbol.Symbol) Literal(io.crate.expression.symbol.Literal) Nullable(javax.annotation.Nullable)

Example 3 with Literal

use of io.crate.expression.symbol.Literal in project crate by crate.

the class ValueNormalizer method normalizeInputForReference.

/**
 * normalize and validate given value according to the corresponding {@link io.crate.metadata.Reference}
 *
 * @param valueSymbol the value to normalize, might be anything from {@link Scalar} to {@link io.crate.expression.symbol.Literal}
 * @param reference   the reference to which the value has to comply in terms of type-compatibility
 * @return the normalized Symbol, should be a literal
 * @throws io.crate.exceptions.ColumnValidationException
 */
public static Symbol normalizeInputForReference(Symbol valueSymbol, Reference reference, TableInfo tableInfo, Function<Symbol, Symbol> normalizer) {
    assert valueSymbol != null : "valueSymbol must not be null";
    DataType<?> targetType = getTargetType(valueSymbol, reference);
    try {
        valueSymbol = normalizer.apply(valueSymbol.cast(reference.valueType()));
    } catch (PgArrayParsingException | ConversionException e) {
        throw new ColumnValidationException(reference.column().name(), tableInfo.ident(), String.format(Locale.ENGLISH, "Cannot cast expression `%s` of type `%s` to `%s`", valueSymbol, valueSymbol.valueType().getName(), reference.valueType().getName()));
    }
    if (!(valueSymbol instanceof Literal)) {
        return valueSymbol.cast(targetType);
    }
    Object value = ((Literal<?>) valueSymbol).value();
    if (value == null) {
        return valueSymbol;
    }
    try {
        if (targetType.id() == ObjectType.ID) {
            // noinspection unchecked
            normalizeObjectValue((Map) value, reference, tableInfo);
        } else if (isObjectArray(targetType)) {
            normalizeObjectArrayValue((List<Map<String, Object>>) value, reference, tableInfo);
        }
    } catch (PgArrayParsingException | ConversionException e) {
        throw new ColumnValidationException(reference.column().name(), tableInfo.ident(), Symbols.format("\"%s\" has a type that can't be implicitly cast to that of \"%s\" (" + reference.valueType().getName() + ")", valueSymbol, reference));
    }
    return valueSymbol;
}
Also used : ConversionException(io.crate.exceptions.ConversionException) Literal(io.crate.expression.symbol.Literal) List(java.util.List) ColumnValidationException(io.crate.exceptions.ColumnValidationException) PgArrayParsingException(io.crate.protocols.postgres.parser.PgArrayParsingException)

Example 4 with Literal

use of io.crate.expression.symbol.Literal in project crate by crate.

the class ScalarTestCase method assertEvaluate.

/**
 * asserts that the given functionExpression matches the given matcher.
 * If the functionExpression contains references the inputs will be used in the order the references appear.
 * <p>
 * E.g.
 * <code>
 * assertEvaluate("foo(name, age)", anyOf("expectedValue1", "expectedValue2"), inputForName, inputForAge)
 * </code>
 */
@SuppressWarnings("unchecked")
public <T> void assertEvaluate(String functionExpression, Matcher<T> expectedValue, Literal<?>... literals) {
    if (expectedValue == null) {
        expectedValue = (Matcher<T>) nullValue();
    }
    sqlExpressions.context().allowEagerNormalize(true);
    Symbol functionSymbol = sqlExpressions.asSymbol(functionExpression);
    functionSymbol = sqlExpressions.normalize(functionSymbol);
    if (functionSymbol instanceof Literal) {
        Object value = ((Literal) functionSymbol).value();
        assertThat((T) value, expectedValue);
        return;
    }
    LinkedList<Literal<?>> unusedLiterals = new LinkedList<>(Arrays.asList(literals));
    Function function = (Function) RefReplacer.replaceRefs(functionSymbol, r -> {
        if (unusedLiterals.isEmpty()) {
            throw new IllegalArgumentException("No value literal for reference=" + r + ", please add more literals");
        }
        // Can be null.
        Literal<?> literal = unusedLiterals.pollFirst();
        return literal;
    });
    if (unusedLiterals.size() == literals.length) {
        // Currently it's supposed that literals will be either references or parameters.
        // One of replaceRefs and bindParameters does nothing and doesn't consume unusedLiterals.
        function = (Function) ParameterBinder.bindParameters(function, p -> {
            if (unusedLiterals.isEmpty()) {
                throw new IllegalArgumentException("No value literal for parameter=" + p + ", please add more literals");
            }
            // Can be null.
            Literal<?> literal = unusedLiterals.pollFirst();
            return literal;
        });
    }
    Scalar scalar = (Scalar) sqlExpressions.nodeCtx.functions().getQualified(function, txnCtx.sessionSettings().searchPath());
    assertThat("Function implementation not found using full qualified lookup", scalar, Matchers.notNullValue());
    AssertMax1ValueCallInput[] arguments = new AssertMax1ValueCallInput[function.arguments().size()];
    InputFactory.Context<CollectExpression<Row, ?>> ctx = inputFactory.ctxForInputColumns(txnCtx);
    for (int i = 0; i < function.arguments().size(); i++) {
        Symbol arg = function.arguments().get(i);
        Input<?> input = ctx.add(arg);
        arguments[i] = new AssertMax1ValueCallInput(input);
    }
    Object actualValue = scalar.compile(function.arguments()).evaluate(txnCtx, sqlExpressions.nodeCtx, (Input[]) arguments);
    assertThat((T) actualValue, expectedValue);
    // Reset calls
    for (AssertMax1ValueCallInput argument : arguments) {
        argument.calls = 0;
    }
    actualValue = scalar.evaluate(txnCtx, sqlExpressions.nodeCtx, arguments);
    assertThat((T) actualValue, expectedValue);
}
Also used : Input(io.crate.data.Input) TransactionContext(io.crate.metadata.TransactionContext) SqlExpressions(io.crate.testing.SqlExpressions) InputColumn(io.crate.expression.symbol.InputColumn) Arrays(java.util.Arrays) ParameterBinder(io.crate.expression.symbol.ParameterBinder) RelationName(io.crate.metadata.RelationName) SessionSettings(io.crate.metadata.settings.SessionSettings) CollectExpression(io.crate.execution.engine.collect.CollectExpression) Matchers.not(org.hamcrest.Matchers.not) SearchPath(io.crate.metadata.SearchPath) CrateDummyClusterServiceUnitTest(io.crate.test.integration.CrateDummyClusterServiceUnitTest) RefReplacer(io.crate.expression.symbol.RefReplacer) Locale(java.util.Locale) Map(java.util.Map) Matchers.nullValue(org.hamcrest.Matchers.nullValue) Is.is(org.hamcrest.core.Is.is) SQLExecutor(io.crate.testing.SQLExecutor) LinkedList(java.util.LinkedList) Before(org.junit.Before) DocTableInfo(io.crate.metadata.doc.DocTableInfo) DataType(io.crate.types.DataType) Matchers(org.hamcrest.Matchers) Function(io.crate.expression.symbol.Function) Lists2(io.crate.common.collections.Lists2) Matchers.instanceOf(org.hamcrest.Matchers.instanceOf) List(java.util.List) DocTableRelation(io.crate.analyze.relations.DocTableRelation) Row(io.crate.data.Row) Literal(io.crate.expression.symbol.Literal) Symbol(io.crate.expression.symbol.Symbol) FunctionImplementation(io.crate.metadata.FunctionImplementation) DocSchemaInfo(io.crate.metadata.doc.DocSchemaInfo) Matcher(org.hamcrest.Matcher) AnalyzedRelation(io.crate.analyze.relations.AnalyzedRelation) InputFactory(io.crate.expression.InputFactory) Scalar(io.crate.metadata.Scalar) CoordinatorTxnCtx(io.crate.metadata.CoordinatorTxnCtx) InputFactory(io.crate.expression.InputFactory) Symbol(io.crate.expression.symbol.Symbol) CollectExpression(io.crate.execution.engine.collect.CollectExpression) LinkedList(java.util.LinkedList) Scalar(io.crate.metadata.Scalar) Function(io.crate.expression.symbol.Function) Input(io.crate.data.Input) Literal(io.crate.expression.symbol.Literal)

Example 5 with Literal

use of io.crate.expression.symbol.Literal in project crate by crate.

the class UpdateAnalyzerTest method testUpdateWithEmptyObjectArray.

@Test
public void testUpdateWithEmptyObjectArray() throws Exception {
    Object[] params = { new Map[0], 0 };
    AnalyzedUpdateStatement update = analyze("update users set friends=? where other_id=0");
    Assignments assignments = Assignments.convert(update.assignmentByTargetCol(), e.nodeCtx);
    Symbol[] sources = assignments.bindSources(((DocTableInfo) update.table().tableInfo()), new RowN(params), SubQueryResults.EMPTY);
    assertThat(sources[0].valueType().id(), is(ArrayType.ID));
    assertThat(((ArrayType) sources[0].valueType()).innerType().id(), is(ObjectType.ID));
    assertThat(((List) ((Literal) sources[0]).value()).size(), is(0));
}
Also used : ArrayType(io.crate.types.ArrayType) DocTableInfo(io.crate.metadata.doc.DocTableInfo) RowN(io.crate.data.RowN) ParameterSymbol(io.crate.expression.symbol.ParameterSymbol) Symbol(io.crate.expression.symbol.Symbol) Literal(io.crate.expression.symbol.Literal) SymbolMatchers.isLiteral(io.crate.testing.SymbolMatchers.isLiteral) Assignments(io.crate.expression.symbol.Assignments) CrateDummyClusterServiceUnitTest(io.crate.test.integration.CrateDummyClusterServiceUnitTest) Test(org.junit.Test)

Aggregations

Literal (io.crate.expression.symbol.Literal)27 CrateDummyClusterServiceUnitTest (io.crate.test.integration.CrateDummyClusterServiceUnitTest)17 Symbol (io.crate.expression.symbol.Symbol)16 Test (org.junit.Test)16 SymbolMatchers.isLiteral (io.crate.testing.SymbolMatchers.isLiteral)13 HashMap (java.util.HashMap)12 ColumnIdent (io.crate.metadata.ColumnIdent)11 Reference (io.crate.metadata.Reference)11 Map (java.util.Map)11 Function (io.crate.expression.symbol.Function)5 DocTableInfo (io.crate.metadata.doc.DocTableInfo)5 List (java.util.List)5 Nullable (javax.annotation.Nullable)5 Lists2 (io.crate.common.collections.Lists2)4 EvaluatingNormalizer (io.crate.expression.eval.EvaluatingNormalizer)4 CoordinatorTxnCtx (io.crate.metadata.CoordinatorTxnCtx)4 DocTableRelation (io.crate.analyze.relations.DocTableRelation)3 Iterables (io.crate.common.collections.Iterables)3 Tuple (io.crate.common.collections.Tuple)3 Input (io.crate.data.Input)3