[evolution-data-server] Bug #656058 - Improve EBookBackendSqliteDB searching API
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Bug #656058 - Improve EBookBackendSqliteDB searching API
- Date: Mon, 8 Aug 2011 08:50:53 +0000 (UTC)
commit edd27133ce98107f3a7a376e18ba82527ac74790
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date: Mon Aug 8 10:49:24 2011 +0200
Bug #656058 - Improve EBookBackendSqliteDB searching API
addressbook/backends/file/e-book-backend-file.c | 187 +++++++++++++-----
.../libedata-book/e-book-backend-sqlitedb-test.c | 4 +-
.../libedata-book/e-book-backend-sqlitedb.c | 211 +++++++++++++-------
.../libedata-book/e-book-backend-sqlitedb.h | 28 ++-
4 files changed, 293 insertions(+), 137 deletions(-)
---
diff --git a/addressbook/backends/file/e-book-backend-file.c b/addressbook/backends/file/e-book-backend-file.c
index 23b5ac4..d976de8 100644
--- a/addressbook/backends/file/e-book-backend-file.c
+++ b/addressbook/backends/file/e-book-backend-file.c
@@ -125,6 +125,45 @@ string_to_dbt (const gchar *str, DBT *dbt)
dbt->flags = DB_DBT_USERMEM;
}
+static gboolean
+remove_file (const gchar *filename, GError **error)
+{
+ if (-1 == g_unlink (filename)) {
+ if (errno == EACCES || errno == EPERM) {
+ g_propagate_error (error, EDB_ERROR (PERMISSION_DENIED));
+ } else {
+ g_propagate_error (error, e_data_book_create_error_fmt
+ (E_DATA_BOOK_STATUS_OTHER_ERROR,
+ "Failed to remove file '%s': %s",
+ filename, g_strerror (errno)));
+ }
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+create_directory (const gchar *dirname,
+ GError **error)
+{
+ gint rv;
+
+ rv = g_mkdir_with_parents (dirname, 0700);
+ if (rv == -1 && errno != EEXIST) {
+ g_warning ("failed to make directory %s: %s", dirname, g_strerror (errno));
+ if (errno == EACCES || errno == EPERM)
+ g_propagate_error (error, EDB_ERROR (PERMISSION_DENIED));
+ else
+ g_propagate_error (error,
+ e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_OTHER_ERROR,
+ "Failed to make directory %s: %s",
+ dirname, g_strerror (errno)));
+ return FALSE;
+ }
+ return TRUE;
+}
+
static EContact*
create_contact (const gchar *uid, const gchar *vcard)
{
@@ -135,6 +174,34 @@ create_contact (const gchar *uid, const gchar *vcard)
return contact;
}
+static gchar *
+load_vcard (EBookBackendFile *bf,
+ const gchar *uid,
+ GError **error)
+{
+ DB *db = bf->priv->file_db;
+ DBT id_dbt, vcard_dbt;
+ gchar *vcard;
+ gint db_error;
+
+ /* Get the old contact from the db and compare the photo fields */
+ string_to_dbt (uid, &id_dbt);
+ memset (&vcard_dbt, 0, sizeof (vcard_dbt));
+ vcard_dbt.flags = DB_DBT_MALLOC;
+
+ db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0);
+
+ if (db_error == 0) {
+ vcard = vcard_dbt.data;
+ } else {
+ g_warning (G_STRLOC ": db->get failed with %s", db_strerror (db_error));
+ g_propagate_error (error, EDB_ERROR (CONTACT_NOT_FOUND));
+ return NULL;
+ }
+
+ return vcard;
+}
+
static gboolean
build_sqlitedb (EBookBackendFilePrivate *bfpriv)
{
@@ -440,33 +507,17 @@ e_book_backend_file_get_contact (EBookBackendSync *backend,
gchar **vcard,
GError **perror)
{
- EBookBackendFile *bf;
- DB *db;
- DBT id_dbt, vcard_dbt;
- gint db_error = 0;
-
- bf = E_BOOK_BACKEND_FILE (backend);
- db = bf->priv->file_db;
+ EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
- if (!db) {
+ if (!bf || !bf->priv || !bf->priv->file_db) {
g_propagate_error (perror, EDB_NOT_OPENED_ERROR);
return;
}
- string_to_dbt (id, &id_dbt);
- memset (&vcard_dbt, 0, sizeof (vcard_dbt));
- vcard_dbt.flags = DB_DBT_MALLOC;
+ *vcard = load_vcard (bf, id, perror);
- db_error = db->get (db, NULL, &id_dbt, &vcard_dbt, 0);
-
- if (db_error == 0) {
- *vcard = vcard_dbt.data;
- } else {
- g_warning (G_STRLOC ": db->get failed with %s", db_strerror (db_error));
+ if (!*vcard)
*vcard = g_strdup ("");
-
- g_propagate_error (perror, EDB_ERROR (CONTACT_NOT_FOUND));
- }
}
static void
@@ -487,6 +538,8 @@ e_book_backend_file_get_contact_list (EBookBackendSync *backend,
const gchar *search = query;
GSList *contact_list = NULL, *l;
GSList *summary_list = NULL;
+ gboolean searched_summary = FALSE;
+ gboolean with_all_required_fields = FALSE;
d(printf ("e_book_backend_file_get_contact_list (%s)\n", search));
@@ -497,15 +550,32 @@ e_book_backend_file_get_contact_list (EBookBackendSync *backend,
summary_list = e_book_backend_sqlitedb_search (bf->priv->sqlitedb,
SQLITEDB_FOLDER_ID,
- search, NULL, NULL);
+ search, NULL,
+ &searched_summary,
+ &with_all_required_fields, NULL);
if (summary_list) {
for (l = summary_list; l; l = l->next) {
EbSdbSearchData *data = l->data;
- contact_list = g_slist_prepend (contact_list, data->vcard);
- data->vcard = NULL;
+ if (with_all_required_fields) {
+ contact_list = g_slist_prepend (contact_list, data->vcard);
+ data->vcard = NULL;
+ } else {
+ /* In this case the sqlitedb helped us with the query, but
+ * the return information is incomplete so we need to load it up.
+ */
+ gchar *vcard;
+
+ vcard = load_vcard (bf, data->uid, perror);
+
+ /* Break out on the first BDB error */
+ if (!vcard)
+ break;
+
+ contact_list = g_slist_prepend (contact_list, vcard);
+ }
}
g_slist_foreach (summary_list, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
@@ -589,6 +659,7 @@ e_book_backend_file_get_contact_list_uids (EBookBackendSync *backend,
gboolean search_needed;
const gchar *search = query;
GSList *uids = NULL;
+ gboolean searched = FALSE;
d(printf ("e_book_backend_file_get_contact_list (%s)\n", search));
@@ -599,9 +670,9 @@ e_book_backend_file_get_contact_list_uids (EBookBackendSync *backend,
uids = e_book_backend_sqlitedb_search_uids (bf->priv->sqlitedb,
SQLITEDB_FOLDER_ID,
- search, NULL);
+ search, &searched, NULL);
- if (!uids) {
+ if (!searched) {
search_needed = TRUE;
if (!strcmp (search, "(contains \"x-evolution-any-field\" \"\")"))
search_needed = FALSE;
@@ -720,6 +791,8 @@ book_view_thread (gpointer data)
gboolean allcontacts;
GSList *summary_list, *l;
GHashTable *fields_of_interest;
+ gboolean searched = FALSE;
+ gboolean with_all_required_fields = FALSE;
g_return_val_if_fail (E_IS_DATA_BOOK_VIEW (data), NULL);
@@ -760,14 +833,37 @@ book_view_thread (gpointer data)
summary_list = e_book_backend_sqlitedb_search (bf->priv->sqlitedb,
SQLITEDB_FOLDER_ID,
- query, fields_of_interest, NULL);
- if (summary_list) {
+ query, fields_of_interest,
+ &searched, &with_all_required_fields, NULL);
+
+ if (searched) {
for (l = summary_list; l; l = l->next) {
EbSdbSearchData *data = l->data;
+ gchar *vcard = NULL;
+
+ if (with_all_required_fields) {
+ vcard = data->vcard;
+ data->vcard = NULL;
+ } else {
+ GError *error = NULL;
+
+ /* The sqlitedb summary did not satisfy 'fields-of-interest',
+ * load the complete vcard here. */
+ vcard = load_vcard (bf, data->uid, &error);
+
+ if (error) {
+ g_warning ("Error loading contact %s: %s",
+ data->uid, error->message);
+ g_error_free (error);
+ }
+
+ if (!vcard)
+ continue;
+
+ }
- notify_update_vcard (book_view, TRUE, data->uid, data->vcard);
- data->vcard = NULL;
+ notify_update_vcard (book_view, TRUE, data->uid, vcard);
}
g_slist_foreach (summary_list, (GFunc)e_book_backend_sqlitedb_search_data_free, NULL);
@@ -1196,18 +1292,12 @@ e_book_backend_file_open (EBookBackendSync *backend,
db_error = (*db->open) (db, NULL, filename, NULL, DB_HASH, DB_RDONLY | DB_THREAD, 0666);
if (db_error != 0 && !only_if_exists) {
- gint rv;
/* the database didn't exist, so we create the
directory then the .db */
db->close (db, 0);
- rv = g_mkdir_with_parents (dirname, 0700);
- if (rv == -1 && errno != EEXIST) {
- g_warning ("failed to make directory %s: %s", dirname, g_strerror (errno));
- if (errno == EACCES || errno == EPERM)
- g_propagate_error (perror, EDB_ERROR (PERMISSION_DENIED));
- else
- g_propagate_error (perror, e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_OTHER_ERROR, "Failed to make directory %s: %s", dirname, g_strerror (errno)));
+
+ if (!create_directory (dirname, perror)) {
g_free (dirname);
g_free (filename);
return;
@@ -1326,14 +1416,8 @@ e_book_backend_file_remove (EBookBackendSync *backend,
EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
GDir *dir;
- if (-1 == g_unlink (bf->priv->filename)) {
- if (errno == EACCES || errno == EPERM) {
- g_propagate_error (perror, EDB_ERROR (PERMISSION_DENIED));
- } else {
- g_propagate_error (perror, e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_OTHER_ERROR, "Failed to remove file '%s': %s", bf->priv->filename, g_strerror (errno)));
- }
+ if (!remove_file (bf->priv->filename, perror))
return;
- }
if (!e_book_backend_sqlitedb_remove (bf->priv->sqlitedb, perror))
return;
@@ -1434,19 +1518,26 @@ view_notify_update (EDataBookView *view, gpointer data)
NotifyData *ndata = data;
GHashTable *fields = e_data_book_view_get_fields_of_interest (view);
gboolean notified = FALSE;
+ gboolean with_all_required_fields = FALSE;
- if (e_book_backend_sqlitedb_is_summary_query (e_data_book_view_get_card_query (view), fields)) {
+ if (e_book_backend_sqlitedb_is_summary_query (e_data_book_view_get_card_query (view)) &&
+ e_book_backend_sqlitedb_is_summary_fields (fields)) {
const gchar *uid = e_contact_get_const (ndata->contact, E_CONTACT_UID);
gchar *vcard;
vcard = e_book_backend_sqlitedb_get_vcard_string (ndata->bf->priv->sqlitedb,
SQLITEDB_FOLDER_ID, uid,
- fields, NULL);
+ fields, &with_all_required_fields, NULL);
if (vcard) {
- e_data_book_view_notify_update_prefiltered_vcard (view, uid, vcard);
- notified = TRUE;
+
+ if (with_all_required_fields) {
+ e_data_book_view_notify_update_prefiltered_vcard (view, uid, vcard);
+ notified = TRUE;
+ } else {
+ g_free (vcard);
+ }
}
}
diff --git a/addressbook/libedata-book/e-book-backend-sqlitedb-test.c b/addressbook/libedata-book/e-book-backend-sqlitedb-test.c
index 36df25a..16f8248 100644
--- a/addressbook/libedata-book/e-book-backend-sqlitedb-test.c
+++ b/addressbook/libedata-book/e-book-backend-sqlitedb-test.c
@@ -96,7 +96,7 @@ search_db (EBookBackendSqliteDB *ebsdb, const gchar *type, const gchar *sexp)
g_print ("%s - query: %s \n", type, sexp);
op = type;
- vcards = e_book_backend_sqlitedb_search (ebsdb, folderid, sexp, NULL, &error);
+ vcards = e_book_backend_sqlitedb_search (ebsdb, folderid, sexp, NULL, NULL, NULL, &error);
if (error)
return;
@@ -148,7 +148,7 @@ start_tests (gpointer data)
g_print ("Get Vcard string \n");
op = "get vcard string";
- vcard_str = e_book_backend_sqlitedb_get_vcard_string (ebsdb, folderid, uid, NULL, &error);
+ vcard_str = e_book_backend_sqlitedb_get_vcard_string (ebsdb, folderid, uid, NULL, NULL, &error);
if (error)
goto exit;
g_print ("VCard: %s \n", vcard_str);
diff --git a/addressbook/libedata-book/e-book-backend-sqlitedb.c b/addressbook/libedata-book/e-book-backend-sqlitedb.c
index 1b9b2f3..6879bb6 100644
--- a/addressbook/libedata-book/e-book-backend-sqlitedb.c
+++ b/addressbook/libedata-book/e-book-backend-sqlitedb.c
@@ -277,7 +277,7 @@ create_folders_table (EBookBackendSqliteDB *ebsdb,
/* sync_data points to syncronization data, it could be last_modified time
or a sequence number or some text depending on the backend.
- parial_content says whether the contents are partially downloaded for
+ partial_content says whether the contents are partially downloaded for
auto-completion or if it has the complete content.
Have not included a bdata here since the keys table should suffice any
@@ -813,12 +813,13 @@ e_book_backend_sqlitedb_get_contact (EBookBackendSqliteDB *ebsdb,
const gchar *folderid,
const gchar *uid,
GHashTable *fields_of_interest,
- GError **error)
+ gboolean *with_all_required_fields,
+ GError **error)
{
GError *err = NULL;
EContact *contact = NULL;
gchar *vcard = e_book_backend_sqlitedb_get_vcard_string (ebsdb, folderid, uid,
- fields_of_interest, &err);
+ fields_of_interest, with_all_required_fields, &err);
if (!err) {
contact = e_contact_new_from_vcard (vcard);
g_free (vcard);
@@ -852,28 +853,56 @@ accumulate_fields_select_stmt (const gchar *field_name,
g_string_append (string, dbname);
}
+static void
+check_field_foreach (const gchar *field_name,
+ gpointer is_present,
+ gboolean *is_summary_query)
+{
+ EContactField field = e_contact_field_id (field_name);
+
+ if (!summary_dbname_from_field (field)) {
+ *is_summary_query = FALSE;
+ }
+}
+
+gboolean
+e_book_backend_sqlitedb_is_summary_fields (GHashTable *fields_of_interest)
+{
+ gboolean summary_fields = TRUE;
+
+ if (!fields_of_interest)
+ return FALSE;
+
+ g_hash_table_foreach (fields_of_interest, (GHFunc)check_field_foreach, &summary_fields);
+
+ return summary_fields;
+}
+
/* free return value with g_free */
static gchar *
summary_select_stmt (const gchar *folderid,
- GHashTable *fields_of_interest)
+ GHashTable *fields_of_interest,
+ gboolean *with_all_required_fields)
{
GString *string;
gchar *str;
- gint i;
string = g_string_new ("SELECT uid");
- /* If filtering by fields of interest, only query those and include the 'uid' */
- if (fields_of_interest) {
-
+ /* If filtering by fields of interest, only query those and include the 'uid'
+ *
+ */
+ if (fields_of_interest && e_book_backend_sqlitedb_is_summary_fields (fields_of_interest)) {
g_hash_table_foreach (fields_of_interest, (GHFunc)accumulate_fields_select_stmt, string);
- } else {
- /* ... Otherwise just select all the summary information */
- for (i = 1; i < G_N_ELEMENTS (summary_fields); i++) {
- g_string_append (string, ", ");
- g_string_append (string, summary_fields[i].dbname);
- }
+ /* The query should return all the required information */
+ if (with_all_required_fields)
+ *with_all_required_fields = TRUE;
+ } else if (with_all_required_fields) {
+ /* If the fields of interest is null or contains fields that are not
+ * part of the summary then only the uids are returned.
+ */
+ *with_all_required_fields = FALSE;
}
str = sqlite3_mprintf (" FROM %Q", folderid);
@@ -884,22 +913,44 @@ summary_select_stmt (const gchar *folderid,
}
+/**
+ * e_book_backend_sqlitedb_get_vcard_string:
+ * @ebsdb: An #EBookBackendSqliteDB
+ * @folderid: The folder id
+ * @uid: The uid to fetch a vcard for
+ * @fields_of_interest: The required fields for this vcard, or %NULL to require all fields.
+ * @with_all_required_fields: (allow none) (out): Whether all the required fields are present in the returned vcard.
+ * @error: A location to store any error that may have occurred.
+ *
+ * Searches @ebsdb in the context of @folderid for @uid.
+ *
+ * If @ebsdb is configured to store the whole vcards, the whole vcard will be returned.
+ * Otherwise the summary cache will be searched and the virtual vcard will be built
+ * from the summary cache.
+ *
+ * In either case, @with_all_required_fields if specified, will be updated to reflect whether
+ * the returned vcard string satisfies the passed 'fields_of_interest' parameter.
+ *
+ * Returns: (transfer full): The vcard string for @uid or %NULL if @uid was not found.
+ */
gchar *
e_book_backend_sqlitedb_get_vcard_string (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- const gchar *uid,
- GHashTable *fields_of_interest,
- GError **error)
+ const gchar *folderid,
+ const gchar *uid,
+ GHashTable *fields_of_interest,
+ gboolean *with_all_required_fields,
+ GError **error)
{
gchar *stmt, *select_stmt;
gchar *vcard_str = NULL;
+ gboolean local_with_all_required_fields = FALSE;
READER_LOCK (ebsdb);
if (!ebsdb->priv->store_vcard) {
GSList *vcards = NULL;
- select_stmt = summary_select_stmt (folderid, fields_of_interest);
+ select_stmt = summary_select_stmt (folderid, fields_of_interest, &local_with_all_required_fields);
stmt = sqlite3_mprintf ("%s WHERE uid = %Q", select_stmt, uid);
book_backend_sql_exec (ebsdb->priv->db, stmt, store_data_to_vcard, &vcards, error);
@@ -922,10 +973,15 @@ e_book_backend_sqlitedb_get_vcard_string (EBookBackendSqliteDB *ebsdb,
stmt = sqlite3_mprintf ("SELECT vcard FROM %Q WHERE uid = %Q", folderid, uid);
book_backend_sql_exec (ebsdb->priv->db, stmt, get_vcard_cb , &vcard_str, error);
sqlite3_free (stmt);
+
+ local_with_all_required_fields = TRUE;
}
READER_UNLOCK (ebsdb);
+ if (with_all_required_fields)
+ *with_all_required_fields = local_with_all_required_fields;
+
return vcard_str;
}
@@ -934,7 +990,6 @@ func_check (struct _ESExp *f, gint argc, struct _ESExpResult **argv, gpointer da
{
ESExpResult *r;
gint truth = FALSE;
- gboolean fields = GPOINTER_TO_INT (data);
if (argc == 2
&& argv[0]->type == ESEXP_RES_STRING
@@ -943,15 +998,9 @@ func_check (struct _ESExp *f, gint argc, struct _ESExpResult **argv, gpointer da
gchar *query_name = argv[0]->value.string;
gint i;
- /* The "contains x-evolution-any-field" query is the standard query
- * with no query specified, in this case the query is indeed a summary
- * query if fields-of-interest have been specified as all summary fields.
- *
- * If no filtering is specified we assume that the special "any-field" means
- * that the client wants all the fields returned (thus it would not
- * be a summary query).
- */
- if (fields && !strcmp ("x-evolution-any-field", query_name))
+ /* Special case, when testing the special symbolic 'any field' we can
+ * consider it a summary query (it's similar to a 'no query'). */
+ if (!strcmp ("x-evolution-any-field", query_name))
truth = TRUE;
for (i = 0; truth == FALSE && i < G_N_ELEMENTS (summary_fields); i++) {
@@ -981,57 +1030,27 @@ static const struct {
{ "exists", func_check, 0 }
};
-static void
-check_field_foreach (const gchar *field_name,
- gpointer is_present,
- gboolean *is_summary_query)
-{
- EContactField field = e_contact_field_id (field_name);
-
- if (!summary_dbname_from_field (field)) {
- *is_summary_query = FALSE;
- }
-}
-
-static gboolean
-book_backend_sqlitedb_is_summary_fields (GHashTable *fields_of_interest)
-{
- gboolean summary_fields = TRUE;
-
- g_hash_table_foreach (fields_of_interest, (GHFunc)check_field_foreach, &summary_fields);
-
- return summary_fields;
-}
-
gboolean
-e_book_backend_sqlitedb_is_summary_query (const gchar *query, GHashTable *fields_of_interest)
+e_book_backend_sqlitedb_is_summary_query (const gchar *query)
{
ESExp *sexp;
ESExpResult *r;
- gboolean retval, fields_are_summary;
+ gboolean retval;
gint i;
gint esexp_error;
g_return_val_if_fail (query != NULL, FALSE);
g_return_val_if_fail (*query, FALSE);
- fields_are_summary =
- (fields_of_interest && book_backend_sqlitedb_is_summary_fields (fields_of_interest));
-
- if (fields_of_interest && !fields_are_summary)
- return FALSE;
-
sexp = e_sexp_new ();
for (i = 0; i < G_N_ELEMENTS (check_symbols); i++) {
if (check_symbols[i].type == 1) {
e_sexp_add_ifunction (sexp, 0, check_symbols[i].name,
- (ESExpIFunc *) check_symbols[i].func,
- GINT_TO_POINTER (fields_are_summary));
+ (ESExpIFunc *) check_symbols[i].func, NULL);
} else {
e_sexp_add_function (sexp, 0, check_symbols[i].name,
- check_symbols[i].func,
- GINT_TO_POINTER (fields_are_summary));
+ check_symbols[i].func, NULL);
}
}
@@ -1311,17 +1330,19 @@ book_backend_sqlitedb_search_query (EBookBackendSqliteDB *ebsdb,
const gchar *sql,
const gchar *folderid,
/* const */ GHashTable *fields_of_interest,
- GError **error)
+ gboolean *with_all_required_fields,
+ GError **error)
{
GError *err = NULL;
GSList *vcard_data = NULL;
gchar *stmt, *select_stmt;
+ gboolean local_with_all_required_fields = FALSE;
READER_LOCK (ebsdb);
if (!ebsdb->priv->store_vcard) {
- select_stmt = summary_select_stmt (folderid, fields_of_interest);
+ select_stmt = summary_select_stmt (folderid, fields_of_interest, &local_with_all_required_fields);
if (sql && sql[0]) {
stmt = sqlite3_mprintf ("%s WHERE %s", select_stmt, sql);
@@ -1344,6 +1365,7 @@ book_backend_sqlitedb_search_query (EBookBackendSqliteDB *ebsdb,
book_backend_sql_exec (ebsdb->priv->db, stmt, addto_vcard_list_cb , &vcard_data, &err);
sqlite3_free (stmt);
}
+ local_with_all_required_fields = TRUE;
}
READER_UNLOCK (ebsdb);
@@ -1354,6 +1376,9 @@ book_backend_sqlitedb_search_query (EBookBackendSqliteDB *ebsdb,
if (err)
g_propagate_error (error, err);
+ if (with_all_required_fields)
+ * with_all_required_fields = local_with_all_required_fields;
+
return vcard_data;
}
@@ -1406,13 +1431,22 @@ book_backend_sqlitedb_search_full (EBookBackendSqliteDB *ebsdb, const gchar *sex
* @fields_of_interest: a #GHashTable containing the names of fields to return, or NULL for all.
* At the moment if this is non-null, the vcard will be populated with summary fields, else it would return the
* whole vcard if its stored in the db. [not implemented fully]
+ * @searched: (allow none) (out): Whether @ebsdb was capable of searching for the provided query @sexp.
+ * @with_all_required_fields: (allow none) (out): Whether all the required fields are present in the returned vcards.
* @error:
- * Search on summary fields is always supported. Search expression containing
- * any other field is supported only if backend chooses to store the vcard inside the db.
*
- * Summary fields - uid, nickname, given_name, family_name, file_as email_1, email_2, email_3, email_4, is_list,
+ * Searching with summary fields is always supported. Search expressions containing
+ * any other field is supported only if backend chooses to store the vcard inside the db.
+ *
+ * Summary fields - uid, rev, nickname, given_name, family_name, file_as email_1, email_2, email_3, email_4, is_list,
* list_show_addresses, wants_html
*
+ * If @ebsdb was incapable of returning vcards with results that satisfy
+ * @fields_of_interest, then @with_all_required_fields will be updated to @FALSE
+ * and only uid fields will be present in the returned vcards. This can be useful
+ * when a summary query succeeds and the returned list can be used to iterate
+ * and fetch for full required data from another persistance.
+ *
* Returns: List of EbSdbSearchData.
**/
GSList *
@@ -1420,26 +1454,42 @@ e_book_backend_sqlitedb_search (EBookBackendSqliteDB *ebsdb,
const gchar *folderid,
const gchar *sexp,
/* const */ GHashTable *fields_of_interest,
+ gboolean *searched,
+ gboolean *with_all_required_fields,
GError **error)
{
GSList *search_contacts = NULL;
+ gboolean local_searched = FALSE;
+ gboolean local_with_all_required_fields = FALSE;
if (sexp && !*sexp)
sexp = NULL;
- if (!sexp || e_book_backend_sqlitedb_is_summary_query (sexp, fields_of_interest)) {
+ if (!sexp || e_book_backend_sqlitedb_is_summary_query (sexp)) {
gchar *sql_query;
sql_query = sexp ? sexp_to_sql_query (sexp) : NULL;
- search_contacts = book_backend_sqlitedb_search_query (ebsdb, sql_query, folderid, fields_of_interest, error);
+ search_contacts = book_backend_sqlitedb_search_query (ebsdb, sql_query, folderid,
+ fields_of_interest,
+ &local_with_all_required_fields, error);
g_free (sql_query);
- } else if (ebsdb->priv->store_vcard)
+
+ local_searched = TRUE;
+
+ } else if (ebsdb->priv->store_vcard) {
search_contacts = book_backend_sqlitedb_search_full (ebsdb, sexp, folderid, FALSE, error);
- else {
+ local_searched = TRUE;
+ local_with_all_required_fields = TRUE;
+ } else {
g_set_error (error, E_BOOK_SDB_ERROR,
0, "Full search_contacts are not stored in cache. Hence only summary query is supported.");
}
+ if (searched)
+ *searched = local_searched;
+ if (with_all_required_fields)
+ *with_all_required_fields = local_with_all_required_fields;
+
return search_contacts;
}
@@ -1447,14 +1497,16 @@ GSList *
e_book_backend_sqlitedb_search_uids (EBookBackendSqliteDB *ebsdb,
const gchar *folderid,
const gchar *sexp,
- GError **error)
+ gboolean *searched,
+ GError **error)
{
GSList *uids = NULL;
+ gboolean local_searched = FALSE;
if (sexp && !*sexp)
sexp = NULL;
- if (!sexp || e_book_backend_sqlitedb_is_summary_query (sexp, NULL)) {
+ if (!sexp || e_book_backend_sqlitedb_is_summary_query (sexp)) {
gchar *stmt;
gchar *sql_query = sexp ? sexp_to_sql_query (sexp) : NULL;
@@ -1466,14 +1518,21 @@ e_book_backend_sqlitedb_search_uids (EBookBackendSqliteDB *ebsdb,
READER_UNLOCK (ebsdb);
+ local_searched = TRUE;
+
g_free (sql_query);
- } else if (ebsdb->priv->store_vcard)
+ } else if (ebsdb->priv->store_vcard) {
uids = book_backend_sqlitedb_search_full (ebsdb, sexp, folderid, TRUE, error);
- else {
+
+ local_searched = TRUE;
+ } else {
g_set_error (error, E_BOOK_SDB_ERROR,
0, "Full vcards are not stored in cache. Hence only summary query is supported.");
}
+ if (searched)
+ *searched = local_searched;
+
return uids;
}
diff --git a/addressbook/libedata-book/e-book-backend-sqlitedb.h b/addressbook/libedata-book/e-book-backend-sqlitedb.h
index b41aea6..b51e2cd 100644
--- a/addressbook/libedata-book/e-book-backend-sqlitedb.h
+++ b/addressbook/libedata-book/e-book-backend-sqlitedb.h
@@ -100,27 +100,33 @@ gboolean e_book_backend_sqlitedb_has_contact (EBookBackendSqliteDB *ebsdb,
const gchar *uid,
gboolean *partial_content,
GError **error);
-EContact * e_book_backend_sqlitedb_get_contact
- (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- const gchar *uid,
- GHashTable *fields_of_interest,
- GError **error);
-gchar * e_book_backend_sqlitedb_get_vcard_string
- (EBookBackendSqliteDB *ebsdb,
+EContact * e_book_backend_sqlitedb_get_contact (EBookBackendSqliteDB *ebsdb,
const gchar *folderid,
const gchar *uid,
GHashTable *fields_of_interest,
+ gboolean *with_all_required_fields,
GError **error);
+gchar * e_book_backend_sqlitedb_get_vcard_string
+ (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ const gchar *uid,
+ GHashTable *fields_of_interest,
+ gboolean *with_all_required_fields,
+ GError **error);
+
GSList * e_book_backend_sqlitedb_search (EBookBackendSqliteDB *ebsdb,
const gchar *folderid,
const gchar *sexp,
/* const */ GHashTable *fields_of_interest,
- GError **error);
+ gboolean *searched,
+ gboolean *with_all_required_fields,
+ GError **error);
+
GSList * e_book_backend_sqlitedb_search_uids
(EBookBackendSqliteDB *ebsdb,
const gchar *folderid,
const gchar *sexp,
+ gboolean *searched,
GError **error);
gboolean e_book_backend_sqlitedb_get_is_populated
(EBookBackendSqliteDB *ebsdb,
@@ -187,8 +193,8 @@ gboolean e_book_backend_sqlitedb_remove (EBookBackendSqliteDB *ebsdb,
void e_book_backend_sqlitedb_search_data_free
(EbSdbSearchData *s_data);
-gboolean e_book_backend_sqlitedb_is_summary_query (const gchar *query,
- GHashTable *fields_of_interest);
+gboolean e_book_backend_sqlitedb_is_summary_query (const gchar *query);
+gboolean e_book_backend_sqlitedb_is_summary_fields (GHashTable *fields_of_interest);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]