diff --git a/web/pgadmin/feature_tests/query_tool_tests.py b/web/pgadmin/feature_tests/query_tool_tests.py index ac463d3..226b323 100644 --- a/web/pgadmin/feature_tests/query_tool_tests.py +++ b/web/pgadmin/feature_tests/query_tool_tests.py @@ -104,6 +104,16 @@ class QueryToolFeatureTest(BaseFeatureTest): self._query_tool_notify_statements() self._clear_query_tool() + # explain query with JIT stats + print("Explain query with JIT stats... ", + file=sys.stderr, end="") + if self._supported_jit_on_server(): + self._query_tool_explain_check_jit_stats() + print("OK.", file=sys.stderr) + self._clear_query_tool() + else: + print("Skipped.", file=sys.stderr) + def after(self): self.page.remove_server(self.server) connection = test_utils.get_db_connection( @@ -660,9 +670,62 @@ SELECT 1, pg_sleep(300)""" wait.until(WaitForAnyElementWithText( (By.CSS_SELECTOR, 'td.payload'), "Hello")) print("OK.", file=sys.stderr) + self._clear_query_tool() else: print("Skipped.", file=sys.stderr) + def _supported_jit_on_server(self): + connection = test_utils.get_db_connection( + self.server['db'], + self.server['username'], + self.server['db_password'], + self.server['host'], + self.server['port'], + self.server['sslmode'] + ) + + pg_cursor = connection.cursor() + pg_cursor.execute('select version()') + version_string = pg_cursor.fetchone() + + is_edb = False + if len(version_string) > 0: + is_edb = 'EnterpriseDB' in version_string[0] + + connection.close() + + return connection.server_version >= 110000 and not is_edb + + def _query_tool_explain_check_jit_stats(self): + wait = WebDriverWait(self.page.driver, 10) + + self.page.fill_codemirror_area_with("SET jit_above_cost=10;") + self.page.find_by_id("btn-flash").click() + self.page.wait_for_query_tool_loading_indicator_to_disappear() + self._clear_query_tool() + + self.page.fill_codemirror_area_with("SELECT count(*) FROM pg_class;") + query_op = self.page.find_by_id("btn-query-dropdown") + query_op.click() + ActionChains(self.driver).move_to_element( + query_op.find_element_by_xpath( + "//li[contains(.,'Explain Options')]")).perform() + + self.page.find_by_id("btn-explain-verbose").click() + self.page.find_by_id("btn-explain-costs").click() + self.page.find_by_id("btn-explain-analyze").click() + + self.page.wait_for_query_tool_loading_indicator_to_disappear() + self.page.click_tab('Data Output') + + canvas = wait.until(EC.presence_of_element_located( + (By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")) + ) + # Search for 'Output' word in result (verbose option) + canvas.find_element_by_xpath("//*[contains(string(), 'JIT')]") + + self._clear_query_tool() + class WaitForAnyElementWithText(object): def __init__(self, locator, text): diff --git a/web/pgadmin/misc/static/explain/css/explain.css b/web/pgadmin/misc/static/explain/css/explain.css index d549f85..28605df 100644 --- a/web/pgadmin/misc/static/explain/css/explain.css +++ b/web/pgadmin/misc/static/explain/css/explain.css @@ -17,6 +17,19 @@ opacity: 1; } +.pg-explain-stats-area { + position: absolute; + top: 5px; + right: 25px; +} + +.pg-explain-stats-btn { + top: 5px; + min-width: 25px; + border: 1px solid transparent; + background-color: #7777775c; +} + .explain-tooltip { display: table-cell; text-align: left; @@ -37,8 +50,6 @@ td.explain-tooltip-val { .pgadmin-explain-tooltip { position: absolute; - padding:5px; - border: 1px solid white; opacity:0; color: cornsilk; background-color: #010125; @@ -55,4 +66,10 @@ td.explain-tooltip-val { height: 100%; width: 100%; overflow: auto; -} \ No newline at end of file +} + +.pg-explain-stats-btn-disabled:hover, +.pg-explain-stats-btn-disabled:focus, +.pg-explain-stats-btn-disabled:focus { + color:#fff !important; +} diff --git a/web/pgadmin/misc/static/explain/js/explain.js b/web/pgadmin/misc/static/explain/js/explain.js index e028774..67bb531 100644 --- a/web/pgadmin/misc/static/explain/js/explain.js +++ b/web/pgadmin/misc/static/explain/js/explain.js @@ -615,6 +615,9 @@ define('pgadmin.misc.explain', [ }); toolTipContainer.css('left', toolTipX); toolTipContainer.css('top', toolTipY); + + $('.pgadmin-explain-tooltip').css('padding', '5px'); + $('.pgadmin-explain-tooltip').css('border', '1px solid white'); }); // Remove tooltip when mouse is out from node's area @@ -687,6 +690,87 @@ define('pgadmin.misc.explain', [ }, }); + // Backbone model for other statistics + var StatsModel = Backbone.Model.extend({ + defaults: { + JIT: [], + Triggers: [], + }, + set_statistics: function(xpos, ypos, graphContainer, toolTipContainer) { + var jit_stats = this.get('JIT'), + triggers_stats = this.get('Triggers'); + $('.pg-explain-stats-area').on('mouseover', () => { + + // Empty the tooltip content if it has any and add new data + toolTipContainer.empty(); + if (Object.keys(jit_stats).length == 0 && + Object.keys(triggers_stats).length == 0) { + return; + } + + $('#btn-explain-stats').removeClass('pg-explain-stats-btn-disabled'); + var tooltip = $('