[tracker/wip/carlosg/unrestricted-predicates: 17/18] libtracker-data: Use "tracker_triples" table in variable predicate queries



commit 5d186707cc42ab4ffa38fe8d3b9365473b9bcae5
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sun Jan 6 19:22:29 2019 +0100

    libtracker-data: Use "tracker_triples" table in variable predicate queries
    
    There were some special cases that were handled individually:
    - select * { <s> ?p ?o } was handled through querying the rdf:types of <s>,
      and performing an UNION of all related tables. This doesn't play along
      with parameterized variables where the subject might be a variable assigned
      later through the TrackerSparqlStatement.
    - select * { ?s ?p <o> } used similar tricks (querying <o> this time). It had
      all those drawbacks, plus it only worked for properties with rdfs:Resource
      range.
    - select * { ?s ?p ?o . ?p rdfs:domain <dom> } was handled specially.
    - select * { ?s ?p ?o } is unsupported
    - select * { <s> ?p <o> } was silently unhandled
    
    All those combinations are transparently handled with the tracker_triples
    virtual table now.

 src/libtracker-data/tracker-sparql-types.c |  66 +------
 src/libtracker-data/tracker-sparql-types.h |  33 +---
 src/libtracker-data/tracker-sparql.c       | 290 +----------------------------
 src/libtracker-data/tracker-vtab-triples.c |   1 +
 4 files changed, 11 insertions(+), 379 deletions(-)
---
diff --git a/src/libtracker-data/tracker-sparql-types.c b/src/libtracker-data/tracker-sparql-types.c
index c3c8eae3c..38765cb44 100644
--- a/src/libtracker-data/tracker-sparql-types.c
+++ b/src/libtracker-data/tracker-sparql-types.c
@@ -56,45 +56,10 @@ tracker_data_table_free (TrackerDataTable *table)
 }
 
 void
-tracker_data_table_set_predicate_variable (TrackerDataTable         *table,
-                                           TrackerPredicateVariable *variable)
+tracker_data_table_set_predicate_variable (TrackerDataTable *table,
+                                           gboolean          is_variable)
 {
-       table->predicate_variable = variable;
-}
-
-TrackerPredicateVariable *
-tracker_predicate_variable_new (void)
-{
-       return g_new0 (TrackerPredicateVariable, 1);
-}
-
-static void
-tracker_predicate_variable_free (TrackerPredicateVariable *pred_var)
-{
-       g_clear_object (&pred_var->domain);
-       g_free (pred_var->subject);
-       g_free (pred_var->object);
-       g_free (pred_var);
-}
-
-void
-tracker_predicate_variable_set_domain (TrackerPredicateVariable *pred_var,
-                                       TrackerClass             *domain)
-{
-       g_set_object (&pred_var->domain, domain);
-}
-
-void
-tracker_predicate_variable_set_triple_details (TrackerPredicateVariable *pred_var,
-                                               const gchar              *subject,
-                                               const gchar              *object,
-                                               gboolean                  return_graph)
-{
-       g_free (pred_var->subject);
-       pred_var->subject = g_strdup (subject);
-       g_free (pred_var->object);
-       pred_var->object = g_strdup (object);
-       pred_var->return_graph = !!return_graph;
+       table->predicate_variable = is_variable;
 }
 
 static TrackerVariable *
@@ -723,7 +688,6 @@ tracker_select_context_finalize (GObject *object)
        TrackerSelectContext *context = TRACKER_SELECT_CONTEXT (object);
 
        g_clear_pointer (&context->variables, g_hash_table_unref);
-       g_clear_pointer (&context->predicate_variables, g_hash_table_unref);
        g_clear_pointer (&context->generated_variables, g_ptr_array_unref);
        g_clear_pointer (&context->literal_bindings, g_ptr_array_unref);
        g_clear_pointer (&context->path_elements, g_ptr_array_unref);
@@ -807,30 +771,6 @@ tracker_select_context_add_generated_variable (TrackerSelectContext *context)
        return variable;
 }
 
-TrackerPredicateVariable *
-tracker_select_context_lookup_predicate_variable (TrackerSelectContext *context,
-                                                  TrackerVariable      *variable)
-{
-       if (!context->predicate_variables)
-               return NULL;
-       return g_hash_table_lookup (context->predicate_variables, variable);
-}
-
-void
-tracker_select_context_add_predicate_variable (TrackerSelectContext     *context,
-                                               TrackerVariable          *variable,
-                                               TrackerPredicateVariable *pred_var)
-{
-       if (!context->predicate_variables) {
-               context->predicate_variables =
-                       g_hash_table_new_full (tracker_variable_hash,
-                                              tracker_variable_equal, NULL,
-                                              (GDestroyNotify) tracker_predicate_variable_free);
-       }
-
-       g_hash_table_insert (context->predicate_variables, variable, pred_var);
-}
-
 void
 tracker_select_context_add_literal_binding (TrackerSelectContext  *context,
                                             TrackerLiteralBinding *binding)
diff --git a/src/libtracker-data/tracker-sparql-types.h b/src/libtracker-data/tracker-sparql-types.h
index bf3484475..a474f5142 100644
--- a/src/libtracker-data/tracker-sparql-types.h
+++ b/src/libtracker-data/tracker-sparql-types.h
@@ -71,13 +71,12 @@ typedef struct _TrackerVariable TrackerVariable;
 typedef struct _TrackerToken TrackerToken;
 typedef struct _TrackerSolution TrackerSolution;
 typedef struct _TrackerPathElement TrackerPathElement;
-typedef struct _TrackerPredicateVariable TrackerPredicateVariable;
 
 struct _TrackerDataTable {
        gchar *subject; /* Subject this table is pulled from */
        gchar *sql_db_tablename; /* as in db schema */
        gchar *sql_query_tablename; /* temp. name, generated */
-       TrackerPredicateVariable *predicate_variable;
+       gboolean predicate_variable;
 };
 
 struct _TrackerBinding {
@@ -140,14 +139,6 @@ struct _TrackerToken {
        } content;
 };
 
-struct _TrackerPredicateVariable {
-       gchar *subject;
-       gchar *object;
-       TrackerClass *domain;
-
-       guint return_graph : 1;
-};
-
 struct _TrackerSolution {
        GPtrArray *columns;
        GPtrArray *values;
@@ -197,9 +188,6 @@ struct _TrackerContextClass {
 struct _TrackerSelectContext {
        TrackerContext parent_instance;
 
-       /* Variables used as predicates */
-       GHashTable *predicate_variables; /* TrackerVariable -> TrackerPredicateVariable */
-
        /* All variables declared from this context. All these TrackerVariables
         * are shared with children contexts. Only the root context has contents
         * here.
@@ -246,8 +234,8 @@ struct _TrackerTripleContextClass {
 };
 
 /* Data table */
-void tracker_data_table_set_predicate_variable (TrackerDataTable         *table,
-                                               TrackerPredicateVariable *variable);
+void tracker_data_table_set_predicate_variable (TrackerDataTable *table,
+                                                gboolean          is_variable);
 
 /* Binding */
 GType              tracker_binding_get_type (void) G_GNUC_CONST;
@@ -316,16 +304,6 @@ const gchar      * tracker_token_get_idstring (TrackerToken *token);
 const gchar      * tracker_token_get_parameter (TrackerToken *token);
 TrackerPathElement * tracker_token_get_path   (TrackerToken *token);
 
-/* Predicate variable */
-TrackerPredicateVariable *tracker_predicate_variable_new (void);
-
-void tracker_predicate_variable_set_domain (TrackerPredicateVariable *pred_var,
-                                            TrackerClass             *domain);
-void tracker_predicate_variable_set_triple_details (TrackerPredicateVariable *pred_var,
-                                                    const gchar              *subject,
-                                                    const gchar              *object,
-                                                    gboolean                  return_graph);
-
 /* Solution */
 TrackerSolution * tracker_solution_new       (guint            n_cols);
 void              tracker_solution_free      (TrackerSolution *solution);
@@ -366,11 +344,6 @@ TrackerVariable * tracker_select_context_ensure_variable (TrackerSelectContext *
                                                          const gchar          *name);
 TrackerVariable * tracker_select_context_add_generated_variable (TrackerSelectContext *context);
 
-TrackerPredicateVariable * tracker_select_context_lookup_predicate_variable (TrackerSelectContext *context,
-                                                                            TrackerVariable      *variable);
-void tracker_select_context_add_predicate_variable (TrackerSelectContext     *context,
-                                                   TrackerVariable          *variable,
-                                                   TrackerPredicateVariable *pred_var);
 void tracker_select_context_add_literal_binding (TrackerSelectContext  *context,
                                                  TrackerLiteralBinding *binding);
 guint tracker_select_context_get_literal_binding_index (TrackerSelectContext  *context,
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index d123c6330..5d47c7fb1 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -1015,7 +1015,6 @@ _add_quad (TrackerSparql  *sparql,
           TrackerToken   *object,
           GError        **error)
 {
-       TrackerSelectContext *select_context;
        TrackerTripleContext *triple_context;
        TrackerOntologies *ontologies;
        TrackerDataTable *table = NULL;
@@ -1025,7 +1024,6 @@ _add_quad (TrackerSparql  *sparql,
        TrackerClass *subject_type = NULL;
        gboolean new_table = FALSE, is_fts = FALSE, is_rdf_type = FALSE;
 
-       select_context = TRACKER_SELECT_CONTEXT (sparql->current_state.select_context);
        triple_context = TRACKER_TRIPLE_CONTEXT (sparql->current_state.context);
        ontologies = tracker_data_manager_get_ontologies (sparql->data_manager);
 
@@ -1063,35 +1061,6 @@ _add_quad (TrackerSparql  *sparql,
                                GPtrArray *binding_list;
 
                                variable = tracker_token_get_variable (subject);
-
-                               if (!tracker_token_get_variable (object) &&
-                                   g_strcmp0 (tracker_token_get_literal (predicate), RDFS_NS "domain") == 0) 
{
-                                       TrackerPredicateVariable *pred_var;
-                                       TrackerClass *domain;
-
-                                       /* rdfs:domain */
-                                       domain = tracker_ontologies_get_class_by_uri (ontologies,
-                                                                                     
tracker_token_get_literal (object));
-                                       if (!domain) {
-                                               g_set_error (error, TRACKER_SPARQL_ERROR,
-                                                            TRACKER_SPARQL_ERROR_UNKNOWN_CLASS,
-                                                            "Unknown class '%s'",
-                                                            tracker_token_get_literal (object));
-                                               return FALSE;
-                                       }
-
-                                       pred_var = tracker_select_context_lookup_predicate_variable 
(select_context,
-                                                                                                    
variable);
-                                       if (!pred_var) {
-                                               pred_var = tracker_predicate_variable_new ();
-                                               tracker_select_context_add_predicate_variable (select_context,
-                                                                                              variable,
-                                                                                              pred_var);
-                                       }
-
-                                       tracker_predicate_variable_set_domain (pred_var, domain);
-                               }
-
                                binding_list = tracker_triple_context_lookup_variable_binding_list 
(triple_context,
                                                                                                    variable);
                                /* Domain specific index might be a possibility, let's check */
@@ -1149,39 +1118,19 @@ _add_quad (TrackerSparql  *sparql,
                        new_table = TRUE;
                }
        } else if (tracker_token_get_variable (predicate)) {
-               TrackerPredicateVariable *pred_var;
-
                /* Variable in predicate */
                variable = tracker_token_get_variable (predicate);
                table = tracker_triple_context_add_table (triple_context,
                                                          variable->name, variable->name);
+               tracker_data_table_set_predicate_variable (table, TRUE);
                new_table = TRUE;
 
-               pred_var = tracker_select_context_lookup_predicate_variable (select_context,
-                                                                            variable);
-               if (!pred_var) {
-                       pred_var = tracker_predicate_variable_new ();
-                       tracker_predicate_variable_set_triple_details (pred_var,
-                                                                      tracker_token_get_literal (subject),
-                                                                      tracker_token_get_literal (object),
-                                                                      !tracker_token_is_empty (graph));
-
-                       tracker_select_context_add_predicate_variable (select_context,
-                                                                      variable,
-                                                                      pred_var);
-               }
-
-               tracker_data_table_set_predicate_variable (table, pred_var);
-
                /* Add to binding list */
                binding = tracker_variable_binding_new (variable, NULL, table);
                tracker_binding_set_data_type (binding, TRACKER_PROPERTY_TYPE_RESOURCE);
                tracker_binding_set_db_column_name (binding, "predicate");
                _add_binding (sparql, binding);
                g_object_unref (binding);
-
-               if (!tracker_token_is_empty (graph))
-                       pred_var->return_graph = TRUE;
        } else if (tracker_token_get_path (predicate)) {
                table = tracker_triple_context_add_table (triple_context,
                                                          "value",
@@ -1445,232 +1394,6 @@ convert_expression_to_string (TrackerSparql       *sparql,
        }
 }
 
-static TrackerClass **
-lookup_resource_types (TrackerSparql  *sparql,
-                      const gchar    *resource,
-                      gint           *n_types,
-                      GError        **error)
-{
-       TrackerOntologies *ontologies;
-       TrackerDBInterface *iface;
-       TrackerDBStatement *stmt;
-       TrackerDBCursor *cursor = NULL;
-       GError *inner_error = NULL;
-       GPtrArray *types;
-       gint resource_id;
-
-       if (n_types)
-               *n_types = 0;
-
-       ontologies = tracker_data_manager_get_ontologies (sparql->data_manager);
-       iface = tracker_data_manager_get_writable_db_interface (sparql->data_manager);
-       resource_id = tracker_data_query_resource_id (sparql->data_manager,
-                                                     iface, resource);
-
-       /* This is not an error condition, query might refer to an unknown resource */
-       if (resource_id <= 0)
-               return NULL;
-
-       stmt = tracker_db_interface_create_statement (iface, TRACKER_DB_STATEMENT_CACHE_TYPE_SELECT, 
&inner_error,
-                                                     "SELECT (SELECT Uri FROM Resource WHERE ID = 
\"rdf:type\") "
-                                                     "FROM \"rdfs:Resource_rdf:type\" WHERE ID = ?");
-       if (!stmt) {
-               g_propagate_error (error, inner_error);
-               return NULL;
-       }
-
-       tracker_db_statement_bind_int (stmt, 0, resource_id);
-       cursor = tracker_db_statement_start_cursor (stmt, error);
-       g_object_unref (stmt);
-
-       if (!cursor) {
-               g_propagate_error (error, inner_error);
-               return NULL;
-       }
-
-       types = g_ptr_array_new ();
-
-       while (tracker_db_cursor_iter_next (cursor, NULL, &inner_error)) {
-               TrackerClass *type;
-
-               type = tracker_ontologies_get_class_by_uri (ontologies,
-                                                           tracker_db_cursor_get_string (cursor, 0, NULL));
-               g_ptr_array_add (types, type);
-       }
-
-       g_object_unref (cursor);
-
-       if (inner_error) {
-               g_propagate_error (error, inner_error);
-               g_ptr_array_unref (types);
-               return NULL;
-       }
-
-       if (n_types)
-               *n_types = types->len;
-
-       return (TrackerClass **) g_ptr_array_free (types, FALSE);
-}
-
-static gboolean
-append_predicate_variable_query (TrackerSparql             *sparql,
-                                TrackerPredicateVariable  *pred_var,
-                                GError                   **error)
-{
-       TrackerOntologies *ontologies;
-       TrackerProperty **properties;
-       TrackerStringBuilder *str, *old;
-       TrackerClass **types;
-       TrackerBinding *binding = NULL;
-       gint n_properties, n_types, i, j;
-       GError *inner_error = NULL;
-       gboolean first = TRUE;
-
-       ontologies = tracker_data_manager_get_ontologies (sparql->data_manager);
-       properties = tracker_ontologies_get_properties (ontologies, &n_properties);
-
-       if (pred_var->subject) {
-               /* <s> ?p ?o */
-               types = lookup_resource_types (sparql, pred_var->subject, &n_types, &inner_error);
-               if (inner_error) {
-                       g_propagate_error (error, inner_error);
-                       return FALSE;
-               }
-
-               for (i = 0; i < n_types; i++) {
-                       for (j = 0; j < n_properties; j++) {
-                               if (types[i] != tracker_property_get_domain (properties[j]))
-                                       continue;
-
-                               if (!first)
-                                       _append_string (sparql, "UNION ALL ");
-
-                               first = FALSE;
-                               _append_string_printf (sparql,
-                                                      "SELECT ID, (SELECT ID FROM Resource WHERE Uri = '%s') 
AS \"predicate\", ",
-                                                      tracker_property_get_uri (properties[j]));
-
-                               str = _append_placeholder (sparql);
-                               old = tracker_sparql_swap_builder (sparql, str);
-                               _append_string_printf (sparql, "\"%s\" ", tracker_property_get_name 
(properties[j]));
-                               convert_expression_to_string (sparql, tracker_property_get_data_type 
(properties[j]));
-                               tracker_sparql_swap_builder (sparql, old);
-
-                               _append_string (sparql, " AS \"object\" ");
-
-                               if (pred_var->return_graph) {
-                                       _append_string_printf (sparql, ", \"%s:graph\" AS \"graph\" ",
-                                                              tracker_property_get_name (properties[j]));
-                               }
-
-                               _append_string_printf (sparql, "FROM \"%s\" WHERE ID = ",
-                                                      tracker_property_get_table_name (properties[j]));
-
-                               if (!binding) {
-                                       binding = tracker_literal_binding_new (pred_var->subject, NULL);
-                                       tracker_binding_set_data_type (binding, 
TRACKER_PROPERTY_TYPE_RESOURCE);
-                                       tracker_select_context_add_literal_binding (TRACKER_SELECT_CONTEXT 
(sparql->context),
-                                                                                   TRACKER_LITERAL_BINDING 
(binding));
-                               }
-
-                               _append_literal_sql (sparql, TRACKER_LITERAL_BINDING (binding));
-                       }
-               }
-
-               if (first) {
-                       /* No match */
-                       _append_string (sparql,
-                                       "SELECT NULL AS ID, NULL AS \"predicate\", NULL AS \"object\", NULL 
AS \"graph\"");
-               }
-
-               g_free (types);
-       } else if (pred_var->object) {
-               /* ?s ?p <o> */
-               types = lookup_resource_types (sparql, pred_var->object, &n_types, &inner_error);
-               if (inner_error) {
-                       g_propagate_error (error, inner_error);
-                       return FALSE;
-               }
-
-               for (i = 0; i < n_types; i++) {
-                       for (j = 0; j < n_properties; j++) {
-                               if (types[i] != tracker_property_get_range (properties[j]))
-                                       continue;
-
-                               if (!first)
-                                       _append_string (sparql, "UNION ALL ");
-
-                               first = FALSE;
-                               _append_string_printf (sparql,
-                                                      "SELECT ID, (SELECT ID FROM Resource WHERE Uri = '%s') 
AS \"predicate\", ",
-                                                      tracker_property_get_uri (properties[j]));
-
-                               str = _append_placeholder (sparql);
-                               old = tracker_sparql_swap_builder (sparql, str);
-                               _append_string_printf (sparql, "\"%s\" ", tracker_property_get_name 
(properties[j]));
-                               convert_expression_to_string (sparql, tracker_property_get_data_type 
(properties[j]));
-                               tracker_sparql_swap_builder (sparql, old);
-
-                               _append_string (sparql, " AS \"object\" ");
-
-                               if (pred_var->return_graph) {
-                                       _append_string_printf (sparql,
-                                                              ", \"%s:graph\" AS \"graph\" ",
-                                                              tracker_property_get_name (properties[j]));
-                               }
-
-                               _append_string_printf (sparql, " FROM \"%s\" ",
-                                                      tracker_property_get_table_name (properties[j]));
-                       }
-               }
-
-               if (first) {
-                       /* No match */
-                       _append_string (sparql,
-                                       "SELECT NULL AS ID, NULL AS \"predicate\", NULL AS \"object\", NULL 
AS \"graph\" ");
-               }
-
-               g_free (types);
-       } else if (pred_var->domain) {
-               /* Any subject, predicates limited to a specific domain */
-
-               for (j = 0; j < n_properties; j++) {
-                       if (pred_var->domain != tracker_property_get_domain (properties[j]))
-                               continue;
-
-                       if (!first)
-                               _append_string (sparql, "UNION ALL ");
-
-                       first = FALSE;
-                       _append_string_printf (sparql,
-                                              "SELECT ID, (SELECT ID FROM Resource WHERE Uri = '%s') AS 
\"predicate\", ",
-                                              tracker_property_get_uri (properties[j]));
-
-                       str = _append_placeholder (sparql);
-                       old = tracker_sparql_swap_builder (sparql, str);
-                       _append_string_printf (sparql, "\"%s\" ", tracker_property_get_name (properties[j]));
-                       convert_expression_to_string (sparql, tracker_property_get_data_type (properties[j]));
-                       tracker_sparql_swap_builder (sparql, old);
-
-                       _append_string (sparql, " AS \"object\" ");
-
-                       if (pred_var->return_graph) {
-                               _append_string_printf (sparql,
-                                                      ", \"%s:graph\" AS \"graph\" ",
-                                                      tracker_property_get_name (properties[j]));
-                       }
-
-                       _append_string_printf (sparql, "FROM \"%s\" ",
-                                              tracker_property_get_table_name (properties[j]));
-               }
-       } else {
-               /* ?s ?p ?o */
-               _unimplemented ("Unrestricted predicate variables are not supported");
-       }
-
-       return TRUE;
-}
-
 static TrackerContext *
 _begin_triples_block (TrackerSparql *sparql)
 {
@@ -1741,14 +1464,9 @@ _end_triples_block (TrackerSparql  *sparql,
                        _append_string (sparql, ", ");
 
                if (table->predicate_variable) {
-                       _append_string (sparql, "(");
-
-                       if (!append_predicate_variable_query (sparql,
-                                                             table->predicate_variable,
-                                                             error))
-                               return FALSE;
-
-                       _append_string (sparql, ") ");
+                       _append_string (sparql,
+                                       "(SELECT subject AS ID, predicate, "
+                                       "object, graph FROM tracker_triples) ");
                } else {
                        _append_string_printf (sparql, "\"%s\" ", table->sql_db_tablename);
                }
diff --git a/src/libtracker-data/tracker-vtab-triples.c b/src/libtracker-data/tracker-vtab-triples.c
index 37210a7be..9ff15b628 100644
--- a/src/libtracker-data/tracker-vtab-triples.c
+++ b/src/libtracker-data/tracker-vtab-triples.c
@@ -75,6 +75,7 @@ tracker_triples_module_free (gpointer data)
 {
        TrackerTriplesModule *module = data;
 
+       g_clear_object (&module->ontologies);
        g_free (module);
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]