use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.
the class SubfieldExtractor method toRowExpression.
private RowExpression toRowExpression(Subfield subfield, List<Type> types) {
List<Subfield.PathElement> path = subfield.getPath();
if (path.isEmpty()) {
return new VariableReferenceExpression(Optional.empty(), subfield.getRootName(), types.get(0));
}
RowExpression base = toRowExpression(new Subfield(subfield.getRootName(), path.subList(0, path.size() - 1)), types.subList(0, types.size() - 1));
Type baseType = types.get(types.size() - 2);
Subfield.PathElement pathElement = path.get(path.size() - 1);
if (pathElement instanceof Subfield.LongSubscript) {
Type indexType = baseType instanceof MapType ? ((MapType) baseType).getKeyType() : BIGINT;
FunctionHandle functionHandle = functionResolution.subscriptFunction(baseType, indexType);
ConstantExpression index = new ConstantExpression(base.getSourceLocation(), ((Subfield.LongSubscript) pathElement).getIndex(), indexType);
return new CallExpression(base.getSourceLocation(), SUBSCRIPT.name(), functionHandle, types.get(types.size() - 1), ImmutableList.of(base, index));
}
if (pathElement instanceof Subfield.StringSubscript) {
Type indexType = ((MapType) baseType).getKeyType();
FunctionHandle functionHandle = functionResolution.subscriptFunction(baseType, indexType);
ConstantExpression index = new ConstantExpression(base.getSourceLocation(), Slices.utf8Slice(((Subfield.StringSubscript) pathElement).getIndex()), indexType);
return new CallExpression(base.getSourceLocation(), SUBSCRIPT.name(), functionHandle, types.get(types.size() - 1), ImmutableList.of(base, index));
}
if (pathElement instanceof Subfield.NestedField) {
Subfield.NestedField nestedField = (Subfield.NestedField) pathElement;
return new SpecialFormExpression(base.getSourceLocation(), DEREFERENCE, types.get(types.size() - 1), base, new ConstantExpression(base.getSourceLocation(), getFieldIndex((RowType) baseType, nestedField.getName()), INTEGER));
}
verify(false, "Unexpected path element: " + pathElement);
return null;
}
use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.
the class OrCodeGenerator method generateExpression.
@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generator, Type returnType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) {
Preconditions.checkArgument(arguments.size() == 2);
// We flatten the AND here.
Deque<RowExpression> stack = new ArrayDeque<>();
stack.push(arguments.get(1));
stack.push(arguments.get(0));
ImmutableList.Builder<RowExpression> flattenedArgs = ImmutableList.builder();
do {
RowExpression operand = stack.pop();
if (operand instanceof SpecialFormExpression && ((SpecialFormExpression) operand).getForm() == SpecialFormExpression.Form.OR) {
stack.push(((SpecialFormExpression) operand).getArguments().get(1));
stack.push(((SpecialFormExpression) operand).getArguments().get(0));
} else {
flattenedArgs.add(operand);
}
} while (!stack.isEmpty());
BytecodeBlock block = new BytecodeBlock().comment("OR").setDescription("OR");
LabelNode trueLabel = new LabelNode("true");
LabelNode endLabel = new LabelNode("end");
Variable wasNull = generator.wasNull();
Variable hasNulls = generator.getScope().createTempVariable(boolean.class);
block.initializeVariable(hasNulls);
for (RowExpression expression : flattenedArgs.build()) {
block.comment("do { eval arg; if (wasNull) { hasNull = true; wasNull = false; } else if (true) goto ret_true; }").append(generator.generate(expression, Optional.empty()));
IfStatement ifOperandIsNull = new IfStatement("if left wasNulll...").condition(wasNull);
ifOperandIsNull.ifTrue().comment("clear the null flag and remember there was a null").putVariable(hasNulls, true).putVariable(wasNull, false).pop(boolean.class);
ifOperandIsNull.ifFalse().ifTrueGoto(trueLabel);
block.append(ifOperandIsNull);
}
// We evaluated all operands. So check if any of them was null
IfStatement ifHasNulls = new IfStatement("hasNulls is true");
ifHasNulls.condition().append(hasNulls);
ifHasNulls.ifTrue().comment("at least one of the arguments is null and none of them is true. So set wasNull to true").putVariable(wasNull, true).push(false);
ifHasNulls.ifFalse().push(false);
block.append(ifHasNulls).gotoLabel(endLabel);
block.visitLabel(trueLabel).comment("at least one of the args is true, clear wasNull and return true").push(true).gotoLabel(endLabel);
block.visitLabel(endLabel);
outputBlockVariable.ifPresent(output -> block.append(generateWrite(generator, returnType, output)));
return block;
}
use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.
the class RewriteAggregationIfToFilter method shouldRewriteAggregation.
private boolean shouldRewriteAggregation(Aggregation aggregation, ProjectNode sourceProject) {
if (functionAndTypeManager.getFunctionMetadata(aggregation.getFunctionHandle()).isCalledOnNullInput()) {
// This rewrite will filter out the null values. It could change the behavior if the aggregation is also applied on NULLs.
return false;
}
if (!(aggregation.getArguments().size() == 1 && aggregation.getArguments().get(0) instanceof VariableReferenceExpression)) {
// Currently we only handle aggregation with a single VariableReferenceExpression. The detailed expressions are in a project node below this aggregation.
return false;
}
if (aggregation.getFilter().isPresent() || aggregation.getMask().isPresent()) {
// Do not rewrite the aggregation if it already has a filter or mask.
return false;
}
RowExpression sourceExpression = sourceProject.getAssignments().get((VariableReferenceExpression) aggregation.getArguments().get(0));
if (sourceExpression instanceof CallExpression) {
CallExpression callExpression = (CallExpression) sourceExpression;
if (callExpression.getArguments().size() == 1 && standardFunctionResolution.isCastFunction(callExpression.getFunctionHandle())) {
// If the expression is CAST(), check the expression inside.
sourceExpression = callExpression.getArguments().get(0);
}
}
if (!(sourceExpression instanceof SpecialFormExpression) || !rowExpressionDeterminismEvaluator.isDeterministic(sourceExpression)) {
return false;
}
SpecialFormExpression expression = (SpecialFormExpression) sourceExpression;
// Only rewrite the aggregation if the else branch is not present or the else result is NULL.
return expression.getForm() == IF && Expressions.isNull(expression.getArguments().get(2));
}
use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.
the class TestRowExpressionFormatter method testComplex.
@Test
public void testComplex() {
RowExpression complexExpression;
RowExpression expression = createCallExpression(ADD);
complexExpression = call(SUBTRACT.name(), FUNCTION_AND_TYPE_MANAGER.resolveOperator(SUBTRACT, fromTypes(BIGINT, BIGINT)), BIGINT, C_BIGINT, expression);
assertEquals(format(complexExpression), "(c_bigint) - ((c_bigint) + (BIGINT'5'))");
RowExpression expression1 = createCallExpression(ADD);
RowExpression expression2 = call(MULTIPLY.name(), FUNCTION_AND_TYPE_MANAGER.resolveOperator(MULTIPLY, fromTypes(BIGINT, BIGINT)), BIGINT, expression1, C_BIGINT);
RowExpression expression3 = createCallExpression(GREATER_THAN);
complexExpression = new SpecialFormExpression(OR, BOOLEAN, expression2, expression3);
assertEquals(format(complexExpression), "(((c_bigint) + (BIGINT'5')) * (c_bigint)) OR ((c_bigint) > (BIGINT'5'))");
ArrayType arrayType = (ArrayType) C_BIGINT_ARRAY.getType();
Type elementType = arrayType.getElementType();
expression1 = call(SUBSCRIPT.name(), FUNCTION_AND_TYPE_MANAGER.resolveOperator(SUBSCRIPT, fromTypes(arrayType, elementType)), elementType, ImmutableList.of(C_BIGINT_ARRAY, constant(5L, INTEGER)));
expression2 = call(NEGATION.name(), FUNCTION_AND_TYPE_MANAGER.resolveOperator(NEGATION, fromTypes(expression1.getType())), expression1.getType(), expression1);
expression3 = call(ADD.name(), FUNCTION_AND_TYPE_MANAGER.resolveOperator(ADD, fromTypes(expression2.getType(), BIGINT)), BIGINT, expression2, constant(5L, BIGINT));
assertEquals(format(expression3), "(-(c_bigint_array[INTEGER'5'])) + (BIGINT'5')");
}
use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.
the class TestPageFunctionCompiler method testCommonSubExpressionInFilter.
@Test
public void testCommonSubExpressionInFilter() {
PageFunctionCompiler functionCompiler = new PageFunctionCompiler(createTestMetadataManager(), 0);
Supplier<PageFilter> pageFilter = functionCompiler.compileFilter(SESSION.getSqlFunctionProperties(), new SpecialFormExpression(AND, BIGINT, ADD_X_Y_GREATER_THAN_2, ADD_X_Y_LESS_THAN_10), true, Optional.empty());
Page input = createLongBlockPage(2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
SelectedPositions positions = filter(pageFilter.get(), input);
assertEquals(positions.size(), 3);
assertEquals(positions.getPositions(), new int[] { 2, 3, 4 });
}
Aggregations