From 386bf19b6e4d82f6378c4f53c2806139ef178be7 Mon Sep 17 00:00:00 2001 From: morpheus65535 Date: Tue, 4 May 2021 06:38:42 -0400 Subject: [PATCH] Fix for database cleanup routine on new DB. --- bazarr/database.py | 255 +++++++++++++++++++++++---------------------- 1 file changed, 128 insertions(+), 127 deletions(-) diff --git a/bazarr/database.py b/bazarr/database.py index c888cb5d8..b1bf2f13d 100644 --- a/bazarr/database.py +++ b/bazarr/database.py @@ -95,84 +95,6 @@ dict_mapper = SqliteDictPathMapper() def db_upgrade(): - columnToRemove = [ - ['table_shows', 'languages'], - ['table_shows', 'hearing_impaired'], - ['table_shows', 'forced'], - ['table_shows', 'sizeOnDisk'], - ['table_episodes', 'file_ffprobe'], - ['table_movies', 'languages'], - ['table_movies', 'hearing_impaired'], - ['table_movies', 'forced'], - ['table_movies', 'file_ffprobe'], - ] - - for column in columnToRemove: - try: - table_name = column[0] - column_name = column[1] - tables_query = database.execute("SELECT name FROM sqlite_master WHERE type = 'table'") - tables = [table['name'] for table in tables_query] - if table_name not in tables: - # Table doesn't exist in database. Skipping. - continue - - columns_dict = database.execute('''PRAGMA table_info('{0}')'''.format(column[0])) - columns_names_list = [x['name'] for x in columns_dict] - if column_name in columns_names_list: - columns_names_list.remove(column_name) - columns_names_string = ', '.join(columns_names_list) - if not columns_names_list: - logging.debug("BAZARR No more columns in {}. We won't create an empty table. " - "Exiting.".format(table_name)) - continue - else: - logging.debug("BAZARR Column {} doesn't exist in {}".format(column_name, table_name)) - continue - - # get original sql statement used to create the table - original_sql_statement = database.execute("SELECT sql FROM sqlite_master WHERE type='table' AND " - "name='{}'".format(table_name))[0]['sql'] - # pretty format sql statement - original_sql_statement = original_sql_statement.replace('\n, ', ',\n\t') - original_sql_statement = original_sql_statement.replace('", "', '",\n\t"') - original_sql_statement = original_sql_statement.rstrip(')') + '\n' - - # generate sql statement for temp table - table_regex = re.compile(r"CREATE TABLE \"{}\"".format(table_name)) - column_regex = re.compile(r".+\"{}\".+\n".format(column_name)) - new_sql_statement = table_regex.sub("CREATE TABLE \"{}_temp\"".format(table_name), original_sql_statement) - new_sql_statement = column_regex.sub("", new_sql_statement).rstrip('\n').rstrip(',') + '\n)' - - # remove leftover temp table from previous execution - database.execute('DROP TABLE IF EXISTS {}_temp'.format(table_name)) - - # create new temp table - create_error = database.execute(new_sql_statement) - if create_error: - logging.debug('BAZARR cannot create temp table.') - continue - - # validate if row insertion worked as expected - new_table_rows = database.execute('INSERT INTO {0}_temp({1}) SELECT {1} FROM {0}'.format(table_name, - columns_names_string)) - previous_table_rows = database.execute('SELECT COUNT(*) as count FROM {}'.format(table_name), - only_one=True)['count'] - if new_table_rows == previous_table_rows: - drop_error = database.execute('DROP TABLE {}'.format(table_name)) - if drop_error: - logging.debug('BAZARR cannot drop {} table before renaming the temp table'.format(table_name)) - continue - else: - rename_error = database.execute('ALTER TABLE {0}_temp RENAME TO {0}'.format(table_name)) - if rename_error: - logging.debug('BAZARR cannot rename {}_temp table'.format(table_name)) - else: - logging.debug('BAZARR cannot insert existing rows to {} table.'.format(table_name)) - continue - except: - pass - columnToAdd = [ ['table_shows', 'year', 'text'], ['table_shows', 'alternateTitles', 'text'], @@ -276,56 +198,135 @@ def db_upgrade(): "UNION ALL SELECT languages, hearing_impaired, forced FROM table_movies) " "a WHERE languages NOT null and languages NOT IN ('None', '[]')") - for profile in profiles_to_create: - profile_items = [] - languages_list = ast.literal_eval(profile['languages']) - for i, language in enumerate(languages_list, 1): - if profile['forced'] == 'Both': - profile_items.append({'id': i, 'language': language, 'forced': 'True', - 'hi': profile['hearing_impaired'], 'audio_exclude': 'False'}) - profile_items.append({'id': i, 'language': language, 'forced': 'False', - 'hi': profile['hearing_impaired'], 'audio_exclude': 'False'}) + if isinstance(profiles_to_create, list): + for profile in profiles_to_create: + profile_items = [] + languages_list = ast.literal_eval(profile['languages']) + for i, language in enumerate(languages_list, 1): + if profile['forced'] == 'Both': + profile_items.append({'id': i, 'language': language, 'forced': 'True', + 'hi': profile['hearing_impaired'], 'audio_exclude': 'False'}) + profile_items.append({'id': i, 'language': language, 'forced': 'False', + 'hi': profile['hearing_impaired'], 'audio_exclude': 'False'}) + else: + profile_items.append({'id': i, 'language': language, 'forced': profile['forced'], + 'hi': profile['hearing_impaired'], 'audio_exclude': 'False'}) + + # Create profiles + new_profile_name = profile['languages'] + ' (' + profile['hearing_impaired'] + '/' + profile['forced'] + ')' + database.execute("INSERT INTO table_languages_profiles (name, cutoff, items) VALUES(" + "?,null,?)", (new_profile_name, json.dumps(profile_items),)) + created_profile_id = database.execute("SELECT profileId FROM table_languages_profiles WHERE name = ?", + (new_profile_name,), only_one=True)['profileId'] + # Assign profiles to series and movies + database.execute("UPDATE table_shows SET profileId = ? WHERE languages = ? AND hearing_impaired = ? AND " + "forced = ?", (created_profile_id, profile['languages'], profile['hearing_impaired'], + profile['forced'])) + database.execute("UPDATE table_movies SET profileId = ? WHERE languages = ? AND hearing_impaired = ? AND " + "forced = ?", (created_profile_id, profile['languages'], profile['hearing_impaired'], + profile['forced'])) + + # Save new defaults + profile_items_list = [] + for item in profile_items: + profile_items_list.append([item['language'], item['forced'], item['hi']]) + try: + if created_profile_id and profile_items_list == series_default: + settings.general.serie_default_profile = str(created_profile_id) + except: + pass + + try: + if created_profile_id and profile_items_list == movies_default: + settings.general.movie_default_profile = str(created_profile_id) + except: + pass + + # null languages, forced and hearing_impaired for all series and movies + database.execute("UPDATE table_shows SET languages = null, forced = null, hearing_impaired = null") + database.execute("UPDATE table_movies SET languages = null, forced = null, hearing_impaired = null") + + # Force series, episodes and movies sync with Sonarr to get all the audio track from video files + # Set environment variable that is going to be use during the init process to run sync once Bazarr is ready. + os.environ['BAZARR_AUDIO_PROFILES_MIGRATION'] = '1' + + columnToRemove = [ + ['table_shows', 'languages'], + ['table_shows', 'hearing_impaired'], + ['table_shows', 'forced'], + ['table_shows', 'sizeOnDisk'], + ['table_episodes', 'file_ffprobe'], + ['table_movies', 'languages'], + ['table_movies', 'hearing_impaired'], + ['table_movies', 'forced'], + ['table_movies', 'file_ffprobe'], + ] + + for column in columnToRemove: + try: + table_name = column[0] + column_name = column[1] + tables_query = database.execute("SELECT name FROM sqlite_master WHERE type = 'table'") + tables = [table['name'] for table in tables_query] + if table_name not in tables: + # Table doesn't exist in database. Skipping. + continue + + columns_dict = database.execute('''PRAGMA table_info('{0}')'''.format(column[0])) + columns_names_list = [x['name'] for x in columns_dict] + if column_name in columns_names_list: + columns_names_list.remove(column_name) + columns_names_string = ', '.join(columns_names_list) + if not columns_names_list: + logging.debug("BAZARR No more columns in {}. We won't create an empty table. " + "Exiting.".format(table_name)) + continue + else: + logging.debug("BAZARR Column {} doesn't exist in {}".format(column_name, table_name)) + continue + + # get original sql statement used to create the table + original_sql_statement = database.execute("SELECT sql FROM sqlite_master WHERE type='table' AND " + "name='{}'".format(table_name))[0]['sql'] + # pretty format sql statement + original_sql_statement = original_sql_statement.replace('\n, ', ',\n\t') + original_sql_statement = original_sql_statement.replace('", "', '",\n\t"') + original_sql_statement = original_sql_statement.rstrip(')') + '\n' + + # generate sql statement for temp table + table_regex = re.compile(r"CREATE TABLE \"{}\"".format(table_name)) + column_regex = re.compile(r".+\"{}\".+\n".format(column_name)) + new_sql_statement = table_regex.sub("CREATE TABLE \"{}_temp\"".format(table_name), original_sql_statement) + new_sql_statement = column_regex.sub("", new_sql_statement).rstrip('\n').rstrip(',') + '\n)' + + # remove leftover temp table from previous execution + database.execute('DROP TABLE IF EXISTS {}_temp'.format(table_name)) + + # create new temp table + create_error = database.execute(new_sql_statement) + if create_error: + logging.debug('BAZARR cannot create temp table.') + continue + + # validate if row insertion worked as expected + new_table_rows = database.execute('INSERT INTO {0}_temp({1}) SELECT {1} FROM {0}'.format(table_name, + columns_names_string)) + previous_table_rows = database.execute('SELECT COUNT(*) as count FROM {}'.format(table_name), + only_one=True)['count'] + if new_table_rows == previous_table_rows: + drop_error = database.execute('DROP TABLE {}'.format(table_name)) + if drop_error: + logging.debug('BAZARR cannot drop {} table before renaming the temp table'.format(table_name)) + continue else: - profile_items.append({'id': i, 'language': language, 'forced': profile['forced'], - 'hi': profile['hearing_impaired'], 'audio_exclude': 'False'}) - - # Create profiles - new_profile_name = profile['languages'] + ' (' + profile['hearing_impaired'] + '/' + profile['forced'] + ')' - database.execute("INSERT INTO table_languages_profiles (name, cutoff, items) VALUES(" - "?,null,?)", (new_profile_name, json.dumps(profile_items),)) - created_profile_id = database.execute("SELECT profileId FROM table_languages_profiles WHERE name = ?", - (new_profile_name,), only_one=True)['profileId'] - # Assign profiles to series and movies - database.execute("UPDATE table_shows SET profileId = ? WHERE languages = ? AND hearing_impaired = ? AND " - "forced = ?", (created_profile_id, profile['languages'], profile['hearing_impaired'], - profile['forced'])) - database.execute("UPDATE table_movies SET profileId = ? WHERE languages = ? AND hearing_impaired = ? AND " - "forced = ?", (created_profile_id, profile['languages'], profile['hearing_impaired'], - profile['forced'])) - - # Save new defaults - profile_items_list = [] - for item in profile_items: - profile_items_list.append([item['language'], item['forced'], item['hi']]) - try: - if created_profile_id and profile_items_list == series_default: - settings.general.serie_default_profile = str(created_profile_id) - except: - pass - - try: - if created_profile_id and profile_items_list == movies_default: - settings.general.movie_default_profile = str(created_profile_id) - except: - pass - - # null languages, forced and hearing_impaired for all series and movies - database.execute("UPDATE table_shows SET languages = null, forced = null, hearing_impaired = null") - database.execute("UPDATE table_movies SET languages = null, forced = null, hearing_impaired = null") - - # Force series, episodes and movies sync with Sonarr to get all the audio track from video files - # Set environment variable that is going to be use during the init process to run sync once Bazarr is ready. - os.environ['BAZARR_AUDIO_PROFILES_MIGRATION'] = '1' + rename_error = database.execute('ALTER TABLE {0}_temp RENAME TO {0}'.format(table_name)) + if rename_error: + logging.debug('BAZARR cannot rename {}_temp table'.format(table_name)) + else: + logging.debug('BAZARR cannot insert existing rows to {} table.'.format(table_name)) + continue + except: + pass def get_exclusion_clause(type):