mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Implementation of View & Materialized View
This commit is contained in:
parent
4dbe058832
commit
ecde42cbed
File diff suppressed because it is too large
Load Diff
@ -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 |
@ -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%;
|
||||
}
|
@ -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'];
|
||||
});
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -0,0 +1,7 @@
|
||||
{# ===== fetch schema name =====#}
|
||||
SELECT
|
||||
nspname
|
||||
FROM
|
||||
pg_namespace
|
||||
WHERE
|
||||
oid = {{ scid }}::oid;
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -0,0 +1,7 @@
|
||||
{# ===== fetch schema name =====#}
|
||||
SELECT
|
||||
nspname
|
||||
FROM
|
||||
pg_namespace
|
||||
WHERE
|
||||
oid = {{ scid }}::oid;
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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;
|
||||
}
|
@ -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'];
|
||||
});
|
@ -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 %}
|
@ -0,0 +1,20 @@
|
||||
{#============================Create new view=========================#}
|
||||
{% if display_comments %}
|
||||
-- View: {{ conn|qtIdent(data.schema, data.name) }}
|
||||
|
||||
-- DROP VIEW {{ conn|qtIdent(data.schema, data.name) }};
|
||||
|
||||
{% endif %}
|
||||
{% if data.name and data.schema and data.definition %}
|
||||
CREATE OR REPLACE VIEW {{ conn|qtIdent(data.schema, data.name) }} AS
|
||||
{{ data.definition.rstrip(';') }};
|
||||
{% if data.owner %}
|
||||
|
||||
ALTER TABLE {{ conn|qtIdent(data.schema, data.name) }}
|
||||
OWNER TO {{ conn|qtIdent(data.owner) }};
|
||||
{% endif %}
|
||||
{% if data.comment %}
|
||||
COMMENT ON VIEW {{ conn|qtIdent(data.schema, data.name) }}
|
||||
IS {{ data.comment|qtLiteral }};
|
||||
{% endif %}
|
||||
{% endif %}
|
@ -0,0 +1,13 @@
|
||||
{# ====================== Drop/Cascade view by name ===================== #}
|
||||
{% if vid %}
|
||||
SELECT
|
||||
c.relname AS name,
|
||||
nsp.nspname
|
||||
FROM
|
||||
pg_class c
|
||||
LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
|
||||
WHERE
|
||||
c.relfilenode = {{ vid }};
|
||||
{% elif (name and nspname) %}
|
||||
DROP VIEW {{ conn|qtIdent(nspname, name) }} {% if cascade %} CASCADE {% endif %};
|
||||
{% endif %}
|
@ -0,0 +1,7 @@
|
||||
{# ===== fetch schema name against schema oid ===== #}
|
||||
SELECT
|
||||
nspname
|
||||
FROM
|
||||
pg_namespace
|
||||
WHERE
|
||||
oid = {{ scid }}::oid;
|
@ -0,0 +1,6 @@
|
||||
{# ===== Grant Permissions to User Role on Views/Tables ===== #}
|
||||
{% import 'macros/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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -0,0 +1,13 @@
|
||||
{# ====================== Drop/Cascade view by name ===================== #}
|
||||
{% if vid %}
|
||||
SELECT
|
||||
c.relname AS name,
|
||||
nsp.nspname
|
||||
FROM
|
||||
pg_class c
|
||||
LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
|
||||
WHERE
|
||||
c.relfilenode = {{ vid }};
|
||||
{% elif (name and nspname) %}
|
||||
DROP VIEW {{ conn|qtIdent(nspname, name) }} {% if cascade %} CASCADE {% endif %};
|
||||
{% endif %}
|
@ -0,0 +1,7 @@
|
||||
{# ===== fetch schema name against schema oid ===== #}
|
||||
SELECT
|
||||
nspname
|
||||
FROM
|
||||
pg_namespace
|
||||
WHERE
|
||||
oid = {{ scid }}::oid;
|
@ -0,0 +1,6 @@
|
||||
{# ===== Grant Permissions to User Role on Views/Tables ===== #}
|
||||
{% import 'macros/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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -0,0 +1,13 @@
|
||||
{# ====================== Drop/Cascade view by name ===================== #}
|
||||
{% if vid %}
|
||||
SELECT
|
||||
c.relname AS name,
|
||||
nsp.nspname
|
||||
FROM
|
||||
pg_class c
|
||||
LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
|
||||
WHERE
|
||||
c.relfilenode = {{ vid }};
|
||||
{% elif (name and nspname) %}
|
||||
DROP VIEW {{ conn|qtIdent(nspname, name) }} {% if cascade %} CASCADE {% endif %};
|
||||
{% endif %}
|
@ -0,0 +1,7 @@
|
||||
{# ===== fetch schema name against schema oid ===== #}
|
||||
SELECT
|
||||
nspname
|
||||
FROM
|
||||
pg_namespace
|
||||
WHERE
|
||||
oid = {{ scid }}::oid;
|
@ -0,0 +1,6 @@
|
||||
{# ===== Grant Permissions to User Role on Views/Tables ===== #}
|
||||
{% import 'macros/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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -0,0 +1,13 @@
|
||||
{# ====================== Drop/Cascade view by name ===================== #}
|
||||
{% if vid %}
|
||||
SELECT
|
||||
c.relname AS name,
|
||||
nsp.nspname
|
||||
FROM
|
||||
pg_class c
|
||||
LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
|
||||
WHERE
|
||||
c.relfilenode = {{ vid }};
|
||||
{% elif (name and nspname) %}
|
||||
DROP VIEW {{ conn|qtIdent(nspname, name) }} {% if cascade %} CASCADE {% endif %};
|
||||
{% endif %}
|
@ -0,0 +1,7 @@
|
||||
{# ===== fetch schema name against schema oid ===== #}
|
||||
SELECT
|
||||
nspname
|
||||
FROM
|
||||
pg_namespace
|
||||
WHERE
|
||||
oid = {{ scid }}::oid;
|
@ -0,0 +1,6 @@
|
||||
{# ===== Grant Permissions to User Role on Views/Tables ===== #}
|
||||
{% import 'macros/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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -0,0 +1,20 @@
|
||||
{#============================Create new view=========================#}
|
||||
{% if display_comments %}
|
||||
-- View: {{ conn|qtIdent(data.schema, data.name) }}
|
||||
|
||||
-- DROP VIEW {{ conn|qtIdent(data.schema, data.name) }};
|
||||
|
||||
{% endif %}
|
||||
{% if data.name and data.schema and data.definition %}
|
||||
CREATE OR REPLACE VIEW {{ conn|qtIdent(data.schema, data.name) }} AS
|
||||
{{ data.definition.rstrip(';') }};
|
||||
{% if data.owner %}
|
||||
|
||||
ALTER TABLE {{ conn|qtIdent(data.schema, data.name) }}
|
||||
OWNER TO {{ conn|qtIdent(data.owner) }};
|
||||
{% endif %}
|
||||
{% if data.comment %}
|
||||
COMMENT ON VIEW {{ conn|qtIdent(data.schema, data.name) }}
|
||||
IS {{ data.comment|qtLiteral }};
|
||||
{% endif %}
|
||||
{% endif %}
|
@ -0,0 +1,13 @@
|
||||
{# ====================== Drop/Cascade view by name ===================== #}
|
||||
{% if vid %}
|
||||
SELECT
|
||||
c.relname AS name,
|
||||
nsp.nspname
|
||||
FROM
|
||||
pg_class c
|
||||
LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
|
||||
WHERE
|
||||
c.relfilenode = {{ vid }};
|
||||
{% elif (name and nspname) %}
|
||||
DROP VIEW {{ conn|qtIdent(nspname, name) }} {% if cascade %} CASCADE {% endif %};
|
||||
{% endif %}
|
@ -0,0 +1,7 @@
|
||||
{# ===== fetch schema name against schema oid ===== #}
|
||||
SELECT
|
||||
nspname
|
||||
FROM
|
||||
pg_namespace
|
||||
WHERE
|
||||
oid = {{ scid }}::oid;
|
@ -0,0 +1,6 @@
|
||||
{# ===== Grant Permissions to User Role on Views/Tables ===== #}
|
||||
{% import 'macros/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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -0,0 +1,13 @@
|
||||
{# ====================== Drop/Cascade view by name ===================== #}
|
||||
{% if vid %}
|
||||
SELECT
|
||||
c.relname AS name,
|
||||
nsp.nspname
|
||||
FROM
|
||||
pg_class c
|
||||
LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
|
||||
WHERE
|
||||
c.relfilenode = {{ vid }};
|
||||
{% elif (name and nspname) %}
|
||||
DROP VIEW {{ conn|qtIdent(nspname, name) }} {% if cascade %} CASCADE {% endif %};
|
||||
{% endif %}
|
@ -0,0 +1,7 @@
|
||||
{# ===== fetch schema name against schema oid ===== #}
|
||||
SELECT
|
||||
nspname
|
||||
FROM
|
||||
pg_namespace
|
||||
WHERE
|
||||
oid = {{ scid }}::oid;
|
@ -0,0 +1,6 @@
|
||||
{# ===== Grant Permissions to User Role on Views/Tables ===== #}
|
||||
{% import 'macros/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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -0,0 +1,13 @@
|
||||
{# ====================== Drop/Cascade view by name ===================== #}
|
||||
{% if vid %}
|
||||
SELECT
|
||||
c.relname AS name,
|
||||
nsp.nspname
|
||||
FROM
|
||||
pg_class c
|
||||
LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
|
||||
WHERE
|
||||
c.relfilenode = {{ vid }};
|
||||
{% elif (name and nspname) %}
|
||||
DROP VIEW {{ conn|qtIdent(nspname, name) }} {% if cascade %} CASCADE {% endif %};
|
||||
{% endif %}
|
@ -0,0 +1,7 @@
|
||||
{# ===== fetch schema name against schema oid ===== #}
|
||||
SELECT
|
||||
nspname
|
||||
FROM
|
||||
pg_namespace
|
||||
WHERE
|
||||
oid = {{ scid }}::oid;
|
@ -0,0 +1,6 @@
|
||||
{# ===== Grant Permissions to User Role on Views/Tables ===== #}
|
||||
{% import 'macros/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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -0,0 +1,13 @@
|
||||
{# ====================== Drop/Cascade view by name ===================== #}
|
||||
{% if vid %}
|
||||
SELECT
|
||||
c.relname AS name,
|
||||
nsp.nspname
|
||||
FROM
|
||||
pg_class c
|
||||
LEFT JOIN pg_namespace nsp ON c.relnamespace = nsp.oid
|
||||
WHERE
|
||||
c.relfilenode = {{ vid }};
|
||||
{% elif (name and nspname) %}
|
||||
DROP VIEW {{ conn|qtIdent(nspname, name) }} {% if cascade %} CASCADE {% endif %};
|
||||
{% endif %}
|
@ -0,0 +1,7 @@
|
||||
{# ===== fetch schema name against schema oid ===== #}
|
||||
SELECT
|
||||
nspname
|
||||
FROM
|
||||
pg_namespace
|
||||
WHERE
|
||||
oid = {{ scid }}::oid;
|
@ -0,0 +1,6 @@
|
||||
{# ===== Grant Permissions to User Role on Views/Tables ===== #}
|
||||
{% import 'macros/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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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');
|
||||
|
Loading…
Reference in New Issue
Block a user