public inbox for [email protected]
help / color / mirror / Atom feedFrom: Khushboo Vashi <[email protected]>
To: Neel Patel <[email protected]>
Cc: pgadmin-hackers <[email protected]>
Subject: Re: pgAdmin4 PATCH: Domain Module
Date: Tue, 23 Feb 2016 12:37:15 +0530
Message-ID: <CAFOhELePQ_m8zmbORLmO3PUY5yTA5o_9suQKk0Tox8A7Fb8ovw@mail.gmail.com> (raw)
In-Reply-To: <CACCA4P1uFijfEV6vvETXX=qjafhGZsOacdi7Og+7edaBb4erxA@mail.gmail.com>
References: <CAFOhELf-n8mM4h8RZuqxUs-Z+f97N6Ux5KT6aoAdWFiHVVURyw@mail.gmail.com>
<CAFOhELf-QTMAgNkTT8AsRwJ38Jn_1BSFRV_G5ZmcHnrKmPsTog@mail.gmail.com>
<CACCA4P1caumXOrpEXrrETMuNGj3G3ctY-PN9=V6GUPF=dTBnWg@mail.gmail.com>
<CAFOhELdgb566u+4XXOOP4pDCF4GGzK8JZzLrrTuPt=OprsqG5Q@mail.gmail.com>
<CACCA4P06PrJ2-VodT133sheH1i+7zc_M_y_me6KfRHkLqrQ7gg@mail.gmail.com>
<CAFOhELc1OAz3BDWkKC0e0xA8sPBKiO-4vWJQ7ipMYmKC-C6YzA@mail.gmail.com>
<CACCA4P1uFijfEV6vvETXX=qjafhGZsOacdi7Og+7edaBb4erxA@mail.gmail.com>
List-Unsubscribe: <mailto:[email protected]?body=unsub%20pgadmin-hackers>
Hi,
Please find attached Revised patch for the Domain module and also my
comments inline as below.
Thanks,
Khushboo
On Wed, Feb 3, 2016 at 4:22 PM, Neel Patel <[email protected]>
wrote:
> Hi Khushboo,
>
> Please find below review comments.
>
> - Reverse engineering SQL generation is not implemented for domain node.
>
Done
> - "Length" and "Precision" fields should be enabled/disabled based on the
> selection of "Base Type" value.
>
This implementation is dependent on the 'Type' module. Once that will be
done, I will merge my code.
> - Query is not getting generated properly. Some of the parameters are not
> reflected in query. As we have provided Length and Precision value in
> below numeric base type. Also do proper indentation in generated query.
>
> * Wrong Query :- *
> CREATE DOMAIN my_schema.test_123
> AS "numeric"
> DEFAULT 5
> ;
>
> * Correct Query :- *
> CREATE DOMAIN my_schema.test_123
> AS numeric(22,4)
> DEFAULT 5
> NOT NULL;
>
> Done
> - After creation of new domain with base type "aclitem" , wrong "Length"
> field value is getting displayed.
>
Done
> - We are getting error saying "*TypeError: the JSON object must be str,
> not 'dict*'" when we add constraint w
>
ith "NOT VALID" and NO INHERIT.
>
Done
> - We should add property "System Domain?" when we select any domain node.
>
Done
> - We think for creation of Security Label, we should include the schema
> name along with domain name.
> *Wrong Query :- *
> SECURITY LABEL FOR pv_label ON DOMAIN test_123 IS 'label_val';
> Correct Query :-
> SECURITY LABEL FOR pv_label ON DOMAIN <schema_name>.test_123 IS
> 'label_val';
>
>
> Done
> Let us know in case of any issues.
>
> Thanks,
> Neel Patel
>
> On Tue, Feb 2, 2016 at 3:51 PM, Khushboo Vashi <
> [email protected]> wrote:
>
>> Hi Neel,
>>
>> Thanks for reviewing my patch.
>>
>> I have modified the code as per your suggestions and also fixed some of
>> the issues got while doing unit testing.
>> Please find attached patch for the same.
>>
>>
>> Thanks,
>> Khushboo
>>
>>
>>
>> On Wed, Jan 20, 2016 at 10:56 PM, Neel Patel <[email protected]
>> > wrote:
>>
>>> Hi Khushboo,
>>>
>>> Please find below review comments.
>>>
>>> - While creating new Domain and clicking on SQL tab, python side we are
>>> getting error saying "*TypeError: 'bool' object is not callable".*
>>> We are not able to create any domain. Fix this issue so that we can
>>> test other functionality.
>>> - Implement the reverse engineering SQL generation for the domain node.
>>> - As per the checklist, remove the "Use Slony" from Constraints tab, as
>>> it is not required.
>>> - No need to pass "*qtIdent=self.qtIdent*" as function argument in
>>> "create" and "getSQL" function in domains/__init__.py
>>> - In "Security" tab , provider and security label fields are not
>>> editable.
>>> - In PG version 9.1, when we update the existing domain name then "ALTER
>>> DOMAIN" is not supported.
>>> Currently there is no checking for the PG version 9.1 and 9.2_plus. It
>>> will fail when we connect to database 9.1
>>>
>>> e.g.
>>> For PG version 9.1 - Update command should be as below.
>>> ALTER TYPE xyz RENAME TO abc;
>>> For PG version 9.2 onwards - Update command should be as below.
>>> ALTER DOMAIN xyz RENAME TO abc;
>>>
>>> - Some of the SQL file, qtIdent is not used. Please check all the
>>> related SQL files.
>>> e.g. - In update.sql file "data.owner" should be
>>> "conn|qtIdent(data.owner)"
>>>
>>> {% if data.owner %}
>>> ALTER DOMAIN {{ conn|qtIdent(o_data.basensp, name) }}
>>> OWNER TO {{ data.owner }};
>>> {% endif %}
>>>
>>> Let us know for any issues.
>>>
>>> Thanks,
>>> Neel Patel
>>>
>>> On Wed, Jan 20, 2016 at 2:50 PM, Khushboo Vashi <
>>> [email protected]> wrote:
>>>
>>>> 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
>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>
--
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers
Attachments:
[text/x-patch] Domains_ver_2.patch (110.6K, 3-Domains_ver_2.patch)
download | inline diff:
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..205b591
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/__init__.py
@@ -0,0 +1,805 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+"""The Domain Module."""
+
+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):
+ """
+ class DomainModule(CollectionNodeModule):
+
+ This class represents The Domain Module.
+
+ Methods:
+ -------
+ * __init__(*args, **kwargs)
+ - Initialize the Domain Module.
+
+ * get_nodes(gid, sid, did, scid)
+ - Generate the domain collection node.
+
+ * script_load()
+ - Load the module script for domain, when schema node is
+ initialized.
+ """
+
+ NODE_TYPE = 'domain'
+ COLLECTION_LABEL = gettext("Domains")
+
+ def __init__(self, *args, **kwargs):
+ super(DomainModule, self).__init__(*args, **kwargs)
+ self.min_ver = None
+ self.max_ver = None
+
+ def get_nodes(self, gid, sid, did, scid):
+ """
+ Generate the domain collection node.
+ """
+ yield self.generate_browser_collection_node(scid)
+
+ @property
+ def script_load(self):
+ """
+ Load the module script for domain, when schema node is
+ initialized.
+ """
+ return schemas.SchemaModule.NODE_TYPE
+
+
+blueprint = DomainModule(__name__)
+
+
+class DomainView(PGChildNodeView):
+ """
+ class DomainView
+
+ This class inherits PGChildNodeView to get the different routes for
+ the module.
+
+ The class is responsible to Create, Read, Update and Delete operations for
+ the Domain.
+
+ Methods:
+ -------
+ * validate_request(f):
+ - Works as a decorator.
+ Validating request on the request of create, update and modified SQL.
+
+ * module_js():
+ - Overrides this property to define javascript for Domain node.
+
+ * check_precondition(f):
+ - Works as a decorator.
+ - Checks database connection status.
+ - Attach connection object and template path.
+
+ * list(gid, sid, did, scid, doid):
+ - List the Domains.
+
+ * nodes(gid, sid, did, scid):
+ - Returns all the Domains to generate Nodes in the browser.
+
+ * properties(gid, sid, did, scid, doid):
+ - Returns the Domain properties.
+
+ * get_schemas(gid, sid, did, scid, doid=None):
+ - Returns Schemas for the particular database.
+
+ * get_collations(gid, sid, did, scid, doid=None):
+ - Returns Collations.
+
+ * get_types(gid, sid, did, scid, doid=None):
+ - Returns Data Types.
+
+ * create(gid, sid, did, scid):
+ - Creates a new Domain object.
+
+ * update(gid, sid, did, scid, doid):
+ - Updates the Domain object.
+
+ * delete(gid, sid, did, scid, doid):
+ - Drops the Domain object.
+
+ * sql(gid, sid, did, scid, doid=None):
+ - Returns the SQL for the Domain object.
+
+ * msql(gid, sid, did, scid, doid=None):
+ - Returns the modified SQL.
+
+ * get_sql(gid, sid, data, scid, doid=None):
+ - Generates the SQL statements to create/update the Domain object.
+
+ * dependents(gid, sid, did, scid, doid):
+ - Returns the dependents for the Domain object.
+
+ * dependencies(gid, sid, did, scid, doid):
+ - Returns the dependencies for the Domain object.
+ """
+
+ 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 validate_request(f):
+ """
+ Works as a decorator.
+ Validating request on the request of create, update and modified SQL.
+
+ Required Args:
+ name: Name of the Domain
+ owner: Domain Owner
+ basensp: Schema Name
+ basttype: Data Type of the Domain
+
+ Above both the arguments will not be validated in the update action.
+ """
+
+ @wraps(f)
+ def wrap(self, **kwargs):
+
+ data = {}
+ if request.data:
+ req = json.loads(request.data)
+ else:
+ req = request.args or request.form
+
+ if 'doid' not in kwargs:
+ required_args = [
+ 'name',
+ 'owner',
+ 'basensp',
+ 'basetype'
+ ]
+
+ for arg in required_args:
+ if arg not in req or req[arg] == '':
+ return make_json_response(
+ status=410,
+ success=0,
+ errormsg=gettext(
+ "Couldn't find the required parameter \
+ (%s)." % arg
+ )
+ )
+
+ try:
+ list_params = []
+ if request.method == 'GET':
+ list_params = ['constraints', 'seclabels']
+
+ for key in req:
+ if key in list_params and req[key] != '' \
+ and req[key] is not None:
+ # Coverts string into python list as expected.
+ data[key] = json.loads(req[key])
+ elif key == 'typnotnull':
+ data[key] = True if req[key] == 'true' or req[key] is\
+ True else\
+ (False if req[key] == 'false' or req[key] is
+ False else '')
+ else:
+ data[key] = req[key]
+
+ except Exception as e:
+ return internal_server_error(errormsg=str(e))
+
+ self.request = data
+ return f(self, **kwargs)
+
+ return wrap
+
+ def module_js(self):
+ """
+ Overrides this property to define javascript for Domain node.
+ """
+ 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):
+ 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 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 >= 90200:
+ self.template_path = 'domains/sql/9.2_plus'
+ elif 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.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ """
+
+ SQL = render_template("/".join([self.template_path, 'node.sql']),
+ scid=scid)
+ status, res = self.conn.execute_dict(SQL)
+
+ if not status:
+ return internal_server_error(errormsg=res)
+ return ajax_response(
+ response=res['rows'],
+ status=200
+ )
+
+ @check_precondition
+ def nodes(self, gid, sid, did, scid):
+ """
+ Returns all the Domains to generate Nodes in the browser.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ """
+
+ res = []
+ SQL = render_template("/".join([self.template_path, 'node.sql']),
+ scid=scid)
+ status, rset = self.conn.execute_2darray(SQL)
+ if not status:
+ return internal_server_error(errormsg=rset)
+
+ for row in rset['rows']:
+ res.append(
+ self.blueprint.generate_browser_node(
+ row['oid'],
+ scid,
+ row['name'],
+ icon="icon-domain"
+ ))
+
+ return make_json_response(
+ data=res,
+ status=200
+ )
+
+ @check_precondition
+ def properties(self, gid, sid, did, scid, doid):
+ """
+ Returns the Domain properties.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ """
+
+ 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]
+
+ # The Length and the precision of the Datatype should be separate.
+ # The Format we getting from database is: numeric(1,1)
+ # So, we need to separate Length: 1, Precision: 1
+ if data['fulltype'] != '' and data['fulltype'].find("(") > 0:
+ substr = data['fulltype'][data['fulltype'].find("(") + 1:len(
+ data['fulltype']) - 1]
+ typlen = substr.split(",")
+ if len(typlen) > 1:
+ data['typlen'] = typlen[0]
+ data['precision'] = typlen[1]
+ else:
+ data['typlen'] = typlen
+ data['precision'] = ''
+
+ # 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']
+
+ # Set System Domain Status
+ data['sysdomain'] = False
+ if doid <= self.manager.db_info[did]['datlastsysoid']:
+ data['sysdomain'] = True
+
+ return ajax_response(
+ response=data,
+ status=200
+ )
+
+ @check_precondition
+ def get_schemas(self, gid, sid, did, scid, doid=None):
+ """
+ Returns Schemas for the particular database.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ """
+
+ 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.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ """
+
+ 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.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ """
+
+ # 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
+ @validate_request
+ def create(self, gid, sid, did, scid):
+ """
+ Creates a new Domain object.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+
+ Required Args:
+ name: Domain Name
+ owner: Owner Name
+ basensp: Schema Name
+ basetype: Domain Base Type
+
+ Returns:
+ Domain object in json format.
+ """
+
+ data = self.request
+ try:
+ SQL = render_template("/".join([self.template_path, 'create.sql']),
+ data=data)
+ 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,
+ scid,
+ 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):
+ """
+ Drops the Domain object.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ """
+
+ 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
+ @validate_request
+ def update(self, gid, sid, did, scid, doid):
+ """
+ Updates the Domain object.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ """
+
+ status, SQL = self.get_sql(gid, sid, self.request, scid, doid)
+
+ if not status:
+ return internal_server_error(errormsg=SQL)
+
+ try:
+ if SQL:
+ 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 sql(self, gid, sid, did, scid, doid=None):
+ """
+ Returns the SQL for the Domain object.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ """
+
+ 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)
+ 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']
+
+ # Toggle Validate and inherit options for 'CREATE Query'
+ for c in data['constraints']:
+ c['convalidated'] = False if c['convalidated'] else True
+ c['connoinherit'] = False if c['connoinherit'] else True
+
+ SQL = render_template("/".join([self.template_path,
+ 'create.sql']), data=data)
+
+ return ajax_response(response=SQL)
+
+ @check_precondition
+ @validate_request
+ def msql(self, gid, sid, did, scid, doid=None):
+ """
+ Returns the modified SQL.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+
+ Required Args:
+ name: Domain Name
+ owner: Owner Name
+ basensp: Schema Name
+ basetype: Domain Base Type
+
+ Returns:
+ SQL statements to create/update the Domain.
+ """
+
+ status, SQL = self.get_sql(gid, sid, self.request, scid, doid)
+
+ if SQL:
+ return make_json_response(
+ data=SQL,
+ status=200
+ )
+ else:
+ return SQL
+
+ def get_sql(self, gid, sid, data, scid, doid=None):
+ """
+ Generates the SQL statements to create/update the Domain.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ """
+
+ 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)
+ else:
+ SQL = render_template("/".join([self.template_path,
+ 'create.sql']),
+ data=data)
+ return True, SQL
+
+ except Exception as e:
+ return False, e
+
+ @check_precondition
+ def dependents(self, gid, sid, did, scid, doid):
+ """
+ This function get the dependents and return ajax response
+ for the Domain node.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ """
+ dependents_result = self.get_dependents(self.conn, doid)
+ return ajax_response(
+ response=dependents_result,
+ status=200
+ )
+
+ @check_precondition
+ def dependencies(self, gid, sid, did, scid, doid):
+ """
+ This function get the dependencies and return ajax response
+ for the Domain node.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ """
+ dependencies_result = self.get_dependencies(self.conn, doid)
+ return ajax_response(
+ response=dependencies_result,
+ status=200
+ )
+
+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..370e585
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/__init__.py
@@ -0,0 +1,640 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+"""The Domain Constraint Module."""
+
+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.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):
+ """
+ class DomainConstraintModule(CollectionNodeModule):
+
+ This class represents The Domain Constraint Module.
+
+ Methods:
+ -------
+ * __init__(*args, **kwargs)
+ - Initialize the Domain Constraint Module.
+
+ * get_nodes(gid, sid, did, scid)
+ - Generate the Domain Constraint collection node.
+
+ * node_inode(gid, sid, did, scid)
+ - Override this property to make the Domain Constraint node as leaf node.
+
+ * script_load()
+ - Load the module script for the Domain Constraint, when any of the
+ Domain node is initialized.
+ """
+ NODE_TYPE = 'domain-constraints'
+ COLLECTION_LABEL = gettext("Domain Constraints")
+
+ def __init__(self, *args, **kwargs):
+ super(DomainConstraintModule, self).__init__(*args, **kwargs)
+ self.min_ver = None
+ self.max_ver = None
+
+ def get_nodes(self, gid, sid, did, scid, doid):
+ """
+ Generate the Domain Constraint 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 the Domain Constraint, when any of the
+ Domain node is initialized.
+ """
+ return domains.DomainModule.NODE_TYPE
+
+
+blueprint = DomainConstraintModule(__name__)
+
+
+class DomainConstraintView(PGChildNodeView):
+ """
+ class DomainConstraintView(PGChildNodeView):
+
+ This class inherits PGChildNodeView to get the different routes for
+ the module.
+
+ The class is responsible to Create, Read, Update and Delete operations for
+ the Domain Constraint.
+
+ Methods:
+ -------
+
+ * module_js():
+ - Overrides this property to define javascript for Domain Constraint node.
+
+ * check_precondition(f):
+ - Works as a decorator.
+ - Checks database connection status.
+ - Attach connection object and template path.
+
+ * list(gid, sid, did, scid, doid):
+ - List the Domain Constraints.
+
+ * nodes(gid, sid, did, scid):
+ - Returns all the Domain Constraints to generate Nodes in the browser.
+
+ * properties(gid, sid, did, scid, doid):
+ - Returns the Domain Constraint properties.
+
+ * create(gid, sid, did, scid):
+ - Creates a new Domain Constraint object.
+
+ * update(gid, sid, did, scid, doid):
+ - Updates the Domain Constraint object.
+
+ * delete(gid, sid, did, scid, doid):
+ - Drops the Domain Constraint object.
+
+ * sql(gid, sid, did, scid, doid=None):
+ - Returns the SQL for the Domain Constraint object.
+
+ * msql(gid, sid, did, scid, doid=None):
+ - Returns the modified SQL.
+
+ * get_sql(gid, sid, data, scid, doid=None):
+ - Generates the SQL statements to create/update the Domain Constraint.
+ object.
+
+ * dependents(gid, sid, did, scid, doid, coid):
+ - Returns the dependents for the Domain Constraint object.
+
+ * dependencies(gid, sid, did, scid, doid, coid):
+ - Returns the dependencies for the Domain Constraint object.
+ """
+ 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):
+ """
+ Overrides this property to define javascript for Domain Constraint node.
+ """
+ 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):
+ 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
+
+ # we will set template path for sql scripts
+ if ver >= 90200:
+ self.template_path = 'domain-constraints/sql/9.2_plus'
+ elif 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.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ """
+ 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.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ """
+ 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'],
+ doid,
+ row['name'],
+ 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.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ coid: Domain Constraint Id
+ """
+
+ 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 a new Domain Constraint object.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+
+ Required Args:
+ name: Constraints Name
+ consrc: Constraints Check
+
+ Returns:
+ Domain Constraint object in json format.
+ """
+
+ data = request.form if request.form else \
+ json.loads(request.data.decode())
+ required_args = [
+ 'name',
+ '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=res)
+
+ domain, schema = res['rows'][0]
+
+ SQL = render_template("/".join([self.template_path,
+ 'create.sql']),
+ data=data, domain=domain, schema=schema)
+ 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['name'])
+ 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,
+ doid,
+ data['name'],
+ icon="icon-domain-constraints"
+ )
+ )
+ except Exception as e:
+ return internal_server_error(errormsg=str(e))
+
+ @check_precondition
+ def delete(self, gid, sid, did, scid, doid, coid):
+ """
+ Drops the Domain Constraint object.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ coid: Domain Constraint Id
+ """
+ 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 Constraint 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):
+ """
+ Updates the Domain Constraint object.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ coid: Domain Constraint Id
+ """
+ data = request.form if request.form else \
+ json.loads(request.data.decode())
+
+ status, SQL = self.get_sql(gid, sid, data, scid, doid, coid)
+
+ try:
+ if SQL and status:
+ status, res = self.conn.execute_scalar(SQL)
+ if not status:
+ return internal_server_error(errormsg=res)
+
+ return make_json_response(
+ success=1,
+ info="Domain Constraint updated",
+ data={
+ 'id': coid,
+ 'doid': doid,
+ 'scid': scid,
+ 'sid': sid,
+ 'gid': gid,
+ 'did': did
+ }
+ )
+ else:
+ return make_json_response(
+ success=1,
+ info="Nothing to update",
+ data={
+ 'id': coid,
+ 'doid': doid,
+ 'scid': scid,
+ 'sid': sid,
+ 'gid': gid,
+ 'did': did
+ }
+ )
+
+ except Exception as e:
+ return internal_server_error(errormsg=str(e))
+
+ @check_precondition
+ def sql(self, gid, sid, did, scid, doid, coid=None):
+ """
+ Returns the SQL for the Domain Constraint object.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ coid: Domain Constraint Id
+ """
+
+ # 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,
+ '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]
+ data['convalidated'] = False if data['convalidated'] else True
+ data['connoinherit'] = False if data['connoinherit'] else True
+
+ SQL = render_template("/".join([self.template_path,
+ 'create.sql']),
+ data=data, domain=domain, schema=schema)
+
+ return ajax_response(response=SQL)
+
+ @check_precondition
+ def msql(self, gid, sid, did, scid, doid, coid=None):
+ """
+ Returns the modified SQL.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ coid: Domain Constraint Id
+
+ Required Args:
+ name: Constraints Name
+ consrc: Constraints Check
+
+ Returns:
+ Domain Constraint object in json format.
+ """
+ data = request.args
+
+ if coid is None:
+ required_args = [
+ 'name',
+ '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
+ )
+ )
+ status, SQL = self.get_sql(gid, sid, data, scid, doid, coid)
+ if status and SQL:
+ return make_json_response(
+ data=SQL,
+ status=200
+ )
+ else:
+ return SQL
+
+ def get_sql(self, gid, sid, data, scid, doid, coid=None):
+ """
+ Generates the SQL statements to create/update the Domain Constraint.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ coid: Domain Constraint Id
+ """
+ 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 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
+ )
+ else:
+ SQL = render_template("/".join([self.template_path,
+ 'get_domain.sql']),
+ doid=doid)
+ status, res = self.conn.execute_2darray(SQL)
+
+ if not status:
+ return False, 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)
+ return True, SQL
+ except Exception as e:
+ return False, internal_server_error(errormsg=str(e))
+
+ @check_precondition
+ def dependents(self, gid, sid, did, scid, doid, coid):
+ """
+ This function get the dependents and return ajax response
+ for the Domain Constraint node.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ coid: Domain Constraint Id
+ """
+ dependents_result = self.get_dependents(self.conn, coid)
+ return ajax_response(
+ response=dependents_result,
+ status=200
+ )
+
+ @check_precondition
+ def dependencies(self, gid, sid, did, scid, doid, coid):
+ """
+ This function get the dependencies and return ajax response
+ for the Domain Constraint node.
+
+ Args:
+ gid: Server Group Id
+ sid: Server Id
+ did: Database Id
+ scid: Schema Id
+ doid: Domain Id
+ coid: Domain Constraint Id
+ """
+ dependencies_result = self.get_dependencies(self.conn, coid)
+ return ajax_response(
+ response=dependencies_result,
+ status=200
+ )
+
+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..57b6612
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/css/domain-constraints.css
@@ -0,0 +1,8 @@
+.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..d9e23a8
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/js/domain-constraints.js
@@ -0,0 +1,129 @@
+// Domain Constraint Module: Collection and Node
+define(
+ ['jquery', 'underscore', 'underscore.string', 'pgadmin', 'pgadmin.browser', 'alertify', 'pgadmin.browser.collection'],
+function($, _, S, pgAdmin, pgBrowser, alertify) {
+
+ // Define Domain Constraint Collection Node
+ if (!pgBrowser.Nodes['coll-domain-constraints']) {
+ var domain_constraints = pgAdmin.Browser.Nodes['coll-domain-constraints'] =
+ pgAdmin.Browser.Collection.extend({
+ node: 'domain-constraints',
+ label: '{{ _('Domain Constraints') }}',
+ type: 'coll-domain-constraints'
+ });
+ };
+
+ // Domain Constraint Node
+ 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,
+ hasDepends: 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: {
+ name: undefined,
+ description: undefined,
+ consrc: undefined,
+ connoinherit: undefined,
+ convalidated: undefined
+ },
+ // Domain Constraint Schema
+ schema: [{
+ id: 'name', label: '{{ _('Name') }}', type:'text', cell:'string',
+ disabled: 'isDisabled'
+ },{
+ 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: 'isDisabled'
+ },{
+ id: 'convalidated', label: "Don't Validate", type: 'switch', cell:
+ 'boolean', group: '{{ _('Definition') }}', disabled: 'isDisabled',
+ mode: ['create', 'edit']
+ },{
+ id: 'convalidated', label: '{{ _('Valid?') }}', type: 'switch', cell:
+ 'boolean', group: '{{ _('Definition') }}', disabled: 'isDisabled',
+ mode: ['properties']
+ }],
+ // Client Side Validation
+ validate: function() {
+ var err = {},
+ errmsg;
+
+ 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('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;
+
+ },
+ isDisabled: function(m){
+ if (!m.isNew()) {
+ var server = this.node_info.server;
+ if (server.version < 90200)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ }),
+ });
+
+ }
+
+ 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..22bad72
--- /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,4 @@
+{% if data and schema and domain %}
+ALTER DOMAIN {{ conn|qtIdent(schema, domain) }}
+ ADD CONSTRAINT {{ conn|qtIdent(data.name) }} CHECK ({{ data.consrc }});
+{% 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..260c3c0
--- /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 {{ conn|qtIdent(data.name) }};
+{% endif %}
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..1040c0e
--- /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,8 @@
+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..f59e08c
--- /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,7 @@
+SELECT
+ oid, conname as name
+FROM
+ pg_constraint
+WHERE
+ contypid = {{doid}}::oid
+ AND conname={{ name|qtLiteral }};
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..95b7310
--- /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,30 @@
+SELECT
+ 'TABLE' AS objectkind, c.oid, conname as name, relname, nspname, description,
+ pg_get_expr(conbin, conrelid, true) as consrc
+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 as name, typname as relname, nspname, description,
+ regexp_replace(pg_get_constraintdef(c.oid, true), E'CHECK \\((.*)\\).*', E'\\1') as consrc
+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..d574430
--- /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.name %}
+ALTER DOMAIN {{ conn|qtIdent(o_data.nspname, o_data.relname) }}
+ RENAME CONSTRAINT {{ conn|qtIdent(o_data.name) }} TO {{ conn|qtIdent(data.name) }};
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.2_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.2_plus/create.sql
new file mode 100644
index 0000000..c50e486
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.2_plus/create.sql
@@ -0,0 +1,8 @@
+{% if data and schema and domain %}
+ALTER DOMAIN {{ conn|qtIdent(schema, domain) }}
+ ADD CONSTRAINT {{ conn|qtIdent(data.name) }} 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.2_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.2_plus/delete.sql
new file mode 100644
index 0000000..260c3c0
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.2_plus/delete.sql
@@ -0,0 +1,4 @@
+{% if data %}
+ALTER DOMAIN {{ conn|qtIdent(data.nspname, data.relname) }}
+ DROP CONSTRAINT {{ conn|qtIdent(data.name) }};
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.2_plus/get_domain.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.2_plus/get_domain.sql
new file mode 100644
index 0000000..1040c0e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.2_plus/get_domain.sql
@@ -0,0 +1,8 @@
+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.2_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.2_plus/get_oid.sql
new file mode 100644
index 0000000..f59e08c
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.2_plus/get_oid.sql
@@ -0,0 +1,7 @@
+SELECT
+ oid, conname as name
+FROM
+ pg_constraint
+WHERE
+ contypid = {{doid}}::oid
+ AND conname={{ name|qtLiteral }};
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.2_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.2_plus/properties.sql
new file mode 100644
index 0000000..80b7ced
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.2_plus/properties.sql
@@ -0,0 +1,29 @@
+SELECT
+ 'TABLE' AS objectkind, c.oid, conname as name, 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 as name, 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.2_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.2_plus/update.sql
new file mode 100644
index 0000000..d574430
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain-constraints/templates/domain-constraints/sql/9.2_plus/update.sql
@@ -0,0 +1,4 @@
+{% if data.name %}
+ALTER DOMAIN {{ conn|qtIdent(o_data.nspname, o_data.relname) }}
+ RENAME CONSTRAINT {{ conn|qtIdent(o_data.name) }} TO {{ conn|qtIdent(data.name) }};
+{% 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..ab9e776
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/css/domains.css
@@ -0,0 +1,8 @@
+.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..e2d1b01
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/js/domains.js
@@ -0,0 +1,277 @@
+// Domain Module: Collection and Node.
+define(
+ ['jquery', 'underscore', 'underscore.string', 'pgadmin', 'pgadmin.browser', 'alertify', 'pgadmin.browser.collection'],
+function($, _, S, pgAdmin, pgBrowser, alertify) {
+
+ // Define Domain Collection Node
+ if (!pgBrowser.Nodes['coll-domain']) {
+ var domains = pgAdmin.Browser.Nodes['coll-domain'] =
+ pgAdmin.Browser.Collection.extend({
+ node: 'domain',
+ label: '{{ _('Domains') }}',
+ type: 'coll-domain',
+ columns: ['name', 'oid', 'owner', 'basensp', 'description', 'basetype',
+ 'typdefault', 'typnotnull', 'sysdomain']
+ });
+ };
+
+ // Security Model
+ 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;
+ }
+ });
+
+ // Constraint Model
+ var ConstraintsModel = pgAdmin.Browser.Node.Model.extend({
+ idAttribute: 'conname',
+ 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'
+ },{
+ id: 'consrc', label: '{{ _('Check') }}', type: 'multiline',
+ cell: 'string', group: '{{ _('Definition') }}'
+ },{
+ id: 'connoinherit', label: '{{ _('No Inherit') }}', type: 'switch',
+ cell:'boolean', group: '{{ _('Definition') }}'
+ },{
+ id: 'convalidated', label: '{{ _('Valid?') }}', type:
+ 'switch', cell: 'boolean', group: '{{ _('Definition') }}', mode:
+ ['properties']
+ },{
+ id: 'convalidated', label: "Don't Validate", type:
+ 'switch', cell: 'boolean', group: '{{ _('Definition') }}', mode:
+ ['create', 'edit']
+ }],
+ validate: function() {
+ // TODO: Add validation here
+ },
+ toJSON: Backbone.Model.prototype.toJSON
+ });
+
+ // Domain Node
+ if (!pgBrowser.Nodes['domain']) {
+ pgAdmin.Browser.Nodes['domain'] = pgBrowser.Node.extend({
+ type: 'domain',
+ label: '{{ _('Domain') }}',
+ collection_type: 'coll-domain',
+ hasSQL: true,
+ hasDepends: 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,
+ // Domain Node Model
+ 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,
+ sysdomain: undefined,
+ collname: undefined,
+ constraints: [],
+ seclabels: []
+ },
+ // Domain Schema
+ 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: 'sysdomain', label:'{{ _('System Domain?') }}', cell: 'boolean',
+ type: 'switch', group: '{{ _('Definition') }}', mode: ['properties']
+ },{
+ 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: true, canEdit: function(o) {
+ if (o instanceof Backbone.Model) {
+ if (o instanceof ConstraintsModel) {
+ return o.isNew();
+ }
+ }
+ return true;
+ }
+ },{
+ id: 'seclabels', label: '{{ _('Security Labels') }}',
+ model: SecurityModel, type: 'collection',
+ group: '{{ _('Security') }}', mode: ['edit', 'create'],
+ min_version: 90100, canAdd: true,
+ canEdit: true, canDelete: true
+ }
+ ],
+ validate: function() // Client Side Validation
+ {
+ 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;
+ },
+ isDisabled: function(m){
+ if (!m.isNew()) {
+ var server = this.node_info.server;
+ if (server.version < 90200)
+ {
+ return false;
+ }
+ }
+ 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..8f3db8e
--- /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\\%'
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..29ae115
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/create.sql
@@ -0,0 +1,36 @@
+{% import 'macros/security.macros' as SECLABLE %}
+{% if data %}
+CREATE DOMAIN {{ conn|qtIdent(data.basensp, data.name) }}
+ AS {{ conn|qtTypeIdent(data.basetype) }}{% if data.typlen %}({{data.typlen}} {% if data.precision %}, {{data.precision}}{% endif %}){% endif %}{% if data.collname %}
+
+ COLLATE {{ data.collname and data.collname != "pg_catalog.\"default\"" }}{% endif %}{% if data.typdefault %}
+
+ DEFAULT {{ data.typdefault }}{% endif %}{% if data.typnotnull %}
+
+ NOT NULL
+{% endif -%};
+
+{% if data.constraints %}
+{% for c in data.constraints %}
+{% if c.conname and c.consrc %}ALTER DOMAIN {{ conn|qtIdent(data.basensp, data.name) }}
+ ADD CONSTRAINT {{ conn|qtIdent(c.conname) }} CHECK ({{ c.consrc }});
+{% endif %}
+{% endfor %}
+{% endif %}
+
+ALTER DOMAIN {{ conn|qtIdent(data.basensp, data.name) }} OWNER TO {{ conn|qtIdent(data.owner) }};
+
+{% if data.description %}
+COMMENT ON DOMAIN {{ conn|qtIdent(data.basensp, data.name) }}
+ IS '{{ data.description }}';
+{% endif %}
+
+{% if data.seclabels %}
+{% for r in data.seclabels %}
+{% if r.security_label and r.provider %}
+{{ SECLABLE.APPLY(conn, 'DOMAIN', data.name, r.provider, r.security_label, data.basensp) }}
+{% endif %}
+{% endfor %}
+{% endif %}
+
+{% endif %}
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..4b1e49f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/delete.sql
@@ -0,0 +1,15 @@
+{% 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 %}
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..819fdbb
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_collations.sql
@@ -0,0 +1,10 @@
+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..c448844
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_constraints.sql
@@ -0,0 +1,29 @@
+SELECT
+ 'TABLE' AS objectkind, c.oid, conname, relname, nspname, description,
+ pg_get_expr(conbin, conrelid, true) as consrc
+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 cons
+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;
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..b1eb768
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_oid.sql
@@ -0,0 +1,9 @@
+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..adb3338
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_schemas.sql
@@ -0,0 +1,24 @@
+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;
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..97621b0
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/get_types.sql
@@ -0,0 +1,22 @@
+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/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/node.sql
new file mode 100644
index 0000000..7bd3e5b
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/node.sql
@@ -0,0 +1,13 @@
+SELECT
+ d.oid, d.typname as name, pg_get_userbyid(d.typowner) as owner,
+ bn.nspname as basensp
+FROM
+ pg_type d
+JOIN
+ pg_type b ON b.oid = d.typbasetype
+JOIN
+ pg_namespace bn ON bn.oid=d.typnamespace
+WHERE
+ d.typnamespace = {{scid}}::oid
+ORDER BY
+ d.typname;
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..216fafe
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/properties.sql
@@ -0,0 +1,28 @@
+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, format_type(b.oid, d.typtypmod) AS fulltype,
+ CASE WHEN length(cn.nspname) > 0 AND length(c.collname) > 0 THEN
+ concat(cn.nspname, '."', c.collname,'"')
+ ELSE '' END AS collname,
+ 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
+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..c80a20e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.1_plus/update.sql
@@ -0,0 +1,72 @@
+{% if data %}
+{% set name = o_data.name %}
+{% if data.name %}
+{% if data.name != o_data.name %}
+ALTER TYPE {{ conn|qtIdent(o_data.basensp, o_data.name) }}
+ RENAME TO {{ conn|qtIdent(data.name) }};
+{% set name = data.name %}
+{% endif %}
+{% endif %}
+
+{% if data.typnotnull and not o_data.typnotnull %}
+ALTER DOMAIN {{ conn|qtIdent(o_data.basensp, name) }}
+ SET NOT NULL;
+{% elif 'typnotnull' in data and not data.typnotnull and o_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 }};
+{% elif not data.typdefault and o_data.typdefault %}
+ALTER DOMAIN {{ conn|qtIdent(o_data.basensp, name) }}
+ DROP DEFAULT;
+{% endif %}
+{% if data.owner %}
+ALTER DOMAIN {{ conn|qtIdent(o_data.basensp, name) }}
+ OWNER TO {{ conn|qtIdent(data.owner) }};
+{% endif %}
+
+{% if data.constraints %}
+{% for c in data.constraints.deleted %}
+ALTER DOMAIN {{ conn|qtIdent(o_data.basensp, name) }}
+ DROP CONSTRAINT {{ conn|qtIdent(c.conname) }}
+{% endfor %}
+{% for c in data.constraints.added %}
+{% if c.conname and c.consrc %}
+ALTER DOMAIN {{ conn|qtIdent(o_data.basensp, name) }}
+ ADD CONSTRAINT {{ conn|qtIdent(c.conname) }} CHECK ({{ c.consrc }} );
+{% 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', name, r.provider, o_data.basensp) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+{{ SECLABLE.APPLY(conn, 'DOMAIN', name, r.provider, r
+.security_label, o_data.basensp) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+{{ SECLABLE.APPLY(conn, 'DOMAIN', name, r.provider, r.label, o_data.basensp) }}
+{% 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/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/backend_support.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/backend_support.sql
new file mode 100644
index 0000000..8f3db8e
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_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\\%'
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/create.sql
new file mode 100644
index 0000000..6dfe5e5
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/create.sql
@@ -0,0 +1,37 @@
+{% import 'macros/security.macros' as SECLABLE %}
+{% if data %}
+CREATE DOMAIN {{ conn|qtIdent(data.basensp, data.name) }}
+ AS {{ conn|qtTypeIdent(data.basetype) }}{% if data.typlen %}({{data.typlen}} {% if data.precision %}, {{data.precision}}{% endif %}){% endif %}{% if data.collname and data.collname != "pg_catalog.\"default\"" %}
+
+ COLLATE {{ data.collname }}{% endif %}{% if data.typdefault %}
+
+ DEFAULT {{ data.typdefault }}{% endif %}{% if data.typnotnull %}
+
+ NOT NULL{% endif -%};
+
+{% if data.constraints %}
+{% for c in data.constraints %}
+{% if c.conname and c.consrc %}ALTER DOMAIN {{ conn|qtIdent(data.basensp, data.name) }}
+ ADD CONSTRAINT {{ conn|qtIdent(c.conname) }} CHECK ({{ c.consrc }}){% if c.convalidated %}
+
+ NOT VALID {% endif %}{% if c.connoinherit %} NO INHERIT{% endif %};
+{% endif -%}
+{% endfor %}
+{% endif %}
+
+ALTER DOMAIN {{ conn|qtIdent(data.basensp, data.name) }} OWNER TO {{ conn|qtIdent(data.owner) }};
+
+{% if data.description %}
+COMMENT ON DOMAIN {{ conn|qtIdent(data.basensp, data.name) }}
+ IS '{{ data.description }}';
+{% endif %}
+
+{% if data.seclabels %}
+{% for r in data.seclabels %}
+{% if r.security_label and r.provider %}
+{{ SECLABLE.APPLY(conn, 'DOMAIN', data.name, r.provider, r.security_label, data.basensp) }}
+{% endif %}
+{% endfor %}
+{% endif %}
+
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/delete.sql
new file mode 100644
index 0000000..7f437ef
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/delete.sql
@@ -0,0 +1,16 @@
+{% 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 %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/get_collations.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/get_collations.sql
new file mode 100644
index 0000000..e59c17d
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/get_collations.sql
@@ -0,0 +1,10 @@
+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.2_plus/get_constraints.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/get_constraints.sql
new file mode 100644
index 0000000..01c8475
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/get_constraints.sql
@@ -0,0 +1,29 @@
+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;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/get_oid.sql
new file mode 100644
index 0000000..7f1afd1
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/get_oid.sql
@@ -0,0 +1,9 @@
+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.2_plus/get_schemas.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/get_schemas.sql
new file mode 100644
index 0000000..ec62dd6
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/get_schemas.sql
@@ -0,0 +1,24 @@
+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;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/get_types.sql
new file mode 100644
index 0000000..c4d46f7
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/get_types.sql
@@ -0,0 +1,22 @@
+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.2_plus/node.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/node.sql
new file mode 100644
index 0000000..7bd3e5b
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/node.sql
@@ -0,0 +1,13 @@
+SELECT
+ d.oid, d.typname as name, pg_get_userbyid(d.typowner) as owner,
+ bn.nspname as basensp
+FROM
+ pg_type d
+JOIN
+ pg_type b ON b.oid = d.typbasetype
+JOIN
+ pg_namespace bn ON bn.oid=d.typnamespace
+WHERE
+ d.typnamespace = {{scid}}::oid
+ORDER BY
+ d.typname;
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/properties.sql
new file mode 100644
index 0000000..5dd2d01
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/properties.sql
@@ -0,0 +1,29 @@
+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, format_type(b.oid, d.typtypmod) AS fulltype,
+ CASE WHEN length(cn.nspname) > 0 AND length(c.collname) > 0 THEN
+ concat(cn.nspname, '."', c.collname,'"')
+ ELSE '' END AS collname,
+ 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.2_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/update.sql
new file mode 100644
index 0000000..5d1987a
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/templates/domains/sql/9.2_plus/update.sql
@@ -0,0 +1,70 @@
+{% 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 data.typnotnull and not o_data.typnotnull %}
+ALTER DOMAIN {{ conn|qtIdent(o_data.basensp, name) }}
+ SET NOT NULL;
+{% elif 'typnotnull' in data and not data.typnotnull and o_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 }};
+{% elif not data.typdefault and o_data.typdefault %}
+ALTER DOMAIN {{ conn|qtIdent(o_data.basensp, name) }}
+ DROP DEFAULT;
+{% endif %}
+{% import 'macros/security.macros' as SECLABLE %}
+{% if data.owner %}
+ALTER DOMAIN {{ conn|qtIdent(o_data.basensp, name) }}
+ OWNER TO {{ conn|qtIdent(data.owner) }};
+{% endif %}
+
+{% if data.constraints %}
+{% for c in data.constraints.deleted %}
+ALTER DOMAIN {{ conn|qtIdent(o_data.basensp, name) }}
+ DROP CONSTRAINT {{ conn|qtIdent(c.conname) }}
+{% endfor %}
+{% for c in data.constraints.added %}
+ALTER DOMAIN {{ conn|qtIdent(o_data.basensp, name) }}
+ ADD CONSTRAINT {{ conn|qtIdent(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', name, r.provider, o_data.basensp) }}
+{% endfor %}
+{% endif %}
+{% if 'added' in seclabels and seclabels.added|length > 0 %}
+{% for r in seclabels.added %}
+{{ SECLABLE.APPLY(conn, 'DOMAIN', name, r.provider, r.label, o_data.basensp) }}
+{% endfor %}
+{% endif %}
+{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
+{% for r in seclabels.changed %}
+{{ SECLABLE.APPLY(conn, 'DOMAIN', name, r.provider, r.label, o_data.basensp) }}
+{% 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/browser/server_groups/servers/templates/macros/security.macros b/web/pgadmin/browser/server_groups/servers/templates/macros/security.macros
index 83fb9d2..6ce4f30 100644
--- a/web/pgadmin/browser/server_groups/servers/templates/macros/security.macros
+++ b/web/pgadmin/browser/server_groups/servers/templates/macros/security.macros
@@ -1,6 +1,17 @@
-{% macro APPLY(conn, type, name, provider, label) -%}
-SECURITY LABEL FOR {{ conn|qtIdent(provider) }} ON {{ type }} {{ conn|qtIdent(name) }} IS {{ label|qtLiteral }};
+{% macro APPLY(conn, type, name, provider, label, schema) -%}
+{% if schema %}
+{% set name = conn|qtIdent(schema, name) %}
+{% else %}
+{% set name = conn|qtIdent(name) %}
+{% endif %}
+SECURITY LABEL FOR {{ conn|qtIdent(provider) }} ON {{ type }} {{ name }} IS {{
+label|qtLiteral }};
{%- endmacro %}
-{% macro DROP(conn, type, name, provider) -%}
-SECURITY LABEL FOR {{ conn|qtIdent(provider) }} ON {{ type }} {{ conn|qtIdent(name) }} IS NULL;
+{% macro DROP(conn, type, name, provider, schema) -%}
+{% if schema %}
+{% set name = conn|qtIdent(schema, name) %}
+{% else %}
+{% set name = conn|qtIdent(name) %}
+{% endif %}
+SECURITY LABEL FOR {{ conn|qtIdent(provider) }} ON {{ type }} {{ name }} IS NULL;
{%- endmacro %}
diff --git a/web/pgadmin/browser/static/js/datamodel.js b/web/pgadmin/browser/static/js/datamodel.js
index 9385adf..61e81ed 100644
--- a/web/pgadmin/browser/static/js/datamodel.js
+++ b/web/pgadmin/browser/static/js/datamodel.js
@@ -340,7 +340,13 @@ function(_, pgAdmin, $, Backbone) {
delete res[k];
}
} else {
- res[k] = (obj && obj.toJSON());
+ if (obj && (obj instanceof Array)) {
+ res[k] = obj;
+ }
+ else
+ {
+ res[k] = obj && obj.toJSON();
+ }
}
});
return res;
diff --git a/web/pgadmin/static/js/backform.pgadmin.js b/web/pgadmin/static/js/backform.pgadmin.js
index 4346156..ae807cb 100644
--- a/web/pgadmin/static/js/backform.pgadmin.js
+++ b/web/pgadmin/static/js/backform.pgadmin.js
@@ -1058,11 +1058,13 @@
if (data.disabled == false && data.canEdit) {
var editCell = Backgrid.Extension.ObjectCell.extend({
schema: gridSchema.schema
- });
+ }),
+ canEdit = self.field.has('canEdit') &&
+ self.field.get('canEdit') || true;
gridSchema.columns.unshift({
name: "pg-backform-edit", label: "", cell : editCell,
- cell_priority: -2
+ cell_priority: -2, editable: canEdit
});
}
@@ -1101,7 +1103,7 @@
grid.insertRow({});
var newRow = $(grid.body.rows[collection.length - 1].$el);
newRow.attr("class", "new").click(function(e) {
- $(this).attr("class", "");
+ $(this).attr("class", "editable");
});
$(newRow).pgMakeVisible('backform-tab');
return false;
@@ -1528,8 +1530,15 @@
/*
* Add empty option as Select2 requires any empty '<option><option>' for
* some of its functionality to work and initialize select2 control.
+ *
+ * But - not for multiple selection.
*/
- this.$el.find("select").prepend($('<option></option>')).select2(col.select2);
+ var s = this.$el.find("select");
+ if (!col.select2.multiple) {
+ s.prepend($('<option></option>'));
+ }
+ s.select2(col.select2);
+
return this;
}
});
view thread (29+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected]
Subject: Re: pgAdmin4 PATCH: Domain Module
In-Reply-To: <CAFOhELePQ_m8zmbORLmO3PUY5yTA5o_9suQKk0Tox8A7Fb8ovw@mail.gmail.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox