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