From d86e6b35bedc668085fac610ced2d198777f3b02 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Fri, 24 Jan 2025 17:49:31 +0400 Subject: [PATCH] test: track agent query plans (#5571) --- .../SQLite/Migrations/agent_query_plans.txt | 1103 +++++++++++++++++ tests/ChatClient.hs | 7 +- tests/ChatTests/DBUtils/SQLite.hs | 3 +- tests/SchemaDump.hs | 54 +- tests/Test.hs | 10 +- 5 files changed, 1155 insertions(+), 22 deletions(-) create mode 100644 src/Simplex/Chat/Store/SQLite/Migrations/agent_query_plans.txt diff --git a/src/Simplex/Chat/Store/SQLite/Migrations/agent_query_plans.txt b/src/Simplex/Chat/Store/SQLite/Migrations/agent_query_plans.txt new file mode 100644 index 0000000000..c4f5007040 --- /dev/null +++ b/src/Simplex/Chat/Store/SQLite/Migrations/agent_query_plans.txt @@ -0,0 +1,1103 @@ +Query: + SELECT + f.snd_file_id, f.snd_file_entity_id, f.user_id, f.num_recipients, f.prefix_path, + c.snd_file_chunk_id, c.chunk_no, c.chunk_offset, c.chunk_size, c.digest, + r.snd_file_chunk_replica_id, r.replica_id, r.replica_key, r.replica_status, r.delay, r.retries + FROM snd_file_chunk_replicas r + JOIN xftp_servers s ON s.xftp_server_id = r.xftp_server_id + JOIN snd_file_chunks c ON c.snd_file_chunk_id = r.snd_file_chunk_id + JOIN snd_files f ON f.snd_file_id = c.snd_file_id + WHERE r.snd_file_chunk_replica_id = ? + +Plan: +SEARCH r USING INTEGER PRIMARY KEY (rowid=?) +SEARCH s USING INTEGER PRIMARY KEY (rowid=?) +SEARCH c USING INTEGER PRIMARY KEY (rowid=?) +SEARCH f USING INTEGER PRIMARY KEY (rowid=?) + +Query: + SELECT + r.snd_file_chunk_replica_id, r.replica_id, r.replica_key, r.replica_status, r.delay, r.retries, + s.xftp_host, s.xftp_port, s.xftp_key_hash + FROM snd_file_chunk_replicas r + JOIN xftp_servers s ON s.xftp_server_id = r.xftp_server_id + WHERE r.snd_file_chunk_id = ? + +Plan: +SEARCH r USING INDEX idx_snd_file_chunk_replicas_snd_file_chunk_id (snd_file_chunk_id=?) +SEARCH s USING INTEGER PRIMARY KEY (rowid=?) + +Query: + SELECT command_id FROM commands + WHERE conn_id = ? AND host = ? AND port = ? AND failed = 0 + ORDER BY created_at ASC, command_id ASC + LIMIT 1 + +Plan: +SEARCH commands USING INDEX idx_commands_server_commands (host=? AND port=?) + +Query: + SELECT command_id FROM commands + WHERE conn_id = ? AND host IS NULL AND port IS NULL AND failed = 0 + ORDER BY created_at ASC, command_id ASC + LIMIT 1 + +Plan: +SEARCH commands USING INDEX idx_commands_server_commands (host=? AND port=?) + +Query: + SELECT m.msg_type, m.msg_flags, m.msg_body, m.pq_encryption, m.internal_ts, s.retry_int_slow, s.retry_int_fast + FROM messages m + JOIN snd_messages s ON s.conn_id = m.conn_id AND s.internal_id = m.internal_id + WHERE m.conn_id = ? AND m.internal_id = ? + +Plan: +SEARCH m USING PRIMARY KEY (conn_id=? AND internal_id=?) +SEARCH s USING PRIMARY KEY (conn_id=?) + +Query: + SELECT rcv_file_chunk_id, chunk_no, chunk_size, digest, tmp_path + FROM rcv_file_chunks + WHERE rcv_file_id = ? + +Plan: +SEARCH rcv_file_chunks USING INDEX idx_rcv_file_chunks_rcv_file_id (rcv_file_id=?) + +Query: + SELECT snd_file_chunk_id, chunk_no, chunk_offset, chunk_size, digest + FROM snd_file_chunks + WHERE snd_file_id = ? + +Plan: +SEARCH snd_file_chunks USING INDEX idx_snd_file_chunks_snd_file_id (snd_file_id=?) + +Query: + SELECT + f.rcv_file_id, f.rcv_file_entity_id, f.user_id, c.rcv_file_chunk_id, c.chunk_no, c.chunk_size, c.digest, f.tmp_path, c.tmp_path, + r.rcv_file_chunk_replica_id, r.replica_id, r.replica_key, r.received, r.delay, r.retries, + f.approved_relays, f.redirect_entity_id + FROM rcv_file_chunk_replicas r + JOIN xftp_servers s ON s.xftp_server_id = r.xftp_server_id + JOIN rcv_file_chunks c ON c.rcv_file_chunk_id = r.rcv_file_chunk_id + JOIN rcv_files f ON f.rcv_file_id = c.rcv_file_id + WHERE r.rcv_file_chunk_replica_id = ? + +Plan: +SEARCH r USING INTEGER PRIMARY KEY (rowid=?) +SEARCH s USING INTEGER PRIMARY KEY (rowid=?) +SEARCH c USING INTEGER PRIMARY KEY (rowid=?) +SEARCH f USING INTEGER PRIMARY KEY (rowid=?) + +Query: + SELECT + r.rcv_file_chunk_replica_id, r.replica_id, r.replica_key, r.received, r.delay, r.retries, + s.xftp_host, s.xftp_port, s.xftp_key_hash + FROM rcv_file_chunk_replicas r + JOIN xftp_servers s ON s.xftp_server_id = r.xftp_server_id + WHERE r.rcv_file_chunk_id = ? + +Plan: +SEARCH r USING INDEX idx_rcv_file_chunk_replicas_rcv_file_chunk_id (rcv_file_chunk_id=?) +SEARCH s USING INTEGER PRIMARY KEY (rowid=?) + +Query: + SELECT c.corr_id, cs.user_id, c.command + FROM commands c + JOIN connections cs USING (conn_id) + WHERE c.command_id = ? + +Plan: +SEARCH c USING INTEGER PRIMARY KEY (rowid=?) +SEARCH cs USING PRIMARY KEY (conn_id=?) + +Query: + SELECT internal_id + FROM snd_message_deliveries + WHERE conn_id = ? AND snd_queue_id = ? AND failed = 0 AND internal_id <= ? + ORDER BY internal_id ASC + +Plan: +SEARCH snd_message_deliveries USING COVERING INDEX idx_snd_message_deliveries_expired (conn_id=? AND snd_queue_id=? AND failed=? AND internal_id= ? + AND failed = 0 + ORDER BY r.retries ASC, r.created_at ASC + LIMIT 1 + +Plan: +SEARCH s USING COVERING INDEX sqlite_autoindex_xftp_servers_1 (xftp_host=? AND xftp_port=? AND xftp_key_hash=?) +SEARCH r USING INDEX idx_deleted_snd_chunk_replicas_xftp_server_id (xftp_server_id=?) +USE TEMP B-TREE FOR ORDER BY + +Query: + SELECT r.rcv_file_chunk_replica_id, f.rcv_file_id + FROM rcv_file_chunk_replicas r + JOIN xftp_servers s ON s.xftp_server_id = r.xftp_server_id + JOIN rcv_file_chunks c ON c.rcv_file_chunk_id = r.rcv_file_chunk_id + JOIN rcv_files f ON f.rcv_file_id = c.rcv_file_id + WHERE s.xftp_host = ? AND s.xftp_port = ? AND s.xftp_key_hash = ? + AND r.received = 0 AND r.replica_number = 1 + AND f.status = ? AND f.deleted = 0 AND f.created_at >= ? + AND f.failed = 0 + ORDER BY r.retries ASC, r.created_at ASC + LIMIT 1 + +Plan: +SEARCH s USING COVERING INDEX sqlite_autoindex_xftp_servers_1 (xftp_host=? AND xftp_port=? AND xftp_key_hash=?) +SEARCH r USING INDEX idx_rcv_file_chunk_replicas_pending (received=? AND replica_number=?) +SEARCH c USING INTEGER PRIMARY KEY (rowid=?) +SEARCH f USING INTEGER PRIMARY KEY (rowid=?) +USE TEMP B-TREE FOR ORDER BY + +Query: + SELECT r.snd_file_chunk_replica_id, f.snd_file_id + FROM snd_file_chunk_replicas r + JOIN xftp_servers s ON s.xftp_server_id = r.xftp_server_id + JOIN snd_file_chunks c ON c.snd_file_chunk_id = r.snd_file_chunk_id + JOIN snd_files f ON f.snd_file_id = c.snd_file_id + WHERE s.xftp_host = ? AND s.xftp_port = ? AND s.xftp_key_hash = ? + AND r.replica_status = ? AND r.replica_number = 1 + AND (f.status = ? OR f.status = ?) AND f.deleted = 0 AND f.created_at >= ? + AND f.failed = 0 + ORDER BY r.retries ASC, r.created_at ASC + LIMIT 1 + +Plan: +SEARCH s USING COVERING INDEX sqlite_autoindex_xftp_servers_1 (xftp_host=? AND xftp_port=? AND xftp_key_hash=?) +SEARCH r USING INDEX idx_snd_file_chunk_replicas_pending (replica_status=? AND replica_number=?) +SEARCH c USING INTEGER PRIMARY KEY (rowid=?) +SEARCH f USING INTEGER PRIMARY KEY (rowid=?) +USE TEMP B-TREE FOR ORDER BY + +Query: + SELECT rcv_file_entity_id, user_id, size, digest, key, nonce, chunk_size, prefix_path, tmp_path, save_path, save_file_key, save_file_nonce, status, deleted, redirect_id, redirect_entity_id, redirect_size, redirect_digest + FROM rcv_files + WHERE rcv_file_id = ? + +Plan: +SEARCH rcv_files USING INTEGER PRIMARY KEY (rowid=?) + +Query: + SELECT rcv_file_id + FROM rcv_files + WHERE status IN (?,?) AND deleted = 0 AND created_at >= ? + AND failed = 0 + ORDER BY created_at ASC LIMIT 1 + +Plan: +SEARCH rcv_files USING INDEX idx_rcv_files_status_created_at (status=? AND created_at>?) +USE TEMP B-TREE FOR ORDER BY + +Query: + SELECT snd_file_entity_id, user_id, path, src_file_key, src_file_nonce, num_recipients, digest, prefix_path, key, nonce, status, deleted, redirect_size, redirect_digest + FROM snd_files + WHERE snd_file_id = ? + +Plan: +SEARCH snd_files USING INTEGER PRIMARY KEY (rowid=?) + +Query: + SELECT snd_file_id + FROM snd_files + WHERE status IN (?,?,?) AND deleted = 0 AND created_at >= ? + AND failed = 0 + ORDER BY created_at ASC LIMIT 1 + +Plan: +SEARCH snd_files USING INDEX idx_snd_files_status_created_at (status=? AND created_at>?) +USE TEMP B-TREE FOR ORDER BY + +Query: + SELECT MAX(internal_id) + FROM messages + WHERE conn_id = ? AND internal_snd_id IS NOT NULL AND internal_ts < ? + +Plan: +SEARCH messages USING PRIMARY KEY (conn_id=?) + +Query: + SELECT user_id FROM users u + WHERE u.user_id = ? + AND u.deleted = ? + AND NOT EXISTS (SELECT c.conn_id FROM connections c WHERE c.user_id = u.user_id) + +Plan: +SEARCH u USING INTEGER PRIMARY KEY (rowid=?) +CORRELATED SCALAR SUBQUERY 1 +SEARCH c USING COVERING INDEX idx_connections_user (user_id=?) + +Query: + INSERT INTO conn_confirmations + (confirmation_id, conn_id, sender_key, e2e_snd_pub_key, ratchet_state, sender_conn_info, smp_reply_queues, smp_client_version, accepted) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0); + +Plan: + +Query: + INSERT INTO conn_invitations + (invitation_id, contact_conn_id, cr_invitation, recipient_conn_info, accepted) VALUES (?, ?, ?, ?, 0); + +Plan: + +Query: + INSERT INTO snd_file_chunk_replica_recipients + (snd_file_chunk_replica_id, rcv_replica_id, rcv_replica_key) + VALUES (?,?,?) + +Plan: + +Query: + SELECT + r.internal_id, m.internal_ts, r.broker_id, r.broker_ts, r.external_snd_id, r.integrity, r.internal_hash, + m.msg_type, m.msg_body, m.pq_encryption, s.internal_id, s.rcpt_status, r.user_ack + FROM rcv_messages r + JOIN messages m ON r.conn_id = m.conn_id AND r.internal_id = m.internal_id + JOIN connections c ON r.conn_id = c.conn_id AND c.last_internal_msg_id = r.internal_id + LEFT JOIN snd_messages s ON s.conn_id = r.conn_id AND s.rcpt_internal_id = r.internal_id + WHERE r.conn_id = ? AND r.broker_id = ? + +Plan: +SEARCH c USING PRIMARY KEY (conn_id=?) +SEARCH m USING PRIMARY KEY (conn_id=? AND internal_id=?) +SEARCH r USING PRIMARY KEY (conn_id=?) +SEARCH s USING PRIMARY KEY (conn_id=?) LEFT-JOIN + +Query: + SELECT + r.internal_id, m.internal_ts, r.broker_id, r.broker_ts, r.external_snd_id, r.integrity, r.internal_hash, + m.msg_type, m.msg_body, m.pq_encryption, s.internal_id, s.rcpt_status, r.user_ack + FROM rcv_messages r + JOIN messages m ON r.conn_id = m.conn_id AND r.internal_id = m.internal_id + LEFT JOIN snd_messages s ON s.conn_id = r.conn_id AND s.rcpt_internal_id = r.internal_id + WHERE r.conn_id = ? AND r.internal_id = ? + +Plan: +SEARCH m USING PRIMARY KEY (conn_id=? AND internal_id=?) +SEARCH r USING PRIMARY KEY (conn_id=?) +SEARCH s USING PRIMARY KEY (conn_id=?) LEFT-JOIN + +Query: + SELECT + r.user_id, r.replica_id, r.replica_key, r.chunk_digest, r.delay, r.retries, + s.xftp_host, s.xftp_port, s.xftp_key_hash + FROM deleted_snd_chunk_replicas r + JOIN xftp_servers s ON s.xftp_server_id = r.xftp_server_id + WHERE r.deleted_snd_chunk_replica_id = ? + +Plan: +SEARCH r USING INTEGER PRIMARY KEY (rowid=?) +SEARCH s USING INTEGER PRIMARY KEY (rowid=?) + +Query: + SELECT + user_id, conn_id, conn_mode, smp_agent_version, enable_ntfs, + last_external_snd_msg_id, deleted, ratchet_sync_state, pq_support + FROM connections + WHERE conn_id = ? + +Plan: +SEARCH connections USING PRIMARY KEY (conn_id=?) + +Query: + SELECT DISTINCT + s.xftp_host, s.xftp_port, s.xftp_key_hash + FROM deleted_snd_chunk_replicas r + JOIN xftp_servers s ON s.xftp_server_id = r.xftp_server_id + WHERE r.created_at >= ? + +Plan: +SEARCH r USING INDEX idx_deleted_snd_chunk_replicas_pending (created_at>?) +SEARCH s USING INTEGER PRIMARY KEY (rowid=?) +USE TEMP B-TREE FOR DISTINCT + +Query: + SELECT DISTINCT + s.xftp_host, s.xftp_port, s.xftp_key_hash + FROM rcv_file_chunk_replicas r + JOIN xftp_servers s ON s.xftp_server_id = r.xftp_server_id + JOIN rcv_file_chunks c ON c.rcv_file_chunk_id = r.rcv_file_chunk_id + JOIN rcv_files f ON f.rcv_file_id = c.rcv_file_id + WHERE r.received = 0 AND r.replica_number = 1 + AND f.status = ? AND f.deleted = 0 AND f.created_at >= ? + +Plan: +SEARCH r USING INDEX idx_rcv_file_chunk_replicas_pending (received=? AND replica_number=?) +SEARCH c USING INTEGER PRIMARY KEY (rowid=?) +SEARCH f USING INTEGER PRIMARY KEY (rowid=?) +SEARCH s USING INTEGER PRIMARY KEY (rowid=?) +USE TEMP B-TREE FOR DISTINCT + +Query: + SELECT DISTINCT + s.xftp_host, s.xftp_port, s.xftp_key_hash + FROM snd_file_chunk_replicas r + JOIN xftp_servers s ON s.xftp_server_id = r.xftp_server_id + JOIN snd_file_chunks c ON c.snd_file_chunk_id = r.snd_file_chunk_id + JOIN snd_files f ON f.snd_file_id = c.snd_file_id + WHERE r.replica_status = ? AND r.replica_number = 1 + AND (f.status = ? OR f.status = ?) AND f.deleted = 0 AND f.created_at >= ? + +Plan: +SEARCH r USING INDEX idx_snd_file_chunk_replicas_pending (replica_status=? AND replica_number=?) +SEARCH c USING INTEGER PRIMARY KEY (rowid=?) +SEARCH f USING INTEGER PRIMARY KEY (rowid=?) +SEARCH s USING INTEGER PRIMARY KEY (rowid=?) +USE TEMP B-TREE FOR DISTINCT + +Query: + SELECT DISTINCT c.host, c.port, COALESCE(c.server_key_hash, s.key_hash) + FROM commands c + LEFT JOIN servers s ON s.host = c.host AND s.port = c.port + WHERE conn_id = ? + +Plan: +SEARCH c USING INDEX idx_commands_conn_id (conn_id=?) +SEARCH s USING PRIMARY KEY (host=? AND port=?) LEFT-JOIN +USE TEMP B-TREE FOR DISTINCT + +Query: + SELECT DISTINCT ntf_host, ntf_port, ntf_key_hash + FROM ntf_tokens_to_delete + +Plan: +SCAN ntf_tokens_to_delete +USE TEMP B-TREE FOR DISTINCT + +Query: + SELECT confirmation_id, ratchet_state, own_conn_info, sender_key, e2e_snd_pub_key, sender_conn_info, smp_reply_queues, smp_client_version + FROM conn_confirmations + WHERE conn_id = ? AND accepted = 1; + +Plan: +SEARCH conn_confirmations USING INDEX idx_conn_confirmations_conn_id (conn_id=?) + +Query: + SELECT conn_id, ratchet_state, sender_key, e2e_snd_pub_key, sender_conn_info, smp_reply_queues, smp_client_version + FROM conn_confirmations + WHERE confirmation_id = ?; + +Plan: +SEARCH conn_confirmations USING PRIMARY KEY (confirmation_id=?) + +Query: + SELECT contact_conn_id, cr_invitation, recipient_conn_info, own_conn_info, accepted + FROM conn_invitations + WHERE invitation_id = ? + AND accepted = 0 + +Plan: +SEARCH conn_invitations USING PRIMARY KEY (invitation_id=?) + +Query: + SELECT last_internal_msg_id, last_internal_rcv_msg_id, last_external_snd_msg_id, last_rcv_msg_hash + FROM connections + WHERE conn_id = ? + +Plan: +SEARCH connections USING PRIMARY KEY (conn_id=?) + +Query: + SELECT last_internal_msg_id, last_internal_snd_msg_id, last_snd_msg_hash + FROM connections + WHERE conn_id = ? + +Plan: +SEARCH connections USING PRIMARY KEY (conn_id=?) + +Query: + SELECT s.internal_id, m.msg_type, s.internal_hash, s.rcpt_internal_id, s.rcpt_status + FROM snd_messages s + JOIN messages m ON s.conn_id = m.conn_id AND s.internal_id = m.internal_id + WHERE s.conn_id = ? AND s.internal_snd_id = ? + +Plan: +SEARCH s USING PRIMARY KEY (conn_id=? AND internal_snd_id=?) +SEARCH m USING PRIMARY KEY (conn_id=? AND internal_id=?) + +Query: + DELETE FROM conn_confirmations + WHERE conn_id = ? + +Plan: +SEARCH conn_confirmations USING COVERING INDEX idx_conn_confirmations_conn_id (conn_id=?) + +Query: + INSERT INTO connections + (user_id, conn_id, conn_mode, smp_agent_version, enable_ntfs, pq_support, duplex_handshake) VALUES (?,?,?,?,?,?,?) + +Plan: + +Query: + INSERT INTO messages + (conn_id, internal_id, internal_ts, internal_rcv_id, internal_snd_id, msg_type, msg_flags, msg_body, pq_encryption) + VALUES (?,?,?,?,?,?,?,?,?); + +Plan: +SEARCH snd_message_deliveries USING COVERING INDEX idx_snd_message_deliveries_conn_id_internal_id (conn_id=? AND internal_id=?) + +Query: + INSERT INTO messages + (conn_id, internal_id, internal_ts, internal_rcv_id, internal_snd_id, msg_type, msg_flags, msg_body, pq_encryption) + VALUES + (?,?,?,?,?,?,?,?,?); + +Plan: +SEARCH snd_message_deliveries USING COVERING INDEX idx_snd_message_deliveries_conn_id_internal_id (conn_id=? AND internal_id=?) + +Query: + INSERT INTO ratchets + (conn_id, ratchet_state, x3dh_pub_key_1, x3dh_pub_key_2, pq_pub_kem) VALUES (?, ?, ?, ?, ?) + ON CONFLICT (conn_id) DO UPDATE SET + ratchet_state = EXCLUDED.ratchet_state, + x3dh_priv_key_1 = NULL, + x3dh_priv_key_2 = NULL, + x3dh_pub_key_1 = EXCLUDED.x3dh_pub_key_1, + x3dh_pub_key_2 = EXCLUDED.x3dh_pub_key_2, + pq_priv_kem = NULL, + pq_pub_kem = EXCLUDED.pq_pub_kem + +Plan: + +Query: + INSERT INTO ratchets (conn_id, ratchet_state) + VALUES (?, ?) + ON CONFLICT (conn_id) DO UPDATE SET + ratchet_state = ?, + x3dh_priv_key_1 = NULL, + x3dh_priv_key_2 = NULL, + x3dh_pub_key_1 = NULL, + x3dh_pub_key_2 = NULL, + pq_priv_kem = NULL, + pq_pub_kem = NULL + +Plan: + +Query: + INSERT INTO rcv_messages + ( conn_id, rcv_queue_id, internal_rcv_id, internal_id, external_snd_id, + broker_id, broker_ts, + internal_hash, external_prev_snd_hash, integrity) + VALUES + (?,?,?,?,?,?,?,?,?,?) + +Plan: +SEARCH messages USING COVERING INDEX idx_messages_conn_id_internal_rcv_id (conn_id=? AND internal_rcv_id=?) + +Query: + INSERT INTO rcv_queues + (host, port, rcv_id, conn_id, rcv_private_key, rcv_dh_secret, e2e_priv_key, e2e_dh_secret, snd_id, snd_secure, status, rcv_queue_id, rcv_primary, replace_rcv_queue_id, smp_client_version, server_key_hash) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?); + +Plan: + +Query: + INSERT INTO snd_file_chunk_replicas + (snd_file_chunk_id, replica_number, xftp_server_id, replica_id, replica_key, replica_status) + VALUES (?,?,?,?,?,?) + +Plan: + +Query: + INSERT INTO snd_messages + ( conn_id, internal_snd_id, internal_id, internal_hash, previous_msg_hash) + VALUES + (?,?,?,?,?) + +Plan: +SEARCH messages USING COVERING INDEX idx_messages_conn_id_internal_snd_id (conn_id=? AND internal_snd_id=?) + +Query: + INSERT INTO snd_queues + (host, port, snd_id, snd_secure, conn_id, snd_public_key, snd_private_key, e2e_pub_key, e2e_dh_secret, + status, snd_queue_id, snd_primary, replace_snd_queue_id, smp_client_version, server_key_hash) + VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) + ON CONFLICT (host, port, snd_id) DO UPDATE SET + host=EXCLUDED.host, + port=EXCLUDED.port, + snd_id=EXCLUDED.snd_id, + snd_secure=EXCLUDED.snd_secure, + conn_id=EXCLUDED.conn_id, + snd_public_key=EXCLUDED.snd_public_key, + snd_private_key=EXCLUDED.snd_private_key, + e2e_pub_key=EXCLUDED.e2e_pub_key, + e2e_dh_secret=EXCLUDED.e2e_dh_secret, + status=EXCLUDED.status, + snd_queue_id=EXCLUDED.snd_queue_id, + snd_primary=EXCLUDED.snd_primary, + replace_snd_queue_id=EXCLUDED.replace_snd_queue_id, + smp_client_version=EXCLUDED.smp_client_version, + server_key_hash=EXCLUDED.server_key_hash + +Plan: + +Query: + SELECT rcv_replica_id, rcv_replica_key + FROM snd_file_chunk_replica_recipients + WHERE snd_file_chunk_replica_id = ? + +Plan: +SEARCH snd_file_chunk_replica_recipients USING INDEX idx_snd_file_chunk_replica_recipients_snd_file_chunk_replica_id (snd_file_chunk_replica_id=?) + +Query: + UPDATE conn_confirmations + SET accepted = 1, + own_conn_info = ? + WHERE confirmation_id = ? + +Plan: +SEARCH conn_confirmations USING PRIMARY KEY (confirmation_id=?) + +Query: + UPDATE conn_invitations + SET accepted = 1, + own_conn_info = ? + WHERE invitation_id = ? + +Plan: +SEARCH conn_invitations USING PRIMARY KEY (invitation_id=?) + +Query: + UPDATE connections + SET last_external_snd_msg_id = ?, + last_rcv_msg_hash = ? + WHERE conn_id = ? + AND last_internal_rcv_msg_id = ? + +Plan: +SEARCH connections USING PRIMARY KEY (conn_id=?) + +Query: + UPDATE connections + SET last_internal_msg_id = ?, + last_internal_rcv_msg_id = ? + WHERE conn_id = ? + +Plan: +SEARCH connections USING PRIMARY KEY (conn_id=?) + +Query: + UPDATE connections + SET last_internal_msg_id = ?, + last_internal_snd_msg_id = ? + WHERE conn_id = ? + +Plan: +SEARCH connections USING PRIMARY KEY (conn_id=?) + +Query: + UPDATE connections + SET last_snd_msg_hash = ? + WHERE conn_id = ? + AND last_internal_snd_msg_id = ?; + +Plan: +SEARCH connections USING PRIMARY KEY (conn_id=?) + +Query: + UPDATE ratchets + SET x3dh_priv_key_1 = ?, x3dh_priv_key_2 = ?, pq_priv_kem = ? + WHERE conn_id = ? + +Plan: +SEARCH ratchets USING PRIMARY KEY (conn_id=?) + +Query: + UPDATE rcv_queues + SET deleted = 1 + WHERE host = ? AND port = ? AND rcv_id = ? + +Plan: +SEARCH rcv_queues USING PRIMARY KEY (host=? AND port=? AND rcv_id=?) + +Query: + UPDATE rcv_queues + SET e2e_dh_secret = ?, + status = ?, + smp_client_version = ? + WHERE host = ? AND port = ? AND rcv_id = ? + +Plan: +SEARCH rcv_queues USING PRIMARY KEY (host=? AND port=? AND rcv_id=?) + +Query: + UPDATE rcv_queues + SET status = ? + WHERE host = ? AND port = ? AND rcv_id = ? + +Plan: +SEARCH rcv_queues USING PRIMARY KEY (host=? AND port=? AND rcv_id=?) + +Query: + UPDATE rcv_queues + SET switch_status = ? + WHERE host = ? AND port = ? AND rcv_id = ? + +Plan: +SEARCH rcv_queues USING PRIMARY KEY (host=? AND port=? AND rcv_id=?) + +Query: + UPDATE snd_queues + SET status = ? + WHERE host = ? AND port = ? AND snd_id = ? + +Plan: +SEARCH snd_queues USING PRIMARY KEY (host=? AND port=? AND snd_id=?) + +Query: + UPDATE snd_queues + SET switch_status = ? + WHERE host = ? AND port = ? AND snd_id = ? + +Plan: +SEARCH snd_queues USING PRIMARY KEY (host=? AND port=? AND snd_id=?) + +Query: + SELECT + c.user_id, COALESCE(q.server_key_hash, s.key_hash), q.conn_id, q.host, q.port, q.snd_id, q.snd_secure, + q.snd_public_key, q.snd_private_key, q.e2e_pub_key, q.e2e_dh_secret, q.status, + q.snd_queue_id, q.snd_primary, q.replace_snd_queue_id, q.switch_status, q.smp_client_version + FROM snd_queues q + JOIN servers s ON q.host = s.host AND q.port = s.port + JOIN connections c ON q.conn_id = c.conn_id + WHERE q.conn_id = ? +Plan: +SEARCH c USING PRIMARY KEY (conn_id=?) +SEARCH q USING INDEX idx_snd_queue_id (conn_id=?) +SEARCH s USING PRIMARY KEY (host=? AND port=?) + +Query: + SELECT c.user_id, COALESCE(q.server_key_hash, s.key_hash), q.conn_id, q.host, q.port, q.rcv_id, q.rcv_private_key, q.rcv_dh_secret, + q.e2e_priv_key, q.e2e_dh_secret, q.snd_id, q.snd_secure, q.status, + q.rcv_queue_id, q.rcv_primary, q.replace_rcv_queue_id, q.switch_status, q.smp_client_version, q.delete_errors, + q.ntf_public_key, q.ntf_private_key, q.ntf_id, q.rcv_ntf_dh_secret + FROM rcv_queues q + JOIN servers s ON q.host = s.host AND q.port = s.port + JOIN connections c ON q.conn_id = c.conn_id + WHERE q.conn_id = ? AND q.deleted = 0 +Plan: +SEARCH c USING PRIMARY KEY (conn_id=?) +SEARCH q USING INDEX idx_rcv_queue_id (conn_id=?) +SEARCH s USING PRIMARY KEY (host=? AND port=?) + +Query: + SELECT c.user_id, COALESCE(q.server_key_hash, s.key_hash), q.conn_id, q.host, q.port, q.rcv_id, q.rcv_private_key, q.rcv_dh_secret, + q.e2e_priv_key, q.e2e_dh_secret, q.snd_id, q.snd_secure, q.status, + q.rcv_queue_id, q.rcv_primary, q.replace_rcv_queue_id, q.switch_status, q.smp_client_version, q.delete_errors, + q.ntf_public_key, q.ntf_private_key, q.ntf_id, q.rcv_ntf_dh_secret + FROM rcv_queues q + JOIN servers s ON q.host = s.host AND q.port = s.port + JOIN connections c ON q.conn_id = c.conn_id + WHERE q.conn_id = ? AND q.host = ? AND q.port = ? AND q.rcv_id = ? AND q.deleted = 0 +Plan: +SEARCH q USING PRIMARY KEY (host=? AND port=? AND rcv_id=?) +SEARCH s USING PRIMARY KEY (host=? AND port=?) +SEARCH c USING PRIMARY KEY (conn_id=?) + +Query: + SELECT c.user_id, COALESCE(q.server_key_hash, s.key_hash), q.conn_id, q.host, q.port, q.rcv_id, q.rcv_private_key, q.rcv_dh_secret, + q.e2e_priv_key, q.e2e_dh_secret, q.snd_id, q.snd_secure, q.status, + q.rcv_queue_id, q.rcv_primary, q.replace_rcv_queue_id, q.switch_status, q.smp_client_version, q.delete_errors, + q.ntf_public_key, q.ntf_private_key, q.ntf_id, q.rcv_ntf_dh_secret + FROM rcv_queues q + JOIN servers s ON q.host = s.host AND q.port = s.port + JOIN connections c ON q.conn_id = c.conn_id + WHERE q.conn_id = ? AND q.host = ? AND q.port = ? AND q.rcv_id = ? AND q.deleted = 1 +Plan: +SEARCH q USING PRIMARY KEY (host=? AND port=? AND rcv_id=?) +SEARCH s USING PRIMARY KEY (host=? AND port=?) +SEARCH c USING PRIMARY KEY (conn_id=?) + +Query: + SELECT c.user_id, COALESCE(q.server_key_hash, s.key_hash), q.conn_id, q.host, q.port, q.rcv_id, q.rcv_private_key, q.rcv_dh_secret, + q.e2e_priv_key, q.e2e_dh_secret, q.snd_id, q.snd_secure, q.status, + q.rcv_queue_id, q.rcv_primary, q.replace_rcv_queue_id, q.switch_status, q.smp_client_version, q.delete_errors, + q.ntf_public_key, q.ntf_private_key, q.ntf_id, q.rcv_ntf_dh_secret + FROM rcv_queues q + JOIN servers s ON q.host = s.host AND q.port = s.port + JOIN connections c ON q.conn_id = c.conn_id + WHERE q.conn_id = ? AND q.rcv_queue_id = ? AND q.deleted = 0 +Plan: +SEARCH c USING PRIMARY KEY (conn_id=?) +SEARCH q USING INDEX idx_rcv_queue_id (conn_id=? AND rcv_queue_id=?) +SEARCH s USING PRIMARY KEY (host=? AND port=?) + +Query: + SELECT c.user_id, COALESCE(q.server_key_hash, s.key_hash), q.conn_id, q.host, q.port, q.rcv_id, q.rcv_private_key, q.rcv_dh_secret, + q.e2e_priv_key, q.e2e_dh_secret, q.snd_id, q.snd_secure, q.status, + q.rcv_queue_id, q.rcv_primary, q.replace_rcv_queue_id, q.switch_status, q.smp_client_version, q.delete_errors, + q.ntf_public_key, q.ntf_private_key, q.ntf_id, q.rcv_ntf_dh_secret + FROM rcv_queues q + JOIN servers s ON q.host = s.host AND q.port = s.port + JOIN connections c ON q.conn_id = c.conn_id + WHERE q.host = ? AND q.port = ? AND q.rcv_id = ? AND q.deleted = 0 +Plan: +SEARCH q USING PRIMARY KEY (host=? AND port=? AND rcv_id=?) +SEARCH s USING PRIMARY KEY (host=? AND port=?) +SEARCH c USING PRIMARY KEY (conn_id=?) + +Query: DELETE FROM commands WHERE command_id = ? +Plan: +SEARCH commands USING INTEGER PRIMARY KEY (rowid=?) + +Query: DELETE FROM conn_invitations WHERE contact_conn_id = ? AND invitation_id = ? +Plan: +SEARCH conn_invitations USING PRIMARY KEY (invitation_id=?) + +Query: DELETE FROM connections WHERE conn_id = ? +Plan: +SEARCH connections USING PRIMARY KEY (conn_id=?) +SEARCH processed_ratchet_key_hashes USING COVERING INDEX idx_processed_ratchet_key_hashes_hash (conn_id=?) +SEARCH encrypted_rcv_message_hashes USING COVERING INDEX idx_encrypted_rcv_message_hashes_hash (conn_id=?) +SEARCH snd_message_deliveries USING COVERING INDEX idx_snd_message_deliveries_conn_id_internal_id (conn_id=?) +SEARCH commands USING COVERING INDEX idx_commands_conn_id (conn_id=?) +SEARCH ratchets USING PRIMARY KEY (conn_id=?) +SEARCH conn_invitations USING COVERING INDEX idx_conn_invitations_contact_conn_id (contact_conn_id=?) +SEARCH conn_confirmations USING COVERING INDEX idx_conn_confirmations_conn_id (conn_id=?) +SEARCH messages USING COVERING INDEX idx_messages_conn_id (conn_id=?) +SEARCH snd_queues USING COVERING INDEX idx_snd_queue_id (conn_id=?) +SEARCH rcv_queues USING COVERING INDEX idx_rcv_queue_id (conn_id=?) + +Query: DELETE FROM deleted_snd_chunk_replicas WHERE deleted_snd_chunk_replica_id = ? +Plan: +SEARCH deleted_snd_chunk_replicas USING INTEGER PRIMARY KEY (rowid=?) + +Query: DELETE FROM messages WHERE conn_id = ? AND internal_id = ?; +Plan: +SEARCH messages USING PRIMARY KEY (conn_id=? AND internal_id=?) +SEARCH snd_message_deliveries USING COVERING INDEX idx_snd_message_deliveries_conn_id_internal_id (conn_id=? AND internal_id=?) +SEARCH snd_messages USING COVERING INDEX idx_snd_messages_conn_id_internal_id (conn_id=? AND internal_id=?) +SEARCH rcv_messages USING COVERING INDEX idx_rcv_messages_conn_id_internal_id (conn_id=? AND internal_id=?) + +Query: DELETE FROM ntf_subscriptions WHERE conn_id = ? +Plan: +SEARCH ntf_subscriptions USING PRIMARY KEY (conn_id=?) + +Query: DELETE FROM ratchets WHERE conn_id = ? +Plan: +SEARCH ratchets USING PRIMARY KEY (conn_id=?) +SEARCH skipped_messages USING COVERING INDEX idx_skipped_messages_conn_id (conn_id=?) + +Query: DELETE FROM rcv_files WHERE rcv_file_id = ? +Plan: +SEARCH rcv_files USING INTEGER PRIMARY KEY (rowid=?) +SEARCH rcv_file_chunks USING COVERING INDEX idx_rcv_file_chunks_rcv_file_id (rcv_file_id=?) +SEARCH rcv_files USING COVERING INDEX idx_rcv_files_redirect_id (redirect_id=?) + +Query: DELETE FROM rcv_queues WHERE conn_id = ? AND rcv_queue_id = ? +Plan: +SEARCH rcv_queues USING COVERING INDEX idx_rcv_queue_id (conn_id=? AND rcv_queue_id=?) + +Query: DELETE FROM snd_files WHERE snd_file_id = ? +Plan: +SEARCH snd_files USING INTEGER PRIMARY KEY (rowid=?) +SEARCH snd_file_chunks USING COVERING INDEX idx_snd_file_chunks_snd_file_id (snd_file_id=?) + +Query: DELETE FROM snd_message_deliveries WHERE conn_id = ? AND snd_queue_id = ? +Plan: +SEARCH snd_message_deliveries USING COVERING INDEX idx_snd_message_deliveries (conn_id=? AND snd_queue_id=?) + +Query: DELETE FROM snd_message_deliveries WHERE conn_id = ? AND snd_queue_id = ? AND internal_id = ? +Plan: +SEARCH snd_message_deliveries USING COVERING INDEX idx_snd_message_deliveries_expired (conn_id=? AND snd_queue_id=?) + +Query: DELETE FROM snd_queues WHERE conn_id = ? AND snd_queue_id = ? +Plan: +SEARCH snd_queues USING COVERING INDEX idx_snd_queue_id (conn_id=? AND snd_queue_id=?) + +Query: DELETE FROM users WHERE user_id = ? +Plan: +SEARCH users USING INTEGER PRIMARY KEY (rowid=?) +SEARCH deleted_snd_chunk_replicas USING COVERING INDEX idx_deleted_snd_chunk_replicas_user_id (user_id=?) +SEARCH snd_files USING COVERING INDEX idx_snd_files_user_id (user_id=?) +SEARCH rcv_files USING COVERING INDEX idx_rcv_files_user_id (user_id=?) +SEARCH connections USING COVERING INDEX idx_connections_user (user_id=?) + +Query: INSERT INTO commands (host, port, corr_id, conn_id, command_tag, command, server_key_hash, created_at) VALUES (?,?,?,?,?,?,?,?) +Plan: + +Query: INSERT INTO deleted_snd_chunk_replicas (user_id, xftp_server_id, replica_id, replica_key, chunk_digest) VALUES (?,?,?,?,?) +Plan: + +Query: INSERT INTO encrypted_rcv_message_hashes (conn_id, hash) VALUES (?,?) +Plan: + +Query: INSERT INTO processed_ratchet_key_hashes (conn_id, hash) VALUES (?,?) +Plan: + +Query: INSERT INTO ratchets (conn_id, x3dh_priv_key_1, x3dh_priv_key_2, pq_priv_kem) VALUES (?, ?, ?, ?) +Plan: + +Query: INSERT INTO rcv_file_chunk_replicas (replica_number, rcv_file_chunk_id, xftp_server_id, replica_id, replica_key) VALUES (?,?,?,?,?) +Plan: + +Query: INSERT INTO rcv_file_chunks (rcv_file_id, chunk_no, chunk_size, digest) VALUES (?,?,?,?) +Plan: + +Query: INSERT INTO rcv_files (rcv_file_entity_id, user_id, size, digest, key, nonce, chunk_size, prefix_path, tmp_path, save_path, save_file_key, save_file_nonce, status, redirect_id, redirect_entity_id, redirect_digest, redirect_size, approved_relays) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) +Plan: + +Query: INSERT INTO servers (host, port, key_hash) VALUES (?,?,?) +Plan: + +Query: INSERT INTO skipped_messages (conn_id, header_key, msg_n, msg_key) VALUES (?, ?, ?, ?) +Plan: + +Query: INSERT INTO snd_file_chunks (snd_file_id, chunk_no, chunk_offset, chunk_size, digest) VALUES (?,?,?,?,?) +Plan: + +Query: INSERT INTO snd_files (snd_file_entity_id, user_id, path, src_file_key, src_file_nonce, num_recipients, prefix_path, key, nonce, status, redirect_size, redirect_digest) VALUES (?,?,?,?,?,?,?,?,?,?,?,?) +Plan: + +Query: INSERT INTO snd_message_deliveries (conn_id, snd_queue_id, internal_id) VALUES (?, ?, ?) +Plan: + +Query: INSERT INTO users (user_id) VALUES (1) +Plan: + +Query: INSERT INTO users DEFAULT VALUES +Plan: + +Query: INSERT INTO xftp_servers (xftp_host, xftp_port, xftp_key_hash) VALUES (?,?,?) +Plan: + +Query: SELECT 1 FROM encrypted_rcv_message_hashes WHERE conn_id = ? AND hash = ? LIMIT 1 +Plan: +SEARCH encrypted_rcv_message_hashes USING COVERING INDEX idx_encrypted_rcv_message_hashes_hash (conn_id=? AND hash=?) + +Query: SELECT 1 FROM processed_ratchet_key_hashes WHERE conn_id = ? AND hash = ? LIMIT 1 +Plan: +SEARCH processed_ratchet_key_hashes USING COVERING INDEX idx_processed_ratchet_key_hashes_hash (conn_id=? AND hash=?) + +Query: SELECT 1 FROM snd_message_deliveries WHERE conn_id = ? AND failed = 0 LIMIT 1 +Plan: +SEARCH snd_message_deliveries USING COVERING INDEX idx_snd_message_deliveries_expired (conn_id=?) + +Query: SELECT DISTINCT conn_id FROM snd_message_deliveries WHERE failed = 0 +Plan: +SCAN snd_message_deliveries USING COVERING INDEX idx_snd_message_deliveries_expired + +Query: SELECT conn_id FROM connections WHERE user_id = ? +Plan: +SEARCH connections USING COVERING INDEX idx_connections_user (user_id=?) + +Query: SELECT count(*) FROM snd_message_deliveries WHERE conn_id = ? AND internal_id = ? AND failed = 0 +Plan: +SEARCH snd_message_deliveries USING COVERING INDEX idx_snd_message_deliveries_expired (conn_id=?) + +Query: SELECT deleted FROM snd_files WHERE snd_file_id = ? +Plan: +SEARCH snd_files USING INTEGER PRIMARY KEY (rowid=?) + +Query: SELECT header_key, msg_n, msg_key FROM skipped_messages WHERE conn_id = ? +Plan: +SEARCH skipped_messages USING INDEX idx_skipped_messages_conn_id (conn_id=?) + +Query: SELECT key_hash FROM servers WHERE host = ? AND port = ? +Plan: +SEARCH servers USING PRIMARY KEY (host=? AND port=?) + +Query: SELECT last_insert_rowid() +Plan: +SCAN CONSTANT ROW + +Query: SELECT ratchet_state FROM ratchets WHERE conn_id = ? +Plan: +SEARCH ratchets USING PRIMARY KEY (conn_id=?) + +Query: SELECT ratchet_state, x3dh_pub_key_1, x3dh_pub_key_2, pq_pub_kem FROM ratchets WHERE conn_id = ? +Plan: +SEARCH ratchets USING PRIMARY KEY (conn_id=?) + +Query: SELECT rcpt_internal_id, rcpt_status FROM snd_messages WHERE conn_id = ? AND internal_id = ? +Plan: +SEARCH snd_messages USING PRIMARY KEY (conn_id=?) + +Query: SELECT rcv_file_id FROM rcv_files WHERE rcv_file_entity_id = ? +Plan: +SEARCH rcv_files USING COVERING INDEX sqlite_autoindex_rcv_files_1 (rcv_file_entity_id=?) + +Query: SELECT rcv_file_id FROM rcv_files WHERE redirect_id = ? +Plan: +SEARCH rcv_files USING COVERING INDEX idx_rcv_files_redirect_id (redirect_id=?) + +Query: SELECT rcv_queue_id FROM rcv_queues WHERE conn_id = ? AND host = ? AND port = ? AND snd_id = ? +Plan: +SEARCH rcv_queues USING INDEX sqlite_autoindex_rcv_queues_2 (host=? AND port=? AND snd_id=?) + +Query: SELECT rcv_queue_id FROM rcv_queues WHERE conn_id = ? ORDER BY rcv_queue_id DESC LIMIT 1 +Plan: +SEARCH rcv_queues USING COVERING INDEX idx_rcv_queue_id (conn_id=?) + +Query: SELECT rcv_queue_id, broker_id FROM rcv_messages WHERE conn_id = ? AND internal_id = ? +Plan: +SEARCH rcv_messages USING PRIMARY KEY (conn_id=?) + +Query: SELECT snd_file_id FROM snd_files WHERE snd_file_entity_id = ? +Plan: +SEARCH snd_files USING COVERING INDEX idx_snd_files_snd_file_entity_id (snd_file_entity_id=?) + +Query: SELECT snd_queue_id FROM snd_queues WHERE conn_id = ? AND host = ? AND port = ? AND snd_id = ? +Plan: +SEARCH snd_queues USING PRIMARY KEY (host=? AND port=? AND snd_id=?) + +Query: SELECT snd_queue_id FROM snd_queues WHERE conn_id = ? ORDER BY snd_queue_id DESC LIMIT 1 +Plan: +SEARCH snd_queues USING COVERING INDEX idx_snd_queue_id (conn_id=?) + +Query: SELECT started_at, servers_stats FROM servers_stats WHERE servers_stats_id = 1 +Plan: +SEARCH servers_stats USING INTEGER PRIMARY KEY (rowid=?) + +Query: SELECT user_id FROM users WHERE user_id = ? AND deleted = ? +Plan: +SEARCH users USING INTEGER PRIMARY KEY (rowid=?) + +Query: SELECT x3dh_priv_key_1, x3dh_priv_key_2, pq_priv_kem FROM ratchets WHERE conn_id = ? +Plan: +SEARCH ratchets USING PRIMARY KEY (conn_id=?) + +Query: SELECT xftp_server_id FROM xftp_servers WHERE xftp_host = ? AND xftp_port = ? AND xftp_key_hash = ? +Plan: +SEARCH xftp_servers USING COVERING INDEX sqlite_autoindex_xftp_servers_1 (xftp_host=? AND xftp_port=? AND xftp_key_hash=?) + +Query: UPDATE connections SET deleted = ? WHERE conn_id = ? +Plan: +SEARCH connections USING PRIMARY KEY (conn_id=?) + +Query: UPDATE connections SET deleted_at_wait_delivery = ? WHERE conn_id = ? +Plan: +SEARCH connections USING PRIMARY KEY (conn_id=?) + +Query: UPDATE connections SET enable_ntfs = ? WHERE conn_id = ? +Plan: +SEARCH connections USING PRIMARY KEY (conn_id=?) + +Query: UPDATE connections SET pq_support = ? WHERE conn_id = ? +Plan: +SEARCH connections USING PRIMARY KEY (conn_id=?) + +Query: UPDATE connections SET ratchet_sync_state = ? WHERE conn_id = ? +Plan: +SEARCH connections USING PRIMARY KEY (conn_id=?) + +Query: UPDATE connections SET smp_agent_version = ? WHERE conn_id = ? +Plan: +SEARCH connections USING PRIMARY KEY (conn_id=?) + +Query: UPDATE connections SET user_id = ? WHERE conn_id = ? and user_id = ? +Plan: +SEARCH connections USING PRIMARY KEY (conn_id=?) + +Query: UPDATE messages SET msg_body = x'' WHERE conn_id = ? AND internal_id = ? +Plan: +SEARCH messages USING PRIMARY KEY (conn_id=? AND internal_id=?) + +Query: UPDATE ratchets SET ratchet_state = ? WHERE conn_id = ? +Plan: +SEARCH ratchets USING PRIMARY KEY (conn_id=?) + +Query: UPDATE rcv_file_chunk_replicas SET delay = ?, retries = retries + 1, updated_at = ? WHERE rcv_file_chunk_replica_id = ? +Plan: +SEARCH rcv_file_chunk_replicas USING INTEGER PRIMARY KEY (rowid=?) + +Query: UPDATE rcv_file_chunk_replicas SET received = 1, updated_at = ? WHERE rcv_file_chunk_replica_id = ? +Plan: +SEARCH rcv_file_chunk_replicas USING INTEGER PRIMARY KEY (rowid=?) + +Query: UPDATE rcv_file_chunks SET tmp_path = ?, updated_at = ? WHERE rcv_file_chunk_id = ? +Plan: +SEARCH rcv_file_chunks USING INTEGER PRIMARY KEY (rowid=?) + +Query: UPDATE rcv_files SET deleted = 1, updated_at = ? WHERE rcv_file_id = ? +Plan: +SEARCH rcv_files USING INTEGER PRIMARY KEY (rowid=?) + +Query: UPDATE rcv_files SET key = ?, nonce = ?, chunk_size = ?, updated_at = ? WHERE rcv_file_id = ? +Plan: +SEARCH rcv_files USING INTEGER PRIMARY KEY (rowid=?) + +Query: UPDATE rcv_files SET status = ?, updated_at = ? WHERE rcv_file_id = ? +Plan: +SEARCH rcv_files USING INTEGER PRIMARY KEY (rowid=?) + +Query: UPDATE rcv_files SET tmp_path = NULL, error = ?, status = ?, updated_at = ? WHERE rcv_file_id = ? +Plan: +SEARCH rcv_files USING INTEGER PRIMARY KEY (rowid=?) + +Query: UPDATE rcv_files SET tmp_path = NULL, status = ?, updated_at = ? WHERE rcv_file_id = ? +Plan: +SEARCH rcv_files USING INTEGER PRIMARY KEY (rowid=?) + +Query: UPDATE rcv_messages SET user_ack = ? WHERE conn_id = ? AND internal_id = ? +Plan: +SEARCH rcv_messages USING COVERING INDEX idx_rcv_messages_conn_id_internal_id (conn_id=? AND internal_id=?) + +Query: UPDATE rcv_queues SET last_broker_ts = ? WHERE conn_id = ? AND rcv_queue_id = ? +Plan: +SEARCH rcv_queues USING COVERING INDEX idx_rcv_queue_id (conn_id=? AND rcv_queue_id=?) + +Query: UPDATE rcv_queues SET rcv_primary = ? WHERE conn_id = ? +Plan: +SEARCH rcv_queues USING COVERING INDEX idx_rcv_queue_id (conn_id=?) + +Query: UPDATE rcv_queues SET rcv_primary = ?, replace_rcv_queue_id = ? WHERE conn_id = ? AND rcv_queue_id = ? +Plan: +SEARCH rcv_queues USING COVERING INDEX idx_rcv_queue_id (conn_id=? AND rcv_queue_id=?) + +Query: UPDATE servers_stats SET servers_stats = ?, updated_at = ? WHERE servers_stats_id = 1 +Plan: +SEARCH servers_stats USING INTEGER PRIMARY KEY (rowid=?) + +Query: UPDATE snd_file_chunk_replicas SET replica_status = ?, updated_at = ? WHERE snd_file_chunk_replica_id = ? +Plan: +SEARCH snd_file_chunk_replicas USING INTEGER PRIMARY KEY (rowid=?) + +Query: UPDATE snd_files SET deleted = 1, updated_at = ? WHERE snd_file_id = ? +Plan: +SEARCH snd_files USING INTEGER PRIMARY KEY (rowid=?) + +Query: UPDATE snd_files SET prefix_path = NULL, status = ?, updated_at = ? WHERE snd_file_id = ? +Plan: +SEARCH snd_files USING INTEGER PRIMARY KEY (rowid=?) + +Query: UPDATE snd_files SET status = ?, digest = ?, updated_at = ? WHERE snd_file_id = ? +Plan: +SEARCH snd_files USING INTEGER PRIMARY KEY (rowid=?) + +Query: UPDATE snd_files SET status = ?, updated_at = ? WHERE snd_file_id = ? +Plan: +SEARCH snd_files USING INTEGER PRIMARY KEY (rowid=?) + +Query: UPDATE snd_messages SET rcpt_internal_id = ?, rcpt_status = ? WHERE conn_id = ? AND internal_snd_id = ? +Plan: +SEARCH snd_messages USING PRIMARY KEY (conn_id=? AND internal_snd_id=?) + +Query: UPDATE snd_messages SET retry_int_slow = ?, retry_int_fast = ? WHERE conn_id = ? AND internal_id = ? +Plan: +SEARCH snd_messages USING COVERING INDEX idx_snd_messages_conn_id_internal_id (conn_id=? AND internal_id=?) + +Query: UPDATE snd_queues SET snd_primary = ? WHERE conn_id = ? +Plan: +SEARCH snd_queues USING COVERING INDEX idx_snd_queue_id (conn_id=?) + +Query: UPDATE snd_queues SET snd_primary = ?, replace_snd_queue_id = ? WHERE conn_id = ? AND snd_queue_id = ? +Plan: +SEARCH snd_queues USING COVERING INDEX idx_snd_queue_id (conn_id=? AND snd_queue_id=?) + +Query: UPDATE users SET deleted = ? WHERE user_id = ? +Plan: +SEARCH users USING INTEGER PRIMARY KEY (rowid=?) + diff --git a/tests/ChatClient.hs b/tests/ChatClient.hs index d330510d62..1a04badc3e 100644 --- a/tests/ChatClient.hs +++ b/tests/ChatClient.hs @@ -70,6 +70,7 @@ import Database.PostgreSQL.Simple (ConnectInfo (..), defaultConnectInfo) #else import Data.ByteArray (ScrubbedBytes) import qualified Data.Map.Strict as M +import Simplex.Messaging.Agent.Client (agentClientStore) import Simplex.Messaging.Agent.Store.Common (withConnection) import System.FilePath (()) #endif @@ -324,8 +325,10 @@ stopTestChat ps TestCC {chatController = cc@ChatController {smpAgent, chatStore} uninterruptibleCancel chatAsync liftIO $ disposeAgentClient smpAgent #if !defined(dbPostgres) - stats <- withConnection chatStore $ readTVarIO . DB.slow - atomically $ modifyTVar' (queryStats ps) $ M.unionWith combineStats stats + chatStats <- withConnection chatStore $ readTVarIO . DB.slow + atomically $ modifyTVar' (chatQueryStats ps) $ M.unionWith combineStats chatStats + agentStats <- withConnection (agentClientStore smpAgent) $ readTVarIO . DB.slow + atomically $ modifyTVar' (agentQueryStats ps) $ M.unionWith combineStats agentStats #endif closeDBStore chatStore threadDelay 200000 diff --git a/tests/ChatTests/DBUtils/SQLite.hs b/tests/ChatTests/DBUtils/SQLite.hs index cdde43b015..b66e5ac851 100644 --- a/tests/ChatTests/DBUtils/SQLite.hs +++ b/tests/ChatTests/DBUtils/SQLite.hs @@ -6,5 +6,6 @@ import Simplex.Messaging.TMap (TMap) data TestParams = TestParams { tmpPath :: FilePath, - queryStats :: TMap Query SlowQueryStats + chatQueryStats :: TMap Query SlowQueryStats, + agentQueryStats :: TMap Query SlowQueryStats } diff --git a/tests/SchemaDump.hs b/tests/SchemaDump.hs index 89a90ec7e5..a6ce19da87 100644 --- a/tests/SchemaDump.hs +++ b/tests/SchemaDump.hs @@ -20,12 +20,13 @@ import qualified Data.Text.IO as T import Database.SQLite.Simple (Query (..)) import Simplex.Chat.Store (createChatStore) import qualified Simplex.Chat.Store as Store +import Simplex.Messaging.Agent.Env.SQLite (createAgentStore) import Simplex.Messaging.Agent.Store.Common (withConnection) -import Simplex.Messaging.Agent.Store.Interface -import Simplex.Messaging.Agent.Store.Shared (Migration (..), MigrationConfirmation (..), MigrationsToRun (..), toDownMigration) import Simplex.Messaging.Agent.Store.DB (TrackQueries (..)) import qualified Simplex.Messaging.Agent.Store.DB as DB +import Simplex.Messaging.Agent.Store.Interface import qualified Simplex.Messaging.Agent.Store.SQLite.Migrations as Migrations +import Simplex.Messaging.Agent.Store.Shared (Migration (..), MigrationConfirmation (..), MigrationsToRun (..), toDownMigration) import Simplex.Messaging.Util (ifM, tshow, whenM) import System.Directory (doesFileExist, removeFile) import System.Process (readCreateProcess, shell) @@ -34,6 +35,9 @@ import Test.Hspec testDB :: FilePath testDB = "tests/tmp/test_chat.db" +testAgentDB :: FilePath +testAgentDB = "tests/tmp/test_agent.db" + appSchema :: FilePath appSchema = "src/Simplex/Chat/Store/SQLite/Migrations/chat_schema.sql" @@ -53,8 +57,11 @@ appSchema = "src/Simplex/Chat/Store/SQLite/Migrations/chat_schema.sql" appLint :: FilePath appLint = "src/Simplex/Chat/Store/SQLite/Migrations/chat_lint.sql" -appQueryPlans :: FilePath -appQueryPlans = "src/Simplex/Chat/Store/SQLite/Migrations/chat_query_plans.txt" +appChatQueryPlans :: FilePath +appChatQueryPlans = "src/Simplex/Chat/Store/SQLite/Migrations/chat_query_plans.txt" + +appAgentQueryPlans :: FilePath +appAgentQueryPlans = "src/Simplex/Chat/Store/SQLite/Migrations/agent_query_plans.txt" testSchema :: FilePath testSchema = "tests/tmp/test_agent_schema.sql" @@ -138,18 +145,35 @@ getLintFKeyIndexes dbPath lintPath = do lint `deepseq` pure lint saveQueryPlans :: SpecWith TestParams -saveQueryPlans = it "verify and overwrite query plans" $ \TestParams {queryStats} -> do - savedPlans <- ifM (doesFileExist appQueryPlans) (T.readFile appQueryPlans) (pure "") - savedPlans `deepseq` pure () - queries <- sort . M.keys <$> readTVarIO queryStats - Right st <- createChatStore (DBOpts testDB "" False True TQOff) MCError - plans' <- withConnection st $ \db -> do - DB.execute_ db "CREATE TABLE IF NOT EXISTS temp_conn_ids (conn_id BLOB)" - mapM (getQueryPlan db) queries - let savedPlans' = T.unlines plans' - T.writeFile appQueryPlans savedPlans' - savedPlans' `shouldBe` savedPlans +saveQueryPlans = it "verify and overwrite query plans" $ \TestParams {chatQueryStats, agentQueryStats} -> do + (chatSavedPlans, chatSavedPlans') <- + updatePlans + appChatQueryPlans + chatQueryStats + (createChatStore (DBOpts testDB "" False True TQOff) MCError) + (`DB.execute_` "CREATE TABLE IF NOT EXISTS temp_conn_ids (conn_id BLOB)") + (agentSavedPlans, agentSavedPlans') <- + updatePlans + appAgentQueryPlans + agentQueryStats + (createAgentStore (DBOpts testAgentDB "" False True TQOff) MCError) + (const $ pure ()) + chatSavedPlans' `shouldBe` chatSavedPlans + agentSavedPlans' `shouldBe` agentSavedPlans + removeFile testDB + removeFile testAgentDB where + updatePlans plansFile statsSel createStore prepareStore = do + savedPlans <- ifM (doesFileExist plansFile) (T.readFile plansFile) (pure "") + savedPlans `deepseq` pure () + queries <- sort . M.keys <$> readTVarIO statsSel + Right st <- createStore + plans' <- withConnection st $ \db -> do + void $ prepareStore db + mapM (getQueryPlan db) queries + let savedPlans' = T.unlines plans' + T.writeFile plansFile savedPlans' + pure (savedPlans, savedPlans') getQueryPlan :: DB.Connection -> Query -> IO Text getQueryPlan db q = (("Query: " <> fromQuery q) <>) . result <$> E.try (DB.query_ db $ "explain query plan " <> q) diff --git a/tests/Test.hs b/tests/Test.hs index b2b4e7201a..42dc5a0524 100644 --- a/tests/Test.hs +++ b/tests/Test.hs @@ -34,7 +34,8 @@ main :: IO () main = do setLogLevel LogError #if !defined(dbPostgres) - queryStats <- TM.emptyIO + chatQueryStats <- TM.emptyIO + agentQueryStats <- TM.emptyIO #endif withGlobalLogging logCfg . hspec #if defined(dbPostgres) @@ -59,7 +60,7 @@ main = do around testBracket . after_ (dropAllSchemasExceptSystem testDBConnectInfo) #else - around (testBracket queryStats) + around (testBracket chatQueryStats agentQueryStats) #endif $ do #if !defined(dbPostgres) @@ -73,10 +74,11 @@ main = do xdescribe'' "Save query plans" saveQueryPlans #endif where -#if defined(dbPostgres) +#if defined(dbPostgres) testBracket test = withSmpServer $ tmpBracket $ test . TestParams #else - testBracket queryStats test = withSmpServer $ tmpBracket $ \tmpPath -> test TestParams {tmpPath, queryStats} + testBracket chatQueryStats agentQueryStats test = + withSmpServer $ tmpBracket $ \tmpPath -> test TestParams {tmpPath, chatQueryStats, agentQueryStats} #endif tmpBracket test = do t <- getSystemTime