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:
parent
e5048b4d0b
commit
d1ecba56b8
@ -4,11 +4,14 @@
|
|||||||
The Procedure Dialog
|
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*,
|
||||||
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.
|
*Parameters*, and *Security*. The *SQL* tab displays the SQL code generated by
|
||||||
|
dialog selections.
|
||||||
|
|
||||||
.. image:: images/procedure_general.png
|
.. image:: images/procedure_general.png
|
||||||
:alt: Procedure dialog general tab
|
:alt: Procedure dialog general tab
|
||||||
|
@ -10,8 +10,9 @@ This release contains a number of features and fixes reported since the release
|
|||||||
Features
|
Features
|
||||||
********
|
********
|
||||||
|
|
||||||
| `Bug #1447 <https://redmine.postgresql.org/issues/1447>`_ - Add support for SSH tunneled connections
|
| `Feature #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 #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
|
Bug fixes
|
||||||
*********
|
*********
|
||||||
|
@ -1502,7 +1502,10 @@ class FunctionView(PGChildNodeView, DataTypeReader):
|
|||||||
name = name.replace(arg, formatted_arg)
|
name = name.replace(arg, formatted_arg)
|
||||||
|
|
||||||
name = name.replace(')', '\n)')
|
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)
|
return ajax_response(response=sql)
|
||||||
|
|
||||||
@ -1592,10 +1595,11 @@ class ProcedureModule(SchemaChildModule):
|
|||||||
"""
|
"""
|
||||||
super(ProcedureModule, self).__init__(*args, **kwargs)
|
super(ProcedureModule, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
self.min_ver = 90100
|
self.min_ver = 110000
|
||||||
self.max_ver = None
|
self.max_ver = None
|
||||||
|
self.min_ppasver = 90100
|
||||||
self.min_gpdbver = 1000000000
|
self.min_gpdbver = 1000000000
|
||||||
self.server_type = ['ppas']
|
self.server_type = ['pg', 'ppas']
|
||||||
|
|
||||||
def get_nodes(self, gid, sid, did, scid):
|
def get_nodes(self, gid, sid, did, scid):
|
||||||
"""
|
"""
|
||||||
|
@ -71,10 +71,13 @@ define('pgadmin.node.procedure', [
|
|||||||
if ('catalog' in node_hierarchy)
|
if ('catalog' in node_hierarchy)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Procedures supported only in PPAS
|
// Procedures supported only in PPAS and PG >= 11
|
||||||
return (
|
return (
|
||||||
'server' in node_hierarchy &&
|
'server' in node_hierarchy && (
|
||||||
node_hierarchy['server'].server_type == 'ppas'
|
node_hierarchy['server'].server_type == 'ppas' ||
|
||||||
|
(node_hierarchy['server'].server_type == 'pg' &&
|
||||||
|
node_hierarchy['server'].version >= 110000)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
model: Function.model.extend({
|
model: Function.model.extend({
|
||||||
@ -103,20 +106,24 @@ define('pgadmin.node.procedure', [
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
switch(this.name){
|
switch(this.name){
|
||||||
case 'provolatility':
|
case 'provolatile':
|
||||||
case 'proisstrict':
|
case 'proisstrict':
|
||||||
case 'prosecdef':
|
|
||||||
case 'procost':
|
case 'procost':
|
||||||
case 'proleakproof':
|
case 'proleakproof':
|
||||||
|
return (this.node_info.server.version < 90500 || this.node_info.server.server_type != 'ppas');
|
||||||
case 'variables':
|
case 'variables':
|
||||||
|
case 'prosecdef':
|
||||||
return this.node_info.server.version < 90500;
|
return this.node_info.server.version < 90500;
|
||||||
case 'prorows':
|
case 'prorows':
|
||||||
var server = this.node_info.server;
|
var server = this.node_info.server;
|
||||||
return !(server.version >= 90500 && m.get('proretset') == true);
|
return !(server.version >= 90500 && m.get('proretset') == true);
|
||||||
case 'funcowner':
|
case 'funcowner':
|
||||||
case 'lanname':
|
|
||||||
case 'proargs':
|
case 'proargs':
|
||||||
return true;
|
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:
|
default:
|
||||||
return false;
|
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 -%}
|
||||||
)
|
)
|
||||||
{% 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 }}
|
LANGUAGE {{ data.lanname|qtLiteral }}
|
||||||
{% if data.procost %}
|
{% 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 json
|
||||||
import uuid
|
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 \
|
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||||
database_utils
|
database_utils
|
||||||
from pgadmin.utils import server_utils as server_utils
|
|
||||||
from pgadmin.utils.route import BaseTestGenerator
|
from pgadmin.utils.route import BaseTestGenerator
|
||||||
from regression import parent_node_dict
|
|
||||||
from regression.python_test_utils import test_utils as utils
|
from regression.python_test_utils import test_utils as utils
|
||||||
|
from . import utils as funcs_utils
|
||||||
|
|
||||||
|
|
||||||
class TriggerFuncAddTestCase(BaseTestGenerator):
|
class TriggerFuncAddTestCase(BaseTestGenerator):
|
||||||
@ -32,30 +29,7 @@ class TriggerFuncAddTestCase(BaseTestGenerator):
|
|||||||
def runTest(self):
|
def runTest(self):
|
||||||
""" This function will add trigger function under schema node. """
|
""" This function will add trigger function under schema node. """
|
||||||
super(TriggerFuncAddTestCase, self).runTest()
|
super(TriggerFuncAddTestCase, self).runTest()
|
||||||
db_name = parent_node_dict["database"][-1]["db_name"]
|
self = funcs_utils.set_up(self)
|
||||||
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.")
|
|
||||||
db_user = self.server["username"]
|
db_user = self.server["username"]
|
||||||
data = {
|
data = {
|
||||||
"acl": [
|
"acl": [
|
||||||
@ -79,7 +53,7 @@ class TriggerFuncAddTestCase(BaseTestGenerator):
|
|||||||
"options": [],
|
"options": [],
|
||||||
"proleakproof": True,
|
"proleakproof": True,
|
||||||
"pronamespace": 2200,
|
"pronamespace": 2200,
|
||||||
"prorettypename": prorettypename,
|
"prorettypename": self.prorettypename,
|
||||||
"prosecdef": True,
|
"prosecdef": True,
|
||||||
"prosrc": "BEGIN RAISE EXCEPTION 'command % is disabled',"
|
"prosrc": "BEGIN RAISE EXCEPTION 'command % is disabled',"
|
||||||
" tg_tag; END;",
|
" tg_tag; END;",
|
||||||
@ -98,16 +72,17 @@ class TriggerFuncAddTestCase(BaseTestGenerator):
|
|||||||
for func_type in trigger_func_types:
|
for func_type in trigger_func_types:
|
||||||
data['prorettypename'] = func_type
|
data['prorettypename'] = func_type
|
||||||
data["name"] = "test_event_add_%s" % str(uuid.uuid4())[1:8]
|
data["name"] = "test_event_add_%s" % str(uuid.uuid4())[1:8]
|
||||||
if schema_id:
|
if self.schema_id:
|
||||||
data['pronamespace'] = schema_id
|
data['pronamespace'] = self.schema_id
|
||||||
else:
|
else:
|
||||||
schema_id = data['pronamespace']
|
self.schema_id = data['pronamespace']
|
||||||
response = self.tester.post(
|
response = self.tester.post(
|
||||||
self.url + str(utils.SERVER_GROUP) + '/' +
|
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'
|
'/', data=json.dumps(data), content_type='html/json'
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEquals(response.status_code, 200)
|
self.assertEquals(response.status_code, 200)
|
||||||
# Disconnect the database
|
# 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
|
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 \
|
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||||
database_utils
|
database_utils
|
||||||
from pgadmin.utils import server_utils as server_utils
|
|
||||||
from pgadmin.utils.route import BaseTestGenerator
|
from pgadmin.utils.route import BaseTestGenerator
|
||||||
from regression import parent_node_dict
|
|
||||||
from regression.python_test_utils import test_utils as utils
|
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):
|
class TriggerFuncDeleteTestCase(BaseTestGenerator):
|
||||||
@ -29,49 +25,27 @@ class TriggerFuncDeleteTestCase(BaseTestGenerator):
|
|||||||
dict(url='/browser/trigger_function/obj/'))
|
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):
|
def runTest(self):
|
||||||
""" This function will delete trigger function under database node. """
|
""" This function will delete trigger function under database node. """
|
||||||
schema_info = parent_node_dict["schema"][-1]
|
super(TriggerFuncDeleteTestCase, self).setUp()
|
||||||
server_id = schema_info["server_id"]
|
self = funcs_utils.set_up(self)
|
||||||
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)
|
|
||||||
|
|
||||||
db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
|
func_name = "test_event_delete_%s" % str(uuid.uuid4())[1:8]
|
||||||
server_id, db_id)
|
function_info = funcs_utils.create_trigger_function(
|
||||||
if not db_con['data']["connected"]:
|
self.server, self.db_name, self.schema_name, func_name,
|
||||||
raise Exception("Could not connect to database to add collation.")
|
self.server_version)
|
||||||
schema_response = schema_utils.verify_schemas(self.server,
|
|
||||||
self.db_name,
|
trigger_func_id = function_info[0]
|
||||||
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]
|
|
||||||
response = self.tester.delete(
|
response = self.tester.delete(
|
||||||
self.url + str(utils.SERVER_GROUP) + '/' + str(server_id) + '/' +
|
self.url + str(utils.SERVER_GROUP) + '/' +
|
||||||
str(db_id) + '/' +
|
str(self.server_id) + '/' +
|
||||||
|
str(self.db_id) + '/' +
|
||||||
str(self.schema_id) + '/' + str(trigger_func_id),
|
str(self.schema_id) + '/' + str(trigger_func_id),
|
||||||
content_type='html/json'
|
content_type='html/json'
|
||||||
)
|
)
|
||||||
self.assertEquals(response.status_code, 200)
|
self.assertEquals(response.status_code, 200)
|
||||||
# Disconnect the database
|
# 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):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
@ -9,15 +9,11 @@
|
|||||||
|
|
||||||
import uuid
|
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 \
|
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||||
database_utils
|
database_utils
|
||||||
from pgadmin.utils import server_utils as server_utils
|
|
||||||
from pgadmin.utils.route import BaseTestGenerator
|
from pgadmin.utils.route import BaseTestGenerator
|
||||||
from regression import parent_node_dict
|
|
||||||
from regression.python_test_utils import test_utils as utils
|
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):
|
class TriggerFuncGetTestCase(BaseTestGenerator):
|
||||||
@ -29,49 +25,26 @@ class TriggerFuncGetTestCase(BaseTestGenerator):
|
|||||||
dict(url='/browser/trigger_function/obj/'))
|
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):
|
def runTest(self):
|
||||||
""" This function will delete trigger function under database node. """
|
""" This function will delete trigger function under database node. """
|
||||||
schema_info = parent_node_dict["schema"][-1]
|
super(TriggerFuncGetTestCase, self).setUp()
|
||||||
server_id = schema_info["server_id"]
|
self = funcs_utils.set_up(self)
|
||||||
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)
|
|
||||||
|
|
||||||
db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
|
func_name = "test_event_delete_%s" % str(uuid.uuid4())[1:8]
|
||||||
server_id, db_id)
|
function_info = funcs_utils.create_trigger_function(
|
||||||
if not db_con['data']["connected"]:
|
self.server, self.db_name, self.schema_name, func_name,
|
||||||
raise Exception("Could not connect to database to add collation.")
|
self.server_version)
|
||||||
schema_response = schema_utils.verify_schemas(self.server,
|
|
||||||
self.db_name,
|
trigger_func_id = function_info[0]
|
||||||
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]
|
|
||||||
response = self.tester.get(
|
response = self.tester.get(
|
||||||
self.url + str(utils.SERVER_GROUP) + '/' + str(server_id) + '/' +
|
self.url + str(utils.SERVER_GROUP) + '/' +
|
||||||
str(db_id) + '/' +
|
str(self.server_id) + '/' +
|
||||||
|
str(self.db_id) + '/' +
|
||||||
str(self.schema_id) + '/' + str(trigger_func_id),
|
str(self.schema_id) + '/' + str(trigger_func_id),
|
||||||
content_type='html/json')
|
content_type='html/json')
|
||||||
self.assertEquals(response.status_code, 200)
|
self.assertEquals(response.status_code, 200)
|
||||||
# Disconnect the database
|
# 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):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
@ -10,15 +10,11 @@
|
|||||||
import json
|
import json
|
||||||
import uuid
|
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 \
|
from pgadmin.browser.server_groups.servers.databases.tests import utils as \
|
||||||
database_utils
|
database_utils
|
||||||
from pgadmin.utils import server_utils as server_utils
|
|
||||||
from pgadmin.utils.route import BaseTestGenerator
|
from pgadmin.utils.route import BaseTestGenerator
|
||||||
from regression import parent_node_dict
|
|
||||||
from regression.python_test_utils import test_utils as utils
|
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):
|
class TriggerFuncPutTestCase(BaseTestGenerator):
|
||||||
@ -30,63 +26,33 @@ class TriggerFuncPutTestCase(BaseTestGenerator):
|
|||||||
dict(url='/browser/trigger_function/obj/'))
|
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):
|
def runTest(self):
|
||||||
""" This function will update trigger function under database node. """
|
""" This function will update trigger function under database node. """
|
||||||
schema_info = parent_node_dict["schema"][-1]
|
super(TriggerFuncPutTestCase, self).setUp()
|
||||||
server_id = schema_info["server_id"]
|
self = funcs_utils.set_up(self)
|
||||||
db_id = schema_info["db_id"]
|
|
||||||
func_name = "test_event_put_%s" % str(uuid.uuid4())[1:8]
|
func_name = "test_event_delete_%s" % str(uuid.uuid4())[1:8]
|
||||||
server_con = server_utils.connect_server(self, server_id)
|
function_info = funcs_utils.create_trigger_function(
|
||||||
if not server_con["info"] == "Server connected.":
|
self.server, self.db_name, self.schema_name, func_name,
|
||||||
raise Exception("Could not connect to server to add resource "
|
self.server_version)
|
||||||
"groups.")
|
|
||||||
server_version = 0
|
trigger_func_id = function_info[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.")
|
|
||||||
|
|
||||||
trigger_func_id = self.function_info[0]
|
|
||||||
data = {
|
data = {
|
||||||
"description": "This is trigger function update comment",
|
"description": "This is a trigger function update comment",
|
||||||
"id": trigger_func_id
|
"id": trigger_func_id
|
||||||
}
|
}
|
||||||
|
|
||||||
put_response = self.tester.put(
|
put_response = self.tester.put(
|
||||||
self.url + str(utils.SERVER_GROUP) +
|
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(self.schema_id) + '/' +
|
||||||
str(trigger_func_id),
|
str(trigger_func_id),
|
||||||
data=json.dumps(data),
|
data=json.dumps(data),
|
||||||
follow_redirects=True)
|
follow_redirects=True)
|
||||||
self.assertEquals(put_response.status_code, 200)
|
self.assertEquals(put_response.status_code, 200)
|
||||||
# Disconnect the database
|
# 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):
|
def tearDown(self):
|
||||||
pass
|
pass
|
||||||
|
@ -13,6 +13,11 @@ import sys
|
|||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from regression.python_test_utils import test_utils as utils
|
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,
|
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()
|
functions = pg_cursor.fetchone()
|
||||||
connection.close()
|
connection.close()
|
||||||
return functions
|
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):
|
def __init__(self, *args, **kwargs):
|
||||||
self.min_ver = 0
|
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.server_type = None
|
||||||
self.min_gpdbver = 80323
|
self.min_gpdbver = 80323
|
||||||
self.max_gpdbver = 1000000000
|
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:
|
if self.server_type is None or manager.server_type in self.server_type:
|
||||||
min_server_version = self.min_ver
|
min_server_version = self.min_ver
|
||||||
max_server_version = self.max_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':
|
if manager.server_type == 'gpdb':
|
||||||
min_server_version = self.min_gpdbver
|
min_server_version = self.min_gpdbver
|
||||||
max_server_version = self.max_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
|
# Check server type is ppas or not
|
||||||
ppas_server = False
|
ppas_server = False
|
||||||
|
is_proc_supported = False
|
||||||
if server_type == 'ppas':
|
if server_type == 'ppas':
|
||||||
ppas_server = True
|
ppas_server = True
|
||||||
|
else:
|
||||||
|
is_proc_supported = True if manager.version >= 110000 else False
|
||||||
|
|
||||||
# Set the template path required to read the sql files
|
# Set the template path required to read the sql files
|
||||||
template_path = 'debugger/sql'
|
template_path = 'debugger/sql'
|
||||||
@ -395,7 +398,10 @@ def init_function(node_type, sid, did, scid, fid, trid=None):
|
|||||||
sql = render_template(
|
sql = render_template(
|
||||||
"/".join([template_path, 'get_function_debug_info.sql']),
|
"/".join([template_path, 'get_function_debug_info.sql']),
|
||||||
is_ppas_database=ppas_server,
|
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)
|
status, r_set = conn.execute_dict(sql)
|
||||||
if not status:
|
if not status:
|
||||||
@ -509,6 +515,7 @@ def init_function(node_type, sid, did, scid, fid, trid=None):
|
|||||||
'oid': fid,
|
'oid': fid,
|
||||||
'name': r_set['rows'][0]['name'],
|
'name': r_set['rows'][0]['name'],
|
||||||
'is_func': r_set['rows'][0]['isfunc'],
|
'is_func': r_set['rows'][0]['isfunc'],
|
||||||
|
'is_ppas_database': ppas_server,
|
||||||
'is_callable': False,
|
'is_callable': False,
|
||||||
'schema': r_set['rows'][0]['schemaname'],
|
'schema': r_set['rows'][0]['schemaname'],
|
||||||
'language': r_set['rows'][0]['lanname'],
|
'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'],
|
'oid': func_data['oid'],
|
||||||
'name': func_data['name'],
|
'name': func_data['name'],
|
||||||
'is_func': func_data['is_func'],
|
'is_func': func_data['is_func'],
|
||||||
|
'is_ppas_database': func_data['is_ppas_database'],
|
||||||
'is_callable': func_data['is_callable'],
|
'is_callable': func_data['is_callable'],
|
||||||
'schema': func_data['schema'],
|
'schema': func_data['schema'],
|
||||||
'language': func_data['language'],
|
'language': func_data['language'],
|
||||||
@ -1062,7 +1070,8 @@ def start_debugger_listener(trans_id):
|
|||||||
func_name=func_name,
|
func_name=func_name,
|
||||||
is_func=session_function_data['is_func'],
|
is_func=session_function_data['is_func'],
|
||||||
ret_type=session_function_data['return_type'],
|
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)
|
status, result = conn.execute_async(str_query)
|
||||||
@ -1946,8 +1955,9 @@ def poll_end_execution_result(trans_id):
|
|||||||
status, result = conn.poll()
|
status, result = conn.poll()
|
||||||
session_function_data = session['functionData'][str(trans_id)]
|
session_function_data = session['functionData'][str(trans_id)]
|
||||||
if status == ASYNC_OK and \
|
if status == ASYNC_OK and \
|
||||||
not session_function_data['is_func'] and \
|
not session_function_data['is_func'] and\
|
||||||
session_function_data['language'] == 'edbspl':
|
(session_function_data['language'] == 'edbspl' or
|
||||||
|
session_function_data['language'] == 'plpgsql'):
|
||||||
status = 'Success'
|
status = 'Success'
|
||||||
additional_msgs = conn.messages()
|
additional_msgs = conn.messages()
|
||||||
if len(additional_msgs) > 0:
|
if len(additional_msgs) > 0:
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
{### Create executer function for plpgsql function debugging ###}
|
{### Create executer function for plpgsql function debugging ###}
|
||||||
{% if not is_func %}
|
{% if is_ppas_database and not is_func %}
|
||||||
EXEC {{ func_name }} (
|
EXEC {{ func_name }} (
|
||||||
|
{% elif not is_func %}
|
||||||
|
CALL {{ func_name }} (
|
||||||
{% elif ret_type == 'record' %}
|
{% elif ret_type == 'record' %}
|
||||||
SELECT {{ func_name }} (
|
SELECT {{ func_name }} (
|
||||||
{% else %}
|
{% else %}
|
||||||
|
@ -41,7 +41,11 @@ SELECT
|
|||||||
0 AS pkgconsoid,
|
0 AS pkgconsoid,
|
||||||
n.oid AS schema,
|
n.oid AS schema,
|
||||||
n.nspname AS schemaname,
|
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%}
|
{%endif%}
|
||||||
pg_catalog.pg_get_function_identity_arguments(p.oid) AS signature,
|
pg_catalog.pg_get_function_identity_arguments(p.oid) AS signature,
|
||||||
|
|
||||||
|
@ -75,7 +75,8 @@ def get_version_mapping(template):
|
|||||||
{'name': "default", 'number': 0}
|
{'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.6_plus", 'number': 90600},
|
||||||
{'name': "9.5_plus", 'number': 90500},
|
{'name': "9.5_plus", 'number': 90500},
|
||||||
{'name': "9.4_plus", 'number': 90400},
|
{'name': "9.4_plus", 'number': 90400},
|
||||||
|
Loading…
Reference in New Issue
Block a user