# -*- 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: DBConnection.py,v 1.24 2008/03/13 10:46:24 hmichelon Exp $
#
import string
import sys
try:
    import pgsql
    havepgsql = True
except:
    try:
        from mx import DateTime
        from pyPgSQL import libpq
        import MyPgSQL
    	havepgsql = False
    except:
       msg = _("please install the python-pgsql or pyPgSQL (with mxDateTime) packages")
       print(msg)
       import gtk
       dialog = gtk.MessageDialog(None,
                                  gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                                  gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, msg)
       result = dialog.run()
       dialog.destroy()
       sys.exit(0)


class DBConnection:
  """Database connection/deconnection and query execution"""

  def __init__(self, host = None, port = None, db = None, user = None, password = None):
    """Try to connect to a database"""
    if (havepgsql) :
        self.connect_pgsql(host, port, db, user, password)
    else :
        self.connect_pypgsql(host, port, db, user, password)

  def connect_pypgsql(self, host = None, port = None, db = None, user = None, password = None):
    dsn = ""
    if (host is not None): dsn = host
    dsn = dsn + ":"
    if (port is not None): dsn = dsn + str(port)
    dsn = dsn + ":"
    if (db is not None): dsn = dsn + db
    dsn = dsn + ":"
    if (user is not None): dsn = dsn + user
    dsn = dsn + ":"
    if (password is not None): dsn = dsn + password
    try:
      self.db = MyPgSQL.connect(dsn)
      self.db.autocommit = 1
      self.host = host
      self.port = port
      self.database = db
      self.user = user
      self.password = password
    except libpq.DatabaseError:
      self.db = None


  def connect_pgsql(self, host = None, port = None, db = None, user = None, password = None):
    try:
        if (port is not None) : 
            self.db = pgsql.connect(db, user, password, host, int(port))
        else :
            self.db = pgsql.connect(db, user, password, host)
        self.host = host
        self.port = port
        self.database = db
        self.user = user
        self.password = password
    except pgsql.ProgrammingError:
        self.db = None


  def pgversion(self):
    if (self.is_connected() and not havepgsql):
     v = string.split(str(self.db.version), ',')
     return v.pop(0)
    return ''


  def query(self, sql):
      if (havepgsql):
          return self.query_pgsql(sql)
      else:
          return self.query_pypgsql(sql)


  def query_pypgsql(self, sql):
    """Execute a query and return the corresponding DB-API cursor."""
    if not self.is_connected() : return None
    cursor = self.db.cursor()
    try:
      cursor.execute("SET CLIENT_ENCODING TO 'UTF-8'")
      cursor.execute(sql)
    except libpq.OperationalError, msg:
      cursor.close()
      return { 'error' : str(msg), 'notices' : self.db.notices }
    return { 'cursor' : cursor, 'notices' : self.db.notices }
  
  def query_pgsql(self, sql):
    """Execute a query and return the corresponding DB-API cursor."""
    if not self.is_connected() : return None
    cursor = self.db.cursor()
    try:
      cursor.execute("SET CLIENT_ENCODING TO 'UTF-8'")
      cursor.execute(sql)
      self.db.commit()
    except pgsql.ProgrammingError, msg:
      cursor.close()
      return { 'error' : str(msg), 'notices' : self.db.notices }
    return { 'cursor' : cursor, 'notices' : self.db.notices }
  

  def commit(self):
    if not self.is_connected() : return
    self.db.commit()


  def is_connected(self):
    return (self.db != None)


  def disconnect(self):
    if not self.is_connected() : return
    self.db.close()
    self.db = None
