mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Function and procedure support for PG11. Fixes #3362
This commit is contained in:
committed by
Dave Page
parent
e5048b4d0b
commit
d1ecba56b8
@@ -1502,7 +1502,10 @@ class FunctionView(PGChildNodeView, DataTypeReader):
|
||||
name = name.replace(arg, formatted_arg)
|
||||
|
||||
name = name.replace(')', '\n)')
|
||||
sql = "EXEC {0}".format(name)
|
||||
if self.manager.server_type == 'pg':
|
||||
sql = "CALL {0}".format(name)
|
||||
else:
|
||||
sql = "EXEC {0}".format(name)
|
||||
|
||||
return ajax_response(response=sql)
|
||||
|
||||
@@ -1592,10 +1595,11 @@ class ProcedureModule(SchemaChildModule):
|
||||
"""
|
||||
super(ProcedureModule, self).__init__(*args, **kwargs)
|
||||
|
||||
self.min_ver = 90100
|
||||
self.min_ver = 110000
|
||||
self.max_ver = None
|
||||
self.min_ppasver = 90100
|
||||
self.min_gpdbver = 1000000000
|
||||
self.server_type = ['ppas']
|
||||
self.server_type = ['pg', 'ppas']
|
||||
|
||||
def get_nodes(self, gid, sid, did, scid):
|
||||
"""
|
||||
|
||||
@@ -71,10 +71,13 @@ define('pgadmin.node.procedure', [
|
||||
if ('catalog' in node_hierarchy)
|
||||
return false;
|
||||
|
||||
// Procedures supported only in PPAS
|
||||
// Procedures supported only in PPAS and PG >= 11
|
||||
return (
|
||||
'server' in node_hierarchy &&
|
||||
node_hierarchy['server'].server_type == 'ppas'
|
||||
'server' in node_hierarchy && (
|
||||
node_hierarchy['server'].server_type == 'ppas' ||
|
||||
(node_hierarchy['server'].server_type == 'pg' &&
|
||||
node_hierarchy['server'].version >= 110000)
|
||||
)
|
||||
);
|
||||
},
|
||||
model: Function.model.extend({
|
||||
@@ -103,20 +106,24 @@ define('pgadmin.node.procedure', [
|
||||
return true;
|
||||
}
|
||||
switch(this.name){
|
||||
case 'provolatility':
|
||||
case 'provolatile':
|
||||
case 'proisstrict':
|
||||
case 'prosecdef':
|
||||
case 'procost':
|
||||
case 'proleakproof':
|
||||
return (this.node_info.server.version < 90500 || this.node_info.server.server_type != 'ppas');
|
||||
case 'variables':
|
||||
case 'prosecdef':
|
||||
return this.node_info.server.version < 90500;
|
||||
case 'prorows':
|
||||
var server = this.node_info.server;
|
||||
return !(server.version >= 90500 && m.get('proretset') == true);
|
||||
case 'funcowner':
|
||||
case 'lanname':
|
||||
case 'proargs':
|
||||
return true;
|
||||
case 'proparallel':
|
||||
return (this.node_info.server.version < 90600 || this.node_info.server.server_type != 'ppas');
|
||||
case 'lanname':
|
||||
return this.node_info.server.version < 110000;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
SELECT
|
||||
funcname AS {{ conn|qtIdent(_('Name')) }},
|
||||
calls AS {{ conn|qtIdent(_('Number of calls')) }},
|
||||
total_time AS {{ conn|qtIdent(_('Total time')) }},
|
||||
self_time AS {{ conn|qtIdent(_('Self time')) }}
|
||||
FROM
|
||||
pg_stat_user_functions
|
||||
WHERE
|
||||
schemaname = {{schema_name|qtLiteral}}
|
||||
AND funcid IN (
|
||||
SELECT p.oid
|
||||
FROM
|
||||
pg_proc p
|
||||
JOIN
|
||||
pg_type typ ON typ.oid=p.prorettype
|
||||
WHERE
|
||||
p.prokind IN ('f', 'w')
|
||||
AND typname NOT IN ('trigger', 'event_trigger')
|
||||
)
|
||||
ORDER BY funcname;
|
||||
@@ -0,0 +1,70 @@
|
||||
{% 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 %}
|
||||
{% if query_for == 'sql_panel' and func_def is defined %}
|
||||
CREATE{% if query_type is defined %}{{' OR REPLACE'}}{% endif %} FUNCTION {{func_def}}
|
||||
{% else %}
|
||||
CREATE{% if query_type is defined %}{{' OR REPLACE'}}{% endif %} FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({% if data.arguments %}
|
||||
{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname) }} {% endif %}{% if p.argtype %}{{ conn|qtTypeIdent(p.argtype) }}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %}
|
||||
{% if not loop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
)
|
||||
{% endif %}
|
||||
RETURNS{% if data.proretset and (data.prorettypename.startswith('SETOF ') or data.prorettypename.startswith('TABLE')) %} {{ data.prorettypename }} {% elif data.proretset %} SETOF {{ conn|qtTypeIdent(data.prorettypename) }}{% else %} {{ conn|qtTypeIdent(data.prorettypename) }}{% endif %}
|
||||
|
||||
LANGUAGE {{ data.lanname|qtLiteral }}
|
||||
{% if data.procost %}
|
||||
|
||||
COST {{data.procost}}
|
||||
{% endif %}
|
||||
{% if data.provolatile %}{% if data.provolatile == 'i' %}IMMUTABLE{% elif data.provolatile == 's' %}STABLE{% else %}VOLATILE{% endif %} {% endif %}{% if data.proleakproof %}LEAKPROOF {% endif %}
|
||||
{% if data.proisstrict %}STRICT {% endif %}
|
||||
{% if data.prosecdef %}SECURITY DEFINER {% endif %}
|
||||
{% if data.proiswindow %}WINDOW {% endif %}
|
||||
{% if data.proparallel and (data.proparallel == 'r' or data.proparallel == 's') %}
|
||||
{% if data.proparallel == 'r' %}PARALLEL RESTRICTED{% elif data.proparallel == 's' %}PARALLEL SAFE{% endif %}{% endif -%}
|
||||
{% if data.prorows and (data.prorows | int) > 0 %}
|
||||
|
||||
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_without}})
|
||||
OWNER TO {{ conn|qtIdent(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_without)}}
|
||||
{% endfor %}{% endif %}
|
||||
{% if data.revoke_all %}
|
||||
|
||||
{{ PRIVILEGE.UNSETALL(conn, "FUNCTION", "PUBLIC", data.name, data.pronamespace, data.func_args_without)}}
|
||||
{% endif %}
|
||||
{% if data.description %}
|
||||
|
||||
COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args_without}})
|
||||
IS {{ data.description|qtLiteral }};
|
||||
{% endif -%}
|
||||
{% if data.seclabels %}
|
||||
{% for r in data.seclabels %}
|
||||
{% if r.label and r.provider %}
|
||||
|
||||
{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.label, data.pronamespace, data.func_args_without) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
|
||||
{% endif %}
|
||||
@@ -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
|
||||
pr.prokind IN ('f', 'w')
|
||||
AND pronamespace = {{scid}}::oid
|
||||
AND typname NOT IN ('trigger', 'event_trigger')
|
||||
AND pr.oid = {{fnid}};
|
||||
{% endif %}
|
||||
|
||||
{% if name %}
|
||||
DROP FUNCTION {{ conn|qtIdent(nspname, name) }}{{func_args}}{% if cascade %} CASCADE{% endif %};
|
||||
{% endif %}
|
||||
@@ -0,0 +1,15 @@
|
||||
SELECT
|
||||
pg_get_functiondef({{fnid}}::oid) AS func_def,
|
||||
COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') as
|
||||
func_with_identity_arguments,
|
||||
nspname,
|
||||
pr.proname as proname,
|
||||
COALESCE(pg_catalog.pg_get_function_arguments(pr.oid), '') as func_args
|
||||
FROM
|
||||
pg_proc pr
|
||||
JOIN
|
||||
pg_namespace nsp ON nsp.oid=pr.pronamespace
|
||||
WHERE
|
||||
pr.prokind IN ('f', 'w')
|
||||
AND pronamespace = {{scid}}::oid
|
||||
AND pr.oid = {{fnid}}::oid;
|
||||
@@ -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, pr.pronamespace as nsp
|
||||
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
|
||||
pr.prokind IN ('f', 'w')
|
||||
AND typname NOT IN ('trigger', 'event_trigger')
|
||||
AND pr.proname = {{ name|qtLiteral }};
|
||||
@@ -0,0 +1,22 @@
|
||||
SELECT
|
||||
pr.oid, pr.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') || ')' 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
|
||||
pr.prokind IN ('f', 'w')
|
||||
{% if fnid %}
|
||||
AND pr.oid = {{ fnid|qtLiteral }}
|
||||
{% endif %}
|
||||
{% if scid %}
|
||||
AND pronamespace = {{scid}}::oid
|
||||
{% endif %}
|
||||
AND typname NOT IN ('trigger', 'event_trigger')
|
||||
ORDER BY
|
||||
proname;
|
||||
@@ -0,0 +1,33 @@
|
||||
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,
|
||||
CASE WHEN pr.prokind = 'w' THEN TRUE ELSE FALSE END AS proiswindow,
|
||||
(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
|
||||
pr.prokind IN ('f', 'w')
|
||||
{% if fnid %}
|
||||
AND pr.oid = {{fnid}}::oid
|
||||
{% else %}
|
||||
AND pronamespace = {{scid}}::oid
|
||||
{% endif %}
|
||||
AND typname NOT IN ('trigger', 'event_trigger')
|
||||
ORDER BY
|
||||
proname;
|
||||
@@ -0,0 +1,116 @@
|
||||
{% 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) }}({% if data.arguments %}
|
||||
{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname) }} {% endif %}{% if p.argtype %}{{ conn|qtTypeIdent(p.argtype) }}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %}
|
||||
{% if not loop.last %},{% endif %}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
)
|
||||
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 'proparallel' in data and data.proparallel %}PARALLEL {{ data.proparallel }}{% elif 'proparallel' not in data and o_data.proparallel %}PARALLEL {{ o_data.proparallel }}{% endif %}
|
||||
|
||||
{% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %}
|
||||
|
||||
ROWS {{data.prorows}}{% elif data.prorows is not defined and o_data.prorows and o_data.prorows != '0' %} 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 {{ conn|qtIdent(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.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.label, o_data.pronamespace, o_data.proargtypenames) }}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if data.description is defined and data.description != o_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 %}
|
||||
@@ -13,7 +13,7 @@ CREATE{% if query_type is defined %}{{' OR REPLACE'}}{% endif %} FUNCTION {{ con
|
||||
{% endif -%}
|
||||
)
|
||||
{% endif -%}
|
||||
RETURNS{% if data.proretset (data.prorettypename.startswith('SETOF ') or data.prorettypename.startswith('TABLE')) %} {{ data.prorettypename }} {% elif data.proretset %} SETOF {{ conn|qtTypeIdent(data.prorettypename) }}{% else %} {{ conn|qtTypeIdent(data.prorettypename) }}{% endif %}
|
||||
RETURNS{% if data.proretset and (data.prorettypename.startswith('SETOF ') or data.prorettypename.startswith('TABLE')) %} {{ data.prorettypename }} {% elif data.proretset %} SETOF {{ conn|qtTypeIdent(data.prorettypename) }}{% else %} {{ conn|qtTypeIdent(data.prorettypename) }}{% endif %}
|
||||
|
||||
LANGUAGE {{ data.lanname|qtLiteral }}
|
||||
{% if data.procost %}
|
||||
|
||||
@@ -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;
|
||||
@@ -0,0 +1,20 @@
|
||||
SELECT
|
||||
funcname AS {{ conn|qtIdent(_('Name')) }},
|
||||
calls AS {{ conn|qtIdent(_('Number of calls')) }},
|
||||
total_time AS {{ conn|qtIdent(_('Total time')) }},
|
||||
self_time AS {{ conn|qtIdent(_('Self time')) }}
|
||||
FROM
|
||||
pg_stat_user_functions
|
||||
WHERE
|
||||
schemaname = {{schema_name|qtLiteral}}
|
||||
AND funcid IN (
|
||||
SELECT p.oid
|
||||
FROM
|
||||
pg_proc p
|
||||
JOIN
|
||||
pg_type typ ON typ.oid=p.prorettype
|
||||
WHERE
|
||||
p.prokind = 'p'::char
|
||||
AND typname NOT IN ('trigger', 'event_trigger')
|
||||
)
|
||||
ORDER BY funcname;
|
||||
@@ -0,0 +1,50 @@
|
||||
{% 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 %}
|
||||
{% if query_for == 'sql_panel' and func_def is defined %}
|
||||
CREATE OR REPLACE PROCEDURE {{func_def}}
|
||||
{% else %}
|
||||
CREATE OR REPLACE PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }}{% if data.arguments is defined %}
|
||||
({% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname)}} {% endif %}{% if p.argtype %}{{ conn|qtTypeIdent(p.argtype) }}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %}
|
||||
{% if not loop.last %}, {% endif %}
|
||||
{% endfor -%}
|
||||
{% endif %}
|
||||
)
|
||||
{% endif %}
|
||||
LANGUAGE {{ data.lanname|qtLiteral }}
|
||||
{% if data.prosecdef %}SECURITY DEFINER {% 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.acl and not is_sql %}
|
||||
{% for p in data.acl %}
|
||||
|
||||
{{ PRIVILEGE.SET(conn, "PROCEDURE", p.grantee, data.name, p.without_grant, p.with_grant, data.pronamespace, data.func_args_without)}}
|
||||
{% endfor %}{% endif %}
|
||||
{% if data.revoke_all %}
|
||||
|
||||
{{ PRIVILEGE.UNSETALL(conn, "PROCEDURE", "PUBLIC", data.name, data.pronamespace, data.func_args_without)}}
|
||||
{% endif %}
|
||||
{% if data.description %}
|
||||
|
||||
COMMENT ON PROCEDURE {{ conn|qtIdent(data.pronamespace, data.name) }}
|
||||
IS {{ data.description|qtLiteral }};
|
||||
{% endif -%}
|
||||
{% if data.seclabels %}
|
||||
{% for r in data.seclabels %}
|
||||
{% if r.label and r.provider %}
|
||||
|
||||
{{ SECLABEL.SET(conn, 'PROCEDURE', data.name, r.provider, r.label, data.pronamespace, data.func_args_without) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
|
||||
{% endif %}
|
||||
@@ -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
|
||||
pr.prokind = 'p'::char
|
||||
AND pronamespace = {{scid}}::oid
|
||||
AND typname NOT IN ('trigger', 'event_trigger')
|
||||
AND pr.oid = {{fnid}};
|
||||
{% endif %}
|
||||
|
||||
{% if name %}
|
||||
DROP PROCEDURE {{ conn|qtIdent(nspname, name) }};
|
||||
{% endif %}
|
||||
@@ -0,0 +1,15 @@
|
||||
SELECT
|
||||
pg_get_functiondef({{fnid}}::oid) AS func_def,
|
||||
COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') as
|
||||
func_with_identity_arguments,
|
||||
nspname,
|
||||
pr.proname as proname,
|
||||
COALESCE(pg_catalog.pg_get_function_arguments(pr.oid), '') as func_args
|
||||
FROM
|
||||
pg_proc pr
|
||||
JOIN
|
||||
pg_namespace nsp ON nsp.oid=pr.pronamespace
|
||||
WHERE
|
||||
pr.prokind = 'p'::char
|
||||
AND pronamespace = {{scid}}::oid
|
||||
AND pr.oid = {{fnid}}::oid;
|
||||
@@ -0,0 +1,4 @@
|
||||
SELECT
|
||||
lanname as label, lanname as value
|
||||
FROM
|
||||
pg_language;
|
||||
@@ -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, pr.pronamespace AS nsp
|
||||
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
|
||||
pr.prokind = 'p'::char
|
||||
AND typname NOT IN ('trigger', 'event_trigger')
|
||||
AND pr.proname = {{ name|qtLiteral }};
|
||||
@@ -0,0 +1,6 @@
|
||||
SELECT
|
||||
format_type(oid, NULL) AS out_arg_type
|
||||
FROM
|
||||
pg_type
|
||||
WHERE
|
||||
oid = {{ out_arg_oid }}::oid;
|
||||
@@ -0,0 +1,6 @@
|
||||
SELECT
|
||||
nspname
|
||||
FROM
|
||||
pg_namespace
|
||||
WHERE
|
||||
oid = {{ scid }}::oid;
|
||||
@@ -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;
|
||||
@@ -0,0 +1,29 @@
|
||||
SELECT
|
||||
pr.oid,
|
||||
CASE WHEN
|
||||
pg_catalog.pg_get_function_identity_arguments(pr.oid) <> ''
|
||||
THEN
|
||||
pr.proname || '(' || pg_catalog.pg_get_function_identity_arguments(pr.oid) || ')'
|
||||
ELSE
|
||||
pr.proname
|
||||
END 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
|
||||
pr.prokind = 'p'::char
|
||||
{% if fnid %}
|
||||
AND pr.oid = {{ fnid|qtLiteral }}
|
||||
{% endif %}
|
||||
{% if scid %}
|
||||
AND pronamespace = {{scid}}::oid
|
||||
{% endif %}
|
||||
AND typname NOT IN ('trigger', 'event_trigger')
|
||||
ORDER BY
|
||||
proname;
|
||||
@@ -0,0 +1,39 @@
|
||||
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,
|
||||
(CASE WHEN
|
||||
pg_catalog.pg_get_function_identity_arguments(pr.oid) <> ''
|
||||
THEN
|
||||
pr.proname || '(' || pg_catalog.pg_get_function_identity_arguments(pr.oid) || ')'
|
||||
ELSE
|
||||
pr.proname
|
||||
END) AS name_with_args,
|
||||
(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
|
||||
pr.prokind = 'p'
|
||||
AND typname NOT IN ('trigger', 'event_trigger')
|
||||
{% if fnid %}
|
||||
AND pr.oid = {{fnid}}::oid
|
||||
{% else %}
|
||||
AND pronamespace = {{scid}}::oid
|
||||
{% endif %}
|
||||
ORDER BY
|
||||
proname;
|
||||
@@ -0,0 +1,8 @@
|
||||
SELECT
|
||||
calls AS {{ conn|qtIdent(_('Number of calls')) }},
|
||||
total_time AS {{ conn|qtIdent(_('Total time')) }},
|
||||
self_time AS {{ conn|qtIdent(_('Self time')) }}
|
||||
FROM
|
||||
pg_stat_user_functions
|
||||
WHERE
|
||||
funcid = {{fnid}}::OID
|
||||
@@ -0,0 +1,106 @@
|
||||
{% import 'macros/functions/security.macros' as SECLABEL %}
|
||||
{% import 'macros/functions/privilege.macros' as PRIVILEGE %}{% if data %}
|
||||
{% set name = o_data.name %}
|
||||
{% if data.name %}
|
||||
{% if data.name != o_data.name %}
|
||||
ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, o_data.name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %}
|
||||
|
||||
RENAME TO {{ conn|qtIdent(data.name) }};
|
||||
{% set name = data.name %}
|
||||
{% endif %}
|
||||
|
||||
{% endif -%}
|
||||
{% if data.change_func %}
|
||||
CREATE OR REPLACE PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}({% if data.arguments %}{% for p in data.arguments %}{% if p.argmode %}{{p.argmode}} {% endif %}{% if p.argname %}{{ conn|qtIdent(p.argname) }} {% endif %}{% if p.argtype %}{{ conn|qtTypeIdent(p.argtype) }}{% endif %}{% if p.argdefval %} DEFAULT {{p.argdefval}}{% endif %}
|
||||
{% if not loop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
)
|
||||
{% if 'lanname' in data %}
|
||||
LANGUAGE {{ data.lanname|qtLiteral }} {% else %}
|
||||
LANGUAGE {{ o_data.lanname|qtLiteral }}
|
||||
{% endif %}
|
||||
{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %}SECURITY DEFINER{% 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 PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}{% if o_data.proargtypenames %}({{ o_data.proargtypenames }}){% endif %}
|
||||
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, 'PROCEDURE', 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, 'PROCEDURE', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
|
||||
|
||||
{{ PRIVILEGE.SET(conn, 'PROCEDURE', 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, 'PROCEDURE', 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, 'PROCEDURE', 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, 'PROCEDURE', name, r.provider, r.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, 'PROCEDURE', name, r.provider, r.label, o_data.pronamespace, o_data.proargtypenames) }}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if data.description is defined and data.description != o_data.description%}
|
||||
|
||||
COMMENT ON PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}
|
||||
IS {{ data.description|qtLiteral }};
|
||||
{% endif -%}
|
||||
{% if data.pronamespace %}
|
||||
|
||||
ALTER PROCEDURE {{ conn|qtIdent(o_data.pronamespace, name) }}
|
||||
SET SCHEMA {{ conn|qtIdent(data.pronamespace) }};
|
||||
{% endif -%}
|
||||
|
||||
{% endif %}
|
||||
@@ -0,0 +1,6 @@
|
||||
SELECT
|
||||
name, vartype, min_val, max_val, enumvals
|
||||
FROM
|
||||
pg_settings
|
||||
WHERE
|
||||
context in ('user', 'superuser');
|
||||
@@ -0,0 +1,20 @@
|
||||
SELECT
|
||||
funcname AS {{ conn|qtIdent(_('Name')) }},
|
||||
calls AS {{ conn|qtIdent(_('Number of calls')) }},
|
||||
total_time AS {{ conn|qtIdent(_('Total time')) }},
|
||||
self_time AS {{ conn|qtIdent(_('Self time')) }}
|
||||
FROM
|
||||
pg_stat_user_functions
|
||||
WHERE
|
||||
schemaname = {{schema_name|qtLiteral}}
|
||||
AND funcid IN (
|
||||
SELECT p.oid
|
||||
FROM
|
||||
pg_proc p
|
||||
JOIN
|
||||
pg_type typ ON typ.oid=p.prorettype
|
||||
WHERE
|
||||
p.prokind IN ('f', 'w')
|
||||
AND typname = 'trigger'
|
||||
)
|
||||
ORDER BY funcname;
|
||||
@@ -0,0 +1,57 @@
|
||||
{% 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) }}({% if data.proargnames %}{{data.proargnames}}{% endif %})
|
||||
RETURNS{% if data.proretset %} SETOF{% endif %} {{ conn|qtTypeIdent(data.prorettypename) }}
|
||||
LANGUAGE {{ data.lanname|qtLiteral }}
|
||||
{% if data.procost %}
|
||||
COST {{data.procost}}
|
||||
{% endif %}
|
||||
{% if data.provolatile %}{% if data.provolatile == 'i' %}IMMUTABLE{% elif data.provolatile == 's' %}STABLE{% else %}VOLATILE{% endif %} {% 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.prorows and (data.prorows | int) > 0 %}
|
||||
|
||||
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 {{ conn|qtIdent(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.revoke_all %}
|
||||
|
||||
{{ PRIVILEGE.UNSETALL(conn, "FUNCTION", "PUBLIC", data.name, data.pronamespace, data.func_args_without)}}
|
||||
{% endif %}
|
||||
{% if data.description %}
|
||||
|
||||
COMMENT ON FUNCTION {{ conn|qtIdent(data.pronamespace, data.name) }}({{data.func_args}})
|
||||
IS {{ data.description|qtLiteral }};
|
||||
{% endif -%}
|
||||
{% if data.seclabels %}
|
||||
{% for r in data.seclabels %}
|
||||
{% if r.label and r.provider %}
|
||||
|
||||
{{ SECLABEL.SET(conn, 'FUNCTION', data.name, r.provider, r.label, data.pronamespace, data.func_args) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
|
||||
{% endif %}
|
||||
@@ -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
|
||||
pr.prokind IN ('f', 'w')
|
||||
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 %}
|
||||
@@ -0,0 +1,15 @@
|
||||
SELECT
|
||||
pg_get_functiondef({{fnid}}::oid) AS func_def,
|
||||
COALESCE(pg_catalog.pg_get_function_identity_arguments(pr.oid), '') as
|
||||
func_with_identity_arguments,
|
||||
nspname,
|
||||
pr.proname as proname,
|
||||
COALESCE(pg_catalog.pg_get_function_arguments(pr.oid), '') as func_args
|
||||
FROM
|
||||
pg_proc pr
|
||||
JOIN
|
||||
pg_namespace nsp ON nsp.oid=pr.pronamespace
|
||||
WHERE
|
||||
pr.prokind IN ('f', 'w')
|
||||
AND pronamespace = {{scid}}::oid
|
||||
AND pr.oid = {{fnid}}::oid;
|
||||
@@ -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, pr.pronamespace AS nsp
|
||||
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
|
||||
pr.prokind IN ('f', 'w')
|
||||
AND typname IN ('trigger', 'event_trigger')
|
||||
AND lanname NOT IN ('edbspl', 'sql', 'internal')
|
||||
AND pr.proname = {{ name|qtLiteral }};
|
||||
@@ -0,0 +1,23 @@
|
||||
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
|
||||
pr.prokind IN ('f', 'w')
|
||||
{% if fnid %}
|
||||
AND pr.oid = {{ fnid|qtLiteral }}
|
||||
{% endif %}
|
||||
{% if scid %}
|
||||
AND pronamespace = {{scid}}::oid
|
||||
{% endif %}
|
||||
AND typname IN ('trigger', 'event_trigger')
|
||||
AND lanname NOT IN ('edbspl', 'sql', 'internal')
|
||||
ORDER BY
|
||||
proname;
|
||||
@@ -0,0 +1,33 @@
|
||||
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
|
||||
pr.prokind IN ('f', 'w')
|
||||
AND typname IN ('trigger', 'event_trigger')
|
||||
AND lanname NOT IN ('edbspl', 'sql', 'internal')
|
||||
{% if fnid %}
|
||||
AND pr.oid = {{fnid}}::oid
|
||||
{% else %}
|
||||
AND pronamespace = {{scid}}::oid
|
||||
{% endif %}
|
||||
ORDER BY
|
||||
proname;
|
||||
@@ -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 data.prorows is not defined and o_data.prorows and o_data.prorows != '0' %} 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 {{ conn|qtIdent(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.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.label, o_data.pronamespace, o_data.proargtypenames) }}
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if data.description is defined and data.description != o_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 %}
|
||||
@@ -0,0 +1,80 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import json
|
||||
import uuid
|
||||
|
||||
|
||||
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||
database_utils
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as funcs_utils
|
||||
|
||||
|
||||
class FunctionAddTestCase(BaseTestGenerator):
|
||||
""" This class will add new function under schema node. """
|
||||
scenarios = [
|
||||
# Fetching default URL for function node.
|
||||
('Fetch Function Node URL', dict(
|
||||
url='/browser/function/obj/'))
|
||||
]
|
||||
|
||||
def runTest(self):
|
||||
""" This function will add function under schema node. """
|
||||
super(FunctionAddTestCase, self).runTest()
|
||||
self = funcs_utils.set_up(self)
|
||||
db_user = self.server["username"]
|
||||
data = {
|
||||
"acl": [
|
||||
{
|
||||
"grantee": db_user,
|
||||
"grantor": db_user,
|
||||
"privileges":
|
||||
[
|
||||
{
|
||||
"privilege_type": "X",
|
||||
"privilege": True,
|
||||
"with_grant": True
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"arguments": [],
|
||||
"funcowner": db_user,
|
||||
"lanname": "sql",
|
||||
"name": "test_function",
|
||||
"options": [],
|
||||
"proleakproof": True,
|
||||
"pronamespace": 2200,
|
||||
"prorettypename": "integer",
|
||||
"prosecdef": True,
|
||||
"prosrc": "SELECT 1;",
|
||||
"probin": "$libdir/",
|
||||
"provolatile": "s",
|
||||
"seclabels": [],
|
||||
"variables": []
|
||||
}
|
||||
|
||||
data["name"] = "test_function_add_%s" % str(uuid.uuid4())[1:8]
|
||||
if self.schema_id:
|
||||
data['pronamespace'] = self.schema_id
|
||||
else:
|
||||
self.schema_id = data['pronamespace']
|
||||
response = self.tester.post(
|
||||
self.url + str(utils.SERVER_GROUP) + '/' +
|
||||
str(self.server_id) + '/' + str(self.db_id) +
|
||||
'/' + str(self.schema_id) + '/',
|
||||
data=json.dumps(data),
|
||||
content_type='html/json'
|
||||
)
|
||||
|
||||
self.assertEquals(response.status_code, 200)
|
||||
# Disconnect the database
|
||||
database_utils.disconnect_database(self, self.server_id, self.db_id)
|
||||
@@ -0,0 +1,49 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import uuid
|
||||
|
||||
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||
database_utils
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as funcs_utils
|
||||
|
||||
|
||||
class FunctionDeleteTestCase(BaseTestGenerator):
|
||||
""" This class will delete the function under schema node. """
|
||||
scenarios = [
|
||||
# Fetching default URL for function node.
|
||||
('Fetch Function Node URL',
|
||||
dict(url='/browser/function/obj/'))
|
||||
]
|
||||
|
||||
def runTest(self):
|
||||
""" This function will delete function under database node. """
|
||||
super(FunctionDeleteTestCase, self).setUp()
|
||||
self = funcs_utils.set_up(self)
|
||||
|
||||
func_name = "test_function_delete_%s" % str(uuid.uuid4())[1:8]
|
||||
function_info = funcs_utils.create_function(
|
||||
self.server, self.db_name, self.schema_name, func_name)
|
||||
|
||||
func_id = function_info[0]
|
||||
response = self.tester.delete(
|
||||
self.url + str(utils.SERVER_GROUP) + '/' +
|
||||
str(self.server_id) + '/' +
|
||||
str(self.db_id) + '/' +
|
||||
str(self.schema_id) + '/' + str(func_id),
|
||||
content_type='html/json'
|
||||
)
|
||||
self.assertEquals(response.status_code, 200)
|
||||
# Disconnect the database
|
||||
database_utils.disconnect_database(self, self.server_id, self.db_id)
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
@@ -0,0 +1,49 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import uuid
|
||||
|
||||
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||
database_utils
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as funcs_utils
|
||||
|
||||
|
||||
class FunctionGetTestCase(BaseTestGenerator):
|
||||
"""This class will fetch added function under schema node."""
|
||||
skip_on_database = ['gpdb']
|
||||
scenarios = [
|
||||
# Fetching default URL for function node.
|
||||
('Fetch Function Node URL',
|
||||
dict(url='/browser/function/obj/'))
|
||||
]
|
||||
|
||||
def runTest(self):
|
||||
""" This function will delete function under database node. """
|
||||
super(FunctionGetTestCase, self).setUp()
|
||||
self = funcs_utils.set_up(self)
|
||||
|
||||
func_name = "test_function_get_%s" % str(uuid.uuid4())[1:8]
|
||||
function_info = funcs_utils.create_function(
|
||||
self.server, self.db_name, self.schema_name, func_name)
|
||||
|
||||
trigger_func_id = function_info[0]
|
||||
response = self.tester.get(
|
||||
self.url + str(utils.SERVER_GROUP) + '/' +
|
||||
str(self.server_id) + '/' +
|
||||
str(self.db_id) + '/' +
|
||||
str(self.schema_id) + '/' + str(trigger_func_id),
|
||||
content_type='html/json')
|
||||
self.assertEquals(response.status_code, 200)
|
||||
# Disconnect the database
|
||||
database_utils.disconnect_database(self, self.server_id, self.db_id)
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
@@ -0,0 +1,57 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import json
|
||||
import uuid
|
||||
|
||||
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||
database_utils
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as funcs_utils
|
||||
|
||||
|
||||
class FunctionPutTestCase(BaseTestGenerator):
|
||||
""" This class will update new function under schema node. """
|
||||
skip_on_database = ['gpdb']
|
||||
scenarios = [
|
||||
# Fetching default URL for function node.
|
||||
('Fetch Function Node URL',
|
||||
dict(url='/browser/function/obj/'))
|
||||
]
|
||||
|
||||
def runTest(self):
|
||||
""" This function will update function under database node. """
|
||||
super(FunctionPutTestCase, self).setUp()
|
||||
self = funcs_utils.set_up(self)
|
||||
|
||||
func_name = "test_event_delete_%s" % str(uuid.uuid4())[1:8]
|
||||
function_info = funcs_utils.create_function(
|
||||
self.server, self.db_name, self.schema_name, func_name)
|
||||
|
||||
func_id = function_info[0]
|
||||
|
||||
data = {
|
||||
"description": "This is a procedure update comment",
|
||||
"id": func_id
|
||||
}
|
||||
|
||||
put_response = self.tester.put(
|
||||
self.url + str(utils.SERVER_GROUP) +
|
||||
'/' + str(self.server_id) + '/' + str(self.db_id) + '/' +
|
||||
str(self.schema_id) + '/' +
|
||||
str(func_id),
|
||||
data=json.dumps(data),
|
||||
follow_redirects=True)
|
||||
self.assertEquals(put_response.status_code, 200)
|
||||
# Disconnect the database
|
||||
database_utils.disconnect_database(self, self.server_id, self.db_id)
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
@@ -0,0 +1,90 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import json
|
||||
import uuid
|
||||
|
||||
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||
database_utils
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as funcs_utils
|
||||
|
||||
|
||||
class ProcedureAddTestCase(BaseTestGenerator):
|
||||
""" This class will add new procedure under schema node. """
|
||||
skip_on_database = ['gpdb']
|
||||
scenarios = [
|
||||
# Fetching default URL for procedure node.
|
||||
('Fetch Procedure Node URL', dict(
|
||||
url='/browser/procedure/obj/'))
|
||||
]
|
||||
|
||||
def runTest(self):
|
||||
""" This function will add procedure under schema node. """
|
||||
super(ProcedureAddTestCase, self).setUp()
|
||||
self = funcs_utils.set_up(self)
|
||||
|
||||
if self.server_type == "pg" and\
|
||||
self.server_version < 110000:
|
||||
message = "Procedures are not supported by PG < 110000."
|
||||
self.skipTest(message)
|
||||
|
||||
db_user = self.server["username"]
|
||||
data = {
|
||||
"acl": [
|
||||
{
|
||||
"grantee": db_user,
|
||||
"grantor": db_user,
|
||||
"privileges":
|
||||
[
|
||||
{
|
||||
"privilege_type": "X",
|
||||
"privilege": True,
|
||||
"with_grant": True
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"arguments": [],
|
||||
"funcowner": db_user,
|
||||
"lanname": "sql",
|
||||
"name": "test_pg_11_proc",
|
||||
"options": [],
|
||||
"proleakproof": True,
|
||||
"pronamespace": 2200,
|
||||
"prosecdef": True,
|
||||
"prosrc": "BEGIN RAISE EXCEPTION 'command % is disabled',"
|
||||
" tg_tag; END;",
|
||||
"seclabels": [],
|
||||
"variables": [
|
||||
{
|
||||
"name": "enable_sort",
|
||||
"value": True
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
data["name"] = "test_proc_add_%s" % str(uuid.uuid4())[1:8]
|
||||
if self.server_type == 'pg':
|
||||
data['prosrc'] = 'SELECT 1;'
|
||||
if self.schema_id:
|
||||
data['pronamespace'] = self.schema_id
|
||||
else:
|
||||
self.schema_id = data['pronamespace']
|
||||
response = self.tester.post(
|
||||
self.url + str(utils.SERVER_GROUP) + '/' +
|
||||
str(self.server_id) + '/' + str(self.db_id) + '/' +
|
||||
str(self.schema_id) + '/', data=json.dumps(data),
|
||||
content_type='html/json'
|
||||
)
|
||||
|
||||
self.assertEquals(response.status_code, 200)
|
||||
# Disconnect the database
|
||||
database_utils.disconnect_database(self, self.server_id, self.db_id)
|
||||
@@ -0,0 +1,56 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import uuid
|
||||
|
||||
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||
database_utils
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as funcs_utils
|
||||
|
||||
|
||||
class procedureDeleteTestCase(BaseTestGenerator):
|
||||
""" This class will delete the procedure under schema node. """
|
||||
skip_on_database = ['gpdb']
|
||||
scenarios = [
|
||||
# Fetching default URL for procedure node.
|
||||
('Fetch Procedure Node URL',
|
||||
dict(url='/browser/procedure/obj/'))
|
||||
]
|
||||
|
||||
def runTest(self):
|
||||
""" This function will delete procedure under database node. """
|
||||
super(procedureDeleteTestCase, self).setUp()
|
||||
self = funcs_utils.set_up(self)
|
||||
|
||||
if self.server_type == "pg" and\
|
||||
self.server_version < 110000:
|
||||
message = "Procedures are not supported by PG < 110000."
|
||||
self.skipTest(message)
|
||||
|
||||
func_name = "test_procedure_delete_%s" % str(uuid.uuid4())[1:8]
|
||||
proc_info = funcs_utils.create_procedure(
|
||||
self.server, self.db_name, self.schema_name, func_name,
|
||||
self.server_type)
|
||||
|
||||
proc_id = proc_info[0]
|
||||
response = self.tester.delete(
|
||||
self.url + str(utils.SERVER_GROUP) + '/' +
|
||||
str(self.server_id) + '/' +
|
||||
str(self.db_id) + '/' +
|
||||
str(self.schema_id) + '/' + str(proc_id),
|
||||
content_type='html/json'
|
||||
)
|
||||
self.assertEquals(response.status_code, 200)
|
||||
# Disconnect the database
|
||||
database_utils.disconnect_database(self, self.server_id, self.db_id)
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
@@ -0,0 +1,55 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import uuid
|
||||
|
||||
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||
database_utils
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as funcs_utils
|
||||
|
||||
|
||||
class ProcedureGetTestCase(BaseTestGenerator):
|
||||
"""This class will fetch added procedure under schema node."""
|
||||
skip_on_database = ['gpdb']
|
||||
scenarios = [
|
||||
# Fetching default URL for procedure node.
|
||||
('Fetch Procedure Node URL',
|
||||
dict(url='/browser/procedure/obj/'))
|
||||
]
|
||||
|
||||
def runTest(self):
|
||||
""" This function will get procedure under database node. """
|
||||
super(ProcedureGetTestCase, self).setUp()
|
||||
self = funcs_utils.set_up(self)
|
||||
|
||||
if self.server_type == "pg" and\
|
||||
self.server_version < 110000:
|
||||
message = "Procedures are not supported by PG < 110000."
|
||||
self.skipTest(message)
|
||||
|
||||
func_name = "test_procedure_get_%s" % str(uuid.uuid4())[1:8]
|
||||
proc_info = funcs_utils.create_procedure(
|
||||
self.server, self.db_name, self.schema_name, func_name,
|
||||
self.server_type)
|
||||
|
||||
proc_id = proc_info[0]
|
||||
response = self.tester.get(
|
||||
self.url + str(utils.SERVER_GROUP) + '/' +
|
||||
str(self.server_id) + '/' +
|
||||
str(self.db_id) + '/' +
|
||||
str(self.schema_id) + '/' + str(proc_id),
|
||||
content_type='html/json')
|
||||
self.assertEquals(response.status_code, 200)
|
||||
# Disconnect the database
|
||||
database_utils.disconnect_database(self, self.server_id, self.db_id)
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
@@ -0,0 +1,62 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import json
|
||||
import uuid
|
||||
|
||||
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||
database_utils
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as funcs_utils
|
||||
|
||||
|
||||
class ProcedurePutTestCase(BaseTestGenerator):
|
||||
""" This class will update new procedure under schema node. """
|
||||
skip_on_database = ['gpdb']
|
||||
scenarios = [
|
||||
# Fetching default URL for procedure node.
|
||||
('Fetch Procedure Node URL',
|
||||
dict(url='/browser/procedure/obj/'))
|
||||
]
|
||||
|
||||
def runTest(self):
|
||||
""" This function will update procedure under database node. """
|
||||
super(ProcedurePutTestCase, self).setUp()
|
||||
self = funcs_utils.set_up(self)
|
||||
|
||||
if self.server_type == "pg" and\
|
||||
self.server_version < 110000:
|
||||
message = "Procedures are not supported by PG < 110000."
|
||||
self.skipTest(message)
|
||||
|
||||
func_name = "test_procedure_put_%s" % str(uuid.uuid4())[1:8]
|
||||
proc_info = funcs_utils.create_procedure(
|
||||
self.server, self.db_name, self.schema_name, func_name,
|
||||
self.server_type)
|
||||
|
||||
proc_id = proc_info[0]
|
||||
data = {
|
||||
"description": "This is procedure update comment",
|
||||
"id": proc_id
|
||||
}
|
||||
|
||||
put_response = self.tester.put(
|
||||
self.url + str(utils.SERVER_GROUP) +
|
||||
'/' + str(self.server_id) + '/' + str(self.db_id) + '/' +
|
||||
str(self.schema_id) + '/' +
|
||||
str(proc_id),
|
||||
data=json.dumps(data),
|
||||
follow_redirects=True)
|
||||
self.assertEquals(put_response.status_code, 200)
|
||||
# Disconnect the database
|
||||
database_utils.disconnect_database(self, self.server_id, self.db_id)
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
@@ -10,14 +10,11 @@
|
||||
import json
|
||||
import uuid
|
||||
|
||||
from pgadmin.browser.server_groups.servers.databases.schemas.tests import \
|
||||
utils as schema_utils
|
||||
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||
database_utils
|
||||
from pgadmin.utils import server_utils as server_utils
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression import parent_node_dict
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as funcs_utils
|
||||
|
||||
|
||||
class TriggerFuncAddTestCase(BaseTestGenerator):
|
||||
@@ -32,30 +29,7 @@ class TriggerFuncAddTestCase(BaseTestGenerator):
|
||||
def runTest(self):
|
||||
""" This function will add trigger function under schema node. """
|
||||
super(TriggerFuncAddTestCase, self).runTest()
|
||||
db_name = parent_node_dict["database"][-1]["db_name"]
|
||||
schema_info = parent_node_dict["schema"][-1]
|
||||
server_id = schema_info["server_id"]
|
||||
db_id = schema_info["db_id"]
|
||||
prorettypename = "event_trigger/trigger"
|
||||
server_con = server_utils.connect_server(self, server_id)
|
||||
if not server_con["info"] == "Server connected.":
|
||||
raise Exception("Could not connect to server to add resource "
|
||||
"groups.")
|
||||
if "type" in server_con["data"]:
|
||||
if server_con["data"]["version"] < 90300:
|
||||
prorettypename = "trigger"
|
||||
|
||||
db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
|
||||
server_id, db_id)
|
||||
if not db_con['data']["connected"]:
|
||||
raise Exception("Could not connect to database to add a function.")
|
||||
schema_id = schema_info["schema_id"]
|
||||
schema_name = schema_info["schema_name"]
|
||||
schema_response = schema_utils.verify_schemas(self.server,
|
||||
db_name,
|
||||
schema_name)
|
||||
if not schema_response:
|
||||
raise Exception("Could not find the schema to add a function.")
|
||||
self = funcs_utils.set_up(self)
|
||||
db_user = self.server["username"]
|
||||
data = {
|
||||
"acl": [
|
||||
@@ -79,7 +53,7 @@ class TriggerFuncAddTestCase(BaseTestGenerator):
|
||||
"options": [],
|
||||
"proleakproof": True,
|
||||
"pronamespace": 2200,
|
||||
"prorettypename": prorettypename,
|
||||
"prorettypename": self.prorettypename,
|
||||
"prosecdef": True,
|
||||
"prosrc": "BEGIN RAISE EXCEPTION 'command % is disabled',"
|
||||
" tg_tag; END;",
|
||||
@@ -98,16 +72,17 @@ class TriggerFuncAddTestCase(BaseTestGenerator):
|
||||
for func_type in trigger_func_types:
|
||||
data['prorettypename'] = func_type
|
||||
data["name"] = "test_event_add_%s" % str(uuid.uuid4())[1:8]
|
||||
if schema_id:
|
||||
data['pronamespace'] = schema_id
|
||||
if self.schema_id:
|
||||
data['pronamespace'] = self.schema_id
|
||||
else:
|
||||
schema_id = data['pronamespace']
|
||||
self.schema_id = data['pronamespace']
|
||||
response = self.tester.post(
|
||||
self.url + str(utils.SERVER_GROUP) + '/' +
|
||||
str(server_id) + '/' + str(db_id) + '/' + str(schema_id) +
|
||||
str(self.server_id) + '/' + str(self.db_id) +
|
||||
'/' + str(self.schema_id) +
|
||||
'/', data=json.dumps(data), content_type='html/json'
|
||||
)
|
||||
|
||||
self.assertEquals(response.status_code, 200)
|
||||
# Disconnect the database
|
||||
database_utils.disconnect_database(self, server_id, db_id)
|
||||
database_utils.disconnect_database(self, self.server_id, self.db_id)
|
||||
|
||||
@@ -9,15 +9,11 @@
|
||||
|
||||
import uuid
|
||||
|
||||
from pgadmin.browser.server_groups.servers.databases.schemas.tests import \
|
||||
utils as schema_utils
|
||||
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||
database_utils
|
||||
from pgadmin.utils import server_utils as server_utils
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression import parent_node_dict
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as trigger_funcs_utils
|
||||
from . import utils as funcs_utils
|
||||
|
||||
|
||||
class TriggerFuncDeleteTestCase(BaseTestGenerator):
|
||||
@@ -29,49 +25,27 @@ class TriggerFuncDeleteTestCase(BaseTestGenerator):
|
||||
dict(url='/browser/trigger_function/obj/'))
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
super(TriggerFuncDeleteTestCase, self).setUp()
|
||||
self.db_name = parent_node_dict["database"][-1]["db_name"]
|
||||
self.schema_name = parent_node_dict["schema"][-1]["schema_name"]
|
||||
self.schema_id = parent_node_dict["schema"][-1]["schema_id"]
|
||||
|
||||
def runTest(self):
|
||||
""" This function will delete trigger function under database node. """
|
||||
schema_info = parent_node_dict["schema"][-1]
|
||||
server_id = schema_info["server_id"]
|
||||
db_id = schema_info["db_id"]
|
||||
func_name = "test_event_delete_%s" % str(uuid.uuid4())[1:8]
|
||||
server_con = server_utils.connect_server(self, server_id)
|
||||
if not server_con["info"] == "Server connected.":
|
||||
raise Exception("Could not connect to server to add resource "
|
||||
"groups.")
|
||||
server_version = 0
|
||||
if "type" in server_con["data"]:
|
||||
if server_con["data"]["version"] < 90300:
|
||||
server_version = server_con["data"]["version"]
|
||||
self.function_info = trigger_funcs_utils.create_trigger_function(
|
||||
self.server, self.db_name, self.schema_name, func_name,
|
||||
server_version)
|
||||
super(TriggerFuncDeleteTestCase, self).setUp()
|
||||
self = funcs_utils.set_up(self)
|
||||
|
||||
db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
|
||||
server_id, db_id)
|
||||
if not db_con['data']["connected"]:
|
||||
raise Exception("Could not connect to database to add collation.")
|
||||
schema_response = schema_utils.verify_schemas(self.server,
|
||||
self.db_name,
|
||||
self.schema_name)
|
||||
if not schema_response:
|
||||
raise Exception("Could not find the schema to add the collation.")
|
||||
trigger_func_id = self.function_info[0]
|
||||
func_name = "test_event_delete_%s" % str(uuid.uuid4())[1:8]
|
||||
function_info = funcs_utils.create_trigger_function(
|
||||
self.server, self.db_name, self.schema_name, func_name,
|
||||
self.server_version)
|
||||
|
||||
trigger_func_id = function_info[0]
|
||||
response = self.tester.delete(
|
||||
self.url + str(utils.SERVER_GROUP) + '/' + str(server_id) + '/' +
|
||||
str(db_id) + '/' +
|
||||
self.url + str(utils.SERVER_GROUP) + '/' +
|
||||
str(self.server_id) + '/' +
|
||||
str(self.db_id) + '/' +
|
||||
str(self.schema_id) + '/' + str(trigger_func_id),
|
||||
content_type='html/json'
|
||||
)
|
||||
self.assertEquals(response.status_code, 200)
|
||||
# Disconnect the database
|
||||
database_utils.disconnect_database(self, server_id, db_id)
|
||||
database_utils.disconnect_database(self, self.server_id, self.db_id)
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@@ -9,15 +9,11 @@
|
||||
|
||||
import uuid
|
||||
|
||||
from pgadmin.browser.server_groups.servers.databases.schemas.tests import \
|
||||
utils as schema_utils
|
||||
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||
database_utils
|
||||
from pgadmin.utils import server_utils as server_utils
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression import parent_node_dict
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as trigger_funcs_utils
|
||||
from . import utils as funcs_utils
|
||||
|
||||
|
||||
class TriggerFuncGetTestCase(BaseTestGenerator):
|
||||
@@ -29,49 +25,26 @@ class TriggerFuncGetTestCase(BaseTestGenerator):
|
||||
dict(url='/browser/trigger_function/obj/'))
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
super(TriggerFuncGetTestCase, self).setUp()
|
||||
self.db_name = parent_node_dict["database"][-1]["db_name"]
|
||||
self.schema_name = parent_node_dict["schema"][-1]["schema_name"]
|
||||
self.schema_id = parent_node_dict["schema"][-1]["schema_id"]
|
||||
|
||||
def runTest(self):
|
||||
""" This function will delete trigger function under database node. """
|
||||
schema_info = parent_node_dict["schema"][-1]
|
||||
server_id = schema_info["server_id"]
|
||||
db_id = schema_info["db_id"]
|
||||
func_name = "test_event_get_%s" % str(uuid.uuid4())[1:8]
|
||||
db_user = self.server["username"]
|
||||
server_con = server_utils.connect_server(self, server_id)
|
||||
if not server_con["info"] == "Server connected.":
|
||||
raise Exception("Could not connect to server to add resource "
|
||||
"groups.")
|
||||
server_version = 0
|
||||
if "type" in server_con["data"]:
|
||||
if server_con["data"]["version"] < 90300:
|
||||
server_version = server_con["data"]["version"]
|
||||
self.function_info = trigger_funcs_utils.create_trigger_function(
|
||||
self.server, self.db_name, self.schema_name, func_name,
|
||||
server_version)
|
||||
super(TriggerFuncGetTestCase, self).setUp()
|
||||
self = funcs_utils.set_up(self)
|
||||
|
||||
db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
|
||||
server_id, db_id)
|
||||
if not db_con['data']["connected"]:
|
||||
raise Exception("Could not connect to database to add collation.")
|
||||
schema_response = schema_utils.verify_schemas(self.server,
|
||||
self.db_name,
|
||||
self.schema_name)
|
||||
if not schema_response:
|
||||
raise Exception("Could not find the schema to add the collation.")
|
||||
trigger_func_id = self.function_info[0]
|
||||
func_name = "test_event_delete_%s" % str(uuid.uuid4())[1:8]
|
||||
function_info = funcs_utils.create_trigger_function(
|
||||
self.server, self.db_name, self.schema_name, func_name,
|
||||
self.server_version)
|
||||
|
||||
trigger_func_id = function_info[0]
|
||||
response = self.tester.get(
|
||||
self.url + str(utils.SERVER_GROUP) + '/' + str(server_id) + '/' +
|
||||
str(db_id) + '/' +
|
||||
self.url + str(utils.SERVER_GROUP) + '/' +
|
||||
str(self.server_id) + '/' +
|
||||
str(self.db_id) + '/' +
|
||||
str(self.schema_id) + '/' + str(trigger_func_id),
|
||||
content_type='html/json')
|
||||
self.assertEquals(response.status_code, 200)
|
||||
# Disconnect the database
|
||||
database_utils.disconnect_database(self, server_id, db_id)
|
||||
database_utils.disconnect_database(self, self.server_id, self.db_id)
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@@ -10,15 +10,11 @@
|
||||
import json
|
||||
import uuid
|
||||
|
||||
from pgadmin.browser.server_groups.servers.databases.schemas.tests import \
|
||||
utils as schema_utils
|
||||
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||
database_utils
|
||||
from pgadmin.utils import server_utils as server_utils
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression import parent_node_dict
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from . import utils as trigger_funcs_utils
|
||||
from . import utils as funcs_utils
|
||||
|
||||
|
||||
class TriggerFuncPutTestCase(BaseTestGenerator):
|
||||
@@ -30,63 +26,33 @@ class TriggerFuncPutTestCase(BaseTestGenerator):
|
||||
dict(url='/browser/trigger_function/obj/'))
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
super(TriggerFuncPutTestCase, self).setUp()
|
||||
self.db_name = parent_node_dict["database"][-1]["db_name"]
|
||||
self.schema_name = parent_node_dict["schema"][-1]["schema_name"]
|
||||
self.schema_id = parent_node_dict["schema"][-1]["schema_id"]
|
||||
|
||||
def runTest(self):
|
||||
""" This function will update trigger function under database node. """
|
||||
schema_info = parent_node_dict["schema"][-1]
|
||||
server_id = schema_info["server_id"]
|
||||
db_id = schema_info["db_id"]
|
||||
func_name = "test_event_put_%s" % str(uuid.uuid4())[1:8]
|
||||
server_con = server_utils.connect_server(self, server_id)
|
||||
if not server_con["info"] == "Server connected.":
|
||||
raise Exception("Could not connect to server to add resource "
|
||||
"groups.")
|
||||
server_version = 0
|
||||
if "type" in server_con["data"]:
|
||||
if server_con["data"]["version"] < 90300:
|
||||
server_version = server_con["data"]["version"]
|
||||
self.function_info = trigger_funcs_utils.create_trigger_function(
|
||||
self.server, self.db_name, self.schema_name, func_name,
|
||||
server_version)
|
||||
db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
|
||||
server_id, db_id)
|
||||
if not db_con['data']["connected"]:
|
||||
raise Exception("Could not connect to database to add collation.")
|
||||
schema_response = schema_utils.verify_schemas(self.server,
|
||||
self.db_name,
|
||||
self.schema_name)
|
||||
if not schema_response:
|
||||
raise Exception("Could not find the schema to add the collation.")
|
||||
func_name = self.function_info[1]
|
||||
func_response = trigger_funcs_utils.verify_trigger_function(
|
||||
self.server,
|
||||
self.db_name,
|
||||
func_name)
|
||||
if not func_response:
|
||||
raise Exception("Could not find the trigger function to update"
|
||||
" it's details.")
|
||||
super(TriggerFuncPutTestCase, self).setUp()
|
||||
self = funcs_utils.set_up(self)
|
||||
|
||||
func_name = "test_event_delete_%s" % str(uuid.uuid4())[1:8]
|
||||
function_info = funcs_utils.create_trigger_function(
|
||||
self.server, self.db_name, self.schema_name, func_name,
|
||||
self.server_version)
|
||||
|
||||
trigger_func_id = function_info[0]
|
||||
|
||||
trigger_func_id = self.function_info[0]
|
||||
data = {
|
||||
"description": "This is trigger function update comment",
|
||||
"description": "This is a trigger function update comment",
|
||||
"id": trigger_func_id
|
||||
}
|
||||
|
||||
put_response = self.tester.put(
|
||||
self.url + str(utils.SERVER_GROUP) +
|
||||
'/' + str(server_id) + '/' + str(db_id) + '/' +
|
||||
'/' + str(self.server_id) + '/' + str(self.db_id) + '/' +
|
||||
str(self.schema_id) + '/' +
|
||||
str(trigger_func_id),
|
||||
data=json.dumps(data),
|
||||
follow_redirects=True)
|
||||
self.assertEquals(put_response.status_code, 200)
|
||||
# Disconnect the database
|
||||
database_utils.disconnect_database(self, server_id, db_id)
|
||||
database_utils.disconnect_database(self, self.server_id, self.db_id)
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
@@ -13,6 +13,11 @@ import sys
|
||||
import traceback
|
||||
|
||||
from regression.python_test_utils import test_utils as utils
|
||||
from pgadmin.utils import server_utils as server_utils
|
||||
from pgadmin.browser.server_groups.servers.databases.schemas.tests import \
|
||||
utils as schema_utils
|
||||
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||
database_utils
|
||||
|
||||
|
||||
def create_trigger_function(server, db_name, schema_name, func_name,
|
||||
@@ -92,3 +97,118 @@ def verify_trigger_function(server, db_name, func_name):
|
||||
functions = pg_cursor.fetchone()
|
||||
connection.close()
|
||||
return functions
|
||||
|
||||
|
||||
def create_procedure(server, db_name, schema_name, func_name, s_type):
|
||||
"""This function add the procedure to schema"""
|
||||
try:
|
||||
connection = utils.get_db_connection(db_name,
|
||||
server['username'],
|
||||
server['db_password'],
|
||||
server['host'],
|
||||
server['port'],
|
||||
server['sslmode'])
|
||||
pg_cursor = connection.cursor()
|
||||
if s_type == 'pg':
|
||||
query = "CREATE PROCEDURE " + schema_name + "." + func_name + \
|
||||
"()" \
|
||||
" LANGUAGE 'sql'" \
|
||||
" SECURITY DEFINER AS $$" \
|
||||
" SELECT 1; $$;"
|
||||
else:
|
||||
query = "CREATE PROCEDURE " + schema_name + "." + func_name + \
|
||||
"()" \
|
||||
" SECURITY DEFINER AS $BODY$ BEGIN" \
|
||||
" NULL; END; $BODY$"
|
||||
pg_cursor.execute(query)
|
||||
connection.commit()
|
||||
# Get 'oid' from newly created function
|
||||
pg_cursor.execute("SELECT pro.oid, pro.proname FROM"
|
||||
" pg_proc pro WHERE pro.proname='%s'" %
|
||||
func_name)
|
||||
functions = pg_cursor.fetchone()
|
||||
connection.close()
|
||||
return functions
|
||||
except Exception:
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
|
||||
|
||||
def create_function(server, db_name, schema_name, func_name):
|
||||
"""This function add the procedure to schema"""
|
||||
try:
|
||||
connection = utils.get_db_connection(db_name,
|
||||
server['username'],
|
||||
server['db_password'],
|
||||
server['host'],
|
||||
server['port'],
|
||||
server['sslmode'])
|
||||
pg_cursor = connection.cursor()
|
||||
query = "CREATE FUNCTION " + schema_name + "." + func_name + \
|
||||
"()" \
|
||||
" RETURNS integer LANGUAGE 'sql' STABLE" \
|
||||
" SECURITY DEFINER AS $$" \
|
||||
" SELECT 1; $$;"
|
||||
pg_cursor.execute(query)
|
||||
connection.commit()
|
||||
# Get 'oid' from newly created function
|
||||
pg_cursor.execute("SELECT pro.oid, pro.proname FROM"
|
||||
" pg_proc pro WHERE pro.proname='%s'" %
|
||||
func_name)
|
||||
functions = pg_cursor.fetchone()
|
||||
connection.close()
|
||||
return functions
|
||||
except Exception:
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
|
||||
|
||||
def verify_procedure(server, db_name, proc_name):
|
||||
"""This function verifies the procedure in db"""
|
||||
connection = utils.get_db_connection(db_name,
|
||||
server['username'],
|
||||
server['db_password'],
|
||||
server['host'],
|
||||
server['port'],
|
||||
server['sslmode'])
|
||||
pg_cursor = connection.cursor()
|
||||
pg_cursor.execute("SELECT pro.oid, pro.proname FROM"
|
||||
" pg_proc pro WHERE pro.proname='%s'" %
|
||||
proc_name)
|
||||
procs = pg_cursor.fetchone()
|
||||
connection.close()
|
||||
return procs
|
||||
|
||||
|
||||
def set_up(obj):
|
||||
"""Common set up function"""
|
||||
from regression import parent_node_dict
|
||||
|
||||
obj.db_name = parent_node_dict["database"][-1]["db_name"]
|
||||
schema_info = parent_node_dict["schema"][-1]
|
||||
obj.server_id = schema_info["server_id"]
|
||||
obj.db_id = schema_info["db_id"]
|
||||
obj.prorettypename = "event_trigger/trigger"
|
||||
server_con = server_utils.connect_server(obj, obj.server_id)
|
||||
|
||||
if not server_con["info"] == "Server connected.":
|
||||
raise Exception("Could not connect to server.")
|
||||
if "version" in server_con["data"]:
|
||||
obj.server_version = server_con["data"]["version"]
|
||||
if server_con["data"]["version"] < 90300:
|
||||
obj.prorettypename = "trigger"
|
||||
if "type" in server_con["data"]:
|
||||
obj.server_type = server_con["data"]["type"]
|
||||
|
||||
db_con = database_utils.connect_database(obj, utils.SERVER_GROUP,
|
||||
obj.server_id,
|
||||
obj.db_id)
|
||||
if not db_con['data']["connected"]:
|
||||
raise Exception("Could not connect to database.")
|
||||
obj.schema_id = schema_info["schema_id"]
|
||||
obj.schema_name = schema_info["schema_name"]
|
||||
schema_response = schema_utils.verify_schemas(obj.server,
|
||||
obj.db_name,
|
||||
obj.schema_name)
|
||||
if not schema_response:
|
||||
raise Exception("Could not find the schema.")
|
||||
|
||||
return obj
|
||||
|
||||
Reference in New Issue
Block a user