ScanLobsterWorkflowColumns.java 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import java.sql.*;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. /** Scan all active tenants for missing company_workflow_lobster.execution_mode */
  5. public class ScanLobsterWorkflowColumns {
  6. private static final String MASTER_HOST = getenv("DB_HOST", "cq-cdb-8fjmemkb.sql.tencentcdb.com");
  7. private static final int MASTER_PORT = Integer.parseInt(getenv("DB_PORT", "27220"));
  8. private static final String MASTER_USER = getenv("DB_USER", "root");
  9. private static final String MASTER_PASSWORD = getenv("DB_PASSWORD", "Ylrz_1q2w3e4r5t6y");
  10. private static final String MASTER_DB = getenv("DB_NAME", "ylrz_saas");
  11. private static final String[] REQUIRED = {
  12. "execution_mode", "enable_content_personalization", "enable_flow_personalization",
  13. "strict_fixed_workflow", "auto_start_instance_on_tag", "template_kind", "source_template_id"
  14. };
  15. public static void main(String[] args) throws Exception {
  16. List<Long> missingTenants = new ArrayList<>();
  17. try (Connection master = open(MASTER_HOST, MASTER_PORT, MASTER_DB, MASTER_USER, MASTER_PASSWORD)) {
  18. List<TenantDb> tenants = loadAllTenants(master);
  19. for (TenantDb tenant : tenants) {
  20. try (Connection conn = open(tenant.host, tenant.port, tenant.database, tenant.user, tenant.password)) {
  21. List<String> missing = new ArrayList<>();
  22. for (String col : REQUIRED) {
  23. if (!columnExists(conn, "company_workflow_lobster", col)) {
  24. missing.add(col);
  25. }
  26. }
  27. if (!missing.isEmpty()) {
  28. missingTenants.add(tenant.id);
  29. System.out.println("[MISSING] tenantId=" + tenant.id + " db=" + tenant.database + " cols=" + missing);
  30. }
  31. } catch (Exception e) {
  32. System.out.println("[ERROR] tenantId=" + tenant.id + " db=" + tenant.database + " " + e.getMessage());
  33. }
  34. }
  35. }
  36. if (missingTenants.isEmpty()) {
  37. System.out.println("[OK] all active tenants have required columns");
  38. } else {
  39. System.out.println("[SUMMARY] tenants needing migration: " + missingTenants);
  40. }
  41. }
  42. private static List<TenantDb> loadAllTenants(Connection master) throws SQLException {
  43. List<TenantDb> list = new ArrayList<>();
  44. String sql = "SELECT id, db_url, db_account, db_pwd FROM tenant_info WHERE status = 1 ORDER BY id";
  45. try (Statement st = master.createStatement(); ResultSet rs = st.executeQuery(sql)) {
  46. while (rs.next()) {
  47. TenantDb t = parseJdbcUrl(rs.getString("db_url"), rs.getString("db_account"), rs.getString("db_pwd"));
  48. t.id = rs.getLong("id");
  49. list.add(t);
  50. }
  51. }
  52. return list;
  53. }
  54. private static boolean columnExists(Connection conn, String table, String column) throws SQLException {
  55. String sql = "SELECT COUNT(*) FROM information_schema.COLUMNS "
  56. + "WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?";
  57. try (PreparedStatement ps = conn.prepareStatement(sql)) {
  58. ps.setString(1, table);
  59. ps.setString(2, column);
  60. try (ResultSet rs = ps.executeQuery()) {
  61. return rs.next() && rs.getInt(1) > 0;
  62. }
  63. }
  64. }
  65. private static TenantDb parseJdbcUrl(String jdbcUrl, String user, String password) {
  66. String body = jdbcUrl.substring("jdbc:mysql://".length());
  67. int slash = body.indexOf('/');
  68. String hostPort = body.substring(0, slash);
  69. String rest = body.substring(slash + 1);
  70. int q = rest.indexOf('?');
  71. String database = q >= 0 ? rest.substring(0, q) : rest;
  72. String host;
  73. int port;
  74. int colon = hostPort.indexOf(':');
  75. if (colon >= 0) {
  76. host = hostPort.substring(0, colon);
  77. port = Integer.parseInt(hostPort.substring(colon + 1));
  78. } else {
  79. host = hostPort;
  80. port = 3306;
  81. }
  82. TenantDb t = new TenantDb();
  83. t.host = host;
  84. t.port = port;
  85. t.database = database;
  86. t.user = user != null ? user : MASTER_USER;
  87. t.password = password != null ? password : MASTER_PASSWORD;
  88. return t;
  89. }
  90. private static Connection open(String host, int port, String database, String user, String password)
  91. throws SQLException {
  92. String url = "jdbc:mysql://" + host + ":" + port + "/" + database
  93. + "?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&allowMultiQueries=true";
  94. return DriverManager.getConnection(url, user, password);
  95. }
  96. private static String getenv(String key, String defaultValue) {
  97. String v = System.getenv(key);
  98. return v != null && !v.isEmpty() ? v : defaultValue;
  99. }
  100. private static final class TenantDb {
  101. long id;
  102. String host;
  103. int port;
  104. String database;
  105. String user;
  106. String password;
  107. }
  108. }