diff --git a/eos/db/saveddata/databaseRepair.py b/eos/db/saveddata/databaseRepair.py index 87442a2dc..e9685381a 100644 --- a/eos/db/saveddata/databaseRepair.py +++ b/eos/db/saveddata/databaseRepair.py @@ -27,111 +27,136 @@ class DatabaseCleanup: def __init__(self): pass + @staticmethod + def ExecuteSQLQuery(saveddata_engine, query): + try: + results = saveddata_engine.execute(query) + return results + except sqlalchemy.exc.DatabaseError: + logger.error("Failed to connect to database or error executing query:\n%s",query) + return None + @staticmethod def OrphanedCharacterSkills(saveddata_engine): # Find orphaned character skills. # This solves an issue where the character doesn't exist, but skills for that character do. # See issue #917 - try: - logger.debug("Running database cleanup for character skills.") - results = saveddata_engine.execute("SELECT COUNT(*) AS num FROM characterSkills " - "WHERE characterID NOT IN (SELECT ID from characters)") - row = results.first() + logger.debug("Running database cleanup for character skills.") + query = "SELECT COUNT(*) AS num FROM characterSkills WHERE characterID NOT IN (SELECT ID from characters)" + results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) - if row and row['num']: - delete = saveddata_engine.execute("DELETE FROM characterSkills WHERE characterID NOT IN (SELECT ID from characters)") - logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount) + if results is None: + return - except sqlalchemy.exc.DatabaseError: - logger.error("Failed to connect to database.") + row = results.first() + + if row and row['num']: + query = "DELETE FROM characterSkills WHERE characterID NOT IN (SELECT ID from characters)" + delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount) @staticmethod def OrphanedFitDamagePatterns(saveddata_engine): # Find orphaned damage patterns. # This solves an issue where the damage pattern doesn't exist, but fits reference the pattern. # See issue #777 - try: - logger.debug("Running database cleanup for orphaned damage patterns attached to fits.") + logger.debug("Running database cleanup for orphaned damage patterns attached to fits.") + query = "SELECT COUNT(*) AS num FROM fits WHERE damagePatternID NOT IN (SELECT ID FROM damagePatterns) OR damagePatternID IS NULL" + results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) - results = saveddata_engine.execute("SELECT COUNT(*) AS num FROM fits WHERE damagePatternID NOT IN (SELECT ID FROM damagePatterns) OR damagePatternID IS NULL") - row = results.first() + if results is None: + return - if row and row['num']: - # Get Uniform damage pattern ID - query = saveddata_engine.execute("SELECT ID FROM damagePatterns WHERE name = 'Uniform'") - rows = query.fetchall() + row = results.first() - if len(rows) == 0: - logger.error("Missing uniform damage pattern.") - elif len(rows) > 1: - logger.error("More than one uniform damage pattern found.") - else: - uniform_damage_pattern_id = rows[0]['ID'] - update = saveddata_engine.execute("UPDATE 'fits' SET 'damagePatternID' = ? " - "WHERE damagePatternID NOT IN (SELECT ID FROM damagePatterns) OR damagePatternID IS NULL", - uniform_damage_pattern_id) - logger.error("Database corruption found. Cleaning up %d records.", update.rowcount) - except sqlalchemy.exc.DatabaseError: - logger.error("Failed to connect to database.") + if row and row['num']: + # Get Uniform damage pattern ID + uniform_query = "SELECT ID FROM damagePatterns WHERE name = 'Uniform'" + uniform_results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, uniform_query) + + if uniform_results is None: + return + + rows = uniform_results.fetchall() + + if len(rows) == 0: + logger.error("Missing uniform damage pattern.") + elif len(rows) > 1: + logger.error("More than one uniform damage pattern found.") + else: + uniform_damage_pattern_id = rows[0]['ID'] + update_query = "UPDATE 'fits' SET 'damagePatternID' = " + str(uniform_damage_pattern_id) + \ + " WHERE damagePatternID NOT IN (SELECT ID FROM damagePatterns) OR damagePatternID IS NULL" + update_results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, update_query) + logger.error("Database corruption found. Cleaning up %d records.", update_results.rowcount) @staticmethod def OrphanedFitCharacterIDs(saveddata_engine): # Find orphaned character IDs. This solves an issue where the character doesn't exist, but fits reference the pattern. - try: - logger.debug("Running database cleanup for orphaned characters attached to fits.") - results = saveddata_engine.execute("SELECT COUNT(*) AS num FROM fits WHERE characterID NOT IN (SELECT ID FROM characters) OR characterID IS NULL") - row = results.first() + logger.debug("Running database cleanup for orphaned characters attached to fits.") + query = "SELECT COUNT(*) AS num FROM fits WHERE characterID NOT IN (SELECT ID FROM characters) OR characterID IS NULL" + results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) - if row['num']: - # Get All 5 character ID - query = saveddata_engine.execute("SELECT ID FROM characters WHERE name = 'All 5'") - rows = query.fetchall() + if results is None: + return - if len(rows) == 0: - logger.error("Missing 'All 5' character.") - elif len(rows) > 1: - logger.error("More than one 'All 5' character found.") - else: - all5_id = rows[0]['ID'] - update = saveddata_engine.execute("UPDATE 'fits' SET 'characterID' = ? " - "WHERE characterID not in (select ID from characters) OR characterID IS NULL", - all5_id) - logger.error("Database corruption found. Cleaning up %d records.", update.rowcount) - except sqlalchemy.exc.DatabaseError: - logger.error("Failed to connect to database.") + row = results.first() + + if row and row['num']: + # Get All 5 character ID + all5_query = "SELECT ID FROM characters WHERE name = 'All 5'" + all5_results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, all5_query) + + if all5_results is None: + return + + rows = all5_results.fetchall() + + if len(rows) == 0: + logger.error("Missing 'All 5' character.") + elif len(rows) > 1: + logger.error("More than one 'All 5' character found.") + else: + all5_id = rows[0]['ID'] + update_query = "UPDATE 'fits' SET 'characterID' = " + str(all5_id) + \ + " WHERE characterID not in (select ID from characters) OR characterID IS NULL" + update_results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, update_query) + logger.error("Database corruption found. Cleaning up %d records.", update_results.rowcount) @staticmethod def NullDamagePatternNames(saveddata_engine): # Find damage patterns that are missing the name. # This solves an issue where the damage pattern ends up with a name that is null. # See issue #949 - try: - logger.debug("Running database cleanup for missing damage pattern names.") + logger.debug("Running database cleanup for missing damage pattern names.") + query = "SELECT COUNT(*) AS num FROM damagePatterns WHERE name IS NULL OR name = ''" + results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) - # Damage Patterns - results = saveddata_engine.execute("SELECT COUNT(*) AS num FROM damagePatterns WHERE name IS NULL OR name = ''") - row = results.first() + if results is None: + return - if row and row['num']: - update = saveddata_engine.execute("UPDATE 'damagePatterns' SET 'name' = 'Unknown' WHERE name IS NULL OR name = ''") - logger.error("Database corruption found. Cleaning up %d records.", update.rowcount) - except sqlalchemy.exc.DatabaseError: - logger.error("Failed to connect to database.") + row = results.first() + + if row and row['num']: + query = "UPDATE 'damagePatterns' SET 'name' = 'Unknown' WHERE name IS NULL OR name = ''" + delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount) @staticmethod def NullTargetResistNames(saveddata_engine): # Find target resists that are missing the name. # This solves an issue where the target resist ends up with a name that is null. # See issue #949 - try: - logger.debug("Running database cleanup for missing target resist names.") + logger.debug("Running database cleanup for missing target resist names.") + query = "SELECT COUNT(*) AS num FROM targetResists WHERE name IS NULL OR name = ''" + results = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) - # Damage Patterns - results = saveddata_engine.execute("SELECT COUNT(*) AS num FROM targetResists WHERE name IS NULL OR name = ''") - row = results.first() + if results is None: + return - if row and row['num']: - update = saveddata_engine.execute("UPDATE 'targetResists' SET 'name' = 'Unknown' WHERE name IS NULL OR name = ''") - logger.error("Database corruption found. Cleaning up %d records.", update.rowcount) - except sqlalchemy.exc.DatabaseError: - logger.error("Failed to connect to database.") + row = results.first() + + if row and row['num']: + query = "UPDATE 'targetResists' SET 'name' = 'Unknown' WHERE name IS NULL OR name = ''" + delete = DatabaseCleanup.ExecuteSQLQuery(saveddata_engine, query) + logger.error("Database corruption found. Cleaning up %d records.", delete.rowcount)