Adding support for the trigger functions node.

This commit is contained in:
Murtuza Zabuawala 2016-05-21 15:09:32 +05:30 committed by Ashesh Vashi
parent 077075c765
commit d2eaa8b3dd
84 changed files with 2550 additions and 15 deletions

View File

@ -833,20 +833,30 @@ class FunctionView(PGChildNodeView, DataTypeReader):
try:
if SQL and SQL.strip('\n') and SQL.strip(' '):
status, res = self.conn.execute_scalar(SQL)
if not status:
return internal_server_error(errormsg=res)
return make_json_response(
success=1,
info="Function Updated.",
data={
'id': fnid,
'scid': scid,
'sid': sid,
'gid': gid,
'did': did
}
resp_data = self._fetch_properties(gid, sid, did, scid, fnid)
if self.node_type == 'procedure':
obj_name = resp_data['name_with_args']
elif self.node_type == 'function':
args = resp_data['proargs'] if resp_data['proargs'] else ''
obj_name = resp_data['name'] + '({0})'.format(args)
else:
obj_name = resp_data['name'] + '()'
return jsonify(
node=self.blueprint.generate_browser_node(
fnid,
resp_data['pronamespace'],
obj_name,
icon="icon-" + self.node_type,
language=resp_data['lanname'],
funcowner=resp_data['funcowner']
)
)
else:
return make_json_response(
@ -878,6 +888,7 @@ class FunctionView(PGChildNodeView, DataTypeReader):
"""
if self.node_type == 'procedure':
object_type = 'procedure'
resp_data = self._fetch_properties(gid, sid, did, scid, fnid)
# Get SQL to create Function
@ -888,6 +899,7 @@ class FunctionView(PGChildNodeView, DataTypeReader):
name = resp_data['pronamespace'] + "." + resp_data['name_with_args']
else:
object_type = 'function'
# Fetch the function definition.
SQL = render_template("/".join([self.sql_template_path,
'get_definition.sql']), fnid=fnid, scid=scid)
@ -901,9 +913,10 @@ class FunctionView(PGChildNodeView, DataTypeReader):
-- DROP {0} {1};
""".format(self.node_type.upper(), name)
""".format(object_type.upper(), name)
SQL = sql_header + func_def
SQL = re.sub('\n{2,}', '\n\n', SQL)
return ajax_response(response=SQL)
@ -924,12 +937,15 @@ class FunctionView(PGChildNodeView, DataTypeReader):
"""
status, SQL = self._get_sql(gid, sid, did, scid, self.request, fnid)
if status:
SQL = re.sub('\n{2,}', '\n\n', SQL)
return make_json_response(
data=SQL,
status=200
)
else:
SQL = re.sub('\n{2,}', '\n\n', SQL)
return SQL
def _get_sql(self, gid, sid, did, scid, data, fnid=None, is_sql=False):
@ -1386,3 +1402,113 @@ class ProcedureView(FunctionView):
)
ProcedureView.register_node_view(procedure_blueprint)
class TriggerFunctionModule(SchemaChildModule):
"""
class TriggerFunctionModule(SchemaChildModule):
This class represents The Trigger function Module.
Methods:
-------
* __init__(*args, **kwargs)
- Initialize the Trigger function Module.
* get_nodes(gid, sid, did, scid)
- Generate the Trigger function collection node.
* node_inode():
- Returns Trigger function node as leaf node.
* script_load()
- Load the module script for Trigger function, when schema node is
initialized.
"""
NODE_TYPE = 'trigger_function'
COLLECTION_LABEL = gettext("Trigger function")
def __init__(self, *args, **kwargs):
"""
Initialize the Trigger function Module.
Args:
*args:
**kwargs:
"""
super(TriggerFunctionModule, self).__init__(*args, **kwargs)
self.min_ver = 90100
self.max_ver = None
def get_nodes(self, gid, sid, did, scid):
"""
Generate Trigger function collection node.
"""
yield self.generate_browser_collection_node(scid)
@property
def node_inode(self):
"""
Make the node as leaf node.
Returns:
False as this node doesn't have child nodes.
"""
return False
@property
def script_load(self):
"""
Load the module script for Trigger function, when the
schema node is initialized.
"""
return schemas.SchemaModule.NODE_TYPE
trigger_function_blueprint = TriggerFunctionModule(__name__)
class TriggerFunctionView(FunctionView):
node_type = trigger_function_blueprint.node_type
def __init__(self, *args, **kwargs):
"""
Initialize the Function Module.
Args:
*args:
**kwargs:
"""
super(TriggerFunctionView, self).__init__(*args, **kwargs)
@property
def required_args(self):
"""
Returns Required arguments for trigger function node.
Where
Required Args:
name: Name of the Trigger function
pronamespace: Trigger function Namespace
lanname: Trigger function Language Name
prosrc: Trigger function Code
"""
return ['name',
'pronamespace',
'lanname',
'prosrc']
def module_js(self):
"""
Load JS file (trigger_function.js) for this module.
"""
return make_response(
render_template(
"trigger_function/js/trigger_functions.js",
_=gettext
),
200, {'Content-Type': 'application/x-javascript'}
)
TriggerFunctionView.register_node_view(trigger_function_blueprint)

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

View File

@ -0,0 +1,3 @@
.functions_code {
height: 130px !important;
}

View File

@ -0,0 +1,405 @@
/* Create and Register Function Collection and Node. */
define(
['jquery', 'underscore', 'underscore.string',
'pgadmin', 'pgadmin.browser', 'alertify',
'pgadmin.browser.collection', 'pgadmin.browser.server.privilege'],
function($, _, S, pgAdmin, pgBrowser, alertify) {
if (!pgBrowser.Nodes['coll-trigger_function']) {
var trigger_functions = pgAdmin.Browser.Nodes['coll-trigger_function'] =
pgAdmin.Browser.Collection.extend({
node: 'trigger_function',
label: '{{ _('Trigger functions') }}',
type: 'coll-trigger_function',
columns: ['name', 'funcowner', 'description']
});
};
if (!pgBrowser.Nodes['trigger_function']) {
pgAdmin.Browser.Nodes['trigger_function'] = pgBrowser.Node.extend({
type: 'trigger_function',
sqlAlterHelp: 'plpgsql-trigger.html',
sqlCreateHelp: 'plpgsql-trigger.html',
dialogHelp: '{{ url_for('help.static', filename='create_trigger_function.html') }}',
label: '{{ _('Trigger function') }}',
collection_type: 'coll-trigger_function',
hasSQL: true,
hasDepends: true,
parent_type: ['schema', 'catalog'],
Init: function(args) {
/* Avoid mulitple registration of menus */
if (this.initialized)
return;
this.initialized = true;
pgBrowser.add_menus([{
name: 'create_trigger_function_on_coll', node: 'coll-trigger_function', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 4, label: '{{ _('Trigger function...') }}',
icon: 'wcTabIcon icon-trigger_function', data: {action: 'create', check: true},
enable: 'canCreate'
},{
name: 'create_trigger_function', node: 'trigger_function', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 4, label: '{{ _('Trigger function...') }}',
icon: 'wcTabIcon icon-trigger_function', data: {action: 'create', check: true},
enable: 'canCreate'
},{
name: 'create_trigger_function', node: 'schema', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 4, label: '{{ _('Trigger function...') }}',
icon: 'wcTabIcon icon-trigger_function', data: {action: 'create', check: false},
enable: 'canCreate'
}
]);
},
canDrop: pgBrowser.Nodes['schema'].canChildDrop,
canDropCascade: pgBrowser.Nodes['schema'].canChildDrop,
model: pgAdmin.Browser.Node.Model.extend({
initialize: function(attrs, args) {
var isNew = (_.size(attrs) === 0);
if (isNew) {
// Set Selected Schema
schema_id = args.node_info.schema._id
this.set({'pronamespace': schema_id}, {silent: true});
// Set Current User
var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user;
this.set({'funcowner': userInfo.name}, {silent: true});
}
pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments);
},
defaults: {
name: undefined,
oid: undefined,
xmin: undefined,
funcowner: undefined,
pronamespace: undefined,
description: undefined,
pronargs: undefined, /* Argument Count */
proargs: undefined, /* Arguments */
proargtypenames: undefined, /* Argument Signature */
prorettypename: 'trigger', /* Return Type */
lanname: 'plpgsql', /* Language Name in which function is being written */
provolatile: undefined, /* Volatility */
proretset: undefined, /* Return Set */
proisstrict: undefined,
prosecdef: undefined, /* Security of definer */
proiswindow: undefined, /* Window Function ? */
procost: undefined, /* Estimated execution Cost */
prorows: undefined, /* Estimated number of rows */
proleakproof: undefined,
arguments: [],
prosrc: undefined,
prosrc_c: undefined,
probin: '$libdir/',
options: [],
variables: [],
proacl: undefined,
seclabels: [],
acl: [],
sysfunc: undefined,
sysproc: undefined
},
schema: [{
id: 'name', label: '{{ _('Name') }}', cell: 'string',
type: 'text', mode: ['properties', 'create', 'edit'],
disabled: 'isDisabled'
},{
id: 'oid', label: '{{ _('OID') }}', cell: 'string',
type: 'text' , mode: ['properties']
},{
id: 'funcowner', label: '{{ _('Owner') }}', cell: 'string',
control: Backform.NodeListByNameControl, node: 'role', type:
'text', disabled: 'isDisabled'
},{
id: 'pronamespace', label: '{{ _('Schema') }}', cell: 'string',
control: 'node-list-by-id', type: 'text', cache_level: 'database',
node: 'schema', disabled: 'isDisabled', mode: ['create', 'edit']
},{
id: 'sysfunc', label: '{{ _('System function?') }}',
cell:'boolean', type: 'switch',
mode: ['properties'], visible: 'isVisible'
},{
id: 'sysproc', label: '{{ _('System procedure?') }}',
cell:'boolean', type: 'switch',
mode: ['properties'], visible: 'isVisible'
},{
id: 'description', label: '{{ _('Comment') }}', cell: 'string',
type: 'multiline', disabled: 'isDisabled'
},{
id: 'pronargs', label: '{{ _('Argument count') }}', cell: 'string',
type: 'text', group: '{{ _('Definition') }}', mode: ['properties']
},{
id: 'proargs', label: '{{ _('Arguments') }}', cell: 'string',
type: 'text', group: '{{ _('Definition') }}', mode: ['properties', 'edit'],
disabled: 'isDisabled'
},{
id: 'proargtypenames', label: '{{ _('Signature arguments') }}', cell:
'string', type: 'text', group: '{{ _('Definition') }}', mode: ['properties'],
disabled: 'isDisabled'
},{
id: 'prorettypename', label: '{{ _('Return type') }}', cell: 'string',
control: 'select2', type: 'text', group: '{{ _('Definition') }}',
disabled: 'isDisabled', first_empty: true,
select2: { width: "100%", allowClear: false },
mode: ['create'], visible: 'isVisible', options: [
{label: 'trigger', value: 'trigger'},
{label: 'event_trigger', value: 'event_trigger'}
]
},{
id: 'prorettypename', label: '{{ _('Return type') }}', cell: 'string',
type: 'text', group: '{{ _('Definition') }}', disabled: true,
mode: ['properties', 'edit'], disabled: 'isDisabled', visible: 'isVisible'
}, {
id: 'lanname', label: '{{ _('Language') }}', cell: 'string',
control: 'node-ajax-options', type: 'text', group: '{{ _('Definition') }}',
url: 'get_languages', disabled: 'isDisabled', transform: function(d, self) {
return _.reject(d, function(o){ return o.label == 'sql'; });
}, select2: { allowClear: false }
},{
id: 'prosrc', label: '{{ _('Code') }}', cell: 'string',
type: 'text', mode: ['properties', 'create', 'edit'],
group: '{{ _('Definition') }}', deps: ['lanname'],
control: Backform.SqlFieldControl,
extraClasses:['custom_height_css_class'],
visible: function(m) {
if (m.get('lanname') == 'c') {
return false;
}
return true;
}, disabled: 'isDisabled'
},{
id: 'probin', label: '{{ _('Object file') }}', cell: 'string',
type: 'text', group: '{{ _('Definition') }}', deps: ['lanname'], visible:
function(m) {
if (m.get('lanname') == 'c') { return true; }
return false;
}, disabled: 'isDisabled'
},{
id: 'prosrc_c', label: '{{ _('Link symbol') }}', cell: 'string',
type: 'text', group: '{{ _('Definition') }}', deps: ['lanname'], visible:
function(m) {
if (m.get('lanname') == 'c') { return true; }
return false;
}, disabled: 'isDisabled'
},{
id: 'provolatile', label: '{{ _('Volatility') }}', cell: 'string',
control: 'node-ajax-options', type: 'text', group: '{{ _('Options') }}',
options:[
{'label': 'VOLATILE', 'value': 'v'},
{'label': 'STABLE', 'value': 's'},
{'label': 'IMMUTABLE', 'value': 'i'},
], disabled: 'isDisabled', select2: { allowClear: false }
},{
id: 'proretset', label: '{{ _('Returns a set?') }}', group: '{{ _('Options') }}',
cell:'boolean', type: 'switch', disabled: 'isDisabled',
visible: 'isVisible'
},{
id: 'proisstrict', label: '{{ _('Strict?') }}', group: '{{ _
('Options') }}',
cell:'boolean', type: 'switch', disabled: 'isDisabled',
options: {
'onText': 'Yes', 'offText': 'No',
'onColor': 'success', 'offColor': 'primary',
'size': 'small'
}
},{
id: 'prosecdef', label: '{{ _('Security of definer?') }}',
group: '{{ _('Options') }}', cell:'boolean', type: 'switch',
disabled: 'isDisabled'
},{
id: 'proiswindow', label: '{{ _('Window?') }}',
group: '{{ _('Options') }}', cell:'boolean', type: 'switch',
disabled: 'isDisabled', visible: 'isVisible'
},{
id: 'procost', label: '{{ _('Estimated cost') }}', group: '{{ _('Options') }}',
cell:'string', type: 'text', disabled: 'isDisabled'
},{
id: 'prorows', label: '{{ _('Estimated rows') }}', group: '{{ _
('Options') }}',
cell:'string', type: 'text', disabled: 'isDisabled',
deps: ['proretset'], visible: 'isVisible'
},{
id: 'proleakproof', label: '{{ _('Leak proof?') }}',
group: '{{ _('Options') }}', cell:'boolean', type: 'switch', min_version: 90200,
disabled: 'isDisabled'
},{
id: 'proacl', label: '{{ _('Privileges') }}',
group: '{{ _('Security') }}', cell:'boolean', type: 'text', cell: 'string',
mode: ['properties']
},{
id: 'variables', label: '{{ _('Parameters') }}', type: 'collection',
group: '{{ _('Parameters') }}', control: 'variable-collection',
model: pgAdmin.Browser.Node.VariableModel,
mode: ['edit', 'create'], canAdd: 'canVarAdd', canEdit: false,
canDelete: true, disabled: 'isDisabled'
},{
id: 'acl', label: '{{ _('Privileges') }}', model: pgAdmin
.Browser.Node.PrivilegeRoleModel.extend(
{privileges: ['X']}), uniqueCol : ['grantee', 'grantor'],
editable: false, type: 'collection', group: '{{ _('Security') }}',
mode: ['edit', 'create'],
canAdd: true, canDelete: true, control: 'unique-col-collection',
disabled: 'isDisabled'
},
{
id: 'seclabels', label: '{{ _('Security Labels') }}',
model: Backform.SecurityModel, type: 'collection',
group: '{{ _('Security') }}', mode: ['edit', 'create'],
min_version: 90100, canAdd: true,
canEdit: true, canDelete: true,
control: 'unique-col-collection', uniqueCol : ['provider'],
disabled: 'isDisabled'
}
],
validate: function(keys)
{
var err = {},
errmsg,
seclabels = this.get('seclabels');
// Nothing to validate
if(keys && keys.length == 0) {
this.errorModel.clear();
return null;
}
if (_.isUndefined(this.get('name')) || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') {
err['name'] = '{{ _('Name cannot be empty.') }}';
errmsg = errmsg || err['name'];
}
if (_.isUndefined(this.get('funcowner')) || String(this.get('funcowner')).replace(/^\s+|\s+$/g, '') == '') {
err['funcowner'] = '{{ _('Owner cannot be empty.') }}';
errmsg = errmsg || err['funcowner'];
}
if (_.isUndefined(this.get('pronamespace')) || String(this.get('pronamespace')).replace(/^\s+|\s+$/g, '') == '') {
err['pronamespace'] = '{{ _('Schema cannot be empty.') }}';
errmsg = errmsg || err['pronamespace'];
}
if (_.isUndefined(this.get('prorettypename')) || String(this.get('prorettypename')).replace(/^\s+|\s+$/g, '') == '') {
err['prorettypename'] = '{{ _('Return Type cannot be empty.') }}';
errmsg = errmsg || err['prorettypename'];
}
if (_.isUndefined(this.get('lanname')) || String(this.get('lanname')).replace(/^\s+|\s+$/g, '') == '') {
err['lanname'] = '{{ _('Language cannot be empty.') }}';
errmsg = errmsg || err['lanname'];
}
if (String(this.get('lanname')) == 'c') {
if (_.isUndefined(this.get('probin')) || String(this.get('probin'))
.replace(/^\s+|\s+$/g, '') == '') {
err['probin'] = '{{ _('Object File cannot be empty.') }}';
errmsg = errmsg || err['probin'];
}
if (_.isUndefined(this.get('prosrc_c')) || String(this.get('prosrc_c')).replace(/^\s+|\s+$/g, '') == '') {
err['prosrc_c'] = '{{ _('Link Symbol cannot be empty.') }}';
errmsg = errmsg || err['prosrc_c'];
}
}
else {
if (_.isUndefined(this.get('prosrc')) || String(this.get('prosrc')).replace(/^\s+|\s+$/g, '') == '') {
err['prosrc'] = '{{ _('Code cannot be empty.') }}';
errmsg = errmsg || err['prosrc'];
}
}
if (seclabels) {
var secLabelsErr;
for (var i = 0; i < seclabels.models.length && !secLabelsErr; i++) {
secLabelsErr = (seclabels.models[i]).validate.apply(seclabels.models[i]);
if (secLabelsErr) {
err['seclabels'] = secLabelsErr;
errmsg = errmsg || secLabelsErr;
}
}
}
this.errorModel.clear().set(err);
if (_.size(err)) {
this.trigger('on-status', {msg: errmsg});
return errmsg;
}
return null;
},
isVisible: function(m){
if (this.name == 'sysproc') { return false; }
return true;
},
isDisabled: function(m){
if(this.node_info && 'catalog' in this.node_info) {
return true;
}
name = this.name;
switch(name){
case 'proargs':
case 'proargtypenames':
case 'prorettypename':
case 'proretset':
case 'proiswindow':
return !m.isNew();
break;
case 'prorows':
if(m.get('proretset') == true) {
return false;
}
else {
return true;
}
break;
default:
return false;
break;
}
return false;
},
canVarAdd: function(m) {
if(this.node_info && 'catalog' in this.node_info) {
return false;
}
return true;
}
}),
canCreate: function(itemData, item, data) {
//If check is false then , we will allow create menu
if (data && data.check == false)
return true;
var t = pgBrowser.tree, i = item, d = itemData;
// To iterate over tree to check parent node
while (i) {
// If it is schema then allow user to create Function
if (_.indexOf(['schema'], d._type) > -1)
return true;
if ('coll-trigger_function' == d._type) {
//Check if we are not child of catalog
prev_i = t.hasParent(i) ? t.parent(i) : null;
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d._type == 'catalog') {
return false;
} else {
return true;
}
}
i = t.hasParent(i) ? t.parent(i) : null;
d = i ? t.itemData(i) : null;
}
// by default we do not want to allow create menu
return true;
}
});
}
return pgBrowser.Nodes['trigger_function'];
});

View File

@ -0,0 +1,35 @@
SELECT
COALESCE(gt.rolname, 'public') AS grantee,
g.rolname AS 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
(d).grantee AS grantee, (d).grantor AS grantor,
(d).is_grantable AS is_grantable,
(d).privilege_type AS privilege_type
FROM
(SELECT aclexplode(db.proacl) AS d FROM pg_proc db
WHERE db.oid = {{fnid}}::OID) a
) d
) d
LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
GROUP BY g.rolname, gt.rolname;

View File

@ -0,0 +1,48 @@
{% import 'macros/functions/security.macros' as SECLABEL %}
{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
{% import 'macros/functions/variable.macros' as VARIABLE %}
{% set is_columns = [] %}
{% if data %}
CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}()
RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }}
LANGUAGE {{ data.lanname|qtLiteral }}
{% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proisstrict %}STRICT {% endif %}{% if data.prosecdef %}SECURITY DEFINER {% endif %}{% if data.proiswindow %}WINDOW{% endif -%}{% if data.procost %}
COST {{data.procost}}{% endif %}{% if data.prorows %}
ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %}
SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %}
{% endif %}
AS {% if data.lanname == 'c' %}
{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
{% else %}
$BODY$
{{ data.prosrc }}
$BODY${% endif %};
{% if data.funcowner %}
ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
OWNER TO {{ data.funcowner }};
{% endif %}
{% if data.acl %}
{% for p in data.acl %}
{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}}
{% endfor %}{% endif %}
{% if data.description %}
COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
IS '{{ data.description }}';
{% endif -%}
{% if data.seclabels %}
{% for r in data.seclabels %}
{% if r.security_label and r.provider %}
{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
{% endif %}
{% endfor %}
{% endif -%}
{% endif %}

View File

@ -0,0 +1,21 @@
{% if scid and fnid %}
SELECT
pr.proname as name, '(' || COALESCE(pg_catalog
.pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args,
nspname
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname = 'trigger'
AND pr.oid = {{fnid}};
{% endif %}
{% if name %}
DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %};
{% endif %}

View File

@ -0,0 +1,11 @@
SELECT
pg_get_functiondef({{fnid}}::oid) AS func_def,
nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name
FROM
pg_proc pr
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND pr.oid = {{fnid}}::oid;

View File

@ -0,0 +1,4 @@
SELECT
lanname as label, lanname as value
FROM
pg_language;

View File

@ -0,0 +1,17 @@
SELECT
pr.oid, pr.proname || '(' || COALESCE(pg_catalog
.pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
lanname, pg_get_userbyid(proowner) as funcowner
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_language lng ON lng.oid=prolang
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
AND nsp.nspname={{ nspname|qtLiteral }}
WHERE
proisagg = FALSE
AND typname = 'trigger' AND lanname != 'edbspl'
AND pr.proname = {{ name|qtLiteral }};

View File

@ -0,0 +1,6 @@
SELECT
format_type(oid, NULL) AS out_arg_type
FROM
pg_type
WHERE
oid = {{ out_arg_oid }}::oid;

View File

@ -0,0 +1,6 @@
SELECT
nspname
FROM
pg_namespace
WHERE
oid = {{ scid }}::oid;

View File

@ -0,0 +1,20 @@
SELECT
*
FROM
(SELECT
format_type(t.oid,NULL) AS typname,
CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname,
(SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup
FROM
pg_type t
JOIN
pg_namespace nsp ON typnamespace=nsp.oid
WHERE
(NOT (typname = 'unknown' AND nspname = 'pg_catalog'))
AND
(
typtype IN ('b', 'c', 'd', 'e', 'p', 'r')
AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger')
)
) AS dummy
ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1;

View File

@ -0,0 +1,17 @@
SELECT
pr.oid, pr.proname || '()' as name,
lanname, pg_get_userbyid(proowner) as funcowner, description
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_language lng ON lng.oid=prolang
LEFT OUTER JOIN
pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname = 'trigger' AND lanname != 'edbspl'
ORDER BY
proname;

View File

@ -0,0 +1,31 @@
SELECT
pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c,
pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename,
typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames,
pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description,
(SELECT
array_agg(provider || '=' || label)
FROM
pg_seclabel sl1
WHERE
sl1.objoid=pr.oid) AS seclabels
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_namespace typns ON typns.oid=typ.typnamespace
JOIN
pg_language lng ON lng.oid=prolang
LEFT OUTER JOIN
pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname = 'trigger' AND lanname != 'edbspl'
{% if fnid %}
AND pr.oid = {{fnid}}::oid
{% endif %}
ORDER BY
proname;

View File

@ -0,0 +1,100 @@
{% import 'macros/functions/security.macros' as SECLABEL %}
{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %}
{% set name = o_data.name %}
{% if data.name %}
{% if data.name != o_data.name %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{o_data.proargtypenames }})
RENAME TO {{ conn|qtIdent(data.name) }};
{% set name = data.name %}
{% endif %}
{% endif -%}
{% if data.change_func %}
CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}()
RETURNS {{ o_data.prorettypename }}
{% if 'lanname' in data %}
LANGUAGE {{ data.lanname|qtLiteral }} {% else %}
LANGUAGE {{ o_data.lanname|qtLiteral }}
{% endif %}{% if 'provolatile' in data and data.provolatile %}{{ data.provolatile }} {% elif 'provolatile' not in data and o_data.provolatile %}{{ o_data.provolatile }}{% endif %}
{% if ('proisstrict' in data and data.proisstrict) or ('proisstrict' not in data and o_data.proisstrict) %} STRICT{% endif %}
{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %}
{% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %}
{% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %}
ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}}{%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %}
SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
{% endif %}
AS {% if 'probin' in data or 'prosrc_c' in data %}
{% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %}
$BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %}
{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %}
$BODY${{ o_data.prosrc }}$BODY${% endif -%};
{% endif -%}
{% if data.funcowner %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }})
OWNER TO {{ data.funcowner }};
{% endif -%}
{# The SQL generated below will change priviledges #}
{% if data.acl %}
{% if 'deleted' in data.acl %}
{% for priv in data.acl.deleted %}
{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}{% endif %}
{% if 'changed' in data.acl %}
{% for priv in data.acl.changed %}
{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}{% endif %}
{% if 'added' in data.acl %}
{% for priv in data.acl.added %}
{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}{% endif %}{% endif %}
{% if data.change_func == False %}
{% if data.variables %}
{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %}
{{ VARIABLE.UNSET(conn, 'FUNCTION', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames ) }}
{% endif -%}
{% if 'merged_variables' in data and data.merged_variables|length > 0 %}
{{ VARIABLE.SET(conn, 'FUNCTION', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames ) }}
{% endif %}
{% endif %}{% endif %}
{% set seclabels = data.seclabels %}
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
{% for r in seclabels.deleted %}
{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}{% endif -%}
{% if data.description %}
COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
IS {{ data.description|qtLiteral }};
{% endif -%}
{% if data.pronamespace %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
SET SCHEMA {{ conn|qtIdent(data.pronamespace) }};
{% endif -%}
{% endif %}

View File

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

View File

@ -0,0 +1,35 @@
SELECT
COALESCE(gt.rolname, 'public') AS grantee,
g.rolname AS 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
(d).grantee AS grantee, (d).grantor AS grantor,
(d).is_grantable AS is_grantable,
(d).privilege_type AS privilege_type
FROM
(SELECT aclexplode(db.proacl) AS d FROM pg_proc db
WHERE db.oid = {{fnid}}::OID) a
) d
) d
LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
GROUP BY g.rolname, gt.rolname;

View File

@ -0,0 +1,52 @@
{% import 'macros/functions/security.macros' as SECLABLE %}
{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
{% import 'macros/functions/variable.macros' as VARIABLE %}
{% set is_columns = [] %}
{% if data %}
CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}()
RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }}
LANGUAGE {{ data.lanname|qtLiteral }}
{% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proleakproof %}LEAKPROOF {% else %}NOT LEAKPROOF {% endif %}
{% if data.proisstrict %}STRICT {% endif %}
{% if data.prosecdef %}SECURITY DEFINER {% endif %}
{% if data.proiswindow %}WINDOW{% endif %}{% if data.procost %}
COST {{data.procost}}{% endif %}{% if data.prorows %}
ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %}
SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %}
{% endif %}
AS {% if data.lanname == 'c' %}
{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
{% else %}
$BODY$
{{ data.prosrc }}
$BODY${% endif -%};
{% if data.funcowner %}
ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
OWNER TO {{ data.funcowner }};
{% endif -%}
{% if data.acl %}
{% for p in data.acl %}
{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}}
{% endfor -%}
{% endif -%}
{% if data.description %}
COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
IS '{{ data.description }}';
{% endif -%}
{% if data.seclabels %}
{% for r in data.seclabels %}
{% if r.security_label and r.provider %}
{{ SECLABLE.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
{% endif %}
{% endfor %}
{% endif -%}
{% endif -%}

View File

@ -0,0 +1,21 @@
{% if scid and fnid %}
SELECT
pr.proname as name, '(' || COALESCE(pg_catalog
.pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args,
nspname
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname IN ('trigger', 'event_trigger')
AND pr.oid = {{fnid}};
{% endif %}
{% if name %}
DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %};
{% endif %}

View File

@ -0,0 +1,11 @@
SELECT
pg_get_functiondef({{fnid}}::oid) AS func_def,
nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name
FROM
pg_proc pr
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND pr.oid = {{fnid}}::oid;

View File

@ -0,0 +1,4 @@
SELECT
lanname as label, lanname as value
FROM
pg_language;

View File

@ -0,0 +1,18 @@
SELECT
pr.oid, pr.proname || '(' || COALESCE(pg_catalog
.pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
lanname, pg_get_userbyid(proowner) as funcowner
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_language lng ON lng.oid=prolang
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
AND nsp.nspname={{ nspname|qtLiteral }}
WHERE
proisagg = FALSE
AND typname IN ('trigger', 'event_trigger')
AND lanname NOT IN ('edbspl', 'sql', 'internal')
AND pr.proname = {{ name|qtLiteral }};

View File

@ -0,0 +1,6 @@
SELECT
format_type(oid, NULL) AS out_arg_type
FROM
pg_type
WHERE
oid = {{ out_arg_oid }}::oid;

View File

@ -0,0 +1,6 @@
SELECT
nspname
FROM
pg_namespace
WHERE
oid = {{ scid }}::oid;

View File

@ -0,0 +1,20 @@
SELECT
*
FROM
(SELECT
format_type(t.oid,NULL) AS typname,
CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname,
(SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup
FROM
pg_type t
JOIN
pg_namespace nsp ON typnamespace=nsp.oid
WHERE
(NOT (typname = 'unknown' AND nspname = 'pg_catalog'))
AND
(
typtype IN ('b', 'c', 'd', 'e', 'p', 'r')
AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger')
)
) AS dummy
ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1;

View File

@ -0,0 +1,18 @@
SELECT
pr.oid, pr.proname || '()' as name,
lanname, pg_get_userbyid(proowner) as funcowner, description
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_language lng ON lng.oid=prolang
LEFT OUTER JOIN
pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname IN ('trigger', 'event_trigger')
AND lanname NOT IN ('edbspl', 'sql', 'internal')
ORDER BY
proname;

View File

@ -0,0 +1,32 @@
SELECT
pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c,
pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename,
typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames,
pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description,
(SELECT
array_agg(provider || '=' || label)
FROM
pg_shseclabel sl1
WHERE
sl1.objoid=pr.oid) AS seclabels
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_namespace typns ON typns.oid=typ.typnamespace
JOIN
pg_language lng ON lng.oid=prolang
LEFT OUTER JOIN
pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname IN ('trigger', 'event_trigger')
AND lanname NOT IN ('edbspl', 'sql', 'internal')
{% if fnid %}
AND pr.oid = {{fnid}}::oid
{% endif %}
ORDER BY
proname;

View File

@ -0,0 +1,109 @@
{% import 'macros/functions/security.macros' as SECLABEL %}
{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %}
{% set name = o_data.name %}
{% if data.name %}
{% if data.name != o_data.name %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{o_data.proargtypenames }})
RENAME TO {{ conn|qtIdent(data.name) }};
{% set name = data.name %}
{% endif %}
{% endif -%}
{% if data.change_func %}
CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}()
RETURNS {{ o_data.prorettypename }}
{% if 'lanname' in data %}
LANGUAGE {{ data.lanname|qtLiteral }} {% else %}
LANGUAGE {{ o_data.lanname|qtLiteral }}
{% endif %}{% if 'provolatile' in data and data.provolatile %}{{ data.provolatile }} {% elif 'provolatile' not in data and o_data.provolatile %}{{ o_data.provolatile }}{% endif %}
{% if ('proleakproof' in data and data.proleakproof) or ('proleakproof' not in data and o_data.proleakproof) %} LEAKPROOF{% elif 'proleakproof' in data and not data.proleakproof %}NOT LEAKPROOF{% endif %}
{% if ('proisstrict' in data and data.proisstrict) or ('proisstrict' not in data and o_data.proisstrict) %} STRICT{% endif %}
{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %}
{% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %}
{% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %}
ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}}{% endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %}
SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
{% endif %}
AS {% if 'probin' in data or 'prosrc_c' in data %}
{% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %}
$BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %}
{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %}
$BODY${{ o_data.prosrc }}$BODY${% endif -%};
{% endif -%}
{% if data.funcowner %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }})
OWNER TO {{ data.funcowner }};
{% endif -%}
{# The SQL generated below will change priviledges #}
{% if data.acl %}
{% if 'deleted' in data.acl %}
{% for priv in data.acl.deleted %}
{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'changed' in data.acl %}
{% for priv in data.acl.changed %}
{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'added' in data.acl %}
{% for priv in data.acl.added %}
{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif %}
{% endif -%}
{% if data.change_func == False %}
{% if data.variables %}
{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %}
{{ VARIABLE.UNSET(conn, 'FUNCTION', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames ) }}
{% endif -%}
{% if 'merged_variables' in data and data.merged_variables|length > 0 %}
{{ VARIABLE.SET(conn, 'FUNCTION', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames ) }}
{% endif -%}
{% endif -%}
{% endif -%}
{% set seclabels = data.seclabels %}
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
{% for r in seclabels.deleted %}
{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if data.description %}
COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }})
IS {{ data.description|qtLiteral }};
{% endif -%}
{% if data.pronamespace %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }})
SET SCHEMA {{ conn|qtIdent(data.pronamespace) }};
{% endif -%}
{% endif %}

View File

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

View File

@ -0,0 +1,35 @@
SELECT
COALESCE(gt.rolname, 'public') AS grantee,
g.rolname AS 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
(d).grantee AS grantee, (d).grantor AS grantor,
(d).is_grantable AS is_grantable,
(d).privilege_type AS privilege_type
FROM
(SELECT aclexplode(db.proacl) AS d FROM pg_proc db
WHERE db.oid = {{fnid}}::OID) a
) d
) d
LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
GROUP BY g.rolname, gt.rolname;

View File

@ -0,0 +1,51 @@
{% import 'macros/functions/security.macros' as SECLABEL %}
{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
{% import 'macros/functions/variable.macros' as VARIABLE %}
{% set is_columns = [] %}
{% if data %}
CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}()
RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }}
LANGUAGE {{ data.lanname|qtLiteral }}
{% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proleakproof %}LEAKPROOF {% else %}NOT LEAKPROOF {% endif %}
{% if data.proisstrict %}STRICT {% endif %}
{% if data.prosecdef %}SECURITY DEFINER {% endif %}
{% if data.proiswindow %}WINDOW{% endif %}{% if data.procost %}
COST {{data.procost}}{% endif %}{% if data.prorows %}
ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %}
SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %}
{% endif %}
AS {% if data.lanname == 'c' %}
{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
{% else %}
$BODY$
{{ data.prosrc }}
$BODY${% endif -%};
{% if data.funcowner %}
ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
OWNER TO {{ data.funcowner }};
{% endif -%}
{% if data.acl %}
{% for p in data.acl %}
{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}}
{% endfor %}{% endif %}
{% if data.description %}
COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
IS '{{ data.description }}';
{% endif -%}
{% if data.seclabels %}
{% for r in data.seclabels %}
{% if r.security_label and r.provider %}
{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
{% endif %}
{% endfor %}
{% endif -%}
{% endif %}

View File

@ -0,0 +1,21 @@
{% if scid and fnid %}
SELECT
pr.proname as name, '(' || COALESCE(pg_catalog
.pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args,
nspname
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname IN ('trigger', 'event_trigger')
AND pr.oid = {{fnid}};
{% endif %}
{% if name %}
DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %};
{% endif %}

View File

@ -0,0 +1,11 @@
SELECT
pg_get_functiondef({{fnid}}::oid) AS func_def,
nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name
FROM
pg_proc pr
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND pr.oid = {{fnid}}::oid;

View File

@ -0,0 +1,4 @@
SELECT
lanname as label, lanname as value
FROM
pg_language;

View File

@ -0,0 +1,18 @@
SELECT
pr.oid, pr.proname || '(' || COALESCE(pg_catalog
.pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
lanname, pg_get_userbyid(proowner) as funcowner
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_language lng ON lng.oid=prolang
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
AND nsp.nspname={{ nspname|qtLiteral }}
WHERE
proisagg = FALSE
AND typname IN ('trigger', 'event_trigger')
AND lanname NOT IN ('edbspl', 'sql', 'internal')
AND pr.proname = {{ name|qtLiteral }};

View File

@ -0,0 +1,6 @@
SELECT
format_type(oid, NULL) AS out_arg_type
FROM
pg_type
WHERE
oid = {{ out_arg_oid }}::oid;

View File

@ -0,0 +1,6 @@
SELECT
nspname
FROM
pg_namespace
WHERE
oid = {{ scid }}::oid;

View File

@ -0,0 +1,20 @@
SELECT
*
FROM
(SELECT
format_type(t.oid,NULL) AS typname,
CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname,
(SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup
FROM
pg_type t
JOIN
pg_namespace nsp ON typnamespace=nsp.oid
WHERE
(NOT (typname = 'unknown' AND nspname = 'pg_catalog'))
AND
(
typtype IN ('b', 'c', 'd', 'e', 'p', 'r')
AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger')
)
) AS dummy
ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1;

View File

@ -0,0 +1,18 @@
SELECT
pr.oid, pr.proname || '()' as name,
lanname, pg_get_userbyid(proowner) as funcowner, description
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_language lng ON lng.oid=prolang
LEFT OUTER JOIN
pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname IN ('trigger', 'event_trigger')
AND lanname NOT IN ('edbspl', 'sql', 'internal')
ORDER BY
proname;

View File

@ -0,0 +1,32 @@
SELECT
pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c,
pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename,
typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames,
pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description,
(SELECT
array_agg(provider || '=' || label)
FROM
pg_shseclabel sl1
WHERE
sl1.objoid=pr.oid) AS seclabels
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_namespace typns ON typns.oid=typ.typnamespace
JOIN
pg_language lng ON lng.oid=prolang
LEFT OUTER JOIN
pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname IN ('trigger', 'event_trigger')
AND lanname NOT IN ('edbspl', 'sql', 'internal')
{% if fnid %}
AND pr.oid = {{fnid}}::oid
{% endif %}
ORDER BY
proname;

View File

@ -0,0 +1,109 @@
{% import 'macros/functions/security.macros' as SECLABEL %}
{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %}
{% set name = o_data.name %}
{% if data.name %}
{% if data.name != o_data.name %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{
o_data.proargtypenames }})
RENAME TO {{ conn|qtIdent(data.name) }};
{% set name = data.name %}
{% endif %}
{% endif -%}
{% if data.change_func %}
CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}()
RETURNS {{ o_data.prorettypename }}
{% if 'lanname' in data %}
LANGUAGE {{ data.lanname|qtLiteral }} {% else %}
LANGUAGE {{ o_data.lanname|qtLiteral }}
{% endif %}{% if 'provolatile' in data and data.provolatile %}{{ data.provolatile }} {% elif 'provolatile' not in data and o_data.provolatile %}{{ o_data.provolatile }}{% endif %}
{% if ('proleakproof' in data and data.proleakproof) or ('proleakproof' not in data and o_data.proleakproof) %} LEAKPROOF{% elif 'proleakproof' in data and not data.proleakproof %} NOT LEAKPROOF{% endif %}
{% if ('proisstrict' in data and data.proisstrict) or ('proisstrict' not in data and o_data.proisstrict) %} STRICT{% endif %}
{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %}
{% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %}
{% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %}
ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}} {%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %}
SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
{% endif %}
AS {% if 'probin' in data or 'prosrc_c' in data %}
{% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %}
$BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %}
{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %}
$BODY${{ o_data.prosrc }}$BODY${% endif -%};
{% endif -%}
{% if data.funcowner %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
OWNER TO {{ data.funcowner }};
{% endif -%}
{# The SQL generated below will change priviledges #}
{% if data.acl %}
{% if 'deleted' in data.acl %}
{% for priv in data.acl.deleted %}
{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'changed' in data.datacl %}
{% for priv in data.acl.changed %}
{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'added' in data.acl %}
{% for priv in data.acl.added %}
{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}{% endif -%}
{% endif -%}
{% if data.change_func == False %}
{% if data.variables %}
{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %}
{{ VARIABLE.UNSET(conn, 'FUNCTION', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames) }}
{% endif -%}
{% if 'merged_variables' in data and data.merged_variables|length > 0 %}
{{ VARIABLE.SET(conn, 'FUNCTION', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames) }}
{% endif -%}
{% endif -%}
{% endif -%}
{% set seclabels = data.seclabels %}
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
{% for r in seclabels.deleted %}
{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if data.description %}
COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
IS {{ data.description|qtLiteral }};
{% endif -%}
{% if data.pronamespace %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
SET SCHEMA {{ conn|qtIdent(data.pronamespace) }};
{% endif -%}
{% endif %}

View File

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

View File

@ -0,0 +1,35 @@
SELECT
COALESCE(gt.rolname, 'public') AS grantee,
g.rolname AS 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
(d).grantee AS grantee, (d).grantor AS grantor,
(d).is_grantable AS is_grantable,
(d).privilege_type AS privilege_type
FROM
(SELECT aclexplode(db.proacl) AS d FROM pg_proc db
WHERE db.oid = {{fnid}}::OID) a
) d
) d
LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
GROUP BY g.rolname, gt.rolname;

View File

@ -0,0 +1,48 @@
{% import 'macros/functions/security.macros' as SECLABEL %}
{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
{% import 'macros/functions/variable.macros' as VARIABLE %}
{% set is_columns = [] %}
{% if data %}
CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}()
RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }}
LANGUAGE {{ data.lanname|qtLiteral }}
{% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proisstrict %}STRICT {% endif %}{% if data.prosecdef %}SECURITY DEFINER {% endif %}{% if data.proiswindow %}WINDOW{% endif -%}{% if data.procost %}
COST {{data.procost}}{% endif %}{% if data.prorows %}
ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %}
SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %}
{% endif %}
AS {% if data.lanname == 'c' %}
{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
{% else %}
$BODY$
{{ data.prosrc }}
$BODY${% endif %};
{% if data.funcowner %}
ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
OWNER TO {{ data.funcowner }};
{% endif %}
{% if data.acl %}
{% for p in data.acl %}
{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}}
{% endfor %}{% endif %}
{% if data.description %}
COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
IS '{{ data.description }}';
{% endif -%}
{% if data.seclabels %}
{% for r in data.seclabels %}
{% if r.security_label and r.provider %}
{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
{% endif %}
{% endfor %}
{% endif -%}
{% endif %}

View File

@ -0,0 +1,21 @@
{% if scid and fnid %}
SELECT
pr.proname as name, '(' || COALESCE(pg_catalog
.pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args,
nspname
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname = 'trigger'
AND pr.oid = {{fnid}};
{% endif %}
{% if name %}
DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %};
{% endif %}

View File

@ -0,0 +1,11 @@
SELECT
pg_get_functiondef({{fnid}}::oid) AS func_def,
nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name
FROM
pg_proc pr
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND pr.oid = {{fnid}}::oid;

View File

@ -0,0 +1,4 @@
SELECT
lanname as label, lanname as value
FROM
pg_language;

View File

@ -0,0 +1,17 @@
SELECT
pr.oid, pr.proname || '(' || COALESCE(pg_catalog
.pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
lanname, pg_get_userbyid(proowner) as funcowner
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_language lng ON lng.oid=prolang
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
AND nsp.nspname={{ nspname|qtLiteral }}
WHERE
proisagg = FALSE
AND typname = 'trigger' AND lanname != 'edbspl'
AND pr.proname = {{ name|qtLiteral }};

View File

@ -0,0 +1,6 @@
SELECT
format_type(oid, NULL) AS out_arg_type
FROM
pg_type
WHERE
oid = {{ out_arg_oid }}::oid;

View File

@ -0,0 +1,6 @@
SELECT
nspname
FROM
pg_namespace
WHERE
oid = {{ scid }}::oid;

View File

@ -0,0 +1,20 @@
SELECT
*
FROM
(SELECT
format_type(t.oid,NULL) AS typname,
CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname,
(SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup
FROM
pg_type t
JOIN
pg_namespace nsp ON typnamespace=nsp.oid
WHERE
(NOT (typname = 'unknown' AND nspname = 'pg_catalog'))
AND
(
typtype IN ('b', 'c', 'd', 'e', 'p', 'r')
AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger')
)
) AS dummy
ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1;

View File

@ -0,0 +1,17 @@
SELECT
pr.oid, pr.proname || '()' AS name,
lanname, pg_get_userbyid(proowner) AS funcowner, description
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_language lng ON lng.oid=prolang
LEFT OUTER JOIN
pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname = 'trigger' AND lanname != 'edbspl'
ORDER BY
proname;

View File

@ -0,0 +1,31 @@
SELECT
pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c,
pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename,
typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames,
pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description,
(SELECT
array_agg(provider || '=' || label)
FROM
pg_seclabel sl1
WHERE
sl1.objoid=pr.oid) AS seclabels
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_namespace typns ON typns.oid=typ.typnamespace
JOIN
pg_language lng ON lng.oid=prolang
LEFT OUTER JOIN
pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname = 'trigger' AND lanname != 'edbspl'
{% if fnid %}
AND pr.oid = {{fnid}}::oid
{% endif %}
ORDER BY
proname;

View File

@ -0,0 +1,100 @@
{% import 'macros/functions/security.macros' as SECLABEL %}
{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %}
{% set name = o_data.name %}
{% if data.name %}
{% if data.name != o_data.name %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{o_data.proargtypenames }})
RENAME TO {{ conn|qtIdent(data.name) }};
{% set name = data.name %}
{% endif %}
{% endif -%}
{% if data.change_func %}
CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}()
RETURNS {{ o_data.prorettypename }}
{% if 'lanname' in data %}
LANGUAGE {{ data.lanname|qtLiteral }} {% else %}
LANGUAGE {{ o_data.lanname|qtLiteral }}
{% endif %}{% if 'provolatile' in data and data.provolatile %}{{ data.provolatile }} {% elif 'provolatile' not in data and o_data.provolatile %}{{ o_data.provolatile }}{% endif %}
{% if ('proisstrict' in data and data.proisstrict) or ('proisstrict' not in data and o_data.proisstrict) %} STRICT{% endif %}
{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %}
{% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %}
{% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %}
ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}}{%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %}
SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
{% endif %}
AS {% if 'probin' in data or 'prosrc_c' in data %}
{% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %}
$BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %}
{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %}
$BODY${{ o_data.prosrc }}$BODY${% endif -%};
{% endif -%}
{% if data.funcowner %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }})
OWNER TO {{ data.funcowner }};
{% endif -%}
{# The SQL generated below will change priviledges #}
{% if data.acl %}
{% if 'deleted' in data.acl %}
{% for priv in data.acl.deleted %}
{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}{% endif %}
{% if 'changed' in data.acl %}
{% for priv in data.acl.changed %}
{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}{% endif %}
{% if 'added' in data.acl %}
{% for priv in data.acl.added %}
{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}{% endif %}{% endif %}
{% if data.change_func == False %}
{% if data.variables %}
{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %}
{{ VARIABLE.UNSET(conn, 'FUNCTION', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames ) }}
{% endif -%}
{% if 'merged_variables' in data and data.merged_variables|length > 0 %}
{{ VARIABLE.SET(conn, 'FUNCTION', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames ) }}
{% endif %}
{% endif %}{% endif %}
{% set seclabels = data.seclabels %}
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
{% for r in seclabels.deleted %}
{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}{% endif -%}
{% if data.description %}
COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
IS {{ data.description|qtLiteral }};
{% endif -%}
{% if data.pronamespace %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
SET SCHEMA {{ conn|qtIdent(data.pronamespace) }};
{% endif -%}
{% endif %}

View File

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

View File

@ -0,0 +1,35 @@
SELECT
COALESCE(gt.rolname, 'public') AS grantee,
g.rolname AS 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
(d).grantee AS grantee, (d).grantor AS grantor,
(d).is_grantable AS is_grantable,
(d).privilege_type AS privilege_type
FROM
(SELECT aclexplode(db.proacl) AS d FROM pg_proc db
WHERE db.oid = {{fnid}}::OID) a
) d
) d
LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
GROUP BY g.rolname, gt.rolname;

View File

@ -0,0 +1,52 @@
{% import 'macros/functions/security.macros' as SECLABEL %}
{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
{% import 'macros/functions/variable.macros' as VARIABLE %}
{% set is_columns = [] %}
{% if data %}
CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}()
RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }}
LANGUAGE {{ data.lanname|qtLiteral }}
{% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proleakproof %} LEAKPROOF {% else %} NOT LEAKPROOF {% endif %}
{% if data.proisstrict %}STRICT {% endif %}
{% if data.prosecdef %}SECURITY DEFINER {% endif %}
{% if data.proiswindow %}WINDOW{% endif %}{% if data.procost %}
COST {{data.procost}}{% endif %}{% if data.prorows %}
ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %}
SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %}
{% endif %}
AS {% if data.lanname == 'c' %}
{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
{% else %}
$BODY$
{{ data.prosrc }}
$BODY${% endif -%};
{% if data.funcowner %}
ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
OWNER TO {{ data.funcowner }};
{% endif -%}
{% if data.acl %}
{% for p in data.acl %}
{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}}
{% endfor -%}
{% endif -%}
{% if data.description %}
COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
IS '{{ data.description }}';
{% endif -%}
{% if data.seclabels %}
{% for r in data.seclabels %}
{% if r.security_label and r.provider %}
{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
{% endif %}
{% endfor %}
{% endif -%}
{% endif -%}

View File

@ -0,0 +1,22 @@
{% if scid and fnid %}
SELECT
pr.proname as name, '(' || COALESCE(pg_catalog
.pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args,
nspname
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname IN ('trigger', 'event_trigger')
AND pr.oid = {{fnid}};
{% endif %}
{% if name %}
DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade%} CASCADE{%
endif %};
{% endif %}

View File

@ -0,0 +1,11 @@
SELECT
pg_get_functiondef({{fnid}}::oid) AS func_def,
nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name
FROM
pg_proc pr
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND pr.oid = {{fnid}}::oid;

View File

@ -0,0 +1,4 @@
SELECT
lanname as label, lanname as value
FROM
pg_language;

View File

@ -0,0 +1,18 @@
SELECT
pr.oid, pr.proname || '(' || COALESCE(pg_catalog
.pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
lanname, pg_get_userbyid(proowner) as funcowner
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_language lng ON lng.oid=prolang
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
AND nsp.nspname={{ nspname|qtLiteral }}
WHERE
proisagg = FALSE
AND typname IN ('trigger', 'event_trigger')
AND lanname NOT IN ('edbspl', 'sql', 'internal')
AND pr.proname = {{ name|qtLiteral }};

View File

@ -0,0 +1,6 @@
SELECT
format_type(oid, NULL) AS out_arg_type
FROM
pg_type
WHERE
oid = {{ out_arg_oid }}::oid;

View File

@ -0,0 +1,6 @@
SELECT
nspname
FROM
pg_namespace
WHERE
oid = {{ scid }}::oid;

View File

@ -0,0 +1,20 @@
SELECT
*
FROM
(SELECT
format_type(t.oid,NULL) AS typname,
CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname,
(SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup
FROM
pg_type t
JOIN
pg_namespace nsp ON typnamespace=nsp.oid
WHERE
(NOT (typname = 'unknown' AND nspname = 'pg_catalog'))
AND
(
typtype IN ('b', 'c', 'd', 'e', 'p', 'r')
AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger')
)
) AS dummy
ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1;

View File

@ -0,0 +1,18 @@
SELECT
pr.oid, pr.proname || '()' AS name,
lanname, pg_get_userbyid(proowner) AS funcowner, description
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_language lng ON lng.oid=prolang
LEFT OUTER JOIN
pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname IN ('trigger', 'event_trigger')
AND lanname NOT IN ('edbspl', 'sql', 'internal')
ORDER BY
proname;

View File

@ -0,0 +1,32 @@
SELECT
pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c,
pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename,
typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames,
pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description,
(SELECT
array_agg(provider || '=' || label)
FROM
pg_shseclabel sl1
WHERE
sl1.objoid=pr.oid) AS seclabels
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_namespace typns ON typns.oid=typ.typnamespace
JOIN
pg_language lng ON lng.oid=prolang
LEFT OUTER JOIN
pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname IN ('trigger', 'event_trigger')
AND lanname NOT IN ('edbspl', 'sql', 'internal')
{% if fnid %}
AND pr.oid = {{fnid}}::oid
{% endif %}
ORDER BY
proname;

View File

@ -0,0 +1,109 @@
{% import 'macros/functions/security.macros' as SECLABEL %}
{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %}
{% set name = o_data.name %}
{% if data.name %}
{% if data.name != o_data.name %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{o_data.proargtypenames }})
RENAME TO {{ conn|qtIdent(data.name) }};
{% set name = data.name %}
{% endif %}
{% endif -%}
{% if data.change_func %}
CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}()
RETURNS {{ o_data.prorettypename }}
{% if 'lanname' in data %}
LANGUAGE {{ data.lanname|qtLiteral }} {% else %}
LANGUAGE {{ o_data.lanname|qtLiteral }}
{% endif %}{% if 'provolatile' in data and data.provolatile %}{{ data.provolatile }} {% elif 'provolatile' not in data and o_data.provolatile %}{{ o_data.provolatile }}{% endif %}
{% if ('proleakproof' in data and data.proleakproof) or ('proleakproof' not in data and o_data.proleakproof) %} LEAKPROOF{% elif 'proleakproof' in data and not data.proleakproof %} NOT LEAKPROOF{% endif %}
{% if ('proisstrict' in data and data.proisstrict) or ('proisstrict' not in data and o_data.proisstrict) %} STRICT{% endif %}
{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %}
{% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %}
{% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %}
ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}}{% endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %}
SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
{% endif %}
AS {% if 'probin' in data or 'prosrc_c' in data %}
{% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %}
$BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %}
{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %}
$BODY${{ o_data.prosrc }}$BODY${% endif -%};
{% endif -%}
{% if data.funcowner %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }})
OWNER TO {{ data.funcowner }};
{% endif -%}
{# The SQL generated below will change priviledges #}
{% if data.acl %}
{% if 'deleted' in data.acl %}
{% for priv in data.acl.deleted %}
{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'changed' in data.acl %}
{% for priv in data.acl.changed %}
{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'added' in data.acl %}
{% for priv in data.acl.added %}
{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif %}
{% endif -%}
{% if data.change_func == False %}
{% if data.variables %}
{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %}
{{ VARIABLE.UNSET(conn, 'FUNCTION', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames ) }}
{% endif -%}
{% if 'merged_variables' in data and data.merged_variables|length > 0 %}
{{ VARIABLE.SET(conn, 'FUNCTION', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames ) }}
{% endif -%}
{% endif -%}
{% endif -%}
{% set seclabels = data.seclabels %}
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
{% for r in seclabels.deleted %}
{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if data.description %}
COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }})
IS {{ data.description|qtLiteral }};
{% endif -%}
{% if data.pronamespace %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{ o_data.proargtypenames }})
SET SCHEMA {{ conn|qtIdent(data.pronamespace) }};
{% endif -%}
{% endif %}

View File

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

View File

@ -0,0 +1,35 @@
SELECT
COALESCE(gt.rolname, 'public') AS grantee,
g.rolname AS 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
(d).grantee AS grantee, (d).grantor AS grantor,
(d).is_grantable AS is_grantable,
(d).privilege_type AS privilege_type
FROM
(SELECT aclexplode(db.proacl) AS d FROM pg_proc db
WHERE db.oid = {{fnid}}::OID) a
) d
) d
LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
GROUP BY g.rolname, gt.rolname;

View File

@ -0,0 +1,51 @@
{% import 'macros/functions/security.macros' as SECLABEL %}
{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
{% import 'macros/functions/variable.macros' as VARIABLE %}
{% set is_columns = [] %}
{% if data %}
CREATE FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}()
RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }}
LANGUAGE {{ data.lanname|qtLiteral }}
{% if data.provolatile %}{{ data.provolatile }} {% endif %}{% if data.proleakproof %}LEAKPROOF {% else %}NOT LEAKPROOF {% endif %}
{% if data.proisstrict %}STRICT {% endif %}
{% if data.prosecdef %}SECURITY DEFINER {% endif %}
{% if data.proiswindow %}WINDOW{% endif %}{% if data.procost %}
COST {{data.procost}}{% endif %}{% if data.prorows %}
ROWS {{data.prorows}}{% endif -%}{% if data.variables %}{% for v in data.variables %}
SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor %}
{% endif %}
AS {% if data.lanname == 'c' %}
{{ data.probin|qtLiteral }}, {{ data.prosrc_c|qtLiteral }}
{% else %}
$BODY$
{{ data.prosrc }}
$BODY${% endif -%};
{% if data.funcowner %}
ALTER FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
OWNER TO {{ data.funcowner }};
{% endif -%}
{% if data.acl %}
{% for p in data.acl %}
{{ PRIVILEGE.SET(conn, "FUNCTION", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args)}}
{% endfor %}{% endif %}
{% if data.description %}
COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
IS '{{ data.description }}';
{% endif -%}
{% if data.seclabels %}
{% for r in data.seclabels %}
{% if r.security_label and r.provider %}
{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.security_label, data.pronamespace, data.func_args) }}
{% endif %}
{% endfor %}
{% endif -%}
{% endif %}

View File

@ -0,0 +1,21 @@
{% if scid and fnid %}
SELECT
pr.proname as name, '(' || COALESCE(pg_catalog
.pg_get_function_identity_arguments(pr.oid), '') || ')' as func_args,
nspname
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname IN ('trigger', 'event_trigger')
AND pr.oid = {{fnid}};
{% endif %}
{% if name %}
DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %};
{% endif %}

View File

@ -0,0 +1,11 @@
SELECT
pg_get_functiondef({{fnid}}::oid) AS func_def,
nspname || '.' || pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' as name
FROM
pg_proc pr
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND pr.oid = {{fnid}}::oid;

View File

@ -0,0 +1,4 @@
SELECT
lanname as label, lanname as value
FROM
pg_language;

View File

@ -0,0 +1,18 @@
SELECT
pr.oid, pr.proname || '(' || COALESCE(pg_catalog
.pg_get_function_identity_arguments(pr.oid), '') || ')' as name,
lanname, pg_get_userbyid(proowner) as funcowner
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_language lng ON lng.oid=prolang
JOIN
pg_namespace nsp ON nsp.oid=pr.pronamespace
AND nsp.nspname={{ nspname|qtLiteral }}
WHERE
proisagg = FALSE
AND typname IN ('trigger', 'event_trigger')
AND lanname NOT IN ('edbspl', 'sql', 'internal')
AND pr.proname = {{ name|qtLiteral }};

View File

@ -0,0 +1,6 @@
SELECT
format_type(oid, NULL) AS out_arg_type
FROM
pg_type
WHERE
oid = {{ out_arg_oid }}::oid;

View File

@ -0,0 +1,6 @@
SELECT
nspname
FROM
pg_namespace
WHERE
oid = {{ scid }}::oid;

View File

@ -0,0 +1,20 @@
SELECT
*
FROM
(SELECT
format_type(t.oid,NULL) AS typname,
CASE WHEN typelem > 0 THEN typelem ELSE t.oid END as elemoid, typlen, typtype, t.oid, nspname,
(SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup
FROM
pg_type t
JOIN
pg_namespace nsp ON typnamespace=nsp.oid
WHERE
(NOT (typname = 'unknown' AND nspname = 'pg_catalog'))
AND
(
typtype IN ('b', 'c', 'd', 'e', 'p', 'r')
AND typname NOT IN ('any', 'trigger', 'language_handler', 'event_trigger')
)
) AS dummy
ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1;

View File

@ -0,0 +1,18 @@
SELECT
pr.oid, pr.proname || '()' AS name,
lanname, pg_get_userbyid(proowner) AS funcowner, description
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_language lng ON lng.oid=prolang
LEFT OUTER JOIN
pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname IN ('trigger', 'event_trigger')
AND lanname NOT IN ('edbspl', 'sql', 'internal')
ORDER BY
proname;

View File

@ -0,0 +1,32 @@
SELECT
pr.oid, pr.xmin, pr.*, pr.prosrc AS prosrc_c,
pr.proname AS name, pg_get_function_result(pr.oid) AS prorettypename,
typns.nspname AS typnsp, lanname, proargnames, oidvectortypes(proargtypes) AS proargtypenames,
pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals,
pronargdefaults, proconfig, pg_get_userbyid(proowner) AS funcowner, description,
(SELECT
array_agg(provider || '=' || label)
FROM
pg_shseclabel sl1
WHERE
sl1.objoid=pr.oid) AS seclabels
FROM
pg_proc pr
JOIN
pg_type typ ON typ.oid=prorettype
JOIN
pg_namespace typns ON typns.oid=typ.typnamespace
JOIN
pg_language lng ON lng.oid=prolang
LEFT OUTER JOIN
pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
WHERE
proisagg = FALSE
AND pronamespace = {{scid}}::oid
AND typname IN ('trigger', 'event_trigger')
AND lanname NOT IN ('edbspl', 'sql', 'internal')
{% if fnid %}
AND pr.oid = {{fnid}}::oid
{% endif %}
ORDER BY
proname;

View File

@ -0,0 +1,109 @@
{% import 'macros/functions/security.macros' as SECLABEL %}
{% import 'macros/functions/privilege.macros' as PRIVILEGE %}
{% import 'macros/functions/variable.macros' as VARIABLE %}{% if data %}
{% set name = o_data.name %}
{% if data.name %}
{% if data.name != o_data.name %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}({{
o_data.proargtypenames }})
RENAME TO {{ conn|qtIdent(data.name) }};
{% set name = data.name %}
{% endif %}
{% endif -%}
{% if data.change_func %}
CREATE OR REPLACE FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}()
RETURNS {{ o_data.prorettypename }}
{% if 'lanname' in data %}
LANGUAGE {{ data.lanname|qtLiteral }} {% else %}
LANGUAGE {{ o_data.lanname|qtLiteral }}
{% endif %}{% if 'provolatile' in data and data.provolatile %}{{ data.provolatile }} {% elif 'provolatile' not in data and o_data.provolatile %}{{ o_data.provolatile }}{% endif %}
{% if ('proleakproof' in data and data.proleakproof) or ('proleakproof' not in data and o_data.proleakproof) %} LEAKPROOF{% elif 'proleakproof' in data and not data.proleakproof %} NOT LEAKPROOF{% endif %}
{% if ('proisstrict' in data and data.proisstrict) or ('proisstrict' not in data and o_data.proisstrict) %} STRICT{% endif %}
{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %}
{% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %}
{% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %}
ROWS {{data.prorows}}{% elif o_data.prorows %}ROWS {{o_data.prorows}} {%endif -%}{% if data.merged_variables %}{% for v in data.merged_variables %}
SET {{ conn|qtIdent(v.name) }}={{ v.value|qtLiteral }}{% endfor -%}
{% endif %}
AS {% if 'probin' in data or 'prosrc_c' in data %}
{% if 'probin' in data %}{{ data.probin|qtLiteral }}{% else %}{{ o_data.probin|qtLiteral }}{% endif %}, {% if 'prosrc_c' in data %}{{ data.prosrc_c|qtLiteral }}{% else %}{{ o_data.prosrc_c|qtLiteral }}{% endif %}{% elif 'prosrc' in data %}
$BODY${{ data.prosrc }}$BODY${% elif o_data.lanname == 'c' %}
{{ o_data.probin|qtLiteral }}, {{ o_data.prosrc_c|qtLiteral }}{% else %}
$BODY${{ o_data.prosrc }}$BODY${% endif -%};
{% endif -%}
{% if data.funcowner %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
OWNER TO {{ data.funcowner }};
{% endif -%}
{# The SQL generated below will change priviledges #}
{% if data.acl %}
{% if 'deleted' in data.acl %}
{% for priv in data.acl.deleted %}
{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'changed' in data.datacl %}
{% for priv in data.acl.changed %}
{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'added' in data.acl %}
{% for priv in data.acl.added %}
{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}{% endif -%}
{% endif -%}
{% if data.change_func == False %}
{% if data.variables %}
{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %}
{{ VARIABLE.UNSET(conn, 'FUNCTION', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames) }}
{% endif -%}
{% if 'merged_variables' in data and data.merged_variables|length > 0 %}
{{ VARIABLE.SET(conn, 'FUNCTION', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames) }}
{% endif -%}
{% endif -%}
{% endif -%}
{% set seclabels = data.seclabels %}
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
{% for r in seclabels.deleted %}
{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.security_label, o_data.pronamespace, o_data.proargtypenames) }}
{% endfor %}
{% endif -%}
{% if data.description %}
COMMENT ON FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
IS {{ data.description|qtLiteral }};
{% endif -%}
{% if data.pronamespace %}
ALTER FUNCTION {{ conn|qtIdent(o_data.pronamespace, name) }}({{o_data.proargtypenames }})
SET SCHEMA {{ conn|qtIdent(data.pronamespace) }};
{% endif -%}
{% endif %}

View File

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

View File

@ -2,12 +2,18 @@
{# Macros for Variables (functions module) #}
{################################################}
{% macro SET(conn, object_type, object_name, options, schema, func_args) -%}
{% for opt in options %}
ALTER {{object_type}} {{ conn|qtIdent(schema, object_name) }}({{func_args}})
SET ({% for opt in options %}{% if loop.index != 1 %}
, {% endif %}{{ conn|qtIdent(opt.name) }}={{ opt.value|qtLiteral }}{% endfor %});
SET {{ conn|qtIdent(opt.name) }}={{ opt.value|qtLiteral }};
{% endfor %}
{%- endmacro %}
{% macro UNSET(conn, object_type, object_name, options, schema, func_args) -%}
{% for opt in options %}
ALTER {{object_type}} {{ conn|qtIdent(schema, object_name) }}({{func_args}})
RESET ({% for opt in options %}{% if loop.index != 1 %}
, {% endif %}{{ conn|qtIdent(opt.name) }}{% endfor %});
RESET {{ conn|qtIdent(opt.name) }};
{% endfor %}
{%- endmacro %}