[gom] sorting: Allow adding sorting clauses to an existing GomSorting



commit e7a8801109b1d361b7aab144c08eadaaba998605
Author: Mathieu Bridon <bochecha daitauha fr>
Date:   Wed Jul 8 23:05:06 2015 +0200

    sorting: Allow adding sorting clauses to an existing GomSorting
    
    This allows another way to use GomSorting objects.
    
    In addition, it makes it possible to use GomSorting from GI-based
    bindings.
    
    As it turns out, GObject Introspection does not support variadic
    functions, so gom_sorting_new just isn't usable from GI-based bindings.
    
    But with this commit, GI-based bindings can now simply create a new,
    empty GomSorting object, then add their sorting clauses to it.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=752141

 gom/gom-sorting.c        |   56 +++++++++++++++++++++++++------
 gom/gom-sorting.h        |    4 ++
 tests/test-gom-sorting.c |   82 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 131 insertions(+), 11 deletions(-)
---
diff --git a/gom/gom-sorting.c b/gom/gom-sorting.c
index 81e98fe..e547589 100644
--- a/gom/gom-sorting.c
+++ b/gom/gom-sorting.c
@@ -170,17 +170,7 @@ gom_sorting_new (GType           first_resource_type,
    va_start(args, first_sorting_mode);
 
    while TRUE {
-      GomOrderByTerm *o = g_new(GomOrderByTerm, 1);
-
-      g_return_val_if_fail(g_type_is_a(resource_type, GOM_TYPE_RESOURCE),
-                           NULL);
-      g_return_val_if_fail(property_name != NULL, NULL);
-      g_return_val_if_fail(sorting_mode, NULL);
-
-      o->resource_type = resource_type;
-      o->property_name = strdup(property_name);
-      o->mode = sorting_mode;
-      g_queue_push_tail(sorting->priv->order_by_terms, o);
+      gom_sorting_add(sorting, resource_type, property_name, sorting_mode);
 
       resource_type = va_arg(args, GType);
 
@@ -197,6 +187,50 @@ gom_sorting_new (GType           first_resource_type,
 }
 
 /**
+ * gom_sorting_add:
+ * @sorting: A #GomSorting.
+ * @resource_type: A subclass of #GomResource.
+ * @property_name: A string.
+ * @sorting_mode: A #GomSortingMode.
+ *
+ * Add a new ORDER BY clause to the sorting object.
+ *
+ * This allows chaining ORDER BY clauses, adding them one at a time, rather
+ * than passing them all to the constructor.
+ *
+ * Example:
+ * |[<!-- language="C" -->
+ *     GomSorting *sorting = g_object_new (GOM_TYPE_SORTING, NULL);
+ *     gom_sorting_add (sorting, EPISODE_TYPE_RESOURCE, "season-number",
+ *                      GOM_SORTING_DESCENDING);
+ *     gom_sorting_add (sorting, EPISODE_TYPE_RESOURCE, "episode-number",
+ *                      GOM_SORTING_ASCENDING);
+ * ]|
+ *
+ * The above example maps to the following SQL statement:
+ * |[<!-- language="SQL" -->
+ *     ORDER BY 'episodes'.'season-number' DESC, 'episodes'.'episode-number'
+ * ]|
+ */
+void
+gom_sorting_add (GomSorting     *sorting,
+                 GType           resource_type,
+                 const gchar    *property_name,
+                 GomSortingMode  sorting_mode)
+{
+   GomOrderByTerm *o = g_new(GomOrderByTerm, 1);
+
+   g_return_if_fail(g_type_is_a(resource_type, GOM_TYPE_RESOURCE));
+   g_return_if_fail(property_name != NULL);
+   g_return_if_fail(sorting_mode);
+
+   o->resource_type = resource_type;
+   o->property_name = g_strdup(property_name);
+   o->mode = sorting_mode;
+   g_queue_push_tail(sorting->priv->order_by_terms, o);
+}
+
+/**
  * gom_sorting_get_sql:
  * @sorting: (in): A #GomSorting.
  * @table_map: (in): A #GHashTable.
diff --git a/gom/gom-sorting.h b/gom/gom-sorting.h
index 87fb1db..dc81a0b 100644
--- a/gom/gom-sorting.h
+++ b/gom/gom-sorting.h
@@ -62,6 +62,10 @@ GomSorting *gom_sorting_new           (GType           first_resource_type,
                                        const gchar    *first_property_name,
                                        GomSortingMode  first_sorting_mode,
                                        ...);
+void gom_sorting_add                  (GomSorting     *sorting,
+                                       GType           resource_type,
+                                       const gchar    *property_name,
+                                       GomSortingMode  sorting_mode);
 
 G_END_DECLS
 
diff --git a/tests/test-gom-sorting.c b/tests/test-gom-sorting.c
index 1e2ce3c..a20a368 100644
--- a/tests/test-gom-sorting.c
+++ b/tests/test-gom-sorting.c
@@ -441,6 +441,86 @@ find_order_by_complex (void)
 }
 
 static void
+find_order_by_complex_add (void)
+{
+   GomAdapter *adapter;
+   GomRepository *repository;
+   GomFilter *filter;
+   GomSorting *sorting;
+   GomResourceGroup *group;
+   GValue value = { 0, };
+   GError *error = NULL;
+   EpisodeResource *eres;
+   guint count;
+   gchar *id;
+   guint8 season, episode;
+
+   create_memory_db(&adapter, &repository);
+
+   /* Select only the episode for a single show */
+   g_value_init(&value, G_TYPE_STRING);
+   g_value_set_string(&value, "84947");
+   filter = gom_filter_new_eq(EPISODE_TYPE_RESOURCE, "series-id", &value);
+   g_value_unset(&value);
+
+   /* Order by season, then by episode */
+   sorting = g_object_new(GOM_TYPE_SORTING, NULL);
+   gom_sorting_add(sorting, EPISODE_TYPE_RESOURCE, "season-number",
+                   GOM_SORTING_DESCENDING);
+   gom_sorting_add(sorting, EPISODE_TYPE_RESOURCE, "episode-number",
+                   GOM_SORTING_ASCENDING);
+
+   group = gom_repository_find_sorted_sync(repository, EPISODE_TYPE_RESOURCE,
+                                           filter, sorting, &error);
+   g_assert_no_error(error);
+   g_object_unref(sorting);
+
+   count = gom_resource_group_get_count(group);
+   g_assert_cmpuint(count, ==, 4);
+
+   gom_resource_group_fetch_sync(group, 0, count, &error);
+   g_assert_no_error(error);
+
+   eres = EPISODE_RESOURCE(gom_resource_group_get_index(group, 0));
+   g_assert(eres);
+   g_object_get(eres, "series-id", &id, "season-number", &season,
+                "episode-number", &episode, NULL);
+   g_assert_cmpstr(id, ==, "84947");
+   g_assert_cmpuint(season, ==, 5);
+   g_assert_cmpuint(episode, ==, 1);
+   g_object_unref(eres);
+
+   eres = EPISODE_RESOURCE(gom_resource_group_get_index(group, 1));
+   g_assert(eres);
+   g_object_get(eres, "series-id", &id, "season-number", &season,
+                "episode-number", &episode, NULL);
+   g_assert_cmpstr(id, ==, "84947");
+   g_assert_cmpuint(season, ==, 5);
+   g_assert_cmpuint(episode, ==, 2);
+   g_object_unref(eres);
+
+   eres = EPISODE_RESOURCE(gom_resource_group_get_index(group, 2));
+   g_assert(eres);
+   g_object_get(eres, "series-id", &id, "season-number", &season,
+                "episode-number", &episode, NULL);
+   g_assert_cmpstr(id, ==, "84947");
+   g_assert_cmpuint(season, ==, 4);
+   g_assert_cmpuint(episode, ==, 1);
+   g_object_unref(eres);
+
+   eres = EPISODE_RESOURCE(gom_resource_group_get_index(group, 3));
+   g_assert(eres);
+   g_object_get(eres, "series-id", &id, "season-number", &season,
+                "episode-number", &episode, NULL);
+   g_assert_cmpstr(id, ==, "84947");
+   g_assert_cmpuint(season, ==, 4);
+   g_assert_cmpuint(episode, ==, 2);
+   g_object_unref(eres);
+
+   free_memory_db(adapter, repository);
+}
+
+static void
 find_cb (GObject      *object,
          GAsyncResult *result,
          gpointer      user_data)
@@ -547,6 +627,8 @@ main (gint argc, gchar *argv[])
    g_test_add_func("/GomRepository/find-order-by-desc", find_order_by_desc);
    g_test_add_func("/GomRepository/find-order-by-complex",
                    find_order_by_complex);
+   g_test_add_func("/GomRepository/find-order-by-complex-add",
+                   find_order_by_complex_add);
    g_test_add_func("/GomRepository/find-order-by-complex-async",
                    find_order_by_complex_async);
    gMainLoop = g_main_loop_new(NULL, FALSE);


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