[tracker/parser] SPARQL: Fix UNION graph patterns with different variable sets
- From: Jürg Billeter <juergbi src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [tracker/parser] SPARQL: Fix UNION graph patterns with different variable sets
- Date: Fri, 14 Aug 2009 13:38:35 +0000 (UTC)
commit 0d26b5c2b36e1e26b96534ebcd8403fab3eb96d2
Author: Jürg Billeter <j bitron ch>
Date: Fri Aug 14 14:48:24 2009 +0200
SPARQL: Fix UNION graph patterns with different variable sets
src/libtracker-data/tracker-sparql-query.vala | 69 +++++++++++++++++++++++-
1 files changed, 66 insertions(+), 3 deletions(-)
---
diff --git a/src/libtracker-data/tracker-sparql-query.vala b/src/libtracker-data/tracker-sparql-query.vala
index 3e0e434..80accf9 100644
--- a/src/libtracker-data/tracker-sparql-query.vala
+++ b/src/libtracker-data/tracker-sparql-query.vala
@@ -277,6 +277,9 @@ public class Tracker.SparqlQuery : Object {
List<string> pattern_variables;
HashTable<string,VariableBindingList> pattern_var_map;
+ // All SPARQL variables within a subgraph pattern (used by UNION)
+ HashTable<string,bool> subgraph_var_set;
+
// Variables used as predicates
HashTable<string,PredicateVariable> predicate_variable_map;
@@ -293,6 +296,7 @@ public class Tracker.SparqlQuery : Object {
public SparqlQuery (string query) {
tokens = new TokenInfo[BUFFER_SIZE];
prefix_map = new HashTable<string,string>.full (str_hash, str_equal, g_free, g_free);
+ subgraph_var_set = new HashTable<string,bool>.full (str_hash, str_equal, g_free, null);
this.query_string = query;
}
@@ -1908,11 +1912,64 @@ public class Tracker.SparqlQuery : Object {
}
void translate_group_or_union_graph_pattern (StringBuilder sql) throws SparqlError {
- translate_group_graph_pattern (sql);
- while (accept (SparqlTokenType.UNION)) {
- sql.append (" UNION ALL ");
+ var old_subgraph_var_set = subgraph_var_set;
+
+ string[] all_vars = { };
+ HashTable<string,bool> all_var_set = new HashTable<string,bool>.full (str_hash, str_equal, g_free, null);
+
+ HashTable<string,bool>[] var_sets = { };
+ long[] offsets = { };
+
+ do {
+ subgraph_var_set = new HashTable<string,bool>.full (str_hash, str_equal, g_free, null);
+ var_sets += subgraph_var_set;
+ offsets += sql.len;
translate_group_graph_pattern (sql);
+ } while (accept (SparqlTokenType.UNION));
+
+ if (var_sets.length > 1) {
+ // union graph pattern
+
+ // create union of all variables
+ foreach (var var_set in var_sets) {
+ foreach (string v in var_set.get_keys ()) {
+ if (!all_var_set.lookup (v)) {
+ all_vars += v;
+ all_var_set.insert (v, true);
+ old_subgraph_var_set.insert (v, true);
+ }
+ }
+ }
+
+ long extra_offset = 0;
+ for (int i = 0; i < var_sets.length; i++) {
+ var projection = new StringBuilder ();
+ if (i > 0) {
+ projection.append (") UNION ALL ");
+ }
+ projection.append ("SELECT ");
+ foreach (string v in all_vars) {
+ if (!var_sets[i].lookup (v)) {
+ // variable not used in this subgraph
+ // use NULL
+ projection.append ("NULL AS ");
+ }
+ projection.append_printf ("\"%s_u\", ", v);
+ }
+ // delete last comma and space
+ projection.truncate (projection.len - 2);
+ projection.append (" FROM (");
+
+ sql.insert (offsets[i] + extra_offset, projection.str);
+ extra_offset += projection.len;
+ }
+ sql.append (")");
+ } else {
+ foreach (string key in subgraph_var_set.get_keys ()) {
+ old_subgraph_var_set.insert (key, true);
+ }
}
+ subgraph_var_set = old_subgraph_var_set;
}
void parse_object (StringBuilder sql) throws SparqlError {
@@ -2009,6 +2066,8 @@ public class Tracker.SparqlQuery : Object {
binding.table.sql_query_tablename,
binding.sql_db_column_name,
binding.variable);
+
+ subgraph_var_set.insert (binding.variable, true);
}
binding_list.list.append (binding);
if (var_map.lookup (binding.variable) == null) {
@@ -2033,6 +2092,8 @@ public class Tracker.SparqlQuery : Object {
binding.table.sql_query_tablename,
binding.sql_db_column_name,
binding.variable);
+
+ subgraph_var_set.insert (binding.variable, true);
}
binding_list.list.append (binding);
if (var_map.lookup (binding.variable) == null) {
@@ -2089,6 +2150,8 @@ public class Tracker.SparqlQuery : Object {
binding.table.sql_query_tablename,
binding.sql_db_column_name,
binding.variable);
+
+ subgraph_var_set.insert (binding.variable, true);
}
binding_list.list.append (binding);
if (var_map.lookup (binding.variable) == null) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]