summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2020-08-29 14:28:08 +0200
committerCarlos Garnacho <carlosg@gnome.org>2020-08-30 23:26:23 +0200
commitfc69eaa2d7825cce696541f6824021df00593b32 (patch)
treecc42282345f74e9efbe868448cf84c11d1341d59
parent97474303800141fbd4db71d91684474dc32cbba0 (diff)
downloadtracker-fc69eaa2d7825cce696541f6824021df00593b32.tar.gz
libtracker-data: Handle unbound variables in resultsets
We error out on undefined variables, SPARQL 1.1 does not seem to have a problem with that, and e.g. https://www.w3.org/TR/sparql11-query/#emptyGroupPattern specifically says this query is valid: SELECT ?x WHERE { } Soften our restriction so these queries work as specified in the docs.
-rw-r--r--src/libtracker-data/tracker-sparql.c82
1 files changed, 54 insertions, 28 deletions
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index 91382f5db..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);
@@ -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);