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 Joshi
pull/3/head
Ashesh Vashi 2016-02-05 13:06:46 +05:30
parent 3ca29b18b5
commit 657f14997b
48 changed files with 2232 additions and 0 deletions

View File

@ -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)

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

View File

@ -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
}

View File

@ -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'];
});

View File

@ -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

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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

View File

@ -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 %}

View File

@ -0,0 +1,5 @@
SELECT DISTINCT(datctype) AS cname
FROM pg_database
UNION
SELECT DISTINCT(datcollate) AS cname
FROM pg_database

View File

@ -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 != ''
#}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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}}

View File

@ -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 %}

View File

@ -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

View File

@ -0,0 +1,2 @@
SELECT name, vartype, min_val, max_val, enumvals
FROM pg_settings WHERE context in ('user', 'superuser')

View File

@ -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

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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

View File

@ -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 %}

View File

@ -0,0 +1,5 @@
SELECT DISTINCT(datctype) AS cname
FROM pg_database
UNION
SELECT DISTINCT(datcollate) AS cname
FROM pg_database

View File

@ -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 != ''
#}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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}}

View File

@ -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 %}

View File

@ -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

View File

@ -0,0 +1 @@
SELECT name, vartype, min_val, max_val, enumvals FROM pg_settings WHERE context in ('user', 'superuser')

View File

@ -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

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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

View File

@ -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 %}

View File

@ -0,0 +1,5 @@
SELECT DISTINCT(datctype) AS cname
FROM pg_database
UNION
SELECT DISTINCT(datcollate) AS cname
FROM pg_database

View File

@ -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 != ''
#}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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}}

View File

@ -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 %}

View File

@ -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

View File

@ -0,0 +1 @@
SELECT name, vartype, min_val, max_val, enumvals FROM pg_settings WHERE context in ('user', 'superuser')