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