mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2024-11-25 10:10:19 -06:00
Function and procedure support for PG11. Fixes #3362
This commit is contained in:
parent
e5048b4d0b
commit
d1ecba56b8
@ -4,11 +4,14 @@
|
||||
The Procedure Dialog
|
||||
********************
|
||||
|
||||
Use the *Procedure* dialog to create a procedure; procedures are supported by EDB Postgres Advanced Server. The *Procedure* dialog allows you to implement options of the CREATE PROCEDURE command; for more information about the CREATE PROCEDURE SQL command, please see the Database Compatibility for Oracle Developer's, available at:
|
||||
Use the *Procedure* dialog to create a procedure; procedures are supported by
|
||||
PostgreSQL v11+ and EDB Postgres Advanced Server. The *Procedure* dialog allows
|
||||
you to implement options of the CREATE PROCEDURE command.
|
||||
|
||||
http://www.enterprisedb.com
|
||||
|
||||
The *Procedure* dialog organizes the development of a procedure through the following dialog tabs: *General*, *Definition*, *Options*, *Arguments*, *Parameters*, and *Security*. The *SQL* tab displays the SQL code generated by dialog selections.
|
||||
The *Procedure* dialog organizes the development of a procedure through the
|
||||
following dialog tabs: *General*, *Definition*, *Options*, *Arguments*,
|
||||
*Parameters*, and *Security*. The *SQL* tab displays the SQL code generated by
|
||||
dialog selections.
|
||||
|
||||
.. image:: images/procedure_general.png
|
||||
:alt: Procedure dialog general tab
|
||||
|
@ -10,8 +10,9 @@ This release contains a number of features and fixes reported since the release
|
||||
Features
|
||||
********
|
||||
|
||||
| `Bug #1447 <https://redmine.postgresql.org/issues/1447>`_ - Add support for SSH tunneled connections
|
||||
| `Bug #3204 <https://redmine.postgresql.org/issues/3204>`_ - Add support for LISTEN/NOTIFY in the query tool
|
||||
| `Feature #1447 <https://redmine.postgresql.org/issues/1447>`_ - Add support for SSH tunneled connections
|
||||
| `Feature #3204 <https://redmine.postgresql.org/issues/3204>`_ - Add support for LISTEN/NOTIFY in the query tool
|
||||
| `Feature #3362 <https://redmine.postgresql.org/issues/3362>`_ - Function and procedure support for PG11
|
||||
|
||||
Bug fixes
|
||||
*********
|
||||
|
@ -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
|
||||
|
@ -51,7 +51,9 @@ class PGChildModule(object):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.min_ver = 0
|
||||
self.max_ver = 1000000000
|
||||
self.max_ver = 1100000000
|
||||
self.min_ppasver = 0
|
||||
self.max_ppasver = 1100000000
|
||||
self.server_type = None
|
||||
self.min_gpdbver = 80323
|
||||
self.max_gpdbver = 1000000000
|
||||
@ -72,6 +74,9 @@ class PGChildModule(object):
|
||||
if self.server_type is None or manager.server_type in self.server_type:
|
||||
min_server_version = self.min_ver
|
||||
max_server_version = self.max_ver
|
||||
if manager.server_type == 'ppas':
|
||||
min_server_version = self.min_ppasver
|
||||
max_server_version = self.max_ppasver
|
||||
if manager.server_type == 'gpdb':
|
||||
min_server_version = self.min_gpdbver
|
||||
max_server_version = self.max_gpdbver
|
||||
|
@ -365,8 +365,11 @@ def init_function(node_type, sid, did, scid, fid, trid=None):
|
||||
|
||||
# Check server type is ppas or not
|
||||
ppas_server = False
|
||||
is_proc_supported = False
|
||||
if server_type == 'ppas':
|
||||
ppas_server = True
|
||||
else:
|
||||
is_proc_supported = True if manager.version >= 110000 else False
|
||||
|
||||
# Set the template path required to read the sql files
|
||||
template_path = 'debugger/sql'
|
||||
@ -395,7 +398,10 @@ def init_function(node_type, sid, did, scid, fid, trid=None):
|
||||
sql = render_template(
|
||||
"/".join([template_path, 'get_function_debug_info.sql']),
|
||||
is_ppas_database=ppas_server,
|
||||
hasFeatureFunctionDefaults=True, fid=fid
|
||||
hasFeatureFunctionDefaults=True,
|
||||
fid=fid,
|
||||
is_proc_supported=is_proc_supported
|
||||
|
||||
)
|
||||
status, r_set = conn.execute_dict(sql)
|
||||
if not status:
|
||||
@ -509,6 +515,7 @@ def init_function(node_type, sid, did, scid, fid, trid=None):
|
||||
'oid': fid,
|
||||
'name': r_set['rows'][0]['name'],
|
||||
'is_func': r_set['rows'][0]['isfunc'],
|
||||
'is_ppas_database': ppas_server,
|
||||
'is_callable': False,
|
||||
'schema': r_set['rows'][0]['schemaname'],
|
||||
'language': r_set['rows'][0]['lanname'],
|
||||
@ -765,6 +772,7 @@ def initialize_target(debug_type, sid, did, scid, func_id, tri_id=None):
|
||||
'oid': func_data['oid'],
|
||||
'name': func_data['name'],
|
||||
'is_func': func_data['is_func'],
|
||||
'is_ppas_database': func_data['is_ppas_database'],
|
||||
'is_callable': func_data['is_callable'],
|
||||
'schema': func_data['schema'],
|
||||
'language': func_data['language'],
|
||||
@ -1062,7 +1070,8 @@ def start_debugger_listener(trans_id):
|
||||
func_name=func_name,
|
||||
is_func=session_function_data['is_func'],
|
||||
ret_type=session_function_data['return_type'],
|
||||
data=session_function_data['args_value']
|
||||
data=session_function_data['args_value'],
|
||||
is_ppas_database=session_function_data['is_ppas_database']
|
||||
)
|
||||
|
||||
status, result = conn.execute_async(str_query)
|
||||
@ -1946,8 +1955,9 @@ def poll_end_execution_result(trans_id):
|
||||
status, result = conn.poll()
|
||||
session_function_data = session['functionData'][str(trans_id)]
|
||||
if status == ASYNC_OK and \
|
||||
not session_function_data['is_func'] and \
|
||||
session_function_data['language'] == 'edbspl':
|
||||
not session_function_data['is_func'] and\
|
||||
(session_function_data['language'] == 'edbspl' or
|
||||
session_function_data['language'] == 'plpgsql'):
|
||||
status = 'Success'
|
||||
additional_msgs = conn.messages()
|
||||
if len(additional_msgs) > 0:
|
||||
|
@ -1,6 +1,8 @@
|
||||
{### Create executer function for plpgsql function debugging ###}
|
||||
{% if not is_func %}
|
||||
{% if is_ppas_database and not is_func %}
|
||||
EXEC {{ func_name }} (
|
||||
{% elif not is_func %}
|
||||
CALL {{ func_name }} (
|
||||
{% elif ret_type == 'record' %}
|
||||
SELECT {{ func_name }} (
|
||||
{% else %}
|
||||
|
@ -41,7 +41,11 @@ SELECT
|
||||
0 AS pkgconsoid,
|
||||
n.oid AS schema,
|
||||
n.nspname AS schemaname,
|
||||
true AS isfunc,
|
||||
{% if is_proc_supported %}
|
||||
CASE WHEN p.prokind in ('f', 'w') THEN TRUE ELSE FALSE END AS isfunc,
|
||||
{% else %}
|
||||
TRUE AS isfunc,
|
||||
{% endif %}
|
||||
{%endif%}
|
||||
pg_catalog.pg_get_function_identity_arguments(p.oid) AS signature,
|
||||
|
||||
@ -61,4 +65,4 @@ FROM
|
||||
{% endif %}
|
||||
{% if fid %}
|
||||
WHERE p.oid = {{fid}}::oid;
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
@ -75,7 +75,8 @@ def get_version_mapping(template):
|
||||
{'name': "default", 'number': 0}
|
||||
)
|
||||
|
||||
return ({'name': "10_plus", 'number': 100000},
|
||||
return ({'name': "11_plus", 'number': 110000},
|
||||
{'name': "10_plus", 'number': 100000},
|
||||
{'name': "9.6_plus", 'number': 90600},
|
||||
{'name': "9.5_plus", 'number': 90500},
|
||||
{'name': "9.4_plus", 'number': 90400},
|
||||
|
Loading…
Reference in New Issue
Block a user