mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Display functions in Greenplum. Fixes #3044
This commit is contained in:
committed by
Dave Page
parent
678699c408
commit
65337daeba
@@ -71,10 +71,10 @@ class FunctionModule(SchemaChildModule):
|
||||
"""
|
||||
super(FunctionModule, self).__init__(*args, **kwargs)
|
||||
|
||||
self.min_ver = 90100
|
||||
self.min_ver = None
|
||||
self.max_ver = None
|
||||
self.server_type = None
|
||||
self.min_gpdbver = 1000000000
|
||||
self.min_gpdbver = None
|
||||
|
||||
def get_nodes(self, gid, sid, did, scid):
|
||||
"""
|
||||
@@ -659,7 +659,7 @@ class FunctionView(PGChildNodeView, DataTypeReader):
|
||||
condition += " AND nspname NOT LIKE E'pg\\\\_toast%' AND nspname NOT LIKE E'pg\\\\_temp%'"
|
||||
|
||||
# Get Types
|
||||
status, types = self.get_types(self.conn, condition)
|
||||
status, types = self.get_types(self.conn, condition, False, scid)
|
||||
|
||||
if not status:
|
||||
return internal_server_error(errormsg=types)
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
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 AS grantee,
|
||||
(d).grantor AS grantor,
|
||||
(d).is_grantable AS is_grantable,
|
||||
CASE (d).privilege_type
|
||||
WHEN 'EXECUTE' THEN 'X'
|
||||
ELSE 'UNKNOWN' END AS privilege_type
|
||||
FROM
|
||||
(SELECT
|
||||
u_grantor.oid AS grantor,
|
||||
grantee.oid AS grantee,
|
||||
pr.type AS privilege_type,
|
||||
aclcontains(c.proacl, makeaclitem(grantee.oid, u_grantor.oid, pr.type, true)) AS is_grantable
|
||||
FROM pg_proc c, pg_namespace nc, pg_authid u_grantor, (
|
||||
SELECT pg_authid.oid, pg_authid.rolname
|
||||
FROM pg_authid
|
||||
UNION ALL
|
||||
SELECT 0::oid AS oid, 'PUBLIC') grantee(oid, rolname),
|
||||
(SELECT 'EXECUTE') pr(type)
|
||||
WHERE c.pronamespace = nc.oid
|
||||
AND (
|
||||
c.proacl is NULL
|
||||
OR aclcontains(c.proacl, makeaclitem(grantee.oid, u_grantor.oid, pr.type, false))
|
||||
)
|
||||
AND (pg_has_role(u_grantor.oid, 'USAGE'::text)
|
||||
OR pg_has_role(grantee.oid, 'USAGE'::text)
|
||||
OR grantee.rolname = 'PUBLIC'::name)
|
||||
AND c.oid = {{ fnid }}::OID
|
||||
) 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.proisagg = FALSE
|
||||
AND typname NOT IN ('trigger', 'event_trigger')
|
||||
)
|
||||
ORDER BY funcname;
|
||||
@@ -0,0 +1,63 @@
|
||||
{% 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.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_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
|
||||
proisagg = FALSE
|
||||
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 proretset, prosrc, probin,
|
||||
pg_catalog.pg_get_function_arguments(pg_proc.oid) AS funcargs,
|
||||
pg_catalog.pg_get_function_identity_arguments(pg_proc.oid) AS funciargs,
|
||||
pg_catalog.pg_get_function_result(pg_proc.oid) AS funcresult,
|
||||
proiswin, provolatile, proisstrict, prosecdef,
|
||||
proconfig, procost, prorows, prodataaccess,
|
||||
'a' as proexeclocation,
|
||||
(SELECT lanname FROM pg_catalog.pg_language WHERE pg_proc.oid = prolang) as lanname,
|
||||
nspname || '.' || pg_proc.proname || '(' || COALESCE(pg_catalog.pg_get_function_identity_arguments(pg_proc.oid), '') || ')' as name,
|
||||
nspname || '.' || pg_proc.proname || '(' || COALESCE(pg_catalog.pg_get_function_arguments(pg_proc.oid), '') || ')' as name_with_default_args
|
||||
FROM pg_catalog.pg_proc
|
||||
JOIN pg_namespace nsp ON nsp.oid=pg_proc.pronamespace
|
||||
WHERE proisagg = FALSE
|
||||
AND pronamespace = {{scid}}::oid
|
||||
AND pg_proc.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
|
||||
proisagg = FALSE
|
||||
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,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
|
||||
proisagg = FALSE
|
||||
{% 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,27 @@
|
||||
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,
|
||||
NULL AS seclabels
|
||||
FROM
|
||||
pg_proc pr
|
||||
JOIN
|
||||
pg_type typ ON typ.oid=prorettype
|
||||
JOIN
|
||||
pg_namespace typns ON typns.oid=typ.typnamespace
|
||||
JOIN
|
||||
pg_language lng ON lng.oid=prolang
|
||||
LEFT OUTER JOIN
|
||||
pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
|
||||
WHERE
|
||||
proisagg = FALSE
|
||||
{% 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,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,105 @@
|
||||
{% 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 ('proisstrict' in data and data.proisstrict) or ('proisstrict' not in data and o_data.proisstrict) %} STRICT{% endif %}
|
||||
{% if ('prosecdef' in data and data.prosecdef) or ('prosecdef' not in data and o_data.prosecdef) %} SECURITY DEFINER{% endif %}
|
||||
{% if ('proiswindow' in data and data.proiswindow) or ('proiswindow' not in data and o_data.proiswindow) %} WINDOW{% endif %}
|
||||
|
||||
{% if data.procost %}COST {{data.procost}}{% elif o_data.procost %}COST {{o_data.procost}}{% endif %}{% if data.prorows %}
|
||||
|
||||
ROWS {{data.prorows}}{% elif o_data.prorows 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.acl %}
|
||||
{% for priv in data.acl.changed %}
|
||||
{{ PRIVILEGE.UNSETALL(conn, 'FUNCTION', priv.grantee, name, o_data.pronamespace, o_data.proargtypenames) }}
|
||||
|
||||
{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
|
||||
|
||||
{% endfor %}{% endif %}
|
||||
{% if 'added' in data.acl %}
|
||||
{% for priv in data.acl.added %}
|
||||
|
||||
{{ PRIVILEGE.SET(conn, 'FUNCTION', priv.grantee, name, priv.without_grant, priv.with_grant, o_data.pronamespace, o_data.proargtypenames) }}
|
||||
{% endfor %}{% endif %}{% endif %}
|
||||
{% if data.change_func == False %}
|
||||
{% if data.variables %}
|
||||
{% if 'deleted' in data.variables and data.variables.deleted|length > 0 %}
|
||||
|
||||
{{ VARIABLE.UNSET(conn, 'FUNCTION', name, data.variables.deleted, o_data.pronamespace, o_data.proargtypenames ) }}
|
||||
{% endif -%}
|
||||
{% if 'merged_variables' in data and data.merged_variables|length > 0 %}
|
||||
|
||||
{{ VARIABLE.SET(conn, 'FUNCTION', name, data.merged_variables, o_data.pronamespace, o_data.proargtypenames ) }}
|
||||
{% endif %}
|
||||
{% endif %}{% endif %}
|
||||
{% set seclabels = data.seclabels %}
|
||||
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
|
||||
{% for r in seclabels.deleted %}
|
||||
{{ SECLABEL.UNSET(conn, 'FUNCTION', name, r.provider, o_data.pronamespace, o_data.proargtypenames) }}
|
||||
|
||||
{% endfor %}
|
||||
{% endif -%}
|
||||
{% if 'added' in seclabels and seclabels.added|length > 0 %}
|
||||
{% for r in seclabels.added %}
|
||||
|
||||
{{ SECLABEL.SET(conn, 'FUNCTION', name, r.provider, r.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,6 @@
|
||||
SELECT
|
||||
name, vartype, min_val, max_val, enumvals
|
||||
FROM
|
||||
pg_settings
|
||||
WHERE
|
||||
context in ('user', 'superuser');
|
||||
@@ -21,5 +21,8 @@ FROM
|
||||
UNION SELECT 'bigserial', 0, 8, 'b', 0, 'pg_catalog', false, false
|
||||
UNION SELECT 'serial', 0, 4, 'b', 0, 'pg_catalog', false, false
|
||||
{% endif %}
|
||||
) AS dummy
|
||||
AND (
|
||||
typnamespace = {{schema_oid}}::oid
|
||||
OR nsp.nspname = 'pg_catalog'
|
||||
)) AS dummy
|
||||
ORDER BY nspname <> 'pg_catalog', nspname <> 'public', nspname, 1
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import sys
|
||||
|
||||
from pgadmin.browser.server_groups.servers.databases.schemas.utils import DataTypeReader
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
|
||||
if sys.version_info < (3, 3):
|
||||
from mock import patch, Mock
|
||||
else:
|
||||
from unittest.mock import patch, Mock
|
||||
|
||||
_default_database_response = [
|
||||
{
|
||||
'typname': 'type name',
|
||||
'elemoid': 1560,
|
||||
'is_collatable': True
|
||||
}
|
||||
]
|
||||
_default_expected_function_output = [
|
||||
{
|
||||
'label': 'type name',
|
||||
'value': 'type name',
|
||||
'typval': 'L',
|
||||
'precision': False,
|
||||
'length': True,
|
||||
'min_val': 1,
|
||||
'max_val': 2147483647,
|
||||
'is_collatable': True
|
||||
}
|
||||
]
|
||||
_default_manager = dict(
|
||||
server_type='ppas',
|
||||
version='456'
|
||||
)
|
||||
|
||||
|
||||
class DataTypeReaderTest(BaseTestGenerator):
|
||||
scenarios = [
|
||||
('Schema Oid is passed to the SQL Renderer',
|
||||
dict(
|
||||
manager=_default_manager,
|
||||
execute_return_values=_default_database_response,
|
||||
data_type_template_path='someplate/where/templates/are',
|
||||
sql_condition='new condition',
|
||||
schema_oid='123',
|
||||
add_serials=False,
|
||||
expected_sql_template_path='someplate/where/templates/are',
|
||||
expected_function_output=_default_expected_function_output
|
||||
)),
|
||||
('When no data_type_template_path is present in class, should create template path with version number',
|
||||
dict(
|
||||
manager=_default_manager,
|
||||
execute_return_values=_default_database_response,
|
||||
sql_condition='new condition',
|
||||
schema_oid='123',
|
||||
add_serials=False,
|
||||
expected_sql_template_path='datatype/sql/#456#',
|
||||
expected_function_output=_default_expected_function_output
|
||||
)),
|
||||
('When no data_type_template_path is present in class for GreenPlum, '
|
||||
'should create template path with gpdb and the version number',
|
||||
dict(
|
||||
manager=dict(
|
||||
server_type='gpdb',
|
||||
version='456'
|
||||
),
|
||||
execute_return_values=_default_database_response,
|
||||
sql_condition='new condition',
|
||||
schema_oid='123',
|
||||
add_serials=False,
|
||||
expected_sql_template_path='datatype/sql/#gpdb#456#',
|
||||
expected_function_output=_default_expected_function_output
|
||||
))
|
||||
]
|
||||
|
||||
@patch('pgadmin.browser.server_groups.servers.databases.schemas.utils.render_template')
|
||||
def runTest(self, template_mock):
|
||||
connection = Mock()
|
||||
connection.execute_2darray.return_value = [
|
||||
True,
|
||||
{
|
||||
'rows': self.execute_return_values
|
||||
|
||||
}
|
||||
]
|
||||
|
||||
reader = DataTypeReader()
|
||||
reader.manager = Mock()
|
||||
reader.manager.server_type = self.manager['server_type']
|
||||
reader.manager.version = self.manager['version']
|
||||
try:
|
||||
reader.data_type_template_path = self.data_type_template_path
|
||||
except AttributeError:
|
||||
''
|
||||
result = reader.get_types(connection, self.sql_condition, self.add_serials, self.schema_oid)
|
||||
self.assertEqual(result[1], self.expected_function_output)
|
||||
self.assertTrue(result[0])
|
||||
|
||||
connection.execute_2darray.assert_called()
|
||||
template_mock.assert_called_with(
|
||||
self.expected_sql_template_path + '/get_types.sql',
|
||||
condition=self.sql_condition,
|
||||
add_serials=self.add_serials,
|
||||
schema_oid=self.schema_oid
|
||||
)
|
||||
@@ -82,7 +82,7 @@ class DataTypeReader:
|
||||
- Returns data-types on the basis of the condition provided.
|
||||
"""
|
||||
|
||||
def get_types(self, conn, condition, add_serials=False):
|
||||
def get_types(self, conn, condition, add_serials=False, schema_oid = ''):
|
||||
"""
|
||||
Returns data-types including calculation for Length and Precision.
|
||||
|
||||
@@ -90,6 +90,7 @@ class DataTypeReader:
|
||||
conn: Connection Object
|
||||
condition: condition to restrict SQL statement
|
||||
add_serials: If you want to serials type
|
||||
schema_oid: If needed pass the schema OID to restrict the search
|
||||
"""
|
||||
res = []
|
||||
try:
|
||||
@@ -103,11 +104,12 @@ class DataTypeReader:
|
||||
) if self.manager.server_type == 'gpdb' else
|
||||
'#{0}#'.format(self.manager.version)
|
||||
)
|
||||
|
||||
SQL = render_template(
|
||||
"/".join([self.data_type_template_path,'get_types.sql']),
|
||||
condition=condition,
|
||||
add_serials=add_serials)
|
||||
add_serials=add_serials,
|
||||
schema_oid=schema_oid
|
||||
)
|
||||
status, rset = conn.execute_2darray(SQL)
|
||||
if not status:
|
||||
return status, rset
|
||||
|
||||
Reference in New Issue
Block a user