mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-20 11:48:31 -06:00
Fixed debugger execution 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. 4. Remove saved debug arguments. Fixes #3191
This commit is contained in:
parent
b7ad95907a
commit
208ee4da8c
@ -17,6 +17,7 @@ Bug fixes
|
||||
*********
|
||||
|
||||
| `Bug #3136 <https://redmine.postgresql.org/issues/3136>`_ - Stabilise feature tests for continuous running on CI systems.
|
||||
| `Bug #3191 <https://redmine.postgresql.org/issues/3191>`_ - Fixed debugger execution issues.
|
||||
| `Bug #3313 <https://redmine.postgresql.org/issues/3313>`_ - Ensure 'select all' and 'unselect all' working properly for pgAgent schedule.
|
||||
| `Bug #3325 <https://redmine.postgresql.org/issues/3325>`_ - Fix sort/filter dialog issue where it incorrectly requires ASC/DESC.
|
||||
| `Bug #3347 <https://redmine.postgresql.org/issues/3347>`_ - Ensure backup should work with '--data-only' and '--schema-only' for any format.
|
||||
|
34
web/migrations/versions/ca00ec32581b_.py
Normal file
34
web/migrations/versions/ca00ec32581b_.py
Normal file
@ -0,0 +1,34 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
"""
|
||||
Deleting old debug logs
|
||||
|
||||
Revision ID: ca00ec32581b
|
||||
Revises: aa86fb60b73d
|
||||
Create Date: 2018-08-29 15:33:57.855491
|
||||
|
||||
"""
|
||||
|
||||
from pgadmin.model import db
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'ca00ec32581b'
|
||||
down_revision = 'aa86fb60b73d'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
db.engine.execute(
|
||||
'DELETE FROM debugger_function_arguments'
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
pass
|
@ -29,7 +29,7 @@ from flask_sqlalchemy import SQLAlchemy
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
SCHEMA_VERSION = 18
|
||||
SCHEMA_VERSION = 19
|
||||
|
||||
##########################################################################
|
||||
#
|
||||
|
@ -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
|
||||
|
@ -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,47 +282,43 @@ 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>';
|
||||
}
|
||||
} else {
|
||||
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];
|
||||
@ -327,12 +326,19 @@ define([
|
||||
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 {
|
||||
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,
|
||||
@ -879,7 +893,12 @@ define([
|
||||
|
||||
for (var i = 0; i < this.collection.length; i++) {
|
||||
|
||||
// TODO: Need to check the "NULL" and "Expression" column value to
|
||||
if (this.collection.models[i].get('is_null')) {
|
||||
obj.__internal.buttons[0].element.disabled = false;
|
||||
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 ||
|
||||
@ -905,7 +924,7 @@ define([
|
||||
}
|
||||
|
||||
Alertify.debuggerInputArgsDialog(
|
||||
gettext('Debugger'), args, restart_debug
|
||||
gettext('Debugger'), debug_info, restart_debug, is_edb_proc
|
||||
).resizeTo('60%', '60%');
|
||||
|
||||
};
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user