diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py index 36fdd2d2..ad376453 100644 --- a/pyfpdb/Database.py +++ b/pyfpdb/Database.py @@ -187,6 +187,7 @@ class Database: def __init__(self, c, sql = None): log.info("Creating Database instance, sql = %s" % sql) self.config = c + self.__connected = False self.fdb = fpdb_db.fpdb_db() # sets self.fdb.db self.fdb.cursor and self.fdb.sql self.do_connect(c) @@ -237,7 +238,12 @@ class Database: self.hud_style = style def do_connect(self, c): - self.fdb.do_connect(c) + try: + self.fdb.do_connect(c) + except: + # error during connect + self.__connected = False + raise self.connection = self.fdb.db self.wrongDbVersion = self.fdb.wrongDbVersion @@ -247,6 +253,7 @@ class Database: self.db_server = db_params['db-server'] self.database = db_params['db-databaseName'] self.host = db_params['db-host'] + self.__connected = True def commit(self): self.fdb.db.commit() @@ -254,6 +261,9 @@ class Database: def rollback(self): self.fdb.db.rollback() + def connected(self): + return self.__connected + def get_cursor(self): return self.connection.cursor() diff --git a/pyfpdb/Exceptions.py b/pyfpdb/Exceptions.py index 5b4f4391..fd7c20e3 100644 --- a/pyfpdb/Exceptions.py +++ b/pyfpdb/Exceptions.py @@ -34,5 +34,19 @@ class FpdbMySQLNoDatabase(FpdbDatabaseError): def __str__(self): return repr(self.value +" " + self.errmsg) +class FpdbPostgresqlAccessDenied(FpdbDatabaseError): + def __init__(self, value='', errmsg=''): + self.value = value + self.errmsg = errmsg + def __str__(self): + return repr(self.value +" " + self.errmsg) + +class FpdbPostgresqlNoDatabase(FpdbDatabaseError): + def __init__(self, value='', errmsg=''): + self.value = value + self.errmsg = errmsg + def __str__(self): + return repr(self.value +" " + self.errmsg) + class DuplicateError(FpdbError): pass diff --git a/pyfpdb/fpdb.py b/pyfpdb/fpdb.py index b7013a92..da03b2cc 100755 --- a/pyfpdb/fpdb.py +++ b/pyfpdb/fpdb.py @@ -700,21 +700,26 @@ class fpdb: self.settings.update(self.config.get_import_parameters()) self.settings.update(self.config.get_default_paths()) - if self.db is not None and self.db.fdb is not None: + if self.db is not None and self.db.connected: self.db.disconnect() self.sql = SQL.Sql(db_server = self.settings['db-server']) + err_msg = None try: self.db = Database.Database(self.config, sql = self.sql) except Exceptions.FpdbMySQLAccessDenied: - #self.db = None - self.warning_box("MySQL Server reports: Access denied. Are your permissions set correctly?") - exit() + err_msg = "MySQL Server reports: Access denied. Are your permissions set correctly?" except Exceptions.FpdbMySQLNoDatabase: - #self.db = None - msg = "MySQL client reports: 2002 or 2003 error. Unable to connect - Please check that the MySQL service has been started" - self.warning_box(msg) - exit + err_msg = "MySQL client reports: 2002 or 2003 error. Unable to connect - " \ + + "Please check that the MySQL service has been started" + except Exceptions.FpdbPostgresqlAccessDenied: + err_msg = "Postgres Server reports: Access denied. Are your permissions set correctly?" + except Exceptions.FpdbPostgresqlNoDatabase: + err_msg = "Postgres client reports: Unable to connect - " \ + + "Please check that the Postgres service has been started" + if err_msg is not None: + self.db = None + self.warning_box(err_msg) # except FpdbMySQLFailedError: # self.warning_box("Unable to connect to MySQL! Is the MySQL server running?!", "FPDB ERROR") @@ -732,7 +737,7 @@ class fpdb: # print "*** Error: " + err[2] + "(" + str(err[1]) + "): " + str(sys.exc_info()[1]) # sys.stderr.write("Failed to connect to %s database with username %s." % (self.settings['db-server'], self.settings['db-user'])) - if self.db.wrongDbVersion: + if self.db is not None and self.db.wrongDbVersion: diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) label = gtk.Label("An invalid DB version or missing tables have been detected.") @@ -751,14 +756,15 @@ class fpdb: diaDbVersionWarning.destroy() if self.status_bar is None: - self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.get_backend_name(),self.db.database, self.db.host)) + self.status_bar = gtk.Label("") self.main_vbox.pack_end(self.status_bar, False, True, 0) self.status_bar.show() - else: - self.status_bar.set_text("Status: Connected to %s database named %s on host %s" % (self.db.get_backend_name(),self.db.database, self.db.host)) - # Database connected to successfully, load queries to pass on to other classes - self.db.rollback() + if self.db is not None and self.db.connected: + self.status_bar.set_text("Status: Connected to %s database named %s on host %s" + % (self.db.get_backend_name(),self.db.database, self.db.host)) + # rollback to make sure any locks are cleared: + self.db.rollback() self.validate_config() @@ -779,7 +785,8 @@ class fpdb: # TODO: can we get some / all of the stuff done in this function to execute on any kind of abort? print "Quitting normally" # TODO: check if current settings differ from profile, if so offer to save or abort - self.db.disconnect() + if self.db is not None and self.db.connected: + self.db.disconnect() self.statusIcon.set_visible(False) gtk.main_quit() diff --git a/pyfpdb/fpdb_db.py b/pyfpdb/fpdb_db.py index 405a142c..baabb4bf 100644 --- a/pyfpdb/fpdb_db.py +++ b/pyfpdb/fpdb_db.py @@ -129,18 +129,22 @@ class fpdb_db: self.db = psycopg2.connect(database = database) connected = True except: + # direct connection failed so try user/pass/... version pass - #msg = "PostgreSQL direct connection to database (%s) failed, trying with user ..." % (database,) - #print msg - #raise FpdbError(msg) if not connected: try: self.db = psycopg2.connect(host = host, user = user, password = password, database = database) - except: - msg = "PostgreSQL connection to database (%s) user (%s) failed. Are you sure the DB is running?" % (database, user) + except Exception, ex: + if 'Connection refused' in ex.args[0]: + # meaning eg. db not running + raise FpdbPostgresqlNoDatabase(errmsg = ex.args[0]) + elif 'password authentication' in ex.args[0]: + raise FpdbPostgresqlAccessDenied(errmsg = ex.args[0]) + else: + msg = ex.args[0] print msg raise FpdbError(msg) elif backend == fpdb_db.SQLITE: @@ -167,6 +171,7 @@ class fpdb_db: logging.warning("Some database functions will not work without NumPy support") else: raise FpdbError("unrecognised database backend:"+backend) + self.cursor = self.db.cursor() # Set up query dictionary as early in the connection process as we can. self.sql = FpdbSQLQueries.FpdbSQLQueries(self.get_backend_name())