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());
}
}
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);
}
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;
}
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);
}
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));
}
Aggregations