import java.io.*; import java.sql.*; import java.util.*; /** * Delete hidden lobster menu 29926 (node-detail) from master + all tenant DBs. */ public class DeleteLobsterNodeDetailMenu29926 { private static final long MENU_ID = 29926L; private static final String HOST = getenv("DB_HOST", "cq-cdb-8fjmemkb.sql.tencentcdb.com"); private static final int PORT = Integer.parseInt(getenv("DB_PORT", "27220")); private static final String USER = getenv("DB_USER", "root"); private static final String PASS = getenv("DB_PASSWORD", "Ylrz_1q2w3e4r5t6y"); private static final String MASTER_DB = getenv("DB_NAME", "ylrz_saas"); private static final String[] MENU_TABLES = {"sys_menu", "tenant_sys_menu", "tenant_company_menu", "company_menu"}; private static final String[][] ROLE_TABLES = { {"sys_role_menu", "sys_menu"}, {"company_role_menu", "company_menu"} }; public static void main(String[] args) throws Exception { Class.forName("com.mysql.cj.jdbc.Driver"); new File("output").mkdirs(); try (PrintWriter report = new PrintWriter(new OutputStreamWriter( new FileOutputStream("output/delete-menu-29926-report.txt"), "UTF-8")); Connection master = open(MASTER_DB)) { deleteOnConn(master, report, MASTER_DB); for (TenantDb tenant : loadTenants(master)) { try (Connection c = openDb(tenant)) { deleteOnConn(c, report, tenant.database); } catch (Exception e) { report.println("[ERROR] " + tenant.database + ": " + e.getMessage()); } } report.println("\nDone."); System.out.println("Wrote output/delete-menu-29926-report.txt"); } } private static void deleteOnConn(Connection conn, PrintWriter report, String label) throws SQLException { if (!menuExists(conn)) { report.println(label + ": menu 29926 not found, skip"); return; } for (String[] pair : ROLE_TABLES) { if (!tableExists(conn, pair[0])) { continue; } try (PreparedStatement ps = conn.prepareStatement( "DELETE FROM " + pair[0] + " WHERE menu_id = ?")) { ps.setLong(1, MENU_ID); int n = ps.executeUpdate(); if (n > 0) { report.println(label + "." + pair[0] + " deleted role refs=" + n); } } } for (String table : MENU_TABLES) { if (!tableExists(conn, table)) { continue; } try (PreparedStatement ps = conn.prepareStatement("DELETE FROM " + table + " WHERE menu_id = ?")) { ps.setLong(1, MENU_ID); int n = ps.executeUpdate(); if (n > 0) { report.println(label + "." + table + " deleted rows=" + n); } } } } private static boolean menuExists(Connection conn) throws SQLException { for (String table : MENU_TABLES) { if (!tableExists(conn, table)) { continue; } try (PreparedStatement ps = conn.prepareStatement("SELECT 1 FROM " + table + " WHERE menu_id = ? LIMIT 1")) { ps.setLong(1, MENU_ID); try (ResultSet rs = ps.executeQuery()) { if (rs.next()) { return true; } } } } return false; } private static List loadTenants(Connection master) throws SQLException { List list = new ArrayList<>(); try (Statement st = master.createStatement(); ResultSet rs = st.executeQuery("SELECT id, db_url, db_account, db_pwd FROM tenant_info WHERE status = 1 ORDER BY id")) { while (rs.next()) { TenantDb t = parseJdbcUrl(rs.getString("db_url"), rs.getString("db_account"), rs.getString("db_pwd")); if (t != null) { list.add(t); } } } return list; } private static TenantDb parseJdbcUrl(String jdbcUrl, String user, String password) { if (jdbcUrl == null || !jdbcUrl.startsWith("jdbc:mysql://")) { return null; } String body = jdbcUrl.substring("jdbc:mysql://".length()); int slash = body.indexOf('/'); if (slash < 0) { return null; } String hostPort = body.substring(0, slash); String rest = body.substring(slash + 1); int q = rest.indexOf('?'); String database = q >= 0 ? rest.substring(0, q) : rest; TenantDb t = new TenantDb(); int colon = hostPort.indexOf(':'); if (colon >= 0) { t.host = hostPort.substring(0, colon); t.port = Integer.parseInt(hostPort.substring(colon + 1)); } else { t.host = hostPort; t.port = 3306; } t.database = database; t.user = user != null ? user : USER; t.password = password != null ? password : PASS; return t; } private static boolean tableExists(Connection conn, String table) throws SQLException { try (PreparedStatement ps = conn.prepareStatement( "SELECT 1 FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ? LIMIT 1")) { ps.setString(1, table); try (ResultSet rs = ps.executeQuery()) { return rs.next(); } } } private static Connection open(String database) throws SQLException { return DriverManager.getConnection(buildUrl(HOST, PORT, database), USER, PASS); } private static Connection openDb(TenantDb tenant) throws SQLException { return DriverManager.getConnection(buildUrl(tenant.host, tenant.port, tenant.database), tenant.user, tenant.password); } private static String buildUrl(String host, int port, String database) { return "jdbc:mysql://" + host + ":" + port + "/" + database + "?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&allowMultiQueries=true"; } private static String getenv(String key, String defaultValue) { String v = System.getenv(key); return v != null && !v.isEmpty() ? v : defaultValue; } private static class TenantDb { String host; int port; String database; String user; String password; } }