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 @@ -15,8 +15,6 @@

import com.facebook.presto.metadata.Metadata;
import com.facebook.presto.security.AccessControl;
import com.facebook.presto.spi.CatalogSchemaName;
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;
Expand All @@ -34,12 +32,10 @@
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;

Expand Down Expand Up @@ -77,14 +73,7 @@ public ListenableFuture<?> execute(CreateFunction statement, TransactionManager

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

QualifiedFunctionName functionName = QualifiedFunctionName.of(
new CatalogSchemaName(parts.get(0), parts.get(1)),
parts.get(2));
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());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* 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.function.QualifiedFunctionName;
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.DropFunction;
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.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static java.util.Objects.requireNonNull;

public class DropFunctionTask
implements DataDefinitionTask<DropFunction>
{
private final SqlParser sqlParser;

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

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

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

@Override
public ListenableFuture<?> execute(DropFunction 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().dropFunction(
QualifiedFunctionName.of(statement.getFunctionName().toString()),
statement.getParameterTypes().map(types -> types.stream().map(TypeSignature::parseTypeSignature).collect(toImmutableList())),
statement.isExists());
return immediateFuture(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,12 @@ public void createFunction(SqlInvokedFunction function, boolean replace)
throw new PrestoException(GENERIC_USER_ERROR, format("Cannot create function in built-in function namespace: %s", function.getSignature().getName()));
}

@Override
public void dropFunction(QualifiedFunctionName functionName, Optional<List<TypeSignature>> parameterTypes, boolean exists)
{
throw new PrestoException(GENERIC_USER_ERROR, format("Cannot drop function in built-in function namespace: %s", functionName));
}

public String getName()
{
return NAME;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,17 @@ public void createFunction(SqlInvokedFunction function, boolean replace)
functionNamespaceManager.get().createFunction(function, replace);
}

public void dropFunction(QualifiedFunctionName functionName, Optional<List<TypeSignature>> parameterTypes, boolean exists)
{
Optional<FunctionNamespaceManager<?>> functionNamespaceManager = getServingFunctionNamespaceManager(functionName.getFunctionNamespace());
if (functionNamespaceManager.isPresent()) {
functionNamespaceManager.get().dropFunction(functionName, parameterTypes, exists);
}
else if (!exists) {
throw new PrestoException(FUNCTION_NOT_FOUND, format("Function not found: %s", functionName.getFunctionNamespace()));
}
}

/**
* Resolves a function using implicit type coercions. We enforce explicit naming for dynamic function namespaces.
* All unqualified function names will only be resolved against the built-in static function namespace. While it is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.facebook.presto.execution.DataDefinitionTask;
import com.facebook.presto.execution.DeallocateTask;
import com.facebook.presto.execution.DropColumnTask;
import com.facebook.presto.execution.DropFunctionTask;
import com.facebook.presto.execution.DropRoleTask;
import com.facebook.presto.execution.DropSchemaTask;
import com.facebook.presto.execution.DropTableTask;
Expand Down Expand Up @@ -106,6 +107,7 @@
import com.facebook.presto.sql.tree.CreateView;
import com.facebook.presto.sql.tree.Deallocate;
import com.facebook.presto.sql.tree.DropColumn;
import com.facebook.presto.sql.tree.DropFunction;
import com.facebook.presto.sql.tree.DropRole;
import com.facebook.presto.sql.tree.DropSchema;
import com.facebook.presto.sql.tree.DropTable;
Expand Down Expand Up @@ -307,6 +309,7 @@ protected void setup(Binder binder)
bindDataDefinitionTask(binder, executionBinder, CreateView.class, CreateViewTask.class);
bindDataDefinitionTask(binder, executionBinder, DropView.class, DropViewTask.class);
bindDataDefinitionTask(binder, executionBinder, CreateFunction.class, CreateFunctionTask.class);
bindDataDefinitionTask(binder, executionBinder, DropFunction.class, DropFunctionTask.class);
bindDataDefinitionTask(binder, executionBinder, Use.class, UseTask.class);
bindDataDefinitionTask(binder, executionBinder, SetSession.class, SetSessionTask.class);
bindDataDefinitionTask(binder, executionBinder, ResetSession.class, ResetSessionTask.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public enum SemanticErrorCode
INVALID_LITERAL,

FUNCTION_NOT_FOUND,
INVALID_FUNCTION_NAME,
DUPLICATE_PARAMETER_NAME,

ORDER_BY_MUST_BE_IN_SELECT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
import com.facebook.presto.sql.tree.Delete;
import com.facebook.presto.sql.tree.DereferenceExpression;
import com.facebook.presto.sql.tree.DropColumn;
import com.facebook.presto.sql.tree.DropFunction;
import com.facebook.presto.sql.tree.DropSchema;
import com.facebook.presto.sql.tree.DropTable;
import com.facebook.presto.sql.tree.DropView;
Expand Down Expand Up @@ -173,6 +174,7 @@
import static com.facebook.presto.sql.analyzer.SemanticErrorCode.DUPLICATE_PARAMETER_NAME;
import static com.facebook.presto.sql.analyzer.SemanticErrorCode.DUPLICATE_PROPERTY;
import static com.facebook.presto.sql.analyzer.SemanticErrorCode.DUPLICATE_RELATION;
import static com.facebook.presto.sql.analyzer.SemanticErrorCode.INVALID_FUNCTION_NAME;
import static com.facebook.presto.sql.analyzer.SemanticErrorCode.INVALID_ORDINAL;
import static com.facebook.presto.sql.analyzer.SemanticErrorCode.INVALID_PROCEDURE_ARGUMENTS;
import static com.facebook.presto.sql.analyzer.SemanticErrorCode.INVALID_WINDOW_FRAME;
Expand Down Expand Up @@ -552,6 +554,9 @@ protected Scope visitCreateFunction(CreateFunction node, Optional<Scope> scope)
{
analysis.setUpdateType("CREATE FUNCTION");

// Check function name
checkFunctionName(node, node.getFunctionName());

// Check parameter
List<String> duplicateParameters = node.getParameters().stream()
.map(SqlParameterDeclaration::getName)
Expand Down Expand Up @@ -586,6 +591,13 @@ protected Scope visitCreateFunction(CreateFunction node, Optional<Scope> scope)
return createAndAssignScope(node, scope);
}

@Override
protected Scope visitDropFunction(DropFunction node, Optional<Scope> scope)
{
checkFunctionName(node, node.getFunctionName());
return createAndAssignScope(node, scope);
}

@Override
protected Scope visitSetSession(SetSession node, Optional<Scope> scope)
{
Expand Down Expand Up @@ -1543,6 +1555,13 @@ else if (column.getExpression() instanceof Identifier) {
return assignments.build();
}

private void checkFunctionName(Statement node, QualifiedName functionName)
{
if (functionName.getParts().size() != 3) {
throw new SemanticException(INVALID_FUNCTION_NAME, node, format("Function name should be in the form of catalog.schema.function_name, found: %s", functionName));
}
}

private class OrderByExpressionRewriter
extends ExpressionRewriter<Void>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,20 @@
import com.facebook.presto.spi.function.SqlFunctionHandle;
import com.facebook.presto.spi.function.SqlFunctionId;
import com.facebook.presto.spi.function.SqlInvokedFunction;
import com.facebook.presto.spi.type.TypeSignature;
import com.facebook.presto.sqlfunction.AbstractSqlInvokedFunctionNamespaceManager;
import com.facebook.presto.sqlfunction.SqlInvokedFunctionNamespaceManagerConfig;

import javax.annotation.concurrent.ThreadSafe;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

import static com.facebook.presto.spi.StandardErrorCode.GENERIC_USER_ERROR;
import static com.facebook.presto.spi.StandardErrorCode.NOT_SUPPORTED;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.MoreCollectors.onlyElement;
import static java.lang.String.format;
Expand Down Expand Up @@ -69,6 +73,12 @@ public synchronized void createFunction(SqlInvokedFunction function, boolean rep
latestFunctions.put(functionId, function.withVersion(version));
}

@Override
public synchronized void dropFunction(QualifiedFunctionName functionName, Optional<List<TypeSignature>> parameterTypes, boolean exists)
{
throw new PrestoException(NOT_SUPPORTED, "Drop Function is not supported in InMemoryFunctionNamespaceManager");
}

@Override
public Collection<SqlInvokedFunction> listFunctions()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import com.facebook.presto.execution.CreateViewTask;
import com.facebook.presto.execution.DataDefinitionTask;
import com.facebook.presto.execution.DeallocateTask;
import com.facebook.presto.execution.DropFunctionTask;
import com.facebook.presto.execution.DropTableTask;
import com.facebook.presto.execution.DropViewTask;
import com.facebook.presto.execution.Lifespan;
Expand Down Expand Up @@ -156,6 +157,7 @@
import com.facebook.presto.sql.tree.CreateTable;
import com.facebook.presto.sql.tree.CreateView;
import com.facebook.presto.sql.tree.Deallocate;
import com.facebook.presto.sql.tree.DropFunction;
import com.facebook.presto.sql.tree.DropTable;
import com.facebook.presto.sql.tree.DropView;
import com.facebook.presto.sql.tree.Explain;
Expand Down Expand Up @@ -431,6 +433,7 @@ private LocalQueryRunner(Session defaultSession, FeaturesConfig featuresConfig,
.put(CreateTable.class, new CreateTableTask())
.put(CreateView.class, new CreateViewTask(jsonCodec(ViewDefinition.class), sqlParser, new FeaturesConfig()))
.put(CreateFunction.class, new CreateFunctionTask(sqlParser))
.put(DropFunction.class, new DropFunctionTask(sqlParser))
.put(DropTable.class, new DropTableTask())
.put(DropView.class, new DropViewTask())
.put(RenameColumn.class, new RenameColumnTask())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.facebook.presto.sql.tree.DescribeInput;
import com.facebook.presto.sql.tree.DescribeOutput;
import com.facebook.presto.sql.tree.DropColumn;
import com.facebook.presto.sql.tree.DropFunction;
import com.facebook.presto.sql.tree.DropRole;
import com.facebook.presto.sql.tree.DropSchema;
import com.facebook.presto.sql.tree.DropTable;
Expand Down Expand Up @@ -111,6 +112,7 @@ private StatementUtils() {}
builder.put(CreateView.class, QueryType.DATA_DEFINITION);
builder.put(DropView.class, QueryType.DATA_DEFINITION);
builder.put(CreateFunction.class, QueryType.DATA_DEFINITION);
builder.put(DropFunction.class, QueryType.DATA_DEFINITION);
builder.put(Use.class, QueryType.DATA_DEFINITION);
builder.put(SetSession.class, QueryType.DATA_DEFINITION);
builder.put(ResetSession.class, QueryType.DATA_DEFINITION);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ public void testCreateFunction()
assertEquals(
ImmutableSet.copyOf(functionNamespaceManager.listFunctions()),
ImmutableSet.of(FUNCTION_POWER_TOWER_DOUBLE_UPDATED.withVersion(2), FUNCTION_POWER_TOWER_INT.withVersion(1)));

System.out.println(FUNCTION_POWER_TOWER_DOUBLE);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ private static class TestFunctionHandle
@Override
public CatalogSchemaName getFunctionNamespace()
{
return QualifiedFunctionName.of("a.b.c").getFunctionNamespace();
return QualifiedFunctionName.of(new CatalogSchemaName("a", "b"), "c").getFunctionNamespace();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ statement
RETURNS returnType=type
(COMMENT string)?
routineCharacteristics routineBody #createFunction
| DROP FUNCTION (IF EXISTS)? qualifiedName types? #dropFunction
| CALL qualifiedName '(' (callArgument (',' callArgument)*)? ')' #call
| CREATE ROLE name=identifier
(WITH ADMIN grantor)? #createRole
Expand Down Expand Up @@ -394,6 +395,10 @@ normalForm
: NFD | NFC | NFKD | NFKC
;

types
: '(' (type (',' type)*)? ')'
;

type
: type ARRAY
| ARRAY '<' type '>'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import com.facebook.presto.sql.tree.DescribeInput;
import com.facebook.presto.sql.tree.DescribeOutput;
import com.facebook.presto.sql.tree.DropColumn;
import com.facebook.presto.sql.tree.DropFunction;
import com.facebook.presto.sql.tree.DropRole;
import com.facebook.presto.sql.tree.DropSchema;
import com.facebook.presto.sql.tree.DropTable;
Expand Down Expand Up @@ -573,6 +574,26 @@ protected Void visitCreateFunction(CreateFunction node, Integer indent)
return null;
}

@Override
protected Void visitDropFunction(DropFunction node, Integer indent)
{
builder.append("DROP FUNCTION ");
if (node.isExists()) {
builder.append("IF EXISTS ");
}
builder.append(formatName(node.getFunctionName()));
if (node.getParameterTypes().isPresent()) {
String elementIndent = indentString(indent + 1);
builder.append("(\n")
.append(node.getParameterTypes().get().stream()
.map(type -> elementIndent + type)
.collect(joining(",\n")))
.append(")\n");
}

return null;
}

@Override
protected Void visitDropView(DropView node, Integer context)
{
Expand Down
Loading