diff options
author | Sam Thursfield <sam@afuera.me.uk> | 2019-10-02 23:56:34 +0200 |
---|---|---|
committer | Sam Thursfield <sam@afuera.me.uk> | 2019-10-03 00:44:40 +0200 |
commit | 6cf094ecdef9f66aab5d08f2adfa65185fa36046 (patch) | |
tree | fb8f37ec05c30384c3ec3f1f861af6740cb82c84 | |
parent | 7f0776026548e5e000d28ecfe048ed4bdd7ebcf4 (diff) | |
download | tracker-6cf094ecdef9f66aab5d08f2adfa65185fa36046.tar.gz |
libtracker-sparql: Generate DELETEs for relations inside arrays
When a TrackerResource is serialized to SPARQL, we generate a series of
DELETE {} INSERT {} statements. For every single-value properties whose
value we set, we need to delete its value first. (Otherwise we might see
"Unable to insert multiple values" errors).
The tracker_resource_print_sparql() function was not generating the
DELETE statements for relations if there were multiple relations for
a single property.
This indirectly led to https://gitlab.gnome.org/GNOME/tracker/issues/154
and https://gitlab.gnome.org/GNOME/tracker/issues/121
-rw-r--r-- | src/libtracker-sparql/tracker-resource.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/src/libtracker-sparql/tracker-resource.c b/src/libtracker-sparql/tracker-resource.c index 059289b78..8f69be646 100644 --- a/src/libtracker-sparql/tracker-resource.c +++ b/src/libtracker-sparql/tracker-resource.c @@ -1308,13 +1308,23 @@ generate_sparql_relation_deletes_foreach (gpointer key, { const GValue *value = value_ptr; GenerateSparqlData *data = user_data; + int i; if (G_VALUE_HOLDS (value, TRACKER_TYPE_RESOURCE)) { TrackerResource *relation = g_value_get_object (value); - if (g_list_find_custom (data->done_list, relation, (GCompareFunc) tracker_resource_compare) == NULL) { - data->done_list = g_list_prepend (data->done_list, relation); - generate_sparql_deletes (relation, data); + generate_sparql_deletes (relation, data); + } else if (G_VALUE_HOLDS (value, G_TYPE_PTR_ARRAY)) { + GPtrArray *array = g_value_get_boxed (value); + + for (i = 0; i < array->len; i ++) { + GValue *value = g_ptr_array_index (array, i); + + if (G_VALUE_HOLDS (value, TRACKER_TYPE_RESOURCE)) { + TrackerResource *relation = g_value_get_object (value); + + generate_sparql_deletes (relation, data); + } } } } @@ -1419,6 +1429,12 @@ generate_sparql_deletes (TrackerResource *resource, { TrackerResourcePrivate *priv = GET_PRIVATE (resource); + if (g_list_find_custom (data->done_list, resource, (GCompareFunc) tracker_resource_compare) != NULL) + /* We already processed this resource. */ + return; + + data->done_list = g_list_prepend (data->done_list, resource); + if (! is_blank_node (priv->identifier) && g_hash_table_size (priv->overwrite) > 0) { generate_sparql_delete_queries (resource, priv->overwrite, data); } @@ -1520,7 +1536,7 @@ tracker_resource_print_sparql_update (TrackerResource *resource, /* Resources can be recursive, and may have repeated or even cyclic * relationships. This list keeps track of what we already processed. */ - context.done_list = g_list_prepend (NULL, resource); + context.done_list = NULL; /* Delete the existing data. If we don't do this, we may get constraint * violations due to trying to add a second value to a single-valued |