Support CREATE LANGUAGE. Fixes #1252
parent
013ff1090e
commit
7dffb020f1
|
|
@ -13,7 +13,7 @@ import simplejson as json
|
|||
from functools import wraps
|
||||
|
||||
import pgadmin.browser.server_groups.servers.databases as databases
|
||||
from flask import render_template, make_response, request
|
||||
from flask import render_template, make_response, request, jsonify
|
||||
from flask_babel import gettext
|
||||
from pgadmin.browser.collection import CollectionNodeModule
|
||||
from pgadmin.browser.server_groups.servers.utils import parse_priv_from_db, \
|
||||
|
|
@ -133,6 +133,12 @@ class LanguageView(PGChildNodeView):
|
|||
* update(gid, sid, did, lid)
|
||||
- This function will update the data for the selected language node
|
||||
|
||||
* create(gid, sid, did)
|
||||
- This function will create the new language node
|
||||
|
||||
* delete(gid, sid, did, lid)
|
||||
- This function will delete the selected language node
|
||||
|
||||
* msql(gid, sid, did, lid)
|
||||
- This function is used to return modified SQL for the selected language node
|
||||
|
||||
|
|
@ -142,6 +148,9 @@ class LanguageView(PGChildNodeView):
|
|||
* get_functions(gid, sid, did)
|
||||
- This function returns the handler and inline functions for the selected language node
|
||||
|
||||
* get_templates(gid, sid, did)
|
||||
- This function returns language templates.
|
||||
|
||||
* sql(gid, sid, did, lid):
|
||||
- This function will generate sql to show it in sql pane for the selected language node.
|
||||
|
||||
|
|
@ -165,8 +174,8 @@ class LanguageView(PGChildNodeView):
|
|||
|
||||
operations = dict({
|
||||
'obj': [
|
||||
{'get': 'properties', 'put': 'update'},
|
||||
{'get': 'list'}
|
||||
{'get': 'properties', 'delete': 'delete', 'put': 'update'},
|
||||
{'get': 'list', 'post': 'create'}
|
||||
],
|
||||
'nodes': [{'get': 'node'}, {'get': 'nodes'}],
|
||||
'sql': [{'get': 'sql'}],
|
||||
|
|
@ -175,7 +184,9 @@ class LanguageView(PGChildNodeView):
|
|||
'dependency': [{'get': 'dependencies'}],
|
||||
'dependent': [{'get': 'dependents'}],
|
||||
'module.js': [{}, {}, {'get': 'module_js'}],
|
||||
'get_functions': [{}, {'get': 'get_functions'}]
|
||||
'get_functions': [{}, {'get': 'get_functions'}],
|
||||
'get_templates': [{}, {'get': 'get_templates'}],
|
||||
'delete': [{'delete': 'delete'}]
|
||||
})
|
||||
|
||||
def _init_(self, **kwargs):
|
||||
|
|
@ -337,7 +348,6 @@ class LanguageView(PGChildNodeView):
|
|||
|
||||
res['rows'][0]['seclabels'] = seclabels
|
||||
|
||||
|
||||
return ajax_response(
|
||||
response=res['rows'][0],
|
||||
status=200
|
||||
|
|
@ -390,6 +400,110 @@ class LanguageView(PGChildNodeView):
|
|||
except Exception as e:
|
||||
return internal_server_error(errormsg=str(e))
|
||||
|
||||
@check_precondition
|
||||
def create(self, gid, sid, did):
|
||||
"""
|
||||
This function will create the language object
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
"""
|
||||
required_args = [
|
||||
'name'
|
||||
]
|
||||
|
||||
data = request.form if request.form else json.loads(
|
||||
request.data, encoding='utf-8'
|
||||
)
|
||||
for arg in required_args:
|
||||
if arg not in data:
|
||||
return make_json_response(
|
||||
status=410,
|
||||
success=0,
|
||||
errormsg=gettext(
|
||||
"Could not find the required parameter (%s)." % arg
|
||||
)
|
||||
)
|
||||
|
||||
try:
|
||||
if 'lanacl' in data:
|
||||
data['lanacl'] = parse_priv_to_db(data['lanacl'], ['U'])
|
||||
|
||||
sql = render_template("/".join([self.template_path, 'create.sql']),
|
||||
data=data, conn=self.conn)
|
||||
status, res = self.conn.execute_dict(sql)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
sql = render_template("/".join([self.template_path, 'properties.sql']),
|
||||
lanname=data['name'], conn=self.conn)
|
||||
|
||||
status, r_set = self.conn.execute_dict(sql)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=r_set)
|
||||
|
||||
for row in r_set['rows']:
|
||||
return jsonify(
|
||||
node=self.blueprint.generate_browser_node(
|
||||
row['oid'],
|
||||
did,
|
||||
row['name'],
|
||||
icon='icon-language'
|
||||
)
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return internal_server_error(errormsg=str(e))
|
||||
|
||||
@check_precondition
|
||||
def delete(self, gid, sid, did, lid):
|
||||
"""
|
||||
This function will drop the language object
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
lid: Language ID
|
||||
"""
|
||||
if self.cmd == 'delete':
|
||||
# This is a cascade operation
|
||||
cascade = True
|
||||
else:
|
||||
cascade = False
|
||||
|
||||
try:
|
||||
# Get name for language from lid
|
||||
sql = render_template("/".join([self.template_path, 'delete.sql']), lid=lid, conn=self.conn)
|
||||
status, lname = self.conn.execute_scalar(sql)
|
||||
|
||||
if not status:
|
||||
return internal_server_error(errormsg=lname)
|
||||
|
||||
# drop language
|
||||
sql = render_template("/".join([self.template_path, 'delete.sql']), lname=lname,
|
||||
cascade=cascade, conn=self.conn)
|
||||
status, res = self.conn.execute_scalar(sql)
|
||||
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
return make_json_response(
|
||||
success=1,
|
||||
info=gettext("Language dropped"),
|
||||
data={
|
||||
'id': lid,
|
||||
'did': did,
|
||||
'sid': sid,
|
||||
'gid': gid,
|
||||
}
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
return internal_server_error(errormsg=str(e))
|
||||
|
||||
@check_precondition
|
||||
def msql(self, gid, sid, did, lid=None):
|
||||
"""
|
||||
|
|
@ -454,6 +568,13 @@ class LanguageView(PGChildNodeView):
|
|||
data[arg] = old_data[arg]
|
||||
sql = render_template("/".join([self.template_path, 'update.sql']), data=data,
|
||||
o_data=old_data, conn=self.conn)
|
||||
else:
|
||||
|
||||
if 'lanacl' in data:
|
||||
data['lanacl'] = parse_priv_to_db(data['lanacl'], 'LANGUAGE')
|
||||
|
||||
sql = render_template("/".join([self.template_path, 'create.sql']),
|
||||
data=data, conn=self.conn)
|
||||
return sql.strip('\n')
|
||||
except Exception as e:
|
||||
return internal_server_error(errormsg=str(e))
|
||||
|
|
@ -477,6 +598,25 @@ class LanguageView(PGChildNodeView):
|
|||
status=200
|
||||
)
|
||||
|
||||
@check_precondition
|
||||
def get_templates(self, gid, sid, did):
|
||||
"""
|
||||
This function returns the language template.
|
||||
|
||||
Args:
|
||||
gid: Server Group ID
|
||||
sid: Server ID
|
||||
did: Database ID
|
||||
"""
|
||||
sql = render_template("/".join([self.template_path, 'templates.sql']))
|
||||
status, result = self.conn.execute_dict(sql)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=result)
|
||||
return make_json_response(
|
||||
data=result['rows'],
|
||||
status=200
|
||||
)
|
||||
|
||||
@check_precondition
|
||||
def sql(self, gid, sid, did, lid):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ define(
|
|||
sqlCreateHelp: 'sql-createlanguage.html',
|
||||
label: '{{ _('Language') }}',
|
||||
hasSQL: true,
|
||||
canDrop: true,
|
||||
canDropCascade: true,
|
||||
hasDepends: true,
|
||||
Init: function() {
|
||||
|
||||
|
|
@ -31,6 +33,25 @@ define(
|
|||
return;
|
||||
|
||||
this.initialized = true;
|
||||
|
||||
|
||||
// Add context menus for language
|
||||
pgBrowser.add_menus([{
|
||||
name: 'create_language_on_database', node: 'database', module: this,
|
||||
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||
category: 'create', priority: 4, label: '{{ _('Language...') }}',
|
||||
icon: 'wcTabIcon icon-language', data: {action: 'create'}
|
||||
},{
|
||||
name: 'create_language_on_coll', node: 'coll-language', module: this,
|
||||
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||
category: 'create', priority: 4, label: '{{ _('Language...') }}',
|
||||
icon: 'wcTabIcon icon-language', data: {action: 'create'}
|
||||
},{
|
||||
name: 'create_language', node: 'language', module: this,
|
||||
applies: ['object', 'context'], callback: 'show_obj_properties',
|
||||
category: 'create', priority: 4, label: '{{ _('Language...') }}',
|
||||
icon: 'wcTabIcon icon-language', data: {action: 'create'}
|
||||
}]);
|
||||
},
|
||||
|
||||
// Define the model for language node
|
||||
|
|
@ -40,20 +61,59 @@ define(
|
|||
lanowner: undefined,
|
||||
comment: undefined,
|
||||
lanacl: [],
|
||||
seclabels:[]
|
||||
seclabels:[],
|
||||
trusted: true,
|
||||
lanproc: undefined,
|
||||
laninl: undefined,
|
||||
lanval: undefined,
|
||||
is_template: false,
|
||||
template_list: []
|
||||
},
|
||||
|
||||
// Default values!
|
||||
initialize: function(attrs, args) {
|
||||
var isNew = (_.size(attrs) === 0);
|
||||
if (isNew) {
|
||||
var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user;
|
||||
|
||||
this.set({'lanowner': userInfo.name}, {silent: true});
|
||||
}
|
||||
pgBrowser.Node.Model.prototype.initialize.apply(this, arguments);
|
||||
},
|
||||
|
||||
// Define the schema for the language node
|
||||
schema: [{
|
||||
id: 'name', label: '{{ _('Name') }}', cell: 'string',
|
||||
type: 'text',
|
||||
id: 'name', label: '{{ _('Name') }}', type: 'text',
|
||||
control: 'node-ajax-options', mode: ['properties', 'create', 'edit'],
|
||||
url:'get_templates', select2: { allowClear: false, tags: true, multiple: false },
|
||||
transform: function(data, cell) {
|
||||
var res = [],
|
||||
control = cell || this,
|
||||
label = control.model.get('name');
|
||||
|
||||
if (!control.model.isNew()) {
|
||||
res.push({label: label, value: label});
|
||||
}
|
||||
else {
|
||||
var tmp_list = [];
|
||||
if (data && _.isArray(data)) {
|
||||
_.each(data, function(d) {
|
||||
res.push({label: d.tmplname, value: d.tmplname});
|
||||
tmp_list.push(d.tmplname);
|
||||
})
|
||||
}
|
||||
this.model.set({'template_list': tmp_list});
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
},{
|
||||
id: 'oid', label:'{{ _('OID') }}', cell: 'string', mode: ['properties'],
|
||||
type: 'text', disabled: true
|
||||
},{
|
||||
id: 'lanowner', label:'{{ _('Owner') }}', type: 'text',
|
||||
control: Backform.NodeListByNameControl, node: 'role',
|
||||
mode: ['edit', 'properties'], select2: { allowClear: false }
|
||||
mode: ['edit', 'properties', 'create'], select2: { allowClear: false }
|
||||
},{
|
||||
id: 'acl', label: '{{ _('Privileges') }}', type: 'text',
|
||||
group: '{{ _('Security') }}', mode: ['properties'], disabled: true
|
||||
|
|
@ -67,13 +127,22 @@ define(
|
|||
'onColor': 'success', 'offColor': 'primary',
|
||||
'size': 'small'
|
||||
},
|
||||
group: 'Definition', mode: ['edit', 'properties'],
|
||||
group: 'Definition', mode: ['edit', 'properties', 'create'], deps: ['name'],
|
||||
disabled: function(m) {
|
||||
return !(m.isNew());
|
||||
if (m.isNew()) {
|
||||
if (m.get('template_list').indexOf(m.get('name')) == -1) {
|
||||
m.set({'is_template': false});
|
||||
return false;
|
||||
}
|
||||
else
|
||||
m.set({'is_template': true});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},{
|
||||
id: 'lanproc', label:'{{ _('Handler Function') }}', type: 'text', control: 'node-ajax-options',
|
||||
group: 'Definition', mode: ['edit', 'properties'], url:'get_functions',
|
||||
group: 'Definition', mode: ['edit', 'properties', 'create'], url:'get_functions',
|
||||
deps: ['name'], first_empty: false,
|
||||
/* This function is used to populate the handler function
|
||||
* for the selected language node. It will check if the property
|
||||
* type is 'handler' then push the data into the result array.
|
||||
|
|
@ -81,19 +150,24 @@ define(
|
|||
transform: function(data) {
|
||||
var res = [];
|
||||
if (data && _.isArray(data)) {
|
||||
_.each(data, function(d) {
|
||||
if (d.prop_type == 'handler') {
|
||||
res.push({label: d.label, value: d.label});
|
||||
}
|
||||
})
|
||||
_.each(data, function(d) {
|
||||
if (d.prop_type == 'handler') {
|
||||
res.push({label: d.label, value: d.label});
|
||||
}
|
||||
})
|
||||
}
|
||||
return res;
|
||||
}, disabled: function(m) {
|
||||
return !(m.isNew());
|
||||
if (m.isNew()) {
|
||||
if (m.get('template_list').indexOf(m.get('name')) == -1)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},{
|
||||
id: 'laninl', label:'{{ _('Inline Function') }}', type: 'text', control: 'node-ajax-options',
|
||||
group: 'Definition', mode: ['edit', 'properties'], url:'get_functions',
|
||||
group: 'Definition', mode: ['edit', 'properties', 'create'], url:'get_functions',
|
||||
deps: ['name'], first_empty: false,
|
||||
/* This function is used to populate the inline function
|
||||
* for the selected language node. It will check if the property
|
||||
* type is 'inline' then push the data into the result array.
|
||||
|
|
@ -101,19 +175,24 @@ define(
|
|||
transform: function(data) {
|
||||
var res = [];
|
||||
if (data && _.isArray(data)) {
|
||||
_.each(data, function(d) {
|
||||
if (d.prop_type == 'inline') {
|
||||
res.push({label: d.label, value: d.label});
|
||||
}
|
||||
})
|
||||
_.each(data, function(d) {
|
||||
if (d.prop_type == 'inline') {
|
||||
res.push({label: d.label, value: d.label});
|
||||
}
|
||||
})
|
||||
}
|
||||
return res;
|
||||
}, disabled: function(m) {
|
||||
return !(m.isNew());
|
||||
if (m.isNew()) {
|
||||
if (m.get('template_list').indexOf(m.get('name')) == -1)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},{
|
||||
id: 'lanval', label:'{{ _('Validator Function') }}', type: 'text', control: 'node-ajax-options',
|
||||
group: 'Definition', mode: ['edit', 'properties'], url:'get_functions',
|
||||
group: 'Definition', mode: ['edit', 'properties', 'create'], url:'get_functions',
|
||||
deps: ['name'],
|
||||
/* This function is used to populate the validator function
|
||||
* for the selected language node. It will check if the property
|
||||
* type is 'validator' then push the data into the result array.
|
||||
|
|
@ -129,16 +208,20 @@ define(
|
|||
}
|
||||
return res;
|
||||
}, disabled: function(m) {
|
||||
return !(m.isNew());
|
||||
if (m.isNew()) {
|
||||
if (m.get('template_list').indexOf(m.get('name')) == -1)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, pgBrowser.SecurityGroupUnderSchema, {
|
||||
id: 'lanacl', label: '{{ _('Privileges') }}', type: 'collection',
|
||||
group: 'security', control: 'unique-col-collection', mode: ['edit'],
|
||||
group: 'security', control: 'unique-col-collection', mode: ['edit', 'create'],
|
||||
model: pgBrowser.Node.PrivilegeRoleModel.extend({
|
||||
privileges: ['U']
|
||||
}), canAdd: true, canDelete: true, uniqueCol : ['grantee']
|
||||
},{
|
||||
id: 'seclabels', label: '{{ _('Security Labels') }}', mode: ['edit'],
|
||||
id: 'seclabels', label: '{{ _('Security Labels') }}', mode: ['edit', 'create'],
|
||||
model: pgBrowser.SecLabelModel, editable: false,
|
||||
type: 'collection', group: 'security', min_version: 90200,
|
||||
canAdd: true, canEdit: false, canDelete: true,
|
||||
|
|
@ -160,6 +243,20 @@ define(
|
|||
} else {
|
||||
this.errorModel.unset('name');
|
||||
}
|
||||
|
||||
// If predefined template is selected then no need to validate it.
|
||||
if (!this.get('is_template')) {
|
||||
var handler_func = this.get('lanproc');
|
||||
if (_.isUndefined(handler_func) || _.isNull(handler_func) ||
|
||||
String(handler_func).replace(/^\s+|\s+$/g, '') == '') {
|
||||
var msg = '{{ _('Handler Function cannot be empty') }}';
|
||||
this.errorModel.set('lanproc', msg);
|
||||
return msg;
|
||||
} else {
|
||||
this.errorModel.unset('lanproc');
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
{# ============= CREATE LANGUAGE Query ============= #}
|
||||
{% import 'macros/privilege.macros' as PRIVILEGE %}
|
||||
{% import 'macros/security.macros' as SECLABEL %}
|
||||
{% if data.is_template %}
|
||||
CREATE LANGUAGE {{ conn|qtIdent(data.name) }};
|
||||
{% else %}
|
||||
CREATE{% if data.trusted %} TRUSTED{% endif %} PROCEDURAL LANGUAGE {{ conn|qtIdent(data.name) }}
|
||||
{% if data.lanproc %}
|
||||
HANDLER {{ conn|qtIdent(data.lanproc) }}
|
||||
{% endif %}
|
||||
{% if data.laninl %}
|
||||
INLINE {{ conn|qtIdent(data.laninl) }}
|
||||
{% endif %}
|
||||
{% if data.lanval %}
|
||||
VALIDATOR {{ conn|qtIdent(data.lanval) }}
|
||||
{% endif %};
|
||||
{% endif %}
|
||||
{# ============= Set the owner for language ============= #}
|
||||
{% if data.lanowner %}
|
||||
ALTER LANGUAGE {{ conn|qtIdent(data.name) }}
|
||||
OWNER TO {{ conn|qtIdent(data.lanowner) }};
|
||||
{% endif %}
|
||||
{# ============= Comment on of language object ============= #}
|
||||
{% if data.description %}
|
||||
COMMENT ON LANGUAGE {{ conn|qtIdent(data.name) }}
|
||||
IS {{ data.description|qtLiteral }};
|
||||
{% endif %}
|
||||
{# ============= Create ACL for language ============= #}
|
||||
{% if data.lanacl %}
|
||||
{% for priv in data.lanacl %}
|
||||
{{ PRIVILEGE.APPLY(conn, 'LANGUAGE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{# ========= Change the security labels ========== #}
|
||||
{% if data.seclabels %}
|
||||
{% for r in data.seclabels %}
|
||||
{{ SECLABEL.APPLY(conn, 'LANGUAGE', data.name, r.provider, r.label) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{# ============= Get the language name using oid ============= #}
|
||||
{% if lid %}
|
||||
SELECT lanname FROM pg_language WHERE oid = {{lid}}::int;
|
||||
{% endif %}
|
||||
{# ============= Drop the language ============= #}
|
||||
{% if lname %}
|
||||
DROP LANGUAGE {{ conn|qtIdent(lname) }} {% if cascade %}CASCADE{% endif%};
|
||||
{% endif %}
|
||||
|
|
@ -16,4 +16,8 @@ FROM
|
|||
WHERE lanispl IS TRUE
|
||||
{% if lid %} AND
|
||||
lan.oid={{lid}}::int
|
||||
{% endif %} ORDER BY lanname
|
||||
{% endif %}
|
||||
{% if lanname %} AND
|
||||
lanname={{ lanname|qtLiteral }}::text
|
||||
{% endif %}
|
||||
ORDER BY lanname
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
{# ============= SELECT Language templates ============= #}
|
||||
SELECT
|
||||
tmplname
|
||||
FROM pg_pltemplate
|
||||
LEFT JOIN pg_language ON tmplname=lanname
|
||||
WHERE lanname IS NULL
|
||||
ORDER BY tmplname;
|
||||
|
|
@ -12,7 +12,7 @@ ALTER LANGUAGE {{ conn|qtIdent(data.name) }}
|
|||
OWNER TO {{ conn|qtIdent(data.lanowner) }};
|
||||
{% endif %}
|
||||
{# ============= Update language comments ============= #}
|
||||
{% if data.description and data.description != o_data.description %}
|
||||
{% if data.description is defined and data.description != o_data.description %}
|
||||
COMMENT ON LANGUAGE {{ conn|qtIdent(data.name) }}
|
||||
IS '{{ data.description }}';
|
||||
{% endif %}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
{# ============= CREATE LANGUAGE Query ============= #}
|
||||
{% import 'macros/privilege.macros' as PRIVILEGE %}
|
||||
{% import 'macros/security.macros' as SECLABEL %}
|
||||
{% if data.is_template %}
|
||||
CREATE LANGUAGE {{ conn|qtIdent(data.name) }};
|
||||
{% else %}
|
||||
CREATE{% if data.trusted %} TRUSTED{% endif %} PROCEDURAL LANGUAGE {{ conn|qtIdent(data.name) }}
|
||||
{% if data.lanproc %}
|
||||
HANDLER {{ conn|qtIdent(data.lanproc) }}
|
||||
{% endif %}
|
||||
{% if data.laninl %}
|
||||
INLINE {{ conn|qtIdent(data.laninl) }}
|
||||
{% endif %}
|
||||
{% if data.lanval %}
|
||||
VALIDATOR {{ conn|qtIdent(data.lanval) }}
|
||||
{% endif %};
|
||||
{% endif %}
|
||||
{# ============= Set the owner for language ============= #}
|
||||
{% if data.lanowner %}
|
||||
ALTER LANGUAGE {{ conn|qtIdent(data.name) }}
|
||||
OWNER TO {{ conn|qtIdent(data.lanowner) }};
|
||||
{% endif %}
|
||||
{# ============= Comment on of language object ============= #}
|
||||
{% if data.description %}
|
||||
COMMENT ON LANGUAGE {{ conn|qtIdent(data.name) }}
|
||||
IS {{ data.description|qtLiteral }};
|
||||
{% endif %}
|
||||
{# ============= Create ACL for language ============= #}
|
||||
{% if data.lanacl %}
|
||||
{% for priv in data.lanacl %}
|
||||
{{ PRIVILEGE.APPLY(conn, 'LANGUAGE', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{# ========= Change the security labels ========== #}
|
||||
{% if data.seclabels %}
|
||||
{% for r in data.seclabels %}
|
||||
{{ SECLABEL.APPLY(conn, 'LANGUAGE', data.name, r.provider, r.label) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{# ============= Get the language name using oid ============= #}
|
||||
{% if lid %}
|
||||
SELECT lanname FROM pg_language WHERE oid = {{lid}}::int;
|
||||
{% endif %}
|
||||
{# ============= Drop the language ============= #}
|
||||
{% if lname %}
|
||||
DROP LANGUAGE {{ conn|qtIdent(lname) }} {% if cascade %}CASCADE{% endif%};
|
||||
{% endif %}
|
||||
|
|
@ -16,4 +16,8 @@ FROM
|
|||
WHERE lanispl IS TRUE
|
||||
{% if lid %} AND
|
||||
lan.oid={{lid}}::int
|
||||
{% endif %} ORDER BY lanname
|
||||
{% endif %}
|
||||
{% if lanname %} AND
|
||||
lanname={{ lanname|qtLiteral }}::text
|
||||
{% endif %}
|
||||
ORDER BY lanname
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
{# ============= SELECT Language templates ============= #}
|
||||
SELECT
|
||||
tmplname
|
||||
FROM pg_pltemplate
|
||||
LEFT JOIN pg_language ON tmplname=lanname
|
||||
WHERE lanname IS NULL
|
||||
ORDER BY tmplname;
|
||||
|
|
@ -12,7 +12,7 @@ ALTER LANGUAGE {{ conn|qtIdent(data.name) }}
|
|||
OWNER TO {{ conn|qtIdent(data.lanowner) }};
|
||||
{% endif %}
|
||||
{# ============= Update language comments ============= #}
|
||||
{% if data.description and data.description != o_data.description %}
|
||||
{% if data.description is defined and data.description != o_data.description %}
|
||||
COMMENT ON LANGUAGE {{ conn|qtIdent(data.name) }}
|
||||
IS '{{ data.description }}';
|
||||
{% endif %}
|
||||
|
|
|
|||
Loading…
Reference in New Issue