import java.io.FileInputStream; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.sql.*; import java.util.*; public class MigrateGen { record Idx(String tbl, String name, String cols, boolean isPk, boolean isUnique) {} record Chk(String tbl, String name, String definition) {} public static void main(String[] args) throws Exception { Properties props = new Properties(); try (FileInputStream in = new FileInputStream(args[0])) { props.load(in); } List tables = new ArrayList<>(List.of( "s_autocode","s_field","s_field_edit","s_field_group","s_field_query","s_field_view", "s_i18n","s_log_audit","s_log_audit_field","s_log_login","s_log_technical", "s_menu","s_module","s_power","s_relation","s_role","s_role_power","s_role_scope","s_user_role")); try (Connection conn = DriverManager.getConnection(props.getProperty("url"), props.getProperty("username"), props.getProperty("password"))) { // 1. indexes + key columns Map> idxByTbl = new HashMap<>(); String idxSql = "SELECT OBJECT_NAME(i.object_id) AS tbl, i.name AS idx, i.is_unique, i.is_primary_key, " + " STUFF((SELECT ',' + c.name FROM sys.index_columns ic " + " JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id " + " WHERE ic.object_id = i.object_id AND ic.index_id = i.index_id " + " ORDER BY ic.key_ordinal FOR XML PATH('')), 1, 1, '') AS cols " + "FROM sys.indexes i WHERE i.object_id IN (SELECT object_id FROM sys.tables WHERE name LIKE 's' + char(95) + '%') AND i.type IN (1,2) AND i.is_disabled = 0"; try (Statement st = conn.createStatement(); ResultSet rs = st.executeQuery(idxSql)) { while (rs.next()) { String tbl = rs.getString("tbl"); idxByTbl.computeIfAbsent(tbl, k -> new ArrayList<>()).add( new Idx(tbl, rs.getString("idx"), rs.getString("cols"), rs.getBoolean("is_primary_key"), rs.getBoolean("is_unique"))); } } // 2. check constraints Map> chkByTbl = new HashMap<>(); String chkSql = "SELECT OBJECT_NAME(parent_object_id) AS tbl, name, definition FROM sys.check_constraints WHERE parent_object_id IN (SELECT object_id FROM sys.tables)"; try (Statement st = conn.createStatement(); ResultSet rs = st.executeQuery(chkSql)) { while (rs.next()) { String tbl = rs.getString("tbl"); chkByTbl.computeIfAbsent(tbl, k -> new ArrayList<>()).add( new Chk(tbl, rs.getString("name"), rs.getString("definition"))); } } // 3. generate script String out = "migrate_identity_to_snowflake.sql"; try (PrintWriter w = new PrintWriter(out, StandardCharsets.UTF_8)) { w.println("-- Migrate s_* tables: b_id identity(1,1) -> plain bigint (snowflake by app layer)"); w.println("-- Generated: " + new Timestamp(System.currentTimeMillis())); for (String tbl : tables) { List idxs = idxByTbl.getOrDefault(tbl, List.of()); List chks = chkByTbl.getOrDefault(tbl, List.of()); List pk = idxs.stream().filter(i -> i.isPk()).toList(); List bIdIdx = idxs.stream().filter(i -> !i.isPk() && i.cols().contains("b_id")).toList(); List bIdChk = chks.stream().filter(c -> c.definition().contains("b_id")).toList(); List bIdUq = bIdIdx.stream().filter(i -> i.isUnique()).toList(); List bIdNc = bIdIdx.stream().filter(i -> !i.isUnique()).toList(); w.println(); w.println("-- ===== " + tbl + " ====="); if (pk.isEmpty()) { w.println("-- [SKIP] no PK found"); continue; } w.println("ALTER TABLE [dbo].[" + tbl + "] DROP CONSTRAINT [" + pk.get(0).name() + "];"); for (Chk c : bIdChk) w.println("ALTER TABLE [dbo].[" + tbl + "] DROP CONSTRAINT [" + c.name() + "];"); for (Idx i : bIdUq) w.println("ALTER TABLE [dbo].[" + tbl + "] DROP CONSTRAINT [" + i.name() + "];"); for (Idx i : bIdNc) w.println("DROP INDEX [" + i.name() + "] ON [dbo].[" + tbl + "];"); w.println("ALTER TABLE [dbo].[" + tbl + "] ADD [b_id_new] bigint NULL;"); w.println("UPDATE [dbo].[" + tbl + "] SET [b_id_new] = [b_id];"); w.println("ALTER TABLE [dbo].[" + tbl + "] ALTER COLUMN [b_id_new] bigint NOT NULL;"); w.println("ALTER TABLE [dbo].[" + tbl + "] DROP COLUMN [b_id];"); w.println("GO"); w.println("EXEC sp_rename 'dbo." + tbl + ".b_id_new', 'b_id', 'COLUMN';"); w.println("GO"); w.println("ALTER TABLE [dbo].[" + tbl + "] ADD CONSTRAINT [" + pk.get(0).name() + "] PRIMARY KEY ([b_id]);"); for (Chk c : bIdChk) w.println("ALTER TABLE [dbo].[" + tbl + "] ADD CONSTRAINT [" + c.name() + "] CHECK " + c.definition() + ";"); for (Idx i : bIdUq) w.println("ALTER TABLE [dbo].[" + tbl + "] ADD CONSTRAINT [" + i.name() + "] UNIQUE (" + i.cols() + ");"); for (Idx i : bIdNc) w.println("CREATE INDEX [" + i.name() + "] ON [dbo].[" + tbl + "] (" + i.cols() + ");"); w.println("GO"); } w.println("-- End of migration"); } System.out.println("Script written: " + out); // print preview: first 60 lines try (java.io.BufferedReader r = new java.io.BufferedReader(new java.io.InputStreamReader( new FileInputStream(out), StandardCharsets.UTF_8))) { String line; int n = 0; while ((line = r.readLine()) != null && n < 60) { System.out.println(line); n++; } System.out.println("... (" + n + " lines shown of total)"); } } } }