# -*- coding: latin-1; -*- # # PgWorksheet - PostgreSQL Front End # http://pgworksheet.projects.postgresql.org/ # # Copyright © 2004-2005 Henri Michelon & CML http://www.e-cml.org/ # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details (read LICENSE.txt). # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # $Id # import string import pygtk import gtk import pgw class RunSQL: """Execute the SQL buffer and fill the GtkNotebook with the results.""" def __init__(self, execute, txtSQL, tabResult, result): self.execute = execute self.txtSQL = txtSQL self.lblResult = result self.tabResult = tabResult self.error_font = {} def result(self, msg): """update status bar text""" self.lblResult.set_markup('' + msg + '') def str_limit(self, s, max = 20): s = string.replace(s, '\\\\', '\\') if (len(s) > (max + 3)): return s[:max] + "..." return s def error(self, msg, title = None): """update the error messages""" if (title is None): title = '' + _('Errors') + '' scroll = gtk.ScrolledWindow() txt = gtk.TextView() txt.get_buffer().set_text(unicode(msg, pgw.get_user_encoding())) pgw.set_proportional(txt.get_buffer()) txt.set_editable(False) scroll.add(txt) scroll.show_all() label = gtk.Label() label.set_markup(title) self.tabResult.append_page(scroll, label) def add_treeview(self, title): """Add a new tree view""" scroll = gtk.ScrolledWindow() tvw = gtk.TreeView() scroll.add(tvw) scroll.show() label = gtk.Label(title) self.tabResult.append_page(scroll, label) return (tvw, label) def fill_treeview(self, sql, result): """build the tree view columns and rows""" sql = sql.strip() treeview, label = self.add_treeview(self.str_limit(sql)) type_str = "" cell = gtk.CellRendererText() ncol = 0 for col in result.description: column = gtk.TreeViewColumn(string.replace(col[0], "_", "__")) column.pack_start(cell, True) column.add_attribute(cell, 'text', ncol) column.set_sort_column_id(ncol) treeview.append_column(column) ncol = ncol + 1 if (type_str == ""): type_str = "str" else: type_str = type_str + ",str" pass # dynamically create the liststore code = "liststore = gtk.ListStore(" + type_str + ")" exec compile(code, "", 'exec') # fill the tree view row = result.fetchone() rows = 0 while ( row is not None ) : c = 0 while c < len(row): if (row[c] is None): row[c] = '(null)' c = c + 1 liststore.append(row) row = result.fetchone() rows = rows + 1 result.close() treeview.set_model(liststore) treeview.set_reorderable(True) treeview.columns_autosize() treeview.show() label.set_markup(label.get_text() + ' : ' + str(rows) + "") return rows def run(self): """Run the query and update the results""" # clear the treeviews and the error text buffers for child in self.tabResult.get_children(): self.tabResult.remove(child) self.result(_("Please wait, executing the query and fetching the results...")) # update the display while (gtk.events_pending() == True): gtk.main_iteration_do(False) # execute the query sqlbuffer= self.txtSQL.get_buffer() notices = [] try: result = self.execute.execute(sqlbuffer) rows = 0 if (isinstance(result, list)): # multiple queries and multiple results... parts = self.execute.split(sqlbuffer) sqls = [] have_errors = 0 for sql in parts : sql = string.strip(sql) if (len(sql) > 0) : sqls.append(sql) for res in result: sql = sqls.pop(0) try: if (res['cursor'].description is not None): rows += self.fill_treeview(sql, res['cursor']) else: rows += res['cursor'].rowcount notices = res['notices'] except KeyError: try: self.error(res['text'], "psql : " + self.str_limit(sql)) except KeyError: notices = res['notices'] self.error(res['error'], '' + _('Errors :') + ' ' + self.str_limit(sql)) have_errors += 1 self.tabResult.set_current_page(0) if (rows > 1): res_str = _("%d results or affected rows") % rows elif (rows == 1): res_str = _("1 result or affected row") else: res_str = _("No result or no affected row") if (have_errors > 1) : res_str += ', ' + \ _('%d queries failed') % have_errors + '' elif (have_errors > 0) : res_str += ', ' + \ _('1 query failed') + '' self.result(res_str) else: # one query sql = sqlbuffer.get_text(sqlbuffer.get_start_iter(), sqlbuffer.get_end_iter()) try: if (result is None): self.result(_("No result")) elif (result['cursor'].description is None): # not a SELECT rows = result['cursor'].rowcount notices = result['notices'] if (rows > 1): self.result(_("%d rows affected") % rows) elif (rows == 1): self.result(_("1 row affected")) else: self.result(_("No row affected")) else: # only one SELECT rows = self.fill_treeview(sql, result['cursor']) notices = result['notices'] if (rows > 1): self.result(_("%d results") % rows) elif (rows == 1): self.result(_("1 result")) else: self.result(_("No result")) except KeyError: try: self.error(result['text'], "psql : " + self.str_limit(sql)) self.result("") except KeyError: self.error(result['error']) self.result('' + _('query failed') + '') notices = result['notices'] buffer = self.txtSQL.get_buffer() buffer.move_mark_by_name('selection_bound', buffer.get_start_iter()); buffer.move_mark_by_name('insert', buffer.get_end_iter()); except Exception, errstr: self.result('' + _('query failed') + '') self.error(str(errstr)) if (len(notices) > 0): msg = "" while len(notices): msg += notices.pop() self.error(msg, ''+ _("log") + '') # restore the focus self.txtSQL.grab_focus()