summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Thursfield <sam@afuera.me.uk>2020-08-31 11:43:45 +0000
committerSam Thursfield <sam@afuera.me.uk>2020-08-31 11:43:45 +0000
commit41842f9a19e691e41393e4ce9aa19338f67a1b30 (patch)
treeff764c127f987280db93ab7b5387e13bfe114c72
parent909492e4fa90fee24516fabd2d79d0cab311e038 (diff)
parentd499d59e1dcde44af2da1059816156e4c70fba03 (diff)
downloadtracker-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.c22
-rw-r--r--src/libtracker-data/tracker-sparql-types.h2
-rw-r--r--src/libtracker-data/tracker-sparql.c92
-rw-r--r--tests/libtracker-data/tracker-sparql-test.c5
-rw-r--r--tests/libtracker-data/unbound/data.ontology19
-rw-r--r--tests/libtracker-data/unbound/data.ttl11
-rw-r--r--tests/libtracker-data/unbound/unbound-1.out1
-rw-r--r--tests/libtracker-data/unbound/unbound-1.rq1
-rw-r--r--tests/libtracker-data/unbound/unbound-2.out2
-rw-r--r--tests/libtracker-data/unbound/unbound-2.rq1
-rw-r--r--tests/libtracker-data/unbound/unbound-3.out1
-rw-r--r--tests/libtracker-data/unbound/unbound-3.rq1
-rw-r--r--tests/libtracker-data/unbound/unbound-4.out2
-rw-r--r--tests/libtracker-data/unbound/unbound-4.rq1
-rw-r--r--tests/libtracker-data/unbound/unbound-5.out0
-rw-r--r--tests/libtracker-data/unbound/unbound-5.rq1
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) }