diff --git a/docs/en_US/images/index_definition.png b/docs/en_US/images/index_definition.png index a524b5af4a8..17b941bd703 100644 Binary files a/docs/en_US/images/index_definition.png and b/docs/en_US/images/index_definition.png differ diff --git a/docs/en_US/index_dialog.rst b/docs/en_US/index_dialog.rst index 5635a3329ac..b462b421f8f 100644 --- a/docs/en_US/index_dialog.rst +++ b/docs/en_US/index_dialog.rst @@ -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. diff --git a/docs/en_US/materialized_view_dialog.rst b/docs/en_US/materialized_view_dialog.rst index 1a42aebe6ab..862484ac177 100644 --- a/docs/en_US/materialized_view_dialog.rst +++ b/docs/en_US/materialized_view_dialog.rst @@ -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 diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js index 388956886b4..683a78b9517 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js @@ -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 diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.ui.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.ui.js index d52181b7382..591bc43fac9 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.ui.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.ui.js @@ -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, },{ diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/alter_index_no_depends.msql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/alter_index_no_depends.msql new file mode 100644 index 00000000000..06d7aa7e8f4 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/alter_index_no_depends.msql @@ -0,0 +1,2 @@ +ALTER INDEX public."Idx_$%{}[]()&*^!@""'`\/#" + NO DEPENDS ON EXTENSION postgres_fdw; \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/alter_index_no_depends.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/alter_index_no_depends.sql new file mode 100644 index 00000000000..c10fecc30fe --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/alter_index_no_depends.sql @@ -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'; \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/alter_name_fillfactor_comment.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/alter_name_fillfactor_comment.sql index 3ffe0803c70..bd26995dfb0 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/alter_name_fillfactor_comment.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/alter_name_fillfactor_comment.sql @@ -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'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_index_with_ext.msql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_index_with_ext.msql new file mode 100644 index 00000000000..fd511914ee4 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_index_with_ext.msql @@ -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'; \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_index_with_ext.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_index_with_ext.sql new file mode 100644 index 00000000000..95155212227 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/create_index_with_ext.sql @@ -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'; \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/test_indexes.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/test_indexes.json index 31e555a670f..3a66cbfe03a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/test_indexes.json +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/13_plus/test_indexes.json @@ -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": [""] + }, + "preprocess_data": true + }, { "type": "create", "name": "Create btree index with ASC and NULLS LAST -- 13 Plus", diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/alter_index_no_depends.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/alter_index_no_depends.sql new file mode 100644 index 00000000000..e6b249aea8a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/alter_index_no_depends.sql @@ -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'; \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/alter_name_fillfactor_comment.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/alter_name_fillfactor_comment.sql index 176455eb25b..7e1b3b28a7d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/alter_name_fillfactor_comment.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/alter_name_fillfactor_comment.sql @@ -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'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_index_with_ext.msql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_index_with_ext.msql new file mode 100644 index 00000000000..43c2ddece93 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_index_with_ext.msql @@ -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'; \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_index_with_ext.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_index_with_ext.sql new file mode 100644 index 00000000000..08b50454569 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/create_index_with_ext.sql @@ -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'; \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/test_indexes.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/test_indexes.json index a15d5dcfe0e..4525081f644 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/test_indexes.json +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/15_plus/test_indexes.json @@ -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": [""] + }, + "preprocess_data": true }, - "store_object_id": true - }, { "type": "create", "name": "Create btree index with ASC and NULLS LAST -- 15 Plus", diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/index_test_data.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/index_test_data.json index 619ad047355..1116118c12e 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/index_test_data.json +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/index_test_data.json @@ -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": {}, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/utils.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/utils.py index bde7139ef5e..f4af271b7b9 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/utils.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/utils.py @@ -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: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/13_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/13_plus/create.sql new file mode 100644 index 00000000000..e4a2d368e98 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/13_plus/create.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/13_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/13_plus/properties.sql index bc106935262..2ce7f9d2410 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/13_plus/properties.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/13_plus/properties.sql @@ -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, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/13_plus/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/13_plus/update.sql new file mode 100644 index 00000000000..25fe327978a --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/13_plus/update.sql @@ -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 %} \ No newline at end of file diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/15_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/15_plus/create.sql index f1994631c70..f6740fcb3ab 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/15_plus/create.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/15_plus/create.sql @@ -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 %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/15_plus/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/15_plus/properties.sql index 694515ee450..9b9be97c8f5 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/15_plus/properties.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/15_plus/properties.sql @@ -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, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/alter.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/alter.sql index 837789ef260..8f5d572f104 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/alter.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/alter.sql @@ -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 %} diff --git a/web/regression/javascript/schema_ui_files/index.ui.spec.js b/web/regression/javascript/schema_ui_files/index.ui.spec.js index 61bae8a74f7..6739beea35f 100644 --- a/web/regression/javascript/schema_ui_files/index.ui.spec.js +++ b/web/regression/javascript/schema_ui_files/index.ui.spec.js @@ -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([{