Hi, Here is updated patch for sequence node. As macros are changed for security and privileges.
-- *Harshal Dhumal* *Software Engineer * EenterpriseDB <http://www.enterprisedb.com> On Tue, Feb 9, 2016 at 4:19 PM, Harshal Dhumal < harshal.dhu...@enterprisedb.com> wrote: > Hi, > > PFA patch for sequence node. > > > -- > *Harshal Dhumal* > *Software Engineer * > > > > EenterpriseDB <http://www.enterprisedb.com> >
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py new file mode 100644 index 0000000..27deb16 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py @@ -0,0 +1,537 @@ +########################################################################## +# +# pgAdmin 4 - PostgreSQL Tools +# +# Copyright (C) 2013 - 2016, The pgAdmin Development Team +# This software is released under the PostgreSQL Licence +# +########################################################################## +import json +from flask import render_template, make_response, request, jsonify +from flask.ext.babel import gettext as _ +from pgadmin.utils.ajax import make_json_response, \ + make_response as ajax_response, internal_server_error +from pgadmin.browser.utils import NodeView +from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \ + parse_priv_to_db +from pgadmin.browser.collection import CollectionNodeModule +import pgadmin.browser.server_groups.servers.databases as database +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 SequenceModule(CollectionNodeModule): + NODE_TYPE = 'sequence' + COLLECTION_LABEL = _("Sequences") + + def __init__(self, *args, **kwargs): + self.min_ver = None + self.max_ver = None + super(SequenceModule, self).__init__(*args, **kwargs) + + # Before loading this module we need to make sure that scid is catalog and schema object + # and catalog name is 'sys', 'dbo', 'information_schema' then only we load this module + def BackendSupported(self, manager, **kwargs): + """ + This function will validate schema name & scid against sequence then allow us to + make decision if we want to load this module or not for that schema + """ + if super(SequenceModule, self).BackendSupported(manager, **kwargs): + conn = manager.connection() + # If DB is not connected then return error to browser + if not conn.connected(): + return precondition_required( + _( + "Connection to the server has been lost!" + ) + ) + + ver = manager.version + # we will set template path for sql scripts + if ver >= 90100: + template_path = 'sequence/sql/9.1_plus' + else: + template_path = 'sequence/sql/pre_9.1' + + SQL = render_template("/".join([template_path, 'backend_support.sql']), scid=kwargs['scid']) + status, res = conn.execute_scalar(SQL) + # check if any errors + if not status: + return internal_server_error(errormsg=res) + # Check scid is catalog and from 'sys', 'dbo', 'information_schema', + # then False (Do not load this module), othewise True + if res is True: + return False + else: + return True + + def get_nodes(self, gid, sid, did, scid): + """ + Generate the sequence node + """ + yield self.generate_browser_collection_node(scid) + + @property + def script_load(self): + """ + Load the module script for database, when any of the database node is + initialized. + """ + return database.DatabaseModule.NODE_TYPE + +blueprint = SequenceModule(__name__) + + +class SequenceView(NodeView): + 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': 'seid'} + ] + + operations = dict({ + 'obj': [ + {'get': 'properties', 'delete': 'delete', 'put': 'update'}, + {'get': 'list', 'post': 'create'} + ], + 'delete': [{'delete': 'delete'}], + 'children': [{'get': 'children'}], + 'nodes': [{'get': 'node'}, {'get': 'nodes'}], + 'sql': [{'get': 'sql'}], + 'msql': [{'get': 'msql'}, {'get': 'msql'}], + 'stats': [{'get': 'statistics'}], + 'dependency': [{'get': 'dependencies'}], + 'dependent': [{'get': 'dependents'}], + 'module.js': [{}, {}, {'get': 'module_js'}] + }) + + def module_js(self): + """ + This property defines (if javascript) exists for this node. + Override this property for your own logic. + """ + return make_response( + render_template( + "sequence/js/sequence.js", + _=_ + ), + 200, {'Content-Type': 'application/x-javascript'} + ) + + + def check_precondition(action=None): + """ + This function will behave as a decorator which will checks + database connection before running view, it will also attaches + manager,conn & template_path properties to self + """ + def wrap(f): + @wraps(f) + def wrapped(self, *args, **kwargs): + + self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(kwargs['sid']) + if action and action in ["drop"]: + self.conn = self.manager.connection() + elif 'did' in kwargs: + self.conn = self.manager.connection(did=kwargs['did']) + else: + self.conn = self.manager.connection() + # If DB not connected then return error to browser + if not self.conn.connected(): + return precondition_required( + _( + "Connection to the server has been lost!" + ) + ) + + ver = self.manager.version + # we will set template path for sql scripts + if ver >= 90100: + self.template_path = 'sequence/sql/9.1_plus' + elif ver >= 90100: + self.template_path = 'sequence/sql/pre_9.1' + return f(self, *args, **kwargs) + return wrapped + return wrap + + @check_precondition(action='list') + def list(self, gid, sid, did, scid): + SQL = render_template("/".join([self.template_path, 'properties.sql']), scid=scid) + status, res = self.conn.execute_dict(SQL) + + if not status: + return internal_server_error(errormsg=res) + return ajax_response( + response=res['rows'], + status=200 + ) + + @check_precondition(action='nodes') + def nodes(self, gid, sid, did, scid): + res = [] + SQL = render_template("/".join([self.template_path, 'properties.sql']), scid=scid) + status, rset = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=rset) + + for row in rset['rows']: + res.append( + self.blueprint.generate_browser_node( + row['oid'], + sid, + row['name'], + icon="icon-%s" % self.node_type + )) + + return make_json_response( + data=res, + status=200 + ) + + @check_precondition(action='properties') + def properties(self, gid, sid, did, scid, seid): + SQL = render_template("/".join([self.template_path, 'properties.sql']), scid=scid, seid=seid) + status, res = self.conn.execute_dict(SQL) + + if not status: + return internal_server_error(errormsg=res) + + sec_lbls = [] + if 'securities' in res and res['securities'] is not None: + for sec in res['seclabels']: + sec = re.search(r'([^=]+)=(.*$)', sec) + sec_lbls.append({ + 'provider': sec.group(1), + 'security_label': sec.group(2) + }) + res['securities'] = sec_lbls + + for row in res['rows']: + SQL = render_template("/".join([self.template_path, 'get_def.sql']), data=row) + status, rset1 = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=rset1) + + row['current_value'] = rset1['rows'][0]['last_value'] + row['minimum'] = rset1['rows'][0]['min_value'] + row['maximum'] = rset1['rows'][0]['max_value'] + row['increment'] = rset1['rows'][0]['increment_by'] + row['cache'] = rset1['rows'][0]['cache_value'] + row['cycled'] = rset1['rows'][0]['is_cycled'] + + SQL = render_template("/".join([self.template_path, 'acl.sql']), scid=scid, seid=seid) + status, dataclres = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=res) + + for row in dataclres['rows']: + priv = parse_priv_from_db(row) + if row['deftype'] in res['rows'][0]: + res['rows'][0][row['deftype']].append(priv) + else: + res['rows'][0][row['deftype']] = [priv] + + return ajax_response( + response=res['rows'][0], + status=200 + ) + + @check_precondition(action="create") + def create(self, gid, sid, did, scid): + """Create the sequence.""" + required_args = [ + u'name', + u'schema', + u'seqowner', + ] + + data = request.form if request.form else json.loads(request.data.decode()) + + for arg in required_args: + if arg not in data: + return make_json_response( + status=400, + success=0, + errormsg=_( + "Couldn't find the required parameter (%s)." % arg + ) + ) + try: + # The SQL below will execute CREATE DDL only + SQL = render_template("/".join([self.template_path, 'create.sql']), data=data, conn=self.conn) + status, msg = self.conn.execute_scalar(SQL) + if not status: + return internal_server_error(errormsg=msg) + + if 'relacl' in data: + data['relacl'] = parse_priv_to_db(data['relacl'], 'DATABASE') + + # The SQL below will execute rest DMLs because we can not execute CREATE with any other + SQL = render_template("/".join([self.template_path, 'grant.sql']), data=data, conn=self.conn) + SQL = SQL.strip('\n').strip(' ') + if SQL and SQL != "": + status, msg = self.conn.execute_scalar(SQL) + if not status: + return internal_server_error(errormsg=msg) + + # We need oid of newly created sequence. + SQL = render_template("/".join([self.template_path, 'get_oid.sql']), name=data['name'], scid=scid) + SQL = SQL.strip('\n').strip(' ') + if SQL and SQL != "": + status, seid = self.conn.execute_scalar(SQL) + if not status: + return internal_server_error(errormsg=res) + + return jsonify( + node=self.blueprint.generate_browser_node( + seid, + scid, + data['name'], + icon="icon-%s" % self.node_type + ) + ) + + except Exception as e: + return make_json_response( + status=500, + success=0, + errormsg=str(e) + ) + + @check_precondition(action='delete') + def delete(self, gid, sid, did, scid, seid): + """ + This function will drop the object + """ + # Below will decide if it's simple drop or drop with cascade call + if self.cmd == 'delete': + # This is a cascade operation + cascade = True + else: + cascade = False + + try: + SQL = render_template("/".join([self.template_path, 'properties.sql']), scid=scid, seid=seid) + status, res = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=res) + + SQL = render_template("/".join([self.template_path, 'delete.sql']), data=res['rows'][0], 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=_("Sequence dropped"), + data={ + 'id': seid, + 'scid': scid, + 'sid': sid, + 'gid': gid, + 'did': did + } + ) + + except Exception as e: + return internal_server_error(errormsg=str(e)) + + @check_precondition(action='update') + def update(self, gid, sid, did, scid, seid): + """ + This function will update the object + """ + data = request.form if request.form else json.loads(request.data.decode()) + SQL = self.getSQL(gid, sid, did, data, scid, seid) + try: + if SQL and SQL.strip('\n') and SQL.strip(' '): + status, res = self.conn.execute_scalar(SQL) + if not status: + return internal_server_error(errormsg=res) + + return make_json_response( + success=1, + info="Sequence updated", + data={ + 'id': seid, + 'scid': scid, + 'sid': sid, + 'gid': gid, + 'did': did + } + ) + else: + return make_json_response( + success=1, + info="Nothing to update", + data={ + 'id': seid, + 'scid': scid, + 'sid': sid, + 'gid': gid, + 'did': did + } + ) + + except Exception as e: + return internal_server_error(errormsg=str(e)) + + @check_precondition(action='msql') + def msql(self, gid, sid, did, scid, seid=None): + """ + This function to return modified SQL + """ + data = {} + for k, v in request.args.items(): + try: + data[k] = json.loads(v) + except ValueError: + data[k] = v + + if seid is None: + required_args = [ + 'name', + 'schema' + ] + + for arg in required_args: + if arg not in data: + return make_json_response( + status=400, + success=0, + errormsg=_( + "Couldn't find the required parameter (%s)." % arg + ) + ) + try: + SQL = self.getSQL(gid, sid, did, data, scid, seid) + SQL = SQL.strip('\n').strip(' ') + return make_json_response( + data=SQL, + status=200 + ) + except Exception as e: + return make_json_response( + data="-- modified SQL", + status=200 + ) + + def getSQL(self, gid, sid, did, data, scid, seid=None): + """ + This function will generate sql from model data + """ + required_args = [ + u'name' + ] + + try: + if seid is not None: + SQL = render_template("/".join([self.template_path, 'properties.sql']), scid=scid, seid=seid) + status, res = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=res) + # Making copy of output for further processing + old_data = dict(res['rows'][0]) + old_data = self._formatter(old_data, scid, seid) + + # To format privileges data coming from client + for key in ['relacl']: + if key in data and data[key] is not None: + if 'added' in data[key]: + data[key]['added'] = parse_priv_to_db(data[key]['added'], 'SEQUENCE') + if 'changed' in data[key]: + data[key]['changed'] = parse_priv_to_db(data[key]['changed'], 'SEQUENCE') + if 'deleted' in data[key]: + data[key]['deleted'] = parse_priv_to_db(data[key]['deleted'], 'SEQUENCE') + + # If name is not present with in update data then copy it + # from old data + for arg in required_args: + if arg not in data: + data[arg] = old_data[arg] + SQL = render_template("/".join([self.template_path, 'update.sql']), + data=data, o_data=old_data, conn=self.conn) + else: + # To format privileges coming from client + if 'relacl' in data: + data['relacl'] = parse_priv_to_db(data['relacl'], 'SEQUENCE') + + SQL = render_template("/".join([self.template_path, 'create.sql']), data=data, conn=self.conn) + SQL += render_template("/".join([self.template_path, 'grant.sql']), data=data, conn=self.conn) + return SQL + except Exception as e: + return internal_server_error(errormsg=str(e)) + + @check_precondition(action="sql") + def sql(self, gid, sid, did, scid, seid): + """ + This function will generate sql for sql panel + """ + SQL = render_template("/".join([self.template_path, 'properties.sql']), scid=scid, seid=seid) + status, res = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=res) + + for row in res['rows']: + SQL = render_template("/".join([self.template_path, 'get_def.sql']), data=row) + status, rset1 = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=rset1) + + row['current_value'] = rset1['rows'][0]['last_value'] + row['minimum'] = rset1['rows'][0]['min_value'] + row['maximum'] = rset1['rows'][0]['max_value'] + row['increment'] = rset1['rows'][0]['increment_by'] + row['cache'] = rset1['rows'][0]['cache_value'] + row['cycled'] = rset1['rows'][0]['is_cycled'] + + result = res['rows'][0] + result = self._formatter(result, scid, seid) + SQL = self.getSQL(gid, sid, did, result, scid) + + return ajax_response(response=SQL) + + def _formatter(self, data, scid, seid): + """ + Args: + data: dict of query result + did: sequence oid + + Returns: + It will return formatted output of sequence + """ + + # Need to format security labels according to client js collection + if 'securities' in data and data['securities'] is not None: + seclabels = [] + for seclbls in data['securities']: + k, v = seclbls.split('=') + seclabels.append({'provider': k, 'security_label': v}) + + data['securities'] = seclabels + + # We need to parse & convert ACL coming from database to json format + SQL = render_template("/".join([self.template_path, 'acl.sql']), + scid=scid, seid=seid) + status, acl = self.conn.execute_dict(SQL) + if not status: + return internal_server_error(errormsg=acl) + + # We will set get privileges from acl sql so we don't need + # it from properties sql + data['relacl'] = [] + + for row in acl['rows']: + priv = parse_priv_from_db(row) + data.setdefault(row['deftype'], []).append(priv) + + return data + +SequenceView.register_node_view(blueprint) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/static/img/coll-sequence.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/static/img/coll-sequence.png new file mode 100644 index 0000000..905554d Binary files /dev/null and b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/static/img/coll-sequence.png differ diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/static/img/sequence.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/static/img/sequence.png new file mode 100644 index 0000000..1ce216c Binary files /dev/null and b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/static/img/sequence.png differ diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/js/sequence.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/js/sequence.js new file mode 100644 index 0000000..78a60f4 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/js/sequence.js @@ -0,0 +1,190 @@ +define( + ['jquery', 'underscore', 'underscore.string', 'pgadmin', 'pgadmin.browser', 'alertify', 'pgadmin.browser.collection'], +function($, _, S, pgAdmin, pgBrowser, alertify) { + + var SecurityModel = pgAdmin.Browser.Node.Model.extend({ + defaults: { + provider: undefined, + securitylabel: undefined + }, + schema: [{ + id: 'provider', label: '{{ _('Provider') }}', + type: 'text', editable: true + },{ + id: 'security_label', label: '{{ _('Security Label') }}', + type: 'text', editable: true + }], + 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; + } + }); + + if (!pgBrowser.Nodes['coll-sequence']) { + var databases = pgAdmin.Browser.Nodes['coll-sequence'] = + pgAdmin.Browser.Collection.extend({ + node: 'sequence', + label: '{{ _('Sequences') }}', + type: 'coll-sequence', + columns: ['oid', 'name', 'seqowner', 'comment'] + }); + }; + + if (!pgBrowser.Nodes['sequence']) { + pgAdmin.Browser.Nodes['sequence'] = pgBrowser.Node.extend({ + type: 'sequence', + label: '{{ _('Sequence') }}', + collection_type: 'coll-sequence', + hasSQL: true, + parent_type: ['schema'], + Init: function() { + /* Avoid mulitple registration of menus */ + if (this.initialized) + return; + + this.initialized = true; + + pgBrowser.add_menus([{ + name: 'create_sequence_on_coll', node: 'coll-sequence', module: this, + applies: ['object', 'context'], callback: 'show_obj_properties', + category: 'create', priority: 4, label: '{{ _('Sequence...') }}', + icon: 'wcTabIcon icon-sequence', data: {action: 'create', check: true}, + enable: 'canCreate' + },{ + name: 'create_sequence', node: 'sequence', module: this, + applies: ['object', 'context'], callback: 'show_obj_properties', + category: 'create', priority: 4, label: '{{ _('Sequence...') }}', + icon: 'wcTabIcon icon-sequence', data: {action: 'create', check: true}, + enable: 'canCreate' + },{ + name: 'create_sequence', node: 'sequence', module: this, + applies: ['object', 'context'], callback: 'show_obj_properties', + category: 'create', priority: 4, label: '{{ _('Sequence...') }}', + icon: 'wcTabIcon icon-sequence', data: {action: 'create', check: false}, + enable: 'canCreate' + } + ]); + + }, + canDrop: pgBrowser.Nodes['schema'].canChildDrop, + canDropCascade: pgBrowser.Nodes['schema'].canChildDrop, + model: pgAdmin.Browser.Node.Model.extend({ + defaults: { + name: undefined, + oid: undefined, + seqowner: undefined, + schema: undefined, + comment: undefined, + increment: undefined, + start: undefined, + current_value: undefined, + minimum: undefined, + maximum: undefined, + cache: undefined, + cycled: undefined, + relacl: [], + securities: [] + }, + schema: [{ + id: 'name', label: '{{ _('Name') }}', cell: 'string', + type: 'text', mode: ['properties', 'create', 'edit'] + },{ + id: 'oid', label:'{{ _('Oid') }}', cell: 'string', + type: 'text' , mode: ['properties'] + },{ + id: 'seqowner', label:'{{ _('Owner') }}', cell: 'string', + type: 'text', mode: ['properties', 'create', 'edit'], node: 'role', + control: Backform.NodeListByNameControl + },{ + id: 'schema', label:'{{ _('Schema') }}', cell: 'string', + control: 'node-list-by-name', node: 'schema', + type: 'text', mode: ['create', 'edit'], filter: function(d) { + // If schema name start with pg_* then we need to exclude them + if(d && d.label.match(/^pg_/)) + { + return false; + } + return true; + } + },{ + id: 'comment', label:'{{ _('Comment') }}', type: 'multiline', + mode: ['properties', 'create', 'edit'] + },{ + id: 'increment', label: '{{ _('Increment') }}', type: 'int', + mode: ['properties', 'create', 'edit'], group: '{{ _('Definition') }}' + },{ + id: 'start', label: '{{ _('Start') }}', type: 'int', + mode: ['create'], group: '{{ _('Definition') }}' + },{ + id: 'current_value', label: '{{ _('Current value') }}', type: 'int', + mode: ['properties', 'edit'], group: '{{ _('Definition') }}' + },{ + id: 'minimum', label: '{{ _('Minimum') }}', type: 'int', + mode: ['properties', 'create', 'edit'], group: '{{ _('Definition') }}' + },{ + id: 'maximum', label: '{{ _('Maximum') }}', type: 'int', + mode: ['properties', 'create', 'edit'], group: '{{ _('Definition') }}' + },{ + id: 'cache', label: '{{ _('Cache') }}', type: 'int', + mode: ['properties', 'create', 'edit'], group: '{{ _('Definition') }}' + },{ + id: 'cycled', label: '{{ _('Cycled') }}', type: 'switch', + mode: ['properties', 'create', 'edit'], group: '{{ _('Definition') }}' + },{ + id: 'relacl', label: '{{ _('Privileges') }}', model: pgAdmin.Browser.Node.PrivilegeRoleModel.extend( + {privileges: ['r', 'w', 'U']}), uniqueCol : ['grantee', 'grantor'], + editable: false, type: 'collection', group: '{{ _('Security') }}', mode: ['properties', 'edit', 'create'], + canAdd: true, canDelete: true, control: 'unique-col-collection', + },{ + id: 'securities', label: '{{ _('Securitiy Labels') }}', model: SecurityModel, + editable: false, type: 'collection', canEdit: false, + group: '{{ _('Security') }}', canDelete: true, + mode: ['properties', 'edit', 'create'], canAdd: true, + control: 'unique-col-collection', uniqueCol : ['provider'], + min_version: 90200 + } + ], + validate: function() { + var msg = undefined; + // Clear any existing error msg. + this.errorModel.unset('name'); + this.errorModel.unset('seqowner'); + this.errorModel.unset('schema'); + + if (_.isUndefined(this.get('name')) + || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') { + msg = '{{ _('Sequence name can not be empty!') }}'; + this.errorModel.set('name', msg); + return msg; + } + + if (_.isUndefined(this.get('seqowner')) + || String(this.get('seqowner')).replace(/^\s+|\s+$/g, '') == '') { + msg = '{{ _('Sequence owner can not be empty!') }}'; + this.errorModel.set('seqowner', msg); + return msg; + } + + if (_.isUndefined(this.get('schema')) + || String(this.get('schema')).replace(/^\s+|\s+$/g, '') == '') { + msg = '{{ _('Sequence schema can not be empty!') }}'; + this.errorModel.set('schema', msg); + return msg; + } + return null; + } + }) + }); + + } + + return pgBrowser.Nodes['sequence']; +}); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/acl.sql new file mode 100644 index 0000000..f27c924 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/acl.sql @@ -0,0 +1,30 @@ +SELECT 'relacl' as deftype, COALESCE(gt.rolname, 'public') grantee, g.rolname grantor, array_agg(privilege_type) as privileges, array_agg(is_grantable) as grantable +FROM + (SELECT + d.grantee, d.grantor, d.is_grantable, + CASE d.privilege_type + WHEN 'CONNECT' THEN 'c' + WHEN 'CREATE' THEN 'C' + WHEN 'DELETE' THEN 'd' + WHEN 'EXECUTE' THEN 'X' + WHEN 'INSERT' THEN 'a' + WHEN 'REFERENCES' THEN 'x' + WHEN 'SELECT' THEN 'r' + WHEN 'TEMPORARY' THEN 'T' + WHEN 'TRIGGER' THEN 't' + WHEN 'TRUNCATE' THEN 'D' + WHEN 'UPDATE' THEN 'w' + WHEN 'USAGE' THEN 'U' + ELSE 'UNKNOWN' + END AS privilege_type + FROM + (SELECT relacl + FROM pg_class cl + LEFT OUTER JOIN pg_description des ON (des.objoid=cl.oid AND des.classoid='pg_class'::regclass) + WHERE relkind = 'S' AND relnamespace = {{scid}}::oid + AND cl.oid = {{seid}}::oid ) acl, + aclexplode(relacl) d + ) d + LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid) + LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid) +GROUP BY g.rolname, gt.rolname \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/backend_support.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/backend_support.sql new file mode 100644 index 0000000..f9b9564 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/backend_support.sql @@ -0,0 +1,18 @@ +SELECT + CASE WHEN nsp.nspname IN ('sys', 'dbo', 'information_schema') THEN true ELSE false END AS dbSupport +FROM pg_namespace nsp +WHERE nsp.oid={{scid}}::int +AND ( + (nspname = 'pg_catalog' AND EXISTS + (SELECT 1 FROM pg_class WHERE relname = 'pg_class' AND relnamespace = nsp.oid LIMIT 1)) + OR (nspname = 'pgagent' AND EXISTS + (SELECT 1 FROM pg_class WHERE relname = 'pga_job' AND relnamespace = nsp.oid LIMIT 1)) + OR (nspname = 'information_schema' AND EXISTS + (SELECT 1 FROM pg_class WHERE relname = 'tables' AND relnamespace = nsp.oid LIMIT 1)) + OR (nspname LIKE '_%' AND EXISTS + (SELECT 1 FROM pg_proc WHERE proname='slonyversion' AND pronamespace = nsp.oid LIMIT 1)) +) +AND + nspname NOT LIKE E'pg\\temp\\%' +AND + nspname NOT LIKE E'pg\\toast_temp\\%' \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/create.sql new file mode 100644 index 0000000..5bea409 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/create.sql @@ -0,0 +1,14 @@ +{% if data %} +CREATE SEQUENCE {{ conn|qtIdent(data.schema) }}.{{ conn|qtIdent(data.name) }}{% if data.cycled and data.cycled == True %} CYCLE{% endif %} +{% if data.increment %} + +INCREMENT {{data.increment}}{% endif %}{% if data.start %} + +START {{data.start}}{% endif %}{% if data.minimum %} + +MINVALUE {{data.minimum}}{% endif %}{% if data.maximum %} + +MAXVALUE {{data.maximum}}{% endif %}{% if data.cache %} + +CACHE {{data.cache}}{% endif %}; +{% endif %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/delete.sql new file mode 100644 index 0000000..efd218e --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/delete.sql @@ -0,0 +1 @@ +DROP SEQUENCE {{ conn|qtIdent(data.schema) }}.{{ conn|qtIdent(data.name) }}{% if cascade%} CASCADE{% endif %}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/get_def.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/get_def.sql new file mode 100644 index 0000000..1c926db --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/get_def.sql @@ -0,0 +1,3 @@ +SELECT last_value, min_value, max_value, cache_value, +is_cycled, increment_by, is_called +FROM {{ conn|qtIdent(data.schema) }}.{{ conn|qtIdent(data.name) }} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/get_oid.sql new file mode 100644 index 0000000..361a6bb --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/get_oid.sql @@ -0,0 +1,5 @@ +SELECT cl.oid as oid +FROM pg_class cl +LEFT OUTER JOIN pg_description des ON (des.objoid=cl.oid AND des.classoid='pg_class'::regclass) +WHERE relkind = 'S' AND relnamespace = {{scid}}::oid +AND relname = {{ name|qtLiteral }} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/grant.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/grant.sql new file mode 100644 index 0000000..325ad64 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/grant.sql @@ -0,0 +1,26 @@ +{% import 'macros/security.macros' as SECLABLE %} +{% import 'macros/privilege.macros' as PRIVILEGE %} +{# Construct sequence name from name and schema #} +{% set seqname=conn|qtIdent(data.schema, data.name) %} +{% if data.seqowner %} + +ALTER SEQUENCE {{ seqname }} +OWNER TO {{ conn|qtIdent(data.seqowner) }}; +{% endif %} +{% if data.comment %} + +COMMENT ON SEQUENCE {{ seqname }} + IS {{ data.comment|qtLiteral }}; +{% endif %} +{% if data.securities %} + +{% for r in data.securities %} +{{ SECLABLE.SET(conn, 'SEQUENCE', data.name, r.provider, r.security_label, data.schema) }} +{% endfor %} +{% endif %} +{% if data.relacl %} + +{% for priv in data.relacl %} +{{ PRIVILEGE.SET(conn, 'SEQUENCE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }} +{% endfor %} +{% endif %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/properties.sql new file mode 100644 index 0000000..caab0ed --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/properties.sql @@ -0,0 +1,11 @@ +{% if scid %} +SELECT cl.oid as oid, relname as name, nsp.nspname as schema, pg_get_userbyid(relowner) AS seqowner, description as comment, +(SELECT array_agg(provider || '=' || label) FROM pg_shseclabel sl1 WHERE sl1.objoid=cl.oid) AS securities +FROM pg_class cl +LEFT OUTER JOIN pg_namespace nsp ON cl.relnamespace = nsp.oid +LEFT OUTER JOIN pg_description des ON (des.objoid=cl.oid + AND des.classoid='pg_class'::regclass) +WHERE relkind = 'S' AND relnamespace = {{scid}}::oid +{% if seid %}AND cl.oid = {{seid}}::oid {% endif %} +ORDER BY relname +{% endif %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/update.sql new file mode 100644 index 0000000..95203b3 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/9.1_plus/update.sql @@ -0,0 +1,89 @@ +{% import 'macros/security.macros' as SECLABLE %} +{% import 'macros/privilege.macros' as PRIVILEGE %} +{% if data %} +{% if data.name != o_data.name %} +ALTER SEQUENCE {{ conn|qtIdent(o_data.schema, o_data.name) }} + RENAME TO {{ conn|qtIdent(data.name) }}; +{% endif %} +{% if data.seqowner and data.seqowner != o_data.seqowner %} +ALTER SEQUENCE {{ conn|qtIdent(o_data.schema, data.name) }} + OWNER TO {{ conn|qtIdent(data.seqowner) }}; +{% endif %} +{% if data.current_value %} +{% set seqname = conn|qtIdent(o_data.schema, data.name) %} +SELECT setval({{ seqname|qtLiteral }}, {{ data.current_value }}, true); +{% endif %} +{% set defquery = '' %} +{% if data.increment %} + {% set defquery = defquery+'\n INCREMENT '+data.increment|string %} +{% endif %} +{% if data.minimum %} + {% set defquery = defquery+'\n MINVALUE '+data.minimum|string %} +{% endif %} +{% if data.maximum %} + {% set defquery = defquery+'\n MAXVALUE '+data.maximum|string %} +{% endif %} +{% if data.cache %} + {% set defquery = defquery+'\n CACHE '+data.cache|string %} +{% endif %} +{% if data.cycled == True %} + {% set defquery = defquery+'\n CYCLE' %} +{% elif data.cycled == False %} + {% set defquery = defquery+'\n NO CYCLE' %} +{% endif %} +{% if defquery and defquery != '' %} + +ALTER SEQUENCE {{ conn|qtIdent(o_data.schema, data.name) }} {{ defquery }}; +{% endif %} +{% if data.schema and data.schema != o_data.schema %} +ALTER SEQUENCE {{ conn|qtIdent(o_data.schema, data.name) }} +SET SCHEMA {{ conn|qtIdent(data.schema) }}; +{% set seqname = conn|qtIdent(data.schema, data.name) %} +{% set schema = data.schema %} +{% else %} +{% set seqname = conn|qtIdent(o_data.schema, data.name) %} +{% set schema = o_data.schema %} +{% endif %} +{% if data.comment and data.comment != o_data.comment %} +COMMENT ON SEQUENCE {{ seqname }} + IS {{ data.comment|qtLiteral }}; +{% endif %} +{% if data.securities and data.securities|length > 0 %} + +{% set seclabels = data.securities %} +{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %} +{% for r in seclabels.deleted %} +{{ SECLABLE.UNSET(conn, 'SEQUENCE', data.name, r.provider, schema) }} +{% endfor %} +{% endif %} +{% if 'added' in seclabels and seclabels.added|length > 0 %} +{% for r in seclabels.added %} +{{ SECLABLE.SET(conn, 'SEQUENCE', data.name, r.provider, r.security_label, schema) }} +{% endfor %} +{% endif %} +{% if 'changed' in seclabels and seclabels.changed|length > 0 %} +{% for r in seclabels.changed %} +{{ SECLABLE.SET(conn, 'SEQUENCE', data.name, r.provider, r.security_label, schema) }} +{% endfor %} +{% endif %} +{% endif %} +{% if data.relacl %} + +{% if 'deleted' in data.relacl %} +{% for priv in data.relacl.deleted %} +{{ PRIVILEGE.UNSETALL(conn, 'SEQUENCE', priv.grantee, data.name, schema) }} +{% endfor %} +{% endif %} +{% if 'changed' in data.relacl %} +{% for priv in data.relacl.changed %} +{{ PRIVILEGE.UNSETALL(conn, 'SEQUENCE', priv.grantee, data.name, schema) }} +{{ PRIVILEGE.SET(conn, 'SEQUENCE', priv.grantee, data.name, priv.without_grant, priv.with_grant, schema) }} +{% endfor %} +{% endif %} +{% if 'added' in data.relacl %} +{% for priv in data.relacl.added %} +{{ PRIVILEGE.SET(conn, 'SEQUENCE', priv.grantee, data.name, priv.without_grant, priv.with_grant, schema) }} +{% endfor %} +{% endif %} +{% endif %} +{% endif %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/acl.sql new file mode 100644 index 0000000..f27c924 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/acl.sql @@ -0,0 +1,30 @@ +SELECT 'relacl' as deftype, COALESCE(gt.rolname, 'public') grantee, g.rolname grantor, array_agg(privilege_type) as privileges, array_agg(is_grantable) as grantable +FROM + (SELECT + d.grantee, d.grantor, d.is_grantable, + CASE d.privilege_type + WHEN 'CONNECT' THEN 'c' + WHEN 'CREATE' THEN 'C' + WHEN 'DELETE' THEN 'd' + WHEN 'EXECUTE' THEN 'X' + WHEN 'INSERT' THEN 'a' + WHEN 'REFERENCES' THEN 'x' + WHEN 'SELECT' THEN 'r' + WHEN 'TEMPORARY' THEN 'T' + WHEN 'TRIGGER' THEN 't' + WHEN 'TRUNCATE' THEN 'D' + WHEN 'UPDATE' THEN 'w' + WHEN 'USAGE' THEN 'U' + ELSE 'UNKNOWN' + END AS privilege_type + FROM + (SELECT relacl + FROM pg_class cl + LEFT OUTER JOIN pg_description des ON (des.objoid=cl.oid AND des.classoid='pg_class'::regclass) + WHERE relkind = 'S' AND relnamespace = {{scid}}::oid + AND cl.oid = {{seid}}::oid ) acl, + aclexplode(relacl) d + ) d + LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid) + LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid) +GROUP BY g.rolname, gt.rolname \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/backend_support.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/backend_support.sql new file mode 100644 index 0000000..f9b9564 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/backend_support.sql @@ -0,0 +1,18 @@ +SELECT + CASE WHEN nsp.nspname IN ('sys', 'dbo', 'information_schema') THEN true ELSE false END AS dbSupport +FROM pg_namespace nsp +WHERE nsp.oid={{scid}}::int +AND ( + (nspname = 'pg_catalog' AND EXISTS + (SELECT 1 FROM pg_class WHERE relname = 'pg_class' AND relnamespace = nsp.oid LIMIT 1)) + OR (nspname = 'pgagent' AND EXISTS + (SELECT 1 FROM pg_class WHERE relname = 'pga_job' AND relnamespace = nsp.oid LIMIT 1)) + OR (nspname = 'information_schema' AND EXISTS + (SELECT 1 FROM pg_class WHERE relname = 'tables' AND relnamespace = nsp.oid LIMIT 1)) + OR (nspname LIKE '_%' AND EXISTS + (SELECT 1 FROM pg_proc WHERE proname='slonyversion' AND pronamespace = nsp.oid LIMIT 1)) +) +AND + nspname NOT LIKE E'pg\\temp\\%' +AND + nspname NOT LIKE E'pg\\toast_temp\\%' \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/create.sql new file mode 100644 index 0000000..5bea409 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/create.sql @@ -0,0 +1,14 @@ +{% if data %} +CREATE SEQUENCE {{ conn|qtIdent(data.schema) }}.{{ conn|qtIdent(data.name) }}{% if data.cycled and data.cycled == True %} CYCLE{% endif %} +{% if data.increment %} + +INCREMENT {{data.increment}}{% endif %}{% if data.start %} + +START {{data.start}}{% endif %}{% if data.minimum %} + +MINVALUE {{data.minimum}}{% endif %}{% if data.maximum %} + +MAXVALUE {{data.maximum}}{% endif %}{% if data.cache %} + +CACHE {{data.cache}}{% endif %}; +{% endif %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/delete.sql new file mode 100644 index 0000000..efd218e --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/delete.sql @@ -0,0 +1 @@ +DROP SEQUENCE {{ conn|qtIdent(data.schema) }}.{{ conn|qtIdent(data.name) }}{% if cascade%} CASCADE{% endif %}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/get_def.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/get_def.sql new file mode 100644 index 0000000..1c926db --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/get_def.sql @@ -0,0 +1,3 @@ +SELECT last_value, min_value, max_value, cache_value, +is_cycled, increment_by, is_called +FROM {{ conn|qtIdent(data.schema) }}.{{ conn|qtIdent(data.name) }} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/get_oid.sql new file mode 100644 index 0000000..361a6bb --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/get_oid.sql @@ -0,0 +1,5 @@ +SELECT cl.oid as oid +FROM pg_class cl +LEFT OUTER JOIN pg_description des ON (des.objoid=cl.oid AND des.classoid='pg_class'::regclass) +WHERE relkind = 'S' AND relnamespace = {{scid}}::oid +AND relname = {{ name|qtLiteral }} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/grant.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/grant.sql new file mode 100644 index 0000000..eb119a1 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/grant.sql @@ -0,0 +1,26 @@ +{% import 'macros/security.macros' as SECLABLE %} +{% import 'macros/privilege.macros' as PRIVILEGE %} +{# Construct sequence name from name and schema #} +{% set seqname=conn|qtIdent(data.schema, data.name) %} +{% if data.seqowner %} +ALTER SEQUENCE {{ seqname }} +OWNER TO {{ conn|qtIdent(data.seqowner) }}; +{% endif %} + +{% if data.comment %} +COMMENT ON SEQUENCE {{ seqname }} + IS {{ data.comment|qtLiteral }}; +{% endif %} + +{% if data.securities %} + +{% for r in data.securities %} +{{ SECLABLE.SET(conn, 'SEQUENCE', data.name, r.provider, r.security_label, data.schema) }} +{% endfor %} +{% endif %} +{% if data.relacl %} + +{% for priv in data.relacl %} +{{ PRIVILEGE.SET(conn, 'SEQUENCE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }} +{% endfor %} +{% endif %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/properties.sql new file mode 100644 index 0000000..0d93e5a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/properties.sql @@ -0,0 +1,16 @@ +{% if scid %} +SELECT cl.oid as oid, relname as name, nsp.nspname as schema, +pg_get_userbyid(relowner) AS seqowner, description as comment +FROM pg_class cl +LEFT OUTER JOIN pg_namespace nsp ON cl.relnamespace = nsp.oid +LEFT OUTER JOIN pg_description des ON (des.objoid=cl.oid AND + des.classoid='pg_class'::regclass) +WHERE relkind = 'S' AND relnamespace = {{scid}}::oid +{% if seid %}AND cl.oid = {{seid}}::oid {% endif %} +ORDER BY relname +{% endif %} +{% if name %} +SELECT last_value, min_value, max_value, cache_value, +is_cycled, increment_by, is_called +FROM {{ conn|qtIdent(name) }} +{% endif %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/update.sql new file mode 100644 index 0000000..a90ce2c --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/sql/pre_9.1/update.sql @@ -0,0 +1,70 @@ +{% import 'macros/security.macros' as SECLABLE %} +{% import 'macros/privilege.macros' as PRIVILEGE %} +{% if data %} +{% if data.name != o_data.name %} +ALTER SEQUENCE {{ conn|qtIdent(o_data.schema, o_data.name) }} + RENAME TO {{ conn|qtIdent(data.name) }}; +{% endif %} +{% if data.seqowner and data.seqowner != o_data.seqowner %} +ALTER SEQUENCE {{ conn|qtIdent(o_data.schema, data.name) }} + OWNER TO {{ conn|qtIdent(data.seqowner) }}; +{% endif %} +{% if data.current_value %} +{% set seqname = conn|qtIdent(o_data.schema, data.name) %} +SELECT setval({{ seqname|qtLiteral }}, {{ data.current_value }}, true); +{% endif %} +{% set defquery = '' %} +{% if data.increment %} + {% set defquery = defquery+'\n INCREMENT '+data.increment|string %} +{% endif %} +{% if data.minimum %} + {% set defquery = defquery+'\n MINVALUE '+data.minimum|string %} +{% endif %} +{% if data.maximum %} + {% set defquery = defquery+'\n MAXVALUE '+data.maximum|string %} +{% endif %} +{% if data.cache %} + {% set defquery = defquery+'\n CACHE '+data.cache|string %} +{% endif %} +{% if data.cycled == True %} + {% set defquery = defquery+'\n CYCLE' %} +{% elif data.cycled == False %} + {% set defquery = defquery+'\n NO CYCLE' %} +{% endif %} +{% if defquery and defquery != '' %} + +ALTER SEQUENCE {{ conn|qtIdent(o_data.schema, data.name) }} {{ defquery }}; +{% endif %} +{% if data.schema and data.schema != o_data.schema %} +ALTER SEQUENCE {{ conn|qtIdent(o_data.schema, data.name) }} +SET SCHEMA {{ conn|qtIdent(data.schema) }}; +{% set seqname = conn|qtIdent(data.schema, data.name) %} +{% set schema = data.schema %} +{% else %} +{% set seqname = conn|qtIdent(o_data.schema, data.name) %} +{% set schema = o_data.schema %} +{% endif %} +{% if data.comment and data.comment != o_data.comment %} +COMMENT ON SEQUENCE {{ seqname }} + IS {{ data.comment|qtLiteral }}; +{% endif %} +{% if data.relacl %} + +{% if 'deleted' in data.relacl %} +{% for priv in data.relacl.deleted %} +{{ PRIVILEGE.UNSETALL(conn, 'SEQUENCE', priv.grantee, data.name, schema) }} +{% endfor %} +{% endif %} +{% if 'changed' in data.relacl %} +{% for priv in data.relacl.changed %} +{{ PRIVILEGE.UNSETALL(conn, 'SEQUENCE', priv.grantee, data.name, schema) }} +{{ PRIVILEGE.SET(conn, 'SEQUENCE', priv.grantee, data.name, priv.without_grant, priv.with_grant, schema) }} +{% endfor %} +{% endif %} +{% if 'added' in data.relacl %} +{% for priv in data.relacl.added %} +{{ PRIVILEGE.SET(conn, 'SEQUENCE', priv.grantee, data.name, priv.without_grant, priv.with_grant, schema) }} +{% endfor %} +{% endif %} +{% endif %} +{% endif %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/utils.py b/web/pgadmin/browser/server_groups/servers/utils.py index 765196f..2f47fa4 100644 --- a/web/pgadmin/browser/server_groups/servers/utils.py +++ b/web/pgadmin/browser/server_groups/servers/utils.py @@ -54,7 +54,8 @@ def parse_priv_to_db(str_privileges, object_type = None): privileges_max_cnt = { 'DATABASE': 3, 'TABLESPACE': 2, - 'SCHEMA': 2 + 'SCHEMA': 2, + 'SEQUENCE': 3 } privileges = []
-- Sent via pgadmin-hackers mailing list (pgadmin-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgadmin-hackers