# -*- coding: latin-1; -*-
#
# PgWorksheet - PostgreSQL Front End
# http://pgworksheet.projects.postgresql.org/
#
# Copyright © 2004-2008 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.28 2008/03/12 20:26:23 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
