import java.nio.file.*;
|
import java.sql.*;
|
import java.util.*;
|
import java.util.regex.*;
|
|
/**
|
* Verifies that the create-table statements {@code MerchantOnboardingSchemaInitializer} carries are
|
* executable on MySQL and produce exactly the columns V144 produces.
|
*
|
* <p>Worth checking separately: the initializer swallows DDL failures on purpose (a busy table must not
|
* stop the service), so a typo there would keep the tables missing after a restart — silently, with
|
* the very same symptom this session started from.
|
*
|
* <p>Runs in its own throwaway schema and drops only that schema, which it created itself; the
|
* development and test databases are never written to.
|
*
|
* usage: java -cp <mysql-connector-j.jar>:. VerifyInitializerDdl.java [serverJdbcUrl] [initializerSource]
|
*/
|
public class VerifyInitializerDdl {
|
private static final String PROBE_SCHEMA = "talent_card_schema_probe";
|
|
public static void main(String[] args) throws Exception {
|
String serverUrl = args.length > 0
|
? args[0]
|
: "jdbc:mysql://127.0.0.1:8134/talent_card?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false";
|
String source = Path.of(args.length > 1
|
? args[1]
|
: "../../talent-card-server/src/main/java/com/talentcard/server/business/merchant/MerchantOnboardingSchemaInitializer.java").toAbsolutePath().normalize().toString();
|
|
Map<String, String> ddl = textBlocksWithCreateTable(Files.readString(Path.of(source)));
|
System.out.println("initializer carries " + ddl.size() + " create-table statements: " + ddl.keySet());
|
|
String probeUrl = serverUrl.replaceFirst("/[^/?]+\\?", "/" + PROBE_SCHEMA + "?");
|
try (Connection connection = DriverManager.getConnection(serverUrl, "root", "123456")) {
|
try (Statement statement = connection.createStatement()) {
|
statement.executeUpdate("create database if not exists " + PROBE_SCHEMA + " default charset utf8mb4");
|
}
|
}
|
|
boolean mismatch = false;
|
try (Connection probe = DriverManager.getConnection(probeUrl, "root", "123456");
|
Connection development = DriverManager.getConnection(serverUrl, "root", "123456")) {
|
for (Map.Entry<String, String> table : ddl.entrySet()) {
|
try (Statement statement = probe.createStatement()) {
|
statement.execute(table.getValue());
|
}
|
Set<String> fromInitializer = columns(probe, PROBE_SCHEMA, table.getKey());
|
Set<String> fromMigration = columns(development, "talent_card", table.getKey());
|
boolean same = fromInitializer.equals(fromMigration);
|
mismatch |= !same;
|
System.out.println((same ? "ok " : "DIFF ") + table.getKey() + " -> initializer=" + fromInitializer);
|
if (!same) System.out.println(" migration=" + fromMigration);
|
}
|
} finally {
|
try (Connection connection = DriverManager.getConnection(serverUrl, "root", "123456");
|
Statement statement = connection.createStatement()) {
|
statement.executeUpdate("drop database " + PROBE_SCHEMA);
|
}
|
System.out.println("dropped the probe schema " + PROBE_SCHEMA + "; talent_card and talent_card_test untouched");
|
}
|
System.out.println(mismatch ? "MISMATCH: the initializer's DDL does not match the migration" : "MATCH: the initializer's DDL is executable and identical to the migration's");
|
System.exit(mismatch ? 1 : 0);
|
}
|
|
/** name:type pairs, so a wrong type or length shows up, not just a wrong column name. */
|
private static Set<String> columns(Connection connection, String schema, String table) throws SQLException {
|
try (PreparedStatement statement = connection.prepareStatement(
|
"select column_name, column_type from information_schema.columns where table_schema=? and table_name=? order by ordinal_position")) {
|
statement.setString(1, schema);
|
statement.setString(2, table);
|
Set<String> columns = new LinkedHashSet<>();
|
try (ResultSet rows = statement.executeQuery()) {
|
while (rows.next()) columns.add(rows.getString(1) + ":" + rows.getString(2));
|
}
|
return columns;
|
}
|
}
|
|
private static Map<String, String> textBlocksWithCreateTable(String source) {
|
Map<String, String> statements = new LinkedHashMap<>();
|
Matcher blocks = Pattern.compile("\"\"\"\\r?\\n(.*?)\"\"\"", Pattern.DOTALL).matcher(source);
|
while (blocks.find()) {
|
String block = blocks.group(1);
|
Matcher name = Pattern.compile("(?i)create table if not exists ([a-z_]+)").matcher(block);
|
if (name.find()) statements.put(name.group(1), block);
|
}
|
if (statements.isEmpty()) throw new IllegalStateException("no create-table text blocks found in " + source);
|
return statements;
|
}
|
}
|