use of com.facebook.presto.spi.relation.ConstantExpression in project presto by prestodb.
the class SubfieldExtractor method toSubfield.
private static Optional<Subfield> toSubfield(RowExpression expression, StandardFunctionResolution functionResolution, ExpressionOptimizer expressionOptimizer, ConnectorSession connectorSession) {
List<Subfield.PathElement> elements = new ArrayList<>();
while (true) {
if (expression instanceof VariableReferenceExpression) {
Collections.reverse(elements);
return Optional.of(new Subfield(((VariableReferenceExpression) expression).getName(), unmodifiableList(elements)));
}
if (expression instanceof SpecialFormExpression && ((SpecialFormExpression) expression).getForm() == DEREFERENCE) {
SpecialFormExpression dereferenceExpression = (SpecialFormExpression) expression;
RowExpression base = dereferenceExpression.getArguments().get(0);
RowType baseType = (RowType) base.getType();
RowExpression indexExpression = expressionOptimizer.optimize(dereferenceExpression.getArguments().get(1), ExpressionOptimizer.Level.OPTIMIZED, connectorSession);
if (indexExpression instanceof ConstantExpression) {
Object index = ((ConstantExpression) indexExpression).getValue();
if (index instanceof Number) {
Optional<String> fieldName = baseType.getFields().get(((Number) index).intValue()).getName();
if (fieldName.isPresent()) {
elements.add(new Subfield.NestedField(fieldName.get()));
expression = base;
continue;
}
}
}
return Optional.empty();
}
if (expression instanceof CallExpression && functionResolution.isSubscriptFunction(((CallExpression) expression).getFunctionHandle())) {
List<RowExpression> arguments = ((CallExpression) expression).getArguments();
RowExpression indexExpression = expressionOptimizer.optimize(arguments.get(1), ExpressionOptimizer.Level.OPTIMIZED, connectorSession);
if (indexExpression instanceof ConstantExpression) {
Object index = ((ConstantExpression) indexExpression).getValue();
if (index instanceof Number) {
elements.add(new Subfield.LongSubscript(((Number) index).longValue()));
expression = arguments.get(0);
continue;
}
if (isVarcharType(indexExpression.getType())) {
elements.add(new Subfield.StringSubscript(((Slice) index).toStringUtf8()));
expression = arguments.get(0);
continue;
}
}
return Optional.empty();
}
return Optional.empty();
}
}
use of com.facebook.presto.spi.relation.ConstantExpression in project presto by prestodb.
the class RowExpressionVerifier method visitCast.
@Override
protected Boolean visitCast(Cast expected, RowExpression actual) {
// TODO: clean up cast path
if (actual instanceof ConstantExpression && expected.getExpression() instanceof Literal && expected.getType().equals(actual.getType().toString())) {
Literal literal = (Literal) expected.getExpression();
if (literal instanceof StringLiteral) {
Object value = LiteralInterpreter.evaluate(TEST_SESSION.toConnectorSession(), (ConstantExpression) actual);
String actualString = value instanceof Slice ? ((Slice) value).toStringUtf8() : String.valueOf(value);
return ((StringLiteral) literal).getValue().equals(actualString);
}
return getValueFromLiteral(literal).equals(String.valueOf(LiteralInterpreter.evaluate(TEST_SESSION.toConnectorSession(), (ConstantExpression) actual)));
}
if (actual instanceof VariableReferenceExpression && expected.getExpression() instanceof SymbolReference && expected.getType().equals(actual.getType().toString())) {
return visitSymbolReference((SymbolReference) expected.getExpression(), actual);
}
if (!(actual instanceof CallExpression) || !functionResolution.isCastFunction(((CallExpression) actual).getFunctionHandle())) {
return false;
}
if (!expected.getType().equalsIgnoreCase(actual.getType().toString()) && !(expected.getType().toLowerCase(ENGLISH).equals(VARCHAR) && actual.getType().getTypeSignature().getBase().equals(VARCHAR))) {
return false;
}
return process(expected.getExpression(), ((CallExpression) actual).getArguments().get(0));
}
use of com.facebook.presto.spi.relation.ConstantExpression in project presto by prestodb.
the class TestRowExpressionSerde method testArrayLiteral.
@Test
public void testArrayLiteral() {
RowExpression rowExpression = getRoundTrip("ARRAY [1, 2, 3]", true);
assertTrue(rowExpression instanceof ConstantExpression);
Object value = ((ConstantExpression) rowExpression).getValue();
assertTrue(value instanceof IntArrayBlock);
IntArrayBlock block = (IntArrayBlock) value;
assertEquals(block.getPositionCount(), 3);
assertEquals(block.getInt(0), 1);
assertEquals(block.getInt(1), 2);
assertEquals(block.getInt(2), 3);
}
use of com.facebook.presto.spi.relation.ConstantExpression in project presto by prestodb.
the class LocalExecutionPlanner method createOutputPartitioning.
private Optional<OutputPartitioning> createOutputPartitioning(TaskContext taskContext, PartitioningScheme partitioningScheme) {
if (partitioningScheme.getPartitioning().getHandle().equals(FIXED_BROADCAST_DISTRIBUTION) || partitioningScheme.getPartitioning().getHandle().equals(FIXED_ARBITRARY_DISTRIBUTION) || partitioningScheme.getPartitioning().getHandle().equals(SCALED_WRITER_DISTRIBUTION) || partitioningScheme.getPartitioning().getHandle().equals(SINGLE_DISTRIBUTION) || partitioningScheme.getPartitioning().getHandle().equals(COORDINATOR_DISTRIBUTION)) {
return Optional.empty();
}
List<VariableReferenceExpression> outputLayout = partitioningScheme.getOutputLayout();
// We can convert the variables directly into channels, because the root must be a sink and therefore the layout is fixed
List<Integer> partitionChannels;
List<Optional<ConstantExpression>> partitionConstants;
List<Type> partitionChannelTypes;
if (partitioningScheme.getHashColumn().isPresent()) {
partitionChannels = ImmutableList.of(outputLayout.indexOf(partitioningScheme.getHashColumn().get()));
partitionConstants = ImmutableList.of(Optional.empty());
partitionChannelTypes = ImmutableList.of(BIGINT);
} else {
checkArgument(partitioningScheme.getPartitioning().getArguments().stream().allMatch(argument -> argument instanceof ConstantExpression || argument instanceof VariableReferenceExpression), format("Expect all partitioning arguments to be either ConstantExpression or VariableReferenceExpression, but get %s", partitioningScheme.getPartitioning().getArguments()));
partitionChannels = partitioningScheme.getPartitioning().getArguments().stream().map(argument -> {
if (argument instanceof ConstantExpression) {
return -1;
}
return outputLayout.indexOf(argument);
}).collect(toImmutableList());
partitionConstants = partitioningScheme.getPartitioning().getArguments().stream().map(argument -> {
if (argument instanceof ConstantExpression) {
return Optional.of((ConstantExpression) argument);
}
return Optional.<ConstantExpression>empty();
}).collect(toImmutableList());
partitionChannelTypes = partitioningScheme.getPartitioning().getArguments().stream().map(RowExpression::getType).collect(toImmutableList());
}
PartitionFunction partitionFunction = nodePartitioningManager.getPartitionFunction(taskContext.getSession(), partitioningScheme, partitionChannelTypes);
OptionalInt nullChannel = OptionalInt.empty();
Set<VariableReferenceExpression> partitioningColumns = partitioningScheme.getPartitioning().getVariableReferences();
// partitioningColumns expected to have one column in the normal case, and zero columns when partitioning on a constant
checkArgument(!partitioningScheme.isReplicateNullsAndAny() || partitioningColumns.size() <= 1);
if (partitioningScheme.isReplicateNullsAndAny() && partitioningColumns.size() == 1) {
nullChannel = OptionalInt.of(outputLayout.indexOf(getOnlyElement(partitioningColumns)));
}
return Optional.of(new OutputPartitioning(partitionFunction, partitionChannels, partitionConstants, partitioningScheme.isReplicateNullsAndAny(), nullChannel));
}
use of com.facebook.presto.spi.relation.ConstantExpression in project presto by prestodb.
the class PinotFilterExpressionConverter method handleTimeValueCast.
private Optional<String> handleTimeValueCast(Function<VariableReferenceExpression, Selection> context, RowExpression timeFieldExpression, RowExpression timeValueExpression) {
// Handle the binary comparison logic of <DATE/TIMESTAMP field> <binary op> <DATE/TIMESTAMP literal>.
// Pinot stores time as:
// - `DATE`: Stored as `INT`/`LONG` `daysSinceEpoch` value
// - `TIMESTAMP`: Stored as `LONG` `millisSinceEpoch` value.
// In order to push down this predicate, we need to convert the literal to the type of Pinot time field.
// Below code compares the time type of both side:
// - if same, then directly push down.
// - if not same, then convert the literal time type to the field time type.
// - if not compatible time types, returns Optional.empty(), indicates no change has been made in this cast.
// Take an example of comparing a `DATE` field to a `TIMESTAMP` literal:
// - Sample predicate: `WHERE eventDate < current_time`.
// - Input type is the `eventDate` field data type, which is `DATE`.
// - Expect type is the right side `literal type`, which means right side is `TIMESTAMP`.
// The code below converts `current_time` from `millisSinceEpoch` value to `daysSinceEpoch` value, which is
// comparable to values in `eventDate` column.
Type inputType;
Type expectedType;
if (!isDateTimeConstantType(timeFieldExpression.getType()) || !isDateTimeConstantType(timeValueExpression.getType())) {
return Optional.empty();
}
String timeValueString = timeValueExpression.accept(this, context).getDefinition();
if (timeFieldExpression instanceof CallExpression) {
// Handles cases like: `cast(eventDate as TIMESTAMP) < DATE '2014-01-31'`
// For cast function,
// - inputType is the argument type,
// - expectedType is the cast function return type.
CallExpression callExpression = (CallExpression) timeFieldExpression;
if (!standardFunctionResolution.isCastFunction(callExpression.getFunctionHandle())) {
return Optional.empty();
}
if (callExpression.getArguments().size() != 1) {
return Optional.empty();
}
inputType = callExpression.getArguments().get(0).getType();
expectedType = callExpression.getType();
} else if (timeFieldExpression instanceof VariableReferenceExpression) {
// For VariableReferenceExpression,
// Handles queries like: `eventDate < TIMESTAMP '2014-01-31 00:00:00 UTC'`
// - inputType is timeFieldExpression type,
// - expectedType is the timeValueExpression type.
inputType = timeFieldExpression.getType();
expectedType = timeValueExpression.getType();
} else if (timeFieldExpression instanceof ConstantExpression) {
// timeFieldExpression is a ConstantExpression, directly return.
return Optional.of(timeValueString);
} else {
return Optional.empty();
}
if (inputType == DateType.DATE && (expectedType == TimestampType.TIMESTAMP || expectedType == TimestampWithTimeZoneType.TIMESTAMP_WITH_TIME_ZONE)) {
// time field is `DATE`, try to convert time value from `TIMESTAMP` to `DATE`
try {
return Optional.of(Long.toString(TimeUnit.MILLISECONDS.toDays(Long.parseLong(timeValueString))));
} catch (NumberFormatException e) {
throw new PinotException(PINOT_UNSUPPORTED_EXPRESSION, Optional.empty(), format("Unable to parse timestamp string: '%s'", timeValueString), e);
}
}
if ((inputType == TimestampType.TIMESTAMP || inputType == TimestampWithTimeZoneType.TIMESTAMP_WITH_TIME_ZONE) && expectedType == DateType.DATE) {
// time field is `TIMESTAMP`, try to convert time value from `DATE` to `TIMESTAMP`
try {
return Optional.of(Long.toString(TimeUnit.DAYS.toMillis(Long.parseLong(timeValueString))));
} catch (NumberFormatException e) {
throw new PinotException(PINOT_UNSUPPORTED_EXPRESSION, Optional.empty(), format("Unable to parse date string: '%s'", timeValueString), e);
}
}
// Vacuous cast from variable to same type: cast(eventDate, DAYS). Already handled by handleCast.
return Optional.of(timeValueString);
}
Aggregations