findmissing: Use UNION to query multiple fixes tables

Use sql UNION statement to query multiple fixes tables instead of
querying each table and combining the results.

BUG=None
TEST=Run "findmissing status sha sha ..."

Change-Id: I5e1693d9df8b8728f42cdfe61d412db0ab1a7540
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/dev-util/+/2318408
Tested-by: Guenter Roeck <groeck@chromium.org>
Reviewed-by: Curtis Malainey <cujomalainey@chromium.org>
Commit-Queue: Guenter Roeck <groeck@chromium.org>
diff --git a/contrib/findmissing/cloudsql_interface.py b/contrib/findmissing/cloudsql_interface.py
index 6659fb0..f377956 100755
--- a/contrib/findmissing/cloudsql_interface.py
+++ b/contrib/findmissing/cloudsql_interface.py
@@ -47,29 +47,32 @@
     return (row['kernel_sha'], row['fixedby_upstream_sha'])
 
 
-def get_fix_status_and_changeid(db, fixes_table, kernel_sha, fixedby_upstream_sha):
+def get_fix_status_and_changeid(db, fixes_tables, kernel_sha, fixedby_upstream_sha):
     """Get branch, fix_change_id, initial_status and status for one or more rows in fixes table."""
     c = db.cursor(MySQLdb.cursors.DictCursor)
 
-    q = """SELECT '{fixes_table}' AS 'table', branch, kernel_sha, fixedby_upstream_sha,
-                  fix_change_id, initial_status, status
-           FROM {fixes_table}""".format(fixes_table=fixes_table)
+    pre_q = """SELECT '{fixes_table}' AS 'table', branch, kernel_sha, fixedby_upstream_sha,
+                      fix_change_id, initial_status, status
+               FROM {fixes_table}
+               WHERE """
 
-    if kernel_sha and fixedby_upstream_sha:
-        q += ' WHERE kernel_sha = %s AND fixedby_upstream_sha = %s'
-        sha_list = [kernel_sha, fixedby_upstream_sha]
-    elif fixedby_upstream_sha:
-        q += ' WHERE fixedby_upstream_sha = %s'
-        sha_list = [fixedby_upstream_sha]
-    else:
-        q += ' WHERE kernel_sha = %s'
-        sha_list = [kernel_sha]
+    if kernel_sha:
+        pre_q += ' kernel_sha = "%s"' % kernel_sha
+        if fixedby_upstream_sha:
+            pre_q += ' AND'
+    if fixedby_upstream_sha:
+        pre_q += ' fixedby_upstream_sha = "%s"' % fixedby_upstream_sha
 
-    c.execute(q, sha_list)
+    q = pre_q.format(fixes_table=fixes_tables.pop(0))
+    while fixes_tables:
+        q += ' UNION '
+        q += pre_q.format(fixes_table=fixes_tables.pop(0))
+
+    c.execute(q)
     return c.fetchall()
 
 
-def get_fix_status_and_changeid_from_list(db, fixes_table, sha_list):
+def get_fix_status_and_changeid_from_list(db, fixes_tables, sha_list):
     """Get branch, fix_change_id, initial_status and status for one or more rows in fixes table.
 
     The SHA or SHAs to identify commits are provided as anonymous SHA list. SHAs may either
@@ -95,7 +98,7 @@
         if len(sha_list) > 1:
             fixedby_upstream_sha = sha_list[1]
 
-    return get_fix_status_and_changeid(db, fixes_table, kernel_sha, fixedby_upstream_sha)
+    return get_fix_status_and_changeid(db, fixes_tables, kernel_sha, fixedby_upstream_sha)
 
 
 def update_change_abandoned(db, fixes_table, kernel_sha, fixedby_upstream_sha, reason=None):
@@ -116,7 +119,7 @@
 
 def update_change_restored(db, fixes_table, kernel_sha, fixedby_upstream_sha, reason=None):
     """Updates fixes_table unique fix row to indicate fix cl has been reopened."""
-    rows = get_fix_status_and_changeid(db, fixes_table, kernel_sha, fixedby_upstream_sha)
+    rows = get_fix_status_and_changeid(db, [fixes_table], kernel_sha, fixedby_upstream_sha)
     row = rows[0]
     status = 'OPEN' if row['fix_change_id'] else row['initial_status']
 
diff --git a/contrib/findmissing/main.py b/contrib/findmissing/main.py
index 7c10626..c0abd42 100755
--- a/contrib/findmissing/main.py
+++ b/contrib/findmissing/main.py
@@ -61,13 +61,12 @@
     """Get all table rows for provided fixes table, or for both tables if none is proviced."""
 
     if not fixes_table:
-        rows = get_fixes_rows(cloudsql_db, 'stable_fixes', sha_list)
-        rows += get_fixes_rows(cloudsql_db, 'chrome_fixes', sha_list)
+        fixes_tables = ['stable_fixes', 'chrome_fixes']
     else:
-        rows = cloudsql_interface.get_fix_status_and_changeid_from_list(cloudsql_db,
-                                                                        fixes_table, sha_list)
+        fixes_tables = [fixes_table]
 
-    return rows
+    return cloudsql_interface.get_fix_status_and_changeid_from_list(cloudsql_db, fixes_tables,
+                                                                    sha_list)
 
 
 @util.cloud_sql_proxy_decorator