use of com.facebook.presto.sql.relational.ConstantExpression in project presto by prestodb.
the class TestInCodeGenerator method testVarchar.
@Test
public void testVarchar() {
List<RowExpression> values = new ArrayList<>();
values.add(new ConstantExpression(Slices.utf8Slice("1"), DOUBLE));
values.add(new ConstantExpression(Slices.utf8Slice("2"), DOUBLE));
values.add(new ConstantExpression(Slices.utf8Slice("3"), DOUBLE));
assertEquals(checkSwitchGenerationCase(VARCHAR, values), HASH_SWITCH);
values.add(new ConstantExpression(null, VARCHAR));
assertEquals(checkSwitchGenerationCase(VARCHAR, values), HASH_SWITCH);
for (int i = 5; i <= 32; ++i) {
values.add(new ConstantExpression(Slices.utf8Slice(String.valueOf(i)), VARCHAR));
}
assertEquals(checkSwitchGenerationCase(VARCHAR, values), HASH_SWITCH);
values.add(new ConstantExpression(Slices.utf8Slice("33"), VARCHAR));
assertEquals(checkSwitchGenerationCase(VARCHAR, values), SET_CONTAINS);
}
use of com.facebook.presto.sql.relational.ConstantExpression in project presto by prestodb.
the class TestInCodeGenerator method testDouble.
@Test
public void testDouble() {
List<RowExpression> values = new ArrayList<>();
values.add(new ConstantExpression(1.5, DOUBLE));
values.add(new ConstantExpression(2.5, DOUBLE));
values.add(new ConstantExpression(3.5, DOUBLE));
assertEquals(checkSwitchGenerationCase(DOUBLE, values), HASH_SWITCH);
values.add(new ConstantExpression(null, DOUBLE));
assertEquals(checkSwitchGenerationCase(DOUBLE, values), HASH_SWITCH);
for (int i = 5; i <= 32; ++i) {
values.add(new ConstantExpression(i + 0.5, DOUBLE));
}
assertEquals(checkSwitchGenerationCase(DOUBLE, values), HASH_SWITCH);
values.add(new ConstantExpression(33.5, DOUBLE));
assertEquals(checkSwitchGenerationCase(DOUBLE, values), SET_CONTAINS);
}
use of com.facebook.presto.sql.relational.ConstantExpression in project presto by prestodb.
the class InCodeGenerator method generateExpression.
@Override
public BytecodeNode generateExpression(Signature signature, BytecodeGeneratorContext generatorContext, Type returnType, List<RowExpression> arguments) {
BytecodeNode value = generatorContext.generate(arguments.get(0));
List<RowExpression> values = arguments.subList(1, arguments.size());
ImmutableList.Builder<BytecodeNode> valuesBytecode = ImmutableList.builder();
for (int i = 1; i < arguments.size(); i++) {
BytecodeNode testNode = generatorContext.generate(arguments.get(i));
valuesBytecode.add(testNode);
}
Type type = arguments.get(0).getType();
Class<?> javaType = type.getJavaType();
SwitchGenerationCase switchGenerationCase = checkSwitchGenerationCase(type, values);
Signature hashCodeSignature = internalOperator(HASH_CODE, BIGINT, ImmutableList.of(type));
MethodHandle hashCodeFunction = generatorContext.getRegistry().getScalarFunctionImplementation(hashCodeSignature).getMethodHandle();
ImmutableListMultimap.Builder<Integer, BytecodeNode> hashBucketsBuilder = ImmutableListMultimap.builder();
ImmutableList.Builder<BytecodeNode> defaultBucket = ImmutableList.builder();
ImmutableSet.Builder<Object> constantValuesBuilder = ImmutableSet.builder();
for (RowExpression testValue : values) {
BytecodeNode testBytecode = generatorContext.generate(testValue);
if (testValue instanceof ConstantExpression && ((ConstantExpression) testValue).getValue() != null) {
ConstantExpression constant = (ConstantExpression) testValue;
Object object = constant.getValue();
switch(switchGenerationCase) {
case DIRECT_SWITCH:
case SET_CONTAINS:
constantValuesBuilder.add(object);
break;
case HASH_SWITCH:
try {
int hashCode = toIntExact(Long.hashCode((Long) hashCodeFunction.invoke(object)));
hashBucketsBuilder.put(hashCode, testBytecode);
} catch (Throwable throwable) {
throw new IllegalArgumentException("Error processing IN statement: error calculating hash code for " + object, throwable);
}
break;
default:
throw new IllegalArgumentException("Not supported switch generation case: " + switchGenerationCase);
}
} else {
defaultBucket.add(testBytecode);
}
}
ImmutableListMultimap<Integer, BytecodeNode> hashBuckets = hashBucketsBuilder.build();
ImmutableSet<Object> constantValues = constantValuesBuilder.build();
LabelNode end = new LabelNode("end");
LabelNode match = new LabelNode("match");
LabelNode noMatch = new LabelNode("noMatch");
LabelNode defaultLabel = new LabelNode("default");
Scope scope = generatorContext.getScope();
BytecodeNode switchBlock;
BytecodeBlock switchCaseBlocks = new BytecodeBlock();
LookupSwitch.LookupSwitchBuilder switchBuilder = lookupSwitchBuilder();
switch(switchGenerationCase) {
case DIRECT_SWITCH:
// For these types, it's safe to not use presto HASH_CODE and EQUAL operator.
for (Object constantValue : constantValues) {
switchBuilder.addCase(toIntExact((Long) constantValue), match);
}
switchBuilder.defaultCase(defaultLabel);
switchBlock = new BytecodeBlock().comment("lookupSwitch(<stackValue>))").dup(javaType).append(new IfStatement().condition(new BytecodeBlock().dup(javaType).invokeStatic(InCodeGenerator.class, "isInteger", boolean.class, long.class)).ifFalse(new BytecodeBlock().pop(javaType).gotoLabel(defaultLabel))).longToInt().append(switchBuilder.build());
break;
case HASH_SWITCH:
for (Map.Entry<Integer, Collection<BytecodeNode>> bucket : hashBuckets.asMap().entrySet()) {
LabelNode label = new LabelNode("inHash" + bucket.getKey());
switchBuilder.addCase(bucket.getKey(), label);
Collection<BytecodeNode> testValues = bucket.getValue();
BytecodeBlock caseBlock = buildInCase(generatorContext, scope, type, label, match, defaultLabel, testValues, false);
switchCaseBlocks.append(caseBlock.setDescription("case " + bucket.getKey()));
}
switchBuilder.defaultCase(defaultLabel);
Binding hashCodeBinding = generatorContext.getCallSiteBinder().bind(hashCodeFunction);
switchBlock = new BytecodeBlock().comment("lookupSwitch(hashCode(<stackValue>))").dup(javaType).append(invoke(hashCodeBinding, hashCodeSignature)).invokeStatic(Long.class, "hashCode", int.class, long.class).append(switchBuilder.build()).append(switchCaseBlocks);
break;
case SET_CONTAINS:
Set<?> constantValuesSet = toFastutilHashSet(constantValues, type, registry);
Binding constant = generatorContext.getCallSiteBinder().bind(constantValuesSet, constantValuesSet.getClass());
switchBlock = new BytecodeBlock().comment("inListSet.contains(<stackValue>)").append(new IfStatement().condition(new BytecodeBlock().comment("value").dup(javaType).comment("set").append(loadConstant(constant)).invokeStatic(FastutilSetHelper.class, "in", boolean.class, javaType.isPrimitive() ? javaType : Object.class, constantValuesSet.getClass())).ifTrue(jump(match)));
break;
default:
throw new IllegalArgumentException("Not supported switch generation case: " + switchGenerationCase);
}
BytecodeBlock defaultCaseBlock = buildInCase(generatorContext, scope, type, defaultLabel, match, noMatch, defaultBucket.build(), true).setDescription("default");
BytecodeBlock block = new BytecodeBlock().comment("IN").append(value).append(ifWasNullPopAndGoto(scope, end, boolean.class, javaType)).append(switchBlock).append(defaultCaseBlock);
BytecodeBlock matchBlock = new BytecodeBlock().setDescription("match").visitLabel(match).pop(javaType).append(generatorContext.wasNull().set(constantFalse())).push(true).gotoLabel(end);
block.append(matchBlock);
BytecodeBlock noMatchBlock = new BytecodeBlock().setDescription("noMatch").visitLabel(noMatch).pop(javaType).push(false).gotoLabel(end);
block.append(noMatchBlock);
block.visitLabel(end);
return block;
}
use of com.facebook.presto.sql.relational.ConstantExpression in project presto by prestodb.
the class PageProcessorCompiler method generateProjectColumnarMethod.
private static MethodDefinition generateProjectColumnarMethod(ClassDefinition classDefinition, CallSiteBinder callSiteBinder, String methodName, RowExpression projection, MethodDefinition projectionMethod) {
Parameter session = arg("session", ConnectorSession.class);
Parameter page = arg("page", Page.class);
Parameter selectedPositions = arg("selectedPositions", int[].class);
Parameter pageBuilder = arg("pageBuilder", PageBuilder.class);
Parameter projectionIndex = arg("projectionIndex", int.class);
List<Parameter> params = ImmutableList.<Parameter>builder().add(session).add(page).add(selectedPositions).add(pageBuilder).add(projectionIndex).build();
MethodDefinition method = classDefinition.declareMethod(a(PRIVATE), methodName, type(Block.class), params);
BytecodeBlock body = method.getBody();
Scope scope = method.getScope();
Variable thisVariable = method.getThis();
ImmutableList.Builder<Variable> builder = ImmutableList.builder();
for (int channel : getInputChannels(projection)) {
Variable blockVariable = scope.declareVariable("block_" + channel, body, page.invoke("getBlock", Block.class, constantInt(channel)));
builder.add(blockVariable);
}
List<Variable> inputs = builder.build();
Variable positionCount = scope.declareVariable("positionCount", body, page.invoke("getPositionCount", int.class));
Variable position = scope.declareVariable("position", body, constantInt(0));
Variable cardinality = scope.declareVariable("cardinality", body, selectedPositions.length());
Variable outputBlock = scope.declareVariable(Block.class, "outputBlock");
Variable blockBuilder = scope.declareVariable("blockBuilder", body, pageBuilder.invoke("getBlockBuilder", BlockBuilder.class, projectionIndex));
Variable type = scope.declareVariable("type", body, pageBuilder.invoke("getType", Type.class, projectionIndex));
BytecodeBlock projectBlock = new BytecodeBlock().append(new ForLoop().initialize(position.set(constantInt(0))).condition(lessThan(position, cardinality)).update(position.increment()).body(invokeProject(thisVariable, session, inputs, selectedPositions.getElement(position), pageBuilder, projectionIndex, projectionMethod))).append(outputBlock.set(blockBuilder.invoke("build", Block.class)));
if (isIdentityExpression(projection)) {
// if nothing is filtered out, copy the entire block, else project it
body.append(new IfStatement().condition(equal(cardinality, positionCount)).ifTrue(new BytecodeBlock().append(inputs.get(0).invoke("assureLoaded", void.class)).append(outputBlock.set(inputs.get(0)))).ifFalse(projectBlock));
} else if (isConstantExpression(projection)) {
// if projection is a constant, create RLE block of constant expression with cardinality positions
ConstantExpression constantExpression = (ConstantExpression) projection;
verify(getInputChannels(projection).isEmpty());
BytecodeExpression value = loadConstant(callSiteBinder, constantExpression.getValue(), Object.class);
body.append(outputBlock.set(invokeStatic(RunLengthEncodedBlock.class, "create", Block.class, type, value, cardinality)));
} else {
body.append(projectBlock);
}
body.append(outputBlock.ret());
return method;
}
use of com.facebook.presto.sql.relational.ConstantExpression in project presto by prestodb.
the class TestExpressionOptimizer method testPossibleExponentialOptimizationTime.
@Test(timeOut = 10_000)
public void testPossibleExponentialOptimizationTime() {
TypeRegistry typeManager = new TypeRegistry();
ExpressionOptimizer optimizer = new ExpressionOptimizer(new FunctionRegistry(typeManager, new BlockEncodingManager(typeManager), new FeaturesConfig()), typeManager, TEST_SESSION);
RowExpression expression = new ConstantExpression(1L, BIGINT);
for (int i = 0; i < 100; i++) {
Signature signature = internalOperator(OperatorType.ADD.name(), parseTypeSignature(StandardTypes.BIGINT), parseTypeSignature(StandardTypes.BIGINT), parseTypeSignature(StandardTypes.BIGINT));
expression = new CallExpression(signature, BIGINT, ImmutableList.of(expression, new ConstantExpression(1L, BIGINT)));
}
optimizer.optimize(expression);
}
Aggregations