From c019778a47241fe04b8a9423136c0388566be3c7 Mon Sep 17 00:00:00 2001 From: Khushboo Vashi Date: Mon, 22 Jul 2019 18:42:48 +0530 Subject: [PATCH] 1) Fix an error while retrieving json data from the table. Fixes #4427 2) Fix an issue where Explain and Explain Analyze are not working, it's regression of #1760. Fixes #4484 3) Fix an issue where Filter toolbar button is not working in view/edit data, it's regression of keyboard navigation. Fixes #4485 --- docs/en_US/release_notes_4_11.rst | 5 +- web/pgadmin/static/js/backform.pgadmin.js | 38 ++++--- .../js/sqleditor/call_render_after_poll.js | 5 +- web/pgadmin/tools/sqleditor/__init__.py | 2 + .../tools/sqleditor/static/js/sqleditor.js | 14 ++- .../sqleditor/tests/test_save_changed_data.py | 2 +- .../tools/sqleditor/tests/test_view_data.py | 98 +++++++++++++++++++ 7 files changed, 144 insertions(+), 20 deletions(-) create mode 100644 web/pgadmin/tools/sqleditor/tests/test_view_data.py diff --git a/docs/en_US/release_notes_4_11.rst b/docs/en_US/release_notes_4_11.rst index ac4bc202e..f6ccd3452 100644 --- a/docs/en_US/release_notes_4_11.rst +++ b/docs/en_US/release_notes_4_11.rst @@ -40,6 +40,7 @@ Bug fixes | `Issue #4389 `_ - Fix an error that could be seen when editing column privileges. | `Issue #4393 `_ - Ensure parameter values are quoted when needed when editing roles. | `Issue #4395 `_ - EXPLAIN options should be Query Tool instance-specific. +| `Issue #4427 `_ - Fix an error while retrieving json data from the table. | `Issue #4428 `_ - Fix 'malformed array literal' error when updating a pgAgent job. | `Issue #4429 `_ - Ensure drag/drop from the treeview works as expected on Firefox. | `Issue #4437 `_ - Fix table icon issue when updating any existing field. @@ -48,4 +49,6 @@ Bug fixes | `Issue #4448 `_ - Fix an error seen when updating a connection string in a pgAgent job step. | `Issue #4450 `_ - Fix reverse engineered sql for Foreign Data Wrapper created on EPAS server in redwood mode. | `Issue #4462 `_ - Fix some minor UI issues on IE11. -| `Issue #4470 `_ - Fix sequence reverse engineered SQL generation with quoted names on PG/EPAS 10+. \ No newline at end of file +| `Issue #4470 `_ - Fix sequence reverse engineered SQL generation with quoted names on PG/EPAS 10+. +| `Issue #4484 `_ - Fix an issue where Explain and Explain Analyze are not working, it's regression of #1760. +| `Issue #4485 `_ - Fix an issue where Filter toolbar button is not working in view/edit data, it's regression of keyboard navigation. \ No newline at end of file diff --git a/web/pgadmin/static/js/backform.pgadmin.js b/web/pgadmin/static/js/backform.pgadmin.js index 156430df4..012a7432b 100644 --- a/web/pgadmin/static/js/backform.pgadmin.js +++ b/web/pgadmin/static/js/backform.pgadmin.js @@ -1271,12 +1271,19 @@ define([ var $dialog = gridBody.append(subNodeGrid); - let preferences = pgBrowser.get_preferences_for_module('browser'); - let addBtn = $dialog.find('.add'); - // Add title to the buttons - $(addBtn) - .attr('title', - keyboardShortcuts.shortcut_title(gettext('Add new row'),preferences.add_grid_row)); + let tmp_browser = pgBrowser; + if (pgBrowser.preferences_cache.length == 0) + tmp_browser = window.opener ? window.opener.pgAdmin.Browser : window.top.pgAdmin.Browser; + + let preferences = tmp_browser.get_preferences_for_module('browser'); + + if (preferences) { + let addBtn = $dialog.find('.add'); + // Add title to the buttons + $(addBtn) + .attr('title', + keyboardShortcuts.shortcut_title(gettext('Add new row'),preferences.add_grid_row)); + } // Add button callback if (!(data.disabled || data.canAdd == false)) { @@ -1563,12 +1570,19 @@ define([ var $dialog = gridBody.append(subNodeGrid); - let preferences = pgBrowser.get_preferences_for_module('browser'); - let addBtn = $dialog.find('.add'); - // Add title to the buttons - $(addBtn) - .attr('title', - keyboardShortcuts.shortcut_title(gettext('Add new row'),preferences.add_grid_row)); + let tmp_browser = pgBrowser; + if (pgBrowser.preferences_cache.length == 0) + tmp_browser = window.opener ? window.opener.pgAdmin.Browser : window.top.pgAdmin.Browser; + + let preferences = tmp_browser.get_preferences_for_module('browser'); + + if (preferences) { + let addBtn = $dialog.find('.add'); + // Add title to the buttons + $(addBtn) + .attr('title', + keyboardShortcuts.shortcut_title(gettext('Add new row'),preferences.add_grid_row)); + } // Add button callback diff --git a/web/pgadmin/static/js/sqleditor/call_render_after_poll.js b/web/pgadmin/static/js/sqleditor/call_render_after_poll.js index 57d60537c..ec18b10b5 100644 --- a/web/pgadmin/static/js/sqleditor/call_render_after_poll.js +++ b/web/pgadmin/static/js/sqleditor/call_render_after_poll.js @@ -36,7 +36,10 @@ export function callRenderAfterPoll(sqlEditor, alertify, res) { sqlEditor.query_end_time); const msg = sprintf( gettext('Query returned successfully in %s.'), sqlEditor.total_time); - res.result += '\n\n' + msg; + if (res.result) + res.result += '\n\n' + msg; + else + res.result = msg; sqlEditor.update_msg_history(true, res.result, true); sqlEditor.reset_data_store(); if (isNotificationEnabled(sqlEditor)) { diff --git a/web/pgadmin/tools/sqleditor/__init__.py b/web/pgadmin/tools/sqleditor/__init__.py index 851e3f363..d74357023 100644 --- a/web/pgadmin/tools/sqleditor/__init__.py +++ b/web/pgadmin/tools/sqleditor/__init__.py @@ -407,6 +407,8 @@ def poll(trans_id): if (result != 'SELECT 1' or result != 'SELECT 0') and \ result is not None and additional_messages: result = additional_messages + result + else: + result = None if st: if 'primary_keys' in session_obj: diff --git a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js index 5d734da53..217344107 100644 --- a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js +++ b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js @@ -705,7 +705,7 @@ define('tools.querytool', [ */ // This function is responsible to create and render the SlickGrid. - render_grid: function(collection, columns, is_editable, client_primary_key, rows_affected) { + render_grid: function(collection, columns, is_editable, client_primary_key, rows_affected, is_explain_plan) { var self = this; self.handler.numberOfModifiedCells = 0; @@ -824,7 +824,7 @@ define('tools.querytool', [ } var grid_options = { - editable: is_editable, + editable: is_editable || is_explain_plan, enableAddRow: is_editable, enableCellNavigation: true, enableColumnReorder: false, @@ -2379,7 +2379,7 @@ define('tools.querytool', [ */ _render: function(data) { var self = this; - self.colinfo = data.col_info; + self.colinfo = data.colinfo; self.primary_keys = (_.isEmpty(data.primary_keys) && data.has_oids) ? data.oids : data.primary_keys; self.client_primary_key = data.client_primary_key; self.cell_selected = false; @@ -2388,6 +2388,7 @@ define('tools.querytool', [ self.has_oids = data.has_oids; self.oids = data.oids; $('.sql-editor-explain').empty(); + self.explain_plan = false; /* If object don't have primary keys then set the * can_edit flag to false. @@ -2463,9 +2464,12 @@ define('tools.querytool', [ var explain_data_array = [], explain_data_json = null; - if(data.types[0] && data.types[0].typname === 'json') { + + if(self.colinfo[0].name == 'QUERY PLAN' && data.result + && data.types[0] && data.types[0].typname === 'json') { /* json is sent as text, parse it */ explain_data_json = JSON.parse(data.result[0][0]); + self.is_explain_plan = true; } if (explain_data_json && explain_data_json[0] && @@ -2481,7 +2485,7 @@ define('tools.querytool', [ function() { self.gridView.render_grid( explain_data_array, self.columns, self.can_edit, - self.client_primary_key + self.client_primary_key, 0, self.is_explain_plan ); // Make sure - the 'Explain' panel is visible, before - we // start rendering the grid. diff --git a/web/pgadmin/tools/sqleditor/tests/test_save_changed_data.py b/web/pgadmin/tools/sqleditor/tests/test_save_changed_data.py index badf1c613..29e9cce3b 100644 --- a/web/pgadmin/tools/sqleditor/tests/test_save_changed_data.py +++ b/web/pgadmin/tools/sqleditor/tests/test_save_changed_data.py @@ -251,7 +251,7 @@ class TestSaveChangedData(BaseTestGenerator): }, save_status=True, check_sql='SELECT * FROM %s WHERE pk_col = 2', - check_result='SELECT 0' + check_result=None )), ] diff --git a/web/pgadmin/tools/sqleditor/tests/test_view_data.py b/web/pgadmin/tools/sqleditor/tests/test_view_data.py new file mode 100644 index 000000000..dc96f9cde --- /dev/null +++ b/web/pgadmin/tools/sqleditor/tests/test_view_data.py @@ -0,0 +1,98 @@ +########################################################################## +# +# pgAdmin 4 - PostgreSQL Tools +# +# Copyright (C) 2013 - 2019, The pgAdmin Development Team +# This software is released under the PostgreSQL Licence +# +########################################################################## + +import uuid +import json +import random + +from pgadmin.utils.route import BaseTestGenerator +from pgadmin.browser.server_groups.servers.databases.tests import utils as \ + database_utils +from regression import parent_node_dict +from regression.python_test_utils import test_utils +from pgadmin.utils import server_utils, IS_PY2 + + +class TestViewData(BaseTestGenerator): + """ + This class checks the view data result for a table with JSON datatype + """ + skip_on_database = ['gpdb'] + scenarios = [ + ( + 'Table with JSON datatype', + dict( + table_sql="""Create Table ( + id integer Not Null, + json_val json Not Null, + Constraint table_pk Primary Key(id) + );""", + result_data=None, + rows_fetched_to=0 + ) + ) + ] + + def setUp(self): + self.server_id = self.server_information['server_id'] + self.database_info = parent_node_dict["database"][-1] + self.db_name = self.database_info["db_name"] + self.db_id = self.database_info["db_id"] + + self.connection = test_utils.get_db_connection( + self.db_name, + self.server['username'], + self.server['db_password'], + self.server['host'], + self.server['port'] + ) + + def runTest(self): + self.table = "test_table_%s" % (str(uuid.uuid4())[1:8]) + self.table_sql = self.table_sql.replace('', self.table) + # Create table + test_utils.create_table_with_query(self.server, + self.db_name, + self.table_sql) + + # Fetch Table OID + pg_cursor = self.connection.cursor() + pg_cursor.execute("""Select oid FROM pg_class WHERE + relname = '%s' AND relkind IN ('r','s','t')""" % self.table) + + result = pg_cursor.fetchall() + table_id = result[0][0] + + # Initialize query tool + url = '/datagrid/initialize/datagrid/3/table/{0}/{1}/{2}/{3}'.format( + test_utils.SERVER_GROUP, self.server_id, self.db_id, table_id) + response = self.tester.post(url) + + self.assertEquals(response.status_code, 200) + + response_data = json.loads(response.data.decode('utf-8')) + self.trans_id = response_data['data']['gridTransId'] + + url = "/sqleditor/view_data/start/{0}".format(self.trans_id) + response = self.tester.get(url) + self.assertEquals(response.status_code, 200) + + # Check the query result + url = '/sqleditor/poll/{0}'.format(self.trans_id) + response = self.tester.get(url) + self.assertEquals(response.status_code, 200) + response_data = json.loads(response.data.decode('utf-8')) + + self.assertEquals(response_data['data']['result'], self.result_data) + self.assertEquals(response_data['data']['rows_fetched_to'], + self.rows_fetched_to) + + def tearDown(self): + database_utils.disconnect_database(self, self.server_id, + self.db_id)