diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/__init__.py b/web/pgadmin/browser/server_groups/servers/tablespaces/__init__.py
new file mode 100644
index 0000000..5bcbc87
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/__init__.py
@@ -0,0 +1,496 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2015, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+import json, re
+from flask import render_template, make_response, request, jsonify
+from flask.ext.babel import gettext
+from pgadmin.utils.ajax import make_json_response, \
+    make_response as ajax_response, internal_server_error
+from pgadmin.browser.utils import NodeView, parse_privileges
+from pgadmin.browser.collection import CollectionNodeModule
+import pgadmin.browser.server_groups.servers as servers
+from pgadmin.utils.ajax import precondition_required
+from pgadmin.utils.driver import get_driver
+from config import PG_DEFAULT_DRIVER
+from functools import wraps
+
+class TablespaceModule(CollectionNodeModule):
+    NODE_TYPE = 'tablespace'
+    COLLECTION_LABEL = gettext("Tablespaces")
+
+    def __init__(self, *args, **kwargs):
+        self.min_ver = None
+        self.max_ver = None
+
+        super(TablespaceModule, self).__init__(*args, **kwargs)
+
+    def get_nodes(self, gid, sid):
+        """
+        Generate the collection node
+        """
+        yield self.generate_browser_collection_node(sid)
+
+    @property
+    def script_load(self):
+        """
+        Load the module script for server, when any of the server-group node is
+        initialized.
+        """
+        return servers.ServerModule.NODE_TYPE
+
+
+blueprint = TablespaceModule(__name__)
+
+
+class TablespaceView(NodeView):
+    node_type = blueprint.node_type
+
+    parent_ids = [
+            {'type': 'int', 'id': 'gid'},
+            {'type': 'int', 'id': 'sid'}
+            ]
+    ids = [
+            {'type': 'int', 'id': 'did'}
+            ]
+
+    operations = dict({
+        'obj': [
+            {'get': 'properties', 'delete': 'delete', 'put': 'update'},
+            {'get': 'list', 'post': 'create'}
+        ],
+        'nodes': [{'get': 'node'}, {'get': 'nodes'}],
+        'children': [{'get': 'children'}],
+        'sql': [{'get': 'sql'}],
+        'msql': [{'get': 'msql'}, {'get': 'msql'}],
+        'stats': [{'get': 'statistics'}],
+        'dependency': [{'get': 'dependencies'}],
+        'dependent': [{'get': 'dependents'}],
+        'module.js': [{}, {}, {'get': 'module_js'}],
+        'vopts': [{}, {'get': 'variable_options'}]
+    })
+
+    def module_js(self):
+        """
+        This property defines (if javascript) exists for this node.
+        Override this property for your own logic.
+        """
+        return make_response(
+                render_template(
+                    "tablespaces/js/tablespaces.js",
+                    _=gettext
+                    ),
+                200, {'Content-Type': 'application/x-javascript'}
+                )
+
+    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 self
+        """
+        @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()
+
+            # 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!"
+                    )
+                )
+
+            ver = self.manager.version
+            if ver >= 90200:
+                self.template_path = 'tablespaces/sql/9.1_plus'
+            else:
+                self.template_path = 'tablespaces/sql/pre_9.1'
+
+            return f(*args, **kwargs)
+        return wrap
+
+    @staticmethod
+    def _parse_privileges(str_privileges):
+        """Parse Privileges."""
+        tblspc_privileges = {
+            'C': 'CREATE'
+        }
+
+        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(tblspc_privileges[privilege['privilege_type']])
+                elif privilege['privilege']:
+                    priv_without_grant.append(tblspc_privileges[privilege['privilege_type']])
+
+            priv_with_grant = ", ".join(priv_with_grant)
+            priv_without_grant = ", ".join(priv_without_grant)
+
+            privileges.append({'grantee': priv['grantee'],
+                               'with_grant': priv_with_grant,
+                               'without_grant': priv_without_grant})
+        return privileges
+
+
+    @check_precondition
+    def list(self, gid, sid):
+        SQL = render_template("/".join([self.template_path, 'properties.sql']))
+        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):
+        res = []
+        SQL = render_template("/".join([self.template_path, 'properties.sql']))
+        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'],
+                        row['name'],
+                        icon="icon-tablespace"
+                    ))
+
+        return make_json_response(
+                data=res,
+                status=200
+                )
+
+    def _formatter(self, data, did=None):
+        """
+        Args:
+            data: dict of query result
+            did: tablespace oid
+
+        Returns:
+            It will return formatted output of collections
+        """
+        # We need to format variables according to client js collection
+        if data['spcoptions'] is not None:
+            spcoptions = []
+            for spcoption in data['spcoptions']:
+                k, v = spcoption.split('=')
+                spcoptions.append({'name': k, 'value': v})
+
+            data['spcoptions'] = spcoptions
+
+        # Need to format security labels according to client js collection
+        if data['seclabels'] is not None:
+            seclabels = []
+            for seclbls in data['seclabels']:
+                k, v = seclbls.split('=')
+                seclabels.append({'provider': k, 'security_label': v})
+
+            data['seclabels'] = seclabels
+
+        # We need to parse & convert ACL coming from database to json format
+        SQL = render_template("/".join([self.template_path, 'acl.sql']),
+                              did=did)
+        status, acl = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=acl)
+
+        # We will set get privileges from acl sql so we don't need
+        # it from properties sql
+        data['spcacl'] = []
+
+        for row in acl['rows']:
+            priv = parse_privileges(row)
+            if row['deftype'] in data:
+                data[row['deftype']].append(priv)
+            else:
+                data[row['deftype']] = [priv]
+
+        return data
+
+    @check_precondition
+    def properties(self, gid, sid, did):
+        SQL = render_template("/".join([self.template_path, 'properties.sql']), did=did, conn=self.conn)
+        status, res = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        # Making copy of output for future use
+        copy_data = dict(res['rows'][0])
+        copy_data = self._formatter(copy_data, did)
+
+        return ajax_response(
+                response=copy_data,
+                status=200
+                )
+
+    @check_precondition
+    def create(self, gid, sid):
+        """
+        This function will creates new the tablespace object
+        """
+
+        required_args = {
+            'name': 'Name',
+            'spclocation': 'Location'
+        }
+
+        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)." % required_args[arg]
+                    )
+                )
+
+        # To format privileges coming from client
+        if 'spcacl' in data:
+            data['spcacl'] = self._parse_privileges(data['spcacl'])
+
+        try:
+            SQL = render_template("/".join([self.template_path, 'create.sql']), data=data, conn=self.conn)
+            status, res = self.conn.execute_scalar(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+            SQL = render_template("/".join([self.template_path, 'alter.sql']), data=data, conn=self.conn)
+            # Checking if we are not executing empty query
+            if SQL and SQL.strip('\n') and SQL.strip(' '):
+                status, res = self.conn.execute_scalar(SQL)
+                if not status:
+                    return internal_server_error(errormsg=res)
+            # To fetch the oid of newly created tablespace
+            SQL = render_template("/".join([self.template_path, 'alter.sql']), tablespace=data['name'], conn=self.conn)
+            status, did = self.conn.execute_scalar(SQL)
+            if not status:
+
+                return internal_server_error(errormsg=did)
+
+            return jsonify(
+                node=self.blueprint.generate_browser_node(
+                    did,
+                    data['name'],
+                    icon="icon-tablespace"
+                )
+            )
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    def update(self, gid, sid, did):
+        """
+        This function will update tablespace object
+        """
+        data = request.form if request.form else json.loads(request.data.decode())
+
+        try:
+            SQL = self.getSQL(gid, sid, data, did)
+            if SQL and SQL.strip('\n') and SQL.strip(' '):
+                status, res = self.conn.execute_scalar(SQL)
+                if not status:
+                    return internal_server_error(errormsg=res)
+
+                return make_json_response(
+                    success=1,
+                    info="Tablespace updated",
+                    data={
+                        'id': did,
+                        'sid': sid,
+                        'gid': gid
+                    }
+                )
+            else:
+                return make_json_response(
+                    success=1,
+                    info="Nothing to update",
+                    data={
+                        'id': did,
+                        'sid': sid,
+                        'gid': gid
+                    }
+                )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    def delete(self, gid, sid, did):
+        """
+        This function will drop the tablespace object
+        """
+        try:
+            # Get name for tablespace from did
+            SQL = render_template("/".join([self.template_path, 'delete.sql']), did=did, conn=self.conn)
+            status, tsname = self.conn.execute_scalar(SQL)
+            if not status:
+                return internal_server_error(errormsg=tsname)
+            # drop tablespace
+            SQL = render_template("/".join([self.template_path, 'delete.sql']), tsname=tsname, conn=self.conn)
+            status, res = self.conn.execute_scalar(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            return make_json_response(
+                success=1,
+                info=gettext("Tablespace dropped"),
+                data={
+                    'id': did,
+                    'sid': sid,
+                    'gid': gid,
+                }
+            )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    def msql(self, gid, sid, did=None):
+        """
+        This function to return modified SQL
+        """
+        data = dict()
+        for k, v in request.args.items():
+            try:
+                data[k] = json.loads(v)
+            except ValueError:
+                data[k] = v
+        try:
+            SQL = self.getSQL(gid, sid, data, did)
+
+            if SQL and SQL.strip('\n') and SQL.strip(' '):
+                return make_json_response(
+                        data=SQL,
+                        status=200
+                        )
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    def getSQL(self, gid, sid, data, did=None):
+        """
+        This function will genrate sql from model/properties data
+        """
+        required_args = [
+            'name'
+        ]
+
+        if did is not None:
+            SQL = render_template("/".join([self.template_path, 'properties.sql']), did=did, conn=self.conn)
+            status, res = self.conn.execute_dict(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            # Making copy of output for further processing
+            old_data = dict(res['rows'][0])
+            old_data = self._formatter(old_data, did)
+
+            # To format privileges data coming from client
+            for key in ['spcacl']:
+                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 name is not present with in update data then copy it
+            # from old data
+            for arg in required_args:
+                if arg not in data:
+                    data[arg] = old_data[arg]
+
+            SQL = render_template("/".join([self.template_path, 'update.sql']), data=data, o_data=old_data)
+        else:
+            # To format privileges coming from client
+            if 'spcacl' in data:
+                data['spcacl'] = self._parse_privileges(data['spcacl'])
+            # If the request for new object which do not have did
+            SQL = render_template("/".join([self.template_path, 'create.sql']), data=data)
+            SQL += "\n"
+            SQL += render_template("/".join([self.template_path, 'alter.sql']), data=data)
+
+        return SQL
+
+    @check_precondition
+    def sql(self, gid, sid, did):
+        """
+        This function will generate sql for sql panel
+        """
+        SQL = render_template("/".join([self.template_path, 'properties.sql']), did=did, conn=self.conn)
+        status, res = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        # Making copy of output for future use
+        old_data = dict(res['rows'][0])
+
+        old_data = self._formatter(old_data, did)
+
+        SQL = ''
+        # We are not showing create sql for system tablespace
+        if not old_data['name'].startswith('pg_'):
+            SQL = render_template("/".join([self.template_path, 'create.sql']), data=old_data)
+            SQL += "\n"
+        SQL += render_template("/".join([self.template_path, 'alter.sql']), data=old_data)
+
+        sql_header = """
+-- Tablespace: {0}
+
+-- DROP TABLESPACE {0}
+
+""".format(old_data['name'])
+
+        SQL = sql_header + SQL
+
+        return ajax_response(response=SQL)
+
+
+    @check_precondition
+    def variable_options(self, gid, sid):
+        res = []
+        SQL = render_template("/".join([self.template_path, 'variables.sql']))
+        status, rset = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=rset)
+
+        return make_json_response(
+                data=rset['rows'],
+                status=200
+                )
+
+    @check_precondition
+    def stats(self, gid, sid, did):
+        """
+        This function will return data for statistics panel
+        """
+        SQL = render_template("/".join([self.template_path, 'stats.sql']), did=did)
+        status, res = self.conn.execute_scalar(SQL)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        # TODO:// Format & return output of stats call accordingly
+        # TODO:// for now it's hardcoded as below
+        result = 'Tablespace Size: {0}'.format(res)
+        return ajax_response(response=result)
+
+
+TablespaceView.register_node_view(blueprint)
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/static/img/coll-tablespace.png b/web/pgadmin/browser/server_groups/servers/tablespaces/static/img/coll-tablespace.png
new file mode 100644
index 0000000000000000000000000000000000000000..9b090e419671c8179d99fa534b5bd91037da1036
GIT binary patch
literal 336
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPGa3-AeX1=6RMsysMV_v`ztpWh~b
z|Jr%?nBUhgb)P;LfBclm?tKNMjj<%iFPOpM*^M+HhqJ&VvKUBvfU(=jY&#$$)6>N<
zgyVX0LIb0lqaug%jT-`oL<)g`#n9z23#+gr&qt@^WJgC<HnvW;1#`L?n46y*x!~ex
zsNfv9L1xv&jm)bi7B0&G0)>G23o0rrD-}<$boTZ2xd}KIJv%c~Sn(Sd7uSJUMus_J
z!b;bB{wxAos#@Y2QIe8al4_M)lnSI6j0_A7bqx%4jf_JKjIDsk&{*5R%*w#v<Ye9g
y6b-rgDVb@NAPok(29`iQAx6elCMH$}X4(d(Kn<s+hpqu?VDNPHb6Mw<&;$U0C~VCD

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/static/img/tablespace.png b/web/pgadmin/browser/server_groups/servers/tablespaces/static/img/tablespace.png
new file mode 100644
index 0000000000000000000000000000000000000000..4995c6c44708d99f8df253580d06164125fa2411
GIT binary patch
literal 378
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}V1Q4EE0BJ0s_xWMm0#ay{rooV
z$G3^!zxLcc=Kt+W>z!jhFYcy%{ZjYy+vFE_5<Y(}|Ngb}`JJdwp9-Je4*B>g`_t#*
zC%1iX9kKuTDf96y_sd&6&#aNV&zS!hXeeVzkY6x^!?PP{Kn`btM`SUO_5fqIli7Aa
zMuMk{V~E7%-t+E44GKK00Y9|F0(2ri{9_lL6ftdI?7t;GQ+_!r|76n;da+&4Gw-p$
z)n@iYA6`e@jHp|aN~Rn*)OqizBF~4UFCso0lD3KHa3t}TuuGSfDSUc(Tk`*&D#j~c
zS(dBwMXLerQY~?fC`m~yNwrEYN(E93Mh1okx`sx&28JO<2397<Rwky}2Bua92J_zO
rtwPa|o1c=IRteEyU<uX$RBd8qU<T1}YI^7zpaup{S3j3^P6<r_UColv

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/js/tablespaces.js b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/js/tablespaces.js
new file mode 100644
index 0000000..53b59b8
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/js/tablespaces.js
@@ -0,0 +1,150 @@
+define(
+        ['jquery', 'underscore', 'underscore.string', 'pgadmin', 'pgadmin.browser', 'alertify', 'pgadmin.browser.collection', 'pgadmin.browser.node.ui', 'pgadmin.browser.server.privilege'],
+function($, _, S, pgAdmin, pgBrowser, alertify) {
+
+   var SecurityModel = Backform.SecurityModel = pgAdmin.Browser.Node.Model.extend({
+    defaults: {
+      provider: null,
+      security_label: null
+    },
+    schema: [{
+      id: 'provider', label: '{{ _('Provider') }}',
+      type: 'text', disabled: false
+    },{
+      id: 'security_label', label: '{{ _('Security Label') }}',
+      type: 'text', disabled: false
+    }],
+    validate: function() {
+      var err = {},
+          errmsg = null,
+          data = this.toJSON();
+
+      if (_.isUndefined(data.label) ||
+        _.isNull(data.label) ||
+        String(data.label).replace(/^\s+|\s+$/g, '') == '') {
+            errmsg = _("Please specify the value for all the security providers.");
+            this.errorModel.set('security_label', errmsg);
+          } else {
+            this.errorModel.unset('security_label');
+          }
+      return null;
+    }
+  });
+
+  if (!pgBrowser.Nodes['coll-tablespace']) {
+    var databases = pgAdmin.Browser.Nodes['coll-tablespace'] =
+      pgAdmin.Browser.Collection.extend({
+        node: 'tablespace',
+        label: '{{ _('Tablespaces') }}',
+        type: 'coll-tablespace',
+        columns: ['name', 'oid', 'description']
+      });
+  };
+
+  if (!pgBrowser.Nodes['tablespace']) {
+    pgAdmin.Browser.Nodes['tablespace'] = pgAdmin.Browser.Node.extend({
+      parent_type: 'server',
+      type: 'tablespace',
+      label: '{{ _('Tablespace') }}',
+      hasSQL:  true,
+      canDrop: true,
+      Init: function() {
+        /* Avoid mulitple registration of menus */
+        if (this.initialized)
+            return;
+
+        this.initialized = true;
+
+        pgBrowser.add_menus([{
+          name: 'create_tablespace_on_coll', node: 'coll-tablespace', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 4, label: '{{ _('Tablespace...') }}',
+          icon: 'wcTabIcon pg-icon-tablespace', data: {action: 'create'}
+        },{
+          name: 'create_tablespace', node: 'tablespace', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 4, label: '{{ _('Tablespace...') }}',
+          icon: 'wcTabIcon pg-icon-tablespace', data: {action: 'create'}
+        }
+        ]);
+      },
+      model: pgAdmin.Browser.Node.Model.extend({
+        defaults: {
+          name: undefined,
+          owner: undefined,
+          comment: undefined,
+          spclocation: undefined,
+          spcoptions: [],
+          spcacl: [],
+          seclabels:[]
+        },
+        schema: [{
+          id: 'name', label: '{{ _('Name') }}', cell: 'string',
+          type: 'text'
+        },{
+          id: 'oid', label:'{{ _('Oid') }}', cell: 'string',
+          type: 'text', disabled: true, mode: ['properties', 'edit']
+        },{
+          id: 'spclocation', label:'{{ _('Location') }}', cell: 'string',
+          type: 'text', mode: ['edit','create'],
+          disabled: function(m) {
+            // To disabled it in edit mode,
+            // We'll check if model is new if yes then disabled it
+            return !m.isNew();
+          }
+        },{
+          id: 'spcuser', label:'{{ _('Owner') }}', cell: 'string',
+          type: 'text', control: 'node-list-by-name', node: 'role'
+        },{
+          id: 'description', label:'{{ _('Comment') }}', cell: 'string',
+          type: 'multiline'
+        },{
+          id: 'spcoptions', label: 'Variables', type: 'collection',
+          group: "Variables", control: 'variable-collection',
+          model: pgAdmin.Browser.Node.VariableModel,
+          mode: ['edit', 'create'], canAdd: true, canEdit: false,
+          canDelete: true
+         },{
+          id: 'spcacl', label: 'Privileges', type: 'collection',
+          group: '{{ _('Security') }}', control: 'unique-col-collection',
+          model: pgAdmin.Browser.Node.PrivilegeRoleModel.extend({privileges: ['C']}),
+          mode: ['properties', 'edit', 'create'], canAdd: true, canDelete: true,
+          uniqueCol : ['grantee'],
+          columns: ['grantee', 'grantor', 'privileges']
+         },{
+          id: 'seclabels', label: '{{ _('Security Labels') }}',
+          model: SecurityModel, editable: false, type: 'collection',
+          group: '{{ _('Security') }}', mode: ['edit', 'create'],
+          min_version: 90200, canAdd: true,
+          canEdit: false, canDelete: true, control: 'unique-col-collection'
+        }
+        ],
+        validate: function() {
+        // TODO: Add validation here
+          var err = {},
+            errmsg = null,
+            changedAttrs = this.sessAttrs,
+            msg = undefined;
+          if (_.has(changedAttrs, 'name') &&
+                (_.isUndefined(this.get('name'))
+              || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '')) {
+            msg = '{{ _('Name can not be empty!') }}';
+            this.errorModel.set('name', msg);
+          } else if (_.has(changedAttrs, 'spclocation') &&
+                (_.isUndefined(this.get('spclocation'))
+              || String(this.get('spclocation')).replace(/^\s+|\s+$/g, '') == '')) {
+            msg = '{{ _('Location can not be empty!') }}';
+            this.errorModel.set('spclocation', msg);
+          } else {
+            this.errorModel.unset('name');
+            this.errorModel.unset('spclocation');
+          }
+          return null;
+        }
+      })
+  });
+
+  }
+
+  return pgBrowser.Nodes['coll-tablespace'];
+});
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/acl.sql
new file mode 100644
index 0000000..e116299
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/acl.sql
@@ -0,0 +1,27 @@
+SELECT 'spcacl' 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 'CREATE' THEN 'C'
+    ELSE 'UNKNOWN'
+    END AS privilege_type
+  FROM
+    (SELECT ts.spcacl
+        FROM pg_tablespace ts
+        {% if did %}
+        WHERE ts.oid={{did}}::int
+        {% endif %}
+    ) 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(ts.spcacl) as d FROM pg_tablespace ts
+        {% if did %}
+        WHERE ts.oid={{did}}::int
+        {% endif %}
+        ) 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
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/alter.sql b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/alter.sql
new file mode 100755
index 0000000..964af10
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/alter.sql
@@ -0,0 +1,42 @@
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/variable.macros' as VARIABLE %}
+{% import 'macros/privilege.macros' as PRIVILEGE %}
+{% if data %}
+{### Owner on tablespace ###}
+{% if data.spcuser  %}
+ALTER TABLESPACE {{ conn|qtIdent(data.name) }}
+  OWNER TO {{ data.spcuser }};
+
+{% endif %}
+{### Comments on tablespace ###}
+{% if data.description %}
+COMMENT ON TABLESPACE {{ conn|qtIdent(data.name) }}
+  IS {{ data.description|qtLiteral }};
+
+{% endif %}
+{### Security Labels on tablespace ###}
+{% if data.seclabels and data.seclabels|length > 0 %}
+{% for r in data.seclabels %}
+{{ SECLABLE.APPLY(conn, 'TABLESPACE', data.name, r.provider, r.security_label) }}
+{% endfor %}
+
+{% endif %}
+{### Variables on tablespace ###}
+{% if data.spcoptions %}
+{% for var in data.spcoptions %}
+{{ VARIABLE.SET(conn, 'TABLESPACE', data.name, var.name, var.value) }}
+{% endfor %}
+
+{% endif %}
+{###  ACL on tablespace ###}
+{% if data.spcacl %}
+{% for priv in data.spcacl %}
+{{ PRIVILEGE.APPLY(conn, 'TABLESPACE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
+{% endfor %}
+
+{% endif %}
+{% endif %}
+{# ======== The SQl Below will fetch id for given dataspace ======== #}
+{% if tablespace %}
+SELECT ts.oid FROM pg_tablespace ts WHERE spcname = {{tablespace|qtLiteral}}
+{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/create.sql b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/create.sql
new file mode 100644
index 0000000..1e29dee
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/create.sql
@@ -0,0 +1,8 @@
+{% if data %}
+CREATE TABLESPACE {{ conn|qtIdent(data.name) }}
+{% if data.spcuser %}
+  OWNER {{ data.spcuser }}
+{% endif %}
+  LOCATION {{ data.spclocation|qtLiteral }};
+
+{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/delete.sql
new file mode 100644
index 0000000..9ba4d8c
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/delete.sql
@@ -0,0 +1,8 @@
+{% if did %}
+SELECT spcname
+  FROM pg_tablespace ts
+  WHERE ts.oid = {{did}}
+{% endif %}
+{% if tsname %}
+DROP TABLESPACE {{ conn|qtIdent(tsname) }};
+{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/properties.sql
new file mode 100755
index 0000000..8c18781
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/properties.sql
@@ -0,0 +1,9 @@
+SELECT ts.oid, spcname AS name, pg_catalog.pg_tablespace_location(ts.oid) AS spclocation, spcoptions,
+pg_get_userbyid(spcowner) as spcuser, spcacl::text[],
+pg_catalog.shobj_description(oid, 'pg_tablespace') AS description
+,(SELECT array_agg(provider || '=' || label) FROM pg_shseclabel sl1 WHERE sl1.objoid=ts.oid) AS seclabels
+FROM pg_tablespace ts
+{% if did %}
+WHERE ts.oid={{did}}::int
+{% endif %}
+ORDER BY name
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/stats.sql b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/stats.sql
new file mode 100644
index 0000000..817620c
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/stats.sql
@@ -0,0 +1 @@
+SELECT pg_size_pretty(pg_tablespace_size({{did}})) AS tablespace_size
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/update.sql b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/update.sql
new file mode 100644
index 0000000..e9eae02
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/update.sql
@@ -0,0 +1,85 @@
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/variable.macros' as VARIABLE %}
+{% import 'macros/privilege.macros' as PRIVILEGE %}
+{% if data %}
+{# ============= The SQL below will update tablespace name ============= #}
+{% if data.name != o_data.name %}
+ALTER TABLESPACE {{ o_data.name }}
+  RENAME TO {{ conn|qtIdent(data.name) }};
+
+{% endif %}
+{# ============= The SQL below will update tablespace user ============= #}
+{% if data.spcuser and data.spcuser != o_data.spcuser %}
+ALTER TABLESPACE {{ conn|qtIdent(data.name) }}
+  OWNER TO {{ data.spcuser }};
+
+{% endif %}
+{# ============= The SQL below will update tablespace comments ============= #}
+{% if data.description and data.description != o_data.description %}
+COMMENT ON TABLESPACE {{ data.name }}
+  IS {{ data.description|qtLiteral }};
+
+{% endif %}
+{# ============= The SQL below will update tablespace variables ============= #}
+{% if 'spcoptions' in data and data.spcoptions|length > 0 %}
+{% set variables = data.spcoptions %}
+{% if 'deleted' in variables and variables.deleted|length > 0 %}
+{% for var in variables.deleted %}
+{{ VARIABLE.UNSET(conn, 'TABLESPACE', data.name, var.name) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in variables and variables.added|length > 0 %}
+{% for var in variables.added %}
+{{ VARIABLE.SET(conn, 'TABLESPACE', data.name, var.name, var.value) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in variables and variables.changed|length > 0 %}
+{% for var in variables.changed %}
+{{ VARIABLE.SET(conn, 'TABLESPACE', data.name, var.name, var.value) }}
+{% endfor %}
+{% endif %}
+
+{% endif %}
+{# ============= The SQL below will update tablespace securitylabel ============= #}
+{# The SQL generated below will change Security Label #}
+{% if data.seclabels 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, 'TABLESPACE', data.name, r.provider) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+{{ SECLABLE.APPLY(conn, 'TABLESPACE', 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, 'TABLESPACE', data.name, r.provider, r.security_label) }}
+{% endfor %}
+{% endif %}
+
+{% endif %}
+{# ============= The SQL below will update tablespace privileges ============= #}
+{# Change the privileges #}
+{% if data.spcacl %}
+{% if 'deleted' in data.spcacl %}
+{% for priv in data.spcacl.deleted %}
+{{ PRIVILEGE.RESETALL(conn, 'TABLESPACE', priv.grantee, data.name) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in data.spcacl %}
+{% for priv in data.spcacl.changed %}
+{{ PRIVILEGE.RESETALL(conn, 'TABLESPACE', priv.grantee, data.name) }}
+{{ PRIVILEGE.APPLY(conn, 'TABLESPACE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in data.spcacl %}
+{% for priv in data.spcacl.added %}
+{{ PRIVILEGE.APPLY(conn, 'TABLESPACE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
+{% endfor %}
+{% endif %}
+
+{% endif %}
+{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/variables.sql
new file mode 100644
index 0000000..3053874
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/9.1_plus/variables.sql
@@ -0,0 +1,3 @@
+SELECT name, vartype, min_val, max_val, enumvals
+FROM pg_settings
+WHERE name IN ('seq_page_cost', 'random_page_cost');
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/acl.sql b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/acl.sql
new file mode 100644
index 0000000..e116299
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/acl.sql
@@ -0,0 +1,27 @@
+SELECT 'spcacl' 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 'CREATE' THEN 'C'
+    ELSE 'UNKNOWN'
+    END AS privilege_type
+  FROM
+    (SELECT ts.spcacl
+        FROM pg_tablespace ts
+        {% if did %}
+        WHERE ts.oid={{did}}::int
+        {% endif %}
+    ) 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(ts.spcacl) as d FROM pg_tablespace ts
+        {% if did %}
+        WHERE ts.oid={{did}}::int
+        {% endif %}
+        ) 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
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/alter.sql b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/alter.sql
new file mode 100755
index 0000000..964af10
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/alter.sql
@@ -0,0 +1,42 @@
+{% import 'macros/security.macros' as SECLABLE %}
+{% import 'macros/variable.macros' as VARIABLE %}
+{% import 'macros/privilege.macros' as PRIVILEGE %}
+{% if data %}
+{### Owner on tablespace ###}
+{% if data.spcuser  %}
+ALTER TABLESPACE {{ conn|qtIdent(data.name) }}
+  OWNER TO {{ data.spcuser }};
+
+{% endif %}
+{### Comments on tablespace ###}
+{% if data.description %}
+COMMENT ON TABLESPACE {{ conn|qtIdent(data.name) }}
+  IS {{ data.description|qtLiteral }};
+
+{% endif %}
+{### Security Labels on tablespace ###}
+{% if data.seclabels and data.seclabels|length > 0 %}
+{% for r in data.seclabels %}
+{{ SECLABLE.APPLY(conn, 'TABLESPACE', data.name, r.provider, r.security_label) }}
+{% endfor %}
+
+{% endif %}
+{### Variables on tablespace ###}
+{% if data.spcoptions %}
+{% for var in data.spcoptions %}
+{{ VARIABLE.SET(conn, 'TABLESPACE', data.name, var.name, var.value) }}
+{% endfor %}
+
+{% endif %}
+{###  ACL on tablespace ###}
+{% if data.spcacl %}
+{% for priv in data.spcacl %}
+{{ PRIVILEGE.APPLY(conn, 'TABLESPACE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
+{% endfor %}
+
+{% endif %}
+{% endif %}
+{# ======== The SQl Below will fetch id for given dataspace ======== #}
+{% if tablespace %}
+SELECT ts.oid FROM pg_tablespace ts WHERE spcname = {{tablespace|qtLiteral}}
+{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/create.sql b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/create.sql
new file mode 100644
index 0000000..1e29dee
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/create.sql
@@ -0,0 +1,8 @@
+{% if data %}
+CREATE TABLESPACE {{ conn|qtIdent(data.name) }}
+{% if data.spcuser %}
+  OWNER {{ data.spcuser }}
+{% endif %}
+  LOCATION {{ data.spclocation|qtLiteral }};
+
+{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/delete.sql b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/delete.sql
new file mode 100644
index 0000000..9ba4d8c
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/delete.sql
@@ -0,0 +1,8 @@
+{% if did %}
+SELECT spcname
+  FROM pg_tablespace ts
+  WHERE ts.oid = {{did}}
+{% endif %}
+{% if tsname %}
+DROP TABLESPACE {{ conn|qtIdent(tsname) }};
+{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/properties.sql b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/properties.sql
new file mode 100755
index 0000000..60d229b
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/properties.sql
@@ -0,0 +1,8 @@
+SELECT ts.oid, spcname AS name, pg_catalog.pg_tablespace_location(ts.oid) AS spclocation, spcoptions,
+pg_get_userbyid(spcowner) as spcuser, spcacl::text[],
+pg_catalog.shobj_description(oid, 'pg_tablespace') AS description
+FROM pg_tablespace ts
+{% if did %}
+WHERE ts.oid={{did}}::int
+{% endif %}
+ORDER BY name
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/stats.sql b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/stats.sql
new file mode 100644
index 0000000..817620c
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/stats.sql
@@ -0,0 +1 @@
+SELECT pg_size_pretty(pg_tablespace_size({{did}})) AS tablespace_size
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/update.sql b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/update.sql
new file mode 100644
index 0000000..5b5476c
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/update.sql
@@ -0,0 +1,63 @@
+{% import 'macros/variable.macros' as VARIABLE %}
+{% import 'macros/privilege.macros' as PRIVILEGE %}
+{% if data %}
+{# ============= The SQL below will update tablespace name ============= #}
+{% if data.name != o_data.name %}
+ALTER TABLESPACE {{ o_data.name }}
+  RENAME TO {{ conn|qtIdent(data.name) }};
+
+{% endif %}
+{# ============= The SQL below will update tablespace user ============= #}
+{% if data.spcuser and data.spcuser != o_data.spcuser %}
+ALTER TABLESPACE {{ conn|qtIdent(data.name) }}
+  OWNER TO {{ data.spcuser }};
+
+{% endif %}
+{# ============= The SQL below will update tablespace comments ============= #}
+{% if data.description and data.description != o_data.description %}
+COMMENT ON TABLESPACE {{ data.name }}
+  IS {{ data.description|qtLiteral }};
+
+{% endif %}
+{# ============= The SQL below will update tablespace variables ============= #}
+{% if 'spcoptions' in data and data.spcoptions|length > 0 %}
+{% set variables = data.spcoptions %}
+{% if 'deleted' in variables and variables.deleted|length > 0 %}
+{% for var in variables.deleted %}
+{{ VARIABLE.UNSET(conn, 'TABLESPACE', data.name, var.name) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in variables and variables.added|length > 0 %}
+{% for var in variables.added %}
+{{ VARIABLE.SET(conn, 'TABLESPACE', data.name, var.name, var.value) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in variables and variables.changed|length > 0 %}
+{% for var in variables.changed %}
+{{ VARIABLE.SET(conn, 'TABLESPACE', data.name, var.name, var.value) }}
+{% endfor %}
+{% endif %}
+
+{% endif %}
+{# ============= The SQL below will update tablespace privileges ============= #}
+{# Change the privileges #}
+{% if data.spcacl %}
+{% if 'deleted' in data.spcacl %}
+{% for priv in data.spcacl.deleted %}
+{{ PRIVILEGE.RESETALL(conn, 'TABLESPACE', priv.grantee, data.name) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in data.spcacl %}
+{% for priv in data.spcacl.changed %}
+{{ PRIVILEGE.RESETALL(conn, 'TABLESPACE', priv.grantee, data.name) }}
+{{ PRIVILEGE.APPLY(conn, 'TABLESPACE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in data.spcacl %}
+{% for priv in data.spcacl.added %}
+{{ PRIVILEGE.APPLY(conn, 'TABLESPACE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
+{% endfor %}
+{% endif %}
+
+{% endif %}
+{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/variables.sql b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/variables.sql
new file mode 100644
index 0000000..3053874
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/templates/tablespaces/sql/pre_9.1/variables.sql
@@ -0,0 +1,3 @@
+SELECT name, vartype, min_val, max_val, enumvals
+FROM pg_settings
+WHERE name IN ('seq_page_cost', 'random_page_cost');
\ No newline at end of file
