From 8ed08f701d0599331cb4e0143992ae43799cca93 Mon Sep 17 00:00:00 2001 From: Alexander Krotov Date: Sat, 15 Feb 2020 16:30:11 +0300 Subject: [PATCH] Do not use grpid to find last inserted row in chats table Instead, use last_insert_rowid() function to find the row. There is no race condition in using last_insert_rowid(), because last_insert_rowid() returns row id last inserted in this connection. As we hold the connection during the whole transaction, it is impossible that some other thread will execute INSERT statement in parallel. This commit is part of the effort to get rid of sql::get_rowid hack and use transactions more for related SQL statements. --- src/chat.rs | 36 +++++++++++++++++------------------- src/sql.rs | 5 +++++ 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/chat.rs b/src/chat.rs index 91fc16a82..51bc2bde8 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -1184,33 +1184,31 @@ pub fn create_or_lookup_by_contact_id( let contact = Contact::load_from_db(context, contact_id)?; let chat_name = contact.get_display_name(); - sql::execute( - context, - &context.sql, - "INSERT INTO chats (type, name, param, blocked, grpid, created_timestamp) VALUES(?, ?, ?, ?, ?, ?)", + context + .sql + .start_stmt("create_or_lookup_by_contact_id transaction"); + context.sql.with_conn(|conn| { + let tx = conn.transaction()?; + tx.execute( + "INSERT INTO chats (type, name, param, blocked, created_timestamp) VALUES(?, ?, ?, ?, ?)", params![ - 100, + Chattype::Single, chat_name, match contact_id { DC_CONTACT_ID_SELF => "K=1".to_string(), // K = Param::Selftalk DC_CONTACT_ID_DEVICE => "D=1".to_string(), // D = Param::Devicetalk - _ => "".to_string() + _ => "".to_string(), }, create_blocked as u8, - contact.get_addr(), time(), ] - )?; - - let row_id = sql::get_rowid(context, &context.sql, "chats", "grpid", contact.get_addr()); - let chat_id = ChatId::new(row_id); - - sql::execute( - context, - &context.sql, - "INSERT INTO chats_contacts (chat_id, contact_id) VALUES(?, ?)", - params![chat_id, contact_id], - )?; + )?; + tx.execute( + "INSERT INTO chats_contacts (chat_id, contact_id) VALUES((SELECT last_insert_rowid()), ?)", + params![contact_id])?; + tx.commit()?; + Ok(()) + })?; if contact_id == DC_CONTACT_ID_SELF { update_saved_messages_icon(context)?; @@ -1218,7 +1216,7 @@ pub fn create_or_lookup_by_contact_id( update_device_icon(context)?; } - Ok((chat_id, create_blocked)) + lookup_by_contact_id(context, contact_id) } pub fn lookup_by_contact_id( diff --git a/src/sql.rs b/src/sql.rs index ea073ee5d..8e15d1fdd 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -893,6 +893,11 @@ fn open( )?; sql.set_raw_config_int(context, "dbversion", 62)?; } + if dbversion < 63 { + info!(context, "[migration] v63"); + sql.execute("UPDATE chats SET grpid='' WHERE type=100", NO_PARAMS)?; + sql.set_raw_config_int(context, "dbversion", 63)?; + } // (2) updates that require high-level objects // (the structure is complete now and all objects are usable)