Files

322 lines
17 KiB
Java
Raw Permalink Normal View History

package scripts.qa;
import java.io.File;
import java.nio.file.Files;
import java.sql.*;
import java.util.*;
public class IntegratedQaBootstrapAndValidation {
private static final String TARGET_DB = "railwaysystem_integrated_qa_20260916";
private static final String TEMPLATE_DB = "training";
private static final String MAINTENANCE_DB_URL = "jdbc:kingbase8://127.0.0.1:4321/kingbase?useUnicode=true&characterEncoding=utf8";
private static final String QA_DB_URL = "jdbc:kingbase8://127.0.0.1:4321/" + TARGET_DB + "?useUnicode=true&characterEncoding=utf8&currentSchema=public,sys_catalog";
private static final String USER = "kingbase";
public static void main(String[] args) {
String password = resolveDbPassword();
try {
Class.forName("com.kingbase8.Driver");
// 1. Re-create QA Database from template training
System.out.println("=== 1. DATABASE PROVISIONING ===");
try (Connection conn = DriverManager.getConnection(MAINTENANCE_DB_URL, USER, password)) {
try (Statement st = conn.createStatement()) {
// Disconnect any active connections to TARGET_DB
st.execute("SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '" + TARGET_DB + "' AND pid <> pg_backend_pid()");
st.execute("DROP DATABASE IF EXISTS " + TARGET_DB);
System.out.println("Dropped existing " + TARGET_DB);
st.execute("CREATE DATABASE " + TARGET_DB + " TEMPLATE " + TEMPLATE_DB);
System.out.println("Created " + TARGET_DB + " from TEMPLATE " + TEMPLATE_DB + " successfully.");
}
}
// 2. DB Identity Gate & Clean Business State
System.out.println("\n=== 2. DB IDENTITY GATE & CLEAN BUSINESS STATE ===");
Map<String, Integer> initialBusinessCounts = new LinkedHashMap<>();
try (Connection conn = DriverManager.getConnection(QA_DB_URL, USER, password)) {
try (Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT current_database(), current_user, inet_server_addr(), inet_server_port()")) {
if (rs.next()) {
System.out.println("CURRENT_DATABASE: " + rs.getString(1));
System.out.println("CURRENT_USER: " + rs.getString(2));
System.out.println("SERVER_ADDR: " + rs.getString(3));
System.out.println("SERVER_PORT: " + rs.getString(4));
System.out.println("DB_ENVIRONMENT: ISOLATED_QA");
}
}
// Drop legacy backup tables
try (Statement st = conn.createStatement()) {
List<String> bakTables = new ArrayList<>();
try (ResultSet rs = st.executeQuery("SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_name LIKE 'bak_v1_%'")) {
while (rs.next()) bakTables.add(rs.getString(1));
}
for (String bak : bakTables) {
st.execute("DROP TABLE IF EXISTS " + bak + " CASCADE");
}
System.out.println("Dropped " + bakTables.size() + " legacy backup tables (bak_v1_*).");
}
// Truncate all business demo tables in dependency order
String[] businessTables = new String[]{
"train_student_checkin",
"train_class_report",
"train_student_score",
"train_student_portrait",
"train_study_duration",
"train_accommodation",
"train_external_operation",
"train_external_resource_mapping",
"train_dorm_auth",
"train_lesson",
"train_plan_course",
"train_enrollment",
"train_score_item",
"train_course_resource",
"train_resource",
"train_course",
"train_class_plan",
"train_dormitory_info",
"train_classroom_info",
"train_training_site",
"train_electronic_board",
"train_student",
"train_teacher",
"sys_logininfor",
"sys_oper_log",
"sys_job_log",
"gen_table_column",
"gen_table",
"app_config"
};
try (Statement st = conn.createStatement()) {
for (String table : businessTables) {
try {
st.execute("TRUNCATE TABLE " + table + " CASCADE");
} catch (Exception e) {
try {
st.execute("DELETE FROM " + table);
} catch (Exception ex) {
System.err.println("Clean table " + table + " warning: " + ex.getMessage());
}
}
}
System.out.println("Business tables truncated successfully.");
}
// Clean sys_user to keep only system accounts (admin, ry)
try (Statement st = conn.createStatement()) {
st.execute("DELETE FROM sys_user_role WHERE user_id NOT IN (SELECT user_id FROM sys_user WHERE user_name IN ('admin', 'ry'))");
st.execute("DELETE FROM sys_user_post WHERE user_id NOT IN (SELECT user_id FROM sys_user WHERE user_name IN ('admin', 'ry'))");
st.execute("DELETE FROM sys_user WHERE user_name NOT IN ('admin', 'ry')");
System.out.println("sys_user cleaned: only admin/ry retained.");
}
// Verify and record initial business counts
System.out.println("\n--- INITIAL BUSINESS DATA COUNTS ---");
try (Statement st = conn.createStatement()) {
for (String table : businessTables) {
try (ResultSet rs = st.executeQuery("SELECT count(*) FROM " + table)) {
if (rs.next()) {
int c = rs.getInt(1);
initialBusinessCounts.put(table, c);
System.out.println(String.format("%-35s : %d", table, c));
}
} catch (Exception e) {
System.out.println(String.format("%-35s : TABLE_NOT_EXIST_YET", table));
}
}
}
}
// 3. Migration First Run & Second Run
System.out.println("\n=== 3. MIGRATION EXECUTION & IDEMPOTENCY ===");
String[] migrationFiles = new String[]{
"RuoYi-Vue/sql/system/kingbase/006_accommodation_history_constraint.sql",
"RuoYi-Vue/sql/system/kingbase/008_external_resource_operation.sql",
"RuoYi-Vue/sql/system/kingbase/009_dorm_authorization_orchestration.sql",
"RuoYi-Vue/sql/system/kingbase/010_dms_access_management_permissions.sql"
};
// FIRST RUN
System.out.println("--- FIRST RUN ---");
boolean firstRunAllPass = true;
try (Connection conn = DriverManager.getConnection(QA_DB_URL, USER, password)) {
for (String path : migrationFiles) {
boolean pass = executeSqlScript(conn, path);
System.out.println("Migration " + new File(path).getName() + " FIRST_RUN: " + (pass ? "PASS" : "FAIL"));
if (!pass) firstRunAllPass = false;
}
}
// SECOND RUN (IDEMPOTENCY TEST)
System.out.println("\n--- SECOND RUN (IDEMPOTENCY TEST) ---");
boolean secondRunAllPass = true;
try (Connection conn = DriverManager.getConnection(QA_DB_URL, USER, password)) {
for (String path : migrationFiles) {
boolean pass = executeSqlScript(conn, path);
System.out.println("Migration " + new File(path).getName() + " SECOND_RUN: " + (pass ? "PASS" : "FAIL"));
if (!pass) secondRunAllPass = false;
}
}
System.out.println("MIGRATION_FIRST_RUN = " + (firstRunAllPass ? "PASS" : "FAIL"));
System.out.println("MIGRATION_SECOND_RUN = " + (secondRunAllPass ? "PASS" : "FAIL"));
System.out.println("MIGRATION_IDEMPOTENT = " + (firstRunAllPass && secondRunAllPass ? "PASS" : "FAIL"));
// 4. Schema Validation
System.out.println("\n=== 4. SCHEMA VALIDATION ===");
try (Connection conn = DriverManager.getConnection(QA_DB_URL, USER, password)) {
// Check required tables
String[] requiredTables = new String[]{
"train_class_plan",
"train_course",
"train_enrollment",
"train_lesson",
"train_student_checkin",
"train_accommodation",
"train_dorm_auth",
"train_external_resource_mapping",
"train_external_operation"
};
for (String t : requiredTables) {
try (Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = '" + t + "'")) {
boolean ok = rs.next();
System.out.println("TABLE " + t + " EXISTS: " + (ok ? "YES" : "NO"));
}
}
// Check constraints & indexes
checkIndexOrConstraint(conn, "train_accommodation", "uq_accommodation_enroll_active", "Active accommodation partial unique index");
checkIndexOrConstraint(conn, "train_external_resource_mapping", "uq_ext_res_map_active_room", "Active room mapping partial unique index");
checkIndexOrConstraint(conn, "train_external_resource_mapping", "uq_ext_res_map_active_ext_res", "Active external res partial unique index");
checkIndexOrConstraint(conn, "train_external_operation", "uq_ext_op_idempotency", "External op idempotency unique index");
checkIndexOrConstraint(conn, "train_dorm_auth", "idx_dorm_auth_status", "Dorm auth status index");
checkIndexOrConstraint(conn, "train_dorm_auth", "idx_dorm_auth_latest_op", "Dorm auth latest op index");
// Check RBAC roles
System.out.println("\n--- RBAC ROLES CHECK ---");
try (Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT role_id, role_name, role_key, status FROM sys_role WHERE role_key IN ('admin', 'train_admin', 'train_teacher', 'train_student')")) {
while (rs.next()) {
System.out.println("ROLE: " + rs.getString("role_key") + " (" + rs.getString("role_name") + ") status=" + rs.getString("status"));
}
}
// Check DMS Permissions in sys_menu
System.out.println("\n--- DMS PERMISSIONS IN SYS_MENU ---");
try (Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT menu_id, menu_name, perms FROM sys_menu WHERE perms IN ('train:access:query', 'train:access:manage', 'train:access:reconcile')")) {
while (rs.next()) {
System.out.println("MENU: " + rs.getString("perms") + " - " + rs.getString("menu_name"));
}
}
// Check Orphan counts
System.out.println("\n--- ORPHAN COUNTS CHECK ---");
int totalOrphans = 0;
String[] orphanChecks = new String[]{
"SELECT count(*) FROM train_enrollment e WHERE NOT EXISTS (SELECT 1 FROM train_student s WHERE s.s_id = e.student_id)",
"SELECT count(*) FROM train_enrollment e WHERE NOT EXISTS (SELECT 1 FROM train_class_plan p WHERE p.plan_id = e.plan_id)",
"SELECT count(*) FROM train_lesson l WHERE NOT EXISTS (SELECT 1 FROM train_plan_course pc WHERE pc.plan_course_id = l.plan_course_id)",
"SELECT count(*) FROM train_accommodation a WHERE NOT EXISTS (SELECT 1 FROM train_enrollment e WHERE e.enrollment_id = a.enrollment_id)",
"SELECT count(*) FROM train_student_checkin c WHERE NOT EXISTS (SELECT 1 FROM train_enrollment e WHERE e.enrollment_id = c.enrollment_id)",
"SELECT count(*) FROM train_dorm_auth d WHERE NOT EXISTS (SELECT 1 FROM train_accommodation a WHERE a.accommodation_id = d.accommodation_id)",
"SELECT count(*) FROM train_external_operation o WHERE NOT EXISTS (SELECT 1 FROM train_dorm_auth d WHERE d.auth_id = o.door_auth_id)"
};
for (String q : orphanChecks) {
try (Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(q)) {
if (rs.next()) {
totalOrphans += rs.getInt(1);
}
}
}
System.out.println("ORPHAN_COUNT = " + totalOrphans);
}
} catch (Exception e) {
System.err.println("Execution failed: " + e.getMessage());
e.printStackTrace();
System.exit(1);
}
}
private static boolean executeSqlScript(Connection conn, String path) {
try {
File f = new File(path);
if (!f.exists()) {
System.err.println("Script not found: " + path);
return false;
}
String content = new String(Files.readAllBytes(f.toPath()));
// For DO $$ ... $$; block
if (content.contains("DO $$")) {
try (Statement st = conn.createStatement()) {
st.execute(content);
}
return true;
}
// Split by semicolon, accounting for BEGIN/COMMIT
String[] stmts = content.split(";");
try (Statement st = conn.createStatement()) {
for (String s : stmts) {
String trimmed = s.trim();
if (!trimmed.isEmpty() && !trimmed.startsWith("--")) {
st.execute(trimmed);
}
}
}
return true;
} catch (Exception e) {
System.err.println("Script execution failed on " + path + ": " + e.getMessage());
return false;
}
}
private static void checkIndexOrConstraint(Connection conn, String table, String name, String desc) {
try (Statement st = conn.createStatement()) {
boolean found = false;
// check constraint
try (ResultSet rs = st.executeQuery("SELECT 1 FROM pg_constraint c JOIN pg_class t ON c.conrelid = t.oid WHERE t.relname = '" + table + "' AND c.conname = '" + name + "'")) {
if (rs.next()) found = true;
}
if (!found) {
// check index
try (ResultSet rs = st.executeQuery("SELECT 1 FROM pg_class c JOIN pg_index i ON c.oid = i.indexrelid JOIN pg_class t ON i.indrelid = t.oid WHERE t.relname = '" + table + "' AND c.relname = '" + name + "'")) {
if (rs.next()) found = true;
}
}
System.out.println("CONSTRAINT/INDEX " + name + " (" + desc + ") ON " + table + ": " + (found ? "PASS" : "FAIL"));
} catch (Exception e) {
System.out.println("CONSTRAINT/INDEX " + name + " ERROR: " + e.getMessage());
}
}
private static String resolveDbPassword() {
String env = System.getenv("DB_PASSWORD");
if (env != null && !env.isEmpty()) return env;
try {
File yml = new File("RuoYi-Vue/ruoyi-admin/src/main/resources/application-druid.yml");
if (!yml.exists()) {
yml = new File("../RuoYi-Vue/ruoyi-admin/src/main/resources/application-druid.yml");
}
if (yml.exists()) {
for (String line : Files.readAllLines(yml.toPath())) {
if (line.trim().startsWith("password:")) {
return line.trim().substring("password:".length()).trim();
}
}
}
} catch (Exception ignored) {}
return "123456";
}
}