[tracker/wip/carlosg/fix-minus: 2/3] libtracker-data: Fix MINUS support
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/carlosg/fix-minus: 2/3] libtracker-data: Fix MINUS support
- Date: Sat, 7 Mar 2020 14:04:31 +0000 (UTC)
commit f6f4da9c9e7839c8b30a5063c8a2f319ec43e228
Author: Carlos Garnacho <carlosg gnome org>
Date: Fri Mar 6 19:59:41 2020 +0100
libtracker-data: Fix MINUS support
We implement MINUS through sqlite's EXCEPT, which requires SELECTS on
both sides of the operation to have the same variables in the same
order. Ensure this is what happens.
One thing to note is that we do not bother checking whether new
variables are created on the right hand, as per MINUS semantics those
cannot count in the result set.
Closes: https://gitlab.gnome.org/GNOME/tracker/issues/190
src/libtracker-data/tracker-sparql.c | 68 ++++++++++++++++++++++++++++++++++--
1 file changed, 66 insertions(+), 2 deletions(-)
---
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index bcdcd52e7..51fe37acb 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -5005,16 +5005,80 @@ append_subquery_select_vars (TrackerSparql *sparql,
_append_string (sparql, "FROM (");
}
+static GList *
+intersect_var_set (GHashTable *ht1,
+ GHashTable *ht2)
+{
+ GHashTableIter iter;
+ GList *intersection = NULL;
+ gpointer key;
+
+ g_hash_table_iter_init (&iter, ht1);
+
+ while (g_hash_table_iter_next (&iter, &key, NULL)) {
+ if (g_hash_table_contains (ht2, key))
+ intersection = g_list_prepend (intersection, key);
+ }
+
+ return intersection;
+}
+
+
static gboolean
translate_MinusGraphPattern (TrackerSparql *sparql,
GError **error)
{
+ TrackerStringBuilder *pre, *post, *cur;
+ TrackerContext *cur_context, *context;
+ GList *intersection, *l;
+
+ cur_context = sparql->current_state.context;
+
/* MinusGraphPattern ::= 'MINUS' GroupGraphPattern
*/
_expect (sparql, RULE_TYPE_LITERAL, LITERAL_MINUS);
- _prepend_string (sparql, "SELECT * FROM (");
- _append_string (sparql, ") EXCEPT ");
+
+ pre = _prepend_placeholder (sparql);
+ post = _append_placeholder (sparql);
+
+ context = tracker_context_new ();
+ tracker_sparql_push_context (sparql, context);
_call_rule (sparql, NAMED_RULE_GroupGraphPattern, error);
+ tracker_sparql_pop_context (sparql, FALSE);
+
+ intersection = intersect_var_set (cur_context->variable_set, context->variable_set);
+
+ cur = tracker_sparql_swap_builder (sparql, pre);
+ append_subquery_select_vars (sparql, cur_context, intersection);
+ tracker_sparql_swap_builder (sparql, cur);
+
+ if (intersection) {
+ cur = tracker_sparql_swap_builder (sparql, post);
+ _append_string (sparql, ") WHERE (");
+ for (l = intersection; l; l = l->next) {
+ if (l != intersection)
+ _append_string (sparql, ", ");
+ _append_string_printf (sparql, "%s ",
+ tracker_variable_get_sql_expression (l->data));
+ }
+
+ _append_string (sparql, ") NOT IN (");
+ append_subquery_select_vars (sparql, context, intersection);
+
+ tracker_sparql_swap_builder (sparql, cur);
+ _append_string (sparql, ")) ");
+ } else {
+ GList *vars;
+
+ cur = tracker_sparql_swap_builder (sparql, post);
+ _append_string (sparql, ") EXCEPT ");
+ vars = g_hash_table_get_keys (cur_context->variable_set);
+ append_subquery_select_vars (sparql, context, vars);
+ g_list_free (vars);
+
+ tracker_sparql_swap_builder (sparql, cur);
+ _append_string (sparql, ") ");
+ }
return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]