From d6ecc531e0b32566df2fd809191bc6299acb4166 Mon Sep 17 00:00:00 2001 From: Akshay Joshi Date: Thu, 20 Apr 2023 12:35:10 +0530 Subject: [PATCH] Added support to create an unnamed index. #3318 --- docs/en_US/release_notes_7_1.rst | 6 +- .../schemas/tables/indexes/__init__.py | 59 +++++++++++-------- .../tables/indexes/static/js/index.ui.js | 23 ++++++-- .../create_unnamed_hash_index_msql.sql | 4 ++ .../indexes/tests/default/test_indexes.json | 27 +++++++++ .../tables/indexes/tests/index_test_data.json | 49 ++++++++------- .../tables/indexes/tests/test_indexes_add.py | 12 ++-- .../databases/schemas/tables/indexes/utils.py | 1 - .../sql/default/get_oid_with_transaction.sql | 3 +- .../sql/default/get_oid_with_transaction.sql | 3 +- .../sql/default/get_oid_with_transaction.sql | 3 +- .../sql/default/get_oid_with_transaction.sql | 3 +- .../templates/indexes/sql/11_plus/create.sql | 3 +- .../templates/indexes/sql/default/create.sql | 3 +- .../indexes/sql/default/get_oid_name.sql | 5 ++ 15 files changed, 137 insertions(+), 67 deletions(-) create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/create_unnamed_hash_index_msql.sql create mode 100644 web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/get_oid_name.sql diff --git a/docs/en_US/release_notes_7_1.rst b/docs/en_US/release_notes_7_1.rst index 5e703909d..0b9c45813 100644 --- a/docs/en_US/release_notes_7_1.rst +++ b/docs/en_US/release_notes_7_1.rst @@ -2,7 +2,7 @@ Version 7.1 *********** -Release date: 2023-05-01 +Release date: 2023-05-04 This release contains a number of bug fixes and new features since the release of pgAdmin 4 v7.0. @@ -22,6 +22,7 @@ New features | `Issue #3275 `_ - Allow on demand record count setting to be changed per user using preferences. | `Issue #3316 `_ - Added support to show statistics for materialized views. + | `Issue #3318 `_ - Added support to create an unnamed index. Housekeeping ************ @@ -33,5 +34,8 @@ Bug fixes | `Issue #5777 `_ - Fixed an issue where the browser tree state is not remembered when reopening pgAdmin. | `Issue #5820 `_ - Fixed an issue where collation was set to none if we remove it while creating partitioned table. | `Issue #6075 `_ - Ensure that the save button is enabled when registering a new server fails due to an API error. + | `Issue #6120 `_ - Fixed error occurring while logging out from pgAdmin keeping a query tool opened. + | `Issue #6128 `_ - Fix a SQL error occurring on roles dependents SQL. | `Issue #6130 `_ - Ensure to quote the primary key value if needed while deleting rows from the table. | `Issue #6137 `_ - Fixed error occurring while dumping the servers from CLI. + | `Issue #6138 `_ - Throw an appropriate error when a table for which View/Edit data is open, is deleted, and query is executed. diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py index 922e41241..e4c8ce71c 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/__init__.py @@ -551,10 +551,17 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): return True, err_msg return False, '' + def end_transaction(self, data): + """ + This function is used to end the transaction + """ + if hasattr(data, "isconcurrent") and not data['isconcurrent']: + self.conn.execute_scalar("END;") + @check_precondition def create(self, gid, sid, did, scid, tid): """ - This function will creates new the schema object + This function will create the new index object Args: gid: Server Group ID @@ -579,7 +586,6 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): data[k] = v required_args = { - 'name': 'Name', 'columns': 'Columns' } @@ -611,8 +617,7 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): status, res = self.conn.execute_scalar(SQL) if not status: # End transaction. - if hasattr(data, "isconcurrent") and not data['isconcurrent']: - self.conn.execute_scalar("END;") + self.end_transaction(data) return internal_server_error(errormsg=res) # If user chooses concurrent index then we cannot run it along @@ -625,27 +630,35 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): if SQL != '': status, res = self.conn.execute_scalar(SQL) if not status: - if hasattr(data, "isconcurrent") and not data[ - 'isconcurrent']: - # End transaction. - self.conn.execute_scalar("END;") + self.end_transaction(data) return internal_server_error(errormsg=res) # we need oid to add object in tree at browser - SQL = render_template( - "/".join([self.template_path, self._OID_SQL]), - tid=tid, data=data, conn=self.conn - ) - status, idx = self.conn.execute_scalar(SQL) - if not status: - if hasattr(data, "isconcurrent") and not data['isconcurrent']: - # End transaction. - self.conn.execute_scalar("END;") - return internal_server_error(errormsg=tid) + idx = 0 + if data.get('name', '') == "": + SQL = render_template( + "/".join([self.template_path, 'get_oid_name.sql']), + tid=tid, conn=self.conn + ) + status, res = self.conn.execute_dict(SQL) + if not status: + self.end_transaction(data) + return internal_server_error(errormsg=tid) - if hasattr(data, "isconcurrent") and not data['isconcurrent']: - # End transaction. - self.conn.execute_scalar("END;") + if 'rows' in res and len(res['rows']) > 0: + data['name'] = res['rows'][0]['relname'] + idx = res['rows'][0]['oid'] + else: + SQL = render_template( + "/".join([self.template_path, self._OID_SQL]), + tid=tid, data=data, conn=self.conn + ) + status, idx = self.conn.execute_scalar(SQL) + if not status: + self.end_transaction(data) + return internal_server_error(errormsg=tid) + + self.end_transaction(data) return jsonify( node=self.blueprint.generate_browser_node( idx, @@ -655,9 +668,7 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): ) ) except Exception as e: - if hasattr(data, "isconcurrent") and not data['isconcurrent']: - # End transaction. - self.conn.execute_scalar("END;") + self.end_transaction(data) return internal_server_error(errormsg=str(e)) @check_precondition 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 74b2cd4f2..9ff198232 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 @@ -263,7 +263,7 @@ export default class IndexSchema extends BaseUISchema { return [ { id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', noEmpty: true, + type: 'text', disabled: () => inSchema(indexSchemaObj.node_info), },{ id: 'oid', label: gettext('OID'), cell: 'string', @@ -366,8 +366,15 @@ export default class IndexSchema extends BaseUISchema { group: gettext('Definition'), },{ id: 'indisclustered', label: gettext('Clustered?'), cell: 'string', - type: 'switch', disabled: () => inSchema(indexSchemaObj.node_info), - group: gettext('Definition'), + type: 'switch', group: gettext('Definition'), deps: ['name'], + disabled: function (state) { + return isEmptyString(state.name) || inSchema(indexSchemaObj.node_info); + }, + depChange: (state)=>{ + if(isEmptyString(state.name)) { + return {indisclustered: false}; + } + } },{ id: 'indisvalid', label: gettext('Valid?'), cell: 'string', type: 'switch', mode: ['properties'], @@ -429,7 +436,15 @@ export default class IndexSchema extends BaseUISchema { },{ id: 'description', label: gettext('Comment'), cell: 'string', type: 'multiline', mode: ['properties', 'create', 'edit'], - disabled: () => inSchema(indexSchemaObj.node_info), + deps: ['name'], + disabled: function (state) { + return isEmptyString(state.name) || inSchema(indexSchemaObj.node_info); + }, + depChange: (state)=>{ + if(isEmptyString(state.name)) { + return {comment: ''}; + } + } }, ]; } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/create_unnamed_hash_index_msql.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/create_unnamed_hash_index_msql.sql new file mode 100644 index 000000000..2babaaea7 --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/create_unnamed_hash_index_msql.sql @@ -0,0 +1,4 @@ +CREATE INDEX + ON public.test_table_for_indexes USING hash + (id) + TABLESPACE pg_default; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/test_indexes.json b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/test_indexes.json index a548f5eff..a85e2804a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/test_indexes.json +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/default/test_indexes.json @@ -258,6 +258,33 @@ "data": { "name": "test_table_for_indexes" } + }, + { + "type": "create", + "name": "Create unnamed hash index", + "endpoint": "NODE-index.obj", + "sql_endpoint": "NODE-index.sql_id", + "msql_endpoint": "NODE-index.msql", + "data": { + "spcname": "pg_default", + "amname": "hash", + "columns": [{ + "colname": "id", + "collspcname": "", + "op_class": "", + "sort_order": false, + "nulls": false, + "is_sort_nulls_applicable": false + }], + "indisunique": false, + "isconcurrent": false + }, + "expected_msql_file": "create_unnamed_hash_index_msql.sql" + }, + { + "type": "delete", + "name": "Drop hash index", + "endpoint": "NODE-index.delete_id" } ] } 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 6d39edadf..ebd32f242 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 @@ -1,5 +1,28 @@ { "index_create": [ + { + "name": "Create unnamed index: With valid data.", + "is_positive_test": true, + "inventory_data": {}, + "test_data": { + "spcname": "pg_default", + "amname": "btree", + "columns": [ + { + "colname": "id", + "sort_order": false, + "nulls": false + } + ] + }, + "mocking_required": false, + "mock_data": {}, + "expected_data": { + "status_code": 200, + "error_msg": null, + "test_result_data": {} + } + }, { "name": "Create index: With valid data.", "is_positive_test": true, @@ -108,32 +131,6 @@ "test_result_data": {} } }, - { - "name": "Create index: With invalid data - Missing Parameter.", - "is_positive_test": false, - "inventory_data": {}, - "test_data": { - "spcname": "pg_default", - "amname": "btree", - "columns": [ - { - "colname": "id", - "sort_order": false, - "nulls": false - } - ], - "include": [ - "name" - ] - }, - "mocking_required": false, - "mock_data": {}, - "expected_data": { - "status_code": 410, - "error_msg": "Could not find the required parameter (Name).", - "test_result_data": {} - } - }, { "name": "Create index: With valid data while server is down.", "is_positive_test": false, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/test_indexes_add.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/test_indexes_add.py index 43a4c0fef..0dea1f111 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/test_indexes_add.py +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/tests/test_indexes_add.py @@ -61,11 +61,13 @@ class IndexesAddTestCase(BaseTestGenerator): if self.is_positive_test: response = indexes_utils.api_create_index(self) indexes_utils.assert_status_code(self, response) - index_response = indexes_utils.verify_index(self.server, - self.db_name, - self.index_name) - self.assertIsNot(index_response, "Could not find the newly " - "created index.") + # In case of unnamed index the below logic is not required + if hasattr(self, 'index_name'): + index_response = indexes_utils.verify_index(self.server, + self.db_name, + self.index_name) + self.assertIsNot(index_response, "Could not find the newly " + "created index.") else: if self.mocking_required: 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 f82a26396..db3ac47da 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 @@ -184,7 +184,6 @@ def _get_create_sql(data, template_path, conn, mode, name, :return: """ required_args = { - 'name': 'Name', 'columns': 'Columns' } for arg in required_args: diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/check_constraint/sql/default/get_oid_with_transaction.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/check_constraint/sql/default/get_oid_with_transaction.sql index 7fca1ae37..da17d82fe 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/check_constraint/sql/default/get_oid_with_transaction.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/check_constraint/sql/default/get_oid_with_transaction.sql @@ -3,4 +3,5 @@ SELECT ct.oid, NOT convalidated as convalidated FROM pg_catalog.pg_constraint ct WHERE contype='c' AND - conrelid = {{tid}}::oid LIMIT 1; + conrelid = {{tid}}::oid +ORDER BY ct.oid DESC LIMIT 1; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/exclusion_constraint/sql/default/get_oid_with_transaction.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/exclusion_constraint/sql/default/get_oid_with_transaction.sql index fd7ac3953..abc785c86 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/exclusion_constraint/sql/default/get_oid_with_transaction.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/exclusion_constraint/sql/default/get_oid_with_transaction.sql @@ -3,4 +3,5 @@ SELECT ct.conindid AS oid, NOT convalidated AS convalidated FROM pg_catalog.pg_constraint ct WHERE contype='x' AND - conrelid = {{tid}}::oid LIMIT 1; + conrelid = {{tid}}::oid +ORDER BY oid DESC LIMIT 1; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/foreign_key/sql/default/get_oid_with_transaction.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/foreign_key/sql/default/get_oid_with_transaction.sql index 1a700e62e..15bc7d097 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/foreign_key/sql/default/get_oid_with_transaction.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/foreign_key/sql/default/get_oid_with_transaction.sql @@ -3,4 +3,5 @@ SELECT ct.oid, NOT convalidated as convalidated FROM pg_catalog.pg_constraint ct WHERE contype='f' AND - conrelid = {{tid}}::oid LIMIT 1; + conrelid = {{tid}}::oid +ORDER BY ct.oid DESC LIMIT 1; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/index_constraint/sql/default/get_oid_with_transaction.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/index_constraint/sql/default/get_oid_with_transaction.sql index 968c4be38..2c59bc5e5 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/index_constraint/sql/default/get_oid_with_transaction.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/index_constraint/sql/default/get_oid_with_transaction.sql @@ -2,4 +2,5 @@ SELECT ct.conindid as oid, ct.conname as name FROM pg_catalog.pg_constraint ct WHERE contype='{{constraint_type}}' AND - conrelid = {{tid}}::oid LIMIT 1; + conrelid = {{tid}}::oid +ORDER BY oid DESC LIMIT 1; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/11_plus/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/11_plus/create.sql index d43a64ee0..0b2b82910 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/11_plus/create.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/11_plus/create.sql @@ -1,4 +1,5 @@ -CREATE {% if data.indisunique %}UNIQUE {% endif %}INDEX{% if add_not_exists_clause %} IF NOT EXISTS{% endif %} {% if data.isconcurrent %}CONCURRENTLY {% endif %}{{conn|qtIdent(data.name)}} +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' %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/create.sql index 328a1efe6..34b8d3c70 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/create.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/create.sql @@ -1,4 +1,5 @@ -CREATE {% if data.indisunique %}UNIQUE {% endif %}INDEX{% if add_not_exists_clause %} IF NOT EXISTS{% endif %} {% if data.isconcurrent %}CONCURRENTLY {% endif %}{{conn|qtIdent(data.name)}} +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' %} diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/get_oid_name.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/get_oid_name.sql new file mode 100644 index 000000000..8d3a603ca --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/indexes/sql/default/get_oid_name.sql @@ -0,0 +1,5 @@ +SELECT cls.relname, cls.oid +FROM pg_catalog.pg_index idx + JOIN pg_catalog.pg_class cls ON cls.oid=indexrelid +WHERE indrelid = {{tid}}::OID +ORDER BY cls.oid DESC LIMIT 1;