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); }
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); }
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; }
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]); }
/** * 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; }
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)); }
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); }