]> gitweb.ps.run Git - l21s-case-study/blob - src/DbMigration.java
db scripts
[l21s-case-study] / src / DbMigration.java
1 import java.io.*;
2 import java.nio.file.*;
3 import java.sql.*;
4 import java.util.*;
5
6 class DbMigration {
7     // constants
8     static final boolean CONFIG_PRINT_DB = false;
9     static final String CSV_SEPARATOR = ",";
10     static final String DB_URL = "jdbc:postgresql:users";
11     static final String SQL_GET_USERS = "SELECT * FROM users;";
12     static final String SQL_UPSERT_USER =
13             """
14               INSERT INTO users VALUES (?, ?, ?, ?, ?)
15               ON CONFLICT (ID)
16               DO UPDATE SET
17                 Mail = EXCLUDED.Mail,
18                 CanRead = EXCLUDED.CanRead,
19                 CanWrite = EXCLUDED.CanWrite,
20                 CanDelete = EXCLUDED.CanDelete
21               ;
22             """;
23
24     // user
25     public record User(int id, String mail, Role role) {
26         public String toString() {
27             return this.id + " " + this.mail + " " + this.role;
28         }
29     }
30
31     // role
32     public record Role(boolean read, boolean write, boolean delete) {
33         static final Role Default = new Role(false, false, false);
34     }
35
36     // csv
37     public static String[][] LoadCSV(String filename) throws IOException {
38         var path = Paths.get(filename);
39         return Files.lines(path)
40                 .skip(1)
41                 .map(line -> line.split(CSV_SEPARATOR))
42                 .toArray(String[][]::new);
43     }
44
45     // db
46     public static void insertUser(PreparedStatement stmt, User user) throws SQLException {
47         stmt.setInt(1, user.id);
48         stmt.setString(2, user.mail);
49         stmt.setBoolean(3, user.role.read);
50         stmt.setBoolean(4, user.role.write);
51         stmt.setBoolean(5, user.role.delete);
52
53         // batching
54         stmt.addBatch();
55     }
56
57     static User[] getUsers(Connection conn) throws SQLException {
58         var users = new ArrayList<User>();
59
60         try (var st = conn.createStatement();
61                 var rs = st.executeQuery(SQL_GET_USERS); ) {
62             while (rs.next()) {
63                 var userId = rs.getInt(1);
64                 var userMail = rs.getString(2);
65                 var userRole = new Role(rs.getBoolean(3), rs.getBoolean(4), rs.getBoolean(5));
66                 users.add(new User(userId, userMail, userRole));
67             }
68         }
69
70         return users.toArray(User[]::new);
71     }
72
73     // main
74     public static void main(String[] args) {
75         // filenames from command line args
76         if (args.length != 2) {
77             System.out.printf("Usage: java src/DbMigrations.java <users.csv> <roles.csv>\n");
78             return;
79         }
80         String filenameUsers = args[0];
81         String filenameRoles = args[1];
82
83         // read csvs
84         String[][] csvUsers;
85         String[][] csvRoles;
86         try {
87             csvUsers = LoadCSV(filenameUsers);
88             csvRoles = LoadCSV(filenameRoles);
89         } catch (IOException e) {
90             System.out.printf("Expection occured while trying to load CSV: %s\n", e);
91             return;
92         }
93
94         // process roles
95         var roles = new HashMap<Integer, Role>();
96         for (var row : csvRoles) {
97             // get id and single role
98             var userId = Integer.parseInt(row[0], 10);
99             var roleStr = row[1];
100
101             // make sure userId is present
102             roles.putIfAbsent(userId, Role.Default);
103
104             // update value by setting one role to true and copying the rest
105             roles.computeIfPresent(
106                     userId,
107                     (id, role) -> {
108                         if (roleStr.equals("read")) return new Role(true, role.write, role.delete);
109                         if (roleStr.equals("write")) return new Role(role.read, true, role.delete);
110                         if (roleStr.equals("delete")) return new Role(role.read, role.write, true);
111                         return role;
112                     });
113         }
114
115         // OPTIONAL: open db connection for reading
116         if (CONFIG_PRINT_DB) {
117             try (var conn = DriverManager.getConnection(DB_URL)) {
118
119                 var users = getUsers(conn);
120                 System.out.println("DB before update:");
121                 for (var user : users) {
122                     System.out.println(user);
123                 }
124
125             } catch (SQLException e) {
126                 System.out.printf("Expection occured while accessing database: %s\n", e);
127                 return;
128             }
129         }
130
131         // open db connection for updating
132         try (var conn = DriverManager.getConnection(DB_URL);
133                 var stmt = conn.prepareStatement(SQL_UPSERT_USER); ) {
134             // batching
135             conn.setAutoCommit(false);
136
137             // update db from csv
138             for (var row : csvUsers) {
139                 var userId = Integer.parseInt(row[0], 10);
140                 var userMail = row[1];
141                 var userRoles = roles.get(userId);
142
143                 User user = new User(userId, userMail, userRoles);
144                 insertUser(stmt, user);
145             }
146
147             // commit batch
148             stmt.executeBatch();
149             conn.commit();
150         } catch (SQLException e) {
151             System.out.printf("Expection occured while accessing database: %s\n", e);
152             return;
153         }
154
155         System.out.println("Updated successfully");
156     }
157 }