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 98edab92..6199b890 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 @@ -605,8 +605,12 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): return gone(gettext(self.not_found_error_msg('Table'))) try: - # Start transaction. - self.conn.execute_scalar("BEGIN;") + # If user chooses concurrent index then we cannot run it inside + # a transaction block. + # Don't start transaction if isconcurrent is True + if hasattr(data, "isconcurrent") and not data['isconcurrent']: + # Start transaction. + self.conn.execute_scalar("BEGIN;") SQL = render_template( "/".join([self.template_path, self._CREATE_SQL]), data=data, conn=self.conn, mode='create' @@ -614,7 +618,8 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): status, res = self.conn.execute_scalar(SQL) if not status: # End transaction. - self.conn.execute_scalar("END;") + if hasattr(data, "isconcurrent") and not data['isconcurrent']: + self.conn.execute_scalar("END;") return internal_server_error(errormsg=res) # If user chooses concurrent index then we cannot run it along @@ -627,8 +632,10 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): if SQL != '': status, res = self.conn.execute_scalar(SQL) if not status: - # End transaction. - self.conn.execute_scalar("END;") + if hasattr(data, "isconcurrent") and not data[ + 'isconcurrent']: + # End transaction. + self.conn.execute_scalar("END;") return internal_server_error(errormsg=res) # we need oid to add object in tree at browser @@ -638,12 +645,14 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): ) status, idx = self.conn.execute_scalar(SQL) if not status: - # End transaction. - self.conn.execute_scalar("END;") + if hasattr(data, "isconcurrent") and not data['isconcurrent']: + # End transaction. + self.conn.execute_scalar("END;") return internal_server_error(errormsg=tid) - # End transaction. - self.conn.execute_scalar("END;") + if hasattr(data, "isconcurrent") and not data['isconcurrent']: + # End transaction. + self.conn.execute_scalar("END;") return jsonify( node=self.blueprint.generate_browser_node( idx, @@ -653,8 +662,9 @@ class IndexesView(PGChildNodeView, SchemaDiffObjectCompare): ) ) except Exception as e: - # End transaction. - self.conn.execute_scalar("END;") + if hasattr(data, "isconcurrent") and not data['isconcurrent']: + # End transaction. + self.conn.execute_scalar("END;") 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 5eab1b66..56958c5a 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 @@ -113,7 +113,7 @@ export class ColumnSchema extends BaseUISchema { * to access method selected by user if not selected * send btree related op_class options */ - var amname = columnSchemaObj._top._sessData ? columnSchemaObj._top._sessData.amname : columnSchemaObj._top._origData.amname; + var amname = columnSchemaObj._top?._sessData ? columnSchemaObj._top?._sessData.amname : columnSchemaObj._top?._origData.amname; if(_.isUndefined(amname)) return options; @@ -315,13 +315,8 @@ export default class IndexSchema extends BaseUISchema { return Promise.resolve(()=>{}); } }, - },{ - id: 'columns_csv', label: gettext('Columns'), cell: 'string', - type: 'text', - disabled: () => inSchema(indexSchemaObj.node_info), - mode: ['properties'], - group: gettext('Definition'), - },{ + }, + { id: 'include', label: gettext('Include columns'), group: gettext('Definition'), editable: false, canDelete: true, canAdd: true, mode: ['properties'], @@ -394,7 +389,7 @@ export default class IndexSchema extends BaseUISchema { readonly: function (state) { return !indexSchemaObj.isNew(state); }, - mode: ['create', 'edit'], group: gettext('Definition'), + mode: ['create'], group: gettext('Definition'), },{ id: 'indconstraint', label: gettext('Constraint'), cell: 'string', type: 'sql', controlProps: {className:['custom_height_css_class']}, @@ -407,7 +402,7 @@ export default class IndexSchema extends BaseUISchema { }, { id: 'columns', label: gettext('Columns'), type: 'collection', deps: ['amname'], group: gettext('Definition'), schema: indexSchemaObj.getColumnSchema(), - mode: ['edit', 'create'], + mode: ['edit', 'create', 'properties'], canAdd: function(state) { // We will disable it if it's in 'edit' mode return indexSchemaObj.isNew(state); 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 83e29e1c..32c92020 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 @@ -27,6 +27,34 @@ "test_result_data": {} } }, + { + "name": "Create index concurrently: With valid data.", + "is_positive_test": true, + "inventory_data": {}, + "test_data": { + "name": "test_index_add", + "spcname": "pg_default", + "amname": "btree", + "isconcurrent": true, + "columns": [ + { + "colname": "id", + "sort_order": false, + "nulls": false + } + ], + "include": [ + "name" + ] + }, + "mocking_required": false, + "mock_data": {}, + "expected_data": { + "status_code": 200, + "error_msg": null, + "test_result_data": {} + } + }, { "name": "Create index: With valid data mumtiple.", "is_positive_test": true, @@ -114,6 +142,7 @@ "name": "test_index_add", "spcname": "pg_default", "amname": "btree", + "isconcurrent": false, "columns": [ { "colname": "id", @@ -128,7 +157,7 @@ "mocking_required": true, "mock_data": { "function_name": "pgadmin.utils.driver.psycopg2.connection.Connection.execute_scalar", - "return_value": "[(True, True),(False, 'Mocked Internal Server Error'),(True,True)]" + "return_value": "[(False, 'Mocked Internal Server Error'),(True,True)]" }, "expected_data": { "status_code": 500, @@ -144,6 +173,7 @@ "name": "test_index_add", "spcname": "pg_default", "amname": "btree", + "isconcurrent": false, "columns": [ { "colname": "id", @@ -158,7 +188,7 @@ "mocking_required": true, "mock_data": { "function_name": "pgadmin.utils.driver.psycopg2.connection.Connection.execute_scalar", - "return_value": "[(True, True),(True, True),(False, 'Mocked Internal Server Error'),(False, 'Mocked Internal Server Error')]" + "return_value": "[(True, True),(False, 'Mocked Internal Server Error'),(False, 'Mocked Internal Server Error')]" }, "expected_data": { "status_code": 500, diff --git a/web/pgadmin/static/js/SchemaView/DataGridView.jsx b/web/pgadmin/static/js/SchemaView/DataGridView.jsx index 8363c6b1..cf11e960 100644 --- a/web/pgadmin/static/js/SchemaView/DataGridView.jsx +++ b/web/pgadmin/static/js/SchemaView/DataGridView.jsx @@ -183,7 +183,7 @@ function DataTableRow({row, totalRows, isResizing, schema, schemaRef, accessPath schemaRef.current.fields.forEach((field)=>{ /* Self change is also dep change */ if(field.depChange || field.deferredDepChange) { - depListener.addDepListener(accessPath.concat(field.id), accessPath.concat(field.id), field.depChange, field.deferredDepChange); + depListener?.addDepListener(accessPath.concat(field.id), accessPath.concat(field.id), field.depChange, field.deferredDepChange); } (evalFunc(null, field.deps) || []).forEach((dep)=>{ let source = accessPath.concat(dep); @@ -191,7 +191,7 @@ function DataTableRow({row, totalRows, isResizing, schema, schemaRef, accessPath source = dep; } if(field.depChange) { - depListener.addDepListener(source, accessPath.concat(field.id), field.depChange); + depListener?.addDepListener(source, accessPath.concat(field.id), field.depChange); } }); });