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



commit d46bdef70fe95867ad3ff0eae2b5de511877823a
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 |   8 -
 src/libtracker-data/tracker-sparql-types.h |   4 -
 src/libtracker-data/tracker-sparql.c       | 258 +++--------------------------
 src/libtracker-data/tracker-vtab-triples.c |   1 +
 4 files changed, 25 insertions(+), 246 deletions(-)
---
diff --git a/src/libtracker-data/tracker-sparql-types.c b/src/libtracker-data/tracker-sparql-types.c
index c3c8eae3c..05b0600d7 100644
--- a/src/libtracker-data/tracker-sparql-types.c
+++ b/src/libtracker-data/tracker-sparql-types.c
@@ -71,19 +71,11 @@ tracker_predicate_variable_new (void)
 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,
diff --git a/src/libtracker-data/tracker-sparql-types.h b/src/libtracker-data/tracker-sparql-types.h
index bf3484475..bd3b063ba 100644
--- a/src/libtracker-data/tracker-sparql-types.h
+++ b/src/libtracker-data/tracker-sparql-types.h
@@ -143,8 +143,6 @@ struct _TrackerToken {
 struct _TrackerPredicateVariable {
        gchar *subject;
        gchar *object;
-       TrackerClass *domain;
-
        guint return_graph : 1;
 };
 
@@ -319,8 +317,6 @@ 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,
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index d123c6330..80d41d4a5 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -1063,35 +1063,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 */
@@ -1445,227 +1416,46 @@ 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;
-               }
+       TrackerBinding *binding;
 
-               for (i = 0; i < n_types; i++) {
-                       for (j = 0; j < n_properties; j++) {
-                               if (types[i] != tracker_property_get_range (properties[j]))
-                                       continue;
+       _append_string (sparql,
+                       "SELECT subject AS ID, predicate, object ");
 
-                               if (!first)
-                                       _append_string (sparql, "UNION ALL ");
+       if (pred_var->return_graph)
+               _append_string (sparql, ", graph ");
 
-                               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, "FROM tracker_triples ");
 
-                               _append_string (sparql, " AS \"object\" ");
+       if (pred_var->subject || pred_var->object) {
+               _append_string (sparql, "WHERE ");
 
-                               if (pred_var->return_graph) {
-                                       _append_string_printf (sparql,
-                                                              ", \"%s:graph\" AS \"graph\" ",
-                                                              tracker_property_get_name (properties[j]));
-                               }
+               if (pred_var->subject) {
+                       _append_string (sparql, "subject = ");
+                       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_string_printf (sparql, " FROM \"%s\" ",
-                                                      tracker_property_get_table_name (properties[j]));
-                       }
-               }
+                       _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\" ");
+                       if (pred_var->object)
+                               _append_string (sparql, "AND ");
                }
 
-               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]));
-                       }
+               if (pred_var->object) {
+                       _append_string (sparql, "object = ");
+                       binding = tracker_literal_binding_new (pred_var->object, NULL);
+                       tracker_binding_set_data_type (binding, TRACKER_PROPERTY_TYPE_STRING);
+                       tracker_select_context_add_literal_binding (TRACKER_SELECT_CONTEXT (sparql->context),
+                                                                   TRACKER_LITERAL_BINDING (binding));
 
-                       _append_string_printf (sparql, "FROM \"%s\" ",
-                                              tracker_property_get_table_name (properties[j]));
+                       _append_literal_sql (sparql, TRACKER_LITERAL_BINDING (binding));
                }
-       } else {
-               /* ?s ?p ?o */
-               _unimplemented ("Unrestricted predicate variables are not supported");
        }
 
        return TRUE;
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]