public inbox for [email protected]  
help / color / mirror / Atom feed
From: Surinder Kumar <[email protected]>
To: Akshay Joshi <[email protected]>
Cc: pgadmin-hackers <[email protected]>
Subject: Re: [pgAdmin4][Patch]: View and Materialised View Nodes
Date: Fri, 13 May 2016 23:44:39 +0530
Message-ID: <CAM5-9D_28KxDdr_FhWm7wjWwsCejudE2Q1FA4pX8DKFMReYaaA@mail.gmail.com> (raw)
In-Reply-To: <CANxoLDesxCagwR2DEBa5jRqRd755Z84iFnV2cHJM9tgfhHq7-w@mail.gmail.com>
References: <CAM5-9D9t_ytZ5eA=Xb4pz8wKKt+-XhXX7L_kPEa=w=gkHa=tGg@mail.gmail.com>
	<CANxoLDesxCagwR2DEBa5jRqRd755Z84iFnV2cHJM9tgfhHq7-w@mail.gmail.com>
List-Unsubscribe:  <mailto:[email protected]?body=unsub%20pgadmin-hackers>

Hi,

Please find updated patch with fixed review comments:

Most of the issues occurred because some code was missing in tables
subnodes patch.
Now I have shared the code related to table subnodes with harshal to
integrate in tables patch.

This patch has dependency on tables patch.

On Tue, May 10, 2016 at 7:46 PM, Akshay Joshi <[email protected]
> wrote:

> Hi Surinder
>
> On Fri, Apr 29, 2016 at 8:07 PM, Surinder Kumar <surinder.kumar@
> enterprisedb.com> wrote:
>
>> Hi,
>>
>>
>> PFA patch for View and Materialised View Nodes.
>> This patch is dependent on *tables node* and its subnodes patch.
>> Please test this patch once latest tables node patch is submitted.
>>
>> I have merged one other patch:
>> *"Don't show Security group of node if it is under Catalogs"*
>>
>> http://www.postgresql.org/message-id/[email protected]....
>>
>> Below are the fix for the review comments given by Dave:
>>
>> *Views*:
>>
>> - Please add sqlCreateHelp and sqlAlterHelp properties to all nodes.
>> *I have added these in View and Materialised View. *
>>
>> - Some of the SQL templates have inconsistent indenting (i.e. not 4
>> chars), e.g.
>>
>> CREATE OR REPLACE VIEW pem.avail_agents
>>  AS
>>  ...
>> *Fixed*
>>
>> - When creating any object, the Owner, Schema and Tablespace should
>> have default values.
>> *Fixed*
>>
>> - Property labels should only have the first word capitalised, e.g.
>>
>>   Security barrier
>>   Check options
>> *Fixed*
>>
>> - The Definition box on the View dialogue should start at a single
>> line and expand as needed - see the Function dialogue
>> *Fixed*
>>
>
>    Still reproducible.
>
>>
>>
>> - The Cancel button doesn't work on the View dialog. Please check them
>> all.
>> *In latest code pull, It **seems to be** fixed. not reproducible at my
>> end.*
>>
>> - The Save button doesn't close the View dialog, nor does it add the tree
>> node.
>> *In latest code pull, It **seems to be** fixed. not reproducible at my
>> end.*
>>
>> - Dependencies and Dependents don't show icons, and have very tall
>> rows. This issue likely comes from elsewhere as I'm seeing it on other
>> object types as well.
>> Yes, it is general, previously images were visible. It is regression of
>> some commit. I will check it.
>>
>> - Reverse engineered SQL for a column on a view is shown like:
>>
>> <html><head></head><body>-- Column: id -- ALTER TABLE pem.avail_agents
>> DROP COLUMN id; ALTER TABLE pem.avail_agents ADD COLUMN id
>> integer(4);</body></html>
>>
>> (yes, it's displaying the HTML tags)
>> *I pulled the latest code, but it is not reproducible.*
>>
>> - The ACL property should be called Privileges and be in the Security
>> group (see functions, sequences etc).
>> *Fixed*
>>
>> - The Schema should not be shown in "Properties" view.
>> *Fixed*
>>
>> - Fields in the General section should be in the order: Name, OID,
>> Owner, System xxx? (where appropriate), Comment
>> *I have checked that In view Fields (Name, Owner, Schema & Comment) are
>> in this order.*
>> *I didn't got your point. Can you please give and example, if possible.*
>>
>
>    Not Fixed yet.
>
Now it is fixed.

>
>>
>>
>> *Materialised Views:*
>> - Selecting an MV results in:
>>
>> 2016-04-14 09:34:58,863: ERROR pgadmin: Exception on
>> /browser/materialized_view/obj/1/1/24587/27424/107612 [GET]
>> Traceback (most recent call last):
>>   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/views/__init__.py",
>> line 185, in wrap
>>     return f(*args, **kwargs)
>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_
>> groups/servers/databases/schemas/views/__init__.py",
>> line 1226, in properties
>>     self.conn, result, 'table')
>>   File "/Users/dpage/git/pgadmin4/web/pgadmin/browser/server_
>> groups/servers/databases/schemas/utils.py",
>> line 357, in parse_vacuum_data
>>     vacuum_fields = render_template("vacuum_settings/vacuum_fields.json")
>>   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: vacuum_settings/vacuum_fields.json
>>
>> *It seems this patch*
>>
>> http://www.postgresql.org/message-id/[email protected]....
>> *wasn't applied properly. Now this patch is sent with tables patch.*
>>
>> - When creating an MV, an error is immediately shown telling me to
>> specify a name. We do not normally show such errors until the field
>> loses focus.
>> *Now its fixed.*
>>
>
>     Not fixed. Issue is reproducible.
>
>>
>>
>> - No default owner is shown in create mode.
>> *Fixed.*
>>
>> - "Please enter function definition." is shown as an error on the
>> definition field.
>> *It triggers this error message as it is mandatory.*
>>
>> - The Definition field is missing a label. If relying on the tab title
>> to be the label, the control should fill the tab (as with Security
>> options etc).
>> *Fixed.*
>>
>> - No default tablespace is shown.
>> *Fixed*
>>
>> - If I enable custom auto-vacuum, there is no way to add a row to
>> specify options.
>> *You can enable custom auto vacuum field and add new values in the auto
>> vacuum settings.*
>>
>> - If I specify a comment on an MV, I get "ERROR: "mv_pg_tables" is not a
>> view"
>> *For some reason tablespace name was missing in generated sql.*
>>
>
>    Not Fixed. Wrong sql generated "COMMENT ON VIEW ..." instead of
> "COMMENT ON MATERIALIZED VIEW ..."
>
Fixed

>
>>
>> - Save/Cancel buttons not working as expected (like other objects)
>> *In latest code pull, It **seems to be** fixed. not reproducible at my
>> end.*
>>
>
>
>    Apart from above below are my review comments
>
>    *Views*:-
>
>    - As per pgAdmin3 "indexes" node should not be listed under Views.
>
> Done

>
>    - SQL not generated when changing the value of "Event" and "Do
>    Instead" for Rule node under View node.
>
> Done

>
>    - Changing the "Event" in Rule node not working.
>
> Done

>
>    - As per pgAdmin3 user can't be able to create columns inside View
>    node.
>
> Done

>
>    - User can't be able to delete/drop columns and system generated
>    Rule's, Trigger's etc..
>
>
Done

>
>    - Found one issue when changing value of "Security Barrier" from "Yes"
>    to "No" it is not reflected on GUI when we open the dialog again while
>    in backend value is updated, but on GUI it is showing "Yes".
>
> Done

>
>    - Create -> Trigger menu is missing when any view node is selected.
>
> Done

>
>    *Materialized View:-*
>
>    - *As per pgAdmin3 user can't be able to create columns inside
>    Materialized View node.*
>
> Done

>
>    -
> -
> *User can't be able to delete/drop columns and system generated Rule's,
>    Trigger's etc. *
>
> I have checked in pgAdmin3 that delete/drop option specific to rules has 2
cases:
1. If rule is system rule, user can't delete/drop it.
2. If not system rule, it can drop dropped.
Done

>
>    -
>    - Create -> Trigger/Rule/Index menu is missing when any materialized
>    view node is selected.
>
> Done

>
>    - In pgAdmin3 we have two more refresh options "Refresh data" and
>    "Refresh data concurrently" which is missing.
>
> Done

>
>    - "Custom Auto Vaccum" for Table and Toast Table not working.
>
> Done

>
>
>>
>> Thanks,
>> Surinder Kumar
>>
>>
>>
>> --
>> Sent via pgadmin-hackers mailing list ([email protected])
>> To make changes to your subscription:
>> http://www.postgresql.org/mailpref/pgadmin-hackers
>>
>>
>
>
> --
> *Akshay Joshi*
> *Principal Software Engineer *
>
>
>
> *Phone: +91 20-3058-9517Mobile: +91 976-788-8246*
>


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


Attachments:

  [application/octet-stream] view_and_mat_view_nodes_v1.patch (211.7K, 3-view_and_mat_view_nodes_v1.patch)
  download | inline diff:
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/__init__.py
new file mode 100644
index 0000000..9d41c88
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/__init__.py
@@ -0,0 +1,1399 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+"""Implements View and Materialized View Node"""
+
+import simplejson as json
+from flask import render_template, request, jsonify
+from flask.ext.babel import gettext
+from pgadmin.utils.ajax import make_json_response, \
+    make_response as ajax_response, internal_server_error, \
+    bad_request
+from pgadmin.browser.utils import PGChildNodeView
+import pgadmin.browser.server_groups.servers.databases as databases
+from pgadmin.browser.server_groups.servers.databases.schemas.utils import \
+    SchemaChildModule, parse_rule_definition, VacuumSettings
+from pgadmin.utils.ajax import precondition_required
+from pgadmin.utils.driver import get_driver
+from config import PG_DEFAULT_DRIVER
+from functools import wraps
+
+
+"""
+    This module is responsible for generating two nodes
+    1) View
+    2) Materialized View
+
+    We have created single file because view & material view has same
+    functionality. It allows us to share the same submodules for both
+    view, and material view modules.
+
+    This modules uses separate template paths for each respective node
+    - templates/view for View node
+    - templates/materialized_view for MaterializedView node
+
+    [Each path contains node specific js files as well as sql template files.]
+"""
+
+
+class ViewModule(SchemaChildModule):
+    """
+    class ViewModule(SchemaChildModule):
+
+        A module class for View node derived from SchemaChildModule.
+
+    Methods:
+    -------
+    * __init__(*args, **kwargs)
+      - Method is used to initialize the View and it's base module.
+
+    * get_nodes(gid, sid, did, scid)
+      - Method is used to generate the browser collection node.
+
+    * node_inode()
+      - Method is overridden from its base class to make the node as leaf node.
+
+    * script_load()
+      - Load the module script for View, when any of the server node is
+        initialized.
+    """
+    NODE_TYPE = 'view'
+    COLLECTION_LABEL = gettext("Views")
+
+    def __init__(self, *args, **kwargs):
+        """
+        Method is used to initialize the ViewModule and it's base module.
+
+        Args:
+            *args:
+            **kwargs:
+        """
+        super(ViewModule, self).__init__(*args, **kwargs)
+        self.min_ver = None
+        self.max_ver = None
+
+    def get_nodes(self, gid, sid, did, scid):
+        """
+        Generate the collection node
+        """
+        yield self.generate_browser_collection_node(scid)
+
+    @property
+    def script_load(self):
+        """
+        Load the module script for views, when any database node is
+        initialized, The reason is views are also listed under catalogs
+        which are loaded under database node.
+        """
+        return databases.DatabaseModule.NODE_TYPE
+
+    @property
+    def csssnippets(self):
+        """
+        Returns a snippet of css to include in the page
+        """
+        snippets = [
+                render_template(
+                    "browser/css/collection.css",
+                    node_type=self.node_type,
+                    _=gettext
+                    ),
+                render_template(
+                    "view/css/view.css",
+                    node_type=self.node_type,
+                    _=gettext
+                    ),
+                render_template(
+                    "mview/css/mview.css",
+                    node_type='mview',
+                    _=gettext
+                    )
+                ]
+
+        for submodule in self.submodules:
+            snippets.extend(submodule.csssnippets)
+
+        return snippets
+
+
+class MaterializedViewModule(ViewModule):
+    """
+     class MaterializedViewModule(ViewModule)
+        A module class for the materialized view and view node derived
+        from ViewModule.
+    """
+
+    NODE_TYPE = 'mview'
+    COLLECTION_LABEL = gettext("Materialized Views")
+
+    def __init__(self, *args, **kwargs):
+        """
+        Method is used to initialize the MaterializedViewModule and
+        it's base module.
+
+        Args:
+            *args:
+            **kwargs:
+        """
+        super(MaterializedViewModule, self).__init__(*args, **kwargs)
+        self.min_ver = 90300
+        self.max_ver = None
+
+view_blueprint = ViewModule(__name__)
+mview_blueprint = MaterializedViewModule(
+        __name__)
+
+
+def check_precondition(f):
+    """
+    This function will behave as a decorator which will checks
+    database connection before running view, it will also attaches
+    manager,conn & template_path properties to instance of the method.
+
+    Assumptions:
+        This function will always be used as decorator of a class method.
+    """
+    @wraps(f)
+    def wrap(*args, **kwargs):
+
+        # Here args[0] will hold self & kwargs will hold gid,sid,did
+        self = args[0]
+        self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(
+            kwargs['sid']
+        )
+        self.conn = self.manager.connection(did=kwargs['did'])
+        # If DB not connected then return error to browser
+        if not self.conn.connected():
+            return precondition_required(
+                gettext("Connection to the server has been lost!")
+            )
+        self.datlastsysoid = self.manager.db_info[
+                kwargs['did']]['datlastsysoid']
+
+        # Set template path for sql scripts
+        self.template_path = self.template_initial + '/' + (
+            self.ppas_template_path(self.manager.version)
+            if self.manager.server_type == 'ppas' else
+            self.pg_template_path(self.manager.version)
+            )
+
+        return f(*args, **kwargs)
+
+    return wrap
+
+
+class ViewNode(PGChildNodeView, VacuumSettings):
+    """
+    This class is responsible for generating routes for view node.
+
+    Methods:
+    -------
+    * __init__(**kwargs)
+      - Method is used to initialize the ViewNode and it's base view.
+
+    * module_js()
+      - Request handler for module.js routes for the view node module
+      javascript, which returns javscript for this module.
+
+    * list()
+      - This function is used to list all the view nodes within the
+      collection.
+
+    * nodes()
+      - This function will used to create all the child node within the
+        collection, Here it will create all the view node.
+
+    * properties(gid, sid, did, scid)
+      - This function will show the properties of the selected view node.
+
+    * create(gid, sid, did, scid)
+      - This function will create the new view object.
+
+    * update(gid, sid, did, scid)
+      - This function will update the data for the selected view node.
+
+    * delete(self, gid, sid, scid):
+      - This function will drop the view object
+
+    * msql(gid, sid, did, scid)
+      - This function is used to return modified SQL for the selected view
+        node.
+
+    * get_sql(data, scid)
+      - This function will generate sql from model data
+
+    * sql(gid, sid, did, scid):
+      - This function will generate sql to show it in sql pane for the view
+        node.
+
+    * dependency(gid, sid, did, scid):
+      - This function will generate dependency list show it in dependency
+        pane for the selected view node.
+
+    * dependent(gid, sid, did, scid):
+      - This function will generate dependent list to show it in dependent
+        pane for the selected view node.
+    """
+    node_type = view_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': 'vid'}
+            ]
+
+    operations = dict({
+        'obj': [
+            {'get': 'properties', 'delete': 'delete', 'put': 'update'},
+            {'get': 'list', 'post': 'create'}
+        ],
+        'children': [{
+            'get': 'children'
+        }],
+        'delete': [{'delete': 'delete'}],
+        'refresh_data': [{'put': 'refresh_data'}, {'put': 'refresh_data'}],
+        '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'}],
+        'configs': [{'get': 'configs'}],
+        'get_tblspc': [{'get': 'get_tblspc'}, {'get': 'get_tblspc'}],
+        'get_table_vacuum': [
+          {'get': 'get_table_vacuum'},
+          {'get': 'get_table_vacuum'}],
+        'get_toast_table_vacuum': [
+          {'get': 'get_toast_table_vacuum'},
+          {'get': 'get_toast_table_vacuum'}]
+    })
+
+    def __init__(self, *args, **kwargs):
+        """
+        Initialize the variables used by methods of ViewNode.
+        """
+
+        super(ViewNode, self).__init__(*args, **kwargs)
+
+        self.manager = None
+        self.conn = None
+        self.template_path = None
+        self.template_initial = 'view'
+
+    @staticmethod
+    def ppas_template_path(ver):
+        """
+        Returns the template path for PPAS servers.
+        """
+        return 'ppas/9.3_plus'
+
+    @staticmethod
+    def pg_template_path(ver):
+        """
+        Returns the template path for PostgreSQL servers.
+        """
+        if ver >= 90400:
+            return 'pg/9.4_plus'
+        elif ver >= 90300:
+            return 'pg/9.3_plus'
+        elif ver >= 90200:
+            return 'pg/9.2_plus'
+        elif ver >= 90100:
+            return 'pg/9.1_plus'
+        return 'pg/9.1_plus'
+
+    @check_precondition
+    def list(self, gid, sid, did, scid):
+        """
+        Fetches all views properties and render into properties tab
+        """
+        SQL = render_template("/".join(
+          [self.template_path, 'sql/properties.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):
+        """
+        Lists all views under the Views Collection node
+        """
+        res = []
+        SQL = render_template("/".join(
+          [self.template_path, 'sql/properties.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-view"
+                    ))
+
+        return make_json_response(
+                data=res,
+                status=200
+                )
+
+    def parse_views_privileges(self, db_privileges):
+        """
+        This function forms a separate list of grantable
+        and non grantable privileges.
+        """
+        acl = {'grantor': db_privileges['grantor'],
+               'grantee': db_privileges['grantee'],
+               'privileges': []
+               }
+
+        privileges = []
+        for idx, priv in enumerate(db_privileges['privileges']):
+            if db_privileges['grantable'][idx]:
+                privileges.append({"privilege_type": priv,
+                                   "privilege": True,
+                                   "with_grant": True
+                                   })
+            else:
+                privileges.append({"privilege_type": priv,
+                                   "privilege": True,
+                                   "with_grant": False
+                                   })
+
+        acl['privileges'] = privileges
+
+        return acl
+
+    @check_precondition
+    def properties(self, gid, sid, did, scid, vid):
+        """
+        Fetches the properties of an individual view
+        and render in the properties tab
+        """
+        SQL = render_template("/".join(
+            [self.template_path, 'sql/properties.sql']
+          ), vid=vid, datlastsysoid=self.datlastsysoid)
+        status, res = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        SQL = render_template("/".join(
+          [self.template_path, 'sql/acl.sql']), vid=vid)
+        status, dataclres = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        for row in dataclres['rows']:
+            priv = self.parse_views_privileges(row)
+            if row['deftype'] in res['rows'][0]:
+                res['rows'][0][row['deftype']].append(priv)
+            else:
+                res['rows'][0][row['deftype']] = [priv]
+
+        result = res['rows'][0]
+
+        # sending result to formtter
+        frmtd_reslt = self.formatter(result)
+
+        # merging formated result with main result again
+        result.update(frmtd_reslt)
+
+        return ajax_response(
+                response=result,
+                status=200
+                )
+
+    @staticmethod
+    def formatter(result):
+        """ This function formats output for security label & variables"""
+        frmtd_result = dict()
+        sec_lbls = []
+        if 'seclabels' in result and result['seclabels'] is not None:
+            for sec in result['seclabels']:
+                import re
+                sec = re.search(r'([^=]+)=(.*$)', sec)
+                sec_lbls.append({
+                    'provider': sec.group(1),
+                    'security_label': sec.group(2)
+                    })
+
+        frmtd_result.update({"seclabels": sec_lbls})
+        return frmtd_result
+
+    @check_precondition
+    def create(self, gid, sid, did, scid):
+        """
+        This function will create a new view object
+        """
+        required_args = [
+            'name',
+            'definition'
+        ]
+
+        data = request.form if request.form else \
+            json.loads(request.data.decode())
+        for arg in required_args:
+            if arg not in data:
+                return make_json_response(
+                    status=410,
+                    success=0,
+                    errormsg=gettext(
+                        "Couldn't find the required parameter (%s)." % arg
+                    )
+                )
+
+        SQL = self.getSQL(gid, sid, data)
+        try:
+            status, res = self.conn.execute_scalar(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            SQL = render_template("/".join(
+                  [self.template_path, 'sql/view_id.sql']), data=data)
+            status, view_id = self.conn.execute_scalar(SQL)
+            return jsonify(
+                node=self.blueprint.generate_browser_node(
+                  view_id,
+                  scid,
+                  data['name'],
+                  icon="icon-view"
+                )
+            )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    def update(self, gid, sid, did, scid, vid):
+        """
+        This function will update a view object
+        """
+        data = request.form if request.form else \
+            json.loads(request.data.decode())
+        SQL = self.getSQL(gid, sid, data, vid)
+        try:
+            status, res = self.conn.execute_scalar(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            SQL = render_template("/".join(
+                  [self.template_path, 'sql/view_id.sql']), data=data)
+            status, view_id = self.conn.execute_scalar(SQL)
+            return jsonify(
+                node=self.blueprint.generate_browser_node(
+                  view_id,
+                  scid,
+                  data['name'],
+                  icon="icon-view"
+                )
+            )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    def delete(self, gid, sid, did, scid, vid):
+        """
+        This function will drop a view object
+        """
+
+        # Below will decide if it's simple drop or drop with cascade call
+        cascade = True if self.cmd == 'delete' else False
+
+        try:
+
+            # Get name for view from did
+            SQL = render_template("/".join(
+              [self.template_path, 'sql/delete.sql']), vid=vid)
+            status, res_data = self.conn.execute_dict(SQL)
+            if not status:
+                return internal_server_error(errormsg=res_data)
+
+            # drop view
+            SQL = render_template("/".join(
+              [self.template_path, 'sql/delete.sql']),
+                nspname=res_data['rows'][0]['nspname'],
+                name=res_data['rows'][0]['name'], 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("View dropped"),
+                data={
+                    'id': vid,
+                    'sid': sid,
+                    'gid': gid,
+                    'did': did
+                }
+            )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    def _get_schema(self, scid):
+        """
+        Returns Schema Name from its OID.
+
+        Args:
+            scid: Schema Id
+        """
+        SQL = render_template("/".join([self.template_path,
+                              'sql/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 msql(self, gid, sid, did, scid, vid=None):
+        """
+        This function returns modified SQL
+        """
+        data = {}
+        for k, v in request.args.items():
+            try:
+                data[k] = json.loads(v)
+            except ValueError:
+                data[k] = v
+
+        SQL = self.getSQL(gid, sid, data, vid)
+        if(SQL):
+            return make_json_response(
+                    data=SQL,
+                    status=200
+                    )
+        else:
+            return make_json_response(
+                    data=gettext("-- Nothing changed"),
+                    status=200
+                    )
+
+    @staticmethod
+    def parse_privileges(str_privileges, object_type='VIEW'):
+        """Parse Privileges."""
+        db_privileges = {
+            'a': 'INSERT',
+            'r': 'SELECT',
+            'w': 'UPDATE',
+            'd': 'DELETE',
+            'D': 'TRUNCATE',
+            'x': 'REFERENCES',
+            't': 'TRIGGER'
+            }
+        privileges = []
+        for priv in str_privileges:
+            priv_with_grant = []
+            priv_without_grant = []
+            for privilege in priv['privileges']:
+                if privilege['with_grant']:
+                    priv_with_grant.append(
+                      db_privileges[privilege['privilege_type']])
+                elif privilege['privilege']:
+                    priv_without_grant.append(
+                      db_privileges[privilege['privilege_type']])
+
+                # If we have all acl then just return all
+                if len(priv_with_grant) == len(db_privileges):
+                    priv_with_grant = ['ALL']
+                if len(priv_without_grant) == len(db_privileges):
+                    priv_without_grant = ['ALL']
+
+            # Server Level validation
+            if 'grantee' in priv:
+                privileges.append(
+                  {
+                    'grantee': priv['grantee'] if 'grantee' in priv else '',
+                    'with_grant': priv_with_grant,
+                    'without_grant': priv_without_grant
+                  }
+                )
+            else:
+                return ''
+        return privileges
+
+    def getSQL(self, gid, sid, data, vid=None):
+        """
+        This function will generate sql from model data
+        """
+        try:
+            if vid is not None:
+                SQL = render_template("/".join(
+                    [self.template_path, 'sql/properties.sql']),
+                  vid=vid,
+                  datlastsysoid=self.datlastsysoid
+                )
+                status, res = self.conn.execute_dict(SQL)
+                if not status:
+                    return internal_server_error(errormsg=res)
+                old_data = res['rows'][0]
+
+                if 'name' not in data:
+                    data['name'] = res['rows'][0]['name']
+                if 'schema' not in data:
+                    data['schema'] = res['rows'][0]['schema']
+
+                key = 'datacl'
+                if key in data and data[key] is not None:
+                    if 'added' in data[key]:
+                        data[key]['added'] = self.parse_privileges(
+                          data[key]['added'])
+                    if 'changed' in data[key]:
+                        data[key]['changed'] = self.parse_privileges(
+                          data[key]['changed'])
+                    if 'deleted' in data[key]:
+                        data[key]['deleted'] = self.parse_privileges(
+                          data[key]['deleted'])
+                try:
+                    SQL = render_template("/".join(
+                      [self.template_path, 'sql/update.sql']), data=data,
+                        o_data=old_data, conn=self.conn)
+                except Exception as e:
+                    return internal_server_error(errormsg=str(e))
+            else:
+                required_args = [
+                    'name',
+                    'schema',
+                    'definition'
+                ]
+                for arg in required_args:
+                    if arg not in data:
+                        return " -- definition incomplete"
+
+                # Get Schema Name from its OID.
+                if 'schema' in data:
+                    data['schema'] = self._get_schema(data['schema'])
+
+                if 'datacl' in data and data['datacl'] is not None:
+                    data['datacl'] = self.parse_privileges(data['datacl'])
+                SQL = render_template("/".join(
+                  [self.template_path, 'sql/create.sql']), data=data)
+                if data['definition']:
+                    SQL += "\n"
+                    SQL += render_template("/".join(
+                      [self.template_path, 'sql/grant.sql']), data=data)
+            return SQL
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    def get_index_column_details(self, idx, data):
+        """
+        This functional will fetch list of column details for index
+
+        Args:
+            idx: Index OID
+            data: Properties data
+
+        Returns:
+            Updated properties data with column details
+        """
+
+        self.index_temp_path = 'index'
+        SQL = render_template("/".join([self.index_temp_path,
+                              'sql/9.1_plus/column_details.sql']), idx=idx)
+        status, rset = self.conn.execute_2darray(SQL)
+        if not status:
+            return internal_server_error(errormsg=rset)
+
+        # 'attdef' comes with quotes from query so we need to strip them
+        # 'options' we need true/false to render switch ASC(false)/DESC(true)
+        columns = []
+        cols = []
+        for row in rset['rows']:
+
+            # We need all data as collection for ColumnsModel
+            cols_data = {
+                'colname': row['attdef'].strip('"'),
+                'collspcname': row['collnspname'],
+                'op_class': row['opcname'],
+            }
+            if row['options'][0] == 'DESC':
+                cols_data['sort_order'] = True
+            columns.append(cols_data)
+
+            # We need same data as string to display in properties window
+            # If multiple column then separate it by colon
+            cols_str = row['attdef']
+            if row['collnspname']:
+                cols_str += ' COLLATE ' + row['collnspname']
+            if row['opcname']:
+                cols_str += ' ' + row['opcname']
+            if row['options'][0] == 'DESC':
+                cols_str += ' DESC'
+            cols.append(cols_str)
+
+        # Push as collection
+        data['columns'] = columns
+        # Push as string
+        data['cols'] = ', '.join(cols)
+
+        return data
+
+    def get_trigger_column_details(self, tid, clist):
+        """
+        This function will fetch list of column for trigger
+
+        Args:
+            tid: Table OID
+            clist: List of columns
+
+        Returns:
+            Updated properties data with column
+        """
+
+        self.trigger_temp_path = 'schema/trigger'
+        SQL = render_template("/".join([self.trigger_temp_path,
+                                        'get_columns.sql']),
+                              tid=tid, clist=clist)
+        status, rset = self.conn.execute_2darray(SQL)
+        if not status:
+            return internal_server_error(errormsg=rset)
+        # 'tgattr' contains list of columns from table used in trigger
+        columns = []
+
+        for row in rset['rows']:
+            columns.append({'column': row['name']})
+
+        return columns
+
+    def get_rule_sql(self, vid):
+        """
+        Get all non system rules of view node,
+        generate their sql and render
+        into sql tab
+        """
+
+        self.rule_temp_path = 'rules'
+        SQL_data = ''
+        SQL = render_template("/".join(
+          [self.rule_temp_path, 'sql/properties.sql']), tid=vid)
+
+        status, data = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=data)
+
+        for rule in data['rows']:
+
+            # Generate SQL only for non system rule
+            if rule['name'] != '_RETURN':
+                res = []
+                SQL = render_template("/".join(
+                  [self.rule_temp_path, 'sql/properties.sql']),
+                    rid=rule['oid']
+                    )
+                status, res = self.conn.execute_dict(SQL)
+                res = parse_rule_definition(res)
+                SQL = render_template("/".join(
+                  [self.rule_temp_path, 'sql/create.sql']),
+                    data=res, display_comments=True)
+                SQL_data += '\n'
+                SQL_data += SQL
+        return SQL_data
+
+    def get_trigger_sql(self, vid):
+        """
+        Get all trigger nodes associated with view node,
+        generate their sql and render
+        into sql tab
+        """
+
+        # Define template path
+        self.trigger_temp_path = 'trigger'
+
+        SQL_data = ''
+        SQL = render_template("/".join(
+            [self.trigger_temp_path, 'sql/9.1_plus/properties.sql']),
+            tid=vid)
+
+        status, data = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=data)
+
+        for trigger in data['rows']:
+            SQL = render_template("/".join(
+              [self.trigger_temp_path, 'sql/9.1_plus/properties.sql']),
+                tid=trigger['oid'],
+                tgrelid=vid
+                )
+
+            status, res = self.conn.execute_dict(SQL)
+
+            res_rows = dict(res['rows'][0])
+            if res_rows['tgnargs'] > 1:
+                # We know that trigger has more than 1
+                # arguments, let's join them
+                res_rows['tgargs'] = ', '.join(
+                    res_rows['tgargs'])
+
+            if len(res_rows['tgattr']) > 1:
+                columns = ', '.join(res_rows['tgattr'].split(' '))
+                res_rows['columns'] = self.get_trigger_column_details(
+                    trigger['oid'], columns)
+            res_rows = trigger_definition(res_rows)
+
+            SQL = render_template("/".join(
+              [self.trigger_temp_path, 'sql/9.1_plus/create.sql']),
+                data=res_rows, display_comments=True)
+            SQL_data += '\n'
+            SQL_data += SQL
+
+        return SQL_data
+
+    def get_index_sql(self, vid):
+        """
+        Get all index associated with view node,
+        generate their sql and render
+        into sql tab
+        """
+
+        self.index_temp_path = 'index'
+        SQL_data = ''
+        SQL = render_template("/".join(
+          [self.index_temp_path, 'sql/9.1_plus/properties.sql']), tid=vid)
+        status, data = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=data)
+
+        for index in data['rows']:
+            res = []
+            SQL = render_template("/".join(
+              [self.index_temp_path, 'sql/9.1_plus/properties.sql']),
+                idx=index['oid'],
+                tid=vid
+                )
+            status, res = self.conn.execute_dict(SQL)
+
+            data = dict(res['rows'][0])
+            # Adding parent into data dict, will be using it while creating sql
+            data['schema'] = data['nspname']
+            data['table'] = data['tabname']
+
+            # Add column details for current index
+            data = self.get_index_column_details(index['oid'], data)
+
+            SQL = render_template("/".join(
+              [self.index_temp_path, 'sql/9.1_plus/create.sql']),
+                data=data, display_comments=True)
+            SQL_data += '\n'
+            SQL_data += SQL
+        return SQL_data
+
+    @check_precondition
+    def sql(self, gid, sid, did, scid, vid):
+        """
+        This function will generate sql to render into the sql panel
+        """
+
+        SQL_data = ''
+        SQL = render_template("/".join(
+          [self.template_path, 'sql/properties.sql']),
+          vid=vid,
+          datlastsysoid=self.datlastsysoid
+        )
+
+        status, res = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        result = res['rows'][0]
+
+        # Fetch all privileges for view
+        SQL = render_template("/".join(
+          [self.template_path, 'sql/acl.sql']), vid=vid)
+        status, dataclres = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        for row in dataclres['rows']:
+            priv = self.parse_views_privileges(row)
+            if row['deftype'] in res['rows'][0]:
+                res['rows'][0]['datacl'].append(priv)
+            else:
+                res['rows'][0]['datacl'] = [priv]
+
+        result.update(res['rows'][0])
+        if 'datacl' in result:
+            result['datacl'] = self.parse_privileges(result['datacl'])
+
+        SQL = render_template("/".join(
+                [self.template_path, 'sql/create.sql']),
+                data=result,
+                conn=self.conn,
+                display_comments=True
+              )
+        SQL += "\n"
+        SQL += render_template("/".join(
+          [self.template_path, 'sql/grant.sql']), data=result)
+
+        SQL_data += SQL
+        SQL_data += self.get_rule_sql(vid)
+        SQL_data += self.get_trigger_sql(vid)
+        SQL_data += self.get_index_sql(vid)
+
+        return ajax_response(response=SQL_data)
+
+    @check_precondition
+    def get_tblspc(self, gid, sid, did, scid):
+        """
+        This function to return list of tablespaces
+        """
+        res = []
+        try:
+            SQL = render_template(
+                "/".join([self.template_path, 'sql/get_tblspc.sql'])
+                )
+            status, rset = self.conn.execute_dict(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            for row in rset['rows']:
+                res.append(
+                            {'label': row['spcname'], 'value': row['spcname']}
+                        )
+
+            return make_json_response(
+                    data=res,
+                    status=200
+                    )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    def dependents(self, gid, sid, did, scid, vid):
+        """
+        This function gets the dependents and returns an ajax response
+        for the view node.
+
+        Args:
+            gid: Server Group ID
+            sid: Server ID
+            did: Database ID
+            vid: View ID
+        """
+        dependents_result = self.get_dependents(self.conn, vid)
+        return ajax_response(
+            response=dependents_result,
+            status=200
+            )
+
+    @check_precondition
+    def dependencies(self, gid, sid, did, scid, vid):
+        """
+        This function gets the dependencies and returns an ajax response
+        for the view node.
+
+        Args:
+            gid: Server Group ID
+            sid: Server ID
+            did: Database ID
+            vid: View ID
+        """
+        dependencies_result = self.get_dependencies(self.conn, vid)
+        return ajax_response(
+            response=dependencies_result,
+            status=200
+            )
+
+
+class MaterializedViewNode(ViewNode, VacuumSettings):
+    """
+    This class is responsible for generating routes for
+    materialized view node.
+
+    Methods:
+    -------
+    * __init__(**kwargs)
+      - Method is used to initialize the MaterializedView
+      and it's base view.
+
+    * module_js()
+      - This property defines (if javascript) exists for this node.
+        Override this property for your own logic
+
+    * create(gid, sid, did, scid)
+      - Raise an error - we can not create a material view.
+
+    * update(gid, sid, did, scid)
+      - This function will update the data for the selected material node
+
+    * delete(self, gid, sid, scid):
+      - Raise an error - we can not delete a material view.
+
+    * get_sql(data, scid)
+      - This function will generate sql from model data
+
+    """
+
+    node_type = mview_blueprint.node_type
+
+    def __init__(self, *args, **kwargs):
+        """
+        Initialize the variables used by methods of ViewNode.
+        """
+
+        super(MaterializedViewNode, self).__init__(*args, **kwargs)
+
+        self.template_initial = 'mview'
+
+    @staticmethod
+    def pg_template_path(ver):
+        """
+        Returns the template path for PostgreSQL servers.
+        """
+        if ver >= 90300:
+            return 'pg/9.3_plus'
+        return 'pg/9.3_plus'
+
+    def get_sql(self, gid, sid, data, scid, vid=None):
+        """
+        This function will generate sql from model data
+        """
+        if scid is None:
+            return bad_request('Cannot create a View!')
+
+        return super(MaterializedViewNode, self).get_sql(
+                gid, sid, data, scid, vid)
+
+    def getSQL(self, gid, sid, data, vid=None):
+        """
+        This function will genrate sql from model data
+        """
+        try:
+            if vid is not None:
+                SQL = render_template("/".join(
+                    [self.template_path, 'sql/properties.sql']),
+                  vid=vid,
+                  datlastsysoid=self.datlastsysoid
+                )
+                status, res = self.conn.execute_dict(SQL)
+                if not status:
+                    return internal_server_error(errormsg=res)
+                old_data = res['rows'][0]
+
+                if 'name' not in data:
+                    data['name'] = res['rows'][0]['name']
+                if 'schema' not in data:
+                    data['schema'] = res['rows'][0]['schema']
+
+                # merge vacuum lists into one
+                data['vacuum_data'] = {}
+                data['vacuum_data']['changed'] = []
+                data['vacuum_data']['reset'] = []
+                if ('vacuum_table' in data):
+                    if ('changed' in data['vacuum_table']):
+                        for item in data['vacuum_table']['changed']:
+                            if 'value' in item.keys():
+                                if item['value'] is None:
+                                    data['vacuum_data']['reset'].append(item)
+                                else:
+                                    data['vacuum_data']['changed'].append(item)
+
+                        if ('autovacuum_enabled' in data and
+                           str(data['autovacuum_enabled']).lower() == 'true'):
+                            data['vacuum_data']['changed'].append(
+                                {'name': 'autovacuum_enabled',
+                                 'value': data['autovacuum_enabled']})
+                        elif (old_data['autovacuum_enabled'] == 'true'):
+                            data['vacuum_data']['changed'].append(
+                                {'name': 'autovacuum_enabled',
+                                 'value': 'true'})
+                        else:
+                            data['vacuum_data']['changed'] = {}
+
+                key = 'datacl'
+                if key in data and data[key] is not None:
+                    if 'added' in data[key]:
+                        data[key]['added'] = self.parse_privileges(
+                          data[key]['added'])
+                    if 'changed' in data[key]:
+                        data[key]['changed'] = self.parse_privileges(
+                          data[key]['changed'])
+                    if 'deleted' in data[key]:
+                        data[key]['deleted'] = self.parse_privileges(
+                          data[key]['deleted'])
+
+                if (len(data['vacuum_data']['changed']) == 0 and
+                   len(data['vacuum_data']['reset']) == 0):
+                    data['settings'] = dict()
+                    if ('autovacuum_custom' in data and data['autovacuum_custom'] is True and
+                       (data['autovacuum_custom'] != old_data['autovacuum_custom']) and
+                       ('autovacuum_enabled' in data and data['autovacuum_enabled'] is True)):
+                        data['settings']['autovacuum_enabled'] = data['autovacuum_custom']
+                    elif ('autovacuum_enabled' in data and old_data['autovacuum_enabled'] is not None and
+                          str(data['autovacuum_enabled']).lower() != old_data['autovacuum_enabled'].lower()):
+                        data['settings']['autovacuum_enabled'] = data['autovacuum_enabled']
+
+                try:
+                    SQL = render_template("/".join(
+                      [self.template_path, 'sql/update.sql']), data=data,
+                        o_data=old_data, conn=self.conn)
+                except Exception as e:
+                    return internal_server_error(errormsg=str(e))
+            else:
+                required_args = [
+                    'name',
+                    'schema',
+                    'definition'
+                ]
+                for arg in required_args:
+                    if arg not in data:
+                        return " -- definition incomplete"
+
+                # Get Schema Name from its OID.
+                if 'schema' in data:
+                    data['schema'] = self._get_schema(data['schema'])
+
+                # merge vacuum lists into one
+                vacuum_table = [item for item in data['vacuum_table']
+                                if 'value' in item.keys() and item['value'] is not None]
+                vacuum_toast = [
+                    {'name': 'toast.'+item['name'], 'value':item['value']}
+                    for item in data['vacuum_toast'] if 'value' in item.keys() and item['value'] is not None]
+
+                # add vacuum_toast dict to vacuum_data only if
+                # toast's autovacuum is enabled
+                if ('toast_autovacuum_enabled' in data and
+                   data['toast_autovacuum_enabled'] is True):
+                    data['vacuum_data'] = vacuum_table + vacuum_toast
+                else:
+                    data['vacuum_data'] = vacuum_table
+
+                if 'datacl' in data and data['datacl'] is not None:
+                    data['datacl'] = self.parse_privileges(data['datacl'])
+                SQL = render_template("/".join(
+                  [self.template_path, 'sql/create.sql']), data=data)
+                if data['definition']:
+                    SQL += "\n"
+                    SQL += render_template("/".join(
+                      [self.template_path, 'sql/grant.sql']), data=data)
+            return SQL
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    def sql(self, gid, sid, did, scid, vid):
+        """
+        This function will generate sql to render into the sql panel
+        """
+
+        SQL_data = ''
+        SQL = render_template("/".join(
+          [self.template_path, 'sql/properties.sql']),
+          vid=vid,
+          datlastsysoid=self.datlastsysoid
+        )
+
+        status, res = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        result = res['rows'][0]
+
+        # sending result to formtter
+        frmtd_reslt = self.formatter(result)
+
+        # merging formated result with main result again
+        result.update(frmtd_reslt)
+        result['vacuum_table'] = self.parse_vacuum_data(
+            self.conn, result, 'table')
+        result['vacuum_toast'] = self.parse_vacuum_data(
+            self.conn, result, 'toast')
+
+        # merge vacuum lists into one
+        vacuum_table = [item for item in result['vacuum_table']
+                        if 'value' in item.keys() and item['value'] is not None]
+        vacuum_toast = [
+            {'name': 'toast.'+item['name'], 'value':item['value']}
+            for item in result['vacuum_toast'] if 'value' in item.keys() and item['value'] is not None]
+
+        # add vacuum_toast dict to vacuum_data only if
+        # toast's autovacuum is enabled
+        if ('toast_autovacuum_enabled' in result and
+           result['toast_autovacuum_enabled'] is True):
+            result['vacuum_data'] = vacuum_table + vacuum_toast
+        else:
+            result['vacuum_data'] = vacuum_table
+
+        # Fetch all privileges for view
+        SQL = render_template("/".join(
+          [self.template_path, 'sql/acl.sql']), vid=vid)
+        status, dataclres = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        for row in dataclres['rows']:
+            priv = self.parse_views_privileges(row)
+            if row['deftype'] in res['rows'][0]:
+                res['rows'][0]['datacl'].append(priv)
+            else:
+                res['rows'][0]['datacl'] = [priv]
+
+        result.update(res['rows'][0])
+        if 'datacl' in result:
+            result['datacl'] = self.parse_privileges(result['datacl'])
+
+        SQL = render_template("/".join(
+                [self.template_path, 'sql/create.sql']),
+                data=result,
+                conn=self.conn,
+                display_comments=True
+              )
+        SQL += "\n"
+        SQL += render_template("/".join(
+          [self.template_path, 'sql/grant.sql']), data=result)
+
+        SQL_data += SQL
+        SQL_data += self.get_rule_sql(vid)
+        SQL_data += self.get_trigger_sql(vid)
+        SQL_data += self.get_index_sql(vid)
+
+        return ajax_response(response=SQL_data)
+
+    @check_precondition
+    def get_table_vacuum(self, gid, sid, did, scid):
+        """
+        Fetch the default values for autovacuum
+        fields, return an array of
+          - label
+          - name
+          - setting
+        values
+        """
+
+        res = self.get_vacuum_table_settings(self.conn)
+        return ajax_response(
+                response=res['rows'],
+                status=200
+                )
+
+    @check_precondition
+    def get_toast_table_vacuum(self, gid, sid, did, scid):
+        """
+        Fetch the default values for autovacuum
+        fields, return an array of
+          - label
+          - name
+          - setting
+        values
+        """
+        res = self.get_vacuum_toast_settings(self.conn)
+
+        return ajax_response(
+                response=res['rows'],
+                status=200
+                )
+
+    @check_precondition
+    def properties(self, gid, sid, did, scid, vid):
+        """
+        Fetches the properties of an individual view
+        and render in the properties tab
+        """
+        SQL = render_template("/".join(
+            [self.template_path, 'sql/properties.sql']
+          ), vid=vid, datlastsysoid=self.datlastsysoid)
+        status, res = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        SQL = render_template("/".join(
+          [self.template_path, 'sql/acl.sql']), vid=vid)
+        status, dataclres = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        for row in dataclres['rows']:
+            priv = self.parse_views_privileges(row)
+            if row['deftype'] in res['rows'][0]:
+                res['rows'][0][row['deftype']].append(priv)
+            else:
+                res['rows'][0][row['deftype']] = [priv]
+
+        result = res['rows'][0]
+
+        # sending result to formtter
+        frmtd_reslt = self.formatter(result)
+
+        # merging formated result with main result again
+        result.update(frmtd_reslt)
+
+        result['vacuum_table'] = self.parse_vacuum_data(
+            self.conn, result, 'table')
+        result['vacuum_toast'] = self.parse_vacuum_data(
+            self.conn, result, 'toast')
+
+        return ajax_response(
+                response=result,
+                status=200
+                )
+
+    @check_precondition
+    def refresh_data(self, gid, sid, did, scid, vid):
+        """
+        This function will refresh view object
+        """
+
+        # Below will decide if it's refresh data or refresh concurrently
+        data = request.form if request.form else json.loads(request.data.decode())
+        is_concurrent = json.loads(data['concurrent'])
+
+        try:
+
+            # Fetch view name by view id
+            SQL = render_template("/".join(
+              [self.template_path, 'sql/get_view_name.sql']), vid=vid)
+            status, res = self.conn.execute_dict(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            # Refresh view
+            SQL = render_template("/".join(
+              [self.template_path, 'sql/refresh.sql']),
+              name=res['rows'][0]['name'],
+              nspname=res['rows'][0]['schema'], is_concurrent=is_concurrent)
+            status, res_data = self.conn.execute_dict(SQL)
+            if not status:
+                return internal_server_error(errormsg=res_data)
+
+            return make_json_response(
+                success=1,
+                info=gettext("View refreshed"),
+                data={
+                    'id': vid,
+                    'sid': sid,
+                    'gid': gid,
+                    'did': did
+                }
+            )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+ViewNode.register_node_view(view_blueprint)
+MaterializedViewNode.register_node_view(mview_blueprint)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/children/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/children/__init__.py
new file mode 100644
index 0000000..3993ff3
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/children/__init__.py
@@ -0,0 +1,12 @@
+"""
+We will use the exisiting modules for creating children module under
+materialize views.
+"""
+from pgadmin.browser.server_groups.servers.databases.schemas.tables.column \
+  import blueprint as columns_module
+from pgadmin.browser.server_groups.servers.databases.schemas.tables.indexes \
+  import blueprint as indexes_modules
+from pgadmin.browser.server_groups.servers.databases.schemas.tables.triggers \
+  import blueprint as triggers_modules
+from pgadmin.browser.server_groups.servers.databases.schemas.tables.rules \
+  import blueprint as rules_modules
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/img/coll-mview.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/img/coll-mview.png
new file mode 100644
index 0000000000000000000000000000000000000000..40e65a96e18004104b041b0ae32579b26ae97058
GIT binary patch
literal 374
zcmV-+0g3*JP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00009a7bBm000XU
z000XU0RWnu7ytkPC`m*?R5;6}lfO#CP!xy1+eV6l)y;y*AP73Rh@jQQr4BxYLpzBe
z;^H$1;tQlN;N&6>PA(>hLAOE$2b<YN5@VCx>!1V^ni|PnE{A)5-}!eBlsp2!8Jwv{
z_xxYN&Za98fNAM!r+Elb4K<vFpg}d7qay1FRZB!leDaRNo4Drr^^U#up3r_%Zyrty
zMW0`oB8+_iwCrQMIT$PM+D6LOia3pfYk85jS5BDpT2y2muX@kz%fU#$T)=Rmhd1pI
zN{>)_xh3TSloEv+sugkCnz_QX^u*q6^b<Q5U_V`EKMrm6egBz3w%Z*9N-2a8n3kS`
zXhlcZwT)C6BLS_AeIgkU%MT*y6UP3}1TI)wUL=ftA{hW~`DI$wk61H~McHlU3uk+8
Uv}-=(&;S4c07*qoM6N<$f<!@@p#T5?

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/img/coll-view.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/img/coll-view.png
new file mode 100644
index 0000000000000000000000000000000000000000..078d533684b8bd7e185749c4f1c9620af23d114b
GIT binary patch
literal 418
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}Y=BRQE08|>xOdKRnRzD^9{rj2
z_}lVF@Af@;b@}P@d(WRgefI3xqo=p7KVP}!V)Uc`-T(gmd-%V5`%AU||Nn1)p?>Gh
zn(Z&tPJa$N{=xgfzqUJn>TdojJ^s=A@Oy`SZ_IYR((AHW{03+NV@Z%-FoVOh8)+a;
zlDE5yQ1zZ1Ae(`+z$3C4NPB>>+sSM@AS2(?#W6(Ua%g{~P=f-Gv+27P9V>QJ|4;U6
zbe!GKH+kPSMNh%0YD;wVPp!&p$=H2Qa>4_iC-Ws`4oVu`kXvDIe5l_eV|jwW;+5+S
zYgy6~PYdy+-cS45)~k2Z!$WAAUct+ok^krC+MlVs+ppfyc`@F`nC<>l-VMq?t5r)}
zBT7;dOH!?pi&B9UgOP!up{{|Eu910&p^25DrIo3vwt<<IfkFPhkew(Ra`RI%(<*Um
UkbC@w6{vy1)78&qol`;+0LQMW5dZ)H

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/img/mview.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/img/mview.png
new file mode 100644
index 0000000000000000000000000000000000000000..7b72bdbb024d206a9ccccc307b980af7dc9cea88
GIT binary patch
literal 344
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wk0|O(M
zr;B5V#p&b(iHrjr$vHbE{{BC@z1bzxXo_Zv!8F~plmsAX<lOhGZpy*4Te=!QPFFbm
zU;Yt~PrZwz#Q!2=gMZH(vj3d_(fm;OaAw=?^=1c;K4AOv`+xgG`_JKRvEsKs+|pZn
z;^>D*x6OT+Cpd08n!IM#^LZ1F3M3y)72cH;)3)hB@w(<$ENtuI!+37X&3YKpe7)iO
zo7EB_E>059WTrQES9;xXdidD%!K10kJRqPs&0k{Df9H%vu?(M!xtNs?&v|Ub)6*j$
zbyq+v$yxg5%?jQE!}Cc$KEG!_e82v_q}|_|69*1#=yHs8ZfyjDhri#K1C8<Dp#F4o
lfA#<Q^_TpMg5)ZIft4K|E4KUpCSXu8c)I$ztaD0e0sxS)lm-9*

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/img/view.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/img/view.png
new file mode 100644
index 0000000000000000000000000000000000000000..44116db56496bb477c8ece7d3fdda666e1b3758b
GIT binary patch
literal 437
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}X@F0NE08|>xOdKRnaBToAO4>7
z;On9XZ+AU@dGYD<`_G?0efI3x<EOW7JYRF{Me@Q^nvec>Z-1%w|NsB(FVt^;p7P|y
zjoU9bT=|i6;cMdQ&tb<tdSCgTbKzU!@sHlyU#LC&-+lap_k(|JcmCAf{8f7ONA}_O
z4*TAi?Rus6RdrP&&|=1tAirP+hi5m^K%69RcNf7&TWxm%Ih+L^k;OpT1B~5HX4?T7
zS)MMAArhC96Am!+_;@g=95{03(5YkR4xT)E^z7l&>_QLRH3SlxI5?abofwq#PpGhn
z3y3`waupO1o<6}vaKfZ%6BvUwB`{h}XxPzW6T>ijp+R<{)&<#R3sx-A(NkQ!Xcb#n
z<0DHqpYzNNJzLm||5$yx0JK%L#5JNMC9x#cD!C{XNHG{07#ipr8tEDsh8P)GnHXD{
zm}(oCS{WG3d#ASwMMG|WN@iLmM1z4PSOZYCiIssFM8m1+p=*E|7(8A5T-G@yGywnx
Cm9(({

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/css/mview.css b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/css/mview.css
new file mode 100644
index 0000000..cd8658a
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/css/mview.css
@@ -0,0 +1,13 @@
+.icon-mview{
+  background-image: url('{{ url_for('NODE-mview.static', filename='img/mview.png') }}') !important;
+  border-radius: 10px;
+  background-repeat: no-repeat;
+  align-content: center;
+  vertical-align: middle;
+  height: 1.3em;
+}
+
+.sql_field_height_280 {
+  height: 280px;
+  width: 100%;
+}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/js/mview.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/js/mview.js
new file mode 100644
index 0000000..7065400
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/js/mview.js
@@ -0,0 +1,315 @@
+define(
+  ['jquery', 'underscore', 'underscore.string', 'pgadmin', 'alertify',
+    'pgadmin.browser', 'codemirror', 'pgadmin.browser.server.privilege'],
+
+function($, _, S, pgAdmin, alertify, pgBrowser, CodeMirror) {
+
+  /**
+    Create and add a view collection into nodes
+    @param {variable} label - Label for Node
+    @param {variable} type - Type of Node
+    @param {variable} columns - List of columns to
+      display under under properties.
+   */
+  if (!pgBrowser.Nodes['coll-mview']) {
+    var mviews= pgAdmin.Browser.Nodes['coll-mview'] =
+      pgAdmin.Browser.Collection.extend({
+        node: 'mview',
+        label: '{{ _("Materialized Views") }}',
+        type: 'coll-mview',
+        columns: ['name', 'owner']
+      });
+  }
+
+  /**
+    Create and Add a View Node into nodes
+    @param {variable} parent_type - The list of nodes
+    under which this node to display
+    @param {variable} type - Type of Node
+    @param {variable} hasSQL - To show SQL tab
+    @param {variable} canDrop - Adds drop view option
+    in the context menu
+    @param {variable} canDropCascade - Adds drop Cascade
+    view option in the context menu
+   */
+  if (!pgBrowser.Nodes['mview']) {
+    pgAdmin.Browser.Nodes['mview'] = pgAdmin.Browser.Node.extend({
+      parent_type: ['schema', 'catalog'],
+      type: 'mview',
+      sqlAlterHelp: 'sql-altermaterializedview.html',
+      sqlCreateHelp: 'sql-creatematerializedview.html',
+      label: '{{ _("Materialized View") }}',
+      hasSQL:  true,
+      hasDepends: true,
+      collection_type: 'coll-mview',
+      canDrop: pgBrowser.Nodes['schema'].canChildDrop,
+      canDropCascade: pgBrowser.Nodes['schema'].canChildDrop,
+      Init: function() {
+
+        // Avoid mulitple registration of menus
+        if (this.initialized)
+          return;
+
+        this.initialized = true;
+
+        /**
+          Add "create view" menu option into context and object menu
+          for the following nodes:
+          coll-mview, view and schema.
+          @property {data} - Allow create view option on schema node or
+          system view nodes.
+         */
+        pgBrowser.add_menus([{
+          name: 'create_mview_on_coll', node: 'coll-mview',
+          module: this, applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 1, label: '{{ _("Materialized View...") }}',
+          icon: 'wcTabIcon icon-mview', data: {action: 'create', check: true},
+          enable: 'canCreate'
+        },{
+          name: 'create_mview', node: 'mview', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 1, label: '{{ _("Materialized View...") }}',
+          icon: 'wcTabIcon icon-mview', data: {action: 'create', check: true},
+          enable: 'canCreate'
+        },{
+          name: 'create_mview', node: 'schema', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 18, label: '{{ _("Materialized View...") }}',
+          icon: 'wcTabIcon icon-mview', data: {action: 'create', check: false},
+          enable: 'canCreate'
+        },{
+          name: 'refresh_mview', node: 'mview', module: this, category: 'Refresh view',
+          applies: ['object', 'context'], callback: 'refresh_mview',
+          priority: 1, label: '{{ _("Refresh data") }}', data: {concurrent: false}
+        },{
+          name: 'refresh_mview_concurrent', node: 'mview', module: this,
+          category: 'Refresh view',
+          applies: ['object', 'context'], callback: 'refresh_mview',
+          priority: 2, label: '{{ _("Refresh concurrently") }}', data: {concurrent: true}
+        }
+        ]);
+      },
+
+      /**
+        Define model for the view node and specify the
+        properties of the model in schema.
+       */
+      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({'schema': schema_id}, {silent: true});
+
+            // Set Current User
+            var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user;
+            this.set({'owner': userInfo.name}, {silent: true});
+          }
+          pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments);
+        },
+        defaults: {
+          spcname: 'pg_default',
+          toast_autovacuum_enabled: false,
+          autovacuum_enabled: false
+        },
+        schema: [{
+          id: 'name', label: '{{ _("Name") }}', cell: 'string',
+          type: 'text', disabled: 'inSchema'
+        },
+        {
+          id: 'oid', label:'{{ _("OID") }}', cell: 'string',
+          type: 'text', disabled: true, mode: ['properties']
+        },
+        {
+          id: 'owner', label:'{{ _("Owner") }}', cell: 'string',
+          control: 'node-list-by-name',
+          node: 'role', disabled: 'inSchema'
+        },
+        {
+          id: 'schema', label:'{{ _("Schema") }}', cell: 'string', first_empty: false,
+          control: 'node-list-by-id', type: 'text', cache_level: 'database',
+          node: 'schema', mode: ['create', 'edit'], disabled: 'inSchema'
+        },
+        {
+          id: 'system_view', label:'{{ _("System view?") }}', cell: 'string',
+          type: 'switch', disabled: true, mode: ['properties'],
+        },
+        {
+          id: 'acl', label: '{{ _("ACL") }}',
+          mode: ['properties'], type: 'text'
+        },
+        {
+          id: 'comment', label:'{{ _("Comment") }}', cell: 'string',
+          type: 'multiline'
+        },
+        {
+          id: 'definition', label:'{{ _("") }}', cell: 'string',
+          type: 'text', mode: ['create', 'edit'], group: 'Definition',
+          control: Backform.SqlFieldControl, extraClasses:['sql_field_height_280']
+        },
+        // Add Privilege Control
+        {
+          id: 'datacl', label: '{{ _("Privileges") }}',
+          model: pgAdmin.Browser.Node.PrivilegeRoleModel.extend(
+            {privileges: ['a', 'r', 'w', 'd', 'D', 'x', 't']}), uniqueCol : ['grantee'],
+          editable: false, type: 'collection', group: '{{ _("Security") }}',
+          mode: ['edit', 'create'], canAdd: true, canDelete: true,
+          control: 'unique-col-collection', priority: 3
+        },
+
+        // Add Security Labels Control
+        {
+          id: 'seclabels', label: '{{ _("Security Labels") }}',
+          model: Backform.SecurityModel, editable: false, type: 'collection',
+          canEdit: false, group: '{{ _("Security") }}', canDelete: true,
+          mode: ['edit', 'create'], canAdd: true,
+          control: 'unique-col-collection', uniqueCol : ['provider']
+        },
+        {
+          id: 'with_data', label: '{{ _("With Data") }}',
+          group: '{{ _("Storage") }}', mode: ['edit', 'create'],
+          type: 'switch',
+        },
+        {
+          id: 'spcname', label: '{{ _("Tablespace") }}', cell: 'string',
+          type: 'text', group: '{{ _("Storage") }}', first_empty: false,
+          control: 'node-list-by-name', node: 'tablespace',
+          filter: function(m) {
+            if (m.label == "pg_global") return false;
+            else return true;
+          }
+        },
+        {
+          id: 'fillfactor', label: '{{ _("Fill Factor") }}',
+          group: '{{ _("Storage") }}', mode: ['edit', 'create'],
+          type: 'integer', min: 10, max: 100
+        },
+        {
+          type: 'nested', control: 'tab', id: 'materialization',
+          label: '{{ _("Materialization") }}', mode: ['edit', 'create'],
+          group: '{{ _("Storage") }}',
+          schema: Backform.VacuumSettingsSchema
+        },
+        ],
+        validate: function(keys) {
+
+          // Triggers specific error messages for fields
+          var err = {},
+            errmsg,
+            field_name = this.get('name'),
+            field_def = this.get('definition');
+          if (_.indexOf(keys, 'autovacuum_enabled') != -1 ||
+              _.indexOf(keys, 'toast_autovacuum_enabled') != -1 )
+              return null;
+
+          if (_.isUndefined(field_name) || _.isNull(field_name) ||
+            String(field_name).replace(/^\s+|\s+$/g, '') == '') {
+            err['name'] = '{{ _("Please specify name.") }}';
+            errmsg = errmsg || err['name'];
+            this.errorModel.set('name', errmsg);
+            return errmsg;
+          }else{
+            this.errorModel.unset('name');
+          }
+          if(this.isNew()){
+            if (_.isUndefined(field_def) || _.isNull(field_def) ||
+              String(field_def).replace(/^\s+|\s+$/g, '') == '') {
+              err['definition'] = '{{ _("Please enter function definition.") }}';
+              errmsg = errmsg || err['definition'];
+              this.errorModel.set('definition', errmsg);
+              return errmsg;
+            }else{
+              this.errorModel.unset('definition');
+            }
+          }
+          return null;
+        },
+        // We will disable everything if we are under catalog node
+        inSchema: function() {
+          if(this.node_info && 'catalog' in this.node_info)
+          {
+            return true;
+          }
+          return false;
+        }
+
+      }),
+
+      /**
+        Show or hide create view menu option on parent node
+        and hide for system view in catalogs.
+       */
+      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 view
+          if (_.indexOf(['schema'], d._type) > -1)
+            return true;
+
+          if ('coll-mview' == d._type) {
+
+            // Check if we are not child of view
+            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;
+
+      },
+      refresh_mview: function(args) {
+          var input = args || {};
+          obj = this,
+          t = pgBrowser.tree,
+          i = input.item || t.selected(),
+          d = i && i.length == 1 ? t.itemData(i) : undefined;
+
+          if (!d)
+            return false;
+
+        // Make ajax call to refresh mview data
+        $.ajax({
+          url: obj.generate_url(i, 'refresh_data' , d, true),
+          type: 'PUT',
+          data: {'concurrent': args.concurrent},
+          dataType: "json",
+          success: function(res) {
+            if (res.success == 1) {
+              alertify.success('View refreshed successfully');
+            }
+            else {
+              alertify.alert(
+                'Error refreshing view',
+                  res.data.result
+              );
+            }
+          },
+          error: function(e) {
+            var errmsg = $.parseJSON(e.responseText);
+            alertify.alert('Error refreshing view', errmsg.errormsg);
+          }
+        });
+
+      }
+  });
+  }
+
+  return pgBrowser.Nodes['coll-mview'];
+});
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/acl.sql
new file mode 100644
index 0000000..0c1bd6c
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/acl.sql
@@ -0,0 +1,41 @@
+{#============================Get ACLs=========================#}
+{% if vid %}
+SELECT
+    'datacl' as deftype,
+    COALESCE(gt.rolname, 'public') grantee,
+    g.rolname 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 'DELETE' THEN 'd'
+          WHEN 'INSERT' THEN 'a'
+          WHEN 'REFERENCES' THEN 'x'
+          WHEN 'SELECT' THEN 'r'
+          WHEN 'TRIGGER' THEN 't'
+          WHEN 'UPDATE' THEN 'w'
+          WHEN 'TRUNCATE' THEN 'D'
+          ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            relacl
+         FROM
+            pg_class cl
+         LEFT OUTER JOIN pg_shdescription descr ON
+            (cl.oid=descr.objoid AND descr.classoid='pg_class'::regclass)
+         WHERE
+            cl.oid = {{ vid }}::OID AND relkind = 'm'
+        ) acl,
+        aclexplode(relacl) 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
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/create.sql
new file mode 100644
index 0000000..29c9d1a
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/create.sql
@@ -0,0 +1,42 @@
+{# ===================== Create new view ===================== #}
+{% if display_comments %}
+-- View: {{ conn|qtIdent(data.schema, data.name) }}
+
+-- DROP MATERIALIZED VIEW {{ conn|qtIdent(data.schema, data.name) }};
+
+{% endif %}
+{% if data.name and data.schema and data.definition %}
+CREATE MATERIALIZED VIEW {{ conn|qtIdent(data.schema, data.name) }}
+{% if(data.fillfactor or data['autovacuum_enabled'] or data['toast_autovacuum_enabled']) %}
+WITH (
+{% if data.fillfactor %}
+    FILLFACTOR = {{ data.fillfactor }}{% if data['autovacuum_enabled'] or data['toast_autovacuum_enabled'] or data['vacuum_data']|length > 0 %},{{ '\r' }}{% endif %}
+{% endif %}
+{% if data['autovacuum_enabled'] %}
+    autovacuum_enabled = {{ data['autovacuum_enabled']|lower }}{% if data['toast_autovacuum_enabled'] or data['vacuum_data']|length > 0 %},{{ '\r' }}{% endif %}
+{% endif %}
+{% if data['toast_autovacuum_enabled'] %}
+    {{ 'toast.autovacuum_enabled' }} = {{ data['toast_autovacuum_enabled']|lower }}{% if data['vacuum_data']|length > 0 %},{{ '\r' }}{% endif %}
+{% endif %}
+{% for field in data['vacuum_data'] %}
+{% if field.value is defined and field.value != '' and field.value != none %}
+{% if loop.index > 1%},
+{% endif %}    {{ field.name }} = {{ field.value|lower }}{% endif %}
+{% endfor %}
+
+)
+{% endif %}
+{% if data.spcname %}TABLESPACE {{ data.spcname }}
+{% endif %}AS
+{{ data.definition.rstrip(';') }}
+{% if data.with_data %}
+WITH DATA;
+{% else %}
+WITH NO DATA;
+{% endif %}
+{% if data.comment %}
+
+COMMENT ON VIEW {{ conn|qtIdent(data.schema, data.name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/delete.sql
new file mode 100644
index 0000000..cf667fc
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/delete.sql
@@ -0,0 +1,13 @@
+{# =================== Drop/Cascade materialized view by name ====================#}
+{% if vid %}
+SELECT
+    c.relname As name,
+    nsp.nspname
+FROM
+    pg_class c
+LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
+WHERE
+    c.relfilenode = {{ vid }};
+{% elif (name and nspname) %}
+DROP MATERIALIZED VIEW {{ conn|qtIdent(nspname, name) }} {% if cascade %} CASCADE {% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/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/views/templates/mview/pg/9.3_plus/sql/get_view_name.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/get_view_name.sql
new file mode 100644
index 0000000..f7e404a
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/get_view_name.sql
@@ -0,0 +1,11 @@
+{# ===== Get view name against view id ==== #}
+{% if vid %}
+SELECT
+    c.relname AS name,
+    nsp.nspname AS schema
+FROM
+    pg_class c
+    LEFT OUTER JOIN pg_namespace nsp on nsp.oid = c.relnamespace
+WHERE
+    c.oid = {{vid}}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/grant.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/grant.sql
new file mode 100644
index 0000000..cff9d31
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/grant.sql
@@ -0,0 +1,6 @@
+{# ===== Grant Permissions to User Role on Views/Tables ==== #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{# We will generate Security Label SQL using macro #}
+{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{% endfor %}{% endif %}
+{% if data.datacl %}{% for priv in data.datacl %}{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}{% endfor %}{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/properties.sql
new file mode 100644
index 0000000..f02bc54
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/properties.sql
@@ -0,0 +1,111 @@
+{# ========================== Fetch Materialized View Properties ========================= #}
+{% if (vid and datlastsysoid) or scid %}
+SELECT
+    c.oid,
+    c.xmin,
+    c.relname AS name,
+    c.reltablespace AS spcoid,
+    c.relispopulated AS with_data,
+    (CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
+    c.relacl,
+    nsp.nspname as schema,
+    pg_get_userbyid(c.relowner) AS owner,
+    description AS comment,
+    pg_get_viewdef(c.oid, true) AS definition,
+    {#=============Checks if it is system view================#}
+    {% if vid and datlastsysoid %}
+    CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
+    {% endif %}
+    array_to_string(c.relacl::text[], ', ') AS acl,
+    (SELECT array_agg(provider || '=' || label) FROM pg_seclabels sl1 WHERE sl1.objoid=c.oid AND sl1.objsubid=0) AS seclabels,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'fillfactor=([0-9]*)') AS fillfactor,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_enabled=([a-z|0-9]*)') AS autovacuum_enabled,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_vacuum_threshold=([0-9]*)') AS autovacuum_vacuum_threshold,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_vacuum_scale_factor=([0-9]*[.][0-9]*)') AS autovacuum_vacuum_scale_factor,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_analyze_threshold=([0-9]*)') AS autovacuum_analyze_threshold,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_analyze_scale_factor=([0-9]*[.][0-9]*)') AS autovacuum_analyze_scale_factor,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_vacuum_cost_delay=([0-9]*)') AS autovacuum_vacuum_cost_delay,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_vacuum_cost_limit=([0-9]*)') AS autovacuum_vacuum_cost_limit,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_freeze_min_age=([0-9]*)') AS autovacuum_freeze_min_age,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_freeze_max_age=([0-9]*)') AS autovacuum_freeze_max_age,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_freeze_table_age=([0-9]*)') AS autovacuum_freeze_table_age,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_enabled=([a-z|0-9]*)') AS toast_autovacuum_enabled,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_vacuum_threshold=([0-9]*)') AS toast_autovacuum_vacuum_threshold,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_vacuum_scale_factor=([0-9]*[.][0-9]*)') AS toast_autovacuum_vacuum_scale_factor,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_analyze_threshold=([0-9]*)') AS toast_autovacuum_analyze_threshold,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_analyze_scale_factor=([0-9]*[.][0-9]*)') AS toast_autovacuum_analyze_scale_factor,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_vacuum_cost_delay=([0-9]*)') AS toast_autovacuum_vacuum_cost_delay,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_vacuum_cost_limit=([0-9]*)') AS toast_autovacuum_vacuum_cost_limit,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_freeze_min_age=([0-9]*)') AS toast_autovacuum_freeze_min_age,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_freeze_max_age=([0-9]*)') AS toast_autovacuum_freeze_max_age,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_freeze_table_age=([0-9]*)') AS toast_autovacuum_freeze_table_age,
+    c.reloptions AS reloptions, tst.reloptions AS toast_reloptions,
+    (CASE WHEN c.reltoastrelid = 0 THEN false ELSE true END) AS hastoasttable,
+    (CASE WHEN (substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_enabled=([a-z|0-9]*)'))::boolean  THEN true ELSE false END) AS autovacuum_custom,
+    (CASE WHEN (substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_enabled=([a-z|0-9]*)'))::boolean  AND c.reltoastrelid = 0 THEN true ELSE false END) AS toast_autovaccum
+FROM
+    pg_class c
+LEFT OUTER JOIN pg_namespace nsp on nsp.oid = c.relnamespace
+LEFT OUTER JOIN pg_tablespace spc on spc.oid=c.reltablespace
+LEFT OUTER JOIN pg_description des ON (des.objoid=c.oid and des.objsubid=0 AND des.classoid='pg_class'::regclass)
+LEFT OUTER JOIN pg_class tst ON tst.oid = c.reltoastrelid
+    WHERE ((c.relhasrules AND (EXISTS (
+        SELECT
+            r.rulename
+        FROM
+            pg_rewrite r
+        WHERE
+            ((r.ev_class = c.oid)
+                AND (bpchar(r.ev_type) = '1'::bpchar)) )))
+            AND (c.relkind = 'm'::char)
+          )
+{% if (vid and datlastsysoid) %}
+    AND c.oid = {{vid}}::oid
+{% elif scid %}
+    AND c.relnamespace = {{scid}}::oid
+ORDER BY
+    c.relname
+{% endif %}
+
+{% elif type == 'roles' %}
+SELECT
+    pr.rolname
+FROM
+    pg_roles pr
+WHERE
+    pr.rolcanlogin
+ORDER BY
+    pr.rolname
+
+{% elif type == 'schemas' %}
+SELECT
+    nsp.nspname
+FROM
+    pg_namespace nsp
+WHERE
+    (nsp.nspname NOT LIKE E'pg\\_%'
+        AND nsp.nspname != 'information_schema')
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/refresh.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/refresh.sql
new file mode 100644
index 0000000..a60534b
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/refresh.sql
@@ -0,0 +1,4 @@
+{#=== refresh mat view [concurrenlty] ===#}
+{% if name and nspname %}
+REFRESH MATERIALIZED VIEW {% if is_concurrent %}CONCURRENTLY{% endif %} {{ conn|qtIdent(nspname, name) }} ;
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/update.sql
new file mode 100644
index 0000000..c3c226a
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/update.sql
@@ -0,0 +1,164 @@
+{# ===================== Update View ===================#}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{%- if data -%}
+{% set view_name = data.name if data.name else o_data.name %}
+{% set view_schema = data.schema if data.schema else o_data.schema %}
+{% set def = data.definition.rstrip(';') if data.definition %}
+{# ===== Rename mat view ===== #}
+{% if data.name and data.name != o_data.name %}
+ALTER MATERIALIZED VIEW {{ conn|qtIdent(o_data.schema, o_data.name) }}
+  RENAME TO {{ conn|qtIdent(data.name) }};
+
+{% endif %}
+{# ===== Alter schema view ===== #}
+{% if data.schema and data.schema != o_data.schema %}
+ALTER MATERIALIZED VIEW {{ conn|qtIdent(o_data.schema, view_name ) }}
+  SET SCHEMA {{ conn|qtIdent(data.schema) }};
+
+{% endif %}
+{# ===== Alter Table owner ===== #}
+{% if data.owner and data.owner != o_data.owner %}
+ALTER TABLE {{ conn|qtIdent(view_schema, view_name) }}
+  OWNER TO {{ conn|qtIdent(data.owner) }};
+
+{% endif %}
+{% if data['vacuum_data']['reset']|length == 0 and
+data['vacuum_data']['reset']|length == 0 and data['settings']|length > 0 %}
+ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
+SET(
+{% for field in data['settings'] %}
+  {{ field }} = {{ data['settings'][field]|lower }}{% if not loop.last  %},{% endif %}{{ '\r' }}
+{% endfor %}
+);
+
+{% endif %}
+{% if data['vacuum_data']['reset']|length > 0 %}
+ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
+RESET(
+{% for field in data['vacuum_data']['reset'] %}
+  {{ field.name }}{% if not loop.last  %},{% endif %}{{ '\r' }}
+{% endfor %}
+);
+{% endif %}
+{# ===== First Drop and then create mat view ===== #}
+{% if def and def != o_data.definition.rstrip(';') %}
+{% if data.fillfactor or ( data['vacuum_data']['changed']|length > 0 ) %}
+DROP MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }};
+CREATE MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
+WITH(
+{% if data.fillfactor %}
+  FILLFACTOR = {{ data.fillfactor }}{% if data['vacuum_data']['changed']|length > 0 %},{% endif %}{{ '\r' }}
+{% endif %}
+{% if data['vacuum_data']['changed']|length > 0 %}
+{% for field in data['vacuum_data']['changed'] %}
+  {{ field.name }} = {{ field.value|lower }}{% if not loop.last  %},{% endif %}{{ '\r' }}
+{% endfor %}
+{% endif %}
+)
+ AS
+{{ def }}
+{% if data.with_data %}
+ WITH DATA;
+
+{% else %}
+ WITH NO DATA;
+
+{% endif %}
+{% endif %}
+{% else %}
+{# ======= Alter Tablespace ========= #}
+{%- if data.spcoid and o_data.spcoid != data.spcoid  -%}
+ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
+  SET TABLESPACE {{ data.spcoid }};
+
+{% endif %}
+{# ======= SET/RESET Fillfactor ========= #}
+{% if data.fillfactor and o_data.fillfactor != data.fillfactor %}
+ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
+SET(FILLFACTOR = {{ data.fillfactor }});
+
+{% elif data.fillfactor == '' %}
+ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
+RESET(
+  FILLFACTOR
+);
+
+{% endif %}
+{# ===== Check for with_data property ===== #}
+{% if data.with_data is defined and o_data.with_data|lower != data.with_data|lower  %}
+REFRESH MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }} WITH{{ ' NO' if data.with_data|lower == 'false' else '' }} DATA;
+
+{% endif %}
+{# ===== Check for Table tab properties ===== #}
+{% if data.autovacuum_custom is defined and data.autovacuum_custom|lower == 'false' %}
+ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
+RESET(
+  autovacuum_vacuum_threshold,
+  autovacuum_analyze_threshold,
+  autovacuum_vacuum_scale_factor,
+  autovacuum_analyze_scale_factor,
+  autovacuum_vacuum_cost_delay,
+  autovacuum_vacuum_cost_limit,
+  autovacuum_freeze_min_age,
+  autovacuum_freeze_max_age,
+  autovacuum_freeze_table_age
+);
+
+{% elif(data['vacuum_data']['changed']|length > 0) %}
+{% if data['vacuum_data']['changed']|length == 1 and data['vacuum_data']['changed'][0]['name'] != 'autovacuum_enabled' %}
+ALTER MATERIALIZED VIEW {{ conn|qtIdent(data.schema, data.name) }} SET(
+{% for field in data['vacuum_data']['changed'] %}
+{% if field.value != None %}
+  {{ field.name }} = {{ field.value|lower }}{% if not loop.last  %},{% endif %}{{ '\r' }}
+{% endif %}
+{% endfor %}
+);
+{% endif %}
+
+{% endif %}{# ===== End check for custom autovaccum ===== #}
+{% endif %}{# ===== End block for check data definition ===== #}
+{%- if data.comment and data.comment != o_data.comment -%}
+COMMENT ON MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
+  IS {{ data.comment|qtLiteral }};
+
+{% endif %}
+{# ============= The SQL generated below will change privileges ============= #}
+{% if data.datacl %}
+{% if 'deleted' in data.datacl %}
+{% for priv in data.datacl.deleted %}
+{{ PRIVILEGE.RESETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in data.datacl %}
+{% for priv in data.datacl.changed -%}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{%- endfor %}
+{% endif %}
+{% if 'added' in data.datacl %}
+{% for priv in data.datacl.added %}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{# ============== The SQL generated below will change Security Label ========= #}
+{% if data.seclabels is not none and data.seclabels|length > 0 %}
+{% set seclabels = data.seclabels %}
+{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+{% for r in seclabels.deleted %}
+{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/view_id.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/view_id.sql
new file mode 100644
index 0000000..d192a80
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/pg/9.3_plus/sql/view_id.sql
@@ -0,0 +1,4 @@
+{# ===== Below will provide view id for last created view ==== #}
+{% if data %}
+SELECT c.oid FROM pg_class c WHERE c.relname = '{{ data.name }}';
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/acl.sql
new file mode 100644
index 0000000..0c1bd6c
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/acl.sql
@@ -0,0 +1,41 @@
+{#============================Get ACLs=========================#}
+{% if vid %}
+SELECT
+    'datacl' as deftype,
+    COALESCE(gt.rolname, 'public') grantee,
+    g.rolname 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 'DELETE' THEN 'd'
+          WHEN 'INSERT' THEN 'a'
+          WHEN 'REFERENCES' THEN 'x'
+          WHEN 'SELECT' THEN 'r'
+          WHEN 'TRIGGER' THEN 't'
+          WHEN 'UPDATE' THEN 'w'
+          WHEN 'TRUNCATE' THEN 'D'
+          ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            relacl
+         FROM
+            pg_class cl
+         LEFT OUTER JOIN pg_shdescription descr ON
+            (cl.oid=descr.objoid AND descr.classoid='pg_class'::regclass)
+         WHERE
+            cl.oid = {{ vid }}::OID AND relkind = 'm'
+        ) acl,
+        aclexplode(relacl) 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
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/create.sql
new file mode 100644
index 0000000..29c9d1a
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/create.sql
@@ -0,0 +1,42 @@
+{# ===================== Create new view ===================== #}
+{% if display_comments %}
+-- View: {{ conn|qtIdent(data.schema, data.name) }}
+
+-- DROP MATERIALIZED VIEW {{ conn|qtIdent(data.schema, data.name) }};
+
+{% endif %}
+{% if data.name and data.schema and data.definition %}
+CREATE MATERIALIZED VIEW {{ conn|qtIdent(data.schema, data.name) }}
+{% if(data.fillfactor or data['autovacuum_enabled'] or data['toast_autovacuum_enabled']) %}
+WITH (
+{% if data.fillfactor %}
+    FILLFACTOR = {{ data.fillfactor }}{% if data['autovacuum_enabled'] or data['toast_autovacuum_enabled'] or data['vacuum_data']|length > 0 %},{{ '\r' }}{% endif %}
+{% endif %}
+{% if data['autovacuum_enabled'] %}
+    autovacuum_enabled = {{ data['autovacuum_enabled']|lower }}{% if data['toast_autovacuum_enabled'] or data['vacuum_data']|length > 0 %},{{ '\r' }}{% endif %}
+{% endif %}
+{% if data['toast_autovacuum_enabled'] %}
+    {{ 'toast.autovacuum_enabled' }} = {{ data['toast_autovacuum_enabled']|lower }}{% if data['vacuum_data']|length > 0 %},{{ '\r' }}{% endif %}
+{% endif %}
+{% for field in data['vacuum_data'] %}
+{% if field.value is defined and field.value != '' and field.value != none %}
+{% if loop.index > 1%},
+{% endif %}    {{ field.name }} = {{ field.value|lower }}{% endif %}
+{% endfor %}
+
+)
+{% endif %}
+{% if data.spcname %}TABLESPACE {{ data.spcname }}
+{% endif %}AS
+{{ data.definition.rstrip(';') }}
+{% if data.with_data %}
+WITH DATA;
+{% else %}
+WITH NO DATA;
+{% endif %}
+{% if data.comment %}
+
+COMMENT ON VIEW {{ conn|qtIdent(data.schema, data.name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/delete.sql
new file mode 100644
index 0000000..cf667fc
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/delete.sql
@@ -0,0 +1,13 @@
+{# =================== Drop/Cascade materialized view by name ====================#}
+{% if vid %}
+SELECT
+    c.relname As name,
+    nsp.nspname
+FROM
+    pg_class c
+LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
+WHERE
+    c.relfilenode = {{ vid }};
+{% elif (name and nspname) %}
+DROP MATERIALIZED VIEW {{ conn|qtIdent(nspname, name) }} {% if cascade %} CASCADE {% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/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/views/templates/mview/ppas/9.3_plus/sql/grant.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/grant.sql
new file mode 100644
index 0000000..cff9d31
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/grant.sql
@@ -0,0 +1,6 @@
+{# ===== Grant Permissions to User Role on Views/Tables ==== #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{# We will generate Security Label SQL using macro #}
+{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{% endfor %}{% endif %}
+{% if data.datacl %}{% for priv in data.datacl %}{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}{% endfor %}{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/properties.sql
new file mode 100644
index 0000000..f02bc54
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/properties.sql
@@ -0,0 +1,111 @@
+{# ========================== Fetch Materialized View Properties ========================= #}
+{% if (vid and datlastsysoid) or scid %}
+SELECT
+    c.oid,
+    c.xmin,
+    c.relname AS name,
+    c.reltablespace AS spcoid,
+    c.relispopulated AS with_data,
+    (CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
+    c.relacl,
+    nsp.nspname as schema,
+    pg_get_userbyid(c.relowner) AS owner,
+    description AS comment,
+    pg_get_viewdef(c.oid, true) AS definition,
+    {#=============Checks if it is system view================#}
+    {% if vid and datlastsysoid %}
+    CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
+    {% endif %}
+    array_to_string(c.relacl::text[], ', ') AS acl,
+    (SELECT array_agg(provider || '=' || label) FROM pg_seclabels sl1 WHERE sl1.objoid=c.oid AND sl1.objsubid=0) AS seclabels,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'fillfactor=([0-9]*)') AS fillfactor,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_enabled=([a-z|0-9]*)') AS autovacuum_enabled,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_vacuum_threshold=([0-9]*)') AS autovacuum_vacuum_threshold,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_vacuum_scale_factor=([0-9]*[.][0-9]*)') AS autovacuum_vacuum_scale_factor,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_analyze_threshold=([0-9]*)') AS autovacuum_analyze_threshold,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_analyze_scale_factor=([0-9]*[.][0-9]*)') AS autovacuum_analyze_scale_factor,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_vacuum_cost_delay=([0-9]*)') AS autovacuum_vacuum_cost_delay,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_vacuum_cost_limit=([0-9]*)') AS autovacuum_vacuum_cost_limit,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_freeze_min_age=([0-9]*)') AS autovacuum_freeze_min_age,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_freeze_max_age=([0-9]*)') AS autovacuum_freeze_max_age,
+    substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_freeze_table_age=([0-9]*)') AS autovacuum_freeze_table_age,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_enabled=([a-z|0-9]*)') AS toast_autovacuum_enabled,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_vacuum_threshold=([0-9]*)') AS toast_autovacuum_vacuum_threshold,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_vacuum_scale_factor=([0-9]*[.][0-9]*)') AS toast_autovacuum_vacuum_scale_factor,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_analyze_threshold=([0-9]*)') AS toast_autovacuum_analyze_threshold,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_analyze_scale_factor=([0-9]*[.][0-9]*)') AS toast_autovacuum_analyze_scale_factor,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_vacuum_cost_delay=([0-9]*)') AS toast_autovacuum_vacuum_cost_delay,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_vacuum_cost_limit=([0-9]*)') AS toast_autovacuum_vacuum_cost_limit,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_freeze_min_age=([0-9]*)') AS toast_autovacuum_freeze_min_age,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_freeze_max_age=([0-9]*)') AS toast_autovacuum_freeze_max_age,
+    substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_freeze_table_age=([0-9]*)') AS toast_autovacuum_freeze_table_age,
+    c.reloptions AS reloptions, tst.reloptions AS toast_reloptions,
+    (CASE WHEN c.reltoastrelid = 0 THEN false ELSE true END) AS hastoasttable,
+    (CASE WHEN (substring(array_to_string(c.reloptions, ',')
+      FROM 'autovacuum_enabled=([a-z|0-9]*)'))::boolean  THEN true ELSE false END) AS autovacuum_custom,
+    (CASE WHEN (substring(array_to_string(tst.reloptions, ',')
+      FROM 'autovacuum_enabled=([a-z|0-9]*)'))::boolean  AND c.reltoastrelid = 0 THEN true ELSE false END) AS toast_autovaccum
+FROM
+    pg_class c
+LEFT OUTER JOIN pg_namespace nsp on nsp.oid = c.relnamespace
+LEFT OUTER JOIN pg_tablespace spc on spc.oid=c.reltablespace
+LEFT OUTER JOIN pg_description des ON (des.objoid=c.oid and des.objsubid=0 AND des.classoid='pg_class'::regclass)
+LEFT OUTER JOIN pg_class tst ON tst.oid = c.reltoastrelid
+    WHERE ((c.relhasrules AND (EXISTS (
+        SELECT
+            r.rulename
+        FROM
+            pg_rewrite r
+        WHERE
+            ((r.ev_class = c.oid)
+                AND (bpchar(r.ev_type) = '1'::bpchar)) )))
+            AND (c.relkind = 'm'::char)
+          )
+{% if (vid and datlastsysoid) %}
+    AND c.oid = {{vid}}::oid
+{% elif scid %}
+    AND c.relnamespace = {{scid}}::oid
+ORDER BY
+    c.relname
+{% endif %}
+
+{% elif type == 'roles' %}
+SELECT
+    pr.rolname
+FROM
+    pg_roles pr
+WHERE
+    pr.rolcanlogin
+ORDER BY
+    pr.rolname
+
+{% elif type == 'schemas' %}
+SELECT
+    nsp.nspname
+FROM
+    pg_namespace nsp
+WHERE
+    (nsp.nspname NOT LIKE E'pg\\_%'
+        AND nsp.nspname != 'information_schema')
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/update.sql
new file mode 100644
index 0000000..184bbcd
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/update.sql
@@ -0,0 +1,154 @@
+{# ===================== Update View ===================#}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{%- if data -%}
+{% set view_name = data.name if data.name else o_data.name %}
+{% set view_schema = data.schema if data.schema else o_data.schema %}
+{% set def = data.definition.rstrip(';') if data.definition %}
+{# ===== Rename mat view ===== #}
+{% if data.name and data.name != o_data.name %}
+ALTER MATERIALIZED VIEW {{ conn|qtIdent(o_data.schema, o_data.name) }}
+  RENAME TO {{ conn|qtIdent(data.name) }};
+
+{% endif %}
+{# ===== Alter schema view ===== #}
+{% if data.schema and data.schema != o_data.schema %}
+ALTER MATERIALIZED VIEW {{ conn|qtIdent(o_data.schema, view_name ) }}
+  SET SCHEMA {{ conn|qtIdent(data.schema) }};
+
+{% endif %}
+{# ===== Alter Table owner ===== #}
+{% if data.owner and data.owner != o_data.owner %}
+ALTER TABLE {{ conn|qtIdent(view_schema, view_name) }}
+  OWNER TO {{ conn|qtIdent(data.owner) }};
+
+{% endif %}
+{% if data['vacuum_data']['reset']|length > 0 %}
+ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
+RESET(
+{% for field in data['vacuum_data']['reset'] %}
+  {{ field.name }}{% if not loop.last  %},{% endif %}{{ '\r' }}
+{% endfor %}
+);
+{% endif %}
+{# ===== First Drop and then create mat view ===== #}
+{% if def and def != o_data.definition.rstrip(';') %}
+{% if data.fillfactor or ( data['vacuum_data']['changed']|length > 0 ) %}
+DROP MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }};
+CREATE MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
+WITH(
+{% if data.fillfactor %}
+  FILLFACTOR = {{ data.fillfactor }}{% if data['vacuum_data']['changed']|length > 0 %},{% endif %}{{ '\r' }}
+{% endif %}
+{% if data['vacuum_data']['changed']|length > 0 %}
+{% for field in data['vacuum_data']['changed'] %}
+  {{ field.name }} = {{ field.value|lower }}{% if not loop.last  %},{% endif %}{{ '\r' }}
+{% endfor %}
+{% endif %}
+)
+ AS
+{{ def }}
+{% if data.with_data %}
+ WITH DATA;
+
+{% else %}
+ WITH NO DATA;
+
+{% endif %}
+{% endif %}
+{% else %}
+{# ======= Alter Tablespace ========= #}
+{%- if data.spcoid and o_data.spcoid != data.spcoid  -%}
+ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
+  SET TABLESPACE {{ data.spcoid }};
+
+{% endif %}
+{# ======= SET/RESET Fillfactor ========= #}
+{% if data.fillfactor and o_data.fillfactor != data.fillfactor %}
+ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
+SET(FILLFACTOR = {{ data.fillfactor }});
+
+{% elif data.fillfactor == '' %}
+ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
+RESET(
+  FILLFACTOR
+);
+
+{% endif %}
+{# ===== Check for with_data property ===== #}
+{% if data.with_data is defined and o_data.with_data|lower != data.with_data|lower  %}
+REFRESH MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }} WITH{{ ' NO' if data.with_data|lower == 'false' else '' }} DATA;
+
+{% endif %}
+{# ===== Check for Table tab properties ===== #}
+{% if data.autovacuum_custom is defined and data.autovacuum_custom|lower == 'false' %}
+ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
+RESET(
+  autovacuum_vacuum_threshold,
+  autovacuum_analyze_threshold,
+  autovacuum_vacuum_scale_factor,
+  autovacuum_analyze_scale_factor,
+  autovacuum_vacuum_cost_delay,
+  autovacuum_vacuum_cost_limit,
+  autovacuum_freeze_min_age,
+  autovacuum_freeze_max_age,
+  autovacuum_freeze_table_age
+);
+
+{% elif(data['vacuum_data']['changed']|length > 0) %}
+{% if data['vacuum_data']['changed']|length == 1 and data['vacuum_data']['changed'][0]['name'] != 'autovacuum_enabled' %}
+ALTER MATERIALIZED VIEW {{ conn|qtIdent(data.schema, data.name) }} SET(
+{% for field in data['vacuum_data']['changed'] %}
+{% if field.value != None %}
+  {{ field.name }} = {{ field.value|lower }}{% if not loop.last  %},{% endif %}{{ '\r' }}
+{% endif %}
+{% endfor %}
+);
+{% endif %}
+
+{% endif %}{# ===== End check for custom autovaccum ===== #}
+{% endif %}{# ===== End block for check data definition ===== #}
+{%- if data.comment and data.comment != o_data.comment -%}
+COMMENT ON MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
+  IS {{ data.comment|qtLiteral }};
+
+{% endif %}
+{# ============= The SQL generated below will change privileges ============= #}
+{% if data.datacl %}
+{% if 'deleted' in data.datacl %}
+{% for priv in data.datacl.deleted %}
+{{ PRIVILEGE.RESETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in data.datacl %}
+{% for priv in data.datacl.changed -%}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{%- endfor %}
+{% endif %}
+{% if 'added' in data.datacl %}
+{% for priv in data.datacl.added %}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{# ============== The SQL generated below will change Security Label ========= #}
+{% if data.seclabels is not none and data.seclabels|length > 0 %}
+{% set seclabels = data.seclabels %}
+{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+{% for r in seclabels.deleted %}
+{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/view_id.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/view_id.sql
new file mode 100644
index 0000000..d192a80
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/ppas/9.3_plus/sql/view_id.sql
@@ -0,0 +1,4 @@
+{# ===== Below will provide view id for last created view ==== #}
+{% if data %}
+SELECT c.oid FROM pg_class c WHERE c.relname = '{{ data.name }}';
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/css/view.css b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/css/view.css
new file mode 100644
index 0000000..89eae4e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/css/view.css
@@ -0,0 +1,12 @@
+.icon-view{
+  background-image: url('{{ url_for('NODE-view.static', filename='img/view.png') }}') !important;
+  border-radius: 10px;
+  background-repeat: no-repeat;
+  align-content: center;
+  vertical-align: middle;
+  height: 1.3em;
+}
+
+.sql_field_height_140 {
+  height: 140px;
+}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/js/view.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/js/view.js
new file mode 100644
index 0000000..878a5ac
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/js/view.js
@@ -0,0 +1,268 @@
+define(
+  ['jquery', 'underscore', 'underscore.string', 'pgadmin',
+    'pgadmin.browser', 'codemirror', 'pgadmin.browser.server.privilege', 'pgadmin.node.rule'],
+
+function($, _, S, pgAdmin, pgBrowser, CodeMirror) {
+
+  /**
+    Create and add a view collection into nodes
+    @param {variable} label - Label for Node
+    @param {variable} type - Type of Node
+    @param {variable} columns - List of columns to
+      display under under properties.
+   */
+  if (!pgBrowser.Nodes['coll-view']) {
+    var views= pgAdmin.Browser.Nodes['coll-view'] =
+      pgAdmin.Browser.Collection.extend({
+        node: 'view',
+        label: '{{ _("Views") }}',
+        type: 'coll-view',
+        columns: ["name", "owner"]
+      });
+  }
+
+  /**
+    Create and Add a View Node into nodes
+    @param {variable} parent_type - The list of nodes
+    under which this node to display
+    @param {variable} type - Type of Node
+    @param {variable} hasSQL - To show SQL tab
+    @param {variable} canDrop - Adds drop view option
+    in the context menu
+    @param {variable} canDropCascade - Adds drop Cascade
+    view option in the context menu
+   */
+  if (!pgBrowser.Nodes['view']) {
+    pgAdmin.Browser.Nodes['view'] = pgAdmin.Browser.Node.extend({
+      parent_type: ['schema', 'catalog'],
+      type: 'view',
+      sqlAlterHelp: 'sql-alterview.html',
+      sqlCreateHelp: 'sql-createview.html',
+      label: '{{ _("View") }}',
+      hasSQL:  true,
+      hasDepends: true,
+      collection_type: 'coll-view',
+      canDrop: pgBrowser.Nodes['schema'].canChildDrop,
+      canDropCascade: pgBrowser.Nodes['schema'].canChildDrop,
+      Init: function() {
+
+        // Avoid mulitple registration of menus
+        if (this.initialized)
+          return;
+
+        this.initialized = true;
+
+        /**
+          Add "create view" menu option into context and object menu
+          for the following nodes:
+          coll-view, view and schema.
+          @property {data} - Allow create view option on schema node or
+          system view nodes.
+         */
+        pgBrowser.add_menus([{
+          name: 'create_view_on_coll', node: 'coll-view', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 1, label: '{{ _("View...") }}',
+          icon: 'wcTabIcon icon-view', data: {action: 'create', check: true},
+          enable: 'canCreate'
+        },{
+          name: 'create_view', node: 'view', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 1, label: '{{ _("View...") }}',
+          icon: 'wcTabIcon icon-view', data: {action: 'create', check: true},
+          enable: 'canCreate'
+        },{
+          name: 'create_view', node: 'schema', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 17, label: '{{ _("View...") }}',
+          icon: 'wcTabIcon icon-view', data: {action: 'create', check: false},
+          enable: 'canCreate'
+        }
+        ]);
+      },
+
+      /**
+        Define model for the view node and specify the
+        properties of the model in schema.
+       */
+      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({'schema': schema_id}, {silent: true});
+
+            // Set Current User
+            var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user;
+            this.set({'owner': userInfo.name}, {silent: true});
+          }
+          pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments);
+        },
+        schema: [{
+          id: 'name', label: '{{ _("Name") }}', cell: 'string',
+          type: 'text', disabled: 'inSchema'
+        },
+        {
+          id: 'oid', label:'{{ _("OID") }}', cell: 'string',
+          type: 'text', disabled: true, mode: ['properties']
+        },
+        {
+          id: 'owner', label:'{{ _("Owner") }}', cell: 'string', control: 'node-list-by-name',
+          node: 'role', disabled: 'inSchema'
+        },
+        {
+          id: 'schema', label:'{{ _("Schema") }}', cell: 'string', first_empty: false,
+          control: 'node-list-by-id', type: 'text', cache_level: 'database',
+          node: 'schema', disabled: 'inSchema', mode: ['create', 'edit'],
+        },
+        {
+          id: 'system_view', label:'{{ _("System view?") }}', cell: 'string',
+          type: 'switch', disabled: true, mode: ['properties']
+        },
+        {
+          id: 'acl', label: '{{ _("Privileges") }}',
+          mode: ['properties'], type: 'text'
+        },
+        {
+          id: 'comment', label:'{{ _("Comment") }}', cell: 'string',
+          type: 'multiline', disabled: 'inSchema'
+        },
+        {
+          id: 'security_barrier', label:'{{ _("Security barrier") }}', cell: 'string',
+          type: 'switch', min_version: '90200', mode: ['create', 'edit'],
+          group: 'Definition', disabled: 'inSchema'
+        },
+        {
+          id: 'check_option', label:'{{ _("Check options") }}',
+          control: 'select2', group: 'Definition', type: 'text',
+          min_version: '90400', mode:['properties', 'create', 'edit'],
+          select2: {
+
+            // set select2 option width to 100%
+            width: '100%'
+          },
+          options:[
+            {label: "No", value: "no"},
+            {label: "Local", value: "local"},
+            {label: "Cascaded", value: "cascaded"}
+          ], disabled: 'inSchema'
+        },
+        {
+          id: 'definition', label:'{{ _("Definition") }}', cell: 'string',
+          type: 'text', mode: ['create', 'edit'], group: 'Definition',
+          control: Backform.SqlFieldControl, extraClasses:['sql_field_height_140'],
+          disabled: 'inSchema'
+        },
+        {
+          id: 'security', label: '{{ _("Security") }}',
+          type: 'group',
+          visible: function(m) {
+            if (m.top && 'catalog' in m.top.node_info) {
+              return false;
+            }
+            return true;
+          }
+        },
+
+        // Add Privilege Control
+        {
+          id: 'datacl', label: '{{ _("Privileges") }}',
+          model: pgAdmin.Browser.Node.PrivilegeRoleModel.extend(
+            {privileges: ['a', 'r', 'w', 'd', 'D', 'x', 't']}), uniqueCol : ['grantee'],
+          editable: false, type: 'collection', group: 'security',
+          mode: ['edit', 'create'], canAdd: true, canDelete: true,
+          control: 'unique-col-collection', disabled: 'inSchema'
+        },
+
+        // Add Security Labels Control
+        {
+          id: 'seclabels', label: '{{ _("Security labels") }}',
+          model: Backform.SecurityModel, editable: false, type: 'collection',
+          canEdit: false, group: 'security', canDelete: true,
+          mode: ['edit', 'create'], canAdd: true, disabled: 'inSchema',
+          control: 'unique-col-collection', uniqueCol : ['provider']
+        },
+        ],
+        validate: function() {
+
+          // Triggers specific error messages for fields
+          var err = {},
+            errmsg,
+            field_name = this.get('name'),
+            field_def = this.get('definition');
+          if (_.isUndefined(field_name) || _.isNull(field_name) ||
+            String(field_name).replace(/^\s+|\s+$/g, '') == '') {
+            err['name'] = '{{ _("Please specify name.") }}';
+            errmsg = errmsg || err['name'];
+            this.errorModel.set('name', errmsg);
+            return errmsg;
+          }else{
+            this.errorModel.unset('name');
+          }
+          if(this.isNew()){
+            if (_.isUndefined(field_def) || _.isNull(field_def) ||
+              String(field_def).replace(/^\s+|\s+$/g, '') == '') {
+              err['definition'] = '{{ _("Please enter function definition.") }}';
+              errmsg = errmsg || err['definition'];
+              this.errorModel.set('definition', errmsg);
+              return errmsg;
+            }else{
+              this.errorModel.unset('definition');
+            }
+          }
+          return null;
+        },
+        // We will disable everything if we are under catalog node
+        inSchema: function() {
+          if(this.node_info && 'catalog' in this.node_info)
+          {
+            return true;
+          }
+          return false;
+        }
+      }),
+
+      /**
+        Show or hide create view menu option on parent node
+        and hide for system view in catalogs.
+       */
+      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 view
+          if (_.indexOf(['schema'], d._type) > -1)
+            return true;
+
+          if ('coll-view' == d._type) {
+
+            // Check if we are not child of view
+            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['coll-view'];
+});
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/acl.sql
new file mode 100644
index 0000000..5850639
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/acl.sql
@@ -0,0 +1,51 @@
+{# ============================ Get ACLs ========================= #}
+{% if vid %}
+SELECT
+    'datacl' as deftype,
+    COALESCE(gt.rolname, 'public') grantee,
+    g.rolname 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 'DELETE' THEN 'd'
+        WHEN 'INSERT' THEN 'a'
+        WHEN 'REFERENCES' THEN 'x'
+        WHEN 'SELECT' THEN 'r'
+        WHEN 'TRIGGER' THEN 't'
+        WHEN 'UPDATE' THEN 'w'
+        WHEN 'TRUNCATE' THEN 'D'
+        ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            relacl
+        FROM
+            pg_class cl
+        LEFT OUTER JOIN pg_shdescription descr ON (
+            cl.oid=descr.objoid AND descr.classoid='pg_class'::regclass)
+        WHERE
+            cl.oid = {{ vid }}::OID AND relkind = 'v'
+        ) acl,
+        (SELECT
+            (d).grantee AS grantee,
+            (d).grantor AS grantor,
+            (d).is_grantable AS is_grantable,
+            (d).privilege_type AS privilege_type
+        FROM
+            (SELECT
+                aclexplode(relacl) AS d
+             FROM
+                pg_class cl1
+             WHERE
+                cl1.oid = {{ vid }}
+            ) 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
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/create.sql
new file mode 100644
index 0000000..b11bc8e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/create.sql
@@ -0,0 +1,20 @@
+{#============================Create new view=========================#}
+{% if display_comments %}
+-- View: {{ conn|qtIdent(data.schema, data.name) }}
+
+-- DROP VIEW {{ conn|qtIdent(data.schema, data.name) }};
+
+{% endif %}
+{% if data.name and data.schema and data.definition %}
+CREATE OR REPLACE VIEW {{ conn|qtIdent(data.schema, data.name) }} AS
+{{ data.definition.rstrip(';') }};
+{% if data.owner %}
+
+ALTER TABLE {{ conn|qtIdent(data.schema, data.name) }}
+    OWNER TO {{ data.owner }};
+{% endif %}
+{% if data.comment %}
+COMMENT ON VIEW {{ conn|qtIdent(data.schema, data.name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/delete.sql
new file mode 100644
index 0000000..e50beec
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/delete.sql
@@ -0,0 +1,13 @@
+{# ====================== Drop/Cascade view by name ===================== #}
+{% if vid %}
+SELECT
+    c.relname AS name,
+    nsp.nspname
+FROM
+    pg_class c
+LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
+WHERE
+    c.relfilenode = {{ vid }};
+{% elif (name and nspname) %}
+DROP VIEW {{nspname}}.{{ conn|qtIdent(name) }} {% if cascade %} CASCADE {% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/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/views/templates/view/pg/9.1_plus/sql/grant.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/grant.sql
new file mode 100644
index 0000000..59a310f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/grant.sql
@@ -0,0 +1,6 @@
+{# ===== Grant Permissions to User Role on Views/Tables ===== #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{# ===== We will generate Security Label SQL using macro ===== #}
+{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{% endfor %}{% endif %}{% if data.datacl %}
+{% for priv in data.datacl %}{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}{% endfor %}{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/properties.sql
new file mode 100644
index 0000000..ce1d801
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/properties.sql
@@ -0,0 +1,69 @@
+{% if (vid and datlastsysoid) or scid %}
+SELECT
+    c.oid,
+    c.xmin,
+    (CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
+    c.relname AS name,
+    nsp.nspname AS schema,
+    description AS comment,
+    c.reltablespace AS spcoid,
+    pg_get_userbyid(c.relowner) AS owner,
+    pg_get_viewdef(c.oid, true) AS definition,
+    array_to_string(c.relacl::text[], ', ') AS acl,
+    {#=============Checks if it is system view================#}
+    {% if vid and datlastsysoid %}
+    CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
+    {% endif %}
+    (SELECT
+        array_agg(label)
+     FROM
+        pg_seclabels sl1
+     WHERE
+        sl1.objoid=c.oid AND sl1.objsubid=0
+    ) AS labels,
+    (SELECT
+        array_agg(provider)
+     FROM
+        pg_seclabels sl2
+     WHERE sl2.objoid=c.oid AND sl2.objsubid=0
+    ) AS providers
+FROM pg_class c
+    LEFT OUTER JOIN pg_namespace nsp on nsp.oid = c.relnamespace
+    LEFT OUTER JOIN pg_tablespace spc on spc.oid=c.reltablespace
+    LEFT OUTER JOIN pg_description des ON (des.objoid=c.oid and des.objsubid=0 AND des.classoid='pg_class'::regclass)
+WHERE ((c.relhasrules
+            AND
+                (EXISTS(
+                    SELECT
+                        r.rulename
+                    FROM
+                        pg_rewrite r
+                    WHERE
+                        ((r.ev_class = c.oid) AND (bpchar(r.ev_type) = '1'::bpchar))
+                ))
+       ) AND (c.relkind = 'v'::char))
+{% if (vid and datlastsysoid) %}
+    AND c.oid = {{vid}}::oid
+{% elif scid %}
+    AND c.relnamespace = {{scid}}::oid ORDER BY c.relname
+{% endif %}
+
+{% elif type == 'roles' %}
+SELECT
+    pr.rolname
+FROM
+    pg_roles pr
+WHERE
+    pr.rolcanlogin
+ORDER BY
+    pr.rolname
+
+{% elif type == 'schemas' %}
+SELECT
+    nsp.nspname
+FROM
+    pg_namespace nsp
+WHERE
+    (nsp.nspname NOT LIKE E'pg\\_%'
+        AND nsp.nspname != 'information_schema')
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/update.sql
new file mode 100644
index 0000000..2f7f82e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/update.sql
@@ -0,0 +1,66 @@
+{# ============================ Update View ========================= #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{% if data %}
+{% set view_name = data.name if data.name else o_data.name %}
+{% set view_schema = data.schema if data.schema else o_data.schema %}
+{% set def = data.definition.rstrip(';') if data.definition %}
+{% if data.name and data.name != o_data.name %}
+ALTER VIEW {{ conn|qtIdent(o_data.schema, o_data.name) }}
+    RENAME TO {{ conn|qtIdent(data.name) }};
+{% endif %}
+{% if data.schema and data.schema != o_data.schema %}
+ALTER VIEW {{ conn|qtIdent(o_data.schema, view_name ) }}
+    SET SCHEMA {{ conn|qtIdent(data.schema) }};
+{% endif %}
+{% if data.owner and data.owner != o_data.owner %}
+ALTER TABLE {{ conn|qtIdent(view_schema, view_name) }}
+    OWNER TO {{ conn|qtIdent(data.owner) }};
+{% endif %}
+{% if def and def != o_data.definition.rstrip(';') %}
+CREATE OR REPLACE VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    AS{{ def }};
+{% endif %}
+{% if data.comment and data.comment != o_data.comment %}
+COMMENT ON VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{# The SQL generated below will change privileges #}
+{% if data.datacl %}
+{% if 'deleted' in data.datacl %}
+{% for priv in data.datacl.deleted %}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in data.datacl %}
+{% for priv in data.datacl.changed %}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in data.datacl %}
+{% for priv in data.datacl.added %}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{# The SQL generated below will change Security Label #}
+{% if data.seclabels is not none and data.seclabels|length > 0 %}
+{% set seclabels = data.seclabels %}
+{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+{% for r in seclabels.deleted %}
+{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/view_id.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/view_id.sql
new file mode 100644
index 0000000..6dff04e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.1_plus/sql/view_id.sql
@@ -0,0 +1,4 @@
+{# Below will provide view id for newly created view #}
+{% if data %}
+SELECT c.oid FROM pg_class c WHERE c.relname = '{{ data.name }}';
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/acl.sql
new file mode 100644
index 0000000..5f2d0fb
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/acl.sql
@@ -0,0 +1,52 @@
+{# ============================ Get ACLs ========================= #}
+{% if vid %}
+SELECT
+    'datacl' as deftype,
+    COALESCE(gt.rolname, 'public') grantee,
+    g.rolname 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 'DELETE' THEN 'd'
+        WHEN 'INSERT' THEN 'a'
+        WHEN 'REFERENCES' THEN 'x'
+        WHEN 'SELECT' THEN 'r'
+        WHEN 'TRIGGER' THEN 't'
+        WHEN 'UPDATE' THEN 'w'
+        WHEN 'TRUNCATE' THEN 'D'
+        ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            relacl
+        FROM
+            pg_class cl
+        LEFT OUTER JOIN pg_shdescription descr ON (
+            cl.oid=descr.objoid AND descr.classoid='pg_class'::regclass)
+        WHERE
+            cl.oid = {{ vid }}::OID AND relkind = 'v'
+        ) acl,
+        (SELECT
+            (d).grantee AS grantee,
+            (d).grantor AS grantor,
+            (d).is_grantable AS is_grantable,
+            (d).privilege_type AS privilege_type
+        FROM
+            (SELECT
+                aclexplode(relacl) AS d
+             FROM
+                pg_class cl1
+             WHERE
+                cl1.oid = {{ vid }}
+            ) 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
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/create.sql
new file mode 100644
index 0000000..4ffb72f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/create.sql
@@ -0,0 +1,23 @@
+{#============================Create new view=========================#}
+{% if display_comments %}
+-- View: {{ conn|qtIdent(data.schema, data.name) }}
+
+-- DROP VIEW {{ conn|qtIdent(data.schema, data.name) }};
+
+{% endif %}
+{% if data.name and data.schema and data.definition %}
+CREATE OR REPLACE VIEW {{ conn|qtIdent(data.schema, data.name) }}{% if (data.security_barrier) %}{{'\r'}}
+WITH (
+{% if data.security_barrier %}    security_barrier={{ data.security_barrier|lower }}{% endif %}{{'\r'}}
+){% endif %} AS
+{{ data.definition.rstrip(';') }};
+{% if data.owner %}
+
+ALTER TABLE {{ conn|qtIdent(data.schema, data.name) }}
+    OWNER TO {{ data.owner }};
+{% endif %}
+{% if data.comment %}
+COMMENT ON VIEW {{ conn|qtIdent(data.schema, data.name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/delete.sql
new file mode 100644
index 0000000..e50beec
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/delete.sql
@@ -0,0 +1,13 @@
+{# ====================== Drop/Cascade view by name ===================== #}
+{% if vid %}
+SELECT
+    c.relname AS name,
+    nsp.nspname
+FROM
+    pg_class c
+LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
+WHERE
+    c.relfilenode = {{ vid }};
+{% elif (name and nspname) %}
+DROP VIEW {{nspname}}.{{ conn|qtIdent(name) }} {% if cascade %} CASCADE {% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/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/views/templates/view/pg/9.2_plus/sql/grant.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/grant.sql
new file mode 100644
index 0000000..59a310f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/grant.sql
@@ -0,0 +1,6 @@
+{# ===== Grant Permissions to User Role on Views/Tables ===== #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{# ===== We will generate Security Label SQL using macro ===== #}
+{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{% endfor %}{% endif %}{% if data.datacl %}
+{% for priv in data.datacl %}{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}{% endfor %}{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/properties.sql
new file mode 100644
index 0000000..20eb3df
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/properties.sql
@@ -0,0 +1,70 @@
+{% if (vid and datlastsysoid) or scid %}
+SELECT
+    c.oid,
+    c.xmin,
+    c.relname AS name,
+    c.reltablespace AS spcoid,
+    (CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
+    pg_get_userbyid(c.relowner) AS owner,
+    description As comment,
+    pg_get_viewdef(c.oid, true) AS definition,
+    nsp.nspname AS schema,
+    array_to_string(c.relacl::text[], ', ') AS acl,
+    {#=============Checks if it is system view================#}
+    {% if vid and datlastsysoid %}
+    CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
+    {% endif %}
+(SELECT
+    array_agg(label)
+FROM
+    pg_seclabels sl1
+WHERE
+    sl1.objoid=c.oid AND sl1.objsubid=0) AS labels,
+(SELECT
+    array_agg(provider)
+FROM
+    pg_seclabels sl2
+WHERE
+    sl2.objoid=c.oid AND sl2.objsubid=0) AS providers,
+    (substring(array_to_string(c.reloptions, ',')
+        FROM 'security_barrier=([a-z|0-9]*)'))::boolean AS security_barrier
+FROM pg_class c
+LEFT OUTER JOIN pg_namespace nsp on nsp.oid = c.relnamespace
+LEFT OUTER JOIN pg_tablespace spc on spc.oid=c.reltablespace
+LEFT OUTER JOIN pg_description des ON (des.objoid=c.oid and des.objsubid=0 AND des.classoid='pg_class'::regclass)
+    WHERE ((c.relhasrules AND (EXISTS (
+            SELECT
+                r.rulename
+            FROM
+                pg_rewrite r
+            WHERE
+                ((r.ev_class = c.oid)
+                    AND (bpchar(r.ev_type) = '1'::bpchar)
+                ) ))
+           ) AND (c.relkind = 'v'::char)
+          )
+{% if (vid and datlastsysoid) %}
+    AND c.oid = {{vid}}::oid
+{% elif scid %}
+    AND c.relnamespace = {{scid}}::oid ORDER BY c.relname
+{% endif %}
+
+{% elif type == 'roles' %}
+SELECT
+    pr.rolname
+FROM
+    pg_roles pr
+WHERE
+    pr.rolcanlogin
+ORDER BY
+    pr.rolname
+
+{% elif type == 'schemas' %}
+SELECT
+    nsp.nspname
+FROM
+    pg_namespace nsp
+WHERE
+    (nsp.nspname NOT LIKE E'pg\\_%'
+        AND nsp.nspname != 'information_schema')
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/update.sql
new file mode 100644
index 0000000..c37d4ba
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/update.sql
@@ -0,0 +1,74 @@
+{# ============================ Update View ========================= #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{% if data %}
+{% set view_name = data.name if data.name else o_data.name %}
+{% set view_schema = data.schema if data.schema else o_data.schema %}
+{% set def = data.definition.rstrip(';') if data.definition %}
+{% if data.name and data.name != o_data.name %}
+ALTER VIEW {{ conn|qtIdent(o_data.schema, o_data.name) }}
+    RENAME TO {{ conn|qtIdent(data.name) }};
+{% endif %}
+{% if data.schema and data.schema != o_data.schema %}
+ALTER VIEW {{ conn|qtIdent(o_data.schema, view_name ) }}
+    SET SCHEMA {{ conn|qtIdent(data.schema) }};
+{% endif %}
+{% if data.owner and data.owner != o_data.owner %}
+ALTER TABLE {{ conn|qtIdent(view_schema, view_name) }}
+    OWNER TO {{ conn|qtIdent(data.owner) }};
+{% endif %}
+{% if def and def != o_data.definition.rstrip(';') %}
+CREATE OR REPLACE VIEW {{ conn|qtIdent(view_schema, view_name) }}
+{% if (data.security_barrier and data.security_barrier != o_data.security_barrier) %}
+    WITH ({% if data.security_barrier %}security_barrier={{ data.security_barrier|lower }}{% endif %}) {% endif %}
+    AS{{ def }};
+{% else %}
+{% if (data.security_barrier is defined and data.security_barrier|lower !=  o_data.security_barrier|lower) %}
+ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    SET (security_barrier={{ data.security_barrier|lower }});
+{% endif %}
+{% endif %}
+
+{% if data.comment and data.comment != o_data.comment %}
+COMMENT ON VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{# The SQL generated below will change privileges #}
+{% if data.datacl %}
+{% if 'deleted' in data.datacl %}
+{% for priv in data.datacl.deleted %}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in data.datacl %}
+{% for priv in data.datacl.changed %}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in data.datacl %}
+{% for priv in data.datacl.added %}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{# The SQL generated below will change Security Label #}
+{% if data.seclabels is not none and data.seclabels|length > 0 %}
+{% set seclabels = data.seclabels %}
+{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+{% for r in seclabels.deleted %}
+{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/view_id.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/view_id.sql
new file mode 100644
index 0000000..6dff04e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.2_plus/sql/view_id.sql
@@ -0,0 +1,4 @@
+{# Below will provide view id for newly created view #}
+{% if data %}
+SELECT c.oid FROM pg_class c WHERE c.relname = '{{ data.name }}';
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/acl.sql
new file mode 100644
index 0000000..84300cf
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/acl.sql
@@ -0,0 +1,38 @@
+{# ============================ Get ACLs ========================= #}
+{% if vid %}
+SELECT
+    'datacl' as deftype,
+    COALESCE(gt.rolname, 'public') grantee,
+    g.rolname 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 'DELETE' THEN 'd'
+        WHEN 'INSERT' THEN 'a'
+        WHEN 'REFERENCES' THEN 'x'
+        WHEN 'SELECT' THEN 'r'
+        WHEN 'TRIGGER' THEN 't'
+        WHEN 'UPDATE' THEN 'w'
+        WHEN 'TRUNCATE' THEN 'D'
+        ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            relacl
+        FROM
+            pg_class cl
+        LEFT OUTER JOIN pg_shdescription descr ON (
+            cl.oid=descr.objoid AND descr.classoid='pg_class'::regclass)
+        WHERE cl.oid = {{ vid }}::OID AND relkind = 'v'
+        ) acl,
+        aclexplode(relacl) 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
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/create.sql
new file mode 100644
index 0000000..4ffb72f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/create.sql
@@ -0,0 +1,23 @@
+{#============================Create new view=========================#}
+{% if display_comments %}
+-- View: {{ conn|qtIdent(data.schema, data.name) }}
+
+-- DROP VIEW {{ conn|qtIdent(data.schema, data.name) }};
+
+{% endif %}
+{% if data.name and data.schema and data.definition %}
+CREATE OR REPLACE VIEW {{ conn|qtIdent(data.schema, data.name) }}{% if (data.security_barrier) %}{{'\r'}}
+WITH (
+{% if data.security_barrier %}    security_barrier={{ data.security_barrier|lower }}{% endif %}{{'\r'}}
+){% endif %} AS
+{{ data.definition.rstrip(';') }};
+{% if data.owner %}
+
+ALTER TABLE {{ conn|qtIdent(data.schema, data.name) }}
+    OWNER TO {{ data.owner }};
+{% endif %}
+{% if data.comment %}
+COMMENT ON VIEW {{ conn|qtIdent(data.schema, data.name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/delete.sql
new file mode 100644
index 0000000..e50beec
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/delete.sql
@@ -0,0 +1,13 @@
+{# ====================== Drop/Cascade view by name ===================== #}
+{% if vid %}
+SELECT
+    c.relname AS name,
+    nsp.nspname
+FROM
+    pg_class c
+LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
+WHERE
+    c.relfilenode = {{ vid }};
+{% elif (name and nspname) %}
+DROP VIEW {{nspname}}.{{ conn|qtIdent(name) }} {% if cascade %} CASCADE {% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/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/views/templates/view/pg/9.3_plus/sql/grant.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/grant.sql
new file mode 100644
index 0000000..59a310f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/grant.sql
@@ -0,0 +1,6 @@
+{# ===== Grant Permissions to User Role on Views/Tables ===== #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{# ===== We will generate Security Label SQL using macro ===== #}
+{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{% endfor %}{% endif %}{% if data.datacl %}
+{% for priv in data.datacl %}{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}{% endfor %}{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/properties.sql
new file mode 100644
index 0000000..7f03304
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/properties.sql
@@ -0,0 +1,74 @@
+{% if (vid and datlastsysoid) or scid %}
+SELECT
+    c.oid,
+    c.xmin,
+    c.relkind,
+    description,
+    (CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
+    c.relname AS name,
+    nsp.nspname AS schema,
+    c.reltablespace AS spcoid,
+    c.relispopulated AS ispopulated,
+    pg_get_userbyid(c.relowner) AS owner,
+    array_to_string(c.relacl::text[], ', ') AS acl,
+    pg_get_viewdef(c.oid, true) AS definition,
+    {# ===== Checks if it is system view ===== #}
+    {% if vid and datlastsysoid %}
+    CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
+    {% endif %}
+(SELECT
+    array_agg(label)
+FROM
+    pg_seclabels sl1
+WHERE
+    sl1.objoid=c.oid AND sl1.objsubid=0) AS labels,
+(SELECT
+    array_agg(provider)
+FROM
+    pg_seclabels sl2
+WHERE
+    sl2.objoid=c.oid AND sl2.objsubid=0) AS providers,
+    (substring(array_to_string(c.reloptions, ',')
+        FROM 'security_barrier=([a-z|0-9]*)'))::boolean AS security_barrier
+FROM pg_class c
+LEFT OUTER JOIN pg_namespace nsp on nsp.oid = c.relnamespace
+LEFT OUTER JOIN pg_tablespace spc on spc.oid=c.reltablespace
+LEFT OUTER JOIN pg_description des ON (des.objoid=c.oid and des.objsubid=0 AND des.classoid='pg_class'::regclass)
+LEFT OUTER JOIN pg_class tst ON tst.oid = c.reltoastrelid
+    WHERE ((c.relhasrules AND (EXISTS (
+        SELECT
+            r.rulename
+        FROM
+            pg_rewrite r
+        WHERE
+            ((r.ev_class = c.oid)
+                AND (bpchar(r.ev_type) = '1'::bpchar)) )))
+            AND (c.relkind = 'v'::char)
+          )
+{% if (vid and datlastsysoid) %}
+    AND c.oid = {{vid}}::oid
+{% elif scid %}
+    AND c.relnamespace = {{scid}}::oid
+ORDER BY
+    c.relname
+{% endif %}
+
+{% elif type == 'roles' %}
+SELECT
+    pr.rolname
+FROM
+    pg_roles pr
+WHERE
+    pr.rolcanlogin
+ORDER BY
+    pr.rolname
+
+{% elif type == 'schemas' %}
+SELECT
+    nsp.nspname
+FROM
+    pg_namespace nsp
+WHERE
+    (nsp.nspname NOT LIKE E'pg\\_%'
+        AND nsp.nspname != 'information_schema')
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/update.sql
new file mode 100644
index 0000000..02d8f37
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/update.sql
@@ -0,0 +1,75 @@
+{# ============================ Update View ========================= #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{% if data %}
+{% set view_name = data.name if data.name else o_data.name %}
+{% set view_schema = data.schema if data.schema else o_data.schema %}
+{% set def = data.definition.rstrip(';') if data.definition %}
+{% if data.name and data.name != o_data.name %}
+ALTER VIEW {{ conn|qtIdent(o_data.schema, o_data.name) }}
+    RENAME TO {{ conn|qtIdent(data.name) }};
+{% endif %}
+{% if data.schema and data.schema != o_data.schema %}
+ALTER VIEW {{ conn|qtIdent(o_data.schema, view_name ) }}
+    SET SCHEMA {{ conn|qtIdent(data.schema) }};
+{% endif %}
+{% if data.owner and data.owner != o_data.owner %}
+ALTER TABLE {{ conn|qtIdent(view_schema, view_name) }}
+    OWNER TO {{ conn|qtIdent(data.owner) }};
+{% endif %}
+{% if def and def != o_data.definition.rstrip(';') %}
+CREATE OR REPLACE VIEW {{ conn|qtIdent(view_schema, view_name) }}
+{% if (data.security_barrier and data.security_barrier != o_data.security_barrier) %}
+    WITH ({% if data.security_barrier %}security_barrier={{ data.security_barrier|lower }}{% endif %})
+{% endif %}
+    AS{{ def }};
+{% else %}
+{% if (data.security_barrier is defined and data.security_barrier|lower !=  o_data.security_barrier|lower) %}
+ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    SET (security_barrier={{ data.security_barrier|lower }});
+{% endif %}
+{% endif %}
+
+{% if data.comment and data.comment != o_data.comment %}
+COMMENT ON VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{# The SQL generated below will change privileges #}
+{% if data.datacl %}
+{% if 'deleted' in data.datacl %}
+{% for priv in data.datacl.deleted %}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in data.datacl %}
+{% for priv in data.datacl.changed %}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in data.datacl %}
+{% for priv in data.datacl.added %}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{# The SQL generated below will change Security Label #}
+{% if data.seclabels is not none and data.seclabels|length > 0 %}
+{% set seclabels = data.seclabels %}
+{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+{% for r in seclabels.deleted %}
+{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/view_id.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/view_id.sql
new file mode 100644
index 0000000..6dff04e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.3_plus/sql/view_id.sql
@@ -0,0 +1,4 @@
+{# Below will provide view id for newly created view #}
+{% if data %}
+SELECT c.oid FROM pg_class c WHERE c.relname = '{{ data.name }}';
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/acl.sql
new file mode 100644
index 0000000..7d791f5
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/acl.sql
@@ -0,0 +1,39 @@
+{# ============================ Get ACLs ========================= #}
+{% if vid %}
+SELECT
+    'datacl' as deftype,
+    COALESCE(gt.rolname, 'public') grantee,
+    g.rolname 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 'DELETE' THEN 'd'
+        WHEN 'INSERT' THEN 'a'
+        WHEN 'REFERENCES' THEN 'x'
+        WHEN 'SELECT' THEN 'r'
+        WHEN 'TRIGGER' THEN 't'
+        WHEN 'UPDATE' THEN 'w'
+        WHEN 'TRUNCATE' THEN 'D'
+        ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            relacl
+         FROM
+            pg_class cl
+         LEFT OUTER JOIN pg_shdescription descr ON
+            (cl.oid=descr.objoid AND descr.classoid='pg_class'::regclass)
+         WHERE
+            cl.oid = {{ vid }}::OID AND relkind = 'v'
+        ) acl,
+        aclexplode(relacl) 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
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/create.sql
new file mode 100644
index 0000000..b43b519
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/create.sql
@@ -0,0 +1,22 @@
+{#============================Create new view=========================#}
+{% if display_comments %}
+-- View: {{ conn|qtIdent(data.schema, data.name) }}
+
+-- DROP VIEW {{ conn|qtIdent(data.schema, data.name) }};
+
+{% endif %}
+{% if data.name and data.schema and data.definition %}
+CREATE OR REPLACE VIEW {{ conn|qtIdent(data.schema, data.name) }}{% if ((data.check_option and data.check_option.lower() != 'no') or data.security_barrier) %}{{ '\n' }}WITH (
+{% if data.check_option and data.check_option.lower() != 'no' %}    check_option={{ data.check_option }}{% endif %}{{ ',\r' if data.check_option and data.check_option.lower() != 'no' and data.security_barrier }}{% if data.security_barrier %}    security_barrier={{ data.security_barrier|lower }}{% endif %}{{'\r'}}
+){% endif %} AS
+{{ data.definition.rstrip(';') }};
+{% if data.owner and data.m_view is undefined %}
+
+ALTER TABLE {{ conn|qtIdent(data.schema, data.name) }}
+    OWNER TO {{ conn|qtIdent(data.owner) }};
+{% endif %}
+{% if data.comment %}
+COMMENT ON VIEW {{ conn|qtIdent(data.schema, data.name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/delete.sql
new file mode 100644
index 0000000..e50beec
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/delete.sql
@@ -0,0 +1,13 @@
+{# ====================== Drop/Cascade view by name ===================== #}
+{% if vid %}
+SELECT
+    c.relname AS name,
+    nsp.nspname
+FROM
+    pg_class c
+LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
+WHERE
+    c.relfilenode = {{ vid }};
+{% elif (name and nspname) %}
+DROP VIEW {{nspname}}.{{ conn|qtIdent(name) }} {% if cascade %} CASCADE {% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/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/views/templates/view/pg/9.4_plus/sql/grant.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/grant.sql
new file mode 100644
index 0000000..59a310f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/grant.sql
@@ -0,0 +1,6 @@
+{# ===== Grant Permissions to User Role on Views/Tables ===== #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{# ===== We will generate Security Label SQL using macro ===== #}
+{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{% endfor %}{% endif %}{% if data.datacl %}
+{% for priv in data.datacl %}{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}{% endfor %}{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/properties.sql
new file mode 100644
index 0000000..ccd957f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/properties.sql
@@ -0,0 +1,77 @@
+{# ========================== Fetch View Properties ========================= #}
+{% if (vid and datlastsysoid) or scid %}
+SELECT
+    c.oid,
+    c.xmin,
+    c.relkind,
+    description,
+    (CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
+    c.relname AS name,
+    c.reltablespace AS spcoid,
+    nsp.nspname AS schema,
+    c.relispopulated AS ispopulated,
+    pg_get_userbyid(c.relowner) AS owner,
+    array_to_string(c.relacl::text[], ', ') AS acl,
+    pg_get_viewdef(c.oid, true) AS definition,
+    {# ===== Checks if it is system view ===== #}
+    {% if vid and datlastsysoid %}
+    CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
+    {% endif %}
+(SELECT
+    array_agg(label)
+FROM
+    pg_seclabels sl1
+WHERE
+    sl1.objoid=c.oid AND sl1.objsubid=0) AS labels,
+(SELECT
+    array_agg(provider)
+FROM
+    pg_seclabels sl2
+WHERE
+    sl2.objoid=c.oid AND sl2.objsubid=0) AS providers,
+    substring(array_to_string(c.reloptions, ',')
+        FROM 'check_option=([a-z]*)') AS check_option,
+    (substring(array_to_string(c.reloptions, ',')
+        FROM 'security_barrier=([a-z|0-9]*)'))::boolean AS security_barrier
+FROM pg_class c
+LEFT OUTER JOIN pg_namespace nsp on nsp.oid = c.relnamespace
+LEFT OUTER JOIN pg_tablespace spc on spc.oid=c.reltablespace
+LEFT OUTER JOIN pg_description des ON (des.objoid=c.oid and des.objsubid=0 AND des.classoid='pg_class'::regclass)
+LEFT OUTER JOIN pg_class tst ON tst.oid = c.reltoastrelid
+    WHERE ((c.relhasrules AND (EXISTS (
+        SELECT
+            r.rulename
+        FROM
+            pg_rewrite r
+        WHERE
+            ((r.ev_class = c.oid)
+                AND (bpchar(r.ev_type) = '1'::bpchar)) )))
+            AND (c.relkind = 'v'::char)
+          )
+{% if (vid and datlastsysoid) %}
+    AND c.oid = {{vid}}::oid
+{% elif scid %}
+    AND c.relnamespace = {{scid}}::oid
+ORDER BY
+    c.relname
+{% endif %}
+
+{% elif type == 'roles' %}
+SELECT
+    pr.rolname
+FROM
+    pg_roles pr
+WHERE
+    pr.rolcanlogin
+ORDER BY
+    pr.rolname
+
+{% elif type == 'schemas' %}
+SELECT
+    nsp.nspname
+FROM
+    pg_namespace nsp
+WHERE
+    (nsp.nspname NOT LIKE E'pg\\_%'
+        AND nsp.nspname != 'information_schema')
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/update.sql
new file mode 100644
index 0000000..56183fd
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/update.sql
@@ -0,0 +1,82 @@
+{# ============================ Update View ========================= #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{% if data %}
+{% set view_name = data.name if data.name else o_data.name %}
+{% set view_schema = data.schema if data.schema else o_data.schema %}
+{% set def = data.definition.rstrip(';') if data.definition %}
+{% if data.name and data.name != o_data.name %}
+ALTER VIEW {{ conn|qtIdent(o_data.schema, o_data.name) }}
+    RENAME TO {{ conn|qtIdent(data.name) }};
+{% endif %}
+{% if data.schema and data.schema != o_data.schema %}
+ALTER VIEW {{ conn|qtIdent(o_data.schema, view_name ) }}
+    SET SCHEMA {{ conn|qtIdent(data.schema) }};
+{% endif %}
+{% if data.owner and data.owner != o_data.owner %}
+ALTER TABLE {{ conn|qtIdent(view_schema, view_name) }}
+    OWNER TO {{ conn|qtIdent(data.owner) }};
+{% endif %}
+{% if def and def != o_data.definition.rstrip(';') %}
+CREATE OR REPLACE VIEW {{ conn|qtIdent(view_schema, view_name) }}
+{% if (data.check_option and data.check_option != o_data.check_option)
+    or (data.security_barrier and data.security_barrier != o_data.security_barrier) %}
+    WITH ({% if (data.check_option and data.check_option != 'no') %}check_option={{ data.check_option }}{% endif %}{{', ' if data.check_option and data.check_option != 'no' and data.security_barrier }}{% if data.security_barrier %}security_barrier={{ data.security_barrier|lower }}{% endif %})
+{% endif %}
+    AS{{ def }};
+{% else %}
+{% if (data.security_barrier is defined and data.security_barrier|lower !=  o_data.security_barrier|lower) %}
+ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    SET (security_barrier={{ data.security_barrier|lower }});
+{% endif %}
+{% if (data.check_option and data.check_option != o_data.check_option and data.check_option != 'no') %}
+ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    SET (check_option={{ data.check_option }});
+{% elif (data.check_option and data.check_option != o_data.check_option and data.check_option == 'no') %}
+ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }} RESET (check_option);
+{% endif %}
+{% endif %}
+
+{% if data.comment and data.comment != o_data.comment %}
+COMMENT ON VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{# The SQL generated below will change privileges #}
+{% if data.datacl %}
+{% if 'deleted' in data.datacl %}
+{% for priv in data.datacl.deleted %}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in data.datacl %}
+{% for priv in data.datacl.changed %}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in data.datacl %}
+{% for priv in data.datacl.added %}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{# The SQL generated below will change Security Label #}
+{% if data.seclabels is not none and data.seclabels|length > 0 %}
+{% set seclabels = data.seclabels %}
+{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+{% for r in seclabels.deleted %}
+{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/view_id.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/view_id.sql
new file mode 100644
index 0000000..ef27594
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/pg/9.4_plus/sql/view_id.sql
@@ -0,0 +1,4 @@
+{# ===== Below will provide view id for last created view ===== #}
+{% if data %}
+SELECT c.oid FROM pg_class c WHERE c.relname = '{{ data.name }}';
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/acl.sql
new file mode 100644
index 0000000..7d791f5
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/acl.sql
@@ -0,0 +1,39 @@
+{# ============================ Get ACLs ========================= #}
+{% if vid %}
+SELECT
+    'datacl' as deftype,
+    COALESCE(gt.rolname, 'public') grantee,
+    g.rolname 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 'DELETE' THEN 'd'
+        WHEN 'INSERT' THEN 'a'
+        WHEN 'REFERENCES' THEN 'x'
+        WHEN 'SELECT' THEN 'r'
+        WHEN 'TRIGGER' THEN 't'
+        WHEN 'UPDATE' THEN 'w'
+        WHEN 'TRUNCATE' THEN 'D'
+        ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            relacl
+         FROM
+            pg_class cl
+         LEFT OUTER JOIN pg_shdescription descr ON
+            (cl.oid=descr.objoid AND descr.classoid='pg_class'::regclass)
+         WHERE
+            cl.oid = {{ vid }}::OID AND relkind = 'v'
+        ) acl,
+        aclexplode(relacl) 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
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/create.sql
new file mode 100644
index 0000000..5720b14
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/create.sql
@@ -0,0 +1,20 @@
+{#============================Create new view=========================#}
+{% if display_comments %}
+-- View: {{ conn|qtIdent(data.schema, data.name) }}
+
+-- DROP VIEW {{ conn|qtIdent(data.schema, data.name) }};
+
+{% endif %}
+{% if data.name and data.schema and data.definition %}
+CREATE OR REPLACE VIEW {{ conn|qtIdent(data.schema, data.name) }} AS
+{{ data.definition.rstrip(';') }};
+{% if data.owner %}
+
+ALTER TABLE {{ conn|qtIdent(data.schema, data.name) }}
+    OWNER TO {{ conn|qtIdent(data.owner) }};
+{% endif %}
+{% if data.comment %}
+COMMENT ON VIEW {{ conn|qtIdent(data.schema, data.name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/delete.sql
new file mode 100644
index 0000000..e50beec
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/delete.sql
@@ -0,0 +1,13 @@
+{# ====================== Drop/Cascade view by name ===================== #}
+{% if vid %}
+SELECT
+    c.relname AS name,
+    nsp.nspname
+FROM
+    pg_class c
+LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
+WHERE
+    c.relfilenode = {{ vid }};
+{% elif (name and nspname) %}
+DROP VIEW {{nspname}}.{{ conn|qtIdent(name) }} {% if cascade %} CASCADE {% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/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/views/templates/view/ppas/9.1_plus/sql/grant.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/grant.sql
new file mode 100644
index 0000000..59a310f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/grant.sql
@@ -0,0 +1,6 @@
+{# ===== Grant Permissions to User Role on Views/Tables ===== #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{# ===== We will generate Security Label SQL using macro ===== #}
+{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{% endfor %}{% endif %}{% if data.datacl %}
+{% for priv in data.datacl %}{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}{% endfor %}{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/properties.sql
new file mode 100644
index 0000000..4adbebb
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/properties.sql
@@ -0,0 +1,76 @@
+{% if (vid and datlastsysoid) or scid %}
+SELECT
+    c.oid,
+    c.xmin,
+    c.relkind,
+    description,
+    (CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
+    c.relname AS name,
+    c.reltablespace AS spcoid,
+    nsp.nspname AS schema,
+    c.relispopulated AS ispopulated,
+    pg_get_userbyid(c.relowner) AS owner,
+    array_to_string(c.relacl::text[], ', ') AS acl,
+    pg_get_viewdef(c.oid, true) AS definition,
+    {# ===== Checks if it is system view ===== #}
+    {% if vid and datlastsysoid %}
+    CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
+    {% endif %}
+(SELECT
+    array_agg(label)
+FROM
+    pg_seclabels sl1
+WHERE
+    sl1.objoid=c.oid AND sl1.objsubid=0) AS labels,
+(SELECT
+    array_agg(provider)
+FROM
+    pg_seclabels sl2
+WHERE
+    sl2.objoid=c.oid AND sl2.objsubid=0) AS providers,
+    substring(array_to_string(c.reloptions, ',')
+        FROM 'check_option=([a-z]*)') AS check_option,
+    (substring(array_to_string(c.reloptions, ',')
+        FROM 'security_barrier=([a-z|0-9]*)'))::boolean AS security_barrier
+FROM pg_class c
+LEFT OUTER JOIN pg_namespace nsp on nsp.oid = c.relnamespace
+LEFT OUTER JOIN pg_tablespace spc on spc.oid=c.reltablespace
+LEFT OUTER JOIN pg_description des ON (des.objoid=c.oid and des.objsubid=0 AND des.classoid='pg_class'::regclass)
+LEFT OUTER JOIN pg_class tst ON tst.oid = c.reltoastrelid
+    WHERE ((c.relhasrules AND (EXISTS (
+        SELECT
+            r.rulename
+        FROM
+            pg_rewrite r
+        WHERE
+            ((r.ev_class = c.oid)
+                AND (bpchar(r.ev_type) = '1'::bpchar)) )))
+            AND (c.relkind = 'v'::char)
+          )
+{% if (vid and datlastsysoid) %}
+    AND c.oid = {{vid}}::oid
+{% elif scid %}
+    AND c.relnamespace = {{scid}}::oid
+ORDER BY
+    c.relname
+{% endif %}
+
+{% elif type == 'roles' %}
+SELECT
+    pr.rolname
+FROM
+    pg_roles pr
+WHERE
+    pr.rolcanlogin
+ORDER BY
+    pr.rolname
+
+{% elif type == 'schemas' %}
+SELECT
+    nsp.nspname
+FROM
+    pg_namespace nsp
+WHERE
+    (nsp.nspname NOT LIKE E'pg\\_%'
+        AND nsp.nspname != 'information_schema')
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/update.sql
new file mode 100644
index 0000000..56183fd
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/update.sql
@@ -0,0 +1,82 @@
+{# ============================ Update View ========================= #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{% if data %}
+{% set view_name = data.name if data.name else o_data.name %}
+{% set view_schema = data.schema if data.schema else o_data.schema %}
+{% set def = data.definition.rstrip(';') if data.definition %}
+{% if data.name and data.name != o_data.name %}
+ALTER VIEW {{ conn|qtIdent(o_data.schema, o_data.name) }}
+    RENAME TO {{ conn|qtIdent(data.name) }};
+{% endif %}
+{% if data.schema and data.schema != o_data.schema %}
+ALTER VIEW {{ conn|qtIdent(o_data.schema, view_name ) }}
+    SET SCHEMA {{ conn|qtIdent(data.schema) }};
+{% endif %}
+{% if data.owner and data.owner != o_data.owner %}
+ALTER TABLE {{ conn|qtIdent(view_schema, view_name) }}
+    OWNER TO {{ conn|qtIdent(data.owner) }};
+{% endif %}
+{% if def and def != o_data.definition.rstrip(';') %}
+CREATE OR REPLACE VIEW {{ conn|qtIdent(view_schema, view_name) }}
+{% if (data.check_option and data.check_option != o_data.check_option)
+    or (data.security_barrier and data.security_barrier != o_data.security_barrier) %}
+    WITH ({% if (data.check_option and data.check_option != 'no') %}check_option={{ data.check_option }}{% endif %}{{', ' if data.check_option and data.check_option != 'no' and data.security_barrier }}{% if data.security_barrier %}security_barrier={{ data.security_barrier|lower }}{% endif %})
+{% endif %}
+    AS{{ def }};
+{% else %}
+{% if (data.security_barrier is defined and data.security_barrier|lower !=  o_data.security_barrier|lower) %}
+ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    SET (security_barrier={{ data.security_barrier|lower }});
+{% endif %}
+{% if (data.check_option and data.check_option != o_data.check_option and data.check_option != 'no') %}
+ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    SET (check_option={{ data.check_option }});
+{% elif (data.check_option and data.check_option != o_data.check_option and data.check_option == 'no') %}
+ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }} RESET (check_option);
+{% endif %}
+{% endif %}
+
+{% if data.comment and data.comment != o_data.comment %}
+COMMENT ON VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{# The SQL generated below will change privileges #}
+{% if data.datacl %}
+{% if 'deleted' in data.datacl %}
+{% for priv in data.datacl.deleted %}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in data.datacl %}
+{% for priv in data.datacl.changed %}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in data.datacl %}
+{% for priv in data.datacl.added %}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{# The SQL generated below will change Security Label #}
+{% if data.seclabels is not none and data.seclabels|length > 0 %}
+{% set seclabels = data.seclabels %}
+{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+{% for r in seclabels.deleted %}
+{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/view_id.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/view_id.sql
new file mode 100644
index 0000000..ef27594
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.1_plus/sql/view_id.sql
@@ -0,0 +1,4 @@
+{# ===== Below will provide view id for last created view ===== #}
+{% if data %}
+SELECT c.oid FROM pg_class c WHERE c.relname = '{{ data.name }}';
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/acl.sql
new file mode 100644
index 0000000..5f2d0fb
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/acl.sql
@@ -0,0 +1,52 @@
+{# ============================ Get ACLs ========================= #}
+{% if vid %}
+SELECT
+    'datacl' as deftype,
+    COALESCE(gt.rolname, 'public') grantee,
+    g.rolname 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 'DELETE' THEN 'd'
+        WHEN 'INSERT' THEN 'a'
+        WHEN 'REFERENCES' THEN 'x'
+        WHEN 'SELECT' THEN 'r'
+        WHEN 'TRIGGER' THEN 't'
+        WHEN 'UPDATE' THEN 'w'
+        WHEN 'TRUNCATE' THEN 'D'
+        ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            relacl
+        FROM
+            pg_class cl
+        LEFT OUTER JOIN pg_shdescription descr ON (
+            cl.oid=descr.objoid AND descr.classoid='pg_class'::regclass)
+        WHERE
+            cl.oid = {{ vid }}::OID AND relkind = 'v'
+        ) acl,
+        (SELECT
+            (d).grantee AS grantee,
+            (d).grantor AS grantor,
+            (d).is_grantable AS is_grantable,
+            (d).privilege_type AS privilege_type
+        FROM
+            (SELECT
+                aclexplode(relacl) AS d
+             FROM
+                pg_class cl1
+             WHERE
+                cl1.oid = {{ vid }}
+            ) 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
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/create.sql
new file mode 100644
index 0000000..dc4a3ab
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/create.sql
@@ -0,0 +1,23 @@
+{#============================Create new view=========================#}
+{% if display_comments %}
+-- View: {{ conn|qtIdent(data.schema, data.name) }}
+
+-- DROP VIEW {{ conn|qtIdent(data.schema, data.name) }};
+
+{% endif %}
+{% if data.name and data.schema and data.definition %}
+CREATE OR REPLACE VIEW {{ conn|qtIdent(data.schema, data.name) }}{% if (data.security_barrier) %}{{'\r'}}
+WITH (
+{% if data.security_barrier %}    security_barrier={{ data.security_barrier|lower }}{% endif %}{{'\r'}}
+){% endif %} AS
+{{ data.definition.rstrip(';') }};
+{% if data.owner %}
+
+ALTER TABLE {{ conn|qtIdent(data.schema, data.name) }}
+  OWNER TO {{ data.owner }};
+{% endif %}
+{% if data.comment %}
+COMMENT ON VIEW {{ conn|qtIdent(data.schema, data.name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/delete.sql
new file mode 100644
index 0000000..e50beec
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/delete.sql
@@ -0,0 +1,13 @@
+{# ====================== Drop/Cascade view by name ===================== #}
+{% if vid %}
+SELECT
+    c.relname AS name,
+    nsp.nspname
+FROM
+    pg_class c
+LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
+WHERE
+    c.relfilenode = {{ vid }};
+{% elif (name and nspname) %}
+DROP VIEW {{nspname}}.{{ conn|qtIdent(name) }} {% if cascade %} CASCADE {% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/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/views/templates/view/ppas/9.2_plus/sql/grant.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/grant.sql
new file mode 100644
index 0000000..59a310f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/grant.sql
@@ -0,0 +1,6 @@
+{# ===== Grant Permissions to User Role on Views/Tables ===== #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{# ===== We will generate Security Label SQL using macro ===== #}
+{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{% endfor %}{% endif %}{% if data.datacl %}
+{% for priv in data.datacl %}{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}{% endfor %}{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/properties.sql
new file mode 100644
index 0000000..20eb3df
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/properties.sql
@@ -0,0 +1,70 @@
+{% if (vid and datlastsysoid) or scid %}
+SELECT
+    c.oid,
+    c.xmin,
+    c.relname AS name,
+    c.reltablespace AS spcoid,
+    (CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
+    pg_get_userbyid(c.relowner) AS owner,
+    description As comment,
+    pg_get_viewdef(c.oid, true) AS definition,
+    nsp.nspname AS schema,
+    array_to_string(c.relacl::text[], ', ') AS acl,
+    {#=============Checks if it is system view================#}
+    {% if vid and datlastsysoid %}
+    CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
+    {% endif %}
+(SELECT
+    array_agg(label)
+FROM
+    pg_seclabels sl1
+WHERE
+    sl1.objoid=c.oid AND sl1.objsubid=0) AS labels,
+(SELECT
+    array_agg(provider)
+FROM
+    pg_seclabels sl2
+WHERE
+    sl2.objoid=c.oid AND sl2.objsubid=0) AS providers,
+    (substring(array_to_string(c.reloptions, ',')
+        FROM 'security_barrier=([a-z|0-9]*)'))::boolean AS security_barrier
+FROM pg_class c
+LEFT OUTER JOIN pg_namespace nsp on nsp.oid = c.relnamespace
+LEFT OUTER JOIN pg_tablespace spc on spc.oid=c.reltablespace
+LEFT OUTER JOIN pg_description des ON (des.objoid=c.oid and des.objsubid=0 AND des.classoid='pg_class'::regclass)
+    WHERE ((c.relhasrules AND (EXISTS (
+            SELECT
+                r.rulename
+            FROM
+                pg_rewrite r
+            WHERE
+                ((r.ev_class = c.oid)
+                    AND (bpchar(r.ev_type) = '1'::bpchar)
+                ) ))
+           ) AND (c.relkind = 'v'::char)
+          )
+{% if (vid and datlastsysoid) %}
+    AND c.oid = {{vid}}::oid
+{% elif scid %}
+    AND c.relnamespace = {{scid}}::oid ORDER BY c.relname
+{% endif %}
+
+{% elif type == 'roles' %}
+SELECT
+    pr.rolname
+FROM
+    pg_roles pr
+WHERE
+    pr.rolcanlogin
+ORDER BY
+    pr.rolname
+
+{% elif type == 'schemas' %}
+SELECT
+    nsp.nspname
+FROM
+    pg_namespace nsp
+WHERE
+    (nsp.nspname NOT LIKE E'pg\\_%'
+        AND nsp.nspname != 'information_schema')
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/update.sql
new file mode 100644
index 0000000..c37d4ba
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/update.sql
@@ -0,0 +1,74 @@
+{# ============================ Update View ========================= #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{% if data %}
+{% set view_name = data.name if data.name else o_data.name %}
+{% set view_schema = data.schema if data.schema else o_data.schema %}
+{% set def = data.definition.rstrip(';') if data.definition %}
+{% if data.name and data.name != o_data.name %}
+ALTER VIEW {{ conn|qtIdent(o_data.schema, o_data.name) }}
+    RENAME TO {{ conn|qtIdent(data.name) }};
+{% endif %}
+{% if data.schema and data.schema != o_data.schema %}
+ALTER VIEW {{ conn|qtIdent(o_data.schema, view_name ) }}
+    SET SCHEMA {{ conn|qtIdent(data.schema) }};
+{% endif %}
+{% if data.owner and data.owner != o_data.owner %}
+ALTER TABLE {{ conn|qtIdent(view_schema, view_name) }}
+    OWNER TO {{ conn|qtIdent(data.owner) }};
+{% endif %}
+{% if def and def != o_data.definition.rstrip(';') %}
+CREATE OR REPLACE VIEW {{ conn|qtIdent(view_schema, view_name) }}
+{% if (data.security_barrier and data.security_barrier != o_data.security_barrier) %}
+    WITH ({% if data.security_barrier %}security_barrier={{ data.security_barrier|lower }}{% endif %}) {% endif %}
+    AS{{ def }};
+{% else %}
+{% if (data.security_barrier is defined and data.security_barrier|lower !=  o_data.security_barrier|lower) %}
+ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    SET (security_barrier={{ data.security_barrier|lower }});
+{% endif %}
+{% endif %}
+
+{% if data.comment and data.comment != o_data.comment %}
+COMMENT ON VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{# The SQL generated below will change privileges #}
+{% if data.datacl %}
+{% if 'deleted' in data.datacl %}
+{% for priv in data.datacl.deleted %}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in data.datacl %}
+{% for priv in data.datacl.changed %}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in data.datacl %}
+{% for priv in data.datacl.added %}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{# The SQL generated below will change Security Label #}
+{% if data.seclabels is not none and data.seclabels|length > 0 %}
+{% set seclabels = data.seclabels %}
+{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+{% for r in seclabels.deleted %}
+{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/view_id.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/view_id.sql
new file mode 100644
index 0000000..6dff04e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.2_plus/sql/view_id.sql
@@ -0,0 +1,4 @@
+{# Below will provide view id for newly created view #}
+{% if data %}
+SELECT c.oid FROM pg_class c WHERE c.relname = '{{ data.name }}';
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/acl.sql
new file mode 100644
index 0000000..84300cf
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/acl.sql
@@ -0,0 +1,38 @@
+{# ============================ Get ACLs ========================= #}
+{% if vid %}
+SELECT
+    'datacl' as deftype,
+    COALESCE(gt.rolname, 'public') grantee,
+    g.rolname 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 'DELETE' THEN 'd'
+        WHEN 'INSERT' THEN 'a'
+        WHEN 'REFERENCES' THEN 'x'
+        WHEN 'SELECT' THEN 'r'
+        WHEN 'TRIGGER' THEN 't'
+        WHEN 'UPDATE' THEN 'w'
+        WHEN 'TRUNCATE' THEN 'D'
+        ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            relacl
+        FROM
+            pg_class cl
+        LEFT OUTER JOIN pg_shdescription descr ON (
+            cl.oid=descr.objoid AND descr.classoid='pg_class'::regclass)
+        WHERE cl.oid = {{ vid }}::OID AND relkind = 'v'
+        ) acl,
+        aclexplode(relacl) 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
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/create.sql
new file mode 100644
index 0000000..dc4a3ab
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/create.sql
@@ -0,0 +1,23 @@
+{#============================Create new view=========================#}
+{% if display_comments %}
+-- View: {{ conn|qtIdent(data.schema, data.name) }}
+
+-- DROP VIEW {{ conn|qtIdent(data.schema, data.name) }};
+
+{% endif %}
+{% if data.name and data.schema and data.definition %}
+CREATE OR REPLACE VIEW {{ conn|qtIdent(data.schema, data.name) }}{% if (data.security_barrier) %}{{'\r'}}
+WITH (
+{% if data.security_barrier %}    security_barrier={{ data.security_barrier|lower }}{% endif %}{{'\r'}}
+){% endif %} AS
+{{ data.definition.rstrip(';') }};
+{% if data.owner %}
+
+ALTER TABLE {{ conn|qtIdent(data.schema, data.name) }}
+  OWNER TO {{ data.owner }};
+{% endif %}
+{% if data.comment %}
+COMMENT ON VIEW {{ conn|qtIdent(data.schema, data.name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/delete.sql
new file mode 100644
index 0000000..e50beec
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/delete.sql
@@ -0,0 +1,13 @@
+{# ====================== Drop/Cascade view by name ===================== #}
+{% if vid %}
+SELECT
+    c.relname AS name,
+    nsp.nspname
+FROM
+    pg_class c
+LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
+WHERE
+    c.relfilenode = {{ vid }};
+{% elif (name and nspname) %}
+DROP VIEW {{nspname}}.{{ conn|qtIdent(name) }} {% if cascade %} CASCADE {% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/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/views/templates/view/ppas/9.3_plus/sql/grant.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/grant.sql
new file mode 100644
index 0000000..59a310f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/grant.sql
@@ -0,0 +1,6 @@
+{# ===== Grant Permissions to User Role on Views/Tables ===== #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{# ===== We will generate Security Label SQL using macro ===== #}
+{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{% endfor %}{% endif %}{% if data.datacl %}
+{% for priv in data.datacl %}{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}{% endfor %}{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/properties.sql
new file mode 100644
index 0000000..7f03304
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/properties.sql
@@ -0,0 +1,74 @@
+{% if (vid and datlastsysoid) or scid %}
+SELECT
+    c.oid,
+    c.xmin,
+    c.relkind,
+    description,
+    (CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
+    c.relname AS name,
+    nsp.nspname AS schema,
+    c.reltablespace AS spcoid,
+    c.relispopulated AS ispopulated,
+    pg_get_userbyid(c.relowner) AS owner,
+    array_to_string(c.relacl::text[], ', ') AS acl,
+    pg_get_viewdef(c.oid, true) AS definition,
+    {# ===== Checks if it is system view ===== #}
+    {% if vid and datlastsysoid %}
+    CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
+    {% endif %}
+(SELECT
+    array_agg(label)
+FROM
+    pg_seclabels sl1
+WHERE
+    sl1.objoid=c.oid AND sl1.objsubid=0) AS labels,
+(SELECT
+    array_agg(provider)
+FROM
+    pg_seclabels sl2
+WHERE
+    sl2.objoid=c.oid AND sl2.objsubid=0) AS providers,
+    (substring(array_to_string(c.reloptions, ',')
+        FROM 'security_barrier=([a-z|0-9]*)'))::boolean AS security_barrier
+FROM pg_class c
+LEFT OUTER JOIN pg_namespace nsp on nsp.oid = c.relnamespace
+LEFT OUTER JOIN pg_tablespace spc on spc.oid=c.reltablespace
+LEFT OUTER JOIN pg_description des ON (des.objoid=c.oid and des.objsubid=0 AND des.classoid='pg_class'::regclass)
+LEFT OUTER JOIN pg_class tst ON tst.oid = c.reltoastrelid
+    WHERE ((c.relhasrules AND (EXISTS (
+        SELECT
+            r.rulename
+        FROM
+            pg_rewrite r
+        WHERE
+            ((r.ev_class = c.oid)
+                AND (bpchar(r.ev_type) = '1'::bpchar)) )))
+            AND (c.relkind = 'v'::char)
+          )
+{% if (vid and datlastsysoid) %}
+    AND c.oid = {{vid}}::oid
+{% elif scid %}
+    AND c.relnamespace = {{scid}}::oid
+ORDER BY
+    c.relname
+{% endif %}
+
+{% elif type == 'roles' %}
+SELECT
+    pr.rolname
+FROM
+    pg_roles pr
+WHERE
+    pr.rolcanlogin
+ORDER BY
+    pr.rolname
+
+{% elif type == 'schemas' %}
+SELECT
+    nsp.nspname
+FROM
+    pg_namespace nsp
+WHERE
+    (nsp.nspname NOT LIKE E'pg\\_%'
+        AND nsp.nspname != 'information_schema')
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/update.sql
new file mode 100644
index 0000000..02d8f37
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/update.sql
@@ -0,0 +1,75 @@
+{# ============================ Update View ========================= #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{% if data %}
+{% set view_name = data.name if data.name else o_data.name %}
+{% set view_schema = data.schema if data.schema else o_data.schema %}
+{% set def = data.definition.rstrip(';') if data.definition %}
+{% if data.name and data.name != o_data.name %}
+ALTER VIEW {{ conn|qtIdent(o_data.schema, o_data.name) }}
+    RENAME TO {{ conn|qtIdent(data.name) }};
+{% endif %}
+{% if data.schema and data.schema != o_data.schema %}
+ALTER VIEW {{ conn|qtIdent(o_data.schema, view_name ) }}
+    SET SCHEMA {{ conn|qtIdent(data.schema) }};
+{% endif %}
+{% if data.owner and data.owner != o_data.owner %}
+ALTER TABLE {{ conn|qtIdent(view_schema, view_name) }}
+    OWNER TO {{ conn|qtIdent(data.owner) }};
+{% endif %}
+{% if def and def != o_data.definition.rstrip(';') %}
+CREATE OR REPLACE VIEW {{ conn|qtIdent(view_schema, view_name) }}
+{% if (data.security_barrier and data.security_barrier != o_data.security_barrier) %}
+    WITH ({% if data.security_barrier %}security_barrier={{ data.security_barrier|lower }}{% endif %})
+{% endif %}
+    AS{{ def }};
+{% else %}
+{% if (data.security_barrier is defined and data.security_barrier|lower !=  o_data.security_barrier|lower) %}
+ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    SET (security_barrier={{ data.security_barrier|lower }});
+{% endif %}
+{% endif %}
+
+{% if data.comment and data.comment != o_data.comment %}
+COMMENT ON VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{# The SQL generated below will change privileges #}
+{% if data.datacl %}
+{% if 'deleted' in data.datacl %}
+{% for priv in data.datacl.deleted %}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in data.datacl %}
+{% for priv in data.datacl.changed %}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in data.datacl %}
+{% for priv in data.datacl.added %}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{# The SQL generated below will change Security Label #}
+{% if data.seclabels is not none and data.seclabels|length > 0 %}
+{% set seclabels = data.seclabels %}
+{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+{% for r in seclabels.deleted %}
+{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/view_id.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/view_id.sql
new file mode 100644
index 0000000..6dff04e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.3_plus/sql/view_id.sql
@@ -0,0 +1,4 @@
+{# Below will provide view id for newly created view #}
+{% if data %}
+SELECT c.oid FROM pg_class c WHERE c.relname = '{{ data.name }}';
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/acl.sql
new file mode 100644
index 0000000..7d791f5
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/acl.sql
@@ -0,0 +1,39 @@
+{# ============================ Get ACLs ========================= #}
+{% if vid %}
+SELECT
+    'datacl' as deftype,
+    COALESCE(gt.rolname, 'public') grantee,
+    g.rolname 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 'DELETE' THEN 'd'
+        WHEN 'INSERT' THEN 'a'
+        WHEN 'REFERENCES' THEN 'x'
+        WHEN 'SELECT' THEN 'r'
+        WHEN 'TRIGGER' THEN 't'
+        WHEN 'UPDATE' THEN 'w'
+        WHEN 'TRUNCATE' THEN 'D'
+        ELSE 'UNKNOWN'
+        END AS privilege_type
+    FROM
+        (SELECT
+            relacl
+         FROM
+            pg_class cl
+         LEFT OUTER JOIN pg_shdescription descr ON
+            (cl.oid=descr.objoid AND descr.classoid='pg_class'::regclass)
+         WHERE
+            cl.oid = {{ vid }}::OID AND relkind = 'v'
+        ) acl,
+        aclexplode(relacl) 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
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/create.sql
new file mode 100644
index 0000000..b43b519
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/create.sql
@@ -0,0 +1,22 @@
+{#============================Create new view=========================#}
+{% if display_comments %}
+-- View: {{ conn|qtIdent(data.schema, data.name) }}
+
+-- DROP VIEW {{ conn|qtIdent(data.schema, data.name) }};
+
+{% endif %}
+{% if data.name and data.schema and data.definition %}
+CREATE OR REPLACE VIEW {{ conn|qtIdent(data.schema, data.name) }}{% if ((data.check_option and data.check_option.lower() != 'no') or data.security_barrier) %}{{ '\n' }}WITH (
+{% if data.check_option and data.check_option.lower() != 'no' %}    check_option={{ data.check_option }}{% endif %}{{ ',\r' if data.check_option and data.check_option.lower() != 'no' and data.security_barrier }}{% if data.security_barrier %}    security_barrier={{ data.security_barrier|lower }}{% endif %}{{'\r'}}
+){% endif %} AS
+{{ data.definition.rstrip(';') }};
+{% if data.owner and data.m_view is undefined %}
+
+ALTER TABLE {{ conn|qtIdent(data.schema, data.name) }}
+    OWNER TO {{ conn|qtIdent(data.owner) }};
+{% endif %}
+{% if data.comment %}
+COMMENT ON VIEW {{ conn|qtIdent(data.schema, data.name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/delete.sql
new file mode 100644
index 0000000..e50beec
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/delete.sql
@@ -0,0 +1,13 @@
+{# ====================== Drop/Cascade view by name ===================== #}
+{% if vid %}
+SELECT
+    c.relname AS name,
+    nsp.nspname
+FROM
+    pg_class c
+LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
+WHERE
+    c.relfilenode = {{ vid }};
+{% elif (name and nspname) %}
+DROP VIEW {{nspname}}.{{ conn|qtIdent(name) }} {% if cascade %} CASCADE {% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/get_schema.sql
new file mode 100644
index 0000000..127d4b9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/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/views/templates/view/ppas/9.4_plus/sql/grant.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/grant.sql
new file mode 100644
index 0000000..59a310f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/grant.sql
@@ -0,0 +1,6 @@
+{# ===== Grant Permissions to User Role on Views/Tables ===== #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{# ===== We will generate Security Label SQL using macro ===== #}
+{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{% endfor %}{% endif %}{% if data.datacl %}
+{% for priv in data.datacl %}{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}{% endfor %}{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/properties.sql
new file mode 100644
index 0000000..ccd957f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/properties.sql
@@ -0,0 +1,77 @@
+{# ========================== Fetch View Properties ========================= #}
+{% if (vid and datlastsysoid) or scid %}
+SELECT
+    c.oid,
+    c.xmin,
+    c.relkind,
+    description,
+    (CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
+    c.relname AS name,
+    c.reltablespace AS spcoid,
+    nsp.nspname AS schema,
+    c.relispopulated AS ispopulated,
+    pg_get_userbyid(c.relowner) AS owner,
+    array_to_string(c.relacl::text[], ', ') AS acl,
+    pg_get_viewdef(c.oid, true) AS definition,
+    {# ===== Checks if it is system view ===== #}
+    {% if vid and datlastsysoid %}
+    CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
+    {% endif %}
+(SELECT
+    array_agg(label)
+FROM
+    pg_seclabels sl1
+WHERE
+    sl1.objoid=c.oid AND sl1.objsubid=0) AS labels,
+(SELECT
+    array_agg(provider)
+FROM
+    pg_seclabels sl2
+WHERE
+    sl2.objoid=c.oid AND sl2.objsubid=0) AS providers,
+    substring(array_to_string(c.reloptions, ',')
+        FROM 'check_option=([a-z]*)') AS check_option,
+    (substring(array_to_string(c.reloptions, ',')
+        FROM 'security_barrier=([a-z|0-9]*)'))::boolean AS security_barrier
+FROM pg_class c
+LEFT OUTER JOIN pg_namespace nsp on nsp.oid = c.relnamespace
+LEFT OUTER JOIN pg_tablespace spc on spc.oid=c.reltablespace
+LEFT OUTER JOIN pg_description des ON (des.objoid=c.oid and des.objsubid=0 AND des.classoid='pg_class'::regclass)
+LEFT OUTER JOIN pg_class tst ON tst.oid = c.reltoastrelid
+    WHERE ((c.relhasrules AND (EXISTS (
+        SELECT
+            r.rulename
+        FROM
+            pg_rewrite r
+        WHERE
+            ((r.ev_class = c.oid)
+                AND (bpchar(r.ev_type) = '1'::bpchar)) )))
+            AND (c.relkind = 'v'::char)
+          )
+{% if (vid and datlastsysoid) %}
+    AND c.oid = {{vid}}::oid
+{% elif scid %}
+    AND c.relnamespace = {{scid}}::oid
+ORDER BY
+    c.relname
+{% endif %}
+
+{% elif type == 'roles' %}
+SELECT
+    pr.rolname
+FROM
+    pg_roles pr
+WHERE
+    pr.rolcanlogin
+ORDER BY
+    pr.rolname
+
+{% elif type == 'schemas' %}
+SELECT
+    nsp.nspname
+FROM
+    pg_namespace nsp
+WHERE
+    (nsp.nspname NOT LIKE E'pg\\_%'
+        AND nsp.nspname != 'information_schema')
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/update.sql
new file mode 100644
index 0000000..56183fd
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/update.sql
@@ -0,0 +1,82 @@
+{# ============================ Update View ========================= #}
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
+{% if data %}
+{% set view_name = data.name if data.name else o_data.name %}
+{% set view_schema = data.schema if data.schema else o_data.schema %}
+{% set def = data.definition.rstrip(';') if data.definition %}
+{% if data.name and data.name != o_data.name %}
+ALTER VIEW {{ conn|qtIdent(o_data.schema, o_data.name) }}
+    RENAME TO {{ conn|qtIdent(data.name) }};
+{% endif %}
+{% if data.schema and data.schema != o_data.schema %}
+ALTER VIEW {{ conn|qtIdent(o_data.schema, view_name ) }}
+    SET SCHEMA {{ conn|qtIdent(data.schema) }};
+{% endif %}
+{% if data.owner and data.owner != o_data.owner %}
+ALTER TABLE {{ conn|qtIdent(view_schema, view_name) }}
+    OWNER TO {{ conn|qtIdent(data.owner) }};
+{% endif %}
+{% if def and def != o_data.definition.rstrip(';') %}
+CREATE OR REPLACE VIEW {{ conn|qtIdent(view_schema, view_name) }}
+{% if (data.check_option and data.check_option != o_data.check_option)
+    or (data.security_barrier and data.security_barrier != o_data.security_barrier) %}
+    WITH ({% if (data.check_option and data.check_option != 'no') %}check_option={{ data.check_option }}{% endif %}{{', ' if data.check_option and data.check_option != 'no' and data.security_barrier }}{% if data.security_barrier %}security_barrier={{ data.security_barrier|lower }}{% endif %})
+{% endif %}
+    AS{{ def }};
+{% else %}
+{% if (data.security_barrier is defined and data.security_barrier|lower !=  o_data.security_barrier|lower) %}
+ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    SET (security_barrier={{ data.security_barrier|lower }});
+{% endif %}
+{% if (data.check_option and data.check_option != o_data.check_option and data.check_option != 'no') %}
+ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    SET (check_option={{ data.check_option }});
+{% elif (data.check_option and data.check_option != o_data.check_option and data.check_option == 'no') %}
+ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }} RESET (check_option);
+{% endif %}
+{% endif %}
+
+{% if data.comment and data.comment != o_data.comment %}
+COMMENT ON VIEW {{ conn|qtIdent(view_schema, view_name) }}
+    IS {{ data.comment|qtLiteral }};
+{% endif %}
+{# The SQL generated below will change privileges #}
+{% if data.datacl %}
+{% if 'deleted' in data.datacl %}
+{% for priv in data.datacl.deleted %}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in data.datacl %}
+{% for priv in data.datacl.changed %}
+{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in data.datacl %}
+{% for priv in data.datacl.added %}
+{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{# The SQL generated below will change Security Label #}
+{% if data.seclabels is not none and data.seclabels|length > 0 %}
+{% set seclabels = data.seclabels %}
+{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+{% for r in seclabels.deleted %}
+{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/view_id.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/view_id.sql
new file mode 100644
index 0000000..ef27594
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/ppas/9.4_plus/sql/view_id.sql
@@ -0,0 +1,4 @@
+{# ===== Below will provide view id for last created view ===== #}
+{% if data %}
+SELECT c.oid FROM pg_class c WHERE c.relname = '{{ data.name }}';
+{% endif %}
diff --git a/web/pgadmin/static/js/backform.pgadmin.js b/web/pgadmin/static/js/backform.pgadmin.js
index 4a81411..e005570 100644
--- a/web/pgadmin/static/js/backform.pgadmin.js
+++ b/web/pgadmin/static/js/backform.pgadmin.js
@@ -1665,13 +1665,18 @@
               (_.isUndefined(s.min_version) ? true :
                (server_info.version >= s.min_version)) &&
               (_.isUndefined(s.max_version) ? true :
-               (server_info.version <= s.max_version))));
+               (server_info.version <= s.max_version)))),
+              visible = true;
+
+          if (s.mode && _.isObject(s.mode))
+            visible = (_.indexOf(s.mode, mode) > -1);
+          if (visible)
+            visible = evalASFunc(s.visible);
+
           groupInfo[s.id] = {
             label: s.label || s.id,
             version_compatible: ver_in_limit,
-            visible: !s.mode || (
-              s && s.mode && _.isObject(s.mode) &&
-                _.indexOf(s.mode, mode) != -1) && evalASFunc(s.visible) || true
+            visible: visible
           };
           return;
         }
@@ -1768,9 +1773,13 @@
       // Create an array from the dictionary with proper required
       // structure.
       _.each(groups, function(val, key) {
-        fields.push(_.extend({
-          label: key, fields: val
-        }, (groupInfo[key] || {version_compatible: true, visible: true})));
+        fields.push(
+          _.extend(
+            _.defaults(
+              groupInfo[key] || {label: key},
+              {version_compatible: true, visible: true}
+            ), {fields: val})
+          );
       });
     }



view thread (5+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected]
  Subject: Re: [pgAdmin4][Patch]: View and Materialised View Nodes
  In-Reply-To: <CAM5-9D_28KxDdr_FhWm7wjWwsCejudE2Q1FA4pX8DKFMReYaaA@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox