summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2018-10-14 11:23:35 +0200
committerCarlos Garnacho <carlosg@gnome.org>2018-11-13 11:17:31 +0100
commitc7c173f4c231c797b2eddebc1cf1a601b08c2e26 (patch)
tree87546db7711add670143ad0b4ceede389b79da67
parent4e7ca8ee05a7d4d34a4c83faa50bbeca5f8ad756 (diff)
downloadtracker-c7c173f4c231c797b2eddebc1cf1a601b08c2e26.tar.gz
libtracker-data: Support parameter bindings
Those relate to PARAMETERIZED_VAR, and allow binding values through it at query preparation time.
-rw-r--r--src/libtracker-data/tracker-data-query.c2
-rw-r--r--src/libtracker-data/tracker-sparql-types.c69
-rw-r--r--src/libtracker-data/tracker-sparql-types.h31
-rw-r--r--src/libtracker-data/tracker-sparql.c114
-rw-r--r--src/libtracker-data/tracker-sparql.h1
-rw-r--r--src/libtracker-direct/tracker-direct.c2
6 files changed, 199 insertions, 20 deletions
diff --git a/src/libtracker-data/tracker-data-query.c b/src/libtracker-data/tracker-data-query.c
index aebfacf61..2694d6d0b 100644
--- a/src/libtracker-data/tracker-data-query.c
+++ b/src/libtracker-data/tracker-data-query.c
@@ -176,7 +176,7 @@ tracker_data_query_sparql_cursor (TrackerDataManager *manager,
sparql_query = tracker_sparql_new (manager, query);
- cursor = tracker_sparql_execute_cursor (sparql_query, error);
+ cursor = tracker_sparql_execute_cursor (sparql_query, NULL, error);
g_object_unref (sparql_query);
diff --git a/src/libtracker-data/tracker-sparql-types.c b/src/libtracker-data/tracker-sparql-types.c
index d48ed886e..1c6125f0f 100644
--- a/src/libtracker-data/tracker-sparql-types.c
+++ b/src/libtracker-data/tracker-sparql-types.c
@@ -25,7 +25,8 @@
enum {
TOKEN_TYPE_NONE,
TOKEN_TYPE_LITERAL,
- TOKEN_TYPE_VARIABLE
+ TOKEN_TYPE_VARIABLE,
+ TOKEN_TYPE_PARAMETER,
};
/* Helper structs */
@@ -189,10 +190,20 @@ tracker_token_variable_init (TrackerToken *token,
}
void
+tracker_token_parameter_init (TrackerToken *token,
+ const gchar *parameter)
+{
+ token->type = TOKEN_TYPE_PARAMETER;
+ token->content.parameter = g_strdup (parameter);
+}
+
+void
tracker_token_unset (TrackerToken *token)
{
if (token->type == TOKEN_TYPE_LITERAL)
g_clear_pointer (&token->content.literal, g_free);
+ else if (token->type == TOKEN_TYPE_PARAMETER)
+ g_clear_pointer (&token->content.parameter, g_free);
token->type = TOKEN_TYPE_NONE;
}
@@ -219,6 +230,14 @@ tracker_token_get_variable (TrackerToken *token)
}
const gchar *
+tracker_token_get_parameter (TrackerToken *token)
+{
+ if (token->type == TOKEN_TYPE_PARAMETER)
+ return token->content.parameter;
+ return NULL;
+}
+
+const gchar *
tracker_token_get_idstring (TrackerToken *token)
{
if (token->type == TOKEN_TYPE_LITERAL)
@@ -419,6 +438,45 @@ tracker_literal_binding_new (const gchar *literal,
return binding;
}
+/* Parameter binding */
+G_DEFINE_TYPE (TrackerParameterBinding, tracker_parameter_binding, TRACKER_TYPE_LITERAL_BINDING)
+
+static void
+tracker_parameter_binding_finalize (GObject *object)
+{
+ TrackerParameterBinding *binding = TRACKER_PARAMETER_BINDING (object);
+
+ g_free (binding->name);
+
+ G_OBJECT_CLASS (tracker_parameter_binding_parent_class)->finalize (object);
+}
+
+static void
+tracker_parameter_binding_class_init (TrackerParameterBindingClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = tracker_parameter_binding_finalize;
+}
+
+static void
+tracker_parameter_binding_init (TrackerParameterBinding *binding)
+{
+}
+
+TrackerBinding *
+tracker_parameter_binding_new (const gchar *name,
+ TrackerDataTable *table)
+{
+ TrackerBinding *binding;
+
+ binding = g_object_new (TRACKER_TYPE_PARAMETER_BINDING, NULL);
+ binding->table = table;
+ TRACKER_PARAMETER_BINDING (binding)->name = g_strdup (name);
+
+ return binding;
+}
+
/* Variable binding */
G_DEFINE_TYPE (TrackerVariableBinding, tracker_variable_binding, TRACKER_TYPE_BINDING)
@@ -593,6 +651,15 @@ tracker_select_context_new (void)
}
TrackerVariable *
+tracker_select_context_lookup_variable (TrackerSelectContext *context,
+ const gchar *name)
+{
+ if (!context->variables)
+ return NULL;
+ return g_hash_table_lookup (context->variables, name);
+}
+
+TrackerVariable *
tracker_select_context_ensure_variable (TrackerSelectContext *context,
const gchar *name)
{
diff --git a/src/libtracker-data/tracker-sparql-types.h b/src/libtracker-data/tracker-sparql-types.h
index 6fdd0cbe7..1df06764c 100644
--- a/src/libtracker-data/tracker-sparql-types.h
+++ b/src/libtracker-data/tracker-sparql-types.h
@@ -31,6 +31,10 @@
#define TRACKER_LITERAL_BINDING(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_LITERAL_BINDING, TrackerLiteralBinding))
#define TRACKER_IS_LITERAL_BINDING(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_LITERAL_BINDING))
+#define TRACKER_TYPE_PARAMETER_BINDING (tracker_parameter_binding_get_type ())
+#define TRACKER_PARAMETER_BINDING(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_PARAMETER_BINDING, TrackerParameterBinding))
+#define TRACKER_IS_PARAMETER_BINDING(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_PARAMETER_BINDING))
+
#define TRACKER_TYPE_VARIABLE_BINDING (tracker_variable_binding_get_type ())
#define TRACKER_VARIABLE_BINDING(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_VARIABLE_BINDING, TrackerVariableBinding))
#define TRACKER_IS_VARIABLE_BINDING(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_VARIABLE_BINDING))
@@ -51,6 +55,8 @@ typedef struct _TrackerBinding TrackerBinding;
typedef struct _TrackerBindingClass TrackerBindingClass;
typedef struct _TrackerLiteralBinding TrackerLiteralBinding;
typedef struct _TrackerLiteralBindingClass TrackerLiteralBindingClass;
+typedef struct _TrackerParameterBinding TrackerParameterBinding;
+typedef struct _TrackerParameterBindingClass TrackerParameterBindingClass;
typedef struct _TrackerVariableBinding TrackerVariableBinding;
typedef struct _TrackerVariableBindingClass TrackerVariableBindingClass;
typedef struct _TrackerContext TrackerContext;
@@ -95,6 +101,16 @@ struct _TrackerLiteralBindingClass {
TrackerBindingClass parent_class;
};
+/* Represents a mapping of a SPARQL parameter variable to a user-provided value */
+struct _TrackerParameterBinding {
+ TrackerLiteralBinding parent_instance;
+ gchar *name;
+};
+
+struct _TrackerParameterBindingClass {
+ TrackerLiteralBindingClass parent_class;
+};
+
/* Represents a mapping of a SPARQL variable to a SQL table and column */
struct _TrackerVariableBinding {
TrackerBinding parent_instance;
@@ -117,6 +133,7 @@ struct _TrackerToken {
guint type;
union {
gchar *literal;
+ gchar *parameter;
TrackerVariable *var;
} content;
};
@@ -225,6 +242,11 @@ GType tracker_literal_binding_get_type (void) G_GNUC_CONST;
TrackerBinding * tracker_literal_binding_new (const gchar *literal,
TrackerDataTable *table);
+/* Parameter binding */
+GType tracker_parameter_binding_get_type (void) G_GNUC_CONST;
+TrackerBinding * tracker_parameter_binding_new (const gchar *name,
+ TrackerDataTable *table);
+
/* Variable binding */
GType tracker_variable_binding_get_type (void) G_GNUC_CONST;
TrackerBinding * tracker_variable_binding_new (TrackerVariable *variable,
@@ -249,15 +271,18 @@ TrackerVariableBinding * tracker_variable_get_sample_binding (TrackerVariable *v
/* Token */
void tracker_token_literal_init (TrackerToken *token,
- const gchar *literal);
+ const gchar *literal);
void tracker_token_variable_init (TrackerToken *token,
TrackerVariable *variable);
-void tracker_token_unset (TrackerToken *token);
+void tracker_token_parameter_init (TrackerToken *token,
+ const gchar *pameter);
+void tracker_token_unset (TrackerToken *token);
gboolean tracker_token_is_empty (TrackerToken *token);
const gchar * tracker_token_get_literal (TrackerToken *token);
TrackerVariable * tracker_token_get_variable (TrackerToken *token);
const gchar * tracker_token_get_idstring (TrackerToken *token);
+const gchar * tracker_token_get_parameter (TrackerToken *token);
/* Predicate variable */
TrackerPredicateVariable *tracker_predicate_variable_new (void);
@@ -298,6 +323,8 @@ gboolean tracker_context_lookup_variable_ref (TrackerContext *context,
/* Select context */
GType tracker_select_context_get_type (void) G_GNUC_CONST;
TrackerContext * tracker_select_context_new (void);
+TrackerVariable * tracker_select_context_lookup_variable (TrackerSelectContext *context,
+ const gchar *name);
TrackerVariable * tracker_select_context_ensure_variable (TrackerSelectContext *context,
const gchar *name);
TrackerVariable * tracker_select_context_add_generated_variable (TrackerSelectContext *context);
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index 600d1c776..54e48a1d2 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -60,6 +60,7 @@ static gboolean helper_translate_time (TrackerSparql *sparql,
static TrackerDBStatement * prepare_query (TrackerDBInterface *iface,
TrackerStringBuilder *str,
GPtrArray *literals,
+ GHashTable *parameters,
gboolean cached,
GError **error);
static inline TrackerVariable * _ensure_variable (TrackerSparql *sparql,
@@ -119,6 +120,8 @@ struct _TrackerSparql
gboolean silent;
gboolean cacheable;
+ GHashTable *parameters;
+
struct {
TrackerContext *context;
TrackerContext *select_context;
@@ -151,6 +154,7 @@ tracker_sparql_finalize (GObject *object)
g_object_unref (sparql->data_manager);
g_hash_table_destroy (sparql->prefix_map);
+ g_hash_table_destroy (sparql->parameters);
if (sparql->sql)
tracker_string_builder_free (sparql->sql);
@@ -555,6 +559,7 @@ _extract_node_string (TrackerParserNode *node,
switch (rule->data.terminal) {
case TERMINAL_TYPE_VAR1:
case TERMINAL_TYPE_VAR2:
+ case TERMINAL_TYPE_PARAMETERIZED_VAR:
add_start = 1;
break;
case TERMINAL_TYPE_STRING_LITERAL1:
@@ -618,14 +623,22 @@ _dup_last_string (TrackerSparql *sparql)
static inline TrackerBinding *
_convert_terminal (TrackerSparql *sparql)
{
+ const TrackerGrammarRule *rule;
TrackerBinding *binding;
gchar *str;
str = _dup_last_string (sparql);
g_assert (str != NULL);
- binding = tracker_literal_binding_new (str, NULL);
- tracker_binding_set_data_type (binding, sparql->current_state.expression_type);
+ rule = tracker_parser_node_get_rule (sparql->current_state.prev_node);
+
+ if (tracker_grammar_rule_is_a (rule, RULE_TYPE_TERMINAL, TERMINAL_TYPE_PARAMETERIZED_VAR)) {
+ binding = tracker_parameter_binding_new (str, NULL);
+ } else {
+ binding = tracker_literal_binding_new (str, NULL);
+ tracker_binding_set_data_type (binding, sparql->current_state.expression_type);
+ }
+
g_free (str);
return binding;
@@ -669,18 +682,18 @@ _ensure_variable (TrackerSparql *sparql,
TrackerVariable *var;
var = tracker_select_context_ensure_variable (TRACKER_SELECT_CONTEXT (sparql->context),
- name);
+ name);
tracker_context_add_variable_ref (sparql->current_state.context, var);
return var;
}
static inline TrackerVariable *
-_extract_node_variable (TrackerParserNode *node,
- TrackerSparql *sparql)
+_extract_node_variable (TrackerParserNode *node,
+ TrackerSparql *sparql)
{
const TrackerGrammarRule *rule = tracker_parser_node_get_rule (node);
- TrackerVariable *variable;
+ TrackerVariable *variable = NULL;
gchar *str;
if (!tracker_grammar_rule_is_a (rule, RULE_TYPE_TERMINAL, TERMINAL_TYPE_VAR1) &&
@@ -722,6 +735,8 @@ _init_token (TrackerToken *token,
value = g_hash_table_lookup (sparql->solution_var_map, str);
tracker_token_literal_init (token, value);
}
+ } else if (tracker_grammar_rule_is_a (rule, RULE_TYPE_TERMINAL, TERMINAL_TYPE_PARAMETERIZED_VAR)) {
+ tracker_token_parameter_init (token, str);
} else {
tracker_token_literal_init (token, str);
}
@@ -911,7 +926,7 @@ _add_quad (TrackerSparql *sparql,
triple_context = TRACKER_TRIPLE_CONTEXT (sparql->current_state.context);
ontologies = tracker_data_manager_get_ontologies (sparql->data_manager);
- if (!tracker_token_get_variable (predicate)) {
+ if (tracker_token_get_literal (predicate)) {
gboolean share_table = TRUE;
const gchar *db_table;
@@ -1030,7 +1045,7 @@ _add_quad (TrackerSparql *sparql,
db_table);
new_table = TRUE;
}
- } else {
+ } else if (tracker_token_get_variable (predicate)) {
TrackerPredicateVariable *pred_var;
/* Variable in predicate */
@@ -1061,15 +1076,23 @@ _add_quad (TrackerSparql *sparql,
tracker_binding_set_db_column_name (binding, "predicate");
_add_binding (sparql, binding);
g_object_unref (binding);
+ } else {
+ /* The parser disallows parameter predicates */
+ g_assert_not_reached ();
}
if (new_table) {
if (tracker_token_get_variable (subject)) {
variable = tracker_token_get_variable (subject);
binding = tracker_variable_binding_new (variable, subject_type, table);
- } else {
+ } else if (tracker_token_get_literal (subject)) {
binding = tracker_literal_binding_new (tracker_token_get_literal (subject),
table);
+ } else if (tracker_token_get_parameter (subject)) {
+ binding = tracker_parameter_binding_new (tracker_token_get_parameter (subject),
+ table);
+ } else {
+ g_assert_not_reached ();
}
tracker_binding_set_data_type (binding, TRACKER_PROPERTY_TYPE_RESOURCE);
@@ -1134,7 +1157,14 @@ _add_quad (TrackerSparql *sparql,
_add_binding (sparql, binding);
g_object_unref (binding);
} else if (is_fts) {
- binding = tracker_literal_binding_new (tracker_token_get_literal (object), table);
+ if (tracker_token_get_literal (object)) {
+ binding = tracker_literal_binding_new (tracker_token_get_literal (object), table);
+ } else if (tracker_token_get_parameter (object)) {
+ binding = tracker_parameter_binding_new (tracker_token_get_parameter (object), table);
+ } else {
+ g_assert_not_reached ();
+ }
+
tracker_binding_set_db_column_name (binding, "fts5");
_add_binding (sparql, binding);
g_object_unref (binding);
@@ -1175,8 +1205,13 @@ _add_quad (TrackerSparql *sparql,
}
}
} else {
- binding = tracker_literal_binding_new (tracker_token_get_literal (object),
- table);
+ if (tracker_token_get_literal (object)) {
+ binding = tracker_literal_binding_new (tracker_token_get_literal (object), table);
+ } else if (tracker_token_get_parameter (object)) {
+ binding = tracker_parameter_binding_new (tracker_token_get_parameter (object), table);
+ } else {
+ g_assert_not_reached ();
+ }
if (tracker_token_get_variable (predicate)) {
tracker_binding_set_db_column_name (binding, "object");
@@ -1195,8 +1230,12 @@ _add_quad (TrackerSparql *sparql,
variable = tracker_token_get_variable (graph);
binding = tracker_variable_binding_new (variable, NULL, table);
tracker_variable_binding_set_nullable (TRACKER_VARIABLE_BINDING (binding), TRUE);
- } else {
+ } else if (tracker_token_get_literal (graph)) {
binding = tracker_literal_binding_new (tracker_token_get_literal (graph), table);
+ } else if (tracker_token_get_parameter (graph)) {
+ binding = tracker_parameter_binding_new (tracker_token_get_parameter (graph), table);
+ } else {
+ g_assert_not_reached ();
}
tracker_binding_set_data_type (binding, TRACKER_PROPERTY_TYPE_RESOURCE);
@@ -2682,7 +2721,7 @@ get_solution_for_pattern (TrackerSparql *sparql,
iface = tracker_data_manager_get_writable_db_interface (sparql->data_manager);
stmt = prepare_query (iface, sparql->sql,
TRACKER_SELECT_CONTEXT (sparql->context)->literal_bindings,
- FALSE,
+ NULL, FALSE,
error);
g_clear_object (&sparql->context);
@@ -5916,12 +5955,17 @@ translate_NumericLiteralUnsigned (TrackerSparql *sparql,
GError **error)
{
/* NumericLiteralUnsigned ::= INTEGER | DECIMAL | DOUBLE
+ *
+ * TRACKER EXTENSION:
+ * The terminal PARAMETERIZED_VAR is additionally accepted
*/
if (_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_INTEGER)) {
sparql->current_state.expression_type = TRACKER_PROPERTY_TYPE_INTEGER;
} else if (_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_DOUBLE) ||
_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_DECIMAL)) {
sparql->current_state.expression_type = TRACKER_PROPERTY_TYPE_DOUBLE;
+ } else if (_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_PARAMETERIZED_VAR)) {
+ sparql->current_state.expression_type = TRACKER_PROPERTY_TYPE_UNKNOWN;
} else {
g_assert_not_reached ();
}
@@ -5934,12 +5978,17 @@ translate_NumericLiteralPositive (TrackerSparql *sparql,
GError **error)
{
/* NumericLiteralPositive ::= INTEGER_POSITIVE | DECIMAL_POSITIVE | DOUBLE_POSITIVE
+ *
+ * TRACKER EXTENSION:
+ * The terminal PARAMETERIZED_VAR is additionally accepted
*/
if (_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_INTEGER_POSITIVE)) {
sparql->current_state.expression_type = TRACKER_PROPERTY_TYPE_INTEGER;
} else if (_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_DECIMAL_POSITIVE) ||
_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_DOUBLE_POSITIVE)) {
sparql->current_state.expression_type = TRACKER_PROPERTY_TYPE_DOUBLE;
+ } else if (_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_PARAMETERIZED_VAR)) {
+ sparql->current_state.expression_type = TRACKER_PROPERTY_TYPE_UNKNOWN;
} else {
g_assert_not_reached ();
}
@@ -5952,12 +6001,17 @@ translate_NumericLiteralNegative (TrackerSparql *sparql,
GError **error)
{
/* NumericLiteralNegative ::= INTEGER_NEGATIVE | DECIMAL_NEGATIVE | DOUBLE_NEGATIVE
+ *
+ * TRACKER EXTENSION:
+ * The terminal PARAMETERIZED_VAR is additionally accepted
*/
if (_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_INTEGER_NEGATIVE)) {
sparql->current_state.expression_type = TRACKER_PROPERTY_TYPE_INTEGER;
} else if (_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_DECIMAL_NEGATIVE) ||
_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_DOUBLE_NEGATIVE)) {
sparql->current_state.expression_type = TRACKER_PROPERTY_TYPE_DOUBLE;
+ } else if (_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_PARAMETERIZED_VAR)) {
+ sparql->current_state.expression_type = TRACKER_PROPERTY_TYPE_UNKNOWN;
} else {
g_assert_not_reached ();
}
@@ -5970,11 +6024,16 @@ translate_BooleanLiteral (TrackerSparql *sparql,
GError **error)
{
/* BooleanLiteral ::= 'true' | 'false'
+ *
+ * TRACKER EXTENSION:
+ * The terminal PARAMETERIZED_VAR is additionally accepted
*/
if (_accept (sparql, RULE_TYPE_LITERAL, LITERAL_TRUE) ||
_accept (sparql, RULE_TYPE_LITERAL, LITERAL_FALSE)) {
sparql->current_state.expression_type = TRACKER_PROPERTY_TYPE_BOOLEAN;
return TRUE;
+ } else if (_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_PARAMETERIZED_VAR)) {
+ sparql->current_state.expression_type = TRACKER_PROPERTY_TYPE_UNKNOWN;
} else {
g_assert_not_reached ();
}
@@ -5987,6 +6046,9 @@ translate_String (TrackerSparql *sparql,
GError **error)
{
/* String ::= STRING_LITERAL1 | STRING_LITERAL2 | STRING_LITERAL_LONG1 | STRING_LITERAL_LONG2
+ *
+ * TRACKER EXTENSION:
+ * The terminal PARAMETERIZED_VAR is additionally accepted
*/
if (_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_STRING_LITERAL1) ||
_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_STRING_LITERAL2) ||
@@ -5994,6 +6056,8 @@ translate_String (TrackerSparql *sparql,
_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_STRING_LITERAL_LONG2)) {
sparql->current_state.expression_type = TRACKER_PROPERTY_TYPE_STRING;
return TRUE;
+ } else if (_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_PARAMETERIZED_VAR)) {
+ sparql->current_state.expression_type = TRACKER_PROPERTY_TYPE_UNKNOWN;
} else {
g_assert_not_reached ();
}
@@ -6291,6 +6355,7 @@ tracker_sparql_init (TrackerSparql *sparql)
{
sparql->prefix_map = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_free);
+ sparql->parameters = g_hash_table_new (g_str_hash, g_str_equal);
sparql->var_names = g_ptr_array_new_with_free_func (g_free);
sparql->var_types = g_array_new (FALSE, FALSE, sizeof (TrackerPropertyType));
sparql->cacheable = TRUE;
@@ -6327,6 +6392,7 @@ static TrackerDBStatement *
prepare_query (TrackerDBInterface *iface,
TrackerStringBuilder *str,
GPtrArray *literals,
+ GHashTable *parameters,
gboolean cached,
GError **error)
{
@@ -6352,7 +6418,23 @@ prepare_query (TrackerDBInterface *iface,
binding = g_ptr_array_index (literals, i);
prop_type = TRACKER_BINDING (binding)->data_type;
- if (prop_type == TRACKER_PROPERTY_TYPE_BOOLEAN) {
+ if (TRACKER_IS_PARAMETER_BINDING (binding)) {
+ const gchar *name;
+ GValue *value = NULL;
+
+ name = TRACKER_PARAMETER_BINDING (binding)->name;
+
+ if (parameters)
+ value = g_hash_table_lookup (parameters, name);
+
+ if (value) {
+ tracker_db_statement_bind_value (stmt, i, value);
+ } else {
+ g_set_error (error, TRACKER_SPARQL_ERROR,
+ TRACKER_SPARQL_ERROR_TYPE,
+ "Parameter '%s' has no given value", name);
+ }
+ } else if (prop_type == TRACKER_PROPERTY_TYPE_BOOLEAN) {
if (g_str_equal (binding->literal, "1") ||
g_ascii_strcasecmp (binding->literal, "true") == 0) {
tracker_db_statement_bind_int (stmt, i, 1);
@@ -6403,6 +6485,7 @@ prepare_query (TrackerDBInterface *iface,
TrackerSparqlCursor *
tracker_sparql_execute_cursor (TrackerSparql *sparql,
+ GHashTable *parameters,
GError **error)
{
TrackerDBStatement *stmt;
@@ -6423,6 +6506,7 @@ tracker_sparql_execute_cursor (TrackerSparql *sparql,
iface = tracker_data_manager_get_db_interface (sparql->data_manager);
stmt = prepare_query (iface, sparql->sql,
TRACKER_SELECT_CONTEXT (sparql->context)->literal_bindings,
+ parameters,
sparql->cacheable,
error);
if (!stmt)
diff --git a/src/libtracker-data/tracker-sparql.h b/src/libtracker-data/tracker-sparql.h
index bf0b3b137..e86665c51 100644
--- a/src/libtracker-data/tracker-sparql.h
+++ b/src/libtracker-data/tracker-sparql.h
@@ -36,6 +36,7 @@ TrackerSparql * tracker_sparql_new (TrackerDataManager *manager,
const gchar *sparql);
TrackerSparqlCursor * tracker_sparql_execute_cursor (TrackerSparql *sparql,
+ GHashTable *parameters,
GError **error);
TrackerSparql * tracker_sparql_new_update (TrackerDataManager *manager,
diff --git a/src/libtracker-direct/tracker-direct.c b/src/libtracker-direct/tracker-direct.c
index b7e2a8449..9bec7429b 100644
--- a/src/libtracker-direct/tracker-direct.c
+++ b/src/libtracker-direct/tracker-direct.c
@@ -438,7 +438,7 @@ tracker_direct_connection_query (TrackerSparqlConnection *self,
g_mutex_lock (&priv->mutex);
query = tracker_sparql_new (priv->data_manager, sparql);
- cursor = tracker_sparql_execute_cursor (query, error);
+ cursor = tracker_sparql_execute_cursor (query, NULL, error);
g_object_unref (query);
if (cursor)