[evolution-data-server] I#5 - Compare only date when searching with Sent/Received dates



commit 4196061d1c6d758f971ab944a3ce9515e45c1a5b
Author: Milan Crha <mcrha redhat com>
Date:   Mon Jun 11 18:33:30 2018 +0200

    I#5 - Compare only date when searching with Sent/Received dates
    
    Closes https://gitlab.gnome.org/GNOME/evolution-data-server/issues/5

 src/camel/camel-db.c              |  19 +++++
 src/camel/camel-folder-search.c   | 159 ++++++++++++++++++++++++++++++++++++++
 src/camel/camel-folder-search.h   |  27 ++++++-
 src/camel/camel-search-sql-sexp.c |  66 ++++++++++++++++
 4 files changed, 269 insertions(+), 2 deletions(-)
---
diff --git a/src/camel/camel-db.c b/src/camel/camel-db.c
index 999d5cb8c..70c45a7a2 100644
--- a/src/camel/camel-db.c
+++ b/src/camel/camel-db.c
@@ -32,6 +32,7 @@
 #include <sqlite3.h>
 
 #include "camel-debug.h"
+#include "camel-folder-search.h"
 #include "camel-object.h"
 #include "camel-string-utils.h"
 
@@ -639,6 +640,23 @@ cdb_match_func (sqlite3_context *ctx,
        sqlite3_result_int (ctx, matches ? 1 : 0);
 }
 
+static void
+cdb_camel_compare_date_func (sqlite3_context *ctx,
+                            gint nArgs,
+                            sqlite3_value **values)
+{
+       sqlite3_int64 v1, v2;
+
+       g_return_if_fail (ctx != NULL);
+       g_return_if_fail (nArgs == 2);
+       g_return_if_fail (values != NULL);
+
+       v1 = sqlite3_value_int64 (values[0]);
+       v2 = sqlite3_value_int64 (values[1]);
+
+       sqlite3_result_int (ctx, camel_folder_search_util_compare_date (v1, v2));
+}
+
 static void
 cdb_writer_lock (CamelDB *cdb)
 {
@@ -818,6 +836,7 @@ camel_db_new (const gchar *filename,
        d (g_print ("\nDatabase succesfully opened  \n"));
 
        sqlite3_create_function (db, "MATCH", 2, SQLITE_UTF8, NULL, cdb_match_func, NULL, NULL);
+       sqlite3_create_function (db, "CAMELCOMPAREDATE", 2, SQLITE_UTF8, NULL, cdb_camel_compare_date_func, 
NULL, NULL);
 
        /* Which is big / costlier ? A Stack frame or a pointer */
        if (g_getenv ("CAMEL_SQLITE_DEFAULT_CACHE_SIZE") != NULL) {
diff --git a/src/camel/camel-folder-search.c b/src/camel/camel-folder-search.c
index 48d3d1af5..e240caa2b 100644
--- a/src/camel/camel-folder-search.c
+++ b/src/camel/camel-folder-search.c
@@ -48,6 +48,13 @@
 #include "camel-string-utils.h"
 #include "camel-search-sql-sexp.h"
 
+#ifdef G_OS_WIN32
+#ifdef localtime_r
+#undef localtime_r
+#endif
+#define localtime_r(tp,tmp) memcpy (tmp, localtime (tp), sizeof (struct tm))
+#endif
+
 #define d(x)
 #define r(x)
 #define dd(x) if (camel_debug("search")) x
@@ -218,6 +225,14 @@ static struct {
        { "message-location",
          G_STRUCT_OFFSET (CamelFolderSearchClass, message_location),
          CAMEL_FOLDER_SEARCH_ALWAYS_ENTER },
+
+       { "make-time",
+         G_STRUCT_OFFSET (CamelFolderSearchClass, make_time),
+         CAMEL_FOLDER_SEARCH_ALWAYS_ENTER },
+
+       { "compare-date",
+         G_STRUCT_OFFSET (CamelFolderSearchClass, compare_date),
+         CAMEL_FOLDER_SEARCH_ALWAYS_ENTER },
 };
 
 G_DEFINE_TYPE (CamelFolderSearch, camel_folder_search, G_TYPE_OBJECT)
@@ -1667,6 +1682,8 @@ folder_search_message_location (CamelSExp *sexp,
        CamelSExpResult *r;
        gboolean same = FALSE;
 
+       r (printf ("executing message-location\n"));
+
        if (argc == 1 && argv[0]->type == CAMEL_SEXP_RES_STRING) {
                if (argv[0]->value.string && search->priv->folder) {
                        CamelStore *store;
@@ -1706,6 +1723,58 @@ folder_search_message_location (CamelSExp *sexp,
        return r;
 }
 
+static CamelSExpResult *
+folder_search_make_time (CamelSExp *sexp,
+                        gint argc,
+                        CamelSExpResult **argv,
+                        CamelFolderSearch *search)
+{
+       CamelSExpResult *res;
+
+       r (printf ("executing make-time\n"));
+
+       res = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_TIME);
+       res->value.time = camel_folder_search_util_make_time (argc, argv);
+
+       return res;
+}
+
+static CamelSExpResult *
+folder_search_compare_date (CamelSExp *sexp,
+                           gint argc,
+                           CamelSExpResult **argv,
+                           CamelFolderSearch *search)
+{
+       CamelSExpResult *res;
+
+       r (printf ("executing compare-date\n"));
+
+       res = camel_sexp_result_new (sexp, CAMEL_SEXP_RES_INT);
+       res->value.number = 0;
+
+       if (argc == 2) {
+               gint64 t1, t2;
+
+               if (argv[0]->type == CAMEL_SEXP_RES_INT)
+                       t1 = argv[0]->value.number;
+               else if (argv[0]->type == CAMEL_SEXP_RES_TIME)
+                       t1 = (gint64) argv[0]->value.time;
+               else
+                       return res;
+
+               if (argv[1]->type == CAMEL_SEXP_RES_INT)
+                       t2 = argv[1]->value.number;
+               else if (argv[1]->type == CAMEL_SEXP_RES_TIME)
+                       t2 = (gint64) argv[1]->value.time;
+               else
+                       return res;
+
+               res->value.number = camel_folder_search_util_compare_date (t1, t2);
+       }
+
+       return res;
+}
+
 static void
 camel_folder_search_class_init (CamelFolderSearchClass *class)
 {
@@ -1741,6 +1810,8 @@ camel_folder_search_class_init (CamelFolderSearchClass *class)
        class->get_size = folder_search_get_size;
        class->uid = folder_search_uid;
        class->message_location = folder_search_message_location;
+       class->make_time = folder_search_make_time;
+       class->compare_date = folder_search_compare_date;
 }
 
 static void
@@ -2456,3 +2527,91 @@ camel_folder_search_util_add_months (time_t t,
 
        return res;
 }
+
+static time_t
+folder_search_num_to_timet (gint num)
+{
+       time_t res = (time_t) -1;
+
+       if (num > 9999999) {
+               GDateTime *dtm;
+
+               dtm = g_date_time_new_utc (num / 10000, (num / 100) % 100, num % 100, 0, 0, 0.0);
+               if (dtm) {
+                       res = (time_t) g_date_time_to_unix (dtm);
+                       g_date_time_unref (dtm);
+               }
+       }
+
+       return res;
+}
+
+/**
+ * camel_folder_search_util_make_time:
+ * @argc: number of arguments in @argv
+ * @argv: array or arguments
+ *
+ * Implementation of 'make-time' function, which expects one argument,
+ * a string or an integer, to be converted into time_t.
+ *
+ * Returns: time_t equivalent of the passed in argument, or (time_t) -1 on error.
+ *
+ * Since: 3.30
+ **/
+time_t
+camel_folder_search_util_make_time (gint argc,
+                                   CamelSExpResult **argv)
+{
+       time_t res = (time_t) -1;
+
+       g_return_val_if_fail (argv != NULL, res);
+
+       if (argc == 1 && argv[0]->type == CAMEL_SEXP_RES_STRING && argv[0]->value.string) {
+               GTimeVal tv;
+
+               if (g_time_val_from_iso8601 (argv[0]->value.string, &tv)) {
+                       res = tv.tv_sec;
+               } else if (strlen (argv[0]->value.string) == 8) {
+                       gint num;
+
+                       num = atoi (argv[0]->value.string);
+                       res = folder_search_num_to_timet (num);
+               }
+       } else if (argc == 1 && argv[0]->type == CAMEL_SEXP_RES_INT) {
+               res = folder_search_num_to_timet (argv[0]->value.number);
+       }
+
+       return res;
+}
+
+/**
+ * camel_folder_search_util_compare_date:
+ * @datetime1: a time_t-like value of the first date-time
+ * @datetime2: a time_t-like value of the second date-time
+ *
+ * Compares date portion of the two date-time values, first converted
+ * into the local time zone. The returned value is like with strcmp().
+ *
+ * Returns: 0 when the dates are equal, < 0 when first is before second and
+ *    > 0 when the first is after the second date
+ *
+ * Since: 3.30
+ **/
+gint
+camel_folder_search_util_compare_date (gint64 datetime1,
+                                      gint64 datetime2)
+{
+       struct tm tm;
+       time_t tt;
+       gint dt1, dt2;
+
+       tt = (time_t) datetime1;
+       localtime_r (&tt, &tm);
+       dt1 = ((tm.tm_year + 1900) * 10000) + ((tm.tm_mon + 1) * 100) + tm.tm_mday;
+
+       tt = (time_t) datetime2;
+       localtime_r (&tt, &tm);
+       dt2 = ((tm.tm_year + 1900) * 10000) + ((tm.tm_mon + 1) * 100) + tm.tm_mday;
+
+       return dt1 - dt2;
+}
diff --git a/src/camel/camel-folder-search.h b/src/camel/camel-folder-search.h
index 7d4cc3d7e..fc95bf8c1 100644
--- a/src/camel/camel-folder-search.h
+++ b/src/camel/camel-folder-search.h
@@ -253,8 +253,26 @@ struct _CamelFolderSearchClass {
                                                 CamelSExpResult **argv,
                                                 CamelFolderSearch *search);
 
+       /* (make-time "string")
+        * (make-time int)
+        * Converts the string or int into a time_t value. The function accepts
+        * date-only value in format YYYYMMDD and also ISO 8601 format. */
+       CamelSExpResult *       (*make_time)    (CamelSExp *sexp,
+                                                gint argc,
+                                                CamelSExpResult **argv,
+                                                CamelFolderSearch *search);
+
+       /* (compare-date time_t time_t)
+        * Compares only date portion of the two time_t values and returns an integer
+        * value < 0 when the first date is before the second, 0 when they are the same
+        * and value > 0 when the first is after the second date. */
+       CamelSExpResult *       (*compare_date) (CamelSExp *sexp,
+                                                gint argc,
+                                                CamelSExpResult **argv,
+                                                CamelFolderSearch *search);
+
        /* Padding for future expansion */
-       gpointer reserved[20];
+       gpointer reserved[18];
 };
 
 GType          camel_folder_search_get_type    (void) G_GNUC_CONST;
@@ -307,7 +325,12 @@ void               camel_folder_search_free_result (CamelFolderSearch *search,
 time_t         camel_folder_search_util_add_months
                                                (time_t t,
                                                 gint months);
-
+time_t         camel_folder_search_util_make_time
+                                               (gint argc,
+                                                CamelSExpResult **argv);
+gint           camel_folder_search_util_compare_date
+                                               (gint64 datetime1,
+                                                gint64 datetime2);
 G_END_DECLS
 
 #endif /* CAMEL_FOLDER_SEARCH_H */
diff --git a/src/camel/camel-search-sql-sexp.c b/src/camel/camel-search-sql-sexp.c
index c317651a3..206d5719a 100644
--- a/src/camel/camel-search-sql-sexp.c
+++ b/src/camel/camel-search-sql-sexp.c
@@ -681,6 +681,70 @@ get_size (struct _CamelSExp *f,
        return r;
 }
 
+static CamelSExpResult *
+make_time_cb (struct _CamelSExp *f,
+             gint argc,
+             struct _CamelSExpResult **argv,
+             gpointer data)
+{
+       CamelSExpResult *r;
+       time_t tt;
+
+       d (printf ("executing make-time\n"));
+
+       tt = camel_folder_search_util_make_time (argc, argv);
+
+       r = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
+       r->value.string = g_strdup_printf ("%" G_GINT64_FORMAT, (gint64) tt);
+
+       return r;
+}
+
+static CamelSExpResult *
+compare_date_cb (struct _CamelSExp *f,
+                gint argc,
+                struct _CamelSExpTerm **argv,
+                gpointer data)
+{
+       struct _CamelSExpResult *res, *r1, *r2;
+
+       d (printf ("executing compare-date\n"));
+
+       res = camel_sexp_result_new (f, CAMEL_SEXP_RES_STRING);
+
+       if (argc == 2) {
+               GString *str = g_string_new ("camelcomparedate( ");
+
+               r1 = camel_sexp_term_eval (f, argv[0]);
+               r2 = camel_sexp_term_eval (f, argv[1]);
+
+               if (r1->type == CAMEL_SEXP_RES_INT)
+                       g_string_append_printf (str, "%d", r1->value.number);
+               else if (r1->type == CAMEL_SEXP_RES_TIME)
+                       g_string_append_printf (str, "%" G_GINT64_FORMAT, (gint64) r1->value.time);
+               else if (r1->type == CAMEL_SEXP_RES_STRING)
+                       g_string_append_printf (str, "%s", r1->value.string);
+
+               g_string_append_printf (str, " , ");
+               if (r2->type == CAMEL_SEXP_RES_INT)
+                       g_string_append_printf (str, "%d", r2->value.number);
+               if (r2->type == CAMEL_SEXP_RES_BOOL)
+                       g_string_append_printf (str, "%d", r2->value.boolean);
+               else if (r2->type == CAMEL_SEXP_RES_TIME)
+                       g_string_append_printf (str, "%" G_GINT64_FORMAT, (gint64) r2->value.time);
+               else if (r2->type == CAMEL_SEXP_RES_STRING)
+                       g_string_append_printf (str, "%s", r2->value.string);
+
+               camel_sexp_result_free (f, r1);
+               camel_sexp_result_free (f, r2);
+               g_string_append (str, " )");
+
+               res->value.string = g_string_free (str, FALSE);
+       }
+
+       return res;
+}
+
 static CamelSExpResult *
 sql_exp (struct _CamelSExp *f,
          gint argc,
@@ -734,6 +798,8 @@ static struct {
        { "get-current-date", get_current_date, 0},
        { "get-relative-months", get_relative_months, 0},
        { "get-size", get_size, 0},
+       { "make-time", make_time_cb, 0},
+       { "compare-date", (CamelSExpFunc) compare_date_cb, 1},
        { "sql-exp", sql_exp, 0},
 
 /*     { "uid", CAMEL_STRUCT_OFFSET(CamelFolderSearchClass, uid), 1 }, */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]