Hi Neel,
Please find updated patch.
Thanks,
Khushboo
On Wed, Jan 20, 2016 at 12:50 PM, Neel Patel <[email protected]>
wrote:
> Hi Khushboo,
>
> While applying the patch file, we are getting below warnings.
>
> #########################################
> domains (1).patch:1340: trailing whitespace.
> oid: undefined,
> domains (1).patch:1483: trailing whitespace.
> (nspname = 'pg_catalog' AND EXISTS
> domains (1).patch:1487: trailing whitespace.
> OR (nspname = 'information_schema' AND EXISTS
> domains (1).patch:1489: trailing whitespace.
> OR (nspname LIKE '_%' AND EXISTS
> domains (1).patch:1642: trailing whitespace.
> (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'))
> warning: squelched 4 whitespace errors
> warning: 9 lines add whitespace errors.
> #########################################
>
> Can you please remove the whitespace and regenerate the patch ?
>
> Thanks,
> Neel Patel
>
> On Wed, Jan 20, 2016 at 12:37 PM, Khushboo Vashi <
> [email protected]> wrote:
>
>> 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
>>>
>>
>>
>>
>> --
>> Sent via pgadmin-hackers mailing list ([email protected])
>> To make changes to your subscription:
>> http://www.postgresql.org/mailpref/pgadmin-hackers
>>
>>
>
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..aa1dd7c
--- /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..64f0941
--- /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