diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py
index cf34ab735..91625bdeb 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py
@@ -1455,6 +1455,8 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
         else:
             FunctionView._merge_variables(data)
 
+        self._format_prosrc_for_pure_sql(data, False)
+
         if allow_code_formatting:
             self.reformat_prosrc_code(data)
 
@@ -1464,6 +1466,28 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
         )
         return True, '', sql
 
+    def _format_prosrc_for_pure_sql(self, data, view_only=True):
+
+        if self.manager.sversion < 139999:
+            return
+
+        # no need to test whether function/procedure definition is pure sql
+        # or not, the parameter from 'is_pure_sql' is sufficient.
+        if view_only:
+            if 'is_pure_sql' in data and data['is_pure_sql'] is True:
+                data['prosrc'] = data['prosrc_sql']
+                if data['prosrc'].endswith(';') is False:
+                    data['prosrc'] = ''.join((data['prosrc'], ';'))
+            else:
+                data['is_pure_sql'] = False
+        else:
+            # when function/procedure definition is changed, we need to find
+            # whether definition is of pure or have std sql definition.
+            if self._is_function_def_sql_standard(data):
+                data['is_pure_sql'] = True
+                if data['prosrc'].endswith(';') is False:
+                    data['prosrc'] = ''.join((data['prosrc'], ';'))
+
     def _get_sql(self, **kwargs):
         """
         Generates the SQL statements to create/update the Function.
@@ -1529,6 +1553,8 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
 
             data['func_args_without'] = ', '.join(args_without_name)
 
+            self._format_prosrc_for_pure_sql(data, False)
+
             if allow_code_formatting:
                 self.reformat_prosrc_code(data)
 
@@ -1610,6 +1636,8 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
             resp_data['provolatile'] = None
             resp_data['proparallel'] = None
 
+        self._format_prosrc_for_pure_sql(resp_data)
+
         return resp_data
 
     def _get_schema(self, scid):
@@ -1946,6 +1974,56 @@ class FunctionView(PGChildNodeView, DataTypeReader, SchemaDiffObjectCompare):
 
         return res
 
+    @staticmethod
+    def _is_function_def_sql_standard(resp_data):
+
+        """
+        This function is responsible for checking the sql to determine
+        whether it is as per SQL-standard or not. In fact, the function
+        is mainly utilised for the sql language with the newly added
+        ATOMIC in the version v14 of Postgres for functions & procedures
+        respectively.
+
+        :param resp_data:
+        :return: boolean
+        """
+        # if language is other than 'sql', return False
+        if 'lanname' in resp_data and resp_data['lanname'] != 'sql':
+            return False
+
+        # invalid regex, these combination should not be present in the sql
+        invalid_match = [r"^.*(?:\'|\")?.*(?=.*?atomic).*(?:\'|\").*$",
+                         r"^.*(?:\"|\')(?=.*(atomic)).*$"]
+
+        # valid regex, these combination a must in definition to detect a
+        # standard sql or pure sql
+        valid_match = [
+            r"(?=.*begin)(.+?(\n)+)(?=.*atomic)|(?=.*begin)(?=.*atomic)",
+            r"(?=return)"
+        ]
+
+        is_func_def_sql_std = False
+
+        if 'prosrc' in resp_data and resp_data['prosrc'] is not None \
+                and resp_data['prosrc'] != '':
+
+            prosrc = str(resp_data['prosrc']).lower().strip('\n').strip('\t')
+
+            for invalid in invalid_match:
+                for match in enumerate(
+                        re.finditer(invalid, prosrc, re.MULTILINE), start=1):
+                    if match:
+                        return is_func_def_sql_std
+
+            for valid in valid_match:
+                for match in enumerate(
+                        re.finditer(valid, prosrc, re.MULTILINE), start=1):
+                    if match:
+                        is_func_def_sql_std = True
+                        return is_func_def_sql_std
+
+        return is_func_def_sql_std
+
 
 SchemaDiffRegistry(blueprint.node_type, FunctionView)
 FunctionView.register_node_view(blueprint)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/14_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/14_plus/create.sql
new file mode 100644
index 000000000..4f4dbc76b
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/14_plus/create.sql
@@ -0,0 +1,76 @@
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}
+{% set is_columns = [] %}
+{% set exclude_quoting = ['search_path'] %}
+{% if data %}
+{% if query_for == 'sql_panel' and func_def is defined %}
+CREATE{% if query_type is defined %}{{' OR REPLACE'}}{% endif %} FUNCTION {{func_def}}
+{% else %}
+CREATE{% if query_type is defined %}{{' OR REPLACE'}}{% endif %} FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({% if data.arguments %}
+{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname) }} {% endif %}{% if p.argtype %}{{ p.argtype }}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %}
+{% if not loop.last %}, {% endif %}
+{% endfor %}
+{% endif -%}
+)
+{% endif %}
+    RETURNS{% if data.proretset and (data.prorettypename.startswith('SETOF ') or data.prorettypename.startswith('TABLE')) %} {{ data.prorettypename }} {% elif data.proretset %} SETOF {{ data.prorettypename }}{% else %} {{ data.prorettypename }}{% endif %}
+
+    LANGUAGE {{ data.lanname|qtLiteral }}
+{% if data.procost %}
+    COST {{data.procost}}
+{% endif %}
+    {% if data.provolatile %}{% if data.provolatile == 'i' %}IMMUTABLE{% elif data.provolatile == 's' %}STABLE{% else %}VOLATILE{% endif %} {% endif %}{% if data.proleakproof %}LEAKPROOF {% endif %}
+{% if data.proisstrict %}STRICT {% endif %}
+{% if data.prosecdef %}SECURITY DEFINER {% endif %}
+{% if data.proiswindow %}WINDOW {% endif %}
+{% if data.proparallel and (data.proparallel == 'r' or data.proparallel == 's' or data.proparallel == 'u') %}
+{% if data.proparallel == 'r' %}PARALLEL RESTRICTED {% elif data.proparallel == 's' %}PARALLEL SAFE {% elif data.proparallel == 'u' %}PARALLEL UNSAFE{% endif %}{% endif %}
+{% if data.prorows and (data.prorows | int) > 0 %}
+
+    ROWS {{data.prorows}}
+{% endif %}
+{% if data.prosupportfunc %}
+    SUPPORT {{ data.prosupportfunc }}
+{% endif -%}
+{% if data.variables %}{% for v in data.variables %}
+
+    SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor %}
+{% endif %}
+
+{% if data.is_pure_sql %}{{ data.prosrc }}
+{% else %}
+AS {% if data.lanname == 'c' %}
+{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
+{% else %}
+$BODY${{ data.prosrc }}$BODY${% endif -%};
+{% endif -%}
+{% if data.funcowner %}
+
+ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args_without}})
+    OWNER TO {{ conn|qtIdent(data.funcowner) }};
+{% endif -%}
+{% if data.acl %}
+{% for p in data.acl %}
+
+{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args_without)}}
+{% endfor %}{% endif %}
+{% if data.revoke_all %}
+
+{{ PRIVILEGE.UNSETALL(conn, "FUNCTION", "PUBLIC", data.name, data.pronamespace, data.func_args_without)}}
+{% endif %}
+{% if data.description %}
+
+COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args_without}})
+    IS {{ data.description|qtLiteral  }};
+{% endif -%}
+{% if data.seclabels %}
+{% for r in data.seclabels %}
+{% if r.label and r.provider %}
+
+{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.label, data.pronamespace, data.func_args_without) }}
+{% endif %}
+{% endfor %}
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/14_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/14_plus/properties.sql
new file mode 100644
index 000000000..782b94385
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/14_plus/properties.sql
@@ -0,0 +1,45 @@
+SELECT
+    pr.oid, pr.xmin,
+    CASE WHEN pr.prokind = 'w' THEN true ELSE false END AS proiswindow,
+    pr.prosrc, pr.prosrc AS prosrc_c, pr.pronamespace, pr.prolang, pr.procost, pr.prorows, pr.prokind,
+    pr.prosecdef, pr.proleakproof, pr.proisstrict, pr.proretset, pr.provolatile, pr.proparallel,
+    pr.pronargs, pr.prorettype, pr.proallargtypes, pr.proargmodes, pr.probin, pr.proacl,
+    pr.proname, pr.proname AS name, pg_catalog.pg_get_function_result(pr.oid) AS prorettypename,
+    typns.nspname AS typnsp, lanname, proargnames, pg_catalog.oidvectortypes(proargtypes) AS proargtypenames,
+    pg_catalog.pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
+    pg_catalog.pg_get_function_sqlbody(pr.oid) AS prosrc_sql,
+    CASE WHEN pr.prosqlbody IS NOT NULL THEN true ELSE false END as is_pure_sql,
+    pr.pronargdefaults, proconfig, pg_catalog.pg_get_userbyid(proowner) AS funcowner, description,
+    CASE WHEN prosupport = 0::oid THEN ''
+    ELSE (
+        SELECT pg_catalog.quote_ident(nspname) || '.' || pg_catalog.quote_ident(proname) AS tfunctions
+          FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n
+              WHERE p.pronamespace = n.oid
+              AND p.oid = pr.prosupport::OID
+    ) END AS prosupportfunc,
+    (SELECT
+        pg_catalog.array_agg(provider || '=' || label)
+    FROM
+        pg_catalog.pg_seclabel sl1
+    WHERE
+        sl1.objoid=pr.oid) AS seclabels
+FROM
+    pg_catalog.pg_proc pr
+JOIN
+    pg_catalog.pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_catalog.pg_namespace typns ON typns.oid=typ.typnamespace
+JOIN
+    pg_catalog.pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_catalog.pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass and des.objsubid = 0)
+WHERE
+    pr.prokind IN ('f', 'w')
+    AND typname NOT IN ('trigger', 'event_trigger')
+{% if fnid %}
+    AND pr.oid = {{fnid}}::oid
+{% else %}
+    AND pronamespace = {{scid}}::oid
+{% endif %}
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/14_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/14_plus/update.sql
new file mode 100644
index 000000000..433fc6577
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/pg/sql/14_plus/update.sql
@@ -0,0 +1,127 @@
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %}
+{% set name = o_data.name %}
+{% set exclude_quoting = ['search_path'] %}
+{% if data.name %}
+{% if data.name != o_data.name %}
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{
+o_data.proargtypenames }})
+    RENAME TO {{ conn|qtIdent(data.name) }};
+{% set name = data.name %}
+{% endif %}
+{% endif -%}
+{% if data.change_func  %}
+
+CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if data.arguments %}
+{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname) }} {% endif %}{% if p.argtype %}{{ p.argtype }}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %}
+{% if not loop.last %},{% endif %}
+{% endfor %}
+{% endif -%}
+)
+    RETURNS {% if 'prorettypename' in data %}{{ data.prorettypename }}{% else %}{{ o_data.prorettypename }}{% endif %}
+
+{% if 'lanname' in data %}
+    LANGUAGE {{ data.lanname|qtLiteral }} {% else %}
+    LANGUAGE {{ o_data.lanname|qtLiteral }}
+    {% endif %}{% if 'provolatile' in data and data.provolatile %}{{ data.provolatile }} {% elif 'provolatile' not in data and o_data.provolatile %}{{ o_data.provolatile }}{% endif %}
+{% if ('proleakproof' in data and data.proleakproof) or ('proleakproof' not in data and o_data.proleakproof) %} LEAKPROOF{% elif 'proleakproof' in data and not data.proleakproof %} NOT LEAKPROOF{% endif %}
+{% if ('proisstrict' in data and data.proisstrict) or ('proisstrict' not in data and o_data.proisstrict) %} STRICT{% endif %}
+{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %}
+{% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %}
+
+    {% if 'proparallel' in data and data.proparallel %}PARALLEL {{ data.proparallel }}{% elif 'proparallel' not in data and o_data.proparallel %}PARALLEL {{ o_data.proparallel }}{% endif %}
+
+    {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows and data.prorows != '0' %}
+
+    ROWS {{data.prorows}}{% elif data.prorows is not defined and o_data.prorows and o_data.prorows != '0' %}    ROWS {{o_data.prorows}} {%endif %}
+
+    {% if data.prosupportfunc %}SUPPORT {{ data.prosupportfunc }}{% elif data.prosupportfunc is not defined and o_data.prosupportfunc %}SUPPORT {{ o_data.prosupportfunc }}{% endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %}
+
+    SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%}
+    {% endif %}
+
+{% if data.is_pure_sql %}{{ data.prosrc }}
+{% else %}
+AS {% if (data.lanname == 'c' or o_data.lanname == 'c') and ('probin' in data or 'prosrc_c' in data) %}
+{% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %}
+$BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %}
+{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %}
+$BODY${{ o_data.prosrc }}$BODY${% endif -%};
+{% endif -%}
+{% endif -%}
+{% if data.funcowner %}
+
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
+    OWNER TO {{ conn|qtIdent(data.funcowner) }};
+{% endif -%}
+{# The SQL generated below will change priviledges #}
+{% if data.acl %}
+{% if 'deleted' in data.acl %}
+{% for priv in data.acl.deleted %}
+
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'changed' in data.acl %}
+{% for priv in data.acl.changed %}
+
+{% if priv.grantee != priv.old_grantee %}
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.old_grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{% else %}
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{% endif %}
+
+{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'added' in data.acl %}
+{% for priv in data.acl.added %}
+
+{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}{% endif -%}
+{% endif -%}
+{% if data.change_func == False %}
+{% if data.variables %}
+{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %}
+
+{{ VARIABLE.UNSET(conn, 'FUNCTION', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames) }}
+{% endif -%}
+{% if 'merged_variables' in data and data.merged_variables|length > 0 %}
+
+{{ VARIABLE.SET(conn, 'FUNCTION', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames) }}
+{% endif -%}
+{% endif -%}
+{% endif -%}
+{% set seclabels = data.seclabels %}
+{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+{% for r in seclabels.deleted %}
+
+{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+
+{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.label, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+
+{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.label, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if data.description is defined and data.description != o_data.description%}
+
+COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
+    IS {{ data.description|qtLiteral }};
+{% endif -%}
+
+{% if data.pronamespace %}
+
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
+    SET SCHEMA {{ conn|qtIdent(data.pronamespace) }};
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/14_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/14_plus/create.sql
new file mode 100644
index 000000000..4f4dbc76b
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/14_plus/create.sql
@@ -0,0 +1,76 @@
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}
+{% set is_columns = [] %}
+{% set exclude_quoting = ['search_path'] %}
+{% if data %}
+{% if query_for == 'sql_panel' and func_def is defined %}
+CREATE{% if query_type is defined %}{{' OR REPLACE'}}{% endif %} FUNCTION {{func_def}}
+{% else %}
+CREATE{% if query_type is defined %}{{' OR REPLACE'}}{% endif %} FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({% if data.arguments %}
+{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname) }} {% endif %}{% if p.argtype %}{{ p.argtype }}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %}
+{% if not loop.last %}, {% endif %}
+{% endfor %}
+{% endif -%}
+)
+{% endif %}
+    RETURNS{% if data.proretset and (data.prorettypename.startswith('SETOF ') or data.prorettypename.startswith('TABLE')) %} {{ data.prorettypename }} {% elif data.proretset %} SETOF {{ data.prorettypename }}{% else %} {{ data.prorettypename }}{% endif %}
+
+    LANGUAGE {{ data.lanname|qtLiteral }}
+{% if data.procost %}
+    COST {{data.procost}}
+{% endif %}
+    {% if data.provolatile %}{% if data.provolatile == 'i' %}IMMUTABLE{% elif data.provolatile == 's' %}STABLE{% else %}VOLATILE{% endif %} {% endif %}{% if data.proleakproof %}LEAKPROOF {% endif %}
+{% if data.proisstrict %}STRICT {% endif %}
+{% if data.prosecdef %}SECURITY DEFINER {% endif %}
+{% if data.proiswindow %}WINDOW {% endif %}
+{% if data.proparallel and (data.proparallel == 'r' or data.proparallel == 's' or data.proparallel == 'u') %}
+{% if data.proparallel == 'r' %}PARALLEL RESTRICTED {% elif data.proparallel == 's' %}PARALLEL SAFE {% elif data.proparallel == 'u' %}PARALLEL UNSAFE{% endif %}{% endif %}
+{% if data.prorows and (data.prorows | int) > 0 %}
+
+    ROWS {{data.prorows}}
+{% endif %}
+{% if data.prosupportfunc %}
+    SUPPORT {{ data.prosupportfunc }}
+{% endif -%}
+{% if data.variables %}{% for v in data.variables %}
+
+    SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor %}
+{% endif %}
+
+{% if data.is_pure_sql %}{{ data.prosrc }}
+{% else %}
+AS {% if data.lanname == 'c' %}
+{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
+{% else %}
+$BODY${{ data.prosrc }}$BODY${% endif -%};
+{% endif -%}
+{% if data.funcowner %}
+
+ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args_without}})
+    OWNER TO {{ conn|qtIdent(data.funcowner) }};
+{% endif -%}
+{% if data.acl %}
+{% for p in data.acl %}
+
+{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args_without)}}
+{% endfor %}{% endif %}
+{% if data.revoke_all %}
+
+{{ PRIVILEGE.UNSETALL(conn, "FUNCTION", "PUBLIC", data.name, data.pronamespace, data.func_args_without)}}
+{% endif %}
+{% if data.description %}
+
+COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args_without}})
+    IS {{ data.description|qtLiteral  }};
+{% endif -%}
+{% if data.seclabels %}
+{% for r in data.seclabels %}
+{% if r.label and r.provider %}
+
+{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.label, data.pronamespace, data.func_args_without) }}
+{% endif %}
+{% endfor %}
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/14_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/14_plus/properties.sql
new file mode 100644
index 000000000..4576d25f8
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/14_plus/properties.sql
@@ -0,0 +1,39 @@
+SELECT
+    pr.oid, pr.xmin,
+    CASE WHEN pr.prokind = 'w' THEN true ELSE false END AS proiswindow,
+    pr.prosrc, pr.prosrc AS prosrc_c, pr.pronamespace, pr.prolang, pr.procost, pr.prorows, pr.prokind,
+    pr.prosecdef, pr.proleakproof, pr.proisstrict, pr.proretset, pr.provolatile, pr.proparallel,
+    pr.pronargs, pr.prorettype, pr.proallargtypes, pr.proargmodes, pr.probin, pr.proacl,
+    pr.proname, pr.proname AS name, pg_catalog.pg_get_function_result(pr.oid) AS prorettypename,
+    typns.nspname AS typnsp, lanname, proargnames, pg_catalog.oidvectortypes(proargtypes) AS proargtypenames,
+    pg_catalog.pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
+    pr.pronargdefaults, proconfig, pg_catalog.pg_get_userbyid(proowner) AS funcowner, description,
+    pg_catalog.pg_get_function_sqlbody(pr.oid) AS prosrc_sql,
+    CASE WHEN pr.prosqlbody IS NOT NULL THEN true ELSE false END as is_pure_sql,
+    CASE WHEN prosupport = 0::oid THEN '' ELSE prosupport::text END AS prosupportfunc,
+    (SELECT
+        pg_catalog.array_agg(provider || '=' || label)
+    FROM
+        pg_catalog.pg_seclabel sl1
+    WHERE
+        sl1.objoid=pr.oid) AS seclabels
+FROM
+    pg_catalog.pg_proc pr
+JOIN
+    pg_catalog.pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_catalog.pg_namespace typns ON typns.oid=typ.typnamespace
+JOIN
+    pg_catalog.pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_catalog.pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass and des.objsubid = 0)
+WHERE
+    pr.prokind IN ('f', 'w')
+    AND typname NOT IN ('trigger', 'event_trigger')
+{% if fnid %}
+    AND pr.oid = {{fnid}}::oid
+{% else %}
+    AND pronamespace = {{scid}}::oid
+{% endif %}
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/14_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/14_plus/update.sql
new file mode 100644
index 000000000..433fc6577
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/functions/ppas/sql/14_plus/update.sql
@@ -0,0 +1,127 @@
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %}
+{% set name = o_data.name %}
+{% set exclude_quoting = ['search_path'] %}
+{% if data.name %}
+{% if data.name != o_data.name %}
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{
+o_data.proargtypenames }})
+    RENAME TO {{ conn|qtIdent(data.name) }};
+{% set name = data.name %}
+{% endif %}
+{% endif -%}
+{% if data.change_func  %}
+
+CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({% if data.arguments %}
+{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname) }} {% endif %}{% if p.argtype %}{{ p.argtype }}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %}
+{% if not loop.last %},{% endif %}
+{% endfor %}
+{% endif -%}
+)
+    RETURNS {% if 'prorettypename' in data %}{{ data.prorettypename }}{% else %}{{ o_data.prorettypename }}{% endif %}
+
+{% if 'lanname' in data %}
+    LANGUAGE {{ data.lanname|qtLiteral }} {% else %}
+    LANGUAGE {{ o_data.lanname|qtLiteral }}
+    {% endif %}{% if 'provolatile' in data and data.provolatile %}{{ data.provolatile }} {% elif 'provolatile' not in data and o_data.provolatile %}{{ o_data.provolatile }}{% endif %}
+{% if ('proleakproof' in data and data.proleakproof) or ('proleakproof' not in data and o_data.proleakproof) %} LEAKPROOF{% elif 'proleakproof' in data and not data.proleakproof %} NOT LEAKPROOF{% endif %}
+{% if ('proisstrict' in data and data.proisstrict) or ('proisstrict' not in data and o_data.proisstrict) %} STRICT{% endif %}
+{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %}
+{% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %}
+
+    {% if 'proparallel' in data and data.proparallel %}PARALLEL {{ data.proparallel }}{% elif 'proparallel' not in data and o_data.proparallel %}PARALLEL {{ o_data.proparallel }}{% endif %}
+
+    {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows and data.prorows != '0' %}
+
+    ROWS {{data.prorows}}{% elif data.prorows is not defined and o_data.prorows and o_data.prorows != '0' %}    ROWS {{o_data.prorows}} {%endif %}
+
+    {% if data.prosupportfunc %}SUPPORT {{ data.prosupportfunc }}{% elif data.prosupportfunc is not defined and o_data.prosupportfunc %}SUPPORT {{ o_data.prosupportfunc }}{% endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %}
+
+    SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%}
+    {% endif %}
+
+{% if data.is_pure_sql %}{{ data.prosrc }}
+{% else %}
+AS {% if (data.lanname == 'c' or o_data.lanname == 'c') and ('probin' in data or 'prosrc_c' in data) %}
+{% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %}
+$BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %}
+{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %}
+$BODY${{ o_data.prosrc }}$BODY${% endif -%};
+{% endif -%}
+{% endif -%}
+{% if data.funcowner %}
+
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
+    OWNER TO {{ conn|qtIdent(data.funcowner) }};
+{% endif -%}
+{# The SQL generated below will change priviledges #}
+{% if data.acl %}
+{% if 'deleted' in data.acl %}
+{% for priv in data.acl.deleted %}
+
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'changed' in data.acl %}
+{% for priv in data.acl.changed %}
+
+{% if priv.grantee != priv.old_grantee %}
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.old_grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{% else %}
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{% endif %}
+
+{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'added' in data.acl %}
+{% for priv in data.acl.added %}
+
+{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}{% endif -%}
+{% endif -%}
+{% if data.change_func == False %}
+{% if data.variables %}
+{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %}
+
+{{ VARIABLE.UNSET(conn, 'FUNCTION', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames) }}
+{% endif -%}
+{% if 'merged_variables' in data and data.merged_variables|length > 0 %}
+
+{{ VARIABLE.SET(conn, 'FUNCTION', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames) }}
+{% endif -%}
+{% endif -%}
+{% endif -%}
+{% set seclabels = data.seclabels %}
+{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+{% for r in seclabels.deleted %}
+
+{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+
+{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.label, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+
+{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.label, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if data.description is defined and data.description != o_data.description%}
+
+COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
+    IS {{ data.description|qtLiteral }};
+{% endif -%}
+
+{% if data.pronamespace %}
+
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
+    SET SCHEMA {{ conn|qtIdent(data.pronamespace) }};
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/pg/sql/14_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/pg/sql/14_plus/create.sql
new file mode 100644
index 000000000..4441ef54c
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/pg/sql/14_plus/create.sql
@@ -0,0 +1,55 @@
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}
+{% set is_columns = [] %}
+{% set exclude_quoting = ['search_path'] %}
+{% if data %}
+{% if query_for == 'sql_panel' and func_def is defined %}
+CREATE OR REPLACE PROCEDURE {{func_def}}
+{% else %}
+CREATE{% if add_replace_clause %} OR REPLACE{% endif %} PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }}{% if data.arguments is defined %}
+({% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname)}} {% endif %}{% if p.argtype %}{{ p.argtype }}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %}
+{% if not loop.last %}, {% endif %}
+{% endfor -%}
+{% endif %}
+)
+{% endif %}
+LANGUAGE {{ data.lanname|qtLiteral }}{% if data.prosecdef %}
+
+    SECURITY DEFINER {% endif %}
+{% if data.variables %}{% for v in data.variables %}
+
+    SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%}
+{% endif %}
+
+{% if data.is_pure_sql %}{{ data.prosrc }}
+{% else %}
+AS {% if data.lanname == 'c' %}
+{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
+{% else %}
+$BODY${{ data.prosrc }}$BODY${% endif -%};
+{% endif -%}
+{% if data.acl and not is_sql %}
+{% for p in data.acl %}
+
+{{ PRIVILEGE.SET(conn, "PROCEDURE", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args_without)}}
+{% endfor %}{% endif %}
+{% if data.revoke_all %}
+
+{{ PRIVILEGE.UNSETALL(conn, "PROCEDURE", "PUBLIC", data.name, data.pronamespace, data.func_args_without)}}
+{% endif %}
+{% if data.description %}
+
+COMMENT ON PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args_without}})
+    IS {{ data.description|qtLiteral  }};
+{% endif -%}
+{% if data.seclabels %}
+{% for r in data.seclabels %}
+{% if r.label and r.provider %}
+
+{{ SECLABEL.SET(conn, 'PROCEDURE', data.name, r.provider, r.label, data.pronamespace, data.func_args_without) }}
+{% endif %}
+{% endfor %}
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/pg/sql/14_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/pg/sql/14_plus/properties.sql
new file mode 100644
index 000000000..4dad586d5
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/pg/sql/14_plus/properties.sql
@@ -0,0 +1,49 @@
+SELECT
+    pr.oid, pr.xmin,
+    CASE WHEN pr.prokind = 'w' THEN true ELSE false END AS proiswindow,
+    pr.prosrc, pr.prosrc AS prosrc_c, pr.pronamespace, pr.prolang, pr.procost, pr.prorows, pr.prokind,
+    pr.prosecdef, pr.proleakproof, pr.proisstrict, pr.proretset, pr.provolatile, pr.proparallel,
+    pr.pronargs, pr.prorettype, pr.proallargtypes, pr.proargmodes, pr.probin, pr.proacl,
+    pr.proname, pr.proname AS name, pg_catalog.pg_get_function_result(pr.oid) AS prorettypename,
+    typns.nspname AS typnsp, lanname, proargnames, pg_catalog.oidvectortypes(proargtypes) AS proargtypenames,
+    pg_catalog.pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
+    pg_catalog.pg_get_function_sqlbody(pr.oid) AS prosrc_sql,
+    CASE WHEN pr.prosqlbody IS NOT NULL THEN true ELSE false END as is_pure_sql,
+    pr.pronargdefaults, proconfig, pg_catalog.pg_get_userbyid(proowner) AS funcowner, description,
+    (
+        WITH name_with_args_tab AS (SELECT pg_catalog.pg_get_function_identity_arguments(pr.oid) AS val)
+        SELECT CASE WHEN
+            val <> ''
+        THEN
+            pr.proname || '(' || val || ')'
+        ELSE
+            pr.proname::text
+        END
+        FROM name_with_args_tab
+    ) AS name_with_args,
+    (SELECT
+        pg_catalog.array_agg(provider || '=' || label)
+    FROM
+        pg_catalog.pg_seclabel sl1
+    WHERE
+        sl1.objoid=pr.oid) AS seclabels
+FROM
+    pg_catalog.pg_proc pr
+JOIN
+    pg_catalog.pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_catalog.pg_namespace typns ON typns.oid=typ.typnamespace
+JOIN
+    pg_catalog.pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_catalog.pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass and des.objsubid = 0)
+WHERE
+    pr.prokind = 'p'
+    AND typname NOT IN ('trigger', 'event_trigger')
+{% if fnid %}
+    AND pr.oid = {{fnid}}::oid
+{% else %}
+    AND pronamespace = {{scid}}::oid
+{% endif %}
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/pg/sql/14_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/pg/sql/14_plus/update.sql
new file mode 100644
index 000000000..a5f907dc8
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/pg/sql/14_plus/update.sql
@@ -0,0 +1,114 @@
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %}
+{% set name = o_data.name %}
+{% set exclude_quoting = ['search_path'] %}
+{% if data.name %}
+{% if data.name != o_data.name %}
+ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %}
+
+    RENAME TO {{ conn|qtIdent(data.name) }};
+{% set name = data.name %}
+{% endif %}
+
+{% endif -%}
+{% if data.change_func  %}
+CREATE OR REPLACE PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}({% if data.arguments %}{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname) }} {% endif %}{% if p.argtype %}{{ p.argtype }}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %}
+{% if not loop.last %}, {% endif %}
+{% endfor %}
+{% endif %}
+)
+{% if 'lanname' in data %}
+    LANGUAGE {{ data.lanname|qtLiteral }} {% else %}
+    LANGUAGE {{ o_data.lanname|qtLiteral }}
+    {% endif %}
+{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %}SECURITY DEFINER{% endif %}
+{% if data.merged_variables %}{% for v in data.merged_variables %}
+
+    SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%}
+{% endif %}
+
+{% if data.is_pure_sql %}{{ data.prosrc }}{% else %}
+AS {% if (data.lanname == 'c' or o_data.lanname == 'c') and ('probin' in data or 'prosrc_c' in data) %}
+{% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %}
+$BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %}
+{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %}
+$BODY${{ o_data.prosrc }}$BODY${% endif -%};
+{% endif -%}
+{% endif -%}
+{% if data.funcowner %}
+
+ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %}
+    OWNER TO {{ conn|qtIdent(data.funcowner) }};
+{% endif -%}
+{# The SQL generated below will change priviledges #}
+{% if data.acl %}
+{% if 'deleted' in data.acl %}
+{% for priv in data.acl.deleted %}
+
+{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'changed' in data.acl %}
+{% for priv in data.acl.changed %}
+
+{% if priv.grantee != priv.old_grantee %}
+{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.old_grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{% else %}
+{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{% endif %}
+
+{{ PRIVILEGE.SET(conn, 'PROCEDURE', priv.grantee, name, priv.without_grant,
+ priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'added' in data.acl %}
+{% for priv in data.acl.added %}
+
+{{ PRIVILEGE.SET(conn, 'PROCEDURE', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif %}
+{% endif -%}
+{% if data.change_func == False %}
+{% if data.variables %}
+{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %}
+
+{{ VARIABLE.UNSET(conn, 'PROCEDURE', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames) }}
+{% endif -%}
+{% if 'merged_variables' in data and data.merged_variables|length > 0 %}
+
+{{ VARIABLE.SET(conn, 'PROCEDURE', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames) }}
+{% endif -%}
+{% endif -%}
+{% endif -%}
+{% set seclabels = data.seclabels %}
+{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+{% for r in seclabels.deleted %}
+
+{{ SECLABEL.UNSET(conn, 'PROCEDURE', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+
+{{ SECLABEL.SET(conn, 'PROCEDURE', name, r.provider, r.label, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+
+{{ SECLABEL.SET(conn, 'PROCEDURE', name, r.provider, r.label, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if data.description is defined and data.description != o_data.description%}
+
+COMMENT ON PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
+    IS {{ data.description|qtLiteral }};
+{% endif -%}
+{% if data.pronamespace %}
+
+ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}
+    SET SCHEMA {{ conn|qtIdent(data.pronamespace) }};
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/ppas/sql/14_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/ppas/sql/14_plus/create.sql
new file mode 100644
index 000000000..8aef2b230
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/ppas/sql/14_plus/create.sql
@@ -0,0 +1,63 @@
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}
+{% set is_columns = [] %}
+{% set exclude_quoting = ['search_path'] %}
+{% if data %}
+{% if query_for == 'sql_panel' and func_def is defined %}
+CREATE OR REPLACE PROCEDURE {{func_def}}
+{% else %}
+CREATE{% if add_replace_clause %} OR REPLACE{% endif %} PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }}{% if data.arguments is defined %}
+({% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname)}} {% endif %}{% if p.argtype %}{{ p.argtype }}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %}
+{% if not loop.last %}, {% endif %}
+{% endfor -%}
+{% endif %}
+)
+{% endif %}
+LANGUAGE {{ data.lanname|qtLiteral }}{% if data.prosecdef %}
+
+    SECURITY DEFINER {% endif %}
+{% if data.lanname == 'edbspl' %}
+{% if data.provolatile %}{% if data.provolatile == 'i' %}IMMUTABLE{% elif data.provolatile == 's' %}STABLE{% else %}VOLATILE{% endif %} {% endif %}{% if data.proleakproof %}LEAKPROOF {% endif %}
+{% if data.proisstrict %}STRICT {% endif %}
+{% if data.proparallel and (data.proparallel == 'r' or data.proparallel == 's' or data.proparallel == 'u') %}
+{% if data.proparallel == 'r' %}PARALLEL RESTRICTED{% elif data.proparallel == 's' %}PARALLEL SAFE{% elif data.proparallel == 'u' %}PARALLEL UNSAFE{% endif %} {% endif %}{% if data.procost %}
+
+    COST {{data.procost}}{% endif %}{% if data.prorows and (data.prorows | int) > 0 %}
+
+    ROWS {{data.prorows}}{% endif -%}{% endif %}{% if data.variables %}{% for v in data.variables %}
+
+    SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%}
+{% endif %}
+
+{% if data.is_pure_sql %}{{ data.prosrc }}
+{% else %}
+AS {% if data.lanname == 'c' %}
+{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
+{% else %}
+$BODY${{ data.prosrc }}$BODY${% endif -%};
+{% endif -%}
+{% if data.acl and not is_sql %}
+{% for p in data.acl %}
+
+{{ PRIVILEGE.SET(conn, "PROCEDURE", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args_without)}}
+{% endfor %}{% endif %}
+{% if data.revoke_all %}
+
+{{ PRIVILEGE.UNSETALL(conn, "PROCEDURE", "PUBLIC", data.name, data.pronamespace, data.func_args_without)}}
+{% endif %}
+{% if data.description %}
+
+COMMENT ON PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args_without}})
+    IS {{ data.description|qtLiteral  }};
+{% endif -%}
+{% if data.seclabels %}
+{% for r in data.seclabels %}
+{% if r.label and r.provider %}
+
+{{ SECLABEL.SET(conn, 'PROCEDURE', data.name, r.provider, r.label, data.pronamespace, data.func_args_without) }}
+{% endif %}
+{% endfor %}
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/ppas/sql/14_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/ppas/sql/14_plus/properties.sql
new file mode 100644
index 000000000..a1a81dcf5
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/ppas/sql/14_plus/properties.sql
@@ -0,0 +1,49 @@
+SELECT
+    pr.oid, pr.xmin,
+    CASE WHEN pr.prokind = 'w' THEN true ELSE false END AS proiswindow,
+    pr.prosrc, pr.prosrc AS prosrc_c, pr.pronamespace, pr.prolang, pr.procost, pr.prorows, pr.prokind,
+    pr.prosecdef, pr.proleakproof, pr.proisstrict, pr.proretset, pr.provolatile, pr.proparallel,
+    pr.pronargs, pr.prorettype, pr.proallargtypes, pr.proargmodes, pr.probin, pr.proacl,
+    pr.proname, pr.proname AS name, pg_catalog.pg_get_function_result(pr.oid) AS prorettypename,
+    typns.nspname AS typnsp, lanname, proargnames, pg_catalog.oidvectortypes(proargtypes) AS proargtypenames,
+    pg_catalog.pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
+    pr.pronargdefaults, proconfig, pg_catalog.pg_get_userbyid(proowner) AS funcowner, description,
+    pg_catalog.pg_get_function_sqlbody(pr.oid) AS prosrc_sql,
+    CASE WHEN pr.prosqlbody IS NOT NULL THEN true ELSE false END as is_pure_sql,
+    (
+        WITH name_with_args_tab AS (SELECT pg_catalog.pg_get_function_identity_arguments(pr.oid) AS val)
+        SELECT CASE WHEN
+            val <> ''
+        THEN
+            pr.proname || '(' || val || ')'
+        ELSE
+            pr.proname::text
+        END
+        FROM name_with_args_tab
+    ) AS name_with_args,
+    (SELECT
+        pg_catalog.array_agg(provider || '=' || label)
+    FROM
+        pg_catalog.pg_seclabel sl1
+    WHERE
+        sl1.objoid=pr.oid) AS seclabels
+FROM
+    pg_catalog.pg_proc pr
+JOIN
+    pg_catalog.pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_catalog.pg_namespace typns ON typns.oid=typ.typnamespace
+JOIN
+    pg_catalog.pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_catalog.pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass and des.objsubid = 0)
+WHERE
+    pr.prokind = 'p'::char
+    AND typname NOT IN ('trigger', 'event_trigger')
+{% if fnid %}
+    AND pr.oid = {{fnid}}::oid
+{% else %}
+    AND pronamespace = {{scid}}::oid
+{% endif %}
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/ppas/sql/14_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/ppas/sql/14_plus/update.sql
new file mode 100644
index 000000000..6b2f589a6
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedures/ppas/sql/14_plus/update.sql
@@ -0,0 +1,124 @@
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %}
+{% set name = o_data.name %}
+{% set exclude_quoting = ['search_path'] %}
+{% if data.name %}
+{% if data.name != o_data.name %}
+ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %}
+
+    RENAME TO {{ conn|qtIdent(data.name) }};
+{% set name = data.name %}
+{% endif %}
+
+{% endif -%}
+{% if data.change_func  %}
+CREATE OR REPLACE PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}({% if data.arguments %}{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname) }} {% endif %}{% if p.argtype %}{{ p.argtype }}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %}
+{% if not loop.last %}, {% endif %}
+{% endfor %}
+{% endif %}
+)
+{% if 'lanname' in data %}
+    LANGUAGE {{ data.lanname|qtLiteral }} {% else %}
+    LANGUAGE {{ o_data.lanname|qtLiteral }}
+    {% endif %}
+{% if 'provolatile' in data and data.provolatile %}{{ data.provolatile }} {% elif 'provolatile' not in data and o_data.provolatile %}{{ o_data.provolatile }} {% endif %}
+{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %}SECURITY DEFINER{% endif %}
+{% if data.lanname == 'edbspl' or (o_data.lanname == 'edbspl' and not 'lanname' in data ) %}
+{% if ('proleakproof' in data and data.proleakproof) or ('proleakproof' not in data and o_data.proleakproof) %} LEAKPROOF{% else %} NOT LEAKPROOF{% endif %}
+    {% if ('proisstrict' in data and data.proisstrict) or ('proisstrict' not in data and o_data.proisstrict) %} STRICT{% endif %}
+
+    {% if 'proparallel' in data and data.proparallel %}PARALLEL {{ data.proparallel }}{% elif 'proparallel' not in data and o_data.proparallel %}PARALLEL {{ o_data.proparallel }}{% endif %}
+
+    {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %}
+
+    ROWS {{data.prorows}}{% elif data.prorows is not defined and o_data.prorows and o_data.prorows != '0' %}    ROWS {{o_data.prorows}}{% endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %}
+
+    SET {{ conn|qtIdent(v.name) }}={% if v.name in exclude_quoting %}{{ v.value }}{% else %}{{ v.value|qtLiteral }}{% endif %}{% endfor -%}
+{% endif %}
+{% endif %}
+
+{% if data.is_pure_sql %}{{ data.prosrc }}
+{% else %}
+AS {% if (data.lanname == 'c' or o_data.lanname == 'c') and ('probin' in data or 'prosrc_c' in data) %}
+{% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %}
+$BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %}
+{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %}
+$BODY${{ o_data.prosrc }}$BODY${% endif -%};
+{% endif -%}
+{% endif -%}
+{% if data.funcowner %}
+
+ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %}
+    OWNER TO {{ conn|qtIdent(data.funcowner) }};
+{% endif -%}
+{# The SQL generated below will change priviledges #}
+{% if data.acl %}
+{% if 'deleted' in data.acl %}
+{% for priv in data.acl.deleted %}
+
+{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'changed' in data.acl %}
+{% for priv in data.acl.changed %}
+
+{% if priv.grantee != priv.old_grantee %}
+{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.old_grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{% else %}
+{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{% endif %}
+
+{{ PRIVILEGE.SET(conn, 'PROCEDURE', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'added' in data.acl %}
+{% for priv in data.acl.added %}
+
+{{ PRIVILEGE.SET(conn, 'PROCEDURE', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif %}
+{% endif -%}
+{% if data.change_func == False %}
+{% if data.variables %}
+{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %}
+
+{{ VARIABLE.UNSET(conn, 'PROCEDURE', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames) }}
+{% endif -%}
+{% if 'merged_variables' in data and data.merged_variables|length > 0 %}
+
+{{ VARIABLE.SET(conn, 'PROCEDURE', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames) }}
+{% endif -%}
+{% endif -%}
+{% endif -%}
+{% set seclabels = data.seclabels %}
+{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+{% for r in seclabels.deleted %}
+
+{{ SECLABEL.UNSET(conn, 'PROCEDURE', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+
+{{ SECLABEL.SET(conn, 'PROCEDURE', name, r.provider, r.label, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+
+{{ SECLABEL.SET(conn, 'PROCEDURE', name, r.provider, r.label, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if data.description is defined and data.description != o_data.description%}
+
+COMMENT ON PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
+    IS {{ data.description|qtLiteral }};
+{% endif -%}
+{% if data.pronamespace %}
+
+ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}
+    SET SCHEMA {{ conn|qtIdent(data.pronamespace) }};
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/create_atomic_func.msql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/create_atomic_func.msql
new file mode 100644
index 000000000..13a004949
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/create_atomic_func.msql
@@ -0,0 +1,12 @@
+CREATE FUNCTION public."Function4_$%{}[]()&*^!@""'`\/#"()
+    RETURNS numeric
+    LANGUAGE 'sql'
+    COST 100
+    VOLATILE LEAKPROOF STRICT SECURITY DEFINER WINDOW PARALLEL UNSAFE
+
+begin atomic
+    select 1;
+end;
+
+ALTER FUNCTION public."Function4_$%{}[]()&*^!@""'`\/#"()
+    OWNER TO postgres;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/create_atomic_func.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/create_atomic_func.sql
new file mode 100644
index 000000000..175b4b6aa
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/create_atomic_func.sql
@@ -0,0 +1,17 @@
+-- FUNCTION: public.Function4_$%{}[]()&*^!@"'`\/#()
+
+-- DROP FUNCTION IF EXISTS public."Function4_$%{}[]()&*^!@""'`\/#"();
+
+CREATE OR REPLACE FUNCTION public."Function4_$%{}[]()&*^!@""'`\/#"(
+	)
+    RETURNS numeric
+    LANGUAGE 'sql'
+    COST 100
+    VOLATILE LEAKPROOF STRICT SECURITY DEFINER WINDOW PARALLEL UNSAFE
+
+BEGIN ATOMIC
+ SELECT 1;
+END;
+
+ALTER FUNCTION public."Function4_$%{}[]()&*^!@""'`\/#"()
+    OWNER TO postgres;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/create_atomic_proc.msql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/create_atomic_proc.msql
new file mode 100644
index 000000000..6d6399cb5
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/create_atomic_proc.msql
@@ -0,0 +1,10 @@
+CREATE PROCEDURE public."Proc3_$%{}[]()&*^!@"'`\/#"()
+LANGUAGE 'sql'
+    SET application_name='demo'
+
+begin atomic
+select 1;
+end;
+
+COMMENT ON PROCEDURE public."Proc3_$%{}[]()&*^!@"'`\/#"()
+    IS 'demo comments';
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/create_atomic_proc.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/create_atomic_proc.sql
new file mode 100644
index 000000000..2d2c176c4
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/create_atomic_proc.sql
@@ -0,0 +1,15 @@
+-- PROCEDURE: public.Proc3_$%{}[]()&*^!@"'`\/#()
+
+-- DROP PROCEDURE IF EXISTS public."Proc3_$%{}[]()&*^!@""'`\/#"();
+
+CREATE OR REPLACE PROCEDURE public."Proc3_$%{}[]()&*^!@""'`\/#"(
+	)
+LANGUAGE 'sql'
+    SET application_name='demo'
+
+BEGIN ATOMIC
+ SELECT 1;
+END;
+
+COMMENT ON PROCEDURE public."Proc3_$%{}[]()&*^!@""'`\/#"()
+    IS 'demo comments';
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/test_function.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/test_function.json
index 9ff8bb6b6..4d1f216b5 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/test_function.json
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/test_function.json
@@ -300,6 +300,46 @@
       "expected_sql_file": "alter_function_delete_acl.sql",
       "expected_msql_file": "alter_function_delete_acl.msql"
     },
+    {
+      "type": "delete",
+      "name": "Drop function",
+      "endpoint": "NODE-function.delete_id",
+      "data": {
+      }
+    },
+    {
+      "type": "create",
+      "endpoint": "NODE-function.obj",
+      "msql_endpoint": "NODE-function.msql",
+      "sql_endpoint": "NODE-function.sql_id",
+      "name": "Create function (atomic).",
+      "store_object_id": "True",
+      "data": {
+        "name": "Function4_$%{}[]()&*^!@\"'`\\/#",
+        "funcowner": "postgres",
+        "pronamespace": 2200,
+        "prorettypename": "numeric",
+        "lanname": "sql",
+        "prorows": 0,
+        "arguments": [],
+        "prosrc": "begin atomic\n    select 1;\nend",
+        "probin": "$libdir/",
+        "options": [],
+        "variables": [],
+        "seclabels": [],
+        "prosecdef":true,
+        "acl": [],
+        "provolatile":"v",
+        "proisstrict":true,
+        "proiswindow":true,
+        "proparallel":"u",
+        "procost":"100",
+        "proleakproof":true,
+        "schema": "public"
+      },
+      "expected_sql_file": "create_atomic_func.sql",
+      "expected_msql_file": "create_atomic_func.msql"
+    },
     {
       "type": "delete",
       "name": "Drop function",
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/test_procedures.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/test_procedures.json
index cf0996aab..00c37d4e1 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/test_procedures.json
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/pg/14_plus/test_procedures.json
@@ -131,6 +131,42 @@
       "expected_sql_file": "alter_proc_change_grantee_priv.sql",
       "expected_msql_file": "alter_proc_change_grantee_priv.msql"
     },
+    {
+      "type": "delete",
+      "name": "Drop procedure",
+      "endpoint": "NODE-procedure.delete_id",
+      "data": {
+      }
+    },
+    {
+      "type": "create",
+      "name": "Create procedure (atomic)",
+      "endpoint": "NODE-procedure.obj",
+      "sql_endpoint": "NODE-procedure.sql_id",
+      "data": {
+        "name":"Proc3_$%{}[]()&*^!@\"'`\\/#",
+        "funcowner":"postgres",
+        "pronamespace":2200,
+        "description":"demo comments",
+        "lanname":"sql",
+        "provolatile":null,
+        "proisstrict":false,
+        "proparallel":null,
+        "procost":null,
+        "prorows":0,
+        "proleakproof":false,
+        "arguments":[],
+        "prosrc":"begin atomic\nselect 1;\nend",
+        "probin":"$libdir/",
+        "options":[],
+        "seclabels":[],
+        "acl":[],
+        "schema": "public",
+        "variables":[{"name":"application_name","value":"demo"}]
+      },
+      "expected_sql_file": "create_atomic_proc.sql",
+      "expected_msql_file": "create_atomic_proc.msql"
+    },
     {
       "type": "delete",
       "name": "Drop procedure",
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/create_atomic_func.msql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/create_atomic_func.msql
new file mode 100644
index 000000000..9adb935cb
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/create_atomic_func.msql
@@ -0,0 +1,12 @@
+CREATE FUNCTION public."Function4_$%{}[]()&*^!@""'`\/#"()
+    RETURNS numeric
+    LANGUAGE 'sql'
+    COST 100
+    VOLATILE LEAKPROOF STRICT SECURITY DEFINER WINDOW PARALLEL UNSAFE
+
+begin atomic
+    select 1;
+end;
+
+ALTER FUNCTION public."Function4_$%{}[]()&*^!@""'`\/#"()
+    OWNER TO enterprisedb;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/create_atomic_func.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/create_atomic_func.sql
new file mode 100644
index 000000000..bf017e28e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/create_atomic_func.sql
@@ -0,0 +1,17 @@
+-- FUNCTION: public.Function4_$%{}[]()&*^!@"'`\/#()
+
+-- DROP FUNCTION IF EXISTS public."Function4_$%{}[]()&*^!@""'`\/#"();
+
+CREATE OR REPLACE FUNCTION public."Function4_$%{}[]()&*^!@""'`\/#"(
+	)
+    RETURNS numeric
+    LANGUAGE 'sql'
+    COST 100
+    VOLATILE LEAKPROOF STRICT SECURITY DEFINER WINDOW PARALLEL UNSAFE
+
+BEGIN ATOMIC
+ SELECT 1;
+END;
+
+ALTER FUNCTION public."Function4_$%{}[]()&*^!@""'`\/#"()
+    OWNER TO enterprisedb;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/create_atomic_proc.msql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/create_atomic_proc.msql
new file mode 100644
index 000000000..6d6399cb5
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/create_atomic_proc.msql
@@ -0,0 +1,10 @@
+CREATE PROCEDURE public."Proc3_$%{}[]()&*^!@"'`\/#"()
+LANGUAGE 'sql'
+    SET application_name='demo'
+
+begin atomic
+select 1;
+end;
+
+COMMENT ON PROCEDURE public."Proc3_$%{}[]()&*^!@"'`\/#"()
+    IS 'demo comments';
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/create_atomic_proc.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/create_atomic_proc.sql
new file mode 100644
index 000000000..2d2c176c4
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/create_atomic_proc.sql
@@ -0,0 +1,15 @@
+-- PROCEDURE: public.Proc3_$%{}[]()&*^!@"'`\/#()
+
+-- DROP PROCEDURE IF EXISTS public."Proc3_$%{}[]()&*^!@""'`\/#"();
+
+CREATE OR REPLACE PROCEDURE public."Proc3_$%{}[]()&*^!@""'`\/#"(
+	)
+LANGUAGE 'sql'
+    SET application_name='demo'
+
+BEGIN ATOMIC
+ SELECT 1;
+END;
+
+COMMENT ON PROCEDURE public."Proc3_$%{}[]()&*^!@""'`\/#"()
+    IS 'demo comments';
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/test_function.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/test_function.json
index 22bf13586..1798b0431 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/test_function.json
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/test_function.json
@@ -312,6 +312,46 @@
       "expected_sql_file": "alter_function_delete_acl.sql",
       "expected_msql_file": "alter_function_delete_acl.msql"
     },
+    {
+      "type": "delete",
+      "name": "Drop function",
+      "endpoint": "NODE-function.delete_id",
+      "data": {
+      }
+    },
+    {
+      "type": "create",
+      "endpoint": "NODE-function.obj",
+      "msql_endpoint": "NODE-function.msql",
+      "sql_endpoint": "NODE-function.sql_id",
+      "name": "Create function (atomic).",
+      "store_object_id": "True",
+      "data": {
+        "name": "Function4_$%{}[]()&*^!@\"'`\\/#",
+        "funcowner": "enterprisedb",
+        "pronamespace": 2200,
+        "prorettypename": "numeric",
+        "lanname": "sql",
+        "prorows": 0,
+        "arguments": [],
+        "prosrc": "begin atomic\n    select 1;\nend",
+        "probin": "$libdir/",
+        "options": [],
+        "variables": [],
+        "seclabels": [],
+        "prosecdef":true,
+        "acl": [],
+        "provolatile":"v",
+        "proisstrict":true,
+        "proiswindow":true,
+        "proparallel":"u",
+        "procost":"100",
+        "proleakproof":true,
+        "schema": "public"
+      },
+      "expected_sql_file": "create_atomic_func.sql",
+      "expected_msql_file": "create_atomic_func.msql"
+    },
     {
       "type": "delete",
       "name": "Drop function",
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/test_procedures.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/test_procedures.json
index ed8de0427..708d1d80e 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/test_procedures.json
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/tests/ppas/14_plus/test_procedures.json
@@ -131,6 +131,42 @@
       "expected_sql_file": "alter_proc_change_grantee_priv.sql",
       "expected_msql_file": "alter_proc_change_grantee_priv.msql"
     },
+    {
+      "type": "delete",
+      "name": "Drop procedure",
+      "endpoint": "NODE-procedure.delete_id",
+      "data": {
+      }
+    },
+    {
+      "type": "create",
+      "name": "Create procedure (atomic)",
+      "endpoint": "NODE-procedure.obj",
+      "sql_endpoint": "NODE-procedure.sql_id",
+      "data": {
+        "name":"Proc3_$%{}[]()&*^!@\"'`\\/#",
+        "funcowner":"enterprisedb",
+        "pronamespace":2200,
+        "description":"demo comments",
+        "lanname":"sql",
+        "provolatile":null,
+        "proisstrict":false,
+        "proparallel":null,
+        "procost":null,
+        "prorows":0,
+        "proleakproof":false,
+        "arguments":[],
+        "prosrc":"begin atomic\nselect 1;\nend",
+        "probin":"$libdir/",
+        "options":[],
+        "seclabels":[],
+        "acl":[],
+        "schema": "public",
+        "variables":[{"name":"application_name","value":"demo"}]
+      },
+      "expected_sql_file": "create_atomic_proc.sql",
+      "expected_msql_file": "create_atomic_proc.msql"
+    },
     {
       "type": "delete",
       "name": "Drop procedure",
