Hi,

Please find attached patch to fix below debugger issues.

1. Allow debugging of EPAS package procedures/functions with INOUT params.
2. Add Support for indirect debugging for EPAS package procedures/functions.
3. Allow debugging with NULL param values.


Thanks,

-- 
*Harshal Dhumal*
*Sr. Software Engineer*

EnterpriseDB India: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
diff --git a/web/pgadmin/tools/debugger/static/js/debugger.js b/web/pgadmin/tools/debugger/static/js/debugger.js
index 39caca7..848737c 100644
--- a/web/pgadmin/tools/debugger/static/js/debugger.js
+++ b/web/pgadmin/tools/debugger/static/js/debugger.js
@@ -354,6 +354,24 @@ define([
             'func_id': debuggerUtils.getProcedureId(treeInfo),
           }
         );
+      } else if (d._type == 'edbfunc') {
+        // Get the existing function parameters available from sqlite database
+        baseUrl = url_for('debugger.initialize_target_for_function', {
+          'debug_type': 'indirect',
+          'sid': treeInfo.server._id,
+          'did': treeInfo.database._id,
+          'scid': treeInfo.schema._id,
+          'func_id': treeInfo.edbfunc._id,
+        });
+      } else if (d._type == 'edbproc') {
+        // Get the existing function parameters available from sqlite database
+        baseUrl = url_for('debugger.initialize_target_for_function', {
+          'debug_type': 'indirect',
+          'sid': treeInfo.server._id,
+          'did': treeInfo.database._id,
+          'scid': treeInfo.schema._id,
+          'func_id': treeInfo.edbproc._id,
+        });
       } else if (d._type == 'trigger_function') {
         baseUrl = url_for(
           'debugger.initialize_target_for_function', {
@@ -449,7 +467,8 @@ define([
         i = item || t.selected(),
         d = i && i.length == 1 ? t.itemData(i) : undefined,
         node = d && pgBrowser.Nodes[d._type],
-        self = this;
+        self = this,
+        is_edb_proc = d._type == 'edbproc';
 
       if (!d)
         return;
@@ -465,7 +484,7 @@ define([
 
         // Open Alertify the dialog to take the input arguments from user if function having input arguments
         if (res.data[0]['require_input']) {
-          get_function_arguments(res.data[0], 0);
+          get_function_arguments(res.data[0], 0, is_edb_proc);
         } else {
           // Initialize the target and create asynchronous connection and unique transaction ID
           // If there is no arguments to the functions then we should not ask for for function arguments and
diff --git a/web/pgadmin/tools/debugger/static/js/debugger_ui.js b/web/pgadmin/tools/debugger/static/js/debugger_ui.js
index 6f6fad5..38f6869 100644
--- a/web/pgadmin/tools/debugger/static/js/debugger_ui.js
+++ b/web/pgadmin/tools/debugger/static/js/debugger_ui.js
@@ -120,14 +120,17 @@ define([
     }
   };
 
-  var res = function(args, restart_debug) {
+  var res = function(debug_info, restart_debug, is_edb_proc) {
     if (!Alertify.debuggerInputArgsDialog) {
       Alertify.dialog('debuggerInputArgsDialog', function factory() {
         return {
-          main: function(title, data, restart_debug) {
+          main: function(title, debug_info, restart_debug, is_edb_proc) {
             this.set('title', title);
-            this.data = data;
-            this.restart_debug = restart_debug;
+
+            // setting value in alertify settings allows us to access it from
+            // other functions other than main function.
+            this.set('debug_info', debug_info);
+            this.set('restart_debug', restart_debug);
 
             // Variables to store the data sent from sqlite database
             var func_args_data = this.func_args_data = [];
@@ -182,10 +185,10 @@ define([
             } else {
               // Get the existing function parameters available from sqlite database
               _Url = url_for('debugger.get_arguments', {
-                'sid': this.data.server_id,
-                'did': this.data.database_id,
-                'scid': this.data.schema_id,
-                'func_id': this.data.function_id,
+                'sid': debug_info.server_id,
+                'did': debug_info.database_id,
+                'scid': debug_info.schema_id,
+                'func_id': debug_info.function_id,
               });
             }
             $.ajax({
@@ -279,60 +282,63 @@ define([
             // Below will calculate the input argument id required to store in sqlite database
             var input_arg_id = this.input_arg_id = [],
               k;
-            if (this.data['proargmodes'] != null) {
-              var argmode_1 = this.data['proargmodes'].split(',');
+            if (debug_info['proargmodes'] != null) {
+              var argmode_1 = debug_info['proargmodes'].split(',');
               for (k = 0; k < argmode_1.length; k++) {
-                if (argmode_1[k] == 'i' || argmode_1[k] == 'b') {
+                if (argmode_1[k] == 'i' || argmode_1[k] == 'b' ||
+                  (is_edb_proc && argmode_1[k] == 'o')) {
                   input_arg_id.push(k);
                 }
               }
             } else {
-              var argtype_1 = this.data['proargtypenames'].split(',');
+              var argtype_1 = debug_info['proargtypenames'].split(',');
               for (k = 0; k < argtype_1.length; k++) {
                 input_arg_id.push(k);
               }
             }
 
-            argtype = this.data['proargtypenames'].split(',');
+            argtype = debug_info['proargtypenames'].split(',');
 
-            if (this.data['proargmodes'] != null) {
-              argmode = this.data['proargmodes'].split(',');
+            if (debug_info['proargmodes'] != null) {
+              argmode = debug_info['proargmodes'].split(',');
             }
 
-            if (this.data['pronargdefaults']) {
-              default_args_count = this.data['pronargdefaults'];
-              default_args = this.data['proargdefaults'].split(',');
+            if (debug_info['pronargdefaults']) {
+              default_args_count = debug_info['pronargdefaults'];
+              default_args = debug_info['proargdefaults'].split(',');
               arg_cnt = default_args_count;
             }
 
             var vals, values, index, use_def_value, j;
 
-            if (this.data['proargnames'] != null) {
-              argname = this.data['proargnames'].split(',');
+            if (debug_info['proargnames'] != null) {
+              argname = debug_info['proargnames'].split(',');
 
               // It will assign default values to "Default value" column
               for (j = (argname.length - 1); j >= 0; j--) {
-                if (this.data['proargmodes'] != null) {
-                  if (arg_cnt && (argmode[j] == 'i' || argmode[j] == 'b')) {
-                    arg_cnt = arg_cnt - 1;
-                    def_val_list[j] = default_args[arg_cnt];
-                  } else {
-                    def_val_list[j] = '<No default value>';
+                if (debug_info['proargmodes'] != null) {
+                  if (argmode[j] == 'i' || argmode[j] == 'b' ||
+                    (is_edb_proc && argmode[j] == 'o')) {
+                    if (arg_cnt) {
+                      arg_cnt = arg_cnt - 1;
+                      def_val_list[j] = default_args[arg_cnt];
+                    } else {
+                      def_val_list[j] = '<No default value>';
+                    }
                   }
+                } else if (arg_cnt) {
+                  arg_cnt = arg_cnt - 1;
+                  def_val_list[j] = default_args[arg_cnt];
                 } else {
-                  if (arg_cnt) {
-                    arg_cnt = arg_cnt - 1;
-                    def_val_list[j] = default_args[arg_cnt];
-                  } else {
-                    def_val_list[j] = '<No default value>';
-                  }
+                  def_val_list[j] = '<No default value>';
                 }
               }
 
               if (argtype.length != 0) {
                 for (i = 0; i < argtype.length; i++) {
-                  if (this.data['proargmodes'] != null) {
-                    if (argmode[i] == 'i' || argmode[i] == 'b') {
+                  if (debug_info['proargmodes'] != null) {
+                    if (argmode[i] == 'i' || argmode[i] == 'b' ||
+                      (is_edb_proc && argmode[i] == 'o')) {
                       use_def_value = false;
                       if (def_val_list[i] != '<No default value>') {
                         use_def_value = true;
@@ -356,14 +362,17 @@ define([
                       'default_value': def_val_list[i],
                     });
                   }
-
-
                 }
               }
 
               // Need to update the func_obj variable from sqlite database if available
               if (func_args_data.length != 0) {
                 for (i = 0; i < func_args_data.length; i++) {
+                  if (debug_info['proargmodes'] != null &&
+                    (argmode[i] == 'o' && !is_edb_proc)) {
+                    continue;
+                  }
+
                   index = func_args_data[i]['arg_id'];
                   values = [];
                   if (argtype[index].indexOf('[]') != -1) {
@@ -407,7 +416,7 @@ define([
               }
 
               // If there is no default arguments
-              if (!this.data['pronargdefaults']) {
+              if (!debug_info['pronargdefaults']) {
                 for (i = 0; i < argtype.length; i++) {
                   my_obj.push({
                     'name': myargname[i],
@@ -421,7 +430,7 @@ define([
                 // If there is default arguments
                 //Below logic will assign default values to "Default value" column
                 for (j = (myargname.length - 1); j >= 0; j--) {
-                  if (this.data['proargmodes'] == null) {
+                  if (debug_info['proargmodes'] == null) {
                     if (arg_cnt) {
                       arg_cnt = arg_cnt - 1;
                       def_val_list[j] = default_args[arg_cnt];
@@ -429,7 +438,7 @@ define([
                       def_val_list[j] = '<No default value>';
                     }
                   } else {
-                    if (arg_cnt && (argmode[j] == 'i' || argmode[j] == 'b')) {
+                    if (arg_cnt) {
                       arg_cnt = arg_cnt - 1;
                       def_val_list[j] = default_args[arg_cnt];
                     } else {
@@ -439,7 +448,7 @@ define([
                 }
 
                 for (i = 0; i < argtype.length; i++) {
-                  if (this.data['proargmodes'] == null) {
+                  if (debug_info['proargmodes'] == null) {
                     use_def_value = false;
                     if (def_val_list[i] != '<No default value>') {
                       use_def_value = true;
@@ -451,7 +460,8 @@ define([
                       'default_value': def_val_list[i],
                     });
                   } else {
-                    if (argmode[i] == 'i' || argmode[i] == 'b') {
+                    if (argmode[i] == 'i' || argmode[i] == 'b' ||
+                      (is_edb_proc && argmode[i] == 'o')) {
                       use_def_value = false;
                       if (def_val_list[i] != '<No default value>') {
                         use_def_value = true;
@@ -536,6 +546,10 @@ define([
             }
 
           },
+          settings: {
+            debug_info: undefined,
+            restart_debug: undefined,
+          },
           setup: function() {
             return {
               buttons: [{
@@ -573,7 +587,7 @@ define([
 
               // If the debugging is started again then treeInfo is already
               // stored in this.data so we can use the same.
-              if (self.restart_debug == 0) {
+              if (self.setting('restart_debug') == 0) {
                 var t = pgBrowser.tree,
                   i = t.selected(),
                   d = i && i.length == 1 ? t.itemData(i) : undefined,
@@ -615,7 +629,7 @@ define([
                   }
                 }
 
-                if (self.restart_debug == 0) {
+                if (self.setting('restart_debug') == 0) {
                   var f_id;
                   if (d._type == 'function') {
                     f_id = treeInfo.function._id;
@@ -642,10 +656,10 @@ define([
                 } else {
                   // Below will format the data to be stored in sqlite database
                   sqlite_func_args_list.push({
-                    'server_id': self.data.server_id,
-                    'database_id': self.data.database_id,
-                    'schema_id': self.data.schema_id,
-                    'function_id': self.data.function_id,
+                    'server_id': self.setting('debug_info').server_id,
+                    'database_id': self.setting('debug_info').database_id,
+                    'schema_id': self.setting('debug_info').schema_id,
+                    'function_id': self.setting('debug_info').function_id,
                     'arg_id': self.input_arg_id[int_count],
                     'is_null': m.get('is_null') ? 1 : 0,
                     'is_expression': m.get('expr') ? 1 : 0,
@@ -660,7 +674,7 @@ define([
               var baseUrl;
 
               // If debugging is not started again then we should initialize the target otherwise not
-              if (self.restart_debug == 0) {
+              if (self.setting('restart_debug') == 0) {
                 if (d._type == 'function') {
                   baseUrl = url_for('debugger.initialize_target_for_function', {
                     'debug_type': 'direct',
@@ -797,7 +811,7 @@ define([
                 // If the debugging is started again then we should only set the
                 // arguments and start the listener again
                 baseUrl = url_for('debugger.start_listener', {
-                  'trans_id': self.data.trans_id,
+                  'trans_id': self.setting('debug_info').trans_id,
                 });
 
                 $.ajax({
@@ -817,10 +831,10 @@ define([
 
                 // Set the new input arguments given by the user during debugging
                 var _Url = url_for('debugger.set_arguments', {
-                  'sid': self.data.server_id,
-                  'did': self.data.database_id,
-                  'scid': self.data.schema_id,
-                  'func_id': self.data.function_id,
+                  'sid': self.setting('debug_info').server_id,
+                  'did': self.setting('debug_info').database_id,
+                  'scid': self.setting('debug_info').schema_id,
+                  'func_id': self.setting('debug_info').function_id,
                 });
                 $.ajax({
                   url: _Url,
@@ -871,33 +885,38 @@ define([
              debug button.
             */
             this.grid.listenTo(this.debuggerInputArgsColl, 'backgrid:edited',
-              (function(obj) {
-
-                return function() {
+                (function(obj) {
 
-                  var enable_btn = false;
+                  return function() {
 
-                  for (var i = 0; i < this.collection.length; i++) {
+                    var enable_btn = false;
 
-                    // TODO: Need to check the "NULL" and "Expression" column value to
-                    // enable/disable the "Debug" button
-                    if (this.collection.models[i].get('value') == '' ||
-                      this.collection.models[i].get('value') == null ||
-                      this.collection.models[i].get('value') == undefined) {
-                      enable_btn = true;
+                    for (var i = 0; i < this.collection.length; i++) {
 
-                      if (this.collection.models[i].get('use_default')) {
+                      if (this.collection.models[i].get('is_null')) {
                         obj.__internal.buttons[0].element.disabled = false;
-                      } else {
-                        obj.__internal.buttons[0].element.disabled = true;
-                        break;
+                        enable_btn = true;
+                        continue;
+                      }
+                      // TODO: Need to check the "Expression" column value to
+                      // enable/disable the "Debug" button
+                      if (this.collection.models[i].get('value') == '' ||
+                        this.collection.models[i].get('value') == null ||
+                        this.collection.models[i].get('value') == undefined) {
+                        enable_btn = true;
+
+                        if (this.collection.models[i].get('use_default')) {
+                          obj.__internal.buttons[0].element.disabled = false;
+                        } else {
+                          obj.__internal.buttons[0].element.disabled = true;
+                          break;
+                        }
                       }
                     }
-                  }
-                  if (!enable_btn)
-                    obj.__internal.buttons[0].element.disabled = false;
-                };
-              })(this)
+                    if (!enable_btn)
+                      obj.__internal.buttons[0].element.disabled = false;
+                  };
+                })(this)
             );
           },
         };
@@ -905,7 +924,7 @@ define([
     }
 
     Alertify.debuggerInputArgsDialog(
-      gettext('Debugger'), args, restart_debug
+      gettext('Debugger'), debug_info, restart_debug, is_edb_proc
     ).resizeTo('60%', '60%');
 
   };
diff --git a/web/pgadmin/tools/debugger/templates/debugger/sql/get_function_debug_info.sql b/web/pgadmin/tools/debugger/templates/debugger/sql/get_function_debug_info.sql
index 64195b5..7262679 100644
--- a/web/pgadmin/tools/debugger/templates/debugger/sql/get_function_debug_info.sql
+++ b/web/pgadmin/tools/debugger/templates/debugger/sql/get_function_debug_info.sql
@@ -26,12 +26,7 @@ SELECT
                     pg_catalog.generate_series(0, pg_catalog.array_upper(proargtypes, 1)) s(i)), ',')
         END AS proargtypes,
     pg_catalog.array_to_string(p.proargnames, ',') AS proargnames,
-    {% if is_ppas_database %}
-    pg_catalog.array_to_string(proargdeclaredmodes, ',') AS proargmodes,
-    {% else %}
     pg_catalog.array_to_string(proargmodes, ',') AS proargmodes,
-    {% endif %}
-
     {% if is_ppas_database %}
         CASE WHEN n.nspparent <> 0 THEN n.oid ELSE 0 END AS pkg,
         CASE WHEN n.nspparent <> 0 THEN n.nspname ELSE '' END AS pkgname,

Reply via email to