[evolution-data-server/openismus-work-3-8] EBookBackendSqliteDB: Added e_book_backend_sqlitedb_get/set_locale()



commit 87a2a86dd6a8fb17bcb08dae1366cef4774be3e3
Author: Tristan Van Berkom <tristanvb openismus com>
Date:   Thu May 23 16:15:34 2013 +0900

    EBookBackendSqliteDB: Added e_book_backend_sqlitedb_get/set_locale()
    
    Locale setting is now only ever guessed when creating a new addressbook
    before e_book_backend_sqlitedb_set_locale() is called, setting the locale
    will save the localization setting and it will be reused on subsequent
    accesses. If and when a locale setting is changed, the contact sort
    keys are regenerated with a new ECollator for the new locale.

 .../libedata-book/e-book-backend-sqlitedb.c        |  253 +++++++++++++++-----
 .../libedata-book/e-book-backend-sqlitedb.h        |   10 +
 2 files changed, 198 insertions(+), 65 deletions(-)
---
diff --git a/addressbook/libedata-book/e-book-backend-sqlitedb.c 
b/addressbook/libedata-book/e-book-backend-sqlitedb.c
index b3e82e1..43bba09 100644
--- a/addressbook/libedata-book/e-book-backend-sqlitedb.c
+++ b/addressbook/libedata-book/e-book-backend-sqlitedb.c
@@ -136,28 +136,14 @@ static SummaryField * append_summary_field (GArray         *array,
                                            gboolean       *have_attr_list,
                                            GError        **error);
 
-static gboolean upgrade_contacts_table (EBookBackendSqliteDB  *ebsdb,
-                                        const gchar           *folderid,
-                                        const gchar           *region,
-                                        GError               **error);
-
-
-static const gchar *
-get_current_collation_locale (void)
-{
-       const gchar *lc_collate;
-
-       /* Allow overriding the locale name explicitly, this is mainly
-        * for test cases since we support locales with ICU that
-        * may not be supported by a given system's setlocale()
-        */
-       lc_collate = g_getenv ("EDS_COLLATE");
-
-       if (!lc_collate)
-               lc_collate = setlocale (LC_COLLATE, NULL);
-
-       return lc_collate;
-}
+static gboolean upgrade_contacts_table (EBookBackendSqliteDB *ebsdb,
+                                       const gchar          *folderid,
+                                       const gchar          *region,
+                                       const gchar          *lc_collate,
+                                       GError              **error);
+static gboolean sqlitedb_set_locale_internal (EBookBackendSqliteDB *ebsdb,
+                                             const gchar          *locale,
+                                             GError              **error);
 
 static const gchar *
 summary_dbname_from_field (EBookBackendSqliteDB *ebsdb,
@@ -246,7 +232,8 @@ e_book_backend_sqlitedb_finalize (GObject *object)
        g_free (priv->path);
        g_free (priv->summary_fields);
 
-       e_collator_unref (priv->collator);
+       if (priv->collator)
+               e_collator_unref (priv->collator);
 
        g_mutex_clear (&priv->lock);
        g_mutex_clear (&priv->updates_lock);
@@ -787,13 +774,17 @@ add_folder_into_db (EBookBackendSqliteDB *ebsdb,
                goto rollback;
 
        if (!exists) {
+               const gchar *lc_collate;
+
                multivalues = format_multivalues (ebsdb);
 
+               lc_collate = setlocale (LC_COLLATE, NULL);
+
                stmt = sqlite3_mprintf (
                        "INSERT OR IGNORE INTO "
-                       "folders ( folder_id, folder_name, version, multivalues ) "
-                       "VALUES ( %Q, %Q, %d, %Q ) ",
-                       folderid, folder_name, FOLDER_VERSION, multivalues);
+                       "folders ( folder_id, folder_name, version, multivalues, lc_collate ) "
+                       "VALUES ( %Q, %Q, %d, %Q, %Q ) ",
+                       folderid, folder_name, FOLDER_VERSION, multivalues, lc_collate);
                success = book_backend_sql_exec (
                        ebsdb->priv->db, stmt, NULL, NULL, error);
                sqlite3_free (stmt);
@@ -998,6 +989,8 @@ create_contacts_table (EBookBackendSqliteDB *ebsdb,
        GString *string;
        gboolean relocalized = FALSE;
        gchar *current_region = NULL;
+       const gchar *lc_collate = NULL;
+       gchar *stored_lc_collate = NULL;
 
        if (e_phone_number_is_supported ()) {
                current_region = e_phone_number_get_default_region (error);
@@ -1187,9 +1180,27 @@ create_contacts_table (EBookBackendSqliteDB *ebsdb,
                }
        }
 
+       /* Get the locale setting for this addressbook */
+       if (success && already_exists) {
+               stmt = sqlite3_mprintf ("SELECT lc_collate FROM folders WHERE folder_id = %Q", folderid);
+               success = book_backend_sql_exec (ebsdb->priv->db, stmt, get_string_cb, &stored_lc_collate, 
error);
+               sqlite3_free (stmt);
+
+               lc_collate = stored_lc_collate;
+
+       } else if (success) {
+               /* When creating a new addressbook, default to system locale */
+               lc_collate = setlocale (LC_COLLATE, NULL);
+       }
+
+       /* Before touching any data, make sure we have a valid ECollator */
+       if (success) {
+               success = sqlitedb_set_locale_internal (ebsdb, lc_collate, error);
+       }
+
        /* Need to relocalize the whole thing if the schema has been upgraded to version 7 */
        if (success && previous_schema >= 1 && previous_schema < 7) {
-               success = upgrade_contacts_table (ebsdb, folderid, current_region, error);
+               success = upgrade_contacts_table (ebsdb, folderid, current_region, lc_collate, error);
                relocalized = TRUE;
        }
 
@@ -1202,32 +1213,15 @@ create_contacts_table (EBookBackendSqliteDB *ebsdb,
                sqlite3_free (stmt);
 
                if (success && g_strcmp0 (current_region, stored_region) != 0) {
-                       success = upgrade_contacts_table (ebsdb, folderid, current_region, error);
+                       success = upgrade_contacts_table (ebsdb, folderid, current_region, lc_collate, error);
                        relocalized = TRUE;
                }
 
                g_free (stored_region);
        }
 
-       /* We may need to relocalize for an LC_COLLATE locale change */
-       if (success && relocalized == FALSE) {
-               const gchar *lc_collate = NULL;
-               gchar *stored_lc_collate;
-
-               stmt = sqlite3_mprintf ("SELECT lc_collate FROM folders WHERE folder_id = %Q", folderid);
-               success = book_backend_sql_exec (ebsdb->priv->db, stmt, get_string_cb, &stored_lc_collate, 
error);
-               sqlite3_free (stmt);
-
-               lc_collate = get_current_collation_locale ();
-
-               if (success && g_strcmp0 (stored_lc_collate, lc_collate) != 0) {
-                       success = upgrade_contacts_table (ebsdb, folderid, current_region, error);
-                       relocalized = TRUE;
-               }
-
-               g_free (stored_lc_collate);
-       }
        g_free (current_region);
+       g_free (stored_lc_collate);
 
        return success;
 }
@@ -1568,8 +1562,6 @@ e_book_backend_sqlitedb_new_internal (const gchar *path,
        gchar *hash_key, *filename;
        gint previous_schema = 0;
        gboolean already_exists = FALSE;
-       const gchar *lc_collate;
-       ECollator *collator;
 
        g_return_val_if_fail (path != NULL, NULL);
        g_return_val_if_fail (emailid != NULL, NULL);
@@ -1589,13 +1581,6 @@ e_book_backend_sqlitedb_new_internal (const gchar *path,
                }
        }
 
-       lc_collate = get_current_collation_locale ();
-       collator = e_collator_new (lc_collate, error);
-       if (!collator) {
-               g_mutex_unlock (&dbcon_lock);
-               return NULL;
-       }
-
        ebsdb = g_object_new (E_TYPE_BOOK_BACKEND_SQLITEDB, NULL);
        ebsdb->priv->path = g_strdup (path);
        ebsdb->priv->summary_fields = fields;
@@ -1603,7 +1588,6 @@ e_book_backend_sqlitedb_new_internal (const gchar *path,
        ebsdb->priv->have_attr_list = have_attr_list;
        ebsdb->priv->attr_list_indexes = attr_list_indexes;
        ebsdb->priv->store_vcard = store_vcard;
-       ebsdb->priv->collator = collator;
 
        if (g_mkdir_with_parents (path, 0777) < 0) {
                g_mutex_unlock (&dbcon_lock);
@@ -4998,13 +4982,13 @@ e_book_backend_sqlitedb_remove (EBookBackendSqliteDB *ebsdb,
 }
 
 static gboolean
-upgrade_contacts_table (EBookBackendSqliteDB  *ebsdb,
-                        const gchar          *folderid,
-                        const gchar          *region,
-                        GError              **error)
+upgrade_contacts_table (EBookBackendSqliteDB *ebsdb,
+                       const gchar          *folderid,
+                       const gchar          *region,
+                       const gchar          *lc_collate,
+                       GError              **error)
 {
        gchar *stmt;
-       const gchar *lc_collate;
        gboolean success = FALSE;
        GSList *vcard_data = NULL;
        GSList *l;
@@ -5014,9 +4998,6 @@ upgrade_contacts_table (EBookBackendSqliteDB  *ebsdb,
                ebsdb->priv->db, stmt, addto_vcard_list_cb, &vcard_data, error);
        sqlite3_free (stmt);
 
-       if (vcard_data == NULL)
-               return TRUE;
-
        for (l = vcard_data; success && l; l = l->next) {
                EbSdbSearchData *const s_data = l->data;
                EContact *contact = e_contact_new_from_vcard_with_uid (s_data->vcard, s_data->uid);
@@ -5032,7 +5013,6 @@ upgrade_contacts_table (EBookBackendSqliteDB  *ebsdb,
        g_slist_free_full (vcard_data, destroy_search_data);
 
        if (success) {
-               lc_collate = get_current_collation_locale ();
 
                stmt = sqlite3_mprintf (
                        "UPDATE folders SET countrycode = %Q WHERE folder_id = %Q",
@@ -5052,6 +5032,149 @@ upgrade_contacts_table (EBookBackendSqliteDB  *ebsdb,
        return success;
 }
 
+static gboolean
+sqlitedb_set_locale_internal (EBookBackendSqliteDB *ebsdb,
+                             const gchar          *locale,
+                             GError              **error)
+{
+       ECollator *collator;
+
+       collator = e_collator_new (locale, error);
+       if (!collator)
+               return FALSE;
+
+       if (ebsdb->priv->collator)
+               e_collator_unref (ebsdb->priv->collator);
+
+       ebsdb->priv->collator = collator;
+
+       return TRUE;
+}
+
+/**
+ * e_book_backend_sqlitedb_set_locale:
+ * @ebsdb: An #EBookBackendSqliteDB
+ * @folderid: folder id of the address-book
+ * @lc_collate: The new locale for the addressbook
+ * @error: A location to store any error that may have occurred
+ *
+ * Relocalizes any locale specific data in the specified
+ * new @lc_collate locale.
+ *
+ * The @lc_collate locale setting is stored and remembered on
+ * subsequent accesses of the addressbook, changing the locale
+ * will store the new locale and will modify sort keys and any
+ * locale specific data in the addressbook.
+ *
+ * Returns: Whether the new locale was successfully set.
+ *
+ * Since: 3.10
+ */
+gboolean
+e_book_backend_sqlitedb_set_locale (EBookBackendSqliteDB *ebsdb,
+                                   const gchar          *folderid,
+                                   const gchar          *lc_collate,
+                                   GError              **error)
+{
+       gboolean success;
+       gchar *stmt;
+       gchar *stored_lc_collate;
+       gchar *current_region = NULL;
+
+       g_return_val_if_fail (E_IS_BOOK_BACKEND_SQLITEDB (ebsdb), FALSE);
+       g_return_val_if_fail (folderid && folderid[0], FALSE);
+
+       LOCK_MUTEX (&ebsdb->priv->lock);
+
+       if (e_phone_number_is_supported ()) {
+               current_region = e_phone_number_get_default_region (error);
+
+               if (current_region == NULL)
+                       return FALSE;
+       }
+
+       if (!sqlitedb_set_locale_internal (ebsdb, lc_collate, error))
+               return FALSE;
+
+       if (!book_backend_sqlitedb_start_transaction (ebsdb, error)) {
+               UNLOCK_MUTEX (&ebsdb->priv->lock);
+               g_free (current_region);
+               return FALSE;
+       }
+
+       stmt = sqlite3_mprintf ("SELECT lc_collate FROM folders WHERE folder_id = %Q", folderid);
+       success = book_backend_sql_exec (ebsdb->priv->db, stmt, get_string_cb, &stored_lc_collate, error);
+       sqlite3_free (stmt);
+
+       if (success && g_strcmp0 (stored_lc_collate, lc_collate) != 0)
+               success = upgrade_contacts_table (ebsdb, folderid, current_region, lc_collate, error);
+
+       /* If for some reason we failed, then reset the collator to use the old locale */
+       if (!success)
+               sqlitedb_set_locale_internal (ebsdb, stored_lc_collate, NULL);
+
+       g_free (stored_lc_collate);
+       g_free (current_region);
+
+       if (!success)
+               goto rollback;
+
+       success = book_backend_sqlitedb_commit_transaction (ebsdb, error);
+       UNLOCK_MUTEX (&ebsdb->priv->lock);
+
+       return success;
+
+ rollback:
+       /* The GError is already set. */
+       book_backend_sqlitedb_rollback_transaction (ebsdb, NULL);
+
+       UNLOCK_MUTEX (&ebsdb->priv->lock);
+
+       return FALSE;
+}
+
+/**
+ * e_book_backend_sqlitedb_get_locale:
+ * @ebsdb: An #EBookBackendSqliteDB
+ * @folderid: folder id of the address-book
+ * @revision_out: (out) (transfer full): The location to return the current locale
+ * @error: A location to store any error that may have occurred
+ *
+ * Fetches the current locale setting for the address-book indicated by @folderid.
+ *
+ * Upon success, @lc_collate_out will hold the returned locale setting,
+ * otherwise %FALSE will be returned and @error will be updated accordingly.
+ *
+ * Returns: Whether the locale was successfully fetched.
+ *
+ * Since: 3.10
+ */
+gboolean
+e_book_backend_sqlitedb_get_locale (EBookBackendSqliteDB *ebsdb,
+                                   const gchar          *folderid,
+                                   gchar               **lc_collate_out,
+                                   GError              **error)
+{
+       gchar *stmt;
+       gboolean success;
+
+       g_return_val_if_fail (E_IS_BOOK_BACKEND_SQLITEDB (ebsdb), FALSE);
+       g_return_val_if_fail (folderid && folderid[0], FALSE);
+       g_return_val_if_fail (lc_collate_out != NULL && *lc_collate_out == NULL, FALSE);
+
+       LOCK_MUTEX (&ebsdb->priv->lock);
+
+       stmt = sqlite3_mprintf (
+               "SELECT lc_collate FROM folders WHERE folder_id = %Q", folderid);
+       success = book_backend_sql_exec (
+               ebsdb->priv->db, stmt, get_string_cb, lc_collate_out, error);
+       sqlite3_free (stmt);
+
+       UNLOCK_MUTEX (&ebsdb->priv->lock);
+
+       return success;
+}
+
 /******************************************************************
  *                          EbSdbCursor apis                       *
  ******************************************************************/
diff --git a/addressbook/libedata-book/e-book-backend-sqlitedb.h 
b/addressbook/libedata-book/e-book-backend-sqlitedb.h
index 571aac0..e4e9ba4 100644
--- a/addressbook/libedata-book/e-book-backend-sqlitedb.h
+++ b/addressbook/libedata-book/e-book-backend-sqlitedb.h
@@ -285,6 +285,16 @@ gboolean        e_book_backend_sqlitedb_check_summary_query
 gboolean        e_book_backend_sqlitedb_check_summary_fields
                                                 (EBookBackendSqliteDB *ebsdb,
                                                 GHashTable *fields_of_interest);
+gboolean        e_book_backend_sqlitedb_set_locale
+                                                (EBookBackendSqliteDB *ebsdb,
+                                                const gchar          *folderid,
+                                                const gchar          *lc_collate,
+                                                GError              **error);
+gboolean        e_book_backend_sqlitedb_get_locale
+                                                (EBookBackendSqliteDB *ebsdb,
+                                                const gchar          *folderid,
+                                                gchar               **lc_collate_out,
+                                                GError              **error);
 
 /* Cursor API */
 EbSdbCursor    *e_book_backend_sqlitedb_cursor_new


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