public inbox for [email protected]  
help / color / mirror / Atom feed
From: Akshay Joshi <[email protected]>
To: Dave Page <[email protected]>
Cc: pgadmin-hackers <[email protected]>
Subject: Re: [pgAdmin4][Patch]: RM #3397 Add support for JIT stats in EXPLAIN output in PG11
Date: Sat, 30 Jun 2018 13:45:36 +0530
Message-ID: <CANxoLDd7P5QKxbhbQ93Hw=gF0NQdFt2pyy5XnQ_LThTVmk8Bnw@mail.gmail.com> (raw)
In-Reply-To: <CA+OCxow4L5AL8QNYxVckjGVtaN9h+J+72Kg_wjuQ+qJA5ffShw@mail.gmail.com>
References: <CANxoLDdnaPB8gt-v+4aVY2urY8suGqK=pFiWFZ-Agxkgkx_VYw@mail.gmail.com>
	<CA+OCxozxjz+m=zy_AN4QPQtNHKuYTpQ6YpihoS=ugpzLe_jvEQ@mail.gmail.com>
	<CANxoLDcKr_A+gCBwgdG6GGrc78Rm2mtLsvmL-pEx7UPSPg8kBA@mail.gmail.com>
	<CA+OCxow4L5AL8QNYxVckjGVtaN9h+J+72Kg_wjuQ+qJA5ffShw@mail.gmail.com>

Hi Dave

On Fri, Jun 29, 2018 at 7:45 PM, Dave Page <[email protected]> wrote:

>
>
> On Fri, Jun 29, 2018 at 3:12 PM, Akshay Joshi <
> [email protected]> wrote:
>
>> Hi Dave
>>
>> On Fri, Jun 29, 2018 at 6:56 PM, Dave Page <[email protected]> wrote:
>>
>>> Hi
>>>
>>> On Fri, Jun 29, 2018 at 9:55 AM, Akshay Joshi <
>>> [email protected]> wrote:
>>>
>>>> Hi Hackers,
>>>>
>>>> Attached is the patch to fix the RM #3397 Add support for JIT stats in
>>>> EXPLAIN output in PG11. Please review it.
>>>>
>>>
>>> A couple of immediate thoughts:
>>>
>>> - When the canvas is first rendered, there's a vertical scrollbar now.
>>> As soon as I mouseover the new icon, it vanishes and the icon jumps to the
>>> right.
>>>
>>
>>      Will look into it. Vertical scrollbar comes even if you remove my
>> patch and try to hover any image.
>>
>>>
>>> - The icon seems lighter than the other controls on the left.
>>>
>>
>>      Same css has been applied, only difference is button is disabled.
>>
>>>
>>> - The icon isn't disabled when there is no info to show.
>>>
>>
>>      Button is always disabled, I have just change the opacity.
>>
>>>
>>> Thanks.
>>>
>>
> Maybe - but I can still click it and it reacts as if it's active. It may
> be lighter to indicate that it's disabled, but its not behaving as such.
>

    Attached is the modified patch. Please review it.

>
> --
> Dave Page
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
> EnterpriseDB UK: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>



-- 
*Akshay Joshi*

*Sr. Software Architect *



*Phone: +91 20-3058-9517Mobile: +91 976-788-8246*


Attachments:

  [application/octet-stream] RM_3397_v2.patch (9.3K, 3-RM_3397_v2.patch)
  download | inline diff:
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..38bb322 100644
--- a/web/pgadmin/misc/static/explain/css/explain.css
+++ b/web/pgadmin/misc/static/explain/css/explain.css
@@ -17,6 +17,18 @@
    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;
+}
+
 .explain-tooltip {
   display: table-cell;
   text-align: left;
@@ -37,8 +49,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 +65,4 @@ td.explain-tooltip-val {
   height: 100%;
   width: 100%;
   overflow: auto;
-}
\ No newline at end of file
+}
diff --git a/web/pgadmin/misc/static/explain/js/explain.js b/web/pgadmin/misc/static/explain/js/explain.js
index e028774..04cc7f8 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,85 @@ 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;
+        }
+
+        var tooltip = $('<table></table>', {
+          class: 'pgadmin-tooltip-table',
+        }).appendTo(toolTipContainer);
+
+        if (Object.keys(jit_stats).length > 0){
+          tooltip.append('<tr><td class="label explain-tooltip">JIT:</td></tr>');
+          _.each(jit_stats, function(value, key) {
+            tooltip.append('<tr><td class="label explain-tooltip">&nbsp&nbsp'
+            + key + '</td><td class="label explain-tooltip-val">'
+            + value + '</td></tr>');
+          });
+        }
+
+        if (Object.keys(triggers_stats).length > 0){
+          tooltip.append('<tr><td class="label explain-tooltip">Triggers:</td></tr>');
+          _.each(triggers_stats, function(triggers, key_id) {
+            if (triggers instanceof Object) {
+              _.each(triggers, function(value, key) {
+                if (key === 'Trigger Name') {
+                  tooltip.append('<tr><td class="label explain-tooltip">&nbsp;&nbsp;'
+                  + key + '</td><td class="label explain-tooltip-val">'
+                  + value + '</td></tr>');
+                } else {
+                  tooltip.append('<tr><td class="label explain-tooltip">&nbsp;&nbsp;&nbsp;&nbsp;'
+                  + key + '</td><td class="label explain-tooltip-val">'
+                  + value + '</td></tr>');
+                }
+              });
+            }
+            else {
+              tooltip.append('<tr><td class="label explain-tooltip">&nbsp;&nbsp;'
+              + key_id + '</td><td class="label explain-tooltip-val">'
+              + triggers + '</td></tr>');
+            }
+          });
+        }
+
+        // Show toolTip at respective x,y coordinates
+        toolTipContainer.css({
+          'opacity': '0.8',
+          'left': '',
+          'right': '65px',
+          'top': '15px',
+        });
+
+        $('.pgadmin-explain-tooltip').css('padding', '5px');
+        $('.pgadmin-explain-tooltip').css('border', '1px solid white');
+      });
+
+      // Remove tooltip when mouse is out from node's area
+      $('.pg-explain-stats-area').on('mouseout', () => {
+        toolTipContainer.empty();
+        toolTipContainer.css({
+          'opacity': '0',
+          'left': 0,
+          'top': 0,
+        });
+      });
+    },
+  });
+
   // Main backbone model to store JSON object
   var MainPlanModel = Backbone.Model.extend({
     defaults: {
@@ -696,6 +778,7 @@ define('pgadmin.misc.explain', [
     },
     initialize: function() {
       this.set('Plan', new PlanModel());
+      this.set('Statistics', new StatsModel());
     },
 
     // Parse the JSON data and fetch its children plans
@@ -718,6 +801,17 @@ define('pgadmin.misc.explain', [
         delete data['Plan'];
       }
 
+      var stats = this.get('Statistics');
+      if (data && 'JIT' in data) {
+        stats.set('JIT', data['JIT']);
+        delete data ['JIT'];
+      }
+
+      if (data && 'Triggers' in data) {
+        stats.set('Triggers', data['Triggers']);
+        delete data ['Triggers'];
+      }
+
       return data;
     },
     toJSON: function() {
@@ -745,6 +839,10 @@ define('pgadmin.misc.explain', [
       plan.draw(
         g, xpos, ypos, undefined, undefined, graphContainer, toolTipContainer
       );
+
+      //Set the Statistics as tooltip
+      var stats = this.get('Statistics');
+      stats.set_statistics(xpos, ypos, graphContainer, toolTipContainer);
     },
   });
 
@@ -784,6 +882,22 @@ define('pgadmin.misc.explain', [
             class: 'fa fa-search-minus',
           }));
 
+      var statsArea = $('<div></div>', {
+        class: 'pg-explain-stats-area btn-group',
+        role: 'group',
+      }).appendTo(container);
+
+      $('<button></button>', {
+        id: 'btn-explain-stats',
+        class: 'btn pg-explain-stats-btn badge',
+        title: 'Statistics',
+        tabindex: 0,
+        disabled: 'disabled',
+      }).appendTo(statsArea).append(
+        $('<i></i>', {
+          class: 'fa fa-line-chart',
+        }));
+
       // Main div to be drawn all images on
       var planDiv = $('<div></div>', {
           class: 'pgadmin-explain-container',


view thread (12+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected]
  Subject: Re: [pgAdmin4][Patch]: RM #3397 Add support for JIT stats in EXPLAIN output in PG11
  In-Reply-To: <CANxoLDd7P5QKxbhbQ93Hw=gF0NQdFt2pyy5XnQ_LThTVmk8Bnw@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox