RenameLobsterEngineBrand.java 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import java.io.*;
  2. import java.sql.*;
  3. import java.util.*;
  4. /**
  5. * Rename menu brand: lobster engine root -> AI digital employee, all master + tenant DBs.
  6. * Also fixes known garbled menu_name on master sys_menu (menu_id=29951).
  7. *
  8. * Usage:
  9. * java -cp ".;lib/mysql-connector-j-8.0.33.jar" RenameLobsterEngineBrand
  10. */
  11. public class RenameLobsterEngineBrand {
  12. private static final String HOST = getenv("DB_HOST", "cq-cdb-8fjmemkb.sql.tencentcdb.com");
  13. private static final int PORT = Integer.parseInt(getenv("DB_PORT", "27220"));
  14. private static final String USER = getenv("DB_USER", "root");
  15. private static final String PASS = getenv("DB_PASSWORD", "Ylrz_1q2w3e4r5t6y");
  16. private static final String MASTER_DB = getenv("DB_NAME", "ylrz_saas");
  17. private static final String OLD_ROOT = "\u9f99\u867e\u5f15\u64ce";
  18. private static final String NEW_ROOT = "AI\u6570\u5b57\u5458\u5de5";
  19. private static final String FIX_QDRANT = "\u5411\u91cf\u77e5\u8bc6\u5e93";
  20. public static void main(String[] args) throws Exception {
  21. Class.forName("com.mysql.cj.jdbc.Driver");
  22. new File("output").mkdirs();
  23. try (PrintWriter report = new PrintWriter(new OutputStreamWriter(
  24. new FileOutputStream("output/rename-lobster-brand-report.txt"), "UTF-8"));
  25. Connection master = open(MASTER_DB)) {
  26. report.println("Rename '" + OLD_ROOT + "' -> '" + NEW_ROOT + "'");
  27. renameOnDb(master, report, MASTER_DB, "sys_menu", "tenant_sys_menu", "tenant_company_menu");
  28. List<TenantDb> tenants = loadTenants(master);
  29. for (TenantDb tenant : tenants) {
  30. try (Connection c = openDb(tenant)) {
  31. renameOnDb(c, report, tenant.database, "sys_menu", "company_menu");
  32. } catch (Exception e) {
  33. report.println("[ERROR] " + tenant.database + ": " + e.getMessage());
  34. }
  35. }
  36. fixGarbledQdrant(master, report);
  37. report.println("\nDone.");
  38. System.out.println("Wrote output/rename-lobster-brand-report.txt");
  39. }
  40. }
  41. private static void renameOnDb(Connection conn, PrintWriter report, String dbLabel, String... tables) throws SQLException {
  42. for (String table : tables) {
  43. if (!tableExists(conn, table)) {
  44. continue;
  45. }
  46. int exact = updateExact(conn, table);
  47. int prefix = updatePrefix(conn, table);
  48. if (exact + prefix > 0) {
  49. report.println(dbLabel + "." + table + " exact=" + exact + " prefix=" + prefix);
  50. }
  51. }
  52. }
  53. private static int updateExact(Connection conn, String table) throws SQLException {
  54. String sql = "UPDATE " + table + " SET menu_name = ?, update_time = NOW() WHERE menu_name = ?";
  55. try (PreparedStatement ps = conn.prepareStatement(sql)) {
  56. ps.setString(1, NEW_ROOT);
  57. ps.setString(2, OLD_ROOT);
  58. return ps.executeUpdate();
  59. }
  60. }
  61. private static int updatePrefix(Connection conn, String table) throws SQLException {
  62. String sql = "UPDATE " + table
  63. + " SET menu_name = CONCAT(?, SUBSTRING(menu_name, CHAR_LENGTH(?) + 1)), update_time = NOW() "
  64. + "WHERE menu_name LIKE CONCAT(?, '%') AND menu_name <> ?";
  65. try (PreparedStatement ps = conn.prepareStatement(sql)) {
  66. ps.setString(1, NEW_ROOT);
  67. ps.setString(2, OLD_ROOT);
  68. ps.setString(3, OLD_ROOT);
  69. ps.setString(4, OLD_ROOT);
  70. return ps.executeUpdate();
  71. }
  72. }
  73. private static void fixGarbledQdrant(Connection master, PrintWriter report) throws SQLException {
  74. if (!tableExists(master, "sys_menu")) {
  75. return;
  76. }
  77. String sql = "UPDATE sys_menu SET menu_name = ?, update_time = NOW() WHERE menu_id = 29951 "
  78. + "AND (menu_name IS NULL OR menu_name <> ? OR menu_name LIKE '%\\ufffd%')";
  79. try (PreparedStatement ps = master.prepareStatement(sql)) {
  80. ps.setString(1, FIX_QDRANT);
  81. ps.setString(2, FIX_QDRANT);
  82. int n = ps.executeUpdate();
  83. if (n > 0) {
  84. report.println(MASTER_DB + ".sys_menu fix qdrant menu_id=29951 rows=" + n);
  85. }
  86. }
  87. }
  88. private static List<TenantDb> loadTenants(Connection master) throws SQLException {
  89. List<TenantDb> list = new ArrayList<>();
  90. try (Statement st = master.createStatement();
  91. ResultSet rs = st.executeQuery("SELECT id, db_url, db_account, db_pwd FROM tenant_info WHERE status = 1 ORDER BY id")) {
  92. while (rs.next()) {
  93. TenantDb t = parseJdbcUrl(rs.getString("db_url"), rs.getString("db_account"), rs.getString("db_pwd"));
  94. if (t != null) {
  95. list.add(t);
  96. }
  97. }
  98. }
  99. return list;
  100. }
  101. private static TenantDb parseJdbcUrl(String jdbcUrl, String user, String password) {
  102. if (jdbcUrl == null || !jdbcUrl.startsWith("jdbc:mysql://")) {
  103. return null;
  104. }
  105. String body = jdbcUrl.substring("jdbc:mysql://".length());
  106. int slash = body.indexOf('/');
  107. if (slash < 0) {
  108. return null;
  109. }
  110. String hostPort = body.substring(0, slash);
  111. String rest = body.substring(slash + 1);
  112. int q = rest.indexOf('?');
  113. String database = q >= 0 ? rest.substring(0, q) : rest;
  114. TenantDb t = new TenantDb();
  115. int colon = hostPort.indexOf(':');
  116. if (colon >= 0) {
  117. t.host = hostPort.substring(0, colon);
  118. t.port = Integer.parseInt(hostPort.substring(colon + 1));
  119. } else {
  120. t.host = hostPort;
  121. t.port = 3306;
  122. }
  123. t.database = database;
  124. t.user = user != null ? user : USER;
  125. t.password = password != null ? password : PASS;
  126. return t;
  127. }
  128. private static boolean tableExists(Connection conn, String table) throws SQLException {
  129. try (PreparedStatement ps = conn.prepareStatement(
  130. "SELECT 1 FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ? LIMIT 1")) {
  131. ps.setString(1, table);
  132. try (ResultSet rs = ps.executeQuery()) {
  133. return rs.next();
  134. }
  135. }
  136. }
  137. private static Connection open(String database) throws SQLException {
  138. return DriverManager.getConnection(buildUrl(HOST, PORT, database), USER, PASS);
  139. }
  140. private static Connection openDb(TenantDb tenant) throws SQLException {
  141. return DriverManager.getConnection(buildUrl(tenant.host, tenant.port, tenant.database), tenant.user, tenant.password);
  142. }
  143. private static String buildUrl(String host, int port, String database) {
  144. return "jdbc:mysql://" + host + ":" + port + "/" + database
  145. + "?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&allowMultiQueries=true";
  146. }
  147. private static String getenv(String key, String defaultValue) {
  148. String v = System.getenv(key);
  149. return v != null && !v.isEmpty() ? v : defaultValue;
  150. }
  151. private static class TenantDb {
  152. String host;
  153. int port;
  154. String database;
  155. String user;
  156. String password;
  157. }
  158. }