Add support for Sequences.
parent
986375d60e
commit
def1a30251
|
@ -0,0 +1,692 @@
|
|||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2016, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
"""Implements Sequence Node"""
|
||||
|
||||
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 PGChildNodeView
|
||||
from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
|
||||
parse_priv_to_db
|
||||
from pgadmin.browser.server_groups.servers.databases.schemas.utils \
|
||||
import SchemaChildModule
|
||||
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(SchemaChildModule):
|
||||
"""
|
||||
class SequenceModule(CollectionNodeModule)
|
||||
|
||||
A module class for Sequence node derived from CollectionNodeModule.
|
||||
|
||||
Methods:
|
||||
-------
|
||||
* __init__(*args, **kwargs)
|
||||
- Method is used to initialize the SequenceModule and it's base module.
|
||||
|
||||
* get_nodes(gid, sid, did)
|
||||
- Method is used to generate the browser collection node.
|
||||
|
||||
* script_load()
|
||||
- Load the module script for sequence, when any of the database node is
|
||||
initialized.
|
||||
|
||||
* node_inode()
|
||||
- Method is overridden from its base class to make the node as leaf node.
|
||||
|
||||
"""
|
||||
|
||||
NODE_TYPE = 'sequence'
|
||||
COLLECTION_LABEL = _("Sequences")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SequenceModule, self).__init__(*args, **kwargs)
|
||||
self.min_ver = None
|
||||
self.max_ver = None
|
||||
|
||||
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
|
||||
|
||||
@property
|
||||
def node_inode(self):
|
||||
"""
|
||||
Override this property to make the node a leaf node.
|
||||
|
||||
Returns: False as this is the leaf node
|
||||
"""
|
||||
return False
|
||||
|
||||
blueprint = SequenceModule(__name__)
|
||||
|
||||
|
||||
class SequenceView(PGChildNodeView):
|
||||
node_type = blueprint.node_type
|
||||
|
||||
parent_ids = [
|
||||
{'type': 'int', 'id': 'gid'},
|
||||
{'type': 'int', 'id': 'sid'},
|
||||
{'type': 'int', 'id': 'did'},
|
||||
{'type': 'int', 'id': 'scid'}
|
||||
]
|
||||
ids = [
|
||||
{'type': 'int', 'id': '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 whether javascript exists for this node.
|
||||
"""
|
||||
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!"
|
||||
)
|
||||
)
|
||||
|
||||
self.template_path = 'sequence/sql/9.1_plus'
|
||||
|
||||
return f(self, *args, **kwargs)
|
||||
return wrapped
|
||||
return wrap
|
||||
|
||||
@check_precondition(action='list')
|
||||
def list(self, gid, sid, did, scid):
|
||||
"""
|
||||
This function is used to list all the sequence nodes within the collection.
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
This function is used to create all the child nodes within the collection.
|
||||
Here it will create all the sequence nodes.
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
res = []
|
||||
SQL = render_template("/".join([self.template_path, 'nodes.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):
|
||||
"""
|
||||
This function will show the properties of the selected sequence node.
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
seid: Sequence ID
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
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.
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
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
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
seid: Sequence ID
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
# 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
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
seid: Sequence ID
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
data = request.form if request.form else json.loads(request.data.decode())
|
||||
try:
|
||||
SQL = self.getSQL(gid, sid, did, data, scid, seid)
|
||||
SQL = SQL.strip('\n').strip(' ')
|
||||
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="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.
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
seid: Sequence ID
|
||||
"""
|
||||
|
||||
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.
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
seid: Sequence ID
|
||||
"""
|
||||
|
||||
required_args = [
|
||||
u'name'
|
||||
]
|
||||
|
||||
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
|
||||
|
||||
@check_precondition(action="sql")
|
||||
def sql(self, gid, sid, did, scid, seid):
|
||||
"""
|
||||
This function will generate sql for sql panel
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
seid: Sequence ID
|
||||
"""
|
||||
|
||||
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)
|
||||
SQL = SQL.strip('\n').strip(' ')
|
||||
return ajax_response(response=SQL)
|
||||
|
||||
def _formatter(self, data, scid, seid):
|
||||
"""
|
||||
Args:
|
||||
data: dict of query result
|
||||
scid: Schema ID
|
||||
seid: Sequence ID
|
||||
|
||||
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
|
||||
|
||||
@check_precondition(action="dependents")
|
||||
def dependents(self, gid, sid, did, scid, seid):
|
||||
"""
|
||||
This function gets the dependents and returns an ajax response
|
||||
for the sequence node.
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
seid: Sequence ID
|
||||
"""
|
||||
dependents_result = self.get_dependents(self.conn, seid)
|
||||
return ajax_response(
|
||||
response=dependents_result,
|
||||
status=200
|
||||
)
|
||||
|
||||
@check_precondition(action="dependencies")
|
||||
def dependencies(self, gid, sid, did, scid, seid):
|
||||
"""
|
||||
This function gets the dependencies and returns an ajax response
|
||||
for the sequence node.
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
scid: Schema ID
|
||||
seid: Sequence ID
|
||||
"""
|
||||
dependencies_result = self.get_dependencies(self.conn, seid)
|
||||
|
||||
# Get missing dependencies.
|
||||
# A Corner case, reported by Guillaume Lelarge, could be found at:
|
||||
# http://archives.postgresql.org/pgadmin-hackers/2009-03/msg00026.php
|
||||
|
||||
sql = render_template("/".join([self.template_path,
|
||||
'get_dependencies.sql']), seid=seid)
|
||||
|
||||
status, result = self.conn.execute_dict(sql)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=result)
|
||||
|
||||
for row in result['rows']:
|
||||
ref_name = row['refname']
|
||||
if ref_name is None:
|
||||
continue
|
||||
|
||||
dep_type = ''
|
||||
dep_str = row['deptype']
|
||||
if dep_str == 'a':
|
||||
dep_type = 'auto'
|
||||
elif dep_str == 'n':
|
||||
dep_type = 'normal'
|
||||
elif dep_str == 'i':
|
||||
dep_type = 'internal'
|
||||
|
||||
dependencies_result.append({'type': 'column',
|
||||
'name': ref_name,
|
||||
'field': dep_type})
|
||||
|
||||
return ajax_response(
|
||||
response=dependencies_result,
|
||||
status=200
|
||||
)
|
||||
|
||||
|
||||
SequenceView.register_node_view(blueprint)
|
Binary file not shown.
After Width: | Height: | Size: 359 B |
Binary file not shown.
After Width: | Height: | Size: 405 B |
|
@ -0,0 +1,249 @@
|
|||
define(
|
||||
['jquery', 'underscore', 'underscore.string', 'pgadmin', 'pgadmin.browser', 'alertify', 'pgadmin.browser.collection'],
|
||||
function($, _, S, pgAdmin, pgBrowser, alertify) {
|
||||
|
||||
// Extend the browser's node model class to create a security model
|
||||
var SecurityModel = pgAdmin.Browser.Node.Model.extend({
|
||||
defaults: {
|
||||
provider: undefined,
|
||||
securitylabel: undefined
|
||||
},
|
||||
// Define the schema for the Security Label
|
||||
schema: [{
|
||||
id: 'provider', label: '{{ _('Provider') }}',
|
||||
type: 'text', editable: true
|
||||
},{
|
||||
id: 'security_label', label: '{{ _('Security Label') }}',
|
||||
type: 'text', editable: true
|
||||
}],
|
||||
/* validate function is used to validate the input given by
|
||||
* the user. In case of error, message will be displayed on
|
||||
* the GUI for the respective control.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
// Extend the browser's collection class for sequence collection
|
||||
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']
|
||||
});
|
||||
};
|
||||
|
||||
// Extend the browser's node class for sequence node
|
||||
if (!pgBrowser.Nodes['sequence']) {
|
||||
pgAdmin.Browser.Nodes['sequence'] = pgBrowser.Node.extend({
|
||||
type: 'sequence',
|
||||
label: '{{ _('Sequence') }}',
|
||||
collection_type: 'coll-sequence',
|
||||
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_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: 'schema', 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,
|
||||
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 collation
|
||||
if (_.indexOf(['schema'], d._type) > -1)
|
||||
return true;
|
||||
|
||||
if ('coll-sequence' == 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 want to allow create menu
|
||||
return true;
|
||||
},
|
||||
// Define the model for sequence node.
|
||||
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: []
|
||||
},
|
||||
|
||||
// Default values!
|
||||
initialize: function(attrs, args) {
|
||||
var isNew = (_.size(attrs) === 0);
|
||||
|
||||
if (isNew) {
|
||||
var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user;
|
||||
var schemaInfo = args.node_info.schema;
|
||||
|
||||
this.set({'seqowner': userInfo.name}, {silent: true});
|
||||
this.set({'schema': schemaInfo.label}, {silent: true});
|
||||
}
|
||||
pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments);
|
||||
},
|
||||
|
||||
// Define the schema for sequence node.
|
||||
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: 'acl', label: '{{ _('Privileges') }}', type: 'text',
|
||||
mode: ['properties'], disabled: true
|
||||
},{
|
||||
id: 'relacl', label: '{{ _('Privileges') }}', model: pgAdmin.Browser.Node.PrivilegeRoleModel.extend(
|
||||
{privileges: ['r', 'w', 'U']}), uniqueCol : ['grantee', 'grantor'],
|
||||
editable: false, type: 'collection', group: '{{ _('Security') }}', mode: ['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: ['edit', 'create'], canAdd: true,
|
||||
control: 'unique-col-collection', uniqueCol : ['provider'],
|
||||
min_version: 90200
|
||||
}],
|
||||
/* validate function is used to validate the input given by
|
||||
* the user. In case of error, message will be displayed on
|
||||
* the GUI for the respective control.
|
||||
*/
|
||||
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'];
|
||||
});
|
|
@ -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
|
|
@ -0,0 +1,15 @@
|
|||
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\\%'
|
|
@ -0,0 +1,16 @@
|
|||
{% 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 %}
|
|
@ -0,0 +1 @@
|
|||
DROP SEQUENCE {{ conn|qtIdent(data.schema) }}.{{ conn|qtIdent(data.name) }}{% if cascade%} CASCADE{% endif %};
|
|
@ -0,0 +1,9 @@
|
|||
SELECT
|
||||
last_value,
|
||||
min_value,
|
||||
max_value,
|
||||
cache_value,
|
||||
is_cycled,
|
||||
increment_by,
|
||||
is_called
|
||||
FROM {{ conn|qtIdent(data.schema) }}.{{ conn|qtIdent(data.name) }}
|
|
@ -0,0 +1,12 @@
|
|||
SELECT
|
||||
CASE WHEN att.attname IS NOT NULL AND ref.relname IS NOT NULL THEN ref.relname || '.' || att.attname
|
||||
ELSE ref.relname
|
||||
END AS refname,
|
||||
d2.refclassid, d1.deptype AS deptype
|
||||
FROM pg_depend d1
|
||||
LEFT JOIN pg_depend d2 ON d1.objid=d2.objid AND d1.refobjid != d2.refobjid
|
||||
LEFT JOIN pg_class ref ON ref.oid = d2.refobjid
|
||||
LEFT JOIN pg_attribute att ON d2.refobjid=att.attrelid AND d2.refobjsubid=att.attnum
|
||||
WHERE d1.classid=(SELECT oid FROM pg_class WHERE relname='pg_attrdef')
|
||||
AND d2.refobjid NOT IN (SELECT d3.refobjid FROM pg_depend d3 WHERE d3.objid=d1.refobjid)
|
||||
AND d1.refobjid={{seid}}::oid
|
|
@ -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 }}
|
|
@ -0,0 +1,26 @@
|
|||
{% import 'macros/schemas/security.macros' as SECLABLE %}
|
||||
{% import 'macros/schemas/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 %}
|
|
@ -0,0 +1,4 @@
|
|||
SELECT cl.oid as oid, relname as name
|
||||
FROM pg_class cl
|
||||
WHERE relkind = 'S' AND relnamespace = {{scid}}::oid
|
||||
ORDER BY relname
|
|
@ -0,0 +1,17 @@
|
|||
{% if scid %}
|
||||
SELECT
|
||||
cl.oid as oid,
|
||||
relname as name,
|
||||
nsp.nspname as schema,
|
||||
pg_get_userbyid(relowner) AS seqowner,
|
||||
description as comment,
|
||||
array_to_string(relacl::text[], ', ') as acl,
|
||||
(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 %}
|
|
@ -0,0 +1,94 @@
|
|||
{% import 'macros/schemas/security.macros' as SECLABLE %}
|
||||
{% import 'macros/schemas/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 %}
|
Loading…
Reference in New Issue