Files
android_development/tools/repo_diff/service/repodiff/tools/upgrade_db.py
Scott Lobdell 96629bd335 Base commit for service layer for repo diff tooling
Test: Changes are currently independent of the rest of this project. Tests can
currently manually be run with "make test". CL is large, but poses no
risk

Change-Id: Ia77e073df077257cab96b7ca4e1d99a900d029b2
2018-03-06 13:38:05 -08:00

156 lines
3.3 KiB
Python

import commands
import os
import sys
GET_VERSION_QUERY = "SELECT latest_revision FROM application_meta LIMIT 1;"
NULL_VERSION = "0000_00_00__00_00_00"
class Commands(object):
UPGRADE = "upgrade"
DOWNGRADE = "downgrade"
@classmethod
def all(cls):
return (
cls.UPGRADE,
cls.DOWNGRADE,
)
def run_command(command):
exit_code, output = commands.getstatusoutput(command)
if exit_code != 0:
raise ValueError("Error running command: %s" % command)
return output
def run_query(query):
return run_command(
"make db_shell EXTRA=\"-e '{query}'\"".format(
query=query,
)
)
def parse_version_query(mysql_output):
print "MYSQL OUTPUT: %s" % mysql_output
lines = (mysql_output.splitlines())
if len(lines) == 3:
# table not yet populated
return NULL_VERSION
return lines[3]
def get_db_version():
return parse_version_query(
run_query(GET_VERSION_QUERY)
)
def get_upgrade_files_gt(db_version, sql_scripts_dir):
return sorted(
filter(
lambda fname: "upgrade" in fname and fname[:len(db_version)] > db_version,
os.listdir(
sql_scripts_dir,
)
)
)
def get_downgrade_file(db_version):
if db_version == NULL_VERSION:
return None
return "%s_downgrade.sql" % db_version
def get_previous_db_version(current_db_version, sql_scripts_dir):
try:
return sorted(
filter(
lambda fname: "downgrade" in fname and fname[:len(current_db_version)] < current_db_version,
os.listdir(
sql_scripts_dir,
)
)
)[-1].replace("_downgrade.sql", "")
except IndexError:
return NULL_VERSION
def run_sql_file(sql_scripts_dir, sql_fname):
run_command(
"make db_shell < %s" % os.path.join(sql_scripts_dir, sql_fname)
)
def update_db_version(canonical_version):
run_query(
"""
START TRANSACTION;
TRUNCATE TABLE application_meta;
INSERT INTO application_meta (latest_revision) VALUES(\\"{canonical_version}\\");
COMMIT;
""".format(
canonical_version=canonical_version,
).replace("\n", "")
)
def fname_to_canonical_version(fname):
return fname.replace(
"_upgrade.sql",
"",
).replace(
"_downgrade.sql",
"",
)
def upgrade_db(sql_scripts_dir):
print "Upgrading..."
upgrade_files = get_upgrade_files_gt(
get_db_version(),
sql_scripts_dir,
)
if not upgrade_files:
print "Database is upgraded to the latest revision"
return
for upgrade_file in upgrade_files:
run_sql_file(sql_scripts_dir, upgrade_file)
update_db_version(
fname_to_canonical_version(upgrade_file),
)
print "Database version is now set to %s" % get_db_version()
def downgrade_db(sql_scripts_dir):
print "Downgrading..."
current_version = get_db_version()
downgrade_file = get_downgrade_file(current_version)
if downgrade_file is None:
print "Database is already in an empty state"
return
run_sql_file(sql_scripts_dir, downgrade_file)
update_db_version(
get_previous_db_version(
current_version,
sql_scripts_dir,
),
)
if __name__ == "__main__":
try:
{
Commands.UPGRADE: upgrade_db,
Commands.DOWNGRADE: downgrade_db,
}[sys.argv[1]](sys.argv[2])
except (IndexError, KeyError):
print "Usage: python tools/upgrade_db.py [%s|%s] {sql_script_dir}" % Commands.all()
sys.exit(1)