# -*- 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: Execute.py,v 1.26 2005/06/10 12:54:30 hmichelon Exp $ # import os import sys import popen2 import string import gtk import pgw import pgw.Lexical class Execute: """SQL query and psql commands handling""" def __init__(self, db): self.db = db self.lexical = pgw.Lexical.Lexical() def execute_one(self, sql): """Execute one query""" if (len(sql) > 0) : # psql commands if (sql[0] == '\\'): sql = string.replace(sql, '\\\\', '\\') if (pgw.mswindows()): cmd = "psql.exe" sql = string.strip(sql) else: cmd = "psql" if (self.db.user is not None): cmd += ' -U "' + self.db.user + '"' if (self.db.host is not None): cmd += ' -h "' + self.db.host + '"' if (self.db.port is not None): cmd += ' -p ' + self.db.port if (self.db.database is not None): cmd += ' -d "' + self.db.database + '"' cmd += ' -c "' + sql + '"' if (self.db.password is not None): os.putenv("PGPASSWORD", self.db.password) #os.putenv("PGCLIENTENCODING", pgw.get_user_encoding()) output, input = popen2.popen4(cmd) result = output.read() output.close() input.close() #os.putenv("PGCLIENTENCODING", "") os.putenv("PGPASSWORD", "") return { 'text' : result } else: # SQL query return self.db.query(sql) def execute(self, buffer): """Execute SQL queries or psql commands""" if not self.db.is_connected() : return # SQL query sqls = self.split(buffer) if (len(sqls) > 1): # multiple queries results = [] for sql in sqls: sql = string.strip(sql) if (len(sql) > 0): results.append(self.execute_one(sql)) if (len(results) == 1): return results[0] return results else: # unique query return self.execute_one(sqls[0]) def split(self, oldbuffer): """Split multiple queries""" # a new textbuffer, because we don't want to modify the original buffer = gtk.TextBuffer() buffer.set_text(oldbuffer.get_text(oldbuffer.get_start_iter(), oldbuffer.get_end_iter())) # filter comments tokens = self.lexical.analyse(buffer, buffer.get_start_iter(), buffer.get_end_iter()) for token in tokens: if (token.token == 'comment'): buffer.delete(token.start_iter, token.end_iter) # restart without the comments buffer.set_text(buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())) start = buffer.get_start_iter() end = buffer.get_end_iter() tokens = self.lexical.analyse(buffer, start, end) # create a list of queries sql = buffer.get_text(start, end) parts = [] stop = start while (len(tokens) > 0): token = tokens.pop(0) if (token.token == 'psql'): i = token.start_iter i.backward_char() parts.append(buffer.get_text(stop, i)) parts.append(token.value) stop = token.end_iter elif (token.value == ';'): i = token.start_iter parts.append(buffer.get_text(stop, i)) stop = token.end_iter if (stop != end): parts.append(buffer.get_text(stop, end)) return parts