[tracker/subqueries] SPARQL: Scalar subqueries
- From: Jürg Billeter <juergbi src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [tracker/subqueries] SPARQL: Scalar subqueries
- Date: Sun, 6 Dec 2009 20:49:43 +0000 (UTC)
commit e113020139a2bfe5d9d17f18783833e2581ddf55
Author: Jürg Billeter <j bitron ch>
Date: Fri Dec 4 19:04:38 2009 +0100
SPARQL: Scalar subqueries
src/libtracker-data/tracker-sparql-query.vala | 114 ++++++++++++++++++++-----
1 files changed, 94 insertions(+), 20 deletions(-)
---
diff --git a/src/libtracker-data/tracker-sparql-query.vala b/src/libtracker-data/tracker-sparql-query.vala
index fd6cd09..2049ae9 100644
--- a/src/libtracker-data/tracker-sparql-query.vala
+++ b/src/libtracker-data/tracker-sparql-query.vala
@@ -48,6 +48,18 @@ public class Tracker.SparqlQuery : Object {
public PropertyType data_type;
public DataTable table;
public string sql_db_column_name;
+ public string sql_expression {
+ get {
+ if (this._sql_expression == null) {
+ this._sql_expression = "\"%s\".\"%s\"".printf (table.sql_query_tablename, sql_db_column_name);
+ }
+ return this._sql_expression;
+ }
+ set {
+ this._sql_expression = value;
+ }
+ }
+ string? _sql_expression;
}
// Represents a mapping of a SPARQL literal to a SQL table and column
@@ -256,6 +268,8 @@ public class Tracker.SparqlQuery : Object {
List<Variable> pattern_variables;
HashTable<Variable,VariableBindingList> pattern_var_map;
+ HashTable<string,Variable> outer_var_map;
+
// All SPARQL variables within a subgraph pattern (used by UNION)
HashTable<Variable,int> subgraph_var_set;
@@ -555,9 +569,31 @@ public class Tracker.SparqlQuery : Object {
return stmt.execute ();
}
+ void skip_bracketted_expression () throws SparqlError {
+ expect (SparqlTokenType.OPEN_PARENS);
+ while (true) {
+ switch (current ()) {
+ case SparqlTokenType.OPEN_PARENS:
+ // skip nested bracketted expression
+ skip_bracketted_expression ();
+ continue;
+ case SparqlTokenType.CLOSE_PARENS:
+ break;
+ default:
+ next ();
+ continue;
+ }
+ break;
+ }
+ expect (SparqlTokenType.CLOSE_PARENS);
+ }
+
void skip_select_variables () throws SparqlError {
while (true) {
switch (current ()) {
+ case SparqlTokenType.OPEN_PARENS:
+ skip_bracketted_expression ();
+ continue;
case SparqlTokenType.FROM:
case SparqlTokenType.WHERE:
case SparqlTokenType.OPEN_BRACE:
@@ -1750,6 +1786,27 @@ public class Tracker.SparqlQuery : Object {
PropertyType translate_bracketted_expression (StringBuilder sql) throws SparqlError {
expect (SparqlTokenType.OPEN_PARENS);
+
+ if (current () == SparqlTokenType.SELECT) {
+ // FIXME ensure that inner variables are only exported if selected
+
+ outer_var_map = var_map;
+ var outer_predicate_variable_map = predicate_variable_map;
+ var outer_used_sql_identifiers = used_sql_identifiers;
+ begin_query ();
+
+ sql.append ("(");
+ translate_select (sql, true);
+ sql.append (")");
+
+ var_map = outer_var_map;
+ predicate_variable_map = outer_predicate_variable_map;
+ used_sql_identifiers = outer_used_sql_identifiers;
+
+ expect (SparqlTokenType.CLOSE_PARENS);
+ return PropertyType.UNKNOWN;
+ }
+
var optype = translate_expression (sql);
expect (SparqlTokenType.CLOSE_PARENS);
return optype;
@@ -2012,7 +2069,7 @@ public class Tracker.SparqlQuery : Object {
foreach (VariableBinding binding in pattern_var_map.lookup (variable).list) {
string name;
if (binding.table != null) {
- name = "\"%s\".\"%s\"".printf (binding.table.sql_query_tablename, binding.sql_db_column_name);
+ name = binding.sql_expression;
} else {
// simple optional with inverse functional property
// always first in loop as variable is required to be unbound
@@ -2055,11 +2112,7 @@ public class Tracker.SparqlQuery : Object {
sql.append (" WHERE ");
first_where = false;
}
- sql.append ("\"");
- sql.append (binding.table.sql_query_tablename);
- sql.append ("\".\"");
- sql.append (binding.sql_db_column_name);
- sql.append ("\"");
+ sql.append (binding.sql_expression);
if (binding.is_fts_match) {
// parameters do not work with fts MATCH
string escaped_literal = string.joinv ("''", binding.literal.split ("'"));
@@ -2465,6 +2518,30 @@ public class Tracker.SparqlQuery : Object {
subgraph_var_set = old_subgraph_var_set;
}
+ VariableBindingList? get_variable_binding_list (Variable variable) {
+ var binding_list = pattern_var_map.lookup (variable);
+ if (binding_list == null && outer_var_map != null) {
+ // in scalar subquery: check variables of outer query
+ var outer_var = outer_var_map.lookup (variable.name);
+ if (outer_var != null) {
+ // capture outer variable
+ var binding = new VariableBinding ();
+ binding.data_type = outer_var.binding.data_type;
+ binding.variable = get_variable (variable.name);
+ binding.type = outer_var.binding.type;
+ binding.sql_expression = outer_var.sql_expression;
+ binding_list = new VariableBindingList ();
+ pattern_variables.append (binding.variable);
+ pattern_var_map.insert (binding.variable, binding_list);
+
+ subgraph_var_set.insert (binding.variable, VariableState.BOUND);
+ binding_list.list.append (binding);
+ binding.variable.binding = binding;
+ }
+ }
+ return binding_list;
+ }
+
void parse_object (StringBuilder sql, bool in_simple_optional = false) throws SparqlError {
bool object_is_var;
string object = parse_var_or_term (sql, out object_is_var);
@@ -2544,10 +2621,10 @@ public class Tracker.SparqlQuery : Object {
// need to use table and column name for object, can't refer to variable in nested select
var object_binding = pattern_var_map.lookup (get_variable (object)).list.data;
- sql.append_printf ("(SELECT ID FROM \"%s\" WHERE \"%s\" = \"%s\".\"%s\") AS %s, ",
+ sql.append_printf ("(SELECT ID FROM \"%s\" WHERE \"%s\" = %s) AS %s, ",
db_table,
prop.name,
- object_binding.table.sql_query_tablename, object_binding.sql_db_column_name,
+ object_binding.sql_expression,
binding.variable.sql_expression);
subgraph_var_set.insert (binding.variable, VariableState.OPTIONAL);
@@ -2586,15 +2663,14 @@ public class Tracker.SparqlQuery : Object {
binding.variable = get_variable (current_predicate);
binding.table = table;
binding.sql_db_column_name = "predicate";
- var binding_list = pattern_var_map.lookup (binding.variable);
+ var binding_list = get_variable_binding_list (binding.variable);
if (binding_list == null) {
binding_list = new VariableBindingList ();
pattern_variables.append (binding.variable);
pattern_var_map.insert (binding.variable, binding_list);
- sql.append_printf ("\"%s\".\"%s\" AS %s, ",
- binding.table.sql_query_tablename,
- binding.sql_db_column_name,
+ sql.append_printf ("%s AS %s, ",
+ binding.sql_expression,
binding.variable.sql_expression);
subgraph_var_set.insert (binding.variable, VariableState.BOUND);
@@ -2617,15 +2693,14 @@ public class Tracker.SparqlQuery : Object {
} else {
binding.sql_db_column_name = "ID";
}
- var binding_list = pattern_var_map.lookup (binding.variable);
+ var binding_list = get_variable_binding_list (binding.variable);
if (binding_list == null) {
binding_list = new VariableBindingList ();
pattern_variables.append (binding.variable);
pattern_var_map.insert (binding.variable, binding_list);
- sql.append_printf ("\"%s\".\"%s\" AS %s, ",
- binding.table.sql_query_tablename,
- binding.sql_db_column_name,
+ sql.append_printf ("%s AS %s, ",
+ binding.sql_expression,
binding.variable.sql_expression);
subgraph_var_set.insert (binding.variable, VariableState.BOUND);
@@ -2668,15 +2743,14 @@ public class Tracker.SparqlQuery : Object {
binding.maybe_null = true;
}
- var binding_list = pattern_var_map.lookup (binding.variable);
+ var binding_list = get_variable_binding_list (binding.variable);
if (binding_list == null) {
binding_list = new VariableBindingList ();
pattern_variables.append (binding.variable);
pattern_var_map.insert (binding.variable, binding_list);
- sql.append_printf ("\"%s\".\"%s\" AS %s, ",
- binding.table.sql_query_tablename,
- binding.sql_db_column_name,
+ sql.append_printf ("%s AS %s, ",
+ binding.sql_expression,
binding.variable.sql_expression);
VariableState state;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]