1. Added USING method while creating the table. #6378

2. Added USING method while creating the materialized view. #6400
This commit is contained in:
Pravesh Sharma 2023-09-06 11:22:30 +05:30 committed by GitHub
parent 095e11247d
commit a43b70e360
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 3064 additions and 58 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 94 KiB

View File

@ -31,17 +31,6 @@ Use the fields in the *General* tab to identify the materialized view:
Click the *Definition* tab to continue.
.. image:: images/materialized_view_definition.png
:alt: Materialized view dialog definition tab
:align: center
Use the text editor field in the *Definition* tab to provide the query that will
populate the materialized view. Please note that updating the definition of existing
materialized view would result in loss of Parameter(Table, Toast), Security(Privileges & Security labels),
Indexes and other dependent objects.
Click the *Storage* tab to continue.
.. image:: images/materialized_view_storage.png
:alt: Materialized view dialog storage tab
:align: center
@ -52,10 +41,24 @@ Use the fields in the *Storage* tab to maintain the materialized view:
cannot be queried until you invoke REFRESH MATERIALIZED VIEW.
* Use the drop-down listbox next to *Tablespace* to select a location for the
materialized view.
* Use the drop-down list box next to Access Method to specify the table access method to use to store the contents
for the new materialized view; the method needs to be an access method of type TABLE. This field is optional.
This option is available from v12 and above.
* Use the *Fill Factor* field to specify a fill factor for the materialized
view. The fill factor for a table is a percentage between 10 and 100. 100
(complete packing) is the default.
Click the *Code* tab to continue.
.. image:: images/materialized_view_code.png
:alt: Materialized view dialog definition tab
:align: center
Use the text editor field in the *Code* tab to provide the query that will
populate the materialized view. Please note that updating the definition of existing
materialized view would result in loss of Parameter(Table, Toast), Security(Privileges & Security labels),
Indexes and other dependent objects.
Click the *Parameter* tab to continue.
.. image:: images/materialized_view_parameter.png

View File

@ -394,6 +394,9 @@ Use the fields in the *Advanced* tab to define advanced features for the table:
* Use the drop-down listbox next to *Of type* to copy the table structure from
the specified composite type. Please note that a typed table will be dropped
if the type is dropped (with DROP TYPE ... CASCADE).
* Use the drop-down list box next to Access Method to specify the table access method to use to store
the contents for the new table; the method needs to be an access method of type TABLE. This field is optional.
This option is available from v12 and above.
* Use the *Fill Factor* field to specify a fill factor for the table. The fill
factor for a table is a percentage between 10 and 100. 100 (complete packing)
is the default.

View File

@ -295,6 +295,7 @@ class TableView(BaseTableView, DataTypeReader, SchemaDiffTableCompare):
'get_toast_table_vacuum': [{}, {'get': 'get_toast_table_vacuum'}],
'all_tables': [{}, {'get': 'get_all_tables'}],
'get_access_methods': [{}, {'get': 'get_access_methods'}],
'get_table_access_methods': [{}, {'get': 'get_table_access_methods'}],
'get_oper_class': [{}, {'get': 'get_oper_class'}],
'get_operator': [{}, {'get': 'get_operator'}],
'get_attach_tables': [
@ -538,6 +539,28 @@ class TableView(BaseTableView, DataTypeReader, SchemaDiffTableCompare):
status=200
)
@BaseTableView.check_precondition
def get_table_access_methods(self, gid, sid, did, scid, tid=None):
"""
This function returns access methods for table.
Args:
gid: Server Group ID
sid: Server ID
did: Database ID
scid: Schema ID
tid: Table ID
Returns:
Returns list of access methods for table
"""
res = BaseTableView.get_access_methods(self)
return make_json_response(
data=res,
status=200
)
@BaseTableView.check_precondition
def get_oper_class(self, gid, sid, did, scid, tid=None):
"""

View File

@ -186,31 +186,6 @@
"expected_sql_file": "create_btree_expr_asc_null_last.sql",
"expected_msql_file": "create_btree_expr_asc_null_last_msql.sql"
},
{
"type": "alter",
"name": "Alter index statistics of expression",
"endpoint": "NODE-index.obj_id",
"sql_endpoint": "NODE-index.sql_id",
"msql_endpoint": "NODE-index.msql_id",
"data": {
"name": "Idx3_$%{}[]()&*^!@\"'`\\/#",
"columns":{
"changed": [{
"is_exp": true,
"col_num": 2,
"colname":"lower(name)",
"collspcname":"pg_catalog.\"POSIX\"",
"op_class":"text_pattern_ops",
"sort_order":false,
"nulls":false,
"is_sort_nulls_applicable":true,
"statistics": 1000
}]
}
},
"expected_sql_file": "alter_expr_statistics.sql",
"expected_msql_file": "alter_expr_statistics_msql.sql"
},
{
"type": "delete",
"name": "Drop index",

View File

@ -545,6 +545,8 @@
"is_positive_test": true,
"update_statistics": true,
"inventory_data": {
"server_min_version": 110000,
"skip_msg": "Update statistics is not supported below PPAS/PG 11.0"
},
"test_data": {
"columns": "PLACE_HOLDER"

View File

@ -23,6 +23,7 @@ from pgadmin.utils.route import BaseTestGenerator
from regression import parent_node_dict
from regression.python_test_utils import test_utils as utils
from . import utils as indexes_utils
from pgadmin.utils import server_utils
class IndexesUpdateTestCase(BaseTestGenerator):
@ -36,6 +37,16 @@ class IndexesUpdateTestCase(BaseTestGenerator):
schema_info = parent_node_dict["schema"][-1]
self.server_id = schema_info["server_id"]
self.db_id = schema_info["db_id"]
if "server_min_version" in self.inventory_data:
server_con = server_utils.connect_server(self, self.server_id)
if not server_con["info"] == "Server connected.":
raise Exception("Could not connect to server to add "
"partitioned table.")
if server_con["data"]["version"] < \
self.inventory_data["server_min_version"]:
self.skipTest(self.inventory_data["skip_msg"])
db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
self.server_id, self.db_id)
if not db_con['data']["connected"]:

View File

@ -211,7 +211,8 @@ class PartitionsView(BaseTableView, DataTypeReader, SchemaDiffObjectCompare):
'msql': [{'get': 'msql'}, {}],
'detach': [{'put': 'detach'}],
'truncate': [{'put': 'truncate'}],
'set_trigger': [{'put': 'enable_disable_triggers'}]
'set_trigger': [{'put': 'enable_disable_triggers'}],
'get_table_access_methods': [{}, {'get': 'get_table_access_methods'}],
})
# Schema Diff: Keys to ignore while comparing
@ -865,6 +866,29 @@ class PartitionsView(BaseTableView, DataTypeReader, SchemaDiffObjectCompare):
return diff + '\n'
@BaseTableView.check_precondition
def get_table_access_methods(self, gid, sid, did, scid, tid, ptid=None):
"""
This function returns access methods for table.
Args:
gid: Server Group ID
sid: Server ID
did: Database ID
scid: Schema ID
tid: Table ID
ptid: Partition Table ID
Returns:
Returns list of access methods for partition table
"""
res = BaseTableView.get_access_methods(self)
return make_json_response(
data=res,
status=200
)
SchemaDiffRegistry(blueprint.node_type, PartitionsView, 'table')
PartitionsView.register_node_view(blueprint)

View File

@ -40,6 +40,7 @@ export function getNodePartitionTableSchema(treeNodeInfo, itemNodeData, pgBrowse
coll_inherits: ()=>getNodeAjaxOptions('get_inherits', partNode, treeNodeInfo, itemNodeData),
typname: ()=>getNodeAjaxOptions('get_oftype', partNode, treeNodeInfo, itemNodeData),
like_relation: ()=>getNodeAjaxOptions('get_relations', partNode, treeNodeInfo, itemNodeData),
table_amname_list: ()=>getNodeAjaxOptions('get_table_access_methods', partNode, treeNodeInfo, itemNodeData),
},
treeNodeInfo,
{
@ -110,6 +111,7 @@ export default class PartitionTableSchema extends BaseUISchema {
partition_type: 'range',
is_partitioned: false,
partition_value: undefined,
amname: undefined,
...initValues,
});
@ -121,7 +123,7 @@ export default class PartitionTableSchema extends BaseUISchema {
this.getAttachTables = getAttachTables;
this.partitionKeysObj = new PartitionKeysSchema([], getCollations, getOperatorClass);
this.partitionsObj = new PartitionsSchema(this.nodeInfo, getCollations, getOperatorClass, getAttachTables);
this.partitionsObj = new PartitionsSchema(this.nodeInfo, getCollations, getOperatorClass, getAttachTables, fieldOptions.table_amname_list);
this.constraintsObj = this.schemas.constraints();
}
@ -229,6 +231,23 @@ export default class PartitionTableSchema extends BaseUISchema {
mode: ['create', 'edit'], group: 'advanced', min_version: 90600,
disabled: obj.isPartitioned,
},
{
id: 'amname', label: gettext('Access Method'), group: 'advanced',
type: (state)=>{
return {
type: 'select', options: this.fieldOptions.table_amname_list,
controlProps: {
allowClear: obj.isNew(state) ? true : false,
}
};
}, mode: ['create', 'properties', 'edit'], min_version: 120000,
disabled: (state) => {
if (obj.getServerVersion() < 150000 && !obj.isNew(state)) {
return true;
}
return obj.isPartitioned(state);
},
},
{
id: 'relhasoids', label: gettext('Has OIDs?'), cell: 'switch',
type: 'switch', mode: ['properties', 'create', 'edit'],

View File

@ -113,7 +113,7 @@ export class PartitionKeysSchema extends BaseUISchema {
}
}
export class PartitionsSchema extends BaseUISchema {
constructor(nodeInfo, getCollations, getOperatorClass, getAttachTables=()=>[]) {
constructor(nodeInfo, getCollations, getOperatorClass, getAttachTables=()=>[], table_amname_list) {
super({
oid: undefined,
is_attach: false,
@ -126,11 +126,13 @@ export class PartitionsSchema extends BaseUISchema {
values_remainder: undefined,
is_sub_partitioned: false,
sub_partition_type: 'range',
amname: undefined,
});
this.subPartitionsObj = new PartitionKeysSchema([], getCollations, getOperatorClass);
this.getAttachTables = getAttachTables;
this.nodeInfo = nodeInfo;
this.table_amname_list = table_amname_list;
}
changeColumnOptions(columns) {
@ -198,6 +200,27 @@ export class PartitionsSchema extends BaseUISchema {
readonly: function(state) {
return !obj.isNew(state);
}, noEmpty: true,
},{
id: 'amname', label: gettext('Access Method'), deps: ['is_sub_partitioned'], cell: 'select',
type: (state)=>{
return {
type: 'select', options: this.table_amname_list,
controlProps: {
allowClear: obj.isNew(state) ? true : false,
}
};
}, min_version: 120000, disabled: state => {
if (obj.getServerVersion() < 150000 && !obj.isNew(state)) {
return true;
}
return state.is_sub_partitioned;
}, depChange: state => {
if (state.is_sub_partitioned) {
return {
amname: undefined
};
}
},
},{
id: 'is_default', label: gettext('Default'), type: 'switch', cell:'switch',
width: 55, disableResizing: true, min_version: 110000,

View File

@ -45,6 +45,7 @@ export function getNodeTableSchema(treeNodeInfo, itemNodeData, pgBrowser) {
coll_inherits: ()=>getNodeAjaxOptions('get_inherits', tableNode, treeNodeInfo, itemNodeData),
typname: ()=>getNodeAjaxOptions('get_oftype', tableNode, treeNodeInfo, itemNodeData),
like_relation: ()=>getNodeAjaxOptions('get_relations', tableNode, treeNodeInfo, itemNodeData),
table_amname_list: ()=>getNodeAjaxOptions('get_table_access_methods', tableNode, treeNodeInfo, itemNodeData),
},
treeNodeInfo,
{
@ -343,6 +344,7 @@ export default class TableSchema extends BaseUISchema {
partition_type: 'range',
is_partitioned: false,
columns: [],
amname: undefined,
...initValues,
});
@ -352,7 +354,7 @@ export default class TableSchema extends BaseUISchema {
this.nodeInfo = nodeInfo;
this.getColumns = getColumns;
this.partitionsObj = new PartitionsSchema(this.nodeInfo, getCollations, getOperatorClass, getAttachTables);
this.partitionsObj = new PartitionsSchema(this.nodeInfo, getCollations, getOperatorClass, getAttachTables, fieldOptions.table_amname_list);
this.constraintsObj = this.schemas.constraints && this.schemas.constraints() || {};
this.columnsSchema = this.schemas.columns && this.schemas.columns() || {};
this.vacuumSettingsSchema = this.schemas.vacuum_settings && this.schemas.vacuum_settings() || {};
@ -760,6 +762,29 @@ export default class TableSchema extends BaseUISchema {
}
},
},
{
id: 'amname', label: gettext('Access Method'), group: 'advanced',
deps:['is_partitioned'], type: (state)=>{
return {
type: 'select', options: this.fieldOptions.table_amname_list,
controlProps: {
allowClear: obj.isNew(state) ? true : false,
}
};
}, mode: ['create', 'properties', 'edit'], min_version: 120000,
disabled: (state) => {
if (obj.getServerVersion() < 150000 && !obj.isNew(state)) {
return true;
}
return obj.isPartitioned(state);
}, depChange: state => {
if (state.is_partitioned) {
return {
amname: undefined
};
}
},
},
{
id: 'fillfactor', label: gettext('Fill factor'), type: 'int',
mode: ['create', 'edit'], min: 10, max: 100,

View File

@ -13,7 +13,7 @@ FIRST{% else %}LAST{% endif %}{% endif %}{% endif %}{% endfor %})
FIRST{% else %}LAST{% endif %}{% endif %}{% endfor %})
{% endif %}
{% if data.fillfactor %}
WITH (FILLFACTOR={{data.fillfactor}})
WITH (fillfactor={{data.fillfactor}})
{% endif %}{% if data.spcname %}
TABLESPACE {{conn|qtIdent(data.spcname)}}{% endif %}{% if data.indconstraint %}

View File

@ -0,0 +1,74 @@
{% import 'tables/sql/macros/constraints.macro' as CONSTRAINTS %}
{#===========================================#}
{#====== MAIN TABLE TEMPLATE STARTS HERE ======#}
{#===========================================#}
{### CREATE TABLE STATEMENT FOR partitions ###}
CREATE {% if data.relpersistence %}UNLOGGED {% endif %}TABLE{% if add_not_exists_clause %} IF NOT EXISTS{% endif %} {{conn|qtIdent(data.schema, data.name)}}{% if data.relispartition is defined and data.relispartition %} PARTITION OF {{conn|qtIdent(data.parent_schema, data.partitioned_table_name)}}{% endif %}
{# Macro to render for constraints #}
{% if data.primary_key|length > 0 or data.unique_constraint|length > 0 or data.foreign_key|length > 0 or data.check_constraint|length > 0 or data.exclude_constraint|length > 0 %}
( {% endif %}
{% if data.primary_key|length > 0 %}{{CONSTRAINTS.PRIMARY_KEY(conn, data.primary_key[0])}}{% endif %}{% if data.unique_constraint|length > 0 %}{% if data.primary_key|length > 0 %},{% endif %}
{{CONSTRAINTS.UNIQUE(conn, data.unique_constraint)}}{% endif %}{% if data.foreign_key|length > 0 %}{% if data.primary_key|length > 0 or data.unique_constraint|length > 0 %},{% endif %}
{{CONSTRAINTS.FOREIGN_KEY(conn, data.foreign_key)}}{% endif %}{% if data.check_constraint|length > 0 %}{% if data.primary_key|length > 0 or data.unique_constraint|length > 0 or data.foreign_key|length > 0 %},{% endif %}
{{CONSTRAINTS.CHECK(conn, data.check_constraint)}}{% endif %}{% if data.exclude_constraint|length > 0 %}{% if data.primary_key|length > 0 or data.unique_constraint|length > 0 or data.foreign_key|length > 0 or data.check_constraint|length > 0 %},{% endif %}
{{CONSTRAINTS.EXCLUDE(conn, data.exclude_constraint)}}{% endif %}
{% if data.primary_key|length > 0 or data.unique_constraint|length > 0 or data.foreign_key|length > 0 or data.check_constraint|length > 0 or data.exclude_constraint|length > 0 %}
)
{% endif %}
{{ data.partition_value }}{% if data.is_partitioned is defined and data.is_partitioned %}
PARTITION BY {{ data.partition_scheme }}{% endif %}
{% if data.default_amname and data.default_amname != data.amname and data.amname is not none %}
USING {{data.amname}}
{% elif not data.default_amname and data.amname %}
USING {{data.amname}}
{% endif %}
{% if data.fillfactor or data.autovacuum_custom or data.autovacuum_enabled in ('t', 'f') or data.toast_autovacuum or data.toast_autovacuum_enabled in ('t', 'f') or (data.autovacuum_enabled in ('t', 'f') and data.vacuum_table|length > 0) or (data.toast_autovacuum_enabled in ('t', 'f') and data.vacuum_toast|length > 0) %}
{% set ns = namespace(add_comma=false) %}
WITH (
{% if data.fillfactor %}{% set ns.add_comma = true%}
FILLFACTOR = {{ data.fillfactor }}{% endif %}{% if data.autovacuum_enabled in ('t', 'f') %}
{% if ns.add_comma %},
{% endif %}
autovacuum_enabled = {% if data.autovacuum_enabled == 't' %}TRUE{% else %}FALSE{% endif %}{% set ns.add_comma = true%}{% endif %}{% if data.toast_autovacuum_enabled in ('t', 'f') %}
{% if ns.add_comma %},
{% endif %}
toast.autovacuum_enabled = {% if data.toast_autovacuum_enabled == 't' %}TRUE{% else %}FALSE{% endif %}{% set ns.add_comma = true%}{% endif %}
{% if data.autovacuum_custom and data.vacuum_table|length > 0 %}
{% for opt in data.vacuum_table %}{% if opt.name and opt.value is defined %}
{% if ns.add_comma %},
{% endif %}
{{opt.name}} = {{opt.value}}{% endif %}{% if opt.name and opt.value is defined %}{% set ns.add_comma = true%}{% endif %}
{% endfor %}{% endif %}
{% if data.toast_autovacuum and data.vacuum_toast|length > 0 %}
{% for opt in data.vacuum_toast %}{% if opt.name and opt.value is defined %}
,
toast.{{opt.name}} = {{opt.value}}{% endif %}{% if opt.name and opt.value is defined %}{% set ns.add_comma = true%}{% endif %}
{% endfor %}{% endif %}
){% endif %}
{### SQL for Tablespace ###}
{% if data.spcname %}
TABLESPACE {{ conn|qtIdent(data.spcname) }};
{% else %}
;
{% endif %}
{### Alter SQL for Owner ###}
{% if data.relowner %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
OWNER to {{conn|qtIdent(data.relowner)}};
{% endif %}
{### SQL for COMMENT ###}
{% if data.description %}
COMMENT ON TABLE {{conn|qtIdent(data.schema, data.name)}}
IS {{data.description|qtLiteral(conn)}};
{% endif %}

View File

@ -0,0 +1,55 @@
SELECT rel.oid, rel.relname AS name,
(SELECT count(*) FROM pg_catalog.pg_trigger WHERE tgrelid=rel.oid AND tgisinternal = FALSE) AS triggercount,
(SELECT count(*) FROM pg_catalog.pg_trigger WHERE tgrelid=rel.oid AND tgisinternal = FALSE AND tgenabled = 'O') AS has_enable_triggers,
pg_catalog.pg_get_expr(rel.relpartbound, rel.oid) AS partition_value,
rel.relnamespace AS schema_id,
nsp.nspname AS schema_name,
(CASE WHEN rel.relkind = 'p' THEN true ELSE false END) AS is_partitioned,
(CASE WHEN rel.relkind = 'p' THEN true ELSE false END) AS is_sub_partitioned,
(CASE WHEN rel.relkind = 'p' THEN pg_catalog.pg_get_partkeydef(rel.oid::oid) ELSE '' END) AS partition_scheme,
(CASE WHEN rel.relkind = 'p' THEN pg_catalog.pg_get_partkeydef(rel.oid::oid) ELSE '' END) AS sub_partition_scheme,
(CASE WHEN rel.relpersistence = 'u' THEN true ELSE false END) AS relpersistence,
(CASE WHEN length(spc.spcname::text) > 0 THEN spc.spcname ELSE
(SELECT sp.spcname FROM pg_catalog.pg_database dtb
JOIN pg_catalog.pg_tablespace sp ON dtb.dattablespace=sp.oid
WHERE dtb.oid = {{ did }}::oid)
END) as spcname,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'fillfactor=([0-9]*)') AS fillfactor,
(substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_enabled=([a-z|0-9]*)'))::BOOL AS autovacuum_enabled,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_vacuum_threshold=([0-9]*)') AS autovacuum_vacuum_threshold,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_vacuum_scale_factor=([0-9]*[.]?[0-9]*)') AS autovacuum_vacuum_scale_factor,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_analyze_threshold=([0-9]*)') AS autovacuum_analyze_threshold,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_analyze_scale_factor=([0-9]*[.]?[0-9]*)') AS autovacuum_analyze_scale_factor,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_vacuum_cost_delay=([0-9]*)') AS autovacuum_vacuum_cost_delay,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_vacuum_cost_limit=([0-9]*)') AS autovacuum_vacuum_cost_limit,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_freeze_min_age=([0-9]*)') AS autovacuum_freeze_min_age,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_freeze_max_age=([0-9]*)') AS autovacuum_freeze_max_age,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_freeze_table_age=([0-9]*)') AS autovacuum_freeze_table_age,
(substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_enabled=([a-z|0-9]*)'))::BOOL AS toast_autovacuum_enabled,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_vacuum_threshold=([0-9]*)') AS toast_autovacuum_vacuum_threshold,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_vacuum_scale_factor=([0-9]*[.]?[0-9]*)') AS toast_autovacuum_vacuum_scale_factor,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_analyze_threshold=([0-9]*)') AS toast_autovacuum_analyze_threshold,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_analyze_scale_factor=([0-9]*[.]?[0-9]*)') AS toast_autovacuum_analyze_scale_factor,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_vacuum_cost_delay=([0-9]*)') AS toast_autovacuum_vacuum_cost_delay,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_vacuum_cost_limit=([0-9]*)') AS toast_autovacuum_vacuum_cost_limit,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_min_age=([0-9]*)') AS toast_autovacuum_freeze_min_age,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_max_age=([0-9]*)') AS toast_autovacuum_freeze_max_age,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_table_age=([0-9]*)') AS toast_autovacuum_freeze_table_age,
rel.reloptions AS reloptions, tst.reloptions AS toast_reloptions, rel.reloftype, typ.typname,
typ.typrelid AS typoid, des.description, pg_catalog.pg_get_userbyid(rel.relowner) AS relowner, am.amname
FROM
(SELECT * FROM pg_catalog.pg_inherits WHERE inhparent = {{ tid }}::oid) inh
LEFT JOIN pg_catalog.pg_class rel ON inh.inhrelid = rel.oid
LEFT JOIN pg_catalog.pg_namespace nsp ON rel.relnamespace = nsp.oid
LEFT OUTER JOIN pg_catalog.pg_class tst ON tst.oid = rel.reltoastrelid
LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=rel.oid AND des.objsubid=0 AND des.classoid='pg_class'::regclass)
LEFT OUTER JOIN pg_catalog.pg_tablespace spc on spc.oid=rel.reltablespace
LEFT OUTER JOIN pg_catalog.pg_am am ON am.oid = rel.relam
LEFT JOIN pg_catalog.pg_type typ ON rel.reloftype=typ.oid
WHERE rel.relispartition
{% if ptid %} AND rel.oid = {{ ptid }}::OID {% endif %}
{% if schema_diff %}
AND CASE WHEN (SELECT COUNT(*) FROM pg_catalog.pg_depend
WHERE objid = rel.oid AND deptype = 'e') > 0 THEN FALSE ELSE TRUE END
{% endif %}
ORDER BY rel.relname;

View File

@ -48,7 +48,8 @@ SELECT rel.oid, rel.relname AS name, rel.reltablespace AS spcoid,rel.relacl AS r
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_max_age=([0-9]*)') AS toast_autovacuum_freeze_max_age,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_table_age=([0-9]*)') AS toast_autovacuum_freeze_table_age,
rel.reloptions AS reloptions, tst.reloptions AS toast_reloptions, rel.reloftype, typ.typname,
typ.typrelid AS typoid,
typ.typrelid AS typoid, am.amname,
(SELECT st.setting from pg_catalog.pg_settings st WHERE st.name = 'default_table_access_method') as default_amname,
(CASE WHEN rel.reltoastrelid = 0 THEN false ELSE true END) AS hastoasttable,
(SELECT pg_catalog.array_agg(provider || '=' || label) FROM pg_catalog.pg_seclabels sl1 WHERE sl1.objoid=rel.oid AND sl1.objsubid=0) AS seclabels,
(CASE WHEN rel.oid <= {{ datlastsysoid}}::oid THEN true ElSE false END) AS is_sys_table,
@ -67,6 +68,7 @@ FROM pg_catalog.pg_class rel
LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=rel.oid AND des.objsubid=0 AND des.classoid='pg_class'::regclass)
LEFT OUTER JOIN pg_catalog.pg_constraint con ON con.conrelid=rel.oid AND con.contype='p'
LEFT OUTER JOIN pg_catalog.pg_class tst ON tst.oid = rel.reltoastrelid
LEFT OUTER JOIN pg_catalog.pg_am am ON am.oid = rel.relam
LEFT JOIN pg_catalog.pg_type typ ON rel.reloftype=typ.oid
LEFT JOIN pg_catalog.pg_inherits inh ON inh.inhrelid = rel.oid
LEFT JOIN pg_catalog.pg_namespace nsp ON rel.relnamespace = nsp.oid

View File

@ -36,7 +36,7 @@ SELECT rel.oid, rel.relname AS name,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_max_age=([0-9]*)') AS toast_autovacuum_freeze_max_age,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_table_age=([0-9]*)') AS toast_autovacuum_freeze_table_age,
rel.reloptions AS reloptions, tst.reloptions AS toast_reloptions, rel.reloftype, typ.typname,
typ.typrelid AS typoid, des.description, pg_catalog.pg_get_userbyid(rel.relowner) AS relowner, inh.inhdetachpending
typ.typrelid AS typoid, des.description, pg_catalog.pg_get_userbyid(rel.relowner) AS relowner, inh.inhdetachpending, am.amname
FROM
(SELECT * FROM pg_catalog.pg_inherits WHERE inhparent = {{ tid }}::oid) inh
LEFT JOIN pg_catalog.pg_class rel ON inh.inhrelid = rel.oid
@ -44,6 +44,7 @@ FROM
LEFT OUTER JOIN pg_catalog.pg_class tst ON tst.oid = rel.reltoastrelid
LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=rel.oid AND des.objsubid=0 AND des.classoid='pg_class'::regclass)
LEFT OUTER JOIN pg_catalog.pg_tablespace spc on spc.oid=rel.reltablespace
LEFT OUTER JOIN pg_catalog.pg_am am ON am.oid = rel.relam
LEFT JOIN pg_catalog.pg_type typ ON rel.reloftype=typ.oid
WHERE rel.relispartition
{% if ptid %} AND rel.oid = {{ ptid }}::OID {% endif %}

View File

@ -0,0 +1,72 @@
{% import 'tables/sql/macros/constraints.macro' as CONSTRAINTS %}
{#===========================================#}
{#====== MAIN TABLE TEMPLATE STARTS HERE ======#}
{#===========================================#}
{### CREATE TABLE STATEMENT FOR partitions ###}
CREATE {% if data.relpersistence %}UNLOGGED {% endif %}TABLE IF NOT EXISTS {{conn|qtIdent(data.schema, data.name)}}{% if data.relispartition is defined and data.relispartition %} PARTITION OF {{conn|qtIdent(data.parent_schema, data.partitioned_table_name)}}{% endif %}
{# Macro to render for constraints #}
{% if data.primary_key|length > 0 or data.unique_constraint|length > 0 or data.foreign_key|length > 0 or data.check_constraint|length > 0 or data.exclude_constraint|length > 0 %}
( {% endif %}
{% if data.primary_key|length > 0 %}{{CONSTRAINTS.PRIMARY_KEY(conn, data.primary_key[0])}}{% endif %}{% if data.unique_constraint|length > 0 %}{% if data.primary_key|length > 0 %},{% endif %}
{{CONSTRAINTS.UNIQUE(conn, data.unique_constraint)}}{% endif %}{% if data.foreign_key|length > 0 %}{% if data.primary_key|length > 0 or data.unique_constraint|length > 0 %},{% endif %}
{{CONSTRAINTS.FOREIGN_KEY(conn, data.foreign_key)}}{% endif %}{% if data.check_constraint|length > 0 %}{% if data.primary_key|length > 0 or data.unique_constraint|length > 0 or data.foreign_key|length > 0 %},{% endif %}
{{CONSTRAINTS.CHECK(conn, data.check_constraint)}}{% endif %}{% if data.exclude_constraint|length > 0 %}{% if data.primary_key|length > 0 or data.unique_constraint|length > 0 or data.foreign_key|length > 0 or data.check_constraint|length > 0 %},{% endif %}
{{CONSTRAINTS.EXCLUDE(conn, data.exclude_constraint)}}{% endif %}
{% if data.primary_key|length > 0 or data.unique_constraint|length > 0 or data.foreign_key|length > 0 or data.check_constraint|length > 0 or data.exclude_constraint|length > 0 %}
)
{% endif %}
{{ data.partition_value }}{% if data.is_partitioned is defined and data.is_partitioned %}
PARTITION BY {{ data.partition_scheme }}{% endif %}
{% if data.default_amname and data.default_amname != data.amname and data.amname is not none %}
USING {{data.amname}}
{% elif not data.default_amname and data.amname %}
USING {{data.amname}}
{% endif %}
{% if data.fillfactor or data.autovacuum_custom or data.autovacuum_enabled in ('t', 'f') or data.toast_autovacuum or data.toast_autovacuum_enabled in ('t', 'f') or (data.autovacuum_enabled in ('t', 'f') and data.vacuum_table|length > 0) or (data.toast_autovacuum_enabled in ('t', 'f') and data.vacuum_toast|length > 0) %}
{% set ns = namespace(add_comma=false) %}
WITH (
{% if data.fillfactor %}{% set ns.add_comma = true%}
FILLFACTOR = {{ data.fillfactor }}{% endif %}{% if data.autovacuum_enabled in ('t', 'f') %}
{% if ns.add_comma %},
{% endif %}
autovacuum_enabled = {% if data.autovacuum_enabled == 't' %}TRUE{% else %}FALSE{% endif %}{% set ns.add_comma = true%}{% endif %}{% if data.toast_autovacuum_enabled in ('t', 'f') %}
{% if ns.add_comma %},
{% endif %}
toast.autovacuum_enabled = {% if data.toast_autovacuum_enabled == 't' %}TRUE{% else %}FALSE{% endif %}{% set ns.add_comma = true%}{% endif %}
{% if data.autovacuum_custom and data.vacuum_table|length > 0 %}
{% for opt in data.vacuum_table %}{% if opt.name and opt.value is defined %}
{% if ns.add_comma %},
{% endif %}
{{opt.name}} = {{opt.value}}{% endif %}{% if opt.name and opt.value is defined %}{% set ns.add_comma = true%}{% endif %}
{% endfor %}{% endif %}{% if data.toast_autovacuum and data.vacuum_toast|length > 0 %}
{% for opt in data.vacuum_toast %}{% if opt.name and opt.value is defined %}
,
toast.{{opt.name}} = {{opt.value}}{% endif %}
{% endfor %}{% endif %}
){% endif %}
{### SQL for Tablespace ###}
{% if data.spcname %}
TABLESPACE {{ conn|qtIdent(data.spcname) }};
{% else %}
;
{% endif %}
{### Alter SQL for Owner ###}
{% if data.relowner %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
OWNER to {{conn|qtIdent(data.relowner)}};
{% endif %}
{### SQL for COMMENT ###}
{% if data.description %}
COMMENT ON TABLE {{conn|qtIdent(data.schema, data.name)}}
IS {{data.description|qtLiteral(conn)}};
{% endif %}

View File

@ -0,0 +1,55 @@
SELECT rel.oid, rel.relname AS name,
(SELECT count(*) FROM pg_catalog.pg_trigger WHERE tgrelid=rel.oid AND tgisinternal = FALSE) AS triggercount,
(SELECT count(*) FROM pg_catalog.pg_trigger WHERE tgrelid=rel.oid AND tgisinternal = FALSE AND tgenabled = 'O') AS has_enable_triggers,
pg_catalog.pg_get_expr(rel.relpartbound, rel.oid) AS partition_value,
rel.relnamespace AS schema_id,
nsp.nspname AS schema_name,
(CASE WHEN rel.relkind = 'p' THEN true ELSE false END) AS is_partitioned,
(CASE WHEN rel.relkind = 'p' THEN true ELSE false END) AS is_sub_partitioned,
(CASE WHEN rel.relkind = 'p' THEN pg_catalog.pg_get_partkeydef(rel.oid::oid) ELSE '' END) AS partition_scheme,
(CASE WHEN rel.relkind = 'p' THEN pg_catalog.pg_get_partkeydef(rel.oid::oid) ELSE '' END) AS sub_partition_scheme,
(CASE WHEN rel.relpersistence = 'u' THEN true ELSE false END) AS relpersistence,
(CASE WHEN length(spc.spcname::text) > 0 THEN spc.spcname ELSE
(SELECT sp.spcname FROM pg_catalog.pg_database dtb
JOIN pg_catalog.pg_tablespace sp ON dtb.dattablespace=sp.oid
WHERE dtb.oid = {{ did }}::oid)
END) as spcname,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'fillfactor=([0-9]*)') AS fillfactor,
(substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_enabled=([a-z|0-9]*)'))::BOOL AS autovacuum_enabled,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_vacuum_threshold=([0-9]*)') AS autovacuum_vacuum_threshold,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_vacuum_scale_factor=([0-9]*[.]?[0-9]*)') AS autovacuum_vacuum_scale_factor,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_analyze_threshold=([0-9]*)') AS autovacuum_analyze_threshold,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_analyze_scale_factor=([0-9]*[.]?[0-9]*)') AS autovacuum_analyze_scale_factor,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_vacuum_cost_delay=([0-9]*)') AS autovacuum_vacuum_cost_delay,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_vacuum_cost_limit=([0-9]*)') AS autovacuum_vacuum_cost_limit,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_freeze_min_age=([0-9]*)') AS autovacuum_freeze_min_age,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_freeze_max_age=([0-9]*)') AS autovacuum_freeze_max_age,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'autovacuum_freeze_table_age=([0-9]*)') AS autovacuum_freeze_table_age,
(substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_enabled=([a-z|0-9]*)'))::BOOL AS toast_autovacuum_enabled,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_vacuum_threshold=([0-9]*)') AS toast_autovacuum_vacuum_threshold,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_vacuum_scale_factor=([0-9]*[.]?[0-9]*)') AS toast_autovacuum_vacuum_scale_factor,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_analyze_threshold=([0-9]*)') AS toast_autovacuum_analyze_threshold,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_analyze_scale_factor=([0-9]*[.]?[0-9]*)') AS toast_autovacuum_analyze_scale_factor,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_vacuum_cost_delay=([0-9]*)') AS toast_autovacuum_vacuum_cost_delay,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_vacuum_cost_limit=([0-9]*)') AS toast_autovacuum_vacuum_cost_limit,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_min_age=([0-9]*)') AS toast_autovacuum_freeze_min_age,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_max_age=([0-9]*)') AS toast_autovacuum_freeze_max_age,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_table_age=([0-9]*)') AS toast_autovacuum_freeze_table_age,
rel.reloptions AS reloptions, tst.reloptions AS toast_reloptions, rel.reloftype, typ.typname,
typ.typrelid AS typoid, des.description, pg_catalog.pg_get_userbyid(rel.relowner) AS relowner, am.amname
FROM
(SELECT * FROM pg_catalog.pg_inherits WHERE inhparent = {{ tid }}::oid) inh
LEFT JOIN pg_catalog.pg_class rel ON inh.inhrelid = rel.oid
LEFT JOIN pg_catalog.pg_namespace nsp ON rel.relnamespace = nsp.oid
LEFT OUTER JOIN pg_catalog.pg_class tst ON tst.oid = rel.reltoastrelid
LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=rel.oid AND des.objsubid=0 AND des.classoid='pg_class'::regclass)
LEFT OUTER JOIN pg_catalog.pg_tablespace spc on spc.oid=rel.reltablespace
LEFT OUTER JOIN pg_catalog.pg_am am ON am.oid = rel.relam
LEFT JOIN pg_catalog.pg_type typ ON rel.reloftype=typ.oid
WHERE rel.relispartition
{% if ptid %} AND rel.oid = {{ ptid }}::OID {% endif %}
{% if schema_diff %}
AND CASE WHEN (SELECT COUNT(*) FROM pg_catalog.pg_depend
WHERE objid = rel.oid AND deptype = 'e') > 0 THEN FALSE ELSE TRUE END
{% endif %}
ORDER BY rel.relname;

View File

@ -48,7 +48,8 @@ SELECT rel.oid, rel.relname AS name, rel.reltablespace AS spcoid,rel.relacl AS r
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_max_age=([0-9]*)') AS toast_autovacuum_freeze_max_age,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_table_age=([0-9]*)') AS toast_autovacuum_freeze_table_age,
rel.reloptions AS reloptions, tst.reloptions AS toast_reloptions, rel.reloftype, typ.typname,
typ.typrelid AS typoid,
typ.typrelid AS typoid, am.amname,
(SELECT st.setting from pg_catalog.pg_settings st WHERE st.name = 'default_table_access_method') as default_amname,
(CASE WHEN rel.reltoastrelid = 0 THEN false ELSE true END) AS hastoasttable,
(SELECT pg_catalog.array_agg(provider || '=' || label) FROM pg_catalog.pg_seclabels sl1 WHERE sl1.objoid=rel.oid AND sl1.objsubid=0) AS seclabels,
(CASE WHEN rel.oid <= {{ datlastsysoid}}::oid THEN true ElSE false END) AS is_sys_table,
@ -67,6 +68,7 @@ FROM pg_catalog.pg_class rel
LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=rel.oid AND des.objsubid=0 AND des.classoid='pg_class'::regclass)
LEFT OUTER JOIN pg_catalog.pg_constraint con ON con.conrelid=rel.oid AND con.contype='p'
LEFT OUTER JOIN pg_catalog.pg_class tst ON tst.oid = rel.reltoastrelid
LEFT OUTER JOIN pg_catalog.pg_am am ON am.oid = rel.relam
LEFT JOIN pg_catalog.pg_type typ ON rel.reloftype=typ.oid
LEFT JOIN pg_catalog.pg_inherits inh ON inh.inhrelid = rel.oid
LEFT JOIN pg_catalog.pg_namespace nsp ON rel.relnamespace = nsp.oid

View File

@ -36,7 +36,7 @@ SELECT rel.oid, rel.relname AS name,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_max_age=([0-9]*)') AS toast_autovacuum_freeze_max_age,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_table_age=([0-9]*)') AS toast_autovacuum_freeze_table_age,
rel.reloptions AS reloptions, tst.reloptions AS toast_reloptions, rel.reloftype, typ.typname,
typ.typrelid AS typoid, des.description, pg_catalog.pg_get_userbyid(rel.relowner) AS relowner, inh.inhdetachpending
typ.typrelid AS typoid, des.description, pg_catalog.pg_get_userbyid(rel.relowner) AS relowner, inh.inhdetachpending, am.amname
FROM
(SELECT * FROM pg_catalog.pg_inherits WHERE inhparent = {{ tid }}::oid) inh
LEFT JOIN pg_catalog.pg_class rel ON inh.inhrelid = rel.oid
@ -44,6 +44,7 @@ FROM
LEFT OUTER JOIN pg_catalog.pg_class tst ON tst.oid = rel.reltoastrelid
LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=rel.oid AND des.objsubid=0 AND des.classoid='pg_class'::regclass)
LEFT OUTER JOIN pg_catalog.pg_tablespace spc on spc.oid=rel.reltablespace
LEFT OUTER JOIN pg_catalog.pg_am am ON am.oid = rel.relam
LEFT JOIN pg_catalog.pg_type typ ON rel.reloftype=typ.oid
WHERE rel.relispartition
{% if ptid %} AND rel.oid = {{ ptid }}::OID {% endif %}

View File

@ -87,6 +87,11 @@ CACHE {{c.seqcache|int}} {% endif %}
{% if data.coll_inherits %}
INHERITS ({% for val in data.coll_inherits %}{% if loop.index != 1 %}, {% endif %}{{val}}{% endfor %}){% if not data.spcname and not with_clause %};{% endif %}
{% endif %}
{% if data.default_amname and data.default_amname != data.amname and data.amname is not none %}
USING {{data.amname}}
{% elif not data.default_amname and data.amname %}
USING {{data.amname}}
{% endif %}
{% if with_clause %}
{% set ns = namespace(add_comma=false) %}

View File

@ -0,0 +1,3 @@
-- Fetches access methods
SELECT oid, amname
FROM pg_catalog.pg_am WHERE amtype = 't';

View File

@ -32,6 +32,7 @@ SELECT rel.oid, rel.relname AS name, rel.reltablespace AS spcoid,rel.relacl AS r
JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace
WHERE i.inhrelid = rel.oid) AS inherited_tables_cnt,
(CASE WHEN rel.relpersistence = 'u' THEN true ELSE false END) AS relpersistence,
(SELECT st.setting from pg_catalog.pg_settings st WHERE st.name = 'default_table_access_method') as default_amname,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'fillfactor=([0-9]*)') AS fillfactor,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'parallel_workers=([0-9]*)') AS parallel_workers,
substring(pg_catalog.array_to_string(rel.reloptions, ',') FROM 'toast_tuple_target=([0-9]*)') AS toast_tuple_target,
@ -55,7 +56,7 @@ SELECT rel.oid, rel.relname AS name, rel.reltablespace AS spcoid,rel.relacl AS r
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_min_age=([0-9]*)') AS toast_autovacuum_freeze_min_age,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_max_age=([0-9]*)') AS toast_autovacuum_freeze_max_age,
substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_freeze_table_age=([0-9]*)') AS toast_autovacuum_freeze_table_age,
rel.reloptions AS reloptions, tst.reloptions AS toast_reloptions, rel.reloftype,
rel.reloptions AS reloptions, tst.reloptions AS toast_reloptions, rel.reloftype, am.amname,
CASE WHEN typ.typname IS NOT NULL THEN (select pg_catalog.quote_ident(nspname) FROM pg_catalog.pg_namespace WHERE oid = {{scid}}::oid )||'.'||pg_catalog.quote_ident(typ.typname) ELSE typ.typname END AS typname,
typ.typrelid AS typoid, rel.relrowsecurity as rlspolicy, rel.relforcerowsecurity as forcerlspolicy,
(CASE WHEN rel.reltoastrelid = 0 THEN false ELSE true END) AS hastoasttable,
@ -69,6 +70,7 @@ FROM pg_catalog.pg_class rel
LEFT OUTER JOIN pg_catalog.pg_constraint con ON con.conrelid=rel.oid AND con.contype='p'
LEFT OUTER JOIN pg_catalog.pg_class tst ON tst.oid = rel.reltoastrelid
LEFT JOIN pg_catalog.pg_type typ ON rel.reloftype=typ.oid
LEFT OUTER JOIN pg_catalog.pg_am am ON am.oid = rel.relam
WHERE rel.relkind IN ('r','s','t','p') AND rel.relnamespace = {{ scid }}::oid
AND NOT rel.relispartition
{% if tid %} AND rel.oid = {{ tid }}::oid {% endif %}

View File

@ -89,6 +89,11 @@ CACHE {{c.seqcache|int}} {% endif %}
{% if data.coll_inherits %}
INHERITS ({% for val in data.coll_inherits %}{% if loop.index != 1 %}, {% endif %}{{val}}{% endfor %}){% if not data.spcname and not with_clause %};{% endif %}
{% endif %}
{% if data.default_amname and data.default_amname != data.amname and data.amname is not none %}
USING {{data.amname}}
{% elif data.amname and not data.default_amname %}
USING {{data.amname}}
{% endif %}
{% if with_clause %}
{% set ns = namespace(add_comma=false) %}

View File

@ -0,0 +1,292 @@
{% import 'macros/schemas/security.macros' as SECLABEL %}
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
{% import 'macros/variable.macros' as VARIABLE %}
{#####################################################}
{## Rename table ##}
{#####################################################}
{% if data.name and data.name != o_data.name %}
ALTER TABLE IF EXISTS {{conn|qtIdent(o_data.schema, o_data.name)}}
RENAME TO {{conn|qtIdent(data.name)}};
{% endif %}
{#####################################################}
{## change table access method ##}
{#####################################################}
{% if data.amname and data.amname != o_data.amname %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET ACCESS METHOD {{conn|qtIdent(data.amname)}};
{% endif %}
{#####################################################}
{## Change table schema ##}
{#####################################################}
{% if data.schema and data.schema != o_data.schema %}
ALTER TABLE IF EXISTS {{conn|qtIdent(o_data.schema, data.name)}}
SET SCHEMA {{conn|qtIdent(data.schema)}};
{% endif %}
{#####################################################}
{## Change table owner ##}
{#####################################################}
{% if data.relowner and data.relowner != o_data.relowner %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
OWNER TO {{conn|qtIdent(data.relowner)}};
{% endif %}
{#####################################################}
{## Update Inherits table definition ##}
{#####################################################}
{% if data.coll_inherits_added|length > 0 %}
{% for val in data.coll_inherits_added %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
INHERIT {{val}};
{% endfor %}
{% endif %}
{% if data.coll_inherits_removed|length > 0 %}
{% for val in data.coll_inherits_removed %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
NO INHERIT {{val}};
{% endfor %}
{% endif %}
{#####################################################}
{## Change tablespace ##}
{#####################################################}
{% if data.spcname and data.spcname != o_data.spcname %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET TABLESPACE {{conn|qtIdent(data.spcname)}};
{% endif %}
{#####################################################}
{## Enable Row Level Security Policy on table ##}
{#####################################################}
{% if data.rlspolicy %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
ENABLE ROW LEVEL SECURITY;
{% elif data.rlspolicy is defined and data.rlspolicy != o_data.rlspolicy%}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
DISABLE ROW LEVEL SECURITY;
{% endif %}
{#####################################################}
{## Force Enable Row Level Security Policy on table ##}
{#####################################################}
{% if data.forcerlspolicy %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
FORCE ROW LEVEL SECURITY;
{% elif data.forcerlspolicy is defined and data.forcerlspolicy != o_data.forcerlspolicy%}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
NO FORCE ROW LEVEL SECURITY;
{% endif %}
{#####################################################}
{## change fillfactor settings ##}
{#####################################################}
{% if data.fillfactor and data.fillfactor != o_data.fillfactor %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET (FILLFACTOR={{data.fillfactor}});
{% elif (data.fillfactor == '' or data.fillfactor == None) and data.fillfactor != o_data.fillfactor %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
RESET (FILLFACTOR);
{% endif %}
{## change parallel_workers settings ##}
{#####################################################}
{% if (data.parallel_workers == '' or data.parallel_workers == None) and data.parallel_workers != o_data.parallel_workers %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
RESET (parallel_workers);
{% elif data.parallel_workers is defined and data.parallel_workers != o_data.parallel_workers %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET (parallel_workers={{data.parallel_workers}});
{% endif %}
{## change toast_tuple_target settings ##}
{#####################################################}
{% if (data.toast_tuple_target == '' or data.toast_tuple_target == None) and data.toast_tuple_target != o_data.toast_tuple_target %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
RESET (toast_tuple_target);
{% elif data.toast_tuple_target is defined and data.toast_tuple_target != o_data.toast_tuple_target %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET (toast_tuple_target={{data.toast_tuple_target}});
{% endif %}
{###############################}
{## Table AutoVacuum settings ##}
{###############################}
{% if data.vacuum_table is defined and data.vacuum_table.set_values|length > 0 %}
{% set has_vacuum_set = true %}
{% endif %}
{% if data.vacuum_table is defined and data.vacuum_table.reset_values|length > 0 %}
{% set has_vacuum_reset = true %}
{% endif %}
{% if o_data.autovacuum_custom and data.autovacuum_custom == false %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}} RESET (
autovacuum_enabled,
autovacuum_analyze_scale_factor,
autovacuum_analyze_threshold,
autovacuum_freeze_max_age,
autovacuum_vacuum_cost_delay,
autovacuum_vacuum_cost_limit,
autovacuum_vacuum_scale_factor,
autovacuum_vacuum_threshold,
autovacuum_freeze_min_age,
autovacuum_freeze_table_age
);
{% else %}
{% if (data.autovacuum_enabled in ('t', 'f') and data.autovacuum_enabled != o_data.autovacuum_enabled) or has_vacuum_set %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}} SET (
{% if data.autovacuum_enabled in ('t', 'f') and data.autovacuum_enabled != o_data.autovacuum_enabled %}
autovacuum_enabled = {% if data.autovacuum_enabled == 't' %}true{% else %}false{% endif %}{% if has_vacuum_set %},
{% endif %}
{% endif %}
{% if has_vacuum_set %}
{% for opt in data.vacuum_table.set_values %}{% if opt.name and opt.value is defined %}
{{opt.name}} = {{opt.value}}{% if not loop.last %},
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
);
{% endif %}
{% if (data.autovacuum_enabled == 'x' and data.autovacuum_enabled != o_data.autovacuum_enabled) or has_vacuum_reset %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}} RESET (
{% if data.autovacuum_enabled =='x' and data.autovacuum_enabled != o_data.autovacuum_enabled %}
autovacuum_enabled{% if has_vacuum_reset %},
{% endif %}
{% endif %}
{% if has_vacuum_reset %}
{% for opt in data.vacuum_table.reset_values %}{% if opt.name %}
{{opt.name}}{% if not loop.last %},
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
);
{% endif %}
{% endif %}
{#####################################}
{## Toast table AutoVacuum settings ##}
{#####################################}
{% if data.vacuum_toast is defined and data.vacuum_toast.set_values|length > 0 %}
{% set has_vacuum_toast_set = true %}
{% endif %}
{% if data.vacuum_toast is defined and data.vacuum_toast.reset_values|length > 0 %}
{% set has_vacuum_toast_reset = true %}
{% endif %}
{% if o_data.toast_autovacuum and data.toast_autovacuum == false %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}} RESET (
toast.autovacuum_enabled,
toast.autovacuum_freeze_max_age,
toast.autovacuum_vacuum_cost_delay,
toast.autovacuum_vacuum_cost_limit,
toast.autovacuum_vacuum_scale_factor,
toast.autovacuum_vacuum_threshold,
toast.autovacuum_freeze_min_age,
toast.autovacuum_freeze_table_age,
toast.autovacuum_analyze_threshold,
toast.autovacuum_analyze_scale_factor
);
{% else %}
{% if (data.toast_autovacuum_enabled in ('t', 'f') and data.toast_autovacuum_enabled != o_data.toast_autovacuum_enabled) or has_vacuum_toast_set %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}} SET (
{% if data.toast_autovacuum_enabled in ('t', 'f') and data.toast_autovacuum_enabled != o_data.toast_autovacuum_enabled %}
toast.autovacuum_enabled = {% if data.toast_autovacuum_enabled == 't' %}true{% else %}false{% endif %}{% if has_vacuum_toast_set %},
{% endif %}
{% endif %}
{% if has_vacuum_toast_set %}
{% for opt in data.vacuum_toast.set_values %}{% if opt.name and opt.value is defined %}
toast.{{opt.name}} = {{opt.value}}{% if not loop.last %},
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
);
{% endif %}
{% if (data.toast_autovacuum_enabled == 'x' and data.toast_autovacuum_enabled != o_data.toast_autovacuum_enabled) or has_vacuum_toast_reset %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}} RESET (
{% if data.toast_autovacuum_enabled == 'x' and data.toast_autovacuum_enabled != o_data.toast_autovacuum_enabled %}
toast.autovacuum_enabled{% if has_vacuum_toast_reset %},
{% endif %}
{% endif %}
{% if has_vacuum_toast_reset %}
{% for opt in data.vacuum_toast.reset_values %}{% if opt.name %}
toast.{{opt.name}}{% if not loop.last %},
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
);
{% endif %}
{% endif %}
{#####################################################}
{## Change table comments ##}
{#####################################################}
{% if data.description is defined and data.description != o_data.description %}
COMMENT ON TABLE {{conn|qtIdent(data.schema, data.name)}}
IS {{data.description|qtLiteral(conn)}};
{% endif %}
{#####################################################}
{## Update table Privileges ##}
{#####################################################}
{% if data.relacl %}
{% if 'deleted' in data.relacl %}
{% for priv in data.relacl.deleted %}
{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
{% endfor %}
{% endif %}
{% if 'changed' in data.relacl %}
{% for priv in data.relacl.changed %}
{% if priv.grantee != priv.old_grantee %}
{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.old_grantee, data.name, data.schema) }}
{% else %}
{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
{% endif %}
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
{% endfor %}
{% endif %}
{% if 'added' in data.relacl %}
{% for priv in data.relacl.added %}
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
{% endfor %}
{% endif %}
{% endif %}
{#####################################################}
{## Update table SecurityLabel ##}
{#####################################################}
{% if data.seclabels and data.seclabels|length > 0 %}
{% set seclabels = data.seclabels %}
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
{% for r in seclabels.deleted %}
{{ SECLABEL.UNSET(conn, 'TABLE', data.name, r.provider, data.schema) }}
{% endfor %}
{% endif %}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABEL.SET(conn, 'TABLE', data.name, r.provider, r.label, data.schema) }}
{% endfor %}
{% endif %}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABEL.SET(conn, 'TABLE', data.name, r.provider, r.label, data.schema) }}
{% endfor %}
{% endif %}
{% endif %}
{#####################################################}
{## Change replica identity ##}
{#####################################################}
{% if data.replica_identity and data.replica_identity != o_data.replica_identity %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.name)}} REPLICA IDENTITY {{data.replica_identity }};
{% endif %}

View File

@ -926,6 +926,8 @@ class BaseTableView(PGChildNodeView, BasePartitionTable, VacuumSettings):
part_data['partition_scheme'] = row['partition_scheme']
part_data['description'] = row['description']
part_data['relowner'] = row['relowner']
part_data['default_amname'] = data.get('default_amname')
part_data['amname'] = row.get('amname')
self.update_autovacuum_properties(row)
@ -1872,6 +1874,7 @@ class BaseTableView(PGChildNodeView, BasePartitionTable, VacuumSettings):
part_data = dict()
part_data['partitioned_table_name'] = partitions['name']
part_data['parent_schema'] = partitions['schema']
part_data['amname'] = row.get('amname')
if 'is_attach' in row and row['is_attach']:
schema_name, table_name = \
@ -2199,3 +2202,23 @@ class BaseTableView(PGChildNodeView, BasePartitionTable, VacuumSettings):
res['toast_autovacuum_freeze_max_age'],
res['toast_autovacuum_freeze_table_age']]) or \
res['toast_autovacuum_enabled'] in ('t', 'f')
def get_access_methods(self):
"""
This function returns the access methods for table
"""
res = []
sql = render_template("/".join([self.table_template_path,
'get_access_methods.sql']))
status, rest = self.conn.execute_2darray(sql)
if not status:
return internal_server_error(errormsg=rest)
for row in rest['rows']:
res.append(
{'label': row['amname'], 'value': row['amname']}
)
return res

View File

@ -1759,7 +1759,8 @@ class ViewNode(PGChildNodeView, VacuumSettings, SchemaDiffObjectCompare):
# Override the operations for materialized view
mview_operations = {
'refresh_data': [{'put': 'refresh_data'}, {}],
'check_utility_exists': [{'get': 'check_utility_exists'}, {}]
'check_utility_exists': [{'get': 'check_utility_exists'}, {}],
'get_access_methods': [{}, {'get': 'get_access_methods'}],
}
mview_operations.update(ViewNode.operations)
@ -2415,6 +2416,35 @@ class MViewNode(ViewNode, VacuumSettings):
status=200
)
@check_precondition
def get_access_methods(self, gid, sid, did, scid, vid=None):
"""
Args:
gid: Server Group ID
sid: Server ID
did: Database ID
scid: Schema ID
vid: View ID
Returns the access method to be used by mview
"""
res = []
sql = render_template("/".join([self.template_path,
'sql/get_access_methods.sql']))
status, rest = self.conn.execute_2darray(sql)
if not status:
return internal_server_error(errormsg=rest)
for row in rest['rows']:
res.append(
{'label': row['amname'], 'value': row['amname']}
)
return make_json_response(
data=res,
status=200
)
SchemaDiffRegistry(view_blueprint.node_type, ViewNode)
ViewNode.register_node_view(view_blueprint)

View File

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
import MViewSchema from './mview.ui';
import { getNodeListByName } from '../../../../../../../static/js/node_ajax';
import { getNodeListByName, getNodeAjaxOptions } from '../../../../../../../static/js/node_ajax';
import { getNodePrivilegeRoleSchema } from '../../../../../static/js/privilege.ui';
import { getNodeVacuumSettingsSchema } from '../../../../../static/js/vacuum.ui';
import Notify from '../../../../../../../../static/js/helpers/Notifier';
@ -140,6 +140,7 @@ define('pgadmin.node.mview', [
spcname: ()=>getNodeListByName('tablespace', treeNodeInfo, itemNodeData, {}, (m)=> {
return (m.label != 'pg_global');
}),
table_amname_list: ()=>getNodeAjaxOptions('get_access_methods', this, treeNodeInfo, itemNodeData),
nodeInfo: treeNodeInfo,
},
{

View File

@ -20,6 +20,7 @@ export default class MViewSchema extends BaseUISchema {
toast_autovacuum_enabled: 'x',
autovacuum_enabled: 'x',
warn_text: undefined,
amname: undefined,
...initValues
});
this.getPrivilegeRoleSchema = getPrivilegeRoleSchema;
@ -29,6 +30,7 @@ export default class MViewSchema extends BaseUISchema {
schema: [],
spcname: [],
nodeInfo: null,
amname: [],
...fieldOptions,
};
@ -71,29 +73,38 @@ export default class MViewSchema extends BaseUISchema {
},{
id: 'comment', label: gettext('Comment'), cell: 'text',
type: 'multiline',
},{
id: 'definition', label: gettext('Definition'), cell: 'text',
type: 'sql', mode: ['create', 'edit'], group: gettext('Definition'),
isFullTab: true, controlProps: { readOnly: this.nodeInfo && 'catalog' in this.nodeInfo ? true: false },
},{
id: 'with_data', label: gettext('With data?'),
group: gettext('Storage'), mode: ['edit', 'create'],
group: gettext('Definition'), mode: ['edit', 'create'],
type: 'switch',
},{
id: 'spcname', label: gettext('Tablespace'), cell: 'text',
type: 'select', group: gettext('Storage'),
type: 'select', group: gettext('Definition'),
options: obj.fieldOptions.spcname,
controlProps: {
allowClear: false,
first_empty: false,
},
}, {
id: 'amname', label: gettext('Access Method'), group: gettext('Definition'),
type: 'select', mode: ['create', 'properties', 'edit'], min_version: 120000,
options: obj.fieldOptions.table_amname_list,
disabled: (state) => {
if (obj.getServerVersion() < 150000 && !obj.isNew(state)) {
return true;
}
},
},{
id: 'fillfactor', label: gettext('Fill factor'),
group: gettext('Storage'), mode: ['edit', 'create'],
group: gettext('Definition'), mode: ['edit', 'create'],
noEmpty: false, type: 'int', controlProps: {min: 10, max: 100}
},{
id: 'vacuum_settings_str', label: gettext('Storage settings'),
type: 'multiline', group: gettext('Storage'), mode: ['properties'],
type: 'multiline', group: gettext('Definition'), mode: ['properties'],
},{
id: 'definition', label: gettext('Definition'), cell: 'text',
type: 'sql', mode: ['create', 'edit'], group: gettext('Code'),
isFullTab: true, controlProps: { readOnly: this.nodeInfo && 'catalog' in this.nodeInfo ? true: false },
},
{
type: 'nested-tab', group: gettext('Parameter'), mode: ['create', 'edit'],
@ -128,7 +139,7 @@ export default class MViewSchema extends BaseUISchema {
/* mview definition validation*/
if (isEmptyString(state.definition)) {
errmsg = gettext('Please enter view definition.');
errmsg = gettext('Please enter view code.');
setError('definition', errmsg);
return true;
} else {

View File

@ -0,0 +1,50 @@
{# ===================== Create new view ===================== #}
{% if display_comments %}
-- View: {{ data.schema }}.{{ data.name }}
-- DROP MATERIALIZED VIEW IF EXISTS {{ conn|qtIdent(data.schema, data.name) }};
{% endif %}
{% if data.name and data.schema and data.definition %}
CREATE MATERIALIZED VIEW{% if add_not_exists_clause %} IF NOT EXISTS{% endif %} {{ conn|qtIdent(data.schema, data.name) }}
{% if data.default_amname and data.default_amname != data.amname %}
USING {{data.amname}}
{% elif not data.default_amname and data.amname %}
USING {{data.amname}}
{% endif %}
{% if(data.fillfactor or data.autovacuum_enabled in ('t', 'f') or data.toast_autovacuum_enabled in ('t', 'f') or data['vacuum_data']|length > 0) %}
{% set ns = namespace(add_comma=false) %}
WITH (
{% if data.fillfactor %}
FILLFACTOR = {{ data.fillfactor }}{% set ns.add_comma = true%}{% endif %}{% if data.autovacuum_enabled in ('t', 'f') %}
{% if ns.add_comma %},
{% endif %}
autovacuum_enabled = {% if data.autovacuum_enabled == 't' %}TRUE{% else %}FALSE{% endif %}{% set ns.add_comma = true%}{% endif %}{% if data.toast_autovacuum_enabled in ('t', 'f') %}
{% if ns.add_comma %},
{% endif %}
toast.autovacuum_enabled = {% if data.toast_autovacuum_enabled == 't' %}TRUE{% else %}FALSE{% endif %}{% set ns.add_comma = true%}{% endif %}
{% for field in data['vacuum_data'] %}
{% if field.value is defined and field.value != '' and field.value != none %}
{% if ns.add_comma %},
{% endif %} {{ field.name }} = {{ field.value|lower }}{% set ns.add_comma = true%}{% endif %}{% endfor %}
{{ '\n' }})
{% 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 IF EXISTS {{ conn|qtIdent(data.schema, data.name) }}
OWNER TO {{ conn|qtIdent(data.owner) }};
{% endif %}
{% if data.comment %}
COMMENT ON MATERIALIZED VIEW {{ conn|qtIdent(data.schema, data.name) }}
IS {{ data.comment|qtLiteral(conn) }};
{% endif %}
{% endif %}

View File

@ -0,0 +1,3 @@
CREATE ACCESS METHOD {{ data.name }}
TYPE {{ data.type }}
HANDLER {{ data.handler }}

View File

@ -0,0 +1,3 @@
-- Fetches access methods
SELECT oid, amname
FROM pg_catalog.pg_am WHERE amtype = 't';

View File

@ -0,0 +1,112 @@
{# ========================== 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(spcname::text) > 0 THEN spcname ELSE
(SELECT sp.spcname FROM pg_catalog.pg_database dtb
JOIN pg_catalog.pg_tablespace sp ON dtb.dattablespace=sp.oid
WHERE dtb.oid = {{ did }}::oid)
END as spcname,
(SELECT st.setting from pg_catalog.pg_settings st
WHERE st.name = 'default_table_access_method') as default_amname,
c.relacl,
nsp.nspname as schema,
pg_catalog.pg_get_userbyid(c.relowner) AS owner,
description AS comment,
pg_catalog.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 %}
pg_catalog.array_to_string(c.relacl::text[], ', ') AS acl,
(SELECT pg_catalog.array_agg(provider || '=' || label) FROM pg_catalog.pg_seclabels sl1 WHERE sl1.objoid=c.oid AND sl1.objsubid=0) AS seclabels,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'fillfactor=([0-9]*)') AS fillfactor,
(substring(pg_catalog.array_to_string(c.reloptions, ',') FROM 'autovacuum_enabled=([a-z|0-9]*)'))::BOOL AS autovacuum_enabled,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_vacuum_threshold=([0-9]*)') AS autovacuum_vacuum_threshold,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_vacuum_scale_factor=([0-9]*[.]?[0-9]*)') AS autovacuum_vacuum_scale_factor,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_analyze_threshold=([0-9]*)') AS autovacuum_analyze_threshold,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_analyze_scale_factor=([0-9]*[.]?[0-9]*)') AS autovacuum_analyze_scale_factor,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_vacuum_cost_delay=([0-9]*)') AS autovacuum_vacuum_cost_delay,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_vacuum_cost_limit=([0-9]*)') AS autovacuum_vacuum_cost_limit,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_freeze_min_age=([0-9]*)') AS autovacuum_freeze_min_age,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_freeze_max_age=([0-9]*)') AS autovacuum_freeze_max_age,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_freeze_table_age=([0-9]*)') AS autovacuum_freeze_table_age,
(substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_enabled=([a-z|0-9]*)'))::BOOL AS toast_autovacuum_enabled,
substring(pg_catalog.array_to_string(tst.reloptions, ',')
FROM 'autovacuum_vacuum_threshold=([0-9]*)') AS toast_autovacuum_vacuum_threshold,
substring(pg_catalog.array_to_string(tst.reloptions, ',')
FROM 'autovacuum_vacuum_scale_factor=([0-9]*[.]?[0-9]*)') AS toast_autovacuum_vacuum_scale_factor,
substring(pg_catalog.array_to_string(tst.reloptions, ',')
FROM 'autovacuum_analyze_threshold=([0-9]*)') AS toast_autovacuum_analyze_threshold,
substring(pg_catalog.array_to_string(tst.reloptions, ',')
FROM 'autovacuum_analyze_scale_factor=([0-9]*[.]?[0-9]*)') AS toast_autovacuum_analyze_scale_factor,
substring(pg_catalog.array_to_string(tst.reloptions, ',')
FROM 'autovacuum_vacuum_cost_delay=([0-9]*)') AS toast_autovacuum_vacuum_cost_delay,
substring(pg_catalog.array_to_string(tst.reloptions, ',')
FROM 'autovacuum_vacuum_cost_limit=([0-9]*)') AS toast_autovacuum_vacuum_cost_limit,
substring(pg_catalog.array_to_string(tst.reloptions, ',')
FROM 'autovacuum_freeze_min_age=([0-9]*)') AS toast_autovacuum_freeze_min_age,
substring(pg_catalog.array_to_string(tst.reloptions, ',')
FROM 'autovacuum_freeze_max_age=([0-9]*)') AS toast_autovacuum_freeze_max_age,
substring(pg_catalog.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, am.amname,
(CASE WHEN c.reltoastrelid = 0 THEN false ELSE true END) AS hastoasttable
FROM
pg_catalog.pg_class c
LEFT OUTER JOIN pg_catalog.pg_namespace nsp on nsp.oid = c.relnamespace
LEFT OUTER JOIN pg_catalog.pg_tablespace spc on spc.oid=c.reltablespace
LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=c.oid and des.objsubid=0 AND des.classoid='pg_class'::regclass)
LEFT OUTER JOIN pg_catalog.pg_class tst ON tst.oid = c.reltoastrelid
LEFT OUTER JOIN pg_catalog.pg_am am ON am.oid = c.relam
WHERE ((c.relhasrules AND (EXISTS (
SELECT
r.rulename
FROM
pg_catalog.pg_rewrite r
WHERE
((r.ev_class = c.oid)
AND (pg_catalog.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_catalog.pg_roles pr
WHERE
pr.rolcanlogin
ORDER BY
pr.rolname
{% elif type == 'schemas' %}
SELECT
nsp.nspname
FROM
pg_catalog.pg_namespace nsp
WHERE
(nsp.nspname NOT LIKE E'pg\\_%'
AND nsp.nspname != 'information_schema')
{% endif %}

View File

@ -0,0 +1,207 @@
{# ===================== Update View ===================#}
{% import 'macros/schemas/security.macros' as SECLABEL %}
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
{%- if data -%}
{% set view_name = data.name if data.name else o_data.name %}
{% set view_schema = data.schema if data.schema else o_data.schema %}
{% set def = data.definition.rstrip(';') if data.definition %}
{# ===== Rename mat view ===== #}
{% if data.name and data.name != o_data.name %}
ALTER MATERIALIZED VIEW IF EXISTS {{ 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 IF EXISTS {{ 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 IF EXISTS {{ 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 IF EXISTS {{ conn|qtIdent(view_schema, view_name) }};
CREATE MATERIALIZED VIEW IF NOT EXISTS {{ conn|qtIdent(view_schema, view_name) }}
{% if data.amname and data.amname != o_data.amname %}
USING {{ data.amname }}
{% endif %}
{% if data.fillfactor or o_data.fillfactor %}
WITH(
{% if data.fillfactor %}
FILLFACTOR = {{ data.fillfactor }}{% if (data['vacuum_data'] is defined and data['vacuum_data']['changed']|length > 0) %},{% endif %}
{% elif o_data.fillfactor %}
FILLFACTOR = {{ o_data.fillfactor }}{% if (data['vacuum_data'] is defined and data['vacuum_data']['changed']|length > 0) %},{% endif %}
{% 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 %}
{% 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 is defined %}
WITH {{ 'DATA' if o_data.with_data else 'NO DATA' }};
{% endif %}
{% if o_data.owner and not data.owner %}
ALTER TABLE IF EXISTS {{ conn|qtIdent(view_schema, view_name) }}
OWNER TO {{ conn|qtIdent(o_data.owner) }};
{% endif %}
{% if o_data.comment and not data.comment %}
COMMENT ON MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
IS {{ o_data.comment|qtLiteral(conn) }};
{% endif %}
{% else %}
{# ======= Alter Tablespace ========= #}
{%- if data.spcname and o_data.spcname != data.spcname -%}
ALTER MATERIALIZED VIEW IF EXISTS {{ conn|qtIdent(view_schema, view_name) }}
SET TABLESPACE {{ data.spcname }};
{% endif %}
{# ======= SET/RESET Fillfactor ========= #}
{% if data.fillfactor and o_data.fillfactor != data.fillfactor %}
ALTER MATERIALIZED VIEW IF EXISTS {{ conn|qtIdent(view_schema, view_name) }}
SET(
FILLFACTOR = {{ data.fillfactor }}
);
{% elif data.fillfactor == '' and o_data.fillfactor|default('', 'true') != data.fillfactor %}
ALTER MATERIALIZED VIEW IF EXISTS {{ 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 Autovacuum options ===== #}
{% if data.autovacuum_custom is defined and data.autovacuum_custom == False %}
ALTER MATERIALIZED VIEW IF EXISTS {{ 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
);
{% endif %}
{% if data.toast_autovacuum is defined and data.toast_autovacuum == False %}
ALTER MATERIALIZED VIEW IF EXISTS {{ 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
);
{% endif %}{#-- toast_endif ends --#}
{% if data['vacuum_data']['changed']|length > 0 or data.autovacuum_enabled in ('t', 'f') or data.toast_autovacuum_enabled in ('t', 'f') %}
ALTER MATERIALIZED VIEW IF EXISTS {{ conn|qtIdent(data.schema, data.name) }} SET(
{% if data.autovacuum_enabled in ('t', 'f') %}
autovacuum_enabled = {% if data.autovacuum_enabled == 't' %}true{% else %}false{% endif %}{% if data['vacuum_data']['changed']|length > 0 or data.toast_autovacuum_enabled in ('t', 'f') %},
{% endif %}
{% endif %}
{% if data.toast_autovacuum_enabled in ('t', 'f') %}
toast.autovacuum_enabled = {% if data.toast_autovacuum_enabled == 't' %}true{% else %}false{% endif %}{% if data['vacuum_data']['changed']|length > 0 %},
{% endif %}
{% endif %}
{% for field in data['vacuum_data']['changed'] %}
{% if field.value != None %} {{ field.name }} = {{ field.value|lower }}{% if not loop.last %},
{% endif %}
{% endif %}
{% endfor %}
);
{% endif %}
{% if data['vacuum_data']['reset']|length > 0 or data.autovacuum_enabled == 'x' or data.toast_autovacuum_enabled == 'x' %}
ALTER MATERIALIZED VIEW IF EXISTS {{ conn|qtIdent(view_schema, view_name) }} RESET(
{% if data.autovacuum_enabled == 'x' %}
autovacuum_enabled{% if data['vacuum_data']['reset']|length > 0 or data.toast_autovacuum_enabled == 'x' %},
{% endif %}
{% endif %}
{% if data.toast_autovacuum_enabled == 'x' %}
toast.autovacuum_enabled{% if data['vacuum_data']['reset']|length > 0 %},
{% endif %}
{% endif %}
{% for field in data['vacuum_data']['reset'] %} {{ field.name }}{% if not loop.last %},
{% endif %}
{% endfor %}
);
{% endif %}
{# ===== End check for custom autovacuum ===== #}
{% 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(conn) }};
{% 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 -%}
{% if priv.grantee != priv.old_grantee %}
{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.old_grantee, data.name, data.schema) }}
{% else %}
{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
{% endif %}
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
{%- endfor %}
{% endif %}
{% if 'added' in data.datacl %}
{% for priv in data.datacl.added %}
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
{% endfor %}
{% endif %}
{% endif %}
{# ============== The SQL generated below will change Security Label ========= #}
{% if data.seclabels is not none and data.seclabels|length > 0 %}
{% set seclabels = data.seclabels %}
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
{% for r in seclabels.deleted %}
{{ SECLABEL.UNSET(conn, 'MATERIALIZED VIEW', data.name, r.provider, data.schema) }}
{% endfor %}
{% endif %}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABEL.SET(conn, 'MATERIALIZED VIEW', data.name, r.provider, r.label, data.schema) }}
{% endfor %}
{% endif %}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABEL.SET(conn, 'MATERIALIZED VIEW', data.name, r.provider, r.label, data.schema) }}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}

View File

@ -0,0 +1,214 @@
{# ===================== Update View ===================#}
{% import 'macros/schemas/security.macros' as SECLABEL %}
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
{%- if data -%}
{% set view_name = data.name if data.name else o_data.name %}
{% set view_schema = data.schema if data.schema else o_data.schema %}
{% set def = data.definition.rstrip(';') if data.definition %}
{# ===== Rename mat view ===== #}
{% if data.name and data.name != o_data.name %}
ALTER MATERIALIZED VIEW IF EXISTS {{ 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 IF EXISTS {{ 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 IF EXISTS {{ 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 IF EXISTS {{ conn|qtIdent(view_schema, view_name) }};
CREATE MATERIALIZED VIEW IF NOT EXISTS {{ conn|qtIdent(view_schema, view_name) }}
{% if data.amname and data.amname != o_data.amname%}
USING {{ data.amname }}
{% endif %}
{% if data.fillfactor or o_data.fillfactor %}
WITH(
{% if data.fillfactor %}
FILLFACTOR = {{ data.fillfactor }}{% if (data['vacuum_data'] is defined and data['vacuum_data']['changed']|length > 0) %},{% endif %}
{% elif o_data.fillfactor %}
FILLFACTOR = {{ o_data.fillfactor }}{% if (data['vacuum_data'] is defined and data['vacuum_data']['changed']|length > 0) %},{% endif %}
{% 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 %}
{% 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 is defined %}
WITH {{ 'DATA' if o_data.with_data else 'NO DATA' }};
{% endif %}
{% if o_data.owner and not data.owner %}
ALTER TABLE IF EXISTS {{ conn|qtIdent(view_schema, view_name) }}
OWNER TO {{ conn|qtIdent(o_data.owner) }};
{% endif %}
{% if o_data.comment and not data.comment %}
COMMENT ON MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
IS {{ o_data.comment|qtLiteral(conn) }};
{% endif %}
{% else %}
{# ======= Alter Tablespace ========= #}
{%- if data.spcname and o_data.spcname != data.spcname -%}
ALTER MATERIALIZED VIEW IF EXISTS {{ conn|qtIdent(view_schema, view_name) }}
SET TABLESPACE {{ data.spcname }};
{% endif %}
{# ======= SET/RESET Fillfactor ========= #}
{% if data.fillfactor and o_data.fillfactor != data.fillfactor %}
ALTER MATERIALIZED VIEW IF EXISTS {{ conn|qtIdent(view_schema, view_name) }}
SET(
FILLFACTOR = {{ data.fillfactor }}
);
{% elif data.fillfactor == '' and o_data.fillfactor|default('', 'true') != data.fillfactor %}
ALTER MATERIALIZED VIEW IF EXISTS {{ conn|qtIdent(view_schema, view_name) }}
RESET(
FILLFACTOR
);
{% endif %}
{# ======= Change Access Method ========= #}
{% if data.amname and o_data.amname != data.amname %}
ALTER MATERIALIZED VIEW IF EXISTS {{ conn|qtIdent(view_schema, view_name) }}
SET ACCESS METHOD {{ data.amname }};
{% endif %}
{# ======= Change Access Method end ========= #}
{# ===== 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 Autovacuum options ===== #}
{% if data.autovacuum_custom is defined and data.autovacuum_custom == False %}
ALTER MATERIALIZED VIEW IF EXISTS {{ 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
);
{% endif %}
{% if data.toast_autovacuum is defined and data.toast_autovacuum == False %}
ALTER MATERIALIZED VIEW IF EXISTS {{ 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
);
{% endif %}{#-- toast_endif ends --#}
{% if data['vacuum_data']['changed']|length > 0 or data.autovacuum_enabled in ('t', 'f') or data.toast_autovacuum_enabled in ('t', 'f') %}
ALTER MATERIALIZED VIEW IF EXISTS {{ conn|qtIdent(data.schema, data.name) }} SET(
{% if data.autovacuum_enabled in ('t', 'f') %}
autovacuum_enabled = {% if data.autovacuum_enabled == 't' %}true{% else %}false{% endif %}{% if data['vacuum_data']['changed']|length > 0 or data.toast_autovacuum_enabled in ('t', 'f') %},
{% endif %}
{% endif %}
{% if data.toast_autovacuum_enabled in ('t', 'f') %}
toast.autovacuum_enabled = {% if data.toast_autovacuum_enabled == 't' %}true{% else %}false{% endif %}{% if data['vacuum_data']['changed']|length > 0 %},
{% endif %}
{% endif %}
{% for field in data['vacuum_data']['changed'] %}
{% if field.value != None %} {{ field.name }} = {{ field.value|lower }}{% if not loop.last %},
{% endif %}
{% endif %}
{% endfor %}
);
{% endif %}
{% if data['vacuum_data']['reset']|length > 0 or data.autovacuum_enabled == 'x' or data.toast_autovacuum_enabled == 'x' %}
ALTER MATERIALIZED VIEW IF EXISTS {{ conn|qtIdent(view_schema, view_name) }} RESET(
{% if data.autovacuum_enabled == 'x' %}
autovacuum_enabled{% if data['vacuum_data']['reset']|length > 0 or data.toast_autovacuum_enabled == 'x' %},
{% endif %}
{% endif %}
{% if data.toast_autovacuum_enabled == 'x' %}
toast.autovacuum_enabled{% if data['vacuum_data']['reset']|length > 0 %},
{% endif %}
{% endif %}
{% for field in data['vacuum_data']['reset'] %} {{ field.name }}{% if not loop.last %},
{% endif %}
{% endfor %}
);
{% endif %}
{# ===== End check for custom autovacuum ===== #}
{% 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(conn) }};
{% 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 -%}
{% if priv.grantee != priv.old_grantee %}
{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.old_grantee, data.name, data.schema) }}
{% else %}
{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
{% endif %}
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
{%- endfor %}
{% endif %}
{% if 'added' in data.datacl %}
{% for priv in data.datacl.added %}
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
{% endfor %}
{% endif %}
{% endif %}
{# ============== The SQL generated below will change Security Label ========= #}
{% if data.seclabels is not none and data.seclabels|length > 0 %}
{% set seclabels = data.seclabels %}
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
{% for r in seclabels.deleted %}
{{ SECLABEL.UNSET(conn, 'MATERIALIZED VIEW', data.name, r.provider, data.schema) }}
{% endfor %}
{% endif %}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABEL.SET(conn, 'MATERIALIZED VIEW', data.name, r.provider, r.label, data.schema) }}
{% endfor %}
{% endif %}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABEL.SET(conn, 'MATERIALIZED VIEW', data.name, r.provider, r.label, data.schema) }}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}

View File

@ -0,0 +1,50 @@
{# ===================== Create new view ===================== #}
{% if display_comments %}
-- View: {{ 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{% if add_not_exists_clause %} IF NOT EXISTS{% endif %} {{ conn|qtIdent(data.schema, data.name) }}
{% if data.default_amname and data.default_amname != data.amname %}
USING {{data.amname}}
{% elif not data.default_amname and data.amname %}
USING {{data.amname}}
{% endif %}
{% if(data.fillfactor or data.autovacuum_enabled in ('t', 'f') or data.toast_autovacuum_enabled in ('t', 'f') or data['vacuum_data']|length > 0) %}
{% set ns = namespace(add_comma=false) %}
WITH (
{% if data.fillfactor %}
FILLFACTOR = {{ data.fillfactor }}{% set ns.add_comma = true%}{% endif %}{% if data.autovacuum_enabled in ('t', 'f') %}
{% if ns.add_comma %},
{% endif %}
autovacuum_enabled = {% if data.autovacuum_enabled == 't' %}TRUE{% else %}FALSE{% endif %}{% set ns.add_comma = true%}{% endif %}{% if data.toast_autovacuum_enabled in ('t', 'f') %}
{% if ns.add_comma %},
{% endif %}
toast.autovacuum_enabled = {% if data.toast_autovacuum_enabled == 't' %}TRUE{% else %}FALSE{% endif %}{% set ns.add_comma = true%}{% endif %}
{% for field in data['vacuum_data'] %}
{% if field.value is defined and field.value != '' and field.value != none %}
{% if ns.add_comma %},
{% endif %} {{ field.name }} = {{ field.value|lower }}{% set ns.add_comma = true%}{% endif %}{% endfor %}
{{ '\n' }})
{% 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 IF EXISTS {{ conn|qtIdent(data.schema, data.name) }}
OWNER TO {{ conn|qtIdent(data.owner) }};
{% endif %}
{% if data.comment %}
COMMENT ON MATERIALIZED VIEW {{ conn|qtIdent(data.schema, data.name) }}
IS {{ data.comment|qtLiteral(conn) }};
{% endif %}
{% endif %}

View File

@ -0,0 +1,3 @@
-- Fetches access methods
SELECT oid, amname
FROM pg_catalog.pg_am WHERE amtype = 't';

View File

@ -0,0 +1,112 @@
{# ========================== 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(spcname::text) > 0 THEN spcname ELSE
(SELECT sp.spcname FROM pg_catalog.pg_database dtb
JOIN pg_catalog.pg_tablespace sp ON dtb.dattablespace=sp.oid
WHERE dtb.oid = {{ did }}::oid)
END as spcname,
(SELECT st.setting from pg_catalog.pg_settings st
WHERE st.name = 'default_table_access_method') as default_amname,
c.relacl,
nsp.nspname as schema,
pg_catalog.pg_get_userbyid(c.relowner) AS owner,
description AS comment,
pg_catalog.pg_get_viewdef(c.oid) 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 %}
pg_catalog.array_to_string(c.relacl::text[], ', ') AS acl,
(SELECT pg_catalog.array_agg(provider || '=' || label) FROM pg_catalog.pg_seclabels sl1 WHERE sl1.objoid=c.oid AND sl1.objsubid=0) AS seclabels,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'fillfactor=([0-9]*)') AS fillfactor,
(substring(pg_catalog.array_to_string(c.reloptions, ',') FROM 'autovacuum_enabled=([a-z|0-9]*)'))::BOOL AS autovacuum_enabled,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_vacuum_threshold=([0-9]*)') AS autovacuum_vacuum_threshold,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_vacuum_scale_factor=([0-9]*[.]?[0-9]*)') AS autovacuum_vacuum_scale_factor,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_analyze_threshold=([0-9]*)') AS autovacuum_analyze_threshold,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_analyze_scale_factor=([0-9]*[.]?[0-9]*)') AS autovacuum_analyze_scale_factor,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_vacuum_cost_delay=([0-9]*)') AS autovacuum_vacuum_cost_delay,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_vacuum_cost_limit=([0-9]*)') AS autovacuum_vacuum_cost_limit,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_freeze_min_age=([0-9]*)') AS autovacuum_freeze_min_age,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_freeze_max_age=([0-9]*)') AS autovacuum_freeze_max_age,
substring(pg_catalog.array_to_string(c.reloptions, ',')
FROM 'autovacuum_freeze_table_age=([0-9]*)') AS autovacuum_freeze_table_age,
(substring(pg_catalog.array_to_string(tst.reloptions, ',') FROM 'autovacuum_enabled=([a-z|0-9]*)'))::BOOL AS toast_autovacuum_enabled,
substring(pg_catalog.array_to_string(tst.reloptions, ',')
FROM 'autovacuum_vacuum_threshold=([0-9]*)') AS toast_autovacuum_vacuum_threshold,
substring(pg_catalog.array_to_string(tst.reloptions, ',')
FROM 'autovacuum_vacuum_scale_factor=([0-9]*[.]?[0-9]*)') AS toast_autovacuum_vacuum_scale_factor,
substring(pg_catalog.array_to_string(tst.reloptions, ',')
FROM 'autovacuum_analyze_threshold=([0-9]*)') AS toast_autovacuum_analyze_threshold,
substring(pg_catalog.array_to_string(tst.reloptions, ',')
FROM 'autovacuum_analyze_scale_factor=([0-9]*[.]?[0-9]*)') AS toast_autovacuum_analyze_scale_factor,
substring(pg_catalog.array_to_string(tst.reloptions, ',')
FROM 'autovacuum_vacuum_cost_delay=([0-9]*)') AS toast_autovacuum_vacuum_cost_delay,
substring(pg_catalog.array_to_string(tst.reloptions, ',')
FROM 'autovacuum_vacuum_cost_limit=([0-9]*)') AS toast_autovacuum_vacuum_cost_limit,
substring(pg_catalog.array_to_string(tst.reloptions, ',')
FROM 'autovacuum_freeze_min_age=([0-9]*)') AS toast_autovacuum_freeze_min_age,
substring(pg_catalog.array_to_string(tst.reloptions, ',')
FROM 'autovacuum_freeze_max_age=([0-9]*)') AS toast_autovacuum_freeze_max_age,
substring(pg_catalog.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, am.amname,
(CASE WHEN c.reltoastrelid = 0 THEN false ELSE true END) AS hastoasttable
FROM
pg_catalog.pg_class c
LEFT OUTER JOIN pg_catalog.pg_namespace nsp on nsp.oid = c.relnamespace
LEFT OUTER JOIN pg_catalog.pg_tablespace spc on spc.oid=c.reltablespace
LEFT OUTER JOIN pg_catalog.pg_description des ON (des.objoid=c.oid and des.objsubid=0 AND des.classoid='pg_class'::regclass)
LEFT OUTER JOIN pg_catalog.pg_class tst ON tst.oid = c.reltoastrelid
LEFT OUTER JOIN pg_catalog.pg_am am ON am.oid = c.relam
WHERE ((c.relhasrules AND (EXISTS (
SELECT
r.rulename
FROM
pg_catalog.pg_rewrite r
WHERE
((r.ev_class = c.oid)
AND (pg_catalog.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_catalog.pg_roles pr
WHERE
pr.rolcanlogin
ORDER BY
pr.rolname
{% elif type == 'schemas' %}
SELECT
nsp.nspname
FROM
pg_catalog.pg_namespace nsp
WHERE
(nsp.nspname NOT LIKE E'pg\\_%'
AND nsp.nspname != 'information_schema')
{% endif %}

View File

@ -0,0 +1,207 @@
{# ===================== Update View ===================#}
{% import 'macros/schemas/security.macros' as SECLABEL %}
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
{%- if data -%}
{% set view_name = data.name if data.name else o_data.name %}
{% set view_schema = data.schema if data.schema else o_data.schema %}
{% set def = data.definition.rstrip(';') if data.definition %}
{# ===== Rename mat view ===== #}
{% if data.name and data.name != o_data.name %}
ALTER MATERIALIZED VIEW IF EXISTS {{ 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 IF EXISTS {{ 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 IF EXISTS {{ 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 IF EXISTS {{ conn|qtIdent(view_schema, view_name) }};
CREATE MATERIALIZED VIEW IF NOT EXISTS {{ conn|qtIdent(view_schema, view_name) }}
{% if data.amname and data.amname != o_data.amname %}
USING {{ data.amname }}
{% endif %}
{% if data.fillfactor or o_data.fillfactor %}
WITH(
{% if data.fillfactor %}
FILLFACTOR = {{ data.fillfactor }}{% if (data['vacuum_data'] is defined and data['vacuum_data']['changed']|length > 0) %},{% endif %}
{% elif o_data.fillfactor %}
FILLFACTOR = {{ o_data.fillfactor }}{% if (data['vacuum_data'] is defined and data['vacuum_data']['changed']|length > 0) %},{% endif %}
{% 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 %}
{% 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 is defined %}
WITH {{ 'DATA' if o_data.with_data else 'NO DATA' }};
{% endif %}
{% if o_data.owner and not data.owner %}
ALTER TABLE IF EXISTS {{ conn|qtIdent(view_schema, view_name) }}
OWNER TO {{ conn|qtIdent(o_data.owner) }};
{% endif %}
{% if o_data.comment and not data.comment %}
COMMENT ON MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
IS {{ o_data.comment|qtLiteral(conn) }};
{% endif %}
{% else %}
{# ======= Alter Tablespace ========= #}
{%- if data.spcoid and o_data.spcoid != data.spcoid -%}
ALTER MATERIALIZED VIEW IF EXISTS {{ 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 IF EXISTS {{ conn|qtIdent(view_schema, view_name) }}
SET(
FILLFACTOR = {{ data.fillfactor }}
);
{% elif data.fillfactor == '' and o_data.fillfactor|default('', 'true') != data.fillfactor %}
ALTER MATERIALIZED VIEW IF EXISTS {{ 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 Autovacuum options ===== #}
{% if data.autovacuum_custom is defined and data.autovacuum_custom == False %}
ALTER MATERIALIZED VIEW IF EXISTS {{ 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
);
{% endif %}
{% if data.toast_autovacuum is defined and data.toast_autovacuum == False %}
ALTER MATERIALIZED VIEW IF EXISTS {{ 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
);
{% endif %}{#-- toast_endif ends --#}
{% if data['vacuum_data']['changed']|length > 0 or data.autovacuum_enabled in ('t', 'f') or data.toast_autovacuum_enabled in ('t', 'f') %}
ALTER MATERIALIZED VIEW IF EXISTS {{ conn|qtIdent(data.schema, data.name) }} SET(
{% if data.autovacuum_enabled in ('t', 'f') %}
autovacuum_enabled = {% if data.autovacuum_enabled == 't' %}true{% else %}false{% endif %}{% if data['vacuum_data']['changed']|length > 0 or data.toast_autovacuum_enabled in ('t', 'f') %},
{% endif %}
{% endif %}
{% if data.toast_autovacuum_enabled in ('t', 'f') %}
toast.autovacuum_enabled = {% if data.toast_autovacuum_enabled == 't' %}true{% else %}false{% endif %}{% if data['vacuum_data']['changed']|length > 0 %},
{% endif %}
{% endif %}
{% for field in data['vacuum_data']['changed'] %}
{% if field.value != None %} {{ field.name }} = {{ field.value|lower }}{% if not loop.last %},
{% endif %}
{% endif %}
{% endfor %}
);
{% endif %}
{% if data['vacuum_data']['reset']|length > 0 or data.autovacuum_enabled == 'x' or data.toast_autovacuum_enabled == 'x' %}
ALTER MATERIALIZED VIEW IF EXISTS {{ conn|qtIdent(view_schema, view_name) }} RESET(
{% if data.autovacuum_enabled == 'x' %}
autovacuum_enabled{% if data['vacuum_data']['reset']|length > 0 or data.toast_autovacuum_enabled == 'x' %},
{% endif %}
{% endif %}
{% if data.toast_autovacuum_enabled == 'x' %}
toast.autovacuum_enabled{% if data['vacuum_data']['reset']|length > 0 %},
{% endif %}
{% endif %}
{% for field in data['vacuum_data']['reset'] %} {{ field.name }}{% if not loop.last %},
{% endif %}
{% endfor %}
);
{% endif %}
{# ===== End check for custom autovacuum ===== #}
{% 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(conn) }};
{% 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 -%}
{% if priv.grantee != priv.old_grantee %}
{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.old_grantee, data.name, data.schema) }}
{% else %}
{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
{% endif %}
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
{%- endfor %}
{% endif %}
{% if 'added' in data.datacl %}
{% for priv in data.datacl.added %}
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
{% endfor %}
{% endif %}
{% endif %}
{# ============== The SQL generated below will change Security Label ========= #}
{% if data.seclabels is not none and data.seclabels|length > 0 %}
{% set seclabels = data.seclabels %}
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
{% for r in seclabels.deleted %}
{{ SECLABEL.UNSET(conn, 'MATERIALIZED VIEW', data.name, r.provider, data.schema) }}
{% endfor %}
{% endif %}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABEL.SET(conn, 'MATERIALIZED VIEW', data.name, r.provider, r.label, data.schema) }}
{% endfor %}
{% endif %}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABEL.SET(conn, 'MATERIALIZED VIEW', data.name, r.provider, r.label, data.schema) }}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}

View File

@ -0,0 +1,214 @@
{# ===================== Update View ===================#}
{% import 'macros/schemas/security.macros' as SECLABEL %}
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
{%- if data -%}
{% set view_name = data.name if data.name else o_data.name %}
{% set view_schema = data.schema if data.schema else o_data.schema %}
{% set def = data.definition.rstrip(';') if data.definition %}
{# ===== Rename mat view ===== #}
{% if data.name and data.name != o_data.name %}
ALTER MATERIALIZED VIEW IF EXISTS {{ 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 IF EXISTS {{ 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 IF EXISTS {{ 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 IF EXISTS {{ conn|qtIdent(view_schema, view_name) }};
CREATE MATERIALIZED VIEW IF NOT EXISTS {{ conn|qtIdent(view_schema, view_name) }}
{% if data.amname and data.amname != o_data.amname%}
USING {{ data.amname }}
{% endif %}
{% if data.fillfactor or o_data.fillfactor %}
WITH(
{% if data.fillfactor %}
FILLFACTOR = {{ data.fillfactor }}{% if (data['vacuum_data'] is defined and data['vacuum_data']['changed']|length > 0) %},{% endif %}
{% elif o_data.fillfactor %}
FILLFACTOR = {{ o_data.fillfactor }}{% if (data['vacuum_data'] is defined and data['vacuum_data']['changed']|length > 0) %},{% endif %}
{% 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 %}
{% 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 is defined %}
WITH {{ 'DATA' if o_data.with_data else 'NO DATA' }};
{% endif %}
{% if o_data.owner and not data.owner %}
ALTER TABLE IF EXISTS {{ conn|qtIdent(view_schema, view_name) }}
OWNER TO {{ conn|qtIdent(o_data.owner) }};
{% endif %}
{% if o_data.comment and not data.comment %}
COMMENT ON MATERIALIZED VIEW {{ conn|qtIdent(view_schema, view_name) }}
IS {{ o_data.comment|qtLiteral(conn) }};
{% endif %}
{% else %}
{# ======= Alter Tablespace ========= #}
{%- if data.spcoid and o_data.spcoid != data.spcoid -%}
ALTER MATERIALIZED VIEW IF EXISTS {{ 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 IF EXISTS {{ conn|qtIdent(view_schema, view_name) }}
SET(
FILLFACTOR = {{ data.fillfactor }}
);
{% elif data.fillfactor == '' and o_data.fillfactor|default('', 'true') != data.fillfactor %}
ALTER MATERIALIZED VIEW IF EXISTS {{ conn|qtIdent(view_schema, view_name) }}
RESET(
FILLFACTOR
);
{% endif %}
{# ======= Change Access Method ========= #}
{% if data.amname and o_data.amname != data.amname %}
ALTER MATERIALIZED VIEW IF EXISTS {{ conn|qtIdent(view_schema, view_name) }}
SET ACCESS Method {{ data.amname }};
{% endif %}
{# ======= Change Access Method end ========= #}
{# ===== 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 Autovacuum options ===== #}
{% if data.autovacuum_custom is defined and data.autovacuum_custom == False %}
ALTER MATERIALIZED VIEW IF EXISTS {{ 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
);
{% endif %}
{% if data.toast_autovacuum is defined and data.toast_autovacuum == False %}
ALTER MATERIALIZED VIEW IF EXISTS {{ 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
);
{% endif %}{#-- toast_endif ends --#}
{% if data['vacuum_data']['changed']|length > 0 or data.autovacuum_enabled in ('t', 'f') or data.toast_autovacuum_enabled in ('t', 'f') %}
ALTER MATERIALIZED VIEW IF EXISTS {{ conn|qtIdent(data.schema, data.name) }} SET(
{% if data.autovacuum_enabled in ('t', 'f') %}
autovacuum_enabled = {% if data.autovacuum_enabled == 't' %}true{% else %}false{% endif %}{% if data['vacuum_data']['changed']|length > 0 or data.toast_autovacuum_enabled in ('t', 'f') %},
{% endif %}
{% endif %}
{% if data.toast_autovacuum_enabled in ('t', 'f') %}
toast.autovacuum_enabled = {% if data.toast_autovacuum_enabled == 't' %}true{% else %}false{% endif %}{% if data['vacuum_data']['changed']|length > 0 %},
{% endif %}
{% endif %}
{% for field in data['vacuum_data']['changed'] %}
{% if field.value != None %} {{ field.name }} = {{ field.value|lower }}{% if not loop.last %},
{% endif %}
{% endif %}
{% endfor %}
);
{% endif %}
{% if data['vacuum_data']['reset']|length > 0 or data.autovacuum_enabled == 'x' or data.toast_autovacuum_enabled == 'x' %}
ALTER MATERIALIZED VIEW IF EXISTS {{ conn|qtIdent(view_schema, view_name) }} RESET(
{% if data.autovacuum_enabled == 'x' %}
autovacuum_enabled{% if data['vacuum_data']['reset']|length > 0 or data.toast_autovacuum_enabled == 'x' %},
{% endif %}
{% endif %}
{% if data.toast_autovacuum_enabled == 'x' %}
toast.autovacuum_enabled{% if data['vacuum_data']['reset']|length > 0 %},
{% endif %}
{% endif %}
{% for field in data['vacuum_data']['reset'] %} {{ field.name }}{% if not loop.last %},
{% endif %}
{% endfor %}
);
{% endif %}
{# ===== End check for custom autovacuum ===== #}
{% 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(conn) }};
{% 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 -%}
{% if priv.grantee != priv.old_grantee %}
{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.old_grantee, data.name, data.schema) }}
{% else %}
{{ PRIVILEGE.UNSETALL(conn, 'TABLE', priv.grantee, data.name, data.schema) }}
{% endif %}
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
{%- endfor %}
{% endif %}
{% if 'added' in data.datacl %}
{% for priv in data.datacl.added %}
{{ PRIVILEGE.SET(conn, 'TABLE', priv.grantee, data.name, priv.without_grant, priv.with_grant, data.schema) }}
{% endfor %}
{% endif %}
{% endif %}
{# ============== The SQL generated below will change Security Label ========= #}
{% if data.seclabels is not none and data.seclabels|length > 0 %}
{% set seclabels = data.seclabels %}
{% if 'deleted' in seclabels and seclabels.deleted|length > 0 %}
{% for r in seclabels.deleted %}
{{ SECLABEL.UNSET(conn, 'MATERIALIZED VIEW', data.name, r.provider, data.schema) }}
{% endfor %}
{% endif %}
{% if 'added' in seclabels and seclabels.added|length > 0 %}
{% for r in seclabels.added %}
{{ SECLABEL.SET(conn, 'MATERIALIZED VIEW', data.name, r.provider, r.label, data.schema) }}
{% endfor %}
{% endif %}
{% if 'changed' in seclabels and seclabels.changed|length > 0 %}
{% for r in seclabels.changed %}
{{ SECLABEL.SET(conn, 'MATERIALIZED VIEW', data.name, r.provider, r.label, data.schema) }}
{% endfor %}
{% endif %}
{% endif %}
{% endif %}

View File

@ -0,0 +1,12 @@
CREATE MATERIALIZED VIEW public."testmview_am_$%{}[]()&*^!/@`#"
USING heap
TABLESPACE pg_default
AS
SELECT 1 AS col1
WITH NO DATA;
ALTER TABLE IF EXISTS public."testmview_am_$%{}[]()&*^!/@`#"
OWNER TO postgres;
COMMENT ON MATERIALIZED VIEW public."testmview_am_$%{}[]()&*^!/@`#"
IS 'comment1';

View File

@ -0,0 +1,279 @@
{
"scenarios": [
{
"type": "create",
"name": "Create Materialised Views",
"endpoint": "NODE-mview.obj",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql",
"data": {
"spcname": "pg_default",
"schema": "public",
"owner": "postgres",
"datacl": [],
"seclabels": [],
"name": "testmview_$%{}[]()&*^!/@`#",
"comment": "comment1",
"definition": "SELECT 1 AS col1"
},
"expected_sql_file": "create_mview.sql",
"expected_msql_file": "create_mview_msql.sql"
},
{
"type": "alter",
"name": "Alter Materialised Views (Adding privileges)",
"endpoint": "NODE-mview.obj_id",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql_id",
"data": {
"datacl": {
"added": [
{
"grantee": "PUBLIC",
"grantor": "postgres",
"privileges": [
{
"privilege_type": "a",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "w",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "d",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "D",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "x",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "t",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_mview.sql",
"expected_msql_file": "alter_mview_msql.sql"
},
{
"type": "alter",
"name": "Alter Materialised Views (Remove all privileges)",
"endpoint": "NODE-mview.obj_id",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql_id",
"data": {
"datacl": {
"deleted": [
{
"grantee": "PUBLIC",
"grantor": "postgres",
"privileges": [
{
"privilege_type": "a",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "w",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "d",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "D",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "x",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "t",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_mview_drop_all_priv.sql",
"expected_msql_file": "alter_mview_drop_all_priv_msql.sql"
},
{
"type": "alter",
"name": "Alter Materialised Views (change grantee in privileges)",
"endpoint": "NODE-mview.obj_id",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql_id",
"data": {
"datacl": {
"changed": [
{
"grantee": "PUBLIC",
"grantor": "postgres",
"old_grantee": "postgres",
"privileges": [
{
"privilege_type": "a",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "w",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "d",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "D",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "x",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "t",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_mview_change_grantee_priv.sql",
"expected_msql_file": "alter_mview_change_grantee_priv_msql.sql"
},
{
"type": "alter",
"name": "Alter Materialised Views (change definition)",
"endpoint": "NODE-mview.obj_id",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql_id",
"data": {
"definition": "SELECT 12 AS col1;"
},
"expected_sql_file": "alter_mview_definition.sql",
"expected_msql_file": "alter_mview_definition_msql.sql"
},
{
"type": "alter",
"name": "Alter Materialised Views (Fillfactor)",
"endpoint": "NODE-mview.obj_id",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql_id",
"data": {
"fillfactor": "18",
"with_data": true
},
"expected_sql_file": "alter_mview_add_fillfactor.sql",
"expected_msql_file": "alter_mview_add_fillfactor_msql.sql"
},
{
"type": "alter",
"name": "Alter Materialised Views (add table parameters)",
"endpoint": "NODE-mview.obj_id",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql_id",
"data": {
"autovacuum_custom": true,
"autovacuum_enabled": "t",
"vacuum_table": {
"changed": [
{
"name": "autovacuum_analyze_scale_factor",
"value": 0.2
}
]
}
},
"expected_sql_file": "alter_mview_add_table_parameter.sql",
"expected_msql_file": "alter_mview_add_table_parameter_msql.sql"
},
{
"type": "alter",
"name": "Alter Materialised Views (remove table parameters)",
"endpoint": "NODE-mview.obj_id",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql_id",
"data": {
"autovacuum_custom": true,
"autovacuum_enabled": "x",
"vacuum_table": {
"changed": [
{
"name": "autovacuum_analyze_scale_factor",
"value": null
}
]
}
},
"expected_sql_file": "alter_mview_remove_table_parameter.sql",
"expected_msql_file": "alter_mview_remove_table_parameter_msql.sql"
},
{
"type": "create",
"name": "Create Materialised Views with access method",
"endpoint": "NODE-mview.obj",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql",
"data": {
"spcname": "pg_default",
"schema": "public",
"owner": "postgres",
"datacl": [],
"seclabels": [],
"name": "testmview_am_$%{}[]()&*^!/@`#",
"comment": "comment1",
"definition": "SELECT 1 AS col1",
"amname": "heap"
},
"expected_msql_file": "create_mview_with_am_msql.sql"
}
]
}

View File

@ -0,0 +1,224 @@
{
"scenarios": [
{
"type": "create",
"name": "Create Table for Views",
"endpoint": "NODE-table.obj",
"sql_endpoint": "NODE-table.sql_id",
"data": {
"name": "test_view_table",
"check_constraint": [],
"coll_inherits": "[]",
"columns": [
{
"name": "col1",
"cltype": "integer"
}
],
"schema": "public"
}
},
{
"type": "create",
"name": "Create View",
"endpoint": "NODE-view.obj",
"sql_endpoint": "NODE-view.sql_id",
"msql_endpoint": "NODE-view.msql",
"data": {
"definition": "select col1 from test_view_table;",
"name": "testview_$%{}[]()&*^!@\"'`\\/#",
"owner": "postgres",
"schema": "public",
"check_option": "local",
"security_barrier": false,
"comment":"Testcomment",
"datacl":[{"grantee":"postgres", "old_grantee": "postgres", "grantor":"postgres", "privileges":[{"privilege_type": "a", "privilege": true,
"with_grant":false}]}]
},
"expected_sql_file": "create_view.sql",
"expected_msql_file": "create_view_msql.sql"
},
{
"type": "alter",
"name": "Alter View",
"endpoint": "NODE-view.obj_id",
"sql_endpoint": "NODE-view.sql_id",
"msql_endpoint": "NODE-view.msql_id",
"data": {
"name": "testview_$%{}[]()&*^!@\"'`\\/#",
"owner": "postgres",
"schema": "public",
"check_option": "cascaded",
"security_barrier": true,
"comment":"Testcomment-updated",
"datacl":[{"grantee":"postgres", "grantor":"postgres", "old_grantee": "postgres", "privileges":[{"privilege_type": "a", "privilege": true,
"with_grant":false}]}]
},
"expected_sql_file": "alter_view.sql",
"expected_msql_file": "alter_view_msql.sql"
},
{
"type": "alter",
"name": "Alter View (changing code)",
"endpoint": "NODE-view.obj_id",
"sql_endpoint": "NODE-view.sql_id",
"msql_endpoint": "NODE-view.msql_id",
"data": {
"definition": "SELECT * FROM test_view_table;"
},
"expected_sql_file": "alter_view_definition.sql",
"expected_msql_file": "alter_view_definition_msql.sql"
},
{
"type": "alter",
"name": "Alter View (adding privileges)",
"endpoint": "NODE-view.obj_id",
"sql_endpoint": "NODE-view.sql_id",
"msql_endpoint": "NODE-view.msql_id",
"data": {
"name": "testview_$%{}[]()&*^!@\"'`\\/#",
"owner": "postgres",
"schema": "public",
"check_option": "cascaded",
"security_barrier": true,
"comment":"Testcomment-updated",
"datacl":{
"added":[
{
"grantee":"PUBLIC",
"grantor":"postgres",
"privileges":[
{
"privilege_type":"r",
"privilege":true,
"with_grant":false
}
]
}
]
}
},
"expected_sql_file": "alter_view_add_some_priv.sql",
"expected_msql_file": "alter_view_add_some_priv_msql.sql"
},
{
"type": "alter",
"name": "Alter View (deleting privileges (PUBLIC))",
"endpoint": "NODE-view.obj_id",
"sql_endpoint": "NODE-view.sql_id",
"msql_endpoint": "NODE-view.msql_id",
"data": {
"name": "testview_$%{}[]()&*^!@\"'`\\/#",
"owner": "postgres",
"schema": "public",
"check_option": "cascaded",
"security_barrier": true,
"comment":"Testcomment-updated",
"datacl":
{
"deleted":[
{
"grantee":"PUBLIC",
"grantor":"postgres",
"privileges":[
{
"privilege_type":"r",
"privilege":true,
"with_grant":false
}
]
}
]
}
}
},
{
"type": "alter",
"name": "Alter View (changing privileges (postgres to PUBLIC))",
"endpoint": "NODE-view.obj_id",
"sql_endpoint": "NODE-view.sql_id",
"msql_endpoint": "NODE-view.msql_id",
"data": {
"name": "testview_$%{}[]()&*^!@\"'`\\/#",
"owner": "postgres",
"schema": "public",
"check_option": "cascaded",
"security_barrier": true,
"comment":"Testcomment-updated",
"datacl":
{
"changed":[
{
"grantee":"PUBLIC",
"grantor":"postgres",
"old_grantee": "postgres",
"privileges":[
{
"privilege_type":"r",
"privilege":true,
"with_grant":false
}
]
}
]
}
},
"expected_sql_file": "alter_view_update_priv.sql",
"expected_msql_file": "alter_view_update_priv_msql.sql"
},
{
"type": "alter",
"name": "Alter View (deleting privileges)",
"endpoint": "NODE-view.obj_id",
"sql_endpoint": "NODE-view.sql_id",
"msql_endpoint": "NODE-view.msql_id",
"data": {
"name": "testview_$%{}[]()&*^!@\"'`\\/#",
"owner": "postgres",
"schema": "public",
"check_option": "cascaded",
"security_barrier": true,
"comment":"Testcomment-updated",
"datacl":
{
"deleted":[
{
"grantee":"PUBLIC",
"grantor":"postgres",
"privileges":[
{
"privilege_type":"r",
"privilege":true,
"with_grant":false
}
]
}
]
}
},
"expected_sql_file": "alter_view_delete_priv.sql",
"expected_msql_file": "alter_view_delete_priv_msql.sql"
},
{
"type": "delete",
"name": "Drop View",
"endpoint": "NODE-view.obj_id",
"data": {
"name": "testview_$%{}[]()&*^!@\"'`\\/#",
"owner": "postgres",
"schema": "public"
}
},
{
"type": "delete",
"name": "Drop Table for view",
"endpoint": "NODE-table.obj_id",
"data": {
"name": "test_view_table",
"owner": "postgres",
"schema": "public"
}
}
]
}

View File

@ -254,6 +254,25 @@
},
"expected_sql_file": "alter_mview_remove_table_parameter.sql",
"expected_msql_file": "alter_mview_remove_table_parameter_msql.sql"
},
{
"type": "create",
"name": "Create Materialised Views with access method",
"endpoint": "NODE-mview.obj",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql",
"data": {
"spcname": "pg_default",
"schema": "public",
"owner": "postgres",
"datacl": [],
"seclabels": [],
"name": "testmview_am_$%{}[]()&*^!/@`#",
"comment": "comment1",
"definition": "SELECT 1 AS col1",
"amname": "heap"
},
"expected_msql_file": "create_mview_with_am_msql.sql"
}
]
}

View File

@ -254,6 +254,25 @@
},
"expected_sql_file": "alter_mview_remove_table_parameter.sql",
"expected_msql_file": "alter_mview_remove_table_parameter_msql.sql"
},
{
"type": "create",
"name": "Create Materialised Views with access method",
"endpoint": "NODE-mview.obj",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql",
"data": {
"spcname": "pg_default",
"schema": "public",
"owner": "postgres",
"datacl": [],
"seclabels": [],
"name": "testmview_am_$%{}[]()&*^!/@`#",
"comment": "comment1",
"definition": "SELECT 1 AS col1",
"amname": "heap"
},
"expected_msql_file": "create_mview_with_am_msql.sql"
}
]
}

View File

@ -0,0 +1,12 @@
CREATE MATERIALIZED VIEW public."testmview_am_$%{}[]()&*^!/@`#"
USING heap
TABLESPACE pg_default
AS
SELECT 1 AS col1
WITH NO DATA;
ALTER TABLE IF EXISTS public."testmview_am_$%{}[]()&*^!/@`#"
OWNER TO enterprisedb;
COMMENT ON MATERIALIZED VIEW public."testmview_am_$%{}[]()&*^!/@`#"
IS 'comment1';

View File

@ -0,0 +1,279 @@
{
"scenarios": [
{
"type": "create",
"name": "Create Materialised Views",
"endpoint": "NODE-mview.obj",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql",
"data": {
"spcname": "pg_default",
"schema": "public",
"owner": "enterprisedb",
"datacl": [],
"seclabels": [],
"name": "testmview_$%{}[]()&*^!/@`#",
"comment": "comment1",
"definition": "SELECT 1 AS col1"
},
"expected_sql_file": "create_mview.sql",
"expected_msql_file": "create_mview_msql.sql"
},
{
"type": "alter",
"name": "Alter Materialised Views (Adding privileges)",
"endpoint": "NODE-mview.obj_id",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql_id",
"data": {
"datacl": {
"added": [
{
"grantee": "PUBLIC",
"grantor": "enterprisedb",
"privileges": [
{
"privilege_type": "a",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "w",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "d",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "D",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "x",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "t",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_mview.sql",
"expected_msql_file": "alter_mview_msql.sql"
},
{
"type": "alter",
"name": "Alter Materialised Views (Remove all privileges)",
"endpoint": "NODE-mview.obj_id",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql_id",
"data": {
"datacl": {
"deleted": [
{
"grantee": "PUBLIC",
"grantor": "enterprisedb",
"privileges": [
{
"privilege_type": "a",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "w",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "d",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "D",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "x",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "t",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_mview_drop_all_priv.sql",
"expected_msql_file": "alter_mview_drop_all_priv_msql.sql"
},
{
"type": "alter",
"name": "Alter Materialised Views (change grantee in privileges)",
"endpoint": "NODE-mview.obj_id",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql_id",
"data": {
"datacl": {
"changed": [
{
"grantee": "PUBLIC",
"grantor": "enterprisedb",
"old_grantee": "enterprisedb",
"privileges": [
{
"privilege_type": "a",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "r",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "w",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "d",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "D",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "x",
"privilege": true,
"with_grant": false
},
{
"privilege_type": "t",
"privilege": true,
"with_grant": false
}
]
}
]
}
},
"expected_sql_file": "alter_mview_change_grantee_priv.sql",
"expected_msql_file": "alter_mview_change_grantee_priv_msql.sql"
},
{
"type": "alter",
"name": "Alter Materialised Views (change definition)",
"endpoint": "NODE-mview.obj_id",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql_id",
"data": {
"definition": "SELECT 12 AS col1;"
},
"expected_sql_file": "alter_mview_definition.sql",
"expected_msql_file": "alter_mview_definition_msql.sql"
},
{
"type": "alter",
"name": "Alter Materialised Views (Fillfactor)",
"endpoint": "NODE-mview.obj_id",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql_id",
"data": {
"fillfactor": "18",
"with_data": true
},
"expected_sql_file": "alter_mview_add_fillfactor.sql",
"expected_msql_file": "alter_mview_add_fillfactor_msql.sql"
},
{
"type": "alter",
"name": "Alter Materialised Views (add table parameters)",
"endpoint": "NODE-mview.obj_id",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql_id",
"data": {
"autovacuum_custom": true,
"autovacuum_enabled": "t",
"vacuum_table": {
"changed": [
{
"name": "autovacuum_analyze_scale_factor",
"value": 0.2
}
]
}
},
"expected_sql_file": "alter_mview_add_table_parameter.sql",
"expected_msql_file": "alter_mview_add_table_parameter_msql.sql"
},
{
"type": "alter",
"name": "Alter Materialised Views (remove table parameters)",
"endpoint": "NODE-mview.obj_id",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql_id",
"data": {
"autovacuum_custom": true,
"autovacuum_enabled": "x",
"vacuum_table": {
"changed": [
{
"name": "autovacuum_analyze_scale_factor",
"value": null
}
]
}
},
"expected_sql_file": "alter_mview_remove_table_parameter.sql",
"expected_msql_file": "alter_mview_remove_table_parameter_msql.sql"
},
{
"type": "create",
"name": "Create Materialised Views with access method",
"endpoint": "NODE-mview.obj",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql",
"data": {
"spcname": "pg_default",
"schema": "public",
"owner": "enterprisedb",
"datacl": [],
"seclabels": [],
"name": "testmview_am_$%{}[]()&*^!/@`#",
"comment": "comment1",
"definition": "SELECT 1 AS col1",
"amname": "heap"
},
"expected_msql_file": "create_mview_with_am_msql.sql"
}
]
}

View File

@ -0,0 +1,206 @@
{
"scenarios": [
{
"type": "create",
"name": "Create Table for Views",
"endpoint": "NODE-table.obj",
"sql_endpoint": "NODE-table.sql_id",
"data": {
"name": "test_view_table",
"check_constraint": [],
"coll_inherits": "[]",
"columns": [
{
"name": "col1",
"cltype": "integer"
}
],
"schema": "public"
}
},
{
"type": "create",
"name": "Create View",
"endpoint": "NODE-view.obj",
"sql_endpoint": "NODE-view.sql_id",
"msql_endpoint": "NODE-view.msql",
"data": {
"definition": "select col1 from test_view_table;",
"name": "testview_$%{}[]()&*^!@\"'`\\/#",
"owner": "enterprisedb",
"schema": "public",
"check_option": "local",
"security_barrier": false,
"comment":"Testcomment",
"datacl":[{"grantee":"enterprisedb", "grantor":"enterprisedb", "privileges":[{"privilege_type": "a", "privilege": true,
"with_grant":false}]}]
},
"expected_sql_file": "create_view.sql",
"expected_msql_file": "create_view_msql.sql"
},
{
"type": "alter",
"name": "Alter View",
"endpoint": "NODE-view.obj_id",
"sql_endpoint": "NODE-view.sql_id",
"msql_endpoint": "NODE-view.msql_id",
"data": {
"name": "testview_$%{}[]()&*^!@\"'`\\/#",
"owner": "enterprisedb",
"schema": "public",
"check_option": "cascaded",
"security_barrier": true,
"comment":"Testcomment-updated",
"datacl":[{"grantee":"enterprisedb", "grantor":"enterprisedb", "privileges":[{"privilege_type": "a", "privilege": true,
"with_grant":false}]}]
},
"expected_sql_file": "alter_view.sql",
"expected_msql_file": "alter_view_msql.sql"
},
{
"type": "alter",
"name": "Alter View (adding privileges)",
"endpoint": "NODE-view.obj_id",
"sql_endpoint": "NODE-view.sql_id",
"msql_endpoint": "NODE-view.msql_id",
"data": {
"datacl":{
"added":[
{
"grantee":"PUBLIC",
"grantor":"enterprisedb",
"privileges":[
{
"privilege_type":"r",
"privilege":true,
"with_grant":false
}
]
}
]
}
},
"expected_sql_file": "alter_view_add_some_priv.sql",
"expected_msql_file": "alter_view_add_some_priv_msql.sql"
},
{
"type": "alter",
"name": "Alter View (deleting privileges (PUBLIC))",
"endpoint": "NODE-view.obj_id",
"sql_endpoint": "NODE-view.sql_id",
"msql_endpoint": "NODE-view.msql_id",
"data": {
"name": "testview_$%{}[]()&*^!@\"'`\\/#",
"owner": "enterprisedb",
"schema": "public",
"check_option": "cascaded",
"security_barrier": true,
"comment":"Testcomment-updated",
"datacl":
{
"deleted":[
{
"grantee":"PUBLIC",
"grantor":"enterprisedb",
"privileges":[
{
"privilege_type":"r",
"privilege":true,
"with_grant":false
}
]
}
]
}
}
},
{
"type": "alter",
"name": "Alter View (changing privileges (enterprisedb to PUBLIC))",
"endpoint": "NODE-view.obj_id",
"sql_endpoint": "NODE-view.sql_id",
"msql_endpoint": "NODE-view.msql_id",
"data": {
"name": "testview_$%{}[]()&*^!@\"'`\\/#",
"owner": "enterprisedb",
"schema": "public",
"check_option": "cascaded",
"security_barrier": true,
"comment":"Testcomment-updated",
"datacl":
{
"changed":[
{
"grantee":"PUBLIC",
"grantor":"enterprisedb",
"old_grantee": "enterprisedb",
"privileges":[
{
"privilege_type":"r",
"privilege":true,
"with_grant":false
}
]
}
]
}
},
"expected_sql_file": "alter_view_update_priv.sql",
"expected_msql_file": "alter_view_update_priv_msql.sql"
},
{
"type": "alter",
"name": "Alter View (deleting privileges)",
"endpoint": "NODE-view.obj_id",
"sql_endpoint": "NODE-view.sql_id",
"msql_endpoint": "NODE-view.msql_id",
"data": {
"name": "testview_$%{}[]()&*^!@\"'`\\/#",
"owner": "enterprisedb",
"schema": "public",
"check_option": "cascaded",
"security_barrier": true,
"comment":"Testcomment-updated",
"datacl":
{
"deleted":[
{
"grantee":"PUBLIC",
"grantor":"enterprisedb",
"privileges":[
{
"privilege_type":"r",
"privilege":true,
"with_grant":false
}
]
}
]
}
},
"expected_sql_file": "alter_view_delete_priv.sql",
"expected_msql_file": "alter_view_delete_priv_msql.sql"
},
{
"type": "delete",
"name": "Drop View",
"endpoint": "NODE-view.obj_id",
"data": {
"name": "testview_$%{}[]()&*^!@\"'`\\/#",
"owner": "enterprisedb",
"schema": "public"
}
},
{
"type": "delete",
"name": "Drop Table for view",
"endpoint": "NODE-table.obj_id",
"data": {
"name": "test_view_table",
"owner": "enterprisedb",
"schema": "public"
}
}
]
}

View File

@ -254,6 +254,25 @@
},
"expected_sql_file": "alter_mview_remove_table_parameter.sql",
"expected_msql_file": "alter_mview_remove_table_parameter_msql.sql"
},
{
"type": "create",
"name": "Create Materialised Views with access method",
"endpoint": "NODE-mview.obj",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql",
"data": {
"spcname": "pg_default",
"schema": "public",
"owner": "postgres",
"datacl": [],
"seclabels": [],
"name": "testmview_am_$%{}[]()&*^!/@`#",
"comment": "comment1",
"definition": "SELECT 1 AS col1",
"amname": "heap"
},
"expected_msql_file": "create_mview_with_am_msql.sql"
}
]
}

View File

@ -254,6 +254,25 @@
},
"expected_sql_file": "alter_mview_remove_table_parameter.sql",
"expected_msql_file": "alter_mview_remove_table_parameter_msql.sql"
},
{
"type": "create",
"name": "Create Materialised Views with access method",
"endpoint": "NODE-mview.obj",
"sql_endpoint": "NODE-mview.sql_id",
"msql_endpoint": "NODE-mview.msql",
"data": {
"spcname": "pg_default",
"schema": "public",
"owner": "postgres",
"datacl": [],
"seclabels": [],
"name": "testmview_am_$%{}[]()&*^!/@`#",
"comment": "comment1",
"definition": "SELECT 1 AS col1",
"amname": "heap"
},
"expected_msql_file": "create_mview_with_am_msql.sql"
}
]
}

View File

@ -40,6 +40,7 @@ describe('MaterializedViewSchema', ()=>{
/* https://material-ui.com/guides/testing/#api */
beforeAll(()=>{
mount = createMount();
spyOn(schemaObj, 'getServerVersion').and.returnValue(100000);
});
afterAll(() => {
@ -68,7 +69,7 @@ describe('MaterializedViewSchema', ()=>{
state.definition = null;
schemaObj.validate(state, setError);
expect(setError).toHaveBeenCalledWith('definition', 'Please enter view definition.');
expect(setError).toHaveBeenCalledWith('definition', 'Please enter view code.');
state.definition = 'SELECT 1;';
schemaObj.validate(state, setError);