public inbox for [email protected]  
help / color / mirror / Atom feed
From: Neel Patel <[email protected]>
To: Dave Page <[email protected]>
Cc: pgadmin-hackers <[email protected]>
Subject: Re: [pgAdmin4][Debugger]: Initial Patch
Date: Mon, 25 Apr 2016 19:18:33 +0530
Message-ID: <CACCA4P2wpVMKCFSvdiWVt49bAiQYKnVnNemqLgZ=p=Qnk1M=9A@mail.gmail.com> (raw)
In-Reply-To: <CA+OCxoxQTncHeTw-Wd=Vmoa1BcouenV00MypEOwz0sGBRJobRA@mail.gmail.com>
References: <CACCA4P1PzVEELk_=8NbpKtgOwVSypG--jRssRLtb8i_SWCcHtg@mail.gmail.com>
	<CA+OCxoyxgw6W8rxUFU=FqeasjJUT+VE+odUGN1JeY-ZVmqNr7Q@mail.gmail.com>
	<CACCA4P2bT+yHiHidnaA9poLZ8ZVLU57pJc8qArmK_nmw=YxHVg@mail.gmail.com>
	<CACCA4P2FuiVH-+xJh1gC5KJAeS4yTZuqMJHHh1u1fgpHdXZFgg@mail.gmail.com>
	<CACCA4P0kT0v9FuC2e_4ua0Jz2DBR8yFjeWKDQG-c--0c5KUY=A@mail.gmail.com>
	<CACCA4P3Qzq=PXWhX2iG7cXNVexJO--RQaK++pE54yKzCVPXcDw@mail.gmail.com>
	<CA+OCxowidzrBrk1C-Z4JyF5Hqpk43TY8RQXtPwHd5TCgBdQQ8g@mail.gmail.com>
	<CACCA4P3DMJ3ArcwZ5v-AOOuHwfMJQqc-iNCeeu09XdHL3rsG1Q@mail.gmail.com>
	<CA+OCxoycghjOcbiRd+sDhYFdOgADhXAc=82HZ=XKmS-CsasqhA@mail.gmail.com>
	<CACCA4P3kNCbDc_BvYi69yDFc2cO44c5yoZg3LRA04REyjYJegg@mail.gmail.com>
	<CA+OCxozPzu3oZxqndT9kihiCU-JjYAgyhHM_xdGaEGErkdXTLw@mail.gmail.com>
	<CACCA4P26NCZhfVVn=AfM3sd1t-JvC-hzEzK84M-O8K6Vz-Jp-A@mail.gmail.com>
	<CA+OCxoxQTncHeTw-Wd=Vmoa1BcouenV00MypEOwz0sGBRJobRA@mail.gmail.com>
List-Unsubscribe:  <mailto:[email protected]?body=unsub%20pgadmin-hackers>

Hi,

Please find attached patch file with below fixes.

   - Removed the "lineWrapping" option from the codemirror textarea because
   it was creating issue in the code folding.
   - Handle the values while depositing during debugging.
   - Properly handle the Array values while saving it to sqlite database
   and displayed in input dialog.
   - SQL code folding was not supported in codemirror so added the same.
   Currently we have added support for below keywords.
         IF-END IF
         LOOP-END LOOP
         BEGIN - END
         CASE- END CASE
   We will add more SQL folding support later ( e.g. Fold multiline query
   inside function, Folding of create function etc.)

           As query tool also requires the use of code folding so below is
the usage for it.
              - Define below require javascript files in modules.
                 'codemirror/addon/fold/foldgutter',
                 'codemirror/addon/fold/foldcode',
                 'codemirror/addon/fold/pgadmin-sqlfoldcode'

              - Remove "lineWrapping" option from the codemirror textarea.

              - Add the below options while creating the Codemirror
textarea.

                      *foldOptions*: {
                        widget: "\u2026"
                      },
                      *foldGutter*: {
                        rangeFinder:
CodeMirror.fold.combine(CodeMirror.pgadminBeginRangeFinder,
CodeMirror.pgadminIfRangeFinder,

 CodeMirror.pgadminLoopRangeFinder, CodeMirror.pgadminCaseRangeFinder)
                     },
                     *gutters*: ["CodeMirror-foldgutter"]


Do review it and let us know for comments.

Thanks,
Neel Patel


On Wed, Apr 20, 2016 at 6:32 PM, Dave Page <[email protected]> wrote:

> Thanks - applied!
>
>
> On Tuesday, April 19, 2016, Neel Patel <[email protected]>
> wrote:
>
>> Hi Dave,
>>
>> Please find the attached patch file with below fix.
>>
>>    - Remove the duplicate CSS and used the actual class for the debugger
>>    button toolbar.
>>    - As per the Ashesh's comment, previously we used 2 wcDocker instance
>>    to arrange the multiple tabs to main debugger panel. Now with this patch
>>    file, we have used only 1 wcDocker instance.
>>
>> Do review it and let us know for comments.
>>
>> Thanks,
>> Neel  Patel
>>
>> On Mon, Apr 18, 2016 at 6:07 PM, Dave Page <[email protected]> wrote:
>>
>>> Hi
>>>
>>> On Monday, April 18, 2016, Neel Patel <[email protected]>
>>> wrote:
>>>
>>>> Hi Dave,
>>>>
>>>> Please find inline comments with all the fixes.
>>>> Attached is the updated patch file. Do review it and let me know for
>>>> any comments.
>>>>
>>>> If you find any issues, let me know .Now, Working on the remaining
>>>> TODOs as mentioned in below email.
>>>>
>>>
>>> Thanks - committed with some minor tweaks. One problem partly still
>>> remains though - you've partially copied the toolbar styling. Please use
>>> the actual classes used by the Properties panel. I've already updated the
>>> query tool in that way. Whilst your version looks much closer, it's missing
>>> the minimum button widths, and duplicates CSS unnecessarily.
>>>
>>> Thanks.
>>>
>>>
>>>>
>>>> On Fri, Apr 15, 2016 at 2:09 AM, Dave Page <[email protected]> wrote:
>>>>
>>>>> Hi
>>>>>
>>>>> On Thu, Apr 14, 2016 at 1:52 PM, Neel Patel <
>>>>> [email protected]> wrote:
>>>>> > Hi,
>>>>> >
>>>>> > Please find attached v2 patch file of the debugger which fixes the
>>>>> below
>>>>> > issues which was not present in the first patch.
>>>>> > In this patch, we have added new table in sqlite database to store
>>>>> the
>>>>> > functions arguments value user has given during debugging.
>>>>> > After applying this patch, user needs to execute "setup.py" to
>>>>> create the
>>>>> > new table in pgadmin4.db file.
>>>>> >
>>>>> > In direct debugging, when user debug the function then arguments
>>>>> values will
>>>>> > be stored in the sqlite database so when user debug the same
>>>>> function again
>>>>> > then previous values will be filled in the user input dialog.
>>>>> > Once the execution is completed then user will be able to do the
>>>>> debug of
>>>>> > the same function again by pressing the "Continue/Restart" button.
>>>>> > User can debug the "procedure" which is supported in PPAS database.
>>>>> > Replaced the "Glyphicon" with the "font-awesome" icons.
>>>>>
>>>>> Very cool! Committed, understanding that there are still improvements
>>>>> to be made.
>>>>>
>>>>> > Below are the TODOs
>>>>> >
>>>>> > Validate the input arguments values changed by user while depositing
>>>>> the
>>>>> > value during debugging.
>>>>> > Need to implement the code folding in the codemirror editor area.
>>>>> > As per the Ashesh's suggestion, need to add debug logs information
>>>>> so that
>>>>> > we can get the state of the debug function. Also need to add "arrow"
>>>>> next to
>>>>> > breakpoint in the gutters as per the pgadmin3.
>>>>> > Need to add "Debug package initializer" in the user input dialog for
>>>>> the
>>>>> > direct debugging.
>>>>> > Last but not least "Review comments" :)
>>>>>
>>>>> Here you go :-)
>>>>>
>>>>> - Ensure all messages are gettext enabled.
>>>>>
>>>>
>>>> Fixed.
>>>>
>>>>>
>>>>> - Constructs like the following won't work, because Jinja will
>>>>> evaluate the string " + err.errormsg + " before it ever gets evaluated
>>>>> as JS by the browser.
>>>>>
>>>>> Alertify.alert("{{ _('" + err.errormsg + "') }}");
>>>>>
>>>>
>>>> Fixed.
>>>>
>>>>
>>>>>
>>>>> - Please adjust the button bar to use the same styling as the button
>>>>> bar on the Properties tab.
>>>>>
>>>>
>>>> Fixed
>>>>
>>>>>
>>>>> - Let's make the stack pane tab part of the tabset at the bottom of
>>>>> the debugger, and ensure docking etc. works so tabs can be split off
>>>>> and arranged around the main source window.
>>>>>
>>>>
>>>> Fixed. Now stack pane will be displayed along with another panel at
>>>> bottom and also docking has been introduced for all the panels so tabs will
>>>> be arranged around main debugger panel.
>>>>
>>>>
>>>>>
>>>>> - Stepping is quite slow. What's causing that? I wonder if we really
>>>>> need to have all the one line SQL templates - they're probably quite
>>>>> expensive to process.
>>>>>
>>>> Fixed. This is due to polling timeout was high (1 second) and we are
>>>> getting delay in getting the results. Now polling timeout has reduced to to
>>>> 200ms.
>>>>
>>>>>
>>>>> - Is backend_running.sql required? I've removed both versions as I
>>>>> can't find any references to them. Are any other templates not
>>>>> required?
>>>>>
>>>> Ok. No other templates.
>>>>
>>>>>
>>>>> Will log any other issues that come up in further work.
>>>>>
>>>>> > Below functionalities are implemented but testing are pending.
>>>>> >
>>>>> > Trigger functions need to test with the debugger.
>>>>> > Functions are tested with data types (like text, integer etc.)  but
>>>>> it needs
>>>>> > to be tested with all the data types for direct debugging.
>>>>> > Functions/Procedures need to test with PPAS 9.2 and earlier version
>>>>> where
>>>>> > debugger version is different.
>>>>>
>>>>> Thanks!
>>>>>
>>>>> --
>>>>> Dave Page
>>>>> Blog: http://pgsnake.blogspot.com
>>>>> Twitter: @pgsnake
>>>>>
>>>>> EnterpriseDB UK: http://www.enterprisedb.com
>>>>> The Enterprise PostgreSQL Company
>>>>>
>>>>
>>>>
>>>
>>> --
>>> Dave Page
>>> Blog: http://pgsnake.blogspot.com
>>> Twitter: @pgsnake
>>>
>>> EnterpriseDB UK: http://www.enterprisedb.com
>>> The Enterprise PostgreSQL Company
>>>
>>>
>>
>
> --
> Dave Page
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
> EnterpriseDB UK: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
>


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers


Attachments:

  [application/octet-stream] debugger_25_April_Fixes.patch (25.3K, 3-debugger_25_April_Fixes.patch)
  download | inline diff:
diff --git a/web/pgadmin/static/js/backgrid/backgrid.pgadmin.js b/web/pgadmin/static/js/backgrid/backgrid.pgadmin.js
index 999ac7c..60f6b84 100644
--- a/web/pgadmin/static/js/backgrid/backgrid.pgadmin.js
+++ b/web/pgadmin/static/js/backgrid/backgrid.pgadmin.js
@@ -762,9 +762,10 @@
     initialize: function() {
       Backgrid.Cell.prototype.initialize.apply(this, arguments);
         // set value to empty array.
+        var m = arguments[0].model;
         if (_.isUndefined(this.collection)) {
             this.collection = new (Backbone.Collection.extend({
-            model: arrayCellModel}));
+            model: arrayCellModel}))(m.get('value'));
         }
 
         this.model.set(this.column.get('name'), this.collection);
@@ -784,9 +785,10 @@
     initialize: function() {
       Backgrid.Cell.prototype.initialize.apply(this, arguments);
         // set value to empty array.
+        var m = arguments[0].model;
         if (_.isUndefined(this.collection)) {
             this.collection = new (Backbone.Collection.extend({
-            model: arrayCellModel}));
+            model: arrayCellModel}))(m.get('value'));
         }
 
 
diff --git a/web/pgadmin/static/js/codemirror/addon/fold/pgadmin-sqlfoldcode.js b/web/pgadmin/static/js/codemirror/addon/fold/pgadmin-sqlfoldcode.js
new file mode 100644
index 0000000..81f8393
--- /dev/null
+++ b/web/pgadmin/static/js/codemirror/addon/fold/pgadmin-sqlfoldcode.js
@@ -0,0 +1,83 @@
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("../../lib/codemirror"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["../../lib/codemirror"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
+  "use strict";
+
+  CodeMirror.pgadminKeywordRangeFinder = function(cm, start, startTkn, endTkn) {
+    var line = start.line, lineText = cm.getLine(line);
+    var at = lineText.length, startChar, tokenType;
+    for (; at > 0;) {
+      var found = lineText.lastIndexOf(startTkn, at);
+      var startToken = startTkn;
+      var endToken = endTkn;
+      if (found < start.ch) {
+        var found = lineText.lastIndexOf("[", at);
+        if (found < start.ch) break;
+        var startToken = '[';
+        var endToken = ']';
+      }
+
+      tokenType = cm.getTokenAt(CodeMirror.Pos(line, found + 1)).type;
+      if (!/^(comment|string)/.test(tokenType)) { startChar = found; break; }
+      at = found - 1;
+    }
+    if (startChar == null || lineText.lastIndexOf(startToken) > startChar) return;
+    var count = 1, lastLine = cm.lineCount(), end, endCh;
+    outer: for (var i = line + 1; i < lastLine; ++i) {
+      var text = cm.getLine(i), pos = 0;
+      for (;;) {
+        var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos);
+        if (nextOpen < 0) nextOpen = text.length;
+        if (nextClose < 0) nextClose = text.length;
+        pos = Math.min(nextOpen, nextClose);
+        if (pos == text.length) break;
+        if (cm.getTokenAt(CodeMirror.Pos(i, pos + 1)).type == tokenType) {
+          if (pos == nextOpen) ++count;
+          else if (!--count) {
+            end = i;
+            endCh = pos;
+            break outer;
+          }
+        }
+        ++pos;
+      }
+    }
+    if (end == null || end == line + 1) return;
+    return {from: CodeMirror.Pos(line, startChar + startTkn.length),
+          to: CodeMirror.Pos(end, endCh)};
+  };
+
+  CodeMirror.pgadminBeginRangeFinder = function(cm, start) {
+    var startToken = 'BEGIN';
+    var endToken = 'END;';
+    var fromToPos = CodeMirror.pgadminKeywordRangeFinder(cm, start, startToken, endToken);
+    return fromToPos;
+  };
+
+  CodeMirror.pgadminIfRangeFinder = function(cm, start) {
+    var startToken = 'IF';
+    var endToken = 'END IF';
+    var fromToPos = CodeMirror.pgadminKeywordRangeFinder(cm, start, startToken, endToken);
+    return fromToPos;
+  };
+
+  CodeMirror.pgadminLoopRangeFinder = function(cm, start) {
+    var startToken = 'LOOP';
+    var endToken = 'END LOOP';
+    var fromToPos = CodeMirror.pgadminKeywordRangeFinder(cm, start, startToken, endToken);
+    return fromToPos;
+  };
+
+  CodeMirror.pgadminCaseRangeFinder = function(cm, start) {
+    var startToken = 'CASE';
+    var endToken = 'END CASE';
+    var fromToPos = CodeMirror.pgadminKeywordRangeFinder(cm, start, startToken, endToken);
+    return fromToPos;
+  };
+
+});
diff --git a/web/pgadmin/tools/debugger/__init__.py b/web/pgadmin/tools/debugger/__init__.py
index 3976498..bc02ba4 100644
--- a/web/pgadmin/tools/debugger/__init__.py
+++ b/web/pgadmin/tools/debugger/__init__.py
@@ -447,13 +447,8 @@ def close(trans_id):
 
     # Release the connection
     if conn.connected():
-        if obj['debug_type'] == 'indirect':
-            # render the SQL template and send the query to server
-            sql = render_template("/".join([template_path, 'abort_target.sql']),
-                          session_id=obj['session_id'])
-            status, res = conn.execute_dict(sql)
-            if not status:
-                return internal_server_error(errormsg=res)
+        # on successful connection cancel the running transaction
+        status, result = conn.cancel_transaction(obj['conn_id'], obj['database_id'])
 
         # Delete the existing debugger data in session variable
         del session['debuggerData'][str(trans_id)]
@@ -1066,11 +1061,18 @@ def deposit_parameter_value(trans_id):
             status, result = conn.execute_dict(sql)
             if not status:
                 return internal_server_error(errormsg=result)
+
+            # Check if value deposited successfully or not and depending on the result, return the message information.
+            if result['rows'][0]['pldbg_deposit_value']:
+                info = gettext('Value deposited successfully')
+            else:
+                info = gettext('Error while setting the value')
+            return make_json_response(data={'status': status, 'info':info, 'result': result['rows'][0]['pldbg_deposit_value']})
     else:
         status = False
         result = gettext('Not connected to server or connection with the server has been closed.')
 
-    return make_json_response(data={'status': status, 'result': result['rows']})
+    return make_json_response(data={'status': status, 'result': result})
 
 
 @blueprint.route('/select_frame/<int:trans_id>/<int:frame_id>', methods=['GET'])
@@ -1200,6 +1202,18 @@ def set_arguments_sqlite(sid, did, scid, func_id):
                     server_id=data[i]['server_id'], database_id=data[i]['database_id'], schema_id=data[i]['schema_id'],
                     function_id=data[i]['function_id'], arg_id=data[i]['arg_id']).count()
 
+            # handle the Array list sent from the client
+            array_string = ''
+            if data[i]['value'].__class__.__name__ in ('list') and data[i]['value']:
+                for k in range(0, len(data[i]['value'])):
+                    array_string += data[i]['value'][k]['value']
+                    if k != (len(data[i]['value']) - 1):
+                        array_string += ','
+            elif data[i]['value'].__class__.__name__ in ('list') and not data[i]['value']:
+                array_string = ''
+            else:
+                array_string = data[i]['value']
+
             # Check if data is already available in database then update the existing value otherwise add the new value
             if DbgFuncArgsExists:
                 DbgFuncArgs = DebuggerFunctionArguments.query.filter_by(
@@ -1209,7 +1223,7 @@ def set_arguments_sqlite(sid, did, scid, func_id):
                 DbgFuncArgs.is_null = data[i]['is_null']
                 DbgFuncArgs.is_expression = data[i]['is_expression']
                 DbgFuncArgs.use_default = data[i]['use_default']
-                DbgFuncArgs.value = data[i]['value']
+                DbgFuncArgs.value = array_string
             else:
                 debugger_func_args = DebuggerFunctionArguments(
                     server_id = data[i]['server_id'],
@@ -1220,7 +1234,7 @@ def set_arguments_sqlite(sid, did, scid, func_id):
                     is_null = data[i]['is_null'],
                     is_expression = data[i]['is_expression'],
                     use_default = data[i]['use_default'],
-                    value = data[i]['value']
+                    value = array_string
                 )
 
                 db.session.add(debugger_func_args)
diff --git a/web/pgadmin/tools/debugger/static/css/debugger.css b/web/pgadmin/tools/debugger/static/css/debugger.css
index cc0c1a5..40eb195 100644
--- a/web/pgadmin/tools/debugger/static/css/debugger.css
+++ b/web/pgadmin/tools/debugger/static/css/debugger.css
@@ -53,4 +53,33 @@
 
 .debugger-container .CodeMirror-activeline-background {
     background: #50B0F0;
-}
\ No newline at end of file
+}
+
+.CodeMirror-foldmarker {
+  color: blue;
+  text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px;
+  font-family: arial;
+  line-height: .3;
+  cursor: pointer;
+}
+
+.CodeMirror, .CodeMirror-gutters {
+    min-height: 100%;
+}
+
+.CodeMirror-foldgutter {
+  width: .9em;
+}
+
+.CodeMirror-foldgutter-open,
+.CodeMirror-foldgutter-folded {
+  cursor: pointer;
+}
+
+.CodeMirror-foldgutter-open:after {
+  content: "\25BC";
+}
+
+.CodeMirror-foldgutter-folded:after {
+  content: "\25B6";
+}
diff --git a/web/pgadmin/tools/debugger/templates/debugger/js/debugger_ui.js b/web/pgadmin/tools/debugger/templates/debugger/js/debugger_ui.js
index f345dc9..846a539 100644
--- a/web/pgadmin/tools/debugger/templates/debugger/js/debugger_ui.js
+++ b/web/pgadmin/tools/debugger/templates/debugger/js/debugger_ui.js
@@ -287,11 +287,25 @@ define(
               }
 
               // Need to update the func_obj variable from sqlite database if available
-              // TODO: Need to check, how to update the value in Array fields....
               if (func_args_data.length != 0) {
                 for (i = 0; i < func_args_data.length; i++) {
                   var index = func_args_data[i]['arg_id'];
-                  func_obj.push({ "name": argname[index], "type": argtype[index], "is_null": func_args_data[i]['is_null'] ? true: false, "expr": func_args_data[i]['is_expression']? true: false, "value": func_args_data[i]['value'], "use_default": func_args_data[i]['use_default']? true: false, "default_value": def_val_list[index]});
+                  var values = [];
+                  if (argtype[index].indexOf("[]") !=-1) {
+                      var vals = func_args_data[i]['value'].split(",");
+                      if (argtype[index].indexOf("integer") != -1) {
+                        _.each(vals, function(val){
+                            values.push({'value': parseInt(val)});
+                        });
+                      }
+                      _.each(vals, function(val){
+                            values.push({'value': val});
+                        });
+                  } else {
+                    values = func_args_data[i]['value'];
+                  }
+
+                  func_obj.push({ "name": argname[index], "type": argtype[index], "is_null": func_args_data[i]['is_null'] ? true: false, "expr": func_args_data[i]['is_expression']? true: false, "value": values, "use_default": func_args_data[i]['use_default']? true: false, "default_value": def_val_list[index]});
                 }
               }
             }
@@ -358,11 +372,24 @@ define(
               }
 
               // Need to update the func_obj variable from sqlite database if available
-              // TODO: Need to check, how to update the value in Array fields....
               if (func_args_data.length != 0) {
                 for (i = 0; i < func_args_data.length; i++) {
                   var index = func_args_data[i]['arg_id'];
-                  func_obj.push({ "name": myargname[index], "type": argtype[index], "is_null": func_args_data[i]['is_null'] ? true: false, "expr": func_args_data[i]['is_expression']? true: false, "value": func_args_data[i]['value'], "use_default": func_args_data[i]['use_default']? true: false, "default_value": def_val_list[index]});
+                  var values = [];
+                  if (argtype[index].indexOf("[]") !=-1) {
+                      var vals = func_args_data[i]['value'].split(",");
+                      if (argtype[index].indexOf("integer") != -1) {
+                        _.each(vals, function(val){
+                            values.push({'value': parseInt(val)});
+                        });
+                      }
+                      _.each(vals, function(val){
+                            values.push({'value': val});
+                        });
+                  } else {
+                    values = func_args_data[i]['value'];
+                  }
+                  func_obj.push({ "name": myargname[index], "type": argtype[index], "is_null": func_args_data[i]['is_null'] ? true: false, "expr": func_args_data[i]['is_expression']? true: false, "value": values, "use_default": func_args_data[i]['use_default']? true: false, "default_value": def_val_list[index]});
                 }
               }
             }
@@ -423,7 +450,6 @@ define(
 
               this.grid.collection.each(function(m) {
 
-                  // TODO: Removed temporary for testing.....
                   // Check if value is set to NULL then we should ignore the value field
                   if (m.get('is_null')) {
                     args_value_list.push({ 'name': m.get('name'),
diff --git a/web/pgadmin/tools/debugger/templates/debugger/js/direct.js b/web/pgadmin/tools/debugger/templates/debugger/js/direct.js
index 05801ea..4574716 100644
--- a/web/pgadmin/tools/debugger/templates/debugger/js/direct.js
+++ b/web/pgadmin/tools/debugger/templates/debugger/js/direct.js
@@ -1,7 +1,8 @@
 define(
   ['jquery', 'underscore', 'underscore.string', 'alertify', 'pgadmin','pgadmin.browser',
    'backbone', 'backgrid', 'codemirror', 'backform','pgadmin.tools.debugger.ui',
-  'wcdocker', 'pgadmin.backform', 'pgadmin.backgrid', 'codemirror/addon/selection/active-line'],
+  'wcdocker', 'pgadmin.backform', 'pgadmin.backgrid', 'codemirror/addon/selection/active-line',
+  'codemirror/addon/fold/foldgutter', 'codemirror/addon/fold/foldcode', 'codemirror/addon/fold/pgadmin-sqlfoldcode'],
   function($, _, S, Alertify, pgAdmin, pgBrowser, Backbone, Backgrid, CodeMirror, Backform, debug_function_again) {
 
   if (pgAdmin.Browser.tree != null) {
@@ -251,7 +252,7 @@ define(
         During the execution we should poll the result in minimum seconds but once the execution is completed
         and wait for the another debugging session then we should decrease the polling frequency.
       */
-      if (pgTools.DirectDebug.direct_execution_completed) {
+      if (pgTools.DirectDebug.polling_timeout_idle) {
         // poll the result after 1 second
         var  poll_timeout = 1000;
       }
@@ -273,6 +274,7 @@ define(
               }
               else {
                 if (res.data.result[0].src != undefined || res.data.result[0].src != null) {
+                pgTools.DirectDebug.polling_timeout_idle = false;
                 pgTools.DirectDebug.docker.finishLoading(50);
                 pgTools.DirectDebug.editor.setValue(res.data.result[0].src);
                 self.UpdateBreakpoint(trans_id);
@@ -293,8 +295,10 @@ define(
                   self.clear_all_breakpoint(trans_id);
                   self.execute_query(trans_id);
                   pgTools.DirectDebug.first_time_indirect_debug = true;
+                  pgTools.DirectDebug.polling_timeout_idle = false;
                 }
                 else {
+                  pgTools.DirectDebug.polling_timeout_idle = false;
                   pgTools.DirectDebug.docker.finishLoading(50);
                   // If the source is really changed then only update the breakpoint information
                   if (res.data.result[0].src != pgTools.DirectDebug.editor.getValue()) {
@@ -321,6 +325,7 @@ define(
               }
             }
             else if (res.data.status === 'Busy') {
+              pgTools.DirectDebug.polling_timeout_idle = true;
               // If status is Busy then poll the result by recursive call to the poll function
               if (!pgTools.DirectDebug.debug_type) {
                 pgTools.DirectDebug.docker.startLoading('{{ _('Waiting for another session to invoke the target...') }}');
@@ -368,7 +373,7 @@ define(
         During the execution we should poll the result in minimum seconds but once the execution is completed
         and wait for the another debugging session then we should decrease the polling frequency.
       */
-      if (pgTools.DirectDebug.direct_execution_completed) {
+      if (pgTools.DirectDebug.polling_timeout_idle) {
         // poll the result to check that execution is completed or not after 1200 ms
         var  poll_end_timeout = 1200;
       }
@@ -391,6 +396,7 @@ define(
                 */
                 pgTools.DirectDebug.editor.removeLineClass(self.active_line_no, 'wrap', 'CodeMirror-activeline-background');
                 pgTools.DirectDebug.direct_execution_completed = true;
+                pgTools.DirectDebug.polling_timeout_idle = true;
 
                 //Set the alertify message to inform the user that execution is completed.
                 Alertify.notify(
@@ -418,6 +424,7 @@ define(
                   self.AddResults(res.data.result);
                   pgTools.DirectDebug.results_panel.focus();
                   pgTools.DirectDebug.direct_execution_completed = true;
+                  pgTools.DirectDebug.polling_timeout_idle = true;
 
                   //Set the alertify message to inform the user that execution is completed.
                   Alertify.notify(
@@ -537,10 +544,9 @@ define(
       var self = this;
 
       //Check first if previous execution was completed or not
-      if (pgTools.DirectDebug.direct_execution_completed) {
-        // TODO: We need to get the arguments given by the user from sqlite database
+      if (pgTools.DirectDebug.direct_execution_completed &&
+          pgTools.DirectDebug.direct_execution_completed == pgTools.DirectDebug.polling_timeout_idle) {
         self.Restart(trans_id);
-        pgTools.DirectDebug.direct_execution_completed = false;
       }
       else {
         // Make ajax call to listen the database message
@@ -802,7 +808,6 @@ define(
         if (result.length != 0)
         {
           for (i = 0; i < result.length; i++) {
-            // TODO: change the my_func_test_2 with name of the function to be executed.
             my_obj.push({ "name": result[i].targetname, "value": result[i].args, "line_no": result[i].linenumber });
           }
         }
@@ -871,7 +876,6 @@ define(
         if (result.value.length != 0)
         {
           for (i = 0; i < result.value.length; i++) {
-            // TODO: change the my_func_test_2 with name of the function to be executed.
             my_obj.push({ "value": result.value[i]});
           }
         }
@@ -1014,6 +1018,13 @@ define(
             if (res.data.status) {
               // Get the updated variables value
               self.GetLocalVariables(pgTools.DirectDebug.trans_id);
+              // Show the message to the user that deposit value is success or failure
+              Alertify.notify(
+                res.data.info,
+                res.data.result ? 'success': 'error',
+                3,
+                function() { }
+              );
             }
           },
           error: function(e) {
@@ -1187,6 +1198,7 @@ define(
       this.debug_type = debug_type;
       this.first_time_indirect_debug = false;
       this.direct_execution_completed = false;
+      this.polling_timeout_idle = false;
 
       var docker = this.docker = new wcDocker(
           '#container', {
@@ -1268,14 +1280,14 @@ define(
           }
           else if (res.data.status === 'NotConnected') {
             Alertify.alert(
-              'Data grid poll result error',
+              'Not connected to server or connection with the server has been closed.',
               res.data.result
             );
           }
         },
         error: function(e) {
           Alertify.alert(
-            'Debugger listener starting error'
+            'Debugger: Error fetching messages information'
           );
         }
       });
@@ -1283,31 +1295,33 @@ define(
     },
 
     // Callback function when user click on gutters of codemirror to set/clear the breakpoint
-    onBreakPoint: function(cm, m) {
+    onBreakPoint: function(cm, m, gutter) {
       var self = this;
 
-      // TODO::
-      // We may want to check, if break-point is allowed at this moment or not
-      var info = cm.lineInfo(m);
+      // If breakpoint gutter is clicked and execution is not completed then only set the breakpoint
+      if (gutter == "breakpoints" && !pgTools.DirectDebug.polling_timeout_idle ) {
+        // We may want to check, if break-point is allowed at this moment or not
+        var info = cm.lineInfo(m);
 
-      // If gutterMarker is undefined that means there is no marker defined previously
-      // So we need to set the breakpoint command here...
-      if (info.gutterMarkers == undefined) {
-        controller.set_breakpoint(self.trans_id,m+1,1); //set the breakpoint
-      }
-      else {
-        controller.set_breakpoint(self.trans_id,m+1,0); //clear the breakpoint
-      }
+        // If gutterMarker is undefined that means there is no marker defined previously
+        // So we need to set the breakpoint command here...
+        if (info.gutterMarkers == undefined) {
+          controller.set_breakpoint(self.trans_id,m+1,1); //set the breakpoint
+        }
+        else {
+          controller.set_breakpoint(self.trans_id,m+1,0); //clear the breakpoint
+        }
 
-      cm.setGutterMarker(
-        m, "breakpoints", info.gutterMarkers ? null : function() {
-          var marker = document.createElement("div");
+        cm.setGutterMarker(
+          m, "breakpoints", info.gutterMarkers ? null : function() {
+            var marker = document.createElement("div");
 
-          marker.style.color = "#822";
-          marker.innerHTML = "●";
+            marker.style.color = "#822";
+            marker.innerHTML = "●";
 
-          return marker;
+            return marker;
         }());
+      }
     },
 
     // Create the debugger layout with splitter and display the appropriate data received from server.
@@ -1401,8 +1415,14 @@ define(
         var editor = self.editor = CodeMirror.fromTextArea(
           code_editor_area.get(0), {
           lineNumbers: true,
-          lineWrapping: true,
-          gutters: ["note-gutter", "CodeMirror-linenumbers", "breakpoints"],
+          foldOptions: {
+            widget: "\u2026"
+          },
+          foldGutter: {
+            rangeFinder: CodeMirror.fold.combine(CodeMirror.pgadminBeginRangeFinder, CodeMirror.pgadminIfRangeFinder,
+                                                 CodeMirror.pgadminLoopRangeFinder, CodeMirror.pgadminCaseRangeFinder)
+          },
+          gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter", "breakpoints"],
           mode: "text/x-pgsql",
           readOnly: true
         });
diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/execute_edbspl.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/execute_edbspl.sql
index d43f0e2..3c0cd78 100644
--- a/web/pgadmin/tools/debugger/templates/debugger/sql/execute_edbspl.sql
+++ b/web/pgadmin/tools/debugger/templates/debugger/sql/execute_edbspl.sql
@@ -34,7 +34,7 @@
 {% set strParam = "p_param" ~ (loop.index - 1) %}
 {% set str_declare = str_declare ~ "\t" ~ strParam ~ " " ~ arg_type[loop.index - 1] %}
 {% if arg_mode == 'b' %}
-{### TODO: to check for Null parameters received from client ###}
+{### Handle Null parameters received from client ###}
 {% if data[input_value_index]['type'] == 'text' and data[input_value_index]['value'] != 'NULL' %}
 {% set tmp_val = data[input_value_index]['value']|qtLiteral %}
 {% set str_declare = str_declare ~ " := " ~ strParam ~ " " ~ tmp_val ~ "::" ~ data[input_value_index]['type'] %}
@@ -61,7 +61,7 @@
 {% set str_statement = str_statement ~ "VARIADIC " %}
 {% endif %}
 
-{### TODO: to check for Null parameters received from client ###}
+{### Handle Null parameters received from client ###}
 {% if data[input_value_index]['type'] == 'text' and data[input_value_index]['value'] != 'NULL' %}
 {% set tmp_var = data[input_value_index]['value']|qtLiteral %}
 {% set str_statement = str_statement ~ tmp_var ~ "::" ~ data[input_value_index]['type'] %}
@@ -101,4 +101,4 @@
 {### Return final query formed with above condition ###}
 {% if not inside_loop.value %}
 {{ strQuery }}
-{% endif %}
\ No newline at end of file
+{% endif %}
diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/execute_plpgsql.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/execute_plpgsql.sql
index ecd75f1..e096703 100644
--- a/web/pgadmin/tools/debugger/templates/debugger/sql/execute_plpgsql.sql
+++ b/web/pgadmin/tools/debugger/templates/debugger/sql/execute_plpgsql.sql
@@ -11,7 +11,7 @@
 {% if 'type' in dict_item and 'value' in dict_item %}
 {% if dict_item['type'] == 'text' and dict_item['value'] != 'NULL' %}
 {{ dict_item['value']|qtLiteral }}::{{ dict_item['type'] }}{% if not loop.last %}, {% endif %}
-{% elif dict_item['type'] == 'text' and dict_item['value'] == 'NULL' %}
+{% elif dict_item['value'] == 'NULL' %}
 {{ dict_item['value'] }}::{{ dict_item['type'] }}{% if not loop.last %}, {% endif %}
 {% else %}
 {% if '[]' in dict_item['type'] %}
@@ -29,4 +29,4 @@
 {% endif %}
 {% endfor %}
 {% endif %}
-)
\ No newline at end of file
+)


view thread (15+ 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][Debugger]: Initial Patch
  In-Reply-To: <CACCA4P2wpVMKCFSvdiWVt49bAiQYKnVnNemqLgZ=p=Qnk1M=9A@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