Repository: marmotta Updated Branches: refs/heads/develop 2a5a66163 -> ea7ed4a81
fix SPARQL queries that use HAVING Project: http://git-wip-us.apache.org/repos/asf/marmotta/repo Commit: http://git-wip-us.apache.org/repos/asf/marmotta/commit/caf9f419 Tree: http://git-wip-us.apache.org/repos/asf/marmotta/tree/caf9f419 Diff: http://git-wip-us.apache.org/repos/asf/marmotta/diff/caf9f419 Branch: refs/heads/develop Commit: caf9f419975c3402e20473751baf2ddd7ad349a2 Parents: 85e5ff3 Author: Sebastian Schaffert <[email protected]> Authored: Thu Oct 30 10:51:37 2014 +0100 Committer: Sebastian Schaffert <[email protected]> Committed: Thu Oct 30 10:51:37 2014 +0100 ---------------------------------------------------------------------- .../kiwi/sparql/builder/ConditionFinder.java | 12 +++++++ .../kiwi/sparql/builder/PatternCollector.java | 4 +++ .../kiwi/sparql/builder/SQLBuilder.java | 36 +++++++++++++++++++- .../kiwi/sparql/builder/SQLFragment.java | 4 +-- 4 files changed, 53 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/marmotta/blob/caf9f419/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/ConditionFinder.java ---------------------------------------------------------------------- diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/ConditionFinder.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/ConditionFinder.java index 16cbc00..f06baf7 100644 --- a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/ConditionFinder.java +++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/ConditionFinder.java @@ -51,6 +51,18 @@ public class ConditionFinder extends QueryModelVisitorBase<RuntimeException> { } @Override + public void meet(Count node) throws RuntimeException { + if(!found && node.getArg() == null) { + // special case: count(*), we need the variable + found = true; + } else { + super.meet(node); + } + } + + + + @Override public void meet(Union node) throws RuntimeException { // stop, subquery } http://git-wip-us.apache.org/repos/asf/marmotta/blob/caf9f419/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 5e7a6ff..5c81f6d 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 @@ -80,6 +80,10 @@ public class PatternCollector extends QueryModelVisitorBase<RuntimeException> { public void meet(Filter node) throws RuntimeException { parts.getLast().getFilters().add(node.getCondition()); + if(node.getArg() instanceof Group) { + parts.getLast().setConditionPosition(SQLFragment.ConditionPosition.HAVING); + } + super.meet(node); } http://git-wip-us.apache.org/repos/asf/marmotta/blob/caf9f419/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 c1a01e7..41fc13e 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 @@ -483,7 +483,7 @@ public class SQLBuilder { // and we need to mark the pattern accordingly. boolean first = true; for(SQLFragment f : fragments) { - if(first) { + if(first && f.getConditionPosition() == SQLFragment.ConditionPosition.JOIN) { // the conditions of the first fragment need to be placed in the WHERE part of the query, because // there is not necessarily a JOIN ... ON where we can put it f.setConditionPosition(SQLFragment.ConditionPosition.WHERE); @@ -624,6 +624,35 @@ public class SQLBuilder { return whereClause; } + private StringBuilder buildHavingClause() { + + // list of where conditions that will later be connected by AND + List<String> havingConditions = new LinkedList<String>(); + + // 1. for the first pattern of the first fragment, we add the conditions to the WHERE clause + + for(SQLFragment fragment : fragments) { + if(fragment.getConditionPosition() == SQLFragment.ConditionPosition.HAVING) { + havingConditions.add(fragment.buildConditionClause()); + } + } + + // construct the having clause + StringBuilder havingClause = new StringBuilder(); + for(Iterator<String> it = havingConditions.iterator(); it.hasNext(); ) { + String condition = it.next(); + if(condition.length() > 0) { + havingClause.append(condition); + havingClause.append("\n "); + if (it.hasNext()) { + havingClause.append("AND "); + } + } + } + return havingClause; + } + + private StringBuilder buildOrderClause() { StringBuilder orderClause = new StringBuilder(); if(orderby.size() > 0) { @@ -1174,6 +1203,7 @@ public class SQLBuilder { StringBuilder whereClause = buildWhereClause(); StringBuilder orderClause = buildOrderClause(); StringBuilder groupClause = buildGroupClause(); + StringBuilder havingClause = buildHavingClause(); StringBuilder limitClause = buildLimitClause(); @@ -1190,6 +1220,10 @@ public class SQLBuilder { queryString.append("GROUP BY ").append(groupClause).append("\n "); } + if(havingClause.length() > 9) { + queryString.append("HAVING ").append(havingClause).append("\n "); + } + if(orderClause.length() > 0) { queryString.append("ORDER BY ").append(orderClause).append("\n "); } http://git-wip-us.apache.org/repos/asf/marmotta/blob/caf9f419/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLFragment.java ---------------------------------------------------------------------- diff --git a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLFragment.java b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLFragment.java index 11689e8..155339b 100644 --- a/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLFragment.java +++ b/libraries/kiwi/kiwi-sparql/src/main/java/org/apache/marmotta/kiwi/sparql/builder/SQLFragment.java @@ -38,7 +38,7 @@ public class SQLFragment extends SQLClause { * always place it in JOIN conditions, because the first pattern will not have a JOIN. */ public static enum ConditionPosition { - JOIN, WHERE + JOIN, WHERE, HAVING }; @@ -154,7 +154,7 @@ public class SQLFragment extends SQLClause { public String buildConditionClause() { StringBuilder conditionClause = new StringBuilder(); - if(conditionPosition == ConditionPosition.WHERE) { + if(conditionPosition == ConditionPosition.WHERE || conditionPosition == ConditionPosition.HAVING) { for (Iterator<SQLClause> it = Iterators.concat(patterns.iterator(), subqueries.iterator()); it.hasNext(); ) { SQLClause p = it.next();
