use of com.facebook.presto.common.function.SqlFunctionProperties in project presto by prestodb.
the class MapToMapCast method buildProcessor.
/**
* The signature of the returned MethodHandle is (Block fromMap, int position, SqlFunctionProperties properties, BlockBuilder mapBlockBuilder)void.
* The processor will get the value from fromMap, cast it and write to toBlock.
*/
private MethodHandle buildProcessor(FunctionAndTypeManager functionAndTypeManager, Type fromType, Type toType, boolean isKey) {
MethodHandle getter = nativeValueGetter(fromType);
// Adapt cast that takes ([SqlFunctionProperties,] ?) to one that takes (?, SqlFunctionProperties), where ? is the return type of getter.
JavaScalarFunctionImplementation castImplementation = functionAndTypeManager.getJavaScalarFunctionImplementation(functionAndTypeManager.lookupCast(CastType.CAST, fromType.getTypeSignature(), toType.getTypeSignature()));
MethodHandle cast = castImplementation.getMethodHandle();
if (cast.type().parameterArray()[0] != SqlFunctionProperties.class) {
cast = MethodHandles.dropArguments(cast, 0, SqlFunctionProperties.class);
}
cast = permuteArguments(cast, methodType(cast.type().returnType(), cast.type().parameterArray()[1], cast.type().parameterArray()[0]), 1, 0);
MethodHandle target = compose(cast, getter);
// If the key cast function is nullable, check the result is not null.
if (isKey && castImplementation.isNullable()) {
target = compose(nullChecker(target.type().returnType()), target);
}
MethodHandle writer = nativeValueWriter(toType);
writer = permuteArguments(writer, methodType(void.class, writer.type().parameterArray()[1], writer.type().parameterArray()[0]), 1, 0);
return compose(writer, target.asType(methodType(unwrap(target.type().returnType()), target.type().parameterArray())));
}
use of com.facebook.presto.common.function.SqlFunctionProperties in project presto by prestodb.
the class ArrayJoin method specializeArrayJoin.
private static BuiltInScalarFunctionImplementation specializeArrayJoin(Map<String, Type> types, FunctionAndTypeManager functionAndTypeManager, List<Boolean> nullableArguments, MethodHandle methodHandleStack, MethodHandle methodHandleProvidedBlock) {
Type type = types.get("T");
List<ArgumentProperty> argumentProperties = nullableArguments.stream().map(nullable -> nullable ? valueTypeArgumentProperty(USE_BOXED_TYPE) : valueTypeArgumentProperty(RETURN_NULL_ON_NULL)).collect(toImmutableList());
if (type instanceof UnknownType) {
return new BuiltInScalarFunctionImplementation(false, argumentProperties, methodHandleStack.bindTo(null), Optional.empty());
} else {
try {
MethodHandle cast = functionAndTypeManager.getJavaScalarFunctionImplementation(functionAndTypeManager.lookupCast(CAST, type.getTypeSignature(), VARCHAR_TYPE_SIGNATURE)).getMethodHandle();
MethodHandle getter;
Class<?> elementType = type.getJavaType();
if (elementType == boolean.class) {
getter = GET_BOOLEAN;
} else if (elementType == double.class) {
getter = GET_DOUBLE;
} else if (elementType == long.class) {
getter = GET_LONG;
} else if (elementType == Slice.class) {
getter = GET_SLICE;
} else {
throw new UnsupportedOperationException("Unsupported type: " + elementType.getName());
}
// if the cast doesn't take a SqlFunctionProperties, create an adapter that drops the provided session
if (cast.type().parameterArray()[0] != SqlFunctionProperties.class) {
cast = MethodHandles.dropArguments(cast, 0, SqlFunctionProperties.class);
}
// Adapt a target cast that takes (SqlFunctionProperties, ?) to one that takes (Block, int, SqlFunctionProperties), which will be invoked by the implementation
// The first two arguments (Block, int) are filtered through the element type's getXXX method to produce the underlying value that needs to be passed to
// the cast.
cast = MethodHandles.permuteArguments(cast, MethodType.methodType(Slice.class, cast.type().parameterArray()[1], cast.type().parameterArray()[0]), 1, 0);
cast = MethodHandles.dropArguments(cast, 1, int.class);
cast = MethodHandles.dropArguments(cast, 1, Block.class);
cast = MethodHandles.foldArguments(cast, getter.bindTo(type));
MethodHandle targetStack = MethodHandles.insertArguments(methodHandleStack, 0, cast);
MethodHandle targetProvidedBlock = MethodHandles.insertArguments(methodHandleProvidedBlock, 0, cast);
return new BuiltInScalarFunctionImplementation(ImmutableList.of(new ScalarFunctionImplementationChoice(false, argumentProperties, STACK, targetStack, Optional.empty()), new ScalarFunctionImplementationChoice(false, argumentProperties, PROVIDED_BLOCKBUILDER, targetProvidedBlock, Optional.empty())));
} catch (PrestoException e) {
throw new PrestoException(INVALID_FUNCTION_ARGUMENT, format("Input type %s not supported", type), e);
}
}
}
use of com.facebook.presto.common.function.SqlFunctionProperties in project presto by prestodb.
the class PageFunctionCompiler method compileProjectionInternal.
private Supplier<PageProjection> compileProjectionInternal(SqlFunctionProperties sqlFunctionProperties, Map<SqlFunctionId, SqlInvokedFunction> sessionFunctions, List<RowExpression> projections, boolean isOptimizeCommonSubExpression, Optional<String> classNameSuffix) {
requireNonNull(projections, "projections is null");
checkArgument(!projections.isEmpty() && projections.stream().allMatch(projection -> projection instanceof CallExpression || projection instanceof SpecialFormExpression));
PageFieldsToInputParametersRewriter.Result result = rewritePageFieldsToInputParameters(projections);
List<RowExpression> rewrittenExpression = result.getRewrittenExpressions();
CallSiteBinder callSiteBinder = new CallSiteBinder();
// generate Work
ClassDefinition pageProjectionWorkDefinition = definePageProjectWorkClass(sqlFunctionProperties, sessionFunctions, rewrittenExpression, callSiteBinder, isOptimizeCommonSubExpression, classNameSuffix);
Class<? extends Work> pageProjectionWorkClass;
try {
pageProjectionWorkClass = defineClass(pageProjectionWorkDefinition, Work.class, callSiteBinder.getBindings(), getClass().getClassLoader());
} catch (PrestoException prestoException) {
throw prestoException;
} catch (Exception e) {
throw new PrestoException(COMPILER_ERROR, e);
}
return () -> new GeneratedPageProjection(rewrittenExpression, rewrittenExpression.stream().allMatch(determinismEvaluator::isDeterministic), result.getInputChannels(), constructorMethodHandle(pageProjectionWorkClass, List.class, SqlFunctionProperties.class, Page.class, SelectedPositions.class));
}
use of com.facebook.presto.common.function.SqlFunctionProperties in project presto by prestodb.
the class PageFunctionCompiler method defineFilterClass.
private ClassDefinition defineFilterClass(SqlFunctionProperties sqlFunctionProperties, Map<SqlFunctionId, SqlInvokedFunction> sessionFunctions, RowExpression filter, InputChannels inputChannels, CallSiteBinder callSiteBinder, boolean isOptimizeCommonSubExpression, Optional<String> classNameSuffix) {
ClassDefinition classDefinition = new ClassDefinition(a(PUBLIC, FINAL), generateFilterClassName(classNameSuffix), type(Object.class), type(PageFilter.class));
CachedInstanceBinder cachedInstanceBinder = new CachedInstanceBinder(classDefinition, callSiteBinder);
Map<LambdaDefinitionExpression, CompiledLambda> compiledLambdaMap = generateMethodsForLambda(classDefinition, callSiteBinder, cachedInstanceBinder, filter, metadata, sqlFunctionProperties, sessionFunctions);
// cse
Map<VariableReferenceExpression, CommonSubExpressionFields> cseFields = ImmutableMap.of();
RowExpressionCompiler compiler = new RowExpressionCompiler(classDefinition, callSiteBinder, cachedInstanceBinder, new FieldAndVariableReferenceCompiler(callSiteBinder, cseFields), metadata, sqlFunctionProperties, sessionFunctions, compiledLambdaMap);
if (isOptimizeCommonSubExpression) {
Map<Integer, Map<RowExpression, VariableReferenceExpression>> commonSubExpressionsByLevel = collectCSEByLevel(filter);
if (!commonSubExpressionsByLevel.isEmpty()) {
cseFields = declareCommonSubExpressionFields(classDefinition, commonSubExpressionsByLevel);
compiler = new RowExpressionCompiler(classDefinition, callSiteBinder, cachedInstanceBinder, new FieldAndVariableReferenceCompiler(callSiteBinder, cseFields), metadata, sqlFunctionProperties, sessionFunctions, compiledLambdaMap);
generateCommonSubExpressionMethods(classDefinition, compiler, commonSubExpressionsByLevel, cseFields);
Map<RowExpression, VariableReferenceExpression> commonSubExpressions = commonSubExpressionsByLevel.values().stream().flatMap(m -> m.entrySet().stream()).collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
filter = rewriteExpressionWithCSE(filter, commonSubExpressions);
if (log.isDebugEnabled()) {
log.debug("Extracted %d common sub-expressions", commonSubExpressions.size());
commonSubExpressions.entrySet().forEach(entry -> log.debug("\t%s = %s", entry.getValue(), entry.getKey()));
log.debug("Rewrote filter: %s", filter);
}
}
}
generateFilterMethod(classDefinition, compiler, filter, cseFields);
FieldDefinition selectedPositions = classDefinition.declareField(a(PRIVATE), "selectedPositions", boolean[].class);
generatePageFilterMethod(classDefinition, selectedPositions);
// isDeterministic
classDefinition.declareMethod(a(PUBLIC), "isDeterministic", type(boolean.class)).getBody().append(constantBoolean(determinismEvaluator.isDeterministic(filter))).retBoolean();
// getInputChannels
classDefinition.declareMethod(a(PUBLIC), "getInputChannels", type(InputChannels.class)).getBody().append(invoke(callSiteBinder.bind(inputChannels, InputChannels.class), "getInputChannels")).retObject();
// toString
String toStringResult = toStringHelper(classDefinition.getType().getJavaClassName()).add("filter", filter).toString();
classDefinition.declareMethod(a(PUBLIC), "toString", type(String.class)).getBody().append(invoke(callSiteBinder.bind(toStringResult, String.class), "toString")).retObject();
// constructor
MethodDefinition constructorDefinition = classDefinition.declareConstructor(a(PUBLIC));
BytecodeBlock body = constructorDefinition.getBody();
Variable thisVariable = constructorDefinition.getThis();
body.comment("super();").append(thisVariable).invokeConstructor(Object.class).append(thisVariable.setField(selectedPositions, newArray(type(boolean[].class), 0)));
initializeCommonSubExpressionFields(cseFields.values(), thisVariable, body);
cachedInstanceBinder.generateInitializations(thisVariable, body);
body.ret();
return classDefinition;
}
use of com.facebook.presto.common.function.SqlFunctionProperties in project presto by prestodb.
the class PageFunctionCompiler method compileProjections.
public List<Supplier<PageProjectionWithOutputs>> compileProjections(SqlFunctionProperties sqlFunctionProperties, Map<SqlFunctionId, SqlInvokedFunction> sessionFunctions, List<? extends RowExpression> projections, boolean isOptimizeCommonSubExpression, Optional<String> classNameSuffix) {
if (isOptimizeCommonSubExpression) {
ImmutableList.Builder<Supplier<PageProjectionWithOutputs>> pageProjections = ImmutableList.builder();
ImmutableMap.Builder<RowExpression, Integer> expressionsWithPositionBuilder = ImmutableMap.builder();
for (int i = 0; i < projections.size(); i++) {
RowExpression projection = projections.get(i);
if (projection instanceof ConstantExpression || projection instanceof InputReferenceExpression) {
pageProjections.add(toPageProjectionWithOutputs(compileProjection(sqlFunctionProperties, sessionFunctions, projection, classNameSuffix), new int[] { i }));
} else {
expressionsWithPositionBuilder.put(projection, i);
}
}
Map<RowExpression, Integer> expressionsWithPosition = expressionsWithPositionBuilder.build();
Map<List<RowExpression>, Boolean> projectionsPartitionedByCSE = getExpressionsPartitionedByCSE(expressionsWithPosition.keySet(), MAX_PROJECTION_GROUP_SIZE);
for (Map.Entry<List<RowExpression>, Boolean> entry : projectionsPartitionedByCSE.entrySet()) {
if (entry.getValue()) {
pageProjections.add(toPageProjectionWithOutputs(compileProjectionCached(sqlFunctionProperties, sessionFunctions, entry.getKey(), true, classNameSuffix), toIntArray(entry.getKey().stream().map(expressionsWithPosition::get).collect(toImmutableList()))));
} else {
verify(entry.getKey().size() == 1, "Expect non-cse expression list to only have one element");
RowExpression projection = entry.getKey().get(0);
pageProjections.add(toPageProjectionWithOutputs(compileProjection(sqlFunctionProperties, sessionFunctions, projection, classNameSuffix), new int[] { expressionsWithPosition.get(projection) }));
}
}
return pageProjections.build();
}
return IntStream.range(0, projections.size()).mapToObj(outputChannel -> toPageProjectionWithOutputs(compileProjection(sqlFunctionProperties, sessionFunctions, projections.get(outputChannel), classNameSuffix), new int[] { outputChannel })).collect(toImmutableList());
}
Aggregations