Added support to create an unnamed index. #3318
parent
ed941b5b95
commit
d6ecc531e0
|
@ -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 <https://github.com/pgadmin-org/pgadmin4/issues/3275>`_ - Allow on demand record count setting to be changed per user using preferences.
|
||||
| `Issue #3316 <https://github.com/pgadmin-org/pgadmin4/issues/3316>`_ - Added support to show statistics for materialized views.
|
||||
| `Issue #3318 <https://github.com/pgadmin-org/pgadmin4/issues/3318>`_ - Added support to create an unnamed index.
|
||||
|
||||
Housekeeping
|
||||
************
|
||||
|
@ -33,5 +34,8 @@ Bug fixes
|
|||
| `Issue #5777 <https://github.com/pgadmin-org/pgadmin4/issues/5777>`_ - Fixed an issue where the browser tree state is not remembered when reopening pgAdmin.
|
||||
| `Issue #5820 <https://github.com/pgadmin-org/pgadmin4/issues/5820>`_ - Fixed an issue where collation was set to none if we remove it while creating partitioned table.
|
||||
| `Issue #6075 <https://github.com/pgadmin-org/pgadmin4/issues/6075>`_ - Ensure that the save button is enabled when registering a new server fails due to an API error.
|
||||
| `Issue #6120 <https://github.com/pgadmin-org/pgadmin4/issues/6120>`_ - Fixed error occurring while logging out from pgAdmin keeping a query tool opened.
|
||||
| `Issue #6128 <https://github.com/pgadmin-org/pgadmin4/issues/6128>`_ - Fix a SQL error occurring on roles dependents SQL.
|
||||
| `Issue #6130 <https://github.com/pgadmin-org/pgadmin4/issues/6130>`_ - Ensure to quote the primary key value if needed while deleting rows from the table.
|
||||
| `Issue #6137 <https://github.com/pgadmin-org/pgadmin4/issues/6137>`_ - Fixed error occurring while dumping the servers from CLI.
|
||||
| `Issue #6138 <https://github.com/pgadmin-org/pgadmin4/issues/6138>`_ - Throw an appropriate error when a table for which View/Edit data is open, is deleted, and query is executed.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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: ''};
|
||||
}
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
CREATE INDEX
|
||||
ON public.test_table_for_indexes USING hash
|
||||
(id)
|
||||
TABLESPACE pg_default;
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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' %}
|
||||
|
|
|
@ -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' %}
|
||||
|
|
|
@ -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;
|
Loading…
Reference in New Issue