Implementation of View & Materialized View

This commit is contained in:
Surinder Kumar 2016-05-20 17:43:30 +05:30 committed by Akshay Joshi
parent 4dbe058832
commit ecde42cbed
95 changed files with 4941 additions and 9 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
"""
We will use the exisiting modules for creating children module under
materialize views.
"""
from pgadmin.browser.server_groups.servers.databases.schemas.tables.column \
import blueprint as columns_module
from pgadmin.browser.server_groups.servers.databases.schemas.tables.indexes \
import blueprint as indexes_modules
from pgadmin.browser.server_groups.servers.databases.schemas.tables.triggers \
import blueprint as triggers_modules
from pgadmin.browser.server_groups.servers.databases.schemas.tables.rules \
import blueprint as rules_modules

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 B

View File

@ -0,0 +1,12 @@
.icon-mview{
background-image: url('{{ url_for('NODE-mview.static', filename='img/mview.png') }}') !important;
border-radius: 10px;
background-repeat: no-repeat;
align-content: center;
vertical-align: middle;
height: 1.3em;
}
.sql_field_width_full {
width: 100%;
}

View File

@ -0,0 +1,313 @@
define(
['jquery', 'underscore', 'underscore.string', 'pgadmin', 'alertify',
'pgadmin.browser', 'codemirror', 'pgadmin.browser.server.privilege'],
function($, _, S, pgAdmin, alertify, pgBrowser, CodeMirror) {
/**
Create and add a view collection into nodes
@param {variable} label - Label for Node
@param {variable} type - Type of Node
@param {variable} columns - List of columns to
display under under properties.
*/
if (!pgBrowser.Nodes['coll-mview']) {
var mviews= pgAdmin.Browser.Nodes['coll-mview'] =
pgAdmin.Browser.Collection.extend({
node: 'mview',
label: '{{ _("Materialized Views") }}',
type: 'coll-mview',
columns: ['name', 'owner']
});
}
/**
Create and Add a View Node into nodes
@param {variable} parent_type - The list of nodes
under which this node to display
@param {variable} type - Type of Node
@param {variable} hasSQL - To show SQL tab
@param {variable} canDrop - Adds drop view option
in the context menu
@param {variable} canDropCascade - Adds drop Cascade
view option in the context menu
*/
if (!pgBrowser.Nodes['mview']) {
pgAdmin.Browser.Nodes['mview'] = pgAdmin.Browser.Node.extend({
parent_type: ['schema', 'catalog'],
type: 'mview',
sqlAlterHelp: 'sql-altermaterializedview.html',
sqlCreateHelp: 'sql-creatematerializedview.html',
label: '{{ _("Materialized View") }}',
hasSQL: true,
hasDepends: true,
collection_type: 'coll-mview',
canDrop: pgBrowser.Nodes['schema'].canChildDrop,
canDropCascade: pgBrowser.Nodes['schema'].canChildDrop,
Init: function() {
// Avoid mulitple registration of menus
if (this.initialized)
return;
this.initialized = true;
/**
Add "create view" menu option into context and object menu
for the following nodes:
coll-mview, view and schema.
@property {data} - Allow create view option on schema node or
system view nodes.
*/
pgBrowser.add_menus([{
name: 'create_mview_on_coll', node: 'coll-mview',
module: this, applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 1, label: '{{ _("Materialized View...") }}',
icon: 'wcTabIcon icon-mview', data: {action: 'create', check: true},
enable: 'canCreate'
},{
name: 'create_mview', node: 'mview', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 1, label: '{{ _("Materialized View...") }}',
icon: 'wcTabIcon icon-mview', data: {action: 'create', check: true},
enable: 'canCreate'
},{
name: 'create_mview', node: 'schema', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 18, label: '{{ _("Materialized View...") }}',
icon: 'wcTabIcon icon-mview', data: {action: 'create', check: false},
enable: 'canCreate'
},{
name: 'refresh_mview', node: 'mview', module: this, category: 'Refresh view',
applies: ['object', 'context'], callback: 'refresh_mview', icon: 'fa fa-refresh',
priority: 1, label: '{{ _("Refresh data") }}', data: {concurrent: false}
},{
name: 'refresh_mview_concurrent', node: 'mview', module: this,
category: 'Refresh view',
applies: ['object', 'context'], callback: 'refresh_mview', icon: 'fa fa-refresh',
priority: 2, label: '{{ _("Refresh concurrently") }}', data: {concurrent: true}
}
]);
},
/**
Define model for the view node and specify the
properties of the model in schema.
*/
model: pgAdmin.Browser.Node.Model.extend({
initialize: function(attrs, args) {
var isNew = (_.size(attrs) === 0);
if (isNew) {
// Set Selected Schema
var schemaLabel = args.node_info.schema.label;
this.set({'schema': schemaLabel}, {silent: true});
// Set Current User
var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user;
this.set({'owner': userInfo.name}, {silent: true});
}
pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments);
},
defaults: {
spcname: 'pg_default',
toast_autovacuum_enabled: false,
autovacuum_enabled: false
},
schema: [{
id: 'name', label: '{{ _("Name") }}', cell: 'string',
type: 'text', disabled: 'inSchema'
},
{
id: 'oid', label:'{{ _("OID") }}', cell: 'string',
type: 'text', disabled: true, mode: ['properties']
},
{
id: 'owner', label:'{{ _("Owner") }}', cell: 'string',
control: 'node-list-by-name', select2: { allowClear: false },
node: 'role', disabled: 'inSchema'
},
{
id: 'schema', label:'{{ _("Schema") }}', cell: 'string', first_empty: false,
control: 'node-list-by-name', type: 'text', cache_level: 'database',
node: 'schema', mode: ['create', 'edit'], disabled: 'inSchema', select2: { allowClear: false }
},
{
id: 'system_view', label:'{{ _("System view?") }}', cell: 'string',
type: 'switch', disabled: true, mode: ['properties'],
},
{
id: 'acl', label: '{{ _("ACL") }}',
mode: ['properties'], type: 'text'
},
{
id: 'comment', label:'{{ _("Comment") }}', cell: 'string',
type: 'multiline'
},
{
id: 'definition', label:'{{ _("") }}', cell: 'string',
type: 'text', mode: ['create', 'edit'], group: 'Definition',
control: Backform.SqlFieldControl, extraClasses:['sql_field_width_full']
},
// Add Privilege Control
{
id: 'datacl', label: '{{ _("Privileges") }}',
model: pgAdmin.Browser.Node.PrivilegeRoleModel.extend(
{privileges: ['a', 'r', 'w', 'd', 'D', 'x', 't']}), uniqueCol : ['grantee'],
editable: false, type: 'collection', group: '{{ _("Security") }}',
mode: ['edit', 'create'], canAdd: true, canDelete: true,
control: 'unique-col-collection', priority: 3
},
// Add Security Labels Control
{
id: 'seclabels', label: '{{ _("Security Labels") }}',
model: Backform.SecurityModel, editable: false, type: 'collection',
canEdit: false, group: '{{ _("Security") }}', canDelete: true,
mode: ['edit', 'create'], canAdd: true,
control: 'unique-col-collection', uniqueCol : ['provider']
},
{
id: 'with_data', label: '{{ _("With Data") }}',
group: '{{ _("Storage") }}', mode: ['edit', 'create'],
type: 'switch',
},
{
id: 'spcname', label: '{{ _("Tablespace") }}', cell: 'string',
type: 'text', group: '{{ _("Storage") }}', first_empty: false,
control: 'node-list-by-name', node: 'tablespace', select2: { allowClear: false },
filter: function(m) {
if (m.label == "pg_global") return false;
else return true;
}
},
{
id: 'fillfactor', label: '{{ _("Fill Factor") }}',
group: '{{ _("Storage") }}', mode: ['edit', 'create'],
type: 'integer'
},
{
type: 'nested', control: 'tab', id: 'materialization',
label: '{{ _("Materialization") }}', mode: ['edit', 'create'],
group: '{{ _("Storage") }}',
schema: Backform.VacuumSettingsSchema
},
],
validate: function(keys) {
// Triggers specific error messages for fields
var err = {},
errmsg,
field_name = this.get('name'),
field_def = this.get('definition');
if (_.indexOf(keys, 'autovacuum_enabled') != -1 ||
_.indexOf(keys, 'toast_autovacuum_enabled') != -1 )
return null;
if (_.isUndefined(field_name) || _.isNull(field_name) ||
String(field_name).replace(/^\s+|\s+$/g, '') == '') {
err['name'] = '{{ _("Please specify name.") }}';
errmsg = errmsg || err['name'];
this.errorModel.set('name', errmsg);
return errmsg;
}else{
this.errorModel.unset('name');
}
if (_.isUndefined(field_def) || _.isNull(field_def) ||
String(field_def).replace(/^\s+|\s+$/g, '') == '') {
err['definition'] = '{{ _("Please enter function definition.") }}';
errmsg = errmsg || err['definition'];
this.errorModel.set('definition', errmsg);
return errmsg;
}else{
this.errorModel.unset('definition');
}
return null;
},
// We will disable everything if we are under catalog node
inSchema: function() {
if(this.node_info && 'catalog' in this.node_info)
{
return true;
}
return false;
}
}),
/**
Show or hide create view menu option on parent node
and hide for system view in catalogs.
*/
canCreate: function(itemData, item, data) {
// If check is false then, we will allow create menu
if (data && data.check === false)
return true;
var t = pgBrowser.tree, i = item, d = itemData;
// To iterate over tree to check parent node
while (i) {
// If it is schema then allow user to create view
if (_.indexOf(['schema'], d._type) > -1)
return true;
if ('coll-mview' == d._type) {
// Check if we are not child of view
prev_i = t.hasParent(i) ? t.parent(i) : null;
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d._type == 'catalog') {
return false;
} else {
return true;
}
}
i = t.hasParent(i) ? t.parent(i) : null;
d = i ? t.itemData(i) : null;
}
// by default we do not want to allow create menu
return true;
},
refresh_mview: function(args) {
var input = args || {};
obj = this,
t = pgBrowser.tree,
i = input.item || t.selected(),
d = i && i.length == 1 ? t.itemData(i) : undefined;
if (!d)
return false;
// Make ajax call to refresh mview data
$.ajax({
url: obj.generate_url(i, 'refresh_data' , d, true),
type: 'PUT',
data: {'concurrent': args.concurrent},
dataType: "json",
success: function(res) {
if (res.success == 1) {
alertify.success('View refreshed successfully');
}
else {
alertify.alert(
'Error refreshing view',
res.data.result
);
}
},
error: function(e) {
var errmsg = $.parseJSON(e.responseText);
alertify.alert('Error refreshing view', errmsg.errormsg);
}
});
}
});
}
return pgBrowser.Nodes['coll-mview'];
});

View File

@ -0,0 +1,41 @@
{#============================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 = 'm'
) acl,
aclexplode(relacl) 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 %}

View File

@ -0,0 +1,41 @@
{# ===================== Create new view ===================== #}
{% if display_comments %}
-- View: {{ conn|qtIdent(data.schema, data.name) }}
-- DROP MATERIALIZED VIEW {{ conn|qtIdent(data.schema, data.name) }};
{% endif %}
{% if data.name and data.schema and data.definition %}
CREATE MATERIALIZED VIEW {{ conn|qtIdent(data.schema, data.name) }}
{% if(data.fillfactor or data['vacuum_data']|length > 0) %}
WITH (
{% if data.fillfactor %}
FILLFACTOR = {{ data.fillfactor }}{% if data['autovacuum_enabled'] or data['toast_autovacuum_enabled'] or data['vacuum_data']|length > 0 %},{{ '\r' }}{% endif %}
{% endif %}
{% for field in data['vacuum_data'] %}
{% if field.value is defined and field.value != '' and field.value != none %}
{% if loop.index > 1%},
{% endif %} {{ field.name }} = {{ field.value|lower }}{% endif %}
{% endfor %}
)
{% endif %}
{% if data.spcname %}TABLESPACE {{ data.spcname }}
{% endif %}AS
{{ data.definition.rstrip(';') }}
{% if data.with_data %}
WITH DATA;
{% else %}
WITH NO DATA;
{% endif %}
{% 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 %}

View File

@ -0,0 +1,13 @@
{# =================== Drop/Cascade materialized 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 MATERIALIZED VIEW {{ conn|qtIdent(nspname, name) }} {% if cascade %} CASCADE {% endif %}
{% endif %}

View File

@ -0,0 +1,7 @@
{# ===== fetch schema name =====#}
SELECT
nspname
FROM
pg_namespace
WHERE
oid = {{ scid }}::oid;

View File

@ -0,0 +1,11 @@
{# ===== get view name against view id ==== #}
{% if vid %}
SELECT
c.relname AS name,
nsp.nspname AS schema
FROM
pg_class c
LEFT OUTER JOIN pg_namespace nsp on nsp.oid = c.relnamespace
WHERE
c.oid = {{vid}}
{% endif %}

View File

@ -0,0 +1,6 @@
{# ===== Grant Permissions to User Role on Views/Tables ==== #}
{% import 'macros/security.macros' as SECLABLE %}
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
{# We will generate Security Label SQL using macro #}
{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{% endfor %}{% 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 %}

View File

@ -0,0 +1,111 @@
{# ========================== Fetch Materialized View Properties ========================= #}
{% if (vid and datlastsysoid) or scid %}
SELECT
c.oid,
c.xmin,
c.relname AS name,
c.reltablespace AS spcoid,
c.relispopulated AS with_data,
(CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
c.relacl,
nsp.nspname as schema,
pg_get_userbyid(c.relowner) AS owner,
description AS comment,
pg_get_viewdef(c.oid, true) AS definition,
{# ============= Checks if it is system view ================ #}
{% if vid and datlastsysoid %}
CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
{% endif %}
array_to_string(c.relacl::text[], ', ') AS acl,
(SELECT array_agg(provider || '=' || label) FROM pg_seclabels sl1 WHERE sl1.objoid=c.oid AND sl1.objsubid=0) AS seclabels,
substring(array_to_string(c.reloptions, ',')
FROM 'fillfactor=([0-9]*)') AS fillfactor,
(CASE WHEN (substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_enabled=([a-z|0-9]*)') = 'true') THEN true ELSE false END) AS autovacuum_enabled,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_vacuum_threshold=([0-9]*)') AS autovacuum_vacuum_threshold,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_vacuum_scale_factor=([0-9]*[.][0-9]*)') AS autovacuum_vacuum_scale_factor,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_analyze_threshold=([0-9]*)') AS autovacuum_analyze_threshold,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_analyze_scale_factor=([0-9]*[.][0-9]*)') AS autovacuum_analyze_scale_factor,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_vacuum_cost_delay=([0-9]*)') AS autovacuum_vacuum_cost_delay,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_vacuum_cost_limit=([0-9]*)') AS autovacuum_vacuum_cost_limit,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_freeze_min_age=([0-9]*)') AS autovacuum_freeze_min_age,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_freeze_max_age=([0-9]*)') AS autovacuum_freeze_max_age,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_freeze_table_age=([0-9]*)') AS autovacuum_freeze_table_age,
(CASE WHEN (substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_enabled=([a-z|0-9]*)') = 'true') THEN true ELSE false END) AS toast_autovacuum_enabled,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_vacuum_threshold=([0-9]*)') AS toast_autovacuum_vacuum_threshold,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_vacuum_scale_factor=([0-9]*[.][0-9]*)') AS toast_autovacuum_vacuum_scale_factor,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_analyze_threshold=([0-9]*)') AS toast_autovacuum_analyze_threshold,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_analyze_scale_factor=([0-9]*[.][0-9]*)') AS toast_autovacuum_analyze_scale_factor,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_vacuum_cost_delay=([0-9]*)') AS toast_autovacuum_vacuum_cost_delay,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_vacuum_cost_limit=([0-9]*)') AS toast_autovacuum_vacuum_cost_limit,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_freeze_min_age=([0-9]*)') AS toast_autovacuum_freeze_min_age,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_freeze_max_age=([0-9]*)') AS toast_autovacuum_freeze_max_age,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_freeze_table_age=([0-9]*)') AS toast_autovacuum_freeze_table_age,
c.reloptions AS reloptions, tst.reloptions AS toast_reloptions,
(CASE WHEN c.reltoastrelid = 0 THEN false ELSE true END) AS hastoasttable,
(CASE WHEN (substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_enabled=([a-z|0-9]*)')) = 'true' THEN true ELSE false END) AS autovacuum_custom,
(CASE WHEN (substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_enabled=([a-z|0-9]*)')) = 'true' THEN true ELSE false END) AS toast_autovacuum
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)
LEFT OUTER JOIN pg_class tst ON tst.oid = c.reltoastrelid
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 = 'm'::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 %}

View File

@ -0,0 +1,4 @@
{#=== refresh mat view [concurrenlty] ===#}
{% if name and nspname %}
REFRESH MATERIALIZED VIEW {% if is_concurrent %}CONCURRENTLY{% endif %} {{ conn|qtIdent(nspname, name) }};
{% endif %}

View File

@ -0,0 +1,216 @@
{# ===================== Update View ===================#}
{% import 'macros/security.macros' as SECLABLE %}
{% 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 %}
{# ===== Rename mat view ===== #}
{% if data.name and data.name != o_data.name %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(o_data.schema, o_data.name) }}
RENAME TO {{ conn|qtIdent(data.name) }};
{% endif %}
{# ===== Alter schema view ===== #}
{% if data.schema and data.schema != o_data.schema %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(o_data.schema, view_name ) }}
SET SCHEMA {{ conn|qtIdent(data.schema) }};
{% endif %}
{# ===== Alter Table owner ===== #}
{% if data.owner and data.owner != o_data.owner %}
ALTER TABLE {{ conn|qtIdent(view_schema, view_name) }}
OWNER TO {{ conn|qtIdent(data.owner) }};
{% endif %}
{# ===== First Drop and then create mat view ===== #}
{% if def and def != o_data.definition.rstrip(';') %}
DROP MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }};
CREATE MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
{% if data.fillfactor or (data['vacuum_data']['changed']|length > 0 ) %}
WITH(
{% if data.fillfactor %}
FILLFACTOR = {{ data.fillfactor }}{% if data['vacuum_data']['changed']|length > 0 %},{% endif %}{{ '\r' }}
{% endif %}
{% if data['vacuum_data']['changed']|length > 0 %}
{% for field in data['vacuum_data']['changed'] %}
{{ field.name }} = {{ field.value|lower }}{% if not loop.last %},{% endif %}{{ '\r' }}
{% endfor %}
{% endif %}
)
{% endif %}
AS
{{ def }}
{% if data.with_data is defined %}
WITH {{ 'DATA' if data.with_data else 'NO DATA' }};
{% elif o_data.with_data %}
WITH {{ 'DATA' if o_data.with_data else 'NO DATA' }};
{% endif %}
{% else %}
{# ======= Alter Tablespace ========= #}
{%- if data.spcoid and o_data.spcoid != data.spcoid -%}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
SET TABLESPACE {{ data.spcoid }};
{% endif %}
{# ======= SET/RESET Fillfactor ========= #}
{% if data.fillfactor and o_data.fillfactor != data.fillfactor %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
SET(
FILLFACTOR = {{ data.fillfactor }}
);
{% elif data.fillfactor == '' and o_data.fillfactor|default('', 'true') != data.fillfactor %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
RESET(
FILLFACTOR
);
{% endif %}
{# ===== Check for with_data property ===== #}
{% if data.with_data is defined and o_data.with_data|lower != data.with_data|lower %}
REFRESH MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }} WITH{{ ' NO' if data.with_data|lower == 'false' else '' }} DATA;
{% endif %}
{# ===== Check for Table tab properties ===== #}
{% if ((data.autovacuum_custom is defined and data.autovacuum_custom|lower == 'false') or
(data.toast_autovacuum is defined and data.toast_autovacuum|lower == 'false')
) %}
{% if data.autovacuum_custom|lower == 'false' %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
RESET(
autovacuum_enabled,
autovacuum_vacuum_threshold,
autovacuum_analyze_threshold,
autovacuum_vacuum_scale_factor,
autovacuum_analyze_scale_factor,
autovacuum_vacuum_cost_delay,
autovacuum_vacuum_cost_limit,
autovacuum_freeze_min_age,
autovacuum_freeze_max_age,
autovacuum_freeze_table_age
);
{% if data.toast_autovacuum is defined and data.toast_autovacuum|lower != 'false' %}
{% if('vacuum_toast' in data and data['vacuum_toast']['changed']|length > 0) %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(data.schema, data.name) }} SET(
{% for field in data['vacuum_toast']['changed'] %}
{% if field.value != None %}
{{ field.name }} = {{ field.value|lower }}{% if not loop.last %},{% endif %}{{ '\r' }}
{% endif %}
{% endfor %}
);
{% endif %}
{% endif %}
{% endif %}
{% if data.toast_autovacuum|lower == 'false' %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
RESET(
toast.autovacuum_enabled,
toast.autovacuum_vacuum_threshold,
toast.autovacuum_analyze_threshold,
toast.autovacuum_vacuum_scale_factor,
toast.autovacuum_analyze_scale_factor,
toast.autovacuum_vacuum_cost_delay,
toast.autovacuum_vacuum_cost_limit,
toast.autovacuum_freeze_min_age,
toast.autovacuum_freeze_max_age,
toast.autovacuum_freeze_table_age
);
{% if data.autovacuum_custom is defined and data.autovacuum_custom|lower != 'false' %}
{% if('vacuum_table' in data and data['vacuum_table']['changed']|length > 0) %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(data.schema, data.name) }} SET(
{% for field in data['vacuum_table']['changed'] %}
{% if field.value != None %}
{{ field.name }} = {{ field.value|lower }}{% if not loop.last %},{% endif %}{{ '\r' }}
{% endif %}
{% endfor %}
);
{% endif %}
{% endif %}
{% endif %}{#-- toast_endif ends --#}
{% else %}
{% if data['vacuum_data']['reset']|length == 0 and
data['vacuum_data']['changed']|length == 0 and data['settings']|length > 0 %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
SET(
{% for field in data['settings'] %}
{{ field }} = {{ data['settings'][field]|lower }}{% if not loop.last %},{% endif %}{{ '\r' }}
{% endfor %}
);
{% endif %}
{% if(data['vacuum_data']['changed']|length > 0) %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(data.schema, data.name) }}
SET(
{% for field in data['vacuum_data']['changed'] %}
{% if field.value != None %}
{{ field.name }} = {{ field.value|lower }}{% if not loop.last %},{% endif %}{{ '\r' }}
{% endif %}
{% endfor %}
);
{% endif %}
{% if data['vacuum_data']['reset']|length > 0 %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
RESET(
{% for field in data['vacuum_data']['reset'] %}
{{ field.name }}{% if not loop.last %},{% endif %}{{ '\r' }}
{% endfor %}
);
{% endif %}
{% endif %}{# ===== End check for custom autovaccum ===== #}
{% endif %}{# ===== End block for check data definition ===== #}
{% set old_comment = o_data.comment|default('', true) %}
{% if (data.comment is defined and (data.comment != old_comment)) %}
COMMENT ON MATERIALIZED 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 %}
{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
{% endfor %}
{% endif %}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}

View File

@ -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 %}

View File

@ -0,0 +1,41 @@
{#============================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 = 'm'
) acl,
aclexplode(relacl) 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 %}

View File

@ -0,0 +1,47 @@
{# ===================== Create new view ===================== #}
{% if display_comments %}
-- View: {{ conn|qtIdent(data.schema, data.name) }}
-- DROP MATERIALIZED VIEW {{ conn|qtIdent(data.schema, data.name) }};
{% endif %}
{% if data.name and data.schema and data.definition %}
CREATE MATERIALIZED VIEW {{ conn|qtIdent(data.schema, data.name) }}
{% if(data.fillfactor or data['autovacuum_enabled'] or data['toast_autovacuum_enabled']) %}
WITH (
{% if data.fillfactor %}
FILLFACTOR = {{ data.fillfactor }}{% if data['autovacuum_enabled'] or data['toast_autovacuum_enabled'] or data['vacuum_data']|length > 0 %},{{ '\r' }}{% endif %}
{% endif %}
{% if data['autovacuum_enabled'] %}
autovacuum_enabled = {{ data['autovacuum_enabled']|lower }}{% if data['toast_autovacuum_enabled'] or data['vacuum_data']|length > 0 %},{{ '\r' }}{% endif %}
{% endif %}
{% if data['toast_autovacuum_enabled'] %}
{{ 'toast.autovacuum_enabled' }} = {{ data['toast_autovacuum_enabled']|lower }}{% if data['vacuum_data']|length > 0 %},{{ '\r' }}{% endif %}
{% endif %}
{% for field in data['vacuum_data'] %}
{% if field.value is defined and field.value != '' and field.value != none %}
{% if loop.index > 1%},
{% endif %} {{ field.name }} = {{ field.value|lower }}{% endif %}
{% endfor %}
)
{% endif %}
{% if data.spcname %}TABLESPACE {{ data.spcname }}
{% endif %}AS
{{ data.definition.rstrip(';') }}
{% if data.with_data %}
WITH DATA;
{% else %}
WITH NO DATA;
{% endif %}
{% 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 %}

View File

@ -0,0 +1,13 @@
{# =================== Drop/Cascade materialized 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 MATERIALIZED VIEW {{ conn|qtIdent(nspname, name) }} {% if cascade %} CASCADE {% endif %}
{% endif %}

View File

@ -0,0 +1,7 @@
{# ===== fetch schema name =====#}
SELECT
nspname
FROM
pg_namespace
WHERE
oid = {{ scid }}::oid;

View File

@ -0,0 +1,11 @@
{# ===== get view name against view id ==== #}
{% if vid %}
SELECT
c.relname AS name,
nsp.nspname AS schema
FROM
pg_class c
LEFT OUTER JOIN pg_namespace nsp on nsp.oid = c.relnamespace
WHERE
c.oid = {{vid}}
{% endif %}

View File

@ -0,0 +1,6 @@
{# ===== Grant Permissions to User Role on Views/Tables ==== #}
{% import 'macros/security.macros' as SECLABLE %}
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
{# We will generate Security Label SQL using macro #}
{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{% endfor %}{% 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 %}

View File

@ -0,0 +1,111 @@
{# ========================== Fetch Materialized View Properties ========================= #}
{% if (vid and datlastsysoid) or scid %}
SELECT
c.oid,
c.xmin,
c.relname AS name,
c.reltablespace AS spcoid,
c.relispopulated AS with_data,
(CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
c.relacl,
nsp.nspname as schema,
pg_get_userbyid(c.relowner) AS owner,
description AS comment,
pg_get_viewdef(c.oid, true) AS definition,
{# ============= Checks if it is system view ================ #}
{% if vid and datlastsysoid %}
CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
{% endif %}
array_to_string(c.relacl::text[], ', ') AS acl,
(SELECT array_agg(provider || '=' || label) FROM pg_seclabels sl1 WHERE sl1.objoid=c.oid AND sl1.objsubid=0) AS seclabels,
substring(array_to_string(c.reloptions, ',')
FROM 'fillfactor=([0-9]*)') AS fillfactor,
(CASE WHEN (substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_enabled=([a-z|0-9]*)') = 'true') THEN true ELSE false END) AS autovacuum_enabled,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_vacuum_threshold=([0-9]*)') AS autovacuum_vacuum_threshold,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_vacuum_scale_factor=([0-9]*[.][0-9]*)') AS autovacuum_vacuum_scale_factor,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_analyze_threshold=([0-9]*)') AS autovacuum_analyze_threshold,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_analyze_scale_factor=([0-9]*[.][0-9]*)') AS autovacuum_analyze_scale_factor,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_vacuum_cost_delay=([0-9]*)') AS autovacuum_vacuum_cost_delay,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_vacuum_cost_limit=([0-9]*)') AS autovacuum_vacuum_cost_limit,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_freeze_min_age=([0-9]*)') AS autovacuum_freeze_min_age,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_freeze_max_age=([0-9]*)') AS autovacuum_freeze_max_age,
substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_freeze_table_age=([0-9]*)') AS autovacuum_freeze_table_age,
(CASE WHEN (substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_enabled=([a-z|0-9]*)') = 'true') THEN true ELSE false END) AS toast_autovacuum_enabled,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_vacuum_threshold=([0-9]*)') AS toast_autovacuum_vacuum_threshold,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_vacuum_scale_factor=([0-9]*[.][0-9]*)') AS toast_autovacuum_vacuum_scale_factor,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_analyze_threshold=([0-9]*)') AS toast_autovacuum_analyze_threshold,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_analyze_scale_factor=([0-9]*[.][0-9]*)') AS toast_autovacuum_analyze_scale_factor,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_vacuum_cost_delay=([0-9]*)') AS toast_autovacuum_vacuum_cost_delay,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_vacuum_cost_limit=([0-9]*)') AS toast_autovacuum_vacuum_cost_limit,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_freeze_min_age=([0-9]*)') AS toast_autovacuum_freeze_min_age,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_freeze_max_age=([0-9]*)') AS toast_autovacuum_freeze_max_age,
substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_freeze_table_age=([0-9]*)') AS toast_autovacuum_freeze_table_age,
c.reloptions AS reloptions, tst.reloptions AS toast_reloptions,
(CASE WHEN c.reltoastrelid = 0 THEN false ELSE true END) AS hastoasttable,
(CASE WHEN (substring(array_to_string(c.reloptions, ',')
FROM 'autovacuum_enabled=([a-z|0-9]*)')) = 'true' THEN true ELSE false END) AS autovacuum_custom,
(CASE WHEN (substring(array_to_string(tst.reloptions, ',')
FROM 'autovacuum_enabled=([a-z|0-9]*)')) = 'true' THEN true ELSE false END) AS toast_autovacuum
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)
LEFT OUTER JOIN pg_class tst ON tst.oid = c.reltoastrelid
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 = 'm'::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 %}

View File

@ -0,0 +1,4 @@
{#=== refresh mat view [concurrenlty] ===#}
{% if name and nspname %}
REFRESH MATERIALIZED VIEW {% if is_concurrent %}CONCURRENTLY{% endif %} {{ conn|qtIdent(nspname, name) }};
{% endif %}

View File

@ -0,0 +1,179 @@
{# ===================== Update View ===================#}
{% import 'macros/security.macros' as SECLABLE %}
{% 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 %}
{# ===== Rename mat view ===== #}
{% if data.name and data.name != o_data.name %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(o_data.schema, o_data.name) }}
RENAME TO {{ conn|qtIdent(data.name) }};
{% endif %}
{# ===== Alter schema view ===== #}
{% if data.schema and data.schema != o_data.schema %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(o_data.schema, view_name ) }}
SET SCHEMA {{ conn|qtIdent(data.schema) }};
{% endif %}
{# ===== Alter Table owner ===== #}
{% 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 data['vacuum_data']['reset']|length == 0 and
data['vacuum_data']['changed']|length == 0 and data['settings']|length > 0 %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
SET(
{% for field in data['settings'] %}
{{ field }} = {{ data['settings'][field]|lower }}{% if not loop.last %},{% endif %}{{ '\r' }}
{% endfor %}
);
{% endif %}
{% if data['vacuum_data']['reset']|length > 0 %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
RESET(
{% for field in data['vacuum_data']['reset'] %}
{{ field.name }}{% if not loop.last %},{% endif %}{{ '\r' }}
{% endfor %}
);
{% endif %}
{# ===== First Drop and then create mat view ===== #}
{% if def and def != o_data.definition.rstrip(';') %}
{% if data.fillfactor or ( data['vacuum_data']['changed']|length > 0 ) %}
DROP MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }};
CREATE MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
WITH(
{% if data.fillfactor %}
FILLFACTOR = {{ data.fillfactor }}{% if data['vacuum_data']['changed']|length > 0 %},{% endif %}{{ '\r' }}
{% endif %}
{% if data['vacuum_data']['changed']|length > 0 %}
{% for field in data['vacuum_data']['changed'] %}
{{ field.name }} = {{ field.value|lower }}{% if not loop.last %},{% endif %}{{ '\r' }}
{% endfor %}
{% endif %}
)
AS
{{ def }}
{% if data.with_data %}
WITH DATA;
{% else %}
WITH NO DATA;
{% endif %}
{% endif %}
{% else %}
{# ======= Alter Tablespace ========= #}
{%- if data.spcoid and o_data.spcoid != data.spcoid -%}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
SET TABLESPACE {{ data.spcoid }};
{% endif %}
{# ======= SET/RESET Fillfactor ========= #}
{% if data.fillfactor and o_data.fillfactor != data.fillfactor %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
SET(FILLFACTOR = {{ data.fillfactor }});
{% elif data.fillfactor == '' %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
RESET(
FILLFACTOR
);
{% endif %}
{# ===== Check for with_data property ===== #}
{% if data.with_data is defined and o_data.with_data|lower != data.with_data|lower %}
REFRESH MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }} WITH{{ ' NO' if data.with_data|lower == 'false' else '' }} DATA;
{% endif %}
{# ===== Check for Table tab properties ===== #}
{% if ((data.autovacuum_custom is defined and data.autovacuum_custom|lower == 'false') or
(data.toast_autovacuum is defined and data.toast_autovacuum|lower == 'false')
) %}
{% if data.autovacuum_custom is defined %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
RESET(
autovacuum_vacuum_threshold,
autovacuum_analyze_threshold,
autovacuum_vacuum_scale_factor,
autovacuum_analyze_scale_factor,
autovacuum_vacuum_cost_delay,
autovacuum_vacuum_cost_limit,
autovacuum_freeze_min_age,
autovacuum_freeze_max_age,
autovacuum_freeze_table_age
);
{% endif %}
{% if data.toast_autovacuum is defined %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
RESET(
toast.autovacuum_vacuum_threshold,
toast.autovacuum_analyze_threshold,
toast.autovacuum_vacuum_scale_factor,
toast.autovacuum_analyze_scale_factor,
toast.autovacuum_vacuum_cost_delay,
toast.autovacuum_vacuum_cost_limit,
toast.autovacuum_freeze_min_age,
toast.autovacuum_freeze_max_age,
toast.autovacuum_freeze_table_age
);
{% endif %}
{% elif(data['vacuum_data']['changed']|length > 0) %}
ALTER MATERIALIZED VIEW {{ conn|qtIdent(data.schema, data.name) }} SET(
{% for field in data['vacuum_data']['changed'] %}
{% if field.value != None %}
{{ field.name }} = {{ field.value|lower }}{% if not loop.last %},{% endif %}{{ '\r' }}
{% endif %}
{% endfor %}
);
{% endif %}{# ===== End check for custom autovaccum ===== #}
{% endif %}{# ===== End block for check data definition ===== #}
{% if data.comment and data.comment != o_data.comment %}
COMMENT ON MATERIALIZED 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 %}
{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
{% endfor %}
{% endif %}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}

View File

@ -0,0 +1,4 @@
{# ===== Below will provide view id for last created view ==== #}
{% if data %}
SELECT c.oid FROM pg_class c WHERE c.relname = '{{ data.name }}';
{% endif %}

View File

@ -0,0 +1,12 @@
.icon-view{
background-image: url('{{ url_for('NODE-view.static', filename='img/view.png') }}') !important;
border-radius: 10px;
background-repeat: no-repeat;
align-content: center;
vertical-align: middle;
height: 1.3em;
}
.sql_field_height_140 {
height: 140px;
}

View File

@ -0,0 +1,267 @@
define(
['jquery', 'underscore', 'underscore.string', 'pgadmin',
'pgadmin.browser', 'codemirror', 'pgadmin.browser.server.privilege', 'pgadmin.node.rule'],
function($, _, S, pgAdmin, pgBrowser, CodeMirror) {
/**
Create and add a view collection into nodes
@param {variable} label - Label for Node
@param {variable} type - Type of Node
@param {variable} columns - List of columns to
display under under properties.
*/
if (!pgBrowser.Nodes['coll-view']) {
var views= pgAdmin.Browser.Nodes['coll-view'] =
pgAdmin.Browser.Collection.extend({
node: 'view',
label: '{{ _("Views") }}',
type: 'coll-view',
columns: ["name", "owner"]
});
}
/**
Create and Add a View Node into nodes
@param {variable} parent_type - The list of nodes
under which this node to display
@param {variable} type - Type of Node
@param {variable} hasSQL - To show SQL tab
@param {variable} canDrop - Adds drop view option
in the context menu
@param {variable} canDropCascade - Adds drop Cascade
view option in the context menu
*/
if (!pgBrowser.Nodes['view']) {
pgAdmin.Browser.Nodes['view'] = pgAdmin.Browser.Node.extend({
parent_type: ['schema', 'catalog'],
type: 'view',
sqlAlterHelp: 'sql-alterview.html',
sqlCreateHelp: 'sql-createview.html',
label: '{{ _("View") }}',
hasSQL: true,
hasDepends: true,
collection_type: 'coll-view',
canDrop: pgBrowser.Nodes['schema'].canChildDrop,
canDropCascade: pgBrowser.Nodes['schema'].canChildDrop,
Init: function() {
// Avoid mulitple registration of menus
if (this.initialized)
return;
this.initialized = true;
/**
Add "create view" menu option into context and object menu
for the following nodes:
coll-view, view and schema.
@property {data} - Allow create view option on schema node or
system view nodes.
*/
pgBrowser.add_menus([{
name: 'create_view_on_coll', node: 'coll-view', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 1, label: '{{ _("View...") }}',
icon: 'wcTabIcon icon-view', data: {action: 'create', check: true},
enable: 'canCreate'
},{
name: 'create_view', node: 'view', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 1, label: '{{ _("View...") }}',
icon: 'wcTabIcon icon-view', data: {action: 'create', check: true},
enable: 'canCreate'
},{
name: 'create_view', node: 'schema', module: this,
applies: ['object', 'context'], callback: 'show_obj_properties',
category: 'create', priority: 17, label: '{{ _("View...") }}',
icon: 'wcTabIcon icon-view', data: {action: 'create', check: false},
enable: 'canCreate'
}
]);
},
/**
Define model for the view node and specify the
properties of the model in schema.
*/
model: pgAdmin.Browser.Node.Model.extend({
initialize: function(attrs, args) {
var isNew = (_.size(attrs) === 0);
if (isNew) {
// Set Selected Schema
var schemaLabel = args.node_info.schema.label;
this.set({'schema': schemaLabel}, {silent: true});
// Set Current User
var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user;
this.set({'owner': userInfo.name}, {silent: true});
}
pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments);
},
schema: [{
id: 'name', label: '{{ _("Name") }}', cell: 'string',
type: 'text', disabled: 'inSchema'
},
{
id: 'oid', label:'{{ _("OID") }}', cell: 'string',
type: 'text', disabled: true, mode: ['properties']
},
{
id: 'owner', label:'{{ _("Owner") }}', cell: 'string', control: 'node-list-by-name',
node: 'role', disabled: 'inSchema', select2: { allowClear: false }
},
{
id: 'schema', label:'{{ _("Schema") }}', cell: 'string', first_empty: false,
control: 'node-list-by-name', type: 'text', cache_level: 'database',
node: 'schema', disabled: 'inSchema', mode: ['create', 'edit'], select2: { allowClear: false }
},
{
id: 'system_view', label:'{{ _("System view?") }}', cell: 'string',
type: 'switch', disabled: true, mode: ['properties']
},
{
id: 'acl', label: '{{ _("Privileges") }}',
mode: ['properties'], type: 'text'
},
{
id: 'comment', label:'{{ _("Comment") }}', cell: 'string',
type: 'multiline', disabled: 'inSchema'
},
{
id: 'security_barrier', label:'{{ _("Security barrier") }}', cell: 'string',
type: 'switch', min_version: '90200',
group: 'Definition', disabled: 'inSchema'
},
{
id: 'check_option', label:'{{ _("Check options") }}',
control: 'select2', group: 'Definition', type: 'text',
min_version: '90400', mode:['properties', 'create', 'edit'],
select2: {
// set select2 option width to 100%
allowClear: false,
width: '100%'
},
options:[
{label: "No", value: "no"},
{label: "Local", value: "local"},
{label: "Cascaded", value: "cascaded"}
], disabled: 'inSchema'
},
{
id: 'definition', label:'{{ _("Definition") }}', cell: 'string',
type: 'text', mode: ['create', 'edit'], group: 'Definition',
control: Backform.SqlFieldControl,
disabled: 'inSchema'
},
{
id: 'security', label: '{{ _("Security") }}',
type: 'group',
visible: function(m) {
if (m.top && 'catalog' in m.top.node_info) {
return false;
}
return true;
}
},
// Add Privilege Control
{
id: 'datacl', label: '{{ _("Privileges") }}',
model: pgAdmin.Browser.Node.PrivilegeRoleModel.extend(
{privileges: ['a', 'r', 'w', 'd', 'D', 'x', 't']}), uniqueCol : ['grantee'],
editable: false, type: 'collection', group: 'security',
mode: ['edit', 'create'], canAdd: true, canDelete: true,
control: 'unique-col-collection', disabled: 'inSchema'
},
// Add Security Labels Control
{
id: 'seclabels', label: '{{ _("Security labels") }}',
model: Backform.SecurityModel, editable: false, type: 'collection',
canEdit: false, group: 'security', canDelete: true,
mode: ['edit', 'create'], canAdd: true, disabled: 'inSchema',
control: 'unique-col-collection', uniqueCol : ['provider']
},
],
validate: function() {
// Triggers specific error messages for fields
var err = {},
errmsg,
field_name = this.get('name'),
field_def = this.get('definition');
if (_.isUndefined(field_name) || _.isNull(field_name) ||
String(field_name).replace(/^\s+|\s+$/g, '') == '') {
err['name'] = '{{ _("Please specify name.") }}';
errmsg = errmsg || err['name'];
this.errorModel.set('name', errmsg);
return errmsg;
}else{
this.errorModel.unset('name');
}
if (_.isUndefined(field_def) || _.isNull(field_def) ||
String(field_def).replace(/^\s+|\s+$/g, '') == '') {
err['definition'] = '{{ _("Please enter function definition.") }}';
errmsg = errmsg || err['definition'];
this.errorModel.set('definition', errmsg);
return errmsg;
}else{
this.errorModel.unset('definition');
}
return null;
},
// We will disable everything if we are under catalog node
inSchema: function() {
if(this.node_info && 'catalog' in this.node_info)
{
return true;
}
return false;
}
}),
/**
Show or hide create view menu option on parent node
and hide for system view in catalogs.
*/
canCreate: function(itemData, item, data) {
// If check is false then, we will allow create menu
if (data && data.check == false)
return true;
var t = pgBrowser.tree, i = item, d = itemData;
// To iterate over tree to check parent node
while (i) {
// If it is schema then allow user to create view
if (_.indexOf(['schema'], d._type) > -1)
return true;
if ('coll-view' == d._type) {
// Check if we are not child of view
prev_i = t.hasParent(i) ? t.parent(i) : null;
prev_d = prev_i ? t.itemData(prev_i) : null;
if( prev_d._type == 'catalog') {
return false;
} else {
return true;
}
}
i = t.hasParent(i) ? t.parent(i) : null;
d = i ? t.itemData(i) : null;
}
// by default we do not want to allow create menu
return true;
}
});
}
return pgBrowser.Nodes['coll-view'];
});

View File

@ -0,0 +1,51 @@
{# ============================ 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
aclexplode(relacl) AS d
FROM
pg_class cl1
WHERE
cl1.oid = {{ vid }}
) a
) d
) d
LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
GROUP BY
g.rolname, gt.rolname
{% endif %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -0,0 +1,7 @@
{# ===== fetch schema name against schema oid ===== #}
SELECT
nspname
FROM
pg_namespace
WHERE
oid = {{ scid }}::oid;

View File

@ -0,0 +1,6 @@
{# ===== Grant Permissions to User Role on Views/Tables ===== #}
{% import 'macros/security.macros' as SECLABLE %}
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
{# ===== We will generate Security Label SQL using macro ===== #}
{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{{'\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 %}

View File

@ -0,0 +1,69 @@
{% 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 %}
(SELECT
array_agg(label)
FROM
pg_seclabels sl1
WHERE
sl1.objoid=c.oid AND sl1.objsubid=0
) AS labels,
(SELECT
array_agg(provider)
FROM
pg_seclabels sl2
WHERE sl2.objoid=c.oid AND sl2.objsubid=0
) AS providers
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 %}

View File

@ -0,0 +1,67 @@
{# ============================ Update View ========================= #}
{% import 'macros/security.macros' as SECLABLE %}
{% 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 %}
{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
{% endfor %}
{% endif %}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}

View File

@ -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 %}

View File

@ -0,0 +1,52 @@
{# ============================ 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
aclexplode(relacl) AS d
FROM
pg_class cl1
WHERE
cl1.oid = {{ vid }}
) a
) d
) d
LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
GROUP BY
g.rolname,
gt.rolname
{% endif %}

View File

@ -0,0 +1,24 @@
{#============================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) }}{% if (data.security_barrier) %}{{'\r'}}
WITH (
{% if data.security_barrier %} security_barrier={{ data.security_barrier|lower }}{% endif %}{{'\r'}}
){% endif %} 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 %}

View File

@ -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 %}

View File

@ -0,0 +1,7 @@
{# ===== fetch schema name against schema oid ===== #}
SELECT
nspname
FROM
pg_namespace
WHERE
oid = {{ scid }}::oid;

View File

@ -0,0 +1,6 @@
{# ===== Grant Permissions to User Role on Views/Tables ===== #}
{% import 'macros/security.macros' as SECLABLE %}
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
{# ===== We will generate Security Label SQL using macro ===== #}
{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{{'\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 %}

View File

@ -0,0 +1,71 @@
{% if (vid and datlastsysoid) or scid %}
SELECT
c.oid,
c.xmin,
c.relname AS name,
description AS comment,
c.reltablespace AS spcoid,
(CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
pg_get_userbyid(c.relowner) AS owner,
description As comment,
pg_get_viewdef(c.oid, true) AS definition,
nsp.nspname AS schema,
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 %}
(SELECT
array_agg(label)
FROM
pg_seclabels sl1
WHERE
sl1.objoid=c.oid AND sl1.objsubid=0) AS labels,
(SELECT
array_agg(provider)
FROM
pg_seclabels sl2
WHERE
sl2.objoid=c.oid AND sl2.objsubid=0) AS providers,
(substring(array_to_string(c.reloptions, ',')
FROM 'security_barrier=([a-z|0-9]*)'))::boolean AS security_barrier
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 %}

View File

@ -0,0 +1,75 @@
{# ============================ Update View ========================= #}
{% import 'macros/security.macros' as SECLABLE %}
{% 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) }}
WITH (security_barrier={{ data.security_barrier|lower if data.security_barrier else o_data.security_barrier|default('false', 'true')|lower }})
AS
{{ def }};
{% else %}
{% if (data.security_barrier is defined and data.security_barrier|lower != o_data.security_barrier|lower) %}
ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
SET (security_barrier={{ data.security_barrier|lower }});
{% endif %}
{% 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 %}
{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
{% endfor %}
{% endif %}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}

View File

@ -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 %}

View File

@ -0,0 +1,38 @@
{# ============================ 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,
aclexplode(relacl) 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 %}

View File

@ -0,0 +1,23 @@
{#============================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) }}{% if (data.security_barrier) %}{{'\r'}}
WITH (
{% if data.security_barrier %} security_barrier={{ data.security_barrier|lower }}{% endif %}{{'\r'}}
){% endif %} 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 %}

View File

@ -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 %}

View File

@ -0,0 +1,7 @@
{# ===== fetch schema name against schema oid ===== #}
SELECT
nspname
FROM
pg_namespace
WHERE
oid = {{ scid }}::oid;

View File

@ -0,0 +1,6 @@
{# ===== Grant Permissions to User Role on Views/Tables ===== #}
{% import 'macros/security.macros' as SECLABLE %}
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
{# ===== We will generate Security Label SQL using macro ===== #}
{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{{'\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 %}

View File

@ -0,0 +1,74 @@
{% if (vid and datlastsysoid) or scid %}
SELECT
c.oid,
c.xmin,
c.relkind,
description AS comment,
(CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
c.relname AS name,
nsp.nspname AS schema,
c.reltablespace AS spcoid,
c.relispopulated AS ispopulated,
pg_get_userbyid(c.relowner) AS owner,
array_to_string(c.relacl::text[], ', ') AS acl,
pg_get_viewdef(c.oid, true) AS definition,
{# ===== Checks if it is system view ===== #}
{% if vid and datlastsysoid %}
CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
{% endif %}
(SELECT
array_agg(label)
FROM
pg_seclabels sl1
WHERE
sl1.objoid=c.oid AND sl1.objsubid=0) AS labels,
(SELECT
array_agg(provider)
FROM
pg_seclabels sl2
WHERE
sl2.objoid=c.oid AND sl2.objsubid=0) AS providers,
(substring(array_to_string(c.reloptions, ',')
FROM 'security_barrier=([a-z|0-9]*)'))::boolean AS security_barrier
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)
LEFT OUTER JOIN pg_class tst ON tst.oid = c.reltoastrelid
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 %}

View File

@ -0,0 +1,75 @@
{# ============================ Update View ========================= #}
{% import 'macros/security.macros' as SECLABLE %}
{% 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) }}
WITH (security_barrier={{ data.security_barrier|lower if data.security_barrier else o_data.security_barrier|default('false', 'true')|lower }})
AS
{{ def }};
{% else %}
{% if (data.security_barrier is defined and data.security_barrier|lower != o_data.security_barrier|lower) %}
ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
SET (security_barrier={{ data.security_barrier|lower }});
{% endif %}
{% 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 %}
{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
{% endfor %}
{% endif %}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}

View File

@ -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 %}

View File

@ -0,0 +1,39 @@
{# ============================ 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,
aclexplode(relacl) 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 %}

View File

@ -0,0 +1,22 @@
{#============================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) }}{% if ((data.check_option and data.check_option.lower() != 'no') or data.security_barrier) %}{{ '\n' }}WITH (
{% if data.check_option and data.check_option.lower() != 'no' %} check_option={{ data.check_option }}{% endif %}{{ ',\r' if data.check_option and data.check_option.lower() != 'no' and data.security_barrier }}{% if data.security_barrier %} security_barrier={{ data.security_barrier|lower }}{% endif %}{{'\r'}}
){% endif %} AS
{{ data.definition.rstrip(';') }};
{% if data.owner and data.m_view is undefined %}
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 %}

View File

@ -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 %}

View File

@ -0,0 +1,7 @@
{# ===== fetch schema name against schema oid ===== #}
SELECT
nspname
FROM
pg_namespace
WHERE
oid = {{ scid }}::oid;

View File

@ -0,0 +1,6 @@
{# ===== Grant Permissions to User Role on Views/Tables ===== #}
{% import 'macros/security.macros' as SECLABLE %}
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
{# ===== We will generate Security Label SQL using macro ===== #}
{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{{'\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 %}

View File

@ -0,0 +1,77 @@
{# ========================== Fetch View Properties ========================= #}
{% if (vid and datlastsysoid) or scid %}
SELECT
c.oid,
c.xmin,
c.relkind,
description AS comment,
(CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
c.relname AS name,
c.reltablespace AS spcoid,
nsp.nspname AS schema,
c.relispopulated AS ispopulated,
pg_get_userbyid(c.relowner) AS owner,
array_to_string(c.relacl::text[], ', ') AS acl,
pg_get_viewdef(c.oid, true) AS definition,
{# ===== Checks if it is system view ===== #}
{% if vid and datlastsysoid %}
CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
{% endif %}
(SELECT
array_agg(label)
FROM
pg_seclabels sl1
WHERE
sl1.objoid=c.oid AND sl1.objsubid=0) AS labels,
(SELECT
array_agg(provider)
FROM
pg_seclabels sl2
WHERE
sl2.objoid=c.oid AND sl2.objsubid=0) AS providers,
substring(array_to_string(c.reloptions, ',')
FROM 'check_option=([a-z]*)') AS check_option,
(substring(array_to_string(c.reloptions, ',')
FROM 'security_barrier=([a-z|0-9]*)'))::boolean AS security_barrier
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)
LEFT OUTER JOIN pg_class tst ON tst.oid = c.reltoastrelid
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 %}

View File

@ -0,0 +1,81 @@
{# ============================ Update View ========================= #}
{% import 'macros/security.macros' as SECLABLE %}
{% 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) }}
WITH (check_option={{ data.check_option|default('no', 'true') if data.check_option else o_data.check_option|default('no', 'true') }}{{', ' }}security_barrier={{ data.security_barrier|lower if data.security_barrier else o_data.security_barrier|default('false', 'true')|lower }})
AS
{{ def }};
{% else %}
{% if (data.security_barrier is defined and data.security_barrier|lower != o_data.security_barrier|lower) %}
ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
SET (security_barrier={{ data.security_barrier|lower }});
{% endif %}
{% if (data.check_option and data.check_option != o_data.check_option and data.check_option != 'no') %}
ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
SET (check_option={{ data.check_option }});
{% elif (data.check_option and data.check_option != o_data.check_option and data.check_option == 'no') %}
ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }} RESET (check_option);
{% endif %}
{% 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 %}
{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
{% endfor %}
{% endif %}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}

View File

@ -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 %}

View File

@ -0,0 +1,39 @@
{# ============================ 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,
aclexplode(relacl) 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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -0,0 +1,7 @@
{# ===== fetch schema name against schema oid ===== #}
SELECT
nspname
FROM
pg_namespace
WHERE
oid = {{ scid }}::oid;

View File

@ -0,0 +1,6 @@
{# ===== Grant Permissions to User Role on Views/Tables ===== #}
{% import 'macros/security.macros' as SECLABLE %}
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
{# ===== We will generate Security Label SQL using macro ===== #}
{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{{'\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 %}

View File

@ -0,0 +1,76 @@
{% if (vid and datlastsysoid) or scid %}
SELECT
c.oid,
c.xmin,
c.relkind,
description AS comment,
(CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
c.relname AS name,
c.reltablespace AS spcoid,
nsp.nspname AS schema,
c.relispopulated AS ispopulated,
pg_get_userbyid(c.relowner) AS owner,
array_to_string(c.relacl::text[], ', ') AS acl,
pg_get_viewdef(c.oid, true) AS definition,
{# ===== Checks if it is system view ===== #}
{% if vid and datlastsysoid %}
CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
{% endif %}
(SELECT
array_agg(label)
FROM
pg_seclabels sl1
WHERE
sl1.objoid=c.oid AND sl1.objsubid=0) AS labels,
(SELECT
array_agg(provider)
FROM
pg_seclabels sl2
WHERE
sl2.objoid=c.oid AND sl2.objsubid=0) AS providers,
substring(array_to_string(c.reloptions, ',')
FROM 'check_option=([a-z]*)') AS check_option,
(substring(array_to_string(c.reloptions, ',')
FROM 'security_barrier=([a-z|0-9]*)'))::boolean AS security_barrier
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)
LEFT OUTER JOIN pg_class tst ON tst.oid = c.reltoastrelid
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 %}

View File

@ -0,0 +1,75 @@
{# ============================ Update View ========================= #}
{% import 'macros/security.macros' as SECLABLE %}
{% 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) }}
WITH (security_barrier={{ data.security_barrier|lower if data.security_barrier else o_data.security_barrier|default('false', 'true')|lower }})
AS
{{ def }};
{% else %}
{% if (data.security_barrier is defined and data.security_barrier|lower != o_data.security_barrier|lower) %}
ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
SET (security_barrier={{ data.security_barrier|lower }});
{% endif %}
{% 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 %}
{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
{% endfor %}
{% endif %}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}

View File

@ -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 %}

View File

@ -0,0 +1,52 @@
{# ============================ 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
aclexplode(relacl) AS d
FROM
pg_class cl1
WHERE
cl1.oid = {{ vid }}
) a
) d
) d
LEFT JOIN pg_catalog.pg_roles g ON (d.grantor = g.oid)
LEFT JOIN pg_catalog.pg_roles gt ON (d.grantee = gt.oid)
GROUP BY
g.rolname,
gt.rolname
{% endif %}

View File

@ -0,0 +1,23 @@
{#============================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) }}{% if (data.security_barrier) %}{{'\r'}}
WITH (
{% if data.security_barrier %} security_barrier={{ data.security_barrier|lower }}{% endif %}{{'\r'}}
){% endif %} 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 %}

View File

@ -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 %}

View File

@ -0,0 +1,7 @@
{# ===== fetch schema name against schema oid ===== #}
SELECT
nspname
FROM
pg_namespace
WHERE
oid = {{ scid }}::oid;

View File

@ -0,0 +1,6 @@
{# ===== Grant Permissions to User Role on Views/Tables ===== #}
{% import 'macros/security.macros' as SECLABLE %}
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
{# ===== We will generate Security Label SQL using macro ===== #}
{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{{'\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 %}

View File

@ -0,0 +1,70 @@
{% if (vid and datlastsysoid) or scid %}
SELECT
c.oid,
c.xmin,
c.relname AS name,
c.reltablespace AS spcoid,
(CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
pg_get_userbyid(c.relowner) AS owner,
description As comment,
pg_get_viewdef(c.oid, true) AS definition,
nsp.nspname AS schema,
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 %}
(SELECT
array_agg(label)
FROM
pg_seclabels sl1
WHERE
sl1.objoid=c.oid AND sl1.objsubid=0) AS labels,
(SELECT
array_agg(provider)
FROM
pg_seclabels sl2
WHERE
sl2.objoid=c.oid AND sl2.objsubid=0) AS providers,
(substring(array_to_string(c.reloptions, ',')
FROM 'security_barrier=([a-z|0-9]*)'))::boolean AS security_barrier
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 %}

View File

@ -0,0 +1,75 @@
{# ============================ Update View ========================= #}
{% import 'macros/security.macros' as SECLABLE %}
{% 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) }}
WITH (security_barrier={{ data.security_barrier|lower if data.security_barrier else o_data.security_barrier|default('false', 'true')|lower }})
AS
{{ def }};
{% else %}
{% if (data.security_barrier is defined and data.security_barrier|lower != o_data.security_barrier|lower) %}
ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
SET (security_barrier={{ data.security_barrier|lower }});
{% endif %}
{% 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 %}
{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
{% endfor %}
{% endif %}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}

View File

@ -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 %}

View File

@ -0,0 +1,38 @@
{# ============================ 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,
aclexplode(relacl) 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 %}

View File

@ -0,0 +1,23 @@
{#============================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) }}{% if (data.security_barrier) %}{{'\r'}}
WITH (
{% if data.security_barrier %} security_barrier={{ data.security_barrier|lower }}{% endif %}{{'\r'}}
){% endif %} 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 %}

View File

@ -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 %}

View File

@ -0,0 +1,7 @@
{# ===== fetch schema name against schema oid ===== #}
SELECT
nspname
FROM
pg_namespace
WHERE
oid = {{ scid }}::oid;

View File

@ -0,0 +1,6 @@
{# ===== Grant Permissions to User Role on Views/Tables ===== #}
{% import 'macros/security.macros' as SECLABLE %}
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
{# ===== We will generate Security Label SQL using macro ===== #}
{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{{'\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 %}

View File

@ -0,0 +1,74 @@
{% if (vid and datlastsysoid) or scid %}
SELECT
c.oid,
c.xmin,
c.relkind,
description AS comment,
(CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
c.relname AS name,
nsp.nspname AS schema,
c.reltablespace AS spcoid,
c.relispopulated AS ispopulated,
pg_get_userbyid(c.relowner) AS owner,
array_to_string(c.relacl::text[], ', ') AS acl,
pg_get_viewdef(c.oid, true) AS definition,
{# ===== Checks if it is system view ===== #}
{% if vid and datlastsysoid %}
CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
{% endif %}
(SELECT
array_agg(label)
FROM
pg_seclabels sl1
WHERE
sl1.objoid=c.oid AND sl1.objsubid=0) AS labels,
(SELECT
array_agg(provider)
FROM
pg_seclabels sl2
WHERE
sl2.objoid=c.oid AND sl2.objsubid=0) AS providers,
(substring(array_to_string(c.reloptions, ',')
FROM 'security_barrier=([a-z|0-9]*)'))::boolean AS security_barrier
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)
LEFT OUTER JOIN pg_class tst ON tst.oid = c.reltoastrelid
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 %}

View File

@ -0,0 +1,75 @@
{# ============================ Update View ========================= #}
{% import 'macros/security.macros' as SECLABLE %}
{% 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) }}
WITH (security_barrier={{ data.security_barrier|lower if data.security_barrier else o_data.security_barrier|default('false', 'true')|lower }})
AS
{{ def }};
{% else %}
{% if (data.security_barrier is defined and data.security_barrier|lower != o_data.security_barrier|lower) %}
ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
SET (security_barrier={{ data.security_barrier|lower }});
{% endif %}
{% 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 %}
{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
{% endfor %}
{% endif %}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}

View File

@ -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 %}

View File

@ -0,0 +1,39 @@
{# ============================ 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,
aclexplode(relacl) 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 %}

View File

@ -0,0 +1,22 @@
{#============================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) }}{% if ((data.check_option and data.check_option.lower() != 'no') or data.security_barrier) %}{{ '\n' }}WITH (
{% if data.check_option and data.check_option.lower() != 'no' %} check_option={{ data.check_option }}{% endif %}{{ ',\r' if data.check_option and data.check_option.lower() != 'no' and data.security_barrier }}{% if data.security_barrier %} security_barrier={{ data.security_barrier|lower }}{% endif %}{{'\r'}}
){% endif %} AS
{{ data.definition.rstrip(';') }};
{% if data.owner and data.m_view is undefined %}
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 %}

View File

@ -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 %}

View File

@ -0,0 +1,7 @@
{# ===== fetch schema name against schema oid ===== #}
SELECT
nspname
FROM
pg_namespace
WHERE
oid = {{ scid }}::oid;

View File

@ -0,0 +1,6 @@
{# ===== Grant Permissions to User Role on Views/Tables ===== #}
{% import 'macros/security.macros' as SECLABLE %}
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
{# ===== We will generate Security Label SQL using macro ===== #}
{% if data.seclabels %}{% for r in data.seclabels %}{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}{{'\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 %}

View File

@ -0,0 +1,77 @@
{# ========================== Fetch View Properties ========================= #}
{% if (vid and datlastsysoid) or scid %}
SELECT
c.oid,
c.xmin,
c.relkind,
description AS comment,
(CASE WHEN length(spc.spcname) > 0 THEN spc.spcname ELSE 'pg_default' END) as spcname,
c.relname AS name,
c.reltablespace AS spcoid,
nsp.nspname AS schema,
c.relispopulated AS ispopulated,
pg_get_userbyid(c.relowner) AS owner,
array_to_string(c.relacl::text[], ', ') AS acl,
pg_get_viewdef(c.oid, true) AS definition,
{# ===== Checks if it is system view ===== #}
{% if vid and datlastsysoid %}
CASE WHEN {{vid}} <= {{datlastsysoid}} THEN True ELSE False END AS system_view,
{% endif %}
(SELECT
array_agg(label)
FROM
pg_seclabels sl1
WHERE
sl1.objoid=c.oid AND sl1.objsubid=0) AS labels,
(SELECT
array_agg(provider)
FROM
pg_seclabels sl2
WHERE
sl2.objoid=c.oid AND sl2.objsubid=0) AS providers,
substring(array_to_string(c.reloptions, ',')
FROM 'check_option=([a-z]*)') AS check_option,
(substring(array_to_string(c.reloptions, ',')
FROM 'security_barrier=([a-z|0-9]*)'))::boolean AS security_barrier
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)
LEFT OUTER JOIN pg_class tst ON tst.oid = c.reltoastrelid
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 %}

View File

@ -0,0 +1,81 @@
{# ============================ Update View ========================= #}
{% import 'macros/security.macros' as SECLABLE %}
{% 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) }}
WITH (check_option={{ data.check_option|default('no', 'true') if data.check_option else o_data.check_option|default('no', 'true') }}{{', ' }}security_barrier={{ data.security_barrier|lower if data.security_barrier else o_data.security_barrier|default('false', 'true')|lower }})
AS
{{ def }};
{% else %}
{% if (data.security_barrier is defined and data.security_barrier|lower != o_data.security_barrier|lower) %}
ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
SET (security_barrier={{ data.security_barrier|lower }});
{% endif %}
{% if (data.check_option and data.check_option != o_data.check_option and data.check_option != 'no') %}
ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }}
SET (check_option={{ data.check_option }});
{% elif (data.check_option and data.check_option != o_data.check_option and data.check_option == 'no') %}
ALTER VIEW {{ conn|qtIdent(view_schema, view_name) }} RESET (check_option);
{% endif %}
{% 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 %}
{{ SECLABLE.DROP(conn, 'VIEW', data.name, r.provider) }}
{% endfor %}
{% endif %}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABLE.APPLY(conn, 'VIEW', data.name, r.provider, r.security_label) }}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}

View File

@ -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 %}

View File

@ -1665,13 +1665,18 @@
(_.isUndefined(s.min_version) ? true :
(server_info.version >= s.min_version)) &&
(_.isUndefined(s.max_version) ? true :
(server_info.version <= s.max_version))));
(server_info.version <= s.max_version)))),
visible = true;
if (s.mode && _.isObject(s.mode))
visible = (_.indexOf(s.mode, mode) > -1);
if (visible)
visible = evalASFunc(s.visible);
groupInfo[s.id] = {
label: s.label || s.id,
version_compatible: ver_in_limit,
visible: !s.mode || (
s && s.mode && _.isObject(s.mode) &&
_.indexOf(s.mode, mode) != -1) && evalASFunc(s.visible) || true
visible: visible
};
return;
}
@ -1768,9 +1773,13 @@
// Create an array from the dictionary with proper required
// structure.
_.each(groups, function(val, key) {
fields.push(_.extend({
label: key, fields: val
}, (groupInfo[key] || {version_compatible: true, visible: true})));
fields.push(
_.extend(
_.defaults(
groupInfo[key] || {label: key},
{version_compatible: true, visible: true}
), {fields: val})
);
});
}
@ -2080,8 +2089,10 @@
'</div>',
'</div>'
].join("\n")),
events: {
"click .select_item": "onSelect",
events: function() {
return _.extend({}, Backform.InputControl.prototype.events, {
"click .select_item": "onSelect",
});
},
onSelect: function(e) {
var dialog_type = this.field.get('dialog_type');