]> nmode's Git Repositories - signal-cli/blob - lib/src/main/java/org/asamk/signal/manager/storage/Database.java
1d69236b4de511395335b05defeff40f81afc40d
[signal-cli] / lib / src / main / java / org / asamk / signal / manager / storage / Database.java
1 package org.asamk.signal.manager.storage;
2
3 import com.zaxxer.hikari.HikariConfig;
4 import com.zaxxer.hikari.HikariDataSource;
5
6 import org.asamk.signal.manager.storage.sendLog.MessageSendLogStore;
7 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory;
9 import org.sqlite.SQLiteConfig;
10
11 import java.io.File;
12 import java.sql.Connection;
13 import java.sql.SQLException;
14
15 public class Database implements AutoCloseable {
16
17 private final static Logger logger = LoggerFactory.getLogger(SignalAccount.class);
18 private static final long DATABASE_VERSION = 1;
19
20 private final HikariDataSource dataSource;
21
22 private Database(final HikariDataSource dataSource) {
23 this.dataSource = dataSource;
24 }
25
26 public static Database init(File databaseFile) throws SQLException {
27 HikariDataSource dataSource = null;
28
29 try {
30 dataSource = getHikariDataSource(databaseFile.getAbsolutePath());
31
32 try (final var connection = dataSource.getConnection()) {
33 final var userVersion = getUserVersion(connection);
34 logger.trace("Current database version: {} Program database version: {}",
35 userVersion,
36 DATABASE_VERSION);
37
38 if (userVersion > DATABASE_VERSION) {
39 logger.error("Database has been updated by a newer signal-cli version");
40 throw new SQLException("Database has been updated by a newer signal-cli version");
41 } else if (userVersion < DATABASE_VERSION) {
42 if (userVersion < 1) {
43 logger.debug("Updating database: Creating message send log tables");
44 MessageSendLogStore.createSql(connection);
45 }
46 setUserVersion(connection, DATABASE_VERSION);
47 }
48
49 final var result = new Database(dataSource);
50 dataSource = null;
51 return result;
52 }
53 } finally {
54 if (dataSource != null) {
55 dataSource.close();
56 }
57 }
58 }
59
60 public Connection getConnection() throws SQLException {
61 return dataSource.getConnection();
62 }
63
64 @Override
65 public void close() throws SQLException {
66 dataSource.close();
67 }
68
69 private static long getUserVersion(final Connection connection) throws SQLException {
70 try (final var statement = connection.createStatement()) {
71 final var resultSet = statement.executeQuery("PRAGMA user_version");
72 return resultSet.getLong(1);
73 }
74 }
75
76 private static void setUserVersion(final Connection connection, long userVersion) throws SQLException {
77 try (final var statement = connection.createStatement()) {
78 statement.executeUpdate("PRAGMA user_version = " + userVersion);
79 }
80 }
81
82 private static HikariDataSource getHikariDataSource(final String databaseFile) {
83 final var sqliteConfig = new SQLiteConfig();
84 sqliteConfig.setBusyTimeout(10_000);
85 sqliteConfig.setTransactionMode(SQLiteConfig.TransactionMode.IMMEDIATE);
86
87 HikariConfig config = new HikariConfig();
88 config.setJdbcUrl("jdbc:sqlite:" + databaseFile);
89 config.setDataSourceProperties(sqliteConfig.toProperties());
90 config.setMinimumIdle(1);
91 config.setConnectionInitSql("PRAGMA foreign_keys=ON");
92 return new HikariDataSource(config);
93 }
94 }