1 package org
.asamk
.signal
.manager
.storage
;
3 import com
.zaxxer
.hikari
.HikariDataSource
;
5 import org
.asamk
.signal
.manager
.storage
.groups
.GroupStore
;
6 import org
.asamk
.signal
.manager
.storage
.identities
.IdentityKeyStore
;
7 import org
.asamk
.signal
.manager
.storage
.prekeys
.PreKeyStore
;
8 import org
.asamk
.signal
.manager
.storage
.prekeys
.SignedPreKeyStore
;
9 import org
.asamk
.signal
.manager
.storage
.recipients
.RecipientStore
;
10 import org
.asamk
.signal
.manager
.storage
.sendLog
.MessageSendLogStore
;
11 import org
.asamk
.signal
.manager
.storage
.senderKeys
.SenderKeyRecordStore
;
12 import org
.asamk
.signal
.manager
.storage
.senderKeys
.SenderKeySharedStore
;
13 import org
.asamk
.signal
.manager
.storage
.sessions
.SessionStore
;
14 import org
.asamk
.signal
.manager
.storage
.stickers
.StickerStore
;
15 import org
.slf4j
.Logger
;
16 import org
.slf4j
.LoggerFactory
;
19 import java
.sql
.Connection
;
20 import java
.sql
.SQLException
;
22 public class AccountDatabase
extends Database
{
24 private final static Logger logger
= LoggerFactory
.getLogger(AccountDatabase
.class);
25 private static final long DATABASE_VERSION
= 9;
27 private AccountDatabase(final HikariDataSource dataSource
) {
28 super(logger
, DATABASE_VERSION
, dataSource
);
31 public static AccountDatabase
init(File databaseFile
) throws SQLException
{
32 return initDatabase(databaseFile
, AccountDatabase
::new);
36 protected void createDatabase(final Connection connection
) throws SQLException
{
37 RecipientStore
.createSql(connection
);
38 MessageSendLogStore
.createSql(connection
);
39 StickerStore
.createSql(connection
);
40 PreKeyStore
.createSql(connection
);
41 SignedPreKeyStore
.createSql(connection
);
42 GroupStore
.createSql(connection
);
43 SessionStore
.createSql(connection
);
44 IdentityKeyStore
.createSql(connection
);
45 SenderKeyRecordStore
.createSql(connection
);
46 SenderKeySharedStore
.createSql(connection
);
50 protected void upgradeDatabase(final Connection connection
, final long oldVersion
) throws SQLException
{
52 logger
.debug("Updating database: Creating recipient table");
53 try (final var statement
= connection
.createStatement()) {
54 statement
.executeUpdate("""
55 CREATE TABLE recipient (
56 _id INTEGER PRIMARY KEY AUTOINCREMENT,
60 profile_key_credential BLOB,
66 expiration_time INTEGER NOT NULL DEFAULT 0,
67 blocked BOOLEAN NOT NULL DEFAULT FALSE,
68 archived BOOLEAN NOT NULL DEFAULT FALSE,
69 profile_sharing BOOLEAN NOT NULL DEFAULT FALSE,
71 profile_last_update_timestamp INTEGER NOT NULL DEFAULT 0,
72 profile_given_name TEXT,
73 profile_family_name TEXT,
75 profile_about_emoji TEXT,
76 profile_avatar_url_path TEXT,
77 profile_mobile_coin_address BLOB,
78 profile_unidentified_access_mode TEXT,
79 profile_capabilities TEXT
85 logger
.debug("Updating database: Creating sticker table");
86 try (final var statement
= connection
.createStatement()) {
87 statement
.executeUpdate("""
88 CREATE TABLE sticker (
89 _id INTEGER PRIMARY KEY,
90 pack_id BLOB UNIQUE NOT NULL,
91 pack_key BLOB NOT NULL,
92 installed BOOLEAN NOT NULL DEFAULT FALSE
98 logger
.debug("Updating database: Creating pre key tables");
99 try (final var statement
= connection
.createStatement()) {
100 statement
.executeUpdate("""
101 CREATE TABLE signed_pre_key (
102 _id INTEGER PRIMARY KEY,
103 account_id_type INTEGER NOT NULL,
104 key_id INTEGER NOT NULL,
105 public_key BLOB NOT NULL,
106 private_key BLOB NOT NULL,
107 signature BLOB NOT NULL,
108 timestamp INTEGER DEFAULT 0,
109 UNIQUE(account_id_type, key_id)
111 CREATE TABLE pre_key (
112 _id INTEGER PRIMARY KEY,
113 account_id_type INTEGER NOT NULL,
114 key_id INTEGER NOT NULL,
115 public_key BLOB NOT NULL,
116 private_key BLOB NOT NULL,
117 UNIQUE(account_id_type, key_id)
122 if (oldVersion
< 5) {
123 logger
.debug("Updating database: Creating group tables");
124 try (final var statement
= connection
.createStatement()) {
125 statement
.executeUpdate("""
126 CREATE TABLE group_v2 (
127 _id INTEGER PRIMARY KEY,
128 group_id BLOB UNIQUE NOT NULL,
129 master_key BLOB NOT NULL,
131 distribution_id BLOB UNIQUE NOT NULL,
132 blocked BOOLEAN NOT NULL DEFAULT FALSE,
133 permission_denied BOOLEAN NOT NULL DEFAULT FALSE
135 CREATE TABLE group_v1 (
136 _id INTEGER PRIMARY KEY,
137 group_id BLOB UNIQUE NOT NULL,
138 group_id_v2 BLOB UNIQUE,
141 expiration_time INTEGER NOT NULL DEFAULT 0,
142 blocked BOOLEAN NOT NULL DEFAULT FALSE,
143 archived BOOLEAN NOT NULL DEFAULT FALSE
145 CREATE TABLE group_v1_member (
146 _id INTEGER PRIMARY KEY,
147 group_id INTEGER NOT NULL REFERENCES group_v1 (_id) ON DELETE CASCADE,
148 recipient_id INTEGER NOT NULL REFERENCES recipient (_id) ON DELETE CASCADE,
149 UNIQUE(group_id, recipient_id)
154 if (oldVersion
< 6) {
155 logger
.debug("Updating database: Creating session tables");
156 try (final var statement
= connection
.createStatement()) {
157 statement
.executeUpdate("""
158 CREATE TABLE session (
159 _id INTEGER PRIMARY KEY,
160 account_id_type INTEGER NOT NULL,
161 recipient_id INTEGER NOT NULL REFERENCES recipient (_id) ON DELETE CASCADE,
162 device_id INTEGER NOT NULL,
163 record BLOB NOT NULL,
164 UNIQUE(account_id_type, recipient_id, device_id)
169 if (oldVersion
< 7) {
170 logger
.debug("Updating database: Creating identity table");
171 try (final var statement
= connection
.createStatement()) {
172 statement
.executeUpdate("""
173 CREATE TABLE identity (
174 _id INTEGER PRIMARY KEY,
175 recipient_id INTEGER UNIQUE NOT NULL REFERENCES recipient (_id) ON DELETE CASCADE,
176 identity_key BLOB NOT NULL,
177 added_timestamp INTEGER NOT NULL,
178 trust_level INTEGER NOT NULL
183 if (oldVersion
< 8) {
184 logger
.debug("Updating database: Creating sender key tables");
185 try (final var statement
= connection
.createStatement()) {
186 statement
.executeUpdate("""
187 CREATE TABLE sender_key (
188 _id INTEGER PRIMARY KEY,
189 recipient_id INTEGER NOT NULL REFERENCES recipient (_id) ON DELETE CASCADE,
190 device_id INTEGER NOT NULL,
191 distribution_id BLOB NOT NULL,
192 record BLOB NOT NULL,
193 created_timestamp INTEGER NOT NULL,
194 UNIQUE(recipient_id, device_id, distribution_id)
196 CREATE TABLE sender_key_shared (
197 _id INTEGER PRIMARY KEY,
198 recipient_id INTEGER NOT NULL REFERENCES recipient (_id) ON DELETE CASCADE,
199 device_id INTEGER NOT NULL,
200 distribution_id BLOB NOT NULL,
201 timestamp INTEGER NOT NULL,
202 UNIQUE(recipient_id, device_id, distribution_id)
207 if (oldVersion
< 9) {
208 logger
.debug("Updating database: Adding urgent field");
209 try (final var statement
= connection
.createStatement()) {
210 statement
.executeUpdate("""
211 ALTER TABLE message_send_log_content ADD COLUMN urgent BOOLEAN NOT NULL DEFAULT TRUE;