diff --git a/web/pgadmin/browser/server_groups/servers/databases/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/__init__.py new file mode 100644 index 000000000..76f40c112 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/__init__.py @@ -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) diff --git a/web/pgadmin/browser/server_groups/servers/databases/static/img/coll-database.png b/web/pgadmin/browser/server_groups/servers/databases/static/img/coll-database.png new file mode 100755 index 000000000..bfc0966c2 Binary files /dev/null and b/web/pgadmin/browser/server_groups/servers/databases/static/img/coll-database.png differ diff --git a/web/pgadmin/browser/server_groups/servers/databases/static/img/database.png b/web/pgadmin/browser/server_groups/servers/databases/static/img/database.png new file mode 100755 index 000000000..1a743d7a3 Binary files /dev/null and b/web/pgadmin/browser/server_groups/servers/databases/static/img/database.png differ diff --git a/web/pgadmin/browser/server_groups/servers/databases/static/img/databasebad.png b/web/pgadmin/browser/server_groups/servers/databases/static/img/databasebad.png new file mode 100644 index 000000000..968329087 Binary files /dev/null and b/web/pgadmin/browser/server_groups/servers/databases/static/img/databasebad.png differ diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/css/database.css b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/css/database.css new file mode 100644 index 000000000..f59bc8e69 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/css/database.css @@ -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 +} diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/js/databases.js b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/js/databases.js new file mode 100644 index 000000000..5f34cfd8c --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/js/databases.js @@ -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']; +}); \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/acl.sql new file mode 100644 index 000000000..2944f1353 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/acl.sql @@ -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 \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/alter_offline.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/alter_offline.sql new file mode 100644 index 000000000..afebb6c2f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/alter_offline.sql @@ -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 %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/alter_online.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/alter_online.sql new file mode 100644 index 000000000..7ca0b527e --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/alter_online.sql @@ -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 %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/create.sql new file mode 100644 index 000000000..d627f115e --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/create.sql @@ -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 %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/defacl.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/defacl.sql new file mode 100644 index 000000000..e36e30a52 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/defacl.sql @@ -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 \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/delete.sql new file mode 100644 index 000000000..3d387714f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/delete.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/get_ctypes.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/get_ctypes.sql new file mode 100644 index 000000000..46246ef65 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/get_ctypes.sql @@ -0,0 +1,5 @@ +SELECT DISTINCT(datctype) AS cname +FROM pg_database +UNION +SELECT DISTINCT(datcollate) AS cname +FROM pg_database \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/get_encodings.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/get_encodings.sql new file mode 100644 index 000000000..fc2f61775 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/get_encodings.sql @@ -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 != '' +#} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/get_name.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/get_name.sql new file mode 100644 index 000000000..cdbbc8299 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/get_name.sql @@ -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 %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/get_nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/get_nodes.sql new file mode 100644 index 000000000..87e32e50f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/get_nodes.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/get_variables.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/get_variables.sql new file mode 100644 index 000000000..d76d02b3f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/get_variables.sql @@ -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}} diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/grant.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/grant.sql new file mode 100644 index 000000000..f7c402941 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/grant.sql @@ -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 %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/properties.sql new file mode 100644 index 000000000..0d241cdc2 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/properties.sql @@ -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 diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/variables.sql new file mode 100644 index 000000000..b4e59ec64 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.1_plus/variables.sql @@ -0,0 +1,2 @@ +SELECT name, vartype, min_val, max_val, enumvals +FROM pg_settings WHERE context in ('user', 'superuser') \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/acl.sql new file mode 100644 index 000000000..d08398e13 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/acl.sql @@ -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 \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/alter_offline.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/alter_offline.sql new file mode 100644 index 000000000..afebb6c2f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/alter_offline.sql @@ -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 %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/alter_online.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/alter_online.sql new file mode 100644 index 000000000..c713bf597 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/alter_online.sql @@ -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 %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/create.sql new file mode 100644 index 000000000..d627f115e --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/create.sql @@ -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 %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/defacl.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/defacl.sql new file mode 100644 index 000000000..e36e30a52 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/defacl.sql @@ -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 \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/delete.sql new file mode 100644 index 000000000..042113e40 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/delete.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/get_ctypes.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/get_ctypes.sql new file mode 100644 index 000000000..46246ef65 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/get_ctypes.sql @@ -0,0 +1,5 @@ +SELECT DISTINCT(datctype) AS cname +FROM pg_database +UNION +SELECT DISTINCT(datcollate) AS cname +FROM pg_database \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/get_encodings.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/get_encodings.sql new file mode 100644 index 000000000..fc2f61775 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/get_encodings.sql @@ -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 != '' +#} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/get_name.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/get_name.sql new file mode 100644 index 000000000..cdbbc8299 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/get_name.sql @@ -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 %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/get_nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/get_nodes.sql new file mode 100644 index 000000000..87e32e50f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/get_nodes.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/get_variables.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/get_variables.sql new file mode 100644 index 000000000..71630ec39 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/get_variables.sql @@ -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}} diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/grant.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/grant.sql new file mode 100644 index 000000000..2c07f2977 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/grant.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/properties.sql new file mode 100644 index 000000000..9f3c3ff03 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/properties.sql @@ -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 diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/variables.sql new file mode 100644 index 000000000..b316dbd8b --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.2_plus/variables.sql @@ -0,0 +1 @@ +SELECT name, vartype, min_val, max_val, enumvals FROM pg_settings WHERE context in ('user', 'superuser') \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/acl.sql new file mode 100644 index 000000000..802cfdcf0 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/acl.sql @@ -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 \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/alter_offline.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/alter_offline.sql new file mode 100644 index 000000000..afebb6c2f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/alter_offline.sql @@ -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 %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/alter_online.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/alter_online.sql new file mode 100644 index 000000000..6923f9333 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/alter_online.sql @@ -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 %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/create.sql new file mode 100644 index 000000000..d627f115e --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/create.sql @@ -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 %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/defacl.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/defacl.sql new file mode 100644 index 000000000..e36e30a52 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/defacl.sql @@ -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 \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/delete.sql new file mode 100644 index 000000000..042113e40 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/delete.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/get_ctypes.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/get_ctypes.sql new file mode 100644 index 000000000..46246ef65 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/get_ctypes.sql @@ -0,0 +1,5 @@ +SELECT DISTINCT(datctype) AS cname +FROM pg_database +UNION +SELECT DISTINCT(datcollate) AS cname +FROM pg_database \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/get_encodings.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/get_encodings.sql new file mode 100644 index 000000000..fc2f61775 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/get_encodings.sql @@ -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 != '' +#} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/get_name.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/get_name.sql new file mode 100644 index 000000000..cdbbc8299 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/get_name.sql @@ -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 %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/get_nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/get_nodes.sql new file mode 100644 index 000000000..87e32e50f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/get_nodes.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/get_variables.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/get_variables.sql new file mode 100644 index 000000000..71630ec39 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/get_variables.sql @@ -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}} diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/grant.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/grant.sql new file mode 100644 index 000000000..6056bd7eb --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/grant.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/properties.sql new file mode 100644 index 000000000..9f3c3ff03 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/properties.sql @@ -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 diff --git a/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/variables.sql b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/variables.sql new file mode 100644 index 000000000..b316dbd8b --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/templates/databases/sql/9.3_plus/variables.sql @@ -0,0 +1 @@ +SELECT name, vartype, min_val, max_val, enumvals FROM pg_settings WHERE context in ('user', 'superuser') \ No newline at end of file