[evolution-data-server] I#5 - Compare only date when searching with Sent/Received dates
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] I#5 - Compare only date when searching with Sent/Received dates
- Date: Mon, 11 Jun 2018 16:32:55 +0000 (UTC)
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]