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