use of com.facebook.presto.spi.relation.SpecialFormExpression in project urban-eureka by errir503.
the class LogicalRowExpressions method extractPredicates.
public static List<RowExpression> extractPredicates(Form form, RowExpression expression) {
if (expression instanceof SpecialFormExpression && ((SpecialFormExpression) expression).getForm() == form) {
SpecialFormExpression specialFormExpression = (SpecialFormExpression) expression;
if (specialFormExpression.getArguments().size() == 2) {
List<RowExpression> predicates = new ArrayList<>();
predicates.addAll(extractPredicates(form, specialFormExpression.getArguments().get(0)));
predicates.addAll(extractPredicates(form, specialFormExpression.getArguments().get(1)));
return unmodifiableList(predicates);
}
if (specialFormExpression.getArguments().size() == 1 && form == IS_NULL) {
return singletonList(expression);
}
throw new IllegalStateException("Unexpected operands:" + expression + " " + form);
}
return singletonList(expression);
}
use of com.facebook.presto.spi.relation.SpecialFormExpression in project urban-eureka by errir503.
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 urban-eureka by errir503.
the class SwitchCodeGenerator method generateExpression.
@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) {
Scope scope = generatorContext.getScope();
BytecodeNode elseValue;
List<RowExpression> whenClauses;
RowExpression last = arguments.get(arguments.size() - 1);
if (last instanceof SpecialFormExpression && ((SpecialFormExpression) last).getForm().equals(WHEN)) {
whenClauses = arguments.subList(1, arguments.size());
elseValue = new BytecodeBlock().append(generatorContext.wasNull().set(constantTrue())).pushJavaDefault(returnType.getJavaType());
} else {
whenClauses = arguments.subList(1, arguments.size() - 1);
elseValue = generatorContext.generate(last, Optional.empty());
}
// determine the type of the value and result
RowExpression value = arguments.get(0);
Class<?> valueType = value.getType().getJavaType();
// We generate SearchedCase as CASE TRUE WHEN p1 THEN v1 WHEN p2 THEN p2...
boolean searchedCase = (value instanceof ConstantExpression && ((ConstantExpression) value).getType() == BOOLEAN && ((ConstantExpression) value).getValue() == Boolean.TRUE);
// evaluate the value and store it in a variable
LabelNode elseLabel = new LabelNode("else");
LabelNode endLabel = new LabelNode("end");
BytecodeBlock block = new BytecodeBlock();
Optional<BytecodeNode> getTempVariableNode;
if (!searchedCase) {
BytecodeNode valueBytecode = generatorContext.generate(value, Optional.empty());
Variable tempVariable = scope.createTempVariable(valueType);
block.append(valueBytecode).append(BytecodeUtils.ifWasNullClearPopAndGoto(scope, elseLabel, void.class, valueType)).putVariable(tempVariable);
getTempVariableNode = Optional.of(VariableInstruction.loadVariable(tempVariable));
} else {
getTempVariableNode = Optional.empty();
}
Variable wasNull = generatorContext.wasNull();
block.putVariable(wasNull, false);
Map<RowExpression, LabelNode> resultLabels = new HashMap<>();
// We already know the P1 .. Pn are all boolean just call them and search for true (false/null don't matter).
for (RowExpression clause : whenClauses) {
checkArgument(clause instanceof SpecialFormExpression && ((SpecialFormExpression) clause).getForm().equals(WHEN));
RowExpression operand = ((SpecialFormExpression) clause).getArguments().get(0);
BytecodeNode operandBytecode;
if (searchedCase) {
operandBytecode = generatorContext.generate(operand, Optional.empty());
} else {
// call equals(value, operandBytecode)
FunctionHandle equalsFunction = generatorContext.getFunctionManager().resolveOperator(EQUAL, fromTypes(value.getType(), operand.getType()));
operandBytecode = generatorContext.generateCall(EQUAL.name(), generatorContext.getFunctionManager().getJavaScalarFunctionImplementation(equalsFunction), ImmutableList.of(generatorContext.generate(operand, Optional.empty()), getTempVariableNode.get()));
}
block.append(operandBytecode);
IfStatement ifWasNull = new IfStatement().condition(wasNull);
ifWasNull.ifTrue().putVariable(wasNull, false).pop(// pop the result of the predicate eval
Boolean.class);
// Here the TOS is the result of the predicate.
RowExpression result = ((SpecialFormExpression) clause).getArguments().get(1);
LabelNode target = resultLabels.get(result);
if (target == null) {
target = new LabelNode(RESULT_LABEL_PREFIX + resultLabels.size());
resultLabels.put(result, target);
}
ifWasNull.ifFalse().ifTrueGoto(target);
block.append(ifWasNull);
}
// Here we evaluate the else result.
block.visitLabel(elseLabel).append(elseValue).gotoLabel(endLabel);
// Now generate the result expression code.
for (Map.Entry<RowExpression, LabelNode> resultLabel : resultLabels.entrySet()) {
block.visitLabel(resultLabel.getValue()).append(generatorContext.generate(resultLabel.getKey(), Optional.empty())).gotoLabel(endLabel);
}
block.visitLabel(endLabel);
outputBlockVariable.ifPresent(output -> block.append(generateWrite(generatorContext, returnType, output)));
return block;
}
use of com.facebook.presto.spi.relation.SpecialFormExpression in project urban-eureka by errir503.
the class TestRowExpressionFormatter method testSpecialForm.
@Test
public void testSpecialForm() {
RowExpression specialFormExpression;
// or and and
specialFormExpression = new SpecialFormExpression(OR, BOOLEAN, createCallExpression(NOT_EQUAL), createCallExpression(IS_DISTINCT_FROM));
assertEquals(format(specialFormExpression), "((c_bigint) <> (BIGINT'5')) OR ((c_bigint) IS DISTINCT FROM (BIGINT'5'))");
specialFormExpression = new SpecialFormExpression(AND, BOOLEAN, createCallExpression(EQUAL), createCallExpression(GREATER_THAN));
assertEquals(format(specialFormExpression), "((c_bigint) = (BIGINT'5')) AND ((c_bigint) > (BIGINT'5'))");
// other
specialFormExpression = new SpecialFormExpression(IS_NULL, BOOLEAN, createCallExpression(ADD));
assertEquals(format(specialFormExpression), "IS_NULL((c_bigint) + (BIGINT'5'))");
}
use of com.facebook.presto.spi.relation.SpecialFormExpression in project urban-eureka by errir503.
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')");
}
Aggregations