Merge branch 'MissingDamageTargetProfileNames' of https://github.com/Ebag333/Pyfa into development

Conflicts:
	service/prefetch.py
This commit is contained in:
blitzman
2017-01-29 15:04:56 -05:00
2 changed files with 112 additions and 53 deletions

View File

@@ -28,77 +28,135 @@ class DatabaseCleanup:
pass
@staticmethod
def OrphanedCharacterSkills(saveddata_engine):
# Finds and fixes database corruption issues.
logger.debug("Start databsae validation and cleanup.")
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
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)
if results is None:
return
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
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)
if results is None:
return
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)

View File

@@ -48,6 +48,7 @@ if config.saveDB and os.path.isfile(config.saveDB):
# Import values that must exist otherwise Pyfa breaks
DefaultDatabaseValues.importRequiredDefaults()
# Finds and fixes database corruption issues.
logging.debug("Starting database validation.")
database_cleanup_instance = DatabaseCleanup()
database_cleanup_instance.OrphanedCharacterSkills(db.saveddata_engine)