diff options
-rw-r--r-- | src/libtracker-data/tracker-sparql.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c index 06c4bb45c..6a914f255 100644 --- a/src/libtracker-data/tracker-sparql.c +++ b/src/libtracker-data/tracker-sparql.c @@ -4501,6 +4501,66 @@ iterate_solution (TrackerSparql *sparql, } static gboolean +check_idempotent_delete (TrackerSparql *sparql, + TrackerParserNode *pattern, + TrackerParserNode *end) +{ + TrackerDBInterface *iface; + TrackerParserNode *node, *subject; + gint n_triples = 0; + gboolean skip = FALSE; + gchar *subject_str; + + /* Look for idempotent delete operations (those that don't change + * the RDF graph) or the easy ones at least. If the quad pattern + * consists of a single triple graph, the subject is an IRI, and + * we know it does not exist yet, we can avoid the busywork. + */ + for (node = tracker_sparql_parser_tree_find_first (pattern, FALSE); + node; + node = tracker_sparql_parser_tree_find_next (node, FALSE)) { + const TrackerGrammarRule *rule; + + if (node == end) + break; + + rule = tracker_parser_node_get_rule (node); + if (tracker_grammar_rule_is_a (rule, RULE_TYPE_RULE, + NAMED_RULE_TriplesTemplate)) + n_triples++; + + if (n_triples > 1) { + skip = FALSE; + break; + } + + if (!tracker_grammar_rule_is_a (rule, RULE_TYPE_RULE, + NAMED_RULE_TriplesSameSubject)) + continue; + + /* Find subject */ + subject = tracker_sparql_parser_tree_find_first (node, TRUE); + + /* If it's not an IRI, bail out */ + rule = tracker_parser_node_get_rule (subject); + if (!tracker_grammar_rule_is_a (rule, RULE_TYPE_TERMINAL, + TERMINAL_TYPE_IRIREF)) + continue; + + subject_str = _extract_node_string (subject, sparql); + iface = tracker_data_manager_get_writable_db_interface (sparql->data_manager); + skip = tracker_data_query_resource_id (sparql->data_manager, + iface, subject_str) == 0; + g_free (subject_str); + + if (!skip) + break; + } + + return skip; +} + +static gboolean translate_DeleteWhere (TrackerSparql *sparql, GError **error) { @@ -4515,6 +4575,10 @@ translate_DeleteWhere (TrackerSparql *sparql, quad_pattern = _skip_rule (sparql, NAMED_RULE_QuadPattern); + if (check_idempotent_delete (sparql, quad_pattern, + sparql->current_state->node)) + return TRUE; + /* 'DELETE WHERE' uses the same pattern for both query and update */ solution = get_solution_for_pattern (sparql, quad_pattern, error); if (!solution) |