Initial version for generationg the CREATE/SELECT/EXEC scripts for the
selected node.pull/3/head
parent
c34e62207a
commit
5ca63fba48
|
@ -173,6 +173,12 @@ class FunctionView(PGChildNodeView, DataTypeReader):
|
|||
|
||||
* types(gid, sid, did, scid, fnid=None):
|
||||
- Returns Data Types.
|
||||
|
||||
* select_sql(gid, sid, did, scid, fnid):
|
||||
- Returns sql for Script
|
||||
|
||||
* exec_sql(gid, sid, did, scid, fnid):
|
||||
- Returns sql for Script
|
||||
"""
|
||||
|
||||
node_type = blueprint.node_type
|
||||
|
@ -203,7 +209,9 @@ class FunctionView(PGChildNodeView, DataTypeReader):
|
|||
'module.js': [{}, {}, {'get': 'module_js'}],
|
||||
'get_types': [{'get': 'types'}, {'get': 'types'}],
|
||||
'get_languages': [{'get': 'get_languages'}, {'get': 'get_languages'}],
|
||||
'vopts': [{}, {'get': 'variable_options'}]
|
||||
'vopts': [{}, {'get': 'variable_options'}],
|
||||
'select_sql': [{'get': 'select_sql'}],
|
||||
'exec_sql': [{'get': 'exec_sql'}]
|
||||
})
|
||||
|
||||
@property
|
||||
|
@ -1198,6 +1206,74 @@ It may have been removed by another user or moved to another schema.
|
|||
status=200
|
||||
)
|
||||
|
||||
@check_precondition
|
||||
def select_sql(self, gid, sid, did, scid, fnid):
|
||||
"""
|
||||
This function returns sql for select script call.
|
||||
|
||||
Args:
|
||||
gid: Server Group Id
|
||||
sid: Server Id
|
||||
did: Database Id
|
||||
scid: Schema Id
|
||||
doid: Function Id
|
||||
"""
|
||||
# Fetch the function definition.
|
||||
SQL = render_template("/".join([self.sql_template_path,
|
||||
'get_definition.sql']), fnid=fnid, scid=scid)
|
||||
status, res = self.conn.execute_2darray(SQL)
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
func_def, name = res['rows'][0]
|
||||
|
||||
# Fetch only arguments
|
||||
args = name[name.rfind('('):].strip('(').strip(')').split(',')
|
||||
# Remove unwanted spaces from arguments
|
||||
args = [arg.strip(' ') for arg in args]
|
||||
|
||||
# Remove duplicate and then format arguments
|
||||
for arg in list(set(args)):
|
||||
formatted_arg = '\n\t<' + arg + '>'
|
||||
name = name.replace(arg, formatted_arg)
|
||||
|
||||
name = name.replace(')', '\n)')
|
||||
sql = "SELECT {0}".format(name)
|
||||
|
||||
return ajax_response(response=sql)
|
||||
|
||||
@check_precondition
|
||||
def exec_sql(self, gid, sid, did, scid, fnid):
|
||||
"""
|
||||
This function returns sql for exec script call.
|
||||
|
||||
Args:
|
||||
gid: Server Group Id
|
||||
sid: Server Id
|
||||
did: Database Id
|
||||
scid: Schema Id
|
||||
doid: Function Id
|
||||
"""
|
||||
resp_data = self._fetch_properties(gid, sid, did, scid, fnid)
|
||||
|
||||
name = resp_data['pronamespace'] + "." + resp_data['name_with_args']
|
||||
|
||||
# Fetch only arguments
|
||||
args = name[name.rfind('('):].strip('(').strip(')').split(',')
|
||||
# Remove unwanted spaces from arguments
|
||||
args = [arg.strip(' ') for arg in args]
|
||||
|
||||
# Remove duplicate and then format arguments
|
||||
for arg in list(set(args)):
|
||||
formatted_arg = '\n\t<' + arg + '>'
|
||||
name = name.replace(arg, formatted_arg)
|
||||
|
||||
name = name.replace(')', '\n)')
|
||||
sql = "EXEC {0}".format(name)
|
||||
|
||||
return ajax_response(response=sql)
|
||||
|
||||
|
||||
FunctionView.register_node_view(blueprint)
|
||||
|
||||
|
||||
|
|
|
@ -108,6 +108,7 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
|
|||
collection_type: 'coll-function',
|
||||
hasSQL: true,
|
||||
hasDepends: true,
|
||||
hasScriptTypes: ['create', 'select'],
|
||||
parent_type: ['schema', 'catalog'],
|
||||
Init: function(args) {
|
||||
/* Avoid mulitple registration of menus */
|
||||
|
|
|
@ -28,6 +28,7 @@ function($, _, S, pgAdmin, pgBrowser, alertify, Function) {
|
|||
collection_type: 'coll-procedure',
|
||||
hasSQL: true,
|
||||
hasDepends: true,
|
||||
hasScriptTypes: ['create', 'exec'],
|
||||
parent_type: ['schema'],
|
||||
Init: function() {
|
||||
/* Avoid mulitple registration of menus */
|
||||
|
|
|
@ -105,6 +105,60 @@ function($, _, S, pgAdmin, Menu, Backbone, Alertify, pgBrowser, Backform) {
|
|||
}]);
|
||||
}
|
||||
}
|
||||
// This will add options of scripts eg:'CREATE Script'
|
||||
if (self.hasScriptTypes && _.isArray(self.hasScriptTypes)
|
||||
&& self.hasScriptTypes.length > 0) {
|
||||
// For each script type create menu
|
||||
_.each(self.hasScriptTypes, function(stype) {
|
||||
|
||||
var type_label = S(
|
||||
"{{ _("%%s Script") }}"
|
||||
).sprintf(stype.toUpperCase()).value(),
|
||||
stype = stype.toLowerCase();
|
||||
|
||||
// Adding menu for each script type
|
||||
pgAdmin.Browser.add_menus([{
|
||||
name: 'show_script_' + stype, node: self.type, module: self,
|
||||
applies: ['object', 'context'], callback: 'show_script',
|
||||
priority: 3, label: type_label, category: 'Scripts',
|
||||
data: {'script': stype}, icon: 'fa fa-pencil',
|
||||
enable: this.check_user_permission
|
||||
}]);
|
||||
});
|
||||
// If node has hasSQL then provide CREATE Script by default
|
||||
} else if(self.hasSQL) {
|
||||
pgAdmin.Browser.add_menus([{
|
||||
name: 'show_script_create', node: self.type, module: self,
|
||||
applies: ['object', 'context'], callback: 'show_script',
|
||||
priority: 3, label: 'CREATE Script', category: 'Scripts',
|
||||
data: {'script': 'create'}, icon: 'fa fa-pencil',
|
||||
enable: this.check_user_permission
|
||||
}]);
|
||||
}
|
||||
},
|
||||
///////
|
||||
// Checks if Script Type is allowed to user
|
||||
// First check if role node & create role allowed
|
||||
// Otherwise test rest of database objects
|
||||
// if no permission matched then do not allow create script
|
||||
///////
|
||||
check_user_permission: function(itemData, item, data) {
|
||||
var node = pgBrowser.Nodes[itemData._type],
|
||||
parentData = node.getTreeNodeHierarchy(item);
|
||||
if ( _.indexOf(['create','insert','update', 'delete'], data.script) != -1) {
|
||||
if (itemData.type == 'role' &&
|
||||
parentData.server.user.can_create_role) {
|
||||
return true;
|
||||
} else if (parentData.server.user.is_superuser ||
|
||||
parentData.server.user.can_create_db ||
|
||||
(parentData.schema && parentData.schema.can_create)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
///////
|
||||
// Generate a Backform view using the node's model type
|
||||
|
@ -499,6 +553,43 @@ function($, _, S, pgAdmin, Menu, Backbone, Alertify, pgBrowser, Backform) {
|
|||
},
|
||||
null).show()
|
||||
},
|
||||
// Callback for creating script(s) & opening them in Query editor
|
||||
show_script: function(args, item) {
|
||||
var scriptType = args.script,
|
||||
obj = this,
|
||||
t = pgBrowser.tree,
|
||||
i = item || t.selected(),
|
||||
d = i && i.length == 1 ? t.itemData(i) : undefined;
|
||||
|
||||
if (!d)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Make sure - we're using the correct version of node
|
||||
*/
|
||||
obj = pgBrowser.Nodes[d._type];
|
||||
var objName = d.label;
|
||||
|
||||
// URL for script type
|
||||
if(scriptType == 'insert') {
|
||||
sql_url = 'insert_sql';
|
||||
} else if(scriptType == 'update') {
|
||||
sql_url = 'update_sql';
|
||||
} else if(scriptType == 'delete') {
|
||||
sql_url = 'delete_sql';
|
||||
} else if(scriptType == 'select') {
|
||||
sql_url = 'select_sql';
|
||||
} else if(scriptType == 'exec') {
|
||||
sql_url = 'exec_sql';
|
||||
} else {
|
||||
// By Default get CREATE SQL
|
||||
sql_url = 'sql';
|
||||
}
|
||||
// Open data grid & pass the URL for fetching
|
||||
pgAdmin.DataGrid.show_query_tool.apply(
|
||||
this, [obj.generate_url(i, sql_url, d, true), i]
|
||||
);
|
||||
},
|
||||
// Callback called - when a node is selected in browser tree.
|
||||
selected: function(item, data, browser) {
|
||||
// Show the information about the selected node in the below panels,
|
||||
|
|
|
@ -18,8 +18,9 @@ from flask.ext.babel import gettext
|
|||
from flask.ext.security import login_required
|
||||
from pgadmin.tools.sqleditor.command import *
|
||||
from pgadmin.utils import PgAdminModule
|
||||
from pgadmin.utils.ajax import make_json_response, bad_request, internal_server_error
|
||||
|
||||
from pgadmin.utils.ajax import make_json_response, bad_request,\
|
||||
internal_server_error
|
||||
from config import PG_DEFAULT_DRIVER
|
||||
|
||||
class DataGridModule(PgAdminModule):
|
||||
"""
|
||||
|
@ -143,17 +144,26 @@ def panel(trans_id, is_query_tool, editor_title):
|
|||
is_query_tool: True if panel calls when query tool menu is clicked.
|
||||
editor_title: Title of the editor
|
||||
"""
|
||||
# Let's fetch Script type URL from request
|
||||
if request.args and request.args['query_url'] != '':
|
||||
sURL = request.args['query_url']
|
||||
else:
|
||||
sURL = None
|
||||
|
||||
return render_template("datagrid/index.html", _=gettext, uniqueId=trans_id,
|
||||
is_query_tool=is_query_tool, editor_title=editor_title)
|
||||
|
||||
is_query_tool=is_query_tool, editor_title=editor_title,
|
||||
script_type_url=sURL)
|
||||
|
||||
@blueprint.route(
|
||||
'/initialize/query_tool/<int:sid>/<int:did>',
|
||||
methods=["PUT", "POST"]
|
||||
methods=["POST"]
|
||||
)
|
||||
@blueprint.route(
|
||||
'/initialize/query_tool/<int:sid>',
|
||||
methods=["POST"]
|
||||
)
|
||||
@login_required
|
||||
def initialize_query_tool(sid, did):
|
||||
def initialize_query_tool(sid, did=None):
|
||||
"""
|
||||
This method is responsible for instantiating and initializing
|
||||
the query tool object. It will also create a unique
|
||||
|
@ -164,6 +174,21 @@ def initialize_query_tool(sid, did):
|
|||
did: Database Id
|
||||
"""
|
||||
|
||||
if did is None:
|
||||
# Use Maintenance database OID
|
||||
from pgadmin.utils.driver import get_driver
|
||||
driver = get_driver(PG_DEFAULT_DRIVER)
|
||||
manager = driver.connection_manager(sid)
|
||||
conn = manager.connection()
|
||||
if conn.connected():
|
||||
did = manager.did
|
||||
else:
|
||||
internal_server_error(
|
||||
errormsg=gettext(
|
||||
'Server disconnected, Please connect and try again'
|
||||
)
|
||||
)
|
||||
|
||||
try:
|
||||
command_obj = ObjectRegistry.get_object('query_tool', sid=sid, did=did)
|
||||
except Exception as e:
|
||||
|
|
|
@ -156,8 +156,36 @@ try {
|
|||
}
|
||||
});
|
||||
|
||||
// Fetch the SQL for Scripts (eg: CREATE/UPDATE/DELETE/SELECT)
|
||||
var script_sql = '';
|
||||
{% if script_type_url%}
|
||||
// Call AJAX only if script type url is present
|
||||
$.ajax({
|
||||
url: '{{ script_type_url }}',
|
||||
type:'GET',
|
||||
async: false,
|
||||
success: function(res) {
|
||||
script_sql = res;
|
||||
},
|
||||
error: function(jqx) {
|
||||
var msg = jqx.responseText;
|
||||
/* Error from the server */
|
||||
if (jqx.status == 410 || jqx.status == 500) {
|
||||
try {
|
||||
var data = $.parseJSON(jqx.responseText);
|
||||
msg = data.errormsg;
|
||||
} catch (e) {}
|
||||
}
|
||||
pgBrowser.report_error(
|
||||
S('{{ _('Error fetching sql for script: "%%s"') }}')
|
||||
.sprintf(msg)
|
||||
.value(), msg);
|
||||
}
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
// Start the query tool.
|
||||
sqlEditorController.start({{ is_query_tool }}, "{{ editor_title }}");
|
||||
sqlEditorController.start({{ is_query_tool }}, "{{ editor_title }}", script_sql);
|
||||
});
|
||||
} catch (err) {
|
||||
/* Show proper error dialog */
|
||||
|
|
|
@ -346,9 +346,10 @@ define(
|
|||
},
|
||||
|
||||
// This is a callback function to show query tool when user click on menu item.
|
||||
show_query_tool: function(data, i) {
|
||||
show_query_tool: function(url, i) {
|
||||
var self = this,
|
||||
d = pgAdmin.Browser.tree.itemData(i);
|
||||
sURL = url || '',
|
||||
d = pgAdmin.Browser.tree.itemData(i);
|
||||
if (d === undefined) {
|
||||
alertify.alert(
|
||||
'Query tool Error',
|
||||
|
@ -362,17 +363,32 @@ define(
|
|||
parentData = node.getTreeNodeHierarchy(i);
|
||||
|
||||
// If server, database is undefined then return from the function.
|
||||
if (parentData.server === undefined || parentData.database === undefined) {
|
||||
if (parentData.server === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
var baseUrl = "{{ url_for('datagrid.index') }}" + "initialize/query_tool/" + parentData.server._id +
|
||||
"/" + parentData.database._id;
|
||||
var grid_title = parentData.database.label + ' on ' + parentData.server.user.name + '@' +
|
||||
var baseUrl = "{{ url_for('datagrid.index') }}" + "initialize/query_tool/" + parentData.server._id;
|
||||
|
||||
// If database not present then use Maintenance database
|
||||
// We will handle this at server side
|
||||
if (parentData.database) {
|
||||
baseUrl += "/" + parentData.database._id;
|
||||
}
|
||||
// If Database is not available then use default db
|
||||
var db_label = parentData.database ? parentData.database.label
|
||||
: parentData.server.db;
|
||||
|
||||
var grid_title = db_label + ' on ' + parentData.server.user.name + '@' +
|
||||
parentData.server.label ;
|
||||
|
||||
var panel_title = ' Query-' + self.title_index;
|
||||
self.title_index += 1;
|
||||
var panel_title = ' Query-';
|
||||
|
||||
if (!_.isUndefined(self.title_index) && !isNaN(self.title_index)) {
|
||||
panel_title += self.title_index;
|
||||
self.title_index += 1;
|
||||
} else {
|
||||
panel_title += "{{ _(' untitled') }}";
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: baseUrl,
|
||||
|
@ -399,7 +415,8 @@ define(
|
|||
});
|
||||
|
||||
// Open the panel if frame is initialized
|
||||
baseUrl = "{{ url_for('datagrid.index') }}" + "panel/" + res.data.gridTransId + "/true/" + grid_title;
|
||||
baseUrl = "{{ url_for('datagrid.index') }}" + "panel/" + res.data.gridTransId + "/true/"
|
||||
+ grid_title + '?' + "query_url=" + encodeURI(sURL);
|
||||
var openQueryToolURL = function(j) {
|
||||
setTimeout(function() {
|
||||
var frameInitialized = j.data('frameInitialized');
|
||||
|
@ -417,7 +434,7 @@ define(
|
|||
},
|
||||
error: function(e) {
|
||||
alertify.alert(
|
||||
'Query Tool Initialize Error',
|
||||
"{{ _('Query Tool Initialize Error') }}",
|
||||
e.responseJSON.errormsg
|
||||
);
|
||||
}
|
||||
|
|
|
@ -678,7 +678,7 @@ define(
|
|||
* call the render method of the grid view to render the backgrid
|
||||
* header and loading icon and start execution of the sql query.
|
||||
*/
|
||||
start: function(is_query_tool, editor_title) {
|
||||
start: function(is_query_tool, editor_title, script_sql) {
|
||||
var self = this;
|
||||
|
||||
self.is_query_tool = is_query_tool;
|
||||
|
@ -731,6 +731,9 @@ define(
|
|||
|
||||
if (self.is_query_tool) {
|
||||
self.gridView.query_tool_obj.refresh();
|
||||
if(script_sql && script_sql !== '') {
|
||||
self.gridView.query_tool_obj.setValue(script_sql);
|
||||
}
|
||||
}
|
||||
else {
|
||||
self.gridView.query_tool_obj.setOption("readOnly",true);
|
||||
|
|
Loading…
Reference in New Issue