ignite-624 - fix
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/cf1cf9d0 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/cf1cf9d0 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/cf1cf9d0 Branch: refs/heads/ignite-30 Commit: cf1cf9d00788482abe89feeb39746f24035fc53b Parents: 3daa0b6 Author: S.Vladykin <svlady...@gridgain.com> Authored: Wed Apr 8 01:20:07 2015 +0300 Committer: S.Vladykin <svlady...@gridgain.com> Committed: Wed Apr 8 01:20:07 2015 +0300 ---------------------------------------------------------------------- .../ignite/internal/util/lang/GridFunc.java | 14 ++++ .../processors/query/h2/sql/GridSqlElement.java | 8 --- .../processors/query/h2/sql/GridSqlQuery.java | 26 +++++-- .../query/h2/sql/GridSqlQueryParser.java | 7 +- .../query/h2/sql/GridSqlQuerySplitter.java | 25 ++++--- .../processors/query/h2/sql/GridSqlSelect.java | 73 +++++++++++++------- .../processors/query/h2/sql/GridSqlUnion.java | 10 +++ .../query/h2/sql/GridQueryParsingTest.java | 6 +- .../query/h2/sql/IgniteVsH2QueryTest.java | 17 ++++- 9 files changed, 131 insertions(+), 55 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cf1cf9d0/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java index edd66d7..773b9ee 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java @@ -5429,6 +5429,20 @@ public class GridFunc { } /** + * @param c Target collection. + * @param it Iterator to fetch. + * @return Modified target collection. + */ + public static <T, C extends Collection<T>> C addAll(C c, Iterator<? extends T> it) { + if (it != null) { + while (it.hasNext()) + c.add(it.next()); + } + + return c; + } + + /** * Gets the value with given key. If that value does not exist, calls given * closure to get the default value, puts it into the map and returns it. If * closure is {@code null} return {@code null}. http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cf1cf9d0/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlElement.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlElement.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlElement.java index 7ebdba1..a1c91ff 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlElement.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlElement.java @@ -51,14 +51,6 @@ public abstract class GridSqlElement implements Cloneable, Iterable<GridSqlEleme public abstract String getSQL(); /** - * Clears all children. - */ - public void clearChildren() { - if (size() != 0) - children = new ArrayList<>(); - } - - /** * @param expr Expr. * @return {@code this}. */ http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cf1cf9d0/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuery.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuery.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuery.java index 5953d5e..c40632f 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuery.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuery.java @@ -17,7 +17,6 @@ package org.apache.ignite.internal.processors.query.h2.sql; -import org.apache.ignite.*; import org.h2.util.*; import java.util.*; @@ -107,12 +106,25 @@ public abstract class GridSqlQuery implements Cloneable { } /** + * @return Number of visible columns. + */ + protected abstract int visibleColumns(); + + /** + * @param col Column index. + * @return Expression for column index. + */ + protected abstract GridSqlElement expression(int col); + + /** * @param buff Statement builder. */ protected void getSortLimitSQL(StatementBuilder buff) { if (!sort.isEmpty()) { buff.append("\nORDER BY "); + int visibleCols = visibleColumns(); + boolean first = true; for (GridSqlSortColumn col : sort) { @@ -123,11 +135,17 @@ public abstract class GridSqlQuery implements Cloneable { int idx = col.column(); - if (idx >= 0) + assert idx >= 0 : idx; + + if (idx < visibleCols) buff.append(idx + 1); else { - throw new IgniteException("Failed to generate query: " + buff); -// buff.append('=').append(StringUtils.unEnclose(entry.getKey().getSQL())); + GridSqlElement expr = expression(idx); + + if (expr == null) // For plain select should never be null, for union H2 itself can't parse query. + throw new IllegalStateException("Failed to build query: " + buff.toString()); + + buff.append('=').append(StringUtils.unEnclose(expr.getSQL())); } if (!col.asc()) http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cf1cf9d0/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java index ea3628f..b174d71 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java @@ -270,8 +270,8 @@ public class GridSqlQueryParser { ArrayList<Expression> expressions = select.getExpressions(); - for (Expression exp : expressions) - res.addExpression(parseExpression(exp)); + for (int i = 0; i < expressions.size(); i++) + res.addSelectExpression(parseExpression(expressions.get(i)), i < select.getColumnCount()); int[] grpIdx = GROUP_INDEXES.get(select); @@ -290,9 +290,6 @@ public class GridSqlQueryParser { res.having(parseExpression(expressions.get(havingIdx))); } - for (int i = 0; i < select.getColumnCount(); i++) - res.addSelectExpression(parseExpression(expressions.get(i))); - processSortOrder(select.getSortOrder(), res); res.limit(parseExpression(select.getLimit())); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cf1cf9d0/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java index 05928c2..b84084b 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java @@ -19,6 +19,7 @@ package org.apache.ignite.internal.processors.query.h2.sql; import org.apache.ignite.*; import org.apache.ignite.internal.processors.cache.query.*; +import org.apache.ignite.internal.util.typedef.*; import org.h2.jdbc.*; import org.h2.value.*; import org.jetbrains.annotations.*; @@ -89,7 +90,7 @@ public class GridSqlQuerySplitter { int c = 0; - for (GridSqlElement expr : left.select()) { + for (GridSqlElement expr : left.select(true)) { String colName; if (expr instanceof GridSqlAlias) @@ -102,11 +103,12 @@ public class GridSqlQuerySplitter { expr = alias(colName, expr); // Set generated alias to the expression. - left.select().set(c, expr); - left.allExpressions().set(c, expr); + left.setSelectExpression(c, expr); } - srcQry.addSelectExpression(column(colName)); + GridSqlColumn col = column(colName); + + srcQry.addSelectExpression(col, true); qry0.sort(); @@ -126,8 +128,8 @@ public class GridSqlQuerySplitter { GridSqlSelect rdcQry = new GridSqlSelect().from(new GridSqlFunction("PUBLIC", TABLE_FUNC_NAME)); // table(mergeTable)); TODO // Split all select expressions into map-reduce parts. - List<GridSqlElement> mapExps = new ArrayList<>(srcQry.allExpressions()); - GridSqlElement[] rdcExps = new GridSqlElement[srcQry.select().size()]; + List<GridSqlElement> mapExps = F.addAll(new ArrayList<GridSqlElement>(), srcQry.select(false).iterator()); + GridSqlElement[] rdcExps = new GridSqlElement[srcQry.visibleColumns()]; Set<String> colNames = new HashSet<>(); @@ -140,13 +142,13 @@ public class GridSqlQuerySplitter { mapQry.clearSelect(); for (GridSqlElement exp : mapExps) - mapQry.addSelectExpression(exp); + mapQry.addSelectExpression(exp, true); for (GridSqlElement rdcExp : rdcExps) - rdcQry.addSelectExpression(rdcExp); + rdcQry.addSelectExpression(rdcExp, true); // -- GROUP BY - if (!srcQry.groups().isEmpty()) { + if (srcQry.hasGroupBy()) { mapQry.clearGroups(); for (int col : srcQry.groupColumns()) @@ -219,6 +221,9 @@ public class GridSqlQuerySplitter { findParams(union.left(), params, target); findParams(union.right(), params, target); + findParams(qry.limit(), params, target); + findParams(qry.offset(), params, target); + return target; } @@ -232,7 +237,7 @@ public class GridSqlQuerySplitter { if (params.length == 0) return target; - for (GridSqlElement el : qry.allExpressions()) + for (GridSqlElement el : qry.select(false)) findParams(el, params, target); findParams(qry.from(), params, target); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cf1cf9d0/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSelect.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSelect.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSelect.java index 154659b..398ae10 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSelect.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSelect.java @@ -26,7 +26,7 @@ import java.util.*; */ public class GridSqlSelect extends GridSqlQuery { /** */ - private List<GridSqlElement> allExprs; + private List<GridSqlElement> allExprs = new ArrayList<>(); /** */ private List<GridSqlElement> select = new ArrayList<>(); @@ -50,6 +50,16 @@ public class GridSqlSelect extends GridSqlQuery { private int havingCol = -1; /** {@inheritDoc} */ + @Override public int visibleColumns() { + return select.size(); + } + + /** {@inheritDoc} */ + @Override protected GridSqlElement expression(int col) { + return allExprs.get(col); + } + + /** {@inheritDoc} */ @Override public String getSQL() { StatementBuilder buff = new StatementBuilder("SELECT"); @@ -91,27 +101,11 @@ public class GridSqlSelect extends GridSqlQuery { } /** - * @param expression Expression. - */ - public void addExpression(GridSqlElement expression) { - if (allExprs == null) - allExprs = new ArrayList<>(); - - allExprs.add(expression); - } - - /** - * @return All expressions in select, group by, order by. - */ - public List<GridSqlElement> allExpressions() { - return allExprs; - } - - /** - * @return Expressions. + * @param visibleOnly If only visible expressions needed. + * @return Select phrase expressions. */ - public List<GridSqlElement> select() { - return select; + public Iterable<GridSqlElement> select(boolean visibleOnly) { + return visibleOnly ? select : allExprs; } /** @@ -119,26 +113,55 @@ public class GridSqlSelect extends GridSqlQuery { */ public void clearSelect() { select = new ArrayList<>(); + allExprs = new ArrayList<>(); } /** * @param expression Expression. + * @param visible Expression is visible in select phrase. */ - public void addSelectExpression(GridSqlElement expression) { + public void addSelectExpression(GridSqlElement expression, boolean visible) { if (expression == null) throw new NullPointerException(); - select.add(expression); + if (visible) { + if (select.size() != allExprs.size()) + throw new IllegalStateException("Already started adding invisible columns."); + + select.add(expression); + } + else if (select.isEmpty()) + throw new IllegalStateException("No visible columns."); + + allExprs.add(expression); + } + + /** + * @param colIdx Column index. + * @param expression Expression. + */ + public void setSelectExpression(int colIdx, GridSqlElement expression) { + if (colIdx < select.size()) // Assuming that all the needed expressions were already added. + select.set(colIdx, expression); + + allExprs.set(colIdx, expression); } /** * @return Expressions. */ - public List<GridSqlElement> groups() { + public Iterable<GridSqlElement> groups() { return groups; } /** + * @return {@code true} If the select has group by expression. + */ + public boolean hasGroupBy() { + return !groups.isEmpty(); + } + + /** * */ public void clearGroups() { @@ -252,7 +275,7 @@ public class GridSqlSelect extends GridSqlQuery { res.groups = new ArrayList<>(groups); res.grpCols = grpCols == null ? null : grpCols.clone(); res.select = new ArrayList<>(select); - res.allExprs = null; + res.allExprs = new ArrayList<>(allExprs); return res; } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cf1cf9d0/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlUnion.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlUnion.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlUnion.java index 6fe3f19..90d9e41 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlUnion.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlUnion.java @@ -36,6 +36,16 @@ public class GridSqlUnion extends GridSqlQuery { private GridSqlQuery left; /** {@inheritDoc} */ + @Override protected int visibleColumns() { + return left.visibleColumns(); + } + + /** {@inheritDoc} */ + @Override protected GridSqlElement expression(int col) { + return null; + } + + /** {@inheritDoc} */ @Override public String getSQL() { StatementBuilder buff = new StatementBuilder(); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cf1cf9d0/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java index 83162f0..66ba6ac 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java @@ -208,6 +208,8 @@ public class GridQueryParsingTest extends GridCommonAbstractTest { checkQuery("select name from Person UNION select street from Address limit ?"); checkQuery("select name from Person UNION select street from Address limit ? offset ?"); checkQuery("(select name from Person limit 4) UNION (select street from Address limit 1) limit ? offset ?"); + checkQuery("(select 2 a) union all (select 1) order by 1"); + checkQuery("(select 2 a) union all (select 1) order by a desc nulls first limit ? offset ?"); } /** @@ -282,9 +284,9 @@ public class GridQueryParsingTest extends GridCommonAbstractTest { else throw new UnsupportedOperationException(); - assertSqlEquals(prepared.getPlanSQL(), res); - System.out.println(normalizeSql(res)); + + assertSqlEquals(prepared.getPlanSQL(), res); } @QuerySqlFunction http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/cf1cf9d0/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/IgniteVsH2QueryTest.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/IgniteVsH2QueryTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/IgniteVsH2QueryTest.java index 1f4771a..5da72b4 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/IgniteVsH2QueryTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/IgniteVsH2QueryTest.java @@ -526,7 +526,7 @@ public class IgniteVsH2QueryTest extends GridCommonAbstractTest { /** * @throws Exception If failed. */ - public void testSimpleReplSelect() throws Exception { + public void _testSimpleReplSelect() throws Exception { compareQueryRes0("select id, name, price from \"repl\".Product"); } @@ -555,6 +555,21 @@ public class IgniteVsH2QueryTest extends GridCommonAbstractTest { } /** + * + */ + public void testUnion() throws SQLException { + String base = "select _val v from \"part\".Person"; + + compareQueryRes0(base + " union all " + base); + compareQueryRes0(base + " union " + base); + + base = "select firstName||lastName name, salary from \"part\".Person"; + + assertEquals(10, compareOrderedQueryRes0(base + " union all " + base + " order by salary desc").size()); + assertEquals(5, compareOrderedQueryRes0(base + " union " + base + " order by salary desc").size()); + } + + /** * @throws Exception If failed. */ public void testEmptyResult() throws Exception {