Add support of DEPENDS/NO DEPENDS ON EXTENSION for INDEX. #6388

pull/9347/head^2
Rohit Bhati 2025-11-19 12:32:35 +05:30 committed by GitHub
parent 4129d38410
commit f06668aed9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 508 additions and 32 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

@ -48,6 +48,9 @@ Use the fields in the *Definition* tab to define the index:
* Select *brin* to create a BRIN index. A BRIN index may improve
performance when managing minimum and maximum values and ranges.
* Use the drop-down listbox next to *Depends on extensions* to select the extension
that this index depends on (for example, edbspl). If set, dropping the extension
will automatically drop the index as well.
* Use the *Fill Factor* field to specify a fill factor for the index. The fill
factor specifies how full the selected method will try to fill each index
page.

View File

@ -10,7 +10,7 @@ the REFRESH MATERIALIZED VIEW command to update the content of a materialized
view.
The *Materialized View* dialog organizes the development of a materialized_view
through the following dialog tabs: *General*, *Definition*, *Storage*,
through the following dialog tabs: *General*, *Definition*, *Code*,
*Parameter*, and *Security*. The *SQL* tab displays the SQL code generated by
dialog selections.
@ -31,10 +31,10 @@ 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 storage tab
:alt: Materialized view dialog definition tab
:align: center
Use the fields in the *Storage* tab to maintain the materialized view:
Use the fields in the *Definition* tab to maintain the materialized view:
* Move the *With Data* switch to the *Yes* position to specify the materialized
view should be populated at creation time. If not, the materialized view
@ -54,7 +54,7 @@ Use the fields in the *Storage* tab to maintain the materialized view:
Click the *Code* tab to continue.
.. image:: images/materialized_view_code.png
:alt: Materialized view dialog definition tab
:alt: Materialized view dialog code tab
:align: center
Use the text editor field in the *Code* tab to provide the query that will

View File

@ -125,6 +125,8 @@ define('pgadmin.node.index', [
},
getSchema: (treeNodeInfo, itemNodeData) => {
let nodeObj = pgAdmin.Browser.Nodes['index'];
let nodeExtObj = pgBrowser.Nodes['extension'];
return new IndexSchema(
{
tablespaceList: ()=>getNodeListByName('tablespace', treeNodeInfo, itemNodeData, {}, (m)=>{
@ -133,7 +135,17 @@ define('pgadmin.node.index', [
amnameList : ()=>getNodeAjaxOptions('get_access_methods', nodeObj, treeNodeInfo, itemNodeData, {jumpAfterNode: 'schema'}),
columnList: ()=>getNodeListByName('column', treeNodeInfo, itemNodeData, {}),
collationList: ()=>getNodeAjaxOptions('get_collations', nodeObj, treeNodeInfo, itemNodeData, {jumpAfterNode: 'schema'}),
opClassList: ()=>getNodeAjaxOptions('get_op_class', nodeObj, treeNodeInfo, itemNodeData, {jumpAfterNode: 'schema'})
opClassList: ()=>getNodeAjaxOptions('get_op_class', nodeObj, treeNodeInfo, itemNodeData, {jumpAfterNode: 'schema'}),
extensionsList:()=>getNodeAjaxOptions('nodes', nodeExtObj, treeNodeInfo, itemNodeData, { cacheLevel: 'server'},
(data)=>{
let res = [];
if (data && _.isArray(data)) {
_.each(data, function(d) {
res.push({label: d.label, value: d.label, data: d});
});
}
return res;
}),
},
{
node_info: treeNodeInfo

View File

@ -505,7 +505,23 @@ export default class IndexSchema extends BaseUISchema {
return Promise.resolve(()=>{/*This is intentional (SonarQube)*/});
}
},
},{
},
{
id: 'dependsonextensions',
label: gettext('Depends on extensions'),
group: gettext('Definition'),
type: 'select',
options: this.fieldOptions.extensionsList,
controlProps: {
multiple: true,
allowClear: true,
allowSelectAll: true,
placeholder: gettext('Select the Depends on extensions...'),
},
min_version: 130000,
mode: ['create', 'edit', 'properties']
},
{
type: 'nested-fieldset', label: gettext('With'), group: gettext('Definition'),
schema: this.withSchema,
},{

View File

@ -0,0 +1,2 @@
ALTER INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
NO DEPENDS ON EXTENSION postgres_fdw;

View File

@ -0,0 +1,17 @@
-- Index: Idx_$%{}[]()&*^!@"'`\/#
-- DROP INDEX IF EXISTS public."Idx_$%{}[]()&*^!@""'`\/#";
CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST)
INCLUDE(name, id)
WITH (fillfactor=10, deduplicate_items=False)
TABLESPACE pg_default
WHERE id < 100;
ALTER INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
DEPENDS ON EXTENSION plpgsql;
COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
IS 'Test Comment';

View File

@ -11,6 +11,5 @@ CREATE UNIQUE INDEX IF NOT EXISTS "Idx1_$%{}[]()&*^!@""'`\/#"
ALTER TABLE IF EXISTS public.test_table_for_indexes
CLUSTER ON "Idx1_$%{}[]()&*^!@""'`\/#";
COMMENT ON INDEX public."Idx1_$%{}[]()&*^!@""'`\/#"
IS 'Test Comment';

View File

@ -0,0 +1,16 @@
CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST)
INCLUDE(name, id)
WITH (fillfactor=10, deduplicate_items=False)
TABLESPACE pg_default
WHERE id < 100;
ALTER INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
DEPENDS ON EXTENSION plpgsql;
ALTER INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
DEPENDS ON EXTENSION postgres_fdw;
COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
IS 'Test Comment';

View File

@ -0,0 +1,20 @@
-- Index: Idx_$%{}[]()&*^!@"'`\/#
-- DROP INDEX IF EXISTS public."Idx_$%{}[]()&*^!@""'`\/#";
CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST)
INCLUDE(name, id)
WITH (fillfactor=10, deduplicate_items=False)
TABLESPACE pg_default
WHERE id < 100;
ALTER INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
DEPENDS ON EXTENSION plpgsql;
ALTER INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
DEPENDS ON EXTENSION postgres_fdw;
COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
IS 'Test Comment';

View File

@ -1,5 +1,17 @@
{
"scenarios": [
{
"type": "create",
"name": "Create Extension",
"endpoint": "NODE-extension.obj",
"sql_endpoint": "NODE-extension.sql_id",
"data": {
"name": "postgres_fdw",
"version": "",
"relocatable": true
},
"store_object_id": true
},
{
"type": "create",
"name": "Create Table for indexes",
@ -21,6 +33,75 @@
},
"store_object_id": true
},
{
"type": "create",
"name": "Create btree index with extensions.",
"endpoint": "NODE-index.obj",
"sql_endpoint": "NODE-index.sql_id",
"msql_endpoint": "NODE-index.msql",
"data": {
"name":"Idx_$%{}[]()&*^!@\"'`\\/#",
"spcname":"pg_default",
"amname":"btree",
"include": ["name", "id"],
"columns":[{
"colname":"id",
"collspcname":"",
"op_class":"",
"sort_order":false,
"nulls":false,
"is_sort_nulls_applicable":true
}, {
"colname":"name",
"collspcname":"pg_catalog.\"POSIX\"",
"op_class":"text_pattern_ops",
"sort_order":false,
"nulls":false,
"is_sort_nulls_applicable":true
}],
"description":"Test Comment",
"fillfactor":"10",
"deduplicate_items": false,
"indisunique":true,
"indnullsnotdistinct":true,
"indisclustered":false,
"isconcurrent":false,
"indconstraint":"id < 100",
"dependsonextensions": ["plpgsql", "postgres_fdw"]
},
"expected_sql_file": "create_index_with_ext.sql",
"expected_msql_file": "create_index_with_ext.msql"
},
{
"type": "alter",
"name": "Alter index with NO DEPENDS ON",
"endpoint": "NODE-index.obj_id",
"sql_endpoint": "NODE-index.sql_id",
"msql_endpoint": "NODE-index.msql_id",
"data": {
"name": "Idx_$%{}[]()&*^!@\"'`\\/#",
"dependsonextensions": ["plpgsql"]
},
"expected_sql_file": "alter_index_no_depends.sql",
"expected_msql_file": "alter_index_no_depends.msql"
},
{
"type": "delete",
"name": "Drop index -- 13 Plus",
"endpoint": "NODE-index.delete_id",
"data": {
"name": "Idx_$%{}[]()&*^!@\"'`\\/#"
}
},
{
"type": "delete",
"name": "Drop Extension",
"endpoint": "NODE-extension.delete",
"data": {
"ids": ["<postgres_fdw>"]
},
"preprocess_data": true
},
{
"type": "create",
"name": "Create btree index with ASC and NULLS LAST -- 13 Plus",

View File

@ -0,0 +1,18 @@
-- Index: Idx_$%{}[]()&*^!@"'`\/#
-- DROP INDEX IF EXISTS public."Idx_$%{}[]()&*^!@""'`\/#";
CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST)
INCLUDE(name, id)
NULLS NOT DISTINCT
WITH (fillfactor=10, deduplicate_items=False)
TABLESPACE pg_default
WHERE id < 100;
ALTER INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
DEPENDS ON EXTENSION plpgsql;
COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
IS 'Test Comment';

View File

@ -12,6 +12,5 @@ CREATE UNIQUE INDEX IF NOT EXISTS "Idx1_$%{}[]()&*^!@""'`\/#"
ALTER TABLE IF EXISTS public.test_table_for_indexes
CLUSTER ON "Idx1_$%{}[]()&*^!@""'`\/#";
COMMENT ON INDEX public."Idx1_$%{}[]()&*^!@""'`\/#"
IS 'Test Comment';

View File

@ -0,0 +1,17 @@
CREATE UNIQUE INDEX "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST)
INCLUDE(name, id)
NULLS NOT DISTINCT
WITH (fillfactor=10, deduplicate_items=False)
TABLESPACE pg_default
WHERE id < 100;
ALTER INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
DEPENDS ON EXTENSION plpgsql;
ALTER INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
DEPENDS ON EXTENSION postgres_fdw;
COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
IS 'Test Comment';

View File

@ -0,0 +1,21 @@
-- Index: Idx_$%{}[]()&*^!@"'`\/#
-- DROP INDEX IF EXISTS public."Idx_$%{}[]()&*^!@""'`\/#";
CREATE UNIQUE INDEX IF NOT EXISTS "Idx_$%{}[]()&*^!@""'`\/#"
ON public.test_table_for_indexes USING btree
(id ASC NULLS LAST, name COLLATE pg_catalog."POSIX" text_pattern_ops ASC NULLS LAST)
INCLUDE(name, id)
NULLS NOT DISTINCT
WITH (fillfactor=10, deduplicate_items=False)
TABLESPACE pg_default
WHERE id < 100;
ALTER INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
DEPENDS ON EXTENSION plpgsql;
ALTER INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
DEPENDS ON EXTENSION postgres_fdw;
COMMENT ON INDEX public."Idx_$%{}[]()&*^!@""'`\/#"
IS 'Test Comment';

View File

@ -1,26 +1,107 @@
{
"scenarios": [
{
"type": "create",
"name": "Create Table for indexes",
"endpoint": "NODE-table.obj",
"sql_endpoint": "NODE-table.sql_id",
"data": {
"name": "test_table_for_indexes",
"columns": [{
"name": "id",
"cltype": "bigint",
"is_primary_key": true
}, {
"name": "name",
"cltype": "text"
}],
"is_partitioned": false,
"spcname": "pg_default",
"schema": "public"
{
"type": "create",
"name": "Create Extension",
"endpoint": "NODE-extension.obj",
"sql_endpoint": "NODE-extension.sql_id",
"data": {
"name": "postgres_fdw",
"version": "",
"relocatable": true
},
"store_object_id": true
},
{
"type": "create",
"name": "Create Table for indexes",
"endpoint": "NODE-table.obj",
"sql_endpoint": "NODE-table.sql_id",
"data": {
"name": "test_table_for_indexes",
"columns": [{
"name": "id",
"cltype": "bigint",
"is_primary_key": true
}, {
"name": "name",
"cltype": "text"
}],
"is_partitioned": false,
"spcname": "pg_default",
"schema": "public"
},
"store_object_id": true
},
{
"type": "create",
"name": "Create btree index with extensions.",
"endpoint": "NODE-index.obj",
"sql_endpoint": "NODE-index.sql_id",
"msql_endpoint": "NODE-index.msql",
"data": {
"name":"Idx_$%{}[]()&*^!@\"'`\\/#",
"spcname":"pg_default",
"amname":"btree",
"include": ["name", "id"],
"columns":[{
"colname":"id",
"collspcname":"",
"op_class":"",
"sort_order":false,
"nulls":false,
"is_sort_nulls_applicable":true
}, {
"colname":"name",
"collspcname":"pg_catalog.\"POSIX\"",
"op_class":"text_pattern_ops",
"sort_order":false,
"nulls":false,
"is_sort_nulls_applicable":true
}],
"description":"Test Comment",
"fillfactor":"10",
"deduplicate_items": false,
"indisunique":true,
"indnullsnotdistinct":true,
"indisclustered":false,
"isconcurrent":false,
"indconstraint":"id < 100",
"dependsonextensions": ["plpgsql", "postgres_fdw"]
},
"expected_sql_file": "create_index_with_ext.sql",
"expected_msql_file": "create_index_with_ext.msql"
},
{
"type": "alter",
"name": "Alter index with NO DEPENDS ON",
"endpoint": "NODE-index.obj_id",
"sql_endpoint": "NODE-index.sql_id",
"msql_endpoint": "NODE-index.msql_id",
"data": {
"name": "Idx_$%{}[]()&*^!@\"'`\\/#",
"dependsonextensions": ["plpgsql"]
},
"expected_sql_file": "alter_index_no_depends.sql",
"expected_msql_file": "alter_index_no_depends.msql"
},
{
"type": "delete",
"name": "Drop index -- 13 Plus",
"endpoint": "NODE-index.delete_id",
"data": {
"name": "Idx_$%{}[]()&*^!@\"'`\\/#"
}
},
{
"type": "delete",
"name": "Drop Extension",
"endpoint": "NODE-extension.delete",
"data": {
"ids": ["<postgres_fdw>"]
},
"preprocess_data": true
},
"store_object_id": true
},
{
"type": "create",
"name": "Create btree index with ASC and NULLS LAST -- 15 Plus",

View File

@ -31,6 +31,7 @@
"name": "test_index_add",
"spcname": "pg_default",
"amname": "btree",
"dependsonextensions": ["plpgsql"],
"columns": [
{
"colname": "id",
@ -529,7 +530,8 @@
},
"test_data": {
"description": "This is test comment for index",
"name": "updating name for index using api tests"
"name": "updating name for index using api tests",
"dependsonextensions": ["plpgsql"]
},
"mocking_required": false,
"mock_data": {},

View File

@ -242,6 +242,9 @@ def get_sql(conn, **kwargs):
show_sys_obj = kwargs.get('show_sys_objects', False)
name = data['name'] if 'name' in data else None
if data.get('dependsonextensions') is None:
data['dependsonextensions'] = \
data.get('dependsonextensions') or []
if idx is not None:
sql = render_template("/".join([template_path, 'properties.sql']),
did=did, tid=tid, idx=idx,
@ -272,7 +275,9 @@ def get_sql(conn, **kwargs):
old_data['withcheck'].startswith('(') and \
old_data['withcheck'].endswith(')'):
old_data['withcheck'] = old_data['withcheck'][1:-1]
if old_data.get('dependsonextensions') is None:
old_data['dependsonextensions'] = \
old_data.get('dependsonextensions') or []
# If name is not present in data then
# we will fetch it from old data, we also need schema & table name
if 'name' not in data:

View File

@ -0,0 +1,33 @@
CREATE{% if data.indisunique %} UNIQUE{% endif %} INDEX{% if add_not_exists_clause %} IF NOT EXISTS{% endif %}{% if data.isconcurrent %} CONCURRENTLY{% endif %}{% if data.name %} {{conn|qtIdent(data.name)}}{% endif %}
ON {{conn|qtIdent(data.schema, data.table)}} {% if data.amname %}USING {{conn|qtIdent(data.amname)}}{% endif %}
{% if mode == 'create' %}
({% for c in data.columns %}{% if loop.index != 1 %}, {% endif %}{% if c.is_exp %}({{c.colname}}){% else %}{{conn|qtIdent(c.colname)}}{% endif %}{% if c.collspcname %} COLLATE {{c.collspcname}}{% endif %}{% if c.op_class %}
{{c.op_class}}{% endif %}{% if data.amname is defined %}{% if c.sort_order is defined and c.is_sort_nulls_applicable %}{% if c.sort_order %} DESC{% else %} ASC{% endif %}{% endif %}{% if c.nulls is defined and c.is_sort_nulls_applicable %} NULLS {% if c.nulls %}
FIRST{% else %}LAST{% endif %}{% endif %}{% endif %}{% endfor %})
{% if data.include|length > 0 %}
INCLUDE({% for col in data.include %}{% if loop.index != 1 %}, {% endif %}{{conn|qtIdent(col)}}{% endfor %})
{% endif %}
{% else %}
{## We will get indented data from postgres for column ##}
({% for c in data.columns %}{% if loop.index != 1 %}, {% endif %}{{c.colname}}{% if c.collspcname %} COLLATE {{c.collspcname}}{% endif %}{% if c.op_class %}
{{c.op_class}}{% endif %}{% if c.sort_order is defined %}{% if c.sort_order %} DESC{% else %} ASC{% endif %}{% endif %}{% if c.nulls is defined %} NULLS {% if c.nulls %}
FIRST{% else %}LAST{% endif %}{% endif %}{% endfor %})
{% if data.include|length > 0 %}
INCLUDE({% for col in data.include %}{% if loop.index != 1 %}, {% endif %}{{conn|qtIdent(col)}}{% endfor %})
{% endif %}
{% endif %}
{% if data.storage_parameters %}
WITH ({% for key, value in data.storage_parameters.items() %}{% if loop.index != 1 %}, {% endif %}{{key}}={{value}}{% endfor %})
{% endif %}{% if data.spcname %}
TABLESPACE {{conn|qtIdent(data.spcname)}}{% endif %}{% if data.indconstraint %}
WHERE {{data.indconstraint}}{% endif %};
{% if data.dependsonextensions %}
{% for ext in data.dependsonextensions %}
ALTER INDEX {{ conn|qtIdent(data.schema, data.name) }}
DEPENDS ON EXTENSION {{ conn|qtIdent(ext) }};
{% endfor %}
{% endif %}

View File

@ -30,6 +30,12 @@ SELECT DISTINCT ON (cls.relname)
WHEN con.contype IN ('p', 'u', 'x') THEN desp.description
ELSE des.description
END AS description,
(
SELECT array_agg(DISTINCT e.extname)
FROM pg_depend d
JOIN pg_extension e ON d.refobjid = e.oid
WHERE d.objid = cls.oid
) AS dependsonextensions,
pg_catalog.pg_get_expr(idx.indpred, idx.indrelid, true) AS indconstraint,
con.contype,
con.condeferrable,

View File

@ -0,0 +1,110 @@
{## Changes name ##}
{% if data.name and o_data.name != data.name %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, o_data.name)}}
RENAME TO {{conn|qtIdent(data.name)}};
{% endif %}
{## Changes fillfactor ##}
{% if data.fillfactor and o_data.fillfactor != data.fillfactor %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET (fillfactor={{data.fillfactor}});
{% elif (data.fillfactor == '' or data.fillfactor == None) and o_data.fillfactor|default('', 'true') != data.fillfactor %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
RESET (fillfactor);
{% endif %}
{## Changes gin_pending_list_limit ##}
{% if data.gin_pending_list_limit and o_data.gin_pending_list_limit != data.gin_pending_list_limit %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET (gin_pending_list_limit={{data.gin_pending_list_limit}});
{% elif (data.gin_pending_list_limit == '' or data.gin_pending_list_limit == None) and o_data.gin_pending_list_limit|default('', 'true') != data.gin_pending_list_limit %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
RESET (gin_pending_list_limit);
{% endif %}
{## Changes deduplicate_items ##}
{% if data.deduplicate_items in [True, False] and o_data.deduplicate_items != data.deduplicate_items %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET (deduplicate_items={{data.deduplicate_items}});
{% endif %}
{## Changes pages_per_range ##}
{% if data.pages_per_range and o_data.pages_per_range != data.pages_per_range %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET (pages_per_range={{data.pages_per_range}});
{% elif (data.pages_per_range == '' or data.pages_per_range == None) and o_data.pages_per_range|default('', 'true') != data.pages_per_range %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
RESET (pages_per_range);
{% endif %}
{## Changes buffering ##}
{% if data.buffering and o_data.buffering != data.buffering %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET (buffering={{data.buffering}});
{% elif (data.buffering == '' or data.buffering == None) and o_data.buffering|default('', 'true') != data.buffering %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
RESET (buffering);
{% endif %}
{## Changes fastupdate ##}
{% if data.fastupdate in [True, False] and o_data.fastupdate != data.fastupdate %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET (fastupdate={{data.fastupdate}});
{% endif %}
{## Changes autosummarize ##}
{% if data.autosummarize in [True, False] and o_data.autosummarize != data.autosummarize %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET (autosummarize={{data.autosummarize}});
{% endif %}
{## Changes tablespace ##}
{% if data.spcname and o_data.spcname != data.spcname %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
SET TABLESPACE {{conn|qtIdent(data.spcname)}};
{% endif %}
{## Alter index to use cluster type ##}
{% if data.indisclustered is defined and o_data.indisclustered != data.indisclustered %}
{% if data.indisclustered %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
CLUSTER ON {{conn|qtIdent(data.name)}};
{% else %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
SET WITHOUT CLUSTER;
{% endif %}
{% endif %}
{## Changes description ##}
{% if data.description is defined and o_data.description != data.description %}
COMMENT ON INDEX {{conn|qtIdent(data.schema, data.name)}}
IS {{data.description|qtLiteral(conn)}};{% endif %}
{## Alter column statistics##}
{% if update_column %}
{% for col in update_column_data %}
ALTER INDEX IF EXISTS {{conn|qtIdent(data.schema, data.name)}}
ALTER COLUMN {{col.col_num}} SET STATISTICS {{col.statistics}};
{% endfor %}
{% endif %}
{% set old_exts = (o_data.dependsonextensions or []) | list %}
{% set new_exts = data.dependsonextensions if 'dependsonextensions' in data else None %}
{% if new_exts is not none and old_exts != new_exts %}
{% for ext in (old_exts + new_exts) | unique %}
{% if ext in new_exts and ext not in old_exts %}
ALTER INDEX {{ conn|qtIdent(data.schema, data.name) }}
DEPENDS ON EXTENSION {{ conn|qtIdent(ext) }};
{% elif ext in old_exts and ext not in new_exts %}
ALTER INDEX {{ conn|qtIdent(data.schema, data.name) }}
NO DEPENDS ON EXTENSION {{ conn|qtIdent(ext) }};
{% endif %}
{% endfor %}
{% endif %}

View File

@ -30,3 +30,10 @@ FIRST{% else %}LAST{% endif %}{% endif %}{% endfor %})
TABLESPACE {{conn|qtIdent(data.spcname)}}{% endif %}{% if data.indconstraint %}
WHERE {{data.indconstraint}}{% endif %};
{% if data.dependsonextensions %}
{% for ext in data.dependsonextensions %}
ALTER INDEX {{ conn|qtIdent(data.schema, data.name) }}
DEPENDS ON EXTENSION {{ conn|qtIdent(ext) }};
{% endfor %}
{% endif %}

View File

@ -31,6 +31,12 @@ SELECT DISTINCT ON (cls.relname)
WHEN con.contype IN ('p', 'u', 'x') THEN desp.description
ELSE des.description
END AS description,
(
SELECT array_agg(DISTINCT e.extname)
FROM pg_depend d
JOIN pg_extension e ON d.refobjid = e.oid
WHERE d.objid = cls.oid
) AS dependsonextensions,
pg_catalog.pg_get_expr(idx.indpred, idx.indrelid, true) AS indconstraint,
con.contype,
con.condeferrable,

View File

@ -1,11 +1,9 @@
{## Alter index to use cluster type ##}
{% if data.indisclustered %}
ALTER TABLE IF EXISTS {{conn|qtIdent(data.schema, data.table)}}
CLUSTER ON {{conn|qtIdent(data.name)}};
{% endif %}
{## Changes description ##}
{% if data.description is defined and data.description %}
COMMENT ON INDEX {{conn|qtIdent(data.schema, data.name)}}
IS {{data.description|qtLiteral(conn)}};{% endif %}

View File

@ -202,6 +202,13 @@ describe('IndexSchema', () => {
});
});
it('dependsonextensions field exists', ()=>{
let field = _.find(indexSchemaObj.fields, (f)=>f.id=='dependsonextensions');
expect(field).toBeTruthy();
expect(field.type).toBe('select');
expect(field.controlProps.multiple).toBe(true);
});
it('columns formatter', () => {
let formatter = _.find(indexSchemaObj.fields, (f) => f.id=='columns').cell().controlProps.formatter;
expect(formatter.fromRaw([{