core: support postgres backend (#5403)

* postgres: modules structure (#5401)

* postgres: schema, field conversions (#5430)

* postgres: rework chat list pagination query (#5441)

* prepare cabal for merge

* restore cabal changes

* simplexmq

* postgres: implementation wip (tests don't pass) (#5481)

* restore ios file

* postgres: implementation - tests pass (#5487)

* refactor DB options

* refactor

* line

* style

* style

* refactor

* $

* update simplexmq

* constraintError

* handleDBErrors

* fix

* remove param

* Ok

* case

* case

* case

* comment

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
This commit is contained in:
spaced4ndy
2025-01-10 15:27:29 +04:00
committed by GitHub
parent 13fae855fc
commit e05a35e26e
187 changed files with 2847 additions and 1291 deletions
+255
View File
@@ -0,0 +1,255 @@
{-# LANGUAGE NamedFieldPuns #-}
module Simplex.Chat.Store.SQLite.Migrations (migrations) where
import Data.List (sortOn)
import Database.SQLite.Simple (Query (..))
import Simplex.Chat.Store.SQLite.Migrations.M20220101_initial
import Simplex.Chat.Store.SQLite.Migrations.M20220122_v1_1
import Simplex.Chat.Store.SQLite.Migrations.M20220205_chat_item_status
import Simplex.Chat.Store.SQLite.Migrations.M20220210_deduplicate_contact_requests
import Simplex.Chat.Store.SQLite.Migrations.M20220224_messages_fks
import Simplex.Chat.Store.SQLite.Migrations.M20220301_smp_servers
import Simplex.Chat.Store.SQLite.Migrations.M20220302_profile_images
import Simplex.Chat.Store.SQLite.Migrations.M20220304_msg_quotes
import Simplex.Chat.Store.SQLite.Migrations.M20220321_chat_item_edited
import Simplex.Chat.Store.SQLite.Migrations.M20220404_files_status_fields
import Simplex.Chat.Store.SQLite.Migrations.M20220514_profiles_user_id
import Simplex.Chat.Store.SQLite.Migrations.M20220626_auto_reply
import Simplex.Chat.Store.SQLite.Migrations.M20220702_calls
import Simplex.Chat.Store.SQLite.Migrations.M20220715_groups_chat_item_id
import Simplex.Chat.Store.SQLite.Migrations.M20220811_chat_items_indices
import Simplex.Chat.Store.SQLite.Migrations.M20220812_incognito_profiles
import Simplex.Chat.Store.SQLite.Migrations.M20220818_chat_notifications
import Simplex.Chat.Store.SQLite.Migrations.M20220822_groups_host_conn_custom_user_profile_id
import Simplex.Chat.Store.SQLite.Migrations.M20220823_delete_broken_group_event_chat_items
import Simplex.Chat.Store.SQLite.Migrations.M20220824_profiles_local_alias
import Simplex.Chat.Store.SQLite.Migrations.M20220909_commands
import Simplex.Chat.Store.SQLite.Migrations.M20220926_connection_alias
import Simplex.Chat.Store.SQLite.Migrations.M20220928_settings
import Simplex.Chat.Store.SQLite.Migrations.M20221001_shared_msg_id_indices
import Simplex.Chat.Store.SQLite.Migrations.M20221003_delete_broken_integrity_error_chat_items
import Simplex.Chat.Store.SQLite.Migrations.M20221004_idx_msg_deliveries_message_id
import Simplex.Chat.Store.SQLite.Migrations.M20221011_user_contact_links_group_id
import Simplex.Chat.Store.SQLite.Migrations.M20221012_inline_files
import Simplex.Chat.Store.SQLite.Migrations.M20221019_unread_chat
import Simplex.Chat.Store.SQLite.Migrations.M20221021_auto_accept__group_links
import Simplex.Chat.Store.SQLite.Migrations.M20221024_contact_used
import Simplex.Chat.Store.SQLite.Migrations.M20221025_chat_settings
import Simplex.Chat.Store.SQLite.Migrations.M20221029_group_link_id
import Simplex.Chat.Store.SQLite.Migrations.M20221112_server_password
import Simplex.Chat.Store.SQLite.Migrations.M20221115_server_cfg
import Simplex.Chat.Store.SQLite.Migrations.M20221129_delete_group_feature_items
import Simplex.Chat.Store.SQLite.Migrations.M20221130_delete_item_deleted
import Simplex.Chat.Store.SQLite.Migrations.M20221209_verified_connection
import Simplex.Chat.Store.SQLite.Migrations.M20221210_idxs
import Simplex.Chat.Store.SQLite.Migrations.M20221211_group_description
import Simplex.Chat.Store.SQLite.Migrations.M20221212_chat_items_timed
import Simplex.Chat.Store.SQLite.Migrations.M20221214_live_message
import Simplex.Chat.Store.SQLite.Migrations.M20221222_chat_ts
import Simplex.Chat.Store.SQLite.Migrations.M20221223_idx_chat_items_item_status
import Simplex.Chat.Store.SQLite.Migrations.M20221230_idxs
import Simplex.Chat.Store.SQLite.Migrations.M20230107_connections_auth_err_counter
import Simplex.Chat.Store.SQLite.Migrations.M20230111_users_agent_user_id
import Simplex.Chat.Store.SQLite.Migrations.M20230117_fkey_indexes
import Simplex.Chat.Store.SQLite.Migrations.M20230118_recreate_smp_servers
import Simplex.Chat.Store.SQLite.Migrations.M20230129_drop_chat_items_group_idx
import Simplex.Chat.Store.SQLite.Migrations.M20230206_item_deleted_by_group_member_id
import Simplex.Chat.Store.SQLite.Migrations.M20230303_group_link_role
import Simplex.Chat.Store.SQLite.Migrations.M20230317_hidden_profiles
import Simplex.Chat.Store.SQLite.Migrations.M20230318_file_description
import Simplex.Chat.Store.SQLite.Migrations.M20230321_agent_file_deleted
import Simplex.Chat.Store.SQLite.Migrations.M20230328_files_protocol
import Simplex.Chat.Store.SQLite.Migrations.M20230402_protocol_servers
import Simplex.Chat.Store.SQLite.Migrations.M20230411_extra_xftp_file_descriptions
import Simplex.Chat.Store.SQLite.Migrations.M20230420_rcv_files_to_receive
import Simplex.Chat.Store.SQLite.Migrations.M20230422_profile_contact_links
import Simplex.Chat.Store.SQLite.Migrations.M20230504_recreate_msg_delivery_events_cleanup_messages
import Simplex.Chat.Store.SQLite.Migrations.M20230505_chat_item_versions
import Simplex.Chat.Store.SQLite.Migrations.M20230511_reactions
import Simplex.Chat.Store.SQLite.Migrations.M20230519_item_deleted_ts
import Simplex.Chat.Store.SQLite.Migrations.M20230526_indexes
import Simplex.Chat.Store.SQLite.Migrations.M20230529_indexes
import Simplex.Chat.Store.SQLite.Migrations.M20230608_deleted_contacts
import Simplex.Chat.Store.SQLite.Migrations.M20230618_favorite_chats
import Simplex.Chat.Store.SQLite.Migrations.M20230621_chat_item_moderations
import Simplex.Chat.Store.SQLite.Migrations.M20230705_delivery_receipts
import Simplex.Chat.Store.SQLite.Migrations.M20230721_group_snd_item_statuses
import Simplex.Chat.Store.SQLite.Migrations.M20230814_indexes
import Simplex.Chat.Store.SQLite.Migrations.M20230827_file_encryption
import Simplex.Chat.Store.SQLite.Migrations.M20230829_connections_chat_vrange
import Simplex.Chat.Store.SQLite.Migrations.M20230903_connections_to_subscribe
import Simplex.Chat.Store.SQLite.Migrations.M20230913_member_contacts
import Simplex.Chat.Store.SQLite.Migrations.M20230914_member_probes
import Simplex.Chat.Store.SQLite.Migrations.M20230926_contact_status
import Simplex.Chat.Store.SQLite.Migrations.M20231002_conn_initiated
import Simplex.Chat.Store.SQLite.Migrations.M20231009_via_group_link_uri_hash
import Simplex.Chat.Store.SQLite.Migrations.M20231010_member_settings
import Simplex.Chat.Store.SQLite.Migrations.M20231019_indexes
import Simplex.Chat.Store.SQLite.Migrations.M20231030_xgrplinkmem_received
import Simplex.Chat.Store.SQLite.Migrations.M20231107_indexes
import Simplex.Chat.Store.SQLite.Migrations.M20231113_group_forward
import Simplex.Chat.Store.SQLite.Migrations.M20231114_remote_control
import Simplex.Chat.Store.SQLite.Migrations.M20231126_remote_ctrl_address
import Simplex.Chat.Store.SQLite.Migrations.M20231207_chat_list_pagination
import Simplex.Chat.Store.SQLite.Migrations.M20231214_item_content_tag
import Simplex.Chat.Store.SQLite.Migrations.M20231215_recreate_msg_deliveries
import Simplex.Chat.Store.SQLite.Migrations.M20240102_note_folders
import Simplex.Chat.Store.SQLite.Migrations.M20240104_members_profile_update
import Simplex.Chat.Store.SQLite.Migrations.M20240115_block_member_for_all
import Simplex.Chat.Store.SQLite.Migrations.M20240122_indexes
import Simplex.Chat.Store.SQLite.Migrations.M20240214_redirect_file_id
import Simplex.Chat.Store.SQLite.Migrations.M20240222_app_settings
import Simplex.Chat.Store.SQLite.Migrations.M20240226_users_restrict
import Simplex.Chat.Store.SQLite.Migrations.M20240228_pq
import Simplex.Chat.Store.SQLite.Migrations.M20240313_drop_agent_ack_cmd_id
import Simplex.Chat.Store.SQLite.Migrations.M20240324_custom_data
import Simplex.Chat.Store.SQLite.Migrations.M20240402_item_forwarded
import Simplex.Chat.Store.SQLite.Migrations.M20240430_ui_theme
import Simplex.Chat.Store.SQLite.Migrations.M20240501_chat_deleted
import Simplex.Chat.Store.SQLite.Migrations.M20240510_chat_items_via_proxy
import Simplex.Chat.Store.SQLite.Migrations.M20240515_rcv_files_user_approved_relays
import Simplex.Chat.Store.SQLite.Migrations.M20240528_quota_err_counter
import Simplex.Chat.Store.SQLite.Migrations.M20240827_calls_uuid
import Simplex.Chat.Store.SQLite.Migrations.M20240920_user_order
import Simplex.Chat.Store.SQLite.Migrations.M20241008_indexes
import Simplex.Chat.Store.SQLite.Migrations.M20241010_contact_requests_contact_id
import Simplex.Chat.Store.SQLite.Migrations.M20241023_chat_item_autoincrement_id
import Simplex.Chat.Store.SQLite.Migrations.M20241027_server_operators
import Simplex.Chat.Store.SQLite.Migrations.M20241125_indexes
import Simplex.Chat.Store.SQLite.Migrations.M20241128_business_chats
import Simplex.Chat.Store.SQLite.Migrations.M20241205_business_chat_members
import Simplex.Chat.Store.SQLite.Migrations.M20241222_operator_conditions
import Simplex.Chat.Store.SQLite.Migrations.M20241223_chat_tags
import Simplex.Chat.Store.SQLite.Migrations.M20241230_reports
import Simplex.Chat.Store.SQLite.Migrations.M20250105_indexes
import Simplex.Messaging.Agent.Store.Shared (Migration (..))
schemaMigrations :: [(String, Query, Maybe Query)]
schemaMigrations =
[ ("20220101_initial", m20220101_initial, Nothing),
("20220122_v1_1", m20220122_v1_1, Nothing),
("20220205_chat_item_status", m20220205_chat_item_status, Nothing),
("20220210_deduplicate_contact_requests", m20220210_deduplicate_contact_requests, Nothing),
("20220224_messages_fks", m20220224_messages_fks, Nothing),
("20220301_smp_servers", m20220301_smp_servers, Nothing),
("20220302_profile_images", m20220302_profile_images, Nothing),
("20220304_msg_quotes", m20220304_msg_quotes, Nothing),
("20220321_chat_item_edited", m20220321_chat_item_edited, Nothing),
("20220404_files_status_fields", m20220404_files_status_fields, Nothing),
("20220514_profiles_user_id", m20220514_profiles_user_id, Nothing),
("20220626_auto_reply", m20220626_auto_reply, Nothing),
("20220702_calls", m20220702_calls, Nothing),
("20220715_groups_chat_item_id", m20220715_groups_chat_item_id, Nothing),
("20220811_chat_items_indices", m20220811_chat_items_indices, Nothing),
("20220812_incognito_profiles", m20220812_incognito_profiles, Nothing),
("20220818_chat_notifications", m20220818_chat_notifications, Nothing),
("20220822_groups_host_conn_custom_user_profile_id", m20220822_groups_host_conn_custom_user_profile_id, Nothing),
("20220823_delete_broken_group_event_chat_items", m20220823_delete_broken_group_event_chat_items, Nothing),
("20220824_profiles_local_alias", m20220824_profiles_local_alias, Nothing),
("20220909_commands", m20220909_commands, Nothing),
("20220926_connection_alias", m20220926_connection_alias, Nothing),
("20220928_settings", m20220928_settings, Nothing),
("20221001_shared_msg_id_indices", m20221001_shared_msg_id_indices, Nothing),
("20221003_delete_broken_integrity_error_chat_items", m20221003_delete_broken_integrity_error_chat_items, Nothing),
("20221004_idx_msg_deliveries_message_id", m20221004_idx_msg_deliveries_message_id, Nothing),
("20221011_user_contact_links_group_id", m20221011_user_contact_links_group_id, Nothing),
("20221012_inline_files", m20221012_inline_files, Nothing),
("20221019_unread_chat", m20221019_unread_chat, Nothing),
("20221021_auto_accept__group_links", m20221021_auto_accept__group_links, Nothing),
("20221024_contact_used", m20221024_contact_used, Nothing),
("20221025_chat_settings", m20221025_chat_settings, Nothing),
("20221029_group_link_id", m20221029_group_link_id, Nothing),
("20221112_server_password", m20221112_server_password, Nothing),
("20221115_server_cfg", m20221115_server_cfg, Nothing),
("20221129_delete_group_feature_items", m20221129_delete_group_feature_items, Nothing),
("20221130_delete_item_deleted", m20221130_delete_item_deleted, Nothing),
("20221209_verified_connection", m20221209_verified_connection, Nothing),
("20221210_idxs", m20221210_idxs, Nothing),
("20221211_group_description", m20221211_group_description, Nothing),
("20221212_chat_items_timed", m20221212_chat_items_timed, Nothing),
("20221214_live_message", m20221214_live_message, Nothing),
("20221222_chat_ts", m20221222_chat_ts, Nothing),
("20221223_idx_chat_items_item_status", m20221223_idx_chat_items_item_status, Nothing),
("20221230_idxs", m20221230_idxs, Nothing),
("20230107_connections_auth_err_counter", m20230107_connections_auth_err_counter, Nothing),
("20230111_users_agent_user_id", m20230111_users_agent_user_id, Nothing),
("20230117_fkey_indexes", m20230117_fkey_indexes, Nothing),
("20230118_recreate_smp_servers", m20230118_recreate_smp_servers, Nothing),
("20230129_drop_chat_items_group_idx", m20230129_drop_chat_items_group_idx, Nothing),
("20230206_item_deleted_by_group_member_id", m20230206_item_deleted_by_group_member_id, Nothing),
("20230303_group_link_role", m20230303_group_link_role, Nothing),
("20230317_hidden_profiles", m20230317_hidden_profiles, Just down_m20230317_hidden_profiles),
("20230318_file_description", m20230318_file_description, Just down_m20230318_file_description),
("20230321_agent_file_deleted", m20230321_agent_file_deleted, Just down_m20230321_agent_file_deleted),
("20230328_files_protocol", m20230328_files_protocol, Just down_m20230328_files_protocol),
("20230402_protocol_servers", m20230402_protocol_servers, Just down_m20230402_protocol_servers),
("20230411_extra_xftp_file_descriptions", m20230411_extra_xftp_file_descriptions, Just down_m20230411_extra_xftp_file_descriptions),
("20230420_rcv_files_to_receive", m20230420_rcv_files_to_receive, Just down_m20230420_rcv_files_to_receive),
("20230422_profile_contact_links", m20230422_profile_contact_links, Just down_m20230422_profile_contact_links),
("20230504_recreate_msg_delivery_events_cleanup_messages", m20230504_recreate_msg_delivery_events_cleanup_messages, Just down_m20230504_recreate_msg_delivery_events_cleanup_messages),
("20230505_chat_item_versions", m20230505_chat_item_versions, Just down_m20230505_chat_item_versions),
("20230511_reactions", m20230511_reactions, Just down_m20230511_reactions),
("20230519_item_deleted_ts", m20230519_item_deleted_ts, Just down_m20230519_item_deleted_ts),
("20230526_indexes", m20230526_indexes, Just down_m20230526_indexes),
("20230529_indexes", m20230529_indexes, Just down_m20230529_indexes),
("20230608_deleted_contacts", m20230608_deleted_contacts, Just down_m20230608_deleted_contacts),
("20230618_favorite_chats", m20230618_favorite_chats, Just down_m20230618_favorite_chats),
("20230621_chat_item_moderations", m20230621_chat_item_moderations, Just down_m20230621_chat_item_moderations),
("20230705_delivery_receipts", m20230705_delivery_receipts, Just down_m20230705_delivery_receipts),
("20230721_group_snd_item_statuses", m20230721_group_snd_item_statuses, Just down_m20230721_group_snd_item_statuses),
("20230814_indexes", m20230814_indexes, Just down_m20230814_indexes),
("20230827_file_encryption", m20230827_file_encryption, Just down_m20230827_file_encryption),
("20230829_connections_chat_vrange", m20230829_connections_chat_vrange, Just down_m20230829_connections_chat_vrange),
("20230903_connections_to_subscribe", m20230903_connections_to_subscribe, Just down_m20230903_connections_to_subscribe),
("20230913_member_contacts", m20230913_member_contacts, Just down_m20230913_member_contacts),
("20230914_member_probes", m20230914_member_probes, Just down_m20230914_member_probes),
("20230926_contact_status", m20230926_contact_status, Just down_m20230926_contact_status),
("20231002_conn_initiated", m20231002_conn_initiated, Just down_m20231002_conn_initiated),
("20231009_via_group_link_uri_hash", m20231009_via_group_link_uri_hash, Just down_m20231009_via_group_link_uri_hash),
("20231010_member_settings", m20231010_member_settings, Just down_m20231010_member_settings),
("20231019_indexes", m20231019_indexes, Just down_m20231019_indexes),
("20231030_xgrplinkmem_received", m20231030_xgrplinkmem_received, Just down_m20231030_xgrplinkmem_received),
("20231107_indexes", m20231107_indexes, Just down_m20231107_indexes),
("20231113_group_forward", m20231113_group_forward, Just down_m20231113_group_forward),
("20231114_remote_control", m20231114_remote_control, Just down_m20231114_remote_control),
("20231126_remote_ctrl_address", m20231126_remote_ctrl_address, Just down_m20231126_remote_ctrl_address),
("20231207_chat_list_pagination", m20231207_chat_list_pagination, Just down_m20231207_chat_list_pagination),
("20231214_item_content_tag", m20231214_item_content_tag, Just down_m20231214_item_content_tag),
("20231215_recreate_msg_deliveries", m20231215_recreate_msg_deliveries, Just down_m20231215_recreate_msg_deliveries),
("20240102_note_folders", m20240102_note_folders, Just down_m20240102_note_folders),
("20240104_members_profile_update", m20240104_members_profile_update, Just down_m20240104_members_profile_update),
("20240115_block_member_for_all", m20240115_block_member_for_all, Just down_m20240115_block_member_for_all),
("20240122_indexes", m20240122_indexes, Just down_m20240122_indexes),
("20240214_redirect_file_id", m20240214_redirect_file_id, Just down_m20240214_redirect_file_id),
("20240222_app_settings", m20240222_app_settings, Just down_m20240222_app_settings),
("20240226_users_restrict", m20240226_users_restrict, Just down_m20240226_users_restrict),
("20240228_pq", m20240228_pq, Just down_m20240228_pq),
("20240313_drop_agent_ack_cmd_id", m20240313_drop_agent_ack_cmd_id, Just down_m20240313_drop_agent_ack_cmd_id),
("20240324_custom_data", m20240324_custom_data, Just down_m20240324_custom_data),
("20240402_item_forwarded", m20240402_item_forwarded, Just down_m20240402_item_forwarded),
("20240430_ui_theme", m20240430_ui_theme, Just down_m20240430_ui_theme),
("20240501_chat_deleted", m20240501_chat_deleted, Just down_m20240501_chat_deleted),
("20240510_chat_items_via_proxy", m20240510_chat_items_via_proxy, Just down_m20240510_chat_items_via_proxy),
("20240515_rcv_files_user_approved_relays", m20240515_rcv_files_user_approved_relays, Just down_m20240515_rcv_files_user_approved_relays),
("20240528_quota_err_counter", m20240528_quota_err_counter, Just down_m20240528_quota_err_counter),
("20240827_calls_uuid", m20240827_calls_uuid, Just down_m20240827_calls_uuid),
("20240920_user_order", m20240920_user_order, Just down_m20240920_user_order),
("20241008_indexes", m20241008_indexes, Just down_m20241008_indexes),
("20241010_contact_requests_contact_id", m20241010_contact_requests_contact_id, Just down_m20241010_contact_requests_contact_id),
("20241023_chat_item_autoincrement_id", m20241023_chat_item_autoincrement_id, Just down_m20241023_chat_item_autoincrement_id),
("20241027_server_operators", m20241027_server_operators, Just down_m20241027_server_operators),
("20241125_indexes", m20241125_indexes, Just down_m20241125_indexes),
("20241128_business_chats", m20241128_business_chats, Just down_m20241128_business_chats),
("20241205_business_chat_members", m20241205_business_chat_members, Just down_m20241205_business_chat_members),
("20241222_operator_conditions", m20241222_operator_conditions, Just down_m20241222_operator_conditions),
("20241223_chat_tags", m20241223_chat_tags, Just down_m20241223_chat_tags),
("20241230_reports", m20241230_reports, Just down_m20241230_reports),
("20250105_indexes", m20250105_indexes, Just down_m20250105_indexes)
]
-- | The list of migrations in ascending order by date
migrations :: [Migration]
migrations = sortOn name $ map migration schemaMigrations
where
migration (name, up, down) = Migration {name, up = fromQuery up, down = fromQuery <$> down}
@@ -0,0 +1,271 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220101_initial where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220101_initial :: Query
m20220101_initial =
[sql|
CREATE TABLE contact_profiles ( -- remote user profile
contact_profile_id INTEGER PRIMARY KEY,
display_name TEXT NOT NULL, -- contact name set by remote user (not unique), this name must not contain spaces
full_name TEXT NOT NULL,
properties TEXT NOT NULL DEFAULT '{}' -- JSON with contact profile properties
);
CREATE INDEX contact_profiles_index ON contact_profiles (display_name, full_name);
CREATE TABLE users (
user_id INTEGER PRIMARY KEY,
contact_id INTEGER NOT NULL UNIQUE REFERENCES contacts ON DELETE CASCADE
DEFERRABLE INITIALLY DEFERRED,
local_display_name TEXT NOT NULL UNIQUE,
active_user INTEGER NOT NULL DEFAULT 0, -- 1 for active user
FOREIGN KEY (user_id, local_display_name)
REFERENCES display_names (user_id, local_display_name)
ON DELETE CASCADE
ON UPDATE CASCADE
DEFERRABLE INITIALLY DEFERRED
);
CREATE TABLE display_names (
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
local_display_name TEXT NOT NULL,
ldn_base TEXT NOT NULL,
ldn_suffix INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (user_id, local_display_name) ON CONFLICT FAIL,
UNIQUE (user_id, ldn_base, ldn_suffix) ON CONFLICT FAIL
) WITHOUT ROWID;
CREATE TABLE contacts (
contact_id INTEGER PRIMARY KEY,
contact_profile_id INTEGER REFERENCES contact_profiles ON DELETE SET NULL,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
local_display_name TEXT NOT NULL,
is_user INTEGER NOT NULL DEFAULT 0, -- 1 if this contact is a user
via_group INTEGER REFERENCES groups (group_id) ON DELETE SET NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (user_id, local_display_name)
REFERENCES display_names (user_id, local_display_name)
ON DELETE CASCADE
ON UPDATE CASCADE,
UNIQUE (user_id, local_display_name),
UNIQUE (user_id, contact_profile_id)
);
CREATE TABLE sent_probes (
sent_probe_id INTEGER PRIMARY KEY,
contact_id INTEGER NOT NULL UNIQUE REFERENCES contacts ON DELETE CASCADE,
probe BLOB NOT NULL,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
UNIQUE (user_id, probe)
);
CREATE TABLE sent_probe_hashes (
sent_probe_hash_id INTEGER PRIMARY KEY,
sent_probe_id INTEGER NOT NULL REFERENCES sent_probes ON DELETE CASCADE,
contact_id INTEGER NOT NULL REFERENCES contacts ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
UNIQUE (sent_probe_id, contact_id)
);
CREATE TABLE received_probes (
received_probe_id INTEGER PRIMARY KEY,
contact_id INTEGER NOT NULL REFERENCES contacts ON DELETE CASCADE,
probe BLOB,
probe_hash BLOB NOT NULL,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE
);
CREATE TABLE known_servers(
server_id INTEGER PRIMARY KEY,
host TEXT NOT NULL,
port TEXT NOT NULL,
key_hash BLOB,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
UNIQUE (user_id, host, port)
) WITHOUT ROWID;
CREATE TABLE group_profiles ( -- shared group profiles
group_profile_id INTEGER PRIMARY KEY,
display_name TEXT NOT NULL, -- this name must not contain spaces
full_name TEXT NOT NULL,
properties TEXT NOT NULL DEFAULT '{}' -- JSON with user or contact profile
);
CREATE TABLE groups (
group_id INTEGER PRIMARY KEY, -- local group ID
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
local_display_name TEXT NOT NULL, -- local group name without spaces
group_profile_id INTEGER REFERENCES group_profiles ON DELETE SET NULL, -- shared group profile
inv_queue_info BLOB, -- received
FOREIGN KEY (user_id, local_display_name)
REFERENCES display_names (user_id, local_display_name)
ON DELETE CASCADE
ON UPDATE CASCADE,
UNIQUE (user_id, local_display_name),
UNIQUE (user_id, group_profile_id)
);
CREATE INDEX idx_groups_inv_queue_info ON groups (inv_queue_info);
CREATE TABLE group_members ( -- group members, excluding the local user
group_member_id INTEGER PRIMARY KEY,
group_id INTEGER NOT NULL REFERENCES groups ON DELETE CASCADE,
member_id BLOB NOT NULL, -- shared member ID, unique per group
member_role TEXT NOT NULL, -- owner, admin, member
member_category TEXT NOT NULL, -- see GroupMemberCategory
member_status TEXT NOT NULL, -- see GroupMemberStatus
invited_by INTEGER REFERENCES contacts (contact_id) ON DELETE SET NULL, -- NULL for the members who joined before the current user and for the group creator
sent_inv_queue_info BLOB, -- sent
group_queue_info BLOB, -- received
direct_queue_info BLOB, -- received
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
local_display_name TEXT NOT NULL, -- should be the same as contact
contact_profile_id INTEGER NOT NULL REFERENCES contact_profiles ON DELETE CASCADE,
contact_id INTEGER REFERENCES contacts ON DELETE CASCADE,
FOREIGN KEY (user_id, local_display_name)
REFERENCES display_names (user_id, local_display_name)
ON DELETE CASCADE
ON UPDATE CASCADE,
UNIQUE (group_id, member_id)
);
CREATE TABLE group_member_intros (
group_member_intro_id INTEGER PRIMARY KEY,
re_group_member_id INTEGER NOT NULL REFERENCES group_members (group_member_id) ON DELETE CASCADE,
to_group_member_id INTEGER NOT NULL REFERENCES group_members (group_member_id) ON DELETE CASCADE,
group_queue_info BLOB,
direct_queue_info BLOB,
intro_status TEXT NOT NULL, -- see GroupMemberIntroStatus
UNIQUE (re_group_member_id, to_group_member_id)
);
CREATE TABLE files (
file_id INTEGER PRIMARY KEY,
contact_id INTEGER REFERENCES contacts ON DELETE CASCADE,
group_id INTEGER REFERENCES groups ON DELETE CASCADE,
file_name TEXT NOT NULL,
file_path TEXT,
file_size INTEGER NOT NULL,
chunk_size INTEGER NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE
);
CREATE TABLE snd_files (
file_id INTEGER NOT NULL REFERENCES files ON DELETE CASCADE,
connection_id INTEGER NOT NULL REFERENCES connections ON DELETE CASCADE,
file_status TEXT NOT NULL, -- new, accepted, connected, completed
group_member_id INTEGER REFERENCES group_members ON DELETE CASCADE,
PRIMARY KEY (file_id, connection_id)
) WITHOUT ROWID;
CREATE TABLE rcv_files (
file_id INTEGER PRIMARY KEY REFERENCES files ON DELETE CASCADE,
file_status TEXT NOT NULL, -- new, accepted, connected, completed
group_member_id INTEGER REFERENCES group_members ON DELETE CASCADE,
file_queue_info BLOB
);
CREATE TABLE snd_file_chunks (
file_id INTEGER NOT NULL,
connection_id INTEGER NOT NULL,
chunk_number INTEGER NOT NULL,
chunk_agent_msg_id INTEGER,
chunk_sent INTEGER NOT NULL DEFAULT 0, -- 0 (sent to agent), 1 (sent to server)
FOREIGN KEY (file_id, connection_id) REFERENCES snd_files ON DELETE CASCADE,
PRIMARY KEY (file_id, connection_id, chunk_number)
) WITHOUT ROWID;
CREATE TABLE rcv_file_chunks (
file_id INTEGER NOT NULL REFERENCES rcv_files ON DELETE CASCADE,
chunk_number INTEGER NOT NULL,
chunk_agent_msg_id INTEGER NOT NULL,
chunk_stored INTEGER NOT NULL DEFAULT 0, -- 0 (received), 1 (appended to file)
PRIMARY KEY (file_id, chunk_number)
) WITHOUT ROWID;
CREATE TABLE connections ( -- all SMP agent connections
connection_id INTEGER PRIMARY KEY,
agent_conn_id BLOB NOT NULL UNIQUE,
conn_level INTEGER NOT NULL DEFAULT 0,
via_contact INTEGER REFERENCES contacts (contact_id) ON DELETE SET NULL,
conn_status TEXT NOT NULL,
conn_type TEXT NOT NULL, -- contact, member, rcv_file, snd_file
user_contact_link_id INTEGER REFERENCES user_contact_links ON DELETE CASCADE,
contact_id INTEGER REFERENCES contacts ON DELETE CASCADE,
group_member_id INTEGER REFERENCES group_members ON DELETE CASCADE,
snd_file_id INTEGER,
rcv_file_id INTEGER REFERENCES rcv_files (file_id) ON DELETE CASCADE,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
FOREIGN KEY (snd_file_id, connection_id)
REFERENCES snd_files (file_id, connection_id)
ON DELETE CASCADE
DEFERRABLE INITIALLY DEFERRED
);
CREATE TABLE user_contact_links (
user_contact_link_id INTEGER PRIMARY KEY,
conn_req_contact BLOB NOT NULL,
local_display_name TEXT NOT NULL DEFAULT '',
created_at TEXT NOT NULL DEFAULT (datetime('now')),
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
UNIQUE (user_id, local_display_name)
);
CREATE TABLE contact_requests (
contact_request_id INTEGER PRIMARY KEY,
user_contact_link_id INTEGER NOT NULL REFERENCES user_contact_links
ON UPDATE CASCADE ON DELETE CASCADE,
agent_invitation_id BLOB NOT NULL,
contact_profile_id INTEGER REFERENCES contact_profiles
ON DELETE SET NULL
DEFERRABLE INITIALLY DEFERRED,
local_display_name TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
FOREIGN KEY (user_id, local_display_name)
REFERENCES display_names (user_id, local_display_name)
ON UPDATE CASCADE
ON DELETE CASCADE
DEFERRABLE INITIALLY DEFERRED,
UNIQUE (user_id, local_display_name),
UNIQUE (user_id, contact_profile_id)
);
-- all message events as received or sent, append only
-- maps to message deliveries as one-to-many for group messages
CREATE TABLE messages (
message_id INTEGER PRIMARY KEY,
msg_sent INTEGER NOT NULL, -- 0 for received, 1 for sent
chat_msg_event TEXT NOT NULL, -- message event tag (the constructor of CMEventTag)
msg_body BLOB, -- agent message body as received or sent
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
-- TODO ? agent_msg_id could be NOT NULL now that pending_group_messages are separate
-- message deliveries communicated with the agent, append only
CREATE TABLE msg_deliveries (
msg_delivery_id INTEGER PRIMARY KEY,
message_id INTEGER NOT NULL REFERENCES messages ON DELETE CASCADE, -- non UNIQUE for group messages
connection_id INTEGER NOT NULL REFERENCES connections ON DELETE CASCADE,
agent_msg_id INTEGER, -- internal agent message ID (NULL while pending)
agent_msg_meta TEXT, -- JSON with timestamps etc. sent in MSG, NULL for sent
chat_ts TEXT NOT NULL DEFAULT (datetime('now')), -- broker_ts for received, created_at for sent
UNIQUE (connection_id, agent_msg_id)
);
-- TODO recovery for received messages with "rcv_agent" status - acknowledge to agent
-- changes of message delivery status, append only
CREATE TABLE msg_delivery_events (
msg_delivery_event_id INTEGER PRIMARY KEY,
msg_delivery_id INTEGER NOT NULL REFERENCES msg_deliveries ON DELETE CASCADE, -- non UNIQUE for multiple events per msg delivery
delivery_status TEXT NOT NULL, -- see MsgDeliveryStatus for allowed values
created_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE (msg_delivery_id, delivery_status)
);
|]
@@ -0,0 +1,221 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220122_v1_1 where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220122_v1_1 :: Query
m20220122_v1_1 =
[sql|
-- * pending group messages
-- pending messages for announced (memberCurrent) but not yet connected (memberActive) group members
CREATE TABLE pending_group_messages (
pending_group_message_id INTEGER PRIMARY KEY,
group_member_id INTEGER NOT NULL REFERENCES group_members ON DELETE CASCADE,
message_id INTEGER NOT NULL REFERENCES messages ON DELETE CASCADE,
group_member_intro_id INTEGER REFERENCES group_member_intros ON DELETE CASCADE,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
-- * chat items
-- mutable chat_items presented to user
CREATE TABLE chat_items (
chat_item_id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
contact_id INTEGER REFERENCES contacts ON DELETE CASCADE,
group_id INTEGER REFERENCES groups ON DELETE CASCADE,
group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL, -- NULL for sent even if group_id is not
chat_msg_id INTEGER, -- sent as part of the message that created the item
created_by_msg_id INTEGER UNIQUE REFERENCES messages (message_id) ON DELETE SET NULL,
item_sent INTEGER NOT NULL, -- 0 for received, 1 for sent
item_ts TEXT NOT NULL, -- broker_ts of creating message for received, created_at for sent
item_deleted INTEGER NOT NULL DEFAULT 0, -- 1 for deleted
item_content TEXT NOT NULL, -- JSON
item_text TEXT NOT NULL, -- textual representation
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE chat_item_messages (
chat_item_id INTEGER NOT NULL REFERENCES chat_items ON DELETE CASCADE,
message_id INTEGER NOT NULL UNIQUE REFERENCES messages ON DELETE CASCADE,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE (chat_item_id, message_id)
);
ALTER TABLE files ADD COLUMN chat_item_id INTEGER DEFAULT NULL REFERENCES chat_items ON DELETE CASCADE;
-- * created_at & updated_at for all tables
PRAGMA ignore_check_constraints=ON;
-- ** contact_profiles
ALTER TABLE contact_profiles ADD COLUMN created_at TEXT CHECK (created_at NOT NULL);
UPDATE contact_profiles SET created_at = '1970-01-01 00:00:00';
ALTER TABLE contact_profiles ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE contact_profiles SET updated_at = '1970-01-01 00:00:00';
-- ** users
ALTER TABLE users ADD COLUMN created_at TEXT CHECK (created_at NOT NULL);
UPDATE users SET created_at = '1970-01-01 00:00:00';
ALTER TABLE users ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE users SET updated_at = '1970-01-01 00:00:00';
-- ** display_names
ALTER TABLE display_names ADD COLUMN created_at TEXT CHECK (created_at NOT NULL);
UPDATE display_names SET created_at = '1970-01-01 00:00:00';
ALTER TABLE display_names ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE display_names SET updated_at = '1970-01-01 00:00:00';
-- ** contacts
ALTER TABLE contacts ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE contacts SET updated_at = '1970-01-01 00:00:00';
-- ** sent_probes
ALTER TABLE sent_probes ADD COLUMN created_at TEXT CHECK (created_at NOT NULL);
UPDATE sent_probes SET created_at = '1970-01-01 00:00:00';
ALTER TABLE sent_probes ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE sent_probes SET updated_at = '1970-01-01 00:00:00';
-- ** sent_probe_hashes
ALTER TABLE sent_probe_hashes ADD COLUMN created_at TEXT CHECK (created_at NOT NULL);
UPDATE sent_probe_hashes SET created_at = '1970-01-01 00:00:00';
ALTER TABLE sent_probe_hashes ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE sent_probe_hashes SET updated_at = '1970-01-01 00:00:00';
-- ** received_probes
ALTER TABLE received_probes ADD COLUMN created_at TEXT CHECK (created_at NOT NULL);
UPDATE received_probes SET created_at = '1970-01-01 00:00:00';
ALTER TABLE received_probes ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE received_probes SET updated_at = '1970-01-01 00:00:00';
-- ** known_servers
ALTER TABLE known_servers ADD COLUMN created_at TEXT CHECK (created_at NOT NULL);
UPDATE known_servers SET created_at = '1970-01-01 00:00:00';
ALTER TABLE known_servers ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE known_servers SET updated_at = '1970-01-01 00:00:00';
-- ** group_profiles
ALTER TABLE group_profiles ADD COLUMN created_at TEXT CHECK (created_at NOT NULL);
UPDATE group_profiles SET created_at = '1970-01-01 00:00:00';
ALTER TABLE group_profiles ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE group_profiles SET updated_at = '1970-01-01 00:00:00';
-- ** groups
ALTER TABLE groups ADD COLUMN created_at TEXT CHECK (created_at NOT NULL);
UPDATE groups SET created_at = '1970-01-01 00:00:00';
ALTER TABLE groups ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE groups SET updated_at = '1970-01-01 00:00:00';
-- ** group_members
ALTER TABLE group_members ADD COLUMN created_at TEXT CHECK (created_at NOT NULL);
UPDATE group_members SET created_at = '1970-01-01 00:00:00';
ALTER TABLE group_members ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE group_members SET updated_at = '1970-01-01 00:00:00';
-- ** group_member_intros
ALTER TABLE group_member_intros ADD COLUMN created_at TEXT CHECK (created_at NOT NULL);
UPDATE group_member_intros SET created_at = '1970-01-01 00:00:00';
ALTER TABLE group_member_intros ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE group_member_intros SET updated_at = '1970-01-01 00:00:00';
-- ** files
ALTER TABLE files ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE files SET updated_at = '1970-01-01 00:00:00';
-- ** snd_files
ALTER TABLE snd_files ADD COLUMN created_at TEXT CHECK (created_at NOT NULL);
UPDATE snd_files SET created_at = '1970-01-01 00:00:00';
ALTER TABLE snd_files ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE snd_files SET updated_at = '1970-01-01 00:00:00';
-- ** rcv_files
ALTER TABLE rcv_files ADD COLUMN created_at TEXT CHECK (created_at NOT NULL);
UPDATE rcv_files SET created_at = '1970-01-01 00:00:00';
ALTER TABLE rcv_files ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE rcv_files SET updated_at = '1970-01-01 00:00:00';
-- ** snd_file_chunks
ALTER TABLE snd_file_chunks ADD COLUMN created_at TEXT CHECK (created_at NOT NULL);
UPDATE snd_file_chunks SET created_at = '1970-01-01 00:00:00';
ALTER TABLE snd_file_chunks ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE snd_file_chunks SET updated_at = '1970-01-01 00:00:00';
-- ** rcv_file_chunks
ALTER TABLE rcv_file_chunks ADD COLUMN created_at TEXT CHECK (created_at NOT NULL);
UPDATE rcv_file_chunks SET created_at = '1970-01-01 00:00:00';
ALTER TABLE rcv_file_chunks ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE rcv_file_chunks SET updated_at = '1970-01-01 00:00:00';
-- ** connections
ALTER TABLE connections ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE connections SET updated_at = '1970-01-01 00:00:00';
-- ** user_contact_links
ALTER TABLE user_contact_links ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE user_contact_links SET updated_at = '1970-01-01 00:00:00';
-- ** contact_requests
ALTER TABLE contact_requests ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE contact_requests SET updated_at = '1970-01-01 00:00:00';
-- ** messages
ALTER TABLE messages ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE messages SET updated_at = '1970-01-01 00:00:00';
-- ** msg_deliveries
ALTER TABLE msg_deliveries ADD COLUMN created_at TEXT CHECK (created_at NOT NULL);
UPDATE msg_deliveries SET created_at = '1970-01-01 00:00:00';
ALTER TABLE msg_deliveries ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE msg_deliveries SET updated_at = '1970-01-01 00:00:00';
-- ** msg_delivery_events
ALTER TABLE msg_delivery_events ADD COLUMN updated_at TEXT CHECK (updated_at NOT NULL);
UPDATE msg_delivery_events SET updated_at = '1970-01-01 00:00:00';
PRAGMA ignore_check_constraints=OFF;
|]
@@ -0,0 +1,20 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220205_chat_item_status where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220205_chat_item_status :: Query
m20220205_chat_item_status =
[sql|
PRAGMA ignore_check_constraints=ON;
ALTER TABLE chat_items ADD COLUMN item_status TEXT CHECK (item_status NOT NULL);
UPDATE chat_items SET item_status = 'rcv_read' WHERE item_sent = 0;
UPDATE chat_items SET item_status = 'snd_sent' WHERE item_sent = 1;
PRAGMA ignore_check_constraints=OFF;
|]
@@ -0,0 +1,25 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220210_deduplicate_contact_requests where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220210_deduplicate_contact_requests :: Query
m20220210_deduplicate_contact_requests =
[sql|
-- hash of contact address uri used by contact request sender to connect,
-- null for contact request recipient and for both parties when using one-off invitation
ALTER TABLE connections ADD COLUMN via_contact_uri_hash BLOB;
CREATE INDEX idx_connections_via_contact_uri_hash ON connections (via_contact_uri_hash);
ALTER TABLE connections ADD COLUMN xcontact_id BLOB;
ALTER TABLE contact_requests ADD COLUMN xcontact_id BLOB;
CREATE INDEX idx_contact_requests_xcontact_id ON contact_requests (xcontact_id);
ALTER TABLE contacts ADD COLUMN xcontact_id BLOB;
CREATE INDEX idx_contacts_xcontact_id ON contacts (xcontact_id);
ALTER TABLE user_contact_links ADD column auto_accept INTEGER DEFAULT 0;
|]
@@ -0,0 +1,13 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220224_messages_fks where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220224_messages_fks :: Query
m20220224_messages_fks =
[sql|
ALTER TABLE messages ADD COLUMN connection_id INTEGER DEFAULT NULL REFERENCES connections ON DELETE CASCADE;
ALTER TABLE messages ADD COLUMN group_id INTEGER DEFAULT NULL REFERENCES groups ON DELETE CASCADE;
|]
@@ -0,0 +1,21 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220301_smp_servers where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220301_smp_servers :: Query
m20220301_smp_servers =
[sql|
CREATE TABLE smp_servers (
smp_server_id INTEGER PRIMARY KEY,
host TEXT NOT NULL,
port TEXT NOT NULL,
key_hash BLOB NOT NULL,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE (host, port)
);
|]
@@ -0,0 +1,13 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220302_profile_images where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220302_profile_images :: Query
m20220302_profile_images =
[sql|
ALTER TABLE contact_profiles ADD COLUMN image TEXT;
ALTER TABLE group_profiles ADD COLUMN image TEXT;
|]
@@ -0,0 +1,24 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220304_msg_quotes where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220304_msg_quotes :: Query
m20220304_msg_quotes =
[sql|
ALTER TABLE messages ADD COLUMN shared_msg_id BLOB;
ALTER TABLE messages ADD COLUMN shared_msg_id_user INTEGER; -- 1 for user messages, NULL for received messages
CREATE INDEX idx_messages_shared_msg_id ON messages (shared_msg_id);
CREATE UNIQUE INDEX idx_messages_direct_shared_msg_id ON messages (connection_id, shared_msg_id_user, shared_msg_id);
CREATE UNIQUE INDEX idx_messages_group_shared_msg_id ON messages (group_id, shared_msg_id_user, shared_msg_id);
ALTER TABLE chat_items ADD COLUMN shared_msg_id BLOB;
ALTER TABLE chat_items ADD COLUMN quoted_shared_msg_id BLOB; -- from MessageRef in QuotedMsg
ALTER TABLE chat_items ADD COLUMN quoted_sent_at TEXT; -- from MessageRef in QuotedMsg
ALTER TABLE chat_items ADD COLUMN quoted_content TEXT; -- from MsgContent in QuotedMsg (JSON)
ALTER TABLE chat_items ADD COLUMN quoted_sent INTEGER; -- from MessageRef, 1 for sent, 0 for received, NULL for messages without quote
ALTER TABLE chat_items ADD COLUMN quoted_member_id BLOB; -- from MessageRef
CREATE INDEX idx_chat_items_shared_msg_id ON chat_items (shared_msg_id);
|]
@@ -0,0 +1,12 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220321_chat_item_edited where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220321_chat_item_edited :: Query
m20220321_chat_item_edited =
[sql|
ALTER TABLE chat_items ADD COLUMN item_edited INTEGER; -- 1 for edited
|]
@@ -0,0 +1,19 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220404_files_status_fields where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220404_files_status_fields :: Query
m20220404_files_status_fields =
[sql|
ALTER TABLE files ADD COLUMN cancelled INTEGER; -- 1 for cancelled
ALTER TABLE files ADD COLUMN ci_file_status TEXT; -- CIFileStatus
DELETE FROM chat_items
WHERE chat_item_id IN (
SELECT chat_item_id
FROM files
);
|]
@@ -0,0 +1,26 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220514_profiles_user_id where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220514_profiles_user_id :: Query
m20220514_profiles_user_id =
[sql|
ALTER TABLE contact_profiles ADD COLUMN user_id INTEGER DEFAULT NULL REFERENCES users ON DELETE CASCADE;
UPDATE contact_profiles SET user_id = (
SELECT user_id
FROM users
WHERE active_user = 1
LIMIT 1
);
ALTER TABLE group_profiles ADD COLUMN user_id INTEGER DEFAULT NULL REFERENCES users ON DELETE CASCADE;
UPDATE group_profiles SET user_id = (
SELECT user_id
FROM users
WHERE active_user = 1
LIMIT 1
);
|]
@@ -0,0 +1,15 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220626_auto_reply where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220626_auto_reply :: Query
m20220626_auto_reply =
[sql|
ALTER TABLE user_contact_links ADD COLUMN auto_reply_msg_content TEXT DEFAULT NULL;
ALTER TABLE connections ADD COLUMN via_user_contact_link INTEGER DEFAULT NULL
REFERENCES user_contact_links (user_contact_link_id) ON DELETE SET NULL;
|]
@@ -0,0 +1,22 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220702_calls where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220702_calls :: Query
m20220702_calls =
[sql|
CREATE TABLE calls ( -- stores call invitations state for communicating state between NSE and app when call notification comes
call_id INTEGER PRIMARY KEY,
contact_id INTEGER NOT NULL REFERENCES contacts ON DELETE CASCADE,
shared_call_id BLOB NOT NULL,
chat_item_id INTEGER NOT NULL REFERENCES chat_items ON DELETE CASCADE,
call_state BLOB NOT NULL,
call_ts TEXT NOT NULL,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
|]
@@ -0,0 +1,12 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220715_groups_chat_item_id where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220715_groups_chat_item_id :: Query
m20220715_groups_chat_item_id =
[sql|
ALTER TABLE groups ADD COLUMN chat_item_id INTEGER DEFAULT NULL REFERENCES chat_items ON DELETE SET NULL;
|]
@@ -0,0 +1,13 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220811_chat_items_indices where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220811_chat_items_indices :: Query
m20220811_chat_items_indices =
[sql|
CREATE INDEX idx_chat_items_groups ON chat_items(user_id, group_id, item_ts, chat_item_id);
CREATE INDEX idx_chat_items_contacts ON chat_items(user_id, contact_id, chat_item_id);
|]
@@ -0,0 +1,16 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220812_incognito_profiles where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220812_incognito_profiles :: Query
m20220812_incognito_profiles =
[sql|
ALTER TABLE connections ADD COLUMN custom_user_profile_id INTEGER REFERENCES contact_profiles ON DELETE SET NULL; -- only set for direct connections
ALTER TABLE group_members ADD COLUMN member_profile_id INTEGER REFERENCES contact_profiles ON DELETE SET NULL; -- member profile id if incognito profile was saved for member (used when invitation is received via incognito direct connection with host)
ALTER TABLE contact_profiles ADD COLUMN incognito INTEGER; -- 1 for incognito
|]
@@ -0,0 +1,14 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220818_chat_notifications where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220818_chat_notifications :: Query
m20220818_chat_notifications =
[sql|
ALTER TABLE contacts ADD COLUMN enable_ntfs INTEGER;
ALTER TABLE groups ADD COLUMN enable_ntfs INTEGER;
|]
@@ -0,0 +1,12 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220822_groups_host_conn_custom_user_profile_id where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220822_groups_host_conn_custom_user_profile_id :: Query
m20220822_groups_host_conn_custom_user_profile_id =
[sql|
ALTER TABLE groups ADD COLUMN host_conn_custom_user_profile_id INTEGER REFERENCES contact_profiles ON DELETE SET NULL; -- id of custom user profile used in direct connection with host
|]
@@ -0,0 +1,13 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220823_delete_broken_group_event_chat_items where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220823_delete_broken_group_event_chat_items :: Query
m20220823_delete_broken_group_event_chat_items =
[sql|
DELETE FROM chat_items WHERE item_content LIKE '%{"rcvGroupEvent":{"rcvGroupEvent":{%';
DELETE FROM chat_items WHERE item_content LIKE '%{"sndGroupEvent":{"sndGroupEvent":{%';
|]
@@ -0,0 +1,17 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220824_profiles_local_alias where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220824_profiles_local_alias :: Query
m20220824_profiles_local_alias =
[sql|
PRAGMA ignore_check_constraints=ON;
ALTER TABLE contact_profiles ADD COLUMN local_alias TEXT DEFAULT '' CHECK (local_alias NOT NULL);
UPDATE contact_profiles SET local_alias = '';
PRAGMA ignore_check_constraints=OFF;
|]
@@ -0,0 +1,24 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220909_commands where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220909_commands :: Query
m20220909_commands =
[sql|
CREATE TABLE commands (
command_id INTEGER PRIMARY KEY AUTOINCREMENT, -- used as ACorrId
connection_id INTEGER REFERENCES connections ON DELETE CASCADE,
command_function TEXT NOT NULL,
command_status TEXT NOT NULL,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
ALTER TABLE msg_deliveries ADD COLUMN agent_ack_cmd_id INTEGER; -- correlation id
ALTER TABLE connections ADD COLUMN conn_req_inv BLOB;
|]
@@ -0,0 +1,17 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220926_connection_alias where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220926_connection_alias :: Query
m20220926_connection_alias =
[sql|
PRAGMA ignore_check_constraints=ON;
ALTER TABLE connections ADD COLUMN local_alias DEFAULT '' CHECK (local_alias NOT NULL);
UPDATE connections SET local_alias = '';
PRAGMA ignore_check_constraints=OFF;
|]
@@ -0,0 +1,18 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20220928_settings where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20220928_settings :: Query
m20220928_settings =
[sql|
CREATE TABLE settings (
settings_id INTEGER PRIMARY KEY,
chat_item_ttl INTEGER,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
|]
@@ -0,0 +1,25 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221001_shared_msg_id_indices where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221001_shared_msg_id_indices :: Query
m20221001_shared_msg_id_indices =
[sql|
DROP INDEX idx_messages_group_shared_msg_id;
CREATE UNIQUE INDEX idx_chat_items_direct_shared_msg_id ON chat_items(
user_id,
contact_id,
shared_msg_id
);
CREATE UNIQUE INDEX idx_chat_items_group_shared_msg_id ON chat_items(
user_id,
group_id,
group_member_id,
shared_msg_id
);
|]
@@ -0,0 +1,12 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221003_delete_broken_integrity_error_chat_items where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221003_delete_broken_integrity_error_chat_items :: Query
m20221003_delete_broken_integrity_error_chat_items =
[sql|
DELETE FROM chat_items WHERE item_content LIKE '%{"rcvIntegrityError":{%';
|]
@@ -0,0 +1,12 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221004_idx_msg_deliveries_message_id where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221004_idx_msg_deliveries_message_id :: Query
m20221004_idx_msg_deliveries_message_id =
[sql|
CREATE INDEX idx_msg_deliveries_message_id ON msg_deliveries(message_id);
|]
@@ -0,0 +1,14 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221011_user_contact_links_group_id where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221011_user_contact_links_group_id :: Query
m20221011_user_contact_links_group_id =
[sql|
ALTER TABLE user_contact_links ADD COLUMN group_id INTEGER REFERENCES groups ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_user_contact_links_group_id ON user_contact_links(group_id);
|]
@@ -0,0 +1,20 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221012_inline_files where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221012_inline_files :: Query
m20221012_inline_files =
[sql|
DROP INDEX idx_messages_direct_shared_msg_id;
ALTER TABLE files ADD COLUMN file_inline TEXT; -- based on offer, determined by file sender for both sides
ALTER TABLE rcv_files ADD COLUMN rcv_file_inline TEXT; -- actual mode when receiving file, determined when invitation is accepted
ALTER TABLE rcv_files ADD COLUMN file_inline TEXT; -- based on offer, determined when invitation is processed
ALTER TABLE snd_files ADD COLUMN file_inline TEXT; -- actual mode when sending file, determined when invitation is accepted
ALTER TABLE snd_files ADD COLUMN last_inline_msg_delivery_id INTEGER;
CREATE UNIQUE INDEX idx_snd_files_last_inline_msg_delivery_id ON snd_files(last_inline_msg_delivery_id);
|]
@@ -0,0 +1,20 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221019_unread_chat where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221019_unread_chat :: Query
m20221019_unread_chat =
[sql|
PRAGMA ignore_check_constraints=ON;
ALTER TABLE contacts ADD COLUMN unread_chat INTEGER DEFAULT 0 CHECK (unread_chat NOT NULL);
UPDATE contacts SET unread_chat = 0;
ALTER TABLE groups ADD COLUMN unread_chat INTEGER DEFAULT 0 CHECK (unread_chat NOT NULL);
UPDATE groups SET unread_chat = 0;
PRAGMA ignore_check_constraints=OFF;
|]
@@ -0,0 +1,20 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221021_auto_accept__group_links where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221021_auto_accept__group_links :: Query
m20221021_auto_accept__group_links =
[sql|
PRAGMA ignore_check_constraints=ON;
ALTER TABLE connections ADD COLUMN via_group_link INTEGER DEFAULT 0 CHECK (via_group_link NOT NULL); -- flag, 1 for connections via group link
UPDATE connections SET via_group_link = 0;
ALTER TABLE user_contact_links ADD column auto_accept_incognito INTEGER DEFAULT 0 CHECK (auto_accept_incognito NOT NULL);
UPDATE user_contact_links SET auto_accept_incognito = 0;
PRAGMA ignore_check_constraints=OFF;
|]
@@ -0,0 +1,22 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221024_contact_used where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221024_contact_used :: Query
m20221024_contact_used =
[sql|
PRAGMA ignore_check_constraints=ON;
ALTER TABLE contacts ADD COLUMN contact_used INTEGER DEFAULT 0 CHECK (contact_used NOT NULL);
UPDATE contacts SET contact_used = 0;
UPDATE contacts SET contact_used = 1 WHERE contact_id IN (
SELECT DISTINCT contact_id FROM chat_items WHERE contact_id IS NOT NULL
);
PRAGMA ignore_check_constraints=OFF;
|]
@@ -0,0 +1,21 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221025_chat_settings where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221025_chat_settings :: Query
m20221025_chat_settings =
[sql|
PRAGMA ignore_check_constraints=ON;
ALTER TABLE group_profiles ADD COLUMN preferences TEXT;
ALTER TABLE contact_profiles ADD COLUMN preferences TEXT;
ALTER TABLE contacts ADD COLUMN user_preferences TEXT DEFAULT '{}' CHECK (user_preferences NOT NULL);
UPDATE contacts SET user_preferences = '{}';
PRAGMA ignore_check_constraints=OFF;
|]
@@ -0,0 +1,14 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221029_group_link_id where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221029_group_link_id :: Query
m20221029_group_link_id =
[sql|
ALTER TABLE user_contact_links ADD COLUMN group_link_id BLOB;
ALTER TABLE connections ADD COLUMN group_link_id BLOB;
|]
@@ -0,0 +1,12 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221112_server_password where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221112_server_password :: Query
m20221112_server_password =
[sql|
ALTER TABLE smp_servers ADD COLUMN basic_auth TEXT;
|]
@@ -0,0 +1,19 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221115_server_cfg where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221115_server_cfg :: Query
m20221115_server_cfg =
[sql|
PRAGMA ignore_check_constraints=ON;
ALTER TABLE smp_servers ADD COLUMN preset INTEGER DEFAULT 0 CHECK (preset NOT NULL);
ALTER TABLE smp_servers ADD COLUMN tested INTEGER;
ALTER TABLE smp_servers ADD COLUMN enabled INTEGER DEFAULT 1 CHECK (enabled NOT NULL);
UPDATE smp_servers SET preset = 0, enabled = 1;
PRAGMA ignore_check_constraints=OFF;
|]
@@ -0,0 +1,13 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221129_delete_group_feature_items where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221129_delete_group_feature_items :: Query
m20221129_delete_group_feature_items =
[sql|
DELETE FROM chat_items WHERE item_content LIKE '%{"rcvGroupFeature":{%';
DELETE FROM chat_items WHERE item_content LIKE '%{"sndGroupFeature":{%';
|]
@@ -0,0 +1,12 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221130_delete_item_deleted where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221130_delete_item_deleted :: Query
m20221130_delete_item_deleted =
[sql|
DELETE FROM chat_items WHERE item_deleted = 1; -- clean up legacy not fully deleted group chat items
|]
@@ -0,0 +1,13 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221209_verified_connection where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221209_verified_connection :: Query
m20221209_verified_connection =
[sql|
ALTER TABLE connections ADD COLUMN security_code TEXT NULL;
ALTER TABLE connections ADD COLUMN security_code_verified_at TEXT NULL;
|]
@@ -0,0 +1,16 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221210_idxs where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221210_idxs :: Query
m20221210_idxs =
[sql|
CREATE INDEX idx_messages_connection_id ON messages(connection_id);
CREATE INDEX idx_chat_items_group_member_id ON chat_items(group_member_id);
CREATE INDEX idx_chat_items_contact_id ON chat_items(contact_id);
|]
@@ -0,0 +1,12 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221211_group_description where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221211_group_description :: Query
m20221211_group_description =
[sql|
ALTER TABLE group_profiles ADD COLUMN description TEXT NULL;
|]
@@ -0,0 +1,16 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221212_chat_items_timed where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221212_chat_items_timed :: Query
m20221212_chat_items_timed =
[sql|
ALTER TABLE chat_items ADD COLUMN timed_ttl INTEGER;
ALTER TABLE chat_items ADD COLUMN timed_delete_at TEXT;
CREATE INDEX idx_chat_items_timed_delete_at ON chat_items(timed_delete_at);
|]
@@ -0,0 +1,12 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221214_live_message where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221214_live_message :: Query
m20221214_live_message =
[sql|
ALTER TABLE chat_items ADD COLUMN item_live INTEGER;
|]
@@ -0,0 +1,14 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221222_chat_ts where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221222_chat_ts :: Query
m20221222_chat_ts =
[sql|
ALTER TABLE contacts ADD COLUMN chat_ts TEXT; -- must be not NULL
ALTER TABLE groups ADD COLUMN chat_ts TEXT; -- must be not NULL
|]
@@ -0,0 +1,12 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221223_idx_chat_items_item_status where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221223_idx_chat_items_item_status :: Query
m20221223_idx_chat_items_item_status =
[sql|
CREATE INDEX idx_chat_items_item_status ON chat_items(item_status);
|]
@@ -0,0 +1,14 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20221230_idxs where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20221230_idxs :: Query
m20221230_idxs =
[sql|
CREATE INDEX idx_connections_group_member ON connections(user_id, group_member_id);
CREATE INDEX idx_commands_connection_id ON commands(connection_id);
|]
@@ -0,0 +1,17 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230107_connections_auth_err_counter where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230107_connections_auth_err_counter :: Query
m20230107_connections_auth_err_counter =
[sql|
PRAGMA ignore_check_constraints=ON;
ALTER TABLE connections ADD COLUMN auth_err_counter INTEGER DEFAULT 0 CHECK (auth_err_counter NOT NULL);
UPDATE connections SET auth_err_counter = 0;
PRAGMA ignore_check_constraints=OFF;
|]
@@ -0,0 +1,17 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230111_users_agent_user_id where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230111_users_agent_user_id :: Query
m20230111_users_agent_user_id =
[sql|
PRAGMA ignore_check_constraints=ON;
ALTER TABLE users ADD COLUMN agent_user_id INTEGER CHECK (agent_user_id NOT NULL);
UPDATE users SET agent_user_id = 1;
PRAGMA ignore_check_constraints=OFF;
|]
@@ -0,0 +1,59 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230117_fkey_indexes where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
-- .lint fkey-indexes
m20230117_fkey_indexes :: Query
m20230117_fkey_indexes =
[sql|
CREATE INDEX idx_calls_user_id ON calls(user_id);
CREATE INDEX idx_calls_chat_item_id ON calls(chat_item_id);
CREATE INDEX idx_calls_contact_id ON calls(contact_id);
CREATE INDEX idx_chat_items_group_id ON chat_items(group_id);
CREATE INDEX idx_commands_user_id ON commands(user_id);
CREATE INDEX idx_connections_custom_user_profile_id ON connections(custom_user_profile_id);
CREATE INDEX idx_connections_via_user_contact_link ON connections(via_user_contact_link);
CREATE INDEX idx_connections_rcv_file_id ON connections(rcv_file_id);
CREATE INDEX idx_connections_contact_id ON connections(contact_id);
CREATE INDEX idx_connections_user_contact_link_id ON connections(user_contact_link_id);
CREATE INDEX idx_connections_via_contact ON connections(via_contact);
CREATE INDEX idx_contact_profiles_user_id ON contact_profiles(user_id);
CREATE INDEX idx_contact_requests_contact_profile_id ON contact_requests(contact_profile_id);
CREATE INDEX idx_contact_requests_user_contact_link_id ON contact_requests(user_contact_link_id);
CREATE INDEX idx_contacts_via_group ON contacts(via_group);
CREATE INDEX idx_contacts_contact_profile_id ON contacts(contact_profile_id);
CREATE INDEX idx_files_chat_item_id ON files(chat_item_id);
CREATE INDEX idx_files_user_id ON files(user_id);
CREATE INDEX idx_files_group_id ON files(group_id);
CREATE INDEX idx_files_contact_id ON files(contact_id);
CREATE INDEX idx_group_member_intros_to_group_member_id ON group_member_intros(to_group_member_id);
CREATE INDEX idx_group_members_user_id_local_display_name ON group_members(user_id, local_display_name);
CREATE INDEX idx_group_members_member_profile_id ON group_members(member_profile_id);
CREATE INDEX idx_group_members_contact_id ON group_members(contact_id);
CREATE INDEX idx_group_members_contact_profile_id ON group_members(contact_profile_id);
CREATE INDEX idx_group_members_user_id ON group_members(user_id);
CREATE INDEX idx_group_members_invited_by ON group_members(invited_by);
CREATE INDEX idx_group_profiles_user_id ON group_profiles(user_id);
CREATE INDEX idx_groups_host_conn_custom_user_profile_id ON groups(host_conn_custom_user_profile_id);
CREATE INDEX idx_groups_chat_item_id ON groups(chat_item_id);
CREATE INDEX idx_groups_group_profile_id ON groups(group_profile_id);
CREATE INDEX idx_messages_group_id ON messages(group_id);
CREATE INDEX idx_pending_group_messages_group_member_intro_id ON pending_group_messages(group_member_intro_id);
CREATE INDEX idx_pending_group_messages_message_id ON pending_group_messages(message_id);
CREATE INDEX idx_pending_group_messages_group_member_id ON pending_group_messages(group_member_id);
CREATE INDEX idx_rcv_file_chunks_file_id ON rcv_file_chunks(file_id);
CREATE INDEX idx_rcv_files_group_member_id ON rcv_files(group_member_id);
CREATE INDEX idx_received_probes_user_id ON received_probes(user_id);
CREATE INDEX idx_received_probes_contact_id ON received_probes(contact_id);
CREATE INDEX idx_sent_probe_hashes_user_id ON sent_probe_hashes(user_id);
CREATE INDEX idx_sent_probe_hashes_contact_id ON sent_probe_hashes(contact_id);
CREATE INDEX idx_settings_user_id ON settings(user_id);
CREATE INDEX idx_smp_servers_user_id ON smp_servers(user_id);
CREATE INDEX idx_snd_file_chunks_file_id_connection_id ON snd_file_chunks(file_id, connection_id);
CREATE INDEX idx_snd_files_group_member_id ON snd_files(group_member_id);
CREATE INDEX idx_snd_files_connection_id ON snd_files(connection_id);
CREATE INDEX idx_snd_files_file_id ON snd_files(file_id);
|]
@@ -0,0 +1,39 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230118_recreate_smp_servers where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
-- UNIQUE constraint includes user_id
m20230118_recreate_smp_servers :: Query
m20230118_recreate_smp_servers =
[sql|
DROP INDEX idx_smp_servers_user_id;
CREATE TABLE new_smp_servers (
smp_server_id INTEGER PRIMARY KEY,
host TEXT NOT NULL,
port TEXT NOT NULL,
key_hash BLOB NOT NULL,
basic_auth TEXT,
preset INTEGER NOT NULL DEFAULT 0,
tested INTEGER,
enabled INTEGER NOT NULL DEFAULT 1,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE (user_id, host, port)
);
INSERT INTO new_smp_servers
(smp_server_id, host, port, key_hash, basic_auth, preset, tested, enabled, user_id, created_at, updated_at)
SELECT
smp_server_id, host, port, key_hash, basic_auth, preset, tested, enabled, user_id, created_at, updated_at
FROM smp_servers;
DROP TABLE smp_servers;
ALTER TABLE new_smp_servers RENAME TO smp_servers;
CREATE INDEX idx_smp_servers_user_id ON "smp_servers"(user_id);
|]
@@ -0,0 +1,12 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230129_drop_chat_items_group_idx where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230129_drop_chat_items_group_idx :: Query
m20230129_drop_chat_items_group_idx =
[sql|
DROP INDEX idx_chat_items_group_id;
|]
@@ -0,0 +1,14 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230206_item_deleted_by_group_member_id where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230206_item_deleted_by_group_member_id :: Query
m20230206_item_deleted_by_group_member_id =
[sql|
ALTER TABLE chat_items ADD COLUMN item_deleted_by_group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL;
CREATE INDEX idx_chat_items_item_deleted_by_group_member_id ON chat_items(item_deleted_by_group_member_id);
|]
@@ -0,0 +1,12 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230303_group_link_role where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230303_group_link_role :: Query
m20230303_group_link_role =
[sql|
ALTER TABLE user_contact_links ADD COLUMN group_link_member_role TEXT NULL; -- member or observer
|]
@@ -0,0 +1,22 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230317_hidden_profiles where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230317_hidden_profiles :: Query
m20230317_hidden_profiles =
[sql|
ALTER TABLE users ADD COLUMN view_pwd_hash BLOB;
ALTER TABLE users ADD COLUMN view_pwd_salt BLOB;
ALTER TABLE users ADD COLUMN show_ntfs INTEGER NOT NULL DEFAULT 1;
|]
down_m20230317_hidden_profiles :: Query
down_m20230317_hidden_profiles =
[sql|
ALTER TABLE users DROP COLUMN view_pwd_hash;
ALTER TABLE users DROP COLUMN view_pwd_salt;
ALTER TABLE users DROP COLUMN show_ntfs;
|]
@@ -0,0 +1,56 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230318_file_description where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
-- this table includes file descriptions for the recipients for both sent and received files
-- in the latter case the user is the recipient
m20230318_file_description :: Query
m20230318_file_description =
[sql|
CREATE TABLE xftp_file_descriptions (
file_descr_id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
file_descr_text TEXT NOT NULL,
file_descr_part_no INTEGER NOT NULL DEFAULT(0),
file_descr_complete INTEGER NOT NULL DEFAULT(0),
created_at TEXT NOT NULL DEFAULT(datetime('now')),
updated_at TEXT NOT NULL DEFAULT(datetime('now'))
);
ALTER TABLE files ADD COLUMN agent_snd_file_id BLOB NULL;
ALTER TABLE files ADD COLUMN private_snd_file_descr TEXT NULL;
ALTER TABLE snd_files ADD COLUMN file_descr_id INTEGER NULL
REFERENCES xftp_file_descriptions ON DELETE SET NULL;
CREATE INDEX idx_snd_files_file_descr_id ON snd_files(file_descr_id);
ALTER TABLE rcv_files ADD COLUMN file_descr_id INTEGER NULL
REFERENCES xftp_file_descriptions ON DELETE SET NULL;
CREATE INDEX idx_rcv_files_file_descr_id ON rcv_files(file_descr_id);
ALTER TABLE rcv_files ADD COLUMN agent_rcv_file_id BLOB NULL;
|]
down_m20230318_file_description :: Query
down_m20230318_file_description =
[sql|
ALTER TABLE rcv_files DROP COLUMN agent_rcv_file_id;
DROP INDEX idx_rcv_files_file_descr_id;
ALTER TABLE rcv_files DROP COLUMN file_descr_id;
DROP INDEX idx_snd_files_file_descr_id;
ALTER TABLE snd_files DROP COLUMN file_descr_id;
ALTER TABLE files DROP COLUMN private_snd_file_descr;
ALTER TABLE files DROP COLUMN agent_snd_file_id;
DROP TABLE xftp_file_descriptions;
|]
@@ -0,0 +1,28 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230321_agent_file_deleted where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230321_agent_file_deleted :: Query
m20230321_agent_file_deleted =
[sql|
PRAGMA ignore_check_constraints=ON;
ALTER TABLE files ADD COLUMN agent_snd_file_deleted INTEGER DEFAULT 0 CHECK (agent_snd_file_deleted NOT NULL);
UPDATE files SET agent_snd_file_deleted = 0;
ALTER TABLE rcv_files ADD COLUMN agent_rcv_file_deleted INTEGER DEFAULT 0 CHECK (agent_rcv_file_deleted NOT NULL);
UPDATE rcv_files SET agent_rcv_file_deleted = 0;
PRAGMA ignore_check_constraints=OFF;
|]
down_m20230321_agent_file_deleted :: Query
down_m20230321_agent_file_deleted =
[sql|
ALTER TABLE rcv_files DROP COLUMN agent_rcv_file_deleted;
ALTER TABLE files DROP COLUMN agent_snd_file_deleted;
|]
@@ -0,0 +1,18 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230328_files_protocol where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230328_files_protocol :: Query
m20230328_files_protocol =
[sql|
ALTER TABLE files ADD COLUMN protocol TEXT NOT NULL DEFAULT 'smp';
|]
down_m20230328_files_protocol :: Query
down_m20230328_files_protocol =
[sql|
ALTER TABLE files DROP COLUMN protocol;
|]
@@ -0,0 +1,20 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230402_protocol_servers where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230402_protocol_servers :: Query
m20230402_protocol_servers =
[sql|
ALTER TABLE smp_servers RENAME TO protocol_servers;
ALTER TABLE protocol_servers ADD COLUMN protocol TEXT NOT NULL DEFAULT 'smp';
|]
down_m20230402_protocol_servers :: Query
down_m20230402_protocol_servers =
[sql|
ALTER TABLE protocol_servers DROP COLUMN protocol;
ALTER TABLE protocol_servers RENAME TO smp_servers;
|]
@@ -0,0 +1,35 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230411_extra_xftp_file_descriptions where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230411_extra_xftp_file_descriptions :: Query
m20230411_extra_xftp_file_descriptions =
[sql|
CREATE TABLE extra_xftp_file_descriptions (
extra_file_descr_id INTEGER PRIMARY KEY,
file_id INTEGER NOT NULL REFERENCES files ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
file_descr_text TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT(datetime('now')),
updated_at TEXT NOT NULL DEFAULT(datetime('now'))
);
CREATE INDEX idx_extra_xftp_file_descriptions_file_id ON extra_xftp_file_descriptions(file_id);
CREATE INDEX idx_extra_xftp_file_descriptions_user_id ON extra_xftp_file_descriptions(user_id);
CREATE INDEX idx_xftp_file_descriptions_user_id ON xftp_file_descriptions(user_id);
|]
down_m20230411_extra_xftp_file_descriptions :: Query
down_m20230411_extra_xftp_file_descriptions =
[sql|
DROP INDEX idx_xftp_file_descriptions_user_id;
DROP INDEX idx_extra_xftp_file_descriptions_user_id;
DROP INDEX idx_extra_xftp_file_descriptions_file_id;
DROP TABLE extra_xftp_file_descriptions;
|]
@@ -0,0 +1,18 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230420_rcv_files_to_receive where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230420_rcv_files_to_receive :: Query
m20230420_rcv_files_to_receive =
[sql|
ALTER TABLE rcv_files ADD COLUMN to_receive INTEGER;
|]
down_m20230420_rcv_files_to_receive :: Query
down_m20230420_rcv_files_to_receive =
[sql|
ALTER TABLE rcv_files DROP COLUMN to_receive;
|]
@@ -0,0 +1,18 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230422_profile_contact_links where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230422_profile_contact_links :: Query
m20230422_profile_contact_links =
[sql|
ALTER TABLE contact_profiles ADD COLUMN contact_link BLOB;
|]
down_m20230422_profile_contact_links :: Query
down_m20230422_profile_contact_links =
[sql|
ALTER TABLE contact_profiles DROP COLUMN contact_link;
|]
@@ -0,0 +1,37 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230504_recreate_msg_delivery_events_cleanup_messages where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230504_recreate_msg_delivery_events_cleanup_messages :: Query
m20230504_recreate_msg_delivery_events_cleanup_messages =
[sql|
DROP TABLE msg_delivery_events;
CREATE TABLE msg_delivery_events (
msg_delivery_event_id INTEGER PRIMARY KEY,
msg_delivery_id INTEGER NOT NULL REFERENCES msg_deliveries ON DELETE CASCADE,
delivery_status TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
DELETE FROM messages WHERE created_at < datetime('now', '-30 days');
|]
down_m20230504_recreate_msg_delivery_events_cleanup_messages :: Query
down_m20230504_recreate_msg_delivery_events_cleanup_messages =
[sql|
DROP TABLE msg_delivery_events;
CREATE TABLE msg_delivery_events (
msg_delivery_event_id INTEGER PRIMARY KEY,
msg_delivery_id INTEGER NOT NULL REFERENCES msg_deliveries ON DELETE CASCADE, -- non UNIQUE for multiple events per msg delivery
delivery_status TEXT NOT NULL, -- see MsgDeliveryStatus for allowed values
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE (msg_delivery_id, delivery_status)
);
|]
@@ -0,0 +1,29 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230505_chat_item_versions where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230505_chat_item_versions :: Query
m20230505_chat_item_versions =
[sql|
CREATE TABLE chat_item_versions ( -- contains versions only for edited chat items, including current version
chat_item_version_id INTEGER PRIMARY KEY AUTOINCREMENT,
chat_item_id INTEGER NOT NULL REFERENCES chat_items ON DELETE CASCADE,
msg_content TEXT NOT NULL,
item_version_ts TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT(datetime('now')),
updated_at TEXT NOT NULL DEFAULT(datetime('now'))
);
CREATE INDEX idx_chat_item_versions_chat_item_id ON chat_item_versions(chat_item_id);
|]
down_m20230505_chat_item_versions :: Query
down_m20230505_chat_item_versions =
[sql|
DROP INDEX idx_chat_item_versions_chat_item_id;
DROP TABLE chat_item_versions;
|]
@@ -0,0 +1,47 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230511_reactions where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230511_reactions :: Query
m20230511_reactions =
[sql|
CREATE TABLE chat_item_reactions (
chat_item_reaction_id INTEGER PRIMARY KEY AUTOINCREMENT,
item_member_id BLOB, -- member that created item, NULL for items in direct chats
shared_msg_id BLOB NOT NULL,
contact_id INTEGER REFERENCES contacts ON DELETE CASCADE,
group_id INTEGER REFERENCES groups ON DELETE CASCADE,
group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL, -- member that sent reaction, NULL for items in direct chats
created_by_msg_id INTEGER REFERENCES messages(message_id) ON DELETE SET NULL,
reaction TEXT NOT NULL, -- JSON of MsgReaction
reaction_sent INTEGER NOT NULL, -- 0 for received, 1 for sent
reaction_ts TEXT NOT NULL, -- broker_ts of creating message for received, created_at for sent
created_at TEXT NOT NULL DEFAULT(datetime('now')),
updated_at TEXT NOT NULL DEFAULT(datetime('now'))
);
CREATE INDEX idx_chat_item_reactions_shared_msg_id ON chat_item_reactions(shared_msg_id);
CREATE INDEX idx_chat_item_reactions_contact_id ON chat_item_reactions(contact_id);
CREATE INDEX idx_chat_item_reactions_group_id ON chat_item_reactions(group_id);
CREATE INDEX idx_chat_item_reactions_group_member_id ON chat_item_reactions(group_member_id);
CREATE INDEX idx_chat_item_reactions_contact ON chat_item_reactions(contact_id, shared_msg_id);
CREATE INDEX idx_chat_item_reactions_group ON chat_item_reactions(group_id, shared_msg_id);
|]
down_m20230511_reactions :: Query
down_m20230511_reactions =
[sql|
DROP INDEX idx_chat_item_reactions_group;
DROP INDEX idx_chat_item_reactions_contact;
DROP INDEX idx_chat_item_reactions_group_member_id;
DROP INDEX idx_chat_item_reactions_group_id;
DROP INDEX idx_chat_item_reactions_contact_id;
DROP INDEX idx_chat_item_reactions_shared_msg_id;
DROP TABLE chat_item_reactions;
|]
@@ -0,0 +1,18 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230519_item_deleted_ts where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230519_item_deleted_ts :: Query
m20230519_item_deleted_ts =
[sql|
ALTER TABLE chat_items ADD COLUMN item_deleted_ts TEXT;
|]
down_m20230519_item_deleted_ts :: Query
down_m20230519_item_deleted_ts =
[sql|
ALTER TABLE chat_items DROP COLUMN item_deleted_ts;
|]
@@ -0,0 +1,22 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230526_indexes where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230526_indexes :: Query
m20230526_indexes =
[sql|
CREATE INDEX idx_messages_created_at ON messages(created_at);
CREATE INDEX idx_chat_item_reactions_created_by_msg_id ON chat_item_reactions(created_by_msg_id);
|]
down_m20230526_indexes :: Query
down_m20230526_indexes =
[sql|
DROP INDEX idx_chat_item_reactions_created_by_msg_id;
DROP INDEX idx_messages_created_at;
|]
@@ -0,0 +1,30 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230529_indexes where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230529_indexes :: Query
m20230529_indexes =
[sql|
DROP INDEX idx_chat_items_timed_delete_at;
CREATE INDEX idx_chat_items_timed_delete_at ON chat_items(user_id, timed_delete_at);
CREATE INDEX idx_group_members_group_id ON group_members(user_id, group_id);
CREATE INDEX idx_msg_deliveries_agent_ack_cmd_id ON msg_deliveries(connection_id, agent_ack_cmd_id);
|]
down_m20230529_indexes :: Query
down_m20230529_indexes =
[sql|
DROP INDEX idx_msg_deliveries_agent_ack_cmd_id;
DROP INDEX idx_group_members_group_id;
DROP INDEX idx_chat_items_timed_delete_at;
CREATE INDEX idx_chat_items_timed_delete_at ON chat_items(timed_delete_at);
|]
@@ -0,0 +1,22 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230608_deleted_contacts where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230608_deleted_contacts :: Query
m20230608_deleted_contacts =
[sql|
ALTER TABLE contacts ADD COLUMN deleted INTEGER NOT NULL DEFAULT 0;
CREATE INDEX msg_delivery_events_msg_delivery_id ON msg_delivery_events(msg_delivery_id);
|]
down_m20230608_deleted_contacts :: Query
down_m20230608_deleted_contacts =
[sql|
DROP INDEX msg_delivery_events_msg_delivery_id;
ALTER TABLE contacts DROP COLUMN deleted;
|]
@@ -0,0 +1,20 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230618_favorite_chats where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230618_favorite_chats :: Query
m20230618_favorite_chats =
[sql|
ALTER TABLE contacts ADD COLUMN favorite INTEGER NOT NULL DEFAULT 0;
ALTER TABLE groups ADD COLUMN favorite INTEGER NOT NULL DEFAULT 0;
|]
down_m20230618_favorite_chats :: Query
down_m20230618_favorite_chats =
[sql|
ALTER TABLE contacts DROP COLUMN favorite;
ALTER TABLE groups DROP COLUMN favorite;
|]
@@ -0,0 +1,41 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230621_chat_item_moderations where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
-- moderations that could not be applied - for messages that haven't been received at the time of moderation
m20230621_chat_item_moderations :: Query
m20230621_chat_item_moderations =
[sql|
CREATE TABLE chat_item_moderations (
chat_item_moderation_id INTEGER PRIMARY KEY,
group_id INTEGER NOT NULL REFERENCES groups ON DELETE CASCADE,
moderator_member_id INTEGER NOT NULL REFERENCES group_members ON DELETE CASCADE,
item_member_id BLOB NOT NULL,
shared_msg_id BLOB NOT NULL,
created_by_msg_id INTEGER REFERENCES messages(message_id) ON DELETE SET NULL,
moderated_at TEXT NOT NULL, -- broker_ts of creating message
created_at TEXT NOT NULL DEFAULT(datetime('now')),
updated_at TEXT NOT NULL DEFAULT(datetime('now'))
);
CREATE INDEX idx_chat_item_moderations_group_id ON chat_item_moderations(group_id);
CREATE INDEX idx_chat_item_moderations_moderator_member_id ON chat_item_moderations(moderator_member_id);
CREATE INDEX idx_chat_item_moderations_created_by_msg_id ON chat_item_moderations(created_by_msg_id);
CREATE INDEX idx_chat_item_moderations_group ON chat_item_moderations(group_id, item_member_id, shared_msg_id);
|]
down_m20230621_chat_item_moderations :: Query
down_m20230621_chat_item_moderations =
[sql|
DROP INDEX idx_chat_item_moderations_group;
DROP INDEX idx_chat_item_moderations_created_by_msg_id;
DROP INDEX idx_chat_item_moderations_moderator_member_id;
DROP INDEX idx_chat_item_moderations_group_id;
DROP TABLE chat_item_moderations;
|]
@@ -0,0 +1,24 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230705_delivery_receipts where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230705_delivery_receipts :: Query
m20230705_delivery_receipts =
[sql|
ALTER TABLE users ADD COLUMN send_rcpts_contacts INTEGER NOT NULL DEFAULT 0;
ALTER TABLE users ADD COLUMN send_rcpts_small_groups INTEGER NOT NULL DEFAULT 0;
ALTER TABLE contacts ADD COLUMN send_rcpts INTEGER;
ALTER TABLE groups ADD COLUMN send_rcpts INTEGER;
|]
down_m20230705_delivery_receipts :: Query
down_m20230705_delivery_receipts =
[sql|
ALTER TABLE users DROP COLUMN send_rcpts_contacts;
ALTER TABLE users DROP COLUMN send_rcpts_small_groups;
ALTER TABLE contacts DROP COLUMN send_rcpts;
ALTER TABLE groups DROP COLUMN send_rcpts;
|]
@@ -0,0 +1,33 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230721_group_snd_item_statuses where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230721_group_snd_item_statuses :: Query
m20230721_group_snd_item_statuses =
[sql|
CREATE TABLE group_snd_item_statuses (
group_snd_item_status_id INTEGER PRIMARY KEY,
chat_item_id INTEGER NOT NULL REFERENCES chat_items ON DELETE CASCADE,
group_member_id INTEGER NOT NULL REFERENCES group_members ON DELETE CASCADE,
group_snd_item_status TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT(datetime('now')),
updated_at TEXT NOT NULL DEFAULT(datetime('now'))
);
CREATE INDEX idx_group_snd_item_statuses_chat_item_id ON group_snd_item_statuses(chat_item_id);
CREATE INDEX idx_group_snd_item_statuses_group_member_id ON group_snd_item_statuses(group_member_id);
UPDATE users SET send_rcpts_small_groups = 1 WHERE send_rcpts_contacts = 1;
|]
down_m20230721_group_snd_item_statuses :: Query
down_m20230721_group_snd_item_statuses =
[sql|
DROP INDEX idx_group_snd_item_statuses_group_member_id;
DROP INDEX idx_group_snd_item_statuses_chat_item_id;
DROP TABLE group_snd_item_statuses;
|]
@@ -0,0 +1,18 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230814_indexes where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230814_indexes :: Query
m20230814_indexes =
[sql|
CREATE INDEX idx_chat_items_user_id_item_status ON chat_items(user_id, item_status);
|]
down_m20230814_indexes :: Query
down_m20230814_indexes =
[sql|
DROP INDEX idx_chat_items_user_id_item_status;
|]
@@ -0,0 +1,20 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230827_file_encryption where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230827_file_encryption :: Query
m20230827_file_encryption =
[sql|
ALTER TABLE files ADD COLUMN file_crypto_key BLOB;
ALTER TABLE files ADD COLUMN file_crypto_nonce BLOB;
|]
down_m20230827_file_encryption :: Query
down_m20230827_file_encryption =
[sql|
ALTER TABLE files DROP COLUMN file_crypto_key;
ALTER TABLE files DROP COLUMN file_crypto_nonce;
|]
@@ -0,0 +1,26 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230829_connections_chat_vrange where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230829_connections_chat_vrange :: Query
m20230829_connections_chat_vrange =
[sql|
ALTER TABLE connections ADD COLUMN peer_chat_min_version INTEGER NOT NULL DEFAULT 1;
ALTER TABLE connections ADD COLUMN peer_chat_max_version INTEGER NOT NULL DEFAULT 1;
ALTER TABLE contact_requests ADD COLUMN peer_chat_min_version INTEGER NOT NULL DEFAULT 1;
ALTER TABLE contact_requests ADD COLUMN peer_chat_max_version INTEGER NOT NULL DEFAULT 1;
|]
down_m20230829_connections_chat_vrange :: Query
down_m20230829_connections_chat_vrange =
[sql|
ALTER TABLE contact_requests DROP COLUMN peer_chat_max_version;
ALTER TABLE contact_requests DROP COLUMN peer_chat_min_version;
ALTER TABLE connections DROP COLUMN peer_chat_max_version;
ALTER TABLE connections DROP COLUMN peer_chat_min_version;
|]
@@ -0,0 +1,20 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230903_connections_to_subscribe where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230903_connections_to_subscribe :: Query
m20230903_connections_to_subscribe =
[sql|
ALTER TABLE connections ADD COLUMN to_subscribe INTEGER DEFAULT 0 NOT NULL;
CREATE INDEX idx_connections_to_subscribe ON connections(to_subscribe);
|]
down_m20230903_connections_to_subscribe :: Query
down_m20230903_connections_to_subscribe =
[sql|
DROP INDEX idx_connections_to_subscribe;
ALTER TABLE connections DROP COLUMN to_subscribe;
|]
@@ -0,0 +1,27 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230913_member_contacts where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230913_member_contacts :: Query
m20230913_member_contacts =
[sql|
ALTER TABLE contacts ADD COLUMN contact_group_member_id INTEGER
REFERENCES group_members(group_member_id) ON DELETE SET NULL;
CREATE INDEX idx_contacts_contact_group_member_id ON contacts(contact_group_member_id);
ALTER TABLE contacts ADD COLUMN contact_grp_inv_sent INTEGER NOT NULL DEFAULT 0;
|]
down_m20230913_member_contacts :: Query
down_m20230913_member_contacts =
[sql|
ALTER TABLE contacts DROP COLUMN contact_grp_inv_sent;
DROP INDEX idx_contacts_contact_group_member_id;
ALTER TABLE contacts DROP COLUMN contact_group_member_id;
|]
@@ -0,0 +1,169 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230914_member_probes where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230914_member_probes :: Query
m20230914_member_probes =
[sql|
CREATE TABLE new__sent_probes(
sent_probe_id INTEGER PRIMARY KEY,
contact_id INTEGER REFERENCES contacts ON DELETE CASCADE,
group_member_id INTEGER REFERENCES group_members ON DELETE CASCADE,
probe BLOB NOT NULL,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
created_at TEXT CHECK(created_at NOT NULL),
updated_at TEXT CHECK(updated_at NOT NULL),
UNIQUE(user_id, probe)
);
CREATE TABLE new__sent_probe_hashes(
sent_probe_hash_id INTEGER PRIMARY KEY,
sent_probe_id INTEGER NOT NULL REFERENCES new__sent_probes ON DELETE CASCADE,
contact_id INTEGER REFERENCES contacts ON DELETE CASCADE,
group_member_id INTEGER REFERENCES group_members ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
created_at TEXT CHECK(created_at NOT NULL),
updated_at TEXT CHECK(updated_at NOT NULL)
);
CREATE TABLE new__received_probes(
received_probe_id INTEGER PRIMARY KEY,
contact_id INTEGER REFERENCES contacts ON DELETE CASCADE,
group_member_id INTEGER REFERENCES group_members ON DELETE CASCADE,
probe BLOB,
probe_hash BLOB NOT NULL,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
created_at TEXT CHECK(created_at NOT NULL),
updated_at TEXT CHECK(updated_at NOT NULL)
);
INSERT INTO new__sent_probes
(sent_probe_id, contact_id, probe, user_id, created_at, updated_at)
SELECT
sent_probe_id, contact_id, probe, user_id, created_at, updated_at
FROM sent_probes;
INSERT INTO new__sent_probe_hashes
(sent_probe_hash_id, sent_probe_id, contact_id, user_id, created_at, updated_at)
SELECT
sent_probe_hash_id, sent_probe_id, contact_id, user_id, created_at, updated_at
FROM sent_probe_hashes;
INSERT INTO new__received_probes
(received_probe_id, contact_id, probe, probe_hash, user_id, created_at, updated_at)
SELECT
received_probe_id, contact_id, probe, probe_hash, user_id, created_at, updated_at
FROM received_probes;
DROP INDEX idx_sent_probe_hashes_user_id;
DROP INDEX idx_sent_probe_hashes_contact_id;
DROP INDEX idx_received_probes_user_id;
DROP INDEX idx_received_probes_contact_id;
DROP TABLE sent_probes;
DROP TABLE sent_probe_hashes;
DROP TABLE received_probes;
ALTER TABLE new__sent_probes RENAME TO sent_probes;
ALTER TABLE new__sent_probe_hashes RENAME TO sent_probe_hashes;
ALTER TABLE new__received_probes RENAME TO received_probes;
CREATE INDEX idx_sent_probes_user_id ON sent_probes(user_id);
CREATE INDEX idx_sent_probes_contact_id ON sent_probes(contact_id);
CREATE INDEX idx_sent_probes_group_member_id ON sent_probes(group_member_id);
CREATE INDEX idx_sent_probe_hashes_user_id ON sent_probe_hashes(user_id);
CREATE INDEX idx_sent_probe_hashes_sent_probe_id ON sent_probe_hashes(sent_probe_id);
CREATE INDEX idx_sent_probe_hashes_contact_id ON sent_probe_hashes(contact_id);
CREATE INDEX idx_sent_probe_hashes_group_member_id ON sent_probe_hashes(group_member_id);
CREATE INDEX idx_received_probes_user_id ON received_probes(user_id);
CREATE INDEX idx_received_probes_contact_id ON received_probes(contact_id);
CREATE INDEX idx_received_probes_probe ON received_probes(probe);
CREATE INDEX idx_received_probes_probe_hash ON received_probes(probe_hash);
|]
down_m20230914_member_probes :: Query
down_m20230914_member_probes =
[sql|
CREATE TABLE old__sent_probes(
sent_probe_id INTEGER PRIMARY KEY,
contact_id INTEGER NOT NULL REFERENCES contacts ON DELETE CASCADE,
probe BLOB NOT NULL,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
created_at TEXT CHECK(created_at NOT NULL),
updated_at TEXT CHECK(updated_at NOT NULL),
UNIQUE(user_id, probe)
);
CREATE TABLE old__sent_probe_hashes(
sent_probe_hash_id INTEGER PRIMARY KEY,
sent_probe_id INTEGER NOT NULL REFERENCES old__sent_probes ON DELETE CASCADE,
contact_id INTEGER NOT NULL REFERENCES contacts ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
created_at TEXT CHECK(created_at NOT NULL),
updated_at TEXT CHECK(updated_at NOT NULL)
);
CREATE TABLE old__received_probes(
received_probe_id INTEGER PRIMARY KEY,
contact_id INTEGER NOT NULL REFERENCES contacts ON DELETE CASCADE,
probe BLOB,
probe_hash BLOB NOT NULL,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
created_at TEXT CHECK(created_at NOT NULL),
updated_at TEXT CHECK(updated_at NOT NULL)
);
DELETE FROM sent_probes WHERE contact_id IS NULL;
DELETE FROM sent_probe_hashes WHERE contact_id IS NULL;
DELETE FROM received_probes WHERE contact_id IS NULL;
INSERT INTO old__sent_probes
(sent_probe_id, contact_id, probe, user_id, created_at, updated_at)
SELECT
sent_probe_id, contact_id, probe, user_id, created_at, updated_at
FROM sent_probes;
INSERT INTO old__sent_probe_hashes
(sent_probe_hash_id, sent_probe_id, contact_id, user_id, created_at, updated_at)
SELECT
sent_probe_hash_id, sent_probe_id, contact_id, user_id, created_at, updated_at
FROM sent_probe_hashes;
INSERT INTO old__received_probes
(received_probe_id, contact_id, probe, probe_hash, user_id, created_at, updated_at)
SELECT
received_probe_id, contact_id, probe, probe_hash, user_id, created_at, updated_at
FROM received_probes;
DROP INDEX idx_sent_probes_user_id;
DROP INDEX idx_sent_probes_contact_id;
DROP INDEX idx_sent_probes_group_member_id;
DROP INDEX idx_sent_probe_hashes_user_id;
DROP INDEX idx_sent_probe_hashes_sent_probe_id;
DROP INDEX idx_sent_probe_hashes_contact_id;
DROP INDEX idx_sent_probe_hashes_group_member_id;
DROP INDEX idx_received_probes_user_id;
DROP INDEX idx_received_probes_contact_id;
DROP INDEX idx_received_probes_probe;
DROP INDEX idx_received_probes_probe_hash;
DROP TABLE sent_probes;
DROP TABLE sent_probe_hashes;
DROP TABLE received_probes;
ALTER TABLE old__sent_probes RENAME TO sent_probes;
ALTER TABLE old__sent_probe_hashes RENAME TO sent_probe_hashes;
ALTER TABLE old__received_probes RENAME TO received_probes;
CREATE INDEX idx_received_probes_user_id ON received_probes(user_id);
CREATE INDEX idx_received_probes_contact_id ON received_probes(contact_id);
CREATE INDEX idx_sent_probe_hashes_user_id ON sent_probe_hashes(user_id);
CREATE INDEX idx_sent_probe_hashes_contact_id ON sent_probe_hashes(contact_id);
|]
@@ -0,0 +1,18 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20230926_contact_status where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20230926_contact_status :: Query
m20230926_contact_status =
[sql|
ALTER TABLE contacts ADD COLUMN contact_status TEXT NOT NULL DEFAULT 'active';
|]
down_m20230926_contact_status :: Query
down_m20230926_contact_status =
[sql|
ALTER TABLE contacts DROP COLUMN contact_status;
|]
@@ -0,0 +1,28 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20231002_conn_initiated where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20231002_conn_initiated :: Query
m20231002_conn_initiated =
[sql|
ALTER TABLE connections ADD COLUMN contact_conn_initiated INTEGER NOT NULL DEFAULT 0;
UPDATE connections SET conn_req_inv = NULL WHERE conn_status IN ('ready', 'deleted');
CREATE INDEX idx_sent_probes_created_at ON sent_probes(created_at);
CREATE INDEX idx_sent_probe_hashes_created_at ON sent_probe_hashes(created_at);
CREATE INDEX idx_received_probes_created_at ON received_probes(created_at);
|]
down_m20231002_conn_initiated :: Query
down_m20231002_conn_initiated =
[sql|
DROP INDEX idx_sent_probes_created_at;
DROP INDEX idx_sent_probe_hashes_created_at;
DROP INDEX idx_received_probes_created_at;
ALTER TABLE connections DROP COLUMN contact_conn_initiated;
|]
@@ -0,0 +1,24 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20231009_via_group_link_uri_hash where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20231009_via_group_link_uri_hash :: Query
m20231009_via_group_link_uri_hash =
[sql|
CREATE INDEX idx_connections_conn_req_inv ON connections(conn_req_inv);
ALTER TABLE groups ADD COLUMN via_group_link_uri_hash BLOB;
CREATE INDEX idx_groups_via_group_link_uri_hash ON groups(via_group_link_uri_hash);
|]
down_m20231009_via_group_link_uri_hash :: Query
down_m20231009_via_group_link_uri_hash =
[sql|
DROP INDEX idx_groups_via_group_link_uri_hash;
ALTER TABLE groups DROP COLUMN via_group_link_uri_hash;
DROP INDEX idx_connections_conn_req_inv;
|]
@@ -0,0 +1,18 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20231010_member_settings where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20231010_member_settings :: Query
m20231010_member_settings =
[sql|
ALTER TABLE group_members ADD COLUMN show_messages INTEGER NOT NULL DEFAULT 1;
|]
down_m20231010_member_settings :: Query
down_m20231010_member_settings =
[sql|
ALTER TABLE group_members DROP COLUMN show_messages;
|]
@@ -0,0 +1,32 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20231019_indexes where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20231019_indexes :: Query
m20231019_indexes =
[sql|
DROP INDEX idx_connections_conn_req_inv;
CREATE INDEX idx_connections_conn_req_inv ON connections(user_id, conn_req_inv);
DROP INDEX idx_groups_via_group_link_uri_hash;
CREATE INDEX idx_groups_via_group_link_uri_hash ON groups(user_id, via_group_link_uri_hash);
DROP INDEX idx_connections_via_contact_uri_hash;
CREATE INDEX idx_connections_via_contact_uri_hash ON connections(user_id, via_contact_uri_hash);
|]
down_m20231019_indexes :: Query
down_m20231019_indexes =
[sql|
DROP INDEX idx_connections_conn_req_inv;
CREATE INDEX idx_connections_conn_req_inv ON connections(conn_req_inv);
DROP INDEX idx_groups_via_group_link_uri_hash;
CREATE INDEX idx_groups_via_group_link_uri_hash ON groups(via_group_link_uri_hash);
DROP INDEX idx_connections_via_contact_uri_hash;
CREATE INDEX idx_connections_via_contact_uri_hash ON connections(via_contact_uri_hash);
|]
@@ -0,0 +1,18 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20231030_xgrplinkmem_received where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20231030_xgrplinkmem_received :: Query
m20231030_xgrplinkmem_received =
[sql|
ALTER TABLE group_members ADD COLUMN xgrplinkmem_received INTEGER NOT NULL DEFAULT 0;
|]
down_m20231030_xgrplinkmem_received :: Query
down_m20231030_xgrplinkmem_received =
[sql|
ALTER TABLE group_members DROP COLUMN xgrplinkmem_received;
|]
@@ -0,0 +1,18 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20231107_indexes where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20231107_indexes :: Query
m20231107_indexes =
[sql|
CREATE INDEX idx_contact_profiles_contact_link ON contact_profiles(user_id, contact_link);
|]
down_m20231107_indexes :: Query
down_m20231107_indexes =
[sql|
DROP INDEX idx_contact_profiles_contact_link;
|]
@@ -0,0 +1,53 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20231113_group_forward where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20231113_group_forward :: Query
m20231113_group_forward =
[sql|
ALTER TABLE group_member_intros ADD COLUMN intro_chat_protocol_version INTEGER NOT NULL DEFAULT 3;
CREATE INDEX idx_group_member_intros_re_group_member_id ON group_member_intros(re_group_member_id);
ALTER TABLE group_members ADD COLUMN invited_by_group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL;
ALTER TABLE group_members ADD COLUMN peer_chat_min_version INTEGER NOT NULL DEFAULT 1;
ALTER TABLE group_members ADD COLUMN peer_chat_max_version INTEGER NOT NULL DEFAULT 1;
CREATE INDEX idx_group_members_invited_by_group_member_id ON group_members(invited_by_group_member_id);
UPDATE group_members
SET (peer_chat_min_version, peer_chat_max_version) = (c.peer_chat_min_version, c.peer_chat_max_version)
FROM connections c
WHERE c.group_member_id = group_members.group_member_id;
ALTER TABLE messages ADD COLUMN author_group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL;
ALTER TABLE messages ADD COLUMN forwarded_by_group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL;
CREATE INDEX idx_messages_author_group_member_id ON messages(author_group_member_id);
CREATE INDEX idx_messages_forwarded_by_group_member_id ON messages(forwarded_by_group_member_id);
CREATE INDEX idx_messages_group_id_shared_msg_id ON messages(group_id, shared_msg_id);
ALTER TABLE chat_items ADD COLUMN forwarded_by_group_member_id INTEGER REFERENCES group_members ON DELETE SET NULL;
CREATE INDEX idx_chat_items_forwarded_by_group_member_id ON chat_items(forwarded_by_group_member_id);
|]
down_m20231113_group_forward :: Query
down_m20231113_group_forward =
[sql|
DROP INDEX idx_chat_items_forwarded_by_group_member_id;
ALTER TABLE chat_items DROP COLUMN forwarded_by_group_member_id;
DROP INDEX idx_messages_group_id_shared_msg_id;
DROP INDEX idx_messages_forwarded_by_group_member_id;
DROP INDEX idx_messages_author_group_member_id;
ALTER TABLE messages DROP COLUMN forwarded_by_group_member_id;
ALTER TABLE messages DROP COLUMN author_group_member_id;
DROP INDEX idx_group_members_invited_by_group_member_id;
ALTER TABLE group_members DROP COLUMN peer_chat_max_version;
ALTER TABLE group_members DROP COLUMN peer_chat_min_version;
ALTER TABLE group_members DROP COLUMN invited_by_group_member_id;
DROP INDEX idx_group_member_intros_re_group_member_id;
ALTER TABLE group_member_intros DROP COLUMN intro_chat_protocol_version;
|]
@@ -0,0 +1,45 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20231114_remote_control where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20231114_remote_control :: Query
m20231114_remote_control =
[sql|
CREATE TABLE remote_hosts ( -- e.g., mobiles known to a desktop app
remote_host_id INTEGER PRIMARY KEY AUTOINCREMENT,
host_device_name TEXT NOT NULL,
store_path TEXT NOT NULL, -- relative folder name for host files
ca_key BLOB NOT NULL,
ca_cert BLOB NOT NULL,
id_key BLOB NOT NULL, -- long-term/identity signing key
host_fingerprint BLOB NOT NULL, -- remote host CA cert fingerprint, set when connected
host_dh_pub BLOB NOT NULL -- last session DH key
);
CREATE UNIQUE INDEX idx_remote_hosts_host_fingerprint ON remote_hosts(host_fingerprint);
CREATE TABLE remote_controllers ( -- e.g., desktops known to a mobile app
remote_ctrl_id INTEGER PRIMARY KEY AUTOINCREMENT,
ctrl_device_name TEXT NOT NULL,
ca_key BLOB NOT NULL,
ca_cert BLOB NOT NULL,
ctrl_fingerprint BLOB NOT NULL, -- remote controller CA cert fingerprint, set when connected
id_pub BLOB NOT NULL, -- remote controller long-term/identity key to verify signatures
dh_priv_key BLOB NOT NULL, -- last session DH key
prev_dh_priv_key BLOB -- previous session DH key
);
CREATE UNIQUE INDEX idx_remote_controllers_ctrl_fingerprint ON remote_controllers(ctrl_fingerprint);
|]
down_m20231114_remote_control :: Query
down_m20231114_remote_control =
[sql|
DROP INDEX idx_remote_hosts_host_fingerprint;
DROP INDEX idx_remote_controllers_ctrl_fingerprint;
DROP TABLE remote_hosts;
DROP TABLE remote_controllers;
|]
@@ -0,0 +1,22 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20231126_remote_ctrl_address where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20231126_remote_ctrl_address :: Query
m20231126_remote_ctrl_address =
[sql|
ALTER TABLE remote_hosts ADD COLUMN bind_addr TEXT;
ALTER TABLE remote_hosts ADD COLUMN bind_iface TEXT;
ALTER TABLE remote_hosts ADD COLUMN bind_port INTEGER;
|]
down_m20231126_remote_ctrl_address :: Query
down_m20231126_remote_ctrl_address =
[sql|
ALTER TABLE remote_hosts DROP COLUMN bind_addr;
ALTER TABLE remote_hosts DROP COLUMN bind_iface;
ALTER TABLE remote_hosts DROP COLUMN bind_port;
|]
@@ -0,0 +1,38 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20231207_chat_list_pagination where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20231207_chat_list_pagination :: Query
m20231207_chat_list_pagination =
[sql|
UPDATE contacts SET contact_used = 1
WHERE contact_id = (
SELECT contact_id FROM connections
WHERE conn_level = 0 AND via_group_link = 0
);
UPDATE contacts
SET chat_ts = updated_at
WHERE chat_ts IS NULL;
UPDATE groups
SET chat_ts = updated_at
WHERE chat_ts IS NULL;
CREATE INDEX idx_contacts_chat_ts ON contacts(user_id, chat_ts);
CREATE INDEX idx_groups_chat_ts ON groups(user_id, chat_ts);
CREATE INDEX idx_contact_requests_updated_at ON contact_requests(user_id, updated_at);
CREATE INDEX idx_connections_updated_at ON connections(user_id, updated_at);
|]
down_m20231207_chat_list_pagination :: Query
down_m20231207_chat_list_pagination =
[sql|
DROP INDEX idx_contacts_chat_ts;
DROP INDEX idx_groups_chat_ts;
DROP INDEX idx_contact_requests_updated_at;
DROP INDEX idx_connections_updated_at;
|]
@@ -0,0 +1,18 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20231214_item_content_tag where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20231214_item_content_tag :: Query
m20231214_item_content_tag =
[sql|
ALTER TABLE chat_items ADD COLUMN item_content_tag TEXT;
|]
down_m20231214_item_content_tag :: Query
down_m20231214_item_content_tag =
[sql|
ALTER TABLE chat_items DROP COLUMN item_content_tag;
|]
@@ -0,0 +1,107 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20231215_recreate_msg_deliveries where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20231215_recreate_msg_deliveries :: Query
m20231215_recreate_msg_deliveries =
[sql|
DROP VIEW IF EXISTS direct_messages;
DROP VIEW IF EXISTS direct_messages_plain;
DROP VIEW IF EXISTS group_messages;
DROP VIEW IF EXISTS group_messages_plain;
DROP VIEW IF EXISTS all_messages;
DROP VIEW IF EXISTS all_messages_plain;
DROP INDEX msg_delivery_events_msg_delivery_id;
DROP TABLE msg_delivery_events;
DROP INDEX idx_msg_deliveries_message_id;
DROP INDEX idx_msg_deliveries_agent_ack_cmd_id;
CREATE TABLE new_msg_deliveries(
msg_delivery_id INTEGER PRIMARY KEY,
message_id INTEGER NOT NULL REFERENCES messages ON DELETE CASCADE, -- non UNIQUE for group messages and for batched messages
connection_id INTEGER NOT NULL REFERENCES connections ON DELETE CASCADE,
agent_msg_id INTEGER, -- internal agent message ID (NULL while pending), non UNIQUE for batched messages
agent_msg_meta TEXT, -- JSON with timestamps etc. sent in MSG, NULL for sent
chat_ts TEXT NOT NULL DEFAULT(datetime('now')),
created_at TEXT CHECK(created_at NOT NULL),
updated_at TEXT CHECK(updated_at NOT NULL),
agent_ack_cmd_id INTEGER, -- broker_ts for received, created_at for sent
delivery_status TEXT -- MsgDeliveryStatus
);
INSERT INTO new_msg_deliveries (
msg_delivery_id, message_id, connection_id, agent_msg_id, agent_msg_meta,
chat_ts, created_at, updated_at, agent_ack_cmd_id
)
SELECT
msg_delivery_id, message_id, connection_id, agent_msg_id, agent_msg_meta,
chat_ts, created_at, updated_at, agent_ack_cmd_id
FROM msg_deliveries;
DROP TABLE msg_deliveries;
ALTER TABLE new_msg_deliveries RENAME TO msg_deliveries;
CREATE INDEX idx_msg_deliveries_message_id ON "msg_deliveries"(message_id);
CREATE INDEX idx_msg_deliveries_agent_ack_cmd_id ON "msg_deliveries"(connection_id, agent_ack_cmd_id);
CREATE INDEX idx_msg_deliveries_agent_msg_id ON "msg_deliveries"(connection_id, agent_msg_id);
|]
down_m20231215_recreate_msg_deliveries :: Query
down_m20231215_recreate_msg_deliveries =
[sql|
DROP INDEX idx_msg_deliveries_message_id;
DROP INDEX idx_msg_deliveries_agent_ack_cmd_id;
DROP INDEX idx_msg_deliveries_agent_msg_id;
CREATE TABLE old_msg_deliveries(
msg_delivery_id INTEGER PRIMARY KEY,
message_id INTEGER NOT NULL REFERENCES messages ON DELETE CASCADE, -- non UNIQUE for group messages
connection_id INTEGER NOT NULL REFERENCES connections ON DELETE CASCADE,
agent_msg_id INTEGER, -- internal agent message ID(NULL while pending)
agent_msg_meta TEXT, -- JSON with timestamps etc. sent in MSG, NULL for sent
chat_ts TEXT NOT NULL DEFAULT(datetime('now')),
created_at TEXT CHECK(created_at NOT NULL),
updated_at TEXT CHECK(updated_at NOT NULL),
agent_ack_cmd_id INTEGER, -- broker_ts for received, created_at for sent
UNIQUE(connection_id, agent_msg_id)
);
INSERT INTO old_msg_deliveries (
msg_delivery_id, message_id, connection_id, agent_msg_id, agent_msg_meta,
chat_ts, created_at, updated_at, agent_ack_cmd_id
)
WITH unique_msg_deliveries AS (
SELECT
msg_delivery_id, message_id, connection_id, agent_msg_id, agent_msg_meta,
chat_ts, created_at, updated_at, agent_ack_cmd_id,
row_number() OVER connection_id_agent_msg_id_win AS row_number
FROM msg_deliveries
WINDOW connection_id_agent_msg_id_win AS (PARTITION BY connection_id, agent_msg_id ORDER BY created_at ASC, msg_delivery_id ASC)
)
SELECT
msg_delivery_id, message_id, connection_id, agent_msg_id, agent_msg_meta,
chat_ts, created_at, updated_at, agent_ack_cmd_id
FROM unique_msg_deliveries
WHERE row_number = 1;
DROP TABLE msg_deliveries;
ALTER TABLE old_msg_deliveries RENAME TO msg_deliveries;
CREATE INDEX idx_msg_deliveries_message_id ON "msg_deliveries"(message_id);
CREATE INDEX idx_msg_deliveries_agent_ack_cmd_id ON "msg_deliveries"(connection_id, agent_ack_cmd_id);
CREATE TABLE msg_delivery_events (
msg_delivery_event_id INTEGER PRIMARY KEY,
msg_delivery_id INTEGER NOT NULL REFERENCES msg_deliveries ON DELETE CASCADE, -- non UNIQUE for multiple events per msg delivery
delivery_status TEXT NOT NULL, -- see MsgDeliveryStatus for allowed values
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
UNIQUE (msg_delivery_id, delivery_status)
);
CREATE INDEX msg_delivery_events_msg_delivery_id ON msg_delivery_events(msg_delivery_id);
|]
@@ -0,0 +1,42 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20240102_note_folders where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20240102_note_folders :: Query
m20240102_note_folders =
[sql|
CREATE TABLE note_folders (
note_folder_id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
created_at TEXT NOT NULL DEFAULT(datetime('now')),
updated_at TEXT NOT NULL DEFAULT(datetime('now')),
chat_ts TEXT NOT NULL DEFAULT(datetime('now')),
favorite INTEGER NOT NULL DEFAULT 0,
unread_chat INTEGER NOT NULL DEFAULT 0
);
ALTER TABLE chat_items ADD COLUMN note_folder_id INTEGER DEFAULT NULL REFERENCES note_folders ON DELETE CASCADE;
ALTER TABLE files ADD COLUMN note_folder_id INTEGER DEFAULT NULL REFERENCES note_folders ON DELETE CASCADE;
CREATE INDEX chat_items_note_folder_id ON chat_items(note_folder_id);
CREATE INDEX files_note_folder_id ON files(note_folder_id);
CREATE INDEX note_folders_user_id ON note_folders(user_id);
INSERT INTO note_folders (user_id) SELECT user_id FROM users;
|]
down_m20240102_note_folders :: Query
down_m20240102_note_folders =
[sql|
DROP INDEX chat_items_note_folder_id;
DROP INDEX files_note_folder_id;
DROP INDEX note_folders_user_id;
ALTER TABLE chat_items DROP COLUMN note_folder_id;
ALTER TABLE files DROP COLUMN note_folder_id;
DROP TABLE note_folders;
|]
@@ -0,0 +1,20 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20240104_members_profile_update where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20240104_members_profile_update :: Query
m20240104_members_profile_update =
[sql|
ALTER TABLE users ADD COLUMN user_member_profile_updated_at TEXT;
ALTER TABLE groups ADD COLUMN user_member_profile_sent_at TEXT;
|]
down_m20240104_members_profile_update :: Query
down_m20240104_members_profile_update =
[sql|
ALTER TABLE groups DROP COLUMN user_member_profile_sent_at;
ALTER TABLE users DROP COLUMN user_member_profile_updated_at;
|]
@@ -0,0 +1,18 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20240115_block_member_for_all where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20240115_block_member_for_all :: Query
m20240115_block_member_for_all =
[sql|
ALTER TABLE group_members ADD COLUMN member_restriction TEXT;
|]
down_m20240115_block_member_for_all :: Query
down_m20240115_block_member_for_all =
[sql|
ALTER TABLE group_members DROP COLUMN member_restriction;
|]
@@ -0,0 +1,26 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20240122_indexes where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20240122_indexes :: Query
m20240122_indexes =
[sql|
CREATE INDEX idx_chat_items_contacts_created_at on chat_items (user_id, contact_id, created_at);
CREATE INDEX idx_chat_items_contacts_item_status on chat_items (user_id, contact_id, item_status);
CREATE INDEX idx_chat_items_groups_item_status on chat_items (user_id, group_id, item_status);
CREATE INDEX idx_chat_items_notes_created_at on chat_items (user_id, note_folder_id, created_at);
CREATE INDEX idx_chat_items_notes_item_status on chat_items (user_id, note_folder_id, item_status);
|]
down_m20240122_indexes :: Query
down_m20240122_indexes =
[sql|
DROP INDEX idx_chat_items_contacts_created_at;
DROP INDEX idx_chat_items_contacts_item_status;
DROP INDEX idx_chat_items_groups_item_status;
DROP INDEX idx_chat_items_notes_created_at;
DROP INDEX idx_chat_items_notes_item_status;
|]
@@ -0,0 +1,22 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20240214_redirect_file_id where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20240214_redirect_file_id :: Query
m20240214_redirect_file_id =
[sql|
ALTER TABLE files ADD COLUMN redirect_file_id INTEGER REFERENCES files ON DELETE CASCADE;
CREATE INDEX idx_files_redirect_file_id on files(redirect_file_id);
|]
down_m20240214_redirect_file_id :: Query
down_m20240214_redirect_file_id =
[sql|
DROP INDEX idx_files_redirect_file_id;
ALTER TABLE files DROP COLUMN redirect_file_id;
|]
@@ -0,0 +1,20 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20240222_app_settings where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20240222_app_settings :: Query
m20240222_app_settings =
[sql|
CREATE TABLE app_settings (
app_settings TEXT NOT NULL
);
|]
down_m20240222_app_settings :: Query
down_m20240222_app_settings =
[sql|
DROP TABLE app_settings;
|]
@@ -0,0 +1,30 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20240226_users_restrict where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20240226_users_restrict :: Query
m20240226_users_restrict =
[sql|
PRAGMA writable_schema=1;
UPDATE sqlite_master
SET sql = replace(sql, 'ON DELETE CASCADE', 'ON DELETE RESTRICT')
WHERE name = 'users' AND type = 'table';
PRAGMA writable_schema=0;
|]
down_m20240226_users_restrict :: Query
down_m20240226_users_restrict =
[sql|
PRAGMA writable_schema=1;
UPDATE sqlite_master
SET sql = replace(sql, 'ON DELETE RESTRICT', 'ON DELETE CASCADE')
WHERE name = 'users' AND type = 'table';
PRAGMA writable_schema=0;
|]
@@ -0,0 +1,30 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20240228_pq where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20240228_pq :: Query
m20240228_pq =
[sql|
ALTER TABLE connections ADD COLUMN conn_chat_version INTEGER;
ALTER TABLE connections ADD COLUMN pq_support INTEGER NOT NULL DEFAULT 0;
ALTER TABLE connections ADD COLUMN pq_encryption INTEGER NOT NULL DEFAULT 0;
ALTER TABLE connections ADD COLUMN pq_snd_enabled INTEGER;
ALTER TABLE connections ADD COLUMN pq_rcv_enabled INTEGER;
ALTER TABLE contact_requests ADD COLUMN pq_support INTEGER NOT NULL DEFAULT 0;
|]
down_m20240228_pq :: Query
down_m20240228_pq =
[sql|
ALTER TABLE contact_requests DROP COLUMN pq_support;
ALTER TABLE connections DROP COLUMN conn_chat_version;
ALTER TABLE connections DROP COLUMN pq_support;
ALTER TABLE connections DROP COLUMN pq_encryption;
ALTER TABLE connections DROP COLUMN pq_snd_enabled;
ALTER TABLE connections DROP COLUMN pq_rcv_enabled;
|]
@@ -0,0 +1,22 @@
{-# LANGUAGE QuasiQuotes #-}
module Simplex.Chat.Store.SQLite.Migrations.M20240313_drop_agent_ack_cmd_id where
import Database.SQLite.Simple (Query)
import Database.SQLite.Simple.QQ (sql)
m20240313_drop_agent_ack_cmd_id :: Query
m20240313_drop_agent_ack_cmd_id =
[sql|
DROP INDEX idx_msg_deliveries_agent_ack_cmd_id;
ALTER TABLE msg_deliveries DROP COLUMN agent_ack_cmd_id;
|]
down_m20240313_drop_agent_ack_cmd_id :: Query
down_m20240313_drop_agent_ack_cmd_id =
[sql|
ALTER TABLE msg_deliveries ADD COLUMN agent_ack_cmd_id INTEGER;
CREATE INDEX idx_msg_deliveries_agent_ack_cmd_id ON msg_deliveries(connection_id, agent_ack_cmd_id);
|]

Some files were not shown because too many files have changed in this diff Show More