[evolution-ews] Merge sqlitedb changes from eds 3.2
- From: Chenthill Palanisamy <pchen src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-ews] Merge sqlitedb changes from eds 3.2
- Date: Thu, 29 Sep 2011 08:58:44 +0000 (UTC)
commit 3cf6fc888431478aaa7188fb5e1ab1e7777f7a1a
Author: Chenthill Palanisamy <pchenthill novell com>
Date: Thu Sep 29 14:27:54 2011 +0530
Merge sqlitedb changes from eds 3.2
src/addressbook/e-book-backend-ews.c | 4 +-
src/addressbook/e-book-backend-sqlitedb-test.c | 4 +-
src/addressbook/e-book-backend-sqlitedb.c | 1102 ++++++++++++++++--------
src/addressbook/e-book-backend-sqlitedb.h | 53 +-
4 files changed, 797 insertions(+), 366 deletions(-)
---
diff --git a/src/addressbook/e-book-backend-ews.c b/src/addressbook/e-book-backend-ews.c
index e7aff28..5977dbd 100644
--- a/src/addressbook/e-book-backend-ews.c
+++ b/src/addressbook/e-book-backend-ews.c
@@ -1060,7 +1060,7 @@ e_book_backend_ews_modify_contact (EBookBackend *backend,
}
old_contact = e_book_backend_sqlitedb_get_contact ( priv->ebsdb, priv->folder_id,
- id->id, &error);
+ id->id, NULL, NULL, &error);
if (!old_contact) {
g_object_unref (contact);
e_data_book_respond_modify (book, opid, EDB_ERROR (NOT_SUPPORTED), NULL);
@@ -1985,7 +1985,7 @@ fetch_from_offline (EBookBackendEws *ews, EDataBookView *book_view, const gchar
return;
}
- contacts = e_book_backend_sqlitedb_search (priv->ebsdb, priv->folder_id, query, NULL, &error);
+ contacts = e_book_backend_sqlitedb_search (priv->ebsdb, priv->folder_id, query, NULL, NULL, NULL, &error);
for (l = contacts; l != NULL; l = g_slist_next (l)) {
EbSdbSearchData *s_data = (EbSdbSearchData *) l->data;
diff --git a/src/addressbook/e-book-backend-sqlitedb-test.c b/src/addressbook/e-book-backend-sqlitedb-test.c
index bc67590..d0a3412 100644
--- a/src/addressbook/e-book-backend-sqlitedb-test.c
+++ b/src/addressbook/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, &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/src/addressbook/e-book-backend-sqlitedb.c b/src/addressbook/e-book-backend-sqlitedb.c
index fc65e5e..f13874a 100644
--- a/src/addressbook/e-book-backend-sqlitedb.c
+++ b/src/addressbook/e-book-backend-sqlitedb.c
@@ -26,12 +26,12 @@
#include <glib/gi18n.h>
#include <glib/gstdio.h>
-#include <libedataserver/e-sexp.h>
-#include <libedata-book/e-book-backend-sexp.h>
#include <sqlite3.h>
-#include "e-sqlite3-vfs.h"
+#include "libedataserver/e-sexp.h"
+#include "libedata-book/e-book-backend-sexp.h"
+#include "libebackend/e-sqlite3-vfs.h"
#include "e-book-backend-sqlitedb.h"
#define d(x)
@@ -61,7 +61,42 @@ G_DEFINE_TYPE (EBookBackendSqliteDB, e_book_backend_sqlitedb, G_TYPE_OBJECT)
static GHashTable *db_connections = NULL;
static GStaticMutex dbcon_lock = G_STATIC_MUTEX_INIT;
-static int
+typedef struct {
+ EContactField field; /* The EContact field */
+ GType fundamental_type; /* The fundamental type (string or gint) */
+ const gchar *dbname; /* The key for this field in the sqlite3 table */
+} SummeryField;
+
+static SummeryField summary_fields[] = {
+ { E_CONTACT_UID, G_TYPE_STRING, "uid" },
+ { E_CONTACT_REV, G_TYPE_STRING, "rev" },
+ { E_CONTACT_FILE_AS, G_TYPE_STRING, "file_as" },
+ { E_CONTACT_NICKNAME, G_TYPE_STRING, "nickname" },
+ { E_CONTACT_FULL_NAME, G_TYPE_STRING, "full_name" },
+ { E_CONTACT_GIVEN_NAME, G_TYPE_STRING, "given_name" },
+ { E_CONTACT_FAMILY_NAME, G_TYPE_STRING, "family_name" },
+ { E_CONTACT_EMAIL_1, G_TYPE_STRING, "email_1" },
+ { E_CONTACT_EMAIL_2, G_TYPE_STRING, "email_2" },
+ { E_CONTACT_EMAIL_3, G_TYPE_STRING, "email_3" },
+ { E_CONTACT_EMAIL_4, G_TYPE_STRING, "email_4" },
+ { E_CONTACT_IS_LIST, G_TYPE_BOOLEAN, "is_list" },
+ { E_CONTACT_LIST_SHOW_ADDRESSES, G_TYPE_BOOLEAN, "list_show_addresses" },
+ { E_CONTACT_WANTS_HTML, G_TYPE_BOOLEAN, "wants_html" }
+};
+
+static const gchar *
+summary_dbname_from_field (EContactField field)
+{
+ gint i;
+
+ for (i = 0; i < G_N_ELEMENTS (summary_fields); i++) {
+ if (summary_fields[i].field == field)
+ return summary_fields[i].dbname;
+ }
+ return NULL;
+}
+
+static gint
store_data_to_vcard (gpointer ref, gint ncol, gchar **cols, gchar **name);
static GQuark
@@ -127,15 +162,16 @@ e_book_backend_sqlitedb_class_init (EBookBackendSqliteDBClass *class)
static void
e_book_backend_sqlitedb_init (EBookBackendSqliteDB *ebsdb)
{
- ebsdb->priv = g_new0 (EBookBackendSqliteDBPrivate, 1) ;
+ ebsdb->priv = g_new0 (EBookBackendSqliteDBPrivate, 1);
ebsdb->priv->store_vcard = TRUE;
g_static_rw_lock_init (&ebsdb->priv->rwlock);
}
-
static void
-e_book_sqlitedb_match_func (sqlite3_context *ctx, gint nArgs, sqlite3_value **values)
+e_book_sqlitedb_match_func (sqlite3_context *ctx,
+ gint nArgs,
+ sqlite3_value **values)
{
gboolean matches = FALSE;
const gchar *what, *where;
@@ -184,11 +220,11 @@ e_book_sqlitedb_match_func (sqlite3_context *ctx, gint nArgs, sqlite3_value **va
* Returns:
**/
static gint
-book_backend_sql_exec (sqlite3 *db,
- const gchar *stmt,
- gint (*callback)(void*,gint,gchar**,gchar**),
- gpointer data,
- GError **error)
+book_backend_sql_exec (sqlite3 *db,
+ const gchar *stmt,
+ gint (*callback)(gpointer ,gint,gchar **,gchar **),
+ gpointer data,
+ GError **error)
{
gchar *errmsg = NULL;
gint ret = -1;
@@ -221,13 +257,15 @@ book_backend_sql_exec (sqlite3 *db,
}
static void
-book_backend_sqlitedb_start_transaction (EBookBackendSqliteDB *ebsdb, GError **error)
+book_backend_sqlitedb_start_transaction (EBookBackendSqliteDB *ebsdb,
+ GError **error)
{
book_backend_sql_exec (ebsdb->priv->db, "BEGIN", NULL, NULL, error);
}
static void
-book_backend_sqlitedb_end_transaction (EBookBackendSqliteDB *ebsdb, GError **error)
+book_backend_sqlitedb_end_transaction (EBookBackendSqliteDB *ebsdb,
+ GError **error)
{
if (!error || !*error)
book_backend_sql_exec (ebsdb->priv->db, "COMMIT", NULL, NULL, error);
@@ -236,18 +274,18 @@ book_backend_sqlitedb_end_transaction (EBookBackendSqliteDB *ebsdb, GError **err
}
static void
-create_folders_table (EBookBackendSqliteDB *ebsdb,
- GError **error)
+create_folders_table (EBookBackendSqliteDB *ebsdb,
+ GError **error)
{
GError *err = NULL;
/* 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
- auto-completion or if it has the complete content.
-
- Have not included a bdata here since the keys table should suffice any
- additional need that arises.
+ * or a sequence number or some text depending on the backend.
+ *
+ * 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
+ * additional need that arises.
*/
const gchar *stmt = "CREATE TABLE IF NOT EXISTS folders"
"( folder_id TEXT PRIMARY KEY,"
@@ -263,7 +301,6 @@ create_folders_table (EBookBackendSqliteDB *ebsdb,
if (!err)
book_backend_sql_exec (ebsdb->priv->db, stmt, NULL, NULL , &err);
-
/* Create a child table to store key/value pairs for a folder */
if (!err) {
stmt = "CREATE TABLE IF NOT EXISTS keys"
@@ -286,9 +323,11 @@ create_folders_table (EBookBackendSqliteDB *ebsdb,
return;
}
-
static gint
-folder_found_cb (gpointer ref, gint col, gchar **cols, gchar **name)
+folder_found_cb (gpointer ref,
+ gint col,
+ gchar **cols,
+ gchar **name)
{
gboolean *found = ref;
@@ -298,9 +337,9 @@ folder_found_cb (gpointer ref, gint col, gchar **cols, gchar **name)
}
static gboolean
-folder_exists (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- GError **error)
+folder_exists (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ GError **error)
{
gchar *stmt;
gboolean found = FALSE;
@@ -317,10 +356,10 @@ folder_exists (EBookBackendSqliteDB *ebsdb,
}
static void
-add_folder_into_db (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- const gchar *folder_name,
- GError **error)
+add_folder_into_db (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ const gchar *folder_name,
+ GError **error)
{
gchar *stmt;
GError *err = NULL;
@@ -333,7 +372,7 @@ add_folder_into_db (EBookBackendSqliteDB *ebsdb,
if (!err) {
stmt = sqlite3_mprintf ("INSERT OR REPLACE INTO folders VALUES ( %Q, %Q, %Q, %d, %d, %d ) ",
- folderid, folder_name, NULL, 0, 0, FOLDER_VERSION);
+ folderid, folder_name, NULL, 0, 0, FOLDER_VERSION);
book_backend_sql_exec (ebsdb->priv->db, stmt, NULL, NULL, &err);
@@ -349,37 +388,43 @@ add_folder_into_db (EBookBackendSqliteDB *ebsdb,
return;
}
-
/* The column names match the fields used in book-backend-sexp */
static gint
-create_contacts_table (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- GError **error)
+create_contacts_table (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ GError **error)
{
- gint ret;
+ gint ret, i;
gchar *stmt, *tmp;
GError *err = NULL;
+ GString *string;
+
+ /* Construct the create statement from the summary fields table */
+ string = g_string_new ("CREATE TABLE IF NOT EXISTS %Q ( uid TEXT PRIMARY KEY, ");
+
+ for (i = 1; i < G_N_ELEMENTS (summary_fields); i++) {
+ g_string_append (string, summary_fields[i].dbname);
+ g_string_append_c (string, ' ');
- stmt = sqlite3_mprintf ("CREATE TABLE IF NOT EXISTS %Q"
- "( uid TEXT PRIMARY KEY,"
- " nickname TEXT, full_name TEXT,"
- " given_name TEXT, family_name TEXT,"
- " file_as TEXT,"
- " email_1 TEXT, email_2 TEXT,"
- " email_3 TEXT, email_4 TEXT,"
- " partial_content INTEGER,"
- " is_list INTEGER, list_show_addresses INTEGER,"
- " wants_html INTEGER,"
- " vcard TEXT, bdata TEXT)", folderid);
+ if (summary_fields[i].fundamental_type == G_TYPE_STRING)
+ g_string_append (string, "TEXT, ");
+ else if (summary_fields[i].fundamental_type == G_TYPE_BOOLEAN)
+ g_string_append (string, "INTEGER, ");
+ else
+ g_assert_not_reached ();
+ }
+ g_string_append (string, "vcard TEXT, bdata TEXT)");
+
+ stmt = sqlite3_mprintf (string->str, folderid);
+ g_string_free (string, TRUE);
WRITER_LOCK (ebsdb);
ret = book_backend_sql_exec (ebsdb->priv->db, stmt, NULL, NULL , &err);
sqlite3_free (stmt);
-
/* Create indexes on full_name and email_1 as autocompletion queries would mainly
- rely on this. Assuming that the frequency of matching on these would be higher than
- on the other fields like email_2, surname etc. email_1 should be the primary email */
+ * rely on this. Assuming that the frequency of matching on these would be higher than
+ * on the other fields like email_2, surname etc. email_1 should be the primary email */
if (!err) {
tmp = g_strdup_printf("FNINDEX-%s", folderid);
stmt = sqlite3_mprintf ("CREATE INDEX IF NOT EXISTS %Q ON %Q (full_name)", tmp, folderid);
@@ -405,9 +450,9 @@ create_contacts_table (EBookBackendSqliteDB *ebsdb,
}
static gboolean
-book_backend_sqlitedb_load (EBookBackendSqliteDB *ebsdb,
- const gchar *filename,
- GError **error)
+book_backend_sqlitedb_load (EBookBackendSqliteDB *ebsdb,
+ const gchar *filename,
+ GError **error)
{
EBookBackendSqliteDBPrivate *priv;
gint ret;
@@ -453,23 +498,25 @@ book_backend_sqlitedb_load (EBookBackendSqliteDB *ebsdb,
* e_book_backend_sqlitedb_new
* @path: location where the db would be created
* @emailid: email id of the user
- * @folderid: folder id of the address-book. This is used as primary_key for the folder.
+ * @folderid: folder id of the address-book
* @folder_name: name of the address-book
* @store_vcard: True if the vcard should be stored inside db, if FALSE only the summary fields would be stored inside db.
* @error:
*
* If the path for multiple addressbooks are same, the contacts from all addressbooks
- * would be stored in same db in different tables. It would also create a new address-book table with folder_id as its name.
+ * would be stored in same db in different tables.
*
* Returns:
+ *
+ * Since: 3.2
**/
EBookBackendSqliteDB *
-e_book_backend_sqlitedb_new (const gchar *path,
- const gchar *emailid,
- const gchar *folderid,
- const gchar *folder_name,
- gboolean store_vcard,
- GError **error)
+e_book_backend_sqlitedb_new (const gchar *path,
+ const gchar *emailid,
+ const gchar *folderid,
+ const gchar *folder_name,
+ gboolean store_vcard,
+ GError **error)
{
EBookBackendSqliteDB *ebsdb;
gchar *hash_key, *filename;
@@ -521,54 +568,55 @@ exit:
return ebsdb;
}
-/* Add Contact */
+/* Add Contact (free the result with g_free() ) */
static gchar *
-insert_stmt_from_contact (EContact *contact,
- gboolean partial_content,
- const gchar *folderid,
- gboolean store_vcard)
+insert_stmt_from_contact (EContact *contact,
+ gboolean partial_content,
+ const gchar *folderid,
+ gboolean store_vcard)
{
- gchar *stmt = NULL;
- gchar *id, *nickname, *full_name;
- gchar *given_name, *surname, *file_as;
- gchar *email_1, *email_2, *email_3, *email_4;
- gchar *vcard_str = NULL;
- gint wants_html, is_list, list_show_addresses;
-
- id = e_contact_get (contact, E_CONTACT_UID);
- nickname = e_contact_get (contact, E_CONTACT_NICKNAME);
- full_name = e_contact_get (contact, E_CONTACT_FULL_NAME);
- given_name = e_contact_get (contact, E_CONTACT_GIVEN_NAME);
- surname = e_contact_get (contact, E_CONTACT_FAMILY_NAME);
- file_as = e_contact_get (contact, E_CONTACT_FILE_AS);
- email_1 = e_contact_get (contact, E_CONTACT_EMAIL_1);
- email_2 = e_contact_get (contact, E_CONTACT_EMAIL_2);
- email_3 = e_contact_get (contact, E_CONTACT_EMAIL_3);
- email_4 = e_contact_get (contact, E_CONTACT_EMAIL_4);
- is_list = GPOINTER_TO_INT (e_contact_get (contact, E_CONTACT_IS_LIST));
- wants_html = GPOINTER_TO_INT (e_contact_get (contact, E_CONTACT_WANTS_HTML));
- list_show_addresses = GPOINTER_TO_INT (e_contact_get (contact, E_CONTACT_LIST_SHOW_ADDRESSES));
-
- if (store_vcard)
- vcard_str = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
-
- stmt = sqlite3_mprintf ("INSERT or REPLACE INTO %Q VALUES (%Q, %Q, %Q, "
- "%Q, %Q, %Q, %Q, %Q, %Q, %Q, %d, %d, %d, %d, %Q, %Q)", folderid, id, nickname,
- full_name, given_name, surname, file_as, email_1,
- email_2, email_3, email_4, partial_content, is_list, wants_html, list_show_addresses, vcard_str, NULL);
-
- g_free (id);
- g_free (nickname);
- g_free (given_name);
- g_free (surname);
- g_free (file_as);
- g_free (email_1);
- g_free (email_2);
- g_free (email_3);
- g_free (email_4);
+ GString *string;
+ gchar *str, *vcard_str;
+ gint i;
+
+ str = sqlite3_mprintf ("INSERT or REPLACE INTO %Q VALUES (", folderid);
+ string = g_string_new (str);
+ sqlite3_free (str);
+
+ for (i = 0; i < G_N_ELEMENTS (summary_fields); i++) {
+ if (i > 0)
+ g_string_append (string, ", ");
+
+ if (summary_fields[i].fundamental_type == G_TYPE_STRING) {
+ gchar *val;
+
+ val = e_contact_get (contact, summary_fields[i].field);
+ str = sqlite3_mprintf ("%Q", val);
+
+ g_string_append (string, str);
+
+ sqlite3_free (str);
+ g_free (val);
+
+ } else if (summary_fields[i].fundamental_type == G_TYPE_BOOLEAN) {
+ gboolean val;
+
+ val = e_contact_get (contact, summary_fields[i].field) ? TRUE : FALSE;
+ g_string_append_printf (string, "%d", val ? 1 : 0);
+
+ } else
+ g_assert_not_reached ();
+ }
+
+ vcard_str = store_vcard ? e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30) : NULL;
+ str = sqlite3_mprintf (", %Q, %Q)", vcard_str, NULL);
+
+ g_string_append (string, str);
+
+ sqlite3_free (str);
g_free (vcard_str);
- return stmt;
+ return g_string_free (string, FALSE);
}
/**
@@ -584,13 +632,15 @@ insert_stmt_from_contact (EContact *contact,
* which is the preferred means to add multiple contacts when possible.
*
* Returns: TRUE on success.
+ *
+ * Since: 3.2
**/
gboolean
-e_book_backend_sqlitedb_add_contact (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- EContact *contact,
- gboolean partial_content,
- GError **error)
+e_book_backend_sqlitedb_add_contact (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ EContact *contact,
+ gboolean partial_content,
+ GError **error)
{
GSList l;
l.data = contact;
@@ -610,13 +660,15 @@ e_book_backend_sqlitedb_add_contact (EBookBackendSqliteDB *ebsdb,
*
*
* Returns: TRUE on success.
+ *
+ * Since: 3.2
**/
gboolean
-e_book_backend_sqlitedb_add_contacts (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- GSList *contacts,
- gboolean partial_content,
- GError **error)
+e_book_backend_sqlitedb_add_contacts (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ GSList *contacts,
+ gboolean partial_content,
+ GError **error)
{
GSList *l;
GError *err = NULL;
@@ -633,10 +685,10 @@ e_book_backend_sqlitedb_add_contacts (EBookBackendSqliteDB *ebsdb,
EContact *contact = (EContact *) l->data;
stmt = insert_stmt_from_contact (contact, partial_content, folderid,
- priv->store_vcard);
+ priv->store_vcard);
book_backend_sql_exec (priv->db, stmt, NULL, NULL, &err);
- sqlite3_free (stmt);
+ g_free (stmt);
}
book_backend_sqlitedb_end_transaction (ebsdb, &err);
@@ -649,24 +701,38 @@ e_book_backend_sqlitedb_add_contacts (EBookBackendSqliteDB *ebsdb,
return ret && !err;
}
+/**
+ * e_book_backend_sqlitedb_remove_contact:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
gboolean
-e_book_backend_sqlitedb_remove_contact (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- const gchar *uid,
- GError **error)
+e_book_backend_sqlitedb_remove_contact (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ const gchar *uid,
+ GError **error)
{
GSList l;
- l.data = (char*)uid; /* Won't modify it, I promise :) */
+ l.data = (gchar *) uid; /* Won't modify it, I promise :) */
l.next = NULL;
return e_book_backend_sqlitedb_remove_contacts (ebsdb, folderid, &l,
error);
}
+/**
+ * e_book_backend_sqlitedb_remove_contacts:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
gboolean
-e_book_backend_sqlitedb_remove_contacts (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- GSList *uids,
- GError **error)
+e_book_backend_sqlitedb_remove_contacts (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ GSList *uids,
+ GError **error)
{
GSList *l;
GError *err = NULL;
@@ -718,22 +784,32 @@ struct _contact_info {
};
static gint
-contact_found_cb (gpointer ref, gint col, gchar **cols, gchar **name)
+contact_found_cb (gpointer ref,
+ gint col,
+ gchar **cols,
+ gchar **name)
{
struct _contact_info *cinfo = ref;
cinfo->exists = TRUE;
- cinfo->partial_content = cols [0] ? strtoul (cols [0], NULL, 10) : 0;
+ cinfo->partial_content = cols[0] ? strtoul (cols[0], NULL, 10) : 0;
return 0;
}
+/**
+ * e_book_backend_sqlitedb_has_contact:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
gboolean
-e_book_backend_sqlitedb_has_contact (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- const gchar *uid,
- gboolean *partial_content,
- GError **error)
+e_book_backend_sqlitedb_has_contact (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ const gchar *uid,
+ gboolean *partial_content,
+ GError **error)
{
GError *err = NULL;
gchar *stmt;
@@ -759,27 +835,40 @@ e_book_backend_sqlitedb_has_contact (EBookBackendSqliteDB *ebsdb,
}
static gint
-get_vcard_cb (gpointer ref, gint col, gchar **cols, gchar **name)
+get_vcard_cb (gpointer ref,
+ gint col,
+ gchar **cols,
+ gchar **name)
{
gchar **vcard_str = ref;
- if (cols [0])
+ if (cols[0])
*vcard_str = g_strdup (cols [0]);
return 0;
}
+/**
+ * e_book_backend_sqlitedb_get_contact:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
EContact *
-e_book_backend_sqlitedb_get_contact (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- const gchar *uid,
- GError **error)
+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)
{
GError *err = NULL;
EContact *contact = NULL;
- gchar *vcard = e_book_backend_sqlitedb_get_vcard_string (ebsdb, folderid, uid, &err);
+ gchar *vcard = e_book_backend_sqlitedb_get_vcard_string (ebsdb, folderid, uid,
+ fields_of_interest, with_all_required_fields, &err);
if (!err) {
- contact = e_contact_new_from_vcard(vcard);
+ contact = e_contact_new_from_vcard (vcard);
g_free (vcard);
} else
g_propagate_error (error, err);
@@ -787,33 +876,150 @@ e_book_backend_sqlitedb_get_contact (EBookBackendSqliteDB *ebsdb,
return contact;
}
+static void
+accumulate_fields_select_stmt (const gchar *field_name,
+ gpointer is_present,
+ GString *string)
+{
+ EContactField field = e_contact_field_id (field_name);
+ const gchar *dbname = NULL;
+
+ if (field == E_CONTACT_UID)
+ return;
+
+ dbname = summary_dbname_from_field (field);
+
+ /* The field of interest is not in the summary information,
+ * technically we shouldnt reach this case
+ */
+ if (!dbname)
+ return;
+
+ g_string_append (string, ", ");
+ 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;
+ }
+}
+
+/**
+ * e_book_backend_sqlitedb_is_summary_fields:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
+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,
+ gboolean *with_all_required_fields)
+{
+ GString *string;
+ gchar *str;
+
+ string = g_string_new ("SELECT uid");
+
+ /* 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);
+
+ /* 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);
+ g_string_append (string, str);
+ sqlite3_free (str);
+
+ return g_string_free (string, FALSE);
+}
+
+/**
+ * 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.
+ *
+ * Since: 3.2
+ */
gchar *
-e_book_backend_sqlitedb_get_vcard_string (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- const gchar *uid,
- GError **error)
+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)
{
- gchar *stmt;
+ 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;
-
- stmt = sqlite3_mprintf ("SELECT uid, nickname, full_name, given_name, family_name, file_as, email_1, email_2, "
- "email_3, is_list, list_show_addresses, wants_html FROM %Q WHERE uid = %Q", folderid, uid);
+
+ 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);
+
sqlite3_free (stmt);
+ g_free (select_stmt);
if (vcards) {
EbSdbSearchData *s_data = (EbSdbSearchData *) vcards->data;
- vcard_str = s_data->vcard;
-
- g_free (s_data->uid);
- g_free (s_data->bdata);
- g_free (s_data);
+ vcard_str = s_data->vcard;
+ s_data->vcard = NULL;
+
+ e_book_backend_sqlitedb_search_data_free (s_data);
+
g_slist_free (vcards);
vcards = NULL;
}
@@ -821,15 +1027,23 @@ 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;
}
static ESExpResult *
-func_check (struct _ESExp *f, gint argc, struct _ESExpResult **argv, gpointer data)
+func_check (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer data)
{
ESExpResult *r;
gint truth = FALSE;
@@ -837,13 +1051,19 @@ func_check (struct _ESExp *f, gint argc, struct _ESExpResult **argv, gpointer da
if (argc == 2
&& argv[0]->type == ESEXP_RES_STRING
&& argv[1]->type == ESEXP_RES_STRING) {
+
gchar *query_name = argv[0]->value.string;
+ gint i;
- if (!strcmp (query_name, "nickname") ||
- !strcmp (query_name, "full_name") ||
- !strcmp (query_name, "file_as") ||
- !strcmp (query_name, "email")) {
+ /* 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++) {
+
+ if (!strcmp (e_contact_field_name (summary_fields[i].field), query_name))
+ truth = TRUE;
}
}
@@ -867,8 +1087,15 @@ static const struct {
{ "exists", func_check, 0 }
};
-static gboolean
-book_backend_sqlitedb_is_summary_query (const gchar *query)
+/**
+ * e_book_backend_sqlitedb_is_summary_query:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_backend_sqlitedb_is_summary_query (const gchar *query)
{
ESExp *sexp;
ESExpResult *r;
@@ -876,15 +1103,18 @@ book_backend_sqlitedb_is_summary_query (const gchar *query)
gint i;
gint esexp_error;
+ g_return_val_if_fail (query != NULL, FALSE);
+ g_return_val_if_fail (*query, 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, NULL);
+ (ESExpIFunc *) check_symbols[i].func, NULL);
} else {
e_sexp_add_function (sexp, 0, check_symbols[i].name,
- check_symbols[i].func, NULL);
+ check_symbols[i].func, NULL);
}
}
@@ -938,7 +1168,10 @@ func_and (ESExp *f, gint argc, struct _ESExpTerm **argv, gpointer data)
}
static ESExpResult *
-func_or (ESExp *f, gint argc, struct _ESExpTerm **argv, gpointer data)
+func_or (ESExp *f,
+ gint argc,
+ struct _ESExpTerm **argv,
+ gpointer data)
{
ESExpResult *r, *r1;
GString *string;
@@ -971,20 +1204,24 @@ typedef enum {
} match_type;
static ESExpResult *
-convert_match_exp (struct _ESExp *f, gint argc, struct _ESExpResult **argv, gpointer data, match_type match)
+convert_match_exp (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer data,
+ match_type match)
{
ESExpResult *r;
- gchar *str=NULL;
+ gchar *str = NULL;
/* are we inside a match-all? */
- if (argc>1 && argv[0]->type == ESEXP_RES_STRING) {
+ if (argc > 1 && argv[0]->type == ESEXP_RES_STRING) {
const gchar *field;
/* only a subset of headers are supported .. */
field = argv[0]->value.string;
- if (argv[1]->type == ESEXP_RES_STRING && argv[1]->value.string [0] != 0) {
- gchar *value=NULL;
+ if (argv[1]->type == ESEXP_RES_STRING && argv[1]->value.string[0] != 0) {
+ gchar *value = NULL;
if (match == MATCH_CONTAINS) {
value = g_strdup_printf ("'%%%s%%'", argv[1]->value.string);
@@ -1035,25 +1272,37 @@ convert_match_exp (struct _ESExp *f, gint argc, struct _ESExpResult **argv, gpoi
}
static ESExpResult *
-func_contains (struct _ESExp *f, gint argc, struct _ESExpResult **argv, gpointer data)
+func_contains (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer data)
{
return convert_match_exp (f, argc, argv, data, MATCH_CONTAINS);
}
static ESExpResult *
-func_is (struct _ESExp *f, gint argc, struct _ESExpResult **argv, gpointer data)
+func_is (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer data)
{
return convert_match_exp (f, argc, argv, data, MATCH_IS);
}
static ESExpResult *
-func_beginswith (struct _ESExp *f, gint argc, struct _ESExpResult **argv, gpointer data)
+func_beginswith (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer data)
{
return convert_match_exp (f, argc, argv, data, MATCH_BEGINS_WITH);
}
static ESExpResult *
-func_endswith (struct _ESExp *f, gint argc, struct _ESExpResult **argv, gpointer data)
+func_endswith (struct _ESExp *f,
+ gint argc,
+ struct _ESExpResult **argv,
+ gpointer data)
{
return convert_match_exp (f, argc, argv, data, MATCH_ENDS_WITH);
}
@@ -1073,7 +1322,7 @@ static struct {
{ "endswith", func_endswith, 0 },
};
-static char *
+static gchar *
sexp_to_sql_query (const gchar *query)
{
ESExp *sexp;
@@ -1109,19 +1358,22 @@ sexp_to_sql_query (const gchar *query)
}
static gint
-addto_vcard_list_cb (gpointer ref, gint col, gchar **cols, gchar **name)
+addto_vcard_list_cb (gpointer ref,
+ gint col,
+ gchar **cols,
+ gchar **name)
{
GSList **vcard_data = ref;
EbSdbSearchData *s_data = g_new0 (EbSdbSearchData, 1);
- if (cols [0])
- s_data->uid = g_strdup (cols [0]);
+ if (cols[0])
+ s_data->uid = g_strdup (cols[0]);
- if (cols [1])
- s_data->vcard = g_strdup (cols [1]);
-
- if (cols [2])
- s_data->bdata = g_strdup (cols [1]);
+ if (cols[1])
+ s_data->vcard = g_strdup (cols[1]);
+
+ if (cols[2])
+ s_data->bdata = g_strdup (cols[2]);
*vcard_data = g_slist_prepend (*vcard_data, s_data);
@@ -1129,64 +1381,64 @@ addto_vcard_list_cb (gpointer ref, gint col, gchar **cols, gchar **name)
}
static gint
-addto_slist_cb (gpointer ref, gint col, gchar **cols, gchar **name)
+addto_slist_cb (gpointer ref,
+ gint col,
+ gchar **cols,
+ gchar **name)
{
GSList **uids = ref;
- if (cols [0])
+ if (cols[0])
*uids = g_slist_prepend (*uids, g_strdup (cols [0]));
return 0;
}
-static int
-store_data_to_vcard (gpointer ref, gint ncol, gchar **cols, gchar **name)
+static gint
+store_data_to_vcard (gpointer ref,
+ gint ncol,
+ gchar **cols,
+ gchar **name)
{
GSList **vcard_data = ref;
EbSdbSearchData *search_data = g_new0 (EbSdbSearchData, 1);
EContact *contact = e_contact_new ();
gchar *vcard;
- gint i;
+ gint i, j;
/* parse through cols, this will be useful if the api starts supporting field restrictions */
for (i = 0; i < ncol; i++)
{
+ gboolean found = FALSE;
+
if (!name[i] || !cols[i])
continue;
- if (!strcmp (name [i], "uid")) {
- e_contact_set (contact, E_CONTACT_UID, cols [i]);
-
- search_data->uid = g_strdup (cols [i]);
- } else if (!strcmp (name [i], "nickname"))
- e_contact_set (contact, E_CONTACT_NICKNAME, cols [i]);
- else if (!strcmp (name [i], "full_name"))
- e_contact_set (contact, E_CONTACT_FULL_NAME, cols [i]);
- else if (!strcmp (name [i], "given_name"))
- e_contact_set (contact, E_CONTACT_GIVEN_NAME, cols [i]);
- else if (!strcmp (name [i], "family_name"))
- e_contact_set (contact, E_CONTACT_FAMILY_NAME, cols [i]);
- else if (!strcmp (name [i], "file_as"))
- e_contact_set (contact, E_CONTACT_FILE_AS, cols [i]);
- else if (!strcmp (name [i], "email_1"))
- e_contact_set (contact, E_CONTACT_EMAIL_1, cols [i]);
- else if (!strcmp (name [i], "email_2"))
- e_contact_set (contact, E_CONTACT_EMAIL_2, cols [i]);
- else if (!strcmp (name [i], "email_3"))
- e_contact_set (contact, E_CONTACT_EMAIL_3, cols [i]);
- else if (!strcmp (name [i], "is_list")) {
- gint val = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
- e_contact_set (contact, E_CONTACT_IS_LIST, GINT_TO_POINTER (val));
- } else if (!strcmp (name [i], "list_show_addresses")) {
- gint val = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
- e_contact_set (contact, E_CONTACT_LIST_SHOW_ADDRESSES, GINT_TO_POINTER (val));
- } else if (!strcmp (name [i], "wants_html")) {
- gint val = cols[i] ? strtoul (cols[i], NULL, 10) : 0;
- e_contact_set (contact, E_CONTACT_WANTS_HTML, GINT_TO_POINTER (val));
- } else if (!strcmp (name [i], "bdata")) {
- search_data->bdata = g_strdup (cols [i]);
+ for (j = 0; j < G_N_ELEMENTS (summary_fields); j++) {
+
+ if (!strcmp (name[i], summary_fields[j].dbname)) {
+
+ if (summary_fields[j].fundamental_type == G_TYPE_STRING)
+ e_contact_set (contact, summary_fields[j].field, cols[i]);
+ else if (summary_fields[j].fundamental_type == G_TYPE_BOOLEAN) {
+ gboolean val = cols[i] ? strtoul (cols[i], NULL, 10) != 0 : FALSE;
+ e_contact_set (contact, summary_fields[j].field, GINT_TO_POINTER (val ? TRUE : FALSE));
+ } else
+ g_assert_not_reached ();
+
+ if (summary_fields[j].field == E_CONTACT_UID)
+ search_data->uid = g_strdup (cols[i]);
+
+ found = TRUE;
+ break;
+ }
}
-
+
+ if (found)
+ continue;
+
+ if (!strcmp (name [i], "bdata"))
+ search_data->bdata = g_strdup (cols[i]);
}
vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
@@ -1198,28 +1450,46 @@ store_data_to_vcard (gpointer ref, gint ncol, gchar **cols, gchar **name)
}
static GSList *
-book_backend_sqlitedb_search_query (EBookBackendSqliteDB *ebsdb,
- const gchar *sql,
- const gchar *folderid,
- GSList *fields_of_interest,
- GError **error)
+book_backend_sqlitedb_search_query (EBookBackendSqliteDB *ebsdb,
+ const gchar *sql,
+ const gchar *folderid,
+ /* const */ GHashTable *fields_of_interest,
+ gboolean *with_all_required_fields,
+ GError **error)
{
GError *err = NULL;
GSList *vcard_data = NULL;
- gchar *stmt;
+ gchar *stmt, *select_stmt;
+ gboolean local_with_all_required_fields = FALSE;
READER_LOCK (ebsdb);
- /* TODO enable return just the requested fields. */
- if (!ebsdb->priv->store_vcard || fields_of_interest) {
- stmt = sqlite3_mprintf ("SELECT uid, nickname, full_name, given_name, family_name, file_as, email_1, email_2, "
- "email_3, is_list, list_show_addresses, wants_html FROM %Q WHERE %s", folderid, sql);
- book_backend_sql_exec (ebsdb->priv->db, stmt, store_data_to_vcard, &vcard_data, &err);
- sqlite3_free (stmt);
+ if (!ebsdb->priv->store_vcard) {
+
+ 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);
+
+ book_backend_sql_exec (ebsdb->priv->db, stmt, store_data_to_vcard, &vcard_data, &err);
+ sqlite3_free (stmt);
+ } else
+ book_backend_sql_exec (ebsdb->priv->db, select_stmt,
+ store_data_to_vcard, &vcard_data, &err);
+
+ g_free (select_stmt);
+
} else {
- stmt = sqlite3_mprintf ("SELECT uid, vcard, bdata FROM %Q WHERE %s", folderid, sql);
- book_backend_sql_exec (ebsdb->priv->db, stmt, addto_vcard_list_cb , &vcard_data, &err);
- sqlite3_free (stmt);
+ if (sql && sql[0]) {
+ stmt = sqlite3_mprintf ("SELECT uid, vcard, bdata FROM %Q WHERE %s", folderid, sql);
+ book_backend_sql_exec (ebsdb->priv->db, stmt, addto_vcard_list_cb , &vcard_data, &err);
+ sqlite3_free (stmt);
+ } else {
+ stmt = sqlite3_mprintf ("SELECT uid, vcard, bdata FROM %Q", folderid);
+ 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);
@@ -1230,11 +1500,18 @@ 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;
}
static GSList *
-book_backend_sqlitedb_search_full (EBookBackendSqliteDB *ebsdb, const gchar *sexp, const gchar *folderid, gboolean return_uids, GError **error)
+book_backend_sqlitedb_search_full (EBookBackendSqliteDB *ebsdb,
+ const gchar *sexp,
+ const gchar *folderid,
+ gboolean return_uids,
+ GError **error)
{
GError *err = NULL;
GSList *r_list = NULL, *all = NULL, *l;
@@ -1254,7 +1531,7 @@ book_backend_sqlitedb_search_full (EBookBackendSqliteDB *ebsdb, const gchar *sex
for (l = all; l != NULL; l = g_slist_next (l)) {
EbSdbSearchData *s_data = (EbSdbSearchData *) l->data;
-
+
if (e_book_backend_sexp_match_vcard (bsexp, s_data->vcard)) {
if (!return_uids)
r_list = g_slist_prepend (r_list, s_data);
@@ -1278,77 +1555,129 @@ book_backend_sqlitedb_search_full (EBookBackendSqliteDB *ebsdb, const gchar *sex
* e_book_backend_sqlitedb_search
* @ebsdb:
* @folderid:
- * @sexp: search expression.
- * &fields_of_interest: a #GList containing the names of fields to return, or NULL for all.
+ * @sexp: search expression; use NULL or an empty string to get all stored contacts.
+ * @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.
+ *
+ * Since: 3.2
**/
GSList *
-e_book_backend_sqlitedb_search (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- const gchar *sexp,
- GSList *fields_of_interest,
- GError **error)
+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 (book_backend_sqlitedb_is_summary_query (sexp)) {
+ if (!sexp || e_book_backend_sqlitedb_is_summary_query (sexp)) {
gchar *sql_query;
- sql_query = sexp_to_sql_query (sexp);
- search_contacts = book_backend_sqlitedb_search_query (ebsdb, sql_query, folderid, fields_of_interest, error);
+ sql_query = sexp ? sexp_to_sql_query (sexp) : NULL;
+ 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;
}
-GSList *
-e_book_backend_sqlitedb_search_uids (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- const gchar *sexp,
- GError **error)
+/**
+ * e_book_backend_sqlitedb_search_uids:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
+GSList *
+e_book_backend_sqlitedb_search_uids (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ const gchar *sexp,
+ gboolean *searched,
+ GError **error)
{
GSList *uids = NULL;
-
- if (book_backend_sqlitedb_is_summary_query (sexp)) {
+ gboolean local_searched = FALSE;
+
+ if (sexp && !*sexp)
+ sexp = NULL;
+
+ if (!sexp || e_book_backend_sqlitedb_is_summary_query (sexp)) {
gchar *stmt;
- gchar *sql_query = sexp_to_sql_query (sexp);
+ gchar *sql_query = sexp ? sexp_to_sql_query (sexp) : NULL;
READER_LOCK (ebsdb);
-
- stmt = sqlite3_mprintf ("SELECT uid FROM %Q WHERE %s", folderid, sql_query);
+
+ stmt = sqlite3_mprintf ("SELECT uid FROM %Q%s%s", folderid, sql_query ? " WHERE " : "", sql_query ? sql_query : "");
book_backend_sql_exec (ebsdb->priv->db, stmt, addto_slist_cb, &uids, error);
sqlite3_free (stmt);
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;
}
static gint
-get_bool_cb (gpointer ref, gint col, gchar **cols, gchar **name)
+get_bool_cb (gpointer ref,
+ gint col,
+ gchar **cols,
+ gchar **name)
{
gboolean *ret = ref;
@@ -1357,10 +1686,17 @@ get_bool_cb (gpointer ref, gint col, gchar **cols, gchar **name)
return 0;
}
+/**
+ * e_book_backend_sqlitedb_get_is_populated:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
gboolean
-e_book_backend_sqlitedb_get_is_populated (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- GError **error)
+e_book_backend_sqlitedb_get_is_populated (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ GError **error)
{
gchar *stmt;
gboolean ret = FALSE;
@@ -1377,12 +1713,18 @@ e_book_backend_sqlitedb_get_is_populated (EBookBackendSqliteDB *ebsdb,
}
-
+/**
+ * e_book_backend_sqlitedb_set_is_populated:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
gboolean
-e_book_backend_sqlitedb_set_is_populated (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- gboolean populated,
- GError **error)
+e_book_backend_sqlitedb_set_is_populated (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ gboolean populated,
+ GError **error)
{
gchar *stmt = NULL;
GError *err = NULL;
@@ -1415,11 +1757,13 @@ e_book_backend_sqlitedb_set_is_populated (EBookBackendSqliteDB *ebsdb,
*
* Returns: TRUE if the vcards stored in the db were downloaded partially. It is to indicate
* the stored vcards does not contain the full data.
+ *
+ * Since: 3.2
**/
gboolean
-e_book_backend_sqlitedb_get_has_partial_content (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- GError **error)
+e_book_backend_sqlitedb_get_has_partial_content (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ GError **error)
{
gchar *stmt;
gboolean ret = FALSE;
@@ -1435,11 +1779,18 @@ e_book_backend_sqlitedb_get_has_partial_content (EBookBackendSqliteDB *ebsdb,
return ret;
}
+/**
+ * e_book_backend_sqlitedb_set_has_partial_content:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
gboolean
-e_book_backend_sqlitedb_set_has_partial_content (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- gboolean partial_content,
- GError **error)
+e_book_backend_sqlitedb_set_has_partial_content (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ gboolean partial_content,
+ GError **error)
{
gchar *stmt = NULL;
GError *err = NULL;
@@ -1463,8 +1814,11 @@ e_book_backend_sqlitedb_set_has_partial_content (EBookBackendSqliteDB *ebsdb,
return !err;
}
-static int
-get_string_cb (gpointer ref, gint col, gchar **cols, gchar **name)
+static gint
+get_string_cb (gpointer ref,
+ gint col,
+ gchar **cols,
+ gchar **name)
{
gchar **ret = ref;
@@ -1473,12 +1827,18 @@ get_string_cb (gpointer ref, gint col, gchar **cols, gchar **name)
return 0;
}
-
-gchar *
-e_book_backend_sqlitedb_get_contact_bdata (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- const gchar *uid,
- GError **error)
+/**
+ * e_book_backend_sqlitedb_get_contact_bdata:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
+gchar *
+e_book_backend_sqlitedb_get_contact_bdata (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ const gchar *uid,
+ GError **error)
{
gchar *stmt, *ret = NULL;
@@ -1493,12 +1853,19 @@ e_book_backend_sqlitedb_get_contact_bdata (EBookBackendSqliteDB *ebsdb,
return ret;
}
-gboolean
-e_book_backend_sqlitedb_set_contact_bdata (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- const gchar *uid,
- const gchar *value,
- GError **error)
+/**
+ * e_book_backend_sqlitedb_set_contact_bdata:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_backend_sqlitedb_set_contact_bdata (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ const gchar *uid,
+ const gchar *value,
+ GError **error)
{
gchar *stmt = NULL;
GError *err = NULL;
@@ -1522,10 +1889,17 @@ e_book_backend_sqlitedb_set_contact_bdata (EBookBackendSqliteDB *ebsdb,
return !err;
}
+/**
+ * e_book_backend_sqlitedb_get_sync_data:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
gchar *
-e_book_backend_sqlitedb_get_sync_data (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- GError **error)
+e_book_backend_sqlitedb_get_sync_data (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ GError **error)
{
gchar *stmt, *ret = NULL;
@@ -1540,11 +1914,18 @@ e_book_backend_sqlitedb_get_sync_data (EBookBackendSqliteDB *ebsdb,
return ret;
}
+/**
+ * e_book_backend_sqlitedb_set_sync_data:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
gboolean
-e_book_backend_sqlitedb_set_sync_data (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- const gchar *sync_data,
- GError **error)
+e_book_backend_sqlitedb_set_sync_data (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ const gchar *sync_data,
+ GError **error)
{
gchar *stmt = NULL;
GError *err = NULL;
@@ -1568,11 +1949,18 @@ e_book_backend_sqlitedb_set_sync_data (EBookBackendSqliteDB *ebsdb,
return !err;
}
+/**
+ * e_book_backend_sqlitedb_get_key_value:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
gchar *
-e_book_backend_sqlitedb_get_key_value (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- const gchar *key,
- GError **error)
+e_book_backend_sqlitedb_get_key_value (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ const gchar *key,
+ GError **error)
{
gchar *stmt, *ret = NULL;
@@ -1588,12 +1976,19 @@ e_book_backend_sqlitedb_get_key_value (EBookBackendSqliteDB *ebsdb,
return ret;
}
+/**
+ * e_book_backend_sqlitedb_set_key_value:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
gboolean
-e_book_backend_sqlitedb_set_key_value (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- const gchar *key,
- const gchar *value,
- GError **error)
+e_book_backend_sqlitedb_set_key_value (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ const gchar *key,
+ const gchar *value,
+ GError **error)
{
gchar *stmt = NULL;
GError *err = NULL;
@@ -1617,10 +2012,17 @@ e_book_backend_sqlitedb_set_key_value (EBookBackendSqliteDB *ebsdb,
return !err;
}
+/**
+ * e_book_backend_sqlitedb_get_partially_cached_ids:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
GSList *
-e_book_backend_sqlitedb_get_partially_cached_ids (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- GError **error)
+e_book_backend_sqlitedb_get_partially_cached_ids (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ GError **error)
{
gchar *stmt;
GSList *uids = NULL;
@@ -1637,10 +2039,17 @@ e_book_backend_sqlitedb_get_partially_cached_ids (EBookBackendSqliteDB *ebsdb,
return uids;
}
+/**
+ * e_book_backend_sqlitedb_delete_addressbook:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
gboolean
-e_book_backend_sqlitedb_delete_addressbook (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- GError **error)
+e_book_backend_sqlitedb_delete_addressbook (EBookBackendSqliteDB *ebsdb,
+ const gchar *folderid,
+ GError **error)
{
gchar *stmt;
GError *err = NULL;
@@ -1679,16 +2088,23 @@ e_book_backend_sqlitedb_delete_addressbook (EBookBackendSqliteDB *ebsdb,
}
/**
- * e_book_backend_sqlitedb_create_addressbook
- * @ebsdb:
- * @folder_id: Used as a primary key.
- * @folder_name: Set the folder name prop.
- * @store_vcard:
- * @error:
- *
- * Creates an address-book table with folder_id as its name.
- * Returns:
+ * e_book_backend_sqlitedb_search_data_free:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
**/
+void
+e_book_backend_sqlitedb_search_data_free (EbSdbSearchData *s_data)
+{
+ if (s_data) {
+ g_free (s_data->uid);
+ g_free (s_data->vcard);
+ g_free (s_data->bdata);
+ g_free (s_data);
+ }
+}
+
gboolean
e_book_backend_sqlitedb_create_addressbook (EBookBackendSqliteDB *ebsdb,
const gchar *folderid,
@@ -1711,20 +2127,16 @@ e_book_backend_sqlitedb_create_addressbook (EBookBackendSqliteDB *ebsdb,
return ret;
}
-void
-e_book_backend_sqlitedb_search_data_free (EbSdbSearchData *s_data)
-{
- if (s_data) {
- g_free (s_data->uid);
- g_free (s_data->vcard);
- g_free (s_data->bdata);
- g_free (s_data);
- }
-}
-
-gboolean
-e_book_backend_sqlitedb_remove (EBookBackendSqliteDB *ebsdb,
- GError **error)
+/**
+ * e_book_backend_sqlitedb_remove:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_book_backend_sqlitedb_remove (EBookBackendSqliteDB *ebsdb,
+ GError **error)
{
EBookBackendSqliteDBPrivate *priv;
gchar *filename;
@@ -1733,7 +2145,7 @@ e_book_backend_sqlitedb_remove (EBookBackendSqliteDB *ebsdb,
priv = ebsdb->priv;
WRITER_LOCK (ebsdb);
-
+
sqlite3_close (priv->db);
filename = g_build_filename (priv->path, DB_FILENAME, NULL);
ret = g_unlink (filename);
@@ -1749,9 +2161,3 @@ e_book_backend_sqlitedb_remove (EBookBackendSqliteDB *ebsdb,
return TRUE;
}
-
-gboolean
-e_book_backend_sqlitedb_is_summary_query (const gchar *query)
-{
- return book_backend_sqlitedb_is_summary_query (query);
-}
diff --git a/src/addressbook/e-book-backend-sqlitedb.h b/src/addressbook/e-book-backend-sqlitedb.h
index 8548c95..ed815e2 100644
--- a/src/addressbook/e-book-backend-sqlitedb.h
+++ b/src/addressbook/e-book-backend-sqlitedb.h
@@ -51,6 +51,14 @@ typedef struct _EBookBackendSqliteDB EBookBackendSqliteDB;
typedef struct _EBookBackendSqliteDBClass EBookBackendSqliteDBClass;
typedef struct _EBookBackendSqliteDBPrivate EBookBackendSqliteDBPrivate;
+/**
+ * EBookBackendSqliteDB:
+ *
+ * Contains only private data that should be read and manipulated using the
+ * functions below.
+ *
+ * Since: 3.2
+ **/
struct _EBookBackendSqliteDB {
GObject parent;
EBookBackendSqliteDBPrivate *priv;
@@ -62,6 +70,13 @@ struct _EBookBackendSqliteDBClass {
/* virtual methods */
};
+/**
+ * EbSdbSearchData:
+ *
+ * FIXME: Document me.
+ *
+ * Since: 3.2
+ **/
typedef struct {
gchar *vcard;
gchar *uid;
@@ -100,25 +115,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,
+EContact * e_book_backend_sqlitedb_get_contact (EBookBackendSqliteDB *ebsdb,
const gchar *folderid,
const gchar *uid,
- GError **error);
-gchar * e_book_backend_sqlitedb_get_vcard_string
- (EBookBackendSqliteDB *ebsdb,
- const gchar *folderid,
- const gchar *uid,
- GError **error);
+ 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,
- GSList *fields_of_interest,
- GError **error);
-GSList * e_book_backend_sqlitedb_search_uids
+ /* const */ GHashTable *fields_of_interest,
+ 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,
@@ -188,10 +211,12 @@ gboolean e_book_backend_sqlitedb_create_addressbook
GError **error);
gboolean e_book_backend_sqlitedb_remove (EBookBackendSqliteDB *ebsdb,
GError **error);
-void e_book_backend_sqlitedb_search_data_free
+void e_book_backend_sqlitedb_search_data_free
(EbSdbSearchData *s_data);
-gboolean e_book_backend_sqlitedb_is_summary_query
- (const gchar *query);
+
+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
#endif /* E_BOOK_BACKEND_SQLITEDB_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]