[evolution-data-server/openismus-work-master: 12/40] EBookBackendSqliteDB: Support regex queries
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/openismus-work-master: 12/40] EBookBackendSqliteDB: Support regex queries
- Date: Mon, 27 May 2013 11:23:10 +0000 (UTC)
commit 60dda0496cd636523e1ea233072eb08712d52c78
Author: Tristan Van Berkom <tristanvb openismus com>
Date: Tue Apr 23 17:36:47 2013 +0900
EBookBackendSqliteDB: Support regex queries
E_BOOK_QUERY_REGEX_NORMAL is supported in summary queries if the
query field is summarized, E_BOOK_QUERY_REGEX_RAW and normalized
but non-summarized queries are delegated to EBookBackendSexp for
matching.
.../libedata-book/e-book-backend-sqlitedb.c | 88 ++++++++++++++++++-
1 files changed, 83 insertions(+), 5 deletions(-)
---
diff --git a/addressbook/libedata-book/e-book-backend-sqlitedb.c
b/addressbook/libedata-book/e-book-backend-sqlitedb.c
index f986bf5..a81b22e 100644
--- a/addressbook/libedata-book/e-book-backend-sqlitedb.c
+++ b/addressbook/libedata-book/e-book-backend-sqlitedb.c
@@ -1425,6 +1425,44 @@ create_collation (gpointer data,
}
}
+static void
+ebsdb_regexp (sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv)
+{
+ GRegex *regex;
+ const gchar *expression;
+ const gchar *text;
+
+ /* Reuse the same GRegex for all REGEXP queries with the same expression */
+ regex = sqlite3_get_auxdata (context, 0);
+ if (!regex) {
+ GError *error = NULL;
+
+ expression = (const gchar *)sqlite3_value_text (argv[0]);
+
+ regex = g_regex_new (expression, 0, 0, &error);
+
+ if (!regex) {
+ sqlite3_result_error (context, error->message, -1);
+ g_error_free (error);
+ return;
+ }
+
+ /* SQLite will take care of freeing the GRegex when we're done with the query */
+ sqlite3_set_auxdata (context, 0, regex, (void(*)(void*))g_regex_unref);
+ }
+
+ /* Now perform the comparison */
+ text = (const gchar *)sqlite3_value_text (argv[1]);
+ if (text != NULL) {
+ gboolean match;
+
+ match = g_regex_match (regex, text, 0, NULL);
+ sqlite3_result_int (context, match ? 1 : 0);
+ }
+}
+
static gboolean
book_backend_sqlitedb_load (EBookBackendSqliteDB *ebsdb,
const gchar *filename,
@@ -1440,6 +1478,10 @@ book_backend_sqlitedb_load (EBookBackendSqliteDB *ebsdb,
if (ret == SQLITE_OK)
ret = sqlite3_collation_needed (ebsdb->priv->db, ebsdb, create_collation);
+ if (ret == SQLITE_OK)
+ ret = sqlite3_create_function (ebsdb->priv->db, "regexp", 2, SQLITE_UTF8, ebsdb,
+ ebsdb_regexp, NULL, NULL);
+
if (ret != SQLITE_OK) {
if (!ebsdb->priv->db) {
g_set_error (
@@ -3037,6 +3079,23 @@ func_check_phone (struct _ESExp *f,
return r;
}
+static ESExpResult *
+func_check_regex_raw (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer data)
+{
+ /* Raw REGEX queries are not in the summary, we only keep
+ * normalized data in the summary
+ */
+ ESExpResult *r;
+
+ r = e_sexp_result_new (f, ESEXP_RES_INT);
+ r->value.number = 0;
+
+ return r;
+}
+
/* 'builtin' functions */
static const struct {
const gchar *name;
@@ -3054,7 +3113,9 @@ static const struct {
{ "exists", func_check, 0 },
{ "eqphone", func_check_phone, 0 },
{ "eqphone_national", func_check_phone, 0 },
- { "eqphone_short", func_check_phone, 0 }
+ { "eqphone_short", func_check_phone, 0 },
+ { "regex_normal", func_check, 0 },
+ { "regex_raw", func_check_regex_raw, 0 },
};
static gboolean
@@ -3236,7 +3297,8 @@ typedef enum {
MATCH_ENDS_WITH,
MATCH_PHONE_NUMBER,
MATCH_NATIONAL_PHONE_NUMBER,
- MATCH_SHORT_PHONE_NUMBER
+ MATCH_SHORT_PHONE_NUMBER,
+ MATCH_REGEX
} MatchType;
typedef enum {
@@ -3288,7 +3350,7 @@ convert_string_value (EBookBackendSqliteDB *ebsdb,
g_return_val_if_fail (value != NULL, NULL);
- if (flags & CONVERT_NORMALIZE)
+ if ((flags & CONVERT_NORMALIZE) && match != MATCH_REGEX)
normal = e_util_utf8_normalize (value);
else
normal = g_strdup (value);
@@ -3312,6 +3374,7 @@ convert_string_value (EBookBackendSqliteDB *ebsdb,
case MATCH_IS:
case MATCH_PHONE_NUMBER:
case MATCH_NATIONAL_PHONE_NUMBER:
+ case MATCH_REGEX:
break;
}
@@ -3328,7 +3391,7 @@ convert_string_value (EBookBackendSqliteDB *ebsdb,
while ((c = *ptr++)) {
if (c == '\'') {
g_string_append_c (str, '\'');
- } else if (c == '%' || c == '^') {
+ } else if ((c == '%' || c == '^') && match != MATCH_REGEX) {
g_string_append_c (str, '^');
escape_modifier_needed = TRUE;
}
@@ -3347,6 +3410,7 @@ convert_string_value (EBookBackendSqliteDB *ebsdb,
case MATCH_PHONE_NUMBER:
case MATCH_NATIONAL_PHONE_NUMBER:
case MATCH_SHORT_PHONE_NUMBER:
+ case MATCH_REGEX:
break;
}
@@ -3523,6 +3587,9 @@ field_oper (MatchType match)
case MATCH_NATIONAL_PHONE_NUMBER:
return "=";
+ case MATCH_REGEX:
+ return "REGEXP";
+
case MATCH_CONTAINS:
case MATCH_BEGINS_WITH:
case MATCH_ENDS_WITH:
@@ -3717,6 +3784,16 @@ func_eqphone_short (struct _ESExp *f,
return convert_match_exp (f, argc, argv, data, MATCH_SHORT_PHONE_NUMBER);
}
+static ESExpResult *
+func_regex (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer data)
+{
+ return convert_match_exp (f, argc, argv, data, MATCH_REGEX);
+}
+
+
/* 'builtin' functions */
static struct {
const gchar *name;
@@ -3732,7 +3809,8 @@ static struct {
{ "endswith", func_endswith, 0 },
{ "eqphone", func_eqphone, 0 },
{ "eqphone_national", func_eqphone_national, 0 },
- { "eqphone_short", func_eqphone_short, 0 }
+ { "eqphone_short", func_eqphone_short, 0 },
+ { "regex_normal", func_regex, 0 }
};
static gchar *
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]