From 9ab86f2a34172f60daf396c0cc3f58f66f5053d1 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Thu, 21 Mar 2019 22:45:14 +0100 Subject: [PATCH] save location together with messages --- src/dc_context.h | 6 ++--- src/dc_job.c | 3 ++- src/dc_location.c | 56 +++++++++++++++++++++++++++++--------------- src/dc_mimefactory.c | 6 +++-- src/dc_mimefactory.h | 2 +- src/dc_receive_imf.c | 2 +- src/dc_sqlite3.c | 16 ++++++++++--- 7 files changed, 61 insertions(+), 30 deletions(-) diff --git a/src/dc_context.h b/src/dc_context.h index 8e40ba9b..7ab2e6a6 100644 --- a/src/dc_context.h +++ b/src/dc_context.h @@ -141,12 +141,12 @@ typedef struct _dc_kml dc_location_t curr; } dc_kml_t; -char* dc_get_location_kml (dc_context_t*, uint32_t chat_id); +char* dc_get_location_kml (dc_context_t*, uint32_t chat_id, uint32_t* last_added_location_id); void dc_set_kml_sent_timestamp (dc_context_t*, uint32_t chat_id, time_t); -int dc_save_locations (dc_context_t*, uint32_t chat_id, uint32_t contact_id, const dc_array_t*); +void dc_set_msg_location_id (dc_context_t*, uint32_t msg_id, uint32_t location_id); +int dc_save_locations (dc_context_t*, uint32_t chat_id, uint32_t msg_id, uint32_t contact_id, const dc_array_t*); dc_kml_t* dc_kml_parse (dc_context_t*, const char* content, size_t content_bytes); void dc_kml_unref (dc_kml_t*); - void dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS (dc_context_t*, dc_job_t*); diff --git a/src/dc_job.c b/src/dc_job.c index ced07781..bf9d3e09 100644 --- a/src/dc_job.c +++ b/src/dc_job.c @@ -310,8 +310,9 @@ int dc_job_send_msg(dc_context_t* context, uint32_t msg_id) dc_set_gossiped_timestamp(context, mimefactory.msg->chat_id, time(NULL)); } - if (mimefactory.out_locations_added) { + if (mimefactory.out_last_added_location_id) { dc_set_kml_sent_timestamp(context, mimefactory.msg->chat_id, time(NULL)); + dc_set_msg_location_id(context, mimefactory.msg->id, mimefactory.out_last_added_location_id); } if (mimefactory.out_encrypted && dc_param_get_int(mimefactory.msg->param, DC_PARAM_GUARANTEE_E2EE, 0)==0) { diff --git a/src/dc_location.c b/src/dc_location.c index 206eb49a..9aa7de50 100644 --- a/src/dc_location.c +++ b/src/dc_location.c @@ -19,14 +19,11 @@ static char* get_kml_timestamp(time_t utc) } -char* dc_get_location_kml(dc_context_t* context, uint32_t chat_id) +char* dc_get_location_kml(dc_context_t* context, uint32_t chat_id, + uint32_t* last_added_location_id) { int success = 0; sqlite3_stmt* stmt = NULL; - double latitude = 0.0; - double longitude = 0.0; - double accuracy = 0.0; - char* timestamp = NULL; char* self_addr = NULL; time_t now = time(NULL); time_t locations_send_begin = 0; @@ -69,7 +66,7 @@ char* dc_get_location_kml(dc_context_t* context, uint32_t chat_id) self_addr); stmt = dc_sqlite3_prepare(context->sql, - "SELECT latitude, longitude, accuracy, timestamp " + "SELECT id, latitude, longitude, accuracy, timestamp " " FROM locations " " WHERE from_id=? " " AND timestamp>=? " @@ -81,10 +78,11 @@ char* dc_get_location_kml(dc_context_t* context, uint32_t chat_id) sqlite3_bind_int (stmt, 4, DC_CONTACT_ID_SELF); while (sqlite3_step(stmt)==SQLITE_ROW) { - latitude = sqlite3_column_double(stmt, 0); - longitude = sqlite3_column_double(stmt, 1); - accuracy = sqlite3_column_double(stmt, 2); - timestamp = get_kml_timestamp(sqlite3_column_int64 (stmt, 3)); + uint32_t location_id = sqlite3_column_int(stmt, 0); + double latitude = sqlite3_column_double(stmt, 1); + double longitude = sqlite3_column_double(stmt, 2); + double accuracy = sqlite3_column_double(stmt, 3); + char* timestamp = get_kml_timestamp(sqlite3_column_int64 (stmt, 4)); dc_strbuilder_catf(&ret, "" @@ -98,6 +96,10 @@ char* dc_get_location_kml(dc_context_t* context, uint32_t chat_id) location_count++; + if (last_added_location_id) { + *last_added_location_id = location_id; + } + free(timestamp); timestamp = NULL; } @@ -137,6 +139,20 @@ void dc_set_kml_sent_timestamp(dc_context_t* context, } +void dc_set_msg_location_id(dc_context_t* context, uint32_t msg_id, uint32_t location_id) +{ + sqlite3_stmt* stmt = NULL; + + stmt = dc_sqlite3_prepare(context->sql, + "UPDATE msgs SET location_id=? WHERE id=?;"); + sqlite3_bind_int64(stmt, 1, location_id); + sqlite3_bind_int (stmt, 2, msg_id); + + sqlite3_step(stmt); + sqlite3_finalize(stmt); +} + + /******************************************************************************* * parse kml-files ******************************************************************************/ @@ -304,7 +320,7 @@ void dc_kml_unref(dc_kml_t* kml) int dc_save_locations(dc_context_t* context, - uint32_t chat_id, uint32_t contact_id, + uint32_t chat_id, uint32_t msg_id, uint32_t contact_id, const dc_array_t* locations) { int saved_locations = 0; @@ -656,22 +672,24 @@ dc_array_t* dc_get_locations(dc_context_t* context, uint32_t chat_id, uint32_t } if (contact_id==DC_CONTACT_ID_SELF) { - #define LOC_FIELDS "latitude, longitude, accuracy, timestamp, msg_id" + #define LOC_FIELDS "l.latitude, l.longitude, l.accuracy, l.timestamp, m.id" stmt = dc_sqlite3_prepare(context->sql, "SELECT " LOC_FIELDS - " FROM locations " - " WHERE from_id=? " - " ORDER BY timestamp DESC, id DESC " + " FROM locations l " + " LEFT JOIN msgs m ON l.id=m.location_id " + " WHERE l.from_id=? " + " ORDER BY l.timestamp DESC, l.id DESC " " LIMIT " LOC_LIMIT); sqlite3_bind_int(stmt, 1, DC_CONTACT_ID_SELF); } else { stmt = dc_sqlite3_prepare(context->sql, "SELECT " LOC_FIELDS - " FROM locations " - " WHERE chat_id=? " - " AND from_id=? " - " ORDER BY timestamp DESC, id DESC " + " FROM locations l " + " LEFT JOIN msgs m ON l.id=m.location_id " + " WHERE l.chat_id=? " + " AND l.from_id=? " + " ORDER BY l.timestamp DESC, l.id DESC " " LIMIT " LOC_LIMIT); sqlite3_bind_int(stmt, 1, chat_id); sqlite3_bind_int(stmt, 2, contact_id); diff --git a/src/dc_mimefactory.c b/src/dc_mimefactory.c index c2cae8b4..006c9432 100644 --- a/src/dc_mimefactory.c +++ b/src/dc_mimefactory.c @@ -702,7 +702,9 @@ int dc_mimefactory_render(dc_mimefactory_t* factory) } if (dc_is_sending_locations_to_chat(msg->context, msg->chat_id)) { - char* kml_file = dc_get_location_kml(msg->context, msg->chat_id); + uint32_t last_added_location_id = 0; + char* kml_file = dc_get_location_kml(msg->context, msg->chat_id, + &last_added_location_id); if (kml_file) { struct mailmime_content* content_type = mailmime_content_new_with_str("application/vnd.google-earth.kml+xml"); struct mailmime_fields* mime_fields = mailmime_fields_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, @@ -712,7 +714,7 @@ int dc_mimefactory_render(dc_mimefactory_t* factory) mailmime_smart_add_part(message, kml_mime_part); parts++; - factory->out_locations_added = 1; + factory->out_last_added_location_id = last_added_location_id; } } } diff --git a/src/dc_mimefactory.h b/src/dc_mimefactory.h index 5b52b1f5..958aee56 100644 --- a/src/dc_mimefactory.h +++ b/src/dc_mimefactory.h @@ -54,7 +54,7 @@ struct _dc_mimefactory { MMAPString* out; int out_encrypted; int out_gossiped; - int out_locations_added; + uint32_t out_last_added_location_id; char* error; /* private */ diff --git a/src/dc_receive_imf.c b/src/dc_receive_imf.c index a89fe25d..99643b0b 100644 --- a/src/dc_receive_imf.c +++ b/src/dc_receive_imf.c @@ -1587,7 +1587,7 @@ void dc_receive_imf(dc_context_t* context, const char* imf_raw_not_terminated, s if (mime_parser->kml->addr && strcasecmp(contact->addr, mime_parser->kml->addr)==0) { - if (dc_save_locations(context, chat_id, from_id, mime_parser->kml->locations)) { + if (dc_save_locations(context, chat_id, insert_msg_id, from_id, mime_parser->kml->locations)) { context->cb(context, DC_EVENT_LOCATION_CHANGED, from_id, 0); } } diff --git a/src/dc_sqlite3.c b/src/dc_sqlite3.c index c2090348..e7773a8c 100644 --- a/src/dc_sqlite3.c +++ b/src/dc_sqlite3.c @@ -576,14 +576,13 @@ int dc_sqlite3_open(dc_sqlite3_t* sql, const char* dbfile, int flags) // the messages containing _only_ locations // are also added to the database as _hidden_. dc_sqlite3_execute(sql, "CREATE TABLE locations (" - " id INTEGER PRIMARY KEY," + " 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," - " msg_id INTEGER DEFAULT 0);"); + " from_id INTEGER DEFAULT 0);"); dc_sqlite3_execute(sql, "CREATE INDEX locations_index1 ON locations (from_id);"); dc_sqlite3_execute(sql, "CREATE INDEX locations_index2 ON locations (timestamp);"); dc_sqlite3_execute(sql, "ALTER TABLE chats ADD COLUMN locations_send_begin INTEGER DEFAULT 0;"); @@ -596,6 +595,17 @@ int dc_sqlite3_open(dc_sqlite3_t* sql, const char* dbfile, int flags) } #undef NEW_DB_VERSION + #define NEW_DB_VERSION 54 + if (dbversion < NEW_DB_VERSION) + { + dc_sqlite3_execute(sql, "ALTER TABLE msgs ADD COLUMN location_id INTEGER DEFAULT 0;"); + dc_sqlite3_execute(sql, "CREATE INDEX msgs_index6 ON msgs (location_id);"); + + dbversion = NEW_DB_VERSION; + dc_sqlite3_set_config_int(sql, "dbversion", NEW_DB_VERSION); + } + #undef NEW_DB_VERSION + // (2) updates that require high-level objects // (the structure is complete now and all objects are usable) // --------------------------------------------------------------------