summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2021-04-12 01:18:00 +0200
committerCarlos Garnacho <carlosg@gnome.org>2021-04-12 11:06:37 +0200
commit3d7aede37569eae215046a8311de8879b3b84707 (patch)
treea78e3abf1b8a56bbaf737832f0bc34968791ef8e
parent3ffe21d9e0274fe3596f9bc9ae2a0cc6539e7d5d (diff)
downloadtracker-3d7aede37569eae215046a8311de8879b3b84707.tar.gz
libtracker-data: Handle relational expressions with arbitrary datetimes
This had some holes, since we can store datetimes in 2 different formats (unix timestamps and iso8601 datetime strings), but rely on direct comparisons for all data types inside FILTER(). Detect date/time comparisons, and use the resulting SparqlTimeSort() to compare the values on both sides of the relational expression, this takes care of evening out the format and timezone differences so we can compare all timestamps.
-rw-r--r--src/libtracker-data/tracker-sparql.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index 6d83ae315..cafe87e6b 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -151,6 +151,7 @@ typedef struct
gboolean convert_to_string;
gboolean in_property_function;
+ gboolean in_relational_expression;
} TrackerSparqlState;
struct _TrackerSparql
@@ -7372,12 +7373,19 @@ static gboolean
translate_RelationalExpression (TrackerSparql *sparql,
GError **error)
{
+ TrackerStringBuilder *str, *old;
const gchar *old_sep;
- gboolean bool_op = TRUE;
+ gboolean in_relational_expression, bool_op = TRUE;
/* RelationalExpression ::= NumericExpression ( '=' NumericExpression | '!=' NumericExpression | '<' NumericExpression | '>' NumericExpression | '<=' NumericExpression | '>=' NumericExpression | 'IN' ExpressionList | 'NOT' 'IN' ExpressionList )?
*/
+ str = _append_placeholder (sparql);
+ old = tracker_sparql_swap_builder (sparql, str);
_call_rule (sparql, NAMED_RULE_NumericExpression, error);
+ tracker_sparql_swap_builder (sparql, old);
+
+ in_relational_expression = sparql->current_state->in_relational_expression;
+ sparql->current_state->in_relational_expression = TRUE;
if (_accept (sparql, RULE_TYPE_LITERAL, LITERAL_OP_IN)) {
_append_string (sparql, "IN ");
@@ -7410,12 +7418,24 @@ translate_RelationalExpression (TrackerSparql *sparql,
_call_rule (sparql, NAMED_RULE_NumericExpression, error);
} else {
/* This is an unary expression */
+ sparql->current_state->in_relational_expression = FALSE;
bool_op = FALSE;
}
+ if (sparql->current_state->in_relational_expression &&
+ (sparql->current_state->expression_type == TRACKER_PROPERTY_TYPE_DATE ||
+ sparql->current_state->expression_type == TRACKER_PROPERTY_TYPE_DATETIME)) {
+ old = tracker_sparql_swap_builder (sparql, str);
+ _prepend_string (sparql, "SparqlTimeSort(");
+ _append_string (sparql, ") ");
+ tracker_sparql_swap_builder (sparql, old);
+ }
+
if (bool_op)
sparql->current_state->expression_type = TRACKER_PROPERTY_TYPE_BOOLEAN;
+ sparql->current_state->in_relational_expression = in_relational_expression;
+
return TRUE;
}
@@ -7555,6 +7575,8 @@ translate_PrimaryExpression (TrackerSparql *sparql,
TrackerGrammarNamedRule rule;
TrackerBinding *binding;
TrackerVariable *variable;
+ TrackerStringBuilder *str, *old;
+ gboolean is_datetime_comparison = FALSE;
gchar *name;
/* PrimaryExpression ::= BrackettedExpression | BuiltInCall | iriOrFunction | RDFLiteral | NumericLiteral | BooleanLiteral | Var
@@ -7562,6 +7584,9 @@ translate_PrimaryExpression (TrackerSparql *sparql,
rule = _current_rule (sparql);
select_context = TRACKER_SELECT_CONTEXT (sparql->context);
+ str = _append_placeholder (sparql);
+ old = tracker_sparql_swap_builder (sparql, str);
+
switch (rule) {
case NAMED_RULE_NumericLiteral:
case NAMED_RULE_BooleanLiteral:
@@ -7576,6 +7601,11 @@ translate_PrimaryExpression (TrackerSparql *sparql,
_call_rule (sparql, rule, error);
name = _dup_last_string (sparql);
+ is_datetime_comparison =
+ (sparql->current_state->in_relational_expression &&
+ (sparql->current_state->expression_type == TRACKER_PROPERTY_TYPE_DATE ||
+ sparql->current_state->expression_type == TRACKER_PROPERTY_TYPE_DATETIME));
+
if (tracker_context_lookup_variable_by_name (sparql->current_state->context,
name)) {
variable = _last_node_variable (sparql);
@@ -7596,6 +7626,13 @@ translate_PrimaryExpression (TrackerSparql *sparql,
_call_rule (sparql, rule, error);
binding = g_ptr_array_index (select_context->literal_bindings,
select_context->literal_bindings->len - 1);
+ sparql->current_state->expression_type = binding->data_type;
+
+ is_datetime_comparison =
+ (sparql->current_state->in_relational_expression &&
+ (binding->data_type == TRACKER_PROPERTY_TYPE_DATE ||
+ binding->data_type == TRACKER_PROPERTY_TYPE_DATETIME));
+
_append_literal_sql (sparql, TRACKER_LITERAL_BINDING (binding));
break;
case NAMED_RULE_BrackettedExpression:
@@ -7607,6 +7644,13 @@ translate_PrimaryExpression (TrackerSparql *sparql,
g_assert_not_reached ();
}
+ if (is_datetime_comparison) {
+ _prepend_string (sparql, "SparqlTimeSort(");
+ _append_string (sparql, ") ");
+ }
+
+ tracker_sparql_swap_builder (sparql, old);
+
return TRUE;
}