use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.
the class DereferenceCodeGenerator method generateExpression.
@Override
public BytecodeNode generateExpression(BytecodeGeneratorContext generator, Type returnType, List<RowExpression> arguments, Optional<Variable> outputBlockVariable) {
checkArgument(arguments.size() == 2);
CallSiteBinder callSiteBinder = generator.getCallSiteBinder();
// Collect all nested intermediateDerefs
ImmutableList.Builder<RowExpression> nestedDerefernces = ImmutableList.builder();
RowExpression nestedObject = arguments.get(0);
int leafFieldIndex = ((Number) ((ConstantExpression) arguments.get(1)).getValue()).intValue();
// Find all the intermediate nestedDerefernces.
while (nestedObject instanceof SpecialFormExpression && ((SpecialFormExpression) nestedObject).getForm() == DEREFERENCE) {
nestedDerefernces.add(nestedObject);
nestedObject = ((SpecialFormExpression) nestedObject).getArguments().get(0);
}
// Here nestedObject is the inner-most expression (so the toplevel object)
// Just generate a loop
BytecodeBlock block = new BytecodeBlock().comment("DEREFERENCE").setDescription("DEREFERENCE");
Variable rowBlock = generator.getScope().createTempVariable(Block.class);
Variable wasNull = generator.wasNull();
// Labels for control-flow
LabelNode end = new LabelNode("end");
LabelNode returnNull = new LabelNode("returnNull");
// clear the wasNull flag before evaluating the row value and evaluate the root (innermost) object
block.putVariable(wasNull, false).append(generator.generate(nestedObject, Optional.empty())).putVariable(rowBlock).comment("If the object is null return null").append(wasNull).ifTrueGoto(returnNull);
for (RowExpression rowExpression : nestedDerefernces.build().reverse()) {
SpecialFormExpression nestedDerefernce = (SpecialFormExpression) rowExpression;
int fieldIndex = ((Number) ((ConstantExpression) nestedDerefernce.getArguments().get(1)).getValue()).intValue();
block.append(rowBlock).push(fieldIndex).invokeInterface(Block.class, "isNull", boolean.class, int.class).comment("If the deref result is null return null").ifTrueGoto(returnNull).append(constantType(callSiteBinder, nestedDerefernce.getType()).getValue(rowBlock, constantInt(fieldIndex))).putVariable(rowBlock);
}
block.append(rowBlock).push(((Number) ((ConstantExpression) arguments.get(1)).getValue()).intValue()).invokeInterface(Block.class, "isNull", boolean.class, int.class).ifTrueGoto(returnNull);
BytecodeExpression value = constantType(callSiteBinder, returnType).getValue(rowBlock, constantInt(leafFieldIndex));
block.append(wasNull).ifTrueGoto(returnNull).append(value).gotoLabel(end);
// Here one of the enclosing objects is null
Class<?> javaType = returnType.getJavaType();
block.visitLabel(returnNull).pushJavaDefault(javaType).comment("if the field is null, push null to stack").putVariable(wasNull, true);
block.visitLabel(end);
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 AndCodeGenerator 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.AND) {
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("AND").setDescription("AND");
LabelNode falseLabel = new LabelNode("false");
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 (false) goto ret_false; }").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().ifFalseGoto(falseLabel);
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 false. So set wasNull to true").putVariable(wasNull, true).push(false);
ifHasNulls.ifFalse().push(true);
block.append(ifHasNulls).gotoLabel(endLabel);
block.visitLabel(falseLabel).comment("at least one of the args is false, clear wasNull and return false").push(false).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 TestLogicalRowExpressions method testDuplicateIsNullExpressions.
@Test
public void testDuplicateIsNullExpressions() {
SpecialFormExpression isNullExpression = new SpecialFormExpression(IS_NULL, BOOLEAN, a);
List<RowExpression> arguments = Arrays.asList(new SpecialFormExpression[] { isNullExpression, isNullExpression });
SpecialFormExpression duplicateIsNullExpression = new SpecialFormExpression(OR, BOOLEAN, arguments);
logicalRowExpressions.minimalNormalForm(duplicateIsNullExpression);
}
use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.
the class TestCursorProcessorCompiler method testRewriteRowExpressionWithCSE.
@Test
public void testRewriteRowExpressionWithCSE() {
CursorProcessorCompiler cseCursorCompiler = new CursorProcessorCompiler(METADATA, true, emptyMap());
ClassDefinition cursorProcessorClassDefinition = new ClassDefinition(a(PUBLIC, FINAL), makeClassName(CursorProcessor.class.getSimpleName()), type(Object.class), type(CursorProcessor.class));
RowExpression filter = new SpecialFormExpression(AND, BIGINT, ADD_X_Y_GREATER_THAN_2);
List<RowExpression> projections = ImmutableList.of(ADD_X_Y_Z);
List<RowExpression> rowExpressions = ImmutableList.<RowExpression>builder().addAll(projections).add(filter).build();
Map<Integer, Map<RowExpression, VariableReferenceExpression>> commonSubExpressionsByLevel = collectCSEByLevel(rowExpressions);
Map<VariableReferenceExpression, CommonSubExpressionRewriter.CommonSubExpressionFields> cseFields = declareCommonSubExpressionFields(cursorProcessorClassDefinition, commonSubExpressionsByLevel);
Map<RowExpression, VariableReferenceExpression> commonSubExpressions = commonSubExpressionsByLevel.values().stream().flatMap(m -> m.entrySet().stream()).collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
// X+Y as CSE
assertEquals(1, cseFields.size());
VariableReferenceExpression cseVariable = cseFields.keySet().iterator().next();
RowExpression rewrittenFilter = cseCursorCompiler.rewriteRowExpressionsWithCSE(ImmutableList.of(filter), commonSubExpressions).get(0);
List<RowExpression> rewrittenProjections = cseCursorCompiler.rewriteRowExpressionsWithCSE(projections, commonSubExpressions);
// X+Y+Z contains CSE X+Y
assertTrue(((CallExpression) rewrittenProjections.get(0)).getArguments().contains(cseVariable));
// X+Y > 2 consists CSE X+Y
assertTrue(((CallExpression) ((SpecialFormExpression) rewrittenFilter).getArguments().get(0)).getArguments().contains(cseVariable));
}
use of com.facebook.presto.spi.relation.SpecialFormExpression in project presto by prestodb.
the class ParquetDereferencePushDown method createNestedColumn.
private Subfield createNestedColumn(Map<String, ColumnHandle> baseColumnHandles, RowExpression rowExpression, ExpressionOptimizer expressionOptimizer, ConnectorSession session) {
if (!(rowExpression instanceof SpecialFormExpression) || ((SpecialFormExpression) rowExpression).getForm() != DEREFERENCE) {
throw new IllegalArgumentException("expecting SpecialFormExpression(DEREFERENCE), but got: " + rowExpression);
}
RowExpression currentRowExpression = rowExpression;
List<Subfield.PathElement> elements = new ArrayList<>();
while (true) {
if (currentRowExpression instanceof VariableReferenceExpression) {
Collections.reverse(elements);
String name = ((VariableReferenceExpression) currentRowExpression).getName();
ColumnHandle handle = baseColumnHandles.get(name);
checkArgument(handle != null, "Missing Column handle: " + name);
String originalColumnName = getColumnName(handle);
return new Subfield(originalColumnName, unmodifiableList(elements));
}
if (currentRowExpression instanceof SpecialFormExpression && ((SpecialFormExpression) currentRowExpression).getForm() == DEREFERENCE) {
SpecialFormExpression dereferenceExpression = (SpecialFormExpression) currentRowExpression;
RowExpression base = dereferenceExpression.getArguments().get(0);
RowType baseType = (RowType) base.getType();
RowExpression indexExpression = expressionOptimizer.optimize(dereferenceExpression.getArguments().get(1), ExpressionOptimizer.Level.OPTIMIZED, session);
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()));
currentRowExpression = base;
continue;
}
}
}
}
break;
}
throw new IllegalArgumentException("expecting SpecialFormExpression(DEREFERENCE) with constants for indices, but got: " + currentRowExpression);
}
Aggregations