[evolution-data-server/intel-work-3-12: 3/4] EBookSqlite: Added support for recording detailed changes of contacts



commit 9453aff114c943f747910c8371b0a81431537cd3
Author: Mateusz Polrola <mateusz polrola gmail com>
Date:   Fri May 30 12:45:28 2014 +0200

    EBookSqlite: Added support for recording detailed changes of contacts
    
    Cherry picked from commit in master:
    EBookSqlite: Allow record detailed changes made to contacts a0d905
    
    Fixes BGO #729251

 addressbook/backends/file/e-book-backend-file.c |   10 +-
 addressbook/libedata-book/e-book-sqlite.c       |  315 ++++++++++++++++++++++-
 addressbook/libedata-book/e-book-sqlite.h       |   33 +++
 tests/libedata-book/data-test-utils.c           |    2 +
 4 files changed, 349 insertions(+), 11 deletions(-)
---
diff --git a/addressbook/backends/file/e-book-backend-file.c b/addressbook/backends/file/e-book-backend-file.c
index bf506fe..346884d 100644
--- a/addressbook/backends/file/e-book-backend-file.c
+++ b/addressbook/backends/file/e-book-backend-file.c
@@ -1469,8 +1469,10 @@ book_backend_file_remove_contacts_sync (EBookBackend *backend,
                /* Remove from summary as well */
                if (!e_book_sqlite_remove_contacts (bf->priv->sqlitedb, removed_ids,
                                                    cancellable, &local_error)) {
-                       g_warning ("Failed to remove contacts: %s", local_error->message);
-                       g_propagate_error (error, local_error);
+                       if (!local_error) {
+                               g_warning ("Failed to remove contacts: %s", local_error->message);
+                               g_propagate_error (error, local_error);
+                       }
                }
 
                e_book_backend_file_bump_revision (bf, NULL);
@@ -1988,7 +1990,7 @@ book_backend_file_initable_init (GInitable *initable,
        /* The old BDB exists, lets migrate that to sqlite right away. */
        if (g_file_test (filename, G_FILE_TEST_EXISTS)) {
                priv->sqlitedb = e_book_sqlite_new_full (
-                       fullpath, setup_extension,
+                       fullpath, source, setup_extension,
                        NULL,
                        book_backend_file_vcard_changed,
                        initable, NULL, cancellable, error);
@@ -2033,7 +2035,7 @@ book_backend_file_initable_init (GInitable *initable,
 
                /* Create the sqlitedb. */
                priv->sqlitedb = e_book_sqlite_new_full (
-                       fullpath, setup_extension,
+                       fullpath, source, setup_extension,
                        NULL,
                        book_backend_file_vcard_changed,
                        initable, NULL, cancellable, error);
diff --git a/addressbook/libedata-book/e-book-sqlite.c b/addressbook/libedata-book/e-book-sqlite.c
index 4881bcb..acadc34 100644
--- a/addressbook/libedata-book/e-book-sqlite.c
+++ b/addressbook/libedata-book/e-book-sqlite.c
@@ -368,9 +368,20 @@ struct _EBookSqlitePrivate {
        sqlite3_stmt   *replace_stmt;    /* Replace statement for main summary table */
        GHashTable     *multi_deletes;   /* Delete statement for each auxiliary table */
        GHashTable     *multi_inserts;   /* Insert statement for each auxiliary table */
+
+       ESource        *source;
 };
 
-G_DEFINE_TYPE (EBookSqlite, e_book_sqlite, G_TYPE_OBJECT)
+enum {
+       BEFORE_INSERT_CONTACT,
+       BEFORE_REMOVE_CONTACT,
+       LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+G_DEFINE_TYPE_WITH_CODE (EBookSqlite, e_book_sqlite, G_TYPE_OBJECT,
+                        G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE, NULL))
 G_DEFINE_QUARK (e-book-backend-sqlite-error-quark,
                e_book_sqlite_error)
 
@@ -2775,6 +2786,7 @@ ebsql_init_locale (EBookSqlite *ebsql,
 
 static EBookSqlite *
 ebsql_new_internal (const gchar *path,
+                   ESource *source,
                     EbSqlVCardCallback vcard_callback,
                     EbSqlChangeCallback change_callback,
                     gpointer user_data,
@@ -2814,6 +2826,10 @@ ebsql_new_internal (const gchar *path,
        ebsql->priv->change_callback = change_callback;
        ebsql->priv->user_data = user_data;
        ebsql->priv->user_data_destroy = user_data_destroy;
+       if (source != NULL)
+               ebsql->priv->source = g_object_ref (source);
+       else
+               ebsql->priv->source = NULL;
 
        EBSQL_NOTE (REF_COUNTS, g_printerr ("EBookSqlite initially created\n"));
 
@@ -6144,6 +6160,8 @@ e_book_sqlite_finalize (GObject *object)
        if (ebsql->priv->transliterator)
                e_transliterator_unref (ebsql->priv->transliterator);
 
+       g_clear_object (&priv->source);
+
        g_mutex_clear (&priv->lock);
        g_mutex_clear (&priv->updates_lock);
 
@@ -6167,6 +6185,51 @@ e_book_sqlite_finalize (GObject *object)
 }
 
 static void
+e_book_sqlite_constructed (GObject *object)
+{
+       /* Chain up to parent's constructed() method. */
+       G_OBJECT_CLASS (e_book_sqlite_parent_class)->constructed (object);
+
+       e_extensible_load_extensions (E_EXTENSIBLE (object));
+}
+
+static gboolean
+ebsql_signals_accumulator (GSignalInvocationHint *ihint,
+                          GValue *return_accu,
+                          const GValue *handler_return,
+                          gpointer data)
+{
+       gboolean handler_result;
+
+       handler_result = g_value_get_boolean (handler_return);
+       g_value_set_boolean (return_accu, handler_result);
+
+       return handler_result;
+}
+
+static gboolean
+ebsql_before_insert_contact_default (EBookSqlite *ebsql,
+                                    gpointer db,
+                                    EContact *contact,
+                                    const gchar *extra,
+                                    gboolean replace,
+                                    GCancellable *cancellable,
+                                    GError **error)
+{
+       return TRUE;
+}
+
+static gboolean
+ebsql_before_remove_contact_default (EBookSqlite *ebsql,
+                                    gpointer db,
+                                    const gchar *contact_uid,
+                                    GCancellable *cancellable,
+                                    GError **error)
+{
+       return TRUE;
+}
+
+static void
 e_book_sqlite_class_init (EBookSqliteClass *class)
 {
        GObjectClass *object_class;
@@ -6176,9 +6239,43 @@ e_book_sqlite_class_init (EBookSqliteClass *class)
        object_class = G_OBJECT_CLASS (class);
        object_class->dispose = e_book_sqlite_dispose;
        object_class->finalize = e_book_sqlite_finalize;
+       object_class->constructed = e_book_sqlite_constructed;
+
+       class->before_insert_contact = ebsql_before_insert_contact_default;
+       class->before_remove_contact = ebsql_before_remove_contact_default;
 
        /* Parse the EBSQL_DEBUG environment variable */
        ebsql_init_debug ();
+
+       signals[BEFORE_INSERT_CONTACT] = g_signal_new (
+               "before-insert-contact",
+               G_OBJECT_CLASS_TYPE (class),
+               G_SIGNAL_RUN_LAST,
+               G_STRUCT_OFFSET (EBookSqliteClass, before_insert_contact),
+               ebsql_signals_accumulator,
+               NULL,
+               g_cclosure_marshal_generic,
+               G_TYPE_BOOLEAN, 6,
+               G_TYPE_POINTER,
+               G_TYPE_OBJECT,
+               G_TYPE_STRING,
+               G_TYPE_BOOLEAN,
+               G_TYPE_OBJECT,
+               G_TYPE_POINTER);
+
+       signals[BEFORE_REMOVE_CONTACT] = g_signal_new (
+               "before-remove-contact",
+               G_OBJECT_CLASS_TYPE (class),
+               G_SIGNAL_RUN_LAST,
+               G_STRUCT_OFFSET (EBookSqliteClass, before_remove_contact),
+               ebsql_signals_accumulator,
+               NULL,
+               g_cclosure_marshal_generic,
+               G_TYPE_BOOLEAN, 4,
+               G_TYPE_POINTER,
+               G_TYPE_STRING,
+               G_TYPE_OBJECT,
+               G_TYPE_POINTER);
 }
 
 static void
@@ -6197,6 +6294,7 @@ e_book_sqlite_init (EBookSqlite *ebsql)
  **********************************************************/
 static EBookSqlite *
 ebsql_new_default (const gchar *path,
+                  ESource *source,
                    EbSqlVCardCallback vcard_callback,
                    EbSqlChangeCallback change_callback,
                    gpointer user_data,
@@ -6221,7 +6319,8 @@ ebsql_new_default (const gchar *path,
                G_N_ELEMENTS (default_indexed_fields));
 
        ebsql = ebsql_new_internal (
-               path, vcard_callback, change_callback,
+               path, source,
+               vcard_callback, change_callback,
                user_data, user_data_destroy,
                (SummaryField *) summary_fields->data,
                summary_fields->len,
@@ -6261,12 +6360,13 @@ ebsql_new_default (const gchar *path,
  **/
 EBookSqlite *
 e_book_sqlite_new (const gchar *path,
+                  ESource *source,
                    GCancellable *cancellable,
                    GError **error)
 {
        g_return_val_if_fail (path && path[0], NULL);
 
-       return ebsql_new_default (path, NULL, NULL, NULL, NULL, cancellable, error);
+       return ebsql_new_default (path, source, NULL, NULL, NULL, NULL, cancellable, error);
 }
 
 /**
@@ -6311,6 +6411,7 @@ e_book_sqlite_new (const gchar *path,
  **/
 EBookSqlite *
 e_book_sqlite_new_full (const gchar *path,
+                       ESource *source,
                         ESourceBackendSummarySetup *setup,
                         EbSqlVCardCallback vcard_callback,
                         EbSqlChangeCallback change_callback,
@@ -6333,6 +6434,7 @@ e_book_sqlite_new_full (const gchar *path,
        if (!setup)
                return ebsql_new_default (
                        path,
+                       source,
                        vcard_callback,
                        change_callback,
                        user_data,
@@ -6352,6 +6454,7 @@ e_book_sqlite_new_full (const gchar *path,
 
                ebsql = ebsql_new_default (
                        path,
+                       source,
                        vcard_callback,
                        change_callback,
                        user_data,
@@ -6401,7 +6504,8 @@ e_book_sqlite_new_full (const gchar *path,
                summary_fields, indexed_fields, index_types, n_indexed_fields);
 
        ebsql = ebsql_new_internal (
-               path, vcard_callback, change_callback,
+               path, source,
+               vcard_callback, change_callback,
                user_data, user_data_destroy,
                (SummaryField *) summary_fields->data,
                summary_fields->len,
@@ -6550,6 +6654,30 @@ e_book_sqlite_ref_collator (EBookSqlite *ebsql)
 }
 
 /**
+ * e_book_sqlite_ref_source:
+ * @ebsql: An #EBookSqlite
+ *
+ * References the #ESource to which @ebsql is paired,
+ * use g_object_unref() when finished using the source.
+ * It can be %NULL in some cases, like when running tests.
+ *
+ * Returns: (transfer-full): A reference to the #ESource to which @ebsql
+ * is paired, or %NULL.
+ *
+ * Since: 3.14
+*/
+ESource *
+e_book_sqlite_ref_source (EBookSqlite *ebsql)
+{
+       g_return_val_if_fail (E_IS_BOOK_SQLITE (ebsql), NULL);
+
+       if (!ebsql->priv->source)
+               return NULL;
+
+       return g_object_ref (ebsql->priv->source);
+}
+
+/**
  * e_book_sqlitedb_add_contact:
  * @ebsql: An #EBookSqlite
  * @contact: EContact to be added
@@ -6641,6 +6769,17 @@ e_book_sqlite_add_contacts (EBookSqlite *ebsql,
                if (ll)
                        extra_data = (const gchar *) ll->data;
 
+               g_signal_emit (ebsql,
+                              signals[BEFORE_INSERT_CONTACT],
+                              0,
+                              ebsql->priv->db,
+                              contact, extra_data,
+                              replace,
+                              cancellable, error,
+                              &success);
+               if (!success)
+                       break;
+
                success = ebsql_insert_contact (
                        ebsql,
                        EBSQL_CHANGE_CONTACT_ADDED,
@@ -6736,6 +6875,8 @@ e_book_sqlite_remove_contacts (EBookSqlite *ebsql,
        gboolean success = TRUE;
        gint i;
        gchar *stmt;
+       const gchar *contact_uid;
+       GSList *l = NULL;
 
        g_return_val_if_fail (E_IS_BOOK_SQLITE (ebsql), FALSE);
        g_return_val_if_fail (uids != NULL, FALSE);
@@ -6747,6 +6888,17 @@ e_book_sqlite_remove_contacts (EBookSqlite *ebsql,
                return FALSE;
        }
 
+       for (l = uids; success && l; l = l->next) {
+               contact_uid = (const gchar *) l->data;
+               g_signal_emit (ebsql,
+                              signals[BEFORE_REMOVE_CONTACT],
+                              0,
+                              ebsql->priv->db,
+                              contact_uid,
+                              cancellable, error,
+                              &success);
+       }
+
        /* Delete data from the auxiliary tables first */
        for (i = 0; success && i < ebsql->priv->n_summary_fields; i++) {
                SummaryField *field = &(ebsql->priv->summary_fields[i]);
@@ -6827,7 +6979,7 @@ e_book_sqlite_has_contact (EBookSqlite *ebsql,
  * Fetch the #EContact specified by @uid in @ebsql.
  *
  * If @meta_contact is specified, then a shallow #EContact will be created
- * holing only the %E_CONTACT_UID and %E_CONTACT_REV fields.
+ * holding only the %E_CONTACT_UID and %E_CONTACT_REV fields.
  *
  * Returns: %TRUE on success, otherwise %FALSE is returned and @error is set appropriately.
  *
@@ -6859,6 +7011,51 @@ e_book_sqlite_get_contact (EBookSqlite *ebsql,
 }
 
 /**
+ * ebsql_get_contact_unlocked:
+ * @ebsql: An #EBookSqlite
+ * @uid: The uid of the contact to fetch
+ * @meta_contact: Whether an entire contact is desired, or only the metadata
+ * @contact: (out) (transfer full): Return location to store the fetched contact
+ * @error: (allow-none): A location to store any error that may have occurred.
+ *
+ * Fetch the #EContact specified by @uid in @ebsql without locking internal mutex.
+ *
+ * If @meta_contact is specified, then a shallow #EContact will be created
+ * holding only the %E_CONTACT_UID and %E_CONTACT_REV fields.
+ *
+ * Returns: %TRUE on success, otherwise %FALSE is returned and @error is set appropriately.
+ *
+ * Since: 3.14
+ **/
+gboolean
+ebsql_get_contact_unlocked (EBookSqlite *ebsql,
+                           const gchar *uid,
+                           gboolean meta_contact,
+                           EContact **contact,
+                           GError **error)
+{
+       gboolean success = FALSE;
+       gchar *vcard = NULL;
+
+       g_return_val_if_fail (E_IS_BOOK_SQLITE (ebsql), FALSE);
+       g_return_val_if_fail (uid != NULL, FALSE);
+       g_return_val_if_fail (contact != NULL && *contact == NULL, FALSE);
+
+       success = ebsql_get_vcard_unlocked (ebsql,
+                                           uid,
+                                           meta_contact,
+                                           &vcard,
+                                           error);
+
+       if (success && vcard) {
+               *contact = e_contact_new_from_vcard_with_uid (vcard, uid);
+               g_free (vcard);
+       }
+
+       return success;
+}
+
+/**
  * e_book_sqlite_get_vcard:
  * @ebsql: An #EBookSqlite
  * @uid: The uid of the contact to fetch
@@ -6869,7 +7066,7 @@ e_book_sqlite_get_contact (EBookSqlite *ebsql,
  * Fetch a vcard string for @uid in @ebsql.
  *
  * If @meta_contact is specified, then a shallow vcard representation will be
- * created holing only the %E_CONTACT_UID and %E_CONTACT_REV fields.
+ * created holding only the %E_CONTACT_UID and %E_CONTACT_REV fields.
  *
  * Returns: %TRUE on success, otherwise %FALSE is returned and @error is set appropriately.
  *
@@ -6933,6 +7130,75 @@ e_book_sqlite_get_vcard (EBookSqlite *ebsql,
 }
 
 /**
+ * ebsql_get_vcard_unlocked:
+ * @ebsql: An #EBookSqlite
+ * @uid: The uid of the contact to fetch
+ * @meta_contact: Whether an entire contact is desired, or only the metadata
+ * @ret_vcard: (out) (transfer full): Return location to store the fetched vcard string
+ * @error: (allow-none): A location to store any error that may have occurred.
+ *
+ * Fetch a vcard string for @uid in @ebsql without locking internal mutex.
+ *
+ * If @meta_contact is specified, then a shallow vcard representation will be
+ * created holding only the %E_CONTACT_UID and %E_CONTACT_REV fields.
+ *
+ * Returns: %TRUE on success, otherwise %FALSE is returned and @error is set appropriately.
+ *
+ * Since: 3.14
+ **/
+gboolean
+ebsql_get_vcard_unlocked (EBookSqlite *ebsql,
+                         const gchar *uid,
+                         gboolean meta_contact,
+                         gchar **ret_vcard,
+                         GError **error)
+{
+       gboolean success = FALSE;
+       gchar *vcard = NULL;
+
+       g_return_val_if_fail (E_IS_BOOK_SQLITE (ebsql), FALSE);
+       g_return_val_if_fail (uid != NULL, FALSE);
+       g_return_val_if_fail (ret_vcard != NULL && *ret_vcard == NULL, FALSE);
+
+       /* Try constructing contacts from only UID/REV first if that's requested */
+       if (meta_contact) {
+               GSList *vcards = NULL;
+
+               success = ebsql_exec_printf (
+                       ebsql, "SELECT summary.uid, summary.Rev FROM %Q AS summary WHERE uid = %Q",
+                       collect_lean_results_cb, &vcards, NULL, error,
+                       ebsql->priv->folderid, uid);
+
+               if (vcards) {
+                       EbSqlSearchData *search_data = (EbSqlSearchData *) vcards->data;
+
+                       vcard = search_data->vcard;
+                       search_data->vcard = NULL;
+
+                       g_slist_free_full (vcards, (GDestroyNotify) e_book_sqlite_search_data_free);
+                       vcards = NULL;
+               }
+
+       } else {
+              success = ebsql_exec_printf (
+                      ebsql, "SELECT %s FROM %Q AS summary WHERE summary.uid = %Q",
+                      get_string_cb, &vcard, NULL, error,
+                      EBSQL_VCARD_FRAGMENT (ebsql), ebsql->priv->folderid, uid);
+       }
+
+       *ret_vcard = vcard;
+
+       if (success && !vcard) {
+               EBSQL_SET_ERROR (error,
+                                E_BOOK_SQLITE_ERROR_CONTACT_NOT_FOUND,
+                                _("Contact '%s' not found"), uid);
+               success = FALSE;
+       }
+
+       return success;
+}
+
+/**
  * e_book_sqlite_set_contact_extra:
  * @ebsql: An #EBookSqlite
  * @uid: The uid of the contact to set the extra data for
@@ -7003,6 +7269,41 @@ e_book_sqlite_get_contact_extra (EBookSqlite *ebsql,
 }
 
 /**
+ * ebsql_get_contact_extra_unlocked:
+ * @ebsql: An #EBookSqlite
+ * @uid: The uid of the contact to fetch the extra data for
+ * @ret_extra: (out) (transfer full): Return location to store the extra data
+ * @error: (allow-none): A location to store any error that may have occurred.
+ *
+ * Fetches the extra data previously set for @uid, either with
+ * e_book_sqlite_set_contact_extra() or when adding contacts,
+ * without locking internal mutex.
+ *
+ * Returns: %TRUE on success, otherwise %FALSE is returned and @error is set appropriately.
+ *
+ * Since: 3.14
+ **/
+gboolean
+ebsql_get_contact_extra_unlocked (EBookSqlite *ebsql,
+                                 const gchar *uid,
+                                 gchar **ret_extra,
+                                 GError **error)
+{
+       gboolean success;
+
+       g_return_val_if_fail (E_IS_BOOK_SQLITE (ebsql), FALSE);
+       g_return_val_if_fail (uid != NULL, FALSE);
+       g_return_val_if_fail (ret_extra != NULL && *ret_extra == NULL, FALSE);
+
+       success = ebsql_exec_printf (
+               ebsql, "SELECT bdata FROM %Q WHERE uid = %Q",
+               get_string_cb, ret_extra, NULL, error,
+               ebsql->priv->folderid, uid);
+
+       return success;
+}
+
+/**
  * e_book_sqlite_search:
  * @ebsql: An #EBookSqlite
  * @sexp: (allow-none): search expression; use %NULL or an empty string to list all stored contacts.
@@ -7023,7 +7324,7 @@ e_book_sqlite_get_contact_extra (EBookSqlite *ebsql,
  * and all elements freed with e_book_sqlite_search_data_free().
  *
  * If @meta_contact is specified, then shallow vcard representations will be
- * created holing only the %E_CONTACT_UID and %E_CONTACT_REV fields.
+ * created holding only the %E_CONTACT_UID and %E_CONTACT_REV fields.
  *
  * Returns: %TRUE on success, otherwise %FALSE is returned and @error is set appropriately.
  *
diff --git a/addressbook/libedata-book/e-book-sqlite.h b/addressbook/libedata-book/e-book-sqlite.h
index 67ba6ff..08e7ecc 100644
--- a/addressbook/libedata-book/e-book-sqlite.h
+++ b/addressbook/libedata-book/e-book-sqlite.h
@@ -244,6 +244,20 @@ struct _EBookSqlite {
 struct _EBookSqliteClass {
        /*< private >*/
        GObjectClass parent_class;
+
+       /* Signals */
+       gboolean        (*before_insert_contact) (EBookSqlite *ebsql,
+                                                 gpointer db, /* sqlite3 */
+                                                 EContact *contact,
+                                                 const gchar *extra,
+                                                 gboolean replace,
+                                                 GCancellable *cancellable,
+                                                 GError **error);
+       gboolean        (*before_remove_contact) (EBookSqlite *ebsql,
+                                                 gpointer db, /* sqlite3 */
+                                                 const gchar *contact_uid,
+                                                 GCancellable *cancellable,
+                                                 GError **error);
 };
 
 /**
@@ -294,9 +308,11 @@ GQuark             e_book_sqlite_error_quark       (void);
 void           e_book_sqlite_search_data_free  (EbSqlSearchData *data);
 
 EBookSqlite *  e_book_sqlite_new               (const gchar *path,
+                                                ESource *source,
                                                 GCancellable *cancellable,
                                                 GError **error);
 EBookSqlite *  e_book_sqlite_new_full          (const gchar *path,
+                                                ESource *source,
                                                 ESourceBackendSummarySetup *setup,
                                                 EbSqlVCardCallback vcard_callback,
                                                 EbSqlChangeCallback change_callback,
@@ -321,6 +337,8 @@ gboolean    e_book_sqlite_get_locale        (EBookSqlite *ebsql,
 
 ECollator *    e_book_sqlite_ref_collator      (EBookSqlite *ebsql);
 
+ESource *      e_book_sqlite_ref_source        (EBookSqlite *ebsql);
+
 /* Adding / Removing / Searching contacts */
 gboolean       e_book_sqlite_add_contact       (EBookSqlite *ebsql,
                                                 EContact *contact,
@@ -351,11 +369,21 @@ gboolean  e_book_sqlite_get_contact       (EBookSqlite *ebsql,
                                                 gboolean meta_contact,
                                                 EContact **ret_contact,
                                                 GError **error);
+gboolean       ebsql_get_contact_unlocked      (EBookSqlite *ebsql,
+                                                const gchar *uid,
+                                                gboolean meta_contact,
+                                                EContact **ret_contact,
+                                                GError **error);
 gboolean       e_book_sqlite_get_vcard         (EBookSqlite *ebsql,
                                                 const gchar *uid,
                                                 gboolean meta_contact,
                                                 gchar **ret_vcard,
                                                 GError **error);
+gboolean       ebsql_get_vcard_unlocked        (EBookSqlite *ebsql,
+                                                const gchar *uid,
+                                                gboolean meta_contact,
+                                                gchar **ret_vcard,
+                                                GError **error);
 gboolean       e_book_sqlite_set_contact_extra (EBookSqlite *ebsql,
                                                 const gchar *uid,
                                                 const gchar *extra,
@@ -364,6 +392,11 @@ gboolean   e_book_sqlite_get_contact_extra (EBookSqlite *ebsql,
                                                 const gchar *uid,
                                                 gchar **ret_extra,
                                                 GError **error);
+gboolean       ebsql_get_contact_extra_unlocked
+                                               (EBookSqlite *ebsql,
+                                                const gchar *uid,
+                                                gchar **ret_extra,
+                                                GError **error);
 gboolean       e_book_sqlite_search            (EBookSqlite *ebsql,
                                                 const gchar *sexp,
                                                 gboolean meta_contacts,
diff --git a/tests/libedata-book/data-test-utils.c b/tests/libedata-book/data-test-utils.c
index 46179d4..40735b4 100644
--- a/tests/libedata-book/data-test-utils.c
+++ b/tests/libedata-book/data-test-utils.c
@@ -210,6 +210,7 @@ e_sqlite_fixture_setup (EbSqlFixture *fixture,
        if (closure->without_vcards)
                fixture->ebsql = e_book_sqlite_new_full (
                        filename,
+                       NULL,
                        setup,
                        fetch_vcard_from_hash,
                        contact_change_cb,
@@ -219,6 +220,7 @@ e_sqlite_fixture_setup (EbSqlFixture *fixture,
        else
                fixture->ebsql = e_book_sqlite_new_full (
                        filename,
+                       NULL,
                        setup,
                        NULL,
                        contact_change_cb,


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