first working version of EXISTS/NOT EXISTS (MARMOTTA-542)
Project: http://git-wip-us.apache.org/repos/asf/marmotta/repo Commit: http://git-wip-us.apache.org/repos/asf/marmotta/commit/becba188 Tree: http://git-wip-us.apache.org/repos/asf/marmotta/tree/becba188 Diff: http://git-wip-us.apache.org/repos/asf/marmotta/diff/becba188 Branch: refs/heads/develop Commit: becba188adeef1760f6a91cd435e5ac55e752cce Parents: 46e3b4f Author: Sebastian Schaffert <[email protected]> Authored: Fri Sep 19 10:43:25 2014 +0200 Committer: Sebastian Schaffert <[email protected]> Committed: Fri Sep 19 10:43:25 2014 +0200 ---------------------------------------------------------------------- .../kiwi/sparql/builder/PatternCollector.java | 15 +++++++++++---- .../marmotta/kiwi/sparql/builder/SQLBuilder.java | 17 +++++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/marmotta/blob/becba188/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/PatternCollector.java ---------------------------------------------------------------------- diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/PatternCollector.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/PatternCollector.java index 10fcb17..5e7a6ff 100644 --- a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/PatternCollector.java +++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/PatternCollector.java @@ -43,13 +43,15 @@ public class PatternCollector extends QueryModelVisitorBase<RuntimeException> { private ValueConverter converter; private KiWiDialect dialect; private Set<String> projectedVars; + private String prefix; - public PatternCollector(TupleExpr expr, BindingSet bindings, Dataset dataset, ValueConverter converter, KiWiDialect dialect, Set<String> projectedVars) { + public PatternCollector(TupleExpr expr, BindingSet bindings, Dataset dataset, ValueConverter converter, KiWiDialect dialect, Set<String> projectedVars, String prefix) { this.bindings = bindings; this.dataset = dataset; this.converter = converter; this.dialect = dialect; this.projectedVars = projectedVars; + this.prefix = prefix; parts.push(new SQLFragment()); expr.visit(this); @@ -57,7 +59,7 @@ public class PatternCollector extends QueryModelVisitorBase<RuntimeException> { @Override public void meet(StatementPattern node) throws RuntimeException { - parts.getLast().getPatterns().add(new SQLPattern("P" + (++counter), node)); + parts.getLast().getPatterns().add(new SQLPattern(prefix + "P" + (++counter), node)); super.meet(node); } @@ -85,13 +87,18 @@ public class PatternCollector extends QueryModelVisitorBase<RuntimeException> { public void meet(Union node) throws RuntimeException { // unions are treated as subqueries, don't continue collection, but add the Union to the last part - parts.getLast().getSubqueries().add(new SQLUnion("U" + (++counter),node, bindings, dataset, converter, dialect)); + parts.getLast().getSubqueries().add(new SQLUnion(prefix + "U" + (++counter),node, bindings, dataset, converter, dialect)); } @Override public void meet(Projection node) throws RuntimeException { // subqueries are represented with a projection inside a JOIN; we don't continue collection - parts.getLast().getSubqueries().add(new SQLSubQuery("S" + (++counter), node, bindings, dataset, converter, dialect, projectedVars)); + parts.getLast().getSubqueries().add(new SQLSubQuery(prefix + "S" + (++counter), node, bindings, dataset, converter, dialect, projectedVars)); + } + + @Override + public void meet(Exists node) throws RuntimeException { + // stop at exists, it is treated as a subquery in the condition part } } http://git-wip-us.apache.org/repos/asf/marmotta/blob/becba188/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLBuilder.java ---------------------------------------------------------------------- diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLBuilder.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLBuilder.java index e8ec9d1..52e85b6 100644 --- a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLBuilder.java +++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLBuilder.java @@ -147,7 +147,7 @@ public class SQLBuilder { * contains information whether the variable needs to be projected, what SQL expressions represent this variable, * and what internal aliases to use. */ - private Map<String,SQLVariable> variables = new HashMap<>(); + private Map<String,SQLVariable> variables; protected void addVariable(SQLVariable v) { variables.put(v.getSparqlName(),v); } @@ -169,6 +169,8 @@ public class SQLBuilder { private KiWiDialect dialect; + // a prefix for naming table aliases (needed in case this is a subquery) + private String prefix; /** * Create a new SQLBuilder for the given query, initial bindings, dataset, and @@ -185,19 +187,26 @@ public class SQLBuilder { }, dialect, projectedVars); } + + public SQLBuilder(TupleExpr query, BindingSet bindings, Dataset dataset, ValueConverter converter, KiWiDialect dialect, Set<String> projectedVars) throws UnsatisfiableQueryException { + this(query,bindings, dataset, converter, dialect, "", projectedVars, new HashMap<String, SQLVariable>()); + } + /** * Create a new SQLBuilder for the given query, initial bindings, dataset, and * @param query * @param bindings * @param dataset */ - public SQLBuilder(TupleExpr query, BindingSet bindings, Dataset dataset, ValueConverter converter, KiWiDialect dialect, Set<String> projectedVars) throws UnsatisfiableQueryException { + public SQLBuilder(TupleExpr query, BindingSet bindings, Dataset dataset, ValueConverter converter, KiWiDialect dialect, String prefix, Set<String> projectedVars, Map<String,SQLVariable> variables) throws UnsatisfiableQueryException { this.query = query; this.bindings = bindings; this.dataset = dataset; this.converter = converter; this.dialect = dialect; this.projectedVars = projectedVars; + this.prefix = prefix; + this.variables = variables; prepareBuilder(); } @@ -217,7 +226,7 @@ public class SQLBuilder { // collect all patterns in a list, using depth-first search over the join - PatternCollector pc = new PatternCollector(query, bindings, dataset, converter, dialect, projectedVars); + PatternCollector pc = new PatternCollector(query, bindings, dataset, converter, dialect, projectedVars, prefix); fragments = pc.parts; @@ -715,7 +724,7 @@ public class SQLBuilder { // TODO: need to make sure that variables of the parent are visible in the subquery // - pattern names need to be unique even in subqueries // - variable lookup for expressions in the subquery need to refer to the parent - SQLBuilder sq_builder = new SQLBuilder(((Exists) expr).getSubQuery(), bindings, dataset, converter, dialect, Collections.EMPTY_SET); + SQLBuilder sq_builder = new SQLBuilder(((Exists) expr).getSubQuery(), bindings, dataset, converter, dialect, "_", Collections.EMPTY_SET, variables); return "EXISTS (" + sq_builder.build() + ")"; } else if(expr instanceof Str) {
