statement ok
CREATE FUNCTION f_test_drop() RETURNS INT LANGUAGE SQL AS $$ SELECT 1 $$;

statement ok
CREATE FUNCTION f_test_drop(int) RETURNS INT LANGUAGE SQL AS $$ SELECT 1 $$;

statement ok
CREATE SCHEMA sc1

statement ok
CREATE FUNCTION sc1.f_test_drop(int) RETURNS INT LANGUAGE SQL AS $$ SELECT 1 $$;

statement ok
SET search_path = public,sc1

query T
SELECT create_statement FROM [SHOW CREATE FUNCTION public.f_test_drop] ORDER BY 1
----
CREATE FUNCTION public.f_test_drop()
  RETURNS INT8
  VOLATILE
  NOT LEAKPROOF
  CALLED ON NULL INPUT
  LANGUAGE SQL
  SECURITY INVOKER
  AS $$
  SELECT 1;
$$
CREATE FUNCTION public.f_test_drop(INT8)
  RETURNS INT8
  VOLATILE
  NOT LEAKPROOF
  CALLED ON NULL INPUT
  LANGUAGE SQL
  SECURITY INVOKER
  AS $$
  SELECT 1;
$$

query T
SELECT create_statement FROM [SHOW CREATE FUNCTION sc1.f_test_drop];
----
CREATE FUNCTION sc1.f_test_drop(INT8)
  RETURNS INT8
  VOLATILE
  NOT LEAKPROOF
  CALLED ON NULL INPUT
  LANGUAGE SQL
  SECURITY INVOKER
  AS $$
  SELECT 1;
$$

statement error pgcode 42883 procedure f_test_drop\(\) does not exist
DROP PROCEDURE f_test_drop;

statement error pgcode 42725 pq: function name \"f_test_drop\" is not unique
DROP FUNCTION f_test_drop;

statement ok
DROP FUNCTION IF EXISTS f_not_existing;

statement error pgcode 42883 pq: unknown function: f_not_existing\(\)
DROP FUNCTION f_not_existing;

# drop a function twice should fail.
statement error pgcode 42883 pq: function f_test_drop\(\) does not exist
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
DROP FUNCTION f_test_drop();
DROP FUNCTION f_test_drop();
COMMIT;

statement ok
ROLLBACK;

statement error pgcode 42883 procedure f_test_drop\(\) does not exist
DROP PROCEDURE f_test_drop

statement ok
DROP PROCEDURE IF EXISTS f_test_drop

statement error pgcode 42809 f_test_drop\(\) is not a procedure
DROP PROCEDURE f_test_drop()

statement error pgcode 42809 f_test_drop\(\) is not a procedure
DROP PROCEDURE IF EXISTS f_test_drop()

statement ok
DROP FUNCTION f_test_drop()

query T
SELECT create_statement FROM [SHOW CREATE FUNCTION public.f_test_drop];
----
CREATE FUNCTION public.f_test_drop(INT8)
  RETURNS INT8
  VOLATILE
  NOT LEAKPROOF
  CALLED ON NULL INPUT
  LANGUAGE SQL
  SECURITY INVOKER
  AS $$
  SELECT 1;
$$

query T
SELECT create_statement FROM [SHOW CREATE FUNCTION sc1.f_test_drop];
----
CREATE FUNCTION sc1.f_test_drop(INT8)
  RETURNS INT8
  VOLATILE
  NOT LEAKPROOF
  CALLED ON NULL INPUT
  LANGUAGE SQL
  SECURITY INVOKER
  AS $$
  SELECT 1;
$$

# Drop with two identical function signatures should be ok. And only first match
# in path should be drop.
statement ok
DROP FUNCTION f_test_drop(INT), f_test_drop(INT);

statement error pgcode 42883 pq: unknown function: public.f_test_drop\(\)
SELECT create_statement FROM [SHOW CREATE FUNCTION public.f_test_drop];

query T
SELECT create_statement FROM [SHOW CREATE FUNCTION sc1.f_test_drop];
----
CREATE FUNCTION sc1.f_test_drop(INT8)
  RETURNS INT8
  VOLATILE
  NOT LEAKPROOF
  CALLED ON NULL INPUT
  LANGUAGE SQL
  SECURITY INVOKER
  AS $$
  SELECT 1;
$$

statement ok
DROP FUNCTION f_test_drop(INT);

statement error pgcode 42883 pq: unknown function: sc1.f_test_drop\(\)
SELECT create_statement FROM [SHOW CREATE FUNCTION sc1.f_test_drop];

# If there are identical function signatures in different schemas, multiple drop
# statements should drop them all. This matches postgres behavior.
statement ok
CREATE FUNCTION public.f_test_drop() RETURNS INT LANGUAGE SQL AS $$ SELECT 1 $$;
CREATE FUNCTION sc1.f_test_drop() RETURNS INT LANGUAGE SQL AS $$ SELECT 1 $$;

query T
SELECT create_statement FROM [SHOW CREATE FUNCTION public.f_test_drop];
----
CREATE FUNCTION public.f_test_drop()
  RETURNS INT8
  VOLATILE
  NOT LEAKPROOF
  CALLED ON NULL INPUT
  LANGUAGE SQL
  SECURITY INVOKER
  AS $$
  SELECT 1;
$$

query T
SELECT create_statement FROM [SHOW CREATE FUNCTION sc1.f_test_drop];
----
CREATE FUNCTION sc1.f_test_drop()
  RETURNS INT8
  VOLATILE
  NOT LEAKPROOF
  CALLED ON NULL INPUT
  LANGUAGE SQL
  SECURITY INVOKER
  AS $$
  SELECT 1;
$$

statement ok;
BEGIN;
DROP FUNCTION f_test_drop();
DROP FUNCTION f_test_drop();
COMMIT;

statement error pgcode 42883 pq: unknown function: public.f_test_drop\(\)
SELECT create_statement FROM [SHOW CREATE FUNCTION public.f_test_drop];

statement error pgcode 42883 pq: unknown function: sc1.f_test_drop\(\)
SELECT create_statement FROM [SHOW CREATE FUNCTION sc1.f_test_drop];

statement ok
SET search_path = public

statement ok
DROP SCHEMA sc1;

# Regression test for #114677 - it should be possible to drop a function with
# a UDT parameter
subtest udt_parameter

statement ok
CREATE TYPE t114677 AS (x INT, y INT);
CREATE TYPE t114677_2 AS (a INT, b INT);

# Create an overload with a composite type that has the same signature to verify
# that the correct overload is dropped.
statement ok
CREATE FUNCTION f114677(v t114677) RETURNS INT LANGUAGE SQL AS $$ SELECT 0; $$;
CREATE FUNCTION f114677(v t114677_2) RETURNS INT LANGUAGE SQL AS $$ SELECT 1; $$;

query T nosort
SELECT create_statement FROM [SHOW CREATE FUNCTION f114677] ORDER BY create_statement;
----
CREATE FUNCTION public.f114677(v public.t114677)
  RETURNS INT8
  VOLATILE
  NOT LEAKPROOF
  CALLED ON NULL INPUT
  LANGUAGE SQL
  SECURITY INVOKER
  AS $$
  SELECT 0;
$$
CREATE FUNCTION public.f114677(v public.t114677_2)
  RETURNS INT8
  VOLATILE
  NOT LEAKPROOF
  CALLED ON NULL INPUT
  LANGUAGE SQL
  SECURITY INVOKER
  AS $$
  SELECT 1;
$$

statement error pgcode 42725 pq: function name \"f114677\" is not unique
DROP FUNCTION f114677;

statement ok
DROP FUNCTION f114677(t114677);

query T
SELECT create_statement FROM [SHOW CREATE FUNCTION f114677];
----
CREATE FUNCTION public.f114677(v public.t114677_2)
  RETURNS INT8
  VOLATILE
  NOT LEAKPROOF
  CALLED ON NULL INPUT
  LANGUAGE SQL
  SECURITY INVOKER
  AS $$
  SELECT 1;
$$

statement ok
DROP FUNCTION f114677;

statement error pgcode 42883 unknown function: f114677\(\)
SHOW CREATE FUNCTION f114677;

subtest end


subtest functions_calling_functions

statement ok
CREATE FUNCTION f_called_by_b() RETURNS INT LANGUAGE SQL AS $$ SELECT 1 $$;

statement ok
CREATE FUNCTION f_called_by_b2() RETURNS INT LANGUAGE SQL AS $$ SELECT 1 + f_called_by_b() $$;

statement ok;
CREATE FUNCTION f_b()  RETURNS INT LANGUAGE SQL AS $$ SELECT (f_called_by_b2()) /f_called_by_b2() FROM f_called_by_b() $$;

statement error pgcode 2BP01 cannot drop function \"f_called_by_b\" because other objects \(\[test.public.f_called_by_b2, test.public.f_b\]\) still depend on it
DROP FUNCTION f_called_by_b;

statement error pgcode 2BP01 cannot drop function \"f_called_by_b2\" because other objects \(\[test.public.f_b\]\) still depend on it
DROP FUNCTION f_called_by_b2;

statement ok
CREATE OR REPLACE FUNCTION f_b()  RETURNS INT LANGUAGE SQL AS $$ SELECT 1 $$;

statement error pgcode 2BP01 cannot drop function \"f_called_by_b\" because other objects \(\[test.public.f_called_by_b2\]\) still depend on it
DROP FUNCTION f_called_by_b;

statement error pgcode 2BP01 cannot drop function \"f_called_by_b\" because other objects \(\[test.public.f_called_by_b2\]\) still depend on it
DROP FUNCTION f_called_by_b;


statement ok
CREATE SCHEMA altSchema;
CREATE FUNCTION altSchema.f_called_by_b() RETURNS INT LANGUAGE SQL AS $$ SELECT 1 $$;
CREATE TABLE t1_with_b_2_ref(j int default altSchema.f_called_by_b() CHECK (altSchema.f_called_by_b() > 0));

statement error pgcode 0A000 cannot set schema for function \"f_called_by_b\" because other functions \(\[test.public.f_called_by_b2\]\) still depend on it
ALTER FUNCTION f_called_by_b SET SCHEMA altSchema;

skipif config local-legacy-schema-changer
statement ok
DROP SCHEMA altSchema CASCADE;

onlyif config local-legacy-schema-changer
statement error pgcode 2BP01 cannot drop function \"f_called_by_b\" because other object \(\[test.public.t1_with_b_2_ref\]\) still depend on it
DROP SCHEMA altSchema CASCADE;

statement ok
SELECT * FROM  f_called_by_b2();

skipif config local-legacy-schema-changer
query T
SELECT create_statement FROM [SHOW CREATE TABLE t1_with_b_2_ref];
----
CREATE TABLE public.t1_with_b_2_ref (
  j INT8 NULL,
  rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
  CONSTRAINT t1_with_b_2_ref_pkey PRIMARY KEY (rowid ASC)
)

onlyif config local-legacy-schema-changer
statement ok
DROP FUNCTION f_called_by_b2;
DROP TABLE t1_with_b_2_ref;

statement ok
SET ROLE testuser;

# Check to ensure ownership is validated properly during a drop. This is a
# regression test to ensure we populate a proper pgcode for our error.
statement error pgcode 42501 must be owner of function f_b
DROP FUNCTION f_b();

statement ok
SET ROLE root;

statement ok
DROP FUNCTION f_b;

statement ok
CREATE FUNCTION f_char(c CHAR) RETURNS INT LANGUAGE SQL AS 'SELECT 1'

statement ok
DROP FUNCTION f_char(BPCHAR)

statement ok
CREATE FUNCTION f_char(c CHAR(2)) RETURNS INT LANGUAGE SQL AS 'SELECT 1'

statement ok
DROP FUNCTION f_char(BPCHAR)

statement ok
CREATE FUNCTION f_char(c BPCHAR) RETURNS INT LANGUAGE SQL AS 'SELECT 1'

statement ok
DROP FUNCTION f_char(BPCHAR)

statement ok
CREATE FUNCTION f_char(c BPCHAR) RETURNS INT LANGUAGE SQL AS 'SELECT 1'

statement ok
DROP FUNCTION f_char(CHAR)

statement ok
CREATE FUNCTION f_char(c BPCHAR) RETURNS INT LANGUAGE SQL AS 'SELECT 1'

statement ok
DROP FUNCTION f_char(CHAR(2))

statement ok
CREATE FUNCTION f_bit(c BIT) RETURNS INT LANGUAGE SQL AS 'SELECT 1'

statement ok
DROP FUNCTION f_bit(BIT(0))

statement ok
CREATE FUNCTION f_bit(c BIT(2)) RETURNS INT LANGUAGE SQL AS 'SELECT 1'

statement ok
DROP FUNCTION f_bit(BIT(0))

statement ok
CREATE FUNCTION f_bit(c BIT(0)) RETURNS INT LANGUAGE SQL AS 'SELECT 1'

statement ok
DROP FUNCTION f_bit(BIT(0))

statement ok
CREATE FUNCTION f_bit(c BIT(0)) RETURNS INT LANGUAGE SQL AS 'SELECT 1'

statement ok
DROP FUNCTION f_bit(BIT(2))
