-- Commented SQLite database schema. -- -- This file should only be used for documentation, -- do not run this SQL e.g. to create databases. -- This is because we want to be 100% sure -- that new users and users who run the migrations -- get the same database schema. -- -- This is a dump of the database schema using `sqlite3 dc.db .schema`, -- formatted, reordered and commented afterwards. -- Raw dump of the database schema does not have comments -- for deprecated columns and columns added by migrations. CREATE TABLE config ( id INTEGER PRIMARY KEY, keyname TEXT UNIQUE, value TEXT NOT NULL ); CREATE INDEX config_index1 ON config (keyname); CREATE TABLE contacts ( id INTEGER PRIMARY KEY AUTOINCREMENT, -- Name of the contact as set by the user. name TEXT DEFAULT '', -- Normalized name for search. name_normalized TEXT, -- Email address last seen as the From address for this contact. -- For address-contacts that have empty "fingerprint" this should never change. -- For key-contacts this address may change when a new signed message is received. -- -- This is the address messages are sent to unless the key -- advertises a different set of addresses, in which case -- this address should be ignored -- (and not appended to the list of addresses advertised in the key). addr TEXT DEFAULT '' COLLATE NOCASE, -- The origin or source of the contact, -- e.g. whether the contact was added from some chat -- or via SecureJoin. origin INTEGER DEFAULT 0, -- True if the contact is blocked. -- Unlike the chat, contact is either blocked or not, -- there is no third "contact request" state. blocked INTEGER DEFAULT 0, -- Timestamp of the last time any message was received from this contact. last_seen INTEGER DEFAULT 0, -- Key-value parameters. param TEXT DEFAULT '', -- Name of the contact as sent by the contact itself. authname TEXT DEFAULT '', -- Timestamp of the last time we have sent our avatar to this contact. -- Used to decide whether to send the avatar. -- Normally avatars are resent after 14 days. -- This column is reset to 0 when avatar is changed. selfavatar_sent INTEGER DEFAULT 0, -- Last seen message signature from this contact, also known as bio in the UI. status TEXT DEFAULT '', -- True if the contact is a bot. is_bot INTEGER NOT NULL DEFAULT 0, -- OpenPGP key fingerprint for "key-contacts", -- empty string for "address-contacts". fingerprint TEXT NOT NULL DEFAULT '', -- ID of the contact that has "introduced" us to this contact -- by sharing the key with a verified attribute or in a "verified" chat. verifier INTEGER NOT NULL DEFAULT 0 ); CREATE INDEX contacts_index1 ON contacts (name COLLATE NOCASE); CREATE INDEX contacts_index2 ON contacts (addr COLLATE NOCASE); CREATE INDEX contacts_fingerprint_index ON contacts (fingerprint); CREATE TABLE chats ( -- Chat ID 0 should never be used as it is used as a sentinel value in some APIs. -- -- Chat IDs 1 to 9, including 9, are reserved. -- The first proper chat gets ID 10, but may not exist if it is deleted. -- -- Chat ID 3 is the trash chat and this chat ID is assigned to deleted messages -- to create "tombstones". id INTEGER PRIMARY KEY AUTOINCREMENT, -- Chat type, e.g. 100 for single chat, 120 for a group etc. -- Check the Chattype enumeration in the code for concrete values. type INTEGER DEFAULT 0, name TEXT DEFAULT '', -- Normalized name for search. name_normalized TEXT, -- 0 for visible chat, 1 for hidden and 2 for contact request. -- 1 does not necessarily mean that the contact is blocked. blocked INTEGER DEFAULT 0, -- Chat-Group-ID header for encrypted groups and channels. -- Empty for unencrypted groups and single chats. grpid TEXT DEFAULT '', -- Key-value parameters. param TEXT DEFAULT '', -- Chat visibility. -- 0 for normal, 1 for archived and 2 for pinned chats. archived INTEGER DEFAULT 0, locations_send_begin INTEGER DEFAULT 0, locations_send_until INTEGER DEFAULT 0, locations_last_sent INTEGER DEFAULT 0, -- Time when the chat was created. -- Used for sorting in the chatlist when the chat has no messages. created_timestamp INTEGER DEFAULT 0, -- 0 if the chat is not muted. -- -1 if the chat is muted forever. -- Otherwise the timestamp until which the chat is muted. muted_until INTEGER DEFAULT 0, -- Disappearing messages timer. -- 0 means the timer is disabled. ephemeral_timer INTEGER, -- Deprecated, but still used to send Chat-Verified headers -- for existing protected chats. -- All new chats are created as "not protected". protected INTEGER DEFAULT 0, gossiped_timestamp INTEGER DEFAULT 0, -- deprecated 2025-04-08, replaced with gossip_timestamp table -- Unused columns, drafts are now tracked as separate -- messages with a special msgs.state value. draft_timestamp INTEGER DEFAULT 0, draft_txt TEXT DEFAULT '' ); CREATE INDEX chats_index1 ON chats (grpid); CREATE INDEX chats_index2 ON chats (archived); CREATE INDEX chats_index3 ON chats (locations_send_until); CREATE INDEX chats_index4 ON chats (name); CREATE TABLE chats_descriptions ( chat_id INTEGER PRIMARY KEY AUTOINCREMENT, description TEXT NOT NULL DEFAULT '' ) STRICT; -- Chat member lists. -- Saved messages has only self. -- Single chats have only the contact, but not self. -- Groups have self if we are part of the group. CREATE TABLE chats_contacts ( chat_id INTEGER, contact_id INTEGER, add_timestamp NOT NULL DEFAULT 0, remove_timestamp NOT NULL DEFAULT 0, UNIQUE(chat_id, contact_id) ); CREATE INDEX chats_contacts_index1 ON chats_contacts (chat_id); CREATE INDEX chats_contacts_index2 ON chats_contacts (contact_id); -- This table contains "message bubbles" that are normally visible -- and "tombstones" that are put into the trash chat -- or have a "hidden" column set to the true value. -- -- Tombstones are used to avoid downloading and processing -- the same messages twice, e.g. when the message is deleted -- but another copy of it arrives later. CREATE TABLE msgs ( id INTEGER PRIMARY KEY AUTOINCREMENT, -- The messages may be split into pre- and post-message. -- Pre-messages have a Chat-Post-Message-ID header -- which contains the Message-ID of the post-message. -- Post-messages have a Chat-Is-Post-Message header. -- -- For outgoing messages that are split into pre-message -- and post-message, rfc724_mid contains the Message-ID -- of the post-message, and pre_rfc724_mid -- contains the Message-ID of the pre-message. -- -- For incoming messages, when a pre-message arrives, -- rfc724_mid is set to the Message-ID of the post-message, -- and pre_rfc724_mid is set to the Message-ID of the arrived pre-messsage. -- For other messages rfc724_mid is taken from the Message-ID -- and pre_rfc724_mid is set to empty string. -- Message-ID as defined in RFC 724 (now replaced by RFC 5322) rfc724_mid TEXT DEFAULT '', -- Message-ID of the pre-message. pre_rfc724_mid TEXT DEFAULT '', -- Chat ID. -- -- Chat ID 3 is the trash chat, messages with this ID are tombstones. chat_id INTEGER DEFAULT 0, -- Contact ID of the message author. from_id INTEGER DEFAULT 0, -- Mostly unused Contact ID of the first recipient or 0. -- For info messages set to ContactID::INFO (2). -- -- If to_id is set to 2, the message must be displayed -- as an info message even if from_id is not set to 2. -- -- Info messages generated by Webxdc status updates -- have from_id set to the contact ID of the sender -- and to_id set to 2. -- from_id is then used to collapse series of updates -- into a single message (see test_webxdc_info_msg_cleanup_series), -- while to_id of 2 makes sure the message is displayed -- as an info message. to_id INTEGER DEFAULT 0, -- Message viewtype. -- 10 is a text message, -- 20 is an image etc. type INTEGER DEFAULT 0, -- Message state, -- e.g. 10 for fresh incoming messages, -- 26 for outgoing delivered message, -- 28 for outgoing message that got a read receipt. -- -- Messages sent by self, but arriving from a second device -- are still considered "outgoing". state INTEGER DEFAULT 0, -- Size of the attachment for file parts, otherwise 0. bytes INTEGER DEFAULT 0, txt TEXT DEFAULT '', -- Message text for display. txt_normalized TEXT, -- Message text normalized for search. txt_raw TEXT DEFAULT '', -- deprecated 2025-03-29 -- Key-value parameters. param TEXT DEFAULT '', -- For messages bookmarked into the Saved Messages chat, -- ID of the original message, making it possible to jump to it. starred INTEGER DEFAULT 0, -- True if the message is pinned. pinned INTEGER NOT NULL DEFAULT 0, timestamp INTEGER DEFAULT 0, -- Timestamp of the message used for sorting. timestamp_sent INTEGER DEFAULT 0, -- Timestamp of the message as sent in the Date header. timestamp_rcvd INTEGER DEFAULT 0, -- True if the message should not be displayed. -- Most messages that should not be displayed -- better go to the trash chat (ID 3), -- but at least reactions are hidden -- so they still belong to the chat -- and can be marked as noticed when the chat is opened. hidden INTEGER DEFAULT 0, -- mime_headers column actually contains BLOBs, i.e. it may -- contain non-UTF8 MIME messages. TEXT was a bad choice, but -- thanks to SQLite 3 being dynamically typed, there is no need to -- change column type. mime_headers TEXT, -- True if mime_headers column is compressed with Brotli. mime_compressed INTEGER NOT NULL DEFAULT 0, mime_modified INTEGER DEFAULT 0, mime_in_reply_to TEXT, mime_references TEXT, -- Location ID for POI locations manually placed on the map. location_id INTEGER DEFAULT 0, error TEXT DEFAULT '', -- Timer value in seconds. For incoming messages this -- timer starts when message is read, so we want to have -- the value stored here until the timer starts. ephemeral_timer INTEGER DEFAULT 0, -- Timestamp indicating when the message should be -- deleted. It is convenient to store it here because UI -- needs this value to display how much time is left until -- the message is deleted. ephemeral_timestamp INTEGER DEFAULT 0, subject TEXT DEFAULT '', -- Download state for the message. -- 0 for most messages, meaning the message is fully downloaded. -- Otherwise 10 for the message available for download etc. download_state INTEGER DEFAULT 0, -- Information extracted from Received headers -- as a plain text for debugging. hop_info TEXT, -- True if the message is deleted on the server. -- If this is true and another copy of the message arrives -- it should be deleted from the server as well. deleted INTEGER NOT NULL DEFAULT 0, -- -- Unused columns. -- -- Always 1 for new messages. -- Previously: -- 0 if the message is a non-chat message, -- 1 if the message is a chat message, -- 2 if the message is a non-chat reply to a chat message msgrmsg INTEGER DEFAULT 1, server_folder TEXT DEFAULT '', -- Deprecated column that was used before "imap" table, replaced by imap.folder server_uid INTEGER DEFAULT 0, -- Deprecated column that was used before "imap" table, replaced by imap.uid -- Unused column formely used to mark the messages -- that should be moved to the dedicated IMAP folder. -- It was replaced with imap.target, which is also now -- used only to mark the messages on IMAP for deletion. move_state INTEGER DEFAULT 1 ); CREATE INDEX msgs_index1 ON msgs (rfc724_mid); CREATE INDEX msgs_index2 ON msgs (chat_id); CREATE INDEX msgs_index3 ON msgs (timestamp); CREATE INDEX msgs_index4 ON msgs (state); CREATE INDEX msgs_index5 ON msgs (starred); CREATE INDEX msgs_index6 ON msgs (location_id); CREATE INDEX msgs_index7 ON msgs (state, hidden, chat_id, timestamp); CREATE INDEX msgs_index8 ON msgs (ephemeral_timestamp); CREATE INDEX msgs_index9 ON msgs (pre_rfc724_mid); CREATE INDEX msgs_index10 ON msgs (pinned) WHERE pinned=1; CREATE TABLE leftgrps ( id INTEGER PRIMARY KEY, grpid TEXT DEFAULT '' ); CREATE INDEX leftgrps_index1 ON leftgrps (grpid); CREATE TABLE msgs_mdns ( msg_id INTEGER, contact_id INTEGER, timestamp_sent INTEGER DEFAULT 0 ); CREATE INDEX msgs_mdns_index1 ON msgs_mdns (msg_id); CREATE TABLE locations ( id INTEGER PRIMARY KEY AUTOINCREMENT, latitude REAL DEFAULT 0.0, longitude REAL DEFAULT 0.0, accuracy REAL DEFAULT 0.0, timestamp INTEGER DEFAULT 0, chat_id INTEGER DEFAULT 0, from_id INTEGER DEFAULT 0, -- If true, the location is an independent POI -- and should not be part of the path. independent INTEGER DEFAULT 0 ); CREATE INDEX locations_index1 ON locations (from_id); CREATE INDEX locations_index2 ON locations (timestamp); CREATE TABLE devmsglabels ( id INTEGER PRIMARY KEY AUTOINCREMENT, label TEXT, msg_id INTEGER DEFAULT 0 ); CREATE INDEX devmsglabels_index1 ON devmsglabels (label); -- Table to store QR code tokens for SecureJoin protocol. CREATE TABLE tokens ( id INTEGER PRIMARY KEY, -- Namespace is one of: -- 0 - unknown -- 100 - invite number -- 110 - auth namespc INTEGER NOT NULL, foreign_key TEXT DEFAULT '' NOT NULL, token TEXT NOT NULL UNIQUE, timestamp INTEGER DEFAULT 0 NOT NULL ) STRICT; -- State of the scanner of the QR code (Bob) in SecureJoin protocol. CREATE TABLE bobstate ( id INTEGER PRIMARY KEY AUTOINCREMENT, invite TEXT NOT NULL, next_step INTEGER NOT NULL, chat_id INTEGER NOT NULL ); CREATE TABLE smtp ( id INTEGER PRIMARY KEY AUTOINCREMENT, rfc724_mid TEXT NOT NULL, -- Message-ID mime TEXT NOT NULL, -- SMTP payload msg_id INTEGER NOT NULL, -- ID of the message in `msgs` table recipients TEXT NOT NULL, -- List of recipients separated by space retries INTEGER NOT NULL DEFAULT 0 -- Number of failed attempts to send the message ); CREATE TABLE smtp_mdns ( msg_id INTEGER NOT NULL, -- id of the message in msgs table which requested MDN (DEPRECATED 2024-06-21) from_id INTEGER NOT NULL, -- id of the contact that sent the message, MDN destination rfc724_mid TEXT NOT NULL, -- Message-ID header retries INTEGER NOT NULL DEFAULT 0 -- Number of failed attempts to send MDN ); CREATE TABLE smtp_status_updates ( msg_id INTEGER NOT NULL UNIQUE, -- msg_id of the webxdc instance with pending updates first_serial INTEGER NOT NULL, -- id in msgs_status_updates last_serial INTEGER NOT NULL, -- id in msgs_status_updates descr TEXT NOT NULL -- text to send along with the updates ); -- Table of "sync items" to be grouped into sync messages -- and sent to own devices. CREATE TABLE multi_device_sync ( id INTEGER PRIMARY KEY AUTOINCREMENT, -- JSON of the "sync item". item TEXT DEFAULT '' ); CREATE TABLE reactions ( msg_id INTEGER NOT NULL, -- id of the message reacted to contact_id INTEGER NOT NULL, -- id of the contact reacting to the message reaction TEXT DEFAULT '' NOT NULL, -- a sequence of emojis separated by spaces PRIMARY KEY(msg_id, contact_id), FOREIGN KEY(msg_id) REFERENCES msgs(id) ON DELETE CASCADE -- delete reactions when message is deleted FOREIGN KEY(contact_id) REFERENCES contacts(id) ON DELETE CASCADE -- delete reactions when contact is deleted ); CREATE INDEX reactions_index1 ON reactions (msg_id); CREATE TABLE pending_reactions ( rfc724_mid TEXT NOT NULL, contact_id INTEGER NOT NULL, reaction TEXT NOT NULL, timestamp INTEGER NOT NULL, PRIMARY KEY(rfc724_mid, contact_id), FOREIGN KEY(contact_id) REFERENCES contacts(id) ON DELETE CASCADE ) STRICT; -- accumulated reactions received from broadcast owner. -- pairs of reaction and their counts. -- these pairs are given to the UI (for non-broadcasts, the pairs are calculated from the `reactions` table) CREATE TABLE broadcasted_reactions ( msg_id INTEGER NOT NULL DEFAULT 0, reaction TEXT NOT NULL DEFAULT '', count INTEGER NOT NULL DEFAULT 0, FOREIGN KEY(msg_id) REFERENCES msgs(id) ON DELETE CASCADE -- delete reactions when message is deleted ) STRICT; CREATE INDEX broadcasted_reactions_index1 ON broadcasted_reactions (msg_id); -- messages that received reactions from broadcast subscriber to broadcast owner. -- the broadcast owner will send them, accumulated by chat_id, -- to all other subscribers every some minutes, and then remove all entries with the chat_id processed. CREATE TABLE reactions_need_broadcast ( chat_id INTEGER NOT NULL DEFAULT 0, msg_id INTEGER NOT NULL DEFAULT 0, UNIQUE (chat_id, msg_id), FOREIGN KEY(msg_id) REFERENCES msgs(id) ON DELETE CASCADE -- delete reactions when message is deleted ) STRICT; CREATE INDEX reactions_need_broadcast_index1 ON reactions_need_broadcast (chat_id); CREATE TABLE connection_history ( host TEXT NOT NULL, -- server hostname port INTEGER NOT NULL, -- server port alpn TEXT NOT NULL, -- ALPN such as smtp or imap addr TEXT NOT NULL, -- IP address timestamp INTEGER NOT NULL, -- timestamp of the most recent successful connection UNIQUE (host, port, alpn, addr) ) STRICT; CREATE TABLE dns_cache ( hostname TEXT NOT NULL, address TEXT NOT NULL, -- IPv4 or IPv6 address timestamp INTEGER NOT NULL, UNIQUE (hostname, address) ); CREATE TABLE tls_spki ( host TEXT NOT NULL UNIQUE, spki_hash TEXT NOT NULL, -- base64 of SPKI SHA-256 hash timestamp INTEGER NOT NULL -- timestamp of the last time we have seen this key ) STRICT; CREATE INDEX tls_spki_index_timestamp ON tls_spki (timestamp); CREATE TABLE http_cache ( url TEXT PRIMARY KEY, expires INTEGER NOT NULL, -- When the cache entry is considered expired, timestamp in seconds. stale INTEGER NOT NULL, -- When the cache entry is considered stale, timestamp in seconds. blobname TEXT NOT NULL, mimetype TEXT NOT NULL DEFAULT '', -- MIME type extracted from Content-Type header. encoding TEXT NOT NULL DEFAULT '' -- Encoding from Content-Type header. ) STRICT; -- Webxdc updates. CREATE TABLE msgs_status_updates ( id INTEGER PRIMARY KEY AUTOINCREMENT, msg_id INTEGER, update_item TEXT DEFAULT '', uid TEXT UNIQUE, FOREIGN KEY(msg_id) REFERENCES msgs(id) ON DELETE CASCADE ); CREATE INDEX msgs_status_updates_index1 ON msgs_status_updates (msg_id); CREATE INDEX msgs_status_updates_index2 ON msgs_status_updates (uid); -- Webxdc realtime. CREATE TABLE iroh_gossip_peers ( msg_id INTEGER not NULL, topic BLOB NOT NULL, public_key BLOB NOT NULL, relay_server TEXT, UNIQUE (topic, public_key), PRIMARY KEY(topic, public_key) ) STRICT; -- -- OpenPGP. -- -- Storage for own private keys. -- Only one of the keys is used. -- -- In the past mulitple keys could be imported, -- so this table can contain multiple keys for existing users. -- Used key is identified by the "key_id" config value. -- Other keys must never be used, even for decryption. CREATE TABLE keypairs ( id INTEGER PRIMARY KEY AUTOINCREMENT, -- OpenPGP private key stored as a binary blob. private_key UNIQUE NOT NULL, -- Unused public key aka OpenPGP certificate. -- Stored only for compatibility. -- OpenPGP certificate is generated at runtime from the private key. public_key UNIQUE NOT NULL, -- -- Unused columns. -- -- -- Columns "addr", "is_default" and "created" were -- dropped in migration 107 -- but added back for compatibility in migration 110. addr TEXT DEFAULT '' COLLATE NOCASE, -- Migrated into "key_id" config value in migration 107. is_default INTEGER DEFAULT 0, created INTEGER DEFAULT 0 ); CREATE TABLE public_keys ( id INTEGER PRIMARY KEY AUTOINCREMENT, fingerprint TEXT NOT NULL UNIQUE, -- Upper-case fingerprint of the key. public_key BLOB NOT NULL -- Binary key, not ASCII-armored ) STRICT; CREATE INDEX public_key_index ON public_keys (fingerprint); CREATE TABLE gossip_timestamp ( chat_id INTEGER NOT NULL, fingerprint TEXT NOT NULL, -- Upper-case fingerprint of the key. timestamp INTEGER NOT NULL, UNIQUE (chat_id, fingerprint) ) STRICT; CREATE INDEX gossip_timestamp_index ON gossip_timestamp (chat_id, fingerprint); -- Timestamps of distributing own key in the Autocrypt header of MDNs. CREATE TABLE mdn_autocrypt_timestamp ( fingerprint TEXT PRIMARY KEY NOT NULL, -- Upper-case fingerprint of the recipient key. attached_timestamp INTEGER NOT NULL ) STRICT; -- Passwords used to derive symmetric keys for broadcast lists aka channels. CREATE TABLE broadcast_secrets( chat_id INTEGER PRIMARY KEY NOT NULL, secret TEXT NOT NULL ) STRICT; -- Candidate chatmail relays for automatic relay management. CREATE TABLE relay_candidates( host TEXT PRIMARY KEY NOT NULL, last_tried INTEGER NOT NULL DEFAULT 0 -- Timestamp of the last connection attempt. ) STRICT; CREATE TABLE transports ( id INTEGER PRIMARY KEY AUTOINCREMENT, -- Email address associated with this transport. -- It uniquely identifies the transport. addr TEXT NOT NULL, -- JSON with the settings entered by the user. -- The settings are not necessary entered manually, -- but can be entered by scanning the QR code. -- These settings are only used during the transport configuration process. entered_param TEXT NOT NULL, -- JSON with the settings used to connect to the transport. -- These settings are derived from entered parameters -- and possibly autoconfiguration XML fetched over HTTPS. -- The settings stored here are known to have worked at least once, -- this is ensured during configuration. configured_param TEXT NOT NULL, add_timestamp INTEGER NOT NULL DEFAULT 0, -- True if the transport address is published -- by sending it in the public key signature. is_published INTEGER DEFAULT 1 NOT NULL, -- Time when the transport was last used to receive a message. -- Used to remove the least recently used transport -- when a new transport is added and there are too many relays already. last_rcvd_timestamp INTEGER NOT NULL DEFAULT 0, UNIQUE(addr) ); CREATE TABLE removed_transports ( addr TEXT NOT NULL, remove_timestamp INTEGER NOT NULL, UNIQUE(addr) ) STRICT; CREATE TABLE imap ( id INTEGER PRIMARY KEY AUTOINCREMENT, transport_id INTEGER NOT NULL, -- ID of the transport in the `transports` table. rfc724_mid TEXT NOT NULL, -- Message-ID header folder TEXT NOT NULL, -- IMAP folder target TEXT NOT NULL, -- Destination folder. Empty string means that the message shall be deleted. uid INTEGER NOT NULL, -- UID uidvalidity INTEGER NOT NULL, UNIQUE (transport_id, folder, uid, uidvalidity) ) STRICT; CREATE INDEX imap_folder ON imap(transport_id, folder); CREATE INDEX imap_rfc724_mid ON imap(transport_id, rfc724_mid); CREATE INDEX imap_only_rfc724_mid ON imap(rfc724_mid); CREATE TABLE imap_markseen ( id INTEGER PRIMARY KEY NOT NULL, FOREIGN KEY(id) REFERENCES imap(id) ON DELETE CASCADE ); CREATE TABLE imap_sync ( transport_id INTEGER NOT NULL, -- ID of the transport in the `transports` table. folder TEXT NOT NULL, uidvalidity INTEGER NOT NULL DEFAULT 0, uid_next INTEGER NOT NULL DEFAULT 0, modseq INTEGER NOT NULL DEFAULT 0, UNIQUE (transport_id, folder) ) STRICT; CREATE INDEX imap_sync_index ON imap_sync(transport_id, folder); CREATE TABLE download ( rfc724_mid TEXT PRIMARY KEY, msg_id INTEGER NOT NULL DEFAULT 0 ) STRICT; CREATE TABLE available_post_msgs ( rfc724_mid TEXT PRIMARY KEY ) STRICT; -- -- Statistics. -- CREATE TABLE stats_securejoin_sources( source INTEGER PRIMARY KEY, count INTEGER NOT NULL DEFAULT 0 ) STRICT; CREATE TABLE stats_securejoin_uipaths( uipath INTEGER PRIMARY KEY, count INTEGER NOT NULL DEFAULT 0 ) STRICT; CREATE TABLE stats_securejoin_invites( already_existed INTEGER NOT NULL, already_verified INTEGER NOT NULL, type TEXT NOT NULL ) STRICT; CREATE TABLE stats_msgs( chattype INTEGER PRIMARY KEY, verified INTEGER NOT NULL DEFAULT 0, unverified_encrypted INTEGER NOT NULL DEFAULT 0, unencrypted INTEGER NOT NULL DEFAULT 0, only_to_self INTEGER NOT NULL DEFAULT 0, last_counted_msg_id INTEGER NOT NULL DEFAULT 0 ) STRICT; CREATE TABLE stats_sending_enabled_events(timestamp INTEGER NOT NULL) STRICT; CREATE TABLE stats_sending_disabled_events(timestamp INTEGER NOT NULL) STRICT; -- Deprecated and unused tables. -- -- We don't immediately drop unused tables, -- because we want users to be able to downgrade. -- Deprecated table for Autocrypt peer states. -- It is replaced by the new "public_keys" table in migration 132 -- that introduced "key contacts" which have a fixed fingerprint. CREATE TABLE acpeerstates ( id INTEGER PRIMARY KEY, addr TEXT DEFAULT '' COLLATE NOCASE, last_seen INTEGER DEFAULT 0, last_seen_autocrypt INTEGER DEFAULT 0, public_key, prefer_encrypted INTEGER DEFAULT 0, gossip_timestamp INTEGER DEFAULT 0, gossip_key, public_key_fingerprint TEXT DEFAULT '', gossip_key_fingerprint TEXT DEFAULT '', verified_key, verified_key_fingerprint TEXT DEFAULT '', verifier TEXT DEFAULT '', secondary_verified_key, secondary_verified_key_fingerprint TEXT DEFAULT '', secondary_verifier TEXT DEFAULT '', backward_verified_key_id -- What we think the contact has as our verified key INTEGER, UNIQUE (addr) -- Only one peerstate per address ); CREATE INDEX acpeerstates_index1 ON acpeerstates (addr); CREATE INDEX acpeerstates_index3 ON acpeerstates (public_key_fingerprint); CREATE INDEX acpeerstates_index4 ON acpeerstates (gossip_key_fingerprint); CREATE INDEX acpeerstates_index5 ON acpeerstates (verified_key_fingerprint); -- Deprecated table previously used to upload sync messages using IMAP APPEND. -- Sync messages are sent over SMTP now as they should be sent to multiple transports. CREATE TABLE imap_send ( id INTEGER PRIMARY KEY AUTOINCREMENT, mime TEXT NOT NULL, -- Message content msg_id INTEGER NOT NULL, -- ID of the message in the `msgs` table attempts INTEGER NOT NULL DEFAULT 0 -- Number of failed attempts to send the message ); -- Deprecated table used for a job system. CREATE TABLE jobs ( id INTEGER PRIMARY KEY AUTOINCREMENT, added_timestamp INTEGER, desired_timestamp INTEGER DEFAULT 0, action INTEGER, foreign_id INTEGER, param TEXT DEFAULT '', thread INTEGER DEFAULT 0, tries INTEGER DEFAULT 0 ); CREATE INDEX jobs_index1 ON jobs (desired_timestamp); -- Backup of the keypairs left after migration 107. -- Not used by any code, it was only for a recovery -- in case migration 107 goes wrong. CREATE TABLE old_keypairs ( id INTEGER PRIMARY KEY, addr TEXT DEFAULT '' COLLATE NOCASE, is_default INTEGER DEFAULT 0, private_key, public_key, created INTEGER DEFAULT 0 ); -- Unused table, previously introduced for AEAP mechanism -- which is replaced by key contacts. CREATE TABLE sending_domains( domain TEXT PRIMARY KEY, dkim_works INTEGER DEFAULT 0 );