# -*- 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()