/soc/2015/igor.gajowiak/chatlog: 9d6836494f9f: Implemented getti...

Igor Gajowiak igor.gajowiak at gmail.com
Sat Jul 25 18:52:53 EDT 2015


Changeset: 9d6836494f9f04ae3708506fbd903f6be5bbd3da
Author:	 Igor Gajowiak <igor.gajowiak at gmail.com>
Date:	 2015-07-26 00:52 +0200
Branch:	 default
URL: https://hg.pidgin.im/soc/2015/igor.gajowiak/chatlog/rev/9d6836494f9f

Description:

Implemented getting older messages from a log.

diffstat:

 libpurple/genericlog.c            |   11 ++
 libpurple/genericlog.h            |   40 +++++++-
 libpurple/plugins/log/logsqlite.c |  170 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 211 insertions(+), 10 deletions(-)

diffs (truncated from 340 to 300 lines):

diff --git a/libpurple/genericlog.c b/libpurple/genericlog.c
--- a/libpurple/genericlog.c
+++ b/libpurple/genericlog.c
@@ -257,6 +257,16 @@ purple_genericlog_get_all_msgs(PurpleBud
 }
 
 gboolean
+purple_genericlog_get_older_msgs(PurpleBuddy *buddy, guint64 timestamp,
+	PurpleMessage *message, GList **result, GError **error)
+{
+	DEFINE_GENERICLOG_FUNC_WITH_RETURN(get_older_msgs,
+		"%s does not support getting older messages",
+		"Getting older messages from %s failed",
+		buddy, timestamp, message, result);
+}
+
+gboolean
 purple_genericlog_get_all_buddies(GList** result, GError** error)
 {
 	DEFINE_GENERICLOG_FUNC_WITH_RETURN(get_all_buddies,
@@ -351,6 +361,7 @@ purple_genericlog_class_init(PurpleGener
 	klass->mark_as_seen = NULL;
 	klass->get_unseen_msgs = NULL;
 	klass->get_all_msgs = NULL;
+	klass->get_older_msgs = NULL;
 	klass->get_all_buddies = NULL;
 
 	klass->reserved1 = NULL;
diff --git a/libpurple/genericlog.h b/libpurple/genericlog.h
--- a/libpurple/genericlog.h
+++ b/libpurple/genericlog.h
@@ -64,6 +64,11 @@ struct _PurpleGenericLog
  * @get_all_msgs:    Gets all messages sent to or received from a buddy.
  *                   Messages are sorted by their timestamp in ascending order.
  *                   Returns %TRUE if operation succeeds, %FALSE otherwise.
+ * @get_older_msgs:  Gets all messages sent to or received from a buddy, older
+ *                   than the message and not older than the timestamp.
+ *                   If message is %NULL then upper bound check is skipped.
+ *                   Messages are sorted by their timestamp in descending order.
+ *                   Returns %TRUE if operation succeeds, %FALSE otherwise.
  * @get_all_buddies: Gets a list of all #PurpleBuddy objects with at least one
  *                   message in the log. Returns %TRUE if operation succeeds,
  *                   %FALSE otherwise. The client is responsible for freeing
@@ -90,6 +95,9 @@ struct _PurpleGenericLogClass
 
 	gboolean (*get_all_msgs)(PurpleBuddy *buddy, GList **result);
 
+	gboolean (*get_older_msgs)(PurpleBuddy *buddy, guint64 timestamp,
+		PurpleMessage *message, GList **result);
+
 	gboolean (*get_all_buddies)(GList **result);
 
 	void (*reserved1)(void);
@@ -242,11 +250,11 @@ purple_genericlog_get_unseen_msgs(Purple
 
 /**
  * purple_genericlog_get_all_msgs:
- * @buddy:  The buddy.
- * @result: Return location for a #GList of #PurpleMessage objects.
- *          This will not be set in case of any errors.
- * @error:  Return location for a #GError or %NULL. If provided, this
- *          will be set to the reason if getting messages fails.
+ * @buddy:       The buddy.
+ * @result[out]: Return location for a #GList of #PurpleMessage objects.
+ *               This will not be set in case of any errors.
+ * @error:       Return location for a #GError or %NULL. If provided, this
+ *               will be set to the reason if getting messages fails.
  *
  * Gets all messages from the active log sent to or received from a buddy.
  *
@@ -261,6 +269,28 @@ purple_genericlog_get_all_msgs(PurpleBud
 	GError **error);
 
 /**
+ * purple_genericlog_get_older_msgs:
+ * @buddy:       The buddy.
+ * @timestamp:   The lower bound.
+ * @message:     The upper bound or %NULL. If not provided then upper bound
+ *               check is skipped.
+ * @result[out]: Return location for a #GList of #PurpleMessage objects.
+ *               This will not be set in case of any errors.
+ * @error:       Return location for a #GError or %NULL. If provided, this
+ *               will be set to the reason if getting messages fails.
+ *
+ * Gets messages older than the message and not older than the timestamp
+ * sent to or received from a buddy from the active log.
+ *
+ * Messages are sorted by their timestamp in descending order.
+ *
+ * Returns: %TRUE if succeeds, %FALSE otherwise.
+ */
+gboolean
+purple_genericlog_get_older_msgs(PurpleBuddy *buddy, guint64 timestamp,
+	PurpleMessage *message, GList **result, GError **error);
+
+/**
  * purple_genericlog_get_all_buddies:
  * @result[out]: Return location for a #GList containing a list of #PurpleBuddy
  *               objects. This will not be set in case of any errors.
diff --git a/libpurple/plugins/log/logsqlite.c b/libpurple/plugins/log/logsqlite.c
--- a/libpurple/plugins/log/logsqlite.c
+++ b/libpurple/plugins/log/logsqlite.c
@@ -123,6 +123,40 @@ typedef enum
 	GET_ALL_MSGS_QUERY_PARAM_WHO       = 2,
 } GetAllMsgsQueryParam;
 
+static sqlite3_stmt *get_older_msgs_q = NULL;
+
+static const char *get_older_msgs_q_str =
+	"SELECT Id, Author, AuthorAlias, Recipient, Contents, MsgTime, Flags "
+	"FROM Messages "
+	"WHERE AccountId = ?1 AND MsgTime >= ?2 "
+	"AND (Author = ?3 OR Recipient = ?3) "
+	"ORDER BY MsgTime, Id;";
+
+typedef enum
+{
+	GET_OLDER_MSGS_QUERY_PARAM_ACCOUNTID  = 1,
+	GET_OLDER_MSGS_QUERY_PARAM_LOWERBOUND = 2,
+	GET_OLDER_MSGS_QUERY_PARAM_WHO        = 3
+} GetOlderMsgsQueryParam;
+
+static sqlite3_stmt *get_older_msgs_upper_q = NULL;
+
+static const char *get_older_msgs_upper_q_str =
+	"SELECT Id, Author, AuthorAlias, Recipient, Contents, MsgTime, Flags "
+	"FROM Messages "
+	"WHERE AccountId = ?1 AND MsgTime >= ?2 AND MsgTime <= ?3 AND Id != ?4 "
+	"AND (Author = ?5 OR Recipient = ?5) "
+	"ORDER BY MsgTime, Id;";
+
+typedef enum
+{
+	GET_OLDER_MSGS_UPPER_QUERY_PARAM_ACCOUNTID  = 1,
+	GET_OLDER_MSGS_UPPER_QUERY_PARAM_LOWERBOUND = 2,
+	GET_OLDER_MSGS_UPPER_QUERY_PARAM_UPPERBOUND = 3,
+	GET_OLDER_MSGS_UPPER_QUERY_PARAM_EXCEPTID   = 4,
+	GET_OLDER_MSGS_UPPER_QUERY_PARAM_WHO        = 5
+} GetOlderMsgsUpperQueryParam;
+
 typedef enum
 {
 	GET_MSGS_QUERY_COL_ID          = 0,
@@ -185,6 +219,8 @@ sqlitelog_finalize_queries()
 	sqlitelog_finalize_query(&insert_message_q);
 	sqlitelog_finalize_query(&get_unseen_msgs_q);
 	sqlitelog_finalize_query(&get_all_msgs_q);
+	sqlitelog_finalize_query(&get_older_msgs_q);
+	sqlitelog_finalize_query(&get_older_msgs_upper_q);
 	sqlitelog_finalize_query(&mark_as_seen_q);
 	sqlitelog_finalize_query(&get_all_buddies_q);
 }
@@ -219,6 +255,9 @@ sqlitelog_prepare_queries()
 		!sqlitelog_prepare_query(insert_message_q_str, &insert_message_q) ||
 		!sqlitelog_prepare_query(get_unseen_msgs_q_str, &get_unseen_msgs_q) ||
 		!sqlitelog_prepare_query(get_all_msgs_q_str, &get_all_msgs_q) ||
+		!sqlitelog_prepare_query(get_older_msgs_q_str, &get_older_msgs_q) ||
+		!sqlitelog_prepare_query(get_older_msgs_upper_q_str,
+			&get_older_msgs_upper_q) ||
 		!sqlitelog_prepare_query(mark_as_seen_q_str, &mark_as_seen_q) ||
 		!sqlitelog_prepare_query(get_all_buddies_q_str, &get_all_buddies_q)) {
 
@@ -261,6 +300,7 @@ sqlitelog_create_tables(sqlite3 *db_hand
 
 		"CREATE INDEX SeenIndex ON Messages (Seen); "
 		"CREATE INDEX SendIndex ON Messages (Send); "
+		"CREATE INDEX MsgTimeIndex ON Messages (MsgTime); "
 
 		"CREATE TRIGGER AccountDeleted AFTER DELETE ON Accounts "
 		"BEGIN "
@@ -512,23 +552,23 @@ sqlitelog_get_all_msgs_impl(PurpleBuddy 
 
 	g_assert(get_all_msgs_q);
 
+	const char *buddy_name = purple_buddy_get_name(buddy);
+	g_return_val_if_fail(buddy_name != NULL, FALSE);
+
 	PurpleAccount *account = purple_buddy_get_account(buddy);
-
 	g_return_val_if_fail(account != NULL, FALSE);
 
 	unsigned account_id;
 	if (!sqlitelog_get_account_id(account, &account_id))
 		return FALSE;
 
+	// If there are no messages sent or received from account
+	// then return empty list
 	if (account_id == SQLITELOG_DB_ID_NONE) {
 		*result = NULL;
 		return TRUE;
 	}
 
-	const char *buddy_name = purple_buddy_get_name(buddy);
-
-	g_return_val_if_fail(buddy_name != NULL, FALSE);
-
 	if (sqlite3_bind_int64(get_all_msgs_q,
 			GET_ALL_MSGS_QUERY_PARAM_ACCOUNTID, account_id) != SQLITE_OK ||
 		sqlite3_bind_text(get_all_msgs_q,
@@ -541,6 +581,105 @@ sqlitelog_get_all_msgs_impl(PurpleBuddy 
 }
 
 static gboolean
+sqlitelog_get_older_msgs_impl(PurpleBuddy *buddy, guint64 timestamp,
+	GList **result)
+{
+	g_assert(buddy);
+	g_assert(result);
+
+	g_assert(get_older_msgs_q);
+
+	const char *buddy_name = purple_buddy_get_name(buddy);
+	g_return_val_if_fail(buddy_name != NULL, FALSE);
+
+	PurpleAccount *account = purple_buddy_get_account(buddy);
+	g_return_val_if_fail(account != NULL, FALSE);
+
+	unsigned account_id;
+	if (!sqlitelog_get_account_id(account, &account_id))
+		return FALSE;
+
+	// If there are no messages sent or received from account
+	// then return empty list
+	if (account_id == SQLITELOG_DB_ID_NONE) {
+		*result = NULL;
+		return TRUE;
+	}
+
+	if (sqlite3_bind_int64(get_older_msgs_q,
+			GET_OLDER_MSGS_QUERY_PARAM_ACCOUNTID, account_id) != SQLITE_OK ||
+		sqlite3_bind_int64(get_older_msgs_q,
+			GET_OLDER_MSGS_QUERY_PARAM_LOWERBOUND, timestamp) != SQLITE_OK ||
+		sqlite3_bind_text(get_older_msgs_q,
+			GET_OLDER_MSGS_QUERY_PARAM_WHO, buddy_name, -1, SQLITE_STATIC)
+		!= SQLITE_OK) {
+		return FALSE;
+	}
+
+	return sqlitelog_execute_get_msgs_query(get_older_msgs_q, result);
+}
+
+static gboolean
+sqlitelog_get_older_msgs_upper_impl(PurpleBuddy *buddy, guint64 timestamp,
+	PurpleMessage *message, GList **result)
+{
+	g_assert(buddy);
+	g_assert(message);
+	g_assert(result);
+
+	g_assert(get_older_msgs_upper_q);
+
+	const char *buddy_name = purple_buddy_get_name(buddy);
+	g_return_val_if_fail(buddy_name != NULL, FALSE);
+
+	unsigned msg_id = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(message),
+		SQLITELOG_MESSAGE_ID_ATTR));
+	g_return_val_if_fail(msg_id != SQLITELOG_DB_ID_NONE, FALSE);
+
+	PurpleAccount *account = purple_buddy_get_account(buddy);
+	g_return_val_if_fail(account != NULL, FALSE);
+
+	guint64 upper_bound = purple_message_get_time(message);
+
+	// If the interval is empty then no need to query the database
+	if (timestamp > upper_bound) {
+		*result = NULL;
+		return TRUE;
+	}
+
+	unsigned account_id;
+	if (!sqlitelog_get_account_id(account, &account_id))
+		return FALSE;
+
+	// If there are no messages sent or received from account
+	// then return empty list
+	if (account_id == SQLITELOG_DB_ID_NONE) {
+		*result = NULL;
+		return TRUE;
+	}
+
+	if (sqlite3_bind_int64(get_older_msgs_upper_q,
+			GET_OLDER_MSGS_UPPER_QUERY_PARAM_ACCOUNTID, account_id)
+		!= SQLITE_OK ||
+		sqlite3_bind_int64(get_older_msgs_upper_q,
+			GET_OLDER_MSGS_UPPER_QUERY_PARAM_LOWERBOUND, timestamp)
+		!= SQLITE_OK ||
+		sqlite3_bind_int64(get_older_msgs_upper_q,
+			GET_OLDER_MSGS_UPPER_QUERY_PARAM_UPPERBOUND, upper_bound)
+		!= SQLITE_OK ||
+		sqlite3_bind_int64(get_older_msgs_upper_q,
+			GET_OLDER_MSGS_UPPER_QUERY_PARAM_EXCEPTID, msg_id)
+		!= SQLITE_OK ||
+		sqlite3_bind_text(get_older_msgs_upper_q,
+			GET_OLDER_MSGS_UPPER_QUERY_PARAM_WHO, buddy_name, -1, SQLITE_STATIC)
+		!= SQLITE_OK) {
+		return FALSE;
+	}
+
+	return sqlitelog_execute_get_msgs_query(get_older_msgs_upper_q, result);
+}



More information about the Commits mailing list