Resending patch with binary option.

On Wed, Jan 20, 2016 at 10:18 AM, Khushboo Vashi <
[email protected]> wrote:

> Hi,
>
> Please find attached patch for the Domain Module.
>
> The patch will be modified after Types module implementation as we need to
> populate Base Type  and some Type related validations from the Types module.
>
> Please review it and let me know the feedback.
>
> Thanks,
> Khushboo
>
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/__init__.py
new file mode 100644
index 0000000..250a665
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/__init__.py
@@ -0,0 +1,510 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+import json
+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 PGChildNodeView
+from pgadmin.browser.collection import CollectionNodeModule
+import pgadmin.browser.server_groups.servers.databases.schemas as schemas
+from pgadmin.utils.ajax import precondition_required
+from pgadmin.utils.driver import get_driver
+from config import PG_DEFAULT_DRIVER
+from functools import wraps
+
+class DomainModule(CollectionNodeModule):
+    NODE_TYPE = 'domain'
+    COLLECTION_LABEL = gettext("Domains")
+
+    def __init__(self, *args, **kwargs):
+        self.min_ver = None
+        self.max_ver = None
+        super(DomainModule, self).__init__(*args, **kwargs)
+
+    # Before loading this module we need to make sure that scid is schema object
+    def BackendSupported(self, manager, **kwargs):
+        """
+        This function will validate schema name & scid against catalogs then allow us to
+        make decision if we want to load this module or not for the schema
+        """
+        if super(DomainModule, self).BackendSupported(manager, **kwargs):
+            conn = manager.connection()
+            # If DB is not connected then return error to browser
+            if not conn.connected():
+                return precondition_required(
+                    gettext(
+                            "Connection to the server has been lost!"
+                    )
+                )
+            ver = manager.version
+            server_type = manager.server_type
+            # we will set template path for sql scripts
+            if ver >= 90100:
+                template_path = 'domains/sql/9.1_plus'
+            else:
+                # Note: Domain is not supported below postgres version 9.1
+                # Hence we will not load this module
+                return False
+
+            SQL = render_template("/".join([template_path, 'backend_support.sql']), scid=kwargs['scid'])
+            status, res = conn.execute_scalar(SQL)
+            # check if any errors
+            if not status:
+                return internal_server_error(errormsg=res)
+            # Check scid is catalog and from 'sys', 'dbo', 'information_schema',
+            # then False (Do not load this module), othewise True
+            if res is True:
+                return False
+            else:
+                return True
+
+    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 database, when any of the database node is
+        initialized.
+        """
+        return schemas.SchemaModule.NODE_TYPE
+
+
+blueprint = DomainModule(__name__)
+
+
+class DomainView(PGChildNodeView):
+    node_type = blueprint.node_type
+
+    parent_ids = [
+            {'type': 'int', 'id': 'gid'},
+            {'type': 'int', 'id': 'sid'},
+            {'type': 'int', 'id': 'did'},
+            {'type': 'int', 'id': 'scid'}
+            ]
+    ids = [
+            {'type': 'int', 'id': 'doid'}
+            ]
+
+    operations = dict({
+        'obj': [
+            {'get': 'properties', 'delete': 'delete', 'put': 'update'},
+            {'get': 'list', 'post': 'create'}
+        ],
+        'delete': [{'delete': 'delete'}],
+        'children': [{'get': 'children'}],
+        'nodes': [{'get': 'node'}, {'get': 'nodes'}],
+        'sql': [{'get': 'sql'}],
+        'msql': [{'get': 'msql'}, {'get': 'msql'}],
+        'stats': [{'get': 'statistics'}],
+        'dependency': [{'get': 'dependencies'}],
+        'dependent': [{'get': 'dependents'}],
+        'module.js': [{}, {}, {'get': 'module_js'}],
+        'get_schemas': [{'get': 'get_schemas'}, {'get': 'get_schemas'}],
+        'get_collations': [{'get': 'get_collations'}, {'get': 'get_collations'}],
+        'get_types': [{'get': 'get_types'}, {'get': 'get_types'}]
+    })
+
+
+    def module_js(self):
+        return make_response(
+                render_template(
+                    "domains/js/domains.js",
+                    _=gettext
+                    ),
+                200, {'Content-Type': 'application/x-javascript'}
+                )
+
+
+    def check_precondition(f):
+        """
+        Works as a decorator.
+        Checks database connection status.
+        Attach connection object and template path.
+        """
+        @wraps(f)
+        def wrap(*args, **kwargs):
+            # Here args[0] will hold self & kwargs will hold gid,sid,did
+            self = args[0]
+            driver = get_driver(PG_DEFAULT_DRIVER)
+            self.manager = driver.connection_manager(kwargs['sid'])
+            # Get database connection
+            self.conn = self.manager.connection(did=kwargs['did'])
+            self.qtIdent = driver.qtIdent
+
+            # If database is not connected then return error
+            if not self.conn.connected():
+                return precondition_required(
+                    gettext(
+                            "Connection to the server has been lost!"
+                    )
+                )
+
+            ver = self.manager.version
+            server_type = self.manager.server_type
+
+            # we will set template path for sql scripts
+            if ver >= 90100:
+                self.template_path = 'domains/sql/9.1_plus'
+            return f(*args, **kwargs)
+
+        return wrap
+
+
+    @check_precondition
+    def list(self, gid, sid, did, scid):
+        """List the Domains."""
+
+        SQL = render_template("/".join([self.template_path, '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):
+        """Returns all the Domains."""
+
+        res = []
+        SQL = render_template("/".join([self.template_path, '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'],
+                        row['name'],
+                        icon="icon-domain"
+                    ))
+
+        return make_json_response(
+                data=res,
+                status=200
+                )
+
+
+    @check_precondition
+    def properties(self, gid, sid, did, scid, doid):
+        """Returns Domain properties."""
+
+        SQL = render_template("/".join([self.template_path, 'properties.sql']),scid=scid, doid=doid)
+        status, res = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        data = res['rows'][0]
+
+        # Get Domain Constraints
+        SQL = render_template("/".join([self.template_path, 'get_constraints.sql']),doid=doid)
+        status, res = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+
+        data['constraints'] = res['rows']
+        return ajax_response(
+                response=data,
+                status=200
+                )
+
+
+    @check_precondition
+    def get_schemas(self, gid, sid, did, scid, doid=None):
+        """Returns Schemas for particular database."""
+
+        res = [{ 'label': '', 'value': '' }]
+        try:
+            SQL = render_template("/".join([self.template_path, 'get_schemas.sql']), scid=scid)
+            status, rset = self.conn.execute_2darray(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            for row in rset['rows']:
+                res.append(
+                            { 'label': row['nspname'], 'value': row['nspname'] }
+                        )
+
+            return make_json_response(
+                    data=res,
+                    status=200
+                    )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+
+    @check_precondition
+    def get_collations(self, gid, sid, did, scid, doid=None):
+        """Returns Collations."""
+
+        res = [{ 'label': '', 'value': '' }]
+        try:
+            SQL = render_template("/".join([self.template_path, 'get_collations.sql']))
+            status, rset = self.conn.execute_2darray(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            for row in rset['rows']:
+                res.append(
+                            { 'label': row['copy_collation'], 'value': row['copy_collation'] }
+                        )
+
+            return make_json_response(
+                    data=res,
+                    status=200
+                    )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+
+    @check_precondition
+    def get_types(self, gid, sid, did, scid, doid=None):
+        """Returns Types."""
+        # TODO: This function should be removed once Types module will be completed.
+
+        res = [{ 'label': '', 'value': '' }]
+        try:
+            SQL = render_template("/".join([self.template_path, 'get_types.sql']))
+            status, rset = self.conn.execute_2darray(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            for row in rset['rows']:
+                res.append(
+                            { 'label': row['typname'], 'value': row['typname'] }
+                        )
+            return make_json_response(
+                    data=res,
+                    status=200
+                    )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+
+    @check_precondition
+    def create(self, gid, sid, did, scid):
+        """
+        Creates new domain object.
+
+        Expected Parameters:
+            name: Domain Name
+            owner: Owner Name
+            basensp: Schema Name
+            basetype: Domain Base Type
+
+        Expected Response:
+            Domain object in json format.
+        """
+
+        data = request.form if request.form else json.loads(request.data.decode())
+        required_args = [
+            'name',
+            'owner',
+            'basensp',
+            'basetype'
+        ]
+
+        for arg in required_args:
+            if arg not in data or data[arg] == '':
+                return make_json_response(
+                    status=410,
+                    success=0,
+                    errormsg=gettext(
+                        "Couldn't find the required parameter (%s)." % arg
+                    )
+                )
+
+        try:
+            SQL = render_template("/".join([self.template_path, 'create.sql']), data=data, qtIdent=self.qtIdent)
+            status, res = self.conn.execute_scalar(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            # we need oid to to add object in tree at browser, below sql will gives the same
+            SQL = render_template("/".join([self.template_path, 'get_oid.sql']), basensp=data['basensp'], name=data['name'])
+            status, doid = self.conn.execute_scalar(SQL)
+            if not status:
+                return internal_server_error(errormsg=doid)
+
+            return jsonify(
+                node=self.blueprint.generate_browser_node(
+                    doid,
+                    data['name'],
+                    icon="icon-domain"
+                )
+            )
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+
+    @check_precondition
+    def delete(self, gid, sid, did, scid, doid):
+        """
+        Drop the Domain.
+        """
+        # Below will decide if it's simple drop or drop with cascade call
+        if self.cmd == 'delete':
+            # This is a cascade operation
+            cascade = True
+        else:
+            cascade = False
+
+        try:
+            SQL = render_template("/".join([self.template_path, 'delete.sql']), scid=scid, doid=doid)
+            status, res = self.conn.execute_2darray(SQL)
+            if not status:
+                return internal_server_error(errormsg=name)
+
+            name, basensp = res['rows'][0]
+
+            SQL = render_template("/".join([self.template_path, 'delete.sql']), name=name, basensp=basensp, 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("Domain dropped"),
+                data={
+                    'id': doid,
+                    'scid': scid,
+                    'sid': sid,
+                    'gid': gid,
+                    'did': did
+                }
+            )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    def update(self, gid, sid, did, scid, doid):
+        """
+        Update the Domain.
+        """
+        data = request.form if request.form else json.loads(request.data.decode())
+
+        status, SQL = self.getSQL(gid, sid, data, scid, doid)
+        if not status:
+            return internal_server_error(errormsg=SQL)
+
+        try:
+            if SQL and SQL.strip('\n') and SQL.strip(' '):
+                status, res = self.conn.execute_scalar(SQL)
+                if not status:
+                    return internal_server_error(errormsg=res)
+
+                return make_json_response(
+                    success=1,
+                    info="Domain updated",
+                    data={
+                        'id': doid,
+                        'scid': scid,
+                        'sid': sid,
+                        'gid': gid,
+                        'did': did
+                    }
+                )
+            else:
+                return make_json_response(
+                    success=1,
+                    info="Nothing to update",
+                    data={
+                        'id': doid,
+                        'scid': scid,
+                        'sid': sid,
+                        'gid': gid,
+                        'did': did
+                    }
+                )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    def msql(self, gid, sid, did, scid, doid=None):
+        """
+        Returns the modified SQL.
+
+        Expected Parameters:
+            name: Domain Name
+            owner: Owner Name
+            basensp: Schema Name
+            basetype: Domain Base Type
+
+        Expected Response:
+            SQL statements to create/update the Domain.
+        """
+        data = request.args
+        if doid is None:
+            required_args = [
+                'name',
+                'owner',
+                'basensp',
+                'basetype'
+            ]
+
+
+            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, scid, doid)
+        if isinstance(SQL, str) and SQL and SQL.strip('\n') and SQL.strip(' '):
+            return make_json_response(
+                    data=SQL,
+                    status=200
+                    )
+        else:
+            return SQL
+
+
+    def getSQL(self, gid, sid, data, scid, doid=None):
+        """
+        Genrates the SQL statements to create/update the Domain.
+        """
+        try:
+            if doid is not None:
+                SQL = render_template("/".join([self.template_path, 'properties.sql']), scid=scid, doid=doid)
+                status, res = self.conn.execute_dict(SQL)
+
+                if not status:
+                    return False, internal_server_error(errormsg=res)
+
+                old_data = res['rows'][0]
+                SQL = render_template(
+                    "/".join([self.template_path,'update.sql']),
+                    data=data, o_data=old_data, conn=self.conn, qtIdent=self.qtIdent
+                    )
+            else:
+                SQL = render_template("/".join([self.template_path, 'create.sql']), data=data, conn=self.conn, qtIdent=self.qtIdent)
+            return True,SQL
+
+        except Exception as e:
+            return False, e
+
+DomainView.register_node_view(blueprint)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/__init__.py
new file mode 100644
index 0000000..7f0575b
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/__init__.py
@@ -0,0 +1,390 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+import json
+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
+from pgadmin.browser.collection import CollectionNodeModule
+import pgadmin.browser.server_groups.servers.databases.schemas.domains as domains
+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 DomainConstraintModule(CollectionNodeModule):
+    NODE_TYPE = 'domain-constraints'
+    COLLECTION_LABEL = gettext("Domain Constraints")
+
+    def __init__(self, *args, **kwargs):
+        self.min_ver = None
+        self.max_ver = None
+        super(DomainConstraintModule, self).__init__(*args, **kwargs)
+
+    def get_nodes(self, gid, sid, did, scid, doid):
+        """
+        Generate the collection node
+        """
+        yield self.generate_browser_collection_node(doid)
+
+    @property
+    def node_inode(self):
+        """
+        Override this property to make the node as leaf node.
+        """
+        return False
+
+
+    @property
+    def script_load(self):
+        """
+        Load the module script for database, when any of the database node is
+        initialized.
+        """
+        return domains.DomainModule.NODE_TYPE
+
+
+blueprint = DomainConstraintModule(__name__)
+
+
+class DomainConstraintView(NodeView):
+    node_type = blueprint.node_type
+
+    parent_ids = [
+            {'type': 'int', 'id': 'gid'},
+            {'type': 'int', 'id': 'sid'},
+            {'type': 'int', 'id': 'did'},
+            {'type': 'int', 'id': 'scid'},
+            {'type': 'int', 'id': 'doid'}
+            ]
+    ids = [
+            {'type': 'int', 'id': 'coid'}
+            ]
+
+    operations = dict({
+        'obj': [
+            {'get': 'properties', 'delete': 'delete', 'put': 'update'},
+            {'get': 'list', 'post': 'create'}
+        ],
+        'delete': [{'delete': 'delete'}],
+        'children': [{'get': 'children'}],
+        'nodes': [{'get': 'node'}, {'get': 'nodes'}],
+        'sql': [{'get': 'sql'}],
+        'msql': [{'get': 'msql'}, {'get': 'msql'}],
+        'stats': [{'get': 'statistics'}],
+        'dependency': [{'get': 'dependencies'}],
+        'dependent': [{'get': 'dependents'}],
+        'module.js': [{}, {}, {'get': 'module_js'}]
+    })
+
+    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(
+                    "domain-constraints/js/domain-constraints.js",
+                    _=gettext
+                    ),
+                200, {'Content-Type': 'application/x-javascript'}
+                )
+
+    def check_precondition(f):
+        """
+        Works as a decorator.
+        Checks database connection status.
+        Attach connection object and template path.
+        """
+        @wraps(f)
+        def wrap(*args, **kwargs):
+            # Here args[0] will hold self & kwargs will hold gid,sid,did
+            self = args[0]
+            driver = get_driver(PG_DEFAULT_DRIVER)
+            self.manager = driver.connection_manager(kwargs['sid'])
+            self.conn = self.manager.connection(did=kwargs['did'])
+            self.qtIdent = driver.qtIdent
+
+            # 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
+            server_type = self.manager.server_type
+
+            # we will set template path for sql scripts
+            if ver >= 90100:
+                self.template_path = 'domain-constraints/sql/9.1_plus'
+            return f(*args, **kwargs)
+
+        return wrap
+
+
+    @check_precondition
+    def list(self, gid, sid, did, scid, doid):
+        """
+        List the Domain Constraints.
+        """
+        SQL = render_template("/".join([self.template_path, 'properties.sql']), doid=doid)
+        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, doid):
+        """
+        Returns all the Domain Constraints.
+        """
+        res = []
+        SQL = render_template("/".join([self.template_path, 'properties.sql']), doid=doid)
+        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['conname'],
+                        icon="icon-domain-constraints"
+                    ))
+
+        return make_json_response(
+                data=res,
+                status=200
+                )
+
+
+    @check_precondition
+    def properties(self, gid, sid, did, scid, doid, coid):
+        """
+        Returns the Domain Constraints property.
+        """
+
+        SQL = render_template("/".join([self.template_path, 'properties.sql']),doid=doid, coid=coid)
+        status, res = self.conn.execute_dict(SQL)
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        return ajax_response(
+                response=res['rows'][0],
+                status=200
+                )
+
+
+    @check_precondition
+    def create(self, gid, sid, did, scid, doid):
+        """
+        Creates new the Domain Constraints.
+
+        Expected Parameters:
+            conname: Constraints Name
+            consrc: Constraints Check
+
+        Expected Response:
+            Domain Constraint object in json format.
+        """
+
+        data = request.form if request.form else json.loads(request.data.decode())
+        required_args = [
+            'conname',
+            'consrc'
+        ]
+
+        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
+                    )
+                )
+
+        try:
+            # Get Schema and Domain.
+            SQL = render_template("/".join([self.template_path, 'get_domain.sql']), doid=doid)
+            status, res = self.conn.execute_2darray(SQL)
+            if not status:
+                return internal_server_error(errormsg=name)
+
+            domain, schema = res['rows'][0]
+
+            SQL = render_template("/".join([self.template_path, 'create.sql']), data=data, domain=domain, schema=schema, qtIdent=self.qtIdent)
+            status, res = self.conn.execute_scalar(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            # Get the recently added constraints oid
+            SQL = render_template("/".join([self.template_path, 'get_oid.sql']), doid=doid, name=data['conname'])
+            status, coid = self.conn.execute_scalar(SQL)
+            if not status:
+                return internal_server_error(errormsg=doid)
+
+            return jsonify(
+                node=self.blueprint.generate_browser_node(
+                    coid,
+                    data['conname'],
+                    icon="icon-domain"
+                )
+            )
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+
+    @check_precondition
+    def delete(self, gid, sid, did, scid, doid, coid):
+        """
+        Drop the Doman Constraints.
+        """
+        try:
+            SQL = render_template("/".join([self.template_path, 'properties.sql']), doid=doid, coid=coid)
+            status, res = self.conn.execute_dict(SQL)
+
+            if not status:
+                return internal_server_error(errormsg=res)
+            data = res['rows'][0]
+
+            SQL = render_template("/".join([self.template_path, 'delete.sql']), data=data)
+            status, res = self.conn.execute_scalar(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            return make_json_response(
+                success=1,
+                info=gettext("Domain dropped"),
+                data={
+                    'id': doid,
+                    'scid': scid,
+                    'sid': sid,
+                    'gid': gid,
+                    'did': did
+                }
+            )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+
+    @check_precondition
+    def update(self, gid, sid, did, scid, doid, coid):
+        """
+        Update the Domain Constraints.
+        """
+        data = request.form if request.form else json.loads(request.data.decode())
+
+        SQL = self.getSQL(gid, sid, data, scid, doid, coid)
+        try:
+            if SQL and SQL.strip('\n') and SQL.strip(' '):
+                status, res = self.conn.execute_scalar(SQL)
+                if not status:
+                    return internal_server_error(errormsg=res)
+
+                return make_json_response(
+                    success=1,
+                    info="Domain updated",
+                    data={
+                        'id': doid,
+                        'scid': scid,
+                        'sid': sid,
+                        'gid': gid,
+                        'did': did
+                    }
+                )
+            else:
+                return make_json_response(
+                    success=1,
+                    info="Nothing to update",
+                    data={
+                        'id': doid,
+                        'scid': scid,
+                        'sid': sid,
+                        'gid': gid,
+                        'did': did
+                    }
+                )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+
+    @check_precondition
+    def msql(self, gid, sid, did, scid, doid=None):
+        """
+        Returns the modified SQL.
+
+        Expected Parameters:
+            conname: Constraints Name
+            consrc: Constraints Check
+
+        Expected Response:
+            Domain Constraint object in json format.
+        """
+        data = request.args
+        if doid is None:
+            required_args = [
+                'conname',
+                'consrc'
+            ]
+
+            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, scid, doid)
+        if isinstance(SQL, str) and SQL and SQL.strip('\n') and SQL.strip(' '):
+            return make_json_response(
+                    data=SQL,
+                    status=200
+                    )
+        else:
+            return SQL
+
+
+    def getSQL(self, gid, sid, data, scid, doid, coid=None):
+        """
+        Genrates the SQL statements to create/update the Domain Constraint.
+        """
+        try:
+            if coid is not None:
+                SQL = render_template("/".join([self.template_path, 'properties.sql']), doid=doid, coid=coid)
+                status, res = self.conn.execute_dict(SQL)
+
+                if not status:
+                    return internal_server_error(errormsg=res)
+                old_data = res['rows'][0]
+
+                SQL = render_template(
+                    "/".join([self.template_path,'update.sql']),
+                    data=data, o_data=old_data, conn=self.conn
+                    )
+            else:
+                SQL = render_template("/".join([self.template_path, 'create.sql']), data=data, conn=self.conn)
+            return SQL
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+DomainConstraintView.register_node_view(blueprint)
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/static/img/coll-domain-constraints.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/static/img/coll-domain-constraints.png
new file mode 100644
index 0000000000000000000000000000000000000000..d62e13705c50e6c0cf8f19d680053e8643e28751
GIT binary patch
literal 314
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFv3GfMV1=2TrO847{Jl`|t`Qpas
zn<hS+l=rMY>RGPqvlydizRJ&>B`Om#V}R-yOM?7@862M7NCR>>3p^r=fwTu0yPeFo
z12TL)T^vI=t|uoPU||ZF<tgaHG*QsQ!?m&Tq=?3mCu}J#Dx3x@mM}}^iE=5NIWXnk
zkpnC4ai%a>@;Gg7=uums=9bIK=Egd~(us-3g@Iv02gfsK^JP^)gH=mhBT7;dOH!?p
zi&B9UgOP!ufv%yEu7P2Qk%5(ov6YF5wt=aYfq}(LRXG$5x%nxXX_XKS29{tAAk|g|
XW)KahriZQpYGCkm^>bP0l+XkKyyRU}

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/static/img/domain-constraints-bad.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/static/img/domain-constraints-bad.png
new file mode 100644
index 0000000000000000000000000000000000000000..32a045b8fafdc08640d53b2a86b1dcabcb0fe0fd
GIT binary patch
literal 579
zcmV-J0=)f+P)<h;3K|Lk000e1NJLTq000mG000mO0{{R3C@l|D00001b5ch_0Itp)
z=>Px$AW%$HMR1Z9#Q*@REHmdHAm<<;=p`lTDl6$LE15$|nM6yxJ3#6&F}^)Qx<p3n
zH#h4zIK)Ou#79fTM@#HJKkY(8?L$QEL`CjJMeasM?ng(;QB>|oNbX2U?n+AUOH1!e
zOz%xi?@dncPEXKRS?^Cz#amtQQBm+xQt(q#@KaRqR8;U)Rq<9<@mE*YVq(`~V)0vB
z+GS<)VPW%PV%=$Jag!JHXlV6qZS`($_HuH3pd<EncJ_C7f1@XWqbGu>Du=8uhpjJ)
zvN4agH<i3UrMYgWyK<eyN1Vq+p2tbA!G5C3PO!m$q|HvV#D$~JOsv;ftk_qv-CeQX
zT*cC%$J3;><6_L$t<Kr8)!w|r@o>cPam4X*+~mi`^K{Glc|xh<NdN!<0d!JMQvg8b
z*k%9#00Cl4M??UK1szBL000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2ipf34<ROg
z(p72z0056kL_t&-)1{2Z3c^qT1mDEody6IZuCW&s1V!`^4}$goe?(18@b2Db*j*w1
z%4M(p;&Zw?9ZaKAxo*x;COX}<8fzjqKRv^2kF1spymYHMjE2m7Hl|a~emCNwG8(i?
z8I#``(kiBrEbh}(Qn8TL2+$}b3Hn^7p`K6R#_6zQ2$?ux;lXBYB>hkN@C%g?4vVBM
R$bbL<002ovPDHLkV1min0OSAw

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/static/img/domain-constraints.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/static/img/domain-constraints.png
new file mode 100644
index 0000000000000000000000000000000000000000..9d1d2a061c7948168d7b1c2474d769b31709f1cf
GIT binary patch
literal 406
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}X@F0NE08{VY2nhHc^eMaU%j`d
zaI$#+HuEKC{pKEZKYn>h(+aIMH^MjGjcs3}f9Cqyt&fvx7AT*)xv^`L;hf{Hi_iP4
zxgK%&V?q65_4c*;8}G%;JMMY<SLM___M4Bi9{E^!<YUpX&n1ga`7PgFwEkdS!(#P<
zNn&@N9OqiK(i&(nV@Z%-FoVOh8)-leXMsm#F_88EW4Dvpc0fjir;B5V#O36K1sn!O
zhRVf}5jSsGPH?f<xudc|vBoY<&5cb=uTGB9v187J4II+it5?jhn8F{TsCZIWRad$D
zg1*K9W%cu2NsD(hEfVT#*wm#pYw;D04+0E(uQE?s`Z6*ZXoqTvYeY#(Vo9o1a#1Rf
zVlXl=G|)9P(lsy)F*2|+F}5->(Kax(GBB{1sVaw}AvZrIGp!P$!N3x%0i@c>zzm|{
T)b!9bKn)C@u6{1-oD!M<=4O^k

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/css/domain-constraints.css b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/css/domain-constraints.css
new file mode 100644
index 0000000..68cd622
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/css/domain-constraints.css
@@ -0,0 +1,9 @@
+.pg-icon-domain-constraints {
+  background-image: url('{{ url_for('NODE-domain-constraints.static', filename='img/domain-constraints.png') }}') !important;
+  border-radius: 10px;
+  background-repeat: no-repeat;
+  align-content: center;
+  vertical-align: middle;
+  height: 1.3em;
+}
+
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/js/domain-constraints.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/js/domain-constraints.js
new file mode 100644
index 0000000..fb3de7d
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/js/domain-constraints.js
@@ -0,0 +1,95 @@
+define(
+        ['jquery', 'underscore', 'underscore.string', 'pgadmin', 'pgadmin.browser', 'alertify', 'pgadmin.browser.collection'],
+function($, _, S, pgAdmin, pgBrowser, alertify) {
+
+  if (!pgBrowser.Nodes['coll-domain-constraints']) {
+    var databases = pgAdmin.Browser.Nodes['coll-domain-constraints'] =
+      pgAdmin.Browser.Collection.extend({
+        node: 'domain-constraints',
+        label: '{{ _('Domain Constraints') }}',
+        type: 'coll-domain-constraints'
+      });
+  };
+
+  if (!pgBrowser.Nodes['domain-constraints']) {
+    pgAdmin.Browser.Nodes['domain-constraints'] = pgBrowser.Node.extend({
+      type: 'domain-constraints',
+      label: '{{ _('Domain Constraints') }}',
+      collection_type: 'coll-domain-constraints',
+      hasSQL: true,
+      parent_type: ['domain'],
+      Init: function() {
+        /* Avoid mulitple registration of menus */
+        if (this.initialized)
+            return;
+
+        this.initialized = true;
+
+        pgBrowser.add_menus([{
+          name: 'create_domain_on_coll', node: 'coll-domain-constraints', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 4, label: '{{ _('Domain Constraint...') }}',
+          icon: 'wcTabIcon icon-domain-constraints', data: {action: 'create', check: true},
+          enable: 'canCreate'
+        },{
+          name: 'create_domain-constraints', node: 'domain-constraints', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 4, label: '{{ _('Domain Constraint...') }}',
+          icon: 'wcTabIcon icon-domain-constraints', data: {action: 'create', check: true},
+          enable: 'canCreate'
+        },{
+          name: 'create_domain-constraints', node: 'domain', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 4, label: '{{ _('Domain Constraint...') }}',
+          icon: 'wcTabIcon icon-domain-constraints', data: {action: 'create', check: false},
+          enable: 'canCreate'
+        }
+        ]);
+
+      },
+      canDrop: pgBrowser.Nodes['schema'].canChildDrop,
+      model: pgAdmin.Browser.Node.Model.extend({
+        defaults: {
+          conname: undefined,
+          description: undefined,
+          consrc: undefined,
+          connoinherit: undefined,
+          convalidated: undefined
+        },
+        schema: [{id: 'conname', label:'Name', type:'text', cell:'string'},
+        {id: 'description', label:'Comment', type: 'multiline', cell: 'string', mode: ['properties', 'create', 'edit'], disabled: function(m) { return !m.isNew(); }},
+        {id: 'consrc', label:'Check', type: 'multiline', cel: 'string', group: 'Definition', mode: ['properties', 'create', 'edit'], disabled: function(m) { return !m.isNew(); }},
+        {id: 'connoinherit', label:'No Inherit', type: 'switch', cell: 'boolean', group: 'Definition', mode: ['properties', 'create', 'edit'], disabled: function(m) { return !m.isNew(); }},
+        {id: 'convalidated', label:"Don't Validate", type: 'switch', cell: 'boolean', group: 'Definition'}
+        ],
+        validate: function() {
+          var err = {},
+              errmsg;
+
+          if (_.isUndefined(this.get('conname')) || String(this.get('conname')).replace(/^\s+|\s+$/g, '') == '') {
+            err['conname'] = '{{ _('Name can not be empty!') }}';
+            errmsg = errmsg || err['conname'];
+          }
+
+          if (_.isUndefined(this.get('consrc')) || String(this.get('consrc')).replace(/^\s+|\s+$/g, '') == '') {
+            err['consrc'] = '{{ _('Check can not be empty!') }}';
+            errmsg = errmsg || err['consrc'];
+          }
+
+          this.errorModel.clear().set(err);
+
+          if (_.size(err)) {
+            this.trigger('on-status', {msg: errmsg});
+            return errmsg;
+          }
+
+          return null;
+
+        },
+      }),
+  });
+
+  }
+
+  return pgBrowser.Nodes['domain'];
+});
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/create.sql
new file mode 100644
index 0000000..ed2610d
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/create.sql
@@ -0,0 +1,6 @@
+{% if data and schema and domain %}
+  ALTER DOMAIN {{ conn|qtIdent(schema, domain) }}
+  ADD CONSTRAINT {{ data.conname }} CHECK ({{ data.consrc }} )
+  {% if data.convalidated %} NOT VALID {% endif %} {% if data.connoinherit %} NO INHERIT {% endif %};
+{% endif %}
+
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/delete.sql
new file mode 100644
index 0000000..1a56583
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/delete.sql
@@ -0,0 +1,4 @@
+{% if data %}
+  ALTER DOMAIN {{ conn|qtIdent(data.nspname, data.relname) }}
+  DROP CONSTRAINT {{ data.conname }}
+{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/get_domain.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/get_domain.sql
new file mode 100644
index 0000000..a199c5c
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/get_domain.sql
@@ -0,0 +1,7 @@
+SELECT d.typname as domain, bn.nspname as schema
+FROM
+  pg_type d
+JOIN
+  pg_namespace bn ON bn.oid=d.typnamespace
+WHERE
+  d.oid = {{doid}}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/get_oid.sql
new file mode 100644
index 0000000..344abcc
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/get_oid.sql
@@ -0,0 +1,4 @@
+SELECT oid, conname as name
+  FROM pg_constraint
+WHERE contypid = {{doid}}::oid
+  AND conname={{ name|qtLiteral }};
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/properties.sql
new file mode 100644
index 0000000..7ed21d9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/properties.sql
@@ -0,0 +1,18 @@
+SELECT 'TABLE' AS objectkind, c.oid, conname, relname, nspname, description,
+  pg_get_expr(conbin, conrelid, true) as consrc, connoinherit, convalidated
+FROM pg_constraint c
+JOIN pg_class cl ON cl.oid=conrelid
+JOIN pg_namespace nl ON nl.oid=relnamespace
+LEFT OUTER JOIN pg_description des ON (des.objoid=c.oid AND des.classoid='pg_constraint'::regclass)
+WHERE contype = 'c' AND conrelid =  {{doid}}::oid
+UNION
+SELECT 'DOMAIN' AS objectkind, c.oid, conname, typname as relname, nspname, description,
+       regexp_replace(pg_get_constraintdef(c.oid, true), E'CHECK \\((.*)\\).*', E'\\1') as consrc
+, connoinherit, convalidated  FROM pg_constraint c
+  JOIN pg_type t ON t.oid=contypid
+  JOIN pg_namespace nl ON nl.oid=typnamespace
+  LEFT OUTER JOIN pg_description des ON (des.objoid=t.oid AND des.classoid='pg_constraint'::regclass)
+ WHERE contype = 'c' AND contypid =  {{doid}}::oid
+{% if coid %}
+  AND c.oid = {{ coid }}
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/update.sql
new file mode 100644
index 0000000..9a2c8d7
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.1_plus/update.sql
@@ -0,0 +1,4 @@
+{% if data.conname %}
+  ALTER DOMAIN {{ conn|qtIdent(o_data.nspname, o_data.relname) }}
+    RENAME CONSTRAINT {{ o_data.conname }} TO {{ data.conname }};
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/static/img/coll-domain.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/static/img/coll-domain.png
new file mode 100644
index 0000000000000000000000000000000000000000..55621528a1dba4928538fe5557b9b988ed78d6ab
GIT binary patch
literal 462
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}U4T!BE0BJeoqfW=;gF{0PD8_o
zi&pN_(K)B7`FPi%2ix`@v9LU(tNUQ*!K1czXOxuggoGT_(#p@zf4Jw!!zHV)`3F7T
zd-Um}H}`iRIijcc@Wq#>&ptkR`SszG54Uz6zW4mg?MLsgZ9jbb>E~y!zTSB9`Re1(
zjS1S99(_9h@YC4`A5Y)^_^>@J3+MvIk|4ie28U-i(tsS!0*}aIAngIhZYQ(tfQ)ue
z7sn8Z%b|U@#hMgESUvs4wKoSxO>~{O=-Yq$8_!r)-^e%4-l6f-Jox1%8}FIVx>FCW
zPMVwluQGbkP1bcSwVV0d_?PZbZVis%HeYTWyU*$OvYp$uTc3QLbD?2trOnDuhZa>f
z=3d_{(zER9xt(<n3UsBI4SNC?Y!rBW<m2`n>yDRyg$uoE8Qx}bo1D0qw;t#u)e_f;
zl9a@fRIB8oR3OD*WMF8ZYiOivU>IU#U}a)#Wn!XjU}|MxU@=ow4n;$5eoAIqB}9XP
eC0GMUwUvPxM8m1+p=*E|7(8A5T-G@yGywoRCC2Lj

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/static/img/domain-sm.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/static/img/domain-sm.png
new file mode 100644
index 0000000000000000000000000000000000000000..7521cddeaaaf0ee4e3c60e948078d70e17e06893
GIT binary patch
literal 401
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}T7XZ8E0Deu9eu*V;gF{0K`pIg
zc6K`r4IeIAc}Q3HxV`=3y+@xudUJpGkt2F~PoI5!^78A$Cm(L@JbcYR=;4bm_nv>b
z{pkI*?T7D#gyiSvKYR7{_S4Tdo_xOg_;X`|_N7Ok&OiKg_QA)~_dlLo85{w$iLoTe
zFPOpM*^M+HhqJ&VvKUBvfU(=jY&#$$$<xI#MB;Mq`IABp20RT9wUXkaL(1R(pOn?c
z>38<+e>KaN2{%0Jd@sMbY$+13Z&%Z<%!P+*SNu+#({Rr={_KxUhswHdID0QWTCBvD
z)^ky;@gu`E#RAC#l`JcnelS0rxkKN7b1B>H56gX)0&P<*ag8WRNi0dVN-jzTQVd20
zh6cKZM!E)uAw~vPCdO7KCfWw3Rt5$ZGgakKH00)|WTsU@G#FTdHGouG8JIydoSGiG
Q2B?9-)78&qol`;+03_q3ga7~l

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/static/img/domain.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/static/img/domain.png
new file mode 100644
index 0000000000000000000000000000000000000000..42ca929325854b8f34787425e8094d08c75983bc
GIT binary patch
literal 424
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}PJmB{E0BJeoqfW=;gF{0PD8^7
zi&s6`bL8oxH}`iRdHU?*lb2r~J^6Th=ix^$zTSWS<?f>oH+CHUa^}pVf`aWvMt7fm
zx&8F>jfd~AY(HF`mUiRG=W9<sUwQB@KR>@QLHo+%PZuA3I{)y~*$1D_JotF({zvHt
zo%ulf7)yfuf*Bm1-ADs+I14-?i-EKU7`vU!wgWPXJzX3_Brcbpe=XFcAmSFNeC3q&
zl!Z+(RsYN12&-NW{P*^#<rx82_2-+ii&SqfGgO`Jcj@;01@HTH{&&7#v?j}I)=J6m
ze`~hppZn7?WA|%z!}T6pf>z0IjbZrS5ICD*275*_bAo)r8t#Vg4A*Lz);xc4JKq03
zXXC}zd)YwiRZCnWN>UO_QmvAUQh^kMk%6IsuAz~xfnkV|ft87|m5GVAfvJ^&fyGQ!
qITQ`K`6-!cl@JXEmS7Da)m8>(5DllMhpqu?VDNPHb6Mw<&;$VOR=Fqu

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/css/domains.css b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/css/domains.css
new file mode 100644
index 0000000..7d4fad0
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/css/domains.css
@@ -0,0 +1,9 @@
+.pg-icon-domain {
+  background-image: url('{{ url_for('NODE-domain.static', filename='img/domain.png') }}') !important;
+  border-radius: 10px;
+  background-repeat: no-repeat;
+  align-content: center;
+  vertical-align: middle;
+  height: 1.3em;
+}
+
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/js/domains.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/js/domains.js
new file mode 100644
index 0000000..8fcf507
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/js/domains.js
@@ -0,0 +1,236 @@
+/* Create and Register Domain Collection and Domain Node. */
+
+define(
+        ['jquery', 'underscore', 'underscore.string', 'pgadmin', 'pgadmin.browser', 'alertify', 'pgadmin.browser.collection'],
+function($, _, S, pgAdmin, pgBrowser, alertify) {
+
+  if (!pgBrowser.Nodes['coll-domain']) {
+    var databases = pgAdmin.Browser.Nodes['coll-domain'] =
+      pgAdmin.Browser.Collection.extend({
+        node: 'domain',
+        label: '{{ _('Domains') }}',
+        type: 'coll-domain'
+      });
+  };
+
+  var SecurityModel = Backform.SecurityModel = pgAdmin.Browser.Node.Model.extend({
+    defaults: {
+      provider: null,
+      security_label: null
+    },
+    schema: [{
+      id: 'provider', label: '{{ _('Provider') }}',
+      type: 'text'
+    },{
+      id: 'security_label', label: '{{ _('Security Label') }}',
+      type: 'text'
+    }],
+    validate: function() {
+      var err = {},
+          errmsg = null,
+          data = this.toJSON();
+
+      if (_.isUndefined(data.label) ||
+        _.isNull(data.label) ||
+        String(data.label).replace(/^\s+|\s+$/g, '') == '') {
+        return _("Please specify the value for all the security providers.");
+      }
+      return null;
+    }
+  });
+
+  var ConstraintsModel = pgAdmin.Browser.Node.Model.extend({
+    defaults: {
+      conname: undefined,
+      description: undefined,
+      slony: undefined,
+      consrc: undefined,
+      connoinherit: undefined,
+      convalidated: undefined
+    },
+    schema: [
+      {id: 'conname', label:'Name', type:'text', cell:'string'},
+      {id: 'description', label:'Comment', type: 'multiline', cell: 'string'},
+      {id: 'slony', label:'Use Slony', type: 'text', cell: 'string'},
+      {id: 'consrc', label:'Check', type: 'multiline', cel: 'string', group: 'definition'},
+      {id: 'connoinherit', label:'No Inherit', type: 'switch', cell: 'boolean', group: 'definition'},
+      {id: 'convalidated', label:"Don't Validate", type: 'switch', cell: 'boolean', group: 'definition'}
+    ],
+    validate: function() {
+      // TODO: Add validation here
+    },
+    toJSON: Backbone.Model.prototype.toJSON
+  });
+
+
+  if (!pgBrowser.Nodes['domain']) {
+    pgAdmin.Browser.Nodes['domain'] = pgBrowser.Node.extend({
+      type: 'domain',
+      label: '{{ _('Domain') }}',
+      collection_type: 'coll-domain',
+      hasSQL: true,
+      parent_type: ['schema'],
+      Init: function() {
+        /* Avoid mulitple registration of menus */
+        if (this.initialized)
+            return;
+
+        this.initialized = true;
+
+        pgBrowser.add_menus([{
+          name: 'create_domain_on_coll', node: 'coll-domain', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 4, label: '{{ _('Domain...') }}',
+          icon: 'wcTabIcon icon-domain', data: {action: 'create', check: true},
+          enable: 'canCreate'
+        },{
+          name: 'create_domain', node: 'domain', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 4, label: '{{ _('Domain...') }}',
+          icon: 'wcTabIcon icon-domain', data: {action: 'create', check: true},
+          enable: 'canCreate'
+        },{
+          name: 'create_domain', node: 'schema', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 4, label: '{{ _('Domain...') }}',
+          icon: 'wcTabIcon icon-domain', data: {action: 'create', check: false},
+          enable: 'canCreate'
+        }
+        ]);
+
+      },
+      canDrop: pgBrowser.Nodes['schema'].canChildDrop,
+      canDropCascade: pgBrowser.Nodes['schema'].canChildDrop,
+      model: pgAdmin.Browser.Node.Model.extend({
+        defaults: {
+          name: undefined,
+          oid: undefined, 
+          owner: undefined,
+          basensp: undefined,
+          description: undefined,
+          basetype: undefined,
+          typlen: undefined,
+          precision: undefined,
+          typdefault: undefined,
+          typnotnull: undefined,
+          collname: undefined,
+          constraints: [],
+          seclabels: []
+        },
+        schema: [{
+          id: 'name', label: '{{ _('Name') }}', cell: 'string',
+          type: 'text', mode: ['properties', 'create', 'edit']
+        },{
+          id: 'oid', label:'{{ _('Oid') }}', cell: 'string',
+          type: 'text' , mode: ['properties']
+        },{
+          id: 'owner', label:'{{ _('Owner') }}', cell: 'string', control: Backform.NodeListByNameControl,
+          node: 'role',  type: 'text', mode: ['edit', 'create', 'properties']
+        },{
+          id: 'basensp', label:'{{ _('Schema') }}', cell: 'string', control: 'node-ajax-options',
+          type: 'text', url: 'get_schemas'
+        },{
+          id: 'description', label:'{{ _('Comment') }}', cell: 'string',
+          type: 'multiline'
+        },{
+          id: 'basetype', label:'{{ _('Base Type') }}', cell: 'string', control: 'node-ajax-options',
+          type: 'text', mode:['properties', 'create', 'edit'], group: 'Definition', url: 'get_types',
+          disabled: function(m) { return !m.isNew(); }
+        },{
+          id: 'typlen', label:'{{ _('Length') }}', cell: 'string',
+          type: 'text', group: 'Definition', disabled: function(m) { return !m.isNew(); }
+        },{
+          id: 'precision', label:'{{ _('Precision') }}', cell: 'string',
+          type: 'text', group: 'Definition', disabled: function(m) { return !m.isNew(); }
+        },{
+          id: 'typdefault', label:'{{ _('Default') }}', cell: 'string',
+          type: 'text', group: 'Definition'
+        },{
+          id: 'typnotnull', label:'{{ _('Not Null') }}', cell: 'boolean',
+          type: 'switch', group: 'Definition'
+        },{
+          id: 'collname', label:'{{ _('Collation') }}', cell: 'string', control: 'node-ajax-options',
+          type: 'text', group: 'Definition', url: 'get_collations', disabled: function(m) { return !m.isNew(); }
+        },{
+          id: 'constraints', label:'{{ _('Constraints') }}', cell: 'string',
+          type: 'collection', group: 'Constraints', visible: false, mode: ['edit', 'create'],
+          model: ConstraintsModel, canAdd: true, canDelete: false, canEdit: false
+        },{
+          id: 'seclabels', label: '{{ _('Security Labels') }}',
+          model: SecurityModel, editable: false, type: 'collection',
+          group: '{{ _('Security') }}', mode: ['edit', 'create'],
+          min_version: 90100, canAdd: true,
+          canEdit: false, canDelete: true, control: 'unique-col-collection'
+        }
+        ],
+        validate: function()
+        {
+          var err = {},
+              errmsg,
+              seclabels = this.get('seclabels');
+
+          if (_.isUndefined(this.get('name')) || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') {
+            err['name'] = '{{ _('Name can not be empty!') }}';
+            errmsg = errmsg || err['name'];
+          }
+
+          if (_.isUndefined(this.get('basetype')) || String(this.get('basetype')).replace(/^\s+|\s+$/g, '') == '') {
+            err['basetype'] = '{{ _('Base Type can not be empty!') }}';
+            errmsg = errmsg || err['basetype'];
+          }
+
+          if (seclabels) {
+            var secLabelsErr;
+            for (var i = 0; i < seclabels.models.length && !secLabelsErr; i++) {
+              secLabelsErr = (seclabels.models[i]).validate.apply(seclabels.models[i]);
+              if (secLabelsErr) {
+                err['seclabels'] = secLabelsErr;
+                errmsg = errmsg || secLabelsErr;
+              }
+            }
+          }
+
+          this.errorModel.clear().set(err);
+
+          if (_.size(err)) {
+            this.trigger('on-status', {msg: errmsg});
+            return errmsg;
+          }
+
+          return null;
+        }
+      }),
+      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 domain
+          if (_.indexOf(['schema'], d._type) > -1)
+            return true;
+
+          if ('coll-domain' == d._type) {
+            //Check if we are not child of catalog
+            prev_i = t.hasParent(i) ? t.parent(i) : null;
+            prev_d = prev_i ? t.itemData(prev_i) : null;
+            if( prev_d._type == 'catalog') {
+              return false;
+            } else {
+              return true;
+            }
+          }
+          i = t.hasParent(i) ? t.parent(i) : null;
+          d = i ? t.itemData(i) : null;
+        }
+        // by default we do not want to allow create menu
+        return true;
+      }
+  });
+
+  }
+
+  return pgBrowser.Nodes['domain'];
+});
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/backend_support.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/backend_support.sql
new file mode 100644
index 0000000..7417b43
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/backend_support.sql
@@ -0,0 +1,20 @@
+SELECT
+  CASE WHEN nsp.nspname IN ('sys', 'dbo', 'information_schema') THEN true ELSE false END AS dbSupport
+FROM
+  pg_namespace nsp
+WHERE
+  nsp.oid={{scid}}::int
+  AND (
+    (nspname = 'pg_catalog' AND EXISTS 
+                                   (SELECT 1 FROM pg_class WHERE relname = 'pg_class' AND relnamespace = nsp.oid LIMIT 1))
+    OR (nspname = 'pgagent' AND EXISTS
+                                   (SELECT 1 FROM pg_class WHERE relname = 'pga_job' AND relnamespace = nsp.oid LIMIT 1))
+    OR (nspname = 'information_schema' AND EXISTS 
+                                   (SELECT 1 FROM pg_class WHERE relname = 'tables' AND relnamespace = nsp.oid LIMIT 1))
+    OR (nspname LIKE '_%' AND EXISTS 
+                                   (SELECT 1 FROM pg_proc WHERE proname='slonyversion' AND pronamespace = nsp.oid LIMIT 1))
+    )
+  AND
+   nspname NOT LIKE E'pg\\temp\\%'
+  AND
+   nspname NOT LIKE E'pg\\toast_temp\\%'
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/create.sql
new file mode 100644
index 0000000..d4cdfe0
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/create.sql
@@ -0,0 +1,32 @@
+{% import 'macros/security.macros' as SECLABLE %}
+
+{% if data %}
+  CREATE DOMAIN {{ conn|qtIdent(data.basensp, data.name) }}
+    AS {{ data.basetype }}
+  {% if data.collname %}
+    COLLATE {{ data.collname }}
+  {% endif %}
+
+  {% if data.typnotnull %}
+    NOT NULL
+  {% endif %}
+  ;
+
+  {% if data.constraints %}
+    {% for c in data.constraints %}
+      ALTER DOMAIN {{ conn|qtIdent(data.basensp, data.name) }}
+      ADD CONSTRAINT {{ c.conname }} CHECK ({{ c.consrc }} )
+      {% if c.convalidated %} NOT VALID {% endif %} {% if c.connoinherit %} NO INHERIT {% endif %};
+    {% endfor %}
+  {% endif %}
+
+  ALTER DOMAIN {{ conn|qtIdent(data.basensp, data.name) }} OWNER TO {{ data.owner }};
+  {% if data.description %}
+    COMMENT ON DOMAIN {{ conn|qtIdent(data.basensp, data.name) }}
+    IS '{{ data.description }}';
+  {% endif %}
+
+  {% for r in data.seclabels %}
+    {{ SECLABLE.APPLY(conn, 'DOMAIN', data.name, r.provider, r.label) }}
+  {% endfor %}
+{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/delete.sql
new file mode 100644
index 0000000..c740f4f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/delete.sql
@@ -0,0 +1,11 @@
+{% if scid and doid %}
+  SELECT d.typname as name, bn.nspname as basensp
+  FROM pg_type d
+  JOIN pg_namespace bn ON bn.oid=d.typnamespace
+  WHERE d.typnamespace = {{scid}}::oid
+  AND d.oid={{doid}}::int;
+{% endif %}
+
+{% if name %}
+  DROP DOMAIN {{ conn|qtIdent(basensp, name) }}{% if cascade%} CASCADE{% endif %}
+{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_collations.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_collations.sql
new file mode 100644
index 0000000..6a13a65
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_collations.sql
@@ -0,0 +1,7 @@
+SELECT --nspname, collname,
+  CASE WHEN length(nspname) > 0 AND length(collname) > 0  THEN
+  concat(nspname, '."', collname,'"')
+  ELSE '' END AS copy_collation
+FROM pg_collation c, pg_namespace n
+WHERE c.collnamespace=n.oid
+ORDER BY nspname, collname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_constraints.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_constraints.sql
new file mode 100644
index 0000000..e26998f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_constraints.sql
@@ -0,0 +1,18 @@
+SELECT 'TABLE' AS objectkind, c.oid, conname, relname, nspname, description,
+  pg_get_expr(conbin, conrelid, true) as consrc, connoinherit, convalidated  FROM pg_constraint c
+JOIN pg_class cl ON cl.oid=conrelid
+JOIN pg_namespace nl ON nl.oid=relnamespace
+LEFT OUTER JOIN pg_description des ON (des.objoid=c.oid AND des.classoid='pg_constraint'::regclass)
+WHERE contype = 'c' AND conrelid =  {{doid}}::oid
+UNION
+SELECT 'DOMAIN' AS objectkind, c.oid, conname, typname as relname, nspname, description,
+  regexp_replace(pg_get_constraintdef(c.oid, true), E'CHECK \\((.*)\\).*', E'\\1') as consrc
+, connoinherit, convalidated
+FROM pg_constraint c
+JOIN pg_type t ON t.oid=contypid
+JOIN pg_namespace nl ON nl.oid=typnamespace
+
+LEFT OUTER JOIN pg_description des ON (des.objoid=t.oid AND des.classoid='pg_constraint'::regclass)
+
+ WHERE contype = 'c' AND contypid =  {{doid}}::oid
+ORDER BY conname
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_oid.sql
new file mode 100644
index 0000000..1c26d6b
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_oid.sql
@@ -0,0 +1,10 @@
+SELECT
+  d.oid, d.typname as name
+FROM
+  pg_type d
+JOIN
+  pg_namespace bn ON bn.oid=d.typnamespace
+WHERE
+  bn.nspname = {{ basensp|qtLiteral }}
+  AND d.typname={{ name|qtLiteral }}
+
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_schemas.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_schemas.sql
new file mode 100644
index 0000000..82dcfcb
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_schemas.sql
@@ -0,0 +1,21 @@
+SELECT
+  nsp.nspname
+FROM
+  pg_namespace nsp
+  LEFT OUTER JOIN pg_description des ON (des.objoid=nsp.oid AND des.classoid='pg_namespace'::regclass)
+  LEFT OUTER JOIN pg_catalog.pg_default_acl dacl ON (dacl.defaclnamespace = nsp.oid)
+WHERE
+  NOT ((nspname = 'pg_catalog' AND EXISTS
+    (SELECT 1 FROM pg_class WHERE relname = 'pg_class' AND relnamespace = nsp.oid LIMIT 1)) OR
+  (nspname = 'pgagent' AND EXISTS
+    (SELECT 1 FROM pg_class WHERE relname = 'pga_job' AND relnamespace = nsp.oid LIMIT 1)) OR
+  (nspname = 'information_schema' AND EXISTS
+    (SELECT 1 FROM pg_class WHERE relname = 'tables' AND relnamespace = nsp.oid LIMIT 1)) OR
+  (nspname LIKE '_%' AND EXISTS
+      (SELECT 1 FROM pg_proc WHERE proname='slonyversion' AND pronamespace = nsp.oid LIMIT 1))
+  )AND
+  nspname NOT LIKE E'pg\\temp\\%' AND
+  nspname NOT LIKE E'pg\\toast_temp\\%' AND
+  -- ADDED: Because We need to omit system schema except the one on which we are trying to  create collation
+  ( nsp.oid = {{ scid }} OR nspname NOT LIKE E'pg\\_%' )
+ORDER BY nspname;
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_types.sql
new file mode 100644
index 0000000..e473056
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_types.sql
@@ -0,0 +1,7 @@
+SELECT * FROM (SELECT format_type(t.oid,NULL) AS typname, CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname,
+       (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup
+  FROM pg_type t
+  JOIN pg_namespace nsp ON typnamespace=nsp.oid
+ WHERE (NOT (typname = 'unknown' AND nspname = 'pg_catalog')) AND typisdefined AND typtype IN ('b', 'c', 'e', 'r')AND NOT EXISTS
+ (select 1 from pg_class where relnamespace=typnamespace and relname = typname and relkind != 'c') AND (typname not like '_%' OR NOT EXISTS (select 1 from pg_class where relnamespace=typnamespace and relname = substring(typname from 2)::name and relkind != 'c')) 
+  ) AS dummy ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/properties.sql
new file mode 100644
index 0000000..901d053
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/properties.sql
@@ -0,0 +1,20 @@
+SELECT d.oid, d.typname as name, d.typbasetype, format_type(b.oid,NULL) as basetype, pg_get_userbyid(d.typowner) as owner,
+  c.oid AS colloid,
+  CASE WHEN length(cn.nspname) > 0 AND length(c.collname) > 0 THEN
+  concat(cn.nspname, '."', c.collname,'"')
+  ELSE '' END AS collname,
+  d.typlen, d.typtypmod, d.typnotnull, d.typdefault, d.typndims, d.typdelim, bn.nspname as basensp,
+  description, (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname=d.typname) > 1 AS domisdup,
+  (SELECT COUNT(1) FROM pg_type t3 WHERE t3.typname=b.typname) > 1 AS baseisdup,
+  (SELECT array_agg(provider || '=' || label) FROM pg_shseclabel sl1 WHERE sl1.objoid=d.oid) AS seclabels
+FROM pg_type d
+  JOIN pg_type b ON b.oid = d.typbasetype
+  JOIN pg_namespace bn ON bn.oid=d.typnamespace
+  LEFT OUTER JOIN pg_description des ON (des.objoid=d.oid AND des.classoid='pg_type'::regclass)
+  LEFT OUTER JOIN pg_collation c ON d.typcollation=c.oid
+  LEFT OUTER JOIN pg_namespace cn ON c.collnamespace=cn.oid
+WHERE d.typnamespace = {{scid}}::oid
+{% if doid %}
+  AND d.oid={{doid}}::int
+{% endif %}
+ORDER BY d.typname
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/update.sql
new file mode 100644
index 0000000..eb9c08f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/update.sql
@@ -0,0 +1,61 @@
+{% if data %}
+  {% set name = o_data.name %}
+  {% if data.name %}
+    {% if data.name != o_data.name %}
+      ALTER DOMAIN {{ conn|qtIdent(o_data.basensp, o_data.name) }}
+        RENAME TO {{ conn|qtIdent(data.name) }};
+        {% set name = data.name %}
+    {% endif %}
+  {% endif %}
+
+  {% if not data.typnotnull %}
+    ALTER DOMAIN {{ conn|qtIdent(o_data.basensp, name) }}
+      DROP NOT NULL;
+  {% endif %}
+
+  {% if data.typdefault %}
+    ALTER DOMAIN {{ conn|qtIdent(o_data.basensp, name) }}
+      SET DEFAULT {{ data.typdefault|qtLiteral }};
+  {% endif %}
+
+  {% if data.owner %}
+    ALTER DOMAIN {{ conn|qtIdent(o_data.basensp, name) }}
+      OWNER TO {{ data.owner }};
+  {% endif %}
+
+  {% if data.constraints %}
+    {% for c in data.constraints.added %}
+        ALTER DOMAIN {{ conn|qtIdent(o_data.basensp, name) }}
+        ADD CONSTRAINT {{ c.conname }} CHECK ({{ c.consrc }} )
+        {% if c.convalidated %} NOT VALID {% endif %} {% if c.connoinherit %} NO INHERIT {% endif %};
+    {% endfor %}
+  {% endif %}
+
+  {% set seclabels = data.seclabels %}
+  {% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
+    {% for r in seclabels.deleted %}
+    {{ SECLABLE.DROP(conn, 'DOMAIN', conn|qtIdent(o_data.basensp, name), r.provider) }}
+    {% endfor %}
+  {% endif %}
+  {% if 'added' in seclabels and seclabels.added|length > 0 %}
+    {% for r in seclabels.added %}
+    {{ SECLABLE.APPLY(conn, 'DOMAIN', conn|qtIdent(o_data.basensp, name), r.provider, r.label) }}
+    {% endfor %}
+  {% endif %}
+  {% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+    {% for r in seclabels.changed %}
+    {{ SECLABLE.APPLY(conn, 'DOMAIN', conn|qtIdent(o_data.basensp, name), r.provider, r.label) }}
+    {% endfor %}
+  {% endif %}
+
+  {% if data.description %}
+    COMMENT ON DOMAIN {{ conn|qtIdent(o_data.basensp, name) }}
+    IS {{ data.description|qtLiteral }};
+  {% endif %}
+
+  {% if data.basensp %}
+    ALTER DOMAIN {{ conn|qtIdent(o_data.basensp, name) }}
+      SET SCHEMA {{ conn|qtIdent(data.basensp) }};
+  {% endif %}
+
+{% endif %}
diff --git a/web/pgadmin/static/js/backform.pgadmin.js b/web/pgadmin/static/js/backform.pgadmin.js
index 8837fa9..67a8705 100644
--- a/web/pgadmin/static/js/backform.pgadmin.js
+++ b/web/pgadmin/static/js/backform.pgadmin.js
@@ -998,9 +998,9 @@
       }
 
       // Insert Edit Cell into Grid
-      if (data.disabled == false && data.canEdit) {
+      if (data.disabled == false && data.canEdit || data.canAdd) {
           var editCell = Backgrid.Extension.ObjectCell.extend({
-            schema: gridSchema.schema
+            schema: gridSchema.schema, editable: false
           });
 
           gridSchema.columns.unshift({
@@ -1043,6 +1043,7 @@
         e.preventDefault();
         grid.insertRow({});
         var newRow = $(grid.body.rows[collection.length - 1].$el);
+        console.log(newRow);
         newRow.attr("class", "new").click(function(e) {
           $(this).attr("class", "");
         });
-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers

Reply via email to