diff options
author | Sam Thursfield <sam@afuera.me.uk> | 2020-08-31 11:43:45 +0000 |
---|---|---|
committer | Sam Thursfield <sam@afuera.me.uk> | 2020-08-31 11:43:45 +0000 |
commit | 41842f9a19e691e41393e4ce9aa19338f67a1b30 (patch) | |
tree | ff764c127f987280db93ab7b5387e13bfe114c72 | |
parent | 909492e4fa90fee24516fabd2d79d0cab311e038 (diff) | |
parent | d499d59e1dcde44af2da1059816156e4c70fba03 (diff) | |
download | tracker-41842f9a19e691e41393e4ce9aa19338f67a1b30.tar.gz |
Merge branch 'wip/carlosg/unbound-vars' into 'master'
Manage unbound vars up to the spec
See merge request GNOME/tracker!304
-rw-r--r-- | src/libtracker-data/tracker-sparql-types.c | 22 | ||||
-rw-r--r-- | src/libtracker-data/tracker-sparql-types.h | 2 | ||||
-rw-r--r-- | src/libtracker-data/tracker-sparql.c | 92 | ||||
-rw-r--r-- | tests/libtracker-data/tracker-sparql-test.c | 5 | ||||
-rw-r--r-- | tests/libtracker-data/unbound/data.ontology | 19 | ||||
-rw-r--r-- | tests/libtracker-data/unbound/data.ttl | 11 | ||||
-rw-r--r-- | tests/libtracker-data/unbound/unbound-1.out | 1 | ||||
-rw-r--r-- | tests/libtracker-data/unbound/unbound-1.rq | 1 | ||||
-rw-r--r-- | tests/libtracker-data/unbound/unbound-2.out | 2 | ||||
-rw-r--r-- | tests/libtracker-data/unbound/unbound-2.rq | 1 | ||||
-rw-r--r-- | tests/libtracker-data/unbound/unbound-3.out | 1 | ||||
-rw-r--r-- | tests/libtracker-data/unbound/unbound-3.rq | 1 | ||||
-rw-r--r-- | tests/libtracker-data/unbound/unbound-4.out | 2 | ||||
-rw-r--r-- | tests/libtracker-data/unbound/unbound-4.rq | 1 | ||||
-rw-r--r-- | tests/libtracker-data/unbound/unbound-5.out | 0 | ||||
-rw-r--r-- | tests/libtracker-data/unbound/unbound-5.rq | 1 |
16 files changed, 121 insertions, 41 deletions
diff --git a/src/libtracker-data/tracker-sparql-types.c b/src/libtracker-data/tracker-sparql-types.c index a029a275e..a638620b2 100644 --- a/src/libtracker-data/tracker-sparql-types.c +++ b/src/libtracker-data/tracker-sparql-types.c @@ -653,8 +653,7 @@ tracker_context_class_init (TrackerContextClass *klass) static void tracker_context_init (TrackerContext *context) { - context->variable_set = g_hash_table_new (tracker_variable_hash, - tracker_variable_equal); + context->variable_set = g_hash_table_new (g_str_hash, g_str_equal); } TrackerContext * @@ -684,27 +683,34 @@ void tracker_context_add_variable_ref (TrackerContext *context, TrackerVariable *variable) { - g_hash_table_add (context->variable_set, variable); + g_hash_table_insert (context->variable_set, variable->name, variable); } gboolean tracker_context_lookup_variable_ref (TrackerContext *context, TrackerVariable *variable) { - return g_hash_table_lookup (context->variable_set, variable) != NULL; + return g_hash_table_lookup (context->variable_set, variable->name) != NULL; +} + +gboolean +tracker_context_lookup_variable_by_name (TrackerContext *context, + const gchar *name) +{ + return g_hash_table_lookup (context->variable_set, name) != NULL; } void tracker_context_propagate_variables (TrackerContext *context) { GHashTableIter iter; - gpointer key; + gpointer key, value; g_assert (context->parent != NULL); g_hash_table_iter_init (&iter, context->variable_set); - while (g_hash_table_iter_next (&iter, &key, NULL)) - g_hash_table_add (context->parent->variable_set, key); + while (g_hash_table_iter_next (&iter, &key, &value)) + g_hash_table_insert (context->parent->variable_set, key, value); } /* Select context */ @@ -985,7 +991,7 @@ tracker_triple_context_get_variable_binding_list (TrackerTripleContext *context, */ if (TRACKER_IS_SELECT_CONTEXT (current_context) && tracker_context_get_parent (current_context) && - g_hash_table_lookup (parent_context->variable_set, variable)) { + g_hash_table_lookup (parent_context->variable_set, variable->name)) { TrackerVariableBinding *sample; TrackerBinding *binding; diff --git a/src/libtracker-data/tracker-sparql-types.h b/src/libtracker-data/tracker-sparql-types.h index fc79798b7..8dc551234 100644 --- a/src/libtracker-data/tracker-sparql-types.h +++ b/src/libtracker-data/tracker-sparql-types.h @@ -346,6 +346,8 @@ void tracker_context_add_variable_ref (TrackerContext *context, TrackerVariable *variable); gboolean tracker_context_lookup_variable_ref (TrackerContext *context, TrackerVariable *variable); +gboolean tracker_context_lookup_variable_by_name (TrackerContext *context, + const gchar *name); /* Select context */ GType tracker_select_context_get_type (void) G_GNUC_CONST; diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c index 5a2795af9..d372ccfc7 100644 --- a/src/libtracker-data/tracker-sparql.c +++ b/src/libtracker-data/tracker-sparql.c @@ -2672,40 +2672,53 @@ translate_SelectClause (TrackerSparql *sparql, } else { do { TrackerVariable *var; - TrackerBinding *binding; if (_check_in_rule (sparql, NAMED_RULE_Var)) { + gchar *name; + gboolean found; + if (!first) _append_string (sparql, ", "); _call_rule (sparql, NAMED_RULE_Var, error); - var = _last_node_variable (sparql); - - if (!tracker_variable_has_bindings (var)) { - _raise (PARSE, "Undefined variable", var->name); - } - - binding = TRACKER_BINDING (tracker_variable_get_sample_binding (var)); + name = _dup_last_string (sparql); str = _append_placeholder (sparql); old = tracker_sparql_swap_builder (sparql, str); - _append_string_printf (sparql, "%s ", - tracker_variable_get_sql_expression (var)); + found = tracker_context_lookup_variable_by_name (sparql->current_state.context, + name); + var = _last_node_variable (sparql); + + if (found) { + _append_string_printf (sparql, "%s ", + tracker_variable_get_sql_expression (var)); - if (sparql->current_state.select_context == sparql->context) - convert_expression_to_string (sparql, binding->data_type); + if (sparql->current_state.select_context == sparql->context) + convert_expression_to_string (sparql, sparql->current_state.expression_type); - select_context->type = binding->data_type; + select_context->type = sparql->current_state.expression_type; + } else { + _append_string (sparql, "NULL "); + select_context->type = TRACKER_PROPERTY_TYPE_UNKNOWN; + } if (_accept (sparql, RULE_TYPE_LITERAL, LITERAL_AS)) { - if (!handle_as (sparql, binding->data_type, error)) + if (!handle_as (sparql, select_context->type, error)) { + g_free (name); return FALSE; + } } else { - tracker_sparql_add_select_var (sparql, var->name, binding->data_type); + if (!found) { + _append_string_printf (sparql, "AS %s ", + tracker_variable_get_sql_expression (var)); + } + + tracker_sparql_add_select_var (sparql, name, select_context->type); } tracker_sparql_swap_builder (sparql, old); + g_free (name); } else { gboolean parens = FALSE; @@ -2990,9 +3003,6 @@ translate_SelectQuery (TrackerSparql *sparql, _call_rule (sparql, NAMED_RULE_WhereClause, error); - if (!_check_undefined_variables (sparql, TRACKER_SELECT_CONTEXT (sparql->context), error)) - return FALSE; - _call_rule (sparql, NAMED_RULE_SolutionModifier, error); tracker_sparql_swap_builder (sparql, old); @@ -5550,13 +5560,13 @@ intersect_var_set (GHashTable *ht1, { GHashTableIter iter; GList *intersection = NULL; - gpointer key; + gpointer key, value; g_hash_table_iter_init (&iter, ht1); - while (g_hash_table_iter_next (&iter, &key, NULL)) { + while (g_hash_table_iter_next (&iter, &key, &value)) { if (g_hash_table_contains (ht2, key)) - intersection = g_list_prepend (intersection, key); + intersection = g_list_prepend (intersection, value); } return intersection; @@ -5587,7 +5597,7 @@ translate_MinusGraphPattern (TrackerSparql *sparql, intersection = intersect_var_set (cur_context->variable_set, context->variable_set); - vars = g_hash_table_get_keys (cur_context->variable_set); + vars = g_hash_table_get_values (cur_context->variable_set); cur = tracker_sparql_swap_builder (sparql, pre); append_subquery_select_vars (sparql, cur_context, vars); tracker_sparql_swap_builder (sparql, cur); @@ -5654,7 +5664,7 @@ translate_GroupOrUnionGraphPattern (TrackerSparql *sparql, } } while (_accept (sparql, RULE_TYPE_LITERAL, LITERAL_UNION)); - vars = g_hash_table_get_keys (context->variable_set); + vars = g_hash_table_get_values (context->variable_set); if (placeholders->len > 1) { /* We are performing an union of multiple GroupGraphPattern, @@ -7020,14 +7030,20 @@ translate_Var (TrackerSparql *sparql, _accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_VAR2)) { if (sparql->current_state.type == TRACKER_SPARQL_TYPE_SELECT || sparql->current_state.type == TRACKER_SPARQL_TYPE_CONSTRUCT) { - TrackerVariableBinding *binding; + TrackerVariableBinding *binding = NULL; TrackerVariable *var; + gchar *name; /* Ensure the variable is referenced in the context */ - var = _extract_node_variable (sparql->current_state.prev_node, - sparql); + name = _dup_last_string (sparql); + var = tracker_select_context_lookup_variable (TRACKER_SELECT_CONTEXT (sparql->context), + name); + g_free (name); - binding = tracker_variable_get_sample_binding (var); + sparql->current_state.expression_type = TRACKER_PROPERTY_TYPE_UNKNOWN; + + if (var) + binding = tracker_variable_get_sample_binding (var); if (binding) sparql->current_state.expression_type = TRACKER_BINDING (binding)->data_type; @@ -7348,6 +7364,7 @@ translate_PrimaryExpression (TrackerSparql *sparql, TrackerGrammarNamedRule rule; TrackerBinding *binding; TrackerVariable *variable; + gchar *name; /* PrimaryExpression ::= BrackettedExpression | BuiltInCall | iriOrFunction | RDFLiteral | NumericLiteral | BooleanLiteral | Var */ @@ -7366,14 +7383,23 @@ translate_PrimaryExpression (TrackerSparql *sparql, break; case NAMED_RULE_Var: _call_rule (sparql, rule, error); - variable = _last_node_variable (sparql); - _append_variable_sql (sparql, variable); + name = _dup_last_string (sparql); - /* If the variable is bound, propagate the binding data type */ - if (tracker_variable_has_bindings (variable)) { - binding = TRACKER_BINDING (tracker_variable_get_sample_binding (variable)); - sparql->current_state.expression_type = binding->data_type; + if (tracker_context_lookup_variable_by_name (sparql->current_state.context, + name)) { + variable = _last_node_variable (sparql); + _append_variable_sql (sparql, variable); + + /* If the variable is bound, propagate the binding data type */ + if (tracker_variable_has_bindings (variable)) { + binding = TRACKER_BINDING (tracker_variable_get_sample_binding (variable)); + sparql->current_state.expression_type = binding->data_type; + } + } else { + _append_string (sparql, "NULL "); } + + g_free (name); break; case NAMED_RULE_RDFLiteral: _call_rule (sparql, rule, error); diff --git a/tests/libtracker-data/tracker-sparql-test.c b/tests/libtracker-data/tracker-sparql-test.c index ff20def91..ca36c3798 100644 --- a/tests/libtracker-data/tracker-sparql-test.c +++ b/tests/libtracker-data/tracker-sparql-test.c @@ -84,6 +84,11 @@ const TestInfo tests[] = { { "bnode/query-5", "bnode/data", FALSE }, { "bnode-coreference/query", "bnode-coreference/data", FALSE }, { "bound/bound1", "bound/data", FALSE }, + { "unbound/unbound-1", "unbound/data", FALSE }, + { "unbound/unbound-2", "unbound/data", FALSE }, + { "unbound/unbound-3", "unbound/data", FALSE }, + { "unbound/unbound-4", "unbound/data", FALSE }, + { "unbound/unbound-5", "unbound/data", FALSE }, { "construct/construct-where", "construct/data", FALSE }, { "construct/construct-pattern", "construct/data", FALSE }, { "construct/construct-with-modifiers", "construct/data", FALSE }, diff --git a/tests/libtracker-data/unbound/data.ontology b/tests/libtracker-data/unbound/data.ontology new file mode 100644 index 000000000..bd22eee3e --- /dev/null +++ b/tests/libtracker-data/unbound/data.ontology @@ -0,0 +1,19 @@ +@prefix example: <http://example.org/ns#> . +@prefix nrl: <http://tracker.api.gnome.org/ontology/v3/nrl#> . +@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . + +example: a nrl:Namespace ; + nrl:prefix "example" . + +example:A a rdfs:Class ; + rdfs:subClassOf rdfs:Resource . + +example:b a rdf:Property ; + rdfs:domain example:A ; + rdfs:range rdfs:Resource . + +example:d a rdf:Property ; + rdfs:domain example:A ; + rdfs:range rdfs:Resource . + diff --git a/tests/libtracker-data/unbound/data.ttl b/tests/libtracker-data/unbound/data.ttl new file mode 100644 index 000000000..7ee5d37d1 --- /dev/null +++ b/tests/libtracker-data/unbound/data.ttl @@ -0,0 +1,11 @@ +@prefix : <http://example.org/ns#> . + +:a1 a :A . +:a2 a :A . +:c1 a :A . +:c2 a :A . + +:a1 :b :c1 . +:c1 :d :e . +:a2 :b :c2 . +:c2 :b :f . diff --git a/tests/libtracker-data/unbound/unbound-1.out b/tests/libtracker-data/unbound/unbound-1.out new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/tests/libtracker-data/unbound/unbound-1.out @@ -0,0 +1 @@ + diff --git a/tests/libtracker-data/unbound/unbound-1.rq b/tests/libtracker-data/unbound/unbound-1.rq new file mode 100644 index 000000000..ad775ebdb --- /dev/null +++ b/tests/libtracker-data/unbound/unbound-1.rq @@ -0,0 +1 @@ +SELECT ?x { } diff --git a/tests/libtracker-data/unbound/unbound-2.out b/tests/libtracker-data/unbound/unbound-2.out new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/tests/libtracker-data/unbound/unbound-2.out @@ -0,0 +1,2 @@ + + diff --git a/tests/libtracker-data/unbound/unbound-2.rq b/tests/libtracker-data/unbound/unbound-2.rq new file mode 100644 index 000000000..fdbf6a33b --- /dev/null +++ b/tests/libtracker-data/unbound/unbound-2.rq @@ -0,0 +1 @@ +SELECT ?x { { } UNION { } }
\ No newline at end of file diff --git a/tests/libtracker-data/unbound/unbound-3.out b/tests/libtracker-data/unbound/unbound-3.out new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/tests/libtracker-data/unbound/unbound-3.out @@ -0,0 +1 @@ + diff --git a/tests/libtracker-data/unbound/unbound-3.rq b/tests/libtracker-data/unbound/unbound-3.rq new file mode 100644 index 000000000..d4c976f98 --- /dev/null +++ b/tests/libtracker-data/unbound/unbound-3.rq @@ -0,0 +1 @@ +SELECT ?x { BIND (?a AS ?x) } diff --git a/tests/libtracker-data/unbound/unbound-4.out b/tests/libtracker-data/unbound/unbound-4.out new file mode 100644 index 000000000..25cadbeeb --- /dev/null +++ b/tests/libtracker-data/unbound/unbound-4.out @@ -0,0 +1,2 @@ + +"1" diff --git a/tests/libtracker-data/unbound/unbound-4.rq b/tests/libtracker-data/unbound/unbound-4.rq new file mode 100644 index 000000000..cc3e0912b --- /dev/null +++ b/tests/libtracker-data/unbound/unbound-4.rq @@ -0,0 +1 @@ +SELECT ?x { { } UNION { BIND (1 AS ?x) } } diff --git a/tests/libtracker-data/unbound/unbound-5.out b/tests/libtracker-data/unbound/unbound-5.out new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/libtracker-data/unbound/unbound-5.out diff --git a/tests/libtracker-data/unbound/unbound-5.rq b/tests/libtracker-data/unbound/unbound-5.rq new file mode 100644 index 000000000..260e25c04 --- /dev/null +++ b/tests/libtracker-data/unbound/unbound-5.rq @@ -0,0 +1 @@ +SELECT ?x { FILTER (?x = 42) } |