diff --git a/Makefile b/Makefile
index c1281871..b198a6a1 100644
--- a/Makefile
+++ b/Makefile
@@ -61,7 +61,8 @@ REGRESS = pathman_array_qual \
 		  pathman_update_triggers \
 		  pathman_upd_del \
 		  pathman_utility_stmt \
-		  pathman_views
+		  pathman_views \
+		  pathman_CVE-2020-14350
 
 
 EXTRA_REGRESS_OPTS=--temp-config=$(top_srcdir)/$(subdir)/conf.add
diff --git a/README.md b/README.md
index b49c20ec..2f95a738 100644
--- a/README.md
+++ b/README.md
@@ -95,11 +95,19 @@ shared_preload_libraries = 'pg_pathman'
 
 It is essential to restart the PostgreSQL instance. After that, execute the following query in psql:
 ```plpgsql
-CREATE EXTENSION pg_pathman;
+CREATE SCHEMA pathman;
+GRANT USAGE ON SCHEMA pathman TO PUBLIC;
+CREATE EXTENSION pg_pathman WITH SCHEMA pathman;
 ```
 
 Done! Now it's time to setup your partitioning schemes.
 
+> **Security notice**: pg_pathman is believed to be secure against
+search-path-based attacks mentioned in Postgres
+[documentation](https://www.postgresql.org/docs/current/sql-createextension.html). However,
+if *your* calls of pathman's functions doesn't exactly match the signature, they
+might be vulnerable to malicious overloading. If in doubt, install pathman to clean schema where nobody except superusers have CREATE object permission to avoid problems.
+
 > **Windows-specific**: pg_pathman imports several symbols (e.g. None_Receiver, InvalidObjectAddress) from PostgreSQL, which is fine by itself, but requires that those symbols are marked as `PGDLLIMPORT`. Unfortunately, some of them are not exported from vanilla PostgreSQL, which means that you have to either use Postgres Pro Standard/Enterprise (which includes all necessary patches), or patch and build your own distribution of PostgreSQL.
 
 ## How to update
@@ -611,7 +619,7 @@ SELECT tableoid::regclass AS partition, * FROM partitioned_table;
 - All running concurrent partitioning tasks can be listed using the `pathman_concurrent_part_tasks` view:
 ```plpgsql
 SELECT * FROM pathman_concurrent_part_tasks;
- userid | pid  | dbid  | relid | processed | status  
+ userid | pid  | dbid  | relid | processed | status
 --------+------+-------+-------+-----------+---------
  dmitry | 7367 | 16384 | test  |    472000 | working
 (1 row)
@@ -625,7 +633,7 @@ WHERE parent = 'part_test'::regclass AND range_min::int < 500;
 NOTICE:  1 rows copied from part_test_11
 NOTICE:  100 rows copied from part_test_1
 NOTICE:  100 rows copied from part_test_2
- drop_range_partition 
+ drop_range_partition
 ----------------------
  dummy_test_11
  dummy_test_1
@@ -780,8 +788,8 @@ All sections and data will remain unchanged and will be handled by the standard
 Do not hesitate to post your issues, questions and new ideas at the [issues](https://github.com/postgrespro/pg_pathman/issues) page.
 
 ## Authors
-[Ildar Musin](https://github.com/zilder)  
-Alexander Korotkov <a.korotkov(at)postgrespro.ru> Postgres Professional Ltd., Russia  
-[Dmitry Ivanov](https://github.com/funbringer)  
-Maksim Milyutin <m.milyutin(at)postgrespro.ru> Postgres Professional Ltd., Russia  
+[Ildar Musin](https://github.com/zilder)
+Alexander Korotkov <a.korotkov(at)postgrespro.ru> Postgres Professional Ltd., Russia
+[Dmitry Ivanov](https://github.com/funbringer)
+Maksim Milyutin <m.milyutin(at)postgrespro.ru> Postgres Professional Ltd., Russia
 [Ildus Kurbangaliev](https://github.com/ildus)
diff --git a/expected/pathman_CVE-2020-14350.out b/expected/pathman_CVE-2020-14350.out
new file mode 100644
index 00000000..c91a280f
--- /dev/null
+++ b/expected/pathman_CVE-2020-14350.out
@@ -0,0 +1,115 @@
+/*
+ * Check fix for CVE-2020-14350.
+ * See also 7eeb1d986 postgresql commit.
+ */
+SET client_min_messages = 'warning';
+DROP FUNCTION IF EXISTS _partition_data_concurrent(oid,integer);
+DROP FUNCTION IF EXISTS create_single_range_partition(TEXT,ANYELEMENT,ANYELEMENT,TEXT);
+DROP TABLE IF EXISTS test1 CASCADE;
+DROP TABLE IF EXISTS test2 CASCADE;
+DROP ROLE IF EXISTS regress_hacker;
+SET client_min_messages = 'notice';
+CREATE EXTENSION pg_pathman;
+CREATE ROLE regress_hacker LOGIN;
+-- Test 1
+RESET ROLE;
+ALTER ROLE regress_hacker NOSUPERUSER;
+SET ROLE regress_hacker;
+SHOW is_superuser;
+ is_superuser 
+--------------
+ off
+(1 row)
+
+CREATE FUNCTION _partition_data_concurrent(relation oid, p_limit INT, OUT p_total BIGINT)
+RETURNS bigint
+AS $$
+BEGIN
+  ALTER ROLE regress_hacker SUPERUSER;
+  SELECT _partition_data_concurrent(relation, NULL::text, NULL::text, p_limit) INTO p_total;
+END
+$$ LANGUAGE plpgsql;
+CREATE TABLE test1(i INT4 NOT NULL);
+INSERT INTO test1 SELECT generate_series(1, 500);
+SELECT create_hash_partitions('test1', 'i', 5, false);
+ create_hash_partitions 
+------------------------
+                      5
+(1 row)
+
+RESET ROLE;
+SELECT partition_table_concurrently('test1', 10, 1);
+NOTICE:  worker started, you can stop it with the following command: select public.stop_concurrent_part_task('test1');
+ partition_table_concurrently 
+------------------------------
+ 
+(1 row)
+
+SELECT pg_sleep(1);
+ pg_sleep 
+----------
+ 
+(1 row)
+
+-- Test result (must be 'off')
+SET ROLE regress_hacker;
+SHOW is_superuser;
+ is_superuser 
+--------------
+ off
+(1 row)
+
+-- Test 2
+RESET ROLE;
+ALTER ROLE regress_hacker NOSUPERUSER;
+SET ROLE regress_hacker;
+SHOW is_superuser;
+ is_superuser 
+--------------
+ off
+(1 row)
+
+CREATE FUNCTION create_single_range_partition(parent_relid TEXT, start_value ANYELEMENT, end_value ANYELEMENT, partition_name TEXT)
+RETURNS REGCLASS
+AS $$
+BEGIN
+  ALTER ROLE regress_hacker SUPERUSER;
+  RETURN create_single_range_partition(parent_relid, start_value, end_value, partition_name, NULL::text);
+END
+$$ LANGUAGE plpgsql;
+RESET ROLE;
+CREATE TABLE test2(i INT4 NOT NULL);
+INSERT INTO test2 VALUES(0);
+SELECT create_range_partitions('test2', 'i', 0, 1);
+ create_range_partitions 
+-------------------------
+                       1
+(1 row)
+
+INSERT INTO test2 values(1);
+-- Test result (must be 'off')
+SET ROLE regress_hacker;
+SHOW is_superuser;
+ is_superuser 
+--------------
+ off
+(1 row)
+
+-- Cleanup
+RESET ROLE;
+DROP FUNCTION _partition_data_concurrent(oid,integer);
+DROP FUNCTION create_single_range_partition(TEXT,ANYELEMENT,ANYELEMENT,TEXT);
+DROP TABLE test1 CASCADE;
+NOTICE:  drop cascades to 5 other objects
+DETAIL:  drop cascades to table test1_0
+drop cascades to table test1_1
+drop cascades to table test1_2
+drop cascades to table test1_3
+drop cascades to table test1_4
+DROP TABLE test2 CASCADE;
+NOTICE:  drop cascades to 3 other objects
+DETAIL:  drop cascades to sequence test2_seq
+drop cascades to table test2_1
+drop cascades to table test2_2
+DROP ROLE regress_hacker;
+DROP EXTENSION pg_pathman;
diff --git a/hash.sql b/hash.sql
index 45c9b71d..b22fd75e 100644
--- a/hash.sql
+++ b/hash.sql
@@ -3,7 +3,7 @@
  * hash.sql
  *		HASH partitioning functions
  *
- * Copyright (c) 2015-2016, Postgres Professional
+ * Copyright (c) 2015-2020, Postgres Professional
  *
  * ------------------------------------------------------------------------
  */
@@ -11,7 +11,7 @@
 /*
  * Creates hash partitions for specified relation
  */
-CREATE OR REPLACE FUNCTION @extschema@.create_hash_partitions(
+CREATE FUNCTION @extschema@.create_hash_partitions(
 	parent_relid		REGCLASS,
 	expression			TEXT,
 	partitions_count	INT4,
@@ -53,7 +53,7 @@ SET client_min_messages = WARNING;
  *
  * lock_parent - should we take an exclusive lock?
  */
-CREATE OR REPLACE FUNCTION @extschema@.replace_hash_partition(
+CREATE FUNCTION @extschema@.replace_hash_partition(
 	old_partition		REGCLASS,
 	new_partition		REGCLASS,
 	lock_parent			BOOL DEFAULT TRUE)
@@ -110,18 +110,18 @@ BEGIN
 
 	/* Fetch definition of old_partition's HASH constraint */
 	SELECT pg_catalog.pg_get_constraintdef(oid) FROM pg_catalog.pg_constraint
-	WHERE conrelid = old_partition AND quote_ident(conname) = old_constr_name
+	WHERE conrelid = old_partition AND pg_catalog.quote_ident(conname) = old_constr_name
 	INTO old_constr_def;
 
 	/* Detach old partition */
-	EXECUTE format('ALTER TABLE %s NO INHERIT %s', old_partition, parent_relid);
-	EXECUTE format('ALTER TABLE %s DROP CONSTRAINT %s',
+	EXECUTE pg_catalog.format('ALTER TABLE %s NO INHERIT %s', old_partition, parent_relid);
+	EXECUTE pg_catalog.format('ALTER TABLE %s DROP CONSTRAINT %s',
 				   old_partition,
 				   old_constr_name);
 
 	/* Attach the new one */
-	EXECUTE format('ALTER TABLE %s INHERIT %s', new_partition, parent_relid);
-	EXECUTE format('ALTER TABLE %s ADD CONSTRAINT %s %s',
+	EXECUTE pg_catalog.format('ALTER TABLE %s INHERIT %s', new_partition, parent_relid);
+	EXECUTE pg_catalog.format('ALTER TABLE %s ADD CONSTRAINT %s %s',
 				   new_partition,
 				   @extschema@.build_check_constraint_name(new_partition::REGCLASS),
 				   old_constr_def);
@@ -146,7 +146,7 @@ $$ LANGUAGE plpgsql;
 /*
  * Just create HASH partitions, called by create_hash_partitions().
  */
-CREATE OR REPLACE FUNCTION @extschema@.create_hash_partitions_internal(
+CREATE FUNCTION @extschema@.create_hash_partitions_internal(
 	parent_relid		REGCLASS,
 	attribute			TEXT,
 	partitions_count	INT4,
@@ -158,14 +158,14 @@ LANGUAGE C;
 /*
  * Calculates hash for integer value
  */
-CREATE OR REPLACE FUNCTION @extschema@.get_hash_part_idx(INT4, INT4)
+CREATE FUNCTION @extschema@.get_hash_part_idx(INT4, INT4)
 RETURNS INTEGER AS 'pg_pathman', 'get_hash_part_idx'
 LANGUAGE C STRICT;
 
 /*
  * Build hash condition for a CHECK CONSTRAINT
  */
-CREATE OR REPLACE FUNCTION @extschema@.build_hash_condition(
+CREATE FUNCTION @extschema@.build_hash_condition(
 	attribute_type		REGTYPE,
 	attribute			TEXT,
 	partitions_count	INT4,
diff --git a/init.sql b/init.sql
index 16ec0b8f..123b2a36 100644
--- a/init.sql
+++ b/init.sql
@@ -3,7 +3,7 @@
  * init.sql
  *		Creates config table and provides common utility functions
  *
- * Copyright (c) 2015-2016, Postgres Professional
+ * Copyright (c) 2015-2020, Postgres Professional
  *
  * ------------------------------------------------------------------------
  */
@@ -14,7 +14,7 @@
  * to partitioning key. The function throws an error if it fails to convert
  * text to Datum
  */
-CREATE OR REPLACE FUNCTION @extschema@.validate_interval_value(
+CREATE FUNCTION @extschema@.validate_interval_value(
 	partrel			REGCLASS,
 	expr			TEXT,
 	parttype		INTEGER,
@@ -31,7 +31,7 @@ LANGUAGE C;
  *		range_interval	- base interval for RANGE partitioning as string
  *		cooked_expr		- cooked partitioning expression (parsed & rewritten)
  */
-CREATE TABLE IF NOT EXISTS @extschema@.pathman_config (
+CREATE TABLE @extschema@.pathman_config (
 	partrel			REGCLASS NOT NULL PRIMARY KEY,
 	expr			TEXT NOT NULL,
 	parttype		INTEGER NOT NULL,
@@ -55,7 +55,7 @@ CREATE TABLE IF NOT EXISTS @extschema@.pathman_config (
  *
  * NOTE: this function is used in CHECK CONSTRAINT.
  */
-CREATE OR REPLACE FUNCTION @extschema@.validate_part_callback(
+CREATE FUNCTION @extschema@.validate_part_callback(
 	callback		REGPROCEDURE,
 	raise_error		BOOL DEFAULT TRUE)
 RETURNS BOOL AS 'pg_pathman', 'validate_part_callback_pl'
@@ -70,7 +70,7 @@ LANGUAGE C STRICT;
  *		init_callback	- text signature of cb to be executed on partition creation
  *		spawn_using_bgw	- use background worker in order to auto create partitions
  */
-CREATE TABLE IF NOT EXISTS @extschema@.pathman_config_params (
+CREATE TABLE @extschema@.pathman_config_params (
 	partrel			REGCLASS NOT NULL PRIMARY KEY,
 	enable_parent	BOOLEAN NOT NULL DEFAULT FALSE,
 	auto			BOOLEAN NOT NULL DEFAULT TRUE,
@@ -91,7 +91,7 @@ TO public;
 /*
  * Check if current user can alter/drop specified relation
  */
-CREATE OR REPLACE FUNCTION @extschema@.check_security_policy(relation regclass)
+CREATE FUNCTION @extschema@.check_security_policy(relation regclass)
 RETURNS BOOL AS 'pg_pathman', 'check_security_policy' LANGUAGE C STRICT;
 
 /*
@@ -113,7 +113,7 @@ ALTER TABLE @extschema@.pathman_config_params ENABLE ROW LEVEL SECURITY;
 /*
  * Invalidate relcache every time someone changes parameters config or pathman_config
  */
-CREATE OR REPLACE FUNCTION @extschema@.pathman_config_params_trigger_func()
+CREATE FUNCTION @extschema@.pathman_config_params_trigger_func()
 RETURNS TRIGGER AS 'pg_pathman', 'pathman_config_params_trigger_func'
 LANGUAGE C;
 
@@ -135,13 +135,13 @@ SELECT pg_catalog.pg_extension_config_dump('@extschema@.pathman_config_params',
 /*
  * Add a row describing the optional parameter to pathman_config_params.
  */
-CREATE OR REPLACE FUNCTION @extschema@.pathman_set_param(
+CREATE FUNCTION @extschema@.pathman_set_param(
 	relation	REGCLASS,
 	param		TEXT,
 	value		ANYELEMENT)
 RETURNS VOID AS $$
 BEGIN
-	EXECUTE format('INSERT INTO @extschema@.pathman_config_params
+	EXECUTE pg_catalog.format('INSERT INTO @extschema@.pathman_config_params
 					(partrel, %1$s) VALUES ($1, $2)
 					ON CONFLICT (partrel) DO UPDATE SET %1$s = $2', param)
 	USING relation, value;
@@ -151,7 +151,7 @@ $$ LANGUAGE plpgsql;
 /*
  * Include\exclude parent relation in query plan.
  */
-CREATE OR REPLACE FUNCTION @extschema@.set_enable_parent(
+CREATE FUNCTION @extschema@.set_enable_parent(
 	relation	REGCLASS,
 	value		BOOLEAN)
 RETURNS VOID AS $$
@@ -163,7 +163,7 @@ $$ LANGUAGE plpgsql STRICT;
 /*
  * Enable\disable automatic partition creation.
  */
-CREATE OR REPLACE FUNCTION @extschema@.set_auto(
+CREATE FUNCTION @extschema@.set_auto(
 	relation	REGCLASS,
 	value		BOOLEAN)
 RETURNS VOID AS $$
@@ -175,7 +175,7 @@ $$ LANGUAGE plpgsql STRICT;
 /*
  * Set partition creation callback
  */
-CREATE OR REPLACE FUNCTION @extschema@.set_init_callback(
+CREATE FUNCTION @extschema@.set_init_callback(
 	relation	REGCLASS,
 	callback	REGPROCEDURE DEFAULT 0)
 RETURNS VOID AS $$
@@ -186,10 +186,10 @@ BEGIN
 
 	/* Fetch schema-qualified name of callback */
 	IF callback != 0 THEN
-		SELECT quote_ident(nspname) || '.' ||
-			   quote_ident(proname) || '(' ||
-					(SELECT string_agg(x.argtype::REGTYPE::TEXT, ',')
-					 FROM unnest(proargtypes) AS x(argtype)) ||
+		SELECT pg_catalog.quote_ident(nspname) || '.' ||
+			   pg_catalog.quote_ident(proname) || '(' ||
+					(SELECT pg_catalog.string_agg(x.argtype::REGTYPE::TEXT, ',')
+					 FROM pg_catalog.unnest(proargtypes) AS x(argtype)) ||
 			   ')'
 		FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n
 		ON n.oid = p.pronamespace
@@ -204,7 +204,7 @@ $$ LANGUAGE plpgsql STRICT;
 /*
  * Set 'spawn using BGW' option
  */
-CREATE OR REPLACE FUNCTION @extschema@.set_spawn_using_bgw(
+CREATE FUNCTION @extschema@.set_spawn_using_bgw(
 	relation	REGCLASS,
 	value		BOOLEAN)
 RETURNS VOID AS $$
@@ -216,7 +216,7 @@ $$ LANGUAGE plpgsql STRICT;
 /*
  * Set (or reset) default interval for auto created partitions
  */
-CREATE OR REPLACE FUNCTION @extschema@.set_interval(
+CREATE FUNCTION @extschema@.set_interval(
 	relation		REGCLASS,
 	value			ANYELEMENT)
 RETURNS VOID AS $$
@@ -240,7 +240,7 @@ $$ LANGUAGE plpgsql;
 /*
  * Show all existing parents and partitions.
  */
-CREATE OR REPLACE FUNCTION @extschema@.show_partition_list()
+CREATE FUNCTION @extschema@.show_partition_list()
 RETURNS TABLE (
 	parent			REGCLASS,
 	partition		REGCLASS,
@@ -254,7 +254,7 @@ LANGUAGE C STRICT;
 /*
  * View for show_partition_list().
  */
-CREATE OR REPLACE VIEW @extschema@.pathman_partition_list
+CREATE VIEW @extschema@.pathman_partition_list
 AS SELECT * FROM @extschema@.show_partition_list();
 
 GRANT SELECT ON @extschema@.pathman_partition_list TO PUBLIC;
@@ -262,7 +262,7 @@ GRANT SELECT ON @extschema@.pathman_partition_list TO PUBLIC;
 /*
  * Show memory usage of pg_pathman's caches.
  */
-CREATE OR REPLACE FUNCTION @extschema@.show_cache_stats()
+CREATE FUNCTION @extschema@.show_cache_stats()
 RETURNS TABLE (
 	context			TEXT,
 	size			INT8,
@@ -274,13 +274,13 @@ LANGUAGE C STRICT;
 /*
  * View for show_cache_stats().
  */
-CREATE OR REPLACE VIEW @extschema@.pathman_cache_stats
+CREATE VIEW @extschema@.pathman_cache_stats
 AS SELECT * FROM @extschema@.show_cache_stats();
 
 /*
  * Show all existing concurrent partitioning tasks.
  */
-CREATE OR REPLACE FUNCTION @extschema@.show_concurrent_part_tasks()
+CREATE FUNCTION @extschema@.show_concurrent_part_tasks()
 RETURNS TABLE (
 	userid		REGROLE,
 	pid			INT,
@@ -294,7 +294,7 @@ LANGUAGE C STRICT;
 /*
  * View for show_concurrent_part_tasks().
  */
-CREATE OR REPLACE VIEW @extschema@.pathman_concurrent_part_tasks
+CREATE VIEW @extschema@.pathman_concurrent_part_tasks
 AS SELECT * FROM @extschema@.show_concurrent_part_tasks();
 
 GRANT SELECT ON @extschema@.pathman_concurrent_part_tasks TO PUBLIC;
@@ -302,7 +302,7 @@ GRANT SELECT ON @extschema@.pathman_concurrent_part_tasks TO PUBLIC;
 /*
  * Partition table using ConcurrentPartWorker.
  */
-CREATE OR REPLACE FUNCTION @extschema@.partition_table_concurrently(
+CREATE FUNCTION @extschema@.partition_table_concurrently(
 	relation		REGCLASS,
 	batch_size		INTEGER DEFAULT 1000,
 	sleep_time		FLOAT8 DEFAULT 1.0)
@@ -312,7 +312,7 @@ LANGUAGE C STRICT;
 /*
  * Stop concurrent partitioning task.
  */
-CREATE OR REPLACE FUNCTION @extschema@.stop_concurrent_part_task(
+CREATE FUNCTION @extschema@.stop_concurrent_part_task(
 	relation		REGCLASS)
 RETURNS BOOL AS 'pg_pathman', 'stop_concurrent_part_task'
 LANGUAGE C STRICT;
@@ -321,7 +321,7 @@ LANGUAGE C STRICT;
 /*
  * Copy rows to partitions concurrently.
  */
-CREATE OR REPLACE FUNCTION @extschema@._partition_data_concurrent(
+CREATE FUNCTION @extschema@._partition_data_concurrent(
 	relation		REGCLASS,
 	p_min			ANYELEMENT DEFAULT NULL::text,
 	p_max			ANYELEMENT DEFAULT NULL::text,
@@ -341,19 +341,19 @@ BEGIN
 
 	/* Format LIMIT clause if needed */
 	IF NOT p_limit IS NULL THEN
-		v_limit_clause := format('LIMIT %s', p_limit);
+		v_limit_clause := pg_catalog.format('LIMIT %s', p_limit);
 	END IF;
 
 	/* Format WHERE clause if needed */
 	IF NOT p_min IS NULL THEN
-		v_where_clause := format('%1$s >= $1', part_expr);
+		v_where_clause := pg_catalog.format('%1$s >= $1', part_expr);
 	END IF;
 
 	IF NOT p_max IS NULL THEN
 		IF NOT p_min IS NULL THEN
 			v_where_clause := v_where_clause || ' AND ';
 		END IF;
-		v_where_clause := v_where_clause || format('%1$s < $2', part_expr);
+		v_where_clause := v_where_clause || pg_catalog.format('%1$s < $2', part_expr);
 	END IF;
 
 	IF v_where_clause != '' THEN
@@ -362,12 +362,12 @@ BEGIN
 
 	/* Lock rows and copy data */
 	RAISE NOTICE 'Copying data to partitions...';
-	EXECUTE format('SELECT array(SELECT ctid FROM ONLY %1$s %2$s %3$s FOR UPDATE NOWAIT)',
+	EXECUTE pg_catalog.format('SELECT array(SELECT ctid FROM ONLY %1$s %2$s %3$s FOR UPDATE NOWAIT)',
 				   relation, v_where_clause, v_limit_clause)
 	USING p_min, p_max
 	INTO ctids;
 
-	EXECUTE format('WITH data AS (
+	EXECUTE pg_catalog.format('WITH data AS (
 					DELETE FROM ONLY %1$s WHERE ctid = ANY($1) RETURNING *)
 					INSERT INTO %1$s SELECT * FROM data',
 				   relation)
@@ -383,7 +383,7 @@ SET pg_pathman.enable_partitionfilter = on; /* ensures that PartitionFilter is O
 /*
  * Old school way to distribute rows to partitions.
  */
-CREATE OR REPLACE FUNCTION @extschema@.partition_data(
+CREATE FUNCTION @extschema@.partition_data(
 	parent_relid	REGCLASS,
 	OUT p_total		BIGINT)
 AS $$
@@ -391,7 +391,7 @@ BEGIN
 	p_total := 0;
 
 	/* Create partitions and copy rest of the data */
-	EXECUTE format('WITH part_data AS (DELETE FROM ONLY %1$s RETURNING *)
+	EXECUTE pg_catalog.format('WITH part_data AS (DELETE FROM ONLY %1$s RETURNING *)
 					INSERT INTO %1$s SELECT * FROM part_data',
 				   parent_relid::TEXT);
 
@@ -405,7 +405,7 @@ SET pg_pathman.enable_partitionfilter = on; /* ensures that PartitionFilter is O
 /*
  * Disable pathman partitioning for specified relation.
  */
-CREATE OR REPLACE FUNCTION @extschema@.disable_pathman_for(
+CREATE FUNCTION @extschema@.disable_pathman_for(
 	parent_relid	REGCLASS)
 RETURNS VOID AS $$
 BEGIN
@@ -420,7 +420,7 @@ $$ LANGUAGE plpgsql STRICT;
 /*
  * Check a few things and take locks before partitioning.
  */
-CREATE OR REPLACE FUNCTION @extschema@.prepare_for_partitioning(
+CREATE FUNCTION @extschema@.prepare_for_partitioning(
 	parent_relid	REGCLASS,
 	expression		TEXT,
 	partition_data	BOOLEAN)
@@ -455,7 +455,7 @@ BEGIN
 		RAISE EXCEPTION 'table "%" has already been partitioned', parent_relid;
 	END IF;
 
-	IF EXISTS (SELECT 1 FROM pg_inherits WHERE inhparent = parent_relid) THEN
+	IF EXISTS (SELECT 1 FROM pg_catalog.pg_inherits WHERE inhparent = parent_relid) THEN
 		RAISE EXCEPTION 'can''t partition table "%" with existing children', parent_relid;
 	END IF;
 
@@ -478,7 +478,7 @@ $$ LANGUAGE plpgsql;
 /*
  * Returns relname without quotes or something.
  */
-CREATE OR REPLACE FUNCTION @extschema@.get_plain_schema_and_relname(
+CREATE FUNCTION @extschema@.get_plain_schema_and_relname(
 	cls				REGCLASS,
 	OUT schema		TEXT,
 	OUT relname		TEXT)
@@ -494,7 +494,7 @@ $$ LANGUAGE plpgsql STRICT;
 /*
  * DDL trigger that removes entry from pathman_config table.
  */
-CREATE OR REPLACE FUNCTION @extschema@.pathman_ddl_trigger_func()
+CREATE FUNCTION @extschema@.pathman_ddl_trigger_func()
 RETURNS event_trigger AS $$
 DECLARE
 	obj				RECORD;
@@ -505,8 +505,8 @@ BEGIN
 	pg_class_oid = 'pg_catalog.pg_class'::regclass;
 
 	/* Find relids to remove from config */
-	SELECT array_agg(cfg.partrel) INTO relids
-	FROM pg_event_trigger_dropped_objects() AS events
+	SELECT pg_catalog.array_agg(cfg.partrel) INTO relids
+	FROM pg_catalog.pg_event_trigger_dropped_objects() AS events
 	JOIN @extschema@.pathman_config AS cfg ON cfg.partrel::oid = events.objid
 	WHERE events.classid = pg_class_oid AND events.objsubid = 0;
 
@@ -522,7 +522,7 @@ $$ LANGUAGE plpgsql;
  * Drop partitions. If delete_data set to TRUE, partitions
  * will be dropped with all the data.
  */
-CREATE OR REPLACE FUNCTION @extschema@.drop_partitions(
+CREATE FUNCTION @extschema@.drop_partitions(
 	parent_relid	REGCLASS,
 	delete_data		BOOLEAN DEFAULT FALSE)
 RETURNS INTEGER AS $$
@@ -552,7 +552,7 @@ BEGIN
 				  ORDER BY inhrelid ASC)
 	LOOP
 		IF NOT delete_data THEN
-			EXECUTE format('INSERT INTO %s SELECT * FROM %s',
+			EXECUTE pg_catalog.format('INSERT INTO %s SELECT * FROM %s',
 							parent_relid::TEXT,
 							child::TEXT);
 			GET DIAGNOSTICS rows_count = ROW_COUNT;
@@ -571,9 +571,9 @@ BEGIN
 		 * DROP TABLE or DROP FOREIGN TABLE.
 		 */
 		IF rel_kind = 'f' THEN
-			EXECUTE format('DROP FOREIGN TABLE %s', child);
+			EXECUTE pg_catalog.format('DROP FOREIGN TABLE %s', child);
 		ELSE
-			EXECUTE format('DROP TABLE %s', child);
+			EXECUTE pg_catalog.format('DROP TABLE %s', child);
 		END IF;
 
 		part_count := part_count + 1;
@@ -592,7 +592,7 @@ SET pg_pathman.enable_partitionfilter = off; /* ensures that PartitionFilter is
 /*
  * Copy all of parent's foreign keys.
  */
-CREATE OR REPLACE FUNCTION @extschema@.copy_foreign_keys(
+CREATE FUNCTION @extschema@.copy_foreign_keys(
 	parent_relid	REGCLASS,
 	partition_relid	REGCLASS)
 RETURNS VOID AS $$
@@ -606,7 +606,7 @@ BEGIN
 	FOR conid IN (SELECT oid FROM pg_catalog.pg_constraint
 				  WHERE conrelid = parent_relid AND contype = 'f')
 	LOOP
-		EXECUTE format('ALTER TABLE %s ADD %s',
+		EXECUTE pg_catalog.format('ALTER TABLE %s ADD %s',
 					   partition_relid::TEXT,
 					   pg_catalog.pg_get_constraintdef(conid));
 	END LOOP;
@@ -617,7 +617,7 @@ $$ LANGUAGE plpgsql STRICT;
 /*
  * Set new relname, schema and tablespace
  */
-CREATE OR REPLACE FUNCTION @extschema@.alter_partition(
+CREATE FUNCTION @extschema@.alter_partition(
 	relation		REGCLASS,
 	new_name		TEXT,
 	new_schema		REGNAMESPACE,
@@ -634,17 +634,17 @@ BEGIN
 
 	/* Alter table name */
 	IF new_name != orig_name THEN
-		EXECUTE format('ALTER TABLE %s RENAME TO %s', relation, new_name);
+		EXECUTE pg_catalog.format('ALTER TABLE %s RENAME TO %s', relation, new_name);
 	END IF;
 
 	/* Alter table schema */
 	IF new_schema != orig_schema THEN
-		EXECUTE format('ALTER TABLE %s SET SCHEMA %s', relation, new_schema);
+		EXECUTE pg_catalog.format('ALTER TABLE %s SET SCHEMA %s', relation, new_schema);
 	END IF;
 
 	/* Move to another tablespace */
 	IF NOT new_tablespace IS NULL THEN
-		EXECUTE format('ALTER TABLE %s SET TABLESPACE %s', relation, new_tablespace);
+		EXECUTE pg_catalog.format('ALTER TABLE %s SET TABLESPACE %s', relation, new_tablespace);
 	END IF;
 END
 $$ LANGUAGE plpgsql;
@@ -661,7 +661,7 @@ EXECUTE PROCEDURE @extschema@.pathman_ddl_trigger_func();
 /*
  * Get partitioning key.
  */
-CREATE OR REPLACE FUNCTION @extschema@.get_partition_key(
+CREATE FUNCTION @extschema@.get_partition_key(
 	parent_relid	REGCLASS)
 RETURNS TEXT AS
 $$
@@ -674,7 +674,7 @@ LANGUAGE sql STRICT;
 /*
  * Get partitioning key type.
  */
-CREATE OR REPLACE FUNCTION @extschema@.get_partition_key_type(
+CREATE FUNCTION @extschema@.get_partition_key_type(
 	parent_relid	REGCLASS)
 RETURNS REGTYPE AS 'pg_pathman', 'get_partition_key_type_pl'
 LANGUAGE C STRICT;
@@ -682,7 +682,7 @@ LANGUAGE C STRICT;
 /*
  * Get parsed and analyzed expression.
  */
-CREATE OR REPLACE FUNCTION @extschema@.get_partition_cooked_key(
+CREATE FUNCTION @extschema@.get_partition_cooked_key(
 	parent_relid	REGCLASS)
 RETURNS TEXT AS 'pg_pathman', 'get_partition_cooked_key_pl'
 LANGUAGE C STRICT;
@@ -690,7 +690,7 @@ LANGUAGE C STRICT;
 /*
  * Get partitioning type.
  */
-CREATE OR REPLACE FUNCTION @extschema@.get_partition_type(
+CREATE FUNCTION @extschema@.get_partition_type(
 	parent_relid	REGCLASS)
 RETURNS INT4 AS
 $$
@@ -703,11 +703,11 @@ LANGUAGE sql STRICT;
 /*
  * Get number of partitions managed by pg_pathman.
  */
-CREATE OR REPLACE FUNCTION @extschema@.get_number_of_partitions(
+CREATE FUNCTION @extschema@.get_number_of_partitions(
 	parent_relid	REGCLASS)
 RETURNS INT4 AS
 $$
-	SELECT count(*)::INT4
+	SELECT pg_catalog.count(*)::INT4
 	FROM pg_catalog.pg_inherits
 	WHERE inhparent = parent_relid;
 $$
@@ -716,7 +716,7 @@ LANGUAGE sql STRICT;
 /*
  * Get parent of pg_pathman's partition.
  */
-CREATE OR REPLACE FUNCTION @extschema@.get_parent_of_partition(
+CREATE FUNCTION @extschema@.get_parent_of_partition(
 	partition_relid		REGCLASS)
 RETURNS REGCLASS AS 'pg_pathman', 'get_parent_of_partition_pl'
 LANGUAGE C STRICT;
@@ -724,7 +724,7 @@ LANGUAGE C STRICT;
 /*
  * Extract basic type of a domain.
  */
-CREATE OR REPLACE FUNCTION @extschema@.get_base_type(
+CREATE FUNCTION @extschema@.get_base_type(
 	typid	REGTYPE)
 RETURNS REGTYPE AS 'pg_pathman', 'get_base_type_pl'
 LANGUAGE C STRICT;
@@ -732,7 +732,7 @@ LANGUAGE C STRICT;
 /*
  * Return tablespace name for specified relation.
  */
-CREATE OR REPLACE FUNCTION @extschema@.get_tablespace(
+CREATE FUNCTION @extschema@.get_tablespace(
 	relid	REGCLASS)
 RETURNS TEXT AS 'pg_pathman', 'get_tablespace_pl'
 LANGUAGE C STRICT;
@@ -741,7 +741,7 @@ LANGUAGE C STRICT;
 /*
  * Check that relation exists.
  */
-CREATE OR REPLACE FUNCTION @extschema@.validate_relname(
+CREATE FUNCTION @extschema@.validate_relname(
 	relid	REGCLASS)
 RETURNS VOID AS 'pg_pathman', 'validate_relname'
 LANGUAGE C;
@@ -749,7 +749,7 @@ LANGUAGE C;
 /*
  * Check that expression is valid
  */
-CREATE OR REPLACE FUNCTION @extschema@.validate_expression(
+CREATE FUNCTION @extschema@.validate_expression(
 	relid	REGCLASS,
 	expression TEXT)
 RETURNS VOID AS 'pg_pathman', 'validate_expression'
@@ -758,7 +758,7 @@ LANGUAGE C;
 /*
  * Check if regclass is date or timestamp.
  */
-CREATE OR REPLACE FUNCTION @extschema@.is_date_type(
+CREATE FUNCTION @extschema@.is_date_type(
 	typid	REGTYPE)
 RETURNS BOOLEAN AS 'pg_pathman', 'is_date_type'
 LANGUAGE C STRICT;
@@ -766,7 +766,7 @@ LANGUAGE C STRICT;
 /*
  * Check if TYPE supports the specified operator.
  */
-CREATE OR REPLACE FUNCTION @extschema@.is_operator_supported(
+CREATE FUNCTION @extschema@.is_operator_supported(
 	type_oid	REGTYPE,
 	opname		TEXT)
 RETURNS BOOLEAN AS 'pg_pathman', 'is_operator_supported'
@@ -775,7 +775,7 @@ LANGUAGE C STRICT;
 /*
  * Check if tuple from first relation can be converted to fit the second one.
  */
-CREATE OR REPLACE FUNCTION @extschema@.is_tuple_convertible(
+CREATE FUNCTION @extschema@.is_tuple_convertible(
 	relation1	REGCLASS,
 	relation2	REGCLASS)
 RETURNS BOOL AS 'pg_pathman', 'is_tuple_convertible'
@@ -785,7 +785,7 @@ LANGUAGE C STRICT;
 /*
  * Build check constraint name for a specified relation's column.
  */
-CREATE OR REPLACE FUNCTION @extschema@.build_check_constraint_name(
+CREATE FUNCTION @extschema@.build_check_constraint_name(
 	partition_relid	REGCLASS)
 RETURNS TEXT AS 'pg_pathman', 'build_check_constraint_name'
 LANGUAGE C STRICT;
@@ -793,7 +793,7 @@ LANGUAGE C STRICT;
 /*
  * Add record to pathman_config (RANGE) and validate partitions.
  */
-CREATE OR REPLACE FUNCTION @extschema@.add_to_pathman_config(
+CREATE FUNCTION @extschema@.add_to_pathman_config(
 	parent_relid	REGCLASS,
 	expression		TEXT,
 	range_interval	TEXT)
@@ -803,7 +803,7 @@ LANGUAGE C;
 /*
  * Add record to pathman_config (HASH) and validate partitions.
  */
-CREATE OR REPLACE FUNCTION @extschema@.add_to_pathman_config(
+CREATE FUNCTION @extschema@.add_to_pathman_config(
 	parent_relid	REGCLASS,
 	expression		TEXT)
 RETURNS BOOLEAN AS 'pg_pathman', 'add_to_pathman_config'
@@ -814,7 +814,7 @@ LANGUAGE C;
  * Lock partitioned relation to restrict concurrent
  * modification of partitioning scheme.
  */
-CREATE OR REPLACE FUNCTION @extschema@.prevent_part_modification(
+CREATE FUNCTION @extschema@.prevent_part_modification(
 	parent_relid	REGCLASS)
 RETURNS VOID AS 'pg_pathman', 'prevent_part_modification'
 LANGUAGE C STRICT;
@@ -822,7 +822,7 @@ LANGUAGE C STRICT;
 /*
  * Lock relation to restrict concurrent modification of data.
  */
-CREATE OR REPLACE FUNCTION @extschema@.prevent_data_modification(
+CREATE FUNCTION @extschema@.prevent_data_modification(
 	parent_relid	REGCLASS)
 RETURNS VOID AS 'pg_pathman', 'prevent_data_modification'
 LANGUAGE C STRICT;
@@ -831,7 +831,7 @@ LANGUAGE C STRICT;
 /*
  * Invoke init_callback on RANGE partition.
  */
-CREATE OR REPLACE FUNCTION @extschema@.invoke_on_partition_created_callback(
+CREATE FUNCTION @extschema@.invoke_on_partition_created_callback(
 	parent_relid	REGCLASS,
 	partition_relid	REGCLASS,
 	init_callback	REGPROCEDURE,
@@ -843,7 +843,7 @@ LANGUAGE C;
 /*
  * Invoke init_callback on HASH partition.
  */
-CREATE OR REPLACE FUNCTION @extschema@.invoke_on_partition_created_callback(
+CREATE FUNCTION @extschema@.invoke_on_partition_created_callback(
 	parent_relid	REGCLASS,
 	partition_relid	REGCLASS,
 	init_callback	REGPROCEDURE)
@@ -853,10 +853,10 @@ LANGUAGE C;
 /*
  * DEBUG: Place this inside some plpgsql fuction and set breakpoint.
  */
-CREATE OR REPLACE FUNCTION @extschema@.debug_capture()
+CREATE FUNCTION @extschema@.debug_capture()
 RETURNS VOID AS 'pg_pathman', 'debug_capture'
 LANGUAGE C STRICT;
 
-CREATE OR REPLACE FUNCTION @extschema@.pathman_version()
+CREATE FUNCTION @extschema@.pathman_version()
 RETURNS CSTRING AS 'pg_pathman', 'pathman_version'
 LANGUAGE C STRICT;
diff --git a/range.sql b/range.sql
index ef439cee..5af17014 100644
--- a/range.sql
+++ b/range.sql
@@ -3,7 +3,7 @@
  * range.sql
  *		RANGE partitioning functions
  *
- * Copyright (c) 2015-2016, Postgres Professional
+ * Copyright (c) 2015-2020, Postgres Professional
  *
  * ------------------------------------------------------------------------
  */
@@ -11,7 +11,7 @@
 /*
  * Check RANGE partition boundaries.
  */
-CREATE OR REPLACE FUNCTION @extschema@.check_boundaries(
+CREATE FUNCTION @extschema@.check_boundaries(
 	parent_relid	REGCLASS,
 	expression		TEXT,
 	start_value		ANYELEMENT,
@@ -24,7 +24,7 @@ DECLARE
 
 BEGIN
 	/* Get min and max values */
-	EXECUTE format('SELECT count(*), min(%1$s), max(%1$s)
+	EXECUTE pg_catalog.format('SELECT count(*), min(%1$s), max(%1$s)
 					FROM %2$s WHERE NOT %1$s IS NULL',
 				   expression, parent_relid::TEXT)
 	INTO rows_count, min_value, max_value;
@@ -49,7 +49,7 @@ $$ LANGUAGE plpgsql;
 /*
  * Creates RANGE partitions for specified relation based on datetime attribute
  */
-CREATE OR REPLACE FUNCTION @extschema@.create_range_partitions(
+CREATE FUNCTION @extschema@.create_range_partitions(
 	parent_relid	REGCLASS,
 	expression		TEXT,
 	start_value		ANYELEMENT,
@@ -76,7 +76,7 @@ BEGIN
 
 	/* Try to determine partitions count if not set */
 	IF p_count IS NULL THEN
-		EXECUTE format('SELECT count(*), max(%s) FROM %s', expression, parent_relid)
+		EXECUTE pg_catalog.format('SELECT count(*), max(%s) FROM %s', expression, parent_relid)
 		INTO rows_count, max_value;
 
 		IF rows_count = 0 THEN
@@ -142,7 +142,7 @@ $$ LANGUAGE plpgsql;
 /*
  * Creates RANGE partitions for specified relation based on numerical expression
  */
-CREATE OR REPLACE FUNCTION @extschema@.create_range_partitions(
+CREATE FUNCTION @extschema@.create_range_partitions(
 	parent_relid	REGCLASS,
 	expression		TEXT,
 	start_value		ANYELEMENT,
@@ -169,7 +169,7 @@ BEGIN
 
 	/* Try to determine partitions count if not set */
 	IF p_count IS NULL THEN
-		EXECUTE format('SELECT count(*), max(%s) FROM %s', expression, parent_relid)
+		EXECUTE pg_catalog.format('SELECT count(*), max(%s) FROM %s', expression, parent_relid)
 		INTO rows_count, max_value;
 
 		IF rows_count = 0 THEN
@@ -239,7 +239,7 @@ $$ LANGUAGE plpgsql;
 /*
  * Creates RANGE partitions for specified relation based on bounds array
  */
-CREATE OR REPLACE FUNCTION @extschema@.create_range_partitions(
+CREATE FUNCTION @extschema@.create_range_partitions(
 	parent_relid	REGCLASS,
 	expression		TEXT,
 	bounds			ANYARRAY,
@@ -297,7 +297,7 @@ LANGUAGE plpgsql;
 /*
  * Append new partition.
  */
-CREATE OR REPLACE FUNCTION @extschema@.append_range_partition(
+CREATE FUNCTION @extschema@.append_range_partition(
 	parent_relid	REGCLASS,
 	partition_name	TEXT DEFAULT NULL,
 	tablespace		TEXT DEFAULT NULL)
@@ -326,7 +326,7 @@ BEGIN
 	INTO part_interval;
 
 	EXECUTE
-		format('SELECT @extschema@.append_partition_internal($1, $2, $3, ARRAY[]::%s[], $4, $5)',
+		pg_catalog.format('SELECT @extschema@.append_partition_internal($1, $2, $3, ARRAY[]::%s[], $4, $5)',
 			   @extschema@.get_base_type(part_expr_type)::TEXT)
 	USING
 		parent_relid,
@@ -347,7 +347,7 @@ $$ LANGUAGE plpgsql;
  *
  * NOTE: we don't take a xact_handling lock here.
  */
-CREATE OR REPLACE FUNCTION @extschema@.append_partition_internal(
+CREATE FUNCTION @extschema@.append_partition_internal(
 	parent_relid	REGCLASS,
 	p_atttype		REGTYPE,
 	p_interval		TEXT,
@@ -368,7 +368,7 @@ BEGIN
 	part_expr_type := @extschema@.get_base_type(p_atttype);
 
 	/* We have to pass fake NULL casted to column's type */
-	EXECUTE format('SELECT @extschema@.get_part_range($1, -1, NULL::%s)',
+	EXECUTE pg_catalog.format('SELECT @extschema@.get_part_range($1, -1, NULL::%s)',
 				   part_expr_type::TEXT)
 	USING parent_relid
 	INTO p_range;
@@ -378,13 +378,13 @@ BEGIN
 	END IF;
 
 	IF @extschema@.is_date_type(p_atttype) THEN
-		v_args_format := format('$1, $2, ($2 + $3::interval)::%s, $4, $5', part_expr_type::TEXT);
+		v_args_format := pg_catalog.format('$1, $2, ($2 + $3::interval)::%s, $4, $5', part_expr_type::TEXT);
 	ELSE
-		v_args_format := format('$1, $2, $2 + $3::%s, $4, $5', part_expr_type::TEXT);
+		v_args_format := pg_catalog.format('$1, $2, $2 + $3::%s, $4, $5', part_expr_type::TEXT);
 	END IF;
 
 	EXECUTE
-		format('SELECT @extschema@.create_single_range_partition(%s)', v_args_format)
+		pg_catalog.format('SELECT @extschema@.create_single_range_partition(%s)', v_args_format)
 	USING
 		parent_relid,
 		p_range[2],
@@ -401,7 +401,7 @@ $$ LANGUAGE plpgsql;
 /*
  * Prepend new partition.
  */
-CREATE OR REPLACE FUNCTION @extschema@.prepend_range_partition(
+CREATE FUNCTION @extschema@.prepend_range_partition(
 	parent_relid	REGCLASS,
 	partition_name	TEXT DEFAULT NULL,
 	tablespace		TEXT DEFAULT NULL)
@@ -430,7 +430,7 @@ BEGIN
 	INTO part_interval;
 
 	EXECUTE
-		format('SELECT @extschema@.prepend_partition_internal($1, $2, $3, ARRAY[]::%s[], $4, $5)',
+		pg_catalog.format('SELECT @extschema@.prepend_partition_internal($1, $2, $3, ARRAY[]::%s[], $4, $5)',
 			   @extschema@.get_base_type(part_expr_type)::TEXT)
 	USING
 		parent_relid,
@@ -451,7 +451,7 @@ $$ LANGUAGE plpgsql;
  *
  * NOTE: we don't take a xact_handling lock here.
  */
-CREATE OR REPLACE FUNCTION @extschema@.prepend_partition_internal(
+CREATE FUNCTION @extschema@.prepend_partition_internal(
 	parent_relid	REGCLASS,
 	p_atttype		REGTYPE,
 	p_interval		TEXT,
@@ -472,7 +472,7 @@ BEGIN
 	part_expr_type := @extschema@.get_base_type(p_atttype);
 
 	/* We have to pass fake NULL casted to column's type */
-	EXECUTE format('SELECT @extschema@.get_part_range($1, 0, NULL::%s)',
+	EXECUTE pg_catalog.format('SELECT @extschema@.get_part_range($1, 0, NULL::%s)',
 				   part_expr_type::TEXT)
 	USING parent_relid
 	INTO p_range;
@@ -482,13 +482,13 @@ BEGIN
 	END IF;
 
 	IF @extschema@.is_date_type(p_atttype) THEN
-		v_args_format := format('$1, ($2 - $3::interval)::%s, $2, $4, $5', part_expr_type::TEXT);
+		v_args_format := pg_catalog.format('$1, ($2 - $3::interval)::%s, $2, $4, $5', part_expr_type::TEXT);
 	ELSE
-		v_args_format := format('$1, $2 - $3::%s, $2, $4, $5', part_expr_type::TEXT);
+		v_args_format := pg_catalog.format('$1, $2 - $3::%s, $2, $4, $5', part_expr_type::TEXT);
 	END IF;
 
 	EXECUTE
-		format('SELECT @extschema@.create_single_range_partition(%s)', v_args_format)
+		pg_catalog.format('SELECT @extschema@.create_single_range_partition(%s)', v_args_format)
 	USING
 		parent_relid,
 		p_range[1],
@@ -505,7 +505,7 @@ $$ LANGUAGE plpgsql;
 /*
  * Add new partition
  */
-CREATE OR REPLACE FUNCTION @extschema@.add_range_partition(
+CREATE FUNCTION @extschema@.add_range_partition(
 	parent_relid	REGCLASS,
 	start_value		ANYELEMENT,
 	end_value		ANYELEMENT,
@@ -547,7 +547,7 @@ $$ LANGUAGE plpgsql;
 /*
  * Drop range partition
  */
-CREATE OR REPLACE FUNCTION @extschema@.drop_range_partition(
+CREATE FUNCTION @extschema@.drop_range_partition(
 	partition_relid	REGCLASS,
 	delete_data		BOOLEAN DEFAULT TRUE)
 RETURNS TEXT AS $$
@@ -576,7 +576,7 @@ BEGIN
 	PERFORM @extschema@.prevent_part_modification(parent_relid);
 
 	IF NOT delete_data THEN
-		EXECUTE format('INSERT INTO %s SELECT * FROM %s',
+		EXECUTE pg_catalog.format('INSERT INTO %s SELECT * FROM %s',
 						parent_relid::TEXT,
 						partition_relid::TEXT);
 		GET DIAGNOSTICS v_rows = ROW_COUNT;
@@ -595,9 +595,9 @@ BEGIN
 	 * DROP TABLE or DROP FOREIGN TABLE.
 	 */
 	IF v_relkind = 'f' THEN
-		EXECUTE format('DROP FOREIGN TABLE %s', partition_relid::TEXT);
+		EXECUTE pg_catalog.format('DROP FOREIGN TABLE %s', partition_relid::TEXT);
 	ELSE
-		EXECUTE format('DROP TABLE %s', partition_relid::TEXT);
+		EXECUTE pg_catalog.format('DROP TABLE %s', partition_relid::TEXT);
 	END IF;
 
 	RETURN part_name;
@@ -608,7 +608,7 @@ SET pg_pathman.enable_partitionfilter = off; /* ensures that PartitionFilter is
 /*
  * Attach range partition
  */
-CREATE OR REPLACE FUNCTION @extschema@.attach_range_partition(
+CREATE FUNCTION @extschema@.attach_range_partition(
 	parent_relid	REGCLASS,
 	partition_relid	REGCLASS,
 	start_value		ANYELEMENT,
@@ -658,10 +658,10 @@ BEGIN
 	END IF;
 
 	/* Set inheritance */
-	EXECUTE format('ALTER TABLE %s INHERIT %s', partition_relid, parent_relid);
+	EXECUTE pg_catalog.format('ALTER TABLE %s INHERIT %s', partition_relid, parent_relid);
 
 	/* Set check constraint */
-	EXECUTE format('ALTER TABLE %s ADD CONSTRAINT %s CHECK (%s)',
+	EXECUTE pg_catalog.format('ALTER TABLE %s ADD CONSTRAINT %s CHECK (%s)',
 				   partition_relid::TEXT,
 				   @extschema@.build_check_constraint_name(partition_relid),
 				   @extschema@.build_range_condition(partition_relid,
@@ -691,7 +691,7 @@ $$ LANGUAGE plpgsql;
 /*
  * Detach range partition
  */
-CREATE OR REPLACE FUNCTION @extschema@.detach_range_partition(
+CREATE FUNCTION @extschema@.detach_range_partition(
 	partition_relid	REGCLASS)
 RETURNS TEXT AS $$
 DECLARE
@@ -718,12 +718,12 @@ BEGIN
 	END IF;
 
 	/* Remove inheritance */
-	EXECUTE format('ALTER TABLE %s NO INHERIT %s',
+	EXECUTE pg_catalog.format('ALTER TABLE %s NO INHERIT %s',
 				   partition_relid::TEXT,
 				   parent_relid::TEXT);
 
 	/* Remove check constraint */
-	EXECUTE format('ALTER TABLE %s DROP CONSTRAINT %s',
+	EXECUTE pg_catalog.format('ALTER TABLE %s DROP CONSTRAINT %s',
 				   partition_relid::TEXT,
 				   @extschema@.build_check_constraint_name(partition_relid));
 
@@ -735,7 +735,7 @@ $$ LANGUAGE plpgsql;
 /*
  * Create a naming sequence for partitioned table.
  */
-CREATE OR REPLACE FUNCTION @extschema@.create_naming_sequence(
+CREATE FUNCTION @extschema@.create_naming_sequence(
 	parent_relid	REGCLASS)
 RETURNS TEXT AS $$
 DECLARE
@@ -744,8 +744,8 @@ DECLARE
 BEGIN
 	seq_name := @extschema@.build_sequence_name(parent_relid);
 
-	EXECUTE format('DROP SEQUENCE IF EXISTS %s', seq_name);
-	EXECUTE format('CREATE SEQUENCE %s START 1', seq_name);
+	EXECUTE pg_catalog.format('DROP SEQUENCE IF EXISTS %s', seq_name);
+	EXECUTE pg_catalog.format('CREATE SEQUENCE %s START 1', seq_name);
 
 	RETURN seq_name;
 END
@@ -755,7 +755,7 @@ SET client_min_messages = WARNING; /* mute NOTICE message */
 /*
  * Drop a naming sequence for partitioned table.
  */
-CREATE OR REPLACE FUNCTION @extschema@.drop_naming_sequence(
+CREATE FUNCTION @extschema@.drop_naming_sequence(
 	parent_relid	REGCLASS)
 RETURNS VOID AS $$
 DECLARE
@@ -764,7 +764,7 @@ DECLARE
 BEGIN
 	seq_name := @extschema@.build_sequence_name(parent_relid);
 
-	EXECUTE format('DROP SEQUENCE IF EXISTS %s', seq_name);
+	EXECUTE pg_catalog.format('DROP SEQUENCE IF EXISTS %s', seq_name);
 END
 $$ LANGUAGE plpgsql
 SET client_min_messages = WARNING; /* mute NOTICE message */
@@ -773,7 +773,7 @@ SET client_min_messages = WARNING; /* mute NOTICE message */
 /*
  * Split RANGE partition in two using a pivot.
  */
-CREATE OR REPLACE FUNCTION @extschema@.split_range_partition(
+CREATE FUNCTION @extschema@.split_range_partition(
 	partition_relid	REGCLASS,
 	split_value		ANYELEMENT,
 	partition_name	TEXT DEFAULT NULL,
@@ -784,7 +784,7 @@ LANGUAGE C;
 /*
  * Merge RANGE partitions.
  */
-CREATE OR REPLACE FUNCTION @extschema@.merge_range_partitions(
+CREATE FUNCTION @extschema@.merge_range_partitions(
 	variadic partitions		REGCLASS[])
 RETURNS REGCLASS AS 'pg_pathman', 'merge_range_partitions'
 LANGUAGE C STRICT;
@@ -796,12 +796,12 @@ LANGUAGE C STRICT;
  * DROP PARTITION. In Oracle partitions only have upper bound and when
  * partition is dropped the next one automatically covers freed range
  */
-CREATE OR REPLACE FUNCTION @extschema@.drop_range_partition_expand_next(
+CREATE FUNCTION @extschema@.drop_range_partition_expand_next(
 	partition_relid		REGCLASS)
 RETURNS VOID AS 'pg_pathman', 'drop_range_partition_expand_next'
 LANGUAGE C STRICT;
 
-CREATE OR REPLACE FUNCTION @extschema@.create_range_partitions_internal(
+CREATE FUNCTION @extschema@.create_range_partitions_internal(
 	parent_relid	REGCLASS,
 	bounds			ANYARRAY,
 	partition_names	TEXT[],
@@ -813,7 +813,7 @@ LANGUAGE C;
  * Creates new RANGE partition. Returns partition name.
  * NOTE: This function SHOULD NOT take xact_handling lock (BGWs in 9.5).
  */
-CREATE OR REPLACE FUNCTION @extschema@.create_single_range_partition(
+CREATE FUNCTION @extschema@.create_single_range_partition(
 	parent_relid	REGCLASS,
 	start_value		ANYELEMENT,
 	end_value		ANYELEMENT,
@@ -825,7 +825,7 @@ LANGUAGE C;
 /*
  * Construct CHECK constraint condition for a range partition.
  */
-CREATE OR REPLACE FUNCTION @extschema@.build_range_condition(
+CREATE FUNCTION @extschema@.build_range_condition(
 	partition_relid	REGCLASS,
 	expression		TEXT,
 	start_value		ANYELEMENT,
@@ -836,7 +836,7 @@ LANGUAGE C;
 /*
  * Generate a name for naming sequence.
  */
-CREATE OR REPLACE FUNCTION @extschema@.build_sequence_name(
+CREATE FUNCTION @extschema@.build_sequence_name(
 	parent_relid	REGCLASS)
 RETURNS TEXT AS 'pg_pathman', 'build_sequence_name'
 LANGUAGE C STRICT;
@@ -844,7 +844,7 @@ LANGUAGE C STRICT;
 /*
  * Returns N-th range (as an array of two elements).
  */
-CREATE OR REPLACE FUNCTION @extschema@.get_part_range(
+CREATE FUNCTION @extschema@.get_part_range(
 	parent_relid	REGCLASS,
 	partition_idx	INTEGER,
 	dummy			ANYELEMENT)
@@ -854,7 +854,7 @@ LANGUAGE C;
 /*
  * Returns min and max values for specified RANGE partition.
  */
-CREATE OR REPLACE FUNCTION @extschema@.get_part_range(
+CREATE FUNCTION @extschema@.get_part_range(
 	partition_relid	REGCLASS,
 	dummy			ANYELEMENT)
 RETURNS ANYARRAY AS 'pg_pathman', 'get_part_range_by_oid'
@@ -864,7 +864,7 @@ LANGUAGE C;
  * Checks if range overlaps with existing partitions.
  * Returns TRUE if overlaps and FALSE otherwise.
  */
-CREATE OR REPLACE FUNCTION @extschema@.check_range_available(
+CREATE FUNCTION @extschema@.check_range_available(
 	parent_relid	REGCLASS,
 	range_min		ANYELEMENT,
 	range_max		ANYELEMENT)
@@ -874,14 +874,14 @@ LANGUAGE C;
 /*
  * Generate range bounds starting with 'p_start' using 'p_interval'.
  */
-CREATE OR REPLACE FUNCTION @extschema@.generate_range_bounds(
+CREATE FUNCTION @extschema@.generate_range_bounds(
 	p_start			ANYELEMENT,
 	p_interval		INTERVAL,
 	p_count			INTEGER)
 RETURNS ANYARRAY AS 'pg_pathman', 'generate_range_bounds_pl'
 LANGUAGE C STRICT;
 
-CREATE OR REPLACE FUNCTION @extschema@.generate_range_bounds(
+CREATE FUNCTION @extschema@.generate_range_bounds(
 	p_start			ANYELEMENT,
 	p_interval		ANYELEMENT,
 	p_count			INTEGER)
diff --git a/sql/pathman_CVE-2020-14350.sql b/sql/pathman_CVE-2020-14350.sql
new file mode 100644
index 00000000..877f3280
--- /dev/null
+++ b/sql/pathman_CVE-2020-14350.sql
@@ -0,0 +1,77 @@
+/*
+ * Check fix for CVE-2020-14350.
+ * See also 7eeb1d986 postgresql commit.
+ */
+
+SET client_min_messages = 'warning';
+DROP FUNCTION IF EXISTS _partition_data_concurrent(oid,integer);
+DROP FUNCTION IF EXISTS create_single_range_partition(TEXT,ANYELEMENT,ANYELEMENT,TEXT);
+DROP TABLE IF EXISTS test1 CASCADE;
+DROP TABLE IF EXISTS test2 CASCADE;
+DROP ROLE IF EXISTS regress_hacker;
+SET client_min_messages = 'notice';
+
+CREATE EXTENSION pg_pathman;
+CREATE ROLE regress_hacker LOGIN;
+
+-- Test 1
+RESET ROLE;
+ALTER ROLE regress_hacker NOSUPERUSER;
+
+SET ROLE regress_hacker;
+SHOW is_superuser;
+CREATE FUNCTION _partition_data_concurrent(relation oid, p_limit INT, OUT p_total BIGINT)
+RETURNS bigint
+AS $$
+BEGIN
+  ALTER ROLE regress_hacker SUPERUSER;
+  SELECT _partition_data_concurrent(relation, NULL::text, NULL::text, p_limit) INTO p_total;
+END
+$$ LANGUAGE plpgsql;
+
+CREATE TABLE test1(i INT4 NOT NULL);
+INSERT INTO test1 SELECT generate_series(1, 500);
+SELECT create_hash_partitions('test1', 'i', 5, false);
+
+RESET ROLE;
+SELECT partition_table_concurrently('test1', 10, 1);
+SELECT pg_sleep(1);
+
+-- Test result (must be 'off')
+SET ROLE regress_hacker;
+SHOW is_superuser;
+
+-- Test 2
+RESET ROLE;
+ALTER ROLE regress_hacker NOSUPERUSER;
+
+SET ROLE regress_hacker;
+SHOW is_superuser;
+CREATE FUNCTION create_single_range_partition(parent_relid TEXT, start_value ANYELEMENT, end_value ANYELEMENT, partition_name TEXT)
+RETURNS REGCLASS
+AS $$
+BEGIN
+  ALTER ROLE regress_hacker SUPERUSER;
+  RETURN create_single_range_partition(parent_relid, start_value, end_value, partition_name, NULL::text);
+END
+$$ LANGUAGE plpgsql;
+
+RESET ROLE;
+CREATE TABLE test2(i INT4 NOT NULL);
+INSERT INTO test2 VALUES(0);
+SELECT create_range_partitions('test2', 'i', 0, 1);
+INSERT INTO test2 values(1);
+
+-- Test result (must be 'off')
+SET ROLE regress_hacker;
+SHOW is_superuser;
+
+-- Cleanup
+RESET ROLE;
+DROP FUNCTION _partition_data_concurrent(oid,integer);
+DROP FUNCTION create_single_range_partition(TEXT,ANYELEMENT,ANYELEMENT,TEXT);
+DROP TABLE test1 CASCADE;
+DROP TABLE test2 CASCADE;
+DROP ROLE regress_hacker;
+DROP EXTENSION pg_pathman;
+
diff --git a/src/partition_creation.c b/src/partition_creation.c
index cd2a7b82..c86ba7aa 100644
--- a/src/partition_creation.c
+++ b/src/partition_creation.c
@@ -604,7 +604,7 @@ spawn_partitions_val(Oid parent_relid,				/* parent's Oid */
 
 		/* Construct call to create_single_range_partition() */
 		create_sql = psprintf(
-			"select %s.create_single_range_partition('%s.%s', '%s'::%s, '%s'::%s, '%s.%s')",
+			"select %s.create_single_range_partition('%s.%s'::regclass, '%s'::%s, '%s'::%s, '%s.%s', NULL::text)",
 			quote_identifier(get_namespace_name(get_pathman_schema())),
 			quote_identifier(parent_nsp_name),
 			quote_identifier(get_rel_name(parent_relid)),
diff --git a/src/pathman_workers.c b/src/pathman_workers.c
index 54d62e7f..a75e912b 100644
--- a/src/pathman_workers.c
+++ b/src/pathman_workers.c
@@ -523,7 +523,7 @@ bgw_main_concurrent_part(Datum main_arg)
 			 * context will be destroyed after transaction finishes
 			 */
 			current_mcxt = MemoryContextSwitchTo(TopPathmanContext);
-			sql = psprintf("SELECT %s._partition_data_concurrent($1::oid, p_limit:=$2)",
+			sql = psprintf("SELECT %s._partition_data_concurrent($1::regclass, NULL::text, NULL::text, p_limit:=$2)",
 						   get_namespace_name(get_pathman_schema()));
 			MemoryContextSwitchTo(current_mcxt);
 		}