[tracker/wip/carlosg/sparql-parser-ng: 303/306] libtracker-data: Support parameter bindings
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/carlosg/sparql-parser-ng: 303/306] libtracker-data: Support parameter bindings
- Date: Mon, 15 Oct 2018 21:25:07 +0000 (UTC)
commit ad89d40dc8c85710e5ab3b262cf2b62eaa2ff425
Author: Carlos Garnacho <carlosg gnome org>
Date: Sun Oct 14 11:23:35 2018 +0200
libtracker-data: Support parameter bindings
Those relate to PARAMETERIZED_VAR, and allow binding values through it at
query preparation time.
src/libtracker-data/tracker-data-query.c | 2 +-
src/libtracker-data/tracker-sparql-types.c | 46 +++++++++++++++++++
src/libtracker-data/tracker-sparql-types.h | 22 +++++++++
src/libtracker-data/tracker-sparql.c | 74 ++++++++++++++++++++++++++----
src/libtracker-data/tracker-sparql.h | 1 +
src/libtracker-direct/tracker-direct.c | 2 +-
6 files changed, 137 insertions(+), 10 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..c79216635 100644
--- a/src/libtracker-data/tracker-sparql-types.c
+++ b/src/libtracker-data/tracker-sparql-types.c
@@ -419,6 +419,43 @@ 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)
+{
+ TrackerBinding *binding;
+
+ binding = g_object_new (TRACKER_TYPE_PARAMETER_BINDING, NULL);
+ TRACKER_PARAMETER_BINDING (binding)->name = g_strdup (name);
+
+ return binding;
+}
+
/* Variable binding */
G_DEFINE_TYPE (TrackerVariableBinding, tracker_variable_binding, TRACKER_TYPE_BINDING)
@@ -592,6 +629,15 @@ tracker_select_context_new (void)
return g_object_new (TRACKER_TYPE_SELECT_CONTEXT, NULL);
}
+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..d7269818a 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;
@@ -225,6 +241,10 @@ 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);
+
/* Variable binding */
GType tracker_variable_binding_get_type (void) G_GNUC_CONST;
TrackerBinding * tracker_variable_binding_new (TrackerVariable *variable,
@@ -298,6 +318,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..986f75463 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);
+ } 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) &&
@@ -2682,7 +2695,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 +5929,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 +5952,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 +5975,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 +5998,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 +6020,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 +6030,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 +6329,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 +6366,7 @@ static TrackerDBStatement *
prepare_query (TrackerDBInterface *iface,
TrackerStringBuilder *str,
GPtrArray *literals,
+ GHashTable *parameters,
gboolean cached,
GError **error)
{
@@ -6352,7 +6392,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 +6459,7 @@ prepare_query (TrackerDBInterface *iface,
TrackerSparqlCursor *
tracker_sparql_execute_cursor (TrackerSparql *sparql,
+ GHashTable *parameters,
GError **error)
{
TrackerDBStatement *stmt;
@@ -6423,6 +6480,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 66409991b..c5d3e5c94 100644
--- a/src/libtracker-direct/tracker-direct.c
+++ b/src/libtracker-direct/tracker-direct.c
@@ -437,7 +437,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)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]