mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
GPDB compatibility fixes:
When connected to a Greenplum database server - Hide items that not work with GPDB, such as Triggers, FDW, FTS_*, etc - Tables/Views/Catalogs/Language node can expand correctly - Views/Languages/Catalogs can show properties dialog with correct information - Show a greenplum icon at the server node Teng Zhang & Hao Wang
This commit is contained in:
parent
048205ead5
commit
821442ed8f
@ -53,6 +53,7 @@ class CastModule(CollectionNodeModule):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(CastModule, self).__init__(*args, **kwargs)
|
||||
self.min_gpdbver = 1000000000
|
||||
|
||||
def get_nodes(self, gid, sid, did):
|
||||
"""
|
||||
|
@ -60,6 +60,7 @@ class EventTriggerModule(CollectionNodeModule):
|
||||
super(EventTriggerModule, self).__init__(*args, **kwargs)
|
||||
self.min_ver = 90300
|
||||
self.max_ver = None
|
||||
self.min_gpdbver = 1000000000
|
||||
|
||||
def get_nodes(self, gid, sid, did):
|
||||
"""
|
||||
|
@ -60,6 +60,7 @@ class ExtensionModule(CollectionNodeModule):
|
||||
Initialising the base class
|
||||
"""
|
||||
super(ExtensionModule, self).__init__(*args, **kwargs)
|
||||
self.min_gpdbver = 1000000000
|
||||
|
||||
def get_nodes(self, gid, sid, did):
|
||||
"""
|
||||
|
@ -64,6 +64,7 @@ class ForeignDataWrapperModule(CollectionNodeModule):
|
||||
self.max_ver = None
|
||||
|
||||
super(ForeignDataWrapperModule, self).__init__(*args, **kwargs)
|
||||
self.min_gpdbver = 1000000000
|
||||
|
||||
def get_nodes(self, gid, sid, did):
|
||||
"""
|
||||
|
@ -223,7 +223,9 @@ class LanguageView(PGChildNodeView):
|
||||
self.manager = self.driver.connection_manager(kwargs['sid'])
|
||||
self.conn = self.manager.connection(did=kwargs['did'])
|
||||
# Set the template path for the SQL scripts
|
||||
self.template_path = "languages/sql/#{0}#".format(self.manager.version)
|
||||
self.template_path = ("languages/sql/#gpdb#{0}#".format(self.manager.version)
|
||||
if self.manager.server_type == 'gpdb'
|
||||
else "languages/sql/#{0}#".format(self.manager.version))
|
||||
|
||||
return f(*args, **kwargs)
|
||||
|
||||
|
@ -0,0 +1,34 @@
|
||||
SELECT 'lanacl' as deftype, COALESCE(gt.rolname, 'PUBLIC') grantee, g.rolname 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 'USAGE' THEN 'U'
|
||||
ELSE 'UNKNOWN'
|
||||
END AS privilege_type
|
||||
FROM
|
||||
(SELECT lanacl FROM pg_language lan
|
||||
LEFT OUTER JOIN pg_shdescription descr ON (lan.oid=descr.objoid AND descr.classoid='pg_language'::regclass)
|
||||
WHERE lan.oid = {{ lid|qtLiteral }}::OID
|
||||
) acl,
|
||||
(SELECT
|
||||
u_grantor.oid AS grantor,
|
||||
grantee.oid AS grantee,
|
||||
pr.type AS privilege_type,
|
||||
aclcontains(lan1.lanacl, makeaclitem(grantee.oid, u_grantor.oid, pr.type, true)) AS is_grantable
|
||||
FROM pg_language lan1, 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 'USAGE') pr(type)
|
||||
WHERE aclcontains(lan1.lanacl, 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 lan1.oid = {{ lid|qtLiteral }}::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,22 @@
|
||||
SELECT
|
||||
lan.oid as oid, lanname as name, lanpltrusted as trusted,
|
||||
array_to_string(lanacl::text[], ', ') as acl, hp.proname as lanproc,
|
||||
vp.proname as lanval, description,
|
||||
pg_get_userbyid(lan.lanowner) as lanowner, ip.proname as laninl
|
||||
FROM
|
||||
pg_language lan JOIN pg_proc hp ON hp.oid=lanplcallfoid
|
||||
LEFT OUTER JOIN pg_proc ip ON ip.oid=laninline
|
||||
LEFT OUTER JOIN pg_proc vp ON vp.oid=lanvalidator
|
||||
LEFT OUTER JOIN pg_description des
|
||||
ON (
|
||||
des.objoid=lan.oid AND des.objsubid=0 AND
|
||||
des.classoid='pg_language'::regclass
|
||||
)
|
||||
WHERE lanispl IS TRUE
|
||||
{% if lid %} AND
|
||||
lan.oid={{lid}}::oid
|
||||
{% endif %}
|
||||
{% if lanname %} AND
|
||||
lanname={{ lanname|qtLiteral }}::text
|
||||
{% endif %}
|
||||
ORDER BY lanname
|
@ -139,11 +139,13 @@ def check_precondition(f):
|
||||
|
||||
self.conn = self.manager.connection(did=kwargs['did'])
|
||||
# Set the template path for the SQL scripts
|
||||
self.template_path = self.template_initial + '/' + (
|
||||
self.ppas_template_path(self.manager.version)
|
||||
if self.manager.server_type == 'ppas' else
|
||||
self.pg_template_path(self.manager.version)
|
||||
)
|
||||
if self.manager.server_type == 'gpdb':
|
||||
_temp = self.gpdb_template_path(self.manager.version)
|
||||
elif self.manager.server_type == 'ppas':
|
||||
_temp = self.ppas_template_path(self.manager.version)
|
||||
else:
|
||||
_temp = self.pg_template_path(self.manager.version)
|
||||
self.template_path = self.template_initial + '/' + _temp
|
||||
|
||||
return f(*args, **kwargs)
|
||||
|
||||
@ -250,6 +252,13 @@ class SchemaView(PGChildNodeView):
|
||||
"""
|
||||
return 'pg/#{0}#'.format(ver)
|
||||
|
||||
@staticmethod
|
||||
def gpdb_template_path(ver):
|
||||
"""
|
||||
Returns the template path for GreenPlum servers.
|
||||
"""
|
||||
return '#gpdb#{0}#'.format(ver)
|
||||
|
||||
def format_request_acls(self, data, modified=False, specific=None):
|
||||
acls = {}
|
||||
try:
|
||||
|
@ -65,6 +65,7 @@ class CollationModule(SchemaChildModule):
|
||||
super(CollationModule, self).__init__(*args, **kwargs)
|
||||
self.min_ver = 90100
|
||||
self.max_ver = None
|
||||
self.min_gpdbver = 1000000000
|
||||
|
||||
def get_nodes(self, gid, sid, did, scid):
|
||||
"""
|
||||
|
@ -56,6 +56,7 @@ class DomainModule(SchemaChildModule):
|
||||
super(DomainModule, self).__init__(*args, **kwargs)
|
||||
self.min_ver = None
|
||||
self.max_ver = None
|
||||
self.min_gpdbver = 1000000000
|
||||
|
||||
def get_nodes(self, gid, sid, did, scid):
|
||||
"""
|
||||
|
@ -63,6 +63,7 @@ class ForeignTableModule(SchemaChildModule):
|
||||
super(ForeignTableModule, self).__init__(*args, **kwargs)
|
||||
self.min_ver = None
|
||||
self.max_ver = None
|
||||
self.min_gpdbver = 1000000000
|
||||
|
||||
def get_nodes(self, gid, sid, did, scid):
|
||||
"""
|
||||
|
@ -59,6 +59,7 @@ class FtsConfigurationModule(SchemaChildModule):
|
||||
self.max_ver = None
|
||||
self.manager = None
|
||||
super(FtsConfigurationModule, self).__init__(*args, **kwargs)
|
||||
self.min_gpdbver = 1000000000
|
||||
|
||||
def get_nodes(self, gid, sid, did, scid):
|
||||
"""
|
||||
|
@ -58,6 +58,7 @@ class FtsDictionaryModule(SchemaChildModule):
|
||||
self.max_ver = None
|
||||
self.manager = None
|
||||
super(FtsDictionaryModule, self).__init__(*args, **kwargs)
|
||||
self.min_gpdbver = 1000000000
|
||||
|
||||
def get_nodes(self, gid, sid, did, scid):
|
||||
"""
|
||||
|
@ -48,6 +48,10 @@ class FtsParserModule(SchemaChildModule):
|
||||
NODE_TYPE = 'fts_parser'
|
||||
COLLECTION_LABEL = _('FTS Parsers')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(FtsParserModule, self).__init__(*args, **kwargs)
|
||||
self.min_gpdbver = 1000000000
|
||||
|
||||
def get_nodes(self, gid, sid, did, scid):
|
||||
"""
|
||||
Generate the collection node
|
||||
|
@ -55,6 +55,7 @@ class FtsTemplateModule(SchemaChildModule):
|
||||
self.min_ver = None
|
||||
self.max_ver = None
|
||||
super(FtsTemplateModule, self).__init__(*args, **kwargs)
|
||||
self.min_gpdbver = 1000000000
|
||||
|
||||
def get_nodes(self, gid, sid, did, scid):
|
||||
"""
|
||||
|
@ -74,6 +74,7 @@ class FunctionModule(SchemaChildModule):
|
||||
self.min_ver = 90100
|
||||
self.max_ver = None
|
||||
self.server_type = None
|
||||
self.min_gpdbver = 1000000000
|
||||
|
||||
def get_nodes(self, gid, sid, did, scid):
|
||||
"""
|
||||
@ -1550,6 +1551,7 @@ class ProcedureModule(SchemaChildModule):
|
||||
|
||||
self.min_ver = 90100
|
||||
self.max_ver = None
|
||||
self.min_gpdbver = 1000000000
|
||||
self.server_type = ['ppas']
|
||||
|
||||
def get_nodes(self, gid, sid, did, scid):
|
||||
@ -1661,6 +1663,7 @@ class TriggerFunctionModule(SchemaChildModule):
|
||||
|
||||
self.min_ver = 90100
|
||||
self.max_ver = None
|
||||
self.min_gpdbver = 1000000000
|
||||
|
||||
def get_nodes(self, gid, sid, did, scid):
|
||||
"""
|
||||
|
@ -60,6 +60,7 @@ class SequenceModule(SchemaChildModule):
|
||||
super(SequenceModule, self).__init__(*args, **kwargs)
|
||||
self.min_ver = None
|
||||
self.max_ver = None
|
||||
self.min_gpdbver = 1000000000
|
||||
|
||||
def get_nodes(self, gid, sid, did, scid):
|
||||
"""
|
||||
|
@ -88,6 +88,8 @@ class PartitionsModule(CollectionNodeModule):
|
||||
"""
|
||||
Load this module if it is a partition table
|
||||
"""
|
||||
if manager.server_type == 'gpdb':
|
||||
return False
|
||||
if 'tid' in kwargs and CollectionNodeModule.BackendSupported(self, manager, **kwargs):
|
||||
conn = manager.connection(did=kwargs['did'])
|
||||
|
||||
|
@ -62,6 +62,7 @@ class TriggerModule(CollectionNodeModule):
|
||||
"""
|
||||
self.min_ver = None
|
||||
self.max_ver = None
|
||||
self.min_gpdbver = 1000000000
|
||||
super(TriggerModule, self).__init__(*args, **kwargs)
|
||||
|
||||
def BackendSupported(self, manager, **kwargs):
|
||||
@ -69,6 +70,8 @@ class TriggerModule(CollectionNodeModule):
|
||||
Load this module if vid is view, we will not load it under
|
||||
material view
|
||||
"""
|
||||
if manager.server_type == 'gpdb':
|
||||
return False
|
||||
if super(TriggerModule, self).BackendSupported(manager, **kwargs):
|
||||
conn = manager.connection(did=kwargs['did'])
|
||||
|
||||
|
@ -0,0 +1,21 @@
|
||||
{% macro LIST(tbl) -%}
|
||||
({{ tbl }}.nspname = 'pg_catalog' AND EXISTS
|
||||
(SELECT 1 FROM pg_class WHERE relname = 'pg_class' AND
|
||||
relnamespace = {{ tbl }}.oid LIMIT 1)) OR
|
||||
({{ tbl }}.nspname = 'information_schema' AND EXISTS
|
||||
(SELECT 1 FROM pg_class WHERE relname = 'tables' AND
|
||||
relnamespace = {{ tbl }}.oid LIMIT 1))
|
||||
{%- endmacro %}
|
||||
{% macro LABELS(tbl, _) -%}
|
||||
CASE {{ tbl }}.nspname
|
||||
WHEN 'pg_catalog' THEN '{{ _( 'PostgreSQL Catalog' ) }} (pg_catalog)'
|
||||
WHEN 'information_schema' THEN '{{ _( 'ANSI' ) }} (information_schema)'
|
||||
ELSE {{ tbl }}.nspname
|
||||
END AS name
|
||||
{%- endmacro %}
|
||||
{% macro DB_SUPPORT(tbl) -%}
|
||||
CASE
|
||||
WHEN {{ tbl }}.nspname = ANY('{information_schema}')
|
||||
THEN false
|
||||
ELSE true END
|
||||
{%- endmacro %}
|
@ -0,0 +1,38 @@
|
||||
{# Fetch privileges for schema #}
|
||||
SELECT
|
||||
'nspacl' as deftype, COALESCE(gt.rolname, 'PUBLIC') AS grantee,
|
||||
g.rolname AS grantor, array_agg(b.privilege_type) AS privileges,
|
||||
array_agg(b.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 'CREATE' THEN 'C'
|
||||
WHEN 'USAGE' THEN 'U'
|
||||
ELSE 'UNKNOWN - ' || (d).privilege_type
|
||||
END AS privilege_type
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
u_grantor.oid AS grantor,
|
||||
grantee.oid AS grantee,
|
||||
pr.type AS privilege_type,
|
||||
aclcontains(nc.nspacl, makeaclitem(grantee.oid, u_grantor.oid, pr.type, true)) AS is_grantable
|
||||
FROM 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 'CREATE'
|
||||
UNION ALL
|
||||
SELECT 'USAGE') pr(type)
|
||||
WHERE aclcontains(nc.nspacl, 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 nsp.oid = {{ scid|qtLiteral }}::OID
|
||||
) a
|
||||
) b
|
||||
LEFT JOIN pg_catalog.pg_roles g ON (b.grantor = g.oid)
|
||||
LEFT JOIN pg_catalog.pg_roles gt ON (b.grantee = gt.oid)
|
||||
GROUP BY g.rolname, gt.rolname;
|
@ -0,0 +1,17 @@
|
||||
{% import 'macros/privilege.macros' as PRIVILEGE %}
|
||||
{% if data %}
|
||||
CREATE SCHEMA {{ conn|qtIdent(data.name) }}
|
||||
{% if data.namespaceowner %}
|
||||
AUTHORIZATION {{ conn|qtIdent(data.namespaceowner) }};
|
||||
|
||||
{% endif %}
|
||||
{% if data.description %}
|
||||
COMMENT ON SCHEMA {{ conn|qtIdent(data.name) }}
|
||||
IS {{ data.description|qtLiteral }};
|
||||
|
||||
{% endif %}
|
||||
{% if data.nspacl %}
|
||||
{% for priv in data.nspacl %}
|
||||
{{ PRIVILEGE.APPLY(conn, 'SCHEMA', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
@ -0,0 +1 @@
|
||||
SELECT nsp.nspname FROM pg_namespace nsp WHERE nsp.oid = {{ scid|qtLiteral }};
|
@ -0,0 +1,9 @@
|
||||
{% import 'catalog/pg/macros/catalogs.sql' as CATALOGS %}
|
||||
SELECT
|
||||
nsp.nspname as schema_name,
|
||||
{{ CATALOGS.LIST('nsp') }} AS is_catalog,
|
||||
{{ CATALOGS.DB_SUPPORT('nsp') }} AS db_support
|
||||
FROM
|
||||
pg_catalog.pg_namespace nsp
|
||||
WHERE
|
||||
nsp.oid = {{ scid|qtLiteral }}::OID;
|
@ -0,0 +1,16 @@
|
||||
{% import 'catalog/gpdb_5.0_plus/macros/catalogs.sql' as CATALOGS %}
|
||||
SELECT
|
||||
nsp.oid,
|
||||
{{ CATALOGS.LABELS('nsp', _) }},
|
||||
has_schema_privilege(nsp.oid, 'CREATE') as can_create,
|
||||
has_schema_privilege(nsp.oid, 'USAGE') as has_usage
|
||||
FROM
|
||||
pg_namespace nsp
|
||||
WHERE
|
||||
{% if scid %}
|
||||
nsp.oid={{scid}}::oid AND
|
||||
{% endif %}
|
||||
(
|
||||
{{ CATALOGS.LIST('nsp') }}
|
||||
)
|
||||
ORDER BY 2;
|
@ -0,0 +1,24 @@
|
||||
{% import 'catalog/pg/macros/catalogs.sql' as CATALOGS %}
|
||||
SELECT
|
||||
2 AS nsptyp,
|
||||
nsp.nspname AS name,
|
||||
nsp.oid,
|
||||
array_to_string(nsp.nspacl::text[], ', ') as acl,
|
||||
r.rolname AS namespaceowner, description,
|
||||
has_schema_privilege(nsp.oid, 'CREATE') AS can_create,
|
||||
CASE
|
||||
WHEN nspname LIKE E'pg\\_%' THEN true
|
||||
ELSE false END AS is_sys_object
|
||||
FROM
|
||||
pg_namespace nsp
|
||||
LEFT OUTER JOIN pg_description des ON
|
||||
(des.objoid=nsp.oid AND des.classoid='pg_namespace'::regclass)
|
||||
LEFT JOIN pg_roles r ON (r.oid = nsp.nspowner)
|
||||
WHERE
|
||||
{% if scid %}
|
||||
nsp.oid={{scid}}::oid AND
|
||||
{% endif %}
|
||||
(
|
||||
{{ CATALOGS.LIST('nsp') }}
|
||||
)
|
||||
ORDER BY 1, nspname;
|
@ -0,0 +1,30 @@
|
||||
{% import 'macros/security.macros' as SECLABEL %}
|
||||
{% if data %}
|
||||
{# ==== To update catalog comments ==== #}
|
||||
{% if data.description and data.description != o_data.description %}
|
||||
COMMENT ON SCHEMA {{ conn|qtIdent(o_data.name) }}
|
||||
IS {{ data.description|qtLiteral }};
|
||||
|
||||
{% endif %}
|
||||
{# ==== To update catalog securitylabel ==== #}
|
||||
{# The SQL generated below will change Security Label #}
|
||||
{% if data.seclabels and data.seclabels|length > 0 %}
|
||||
{% set seclabels = data.seclabels %}
|
||||
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
|
||||
{% for r in seclabels.deleted %}
|
||||
{{ SECLABEL.DROP(conn, 'SCHEMA', o_data.name, r.provider) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in seclabels and seclabels.added|length > 0 %}
|
||||
{% for r in seclabels.added %}
|
||||
{{ SECLABEL.APPLY(conn, 'SCHEMA', o_data.name, r.provider, r.label) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
|
||||
{% for r in seclabels.changed %}
|
||||
{{ SECLABEL.APPLY(conn, 'SCHEMA', o_data.name, r.provider, r.label) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
{% endif %}
|
@ -0,0 +1,30 @@
|
||||
{# List of allowed privileges for PostgreSQL 9.2 or later #}
|
||||
{#
|
||||
Format for allowed privileges is:
|
||||
"acl_col": {
|
||||
"type": "name",
|
||||
"acl": [...]
|
||||
}
|
||||
#}
|
||||
{
|
||||
"nspacl": {
|
||||
"type": "SCHEMA",
|
||||
"acl": ["C", "U"]
|
||||
},
|
||||
"deftblacl": {
|
||||
"type": "TABLE",
|
||||
"acl": ["r", "a", "w", "d", "D", "x", "t"]
|
||||
},
|
||||
"defseqacl": {
|
||||
"type": "SEQUENCE",
|
||||
"acl": ["U", "r", "a"]
|
||||
},
|
||||
"deffuncacl": {
|
||||
"type": "FUNCTION",
|
||||
"acl": ["X"]
|
||||
},
|
||||
"deftypeacl": {
|
||||
"type": "TYPE",
|
||||
"acl": ["U"]
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
{# Fetch privileges for schema #}
|
||||
SELECT
|
||||
'nspacl' as deftype, COALESCE(gt.rolname, 'PUBLIC') AS grantee,
|
||||
g.rolname AS grantor, array_agg(b.privilege_type) AS privileges,
|
||||
array_agg(b.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 'CREATE' THEN 'C'
|
||||
WHEN 'USAGE' THEN 'U'
|
||||
ELSE 'UNKNOWN - ' || (d).privilege_type
|
||||
END AS privilege_type
|
||||
FROM
|
||||
(SELECT aclexplode(nsp.nspacl) as d
|
||||
FROM pg_namespace nsp
|
||||
WHERE nsp.oid = {{ scid|qtLiteral }}::OID
|
||||
) a
|
||||
) b
|
||||
LEFT JOIN pg_catalog.pg_roles g ON (b.grantor = g.oid)
|
||||
LEFT JOIN pg_catalog.pg_roles gt ON (b.grantee = gt.oid)
|
||||
GROUP BY g.rolname, gt.rolname;
|
@ -0,0 +1,40 @@
|
||||
{% import 'macros/security.macros' as SECLABEL %}
|
||||
{% import 'macros/privilege.macros' as PRIVILEGE %}
|
||||
{% import 'macros/default_privilege.macros' as DEFAULT_PRIVILEGE %}
|
||||
{% if data.name %}
|
||||
CREATE SCHEMA {{ conn|qtIdent(data.name) }}{% if data.namespaceowner %}
|
||||
|
||||
AUTHORIZATION {{ conn|qtIdent(data.namespaceowner) }}{% endif %}{% endif %};
|
||||
{# Alter the comment/description #}
|
||||
{% if data.description %}
|
||||
|
||||
COMMENT ON SCHEMA {{ conn|qtIdent(data.name) }}
|
||||
IS {{ data.description|qtLiteral }};
|
||||
{% endif %}
|
||||
{# ACL for the schema #}
|
||||
{% if data.nspacl %}
|
||||
{% for priv in data.nspacl %}
|
||||
|
||||
{{ PRIVILEGE.APPLY(conn, 'SCHEMA', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}{% endfor %}
|
||||
{% endif %}
|
||||
{# Default privileges on tables #}
|
||||
{% for defacl, type in [
|
||||
('deftblacl', 'TABLES'), ('defseqacl', 'SEQUENCES'),
|
||||
('deffuncacl', 'FUNCTIONS'), ('deftypeacl', 'TYPES')]
|
||||
%}
|
||||
{% if data[defacl] %}{% set acl = data[defacl] %}
|
||||
{% for priv in acl %}
|
||||
|
||||
{{ DEFAULT_PRIVILEGE.SET(
|
||||
conn, 'SCHEMA', data.name, type, priv.grantee,
|
||||
priv.without_grant, priv.with_grant
|
||||
) }}{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{# Security Labels on schema #}
|
||||
{% if data.seclabels and data.seclabels|length > 0 %}
|
||||
{% for r in data.seclabels %}
|
||||
|
||||
{{ SECLABEL.APPLY(conn, 'SCHEMA', data.name, r.provider, r.label) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
@ -0,0 +1,40 @@
|
||||
SELECT
|
||||
CASE (a.deftype)
|
||||
WHEN 'r' THEN 'deftblacl'
|
||||
WHEN 'S' THEN 'defseqacl'
|
||||
WHEN 'f' THEN 'deffuncacl'
|
||||
WHEN 'T' THEN 'deftypeacl'
|
||||
ELSE 'UNKNOWN - ' || a.deftype
|
||||
END AS deftype,
|
||||
COALESCE(gt.rolname, 'PUBLIC') grantee, g.rolname grantor, array_agg(a.privilege_type) as privileges, array_agg(a.is_grantable) as grantable
|
||||
FROM
|
||||
(SELECT
|
||||
(acl).grantee as grantee, (acl).grantor AS grantor, (acl).is_grantable AS is_grantable,
|
||||
CASE (acl).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 - ' || (acl).privilege_type
|
||||
END AS privilege_type,
|
||||
defaclobjtype as deftype
|
||||
FROM
|
||||
(SELECT defaclobjtype, aclexplode(defaclacl) as acl
|
||||
FROM
|
||||
pg_namespace nsp
|
||||
LEFT OUTER JOIN pg_catalog.pg_default_acl dacl ON (dacl.defaclnamespace = nsp.oid)
|
||||
WHERE
|
||||
nsp.oid={{scid}}::oid
|
||||
) d) a
|
||||
LEFT JOIN pg_catalog.pg_roles g ON (a.grantor = g.oid)
|
||||
LEFT JOIN pg_catalog.pg_roles gt ON (a.grantee = gt.oid)
|
||||
GROUP BY g.rolname, gt.rolname, a.deftype
|
||||
ORDER BY a.deftype;
|
@ -0,0 +1 @@
|
||||
DROP SCHEMA {{ conn|qtIdent(name) }} {% if cascade %}CASCADE{%endif%};
|
@ -0,0 +1 @@
|
||||
SELECT nsp.nspname FROM pg_namespace nsp WHERE nsp.oid = {{ scid|qtLiteral }};
|
@ -0,0 +1,9 @@
|
||||
{% import 'catalog/pg/macros/catalogs.sql' as CATALOGS %}
|
||||
SELECT
|
||||
nsp.nspname as schema_name,
|
||||
{{ CATALOGS.LIST('nsp') }} AS is_catalog,
|
||||
{{ CATALOGS.DB_SUPPORT('nsp') }} AS db_support
|
||||
FROM
|
||||
pg_catalog.pg_namespace nsp
|
||||
WHERE
|
||||
nsp.oid = {{ scid|qtLiteral }}::OID;
|
@ -0,0 +1,20 @@
|
||||
{% import 'catalog/pg/macros/catalogs.sql' as CATALOGS %}
|
||||
SELECT
|
||||
nsp.oid,
|
||||
nsp.nspname as name,
|
||||
has_schema_privilege(nsp.oid, 'CREATE') as can_create,
|
||||
has_schema_privilege(nsp.oid, 'USAGE') as has_usage
|
||||
FROM
|
||||
pg_namespace nsp
|
||||
WHERE
|
||||
{% if scid %}
|
||||
nsp.oid={{scid}}::oid AND
|
||||
{% else %}
|
||||
{% if not show_sysobj %}
|
||||
nspname NOT LIKE E'pg\_%' AND
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
NOT (
|
||||
{{ CATALOGS.LIST('nsp') }}
|
||||
)
|
||||
ORDER BY nspname;
|
@ -0,0 +1 @@
|
||||
SELECT nsp.oid FROM pg_namespace nsp WHERE nsp.nspname = {{ schema|qtLiteral }};
|
@ -0,0 +1,57 @@
|
||||
{% import 'catalog/pg/macros/catalogs.sql' as CATALOGS %}
|
||||
SELECT
|
||||
CASE
|
||||
WHEN (nspname LIKE E'pg\\_temp\\_%') THEN 1
|
||||
WHEN (nspname LIKE E'pg\\_%') THEN 0
|
||||
ELSE 3 END AS nsptyp,
|
||||
nsp.nspname AS name,
|
||||
nsp.oid,
|
||||
array_to_string(nsp.nspacl::text[], ', ') as acl,
|
||||
r.rolname AS namespaceowner, description,
|
||||
has_schema_privilege(nsp.oid, 'CREATE') AS can_create,
|
||||
CASE
|
||||
WHEN nspname LIKE E'pg\\_%' THEN true
|
||||
ELSE false END AS is_sys_object,
|
||||
{### Default ACL for Tables ###}
|
||||
(SELECT array_to_string(ARRAY(
|
||||
SELECT array_to_string(defaclacl::text[], ', ')
|
||||
FROM pg_default_acl
|
||||
WHERE defaclobjtype = 'r' AND defaclnamespace = nsp.oid
|
||||
), ', ')) AS tblacl,
|
||||
{### Default ACL for Sequnces ###}
|
||||
(SELECT array_to_string(ARRAY(
|
||||
SELECT array_to_string(defaclacl::text[], ', ')
|
||||
FROM pg_default_acl
|
||||
WHERE defaclobjtype = 'S' AND defaclnamespace = nsp.oid
|
||||
), ', ')) AS seqacl,
|
||||
{### Default ACL for Functions ###}
|
||||
(SELECT array_to_string(ARRAY(
|
||||
SELECT array_to_string(defaclacl::text[], ', ')
|
||||
FROM pg_default_acl
|
||||
WHERE defaclobjtype = 'f' AND defaclnamespace = nsp.oid
|
||||
), ', ')) AS funcacl,
|
||||
{### Default ACL for Type ###}
|
||||
(SELECT array_to_string(ARRAY(
|
||||
SELECT array_to_string(defaclacl::text[], ', ')
|
||||
FROM pg_default_acl
|
||||
WHERE defaclobjtype = 'T' AND defaclnamespace = nsp.oid
|
||||
), ', ')) AS typeacl,
|
||||
(SELECT array_agg(provider || '=' || label) FROM pg_seclabels sl1 WHERE sl1.objoid=nsp.oid) AS seclabels
|
||||
FROM
|
||||
pg_namespace nsp
|
||||
LEFT OUTER JOIN pg_description des ON
|
||||
(des.objoid=nsp.oid AND des.classoid='pg_namespace'::regclass)
|
||||
LEFT JOIN pg_roles r ON (r.oid = nsp.nspowner)
|
||||
WHERE
|
||||
{% if scid %}
|
||||
nsp.oid={{scid}}::oid AND
|
||||
{% else %}
|
||||
{% if show_sysobj %}
|
||||
nspname NOT LIKE E'pg\\_temp\\_%' AND
|
||||
nspname NOT LIKE E'pg\\_toast\\_temp\\_%' AND
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
NOT (
|
||||
{{ CATALOGS.LIST('nsp') }}
|
||||
)
|
||||
ORDER BY 1, nspname;
|
@ -0,0 +1,83 @@
|
||||
{% import 'macros/security.macros' as SECLABEL %}
|
||||
{% import 'macros/privilege.macros' as PRIVILEGE %}
|
||||
{% import 'macros/default_privilege.macros' as DEFAULT_PRIVILEGE %}
|
||||
{# Rename the schema #}
|
||||
{% if data.name and data.name != o_data.name %}
|
||||
ALTER SCHEMA {{ conn|qtIdent(o_data.name) }}
|
||||
RENAME TO {{ conn|qtIdent(data.name) }};
|
||||
|
||||
{% endif %}
|
||||
{# Change the owner #}
|
||||
{% if data.namespaceowner and data.namespaceowner != o_data.namespaceowner %}
|
||||
ALTER SCHEMA {{ conn|qtIdent(data.name) }}
|
||||
OWNER TO {{ conn|qtIdent(data.namespaceowner) }};
|
||||
|
||||
{% endif %}
|
||||
{# Update the comments/description #}
|
||||
{% if data.description is defined and data.description != o_data.description %}
|
||||
COMMENT ON SCHEMA {{ conn|qtIdent(data.name) }}
|
||||
IS {{ data.description|qtLiteral }};
|
||||
|
||||
{% endif %}
|
||||
{# Change the privileges #}
|
||||
{% if data.nspacl %}
|
||||
{% if 'deleted' in data.nspacl %}
|
||||
{% for priv in data.nspacl.deleted %}
|
||||
{{ PRIVILEGE.RESETALL(conn, 'SCHEMA', priv.grantee, data.name) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in data.nspacl %}
|
||||
{% for priv in data.nspacl.changed %}
|
||||
{{ PRIVILEGE.RESETALL(conn, 'SCHEMA', priv.grantee, data.name) }}
|
||||
{{ PRIVILEGE.APPLY(conn, 'SCHEMA', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in data.nspacl %}
|
||||
{% for priv in data.nspacl.added %}
|
||||
{{ PRIVILEGE.APPLY(conn, 'SCHEMA', priv.grantee, data.name, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{# Change the default privileges #}
|
||||
{% for defacl, type in [
|
||||
('deftblacl', 'TABLES'), ('defseqacl', 'SEQUENCES'),
|
||||
('deffuncacl', 'FUNCTIONS'), ('deftypeacl', 'TYPES')]
|
||||
%}
|
||||
{% if data[defacl] %}{% set acl = data[defacl] %}
|
||||
{% if 'deleted' in acl %}
|
||||
{% for priv in acl.deleted %}
|
||||
{{ DEFAULT_PRIVILEGE.UNSET(conn, 'SCHEMA', data.name, type, priv.grantee) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in acl %}
|
||||
{% for priv in acl.changed %}
|
||||
{{ DEFAULT_PRIVILEGE.UNSET(conn, 'SCHEMA', data.name, type, priv.grantee) }}
|
||||
{{ DEFAULT_PRIVILEGE.SET(conn,'SCHEMA', data.name, type, priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in acl %}
|
||||
{% for priv in acl.added %}
|
||||
{{ DEFAULT_PRIVILEGE.SET(conn,'SCHEMA', data.name, type, priv.grantee, priv.without_grant, priv.with_grant) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{# Change the security labels #}
|
||||
{% if data.seclabels and data.seclabels|length > 0 %}
|
||||
{% set seclabels = data.seclabels %}
|
||||
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
|
||||
{% for r in seclabels.deleted %}
|
||||
{{ SECLABEL.DROP(conn, 'SCHEMA', data.name, r.provider) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in seclabels and seclabels.added|length > 0 %}
|
||||
{% for r in seclabels.added %}
|
||||
{{ SECLABEL.APPLY(conn, 'SCHEMA', data.name, r.provider, r.label) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
|
||||
{% for r in seclabels.changed %}
|
||||
{{ SECLABEL.APPLY(conn, 'SCHEMA', data.name, r.provider, r.label) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
@ -143,6 +143,7 @@ class MViewModule(ViewModule):
|
||||
super(MViewModule, self).__init__(*args, **kwargs)
|
||||
self.min_ver = 90300
|
||||
self.max_ver = None
|
||||
self.min_gpdbver = 1000000000
|
||||
|
||||
|
||||
view_blueprint = ViewModule(__name__)
|
||||
@ -176,11 +177,13 @@ def check_precondition(f):
|
||||
kwargs['did'] in self.manager.db_info else 0
|
||||
|
||||
# Set template path for sql scripts
|
||||
self.template_path = self.template_initial + '/' + (
|
||||
self.ppas_template_path(self.manager.version)
|
||||
if self.manager.server_type == 'ppas' else
|
||||
self.pg_template_path(self.manager.version)
|
||||
)
|
||||
if self.manager.server_type == 'gpdb':
|
||||
_temp = self.gpdb_template_path(self.manager.version)
|
||||
elif self.manager.server_type == 'ppas':
|
||||
_temp = self.ppas_template_path(self.manager.version)
|
||||
else:
|
||||
_temp = self.pg_template_path(self.manager.version)
|
||||
self.template_path = self.template_initial + '/' + _temp
|
||||
|
||||
self.column_template_path = 'column/sql/#{0}#'.format(self.manager.version)
|
||||
|
||||
@ -313,6 +316,13 @@ class ViewNode(PGChildNodeView, VacuumSettings):
|
||||
"""
|
||||
return 'pg/#{0}#'.format(ver)
|
||||
|
||||
@staticmethod
|
||||
def gpdb_template_path(ver):
|
||||
"""
|
||||
Returns the template path for GreenPlum servers.
|
||||
"""
|
||||
return '#gpdb#{0}#'.format(ver)
|
||||
|
||||
@check_precondition
|
||||
def list(self, gid, sid, did, scid):
|
||||
"""
|
||||
@ -859,6 +869,9 @@ class ViewNode(PGChildNodeView, VacuumSettings):
|
||||
generate their sql and render
|
||||
into sql tab
|
||||
"""
|
||||
if self.manager.server_type == 'gpdb':
|
||||
return ''
|
||||
|
||||
from pgadmin.browser.server_groups.servers.databases.schemas.utils \
|
||||
import trigger_definition
|
||||
|
||||
|
@ -0,0 +1,74 @@
|
||||
{# ============================ Get ACLs ========================= #}
|
||||
{% if vid %}
|
||||
SELECT
|
||||
'datacl' as deftype,
|
||||
COALESCE(gt.rolname, 'PUBLIC') grantee,
|
||||
g.rolname 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 'DELETE' THEN 'd'
|
||||
WHEN 'INSERT' THEN 'a'
|
||||
WHEN 'REFERENCES' THEN 'x'
|
||||
WHEN 'SELECT' THEN 'r'
|
||||
WHEN 'TRIGGER' THEN 't'
|
||||
WHEN 'UPDATE' THEN 'w'
|
||||
WHEN 'TRUNCATE' THEN 'D'
|
||||
ELSE 'UNKNOWN'
|
||||
END AS privilege_type
|
||||
FROM
|
||||
(SELECT
|
||||
relacl
|
||||
FROM
|
||||
pg_class cl
|
||||
LEFT OUTER JOIN pg_shdescription descr ON (
|
||||
cl.oid=descr.objoid AND descr.classoid='pg_class'::regclass)
|
||||
WHERE
|
||||
cl.oid = {{ vid }}::OID AND relkind = 'v'
|
||||
) acl,
|
||||
(SELECT
|
||||
(d).grantee AS grantee,
|
||||
(d).grantor AS grantor,
|
||||
(d).is_grantable AS is_grantable,
|
||||
(d).privilege_type AS privilege_type
|
||||
FROM
|
||||
(SELECT
|
||||
u_grantor.oid AS grantor,
|
||||
grantee.oid AS grantee,
|
||||
pr.type AS privilege_type,
|
||||
aclcontains(c.relacl, makeaclitem(grantee.oid, u_grantor.oid, pr.type, true)) AS is_grantable
|
||||
FROM pg_class 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 'SELECT'
|
||||
UNION ALL
|
||||
SELECT 'INSERT'
|
||||
UNION ALL
|
||||
SELECT 'UPDATE'
|
||||
UNION ALL
|
||||
SELECT 'DELETE'
|
||||
UNION ALL
|
||||
SELECT 'TRUNCATE'
|
||||
UNION ALL
|
||||
SELECT 'REFERENCES'
|
||||
UNION ALL
|
||||
SELECT 'TRIGGER') pr(type)
|
||||
WHERE c.relnamespace = nc.oid
|
||||
AND (c.relkind = ANY (ARRAY['r'::"char", 'v'::"char"]))
|
||||
AND aclcontains(c.relacl, 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 = {{ vid }}
|
||||
) d
|
||||
) 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
|
||||
{% endif %}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"datacl": {
|
||||
"type": "VIEW",
|
||||
"acl": ["a", "r", "w", "d", "D", "x", "t"]
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
{#============================Create new view=========================#}
|
||||
{% if display_comments %}
|
||||
-- View: {{ conn|qtIdent(data.schema, data.name) }}
|
||||
|
||||
-- DROP VIEW {{ conn|qtIdent(data.schema, data.name) }};
|
||||
|
||||
{% endif %}
|
||||
{% if data.name and data.schema and data.definition %}
|
||||
CREATE OR REPLACE VIEW {{ conn|qtIdent(data.schema, data.name) }} AS
|
||||
{{ data.definition.rstrip(';') }};
|
||||
{% if data.owner %}
|
||||
|
||||
ALTER TABLE {{ conn|qtIdent(data.schema, data.name) }}
|
||||
OWNER TO {{ conn|qtIdent(data.owner) }};
|
||||
{% endif %}
|
||||
{% if data.comment %}
|
||||
COMMENT ON VIEW {{ conn|qtIdent(data.schema, data.name) }}
|
||||
IS {{ data.comment|qtLiteral }};
|
||||
{% endif %}
|
||||
{% endif %}
|
@ -0,0 +1,13 @@
|
||||
{# ====================== Drop/Cascade view by name ===================== #}
|
||||
{% if vid %}
|
||||
SELECT
|
||||
c.relname AS name,
|
||||
nsp.nspname
|
||||
FROM
|
||||
pg_class c
|
||||
LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
|
||||
WHERE
|
||||
c.relfilenode = {{ vid }};
|
||||
{% elif (name and nspname) %}
|
||||
DROP VIEW {{ conn|qtIdent(nspname, name) }} {% if cascade %} CASCADE {% endif %};
|
||||
{% endif %}
|
@ -0,0 +1,9 @@
|
||||
{# ===== fetch new assigned schema id ===== #}
|
||||
{% if vid %}
|
||||
SELECT
|
||||
c.relnamespace as scid
|
||||
FROM
|
||||
pg_class c
|
||||
WHERE
|
||||
c.oid = {{vid}}::oid;
|
||||
{% endif %}
|
@ -0,0 +1,7 @@
|
||||
{# ===== fetch schema name against schema oid ===== #}
|
||||
SELECT
|
||||
nspname
|
||||
FROM
|
||||
pg_namespace
|
||||
WHERE
|
||||
oid = {{ scid }}::oid;
|
@ -0,0 +1,6 @@
|
||||
{# ===== Grant Permissions to User Role on Views/Tables ===== #}
|
||||
{% import 'macros/schemas/security.macros' as SECLABEL %}
|
||||
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
|
||||
{# ===== We will generate Security Label SQL using macro ===== #}
|
||||
{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABEL.SET(conn, 'VIEW', data.name, r.provider, r.label, data.schema) }}{{'\r'}}{% endfor %}{{'\r'}}{% endif %}{% if data.datacl %}
|
||||
{% for priv in data.datacl %}{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}{% endfor %}{% endif %}
|
@ -0,0 +1,13 @@
|
||||
SELECT
|
||||
c.oid,
|
||||
c.relname AS name
|
||||
FROM pg_class c
|
||||
WHERE
|
||||
c.relkind = 'v'
|
||||
{% if (vid and datlastsysoid) %}
|
||||
AND c.oid = {{vid}}::oid
|
||||
{% elif scid %}
|
||||
AND c.relnamespace = {{scid}}::oid
|
||||
ORDER BY
|
||||
c.relname
|
||||
{% endif %}
|
@ -0,0 +1,57 @@
|
||||
{% if (vid and datlastsysoid) or scid %}
|
||||
SELECT
|
||||
c.oid,
|
||||
c.xmin,
|
||||
(CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
|
||||
c.relname AS name,
|
||||
nsp.nspname AS schema,
|
||||
description AS comment,
|
||||
c.reltablespace AS spcoid,
|
||||
pg_get_userbyid(c.relowner) AS owner,
|
||||
pg_get_viewdef(c.oid, true) AS definition,
|
||||
array_to_string(c.relacl::text[], ', ') AS acl,
|
||||
{#=============Checks if it is system view================#}
|
||||
{% if vid and datlastsysoid %}
|
||||
CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
|
||||
{% endif %}
|
||||
ARRAY[]::text[] AS seclabels
|
||||
FROM pg_class c
|
||||
LEFT OUTER JOIN pg_namespace nsp on nsp.oid = c.relnamespace
|
||||
LEFT OUTER JOIN pg_tablespace spc on spc.oid=c.reltablespace
|
||||
LEFT OUTER JOIN pg_description des ON (des.objoid=c.oid and des.objsubid=0 AND des.classoid='pg_class'::regclass)
|
||||
WHERE ((c.relhasrules
|
||||
AND
|
||||
(EXISTS(
|
||||
SELECT
|
||||
r.rulename
|
||||
FROM
|
||||
pg_rewrite r
|
||||
WHERE
|
||||
((r.ev_class = c.oid) AND (bpchar(r.ev_type) = '1'::bpchar))
|
||||
))
|
||||
) AND (c.relkind = 'v'::char))
|
||||
{% if (vid and datlastsysoid) %}
|
||||
AND c.oid = {{vid}}::oid
|
||||
{% elif scid %}
|
||||
AND c.relnamespace = {{scid}}::oid ORDER BY c.relname
|
||||
{% endif %}
|
||||
|
||||
{% elif type == 'roles' %}
|
||||
SELECT
|
||||
pr.rolname
|
||||
FROM
|
||||
pg_roles pr
|
||||
WHERE
|
||||
pr.rolcanlogin
|
||||
ORDER BY
|
||||
pr.rolname
|
||||
|
||||
{% elif type == 'schemas' %}
|
||||
SELECT
|
||||
nsp.nspname
|
||||
FROM
|
||||
pg_namespace nsp
|
||||
WHERE
|
||||
(nsp.nspname NOT LIKE E'pg\\_%'
|
||||
AND nsp.nspname != 'information_schema')
|
||||
{% endif %}
|
@ -0,0 +1,67 @@
|
||||
{# ============================ Update View ========================= #}
|
||||
{% import 'macros/schemas/security.macros' as SECLABEL %}
|
||||
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
|
||||
{% if data %}
|
||||
{% set view_name = data.name if data.name else o_data.name %}
|
||||
{% set view_schema = data.schema if data.schema else o_data.schema %}
|
||||
{% set def = data.definition.rstrip(';') if data.definition %}
|
||||
{% if data.name and data.name != o_data.name %}
|
||||
ALTER VIEW {{ conn|qtIdent(o_data.schema, o_data.name) }}
|
||||
RENAME TO {{ conn|qtIdent(data.name) }};
|
||||
{% endif %}
|
||||
{% if data.schema and data.schema != o_data.schema %}
|
||||
ALTER VIEW {{ conn|qtIdent(o_data.schema, view_name ) }}
|
||||
SET SCHEMA {{ conn|qtIdent(data.schema) }};
|
||||
{% endif %}
|
||||
{% if data.owner and data.owner != o_data.owner %}
|
||||
ALTER TABLE {{ conn|qtIdent(view_schema, view_name) }}
|
||||
OWNER TO {{ conn|qtIdent(data.owner) }};
|
||||
{% endif %}
|
||||
{% if def and def != o_data.definition.rstrip(';') %}
|
||||
CREATE OR REPLACE VIEW {{ conn|qtIdent(view_schema, view_name) }}
|
||||
AS{{ def }};
|
||||
{% endif %}
|
||||
{% set old_comment = o_data.comment|default('', true) %}
|
||||
{% if (data.comment is defined and (data.comment != old_comment)) %}
|
||||
COMMENT ON VIEW {{ conn|qtIdent(view_schema, view_name) }}
|
||||
IS {{ data.comment|qtLiteral }};
|
||||
{% endif %}
|
||||
{# The SQL generated below will change privileges #}
|
||||
{% if data.datacl %}
|
||||
{% if 'deleted' in data.datacl %}
|
||||
{% for priv in data.datacl.deleted %}
|
||||
{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in data.datacl %}
|
||||
{% for priv in data.datacl.changed %}
|
||||
{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
|
||||
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in data.datacl %}
|
||||
{% for priv in data.datacl.added %}
|
||||
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{# The SQL generated below will change Security Label #}
|
||||
{% if data.seclabels is not none and data.seclabels|length > 0 %}
|
||||
{% set seclabels = data.seclabels %}
|
||||
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
|
||||
{% for r in seclabels.deleted %}
|
||||
{{ SECLABEL.UNSET(conn, 'VIEW', data.name, r.provider, data.schema) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'added' in seclabels and seclabels.added|length > 0 %}
|
||||
{% for r in seclabels.added %}
|
||||
{{ SECLABEL.SET(conn, 'VIEW', data.name, r.provider, r.label, data.schema) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
|
||||
{% for r in seclabels.changed %}
|
||||
{{ SECLABEL.SET(conn, 'VIEW', data.name, r.provider, r.label, data.schema) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
@ -0,0 +1,4 @@
|
||||
{# ===== Below will provide view id for last created view ===== #}
|
||||
{% if data %}
|
||||
SELECT c.oid, c.relname FROM pg_class c WHERE c.relname = '{{ data.name }}';
|
||||
{% endif %}
|
@ -50,6 +50,9 @@ class JobModule(CollectionNodeModule):
|
||||
|
||||
conn = manager.connection()
|
||||
|
||||
if manager.server_type == 'gpdb':
|
||||
return False
|
||||
|
||||
status, res = conn.execute_scalar("""
|
||||
SELECT
|
||||
has_table_privilege('pgagent.pga_job', 'INSERT, SELECT, UPDATE') has_priviledge
|
||||
|
BIN
web/pgadmin/browser/server_groups/servers/static/img/gpdb.png
Normal file
BIN
web/pgadmin/browser/server_groups/servers/static/img/gpdb.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
68
web/pgadmin/browser/tests/test_version_in_range.py
Normal file
68
web/pgadmin/browser/tests/test_version_in_range.py
Normal file
@ -0,0 +1,68 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2017, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
import json
|
||||
import uuid
|
||||
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
from regression.python_test_utils import test_utils
|
||||
from regression.test_setup import config_data
|
||||
from pgadmin.browser.utils import is_version_in_range
|
||||
|
||||
|
||||
class VersionInRangeTestCase(BaseTestGenerator):
|
||||
"""
|
||||
This class validates the version in range functionality
|
||||
by defining different version scenarios; where dict of
|
||||
parameters describes the scenario appended by test name.
|
||||
"""
|
||||
|
||||
scenarios = [
|
||||
('TestCase for Validating pgversion 8.23 and min_version is 91000, should not show', dict(
|
||||
sversion=82300,
|
||||
min_version=90100,
|
||||
max_version=1000000000,
|
||||
scenario=2
|
||||
)),
|
||||
('TestCase for Validating pgversion 9.2 and should show by default', dict(
|
||||
sversion=90200,
|
||||
min_version=0,
|
||||
max_version=1000000000,
|
||||
scenario=1
|
||||
)),
|
||||
('TestCase for Validating pgversion 9.2 and min/max are None, should show by default', dict(
|
||||
sversion=90200,
|
||||
min_version=None,
|
||||
max_version=None,
|
||||
scenario=1
|
||||
)),
|
||||
('TestCase for Validating pgversion 9.6 and max is lower, should not show', dict(
|
||||
sversion=90600,
|
||||
min_version=None,
|
||||
max_version=90400,
|
||||
scenario=2
|
||||
))
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
pass
|
||||
|
||||
def runTest(self):
|
||||
"""This function will check version in range functionality."""
|
||||
if self.scenario == 1:
|
||||
self.test_result_is_true()
|
||||
if self.scenario == 2:
|
||||
self.test_result_is_false()
|
||||
|
||||
def test_result_is_true(self):
|
||||
self.assertTrue(is_version_in_range(self.sversion, self.min_version, self.max_version))
|
||||
|
||||
def test_result_is_false(self):
|
||||
self.assertFalse(is_version_in_range(self.sversion, self.min_version, self.max_version))
|
@ -19,6 +19,17 @@ from pgadmin.utils.ajax import make_json_response, precondition_required
|
||||
|
||||
from config import PG_DEFAULT_DRIVER
|
||||
|
||||
def is_version_in_range(sversion, min_ver, max_ver):
|
||||
assert (max_ver is None or isinstance(max_ver, int))
|
||||
assert (min_ver is None or isinstance(min_ver, int))
|
||||
|
||||
if min_ver is None and max_ver is None:
|
||||
return True
|
||||
|
||||
if min_ver is None or min_ver <= sversion:
|
||||
if max_ver is None or max_ver >= sversion:
|
||||
return True
|
||||
return False
|
||||
|
||||
class PGChildModule(object):
|
||||
"""
|
||||
@ -40,6 +51,8 @@ class PGChildModule(object):
|
||||
self.min_ver = 0
|
||||
self.max_ver = 1000000000
|
||||
self.server_type = None
|
||||
self.min_gpdbver = 80323
|
||||
self.max_gpdbver = 1000000000
|
||||
|
||||
super(PGChildModule, self).__init__()
|
||||
|
||||
@ -48,20 +61,15 @@ class PGChildModule(object):
|
||||
if not self.show_node:
|
||||
return False
|
||||
sversion = getattr(manager, 'sversion', None)
|
||||
|
||||
if (sversion is None or not isinstance(sversion, int)):
|
||||
return False
|
||||
|
||||
if (self.min_ver is None and self.max_ver is None):
|
||||
return True
|
||||
|
||||
assert (self.max_ver is None or isinstance(self.max_ver, int))
|
||||
assert (self.min_ver is None or isinstance(self.min_ver, int))
|
||||
assert (self.server_type is None or isinstance(self.server_type, list))
|
||||
|
||||
if self.server_type is None or manager.server_type in self.server_type:
|
||||
if self.min_ver is None or self.min_ver <= sversion:
|
||||
if self.max_ver is None or self.max_ver >= sversion:
|
||||
return True
|
||||
return is_version_in_range(sversion, self.min_gpdbver if manager.server_type == 'gpdb' else self.min_ver,
|
||||
self.max_gpdbver if manager.server_type == 'gpdb' else self.max_ver)
|
||||
|
||||
return False
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user