diff --git a/web/pgadmin/browser/server_groups/servers/databases/casts/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/casts/__init__.py index c4c841a4..fd0e8e3a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/casts/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/casts/__init__.py @@ -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): """ diff --git a/web/pgadmin/browser/server_groups/servers/databases/event_triggers/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/event_triggers/__init__.py index 603b7f9e..32dc151c 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/event_triggers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/event_triggers/__init__.py @@ -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): """ diff --git a/web/pgadmin/browser/server_groups/servers/databases/extensions/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/extensions/__init__.py index 8d9d108f..46a09237 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/extensions/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/extensions/__init__.py @@ -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): """ diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/__init__.py index d4ba568e..5b6624d5 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/__init__.py @@ -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): """ diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/languages/__init__.py index b1e796e6..80ba7c70 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/languages/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/languages/__init__.py @@ -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) diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/gpdb_5.0_plus/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/gpdb_5.0_plus/acl.sql new file mode 100644 index 00000000..ef55a511 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/gpdb_5.0_plus/acl.sql @@ -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 diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/gpdb_5.0_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/gpdb_5.0_plus/properties.sql new file mode 100644 index 00000000..ba45c087 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/languages/templates/languages/sql/gpdb_5.0_plus/properties.sql @@ -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 diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/__init__.py index 4e1f011b..04d24326 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/__init__.py @@ -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: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/__init__.py index 9cbbf62a..3f3f80bf 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/__init__.py @@ -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): """ diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/__init__.py index cecdcd97..d00b1872 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/__init__.py @@ -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): """ diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/__init__.py index ed383942..1c1d17f8 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/__init__.py @@ -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): """ diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/__init__.py index 63ba26df..41fe8a27 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/__init__.py @@ -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): """ diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/__init__.py index f0f619e4..658a7bff 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/__init__.py @@ -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): """ diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_parser/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_parser/__init__.py index f80b4a12..ba81ff27 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_parser/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_parser/__init__.py @@ -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 diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/__init__.py index fa4df5d0..310ef64b 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/__init__.py @@ -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): """ diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py index e3277e34..dd677a1d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/__init__.py @@ -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): """ diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py index d886596c..7419abe1 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/__init__.py @@ -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): """ diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/__init__.py index 41918164..25b38b6e 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/__init__.py @@ -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']) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/__init__.py index 19dcf8af..7b2c6101 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/__init__.py @@ -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']) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/macros/catalogs.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/macros/catalogs.sql new file mode 100644 index 00000000..f911e10f --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/macros/catalogs.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/acl.sql new file mode 100644 index 00000000..a4a53863 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/acl.sql @@ -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; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/create.sql new file mode 100644 index 00000000..12dd1025 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/create.sql @@ -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 %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/get_name.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/get_name.sql new file mode 100644 index 00000000..3c5187dc --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/get_name.sql @@ -0,0 +1 @@ +SELECT nsp.nspname FROM pg_namespace nsp WHERE nsp.oid = {{ scid|qtLiteral }}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/is_catalog.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/is_catalog.sql new file mode 100644 index 00000000..9386acbf --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/is_catalog.sql @@ -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; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/nodes.sql new file mode 100644 index 00000000..c75e7ba5 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/nodes.sql @@ -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; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/properties.sql new file mode 100644 index 00000000..2f443ce0 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/properties.sql @@ -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; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/update.sql new file mode 100644 index 00000000..39f7f94c --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/catalog/gpdb_5.0_plus/sql/update.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/allowed_privs.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/allowed_privs.json new file mode 100644 index 00000000..61dfdfe9 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/allowed_privs.json @@ -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"] + } +} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/acl.sql new file mode 100644 index 00000000..e1e64be6 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/acl.sql @@ -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; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/create.sql new file mode 100644 index 00000000..2016209b --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/create.sql @@ -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 %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/defacl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/defacl.sql new file mode 100644 index 00000000..91c3085d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/defacl.sql @@ -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; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/delete.sql new file mode 100644 index 00000000..74e9126d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/delete.sql @@ -0,0 +1 @@ +DROP SCHEMA {{ conn|qtIdent(name) }} {% if cascade %}CASCADE{%endif%}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/get_name.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/get_name.sql new file mode 100644 index 00000000..3c5187dc --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/get_name.sql @@ -0,0 +1 @@ +SELECT nsp.nspname FROM pg_namespace nsp WHERE nsp.oid = {{ scid|qtLiteral }}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/is_catalog.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/is_catalog.sql new file mode 100644 index 00000000..9386acbf --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/is_catalog.sql @@ -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; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/nodes.sql new file mode 100644 index 00000000..df742abc --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/nodes.sql @@ -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; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/oid.sql new file mode 100644 index 00000000..c5329b39 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/oid.sql @@ -0,0 +1 @@ +SELECT nsp.oid FROM pg_namespace nsp WHERE nsp.nspname = {{ schema|qtLiteral }}; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/properties.sql new file mode 100644 index 00000000..ca2254d0 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/properties.sql @@ -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; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/update.sql new file mode 100644 index 00000000..47f6e134 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/templates/schema/gpdb_5.0_plus/sql/update.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/__init__.py index 30d8dd93..c57bdab3 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/__init__.py @@ -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 diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/acl.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/acl.sql new file mode 100644 index 00000000..64ed13b4 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/acl.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/allowed_privs.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/allowed_privs.json new file mode 100644 index 00000000..71f317fb --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/allowed_privs.json @@ -0,0 +1,6 @@ +{ + "datacl": { + "type": "VIEW", + "acl": ["a", "r", "w", "d", "D", "x", "t"] + } +} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/create.sql new file mode 100644 index 00000000..5720b140 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/create.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/delete.sql new file mode 100644 index 00000000..b1c173f9 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/delete.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/get_oid.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/get_oid.sql new file mode 100644 index 00000000..453c2444 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/get_oid.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/get_schema.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/get_schema.sql new file mode 100644 index 00000000..3bdb5dcb --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/get_schema.sql @@ -0,0 +1,7 @@ +{# ===== fetch schema name against schema oid ===== #} +SELECT + nspname +FROM + pg_namespace +WHERE + oid = {{ scid }}::oid; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/grant.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/grant.sql new file mode 100644 index 00000000..a7e1585b --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/grant.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/nodes.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/nodes.sql new file mode 100644 index 00000000..be133967 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/nodes.sql @@ -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 %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/properties.sql new file mode 100644 index 00000000..e911287d --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/properties.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/update.sql new file mode 100644 index 00000000..291b7760 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/update.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/view_id.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/view_id.sql new file mode 100644 index 00000000..73f6da55 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/view/gpdb_5.0_plus/sql/view_id.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/__init__.py b/web/pgadmin/browser/server_groups/servers/pgagent/__init__.py index 5ce8eb18..47c60b1c 100644 --- a/web/pgadmin/browser/server_groups/servers/pgagent/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/pgagent/__init__.py @@ -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 diff --git a/web/pgadmin/browser/server_groups/servers/static/img/gpdb.png b/web/pgadmin/browser/server_groups/servers/static/img/gpdb.png new file mode 100644 index 0000000000000000000000000000000000000000..134393c4582c4ef5615138ff740884098800df83 GIT binary patch literal 1244 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRt!3HF+tk*dLq*&4&eH|GXHuiJ>Nn{1`6_P!I zd>I(3)EF2VS{N990fib~Fff!FFfhDIU|_JC!N4G1FlSew4N!u!z$3DlfkEmO2s3J% zTmXtOp3V%3D2ed(u}aR*)k{ptPfFFR$SnZMFfiCuSOJ;2sU?XD6}dTi#a0!zN?;XM zKsHENUr7P1q$Jx`DZ)2E!8yMuRl!uxM9)CUj!Qv7!KNrB%__*n4XPc;vsKC{DJihh z*Do(G*DE*H%P&gTH?*|0)Hg8FH!{)%s?aU2%qvN((9J7Wh8O}f$0fBmxhS)sBr`ux z0c37sQhsTPt&$SRA~=A!vm`SOVN+f))LTFg>VstT4fPE4v1tQ(7VbV2T@{H15KUlT zK`gTY8D-^Pl$i>2F33@KhBjd1QN$3AvjLiJ$u6JzSMckV7x`k2!pWvAj)Ge>iZ8lV``ULasdgSIn96$5DJM|y z>>ft(ORH3xE;JSi+)8y^YWDNqTkHHH3HGSc2WKt6&v|cc|NRc*zu*v4`?pG5^2--) zU}qCNR$FJxc0z*x@VU4>>z_;!{^FbPwSWE#<-ik`liVfeh#8!mz4F`V&6)f&ElVsp zMO4L9I8Ja^I6iSpEpWgn&5Uxe?t zT+&KXFV}yssB*3XW_m`#~KfZ)n+$5??>Fs54eB3Z@Z1XG28O2j2m8wF3~Si zRx2`YI^^MR9hB4^Q{BlF-GBMaEY~{%^46879^L&DkX~~}Oa82oz(du0x{(J$#d%fw zH$OFuyW{v=;F)Tgq|e6Y4i$k&ot0DfUpJ08eD}G>ybq>*dh7KZGWkx}%sS{F6Wo1q z&y4+t`p#MNZAt&ou;Jw~eGkjs8@I@azh&eNF`jjJ#~lZEkH?0x+(IdbmfUM(I%#;{ zIbBKd$J9gBUBc6^-uWxwym3)`*eh?*4PRN7&f%+B_klI-muQj+-wf3|{Be(_>bw)I znIW3HuV!}g+|=~uy}1%A)T}Mnq+XTLH>lpp`#hzW6O zokdKZN{4>VTH#gy{LgTe~DWM4f?7-Te literal 0 HcmV?d00001 diff --git a/web/pgadmin/browser/tests/test_version_in_range.py b/web/pgadmin/browser/tests/test_version_in_range.py new file mode 100644 index 00000000..e090207b --- /dev/null +++ b/web/pgadmin/browser/tests/test_version_in_range.py @@ -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)) diff --git a/web/pgadmin/browser/utils.py b/web/pgadmin/browser/utils.py index acc16621..5ecbe7ce 100644 --- a/web/pgadmin/browser/utils.py +++ b/web/pgadmin/browser/utils.py @@ -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