Subject: [pgAdmin4][Patch]: Functions/Procedures Module

From: Khushboo Vashi <[email-masked]>
Date: Fri, 11 Mar 2016 15:04:55 +0530

Hi,

Please find attached patch for the Functions/Procedures Module.

To test this patch, "Unique collection Control and Variable Control Fixes"
Patch submitted by me needs to be applied first.

Thanks,
Khushboo
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
new file mode 100644
index 0000000..d76af66
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py
@@ -0,0 +1,1266 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+"""Implements Functions/Procedures Node."""
+
+import json
+import sys
+import traceback
+import copy
+import re
+from flask import render_template, make_response, request, jsonify, \
+    current_app, url_for
+from flask.ext.babel import gettext
+from functools import wraps
+from pgadmin.utils.ajax import make_json_response, \
+    make_response as ajax_response, internal_server_error
+from pgadmin.browser.utils import PGChildNodeView
+from pgadmin.browser.collection import CollectionNodeModule
+import pgadmin.browser.server_groups.servers.databases.schemas as schemas
+from pgadmin.utils.ajax import precondition_required
+from pgadmin.utils.driver import get_driver
+from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
+    parse_priv_to_db
+from pgadmin.browser.server_groups.servers.databases.schemas.utils import \
+    SchemaChildModule
+from config import PG_DEFAULT_DRIVER
+from pgadmin.browser.server_groups.servers.databases.utils import \
+    parse_sec_labels_from_db, parse_variables_from_db
+
+
+class FunctionModule(SchemaChildModule):
+    """
+    class FunctionModule(SchemaChildModule):
+
+        This class represents The Functions Module.
+
+    Methods:
+    -------
+    * __init__(*args, **kwargs)
+      - Initialize the Functions Module.
+
+    * get_nodes(gid, sid, did, scid)
+      - Generate the Functions collection node.
+
+    * node_inode():
+      - Returns Functions node as leaf node.
+
+    * script_load()
+      - Load the module script for Functions, when schema node is
+        initialized.
+
+    * csssnippets()
+      - Returns a snippet of css.
+    """
+
+    NODE_TYPE = 'function'
+    COLLECTION_LABEL = gettext("Functions")
+
+    def __init__(self, *args, **kwargs):
+        """
+        Initialize the Function Module.
+        Args:
+            *args:
+            **kwargs:
+        """
+        super(FunctionModule, self).__init__(*args, **kwargs)
+
+        self.min_ver = 90100
+        self.max_ver = None
+        self.server_type = None
+
+    def get_nodes(self, gid, sid, did, scid):
+        """
+        Generate Functions collection node.
+        """
+        yield self.generate_browser_collection_node(scid)
+
+    @property
+    def node_inode(self):
+        """
+        Make the node as leaf node.
+        Returns:
+            False as this node doesn't have child nodes.
+        """
+        return False
+
+    @property
+    def script_load(self):
+        """
+        Load the module script for Functions, when the
+        schema node is initialized.
+        """
+        return schemas.SchemaModule.NODE_TYPE
+
+    @property
+    def csssnippets(self):
+        """
+        Returns a snippet of css
+        """
+        snippets = [
+            render_template("function/css/function.css")
+        ]
+        snippets.extend(
+            super(SchemaChildModule, self).csssnippets
+        )
+
+        return snippets
+
+blueprint = FunctionModule(__name__)
+
+
+class FunctionView(PGChildNodeView):
+    """
+    class FunctionView(PGChildNodeView)
+
+    This class inherits PGChildNodeView to get the different routes for
+    the module.
+
+    The class is responsible to Create, Read, Update and Delete operations for
+    the Functions.
+
+    Methods:
+    -------
+    * validate_request(f):
+      - Works as a decorator.
+        Validating request on the request of create, update and modified SQL.
+
+    * module_js():
+      - Overrides this property to define javascript for Functions node.
+
+    * check_precondition(f):
+      - Works as a decorator.
+      - Checks database connection status.
+      - Attach connection object and template path.
+
+    * list(gid, sid, did, scid):
+      - List the Functions.
+
+    * nodes(gid, sid, did, scid):
+      - Returns all the Functions to generate Nodes in the browser.
+
+    * properties(gid, sid, did, scid, fnid):
+      - Returns the Functions properties.
+
+    * create(gid, sid, did, scid):
+      - Creates a new Functions object.
+
+    * update(gid, sid, did, scid, fnid):
+      - Updates the Functions object.
+
+    * delete(gid, sid, did, scid, fnid):
+      - Drops the Functions object.
+
+    * sql(gid, sid, did, scid, fnid):
+      - Returns the SQL for the Functions object.
+
+    * msql(gid, sid, did, scid, fnid=None):
+      - Returns the modified SQL.
+
+    * dependents(gid, sid, did, scid, fnid):
+      - Returns the dependents for the Functions object.
+
+    * dependencies(gid, sid, did, scid, fnid):
+      - Returns the dependencies for the Functions object.
+
+    * get_languages(gid, sid, did, scid, fnid=None):
+      - Returns languages.
+
+    * get_types(gid, sid, did, scid, fnid=None):
+      - Returns Data Types.
+    """
+
+    node_type = blueprint.node_type
+
+    parent_ids = [
+        {'type': 'int', 'id': 'gid'},
+        {'type': 'int', 'id': 'sid'},
+        {'type': 'int', 'id': 'did'},
+        {'type': 'int', 'id': 'scid'}
+    ]
+    ids = [
+        {'type': 'int', 'id': 'fnid'}
+    ]
+
+    operations = dict({
+        'obj': [
+            {'get': 'properties', 'delete': 'delete', 'put': 'update'},
+            {'get': 'list', 'post': 'create'}
+        ],
+        'delete': [{'delete': 'delete'}],
+        'children': [{'get': 'children'}],
+        'nodes': [{'get': 'node'}, {'get': 'nodes'}],
+        'sql': [{'get': 'sql'}],
+        'msql': [{'get': 'msql'}, {'get': 'msql'}],
+        'stats': [{'get': 'statistics'}],
+        'dependency': [{'get': 'dependencies'}],
+        'dependent': [{'get': 'dependents'}],
+        'module.js': [{}, {}, {'get': 'module_js'}],
+        'get_types': [{'get': 'get_types'}, {'get': 'get_types'}],
+        'get_languages': [{'get': 'get_languages'}, {'get': 'get_languages'}],
+        'vopts': [{}, {'get': 'variable_options'}]
+    })
+
+    @property
+    def required_args(self):
+        """
+        Returns Required arguments for functions node.
+        Where
+            Required Args:
+                name:           Name of the Function
+                funcowner:      Function Owner
+                pronamespace:   Function Namespace
+                prorettypename: Function Return Type
+                lanname:        Function Language Name
+                prosrc:         Function Code
+                probin:         Function Object File
+        """
+        return [
+            'name',
+            'funcowner',
+            'pronamespace',
+            'prorettypename',
+            'lanname',
+            'prosrc',
+            'probin'
+        ]
+
+    def validate_request(f):
+        """
+        Works as a decorator.
+        Validating request on the request of create, update and modified SQL.
+        """
+
+        @wraps(f)
+        def wrap(self, **kwargs):
+
+            data = {}
+            if request.data:
+                req = json.loads(request.data)
+            else:
+                req = request.args or request.form
+
+            if 'fnid' not in kwargs:
+
+                for arg in self.required_args:
+                    if (arg not in req or req[arg] == '') or\
+                            (arg == 'probin' and req['lanname'] == 'c'
+                             and (arg not in req or req[arg] == '')):
+                        return make_json_response(
+                            status=410,
+                            success=0,
+                            errormsg=gettext(
+                                "Couldn't find the required parameter \
+                                (%s)." % arg
+                            )
+                        )
+
+            try:
+                list_params = []
+                if request.method == 'GET':
+                    list_params = ['arguments', 'variables', 'proacl',
+                                   'seclabels', 'acl']
+
+                for key in req:
+                    if key in list_params and req[key] != '' \
+                            and req[key] is not None:
+                        # Coverts string into python list as expected.
+                        data[key] = json.loads(req[key])
+                    elif (
+                            key == 'proretset' or key == 'proisstrict' or
+                            key == 'prosecdef' or key == 'proiswindow' or
+                            key == 'proleakproof'
+                    ):
+                        data[key] = True if (
+                            req[key] == 'true' or req[key] is True)\
+                            else False if (req[key] == 'false' or
+                                           req[key] is False) else ''
+                    else:
+                        data[key] = req[key]
+
+            except Exception as e:
+                return internal_server_error(errormsg=str(e))
+
+            self.request = data
+            return f(self, **kwargs)
+
+        return wrap
+
+    def module_js(self):
+        """
+        Load JS file (functions.js) for this module.
+        """
+
+        return make_response(
+            render_template(
+                "function/js/functions.js",
+                _=gettext
+            ),
+            200, {'Content-Type': 'application/x-javascript'}
+        )
+
+    def check_precondition(f):
+        """
+        Works as a decorator.
+        Checks the database connection status.
+        Attaches the connection object and template path to the class object.
+        """
+
+        @wraps(f)
+        def wrap(*args, **kwargs):
+            self = args[0]
+            driver = get_driver(PG_DEFAULT_DRIVER)
+            self.manager = driver.connection_manager(kwargs['sid'])
+
+            # Get database connection
+            self.conn = self.manager.connection(did=kwargs['did'])
+
+            self.qtIdent = driver.qtIdent
+            self.qtLiteral = driver.qtLiteral
+
+            if not self.conn.connected():
+                return precondition_required(
+                    gettext(
+                        "Connection to the server has been lost!"
+                    )
+                )
+
+            ver = self.manager.version
+
+            # Set template path for sql scripts depending
+            # on the server version.
+            self.template_path = "/".join([
+                self.node_type
+            ])
+            self.sql_template_path = "/".join([
+                self.template_path,
+                self.manager.server_type,
+                'sql',
+                '9.5_plus' if ver >= 90500 else
+                '9.2_plus' if ver >= 90200 else
+                '9.1_plus'
+                ])
+
+            return f(*args, **kwargs)
+
+        return wrap
+
+    @check_precondition
+    def list(self, gid, sid, did, scid):
+        """
+        List all the Functions.
+
+        Args:
+            gid: Server Group Id
+            sid: Server Id
+            did: Database Id
+            scid: Schema Id
+        """
+
+        SQL = render_template("/".join([self.sql_template_path, 'node.sql']),
+                              scid=scid)
+        status, res = self.conn.execute_dict(SQL)
+
+        if not status:
+            return internal_server_error(errormsg=res)
+        return ajax_response(
+            response=res['rows'],
+            status=200
+        )
+
+    @check_precondition
+    def nodes(self, gid, sid, did, scid):
+        """
+        Returns all the Functions to generate the Nodes.
+
+        Args:
+            gid: Server Group Id
+            sid: Server Id
+            did: Database Id
+            scid: Schema Id
+        """
+
+        res = []
+        SQL = render_template("/".join([self.sql_template_path,
+                                        'node.sql']), scid=scid)
+        status, rset = self.conn.execute_2darray(SQL)
+
+        if not status:
+            return internal_server_error(errormsg=rset)
+
+        for row in rset['rows']:
+            res.append(
+                self.blueprint.generate_browser_node(
+                    row['oid'],
+                    scid,
+                    row['name'],
+                    icon="icon-" + self.node_type,
+                    funcowner=row['funcowner'],
+                    language=row['lanname']
+                ))
+
+        return make_json_response(
+            data=res,
+            status=200
+        )
+
+    @check_precondition
+    def properties(self, gid, sid, did, scid, fnid=None):
+        """
+        Returns the Function properties.
+
+        Args:
+            gid: Server Group Id
+            sid: Server Id
+            did: Database Id
+            scid: Schema Id
+            fnid: Function Id
+        """
+
+        resp_data = self._fetch_properties(gid, sid, did, scid, fnid)
+
+        return ajax_response(
+            response=resp_data,
+            status=200
+        )
+
+    def _format_arguments_from_db(self, data):
+        """
+        Create Argument list of the Function.
+
+        Args:
+            data: Function Data
+
+        Returns:
+            Function Arguments in the following format.
+                [
+                {'proargtypes': 'integer', 'proargmodes: 'IN',
+                'proargnames': 'column1', 'proargdefaultvals': 1}, {...}
+                ]
+            Where
+                Arguments:
+                    proargtypes: Argument Types (Data Type)
+                    proargmodes: Argument Modes [IN, OUT, INOUT, VARIADIC]
+                    proargnames: Argument Name
+                    proargdefaultvals: Default Value of the Argument
+        """
+        proargtypes = [ptype for ptype in data['proargtypenames'].split(",")]\
+            if data['proargtypenames'] else []
+        proargmodes = data['proargmodes'] if data['proargmodes'] else []
+        proargnames = data['proargnames'] if data['proargnames'] else []
+        proargdefaultvals = [ptype for ptype in
+                             data['proargdefaultvals'].split(",")] \
+            if data['proargdefaultvals'] else []
+        proallargtypes = data['proallargtypes'] \
+            if data['proallargtypes'] else []
+
+        proargout = []
+        proargid = []
+        proargmodenames = {'i': 'IN', 'o': 'OUT', 'b': 'INOUT',
+                           'v': 'VARIADIC', 't': 'TABLE'}
+
+        # The proargtypes doesn't give OUT params, so we need to fetch
+        # those from database explicitly, below code is written for this
+        # purpose.
+        #
+        # proallargtypes gives all the Function's argument including OUT,
+        # but we have not used that column; as the data type of this
+        # column (i.e. oid[]) is not supported by oidvectortypes(oidvector)
+        # function which we have used to fetch the datatypes
+        # of the other parameters.
+
+        proargmodes_fltrd = copy.deepcopy(proargmodes)
+        proargnames_fltrd = []
+        cnt = 0
+        for m in proargmodes:
+            if m == 'o':  # Out Mode
+                SQL = render_template("/".join([self.sql_template_path,
+                                                'get_out_types.sql']),
+                                      out_arg_oid=proallargtypes[cnt])
+                status, out_arg_type = self.conn.execute_scalar(SQL)
+                if not status:
+                    return internal_server_error(errormsg=out_arg_type)
+
+                # Insert out parameter datatype
+                proargtypes.insert(cnt, out_arg_type)
+                proargdefaultvals.insert(cnt, '')
+            elif m == 'v':  # Variadic Mode
+                proargdefaultvals.insert(cnt, '')
+            elif m == 't':  # Table Mode
+                proargmodes_fltrd.remove(m)
+                proargnames_fltrd.append(proargnames[cnt])
+
+            cnt += 1
+
+        cnt = 0
+        # Map param's short form to its actual name. (ex: 'i' to 'IN')
+        for m in proargmodes_fltrd:
+            proargmodes_fltrd[cnt] = proargmodenames[m]
+            cnt += 1
+
+        # Removes Argument Names from the list if that argument is removed
+        # from the list
+        for i in proargnames_fltrd:
+            proargnames.remove(i)
+
+        # Insert null value against the parameters which do not have
+        # default values.
+        if len(proargmodes_fltrd) > len(proargdefaultvals):
+            dif = len(proargmodes_fltrd) - len(proargdefaultvals)
+            while (dif > 0):
+                proargdefaultvals.insert(0, '')
+                dif = dif - 1
+
+        # Prepare list of Argument list dict to be displayed in the Data Grid.
+        params = {"arguments": map(
+            lambda argid, argtype, argmode, argname, argdefval: {
+                "argid": argid,
+                "argtype": argtype.strip() if argtype is not None else '',
+                "argmode": argmode,
+                "argname": argname,
+                "argdefval": argdefval
+            }, range(len(proargtypes)), proargtypes, proargmodes_fltrd,
+            proargnames, proargdefaultvals)}
+
+        # Prepare string formatted Argument to be displayed in the Properties
+        # panel.
+        proargs = map(self._map_arguments, proargmodes_fltrd, proargnames,
+                      proargtypes, proargdefaultvals)
+
+        proargs = {"proargs": ", ".join(proargs)}
+
+        return params, proargs
+
+    def _map_arguments(self, argmode, argname, argtype, argdef):
+        """
+        Returns formatted Arguments.
+        Args:
+            argmode: Argument Mode
+            argname: Argument Name
+            argtype: Argument Type
+            argdef: Argument Default Value
+        """
+        arg = ''
+
+        if argmode:
+            arg += argmode + " "
+        if argname:
+            arg += argname + " "
+        if argtype:
+            arg += argtype + " "
+        if argdef:
+            arg += " DEFAULT " + argdef
+
+        return arg
+
+    def _format_proacl_from_db(self, proacl):
+        """
+        Returns privileges.
+        Args:
+            proacl: Privileges Dict
+        """
+        privileges = []
+        for row in proacl:
+            priv = parse_priv_from_db(row)
+            privileges.append(priv)
+
+        return {"acl": privileges}
+
+    @check_precondition
+    def get_types(self, gid, sid, did, scid, fnid=None):
+        """
+        Returns the Types.
+
+        Args:
+            gid: Server Group Id
+            sid: Server Id
+            did: Database Id
+            scid: Schema Id
+            fnid: Function Id
+        """
+        # TODO: This function should be removed once Types module
+        # will be completed.
+
+        res = [{'label': '', 'value': ''}]
+        try:
+            SQL = render_template("/".join([self.sql_template_path,
+                                            'get_types.sql']))
+            status, rset = self.conn.execute_2darray(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            for row in rset['rows']:
+                res.append(
+                    {'label': row['typname'], 'value': row['typname']}
+                )
+
+            return make_json_response(
+                data=res,
+                status=200
+            )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    def get_languages(self, gid, sid, did, scid, fnid=None):
+        """
+        Returns the Languages list.
+
+        Args:
+            gid: Server Group Id
+            sid: Server Id
+            did: Database Id
+            scid: Schema Id
+            fnid: Function Id
+        """
+
+        res = [{'label': '', 'value': ''}]
+        try:
+            SQL = render_template("/".join([self.sql_template_path,
+                                            'get_languages.sql'])
+                                  )
+            status, rows = self.conn.execute_dict(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            res = res + rows['rows']
+
+            return make_json_response(
+                data=res,
+                status=200
+            )
+        except:
+            exc_type, exc_value, exc_traceback = sys.exc_info()
+            current_app.logger.error(traceback.print_exception(
+                exc_type,
+                exc_value,
+                exc_traceback,
+                limit=2
+                )
+            )
+
+            return internal_server_error(errormsg=str(exc_value))
+
+    @check_precondition
+    def variable_options(self, gid, sid, did, scid, fnid=None):
+        """
+        Returns the variables.
+
+        Args:
+            gid: Server Group Id
+            sid: Server Id
+            did: Database Id
+            scid: Schema Id
+            fnid: Function Id
+
+        Returns:
+            This function will return list of variables available for
+            table spaces.
+        """
+        SQL = render_template(
+            "/".join([self.sql_template_path, 'variables.sql'])
+            )
+        status, rset = self.conn.execute_dict(SQL)
+
+        if not status:
+            return internal_server_error(errormsg=rset)
+
+        return make_json_response(
+            data=rset['rows'],
+            status=200
+        )
+
+    @check_precondition
+    @validate_request
+    def create(self, gid, sid, did, scid):
+        """
+        Create a new Function object.
+
+        Args:
+            gid: Server Group Id
+            sid: Server Id
+            did: Database Id
+            scid: Schema Id
+            fnid: Function Id
+
+        Returns:
+            Function object in json format.
+        """
+
+        try:
+            # Get SQL to create Function
+            status, SQL = self._get_sql(gid, sid, did, scid, self.request)
+            if not status:
+                return internal_server_error(errormsg=SQL)
+
+            status, res = self.conn.execute_scalar(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            SQL = render_template("/".join([self.sql_template_path,
+                                            'get_oid.sql']),
+                                  nspname=self.request['pronamespace'],
+                                  name=self.request['name'])
+            status, res = self.conn.execute_dict(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            res = res['rows'][0]
+
+            return jsonify(
+                node=self.blueprint.generate_browser_node(
+                    res['oid'],
+                    self.request['pronamespace'],
+                    res['name'],
+                    icon="icon-" + self.node_type,
+                    language=res['lanname'],
+                    funcowner=res['funcowner']
+                )
+            )
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    def delete(self, gid, sid, did, scid, fnid):
+        """
+        Drop the Function.
+
+        Args:
+            gid: Server Group Id
+            sid: Server Id
+            did: Database Id
+            scid: Schema Id
+            fnid: Function Id
+        """
+
+        if self.cmd == 'delete':
+            # This is a cascade operation
+            cascade = True
+        else:
+            cascade = False
+
+        try:
+            # Fetch Name and Schema Name to delete the Function.
+            SQL = render_template("/".join([self.sql_template_path,
+                                  'delete.sql']), scid=scid, fnid=fnid)
+            status, res = self.conn.execute_2darray(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            name, func_args, nspname = res['rows'][0]
+
+            SQL = render_template("/".join([self.sql_template_path,
+                                            'delete.sql']),
+                                  name=name,
+                                  func_args=func_args,
+                                  nspname=nspname,
+                                  cascade=cascade)
+            status, res = self.conn.execute_scalar(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            return make_json_response(
+                success=1,
+                info=gettext("Function Dropped."),
+                data={
+                    'id': fnid,
+                    'scid': scid,
+                    'sid': sid,
+                    'gid': gid,
+                    'did': did
+                }
+            )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    @validate_request
+    def update(self, gid, sid, did, scid, fnid):
+        """
+        Update the Function.
+
+        Args:
+            gid: Server Group Id
+            sid: Server Id
+            did: Database Id
+            scid: Schema Id
+            fnid: Function Id
+        """
+
+        status, SQL = self._get_sql(gid, sid, did, scid, self.request, fnid)
+
+        if not status:
+            return internal_server_error(errormsg=SQL)
+
+        try:
+            if SQL and SQL.strip('\n') and SQL.strip(' '):
+                status, res = self.conn.execute_scalar(SQL)
+                if not status:
+                    return internal_server_error(errormsg=res)
+
+                return make_json_response(
+                    success=1,
+                    info="Function Updated.",
+                    data={
+                        'id': fnid,
+                        'scid': scid,
+                        'sid': sid,
+                        'gid': gid,
+                        'did': did
+                    }
+                )
+            else:
+                return make_json_response(
+                    success=1,
+                    info="Nothing to update.",
+                    data={
+                        'id': fnid,
+                        'scid': scid,
+                        'sid': sid,
+                        'gid': gid,
+                        'did': did
+                    }
+                )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    def sql(self, gid, sid, did, scid, fnid=None):
+        """
+        Returns the SQL for the Function object.
+
+        Args:
+            gid: Server Group Id
+            sid: Server Id
+            did: Database Id
+            scid: Schema Id
+            fnid: Function Id
+        """
+
+        # Fetch the function definition.
+        SQL = render_template("/".join([self.sql_template_path,
+                              'get_definition.sql']), fnid=fnid, scid=scid)
+        status, res = self.conn.execute_2darray(SQL)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        func_def, name = res['rows'][0]
+        sql_header = """-- {0}: {1}
+
+-- DROP {0} {1};
+
+""".format(self.node_type.upper(), name)
+
+        SQL = sql_header + func_def
+
+        return ajax_response(response=SQL)
+
+    @check_precondition
+    @validate_request
+    def msql(self, gid, sid, did, scid, fnid=None):
+        """
+        Returns the modified SQL.
+
+        Args:
+            gid: Server Group Id
+            sid: Server Id
+            did: Database Id
+            scid: Schema Id
+            fnid: Function Id
+        Returns:
+            SQL statements to create/update the Domain.
+        """
+
+        status, SQL = self._get_sql(gid, sid, did, scid, self.request, fnid)
+        if status:
+            return make_json_response(
+                data=SQL,
+                status=200
+            )
+        else:
+            return SQL
+
+    def _get_sql(self, gid, sid, did, scid, data, fnid=None):
+        """
+        Generates the SQL statements to create/update the Function.
+
+        Args:
+            gid: Server Group Id
+            sid: Server Id
+            did: Database Id
+            scid: Schema Id
+            data: Function data
+            fnid: Function Id
+        """
+
+        try:
+            # Get Schema Name from its OID.
+            if 'pronamespace' in data:
+                data['pronamespace'] = self._get_schema(data[
+                    'pronamespace'])
+            if 'provolatile' in data:
+                vol_dict = {'v': 'VOLATILE', 's': 'STABLE', 'i': 'IMMUTABLE'}
+                data['provolatile'] = vol_dict[data['provolatile']]
+
+            if fnid is not None:
+                # Edit Mode
+
+                # Fetch Old Data from database.
+                old_data = self._fetch_properties(gid, sid, did, scid, fnid)
+
+                # Get Schema Name
+                old_data['pronamespace'] = self._get_schema(old_data[
+                    'pronamespace'])
+
+                # If any of the below argument is changed,
+                # then CREATE OR REPLACE SQL statement should be called
+                fun_change_args = ['lanname', 'prosrc', 'probin', 'prosrc_c',
+                                   'provolatile', 'proisstrict', 'prosecdef',
+                                   'procost', 'proleakproof', 'arguments']
+
+                data['change_func'] = False
+                for arg in fun_change_args:
+                    if arg == 'arguments' and arg in data and len(data[arg]) \
+                            > 0:
+                        data['change_func'] = True
+                    elif arg in data:
+                        data['change_func'] = True
+
+                # If Function Definition/Arguments are changed then merge old
+                #  Arguments with changed ones for Create/Replace Function
+                # SQL statement
+                if 'arguments' in data and len(data['arguments']) > 0:
+                    for arg in data['arguments']['changed']:
+                        for old_arg in old_data['arguments']:
+                            if arg['argid'] == old_arg['argid']:
+                                old_arg.update(arg)
+                                break
+                    data['arguments'] = old_data['arguments']
+                elif data['change_func']:
+                    data['arguments'] = old_data['arguments']
+
+                # Parse Privileges
+                if 'acl' in data:
+                    for key in ['added', 'deleted', 'changed']:
+                        if key in data['acl']:
+                            data['acl'][key] = parse_priv_to_db(
+                                data['acl'][key], ["X"])
+
+                # Parse Variables
+                chngd_variables = {}
+                data['merged_variables'] = []
+                old_data['chngd_variables'] = {}
+                del_variables = {}
+
+                # If Function Definition/Arguments are changed then,
+                # Merge old, new (added, changed, deleted) variables,
+                # which will be used in the CREATE or REPLACE Function sql
+                # statement
+
+                if data['change_func']:
+                    # To compare old and new variables, preparing name :
+                    # value dict
+
+                    # Deleted Variables
+                    if 'variables' in data and 'deleted' in data['variables']:
+                        for v in data['variables']['deleted']:
+                            del_variables[v['name']] = v['value']
+
+                    if 'variables' in data and 'changed' in data['variables']:
+                        for v in data['variables']['changed']:
+                            chngd_variables[v['name']] = v['value']
+
+                    if 'variables' in data and 'added' in data['variables']:
+                        for v in data['variables']['added']:
+                            chngd_variables[v['name']] = v['value']
+
+                    for v in old_data['variables']:
+                        old_data['chngd_variables'][v['name']] = v['value']
+
+                    # Prepare final dict of new and old variables
+                    for name, val in old_data['chngd_variables'].items():
+                        if name not in chngd_variables and name not in \
+                                del_variables:
+                            chngd_variables[name] = val
+
+                    # Prepare dict in [{'name': var_name, 'value': var_val},..]
+                    # format
+                    for name, val in chngd_variables.items():
+                        data['merged_variables'].append({'name': name,
+                                                         'value': val})
+                else:
+                    if 'variables' in data and 'changed' in data['variables']:
+                        for v in data['variables']['changed']:
+                            data['merged_variables'].append(v)
+
+                    if 'variables' in data and 'added' in data['variables']:
+                        for v in data['variables']['added']:
+                            data['merged_variables'].append(v)
+
+                SQL = render_template(
+                    "/".join([self.sql_template_path, 'update.sql']),
+                    data=data, o_data=old_data
+                )
+            else:
+                # Parse Privileges
+                if 'acl' in data:
+                    data['acl'] = parse_priv_to_db(data['acl'], ["X"])
+
+                args = ''
+                cnt = 1
+                if 'arguments' in data:
+                    for a in data['arguments']:
+                        if (('argmode' in a and a['argmode'] != 'OUT' and
+                            a['argmode'] is not None
+                             ) or 'argnode' not in a):
+                            if 'argmode' in a:
+                                args += a['argmode'] + " "
+                            if 'argname' in a and a['argname'] != ''\
+                                    and a['argname'] is not None:
+                                args += self.qtIdent(
+                                    self.conn, a['argname']) + " "
+                            if 'argtype' in a:
+                                args += a['argtype'] + " "
+                            if cnt < len(data['arguments']):
+                                args += ', '
+                        cnt += 1
+
+                data['func_args'] = args
+                # Create mode
+                SQL = render_template("/".join([self.sql_template_path,
+                                                'create.sql']), data=data)
+            return True, SQL
+
+        except Exception as e:
+            return False, e
+
+    def _fetch_properties(self, gid, sid, did, scid, fnid=None):
+        """
+        Return Function Properties which will be used in properties,
+        msql function.
+
+        Args:
+            gid: Server Group Id
+            sid: Server Id
+            did: Database Id
+            scid: Schema Id
+            fnid: Function Id
+        """
+
+        resp_data = {}
+
+        SQL = render_template("/".join([self.sql_template_path,
+                                        'properties.sql']),
+                              scid=scid, fnid=fnid)
+        status, res = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        resp_data = res['rows'][0]
+
+        # Get formatted Arguments
+        frmtd_params, frmtd_proargs = self._format_arguments_from_db(resp_data)
+        resp_data.update(frmtd_params)
+        resp_data.update(frmtd_proargs)
+
+        # Fetch privileges
+        SQL = render_template("/".join([self.sql_template_path, 'acl.sql']),
+                              fnid=fnid)
+        status, proaclres = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        # Get Formatted Privileges
+        resp_data.update(self._format_proacl_from_db(proaclres['rows']))
+
+        # Set System Functions Status
+        resp_data['sysfunc'] = False
+        if fnid <= self.manager.db_info[did]['datlastsysoid']:
+            resp_data['sysfunc'] = True
+
+        # Get formatted Security Labels
+        if 'seclabels' in resp_data:
+            resp_data.update(parse_sec_labels_from_db(resp_data['seclabels']))
+
+        # Get formatted Variable
+        resp_data.update(parse_variables_from_db([
+            {"setconfig": resp_data['proconfig']}]))
+
+        return resp_data
+
+    def _get_schema(self, scid):
+        """
+        Returns Schema Name from its OID.
+
+        Args:
+            scid: Schema Id
+        """
+        SQL = render_template("/".join([self.sql_template_path,
+                              'get_schema.sql']), scid=scid)
+
+        status, schema_name = self.conn.execute_scalar(SQL)
+
+        if not status:
+            return internal_server_error(errormsg=schema_name)
+
+        return schema_name
+
+    @check_precondition
+    def dependents(self, gid, sid, did, scid, fnid):
+        """
+        This function get the dependents and return ajax response
+        for the Function node.
+
+        Args:
+            gid: Server Group Id
+            sid: Server Id
+            did: Database Id
+            scid: Schema Id
+            doid: Function Id
+        """
+        dependents_result = self.get_dependents(self.conn, fnid)
+        return ajax_response(
+            response=dependents_result,
+            status=200
+        )
+
+    @check_precondition
+    def dependencies(self, gid, sid, did, scid, fnid):
+        """
+        This function get the dependencies and return ajax response
+        for the Function node.
+
+        Args:
+            gid: Server Group Id
+            sid: Server Id
+            did: Database Id
+            scid: Schema Id
+            doid: Function Id
+        """
+        dependencies_result = self.get_dependencies(self.conn, fnid)
+        return ajax_response(
+            response=dependencies_result,
+            status=200
+        )
+
+FunctionView.register_node_view(blueprint)
+
+
+class ProcedureModule(SchemaChildModule):
+    """
+    class ProcedureModule(SchemaChildModule):
+
+        This class represents The Procedures Module.
+
+    Methods:
+    -------
+    * __init__(*args, **kwargs)
+      - Initialize the Procedures Module.
+
+    * get_nodes(gid, sid, did, scid)
+      - Generate the Procedures collection node.
+
+    * node_inode():
+      - Returns Procedures node as leaf node.
+
+    * script_load()
+      - Load the module script for Procedures, when schema node is
+        initialized.
+
+    """
+
+    NODE_TYPE = 'procedure'
+    COLLECTION_LABEL = gettext("Procedures")
+
+    def __init__(self, *args, **kwargs):
+        """
+        Initialize the Procedure Module.
+        Args:
+            *args:
+            **kwargs:
+        """
+        super(ProcedureModule, self).__init__(*args, **kwargs)
+
+        self.min_ver = 90100
+        self.max_ver = None
+        self.server_type = ['ppas']
+
+    def get_nodes(self, gid, sid, did, scid):
+        """
+        Generate Procedures collection node.
+        """
+        yield self.generate_browser_collection_node(scid)
+
+    @property
+    def node_inode(self):
+        """
+        Make the node as leaf node.
+        Returns:
+            False as this node doesn't have child nodes.
+        """
+        return False
+
+    @property
+    def script_load(self):
+        """
+        Load the module script for Procedures, when the
+        schema node is initialized.
+        """
+        return schemas.SchemaModule.NODE_TYPE
+
+
+procedure_blueprint = ProcedureModule(__name__)
+
+
+class ProcedureView(FunctionView):
+
+    node_type = procedure_blueprint.node_type
+
+    def __init__(self, *args, **kwargs):
+        """
+        Initialize the Function Module.
+        Args:
+            *args:
+            **kwargs:
+        """
+        super(ProcedureView, self).__init__(*args, **kwargs)
+
+    @property
+    def required_args(self):
+        """
+        Returns Required arguments for procedures node.
+        Where
+            Required Args:
+                name:           Name of the Function
+                pronamespace:   Function Namespace
+                lanname:        Function Language Name
+                prosrc:         Function Code
+        """
+        return ['name',
+                'pronamespace',
+                'lanname',
+                'prosrc']
+
+    def module_js(self):
+        """
+        Load JS file (procedures.js) for this module.
+        """
+
+        return make_response(
+            render_template(
+                "procedure/js/procedures.js",
+                _=gettext
+            ),
+            200, {'Content-Type': 'application/x-javascript'}
+        )
+
+ProcedureView.register_node_view(procedure_blueprint)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/coll-function.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/coll-function.png
new file mode 100644
index 0000000000000000000000000000000000000000..c44874e5574e624c2687689ac75f3ba4ed69e811
GIT binary patch
literal 349
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!aez;VE0CVL=8;#?*`-(h^sRi9
z*>&~c)34PF?}pc0oO}FT&eYpg3!lCJ{{QpuKPl}Gawb0N+VtXry&)e^8)He3UoeBi
zvm0qZ4rhT!WHFHT0Ash4*>*riqNj^vh{WaCes{hD1{^FOt?qvPzrI(~vFzEgEEaCT
zKn8&fCc|T@oHyDw|30!InX~Vp=DDQ@|E}SiWNDf1d5o{vOS9^<jH6JQ%!{XA68~=T
zUVHU-(WR)_zZZZ1_xt(xjh~rXW-{}Bc$;4hv`n?cHKHUXu_V<hxhNG#F&G&b8tNJt
z>Kd7b7@Arcm|Gc`Y8#kY85l5Do_~m<AvZrIGp!P&!9dr*5~wG{$k@un#LB=-+W@H3
U;MDZcH9!pvp00i_>zopr06KSqcmMzZ

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/coll-procedure.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/coll-procedure.png
new file mode 100644
index 0000000000000000000000000000000000000000..7c13a9bc73a782b5139095af596e15d7b68dd20c
GIT binary patch
literal 337
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFv5AX?b1=9EC%sCbm^nUN&dsC)d
z%g%m(?%cJOmUB^2&)2TKR$To5`}b?r)x6ex&wxr9OM?7@862M7NCR>>3p^r=fwTu0
zyPeFo12PglT^vI=t|uoXgaoB9FsmgiGa57px_XMbaBFHxO0zOZW@WzA@{)3Bd#1Ev
zf>nS=wRyl)0gsIDYK$8M1T>mj(wGjaEU<j_)L{XKVdhn(2@iX`tkM;(8Sb=j%x%8O
z&&KdzmZ)RwGzMRwWvV5v5hW>!C8<`)MX5lF!N|bSP}jgv*T^))(A3Jn+{)NY+rZ4q
zz+j);rTHita`RI%(<(t440H`FfqFuWjIB&etPFq}fI1CMO%GiI)WG2B>gTe~DWM4f
DC&Fq!

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/function.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/function.png
new file mode 100644
index 0000000000000000000000000000000000000000..656854a0191b5dd5d465f90cfbceebdc3913f1a2
GIT binary patch
literal 325
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPHF3h)VW1=3U3Jn||!yY$MRhadm{
z{r~UY=bu~de4cgqZS9ih={*lqIv$kGe$v0=Wy+ox+kmPWOM?7@862M7NCR>>3p^r=
zfwTu0yPeFo12Td<T^vI=t|uorFgbMz%nH2e!Eh#_sIZa4a8(-{W2?l}DN`<8YH;#-
zst}-Z;J_6|HZC3?W5<L^3=wBng(l?o+}ds4$eUzU%$C*nPL(la_XP%qilxGbk7sB!
z0Zmseag8WRNi0dVN-jzTQVd20h6cKZM!E)uAw~vPCdO7KrrHLkRt5(1-s!DE(U6;;
ll9^Ts(O_T+)&Nv(Vr5_k(Qs;d=o+8~22WQ%mvv4FO#sGkaAg1h

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/procedure.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/img/procedure.png
new file mode 100644
index 0000000000000000000000000000000000000000..8b65dff9eb2c373df031669adba7a82c0ae2aaa6
GIT binary patch
literal 322
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFv5AX?b1=9Cs%{mqo^m6CUA1_|~
z|NHmbqerjy?R&Ir+0E|mOJ!vji;J%}H<uLMy$n>!SQ6wH%;50sMjDXAS>O>_45U54
z*zIJt9gq>^>Eal|aXmS~fyt>$U{>Hw4~8=dMTLzVhO64x7+WQ#PMLD)QiGGvQ-uJP
z0|%}!vT^bF7&|6RVu(1qDl{Rt=hklXM&2Z=Vz#WlMH3iS#bz)t#6K1K?su<o8qjpr
z64!{5l*E!$tK_0oAjM#0U}&goV5n<k8e(W_WngY)Y^H5sW@TWoPwvuu6b-rgDVb@N
pAPok(29`iQAx6elCMH$}Kn*~h2B)Tnt^sOb@O1TaS?83{1OQh#ZFT?v

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/css/function.css b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/css/function.css
new file mode 100644
index 0000000..16b2e71
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/css/function.css
@@ -0,0 +1,3 @@
+.functions_code {
+    height: 130px !important;
+}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/js/functions.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/js/functions.js
new file mode 100644
index 0000000..583df21
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/js/functions.js
@@ -0,0 +1,437 @@
+/* Create and Register Function Collection and Node. */
+define(
+        ['jquery', 'underscore', 'underscore.string',
+         'pgadmin', 'pgadmin.browser', 'alertify',
+          'pgadmin.browser.collection', 'pgadmin.browser.server.privilege'],
+function($, _, S, pgAdmin, pgBrowser, alertify) {
+
+  if (!pgBrowser.Nodes['coll-function']) {
+    var functions = pgAdmin.Browser.Nodes['coll-function'] =
+      pgAdmin.Browser.Collection.extend({
+        node: 'function',
+        label: '{{ _('Functions') }}',
+        type: 'coll-function',
+        columns: ['name', 'funcowner', 'description']
+      });
+  };
+
+  // Security Model
+  var SecurityModel = Backform.SecurityModel = pgAdmin.Browser.Node.Model.extend({
+    defaults: {
+      provider: null,
+      label: null
+    },
+    schema: [{
+      id: 'provider', label: '{{ _('Provider') }}',
+      type: 'text'
+    },{
+      id: 'label', label: '{{ _('Security Label') }}',
+      type: 'text'
+    }],
+    validate: function() {
+      var err = {},
+          errmsg = null,
+          data = this.toJSON();
+
+      if (_.isUndefined(data.label) ||
+        _.isNull(data.label) ||
+        String(data.label).replace(/^\s+|\s+$/g, '') == '') {
+        return _("Please specify the value for all the security providers.");
+      }
+      return null;
+    }
+  });
+
+  // Argument Model
+  var ArgumentModel = pgAdmin.Browser.Node.Model.extend({
+    idAttribute: 'argid',
+    defaults: {
+      argid: undefined,
+      argtype: undefined,
+      argmode: undefined,
+      argname: undefined,
+      argdefval: undefined
+    },
+    schema: [{
+      id: 'argid', visible: false, type: 'text',
+      mode: ['properties', 'edit','create']
+      },{
+        id: 'argtype', label:'{{ _('Data Type') }}', cell:
+        'node-ajax-options', cellHeaderClasses: 'width_percent_30',
+        control: 'node-ajax-options', type: 'text', url: 'get_types',
+        editable: function(m) {
+          return _.isUndefined(m.isNew) ? true : m.isNew();
+        }
+      },{
+        id: 'argmode', label:'{{ _('Mode') }}', type: 'options',
+        control: 'node-ajax-options', cellHeaderClasses:'width_percent_20',
+        options:[
+          {'label': 'IN', 'value': 'IN'},
+          {'label': 'OUT', 'value': 'OUT'},
+          {'label': 'INOUT', 'value': 'INOUT'},
+          {'label': 'VARIADIC', 'value': 'VARIADIC'}
+        ], editable: function(m) {
+            return _.isUndefined(m.isNew) ? true : m.isNew();
+           }
+      },{
+        id: 'argname', label:'{{ _('Argument Name') }}', type: 'text',
+        cell: 'string', editable: true, cellHeaderClasses:'width_percent_30',
+      },{
+        id: 'argdefval', label:'{{ _('Default Value') }}', type: 'text',
+        cell: 'string', editable: true,  cellHeaderClasses:'width_percent_20'
+      }
+    ],
+    toJSON: Backbone.Model.prototype.toJSON
+  });
+
+  if (!pgBrowser.Nodes['function']) {
+    pgAdmin.Browser.Nodes['function'] = pgBrowser.Node.extend({
+      type: 'function',
+      label: '{{ _('Function') }}',
+      collection_type: 'coll-function',
+      hasSQL: true,
+      hasDepends: true,
+      parent_type: ['schema'],
+      Init: function(args) {
+        /* Avoid mulitple registration of menus */
+        if (this.initialized)
+            return;
+
+        this.initialized = true;
+
+        pgBrowser.add_menus([{
+          name: 'create_function_on_coll', node: 'coll-function', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 4, label: '{{ _('Function...') }}',
+          icon: 'wcTabIcon icon-function', data: {action: 'create', check: true},
+          enable: 'canCreate'
+        },{
+          name: 'create_function', node: 'function', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 4, label: '{{ _('Function...') }}',
+          icon: 'wcTabIcon icon-function', data: {action: 'create', check: true},
+          enable: 'canCreate'
+        },{
+          name: 'create_function', node: 'schema', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 4, label: '{{ _('Function...') }}',
+          icon: 'wcTabIcon icon-function', data: {action: 'create', check: false},
+          enable: 'canCreate'
+        }
+        ]);
+
+      },
+      canDrop: pgBrowser.Nodes['schema'].canChildDrop,
+      canDropCascade: pgBrowser.Nodes['schema'].canChildDrop,
+      model: pgAdmin.Browser.Node.Model.extend({
+        initialize: function(attrs, args) {
+          var isNew = (_.size(attrs) === 0);
+          if (isNew) {
+            // Set Selected Schema
+            schema_id = args.node_info.schema._id
+            this.set({'pronamespace': schema_id}, {silent: true});
+
+            // Set Current User
+            var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user;
+            this.set({'funcowner': userInfo.name}, {silent: true});
+          }
+          pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments);
+        },
+        defaults: {
+          name: undefined,
+          oid: undefined,
+          xmin: undefined,
+          funcowner: undefined,
+          pronamespace: undefined,
+          description: undefined,
+          pronargs: undefined, /* Argument Count */
+          proargs: undefined, /* Arguments */
+          proargtypenames: undefined, /* Argument Signature */
+          prorettypename: undefined, /* Return Type */
+          lanname: 'sql', /* Language Name in which function is being written */
+          provolatile: undefined, /* Volatility */
+          proretset: undefined, /* Return Set */
+          proisstrict: undefined,
+          prosecdef: undefined, /* Security of definer */
+          proiswindow: undefined, /* Window Function ? */
+          procost: undefined, /* Estimated execution Cost */
+          prorows: undefined, /* Estimated number of rows */
+          proleakproof: undefined,
+          arguments: [],
+          prosrc: undefined,
+          prosrc_c: undefined,
+          probin: '$libdir/',
+          options: [],
+          variables: [],
+          proacl: undefined,
+          seclabels: [],
+          acl: [],
+          sysfunc: undefined
+        },
+        schema: [{
+          id: 'name', label: '{{ _('Name') }}', cell: 'string',
+          type: 'text', mode: ['properties', 'create', 'edit']
+        },{
+          id: 'oid', label: '{{ _('OID') }}', cell: 'string',
+          type: 'text' , mode: ['properties']
+        },{
+          id: 'funcowner', label: '{{ _('Owner') }}', cell: 'string',
+          control: Backform.NodeListByNameControl, node: 'role',  type:
+          'text', disabled: 'isDisabled'
+        },{
+          id: 'pronamespace', label: '{{ _('Schema') }}', cell: 'string',
+          control: 'node-list-by-id', type: 'text', cache_level: 'database',
+          node: 'schema'
+        },{
+          id: 'description', label: '{{ _('Comment') }}', cell: 'string',
+          type: 'multiline'
+        },{
+          id: 'pronargs', label: '{{ _('Argument Count') }}', cell: 'string',
+          type: 'text', group: '{{ _('Definition') }}', mode: ['properties']
+        },{
+          id: 'proargs', label: '{{ _('Arguments') }}', cell: 'string',
+          type: 'text', group: '{{ _('Definition') }}', mode: ['properties', 'edit'],
+          disabled: 'isDisabled'
+        },{
+          id: 'proargtypenames', label: '{{ _('Signature Arguments') }}', cell:
+          'string', type: 'text', group: '{{ _('Definition') }}', mode: ['properties'],
+          disabled: 'isDisabled'
+        },{
+          id: 'prorettypename', label: '{{ _('Return Type') }}', cell: 'string',
+          control: 'node-ajax-options', type: 'text', group: '{{ _('Definition') }}',
+          url: 'get_types', disabled: 'isDisabled',
+          mode: ['create']
+        },{
+          id: 'prorettypename', label: '{{ _('Return Type') }}', cell: 'string',
+          type: 'text', group: '{{ _('Definition') }}', disabled: true,
+          mode: ['properties', 'edit']
+        },  {
+          id: 'lanname', label: '{{ _('Language') }}', cell: 'string',
+          control: 'node-ajax-options', type: 'text', group: '{{ _('Definition') }}',
+          url: 'get_languages', disabled: 'isDisabled'
+        },{
+          id: 'prosrc', label: '{{ _('Code') }}', cell: 'string',
+          type: 'multiline', group: '{{ _('Definition') }}', deps: ['lanname'],  visible:
+          function(m) {
+            if (m.get('lanname') == 'c') {
+              return false;
+            }
+            return true;
+          }, maxlength: '', extraClasses: ['functions_code']
+        },{
+          id: 'probin', label: '{{ _('Object File') }}', cell: 'string',
+          type: 'text', group: '{{ _('Definition') }}', deps: ['lanname'], visible:
+          function(m) {
+            if (m.get('lanname') == 'c') { return true; }
+            return false;
+          }
+        },{
+          id: 'prosrc_c', label: '{{ _('Link Symbol') }}', cell: 'string',
+          type: 'text', group: '{{ _('Definition') }}',  deps: ['lanname'], visible:
+          function(m) {
+            if (m.get('lanname') == 'c') { return true; }
+            return false;
+          }
+        },{
+          id: 'provolatile', label: '{{ _('Volatility') }}', cell: 'string',
+          control: 'node-ajax-options', type: 'text', group: '{{ _('Options') }}',
+          options:[
+            {'label': 'VOLATILE', 'value': 'v'},
+            {'label': 'STABLE', 'value': 's'},
+            {'label': 'IMMUTABLE', 'value': 'i'},
+          ], disabled: 'isDisabled'
+        },{
+          id: 'proretset', label: '{{ _('Returns a Set?') }}', group: '{{ _('Options') }}',
+          cell:'boolean', type: 'switch',  disabled: 'isDisabled'
+        },{
+          id: 'proisstrict', label: '{{ _('Strict?') }}', group: '{{ _
+          ('Options') }}',
+          cell:'boolean', type: 'switch', disabled: 'isDisabled'
+        },{
+          id: 'prosecdef', label: '{{ _('Security of definer?') }}',
+           group: '{{ _('Options') }}', cell:'boolean', type: 'switch',
+           disabled: 'isDisabled'
+        },{
+          id: 'proiswindow', label: '{{ _('Window?') }}',
+           group: '{{ _('Options') }}', cell:'boolean', type: 'switch',
+            disabled: 'isDisabled'
+        },{
+          id: 'procost', label: '{{ _('Estimated Cost') }}', group: '{{ _('Options') }}',
+          cell:'string', type: 'text', disabled: 'isDisabled'
+        },{
+          id: 'prorows', label: '{{ _('Estimated Rows') }}', group: '{{ _
+          ('Options') }}',
+          cell:'string', type: 'text', disabled: 'isDisabled',
+          deps: ['proretset']
+        },{
+          id: 'proleakproof', label: '{{ _('Leak proof?') }}',
+          group: '{{ _('Options') }}', cell:'boolean', type: 'switch', min_version: 90200,
+          disabled: 'isDisabled'
+        },{
+          id: 'proacl', label: '{{ _('ACL') }}',
+           group: '{{ _('Options') }}', cell:'boolean', type: 'text', cell: 'string',
+           mode: ['properties']
+        },{
+          id: 'sysfunc', label: '{{ _('System Function?') }}',
+           group: '{{ _('Options') }}', cell:'boolean', type: 'switch',
+           mode: ['properties']
+        },{
+          id: 'arguments', label: '{{ _('Parameters') }}', cell: 'string',
+          group: 'Parameters', type: 'collection', canAdd: function(m){
+            return m.isNew();
+          },
+          canDelete: true, model: ArgumentModel, mode:
+          ['create', 'edit'], editable: false,
+          columns: ['argtype', 'argmode', 'argname', 'argdefval']
+        },{
+          id: 'variables', label: '{{ _('Variables') }}', type: 'collection',
+          group: '{{ _('Variables') }}', control: 'variable-collection',
+          model: pgAdmin.Browser.Node.VariableModel,
+          mode: ['edit', 'create'], canAdd: 'canVarAdd', canEdit: false,
+          canDelete: true, disabled: 'isDisabled'
+         },{
+          id: 'acl', label: '{{ _('Privileges') }}', model: pgAdmin
+          .Browser.Node.PrivilegeRoleModel.extend(
+            {privileges: ['X']}), uniqueCol : ['grantee', 'grantor'],
+          editable: false, type: 'collection', group: '{{ _('Previleges') }}',
+          mode: ['edit', 'create'],
+          canAdd: true, canDelete: true, control: 'unique-col-collection',
+        },
+        {
+          id: 'seclabels', label: '{{ _('Security Labels') }}',
+          model: SecurityModel, type: 'collection',
+          group: '{{ _('Security') }}', mode: ['edit', 'create'],
+          min_version: 90100, canAdd: true,
+          canEdit: true, canDelete: true
+        }
+        ],
+        validate: function()
+        {
+          var err = {},
+              errmsg,
+              seclabels = this.get('seclabels');
+
+          if (_.isUndefined(this.get('name')) || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') {
+            err['name'] = '{{ _('Name can not be empty!') }}';
+            errmsg = errmsg || err['name'];
+          }
+
+          if (_.isUndefined(this.get('funcowner')) || String(this.get('funcowner')).replace(/^\s+|\s+$/g, '') == '') {
+            err['funcowner'] = '{{ _('Owner can not be empty!') }}';
+            errmsg = errmsg || err['funcowner'];
+          }
+
+          if (_.isUndefined(this.get('pronamespace')) || String(this.get('pronamespace')).replace(/^\s+|\s+$/g, '') == '') {
+            err['pronamespace'] = '{{ _('Schema can not be empty!') }}';
+            errmsg = errmsg || err['pronamespace'];
+          }
+
+          if (_.isUndefined(this.get('prorettypename')) || String(this.get('prorettypename')).replace(/^\s+|\s+$/g, '') == '') {
+            err['prorettypename'] = '{{ _('Return Type can not be empty!') }}';
+            errmsg = errmsg || err['prorettypename'];
+          }
+
+          if (_.isUndefined(this.get('lanname')) || String(this.get('lanname')).replace(/^\s+|\s+$/g, '') == '') {
+            err['lanname'] = '{{ _('Language can not be empty!') }}';
+            errmsg = errmsg || err['lanname'];
+          }
+
+          if (String(this.get('lanname')) == 'c') {
+            if (_.isUndefined(this.get('probin')) || String(this.get('probin'))
+              .replace(/^\s+|\s+$/g, '') == '') {
+              err['probin'] = '{{ _('Object File can not be empty!') }}';
+              errmsg = errmsg || err['probin'];
+            }
+
+            if (_.isUndefined(this.get('prosrc_c')) || String(this.get('prosrc_c')).replace(/^\s+|\s+$/g, '') == '') {
+              err['prosrc_c'] = '{{ _('Link Symbol can not be empty!') }}';
+              errmsg = errmsg || err['prosrc_c'];
+            }
+          }
+          else {
+            if (_.isUndefined(this.get('prosrc')) || String(this.get('prosrc')).replace(/^\s+|\s+$/g, '') == '') {
+              err['prosrc'] = '{{ _('Code can not be empty!') }}';
+              errmsg = errmsg || err['prosrc'];
+            }
+          }
+
+          if (seclabels) {
+            var secLabelsErr;
+            for (var i = 0; i < seclabels.models.length && !secLabelsErr; i++) {
+              secLabelsErr = (seclabels.models[i]).validate.apply(seclabels.models[i]);
+              if (secLabelsErr) {
+                err['seclabels'] = secLabelsErr;
+                errmsg = errmsg || secLabelsErr;
+              }
+            }
+          }
+
+          this.errorModel.clear().set(err);
+
+          if (_.size(err)) {
+            this.trigger('on-status', {msg: errmsg});
+            return errmsg;
+          }
+
+          return null;
+        },
+        isDisabled: function(m){
+          name = this.name;
+          switch(name){
+            case 'proargs':
+            case 'proargtypenames':
+            case 'proretset':
+            case 'proiswindow':
+              return !m.isNew();
+              break;
+            case 'prorows':
+              if(m.get('proretset') == true) {
+                return false;
+              }
+              else {
+                return true;
+              }
+              break;
+            default:
+              return false;
+              break;
+          }
+        },
+        canVarAdd: function(m) {
+         return true;
+        }
+      }),
+      canCreate: function(itemData, item, data) {
+        //If check is false then , we will allow create menu
+        if (data && data.check == false)
+          return true;
+
+        var t = pgBrowser.tree, i = item, d = itemData;
+        // To iterate over tree to check parent node
+        while (i) {
+          // If it is schema then allow user to create Function
+          if (_.indexOf(['schema'], d._type) > -1)
+            return true;
+
+          if ('coll-function' == d._type) {
+            //Check if we are not child of catalog
+            prev_i = t.hasParent(i) ? t.parent(i) : null;
+            prev_d = prev_i ? t.itemData(prev_i) : null;
+            if( prev_d._type == 'catalog') {
+              return false;
+            } else {
+              return true;
+            }
+          }
+          i = t.hasParent(i) ? t.parent(i) : null;
+          d = i ? t.itemData(i) : null;
+        }
+        // by default we do not want to allow create menu
+        return true;
+      }
+  });
+
+  }
+
+  return pgBrowser.Nodes['function'];
+});
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/acl.sql
new file mode 100644
index 0000000..ad3e0d1
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/acl.sql
@@ -0,0 +1,35 @@
+SELECT
+    COALESCE(gt.rolname, 'public') AS grantee,
+    g.rolname AS grantor, array_agg(privilege_type) AS privileges,
+    array_agg(is_grantable) AS grantable
+FROM
+    (SELECT
+        d.grantee, d.grantor, d.is_grantable,
+        CASE d.privilege_type
+        WHEN 'CONNECT' THEN 'c'
+        WHEN 'CREATE' THEN 'C'
+        WHEN 'DELETE' THEN 'd'
+        WHEN 'EXECUTE' THEN 'X'
+        WHEN 'INSERT' THEN 'a'
+        WHEN 'REFERENCES' THEN 'x'
+        WHEN 'SELECT' THEN 'r'
+        WHEN 'TEMPORARY' THEN 'T'
+        WHEN 'TRIGGER' THEN 't'
+        WHEN 'TRUNCATE' THEN 'D'
+        WHEN 'UPDATE' THEN 'w'
+        WHEN 'USAGE' THEN 'U'
+        ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            (d).grantee AS grantee, (d).grantor AS grantor,
+            (d).is_grantable AS is_grantable,
+            (d).privilege_type AS privilege_type
+        FROM
+            (SELECT aclexplode(db.proacl) AS d FROM pg_proc db
+            WHERE db.oid = {{fnid}}::OID) a
+        ) d
+    ) d
+    LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
+    LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
+GROUP BY g.rolname, gt.rolname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/create.sql
new file mode 100644
index 0000000..ea43172
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/create.sql
@@ -0,0 +1,66 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}
+{% set is_columns = [] %}
+{% if data %}
+CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({% if data
+.arguments %}
+{% for p in data.arguments %}{{p.argmode}} {% 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 data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data
+    .prorettypename) }} AS
+{% if data.lanname == 'c' %}
+{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
+{% else %}
+$BODY${{ data.prosrc }}$BODY$
+{% endif %}
+LANGUAGE {{ data.lanname|qtLiteral }} {{ data.provolatile }}{% if data.proisstrict %} STRICT{% endif %}
+{% if data.prosecdef %} SECURITY DEFINER{% endif %}
+{% if data.proiswindow %} WINDOW{% endif %}{% if data.procost %}
+
+COST {{data.procost}}{% endif %}{% if data.prorows %}
+
+ROWS {{data.prorows}}{% endif -%}{% if data.variables %}
+
+{% for v in data.variables %}
+
+SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+{% endif -%};
+
+{% if data.funcowner %}
+
+ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data
+.func_args}})
+    OWNER TO {{ 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)}}
+{% endfor %}
+{% endif -%}
+
+{% if data.description %}
+
+COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data
+.func_args}})
+    IS '{{ data.description }}';
+{% endif -%}
+
+{% if data.seclabels %}
+{% for r in data.seclabels %}
+{% if r.label and r.provider %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', data.name, r.provider, r.label, data
+.pronamespace, data.func_args) }}
+{% endif %}
+{% endfor %}
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/delete.sql
new file mode 100644
index 0000000..246bec1
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/delete.sql
@@ -0,0 +1,21 @@
+{% if scid and fnid %}
+SELECT
+    pr.proname as name, '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args,
+    nspname
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.oid = {{fnid}};
+{% endif %}
+
+{% if name %}
+DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %};
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_definition.sql
new file mode 100644
index 0000000..c635f1e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_definition.sql
@@ -0,0 +1,12 @@
+SELECT
+    pg_get_functiondef({{fnid}}::oid) AS func_def,
+    nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name
+FROM
+    pg_proc pr
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND pr.oid = {{fnid}}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_languages.sql
new file mode 100644
index 0000000..f81ddfb
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_languages.sql
@@ -0,0 +1,4 @@
+SELECT
+    lanname as label, lanname as value
+FROM
+    pg_language;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_oid.sql
new file mode 100644
index 0000000..2bc76a2
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_oid.sql
@@ -0,0 +1,17 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
+    lanname, pg_get_userbyid(proowner) as funcowner
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+    AND nsp.nspname={{ nspname|qtLiteral }}
+WHERE
+    proisagg = FALSE
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.proname = {{ name|qtLiteral }};
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_out_types.sql
new file mode 100644
index 0000000..64a1187
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_out_types.sql
@@ -0,0 +1,6 @@
+SELECT
+    format_type(oid, NULL) AS out_arg_type
+FROM
+    pg_type
+WHERE
+    oid = {{ out_arg_oid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_schema.sql
@@ -0,0 +1,6 @@
+SELECT
+    nspname
+FROM
+    pg_namespace
+WHERE
+    oid = {{ scid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_types.sql
new file mode 100644
index 0000000..2a5582e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/get_types.sql
@@ -0,0 +1,20 @@
+SELECT
+    *
+FROM
+    (SELECT
+        format_type(t.oid,NULL) AS typname,
+        CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname,
+        (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup
+    FROM
+        pg_type t
+    JOIN
+        pg_namespace nsp ON typnamespace=nsp.oid
+    WHERE
+        (NOT (typname = 'unknown' AND nspname = 'pg_catalog'))
+    AND
+        (
+            typtype IN ('b', 'c', 'd', 'e', 'p', 'r')
+            AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger')
+        )
+    ) AS dummy
+ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/node.sql
new file mode 100644
index 0000000..5e62cd8
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/node.sql
@@ -0,0 +1,18 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
+    lanname, pg_get_userbyid(proowner) as funcowner, description
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/properties.sql
new file mode 100644
index 0000000..9e8a8ba
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/properties.sql
@@ -0,0 +1,31 @@
+SELECT
+    pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c,
+    pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename,
+    typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames,
+    pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
+    pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description,
+    (SELECT
+        array_agg(provider || '=' || label)
+    FROM
+        pg_seclabel sl1
+    WHERE
+        sl1.objoid=pr.oid) AS seclabels
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace typns ON typns.oid=typ.typnamespace
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+{% if fnid %}
+    AND pr.oid = {{fnid}}::oid
+{% endif %}
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/update.sql
new file mode 100644
index 0000000..358454b
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/update.sql
@@ -0,0 +1,132 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %}
+{% set name = o_data.name %}
+{% 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 {{ o_data.prorettypename }} AS
+{% if 'lanname' in lanname and data.lanname == 'c' %}
+{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
+{% elif 'lanname' in data and '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 -%}
+
+{% if 'lanname' in data %}
+LANGUAGE {{ data.lanname|qtLiteral }}{% else %}
+LANGUAGE {{ o_data.lanname|qtLiteral }}{% 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 data.procost %}
+
+COST {{data.procost}}{% elif o_data.procost %} COST {{o_data.procost}} {% endif %}{% if data.prorows %}
+
+ROWS {{data.prorows}} {% elif o_data.prorows %} ROWS {{o_data.prorows}} {%
+endif -%}{% if data.merged_variables %}
+
+{% for v in data.merged_variables %}
+
+SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+{% endif -%};
+{% endif -%}
+
+{% if data.funcowner %}
+
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{
+o_data.proargtypenames }})
+    OWNER TO {{ 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.datacl %}
+{% for priv in data.acl.changed %}
+
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data
+.pronamespace, o_data.proargtypenames) }}
+{{ 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 %}
+
+{{ SECLABLE.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+
+{% if 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/function/pg/sql/9.1_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/variables.sql
new file mode 100644
index 0000000..5233c71
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.1_plus/variables.sql
@@ -0,0 +1,6 @@
+SELECT
+    name, vartype, min_val, max_val, enumvals
+FROM
+    pg_settings
+WHERE
+    context in ('user', 'superuser');
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/acl.sql
new file mode 100644
index 0000000..ad3e0d1
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/acl.sql
@@ -0,0 +1,35 @@
+SELECT
+    COALESCE(gt.rolname, 'public') AS grantee,
+    g.rolname AS grantor, array_agg(privilege_type) AS privileges,
+    array_agg(is_grantable) AS grantable
+FROM
+    (SELECT
+        d.grantee, d.grantor, d.is_grantable,
+        CASE d.privilege_type
+        WHEN 'CONNECT' THEN 'c'
+        WHEN 'CREATE' THEN 'C'
+        WHEN 'DELETE' THEN 'd'
+        WHEN 'EXECUTE' THEN 'X'
+        WHEN 'INSERT' THEN 'a'
+        WHEN 'REFERENCES' THEN 'x'
+        WHEN 'SELECT' THEN 'r'
+        WHEN 'TEMPORARY' THEN 'T'
+        WHEN 'TRIGGER' THEN 't'
+        WHEN 'TRUNCATE' THEN 'D'
+        WHEN 'UPDATE' THEN 'w'
+        WHEN 'USAGE' THEN 'U'
+        ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            (d).grantee AS grantee, (d).grantor AS grantor,
+            (d).is_grantable AS is_grantable,
+            (d).privilege_type AS privilege_type
+        FROM
+            (SELECT aclexplode(db.proacl) AS d FROM pg_proc db
+            WHERE db.oid = {{fnid}}::OID) a
+        ) d
+    ) d
+    LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
+    LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
+GROUP BY g.rolname, gt.rolname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/create.sql
new file mode 100644
index 0000000..80a4676
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/create.sql
@@ -0,0 +1,68 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}
+{% set is_columns = [] %}
+{% if data %}
+CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({% if data
+.arguments %}
+{% for p in data.arguments %}{{p.argmode}} {% 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 data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data
+    .prorettypename) }} AS
+{% if data.lanname == 'c' %}
+{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
+{% else %}
+$BODY${{ data.prosrc }}$BODY$
+{% endif %}
+LANGUAGE {{ data.lanname|qtLiteral }} {{ data.provolatile }}{% if data
+.proleakproof %} LEAKPROOF{% else %} NOT LEAKPROOF{% endif %}
+{% if data.proisstrict %} STRICT{% endif %}
+{% if data.prosecdef %} SECURITY DEFINER{% endif %}
+{% if data.proiswindow %} WINDOW{% endif %}{% if data.procost %}
+
+COST {{data.procost}}{% endif %}{% if data.prorows %}
+
+ROWS {{data.prorows}}{% endif -%}{% if data.variables %}
+
+{% for v in data.variables %}
+
+SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+{% endif -%};
+
+{% if data.funcowner %}
+
+ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data
+.func_args}})
+    OWNER TO {{ 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)}}
+{% endfor %}
+{% endif -%}
+
+{% if data.description %}
+
+COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data
+.func_args}})
+    IS '{{ data.description }}';
+{% endif -%}
+
+{% if data.seclabels %}
+{% for r in data.seclabels %}
+{% if r.label and r.provider %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', data.name, r.provider, r.label, data
+.pronamespace, data.func_args) }}
+{% endif %}
+{% endfor %}
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/delete.sql
new file mode 100644
index 0000000..246bec1
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/delete.sql
@@ -0,0 +1,21 @@
+{% if scid and fnid %}
+SELECT
+    pr.proname as name, '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args,
+    nspname
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.oid = {{fnid}};
+{% endif %}
+
+{% if name %}
+DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %};
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_definition.sql
new file mode 100644
index 0000000..c635f1e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_definition.sql
@@ -0,0 +1,12 @@
+SELECT
+    pg_get_functiondef({{fnid}}::oid) AS func_def,
+    nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name
+FROM
+    pg_proc pr
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND pr.oid = {{fnid}}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_languages.sql
new file mode 100644
index 0000000..f81ddfb
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_languages.sql
@@ -0,0 +1,4 @@
+SELECT
+    lanname as label, lanname as value
+FROM
+    pg_language;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_oid.sql
new file mode 100644
index 0000000..2bc76a2
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_oid.sql
@@ -0,0 +1,17 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
+    lanname, pg_get_userbyid(proowner) as funcowner
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+    AND nsp.nspname={{ nspname|qtLiteral }}
+WHERE
+    proisagg = FALSE
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.proname = {{ name|qtLiteral }};
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_out_types.sql
new file mode 100644
index 0000000..64a1187
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_out_types.sql
@@ -0,0 +1,6 @@
+SELECT
+    format_type(oid, NULL) AS out_arg_type
+FROM
+    pg_type
+WHERE
+    oid = {{ out_arg_oid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_schema.sql
@@ -0,0 +1,6 @@
+SELECT
+    nspname
+FROM
+    pg_namespace
+WHERE
+    oid = {{ scid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_types.sql
new file mode 100644
index 0000000..2a5582e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/get_types.sql
@@ -0,0 +1,20 @@
+SELECT
+    *
+FROM
+    (SELECT
+        format_type(t.oid,NULL) AS typname,
+        CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname,
+        (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup
+    FROM
+        pg_type t
+    JOIN
+        pg_namespace nsp ON typnamespace=nsp.oid
+    WHERE
+        (NOT (typname = 'unknown' AND nspname = 'pg_catalog'))
+    AND
+        (
+            typtype IN ('b', 'c', 'd', 'e', 'p', 'r')
+            AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger')
+        )
+    ) AS dummy
+ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/node.sql
new file mode 100644
index 0000000..5e62cd8
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/node.sql
@@ -0,0 +1,18 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
+    lanname, pg_get_userbyid(proowner) as funcowner, description
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/properties.sql
new file mode 100644
index 0000000..ff78298
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/properties.sql
@@ -0,0 +1,31 @@
+SELECT
+    pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c,
+    pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename,
+    typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames,
+    pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
+    pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description,
+    (SELECT
+        array_agg(provider || '=' || label)
+    FROM
+        pg_shseclabel sl1
+    WHERE
+        sl1.objoid=pr.oid) AS seclabels
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace typns ON typns.oid=typ.typnamespace
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+{% if fnid %}
+    AND pr.oid = {{fnid}}::oid
+{% endif %}
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/update.sql
new file mode 100644
index 0000000..cb1f081
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/update.sql
@@ -0,0 +1,132 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %}
+{% set name = o_data.name %}
+{% 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 {{ o_data.prorettypename }} AS
+{% if 'lanname' in lanname and data.lanname == 'c' %}
+{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
+{% elif 'lanname' in data and '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 -%}
+
+{% if 'lanname' in data %}
+LANGUAGE {{ data.lanname|qtLiteral }}{% else %}
+LANGUAGE {{ o_data.lanname|qtLiteral }}{% endif -%}{% 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 ('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 data.procost %}
+
+COST {{data.procost}}{% elif o_data.procost %} COST {{o_data.procost}} {% endif %}{% if data.prorows %}
+
+ROWS {{data.prorows}} {% elif o_data.prorows %} ROWS {{o_data.prorows}} {%
+endif -%}{% if data.merged_variables %}
+
+{% for v in data.merged_variables %}
+
+SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+{% endif -%};
+{% endif -%}
+
+{% if data.funcowner %}
+
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{
+o_data.proargtypenames }})
+    OWNER TO {{ 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.datacl %}
+{% for priv in data.acl.changed %}
+
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data
+.pronamespace, o_data.proargtypenames) }}
+{{ 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 %}
+
+{{ SECLABLE.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+
+{% if 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/function/pg/sql/9.2_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/variables.sql
new file mode 100644
index 0000000..5233c71
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.2_plus/variables.sql
@@ -0,0 +1,6 @@
+SELECT
+    name, vartype, min_val, max_val, enumvals
+FROM
+    pg_settings
+WHERE
+    context in ('user', 'superuser');
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/acl.sql
new file mode 100644
index 0000000..ad3e0d1
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/acl.sql
@@ -0,0 +1,35 @@
+SELECT
+    COALESCE(gt.rolname, 'public') AS grantee,
+    g.rolname AS grantor, array_agg(privilege_type) AS privileges,
+    array_agg(is_grantable) AS grantable
+FROM
+    (SELECT
+        d.grantee, d.grantor, d.is_grantable,
+        CASE d.privilege_type
+        WHEN 'CONNECT' THEN 'c'
+        WHEN 'CREATE' THEN 'C'
+        WHEN 'DELETE' THEN 'd'
+        WHEN 'EXECUTE' THEN 'X'
+        WHEN 'INSERT' THEN 'a'
+        WHEN 'REFERENCES' THEN 'x'
+        WHEN 'SELECT' THEN 'r'
+        WHEN 'TEMPORARY' THEN 'T'
+        WHEN 'TRIGGER' THEN 't'
+        WHEN 'TRUNCATE' THEN 'D'
+        WHEN 'UPDATE' THEN 'w'
+        WHEN 'USAGE' THEN 'U'
+        ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            (d).grantee AS grantee, (d).grantor AS grantor,
+            (d).is_grantable AS is_grantable,
+            (d).privilege_type AS privilege_type
+        FROM
+            (SELECT aclexplode(db.proacl) AS d FROM pg_proc db
+            WHERE db.oid = {{fnid}}::OID) a
+        ) d
+    ) d
+    LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
+    LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
+GROUP BY g.rolname, gt.rolname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/create.sql
new file mode 100644
index 0000000..1d7f465
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/create.sql
@@ -0,0 +1,67 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}
+{% set is_columns = [] %}
+{% if data %}
+CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({% if data
+.arguments %}
+{% for p in data.arguments %}{{p.argmode}} {% 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 data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data
+    .prorettypename) }} AS
+{% if data.lanname == 'c' %}
+{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
+{% else %}
+$BODY${{ data.prosrc }}$BODY$
+{% endif %}
+LANGUAGE {{ data.lanname|qtLiteral }} {{ data.provolatile }}{% if data
+.proleakproof %} LEAKPROOF{% else %} NOT LEAKPROOF{% endif %}
+{% if data.proisstrict %} STRICT{% endif %}
+{% if data.prosecdef %} SECURITY DEFINER{% endif %}
+{% if data.proiswindow %} WINDOW{% endif %}{% if data.procost %}
+
+COST {{data.procost}}{% endif %}{% if data.prorows %}
+
+ROWS {{data.prorows}}{% endif -%}{% if data.variables %}
+
+{% for v in data.variables %}
+
+SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+{% endif -%};
+
+{% if data.funcowner %}
+
+ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data
+.func_args}})
+    OWNER TO {{ 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)}}
+{% endfor %}
+{% endif -%}
+
+{% if data.description %}
+
+COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data
+.func_args}})
+    IS '{{ data.description }}';
+{% endif -%}
+
+{% if data.seclabels %}
+{% for r in data.seclabels %}
+{% if r.label and r.provider %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', data.name, r.provider, r.label, data
+.pronamespace, data.func_args) }}
+{% endif %}
+{% endfor %}
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/delete.sql
new file mode 100644
index 0000000..246bec1
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/delete.sql
@@ -0,0 +1,21 @@
+{% if scid and fnid %}
+SELECT
+    pr.proname as name, '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args,
+    nspname
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.oid = {{fnid}};
+{% endif %}
+
+{% if name %}
+DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %};
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_definition.sql
new file mode 100644
index 0000000..c635f1e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_definition.sql
@@ -0,0 +1,12 @@
+SELECT
+    pg_get_functiondef({{fnid}}::oid) AS func_def,
+    nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name
+FROM
+    pg_proc pr
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND pr.oid = {{fnid}}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_languages.sql
new file mode 100644
index 0000000..f81ddfb
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_languages.sql
@@ -0,0 +1,4 @@
+SELECT
+    lanname as label, lanname as value
+FROM
+    pg_language;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_oid.sql
new file mode 100644
index 0000000..2bc76a2
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_oid.sql
@@ -0,0 +1,17 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
+    lanname, pg_get_userbyid(proowner) as funcowner
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+    AND nsp.nspname={{ nspname|qtLiteral }}
+WHERE
+    proisagg = FALSE
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.proname = {{ name|qtLiteral }};
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_out_types.sql
new file mode 100644
index 0000000..64a1187
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_out_types.sql
@@ -0,0 +1,6 @@
+SELECT
+    format_type(oid, NULL) AS out_arg_type
+FROM
+    pg_type
+WHERE
+    oid = {{ out_arg_oid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_schema.sql
@@ -0,0 +1,6 @@
+SELECT
+    nspname
+FROM
+    pg_namespace
+WHERE
+    oid = {{ scid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_types.sql
new file mode 100644
index 0000000..2a5582e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/get_types.sql
@@ -0,0 +1,20 @@
+SELECT
+    *
+FROM
+    (SELECT
+        format_type(t.oid,NULL) AS typname,
+        CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname,
+        (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup
+    FROM
+        pg_type t
+    JOIN
+        pg_namespace nsp ON typnamespace=nsp.oid
+    WHERE
+        (NOT (typname = 'unknown' AND nspname = 'pg_catalog'))
+    AND
+        (
+            typtype IN ('b', 'c', 'd', 'e', 'p', 'r')
+            AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger')
+        )
+    ) AS dummy
+ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/node.sql
new file mode 100644
index 0000000..5e62cd8
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/node.sql
@@ -0,0 +1,18 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
+    lanname, pg_get_userbyid(proowner) as funcowner, description
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/properties.sql
new file mode 100644
index 0000000..ff78298
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/properties.sql
@@ -0,0 +1,31 @@
+SELECT
+    pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c,
+    pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename,
+    typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames,
+    pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
+    pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description,
+    (SELECT
+        array_agg(provider || '=' || label)
+    FROM
+        pg_shseclabel sl1
+    WHERE
+        sl1.objoid=pr.oid) AS seclabels
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace typns ON typns.oid=typ.typnamespace
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+{% if fnid %}
+    AND pr.oid = {{fnid}}::oid
+{% endif %}
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/update.sql
new file mode 100644
index 0000000..8b28134
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/update.sql
@@ -0,0 +1,132 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %}
+{% set name = o_data.name %}
+{% 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 {{ o_data.prorettypename }} AS
+{% if 'lanname' in lanname and data.lanname == 'c' %}
+{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
+{% elif 'lanname' in data and '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 -%}
+
+{% if 'lanname' in data %}
+LANGUAGE {{ data.lanname|qtLiteral }}{% else %}
+LANGUAGE {{ o_data.lanname|qtLiteral }}{% endif -%}{% 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 ('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 data.procost %}
+
+COST {{data.procost}}{% elif o_data.procost %} COST {{o_data.procost}} {% endif %}{% if data.prorows %}
+
+ROWS {{data.prorows}} {% elif o_data.prorows %} ROWS {{o_data.prorows}} {%
+endif -%}{% if data.merged_variables %}
+
+{% for v in data.merged_variables %}
+
+SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+{% endif -%};
+{% endif -%}
+
+{% if data.funcowner %}
+
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{
+o_data.proargtypenames }})
+    OWNER TO {{ 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.datacl %}
+{% for priv in data.acl.changed %}
+
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data
+.pronamespace, o_data.proargtypenames) }}
+{{ 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 %}
+
+{{ SECLABLE.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+
+{% if 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/function/pg/sql/9.5_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/variables.sql
new file mode 100644
index 0000000..5233c71
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/pg/sql/9.5_plus/variables.sql
@@ -0,0 +1,6 @@
+SELECT
+    name, vartype, min_val, max_val, enumvals
+FROM
+    pg_settings
+WHERE
+    context in ('user', 'superuser');
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/acl.sql
new file mode 100644
index 0000000..ad3e0d1
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/acl.sql
@@ -0,0 +1,35 @@
+SELECT
+    COALESCE(gt.rolname, 'public') AS grantee,
+    g.rolname AS grantor, array_agg(privilege_type) AS privileges,
+    array_agg(is_grantable) AS grantable
+FROM
+    (SELECT
+        d.grantee, d.grantor, d.is_grantable,
+        CASE d.privilege_type
+        WHEN 'CONNECT' THEN 'c'
+        WHEN 'CREATE' THEN 'C'
+        WHEN 'DELETE' THEN 'd'
+        WHEN 'EXECUTE' THEN 'X'
+        WHEN 'INSERT' THEN 'a'
+        WHEN 'REFERENCES' THEN 'x'
+        WHEN 'SELECT' THEN 'r'
+        WHEN 'TEMPORARY' THEN 'T'
+        WHEN 'TRIGGER' THEN 't'
+        WHEN 'TRUNCATE' THEN 'D'
+        WHEN 'UPDATE' THEN 'w'
+        WHEN 'USAGE' THEN 'U'
+        ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            (d).grantee AS grantee, (d).grantor AS grantor,
+            (d).is_grantable AS is_grantable,
+            (d).privilege_type AS privilege_type
+        FROM
+            (SELECT aclexplode(db.proacl) AS d FROM pg_proc db
+            WHERE db.oid = {{fnid}}::OID) a
+        ) d
+    ) d
+    LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
+    LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
+GROUP BY g.rolname, gt.rolname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/create.sql
new file mode 100644
index 0000000..8f19af2
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/create.sql
@@ -0,0 +1,66 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}
+{% set is_columns = [] %}
+{% if data %}
+CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({% if data
+.arguments %}
+{% for p in data.arguments %}{{p.argmode}} {% 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 data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data
+    .prorettypename) }} AS
+{% if data.lanname == 'c' %}
+{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
+{% else %}
+$BODY${{ data.prosrc }}$BODY$
+{% endif %}
+LANGUAGE {{ data.lanname|qtLiteral }} {{ data.provolatile }}{% if data
+.proleakproof %} LEAKPROOF{% else %} NOT LEAKPROOF{% endif %}
+{% if data.proisstrict %} STRICT{% endif %}
+{% if data.prosecdef %} SECURITY DEFINER{% endif %}
+{% if data.proiswindow %} WINDOW{% endif %}{% if data.procost %}
+
+COST {{data.procost}}{% endif %}{% if data.prorows %}
+
+ROWS {{data.prorows}}{% endif -%}{% if data.variables %}
+
+{% for v in data.variables %}
+
+SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+{% endif -%};
+
+{% if data.funcowner %}
+
+ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data
+.func_args}})
+    OWNER TO {{ 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)}}
+{% endfor %}
+{% endif -%}
+
+{% if data.description %}
+
+COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data
+.func_args}})
+    IS '{{ data.description }}';
+{% endif -%}
+
+{% if data.seclabels %}
+{% for r in data.seclabels %}
+{% if r.label and r.provider %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', data.name, r.provider, r.label, data
+.pronamespace, data.func_args) }}
+{% endif %}
+{% endfor %}
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/delete.sql
new file mode 100644
index 0000000..246bec1
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/delete.sql
@@ -0,0 +1,21 @@
+{% if scid and fnid %}
+SELECT
+    pr.proname as name, '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args,
+    nspname
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.oid = {{fnid}};
+{% endif %}
+
+{% if name %}
+DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %};
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_definition.sql
new file mode 100644
index 0000000..c635f1e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_definition.sql
@@ -0,0 +1,12 @@
+SELECT
+    pg_get_functiondef({{fnid}}::oid) AS func_def,
+    nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name
+FROM
+    pg_proc pr
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND pr.oid = {{fnid}}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_languages.sql
new file mode 100644
index 0000000..f81ddfb
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_languages.sql
@@ -0,0 +1,4 @@
+SELECT
+    lanname as label, lanname as value
+FROM
+    pg_language;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_oid.sql
new file mode 100644
index 0000000..2bc76a2
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_oid.sql
@@ -0,0 +1,17 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
+    lanname, pg_get_userbyid(proowner) as funcowner
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+    AND nsp.nspname={{ nspname|qtLiteral }}
+WHERE
+    proisagg = FALSE
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.proname = {{ name|qtLiteral }};
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_out_types.sql
new file mode 100644
index 0000000..64a1187
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_out_types.sql
@@ -0,0 +1,6 @@
+SELECT
+    format_type(oid, NULL) AS out_arg_type
+FROM
+    pg_type
+WHERE
+    oid = {{ out_arg_oid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_schema.sql
@@ -0,0 +1,6 @@
+SELECT
+    nspname
+FROM
+    pg_namespace
+WHERE
+    oid = {{ scid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_types.sql
new file mode 100644
index 0000000..2a5582e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/get_types.sql
@@ -0,0 +1,20 @@
+SELECT
+    *
+FROM
+    (SELECT
+        format_type(t.oid,NULL) AS typname,
+        CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname,
+        (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup
+    FROM
+        pg_type t
+    JOIN
+        pg_namespace nsp ON typnamespace=nsp.oid
+    WHERE
+        (NOT (typname = 'unknown' AND nspname = 'pg_catalog'))
+    AND
+        (
+            typtype IN ('b', 'c', 'd', 'e', 'p', 'r')
+            AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger')
+        )
+    ) AS dummy
+ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/node.sql
new file mode 100644
index 0000000..c6d171b
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/node.sql
@@ -0,0 +1,19 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' AS name,
+    lanname, pg_get_userbyid(proowner) AS funcowner, description
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pr.protype = '0'::char
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/properties.sql
new file mode 100644
index 0000000..9e8a8ba
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/properties.sql
@@ -0,0 +1,31 @@
+SELECT
+    pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c,
+    pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename,
+    typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames,
+    pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
+    pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description,
+    (SELECT
+        array_agg(provider || '=' || label)
+    FROM
+        pg_seclabel sl1
+    WHERE
+        sl1.objoid=pr.oid) AS seclabels
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace typns ON typns.oid=typ.typnamespace
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+{% if fnid %}
+    AND pr.oid = {{fnid}}::oid
+{% endif %}
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/update.sql
new file mode 100644
index 0000000..d38d55d
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/update.sql
@@ -0,0 +1,131 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %}
+{% set name = o_data.name %}
+{% 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 {{ o_data.prorettypename }} AS
+{% if 'lanname' in lanname and data.lanname == 'c' %}
+{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
+{% elif 'lanname' in data and '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 -%}
+
+{% if 'lanname' in data %}
+LANGUAGE {{ data.lanname|qtLiteral }}{% else %}
+LANGUAGE {{ o_data.lanname|qtLiteral }}{% 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 data.procost %}
+
+COST {{data.procost}}{% elif o_data.procost %} COST {{o_data.procost}} {% endif %}{% if data.prorows %}
+
+ROWS {{data.prorows}} {% elif o_data.prorows %} ROWS {{o_data.prorows}} {%
+endif -%}{% if data.merged_variables %}
+
+{% for v in data.merged_variables %}
+
+SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+{% endif -%};
+{% endif -%}
+
+{% if data.funcowner %}
+
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{
+o_data.proargtypenames }})
+    OWNER TO {{ 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.datacl %}
+{% for priv in data.acl.changed %}
+
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data
+.pronamespace, o_data.proargtypenames) }}
+{{ 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 %}
+
+{{ SECLABLE.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+
+{% if 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/function/ppas/sql/9.1_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/variables.sql
new file mode 100644
index 0000000..5233c71
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.1_plus/variables.sql
@@ -0,0 +1,6 @@
+SELECT
+    name, vartype, min_val, max_val, enumvals
+FROM
+    pg_settings
+WHERE
+    context in ('user', 'superuser');
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/acl.sql
new file mode 100644
index 0000000..ad3e0d1
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/acl.sql
@@ -0,0 +1,35 @@
+SELECT
+    COALESCE(gt.rolname, 'public') AS grantee,
+    g.rolname AS grantor, array_agg(privilege_type) AS privileges,
+    array_agg(is_grantable) AS grantable
+FROM
+    (SELECT
+        d.grantee, d.grantor, d.is_grantable,
+        CASE d.privilege_type
+        WHEN 'CONNECT' THEN 'c'
+        WHEN 'CREATE' THEN 'C'
+        WHEN 'DELETE' THEN 'd'
+        WHEN 'EXECUTE' THEN 'X'
+        WHEN 'INSERT' THEN 'a'
+        WHEN 'REFERENCES' THEN 'x'
+        WHEN 'SELECT' THEN 'r'
+        WHEN 'TEMPORARY' THEN 'T'
+        WHEN 'TRIGGER' THEN 't'
+        WHEN 'TRUNCATE' THEN 'D'
+        WHEN 'UPDATE' THEN 'w'
+        WHEN 'USAGE' THEN 'U'
+        ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            (d).grantee AS grantee, (d).grantor AS grantor,
+            (d).is_grantable AS is_grantable,
+            (d).privilege_type AS privilege_type
+        FROM
+            (SELECT aclexplode(db.proacl) AS d FROM pg_proc db
+            WHERE db.oid = {{fnid}}::OID) a
+        ) d
+    ) d
+    LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
+    LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
+GROUP BY g.rolname, gt.rolname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/create.sql
new file mode 100644
index 0000000..69ae3b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/create.sql
@@ -0,0 +1,66 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}
+{% set is_columns = [] %}
+{% if data %}
+CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({% if data
+.arguments %}
+{% for p in data.arguments %}{{p.argmode}} {% 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 data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data
+    .prorettypename) }} AS
+{% if data.lanname == 'c' %}
+{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
+{% else %}
+$BODY${{ data.prosrc }}$BODY$
+{% endif %}
+LANGUAGE {{ data.lanname|qtLiteral }} {{ data.pronargs }}{% if data
+.proleakproof %} LEAKPROOF{% else %} NOT LEAKPROOF{% endif %}
+{% if data.proisstrict %} STRICT{% endif %}
+{% if data.prosecdef %} SECURITY DEFINER{% endif %}
+{% if data.proiswindow %} WINDOW{% endif %}{% if data.procost %}
+
+COST {{data.procost}}{% endif %}{% if data.prorows %}
+
+ROWS {{data.prorows}}{% endif -%}{% if data.variables %}
+
+{% for v in data.variables %}
+
+SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+{% endif -%};
+
+{% if data.funcowner %}
+
+ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data
+.func_args}})
+    OWNER TO {{ 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)}}
+{% endfor %}
+{% endif -%}
+
+{% if data.description %}
+
+COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data
+.func_args}})
+    IS '{{ data.description }}';
+{% endif -%}
+
+{% if data.seclabels %}
+{% for r in data.seclabels %}
+{% if r.label and r.provider %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', data.name, r.provider, r.label, data
+.pronamespace, data.func_args) }}
+{% endif %}
+{% endfor %}
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/delete.sql
new file mode 100644
index 0000000..c24970c
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/delete.sql
@@ -0,0 +1,22 @@
+{% if scid and fnid %}
+SELECT
+    pr.proname as name, '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args,
+    nspname
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.oid = {{fnid}};
+{% endif %}
+
+{% if name %}
+DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade%} CASCADE{%
+endif %};
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_definition.sql
new file mode 100644
index 0000000..c635f1e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_definition.sql
@@ -0,0 +1,12 @@
+SELECT
+    pg_get_functiondef({{fnid}}::oid) AS func_def,
+    nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name
+FROM
+    pg_proc pr
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND pr.oid = {{fnid}}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_languages.sql
new file mode 100644
index 0000000..f81ddfb
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_languages.sql
@@ -0,0 +1,4 @@
+SELECT
+    lanname as label, lanname as value
+FROM
+    pg_language;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_oid.sql
new file mode 100644
index 0000000..2bc76a2
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_oid.sql
@@ -0,0 +1,17 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
+    lanname, pg_get_userbyid(proowner) as funcowner
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+    AND nsp.nspname={{ nspname|qtLiteral }}
+WHERE
+    proisagg = FALSE
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.proname = {{ name|qtLiteral }};
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_out_types.sql
new file mode 100644
index 0000000..64a1187
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_out_types.sql
@@ -0,0 +1,6 @@
+SELECT
+    format_type(oid, NULL) AS out_arg_type
+FROM
+    pg_type
+WHERE
+    oid = {{ out_arg_oid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_schema.sql
@@ -0,0 +1,6 @@
+SELECT
+    nspname
+FROM
+    pg_namespace
+WHERE
+    oid = {{ scid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_types.sql
new file mode 100644
index 0000000..2a5582e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/get_types.sql
@@ -0,0 +1,20 @@
+SELECT
+    *
+FROM
+    (SELECT
+        format_type(t.oid,NULL) AS typname,
+        CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname,
+        (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup
+    FROM
+        pg_type t
+    JOIN
+        pg_namespace nsp ON typnamespace=nsp.oid
+    WHERE
+        (NOT (typname = 'unknown' AND nspname = 'pg_catalog'))
+    AND
+        (
+            typtype IN ('b', 'c', 'd', 'e', 'p', 'r')
+            AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger')
+        )
+    ) AS dummy
+ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/node.sql
new file mode 100644
index 0000000..c6d171b
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/node.sql
@@ -0,0 +1,19 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' AS name,
+    lanname, pg_get_userbyid(proowner) AS funcowner, description
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pr.protype = '0'::char
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/properties.sql
new file mode 100644
index 0000000..ff78298
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/properties.sql
@@ -0,0 +1,31 @@
+SELECT
+    pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c,
+    pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename,
+    typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames,
+    pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
+    pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description,
+    (SELECT
+        array_agg(provider || '=' || label)
+    FROM
+        pg_shseclabel sl1
+    WHERE
+        sl1.objoid=pr.oid) AS seclabels
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace typns ON typns.oid=typ.typnamespace
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+{% if fnid %}
+    AND pr.oid = {{fnid}}::oid
+{% endif %}
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/update.sql
new file mode 100644
index 0000000..d2a3aa8
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/update.sql
@@ -0,0 +1,132 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %}
+{% set name = o_data.name %}
+{% 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 {{ o_data.prorettypename }} AS
+{% if 'lanname' in lanname and data.lanname == 'c' %}
+{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
+{% elif 'lanname' in data and '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 -%}
+
+{% if 'lanname' in data %}
+LANGUAGE {{ data.lanname|qtLiteral }}{% else %}
+LANGUAGE {{ o_data.lanname|qtLiteral }}{% endif -%}{% 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 ('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 data.procost %}
+
+COST {{data.procost}}{% elif o_data.procost %} COST {{o_data.procost}} {% endif %}{% if data.prorows %}
+
+ROWS {{data.prorows}} {% elif o_data.prorows %} ROWS {{o_data.prorows}} {%
+endif -%}{% if data.merged_variables %}
+
+{% for v in data.merged_variables %}
+
+SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+{% endif -%};
+{% endif -%}
+
+{% if data.funcowner %}
+
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{
+o_data.proargtypenames }})
+    OWNER TO {{ 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.datacl %}
+{% for priv in data.acl.changed %}
+
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data
+.pronamespace, o_data.proargtypenames) }}
+{{ 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 %}
+
+{{ SECLABLE.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+
+{% if 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/function/ppas/sql/9.2_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/variables.sql
new file mode 100644
index 0000000..5233c71
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.2_plus/variables.sql
@@ -0,0 +1,6 @@
+SELECT
+    name, vartype, min_val, max_val, enumvals
+FROM
+    pg_settings
+WHERE
+    context in ('user', 'superuser');
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/acl.sql
new file mode 100644
index 0000000..ad3e0d1
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/acl.sql
@@ -0,0 +1,35 @@
+SELECT
+    COALESCE(gt.rolname, 'public') AS grantee,
+    g.rolname AS grantor, array_agg(privilege_type) AS privileges,
+    array_agg(is_grantable) AS grantable
+FROM
+    (SELECT
+        d.grantee, d.grantor, d.is_grantable,
+        CASE d.privilege_type
+        WHEN 'CONNECT' THEN 'c'
+        WHEN 'CREATE' THEN 'C'
+        WHEN 'DELETE' THEN 'd'
+        WHEN 'EXECUTE' THEN 'X'
+        WHEN 'INSERT' THEN 'a'
+        WHEN 'REFERENCES' THEN 'x'
+        WHEN 'SELECT' THEN 'r'
+        WHEN 'TEMPORARY' THEN 'T'
+        WHEN 'TRIGGER' THEN 't'
+        WHEN 'TRUNCATE' THEN 'D'
+        WHEN 'UPDATE' THEN 'w'
+        WHEN 'USAGE' THEN 'U'
+        ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            (d).grantee AS grantee, (d).grantor AS grantor,
+            (d).is_grantable AS is_grantable,
+            (d).privilege_type AS privilege_type
+        FROM
+            (SELECT aclexplode(db.proacl) AS d FROM pg_proc db
+            WHERE db.oid = {{fnid}}::OID) a
+        ) d
+    ) d
+    LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
+    LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
+GROUP BY g.rolname, gt.rolname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/create.sql
new file mode 100644
index 0000000..69ae3b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/create.sql
@@ -0,0 +1,66 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}
+{% set is_columns = [] %}
+{% if data %}
+CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({% if data
+.arguments %}
+{% for p in data.arguments %}{{p.argmode}} {% 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 data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data
+    .prorettypename) }} AS
+{% if data.lanname == 'c' %}
+{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
+{% else %}
+$BODY${{ data.prosrc }}$BODY$
+{% endif %}
+LANGUAGE {{ data.lanname|qtLiteral }} {{ data.pronargs }}{% if data
+.proleakproof %} LEAKPROOF{% else %} NOT LEAKPROOF{% endif %}
+{% if data.proisstrict %} STRICT{% endif %}
+{% if data.prosecdef %} SECURITY DEFINER{% endif %}
+{% if data.proiswindow %} WINDOW{% endif %}{% if data.procost %}
+
+COST {{data.procost}}{% endif %}{% if data.prorows %}
+
+ROWS {{data.prorows}}{% endif -%}{% if data.variables %}
+
+{% for v in data.variables %}
+
+SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+{% endif -%};
+
+{% if data.funcowner %}
+
+ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data
+.func_args}})
+    OWNER TO {{ 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)}}
+{% endfor %}
+{% endif -%}
+
+{% if data.description %}
+
+COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data
+.func_args}})
+    IS '{{ data.description }}';
+{% endif -%}
+
+{% if data.seclabels %}
+{% for r in data.seclabels %}
+{% if r.label and r.provider %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', data.name, r.provider, r.label, data
+.pronamespace, data.func_args) }}
+{% endif %}
+{% endfor %}
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/delete.sql
new file mode 100644
index 0000000..246bec1
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/delete.sql
@@ -0,0 +1,21 @@
+{% if scid and fnid %}
+SELECT
+    pr.proname as name, '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args,
+    nspname
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.oid = {{fnid}};
+{% endif %}
+
+{% if name %}
+DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %};
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_definition.sql
new file mode 100644
index 0000000..c635f1e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_definition.sql
@@ -0,0 +1,12 @@
+SELECT
+    pg_get_functiondef({{fnid}}::oid) AS func_def,
+    nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name
+FROM
+    pg_proc pr
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND pr.oid = {{fnid}}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_languages.sql
new file mode 100644
index 0000000..f81ddfb
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_languages.sql
@@ -0,0 +1,4 @@
+SELECT
+    lanname as label, lanname as value
+FROM
+    pg_language;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_oid.sql
new file mode 100644
index 0000000..2bc76a2
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_oid.sql
@@ -0,0 +1,17 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
+    lanname, pg_get_userbyid(proowner) as funcowner
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+    AND nsp.nspname={{ nspname|qtLiteral }}
+WHERE
+    proisagg = FALSE
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.proname = {{ name|qtLiteral }};
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_out_types.sql
new file mode 100644
index 0000000..64a1187
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_out_types.sql
@@ -0,0 +1,6 @@
+SELECT
+    format_type(oid, NULL) AS out_arg_type
+FROM
+    pg_type
+WHERE
+    oid = {{ out_arg_oid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_schema.sql
@@ -0,0 +1,6 @@
+SELECT
+    nspname
+FROM
+    pg_namespace
+WHERE
+    oid = {{ scid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_types.sql
new file mode 100644
index 0000000..2a5582e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/get_types.sql
@@ -0,0 +1,20 @@
+SELECT
+    *
+FROM
+    (SELECT
+        format_type(t.oid,NULL) AS typname,
+        CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname,
+        (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup
+    FROM
+        pg_type t
+    JOIN
+        pg_namespace nsp ON typnamespace=nsp.oid
+    WHERE
+        (NOT (typname = 'unknown' AND nspname = 'pg_catalog'))
+    AND
+        (
+            typtype IN ('b', 'c', 'd', 'e', 'p', 'r')
+            AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger')
+        )
+    ) AS dummy
+ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/node.sql
new file mode 100644
index 0000000..c6d171b
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/node.sql
@@ -0,0 +1,19 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' AS name,
+    lanname, pg_get_userbyid(proowner) AS funcowner, description
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pr.protype = '0'::char
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/properties.sql
new file mode 100644
index 0000000..ff78298
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/properties.sql
@@ -0,0 +1,31 @@
+SELECT
+    pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c,
+    pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename,
+    typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames,
+    pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
+    pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description,
+    (SELECT
+        array_agg(provider || '=' || label)
+    FROM
+        pg_shseclabel sl1
+    WHERE
+        sl1.objoid=pr.oid) AS seclabels
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace typns ON typns.oid=typ.typnamespace
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+{% if fnid %}
+    AND pr.oid = {{fnid}}::oid
+{% endif %}
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/update.sql
new file mode 100644
index 0000000..3bf32da
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/update.sql
@@ -0,0 +1,132 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %}
+{% set name = o_data.name %}
+{% 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 {{ o_data.prorettypename }} AS
+{% if 'lanname' in lanname and data.lanname == 'c' %}
+{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
+{% elif 'lanname' in data and '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 -%}
+
+{% if 'lanname' in data %}
+LANGUAGE {{ data.lanname|qtLiteral }}{% else %}
+LANGUAGE {{ o_data.lanname|qtLiteral }}{% endif -%}{% 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 ('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 data.procost %}
+
+COST {{data.procost}}{% elif o_data.procost %} COST {{o_data.procost}} {% endif %}{% if data.prorows %}
+
+ROWS {{data.prorows}} {% elif o_data.prorows %} ROWS {{o_data.prorows}} {%
+endif -%}{% if data.merged_variables %}
+
+{% for v in data.merged_variables %}
+
+SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+{% endif -%};
+{% endif -%}
+
+{% if data.funcowner %}
+
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{
+o_data.proargtypenames }})
+    OWNER TO {{ 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.datacl %}
+{% for priv in data.acl.changed %}
+
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data
+.pronamespace, o_data.proargtypenames) }}
+{{ 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 %}
+
+{{ SECLABLE.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace) }}
+{% endfor %}
+{% endif -%}
+
+{% if 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/function/ppas/sql/9.5_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/variables.sql
new file mode 100644
index 0000000..5233c71
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/function/ppas/sql/9.5_plus/variables.sql
@@ -0,0 +1,6 @@
+SELECT
+    name, vartype, min_val, max_val, enumvals
+FROM
+    pg_settings
+WHERE
+    context in ('user', 'superuser');
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/js/procedures.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/js/procedures.js
new file mode 100644
index 0000000..f50ffe9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/js/procedures.js
@@ -0,0 +1,171 @@
+/* Create and Register Procedure Collection and Node. */
+define(
+        ['jquery', 'underscore', 'underscore.string',
+         'pgadmin', 'pgadmin.browser', 'alertify',
+         'pgadmin.node.function', 'pgadmin.browser.collection',
+         'pgadmin.browser.server.privilege'],
+function($, _, S, pgAdmin, pgBrowser, alertify, Function) {
+
+  if (!pgBrowser.Nodes['coll-procedure']) {
+    var procedures = pgAdmin.Browser.Nodes['coll-procedure'] =
+      pgAdmin.Browser.Collection.extend({
+        node: 'procedure',
+        label: '{{ _('Procedures') }}',
+        type: 'coll-procedure',
+        columns: ['name', 'funcowner', 'description']
+      });
+  };
+
+  pgSchemaNode = pgBrowser.Nodes['schema'];
+
+  // Inherit Functions Node
+  if (!pgBrowser.Nodes['procedure']) {
+    pgAdmin.Browser.Nodes['procedure'] = Function.extend({
+      type: 'procedure',
+      label: '{{ _('Procedure') }}',
+      collection_type: 'coll-procedure',
+      hasSQL: true,
+      hasDepends: true,
+      parent_type: ['schema'],
+      Init: function() {
+        /* Avoid mulitple registration of menus */
+        if (this.proc_initialized)
+            return;
+
+        this.proc_initialized = true;
+
+        pgBrowser.add_menus([{
+          name: 'create_procedure_on_coll', node: 'coll-procedure', module:
+          this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 4, label: '{{ _('Procedure...') }}',
+          icon: 'wcTabIcon icon-procedure', data: {action: 'create', check:
+          false}
+        },{
+          name: 'create_procedure', node: 'procedure', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 4, label: '{{ _('Procedure...') }}',
+          icon: 'wcTabIcon icon-procedure', data: {action: 'create', check:
+          true},
+        },{
+          name: 'create_procedure', node: 'schema', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 4, label: '{{ _('Procedure...') }}',
+          icon: 'wcTabIcon icon-procedure', data: {action: 'create', check:
+          true}, enable: 'canCreateProc'
+        }
+        ]);
+      },
+      canDrop: pgSchemaNode.canChildDrop,
+      canDropCascade: pgSchemaNode.canChildDrop,
+      model: Function.model.extend({
+        defaults: _.extend({},
+          Function.model.prototype.defaults,
+          {
+            lanname: 'edbspl'
+          }
+        ),
+        canVarAdd: function(m){
+          var server = this.node_info.server;
+            if (server.version < 90500) {
+              return false;
+           }
+           else {
+             return true;
+           }
+        },
+        isDisabled: function(m) {
+          name = this.name;
+          switch(name){
+            case 'provolatility':
+            case 'proisstrict':
+            case 'prosecdef':
+            case 'procost':
+            case 'proleakproof':
+            case 'variables':
+               var server = this.node_info.server;
+               if (server.version < 90500) {
+                 return true;
+               }
+               else {
+                 return false;
+               }
+               break;
+            case 'prorows':
+              var server = this.node_info.server;
+              if(server.version >= 90500 && m.get('proretset') == true) {
+                return false;
+              }
+              else {
+                return true;
+              }
+              break;
+            default:
+              return true;
+              break;
+          }
+       },
+       validate: function()
+        {
+          var err = {},
+              errmsg,
+              seclabels = this.get('seclabels');
+
+          if (_.isUndefined(this.get('name')) || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') {
+            err['name'] = '{{ _('Name can not be empty!') }}';
+            errmsg = errmsg || err['name'];
+          }
+
+          if (_.isUndefined(this.get('pronamespace')) || String(this.get('pronamespace')).replace(/^\s+|\s+$/g, '') == '') {
+            err['pronamespace'] = '{{ _('Schema can not be empty!') }}';
+            errmsg = errmsg || err['pronamespace'];
+          }
+
+          if (_.isUndefined(this.get('lanname')) || String(this.get('lanname')).replace(/^\s+|\s+$/g, '') == '') {
+            err['lanname'] = '{{ _('Language can not be empty!') }}';
+            errmsg = errmsg || err['lanname'];
+          }
+
+          if (_.isUndefined(this.get('prosrc')) || String(this.get('prosrc')).replace(/^\s+|\s+$/g, '') == '') {
+            err['prosrc'] = '{{ _('Code can not be empty!') }}';
+            errmsg = errmsg || err['prosrc'];
+          }
+
+
+          if (seclabels) {
+            var secLabelsErr;
+            for (var i = 0; i < seclabels.models.length && !secLabelsErr; i++) {
+              secLabelsErr = (seclabels.models[i]).validate.apply(seclabels.models[i]);
+              if (secLabelsErr) {
+                err['seclabels'] = secLabelsErr;
+                errmsg = errmsg || secLabelsErr;
+              }
+            }
+          }
+
+          this.errorModel.clear().set(err);
+
+          return null;
+        },
+      }
+      ),
+      canCreateProc: function(itemData, item, data) {
+        var node_hierarchy = this.getTreeNodeHierarchy.apply(this, [item]);
+
+        // Do not provide Create option in catalog
+        if ('catalog' in node_hierarchy)
+          return false;
+
+        // Procedures supported only in PPAS
+        if ('server' in node_hierarchy && node_hierarchy['server'].type == "ppas")
+          return true;
+
+        return false;
+
+      }
+  });
+
+  }
+
+  return pgBrowser.Nodes['procedure'];
+});
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/acl.sql
new file mode 100644
index 0000000..ad3e0d1
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/acl.sql
@@ -0,0 +1,35 @@
+SELECT
+    COALESCE(gt.rolname, 'public') AS grantee,
+    g.rolname AS grantor, array_agg(privilege_type) AS privileges,
+    array_agg(is_grantable) AS grantable
+FROM
+    (SELECT
+        d.grantee, d.grantor, d.is_grantable,
+        CASE d.privilege_type
+        WHEN 'CONNECT' THEN 'c'
+        WHEN 'CREATE' THEN 'C'
+        WHEN 'DELETE' THEN 'd'
+        WHEN 'EXECUTE' THEN 'X'
+        WHEN 'INSERT' THEN 'a'
+        WHEN 'REFERENCES' THEN 'x'
+        WHEN 'SELECT' THEN 'r'
+        WHEN 'TEMPORARY' THEN 'T'
+        WHEN 'TRIGGER' THEN 't'
+        WHEN 'TRUNCATE' THEN 'D'
+        WHEN 'UPDATE' THEN 'w'
+        WHEN 'USAGE' THEN 'U'
+        ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            (d).grantee AS grantee, (d).grantor AS grantor,
+            (d).is_grantable AS is_grantable,
+            (d).privilege_type AS privilege_type
+        FROM
+            (SELECT aclexplode(db.proacl) AS d FROM pg_proc db
+            WHERE db.oid = {{fnid}}::OID) a
+        ) d
+    ) d
+    LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
+    LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
+GROUP BY g.rolname, gt.rolname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/create.sql
new file mode 100644
index 0000000..4acbc58
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/create.sql
@@ -0,0 +1,42 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}
+{% set is_columns = [] %}
+{% if data %}
+CREATE PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }}{% if data
+.arguments %}(
+{% for p in data.arguments %}{{p.argmode}}{% 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 %}
+
+AS
+{{ data.prosrc }};
+
+{% if data.acl %}
+{% for p in data.acl %}
+
+{{ PRIVILEGE.SET(conn, "PROCEDURE", p.grantee, data.name, p.without_grant, p
+.with_grant, data.pronamespace, data.func_args)}}
+{% endfor %}
+{% endif -%}
+
+{% if data.description %}
+
+COMMENT ON PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }}{% if
+data.func_args %}({{data.func_args}}) {% endif %}
+
+    IS '{{ data.description }}';
+{% endif -%}
+
+{% if data.seclabels %}
+{% for r in data.seclabels %}
+{% if r.label and r.provider %}
+
+{{ SECLABLE.SET(conn, 'PROCEDURE', data.name, r.provider, r.label, data
+.pronamespace, data.func_args) }}
+{% endif %}
+{% endfor %}
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/delete.sql
new file mode 100644
index 0000000..18701ec
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/delete.sql
@@ -0,0 +1,21 @@
+{% if scid and fnid %}
+SELECT
+    pr.proname as name, '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args,
+    nspname
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.oid = {{fnid}};
+{% endif %}
+
+{% if name %}
+DROP PROCEDURE {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %};
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_definition.sql
new file mode 100644
index 0000000..c635f1e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_definition.sql
@@ -0,0 +1,12 @@
+SELECT
+    pg_get_functiondef({{fnid}}::oid) AS func_def,
+    nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name
+FROM
+    pg_proc pr
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND pr.oid = {{fnid}}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_languages.sql
new file mode 100644
index 0000000..f81ddfb
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_languages.sql
@@ -0,0 +1,4 @@
+SELECT
+    lanname as label, lanname as value
+FROM
+    pg_language;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_oid.sql
new file mode 100644
index 0000000..2bc76a2
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_oid.sql
@@ -0,0 +1,17 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
+    lanname, pg_get_userbyid(proowner) as funcowner
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+    AND nsp.nspname={{ nspname|qtLiteral }}
+WHERE
+    proisagg = FALSE
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.proname = {{ name|qtLiteral }};
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_out_types.sql
new file mode 100644
index 0000000..64a1187
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_out_types.sql
@@ -0,0 +1,6 @@
+SELECT
+    format_type(oid, NULL) AS out_arg_type
+FROM
+    pg_type
+WHERE
+    oid = {{ out_arg_oid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_schema.sql
@@ -0,0 +1,6 @@
+SELECT
+    nspname
+FROM
+    pg_namespace
+WHERE
+    oid = {{ scid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_types.sql
new file mode 100644
index 0000000..2a5582e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/get_types.sql
@@ -0,0 +1,20 @@
+SELECT
+    *
+FROM
+    (SELECT
+        format_type(t.oid,NULL) AS typname,
+        CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname,
+        (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup
+    FROM
+        pg_type t
+    JOIN
+        pg_namespace nsp ON typnamespace=nsp.oid
+    WHERE
+        (NOT (typname = 'unknown' AND nspname = 'pg_catalog'))
+    AND
+        (
+            typtype IN ('b', 'c', 'd', 'e', 'p', 'r')
+            AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger')
+        )
+    ) AS dummy
+ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/node.sql
new file mode 100644
index 0000000..30cab8d
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/node.sql
@@ -0,0 +1,19 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' AS name,
+    lanname, pg_get_userbyid(proowner) AS funcowner, description
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pr.protype = '1'::char
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/properties.sql
new file mode 100644
index 0000000..9e8a8ba
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/properties.sql
@@ -0,0 +1,31 @@
+SELECT
+    pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c,
+    pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename,
+    typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames,
+    pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
+    pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description,
+    (SELECT
+        array_agg(provider || '=' || label)
+    FROM
+        pg_seclabel sl1
+    WHERE
+        sl1.objoid=pr.oid) AS seclabels
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace typns ON typns.oid=typ.typnamespace
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+{% if fnid %}
+    AND pr.oid = {{fnid}}::oid
+{% endif %}
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/update.sql
new file mode 100644
index 0000000..985e52a
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/update.sql
@@ -0,0 +1,97 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}{% if data %}
+{% set name = o_data.name %}
+{% 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 %}
+
+AS
+{% if data.prosrc %}{{ data.prosrc }}{% else %}{{ o_data.prosrc }}{% endif -%};
+{% endif -%}
+
+
+{% if data.funcowner %}
+
+ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %}
+    OWNER TO {{ 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.datacl %}
+{% for priv in data.acl.changed %}
+
+{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data
+.pronamespace, o_data.proargtypenames) }}
+{{ 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 -%}
+
+{% set seclabels = data.seclabels %}
+{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+{% for r in seclabels.deleted %}
+
+{{ SECLABLE.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 %}
+
+{{ SECLABLE.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data
+.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+
+{{ SECLABLE.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data
+.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+
+{% if data.description %}
+
+COMMENT ON PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %}
+
+    IS {{ data.description|qtLiteral }};
+{% endif -%}
+
+{% if data.pronamespace %}
+
+ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %}
+
+    SET SCHEMA {{ conn|qtIdent(data.pronamespace) }};
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/variables.sql
new file mode 100644
index 0000000..5233c71
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.1_plus/variables.sql
@@ -0,0 +1,6 @@
+SELECT
+    name, vartype, min_val, max_val, enumvals
+FROM
+    pg_settings
+WHERE
+    context in ('user', 'superuser');
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/acl.sql
new file mode 100644
index 0000000..ad3e0d1
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/acl.sql
@@ -0,0 +1,35 @@
+SELECT
+    COALESCE(gt.rolname, 'public') AS grantee,
+    g.rolname AS grantor, array_agg(privilege_type) AS privileges,
+    array_agg(is_grantable) AS grantable
+FROM
+    (SELECT
+        d.grantee, d.grantor, d.is_grantable,
+        CASE d.privilege_type
+        WHEN 'CONNECT' THEN 'c'
+        WHEN 'CREATE' THEN 'C'
+        WHEN 'DELETE' THEN 'd'
+        WHEN 'EXECUTE' THEN 'X'
+        WHEN 'INSERT' THEN 'a'
+        WHEN 'REFERENCES' THEN 'x'
+        WHEN 'SELECT' THEN 'r'
+        WHEN 'TEMPORARY' THEN 'T'
+        WHEN 'TRIGGER' THEN 't'
+        WHEN 'TRUNCATE' THEN 'D'
+        WHEN 'UPDATE' THEN 'w'
+        WHEN 'USAGE' THEN 'U'
+        ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            (d).grantee AS grantee, (d).grantor AS grantor,
+            (d).is_grantable AS is_grantable,
+            (d).privilege_type AS privilege_type
+        FROM
+            (SELECT aclexplode(db.proacl) AS d FROM pg_proc db
+            WHERE db.oid = {{fnid}}::OID) a
+        ) d
+    ) d
+    LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
+    LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
+GROUP BY g.rolname, gt.rolname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/create.sql
new file mode 100644
index 0000000..328c371
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/create.sql
@@ -0,0 +1,41 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}
+{% set is_columns = [] %}
+{% if data %}
+CREATE PROCEDURE {{ 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 %}
+
+AS
+{{ data.prosrc }};
+
+{% if data.acl %}
+{% for p in data.acl %}
+
+{{ PRIVILEGE.SET(conn, "PROCEDURE", p.grantee, data.name, p.without_grant, p
+.with_grant, data.pronamespace, data.func_args)}}
+{% endfor %}
+{% endif -%}
+
+{% if data.description %}
+
+COMMENT ON PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }}{% if
+data.func_args %}({{data.func_args}}) {% endif %}
+
+    IS '{{ data.description }}';
+{% endif -%}
+
+{% if data.seclabels %}
+{% for r in data.seclabels %}
+{% if r.label and r.provider %}
+
+{{ SECLABLE.SET(conn, 'PROCEDURE', data.name, r.provider, r.label, data
+.pronamespace, data.func_args) }}
+{% endif %}
+{% endfor %}
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/delete.sql
new file mode 100644
index 0000000..18701ec
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/delete.sql
@@ -0,0 +1,21 @@
+{% if scid and fnid %}
+SELECT
+    pr.proname as name, '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args,
+    nspname
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.oid = {{fnid}};
+{% endif %}
+
+{% if name %}
+DROP PROCEDURE {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %};
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_definition.sql
new file mode 100644
index 0000000..c635f1e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_definition.sql
@@ -0,0 +1,12 @@
+SELECT
+    pg_get_functiondef({{fnid}}::oid) AS func_def,
+    nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name
+FROM
+    pg_proc pr
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND pr.oid = {{fnid}}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_languages.sql
new file mode 100644
index 0000000..f81ddfb
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_languages.sql
@@ -0,0 +1,4 @@
+SELECT
+    lanname as label, lanname as value
+FROM
+    pg_language;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_oid.sql
new file mode 100644
index 0000000..2bc76a2
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_oid.sql
@@ -0,0 +1,17 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
+    lanname, pg_get_userbyid(proowner) as funcowner
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+    AND nsp.nspname={{ nspname|qtLiteral }}
+WHERE
+    proisagg = FALSE
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.proname = {{ name|qtLiteral }};
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_out_types.sql
new file mode 100644
index 0000000..64a1187
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_out_types.sql
@@ -0,0 +1,6 @@
+SELECT
+    format_type(oid, NULL) AS out_arg_type
+FROM
+    pg_type
+WHERE
+    oid = {{ out_arg_oid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_schema.sql
@@ -0,0 +1,6 @@
+SELECT
+    nspname
+FROM
+    pg_namespace
+WHERE
+    oid = {{ scid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_types.sql
new file mode 100644
index 0000000..2a5582e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/get_types.sql
@@ -0,0 +1,20 @@
+SELECT
+    *
+FROM
+    (SELECT
+        format_type(t.oid,NULL) AS typname,
+        CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname,
+        (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup
+    FROM
+        pg_type t
+    JOIN
+        pg_namespace nsp ON typnamespace=nsp.oid
+    WHERE
+        (NOT (typname = 'unknown' AND nspname = 'pg_catalog'))
+    AND
+        (
+            typtype IN ('b', 'c', 'd', 'e', 'p', 'r')
+            AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger')
+        )
+    ) AS dummy
+ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/node.sql
new file mode 100644
index 0000000..30cab8d
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/node.sql
@@ -0,0 +1,19 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' AS name,
+    lanname, pg_get_userbyid(proowner) AS funcowner, description
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pr.protype = '1'::char
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/properties.sql
new file mode 100644
index 0000000..ff78298
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/properties.sql
@@ -0,0 +1,31 @@
+SELECT
+    pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c,
+    pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename,
+    typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames,
+    pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
+    pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description,
+    (SELECT
+        array_agg(provider || '=' || label)
+    FROM
+        pg_shseclabel sl1
+    WHERE
+        sl1.objoid=pr.oid) AS seclabels
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace typns ON typns.oid=typ.typnamespace
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+{% if fnid %}
+    AND pr.oid = {{fnid}}::oid
+{% endif %}
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/update.sql
new file mode 100644
index 0000000..985e52a
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/update.sql
@@ -0,0 +1,97 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}{% if data %}
+{% set name = o_data.name %}
+{% 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 %}
+
+AS
+{% if data.prosrc %}{{ data.prosrc }}{% else %}{{ o_data.prosrc }}{% endif -%};
+{% endif -%}
+
+
+{% if data.funcowner %}
+
+ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %}
+    OWNER TO {{ 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.datacl %}
+{% for priv in data.acl.changed %}
+
+{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data
+.pronamespace, o_data.proargtypenames) }}
+{{ 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 -%}
+
+{% set seclabels = data.seclabels %}
+{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+{% for r in seclabels.deleted %}
+
+{{ SECLABLE.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 %}
+
+{{ SECLABLE.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data
+.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+
+{{ SECLABLE.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data
+.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+
+{% if data.description %}
+
+COMMENT ON PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %}
+
+    IS {{ data.description|qtLiteral }};
+{% endif -%}
+
+{% if data.pronamespace %}
+
+ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %}
+
+    SET SCHEMA {{ conn|qtIdent(data.pronamespace) }};
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/variables.sql
new file mode 100644
index 0000000..5233c71
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.2_plus/variables.sql
@@ -0,0 +1,6 @@
+SELECT
+    name, vartype, min_val, max_val, enumvals
+FROM
+    pg_settings
+WHERE
+    context in ('user', 'superuser');
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/acl.sql
new file mode 100644
index 0000000..ad3e0d1
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/acl.sql
@@ -0,0 +1,35 @@
+SELECT
+    COALESCE(gt.rolname, 'public') AS grantee,
+    g.rolname AS grantor, array_agg(privilege_type) AS privileges,
+    array_agg(is_grantable) AS grantable
+FROM
+    (SELECT
+        d.grantee, d.grantor, d.is_grantable,
+        CASE d.privilege_type
+        WHEN 'CONNECT' THEN 'c'
+        WHEN 'CREATE' THEN 'C'
+        WHEN 'DELETE' THEN 'd'
+        WHEN 'EXECUTE' THEN 'X'
+        WHEN 'INSERT' THEN 'a'
+        WHEN 'REFERENCES' THEN 'x'
+        WHEN 'SELECT' THEN 'r'
+        WHEN 'TEMPORARY' THEN 'T'
+        WHEN 'TRIGGER' THEN 't'
+        WHEN 'TRUNCATE' THEN 'D'
+        WHEN 'UPDATE' THEN 'w'
+        WHEN 'USAGE' THEN 'U'
+        ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            (d).grantee AS grantee, (d).grantor AS grantor,
+            (d).is_grantable AS is_grantable,
+            (d).privilege_type AS privilege_type
+        FROM
+            (SELECT aclexplode(db.proacl) AS d FROM pg_proc db
+            WHERE db.oid = {{fnid}}::OID) a
+        ) d
+    ) d
+    LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
+    LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
+GROUP BY g.rolname, gt.rolname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/create.sql
new file mode 100644
index 0000000..e09f16e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/create.sql
@@ -0,0 +1,55 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}
+{% set is_columns = [] %}
+{% if data %}
+CREATE PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }}{% if data
+.arguments %}(
+{% for p in data.arguments %}{{p.argmode}}{% 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 %}
+
+{{ data.provolatile }}{% if data.proleakproof %} LEAKPROOF{% else %} NOT LEAKPROOF{% endif %}
+{% if data.proisstrict %} STRICT{% endif %}
+{% if data.prosecdef %} SECURITY DEFINER{% endif %}{% if data.procost %}
+
+COST {{data.procost|qtLiteral}}{% endif %}{% if data.prorows %}
+
+ROWS {{data.prorows|qtLiteral}}{% endif -%}{% if data.variables %}
+
+{% for v in data.variables %}
+
+SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+{% endif %}
+
+AS
+{{ data.prosrc }};
+
+{% if data.acl %}
+{% for p in data.acl %}
+
+{{ PRIVILEGE.SET(conn, "PROCEDURE", p.grantee, data.name, p.without_grant, p
+.with_grant, data.pronamespace, data.func_args)}}
+{% endfor %}
+{% endif -%}
+
+{% if data.description %}
+
+COMMENT ON PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }}{% if
+data.func_args %}({{data.func_args}}) {% endif %}
+
+    IS '{{ data.description }}';
+{% endif -%}
+
+{% if data.seclabels %}
+{% for r in data.seclabels %}
+{% if r.label and r.provider %}
+
+{{ SECLABLE.SET(conn, 'PROCEDURE', data.name, r.provider, r.label, data
+.pronamespace, data.func_args) }}
+{% endif %}
+{% endfor %}
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/delete.sql
new file mode 100644
index 0000000..18701ec
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/delete.sql
@@ -0,0 +1,21 @@
+{% if scid and fnid %}
+SELECT
+    pr.proname as name, '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args,
+    nspname
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.oid = {{fnid}};
+{% endif %}
+
+{% if name %}
+DROP PROCEDURE {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %};
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_definition.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_definition.sql
new file mode 100644
index 0000000..c635f1e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_definition.sql
@@ -0,0 +1,12 @@
+SELECT
+    pg_get_functiondef({{fnid}}::oid) AS func_def,
+    nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name
+FROM
+    pg_proc pr
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND pr.oid = {{fnid}}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_languages.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_languages.sql
new file mode 100644
index 0000000..f81ddfb
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_languages.sql
@@ -0,0 +1,4 @@
+SELECT
+    lanname as label, lanname as value
+FROM
+    pg_language;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_oid.sql
new file mode 100644
index 0000000..2bc76a2
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_oid.sql
@@ -0,0 +1,17 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
+    lanname, pg_get_userbyid(proowner) as funcowner
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+JOIN
+    pg_namespace nsp ON nsp.oid=pr.pronamespace
+    AND nsp.nspname={{ nspname|qtLiteral }}
+WHERE
+    proisagg = FALSE
+    AND typname NOT IN ('trigger', 'event_trigger')
+    AND pr.proname = {{ name|qtLiteral }};
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_out_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_out_types.sql
new file mode 100644
index 0000000..64a1187
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_out_types.sql
@@ -0,0 +1,6 @@
+SELECT
+    format_type(oid, NULL) AS out_arg_type
+FROM
+    pg_type
+WHERE
+    oid = {{ out_arg_oid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_schema.sql
@@ -0,0 +1,6 @@
+SELECT
+    nspname
+FROM
+    pg_namespace
+WHERE
+    oid = {{ scid }}::oid;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_types.sql
new file mode 100644
index 0000000..2a5582e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/get_types.sql
@@ -0,0 +1,20 @@
+SELECT
+    *
+FROM
+    (SELECT
+        format_type(t.oid,NULL) AS typname,
+        CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname,
+        (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup
+    FROM
+        pg_type t
+    JOIN
+        pg_namespace nsp ON typnamespace=nsp.oid
+    WHERE
+        (NOT (typname = 'unknown' AND nspname = 'pg_catalog'))
+    AND
+        (
+            typtype IN ('b', 'c', 'd', 'e', 'p', 'r')
+            AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger')
+        )
+    ) AS dummy
+ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/node.sql
new file mode 100644
index 0000000..30cab8d
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/node.sql
@@ -0,0 +1,19 @@
+SELECT
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog
+    .pg_get_function_identity_arguments(pr.oid), '') || ')' AS name,
+    lanname, pg_get_userbyid(proowner) AS funcowner, description
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pr.protype = '1'::char
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/properties.sql
new file mode 100644
index 0000000..ff78298
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/properties.sql
@@ -0,0 +1,31 @@
+SELECT
+    pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c,
+    pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename,
+    typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames,
+    pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
+    pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description,
+    (SELECT
+        array_agg(provider || '=' || label)
+    FROM
+        pg_shseclabel sl1
+    WHERE
+        sl1.objoid=pr.oid) AS seclabels
+FROM
+    pg_proc pr
+JOIN
+    pg_type typ ON typ.oid=prorettype
+JOIN
+    pg_namespace typns ON typns.oid=typ.typnamespace
+JOIN
+    pg_language lng ON lng.oid=prolang
+LEFT OUTER JOIN
+    pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
+WHERE
+    proisagg = FALSE
+    AND pronamespace = {{scid}}::oid
+    AND typname NOT IN ('trigger', 'event_trigger')
+{% if fnid %}
+    AND pr.oid = {{fnid}}::oid
+{% endif %}
+ORDER BY
+    proname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/update.sql
new file mode 100644
index 0000000..8bf6770
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/update.sql
@@ -0,0 +1,128 @@
+{% import 'macros/functions/security.macros' as SECLABLE %}
+{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
+{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %}
+{% set name = o_data.name %}
+{% 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 ('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 ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %}{% if data.procost %}
+
+COST {{data.procost}}{% elif o_data.procost %} COST {{o_data
+.procost}} {% endif %}{% if data.prorows %}
+
+ROWS {{data.prorows}} {% elif o_data.prorows %} ROWS {{o_data
+.prorows}} {% endif -%}{% if data.merged_variables %}
+
+{% for v in data.merged_variables %}
+
+SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+{% endif %}
+
+AS
+{% if data.prosrc %}{{ data.prosrc }}{% else %}{{ o_data.prosrc }}{% endif -%};
+{% endif -%}
+
+
+{% if data.funcowner %}
+
+ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %}
+    OWNER TO {{ 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.datacl %}
+{% for priv in data.acl.changed %}
+
+{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data
+.pronamespace, o_data.proargtypenames) }}
+{{ 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 %}
+
+{{ SECLABLE.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 %}
+
+{{ SECLABLE.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data
+.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+
+{{ SECLABLE.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data
+.pronamespace, o_data.proargtypenames) }}
+{% endfor %}
+{% endif -%}
+
+{% if data.description %}
+
+COMMENT ON PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %}
+
+    IS {{ data.description|qtLiteral }};
+{% endif -%}
+
+{% if data.pronamespace %}
+
+ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %}
+
+    SET SCHEMA {{ conn|qtIdent(data.pronamespace) }};
+{% endif -%}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/variables.sql
new file mode 100644
index 0000000..5233c71
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/templates/procedure/ppas/sql/9.5_plus/variables.sql
@@ -0,0 +1,6 @@
+SELECT
+    name, vartype, min_val, max_val, enumvals
+FROM
+    pg_settings
+WHERE
+    context in ('user', 'superuser');
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/macros/functions/variable.macros b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/macros/functions/variable.macros
index 02f3307..08d9e5b 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/macros/functions/variable.macros
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/macros/functions/variable.macros
@@ -2,12 +2,13 @@
 {# Macros for Variables (functions module)      #}
 {################################################}
 {% macro SET(conn, object_type, object_name, options, schema, func_args) -%}
-ALTER {{object_type}} {{ conn|qtIdent(schema, object_name) }}({{func_args}})
-    SET ({% for opt in options %}{% if loop.index != 1 %}
-, {% endif %}{{ conn|qtIdent(opt.name) }}={{ opt.value|qtLiteral }}{% endfor %});
+ALTER {{object_type}} {{ conn|qtIdent(schema, object_name) }}({{func_args}}){% for opt in options %}
+
+    SET {{ conn|qtIdent(opt.name) }}={{ opt.value|qtLiteral }}{%
+endfor %};
 {%- endmacro %}
 {% macro UNSET(conn, object_type, object_name, options, schema, func_args) -%}
 ALTER {{object_type}} {{ conn|qtIdent(schema, object_name) }}({{func_args}})
-    RESET ({% for opt in options %}{% if loop.index != 1 %}
-, {% endif %}{{ conn|qtIdent(opt.name) }}{% endfor %});
+    RESET {% for opt in options %}{% if loop.index != 1 %}
+, {% endif %}{{ conn|qtIdent(opt.name) }}{% endfor %};
 {%- endmacro %}

-- 
Sent via pgadmin-hackers mailing list ([email-masked])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers

---

From: Dave Page <[email-masked]>
Date: Fri, 11 Mar 2016 16:47:48 +0000

Hi

Hi,

This is looking pretty good. I did a little bit of cleanup of the SQL
formatting, however I think a little more is needed;

- When creating a function, we might get the following:

=====
CREATE FUNCTION pem.whee(INOUT foo bigint DEFAULT 123) RETURNS bigint AS
$BODY$SELECT $1;$BODY$
LANGUAGE 'sql'  NOT LEAKPROOF

SET backslash_quote='on';

ALTER FUNCTION pem.whee(INOUT foo bigint )
    OWNER TO postgres;

GRANT ALL ON FUNCTION pem.whee(INOUT foo bigint ) TO pem_user;

COMMENT ON FUNCTION pem.whee(INOUT foo bigint )
    IS 'whee func';
=====

  - Remove the spaces after the argument lists, before the )
  - Remove the double blank lines
  - The opening $BODY$ should be indented
  - LANGUAGE should be indented
  - The are two spaces between 'sql' and NOT.

- Reverse engineered SQL may look like:

=====
-- FUNCTION: pem.whee(INOUT foo bigint)

-- DROP FUNCTION pem.whee(INOUT foo bigint);

CREATE OR REPLACE FUNCTION pem.whee(INOUT foo bigint DEFAULT 123)
 RETURNS bigint
 LANGUAGE sql
 SET backslash_quote TO 'on'
AS $function$SELECT $1;$function$
=====

  - We should be consistent with our heredoc markers ($BODY$ vs. $function$)
  - There's a 1 space indent
  - This formatting (bar the issues above) is much nicer that the
CREATE formatting.

I haven't found anything else of note yet, that I haven't fixed in
passing (though I have yet to test with PPAS). Updated patch attached.

Thanks.

-- 
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake

EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

---

From: Khushboo Vashi <[email-masked]>
Date: Tue, 22 Mar 2016 16:21:01 +0530

Hi,

Please find updated Patch for the Functions/Procedures Module.

>   - Remove the spaces after the argument lists, before the )
Done

>   - Remove the double blank lines
Done

>   - The opening $BODY$ should be indented
Done and also replaced it with $function

>   - LANGUAGE should be indented
Done

>   - The are two spaces between 'sql' and NOT.
I have put function options into the next line as Reverse engineered SQL

>   - We should be consistent with our heredoc markers ($BODY$ vs.
Replaced $BODY with $function

>   - There's a 1 space indent
As per our discussion, will not fix this 1 space indent because the
Function definition SQL is coming from pg_def_functiondef function

index 0000000..25bb07e
@@ -0,0 +1,1295 @@
+    SchemaChildModule, DataTypeReader
+class FunctionView(PGChildNodeView, DataTypeReader):
+    * types(gid, sid, did, scid, fnid=None):
+        'get_types': [{'get': 'types'}, {'get': 'types'}],
+                req = json.loads(request.data.decode())
+        params = {"arguments": [
+            self._map_arguments_dict(
+                i, proargmodes_fltrd[i] if len(proargmodes_fltrd) > i else '',
+                proargtypes[i] if len(proargtypes) > i else '',
+                proargnames[i] if len(proargnames) > i else '',
+                proargdefaultvals[i] if len(proargdefaultvals) > i else ''
+            for i in range(len(proargtypes))]}
+        proargs = [self._map_arguments_list(
+            proargmodes_fltrd[i] if len(proargmodes_fltrd) > i else '',
+            proargtypes[i] if len(proargtypes) > i else '',
+            proargnames[i] if len(proargnames) > i else '',
+            proargdefaultvals[i] if len(proargdefaultvals) > i else ''
+        for i in range(len(proargtypes))]
+    def _map_arguments_dict(self, argid, argmode, argtype, argname, argdefval):
+        Returns Dict of formatted Arguments.
+            argid: Argument Sequence Number
+        return {"argid": argid,
+                "argdefval": argdefval}
+    def _map_arguments_list(self, argmode, argtype, argname, argdef):
+        Returns List of formatted Arguments.
+    def types(self, gid, sid, did, scid, fnid=None):
+        Returns the Data Types.
+        condition = "(typtype IN ('b', 'c', 'd', 'e', 'p', 'r') AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger'))"
+        if self.blueprint.show_system_objects:
+            condition += " AND nspname NOT LIKE E'pg\\\\_toast%' AND nspname NOT LIKE E'pg\\\\_temp%'"
+        # Get Types
+        status, types = self.get_types(self.conn, condition)
+            return internal_server_error(errormsg=types)
+            data=types,
+        if self.node_type == 'procedure':
+            status, func_def = self._get_sql(gid, sid, did, scid, resp_data,
+                                             None, True)
+                return internal_server_error(errormsg=func_def)
+            name = resp_data['name']
+    def _get_sql(self, gid, sid, did, scid, data, fnid=None, is_sql=False):
+                if 'provolatile' in old_data:
+                    old_data['provolatile'] = vol_dict[old_data['provolatile']]
+                                args += a['argtype']
+                data['func_args'] = args.strip(' ')
+                                                'create.sql']),
+                                      data=data, is_sql=is_sql)
+            return True, SQL.strip('\n')

literal 0
HcmV?d00001

literal 0
HcmV?d00001

literal 0
HcmV?d00001

literal 0
HcmV?d00001

index 0000000..b0a5d1c
@@ -0,0 +1,438 @@
+      type: 'text', editable: true, cellHeaderClasses:'width_percent_50'
+      id: 'security_label', label: '{{ _('Security Label') }}',
+      type: 'text', editable: true, cellHeaderClasses:'width_percent_50'
+        }, first_empty: true
+           cell:'boolean', type: 'switch',
+          url: 'get_types', disabled: 'isDisabled', first_empty: true,
+          id: 'proacl', label: '{{ _('Privileges') }}',
+           group: '{{ _('Security') }}', cell:'boolean', type: 'text', cell: 'string',
+          group: '{{ _('Parameters') }}', type: 'collection', canAdd: function(m){
+          editable: false, type: 'collection', group: '{{ _('Security') }}',
+          canEdit: true, canDelete: true,
+          control: 'unique-col-collection', uniqueCol : ['provider']
index 0000000..1c88f47
@@ -0,0 +1,53 @@
+CREATE 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 %}
+    RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }}
+    LANGUAGE {{ data.lanname|qtLiteral }}
+    {% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proisstrict %}STRICT {% endif %}{% if data.prosecdef %}SECURITY DEFINER {% endif %}{% if data.proiswindow %}WINDOW{% endif -%}{% if data.procost %}
+    COST {{data.procost}}{% endif %}{% if data.prorows %}
+    ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %}
+    SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %}
+AS {% if data.lanname == 'c' %}
+$function$
+{{ data.prosrc }}
+$function${% endif %};
+ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
+{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}}
+{% endfor %}{% endif %}
+COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
+{% if r.security_label and r.provider %}
+{{ SECLABLE.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
index 0000000..589ecce
@@ -0,0 +1,11 @@
+    nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name
index 0000000..bb6ec9d
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
index 0000000..0072198
@@ -0,0 +1,105 @@
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{o_data.proargtypenames }})
+{% 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 %}
+    RETURNS {{ o_data.prorettypename }}
+    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 ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %}
+    {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %}
+    ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}}{%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %}
+    SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+    {% endif %}
+AS {% if '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 %}
+$function${{ data.prosrc }}$function${% elif o_data.lanname == 'c' %}
+{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %}
+$function${{ o_data.prosrc }}$function${% endif -%};
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }})
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}{% endif %}
+{% if 'changed' in data.acl %}
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}{% endif %}
+{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}{% endif %}{% endif %}
+{% endif %}{% endif %}
+{{ SECLABLE.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}{% endif -%}
+COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
index 0000000..50de6dc
@@ -0,0 +1,57 @@
+CREATE 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 %}
+    RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }}
+    LANGUAGE {{ data.lanname|qtLiteral }}
+    {% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proleakproof %}LEAKPROOF {% else %}NOT LEAKPROOF {% endif %}
+{% if data.proisstrict %}STRICT {% endif %}
+{% if data.prosecdef %}SECURITY DEFINER {% endif %}
+{% if data.proiswindow %}WINDOW{% endif %}{% if data.procost %}
+    COST {{data.procost}}{% endif %}{% if data.prorows %}
+    ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %}
+    SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %}
+AS {% if data.lanname == 'c' %}
+$function$
+{{ data.prosrc }}
+$function${% endif -%};
+ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
+{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}}
+{% endfor -%}
+COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
+{% if r.security_label and r.provider %}
+{{ SECLABLE.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
index 0000000..589ecce
@@ -0,0 +1,11 @@
+    nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name
index 0000000..bb6ec9d
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
index 0000000..0126c8d
@@ -0,0 +1,114 @@
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{o_data.proargtypenames }})
+{% 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 %}
+    RETURNS {{ o_data.prorettypename }}
+    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 ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %}
+    {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %}
+    ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}}{% endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %}
+    SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+    {% endif %}
+AS {% if '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 %}
+$function${{ data.prosrc }}$function${% elif o_data.lanname == 'c' %}
+{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %}
+$function${{ o_data.prosrc }}$function${% endif -%};
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }})
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{% if 'changed' in data.acl %}
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }})
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }})
index 0000000..ec9f23f
@@ -0,0 +1,57 @@
+{% 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 %}
+    RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }}
+    LANGUAGE {{ data.lanname|qtLiteral }}
+    {% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proleakproof %}LEAKPROOF {% else %}NOT LEAKPROOF {% endif %}
+{% if data.proisstrict %}STRICT {% endif %}
+{% if data.prosecdef %}SECURITY DEFINER {% endif %}
+{% if data.proiswindow %}WINDOW{% endif %}{% if data.procost %}
+    COST {{data.procost}}{% endif %}{% if data.prorows %}
+    ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %}
+    SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %}
+AS {% if data.lanname == 'c' %}
+$function$
+{{ data.prosrc }}
+$function${% endif -%};
+ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
+{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}}
+{% endfor %}{% endif %}
+COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
+{% if r.security_label and r.provider %}
+{{ SECLABLE.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
index 0000000..589ecce
@@ -0,0 +1,11 @@
+    nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name
index 0000000..bb6ec9d
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
index 0000000..1a0c3eb
@@ -0,0 +1,114 @@
+{% 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 %}
+    RETURNS {{ o_data.prorettypename }}
+    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 ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %}
+    {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %}
+    ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}} {%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %}
+    SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+    {% endif %}
+AS {% if '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 %}
+$function${{ data.prosrc }}$function${% elif o_data.lanname == 'c' %}
+{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %}
+$function${{ o_data.prosrc }}$function${% endif -%};
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}{% endif -%}
+{{ VARIABLE.UNSET(conn, 'FUNCTION', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames) }}
+{{ VARIABLE.SET(conn, 'FUNCTION', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
index 0000000..1c88f47
@@ -0,0 +1,53 @@
+CREATE 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 %}
+    RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }}
+    LANGUAGE {{ data.lanname|qtLiteral }}
+    {% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proisstrict %}STRICT {% endif %}{% if data.prosecdef %}SECURITY DEFINER {% endif %}{% if data.proiswindow %}WINDOW{% endif -%}{% if data.procost %}
+    COST {{data.procost}}{% endif %}{% if data.prorows %}
+    ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %}
+    SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %}
+AS {% if data.lanname == 'c' %}
+$function$
+{{ data.prosrc }}
+$function${% endif %};
+ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
+{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}}
+{% endfor %}{% endif %}
+COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
+{% if r.security_label and r.provider %}
+{{ SECLABLE.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
index 0000000..589ecce
@@ -0,0 +1,11 @@
+    nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name
index 0000000..c7f4159
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' AS name,
index 0000000..0072198
@@ -0,0 +1,105 @@
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{o_data.proargtypenames }})
+{% 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 %}
+    RETURNS {{ o_data.prorettypename }}
+    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 ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %}
+    {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %}
+    ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}}{%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %}
+    SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+    {% endif %}
+AS {% if '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 %}
+$function${{ data.prosrc }}$function${% elif o_data.lanname == 'c' %}
+{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %}
+$function${{ o_data.prosrc }}$function${% endif -%};
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }})
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}{% endif %}
+{% if 'changed' in data.acl %}
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}{% endif %}
+{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}{% endif %}{% endif %}
+{% endif %}{% endif %}
+{{ SECLABLE.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}{% endif -%}
+COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
index 0000000..50de6dc
@@ -0,0 +1,57 @@
+CREATE 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 %}
+    RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }}
+    LANGUAGE {{ data.lanname|qtLiteral }}
+    {% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proleakproof %}LEAKPROOF {% else %}NOT LEAKPROOF {% endif %}
+{% if data.proisstrict %}STRICT {% endif %}
+{% if data.prosecdef %}SECURITY DEFINER {% endif %}
+{% if data.proiswindow %}WINDOW{% endif %}{% if data.procost %}
+    COST {{data.procost}}{% endif %}{% if data.prorows %}
+    ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %}
+    SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %}
+AS {% if data.lanname == 'c' %}
+$function$
+{{ data.prosrc }}
+$function${% endif -%};
+ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
+{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}}
+{% endfor -%}
+COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
+{% if r.security_label and r.provider %}
+{{ SECLABLE.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
index 0000000..589ecce
@@ -0,0 +1,11 @@
+    nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name
index 0000000..c7f4159
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' AS name,
index 0000000..0126c8d
@@ -0,0 +1,114 @@
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{o_data.proargtypenames }})
+{% 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 %}
+    RETURNS {{ o_data.prorettypename }}
+    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 ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %}
+    {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %}
+    ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}}{% endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %}
+    SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+    {% endif %}
+AS {% if '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 %}
+$function${{ data.prosrc }}$function${% elif o_data.lanname == 'c' %}
+{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %}
+$function${{ o_data.prosrc }}$function${% endif -%};
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }})
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{% if 'changed' in data.acl %}
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }})
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }})
index 0000000..ec9f23f
@@ -0,0 +1,57 @@
+{% 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 %}
+    RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }}
+    LANGUAGE {{ data.lanname|qtLiteral }}
+    {% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proleakproof %}LEAKPROOF {% else %}NOT LEAKPROOF {% endif %}
+{% if data.proisstrict %}STRICT {% endif %}
+{% if data.prosecdef %}SECURITY DEFINER {% endif %}
+{% if data.proiswindow %}WINDOW{% endif %}{% if data.procost %}
+    COST {{data.procost}}{% endif %}{% if data.prorows %}
+    ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %}
+    SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %}
+AS {% if data.lanname == 'c' %}
+$function$
+{{ data.prosrc }}
+$function${% endif -%};
+ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
+{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}}
+{% endfor %}{% endif %}
+COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
+{% if r.security_label and r.provider %}
+{{ SECLABLE.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
index 0000000..589ecce
@@ -0,0 +1,11 @@
+    nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name
index 0000000..c7f4159
+    pr.oid, pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' AS name,
index 0000000..1a0c3eb
@@ -0,0 +1,114 @@
+{% 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 %}
+    RETURNS {{ o_data.prorettypename }}
+    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 ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %}
+    {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %}
+    ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}} {%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %}
+    SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+    {% endif %}
+AS {% if '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 %}
+$function${{ data.prosrc }}$function${% elif o_data.lanname == 'c' %}
+{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %}
+$function${{ o_data.prosrc }}$function${% endif -%};
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{% endfor %}{% endif -%}
+{{ VARIABLE.UNSET(conn, 'FUNCTION', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames) }}
+{{ VARIABLE.SET(conn, 'FUNCTION', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
+ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
index 0000000..8630912
@@ -0,0 +1,33 @@
+CREATE OR REPLACE PROCEDURE {{ 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 data.acl and not is_sql %}
+{{ PRIVILEGE.SET(conn, "PROCEDURE", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}}
+{% endfor %}{% endif %}
+COMMENT ON PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }}
+{{ SECLABLE.SET(conn, 'PROCEDURE', data.name, r.provider, r.label, data.pronamespace, data.func_args) }}
index 0000000..e60e602
@@ -0,0 +1,82 @@
+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 %}
+{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.SET(conn, 'PROCEDURE', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+COMMENT ON PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}
+ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}
index 0000000..1f7690d
@@ -0,0 +1,33 @@
+CREATE OR REPLACE PROCEDURE {{ 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 %}
+{% endfor -%}){% endif %}
+{% if data.acl and not is_sql %}
+{{ PRIVILEGE.SET(conn, "PROCEDURE", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}}
+{% endfor %}{% endif %}
+COMMENT ON PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }}
+{% if r.security_label and r.provider %}
+{{ SECLABLE.SET(conn, 'PROCEDURE', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
index 0000000..42030b3
@@ -0,0 +1,78 @@
+ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}
+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 %}
+AS {% if data.prosrc %}{{ data.prosrc }}{% else %}{{ o_data.prosrc }}{% endif -%};
+{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{% if 'changed' in data.acl %}
+{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.SET(conn, 'PROCEDURE', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.SET(conn, 'PROCEDURE', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+COMMENT ON PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}
+ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}
index 0000000..12f5ad2
@@ -0,0 +1,43 @@
+CREATE OR REPLACE PROCEDURE {{ 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 %}
+{% endfor -%}){% endif %}
+    {{ data.provolatile }}{% if data.proleakproof %}LEAKPROOF {% elif not data.proleakproof %}NOT LEAKPROOF {% endif %}
+{% if data.proisstrict %}STRICT {% endif %}
+{% if data.prosecdef %}SECURITY DEFINER {% endif %}{% if data.procost %}
+    COST {{data.procost}}{% endif %}{% if data.prorows %}
+    ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %}
+    SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+{% if data.acl and not is_sql %}
+{{ PRIVILEGE.SET(conn, "PROCEDURE", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}}
+{% endfor %}{% endif %}
+COMMENT ON PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }}
+{% if r.security_label and r.provider %}
+{{ SECLABLE.SET(conn, 'PROCEDURE', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
index 0000000..54c1d84
@@ -0,0 +1,102 @@
+ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}
+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 ('proleakproof' in data and data.proleakproof) or ('proleakproof' not in data and o_data.proleakproof) %}LEAKPROOF{% else %}NOT LEAKPROOF{% endif %}
+    {% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %}
+    ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}}{% endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %}
+    SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
+{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.UNSETALL(conn, 'PROCEDURE', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.SET(conn, 'PROCEDURE', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{{ PRIVILEGE.SET(conn, 'PROCEDURE', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
+{{ VARIABLE.UNSET(conn, 'PROCEDURE', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABLE.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+COMMENT ON PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}
+ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/macros/functions/privilege.macros b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/macros/functions/privilege.macros
index 08d1198..1ac4cea 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/macros/functions/privilege.macros
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/macros/functions/privilege.macros
@@ -1,13 +1,9 @@
 {##############################################}
 {# Macros for Privileges (functions module)   #}
 {##############################################}
-{% macro SET(conn, type, role, param, privs, with_grant_privs, schema, func_args) -%}
-{% if privs %}
-GRANT {{ privs|join(', ') }} ON {{ type }} {{ conn|qtIdent(schema, param) }}({{func_args}}) TO {{conn|qtIdent(role) }};
-{% endif %}
-{% if with_grant_privs %}
-GRANT {{ with_grant_privs|join(', ') }} ON {{ type }} {{ conn|qtIdent(schema, param) }}({{func_args}}) TO {{ conn|qtIdent(role) }} WITH GRANT OPTION;
-{% endif %}
+{% macro SET(conn, type, role, param, privs, with_grant_privs, schema, func_args) -%}{% if privs %}
+GRANT {{ privs|join(', ') }} ON {{ type }} {{ conn|qtIdent(schema, param) }}({{func_args}}) TO {{conn|qtIdent(role) }};{% endif %}{% if with_grant_privs %}
+GRANT {{ with_grant_privs|join(', ') }} ON {{ type }} {{ conn|qtIdent(schema, param) }}({{func_args}}) TO {{ conn|qtIdent(role) }} WITH GRANT OPTION;{% endif %}
 {%- endmacro %}
 {% macro UNSETALL(conn, type, role, param, schema, func_args) -%}
 REVOKE ALL ON {{ type }} {{ conn|qtIdent(schema, param) }}({{func_args}}) FROM {{conn|qtIdent(role) }};

---

From: Dave Page <[email-masked]>
Date: Wed, 23 Mar 2016 12:03:14 +0000

Hi

Unfortunately I found more issues as I tested in-depth. I've attached
an updated patch in which I've done some cleanup - additional comments
below:

- Some argument lists are shown with an extra space, e.g.

character varying , integer

(pem.create_agent(character varying , integer))

- A 404 error is seen when functions are selected under a Catalog node.

- Procedures have a property of "System function?" - should be "System
procedure?"

- The Return Type, Returns a Set and Window fields should be hidden
for Procedures.

- When creating a procedure (below), I get the following error:

-----
-- PROCEDURE: foo

-- DROP PROCEDURE foo;

CREATE OR REPLACE PROCEDURE public.foo(IN a integer DEFAULT 10, INOUT
b integer DEFAULT  -)
    VOLATILE NOT LEAKPROOF SECURITY DEFINER
    COST 100.0
AS

BEGIN
   b:=a+b+1;
END;

COMMENT ON PROCEDURE public.foo
    IS 'Foo procedure';
-----

-----
2016-03-23 11:22:02,186: INFO werkzeug: 127.0.0.1 - - [23/Mar/2016
11:22:02] "GET /browser/procedure/obj/1/2/14844/13627/16387 HTTP/1.1"
500 -
Traceback (most recent call last):
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1403, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/views.py",
line 84, in view
    return self.dispatch_request(*args, **kwargs)
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/utils.py", line
233, in dispatch_request
    return method(*args, **kwargs)
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py",
line 349, in wrap
    return f(*args, **kwargs)
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py",
line 425, in properties
    resp_data = self._fetch_properties(gid, sid, did, scid, fnid)
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py",
line 1097, in _fetch_properties
    resp_data = res['rows'][0]
IndexError: list index out of range
-----

- After a Python server reset, I get the following error when trying
to view SQL of a Procedure (seems like it thinks it's connected to
PG?):

TemplateNotFound: procedure/pg/sql/9.5_plus/node.sql
2016-03-23 11:28:52,852: INFO werkzeug: 127.0.0.1 - - [23/Mar/2016
11:28:52] "GET /browser/procedure/nodes/1/2/14844/2200/ HTTP/1.1" 500
-
Traceback (most recent call last):
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1403, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/views.py",
line 84, in view
    return self.dispatch_request(*args, **kwargs)
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/utils.py", line
233, in dispatch_request
    return method(*args, **kwargs)
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py",
line 349, in wrap
    return f(*args, **kwargs)
  File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py",
line 390, in nodes
    'node.sql']), scid=scid)
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/templating.py",
line 127, in render_template
    return _render(ctx.app.jinja_env.get_or_select_template(template_name_or_list),
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/jinja2/environment.py",
line 830, in get_or_select_template
    return self.get_template(template_name_or_list, parent, globals)
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/jinja2/environment.py",
line 791, in get_template
    return self._load_template(name, self.make_globals(globals))
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/jinja2/environment.py",
line 765, in _load_template
    template = self.loader.load(self, name, globals)
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/jinja2/loaders.py",
line 113, in load
    source, filename, uptodate = self.get_source(environment, name)
  File "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/templating.py",
line 64, in get_source
    raise TemplateNotFound(template)
TemplateNotFound: procedure/pg/sql/9.5_plus/node.sql
2016-03-23 11:28:57,953: INFO werkzeug: 127.0.0.1 - - [23/Mar/2016
11:28:57] "POST /ping HTTP/1.1" 200 -

- Procedures do not include the schema name in the headers of reverse
engineered SQL, e.g.

- What's the trailing - in the parameter list in this reverse engineered SQL?

-- PROCEDURE: foo

-- DROP PROCEDURE foo;

CREATE OR REPLACE PROCEDURE public.foo(IN a integer DEFAULT 10, INOUT
b integer DEFAULT  -)
    VOLATILE NOT LEAKPROOF SECURITY DEFINER
    COST 100.0
AS

BEGIN
   b:=a+b+1;
END;

COMMENT ON PROCEDURE public.foo
    IS 'Foo procedure';

Thanks!

---

From: Khushboo Vashi <[email-masked]>
Date: Wed, 23 Mar 2016 19:14:56 +0530

Hi Dave,

I think you forgot to attach the updated patch.

Thanks,
Khushboo

On Wed, Mar 23, 2016 at 5:33 PM, Dave Page <[email-masked]> wrote:

>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
> line 1836, in __call__
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
> line 1820, in wsgi_app
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
> line 1817, in wsgi_app
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/views.py",
> line 84, in view
>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py",
> line 349, in wrap
>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py",
> line 425, in properties
>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py",
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
> line 1836, in __call__
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
> line 1820, in wsgi_app
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
> line 1817, in wsgi_app
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/app.py",
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/views.py",
> line 84, in view
>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py",
> line 349, in wrap
>   File
> "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py",
> line 390, in nodes
>     'node.sql']), scid=scid)
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/templating.py",
>     return
> _render(ctx.app.jinja_env.get_or_select_template(template_name_or_list),
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/jinja2/environment.py",
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/jinja2/environment.py",
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/jinja2/environment.py",
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/jinja2/loaders.py",
> line 113, in load
>   File
> "/Users/dpage/.virtualenvs/pgadmin4/lib/python2.7/site-packages/flask/templating.py",
> line 64, in get_source

---

From: Dave Page <[email-masked]>
Date: Wed, 23 Mar 2016 14:01:53 +0000

Ooops :-)

---

From: Khushboo Vashi <[email-masked]>
Date: Mon, 28 Mar 2016 12:56:28 +0530

Hi,

Please find updated patch for the functions/procedures module.

Thanks,
Khushboo

Done

Done

index 0000000..8e6947f
@@ -0,0 +1,1314 @@
+    make_response as ajax_response, internal_server_error, gone
+        # The pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) SQL
+        # statement gives us '-' as a default value for INOUT mode.
+        # so, replacing it with empty string.
+        if argmode == 'INOUT' and argdefval.strip() == '-':
+            argdefval = ''
+        # The pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) SQL
+        # statement gives us '-' as a default value for INOUT mode.
+        # so, replacing it with empty string.
+        if argmode == 'INOUT' and argdef.strip() == '-':
+            argdef = ''
+        if argmode and argmode:
+        return arg.strip(" ")
+            name = resp_data['pronamespace'] + "." + resp_data['name_with_args']
+        if len(res['rows']) == 0:
+            return gone(gettext("""
+Could not find the function in the database.
+It may have been removed by another user or
+created/shifted to the another schema.
+"""))

literal 0
HcmV?d00001

literal 0
HcmV?d00001

literal 0
HcmV?d00001

literal 0
HcmV?d00001

index 0000000..d62889f
@@ -0,0 +1,482 @@
+          node_info = this.get('node_info');
+          if(node_info && 'catalog' in node_info) {
+             node_info = this.get('node_info');
+             if(node_info && 'catalog' in node_info) {
+        cell: 'string', editable: 'isInCatalog', cellHeaderClasses:'width_percent_30'
+        cell: 'string', editable: 'isInCatalog',  cellHeaderClasses:'width_percent_20'
+    toJSON: Backbone.Model.prototype.toJSON,
+    isInCatalog: function(m){
+      node_info = this.get('node_info');
+      if(node_info && 'catalog' in node_info) {
+      parent_type: ['schema', 'catalog'],
+          sysfunc: undefined,
+          sysproc: undefined
+          type: 'text', mode: ['properties', 'create', 'edit'],
+          node: 'schema', disabled: 'isDisabled', mode: ['create', 'edit']
+          id: 'sysfunc', label: '{{ _('System function?') }}',
+           mode: ['properties'], visible: 'isVisible'
+          id: 'sysproc', label: '{{ _('System procedure?') }}',
+           mode: ['properties'], visible: 'isVisible'
+          type: 'multiline', disabled: 'isDisabled'
+          id: 'pronargs', label: '{{ _('Argument count') }}', cell: 'string',
+          id: 'proargtypenames', label: '{{ _('Signature arguments') }}', cell:
+          id: 'prorettypename', label: '{{ _('Return type') }}', cell: 'string',
+          mode: ['create'], visible: 'isVisible'
+          id: 'prorettypename', label: '{{ _('Return type') }}', cell: 'string',
+          mode: ['properties', 'edit'], disabled: 'isDisabled', visible: 'isVisible'
+          type: 'text', mode: ['properties', 'create', 'edit'],
+          group: '{{ _('Definition') }}', deps: ['lanname'],
+          control: Backform.SqlFieldControl,
+          extraClasses:['custom_height_css_class'],
+          visible: function(m) {
+          }, disabled: 'isDisabled'
+          id: 'probin', label: '{{ _('Object file') }}', cell: 'string',
+          }, disabled: 'isDisabled'
+          id: 'prosrc_c', label: '{{ _('Link symbol') }}', cell: 'string',
+          }, disabled: 'isDisabled'
+          id: 'proretset', label: '{{ _('Returns a set?') }}', group: '{{ _('Options') }}',
+          cell:'boolean', type: 'switch',  disabled: 'isDisabled',
+          visible: 'isVisible'
+          cell:'boolean', type: 'switch', disabled: 'isDisabled',
+          options: {
+            'onText': 'Yes', 'offText': 'No',
+            'onColor': 'success', 'offColor': 'primary',
+            'size': 'small'
+            disabled: 'isDisabled', visible: 'isVisible'
+          id: 'procost', label: '{{ _('Estimated cost') }}', group: '{{ _('Options') }}',
+          id: 'prorows', label: '{{ _('Estimated rows') }}', group: '{{ _
+          deps: ['proretset'], visible: 'isVisible'
+          canDelete: true, model: ArgumentModel, mode: ['create', 'edit'],
+          columns: ['argtype', 'argmode', 'argname', 'argdefval'],
+          control: 'unique-col-collection', uniqueCol : ['provider'],
+        isVisible: function(m){
+          if (this.name == 'sysproc') { return false; }
+          if(this.node_info &&  'catalog' in this.node_info) {
+            case 'prorettypename':
+          if(this.node_info &&  'catalog' in this.node_info) {
index 0000000..7b29a3c
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
index 0000000..af0f28e
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
index 0000000..04f8927
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
index 0000000..48a7a84
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
index 0000000..51629b0
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
index 0000000..7b29a3c
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
index 0000000..af0f28e
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
index 0000000..70a3d43
+{% import 'macros/functions/security.macros' as SECLABEL %}
+    {% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proleakproof %} LEAKPROOF {% else %} NOT LEAKPROOF {% endif %}
+{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
index 0000000..5b60590
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{% 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 %}
+{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
index 0000000..48a7a84
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
index 0000000..28e3642
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{% 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 %}
+{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
index 0000000..e713201
@@ -0,0 +1,184 @@
+        isVisible: function(m){
+          if (this.name == 'sysfunc') { return false; }
+          else if (this.name == 'sysproc') { return true; }
+          if(this.node_info &&  'catalog' in this.node_info) {
+            case 'funcowner':
+            case 'lanname':
index 0000000..942181d
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{{ SECLABEL.SET(conn, 'PROCEDURE', data.name, r.provider, r.label, data.pronamespace, data.func_args) }}
index 0000000..4b648c4
@@ -0,0 +1,25 @@
+    pr.oid,
+    CASE WHEN
+        pg_catalog.pg_get_function_identity_arguments(pr.oid) <> ''
+    THEN
+        pr.proname || '(' || pg_catalog.pg_get_function_identity_arguments(pr.oid) || ')'
+    ELSE
+        pr.proname
+    END AS name,
index 0000000..9492f3c
@@ -0,0 +1,38 @@
+    (CASE WHEN
+        pg_catalog.pg_get_function_identity_arguments(pr.oid) <> ''
+    THEN
+        pr.proname || '(' || pg_catalog.pg_get_function_identity_arguments(pr.oid) || ')'
+    ELSE
+        pr.proname
+    END) AS name_with_args,
index 0000000..1cf2c10
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{{ SECLABEL.UNSET(conn, 'PROCEDURE', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
index 0000000..b1ee22c
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{{ SECLABEL.SET(conn, 'PROCEDURE', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
index 0000000..4b648c4
@@ -0,0 +1,25 @@
+    pr.oid,
+    CASE WHEN
+        pg_catalog.pg_get_function_identity_arguments(pr.oid) <> ''
+    THEN
+        pr.proname || '(' || pg_catalog.pg_get_function_identity_arguments(pr.oid) || ')'
+    ELSE
+        pr.proname
+    END AS name,
index 0000000..6cfec94
@@ -0,0 +1,38 @@
+    (CASE WHEN
+        pg_catalog.pg_get_function_identity_arguments(pr.oid) <> ''
+    THEN
+        pr.proname || '(' || pg_catalog.pg_get_function_identity_arguments(pr.oid) || ')'
+    ELSE
+        pr.proname
+    END) AS name_with_args,
index 0000000..4dd4637
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{{ SECLABEL.UNSET(conn, 'PROCEDURE', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
index 0000000..fd81c66
+{% import 'macros/functions/security.macros' as SECLABEL %}
+    {{ data.provolatile }}{% if data.proleakproof %} LEAKPROOF {% elif not data.proleakproof %} NOT LEAKPROOF {% endif %}
+{{ SECLABEL.SET(conn, 'PROCEDURE', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
index 0000000..4b648c4
@@ -0,0 +1,25 @@
+    pr.oid,
+    CASE WHEN
+        pg_catalog.pg_get_function_identity_arguments(pr.oid) <> ''
+    THEN
+        pr.proname || '(' || pg_catalog.pg_get_function_identity_arguments(pr.oid) || ')'
+    ELSE
+        pr.proname
+    END AS name,
index 0000000..6cfec94
@@ -0,0 +1,38 @@
+    (CASE WHEN
+        pg_catalog.pg_get_function_identity_arguments(pr.oid) <> ''
+    THEN
+        pr.proname || '(' || pg_catalog.pg_get_function_identity_arguments(pr.oid) || ')'
+    ELSE
+        pr.proname
+    END) AS name_with_args,
index 0000000..7777ccd
+{% import 'macros/functions/security.macros' as SECLABEL %}
+{{ SECLABEL.UNSET(conn, 'PROCEDURE', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
+{{ SECLABEL.SET(conn, 'PROCEDURE', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}

---

From: Dave Page <[email-masked]>
Date: Tue, 5 Apr 2016 16:21:25 +0100

Thanks - committed.

---

From: Thom Brown <[email-masked]>
Date: Tue, 5 Apr 2016 17:18:46 +0100

I'm getting weirdness with this node.  See the attached picture, where
it shows the servers node appearing under functions.

Thom

-- 
Thom

---

From: Dave Page <[email-masked]>
Date: Tue, 5 Apr 2016 17:20:27 +0100

> it shows the servers node appearing under functions.

Make sure you've restarted the python server, and do a hard-refresh in
your browser. That normally clears that issue up for me.

---

From: Thom Brown <[email-masked]>
Date: Tue, 5 Apr 2016 17:31:28 +0100

> your browser. That normally clears that issue up for me.

I restarted python, but the hard refresh in the browser worked.

Thanks!

Thom