Adding the Database node.
We know that current implemenation have some limitations: i.e. * We should not show the template0 in the browser tree. * Should not connect to the database which does not have permission to connect the server by the current user. * Show default previlige for PUBLIC in creation mode. * Allow to create/database database only if current user have sufficient permission. * Do not show reversed engineered SQL in all supported version. * Do not showing system database or not. Author: Khushboo Vashi, Harshal Dhumal, Murtuza Zabuawala Reviewed by: Neel Patel, Akshay Joshipull/3/head
parent
3ca29b18b5
commit
657f14997b
|
@ -0,0 +1,730 @@
|
|||
##########################################################################
|
||||
#
|
||||
# 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, current_app, 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 as servers
|
||||
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 DatabaseModule(CollectionNodeModule):
|
||||
NODE_TYPE = 'database'
|
||||
COLLECTION_LABEL = _("Databases")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.min_ver = None
|
||||
self.max_ver = None
|
||||
|
||||
super(DatabaseModule, self).__init__(*args, **kwargs)
|
||||
|
||||
def get_nodes(self, gid, sid):
|
||||
"""
|
||||
Generate the collection node
|
||||
"""
|
||||
yield self.generate_browser_collection_node(sid)
|
||||
|
||||
@property
|
||||
def script_load(self):
|
||||
"""
|
||||
Load the module script for server, when any of the server-group node is
|
||||
initialized.
|
||||
"""
|
||||
return servers.ServerModule.NODE_TYPE
|
||||
|
||||
@property
|
||||
def csssnippets(self):
|
||||
"""
|
||||
Returns a snippet of css to include in the page
|
||||
"""
|
||||
snippets = [
|
||||
render_template(
|
||||
"browser/css/collection.css",
|
||||
node_type=self.node_type,
|
||||
_=_
|
||||
),
|
||||
render_template(
|
||||
"databases/css/database.css",
|
||||
node_type=self.node_type,
|
||||
_=_
|
||||
)
|
||||
]
|
||||
|
||||
for submodule in self.submodules:
|
||||
snippets.extend(submodule.csssnippets)
|
||||
|
||||
return snippets
|
||||
|
||||
|
||||
blueprint = DatabaseModule(__name__)
|
||||
|
||||
|
||||
class DatabaseView(NodeView):
|
||||
node_type = blueprint.node_type
|
||||
|
||||
parent_ids = [
|
||||
{'type': 'int', 'id': 'gid'},
|
||||
{'type': 'int', 'id': 'sid'}
|
||||
]
|
||||
ids = [
|
||||
{'type': 'int', 'id': 'did'}
|
||||
]
|
||||
|
||||
operations = dict({
|
||||
'obj': [
|
||||
{'get': 'properties', 'delete': 'delete', 'put': 'update'},
|
||||
{'get': 'list', 'post': 'create'}
|
||||
],
|
||||
'nodes': [{'get': 'node'}, {'get': 'nodes'}],
|
||||
'sql': [{'get': 'sql'}],
|
||||
'msql': [{'get': 'msql'}, {'get': 'msql'}],
|
||||
'stats': [{'get': 'statistics'}],
|
||||
'dependency': [{'get': 'dependencies'}],
|
||||
'dependent': [{'get': 'dependents'}],
|
||||
'children': [{'get': 'children'}],
|
||||
'module.js': [{}, {}, {'get': 'module_js'}],
|
||||
'connect': [{
|
||||
'get': 'connect_status', 'post': 'connect', 'delete': 'disconnect'
|
||||
}],
|
||||
'get_encodings': [{'get': 'getEncodings'}, {'get': 'getEncodings'}],
|
||||
'get_ctypes': [{'get': 'getCtypes'}, {'get': 'getCtypes'}],
|
||||
'vopts': [{}, {'get': 'variable_options'}]
|
||||
})
|
||||
|
||||
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 >= 90300:
|
||||
self.template_path = 'databases/sql/9.3_plus'
|
||||
elif ver >= 90200:
|
||||
self.template_path = 'databases/sql/9.2_plus'
|
||||
else:
|
||||
self.template_path = 'databases/sql/9.1_plus'
|
||||
return f(self, *args, **kwargs)
|
||||
return wrapped
|
||||
return wrap
|
||||
|
||||
@check_precondition(action="list")
|
||||
def list(self, gid, sid):
|
||||
SQL = render_template("/".join([self.template_path, 'properties.sql']))
|
||||
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):
|
||||
res = []
|
||||
SQL = render_template("/".join([self.template_path, 'get_nodes.sql']))
|
||||
status, rset = self.conn.execute_2darray(SQL)
|
||||
|
||||
if not status:
|
||||
return internal_server_error(errormsg=rset)
|
||||
|
||||
for row in rset['rows']:
|
||||
if self.manager.db == row['name']:
|
||||
connected=True
|
||||
canDisConn=False
|
||||
else:
|
||||
conn=self.manager.connection(row['name'])
|
||||
connected=conn.connected()
|
||||
canDisConn=True
|
||||
|
||||
res.append(
|
||||
self.blueprint.generate_browser_node(
|
||||
row['did'],
|
||||
sid,
|
||||
row['name'],
|
||||
icon="icon-database-not-connected" if not connected \
|
||||
else "pg-icon-database",
|
||||
connected=connected,
|
||||
tablespace=row['spcname'],
|
||||
allowConn=row['datallowconn'],
|
||||
canCreate=row['cancreate'],
|
||||
canDisconn=canDisConn
|
||||
)
|
||||
)
|
||||
|
||||
return make_json_response(
|
||||
data=res,
|
||||
status=200
|
||||
)
|
||||
|
||||
@check_precondition(action="node")
|
||||
def node(self, gid, sid, did):
|
||||
SQL = render_template("/".join([self.template_path, 'get_nodes.sql']), did=did)
|
||||
status, rset = self.conn.execute_2darray(SQL)
|
||||
|
||||
if not status:
|
||||
return internal_server_error(errormsg=rset)
|
||||
|
||||
for row in rset['rows']:
|
||||
if self.manager.db == row['name']:
|
||||
connected=True
|
||||
else:
|
||||
conn=self.manager.connection(row['name'])
|
||||
connected=self.conn.connected()
|
||||
return make_json_response(
|
||||
data=self.blueprint.generate_browser_node(
|
||||
row['did'],
|
||||
sid,
|
||||
row['name'],
|
||||
icon="icon-database-not-connected" if not connected \
|
||||
else "pg-icon-database",
|
||||
connected=connected,
|
||||
spcname=row['spcname'],
|
||||
allowConn=row['datallowconn'],
|
||||
canCreate=row['cancreate']
|
||||
),
|
||||
status=200
|
||||
)
|
||||
@check_precondition(action="properties")
|
||||
def properties(self, gid, sid, did):
|
||||
SQL = render_template("/".join([self.template_path, 'properties.sql']), did=did)
|
||||
status, res = self.conn.execute_dict(SQL)
|
||||
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
SQL = render_template("/".join([self.template_path, 'acl.sql']), did=did)
|
||||
status, dataclres = self.conn.execute_dict(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
res = self.formatdbacl(res, dataclres['rows'])
|
||||
|
||||
SQL = render_template("/".join([self.template_path, 'defacl.sql']), did=did)
|
||||
status, defaclres = self.conn.execute_dict(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
res = self.formatdbacl(res, defaclres['rows'])
|
||||
|
||||
result = res['rows'][0]
|
||||
# Fetching variable for database
|
||||
SQL = render_template("/".join([self.template_path, 'get_variables.sql']), did=did)
|
||||
|
||||
status, res1 = self.conn.execute_dict(SQL)
|
||||
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res1)
|
||||
# sending result to formtter
|
||||
frmtd_reslt = self.formatter(result, res1)
|
||||
# mergeing formated result with main result again
|
||||
result.update(frmtd_reslt)
|
||||
return ajax_response(
|
||||
response=result,
|
||||
status=200
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def formatter(result, varibles_rset):
|
||||
""" We will use this function to format our output for
|
||||
security label & variables"""
|
||||
frmtd_result = dict()
|
||||
sec_lbls = []
|
||||
if 'seclabels' in result and result['seclabels'] is not None:
|
||||
for sec in result['seclabels']:
|
||||
sec = re.search(r'([^=]+)=(.*$)', sec)
|
||||
sec_lbls.append({
|
||||
'provider': sec.group(1),
|
||||
'security_label': sec.group(2)
|
||||
})
|
||||
frmtd_result.update({"seclabels" :sec_lbls})
|
||||
|
||||
variablesLst = []
|
||||
for row in varibles_rset['rows']:
|
||||
for d in row['setconfig']:
|
||||
var_name, var_value = d.split("=")
|
||||
# Because we save as boolean string in db so it needs conversion
|
||||
if var_value == 'false' or var_value == 'off':
|
||||
var_value = False
|
||||
variablesLst.append({'role': row['user_name'], 'name': var_name, 'value': var_value, 'database': row['db_name']})
|
||||
frmtd_result.update({"variables" : variablesLst})
|
||||
# returning final result
|
||||
return frmtd_result
|
||||
|
||||
@staticmethod
|
||||
def formatdbacl(res, dbacl):
|
||||
for row in dbacl:
|
||||
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 res
|
||||
|
||||
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(
|
||||
"databases/js/databases.js",
|
||||
_=_
|
||||
),
|
||||
200, {'Content-Type': 'application/x-javascript'}
|
||||
)
|
||||
|
||||
def connect(self, gid, sid, did):
|
||||
"""Connect the Database."""
|
||||
from pgadmin.utils.driver import get_driver
|
||||
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
|
||||
conn = manager.connection(did=did, auto_reconnect=True)
|
||||
status, errmsg = conn.connect()
|
||||
|
||||
if not status:
|
||||
current_app.logger.error(
|
||||
"Could not connected to database(#{0}).\nError: {1}".format(
|
||||
did, errmsg
|
||||
)
|
||||
)
|
||||
|
||||
return internal_server_error(errmsg)
|
||||
else:
|
||||
current_app.logger.info('Connection Established for Database Id: \
|
||||
%s' % (did))
|
||||
|
||||
return make_json_response(
|
||||
success=1,
|
||||
info=_("Database Connected."),
|
||||
data={
|
||||
'icon': 'pg-icon-database',
|
||||
'connected': True
|
||||
}
|
||||
)
|
||||
|
||||
def disconnect(self, gid, sid, did):
|
||||
"""Disconnect the database."""
|
||||
|
||||
# Release Connection
|
||||
from pgadmin.utils.driver import get_driver
|
||||
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
|
||||
|
||||
status = manager.release(did=did)
|
||||
|
||||
if not status:
|
||||
return unauthorized(_("Database Could Not Disconnect."))
|
||||
else:
|
||||
return make_json_response(
|
||||
success=1,
|
||||
info=_("Database Disconnected."),
|
||||
data={
|
||||
'icon': 'icon-database-not-connected',
|
||||
'connected': False
|
||||
}
|
||||
)
|
||||
|
||||
@check_precondition(action="getEncodings")
|
||||
def getEncodings(self, gid, sid, did=None):
|
||||
"""
|
||||
This function to return list of avialable encodings
|
||||
"""
|
||||
res = [{ 'label': '', 'value': '' }]
|
||||
try:
|
||||
SQL = render_template("/".join([self.template_path, 'get_encodings.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['encoding'], 'value': row['encoding'] }
|
||||
)
|
||||
|
||||
return make_json_response(
|
||||
data=res,
|
||||
status=200
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return internal_server_error(errormsg=str(e))
|
||||
|
||||
@check_precondition(action="getCtypes")
|
||||
def getCtypes(self, gid, sid, did=None):
|
||||
"""
|
||||
This function to return list of available collation/character types
|
||||
"""
|
||||
res = [{ 'label': '', 'value': '' }]
|
||||
default_list = ['C', 'POSIX']
|
||||
for val in default_list:
|
||||
res.append(
|
||||
{'label': val, 'value': val}
|
||||
)
|
||||
try:
|
||||
SQL = render_template("/".join([self.template_path, 'get_ctypes.sql']))
|
||||
status, rset = self.conn.execute_2darray(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
for row in rset['rows']:
|
||||
if row['cname'] not in default_list:
|
||||
res.append(
|
||||
{ 'label': row['cname'], 'value': row['cname'] }
|
||||
)
|
||||
|
||||
return make_json_response(
|
||||
data=res,
|
||||
status=200
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return internal_server_error(errormsg=str(e))
|
||||
|
||||
@check_precondition(action="create")
|
||||
def create(self, gid, sid):
|
||||
"""Create the database."""
|
||||
required_args = [
|
||||
u'name'
|
||||
]
|
||||
|
||||
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=410,
|
||||
success=0,
|
||||
errormsg=_(
|
||||
"Couldn't find the required parameter (%s)." % arg
|
||||
)
|
||||
)
|
||||
try:
|
||||
# The below SQL 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 'datacl' in data:
|
||||
data['datacl'] = parse_priv_to_db(data['datacl'], 'DATABASE')
|
||||
|
||||
# The below SQL 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 database
|
||||
SQL = render_template("/".join([self.template_path, 'properties.sql']), name=data['name'])
|
||||
SQL = SQL.strip('\n').strip(' ')
|
||||
if SQL and SQL != "":
|
||||
status, res = self.conn.execute_dict(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
response = res['rows'][0]
|
||||
|
||||
return jsonify(
|
||||
node=self.blueprint.generate_browser_node(
|
||||
response['did'],
|
||||
sid,
|
||||
response['name'],
|
||||
icon="icon-database-not-connected",
|
||||
connected=False,
|
||||
tablespace=response['default_tablespace'],
|
||||
allowConn=True,
|
||||
canCreate=response['cancreate'],
|
||||
canDisconn=True
|
||||
)
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return make_json_response(
|
||||
status=410,
|
||||
success=0,
|
||||
errormsg=e.message
|
||||
)
|
||||
|
||||
@check_precondition(action="update")
|
||||
def update(self, gid, sid, did):
|
||||
"""Update the database."""
|
||||
|
||||
data = request.form if request.form else json.loads(request.data.decode())
|
||||
info = "nothing to update."
|
||||
|
||||
if did is not None:
|
||||
# Fetch the name of database for comparison
|
||||
SQL = render_template("/".join([self.template_path, 'get_name.sql']), did=did)
|
||||
status, name = self.conn.execute_scalar(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=name)
|
||||
|
||||
data['old_name'] = name
|
||||
if 'name' not in data:
|
||||
data['name'] = name
|
||||
|
||||
try:
|
||||
for action in ["rename_database", "tablespace"]:
|
||||
SQL = self.getOfflineSQL(gid, sid, data, did, action)
|
||||
SQL = SQL.strip('\n').strip(' ')
|
||||
if SQL and SQL != "":
|
||||
status = self.manager.release(did=did)
|
||||
|
||||
conn = self.manager.connection()
|
||||
status, msg = conn.execute_scalar(SQL)
|
||||
|
||||
if not status:
|
||||
return internal_server_error(errormsg=msg)
|
||||
|
||||
self.conn = self.manager.connection(database=data['name'], auto_reconnect=True)
|
||||
status, errmsg = self.conn.connect()
|
||||
info = "Database updated."
|
||||
|
||||
SQL = self.getOnlineSQL(gid, sid, data, did)
|
||||
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)
|
||||
|
||||
info = "Database updated."
|
||||
|
||||
return make_json_response(
|
||||
success=1,
|
||||
info = info,
|
||||
data={
|
||||
'id': did,
|
||||
'sid': sid,
|
||||
'gid': gid,
|
||||
}
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return make_json_response(
|
||||
status=410,
|
||||
success=0,
|
||||
errormsg=str(e)
|
||||
)
|
||||
|
||||
@check_precondition(action="drop")
|
||||
def delete(self, gid, sid, did):
|
||||
"""Delete the database."""
|
||||
try:
|
||||
default_conn = self.manager.connection()
|
||||
SQL = render_template("/".join([self.template_path, 'delete.sql']), did=did)
|
||||
status, res = default_conn.execute_scalar(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
if res is None:
|
||||
return make_json_response(
|
||||
success=0,
|
||||
errormsg=_(
|
||||
'The specified database could not be found.\n'
|
||||
)
|
||||
)
|
||||
else:
|
||||
|
||||
status = self.manager.release(did=did)
|
||||
|
||||
SQL = render_template("/".join([self.template_path, 'delete.sql']), datname=res, conn=self.conn)
|
||||
|
||||
status, msg = default_conn.execute_scalar(SQL)
|
||||
if not status:
|
||||
# reconnect if database drop failed.
|
||||
conn = self.manager.connection(did=did, auto_reconnect=True)
|
||||
status, errmsg = conn.connect()
|
||||
return internal_server_error(errormsg=msg)
|
||||
|
||||
except Exception as e:
|
||||
return make_json_response(
|
||||
success=0,
|
||||
errormsg=str(e))
|
||||
|
||||
return make_json_response(success=1)
|
||||
|
||||
@check_precondition(action="msql")
|
||||
def msql(self, gid, sid, did=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
|
||||
try:
|
||||
SQL = self.getSQL(gid, sid, data, did)
|
||||
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, data, did=None):
|
||||
SQL = ''
|
||||
if did is not None:
|
||||
# Fetch the name of database for comparison
|
||||
SQL = render_template("/".join([self.template_path, 'get_name.sql']), did=did)
|
||||
status, name = self.conn.execute_scalar(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=name)
|
||||
|
||||
data['old_name'] = name
|
||||
if 'name' not in data:
|
||||
data['name'] = name
|
||||
SQL = ''
|
||||
for action in ["rename_database", "tablespace"]:
|
||||
SQL += self.getOfflineSQL(gid, sid, data, did, action)
|
||||
|
||||
SQL += self.getOnlineSQL(gid, sid, data, did)
|
||||
else:
|
||||
SQL += self.getNewSQL(gid, sid, data, did)
|
||||
return SQL
|
||||
|
||||
def getNewSQL(self, gid, sid, data, did=None):
|
||||
"""
|
||||
Generates sql for creating new database.
|
||||
"""
|
||||
required_args = [
|
||||
u'name'
|
||||
]
|
||||
|
||||
for arg in required_args:
|
||||
if arg not in data:
|
||||
return " -- definition incomplete"
|
||||
# Privileges
|
||||
data['datacl'] = parse_priv_to_db(data['datacl'], 'DATABASE')
|
||||
|
||||
# Default privileges
|
||||
for key in ['deftblacl', 'defseqacl', 'deffuncacl', 'deftypeacl']:
|
||||
if key in data and data[key] is not None:
|
||||
data[key] = parse_priv_to_db(data[key])
|
||||
|
||||
SQL = render_template("/".join([self.template_path, 'create.sql']), data=data)
|
||||
SQL += "\n"
|
||||
SQL += render_template("/".join([self.template_path, 'grant.sql']), data=data)
|
||||
return SQL
|
||||
|
||||
def getOnlineSQL(self, gid, sid, data, did=None):
|
||||
"""
|
||||
Generates sql for altering database which don not require
|
||||
database to be disconnected before applying.
|
||||
"""
|
||||
|
||||
for key in ['datacl', 'deftblacl', 'defseqacl', 'deffuncacl', 'deftypeacl']:
|
||||
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'])
|
||||
if 'changed' in data[key]:
|
||||
data[key]['changed'] = parse_priv_to_db(data[key]['changed'])
|
||||
if 'deleted' in data[key]:
|
||||
data[key]['deleted'] = parse_priv_to_db(data[key]['deleted'])
|
||||
|
||||
return render_template("/".join([self.template_path, 'alter_online.sql']), data=data, conn=self.conn)
|
||||
|
||||
def getOfflineSQL(self, gid, sid, data, did=None, action=None):
|
||||
"""
|
||||
Generates sql for altering database which require
|
||||
database to be disconnected before applying.
|
||||
"""
|
||||
|
||||
return render_template("/".join([self.template_path, 'alter_offline.sql']),
|
||||
data=data, conn=self.conn, action=action)
|
||||
|
||||
@check_precondition(action="variable_options")
|
||||
def variable_options(self, gid, sid):
|
||||
res = []
|
||||
SQL = render_template("/".join([self.template_path, 'variables.sql']))
|
||||
status, rset = self.conn.execute_dict(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=rset)
|
||||
|
||||
return make_json_response(
|
||||
data=rset['rows'],
|
||||
status=200
|
||||
)
|
||||
|
||||
@check_precondition(action="sql")
|
||||
def sql(self, gid, sid, did):
|
||||
"""
|
||||
This function will generate sql for sql panel
|
||||
"""
|
||||
try:
|
||||
SQL = render_template("/".join([self.template_path, 'properties.sql']), did=did)
|
||||
status, res = self.conn.execute_dict(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
SQL = render_template("/".join([self.template_path, 'acl.sql']), did=did)
|
||||
status, dataclres = self.conn.execute_dict(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
res = self.formatdbacl(res, dataclres['rows'])
|
||||
|
||||
SQL = render_template("/".join([self.template_path, 'defacl.sql']), did=did)
|
||||
status, defaclres = self.conn.execute_dict(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
res = self.formatdbacl(res, defaclres['rows'])
|
||||
|
||||
result = res['rows'][0]
|
||||
|
||||
SQL = render_template("/".join([self.template_path, 'get_variables.sql']), did=did)
|
||||
status, res1 = self.conn.execute_dict(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res1)
|
||||
|
||||
frmtd_reslt = self.formatter(result, res1)
|
||||
result.update(frmtd_reslt)
|
||||
|
||||
SQL = self.getNewSQL(gid, sid, result, did)
|
||||
return ajax_response(response=SQL)
|
||||
|
||||
except Exception as e:
|
||||
return ajax_response(response=str(e))
|
||||
|
||||
DatabaseView.register_node_view(blueprint)
|
BIN
web/pgadmin/browser/server_groups/servers/databases/static/img/coll-database.png
Executable file
BIN
web/pgadmin/browser/server_groups/servers/databases/static/img/coll-database.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 771 B |
Binary file not shown.
After Width: | Height: | Size: 706 B |
Binary file not shown.
After Width: | Height: | Size: 814 B |
|
@ -0,0 +1,12 @@
|
|||
.pg-icon-database {
|
||||
background-image: url('{{ url_for('NODE-database.static', filename='img/database.png') }}') !important;
|
||||
background-repeat: no-repeat;
|
||||
align-content: center;
|
||||
vertical-align: middle;
|
||||
height: 1.3em;
|
||||
}
|
||||
|
||||
.icon-database-not-connected {
|
||||
background-image: url('{{ url_for('NODE-database.static', filename='img/databasebad.png') }}') !important;
|
||||
border-radius: 10px
|
||||
}
|
|
@ -0,0 +1,383 @@
|
|||
define([
|
||||
'jquery', 'underscore', 'underscore.string', 'pgadmin',
|
||||
'pgadmin.browser', 'alertify', 'pgadmin.browser.collection',
|
||||
'pgadmin.browser.server.privilege', 'pgadmin.browser.server.variable',
|
||||
],
|
||||
function($, _, S, pgAdmin, pgBrowser, Alertify) {
|
||||
|
||||
if (!pgBrowser.Nodes['coll-database']) {
|
||||
var databases = pgAdmin.Browser.Nodes['coll-database'] =
|
||||
pgAdmin.Browser.Collection.extend({
|
||||
node: 'database',
|
||||
label: '{{ _('Databases') }}',
|
||||
type: 'coll-database',
|
||||
columns: ['name', 'did', 'datowner', 'comments']
|
||||
});
|
||||
};
|
||||
|
||||
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['database']) {
|
||||
pgAdmin.Browser.Nodes['database'] = pgAdmin.Browser.Node.extend({
|
||||
parent_type: 'server',
|
||||
type: 'database',
|
||||
hasSQL: true,
|
||||
canDrop: true,
|
||||
label: '{{ _('Database') }}',
|
||||
node_image: function() {
|
||||
return 'pg-icon-database';
|
||||
},
|
||||
Init: function() {
|
||||
/* Avoid mulitple registration of menus */
|
||||
if (this.initialized)
|
||||
return;
|
||||
|
||||
this.initialized = true;
|
||||
|
||||
pgBrowser.add_menus([{
|
||||
name: 'create_database_on_server', node: 'server', module: this,
|
||||
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||
category: 'create', priority: 4, label: '{{ _('Database...') }}',
|
||||
icon: 'wcTabIcon pg-icon-database', data: {action: 'create'}
|
||||
},{
|
||||
name: 'create_database_on_coll', node: 'coll-database', module: this,
|
||||
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||
category: 'create', priority: 4, label: '{{ _('Database...') }}',
|
||||
icon: 'wcTabIcon pg-icon-database', data: {action: 'create'}
|
||||
},{
|
||||
name: 'create_database', node: 'database', module: this,
|
||||
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||
category: 'create', priority: 4, label: '{{ _('Database...') }}',
|
||||
icon: 'wcTabIcon pg-icon-database', data: {action: 'create'}
|
||||
},{
|
||||
name: 'connect_database', node: 'database', module: this,
|
||||
applies: ['object', 'context'], callback: 'connect_database',
|
||||
category: 'connect', priority: 4, label: '{{ _('Connect Database...') }}',
|
||||
icon: 'fa fa-link', enable : 'is_not_connected'
|
||||
},{
|
||||
name: 'disconnect_database', node: 'database', module: this,
|
||||
applies: ['object', 'context'], callback: 'disconnect_database',
|
||||
category: 'drop', priority: 5, label: '{{ _('Disconnect Database...') }}',
|
||||
icon: 'fa fa-chain-broken', enable : 'is_connected'
|
||||
}]);
|
||||
},
|
||||
is_not_connected: function(node) {
|
||||
return (node && node.connected != true);
|
||||
},
|
||||
is_connected: function(node) {
|
||||
return (node && node.connected == true && node.canDisconn == true);
|
||||
},
|
||||
callbacks: {
|
||||
/* Connect the database */
|
||||
connect_database: function(args){
|
||||
var input = args || {};
|
||||
obj = this,
|
||||
t = pgBrowser.tree,
|
||||
i = input.item || t.selected(),
|
||||
d = i && i.length == 1 ? t.itemData(i) : undefined;
|
||||
|
||||
if (!d || d.label == "template0")
|
||||
return false;
|
||||
|
||||
connect_to_database(obj, d, t, i, true);
|
||||
return false;
|
||||
},
|
||||
/* Disconnect the database */
|
||||
disconnect_database: function(args) {
|
||||
var input = args || {};
|
||||
obj = this,
|
||||
t = pgBrowser.tree,
|
||||
i = input.item || t.selected(),
|
||||
d = i && i.length == 1 ? t.itemData(i) : undefined;
|
||||
|
||||
if (!d)
|
||||
return false;
|
||||
|
||||
Alertify.confirm(
|
||||
'{{ _('Disconnect the database') }}',
|
||||
S('{{ _('Are you sure you want to disconnect the database - %%s ?') }}').sprintf(d.label).value(),
|
||||
function(evt) {
|
||||
var data = d;
|
||||
$.ajax({
|
||||
url: obj.generate_url(i, 'connect', d, true),
|
||||
type:'DELETE',
|
||||
success: function(res) {
|
||||
if (res.success == 1) {
|
||||
Alertify.success("{{ _('" + res.info + "') }}");
|
||||
t.removeIcon(i);
|
||||
data.connected = false;
|
||||
data.icon = 'icon-database-not-connected';
|
||||
t.addIcon(i, {icon: data.icon});
|
||||
t.unload(i);
|
||||
t.setInode(i);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
try {
|
||||
var err = $.parseJSON(xhr.responseText);
|
||||
if (err.success == 0) {
|
||||
msg = S('{{ _(' + err.errormsg + ')}}').value();
|
||||
Alertify.error("{{ _('" + err.errormsg + "') }}");
|
||||
}
|
||||
} catch (e) {}
|
||||
t.unload(i);
|
||||
}
|
||||
});
|
||||
},
|
||||
function(evt) {
|
||||
return true;
|
||||
});
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
/* Connect the database (if not connected), before opening this node */
|
||||
beforeopen: function(item, data) {
|
||||
if(!data || data._type != 'database' || data.label == "template0") {
|
||||
return false;
|
||||
}
|
||||
|
||||
pgBrowser.tree.addIcon(item, {icon: data.icon});
|
||||
if (!data.connected) {
|
||||
connect_to_database(this, data, pgBrowser.tree, item, true);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
selected: function(item, data) {
|
||||
if(!data || data._type != 'database' || data.label == "template0") {
|
||||
return false;
|
||||
}
|
||||
|
||||
pgBrowser.tree.addIcon(item, {icon: data.icon});
|
||||
if (!data.connected) {
|
||||
connect_to_database(this, data, pgBrowser.tree, item, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
return pgBrowser.Node.callbacks.selected.apply(this, arguments);
|
||||
},
|
||||
},
|
||||
model: pgAdmin.Browser.Node.Model.extend({
|
||||
defaults: {
|
||||
name: undefined,
|
||||
owner: undefined,
|
||||
comment: undefined,
|
||||
encoding: 'UTF8',
|
||||
template: undefined,
|
||||
tablespace: undefined,
|
||||
collation: undefined,
|
||||
char_type: undefined,
|
||||
datconnlimit: -1,
|
||||
datallowconn: undefined,
|
||||
variables: [],
|
||||
privileges: [],
|
||||
securities: [],
|
||||
datacl: [],
|
||||
deftblacl: [],
|
||||
deffuncacl: [],
|
||||
defseqacl: [],
|
||||
deftypeacl: []
|
||||
},
|
||||
schema: [{
|
||||
id: 'name', label: '{{ _('Database') }}', cell: 'string',
|
||||
editable: false, type: 'text'
|
||||
},{
|
||||
id: 'did', label:'{{ _('Oid') }}', cell: 'string', mode: ['properties'],
|
||||
editable: false, type: 'text', visible: false
|
||||
},{
|
||||
id: 'datowner', label:'{{ _('Owner') }}',
|
||||
editable: false, type: 'text', node: 'role',
|
||||
control: Backform.NodeListByNameControl
|
||||
},{
|
||||
id: 'comments', label:'{{ _('Comment') }}',
|
||||
editable: false, type: 'multiline'
|
||||
},{
|
||||
id: 'encoding', label: '{{ _('Encoding') }}',
|
||||
editable: false, type: 'text', group: 'Definition',
|
||||
disabled: function(m) { return !m.isNew(); }, url: 'get_encodings',
|
||||
control: 'node-ajax-options'
|
||||
},{
|
||||
id: 'template', label: '{{ _('Template') }}',
|
||||
editable: false, type: 'text', group: 'Definition',
|
||||
disabled: function(m) { return !m.isNew(); },
|
||||
control: 'node-list-by-name', node: 'database'
|
||||
},{
|
||||
id: 'spcname', label: '{{ _('Tablespace') }}',
|
||||
editable: false, type: 'text', group: 'Definition',
|
||||
control: 'node-list-by-name', node: 'tablespace',
|
||||
filter: function(m) {
|
||||
if (m.label == "pg_global") return false;
|
||||
else return true;
|
||||
}
|
||||
},{
|
||||
id: 'datcollate', label: '{{ _('Collation') }}',
|
||||
editable: false, type: 'text', group: 'Definition',
|
||||
disabled: function(m) { return !m.isNew(); }, url: 'get_ctypes',
|
||||
control: 'node-ajax-options'
|
||||
},{
|
||||
id: 'datctype', label: '{{ _('Character Type') }}',
|
||||
editable: false, type: 'text', group: 'Definition',
|
||||
disabled: function(m) { return !m.isNew(); }, url: 'get_ctypes',
|
||||
control: 'node-ajax-options'
|
||||
},{
|
||||
id: 'datconnlimit', label: '{{ _('Connection Limit') }}',
|
||||
editable: false, type: 'int', group: 'Definition', min: -1
|
||||
},{
|
||||
id: 'datallowconn', label: '{{ _('Allow Connections?') }}',
|
||||
editable: false, type: 'switch', group: 'Definition',
|
||||
mode: ['properties'], disabled: true
|
||||
},{
|
||||
id: 'datacl', label: '{{ _('Privileges') }}', model: pgAdmin.Browser.Node.PrivilegeRoleModel.extend(
|
||||
{privileges: ['C', 'T', 'c']}), uniqueCol : ['grantee', 'grantor'],
|
||||
editable: false, type: 'collection', group: '{{ _('Security') }}', mode: ['edit', 'create'],
|
||||
canAdd: true, canDelete: true, control: 'unique-col-collection',
|
||||
},{
|
||||
id: 'variables', label: '{{ _('Variables') }}', type: 'collection',
|
||||
model: pgAdmin.Browser.Node.VariableModel, editable: false,
|
||||
group: '{{ _('Security') }}', mode: ['edit', 'create'],
|
||||
canAdd: true, canEdit: false, canDelete: true, hasRole: true,
|
||||
control: Backform.VariableCollectionControl, node: 'role'
|
||||
},{
|
||||
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
|
||||
},{
|
||||
type: 'nested', control: 'tab', group: '{{ _('Default Privileges') }}',
|
||||
mode: ['edit', 'create'],
|
||||
schema:[{
|
||||
id: 'deftblacl', model: pgAdmin.Browser.Node.PrivilegeRoleModel.extend(
|
||||
{privileges: ['a', 'r', 'w', 'd', 'D', 'x', 't']}), label: '{{ _('Default Privileges: Tables') }}',
|
||||
editable: false, type: 'collection', group: '{{ _('Tables') }}',
|
||||
mode: ['edit', 'create'], control: 'unique-col-collection',
|
||||
canAdd: true, canDelete: true, uniqueCol : ['grantee', 'grantor']
|
||||
},{
|
||||
id: 'defseqacl', model: pgAdmin.Browser.Node.PrivilegeRoleModel.extend(
|
||||
{privileges: ['r', 'w', 'U']}), label: '{{ _('Default Privileges: Sequences') }}',
|
||||
editable: false, type: 'collection', group: '{{ _('Sequences') }}',
|
||||
mode: ['edit', 'create'], control: 'unique-col-collection',
|
||||
canAdd: true, canDelete: true, uniqueCol : ['grantee', 'grantor']
|
||||
},{
|
||||
id: 'deffuncacl', model: pgAdmin.Browser.Node.PrivilegeRoleModel.extend(
|
||||
{privileges: ['X']}), label: '{{ _('Default Privileges: Functions') }}',
|
||||
editable: false, type: 'collection', group: '{{ _('Functions') }}',
|
||||
mode: ['edit', 'create'], control: 'unique-col-collection',
|
||||
canAdd: true, canDelete: true, uniqueCol : ['grantee', 'grantor']
|
||||
},{
|
||||
id: 'deftypeacl', model: pgAdmin.Browser.Node.PrivilegeRoleModel.extend(
|
||||
{privileges: ['U']}), label: '{{ _('Default Privileges: Types') }}',
|
||||
editable: false, type: 'collection', group: '{{ _('Types') }}',
|
||||
mode: ['edit', 'create'], control: 'unique-col-collection',
|
||||
canAdd: true, canDelete: true, uniqueCol : ['grantee', 'grantor'],
|
||||
min_version: 90200
|
||||
}]
|
||||
}
|
||||
],
|
||||
validate: function(keys) {
|
||||
var name = this.get('name');
|
||||
if (_.isUndefined(name) || _.isNull(name) ||
|
||||
String(name).replace(/^\s+|\s+$/g, '') == '') {
|
||||
var msg = '{{ _('Name can not be empty!') }}';
|
||||
this.errorModel.set('name', msg);
|
||||
return msg;
|
||||
} else {
|
||||
this.errorModel.unset('name');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
})
|
||||
});
|
||||
function connect_to_database(obj, data, tree, item, interactive) {
|
||||
if (interactive) {
|
||||
Alertify.confirm(
|
||||
'{{ _('Connect to Database') }}',
|
||||
'{{ _('Do you want to connect the database?') }}',
|
||||
function(evt) {
|
||||
connect(obj, data, tree, item);
|
||||
},
|
||||
function() {});
|
||||
}
|
||||
else{
|
||||
connect(obj, data, tree, item)
|
||||
}
|
||||
};
|
||||
function connect(obj, data, tree, item) {
|
||||
var onFailure = function(xhr, status, error, _model, _data, _tree, _item) {
|
||||
|
||||
tree.setInode(_item);
|
||||
tree.addIcon(_item, {icon: 'icon-database-not-connected'});
|
||||
|
||||
Alertify.pgNotifier('error', xhr, error, function(msg) {
|
||||
setTimeout(function() {
|
||||
Alertify.dlgServerPass(
|
||||
'{{ _('Connect to Database') }}',
|
||||
msg, _model, _data, _tree, _item
|
||||
).resizeTo();
|
||||
}, 100);
|
||||
});
|
||||
},
|
||||
onSuccess = function(res, model, data, tree, item) {
|
||||
tree.deselect(item);
|
||||
tree.setInode(item);
|
||||
|
||||
if (res && res.data) {
|
||||
if(typeof res.data.connected == 'boolean') {
|
||||
data.connected = res.data.connected;
|
||||
}
|
||||
if (typeof res.data.icon == 'string') {
|
||||
tree.removeIcon(item);
|
||||
data.icon = res.data.icon;
|
||||
tree.addIcon(item, {icon: data.icon});
|
||||
}
|
||||
|
||||
Alertify.success(res.info);
|
||||
setTimeout(function() {tree.select(item);}, 10);
|
||||
setTimeout(function() {tree.open(item);}, 100);
|
||||
}
|
||||
},
|
||||
url = obj.generate_url(item, "connect", data, true);
|
||||
$.post(url)
|
||||
.done(
|
||||
function(res) {
|
||||
if (res.success == 1) {
|
||||
return onSuccess(res, obj, data, tree, item);
|
||||
}
|
||||
})
|
||||
.fail(
|
||||
function(xhr, status, error) {
|
||||
return onFailure(xhr, status, error, obj, data, tree, item);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return pgBrowser.Nodes['coll-database'];
|
||||
});
|
|
@ -0,0 +1,33 @@
|
|||
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 datacl FROM pg_database db
|
||||
LEFT OUTER JOIN pg_tablespace ta ON db.dattablespace=ta.OID
|
||||
LEFT OUTER JOIN pg_shdescription descr ON (
|
||||
db.oid=descr.objoid AND descr.classoid='pg_database'::regclass)
|
||||
WHERE db.oid = {{ did|qtLiteral }}::OID
|
||||
) acl,
|
||||
(SELECT (d).grantee AS grantee, (d).grantor AS grantor, (d).is_grantable AS is_grantable, (d).privilege_type AS privilege_type
|
||||
FROM (SELECT aclexplode(datacl) as d FROM pg_database db1
|
||||
WHERE db1.oid = {{ did|qtLiteral }}::OID) a) 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,8 @@
|
|||
{% if data %}
|
||||
{% if action == "rename_database" and data.old_name != data.name %}
|
||||
ALTER DATABASE {{ conn|qtIdent(data.old_name) }} RENAME TO {{ conn|qtIdent(data.name) }};
|
||||
{% endif %}{% if action == "tablespace" and data.spcname %}
|
||||
|
||||
ALTER DATABASE {{ conn|qtIdent(data.name) }} SET TABLESPACE {{ conn|qtIdent(data.spcname) }};
|
||||
{% endif %}
|
||||
{% endif %}
|
|
@ -0,0 +1,129 @@
|
|||
{% import 'macros/variable.macros' as VARIABLE %}
|
||||
{% import 'macros/privilege.macros' as PRIVILEGE %}
|
||||
{% import 'macros/default_privilege.macros' as DEFAULT_PRIVILEGE %}
|
||||
{% if data %}
|
||||
{# To change owner #}
|
||||
{% if data.datowner %}
|
||||
ALTER DATABASE {{ conn|qtIdent(data.name) }} OWNER TO {{ conn|qtIdent(data.datowner) }};
|
||||
{% endif %}
|
||||
{# To change comments #}
|
||||
{% if data.comments %}
|
||||
COMMENT ON DATABASE {{ conn|qtIdent(data.name) }}
|
||||
IS {{ data.comments|qtLiteral }};
|
||||
{% endif %}
|
||||
{# To change conn limit #}
|
||||
{% if data.datconnlimit %}
|
||||
ALTER DATABASE {{ conn|qtIdent(data.name) }} WITH CONNECTION LIMIT = {{ data.datconnlimit }};
|
||||
{% endif %}
|
||||
{# To change Variables #}
|
||||
{% if data.variables and data.variables|length > 0 %}
|
||||
{% set variables = data.variables %}
|
||||
{% if 'deleted' in variables and variables.deleted|length > 0 %}
|
||||
{% for var in variables.deleted %}
|
||||
{{ VARIABLE.RESET(conn, data.name, var.role, var.name) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in variables and variables.added|length > 0 %}
|
||||
{% for var in variables.added %}
|
||||
{% if var.value == True %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'on') }}
|
||||
{% elif var.value == False %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'off') }}
|
||||
{% else %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, var.value) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in variables and variables.changed|length > 0 %}
|
||||
{% for var in variables.changed %}
|
||||
{% if var.value == True %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'on') }}
|
||||
{% elif var.value == False %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'off') }}
|
||||
{% else %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, var.value) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{# To change priviledges #}
|
||||
{% if data.datacl %}
|
||||
{% if 'deleted' in data.datacl %}
|
||||
{% for priv in data.datacl.deleted %}
|
||||
{{ PRIVILEGE.RESETALL(conn, 'DATABASE', priv.grantee, data.name) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in data.datacl %}
|
||||
{% for priv in data.datacl.changed %}
|
||||
{{ PRIVILEGE.RESETALL(conn, 'DATABASE', priv.grantee, data.name) }}
|
||||
{{ PRIVILEGE.APPLY(conn, 'DATABASE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in data.datacl %}
|
||||
{% for priv in data.datacl.added %}
|
||||
{{ PRIVILEGE.APPLY(conn, 'DATABASE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{# To change default priviledges #}
|
||||
{% if data.deftblacl %}
|
||||
{% if 'deleted' in data.deftblacl %}
|
||||
{% for priv in data.deftblacl.deleted %}
|
||||
{{ DEFAULT_PRIVILEGE.RESET(conn, 'TABLES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in data.deftblacl %}
|
||||
{% for priv in data.deftblacl.changed %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'TABLES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in data.deftblacl %}
|
||||
{% for priv in data.deftblacl.added %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'TABLES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{# To change default priviledges #}
|
||||
{% if data.defseqacl %}
|
||||
{% if 'deleted' in data.defseqacl %}
|
||||
{% for priv in data.defseqacl.deleted %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'SEQUENCES', priv.grantee) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in data.defseqacl %}
|
||||
{% for priv in data.defseqacl.changed %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'SEQUENCES', priv.grantee) }}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'SEQUENCES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in data.defseqacl %}
|
||||
{% for priv in data.defseqacl.added %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'SEQUENCES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{# To change default priviledges #}
|
||||
{% if data.deffuncacl %}
|
||||
{% if 'deleted' in data.deffuncacl %}
|
||||
{% for priv in data.deffuncacl.deleted %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'FUNCTIONS', priv.grantee) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in data.deffuncacl %}
|
||||
{% for priv in data.deffuncacl.changed %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'FUNCTIONS', priv.grantee) }}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'FUNCTIONS', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in data.deffuncacl %}
|
||||
{% for priv in data.deffuncacl.added %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'FUNCTIONS', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
|
@ -0,0 +1,19 @@
|
|||
{% if data %}
|
||||
CREATE DATABASE {{ conn|qtIdent(data.name) }}
|
||||
{% if data.datowner %}
|
||||
WITH {% endif %}{% if data.datowner %}
|
||||
|
||||
OWNER = {{ conn|qtIdent(data.datowner) }}{% endif %}{% if data.template %}
|
||||
|
||||
TEMPLATE = {{ conn|qtIdent(data.template) }}{% endif %}{% if data.encoding %}
|
||||
|
||||
ENCODING = {{ data.encoding|qtLiteral }}{% endif %}{% if data.datcollate %}
|
||||
|
||||
LC_COLLATE = {{ data.datcollate|qtLiteral }}{% endif %}{% if data.datctype %}
|
||||
|
||||
LC_CTYPE = {{ data.datctype|qtLiteral }}{% endif %}{% if data.spcname %}
|
||||
|
||||
TABLESPACE = {{ conn|qtIdent(data.spcname) }}{% endif %}{% if data.datconnlimit %}
|
||||
|
||||
CONNECTION LIMIT = {{ data.datconnlimit }}{% endif %};
|
||||
{% endif %}
|
|
@ -0,0 +1,34 @@
|
|||
SELECT
|
||||
CASE (a.deftype)
|
||||
WHEN 'r' THEN 'deftblacl'
|
||||
WHEN 'S' THEN 'defseqacl'
|
||||
WHEN 'f' THEN 'deffuncacl'
|
||||
WHEN 'T' THEN 'deftypeacl'
|
||||
END AS deftype,
|
||||
COALESCE(gt.rolname, 'public') grantee, g.rolname grantor, array_agg(a.privilege_type) as privileges, array_agg(a.is_grantable) as grantable
|
||||
FROM
|
||||
(SELECT
|
||||
(acl).grantee as grantee, (acl).grantor AS grantor, (acl).is_grantable AS is_grantable,
|
||||
CASE (acl).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,
|
||||
defaclobjtype as deftype
|
||||
FROM
|
||||
(SELECT defaclobjtype, aclexplode(defaclacl) as acl FROM pg_catalog.pg_default_acl dacl
|
||||
WHERE dacl.defaclnamespace = 0::OID) d) a
|
||||
LEFT JOIN pg_catalog.pg_roles g ON (a.grantor = g.oid)
|
||||
LEFT JOIN pg_catalog.pg_roles gt ON (a.grantee = gt.oid)
|
||||
GROUP BY g.rolname, gt.rolname, a.deftype
|
||||
ORDER BY a.deftype
|
|
@ -0,0 +1,8 @@
|
|||
{# We need database name before we execute drop #}
|
||||
{% if did %}
|
||||
SELECT db.datname as name FROM pg_database as db WHERE db.oid = {{did}};
|
||||
{% endif %}
|
||||
{# Using name from above query we will drop the database #}
|
||||
{% if datname %}
|
||||
DROP DATABASE {{ conn|qtIdent(datname) }};
|
||||
{% endif %}
|
|
@ -0,0 +1,5 @@
|
|||
SELECT DISTINCT(datctype) AS cname
|
||||
FROM pg_database
|
||||
UNION
|
||||
SELECT DISTINCT(datcollate) AS cname
|
||||
FROM pg_database
|
|
@ -0,0 +1,17 @@
|
|||
{#
|
||||
-- Given SQL is workaround
|
||||
-- We need to implement a mechanism to check for valid supported server encoding
|
||||
#}
|
||||
SELECT * FROM
|
||||
(SELECT pg_encoding_to_char(s.i) AS encoding
|
||||
FROM (SELECT generate_series(0, 100, 1) as i) s) a
|
||||
WHERE encoding != '';
|
||||
|
||||
{#
|
||||
-- For future use, Do not delete
|
||||
--SELECT * FROM
|
||||
--(SELECT s.i as id, pg_encoding_to_char(s.i)
|
||||
-- as encoding
|
||||
-- FROM (SELECT generate_series(0, 100, 1) as i) s) a
|
||||
--WHERE encoding != ''
|
||||
#}
|
|
@ -0,0 +1,4 @@
|
|||
{# We need database name #}
|
||||
{% if did %}
|
||||
SELECT db.datname as name FROM pg_database as db WHERE db.oid = {{did}}
|
||||
{% endif %}
|
|
@ -0,0 +1,7 @@
|
|||
SELECT
|
||||
db.oid as did, db.datname as name, ta.spcname as spcname, db.datallowconn,
|
||||
has_database_privilege(db.oid, 'CREATE') as cancreate
|
||||
FROM
|
||||
pg_database db
|
||||
LEFT OUTER JOIN pg_tablespace ta ON db.dattablespace = ta.oid
|
||||
{% if did %}WHERE db.oid={{did}}::int {% endif %}
|
|
@ -0,0 +1,5 @@
|
|||
SELECT rl.*, r.rolname AS user_name, db.datname as db_name
|
||||
FROM pg_db_role_setting AS rl
|
||||
LEFT JOIN pg_roles AS r ON rl.setrole = r.oid
|
||||
LEFT JOIN pg_database AS db ON rl.setdatabase = db.oid
|
||||
WHERE setdatabase = {{did}}
|
|
@ -0,0 +1,45 @@
|
|||
{#
|
||||
# CREATE DATABSE does not allow us to run any
|
||||
# other sql statments along with it, so we wrote
|
||||
# seprate sql for rest alter sql statments here
|
||||
#}
|
||||
{% import 'macros/variable.macros' as VARIABLE %}
|
||||
{% import 'macros/privilege.macros' as PRIVILEGE %}
|
||||
{% import 'macros/default_privilege.macros' as DEFAULT_PRIVILEGE %}
|
||||
{% if data.comments %}
|
||||
COMMENT ON DATABASE {{ conn|qtIdent(data.name) }}
|
||||
IS {{ data.comments|qtLiteral }};
|
||||
{% endif %}
|
||||
|
||||
{# TO generate Variable SQL using macro #}
|
||||
{% if data.variables %}
|
||||
{% for var in data.variables %}
|
||||
{% if var.value == True %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'on') }}
|
||||
{% elif var.value == False %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'off') }}
|
||||
{% else %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, var.value) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.datacl %}
|
||||
{% for priv in data.datacl %}
|
||||
{{ PRIVILEGE.APPLY(conn, 'DATABASE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.deftblacl %}
|
||||
{% for priv in data.deftblacl %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'TABLES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.defseqacl %}
|
||||
{% for priv in data.defseqacl %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'SEQUENCES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.deffuncacl %}
|
||||
{% for priv in data.deffuncacl %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'FUNCTIONS', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
|
@ -0,0 +1,19 @@
|
|||
SELECT
|
||||
db.oid as did, db.datname as name, db.dattablespace AS spcoid,
|
||||
spcname, datallowconn, pg_encoding_to_char(encoding) AS encoding,
|
||||
pg_get_userbyid(datdba) AS datowner, datcollate, datctype, datconnlimit,
|
||||
has_database_privilege(db.oid, 'CREATE') as cancreate,
|
||||
current_setting('default_tablespace') AS default_tablespace,
|
||||
descr.description as comments
|
||||
FROM pg_database db
|
||||
LEFT OUTER JOIN pg_tablespace ta ON db.dattablespace=ta.OID
|
||||
LEFT OUTER JOIN pg_shdescription descr ON (
|
||||
db.oid=descr.objoid AND descr.classoid='pg_database'::regclass
|
||||
)
|
||||
{% if did %}
|
||||
WHERE db.oid= {{did}}::int
|
||||
{% endif %}
|
||||
{% if name %}
|
||||
WHERE db.datname = {{name|qtLiteral}}
|
||||
{% endif %}
|
||||
ORDER BY datname
|
|
@ -0,0 +1,2 @@
|
|||
SELECT name, vartype, min_val, max_val, enumvals
|
||||
FROM pg_settings WHERE context in ('user', 'superuser')
|
|
@ -0,0 +1,33 @@
|
|||
SELECT 'datacl' 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 datacl FROM pg_database db
|
||||
LEFT OUTER JOIN pg_tablespace ta ON db.dattablespace=ta.OID
|
||||
LEFT OUTER JOIN pg_shdescription descr ON (
|
||||
db.oid=descr.objoid AND descr.classoid='pg_database'::regclass)
|
||||
WHERE db.oid = {{ did|qtLiteral }}::OID
|
||||
) acl,
|
||||
(SELECT (d).grantee AS grantee, (d).grantor AS grantor, (d).is_grantable AS is_grantable, (d).privilege_type AS privilege_type
|
||||
FROM (SELECT aclexplode(datacl) as d FROM pg_database db1
|
||||
WHERE db1.oid = {{ did|qtLiteral }}::OID) a) 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,8 @@
|
|||
{% if data %}
|
||||
{% if action == "rename_database" and data.old_name != data.name %}
|
||||
ALTER DATABASE {{ conn|qtIdent(data.old_name) }} RENAME TO {{ conn|qtIdent(data.name) }};
|
||||
{% endif %}{% if action == "tablespace" and data.spcname %}
|
||||
|
||||
ALTER DATABASE {{ conn|qtIdent(data.name) }} SET TABLESPACE {{ conn|qtIdent(data.spcname) }};
|
||||
{% endif %}
|
||||
{% endif %}
|
|
@ -0,0 +1,170 @@
|
|||
{% import 'macros/security.macros' as SECLABLE %}
|
||||
{% import 'macros/variable.macros' as VARIABLE %}
|
||||
{% import 'macros/privilege.macros' as PRIVILEGE %}
|
||||
{% import 'macros/default_privilege.macros' as DEFAULT_PRIVILEGE %}
|
||||
{% if data %}
|
||||
{# To change owner #}
|
||||
{% if data.datowner %}
|
||||
ALTER DATABASE {{ conn|qtIdent(data.name) }} OWNER TO {{ conn|qtIdent(data.datowner) }};
|
||||
{% endif %}
|
||||
{# TO change comments #}
|
||||
{% if data.comments %}
|
||||
COMMENT ON DATABASE {{ conn|qtIdent(data.name) }}
|
||||
IS {{ data.comments|qtLiteral }};
|
||||
{% endif %}
|
||||
{# TO change conn limit #}
|
||||
{% if data.datconnlimit %}
|
||||
ALTER DATABASE {{ conn|qtIdent(data.name) }} WITH CONNECTION LIMIT = {{ data.datconnlimit }};
|
||||
{% endif %}
|
||||
{# To change Security Label #}
|
||||
{% if data.seclabels and data.seclabels|length > 0 %}
|
||||
{% set seclabels = data.seclabels %}
|
||||
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
|
||||
{% for r in seclabels.deleted %}
|
||||
{{ SECLABLE.DROP(conn, 'DATABASE', data.name, r.provider) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in seclabels and seclabels.added|length > 0 %}
|
||||
{% for r in seclabels.added %}
|
||||
{{ SECLABLE.APPLY(conn, 'DATABASE', data.name, r.provider, r.security_label) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
|
||||
{% for r in seclabels.changed %}
|
||||
{{ SECLABLE.APPLY(conn, 'DATABASE', data.name, r.provider, r.security_label) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{# To change Variables #}
|
||||
{% if data.variables and data.variables|length > 0 %}
|
||||
{% set variables = data.variables %}
|
||||
{% if 'deleted' in variables and variables.deleted|length > 0 %}
|
||||
{% for var in variables.deleted %}
|
||||
{{ VARIABLE.RESET(conn, data.name, var.role, var.name) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in variables and variables.added|length > 0 %}
|
||||
{% for var in variables.added %}
|
||||
{% if var.value == True %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'on') }}
|
||||
{% elif var.value == False %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'off') }}
|
||||
{% else %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, var.value) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in variables and variables.changed|length > 0 %}
|
||||
{% for var in variables.changed %}
|
||||
{% if var.value == True %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'on') }}
|
||||
{% elif var.value == False %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'off') }}
|
||||
{% else %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, var.value) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{# To change priviledges #}
|
||||
{% if data.datacl %}
|
||||
{% if 'deleted' in data.datacl %}
|
||||
{% for priv in data.datacl.deleted %}
|
||||
{{ PRIVILEGE.RESETALL(conn, 'DATABASE', priv.grantee, data.name) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in data.datacl %}
|
||||
{% for priv in data.datacl.changed %}
|
||||
{{ PRIVILEGE.RESETALL(conn, 'DATABASE', priv.grantee, data.name) }}
|
||||
{{ PRIVILEGE.APPLY(conn, 'DATABASE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in data.datacl %}
|
||||
{% for priv in data.datacl.added %}
|
||||
{{ PRIVILEGE.APPLY(conn, 'DATABASE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{# To change default priviledges #}
|
||||
{% if data.deftblacl %}
|
||||
{% if 'deleted' in data.deftblacl %}
|
||||
{% for priv in data.deftblacl.deleted %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'TABLES', priv.grantee) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in data.deftblacl %}
|
||||
{% for priv in data.deftblacl.changed %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'TABLES', priv.grantee) }}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'TABLES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in data.deftblacl %}
|
||||
{% for priv in data.deftblacl.added %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'TABLES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{# To change default priviledges #}
|
||||
{% if data.defseqacl %}
|
||||
{% if 'deleted' in data.defseqacl %}
|
||||
{% for priv in data.defseqacl.deleted %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'SEQUENCES', priv.grantee) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in data.defseqacl %}
|
||||
{% for priv in data.defseqacl.changed %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'SEQUENCES', priv.grantee) }}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'SEQUENCES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in data.defseqacl %}
|
||||
{% for priv in data.defseqacl.added %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'SEQUENCES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{# To change default priviledges #}
|
||||
{% if data.deffuncacl %}
|
||||
{% if 'deleted' in data.deffuncacl %}
|
||||
{% for priv in data.deffuncacl.deleted %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'FUNCTIONS', priv.grantee) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in data.deffuncacl %}
|
||||
{% for priv in data.deffuncacl.changed %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'FUNCTIONS', priv.grantee) }}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'FUNCTIONS', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in data.deffuncacl %}
|
||||
{% for priv in data.deffuncacl.added %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'FUNCTIONS', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{# To change default priviledges #}
|
||||
{% if data.deftypeacl %}
|
||||
{% if 'deleted' in data.deftypeacl %}
|
||||
{% for priv in data.deftypeacl.deleted %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'TYPES', priv.grantee) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in data.deftypeacl %}
|
||||
{% for priv in data.deftypeacl.changed %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'TYPES', priv.grantee) }}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'TYPES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in data.deftypeacl %}
|
||||
{% for priv in data.deftypeacl.added %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'TYPES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
|
@ -0,0 +1,19 @@
|
|||
{% if data %}
|
||||
CREATE DATABASE {{ conn|qtIdent(data.name) }}
|
||||
{% if data.datowner %}
|
||||
WITH {% endif %}{% if data.datowner %}
|
||||
|
||||
OWNER = {{ conn|qtIdent(data.datowner) }}{% endif %}{% if data.template %}
|
||||
|
||||
TEMPLATE = {{ conn|qtIdent(data.template) }}{% endif %}{% if data.encoding %}
|
||||
|
||||
ENCODING = {{ data.encoding|qtLiteral }}{% endif %}{% if data.datcollate %}
|
||||
|
||||
LC_COLLATE = {{ data.datcollate|qtLiteral }}{% endif %}{% if data.datctype %}
|
||||
|
||||
LC_CTYPE = {{ data.datctype|qtLiteral }}{% endif %}{% if data.spcname %}
|
||||
|
||||
TABLESPACE = {{ conn|qtIdent(data.spcname) }}{% endif %}{% if data.datconnlimit %}
|
||||
|
||||
CONNECTION LIMIT = {{ data.datconnlimit }}{% endif %};
|
||||
{% endif %}
|
|
@ -0,0 +1,34 @@
|
|||
SELECT
|
||||
CASE (a.deftype)
|
||||
WHEN 'r' THEN 'deftblacl'
|
||||
WHEN 'S' THEN 'defseqacl'
|
||||
WHEN 'f' THEN 'deffuncacl'
|
||||
WHEN 'T' THEN 'deftypeacl'
|
||||
END AS deftype,
|
||||
COALESCE(gt.rolname, 'public') grantee, g.rolname grantor, array_agg(a.privilege_type) as privileges, array_agg(a.is_grantable) as grantable
|
||||
FROM
|
||||
(SELECT
|
||||
(acl).grantee as grantee, (acl).grantor AS grantor, (acl).is_grantable AS is_grantable,
|
||||
CASE (acl).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,
|
||||
defaclobjtype as deftype
|
||||
FROM
|
||||
(SELECT defaclobjtype, aclexplode(defaclacl) as acl FROM pg_catalog.pg_default_acl dacl
|
||||
WHERE dacl.defaclnamespace = 0::OID) d) a
|
||||
LEFT JOIN pg_catalog.pg_roles g ON (a.grantor = g.oid)
|
||||
LEFT JOIN pg_catalog.pg_roles gt ON (a.grantee = gt.oid)
|
||||
GROUP BY g.rolname, gt.rolname, a.deftype
|
||||
ORDER BY a.deftype
|
|
@ -0,0 +1,8 @@
|
|||
{# We need database name before we execute drop #}
|
||||
{% if did %}
|
||||
SELECT db.datname as name FROM pg_database as db WHERE db.oid = {{did}}
|
||||
{% endif %}
|
||||
{# Using name from above query we will drop the database #}
|
||||
{% if datname %}
|
||||
DROP DATABASE {{ conn|qtIdent(datname) }};
|
||||
{% endif %}
|
|
@ -0,0 +1,5 @@
|
|||
SELECT DISTINCT(datctype) AS cname
|
||||
FROM pg_database
|
||||
UNION
|
||||
SELECT DISTINCT(datcollate) AS cname
|
||||
FROM pg_database
|
|
@ -0,0 +1,17 @@
|
|||
{#
|
||||
-- Given SQL is workaround
|
||||
-- We need to implement a mechanism to check for valid supported server encoding
|
||||
#}
|
||||
SELECT * FROM
|
||||
(SELECT pg_encoding_to_char(s.i) AS encoding
|
||||
FROM (SELECT generate_series(0, 100, 1) as i) s) a
|
||||
WHERE encoding != '';
|
||||
|
||||
{#
|
||||
-- For future use, Do not delete
|
||||
--SELECT * FROM
|
||||
--(SELECT s.i as id, pg_encoding_to_char(s.i)
|
||||
-- as encoding
|
||||
-- FROM (SELECT generate_series(0, 100, 1) as i) s) a
|
||||
--WHERE encoding != ''
|
||||
#}
|
|
@ -0,0 +1,4 @@
|
|||
{# We need database name #}
|
||||
{% if did %}
|
||||
SELECT db.datname as name FROM pg_database as db WHERE db.oid = {{did}}
|
||||
{% endif %}
|
|
@ -0,0 +1,7 @@
|
|||
SELECT
|
||||
db.oid as did, db.datname as name, ta.spcname as spcname, db.datallowconn,
|
||||
has_database_privilege(db.oid, 'CREATE') as cancreate
|
||||
FROM
|
||||
pg_database db
|
||||
LEFT OUTER JOIN pg_tablespace ta ON db.dattablespace = ta.oid
|
||||
{% if did %}WHERE db.oid={{did}}::int {% endif %}
|
|
@ -0,0 +1,5 @@
|
|||
SELECT rl.*, r.rolname AS user_name, db.datname as db_name
|
||||
FROM pg_db_role_setting AS rl
|
||||
LEFT JOIN pg_roles AS r ON rl.setrole = r.oid
|
||||
LEFT JOIN pg_database AS db ON rl.setdatabase = db.oid
|
||||
WHERE setdatabase = {{did}}
|
|
@ -0,0 +1,57 @@
|
|||
{#
|
||||
# CREATE DATABSE does not allow us to run any
|
||||
# other sql statments along with it, so we wrote
|
||||
# seprate sql for rest alter sql statments here
|
||||
#}
|
||||
{% import 'macros/security.macros' as SECLABLE %}
|
||||
{% import 'macros/variable.macros' as VARIABLE %}
|
||||
{% import 'macros/privilege.macros' as PRIVILEGE %}
|
||||
{% import 'macros/default_privilege.macros' as DEFAULT_PRIVILEGE %}
|
||||
{% if data.comments %}
|
||||
COMMENT ON DATABASE {{ conn|qtIdent(data.name) }}
|
||||
IS {{ data.comments|qtLiteral }};
|
||||
{% endif %}
|
||||
|
||||
{# To generate Security Label SQL using macro #}
|
||||
{% if data.securities %}
|
||||
{% for r in data.securities %}
|
||||
{{ SECLABLE.APPLY(conn, 'DATABASE', data.name, r.provider, r.securitylabel) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{# To generate Variable SQL using macro #}
|
||||
{% if data.variables %}
|
||||
{% for var in data.variables %}
|
||||
{% if var.value == True %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'on') }}
|
||||
{% elif var.value == False %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'off') }}
|
||||
{% else %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, var.value) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.datacl %}
|
||||
{% for priv in data.datacl %}
|
||||
{{ PRIVILEGE.APPLY(conn, 'DATABASE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.deftblacl %}
|
||||
{% for priv in data.deftblacl %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'TABLES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.defseqacl %}
|
||||
{% for priv in data.defseqacl %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'SEQUENCES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.deffuncacl %}
|
||||
{% for priv in data.deffuncacl %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'FUNCTIONS', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.deftypeacl %}
|
||||
{% for priv in data.deftypeacl %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'TYPES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
|
@ -0,0 +1,20 @@
|
|||
SELECT
|
||||
db.oid as did, db.datname as name, db.dattablespace AS spcoid,
|
||||
spcname, datallowconn, pg_encoding_to_char(encoding) AS encoding,
|
||||
pg_get_userbyid(datdba) AS datowner, datcollate, datctype, datconnlimit,
|
||||
has_database_privilege(db.oid, 'CREATE') as cancreate,
|
||||
current_setting('default_tablespace') AS default_tablespace,
|
||||
descr.description as comments
|
||||
,(SELECT array_agg(provider || '=' || label) FROM pg_shseclabel sl1 WHERE sl1.objoid=db.oid) AS seclabels
|
||||
FROM pg_database db
|
||||
LEFT OUTER JOIN pg_tablespace ta ON db.dattablespace=ta.OID
|
||||
LEFT OUTER JOIN pg_shdescription descr ON (
|
||||
db.oid=descr.objoid AND descr.classoid='pg_database'::regclass
|
||||
)
|
||||
{% if did %}
|
||||
WHERE db.oid= {{did}}::int
|
||||
{% endif %}
|
||||
{% if name %}
|
||||
WHERE db.datname = {{name|qtLiteral}}
|
||||
{% endif %}
|
||||
ORDER BY datname
|
|
@ -0,0 +1 @@
|
|||
SELECT name, vartype, min_val, max_val, enumvals FROM pg_settings WHERE context in ('user', 'superuser')
|
|
@ -0,0 +1,33 @@
|
|||
SELECT 'datacl' 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 datacl FROM pg_database db
|
||||
LEFT OUTER JOIN pg_tablespace ta ON db.dattablespace=ta.OID
|
||||
LEFT OUTER JOIN pg_shdescription descr ON (
|
||||
db.oid=descr.objoid AND descr.classoid='pg_database'::regclass)
|
||||
{% if did %}
|
||||
WHERE db.oid = {{ did|qtLiteral }}::OID
|
||||
{% endif %}
|
||||
) acl,
|
||||
aclexplode(datacl) 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,8 @@
|
|||
{% if data %}
|
||||
{% if action == "rename_database" and data.old_name != data.name %}
|
||||
ALTER DATABASE {{ conn|qtIdent(data.old_name) }} RENAME TO {{ conn|qtIdent(data.name) }};
|
||||
{% endif %}{% if action == "tablespace" and data.spcname %}
|
||||
|
||||
ALTER DATABASE {{ conn|qtIdent(data.name) }} SET TABLESPACE {{ conn|qtIdent(data.spcname) }};
|
||||
{% endif %}
|
||||
{% endif %}
|
|
@ -0,0 +1,166 @@
|
|||
{% import 'macros/security.macros' as SECLABLE %}
|
||||
{% import 'macros/variable.macros' as VARIABLE %}
|
||||
{% import 'macros/privilege.macros' as PRIVILEGE %}
|
||||
{% import 'macros/default_privilege.macros' as DEFAULT_PRIVILEGE %}
|
||||
{% if data %}
|
||||
{# The SQL generated below will change owner #}
|
||||
{% if data.datowner %}
|
||||
ALTER DATABASE {{ conn|qtIdent(data.name) }} OWNER TO {{ conn|qtIdent(data.datowner) }};
|
||||
{% endif %}
|
||||
{# The SQL generated below will change comments #}
|
||||
{% if data.comments %}
|
||||
COMMENT ON DATABASE {{ conn|qtIdent(data.name) }}
|
||||
IS {{ data.comments|qtLiteral }};
|
||||
{% endif %}
|
||||
{# The SQL generated below will change conn limit #}
|
||||
{% if data.datconnlimit %}
|
||||
ALTER DATABASE {{ conn|qtIdent(data.name) }} WITH CONNECTION LIMIT = {{ data.datconnlimit }};
|
||||
{% endif %}
|
||||
{# The SQL generated below will change Security Label #}
|
||||
{% if data.seclabels and data.seclabels|length > 0 %}
|
||||
{% set seclabels = data.seclabels %}
|
||||
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
|
||||
{% for r in seclabels.deleted %}
|
||||
{{ SECLABLE.DROP(conn, 'DATABASE', data.name, r.provider) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in seclabels and seclabels.added|length > 0 %}
|
||||
{% for r in seclabels.added %}
|
||||
{{ SECLABLE.APPLY(conn, 'DATABASE', data.name, r.provider, r.security_label) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
|
||||
{% for r in seclabels.changed %}
|
||||
{{ SECLABLE.APPLY(conn, 'DATABASE', data.name, r.provider, r.security_label) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{# The SQL generated below will change Variables #}
|
||||
{% if data.variables and data.variables|length > 0 %}
|
||||
{% set variables = data.variables %}
|
||||
{% if 'deleted' in variables and variables.deleted|length > 0 %}
|
||||
{% for var in variables.deleted %}
|
||||
{{ VARIABLE.RESET(conn, data.name, var.role, var.name) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in variables and variables.added|length > 0 %}
|
||||
{% for var in variables.added %}
|
||||
{% if var.value == True %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'on') }}
|
||||
{% elif var.value == False %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'off') }}
|
||||
{% else %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, var.value) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in variables and variables.changed|length > 0 %}
|
||||
{% for var in variables.changed %}
|
||||
{% if var.value == True %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'on') }}
|
||||
{% elif var.value == False %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'off') }}
|
||||
{% else %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, var.value) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{# The SQL generated below will change priviledges #}
|
||||
{% if data.datacl %}
|
||||
{% if 'deleted' in data.datacl %}
|
||||
{% for priv in data.datacl.deleted %}
|
||||
{{ PRIVILEGE.RESETALL(conn, 'DATABASE', priv.grantee, data.name) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in data.datacl %}
|
||||
{% for priv in data.datacl.changed %}
|
||||
{{ PRIVILEGE.RESETALL(conn, 'DATABASE', priv.grantee, data.name) }}
|
||||
{{ PRIVILEGE.APPLY(conn, 'DATABASE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in data.datacl %}
|
||||
{% for priv in data.datacl.added %}
|
||||
{{ PRIVILEGE.APPLY(conn, 'DATABASE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if data.deftblacl %}
|
||||
{% if 'deleted' in data.deftblacl %}
|
||||
{% for priv in data.deftblacl.deleted %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'TABLES', priv.grantee) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in data.deftblacl %}
|
||||
{% for priv in data.deftblacl.changed %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'TABLES', priv.grantee) }}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'TABLES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in data.deftblacl %}
|
||||
{% for priv in data.deftblacl.added %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'TABLES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if data.defseqacl %}
|
||||
{% if 'deleted' in data.defseqacl %}
|
||||
{% for priv in data.defseqacl.deleted %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'SEQUENCES', priv.grantee) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in data.defseqacl %}
|
||||
{% for priv in data.defseqacl.changed %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'SEQUENCES', priv.grantee) }}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'SEQUENCES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in data.defseqacl %}
|
||||
{% for priv in data.defseqacl.added %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'SEQUENCES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if data.deffuncacl %}
|
||||
{% if 'deleted' in data.deffuncacl %}
|
||||
{% for priv in data.deffuncacl.deleted %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'FUNCTIONS', priv.grantee) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in data.deffuncacl %}
|
||||
{% for priv in data.deffuncacl.changed %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'FUNCTIONS', priv.grantee) }}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'FUNCTIONS', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in data.deffuncacl %}
|
||||
{% for priv in data.deffuncacl.added %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'FUNCTIONS', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if data.deftypeacl %}
|
||||
{% if 'deleted' in data.deftypeacl %}
|
||||
{% for priv in data.deftypeacl.deleted %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'TYPES', priv.grantee) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in data.deftypeacl %}
|
||||
{% for priv in data.deftypeacl.changed %}
|
||||
{{ DEFAULT_PRIVILEGE.RESETALL(conn, 'TYPES', priv.grantee) }}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'TYPES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in data.deftypeacl %}
|
||||
{% for priv in data.deftypeacl.added %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'TYPES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
|
@ -0,0 +1,19 @@
|
|||
{% if data %}
|
||||
CREATE DATABASE {{ conn|qtIdent(data.name) }}
|
||||
{% if data.datowner %}
|
||||
WITH {% endif %}{% if data.datowner %}
|
||||
|
||||
OWNER = {{ conn|qtIdent(data.datowner) }}{% endif %}{% if data.template %}
|
||||
|
||||
TEMPLATE = {{ conn|qtIdent(data.template) }}{% endif %}{% if data.encoding %}
|
||||
|
||||
ENCODING = {{ data.encoding|qtLiteral }}{% endif %}{% if data.datcollate %}
|
||||
|
||||
LC_COLLATE = {{ data.datcollate|qtLiteral }}{% endif %}{% if data.datctype %}
|
||||
|
||||
LC_CTYPE = {{ data.datctype|qtLiteral }}{% endif %}{% if data.spcname %}
|
||||
|
||||
TABLESPACE = {{ conn|qtIdent(data.spcname) }}{% endif %}{% if data.datconnlimit %}
|
||||
|
||||
CONNECTION LIMIT = {{ data.datconnlimit }}{% endif %};
|
||||
{% endif %}
|
|
@ -0,0 +1,34 @@
|
|||
SELECT
|
||||
CASE (a.deftype)
|
||||
WHEN 'r' THEN 'deftblacl'
|
||||
WHEN 'S' THEN 'defseqacl'
|
||||
WHEN 'f' THEN 'deffuncacl'
|
||||
WHEN 'T' THEN 'deftypeacl'
|
||||
END AS deftype,
|
||||
COALESCE(gt.rolname, 'public') grantee, g.rolname grantor, array_agg(a.privilege_type) as privileges, array_agg(a.is_grantable) as grantable
|
||||
FROM
|
||||
(SELECT
|
||||
(acl).grantee as grantee, (acl).grantor AS grantor, (acl).is_grantable AS is_grantable,
|
||||
CASE (acl).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,
|
||||
defaclobjtype as deftype
|
||||
FROM
|
||||
(SELECT defaclobjtype, aclexplode(defaclacl) as acl FROM pg_catalog.pg_default_acl dacl
|
||||
WHERE dacl.defaclnamespace = 0::OID) d) a
|
||||
LEFT JOIN pg_catalog.pg_roles g ON (a.grantor = g.oid)
|
||||
LEFT JOIN pg_catalog.pg_roles gt ON (a.grantee = gt.oid)
|
||||
GROUP BY g.rolname, gt.rolname, a.deftype
|
||||
ORDER BY a.deftype
|
|
@ -0,0 +1,8 @@
|
|||
{# We need database name before we execute drop #}
|
||||
{% if did %}
|
||||
SELECT db.datname as name FROM pg_database as db WHERE db.oid = {{did}}
|
||||
{% endif %}
|
||||
{# Using name from above query we will drop the database #}
|
||||
{% if datname %}
|
||||
DROP DATABASE {{ conn|qtIdent(datname) }};
|
||||
{% endif %}
|
|
@ -0,0 +1,5 @@
|
|||
SELECT DISTINCT(datctype) AS cname
|
||||
FROM pg_database
|
||||
UNION
|
||||
SELECT DISTINCT(datcollate) AS cname
|
||||
FROM pg_database
|
|
@ -0,0 +1,17 @@
|
|||
{#
|
||||
-- Given SQL is workaround
|
||||
-- We need to implement a mechanism to check for valid supported server encoding
|
||||
#}
|
||||
SELECT * FROM
|
||||
(SELECT pg_encoding_to_char(s.i) AS encoding
|
||||
FROM (SELECT generate_series(0, 100, 1) as i) s) a
|
||||
WHERE encoding != '';
|
||||
|
||||
{#
|
||||
-- For future use, Do not delete
|
||||
--SELECT * FROM
|
||||
--(SELECT s.i as id, pg_encoding_to_char(s.i)
|
||||
-- as encoding
|
||||
-- FROM (SELECT generate_series(0, 100, 1) as i) s) a
|
||||
--WHERE encoding != ''
|
||||
#}
|
|
@ -0,0 +1,4 @@
|
|||
{# We need database name #}
|
||||
{% if did %}
|
||||
SELECT db.datname as name FROM pg_database as db WHERE db.oid = {{did}}
|
||||
{% endif %}
|
|
@ -0,0 +1,7 @@
|
|||
SELECT
|
||||
db.oid as did, db.datname as name, ta.spcname as spcname, db.datallowconn,
|
||||
has_database_privilege(db.oid, 'CREATE') as cancreate
|
||||
FROM
|
||||
pg_database db
|
||||
LEFT OUTER JOIN pg_tablespace ta ON db.dattablespace = ta.oid
|
||||
{% if did %}WHERE db.oid={{did}}::int {% endif %}
|
|
@ -0,0 +1,5 @@
|
|||
SELECT rl.*, r.rolname AS user_name, db.datname as db_name
|
||||
FROM pg_db_role_setting AS rl
|
||||
LEFT JOIN pg_roles AS r ON rl.setrole = r.oid
|
||||
LEFT JOIN pg_database AS db ON rl.setdatabase = db.oid
|
||||
WHERE setdatabase = {{did}}
|
|
@ -0,0 +1,57 @@
|
|||
{#
|
||||
# CREATE DATABSE does not allow us to run any
|
||||
# other sql statments along with it, so we wrote
|
||||
# seprate sql for rest alter sql statments here
|
||||
#}
|
||||
{% import 'macros/security.macros' as SECLABLE %}
|
||||
{% import 'macros/variable.macros' as VARIABLE %}
|
||||
{% import 'macros/privilege.macros' as PRIVILEGE %}
|
||||
{% import 'macros/default_privilege.macros' as DEFAULT_PRIVILEGE %}
|
||||
{% if data.comments %}
|
||||
COMMENT ON DATABASE {{ conn|qtIdent(data.name) }}
|
||||
IS {{ data.comments|qtLiteral }};
|
||||
{% endif %}
|
||||
|
||||
{# We will generate Security Label SQL's using macro #}
|
||||
{% if data.securities %}
|
||||
{% for r in data.securities %}
|
||||
{{ SECLABLE.APPLY(conn, 'DATABASE', data.name, r.provider, r.securitylabel) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{# We will generate Variable SQL's using macro #}
|
||||
{% if data.variables %}
|
||||
{% for var in data.variables %}
|
||||
{% if var.value == True %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'on') }}
|
||||
{% elif var.value == False %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, 'off') }}
|
||||
{% else %}
|
||||
{{ VARIABLE.APPLY(conn, data.name, var.role, var.name, var.value) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.datacl %}
|
||||
{% for priv in data.datacl %}
|
||||
{{ PRIVILEGE.APPLY(conn, 'DATABASE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.deftblacl %}
|
||||
{% for priv in data.deftblacl %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'TABLES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.defseqacl %}
|
||||
{% for priv in data.defseqacl %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'SEQUENCES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.deffuncacl %}
|
||||
{% for priv in data.deffuncacl %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'FUNCTIONS', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if data.deftypeacl %}
|
||||
{% for priv in data.deftypeacl %}
|
||||
{{ DEFAULT_PRIVILEGE.APPLY(conn, 'TYPES', priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
|
@ -0,0 +1,20 @@
|
|||
SELECT
|
||||
db.oid as did, db.datname as name, db.dattablespace AS spcoid,
|
||||
spcname, datallowconn, pg_encoding_to_char(encoding) AS encoding,
|
||||
pg_get_userbyid(datdba) AS datowner, datcollate, datctype, datconnlimit,
|
||||
has_database_privilege(db.oid, 'CREATE') as cancreate,
|
||||
current_setting('default_tablespace') AS default_tablespace,
|
||||
descr.description as comments
|
||||
,(SELECT array_agg(provider || '=' || label) FROM pg_shseclabel sl1 WHERE sl1.objoid=db.oid) AS seclabels
|
||||
FROM pg_database db
|
||||
LEFT OUTER JOIN pg_tablespace ta ON db.dattablespace=ta.OID
|
||||
LEFT OUTER JOIN pg_shdescription descr ON (
|
||||
db.oid=descr.objoid AND descr.classoid='pg_database'::regclass
|
||||
)
|
||||
{% if did %}
|
||||
WHERE db.oid= {{did}}::int
|
||||
{% endif %}
|
||||
{% if name %}
|
||||
WHERE db.datname = {{name|qtLiteral}}
|
||||
{% endif %}
|
||||
ORDER BY datname
|
|
@ -0,0 +1 @@
|
|||
SELECT name, vartype, min_val, max_val, enumvals FROM pg_settings WHERE context in ('user', 'superuser')
|
Loading…
Reference in New Issue