Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
*/
package com.facebook.presto.expressions.translator;

import com.facebook.presto.spi.CatalogSchemaName;
import com.facebook.presto.spi.function.FunctionMetadata;
import com.facebook.presto.spi.function.OperatorType;
import com.facebook.presto.spi.function.QualifiedFunctionName;
import com.facebook.presto.spi.function.ScalarFunction;
import com.facebook.presto.spi.function.ScalarOperator;
import com.facebook.presto.spi.function.SqlType;
import com.facebook.presto.spi.relation.FullyQualifiedName;
import com.facebook.presto.spi.type.TypeSignature;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
Expand Down Expand Up @@ -204,7 +205,7 @@ public Set<Method> getMethods()

private static class ScalarTranslationHeader
{
private final FullyQualifiedName name;
private final QualifiedFunctionName name;
private final Optional<OperatorType> operatorType;
private final boolean deterministic;
private final boolean calledOnNullInput;
Expand Down Expand Up @@ -237,7 +238,7 @@ public static List<ScalarTranslationHeader> fromAnnotatedElement(AnnotatedElemen
private ScalarTranslationHeader(String name, boolean deterministic, boolean calledOnNullInput)
{
// TODO This is a hack. Engine should provide an API for connectors to overwrite functions. Connector should not hard code the builtin function namespace.
this.name = requireNonNull(FullyQualifiedName.of("presto", "default", name));
this.name = requireNonNull(QualifiedFunctionName.of(new CatalogSchemaName("presto", "default"), name));
this.operatorType = Optional.empty();
this.deterministic = deterministic;
this.calledOnNullInput = calledOnNullInput;
Expand Down Expand Up @@ -268,7 +269,7 @@ private static String camelToSnake(String name)
return LOWER_CAMEL.to(LOWER_UNDERSCORE, name);
}

FullyQualifiedName getName()
QualifiedFunctionName getName()
{
return name;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.facebook.presto.execution;

import com.facebook.presto.metadata.Metadata;
import com.facebook.presto.security.AccessControl;
import com.facebook.presto.spi.PrestoException;
import com.facebook.presto.spi.function.QualifiedFunctionName;
import com.facebook.presto.spi.function.RoutineCharacteristics;
import com.facebook.presto.spi.function.SqlInvokedFunction;
import com.facebook.presto.spi.function.SqlParameter;
import com.facebook.presto.spi.type.TypeSignature;
import com.facebook.presto.sql.analyzer.Analyzer;
import com.facebook.presto.sql.parser.SqlParser;
import com.facebook.presto.sql.tree.CreateFunction;
import com.facebook.presto.sql.tree.Expression;
import com.facebook.presto.transaction.TransactionManager;
import com.google.common.util.concurrent.ListenableFuture;

import javax.inject.Inject;

import java.util.List;
import java.util.Optional;

import static com.facebook.presto.spi.StandardErrorCode.GENERIC_USER_ERROR;
import static com.facebook.presto.spi.type.TypeSignature.parseTypeSignature;
import static com.facebook.presto.sql.SqlFormatter.formatSql;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static java.lang.String.format;
import static java.util.Locale.ENGLISH;
import static java.util.Objects.requireNonNull;

public class CreateFunctionTask
implements DataDefinitionTask<CreateFunction>
{
private final SqlParser sqlParser;

@Inject
public CreateFunctionTask(SqlParser sqlParser)
{
this.sqlParser = requireNonNull(sqlParser, "sqlParser is null");
}

@Override
public String getName()
{
return "CREATE FUNCTION";
}

@Override
public String explain(CreateFunction statement, List<Expression> parameters)
{
return "CREATE FUNCTION " + statement.getFunctionName();
}

@Override
public ListenableFuture<?> execute(CreateFunction statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters)
{
Analyzer analyzer = new Analyzer(stateMachine.getSession(), metadata, sqlParser, accessControl, Optional.empty(), parameters, stateMachine.getWarningCollector());
analyzer.analyze(statement);
metadata.getFunctionManager().createFunction(createSqlInvokedFunction(statement), statement.isReplace());
return immediateFuture(null);
}

private SqlInvokedFunction createSqlInvokedFunction(CreateFunction statement)
{
if (statement.getFunctionName().getParts().size() != 3) {
throw new PrestoException(GENERIC_USER_ERROR, format("Invalid function name: %s, require exactly 3 parts", statement.getFunctionName()));
}

QualifiedFunctionName functionName = QualifiedFunctionName.of(statement.getFunctionName().toString());
List<SqlParameter> parameters = statement.getParameters().stream()
.map(parameter -> new SqlParameter(parameter.getName().toString().toLowerCase(ENGLISH), parseTypeSignature(parameter.getType())))
.collect(toImmutableList());
TypeSignature returnType = parseTypeSignature(statement.getReturnType());
String description = statement.getComment().orElse("");
RoutineCharacteristics routineCharacteristics = new RoutineCharacteristics(
RoutineCharacteristics.Language.valueOf(statement.getCharacteristics().getLanguage().name()),
RoutineCharacteristics.Determinism.valueOf(statement.getCharacteristics().getDeterminism().name()),
RoutineCharacteristics.NullCallClause.valueOf(statement.getCharacteristics().getNullCallClause().name()));
String body = formatSql(statement.getBody(), Optional.empty());
Comment thread
caithagoras marked this conversation as resolved.
Outdated

return new SqlInvokedFunction(
functionName,
parameters,
returnType,
description,
routineCharacteristics,
body,
Optional.empty());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
*/
package com.facebook.presto.metadata;

import com.facebook.presto.spi.CatalogSchemaName;
import com.facebook.presto.spi.function.FunctionHandle;
import com.facebook.presto.spi.function.Signature;
import com.facebook.presto.spi.relation.FullyQualifiedName;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

Expand All @@ -42,9 +42,9 @@ public Signature getSignature()
}

@Override
public FullyQualifiedName.Prefix getFunctionNamespace()
public CatalogSchemaName getFunctionNamespace()
{
return signature.getName().getPrefix();
return signature.getName().getFunctionNamespace();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@
import com.facebook.presto.operator.window.RowNumberFunction;
import com.facebook.presto.operator.window.SqlWindowFunction;
import com.facebook.presto.operator.window.WindowFunctionSupplier;
import com.facebook.presto.spi.CatalogSchemaName;
import com.facebook.presto.spi.PrestoException;
import com.facebook.presto.spi.block.Block;
import com.facebook.presto.spi.block.BlockEncodingSerde;
Expand All @@ -158,10 +159,11 @@
import com.facebook.presto.spi.function.FunctionNamespaceManager;
import com.facebook.presto.spi.function.FunctionNamespaceTransactionHandle;
import com.facebook.presto.spi.function.OperatorType;
import com.facebook.presto.spi.function.QualifiedFunctionName;
import com.facebook.presto.spi.function.ScalarFunctionImplementation;
import com.facebook.presto.spi.function.Signature;
import com.facebook.presto.spi.function.SqlFunction;
import com.facebook.presto.spi.relation.FullyQualifiedName;
import com.facebook.presto.spi.function.SqlInvokedFunction;
import com.facebook.presto.spi.type.Type;
import com.facebook.presto.spi.type.TypeManager;
import com.facebook.presto.spi.type.TypeSignature;
Expand Down Expand Up @@ -292,6 +294,7 @@
import static com.facebook.presto.operator.scalar.ZipWithFunction.ZIP_WITH_FUNCTION;
import static com.facebook.presto.operator.window.AggregateWindowFunction.supplier;
import static com.facebook.presto.spi.StandardErrorCode.FUNCTION_IMPLEMENTATION_MISSING;
import static com.facebook.presto.spi.StandardErrorCode.GENERIC_USER_ERROR;
import static com.facebook.presto.spi.function.FunctionImplementationType.BUILTIN;
import static com.facebook.presto.spi.function.FunctionKind.AGGREGATE;
import static com.facebook.presto.spi.function.FunctionKind.SCALAR;
Expand Down Expand Up @@ -353,7 +356,7 @@
public class BuiltInFunctionNamespaceManager
implements FunctionNamespaceManager<BuiltInFunction>
{
public static final FullyQualifiedName.Prefix DEFAULT_NAMESPACE = FullyQualifiedName.of("presto.default.foo").getPrefix();
public static final CatalogSchemaName DEFAULT_NAMESPACE = new CatalogSchemaName("presto", "default");
public static final String NAME = "_builtin";

private final TypeManager typeManager;
Expand Down Expand Up @@ -681,9 +684,9 @@ public synchronized void registerBuiltInFunctions(List<? extends BuiltInFunction
}

@Override
public void createFunction(BuiltInFunction function, boolean replace)
public void createFunction(SqlInvokedFunction function, boolean replace)
{
throw new UnsupportedOperationException("createFunction cannot be called on BuiltInFunctionNamespaceManager");
throw new PrestoException(GENERIC_USER_ERROR, format("Cannot create function in built-in function namespace: %s", function.getSignature().getName()));
}

public String getName()
Expand All @@ -703,7 +706,7 @@ public void commit(FunctionNamespaceTransactionHandle transactionHandle)
}

@Override
public void rollback(FunctionNamespaceTransactionHandle transactionHandle)
public void abort(FunctionNamespaceTransactionHandle transactionHandle)
{
}

Expand All @@ -714,7 +717,7 @@ public Collection<BuiltInFunction> listFunctions()
}

@Override
public Collection<BuiltInFunction> getFunctions(Optional<? extends FunctionNamespaceTransactionHandle> transactionHandle, FullyQualifiedName functionName)
public Collection<BuiltInFunction> getFunctions(Optional<? extends FunctionNamespaceTransactionHandle> transactionHandle, QualifiedFunctionName functionName)
{
return functions.get(functionName);
}
Expand Down Expand Up @@ -902,7 +905,7 @@ private static class EmptyTransactionHandle

private static class FunctionMap
{
private final Multimap<FullyQualifiedName, BuiltInFunction> functions;
private final Multimap<QualifiedFunctionName, BuiltInFunction> functions;

public FunctionMap()
{
Expand All @@ -911,13 +914,13 @@ public FunctionMap()

public FunctionMap(FunctionMap map, Iterable<? extends BuiltInFunction> functions)
{
this.functions = ImmutableListMultimap.<FullyQualifiedName, BuiltInFunction>builder()
this.functions = ImmutableListMultimap.<QualifiedFunctionName, BuiltInFunction>builder()
.putAll(map.functions)
.putAll(Multimaps.index(functions, function -> function.getSignature().getName()))
.build();

// Make sure all functions with the same name are aggregations or none of them are
for (Map.Entry<FullyQualifiedName, Collection<BuiltInFunction>> entry : this.functions.asMap().entrySet()) {
for (Map.Entry<QualifiedFunctionName, Collection<BuiltInFunction>> entry : this.functions.asMap().entrySet()) {
Collection<BuiltInFunction> values = entry.getValue();
long aggregations = values.stream()
.map(function -> function.getSignature().getKind())
Expand All @@ -932,7 +935,7 @@ public List<BuiltInFunction> list()
return ImmutableList.copyOf(functions.values());
}

public Collection<BuiltInFunction> get(FullyQualifiedName name)
public Collection<BuiltInFunction> get(QualifiedFunctionName name)
{
return functions.get(name);
}
Expand All @@ -945,7 +948,7 @@ private static class MagicLiteralFunction

MagicLiteralFunction(BlockEncodingSerde blockEncodingSerde)
{
super(new Signature(FullyQualifiedName.of(DEFAULT_NAMESPACE, MAGIC_LITERAL_FUNCTION_PREFIX), SCALAR, TypeSignature.parseTypeSignature("R"), TypeSignature.parseTypeSignature("T")));
super(new Signature(QualifiedFunctionName.of(DEFAULT_NAMESPACE, MAGIC_LITERAL_FUNCTION_PREFIX), SCALAR, TypeSignature.parseTypeSignature("R"), TypeSignature.parseTypeSignature("T")));
this.blockEncodingSerde = requireNonNull(blockEncodingSerde, "blockEncodingSerde is null");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
package com.facebook.presto.metadata;

import com.facebook.presto.spi.function.OperatorType;
import com.facebook.presto.spi.relation.FullyQualifiedName;
import com.facebook.presto.spi.function.QualifiedFunctionName;

import static com.facebook.presto.metadata.BuiltInFunctionNamespaceManager.DEFAULT_NAMESPACE;
import static com.facebook.presto.operator.scalar.JsonStringToArrayCast.JSON_STRING_TO_ARRAY_NAME;
Expand All @@ -27,21 +27,21 @@ public enum CastType
{
CAST(OperatorType.CAST.getFunctionName(), true),
SATURATED_FLOOR_CAST(OperatorType.SATURATED_FLOOR_CAST.getFunctionName(), true),
TRY_CAST(FullyQualifiedName.of(DEFAULT_NAMESPACE, TRY_CAST_NAME), false),
JSON_TO_ARRAY_CAST(FullyQualifiedName.of(DEFAULT_NAMESPACE, JSON_STRING_TO_ARRAY_NAME), false),
JSON_TO_MAP_CAST(FullyQualifiedName.of(DEFAULT_NAMESPACE, JSON_STRING_TO_MAP_NAME), false),
JSON_TO_ROW_CAST(FullyQualifiedName.of(DEFAULT_NAMESPACE, JSON_STRING_TO_ROW_NAME), false);
TRY_CAST(QualifiedFunctionName.of(DEFAULT_NAMESPACE, TRY_CAST_NAME), false),
JSON_TO_ARRAY_CAST(QualifiedFunctionName.of(DEFAULT_NAMESPACE, JSON_STRING_TO_ARRAY_NAME), false),
JSON_TO_MAP_CAST(QualifiedFunctionName.of(DEFAULT_NAMESPACE, JSON_STRING_TO_MAP_NAME), false),
JSON_TO_ROW_CAST(QualifiedFunctionName.of(DEFAULT_NAMESPACE, JSON_STRING_TO_ROW_NAME), false);

private final FullyQualifiedName castName;
private final QualifiedFunctionName castName;
private final boolean isOperatorType;

CastType(FullyQualifiedName castName, boolean isOperatorType)
CastType(QualifiedFunctionName castName, boolean isOperatorType)
{
this.castName = castName;
this.isOperatorType = isOperatorType;
}

public FullyQualifiedName getCastName()
public QualifiedFunctionName getCastName()
{
return castName;
}
Expand Down
Loading