示例#1
0
void
gom_resource_save_async (GomResource         *resource,
                         GAsyncReadyCallback  callback,
                         gpointer             user_data)
{
   GomResourcePrivate *priv;
   GSimpleAsyncResult *simple;
   GomAdapter *adapter;

   g_return_if_fail(GOM_IS_RESOURCE(resource));
   g_return_if_fail(callback != NULL);

   priv = resource->priv;

   if (!priv->repository) {
      g_warning("Cannot save resource, no repository set!");
      return;
   }

   simple = g_simple_async_result_new(G_OBJECT(resource), callback, user_data,
                                      gom_resource_save_async);
   adapter = gom_repository_get_adapter(priv->repository);
   g_assert(GOM_IS_ADAPTER(adapter));
   gom_resource_build_save_cmd(resource, adapter);
   gom_adapter_queue_write(adapter, gom_resource_save_cb, simple);
}
示例#2
0
static void
gom_resource_save_cb (GomAdapter *adapter,
                      gpointer    user_data)
{
   GSimpleAsyncResult *simple = user_data;
   GomResource *resource;
   gboolean ret;
   GError *error = NULL;
   GAsyncQueue *queue;

   g_return_if_fail(GOM_IS_ADAPTER(adapter));
   g_return_if_fail(G_IS_SIMPLE_ASYNC_RESULT(simple));

   resource = GOM_RESOURCE(g_async_result_get_source_object(G_ASYNC_RESULT(simple)));
   g_assert(GOM_IS_RESOURCE(resource));

   queue = g_object_get_data(G_OBJECT(simple), "queue");

   if (!(ret = gom_resource_do_save(resource, adapter, &error))) {
      g_simple_async_result_take_error(simple, error);
   }

   g_simple_async_result_set_op_res_gboolean(simple, ret);
   if (!queue)
      g_simple_async_result_complete_in_idle(simple);
   else
      g_async_queue_push(queue, GINT_TO_POINTER(TRUE));
   g_object_unref(resource);
}
示例#3
0
static gboolean
gom_resource_do_delete (GomResource  *resource,
                        GomAdapter   *adapter,
                        GError      **error)
{
   GomCommandBuilder *builder;
   GType resource_type;

   g_return_val_if_fail(GOM_IS_RESOURCE(resource), FALSE);
   g_return_val_if_fail(GOM_IS_ADAPTER(adapter), FALSE);

   resource_type = G_TYPE_FROM_INSTANCE(resource);
   builder = g_object_new(GOM_TYPE_COMMAND_BUILDER,
                          "adapter", adapter,
                          NULL);

   do {
      GomResourceClass *klass;
      GParamSpec *pspec;
      GomCommand *command;
      GomFilter *filter;
      GArray *values;
      GValue value = { 0 };
      gchar *sql;

      klass = g_type_class_peek(resource_type);
      g_assert(GOM_IS_RESOURCE_CLASS(klass));

      pspec = g_object_class_find_property(G_OBJECT_CLASS(klass),
                                           klass->primary_key);
      g_assert(pspec);

      g_value_init(&value, pspec->value_type);
      g_object_get_property(G_OBJECT(resource), klass->primary_key, &value);
      sql = g_strdup_printf("'%s'.'%s' = ?", klass->table, klass->primary_key);
      values = g_array_sized_new(FALSE, FALSE, sizeof(GValue), 1);
      g_array_append_val(values, value);
      filter = gom_filter_new_sql(sql, values);
      g_free(sql);
      memset(&value, 0, sizeof value);
      g_array_unref(values);
      g_object_set(builder,
                   "filter", filter,
                   "resource-type", resource_type,
                   NULL);
      g_object_unref(filter);

      command = gom_command_builder_build_delete(builder);
      if (!gom_command_execute(command, NULL, error)) {
         g_object_unref(command);
         g_object_unref(builder);
         return FALSE;
      }
      g_object_unref(command);
   } while ((resource_type = g_type_parent(resource_type)) != GOM_TYPE_RESOURCE);

   g_object_unref(builder);

   return TRUE;
}
示例#4
0
gboolean
gom_resource_do_save (GomResource  *resource,
                      GomAdapter   *adapter,
                      GError      **error)
{
   gboolean ret = FALSE;
   gboolean is_insert;
   gint64 row_id = -1;
   GType resource_type;
   GList *cmds, *l;

   g_return_val_if_fail(GOM_IS_RESOURCE(resource), FALSE);
   g_return_val_if_fail(GOM_IS_ADAPTER(adapter), FALSE);

   resource_type = G_TYPE_FROM_INSTANCE(resource);
   g_assert(g_type_is_a(resource_type, GOM_TYPE_RESOURCE));

   is_insert = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(resource), "is-insert"));
   cmds = g_object_get_data(G_OBJECT(resource), "save-commands");

   for (l = cmds; l != NULL; l = l->next) {
      GomCommand *command = l->data;

      if (!gom_command_execute(command, NULL, error))
         goto out;

      if (is_insert && row_id == -1 && gom_resource_has_dynamic_pkey(resource_type)) {
         sqlite3 *handle = gom_adapter_get_handle(adapter);
         GValue *value;

         row_id = sqlite3_last_insert_rowid(handle);
         value = g_new0 (GValue, 1);
         g_value_init(value, G_TYPE_INT64);
         g_value_set_int64(value, row_id);
         g_object_set_data_full(G_OBJECT(resource), "row-id", value, value_free);

         g_object_set_data (G_OBJECT(resource), "is-from-table", GINT_TO_POINTER(TRUE));

         is_insert = FALSE;
      }
   }

   ret = TRUE;

out:
   g_object_set_data (G_OBJECT (resource), "save-commands", NULL);
   g_object_set_data (G_OBJECT (resource), "is-insert", NULL);

   return ret;
}
static void
gom_repository_set_adapter (GomRepository *repository,
                            GomAdapter    *adapter)
{
   GomRepositoryPrivate *priv;

   g_return_if_fail(GOM_IS_REPOSITORY(repository));
   g_return_if_fail(GOM_IS_ADAPTER(adapter));

   priv = repository->priv;

   g_clear_object(&priv->adapter);
   priv->adapter = g_object_ref(adapter);
   g_object_notify_by_pspec(G_OBJECT(repository), gParamSpecs[PROP_ADAPTER]);
}
示例#6
0
/**
 * gom_resource_save_sync:
 * @resource: (in): A #GomResource.
 * @error: (out): A location for a #GError, or %NULL.
 *
 * Returns: %TRUE if successful; otherwise %FALSE.
 */
gboolean
gom_resource_save_sync (GomResource  *resource,
                        GError      **error)
{
   GomResourcePrivate *priv;
   GomAdapter *adapter;
   GAsyncQueue *queue;
   GSimpleAsyncResult *simple;
   gboolean ret;

   g_return_val_if_fail(GOM_IS_RESOURCE(resource), FALSE);

   priv = resource->priv;

   if (!priv->repository) {
      g_set_error(error, GOM_ERROR, GOM_ERROR_COMMAND_NO_REPOSITORY,
                  _("Cannot save resource, no repository set"));
      return FALSE;
   }

   queue = g_async_queue_new();

   simple = g_simple_async_result_new(G_OBJECT(resource), NULL, NULL,
                                      gom_resource_save_sync);
   adapter = gom_repository_get_adapter(priv->repository);
   g_object_set_data(G_OBJECT(simple), "queue", queue);
   g_assert(GOM_IS_ADAPTER(adapter));

   gom_resource_build_save_cmd(resource, adapter);

   gom_adapter_queue_write(adapter, gom_resource_save_cb, simple);
   g_async_queue_pop(queue);
   g_async_queue_unref(queue);

   if (!(ret = g_simple_async_result_get_op_res_gboolean(simple))) {
      g_simple_async_result_propagate_error(simple, error);
   }

   if (ret)
      set_post_save_properties(resource);

   g_object_unref(simple);

   return ret;
}
示例#7
0
void
gom_resource_fetch_m2m_async (GomResource          *resource,
                              GType                 resource_type,
                              const gchar          *m2m_table,
                              GomFilter            *filter,
                              GAsyncReadyCallback   callback,
                              gpointer              user_data)
{
   GSimpleAsyncResult *simple;
   GomRepository *repository;
   GomAdapter *adapter;

   g_return_if_fail(GOM_IS_RESOURCE(resource));
   g_return_if_fail(g_type_is_a(resource_type, GOM_TYPE_RESOURCE));
   g_return_if_fail(m2m_table != NULL);
   g_return_if_fail(callback != NULL);

   repository = gom_resource_get_repository(resource);
   g_assert(GOM_IS_REPOSITORY(repository));

   adapter = gom_repository_get_adapter(repository);
   g_assert(GOM_IS_ADAPTER(adapter));

   simple = g_simple_async_result_new(G_OBJECT(resource), callback, user_data,
                                      gom_resource_fetch_m2m_async);
   g_object_set_data(G_OBJECT(simple), "resource-type",
                     GINT_TO_POINTER(resource_type));
   g_object_set_data_full(G_OBJECT(simple), "m2m-table",
                          g_strdup(m2m_table), g_free);
   if (filter) {
      g_object_set_data_full(G_OBJECT(simple), "filter",
                             g_object_ref(filter), g_object_unref);
   }

   gom_adapter_queue_read(adapter,
                          gom_resource_fetch_m2m_cb,
                          simple);
}
static void
gom_repository_find_cb (GomAdapter *adapter,
                        gpointer    user_data)
{
   GSimpleAsyncResult *simple = user_data;
   GomCommandBuilder *builder = NULL;
   GomResourceGroup *ret;
   GomRepository *repository = NULL;
   GomCommand *command;
   GomCursor *cursor;
   GomFilter *filter;
   GError *error = NULL;
   GType resource_type;
   GAsyncQueue *queue;
   guint count;

   g_return_if_fail(GOM_IS_ADAPTER(adapter));
   g_return_if_fail(G_IS_SIMPLE_ASYNC_RESULT(simple));

   repository = GOM_REPOSITORY(g_async_result_get_source_object(G_ASYNC_RESULT(simple)));
   g_assert(GOM_IS_REPOSITORY(repository));

   resource_type = GPOINTER_TO_SIZE(g_object_get_data(G_OBJECT(simple),
                                                     "resource-type"));
   g_assert(g_type_is_a(resource_type, GOM_TYPE_RESOURCE));

   filter = g_object_get_data(G_OBJECT(simple), "filter");
   g_assert(!filter || GOM_IS_FILTER(filter));

   queue = g_object_get_data(G_OBJECT(simple), "queue");

   builder = g_object_new(GOM_TYPE_COMMAND_BUILDER,
                          "adapter", adapter,
                          "resource-type", resource_type,
                          "filter", filter,
                          NULL);

   command = gom_command_builder_build_count(builder);
   g_assert(GOM_IS_COMMAND(command));

   if (!gom_command_execute(command, &cursor, &error)) {
      g_simple_async_result_take_error(simple, error);
      goto out;
   }

   g_assert(GOM_IS_CURSOR(cursor));
   if (!gom_cursor_next(cursor)) {
      g_assert_not_reached();
      goto out;
   }

   count = gom_cursor_get_column_uint(cursor, 0);
   ret = g_object_new(GOM_TYPE_RESOURCE_GROUP,
                      "adapter", adapter,
                      "count", count,
                      "filter", filter,
                      "repository", repository,
                      "resource-type", resource_type,
                      NULL);
   g_simple_async_result_set_op_res_gpointer(simple, ret, g_object_unref);

out:
   if (!queue)
      g_simple_async_result_complete_in_idle(simple);
   else
      g_async_queue_push(queue, GINT_TO_POINTER(TRUE));
   g_object_unref(repository);
   g_clear_object(&cursor);
   g_clear_object(&command);
   g_clear_object(&builder);
}
static void
gom_repository_migrate_cb (GomAdapter *adapter,
                           gpointer    user_data)
{
   GomRepositoryMigrator migrator;
   GSimpleAsyncResult *simple = user_data;
   GomRepository *repository;
   GomCommand *command = NULL;
   gpointer migrate_data;
   GError *error = NULL;
   guint current;
   guint i;
   guint version;
   GAsyncQueue *queue;

   g_return_if_fail(GOM_IS_ADAPTER(adapter));
   g_return_if_fail(G_IS_SIMPLE_ASYNC_RESULT(simple));

   repository = GOM_REPOSITORY(g_async_result_get_source_object(G_ASYNC_RESULT(simple)));
   version = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(simple), "version"));
   migrator = g_object_get_data(G_OBJECT(simple), "migrator");
   migrate_data = g_object_get_data(G_OBJECT(simple), "migrator_data");
   queue = g_object_get_data(G_OBJECT(simple), "queue");

   g_assert(GOM_IS_REPOSITORY(repository));
   g_assert_cmpint(version, >, 0);
   g_assert(migrator != NULL);

   if (-1 == (current = gom_repository_query_version(repository, &error))) {
      g_warning("Failed to determine schema version: %s", error->message);
      goto error;
   }

   if (version == current) {
      g_simple_async_result_set_op_res_gboolean(simple, TRUE);
      goto out;
   }

   EXECUTE_OR_GOTO(adapter, "PRAGMA synchronous = NORMAL;", &error, rollback);
   EXECUTE_OR_GOTO(adapter, "PRAGMA journal_mode = PERSIST;", &error, rollback);

   EXECUTE_OR_GOTO(adapter, "BEGIN;", &error, rollback);

   for (i = MAX(current, 1); i <= version; i++) {
      if (!migrator(repository, adapter, i, migrate_data, &error)) {
         if (!error)
           g_warning ("Migration function failed without returning a error");
         goto rollback;
      }
      command = g_object_new(GOM_TYPE_COMMAND,
                             "adapter", adapter,
                             "sql", "INSERT INTO _gom_version ("
                                    " version"
                                    ") VALUES (?);",
                             NULL);
      gom_command_set_param_uint(command, 0, i);
      if (!gom_command_execute(command, NULL, &error)) {
         g_object_unref(command);
         goto rollback;
      }
      g_object_unref(command);
   }

   EXECUTE_OR_GOTO(adapter, "COMMIT;", &error, rollback);

   g_simple_async_result_set_op_res_gboolean(simple, TRUE);
   goto out;

rollback:
   EXECUTE_OR_GOTO(adapter, "ROLLBACK;", NULL, error);

error:
   g_assert(error);
   g_simple_async_result_take_error(simple, error);

out:
   g_object_unref(repository);
   if (!queue)
      g_simple_async_result_complete_in_idle(simple);
   else
      g_async_queue_push(queue, GINT_TO_POINTER(TRUE));
}
示例#10
0
static void
gom_resource_fetch_m2m_cb (GomAdapter *adapter,
                           gpointer    user_data)
{
   GSimpleAsyncResult *simple = user_data;
   GomCommandBuilder *builder = NULL;
   GomResourceGroup *group;
   GomRepository *repository;
   const gchar *m2m_table;
   GomResource *resource;
   GomCommand *command = NULL;
   GomCursor *cursor = NULL;
   GomFilter *filter = NULL;
   GError *error = NULL;
   guint count = 0;
   GType resource_type;

   g_return_if_fail(GOM_IS_ADAPTER(adapter));
   g_return_if_fail(G_IS_SIMPLE_ASYNC_RESULT(simple));

   m2m_table = g_object_get_data(G_OBJECT(simple), "m2m-table");
   resource_type = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(simple),
                                                     "resource-type"));
   filter = g_object_get_data(G_OBJECT(simple), "filter");
   resource = GOM_RESOURCE(g_async_result_get_source_object(G_ASYNC_RESULT(simple)));
   repository = gom_resource_get_repository(resource);

   g_assert(GOM_IS_RESOURCE(resource));
   g_assert(m2m_table);
   g_assert(g_type_is_a(resource_type, GOM_TYPE_RESOURCE));
   g_assert(!filter || GOM_IS_FILTER(filter));
   g_assert(GOM_IS_REPOSITORY(repository));

   builder = g_object_new(GOM_TYPE_COMMAND_BUILDER,
                          "adapter", adapter,
                          "filter", filter,
                          "resource-type", resource_type,
                          "m2m-table", m2m_table,
                          "m2m-type", G_TYPE_FROM_INSTANCE(resource),
                          NULL);

   command = gom_command_builder_build_count(builder);

   if (!gom_command_execute(command, &cursor, &error)) {
      g_simple_async_result_take_error(simple, error);
      goto out;
   }

   if (!gom_cursor_next(cursor)) {
      g_simple_async_result_set_error(simple, GOM_ERROR,
                                      GOM_ERROR_RESOURCE_CURSOR,
                                      _("No result was returned from the cursor."));
      goto out;
   }

   count = gom_cursor_get_column_int64(cursor, 0);
   group = g_object_new(GOM_TYPE_RESOURCE_GROUP,
                        "count", count,
                        "filter", filter,
                        "m2m-table", m2m_table,
                        "m2m-type", G_TYPE_FROM_INSTANCE(resource),
                        "repository", repository,
                        "resource-type", resource_type,
                        NULL);

   g_simple_async_result_set_op_res_gpointer(simple, group, g_object_unref);

out:
   g_object_unref(resource);
   g_clear_object(&command);
   g_clear_object(&cursor);
   g_clear_object(&builder);

   g_simple_async_result_complete_in_idle(simple);
   g_object_unref(simple);
}