[tracker/exists: 1/2] SPARQL: Add support for EXISTS and NOT EXISTS
- From: Jürg Billeter <juergbi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/exists: 1/2] SPARQL: Add support for EXISTS and NOT EXISTS
- Date: Mon, 12 Jul 2010 10:28:18 +0000 (UTC)
commit 27295e61425fb02c94f30416c29d3f37c2a1cc60
Author: Jürg Billeter <j bitron ch>
Date: Mon Jul 12 11:58:43 2010 +0200
SPARQL: Add support for EXISTS and NOT EXISTS
src/libtracker-data/tracker-sparql-expression.vala | 12 ++++++
src/libtracker-data/tracker-sparql-pattern.vala | 38 ++++++++++++++++++++
src/libtracker-data/tracker-sparql-scanner.vala | 12 ++++++
3 files changed, 62 insertions(+), 0 deletions(-)
---
diff --git a/src/libtracker-data/tracker-sparql-expression.vala b/src/libtracker-data/tracker-sparql-expression.vala
index ea5052f..4325fcd 100644
--- a/src/libtracker-data/tracker-sparql-expression.vala
+++ b/src/libtracker-data/tracker-sparql-expression.vala
@@ -224,6 +224,12 @@ class Tracker.Sparql.Expression : Object {
expect (SparqlTokenType.CLOSE_PARENS);
}
+ void translate_exists (StringBuilder sql) throws SparqlError {
+ sql.append ("(");
+ pattern.translate_exists (sql);
+ sql.append (")");
+ }
+
internal static void append_expression_as_string (StringBuilder sql, string expression, PropertyType type) {
long begin = sql.len;
sql.append (expression);
@@ -920,6 +926,10 @@ class Tracker.Sparql.Expression : Object {
case SparqlTokenType.REGEX:
translate_regex (sql);
return PropertyType.BOOLEAN;
+ case SparqlTokenType.EXISTS:
+ case SparqlTokenType.NOT:
+ translate_exists (sql);
+ return PropertyType.BOOLEAN;
case SparqlTokenType.COUNT:
next ();
sql.append ("COUNT(");
@@ -1185,6 +1195,8 @@ class Tracker.Sparql.Expression : Object {
case SparqlTokenType.ISBLANK:
case SparqlTokenType.ISLITERAL:
case SparqlTokenType.REGEX:
+ case SparqlTokenType.EXISTS:
+ case SparqlTokenType.NOT:
return translate_primary_expression (sql);
default:
return translate_bracketted_expression (sql);
diff --git a/src/libtracker-data/tracker-sparql-pattern.vala b/src/libtracker-data/tracker-sparql-pattern.vala
index 39e4db5..c0d8f5d 100644
--- a/src/libtracker-data/tracker-sparql-pattern.vala
+++ b/src/libtracker-data/tracker-sparql-pattern.vala
@@ -416,6 +416,44 @@ class Tracker.Sparql.Pattern : Object {
return result;
}
+ internal void translate_exists (StringBuilder sql) throws SparqlError {
+ bool not = accept (SparqlTokenType.NOT);
+ expect (SparqlTokenType.EXISTS);
+
+ SelectContext result;
+ result = new SelectContext.subquery (context);
+ context = result;
+
+ var pattern_sql = new StringBuilder ();
+
+ sql.append ("SELECT ");
+
+ var pattern = translate_group_graph_pattern (pattern_sql);
+ foreach (var key in pattern.var_set.get_keys ()) {
+ context.var_set.insert (key, VariableState.BOUND);
+ }
+
+ // report use of undefined variables
+ foreach (var variable in context.var_set.get_keys ()) {
+ if (variable.binding == null) {
+ throw get_error ("use of undefined variable `%s'".printf (variable.name));
+ }
+ }
+
+ if (not) {
+ // NOT EXISTS
+ sql.append ("COUNT(1) = 0");
+ } else {
+ // EXISTS
+ sql.append ("COUNT(1) > 0");
+ }
+
+ // select from results of WHERE clause
+ sql.append (" FROM (");
+ sql.append (pattern_sql.str);
+ sql.append (")");
+ }
+
internal string parse_var_or_term (StringBuilder? sql, out bool is_var) throws SparqlError {
string result = "";
is_var = false;
diff --git a/src/libtracker-data/tracker-sparql-scanner.vala b/src/libtracker-data/tracker-sparql-scanner.vala
index a42c60e..d803045 100644
--- a/src/libtracker-data/tracker-sparql-scanner.vala
+++ b/src/libtracker-data/tracker-sparql-scanner.vala
@@ -98,6 +98,10 @@ public class Tracker.SparqlScanner : Object {
break;
}
break;
+ case 'N':
+ case 'n':
+ if (matches (begin, "NOT")) return SparqlTokenType.NOT;
+ break;
case 'S':
case 's':
switch (begin[1]) {
@@ -236,6 +240,10 @@ public class Tracker.SparqlScanner : Object {
case 'd':
if (matches (begin, "DELETE")) return SparqlTokenType.DELETE;
break;
+ case 'E':
+ case 'e':
+ if (matches (begin, "EXISTS")) return SparqlTokenType.EXISTS;
+ break;
case 'F':
case 'f':
if (matches (begin, "FILTER")) return SparqlTokenType.FILTER;
@@ -822,6 +830,7 @@ public enum Tracker.SparqlTokenType {
DOUBLE_CIRCUMFLEX,
DROP,
EOF,
+ EXISTS,
FALSE,
FILTER,
FROM,
@@ -843,6 +852,7 @@ public enum Tracker.SparqlTokenType {
MIN,
MINUS,
NAMED,
+ NOT,
OFFSET,
OP_AND,
OP_EQ,
@@ -910,6 +920,7 @@ public enum Tracker.SparqlTokenType {
case DOUBLE_CIRCUMFLEX: return "`^^'";
case DROP: return "`DROP'";
case EOF: return "end of file";
+ case EXISTS: return "`EXISTS'";
case FALSE: return "`false'";
case FILTER: return "`FILTER'";
case FROM: return "`FROM'";
@@ -931,6 +942,7 @@ public enum Tracker.SparqlTokenType {
case MIN: return "`MIN'";
case MINUS: return "`-'";
case NAMED: return "`NAMED'";
+ case NOT: return "`NOT'";
case OFFSET: return "`OFFSET'";
case OP_AND: return "`&&'";
case OP_EQ: return "`='";
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]