@Override
    public void dropFunction(QualifiedObjectName functionName, Optional<List<TypeSignature>> parameterTypes, boolean exists)
    {
        checkCatalog(functionName);
        jdbi.useTransaction(handle -> {
            FunctionNamespaceDao transactionDao = handle.attach(functionNamespaceDaoClass);
            List<SqlInvokedFunction> functions = getSqlFunctions(transactionDao, functionName, parameterTypes);

            checkExists(functions, functionName, parameterTypes);

            if (!parameterTypes.isPresent()) {
                transactionDao.setDeleted(functionName.getCatalogName(), functionName.getSchemaName(), functionName.getObjectName());
            }
            else {
                SqlInvokedFunction latest = getOnlyElement(functions);
                checkState(latest.hasVersion(), "Function version missing: %s", latest.getFunctionId());
                transactionDao.setDeletionStatus(hash(latest.getFunctionId()), latest.getFunctionId(), getLongVersion(latest), true);
            }
        });

        refreshFunctionsCache(functionName);
    }
@Test
    public void testDropFunction()
    {
        // Create functions
        createFunction(FUNCTION_POWER_TOWER_DOUBLE, false);
        createFunction(FUNCTION_POWER_TOWER_INT, false);
        createFunction(FUNCTION_TANGENT, false);

        // Drop function by name
        dropFunction(TANGENT, Optional.empty(), false);
        assertGetFunctions(TANGENT);

        // Recreate functions
        createFunction(FUNCTION_TANGENT, false);

        // Drop a specific function by name and parameter types
        dropFunction(POWER_TOWER, Optional.of(ImmutableList.of(parseTypeSignature(DOUBLE))), true);
        assertGetFunctions(POWER_TOWER, FUNCTION_POWER_TOWER_INT.withVersion("1"));

        dropFunction(TANGENT, Optional.of(ImmutableList.of(parseTypeSignature(DOUBLE))), true);
        assertGetFunctions(POWER_TOWER, FUNCTION_POWER_TOWER_INT.withVersion("1"));
        assertGetFunctions(TANGENT);

        // Recreate functions, power_double(double) is created with a different definition
        createFunction(FUNCTION_POWER_TOWER_DOUBLE_UPDATED, false);
        createFunction(FUNCTION_TANGENT, false);

        // Drop functions consecutively
        dropFunction(POWER_TOWER, Optional.of(ImmutableList.of(parseTypeSignature(DOUBLE))), false);
        dropFunction(POWER_TOWER, Optional.empty(), false);
    }