ignite-gg9499 - avg wip
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/c85b7bea Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/c85b7bea Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/c85b7bea Branch: refs/heads/ignite-gg9499 Commit: c85b7bea4e6a60247b4bd270314bab76cfa95c14 Parents: f941e41 Author: S.Vladykin <svlady...@gridgain.com> Authored: Thu Jan 15 20:24:44 2015 +0300 Committer: S.Vladykin <svlady...@gridgain.com> Committed: Thu Jan 15 20:24:44 2015 +0300 ---------------------------------------------------------------------- .../query/h2/sql/GridSqlAggregateFunction.java | 7 + .../processors/query/h2/sql/GridSqlElement.java | 5 +- .../query/h2/sql/GridSqlQuerySplitter.java | 151 +++++++++++++++++-- 3 files changed, 152 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c85b7bea/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/sql/GridSqlAggregateFunction.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/sql/GridSqlAggregateFunction.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/sql/GridSqlAggregateFunction.java index a0daab0..c48644d 100644 --- a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/sql/GridSqlAggregateFunction.java +++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/sql/GridSqlAggregateFunction.java @@ -44,6 +44,13 @@ public class GridSqlAggregateFunction extends GridSqlFunction { this(distinct, TYPE_INDEX[typeId]); } + /** + * @return Distinct. + */ + public boolean distinct() { + return distinct; + } + /** {@inheritDoc} */ @Override public String getSQL() { String text; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c85b7bea/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/sql/GridSqlElement.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/sql/GridSqlElement.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/sql/GridSqlElement.java index 3a3acbe..16c824b 100644 --- a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/sql/GridSqlElement.java +++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/sql/GridSqlElement.java @@ -30,12 +30,15 @@ public abstract class GridSqlElement implements Cloneable { /** * @param expr Expr. + * @return {@code this}. */ - public void addChild(GridSqlElement expr) { + public GridSqlElement addChild(GridSqlElement expr) { if (expr == null) throw new NullPointerException(); children.add(expr); + + return this; } /** http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/c85b7bea/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/sql/GridSqlQuerySplitter.java ---------------------------------------------------------------------- diff --git a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/sql/GridSqlQuerySplitter.java b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/sql/GridSqlQuerySplitter.java index c9815cc..deeeae0 100644 --- a/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/sql/GridSqlQuerySplitter.java +++ b/modules/indexing/src/main/java/org/gridgain/grid/kernal/processors/query/h2/sql/GridSqlQuerySplitter.java @@ -9,11 +9,14 @@ package org.gridgain.grid.kernal.processors.query.h2.sql; +import org.apache.ignite.*; import org.gridgain.grid.kernal.processors.cache.query.*; import java.sql.*; import java.util.*; +import static org.gridgain.grid.kernal.processors.query.h2.sql.GridSqlFunctionType.*; + /** * Splits a single SQL query into two step map-reduce query. */ @@ -34,9 +37,9 @@ public class GridSqlQuerySplitter { /** * @param idx Index of column. - * @return Column alias. + * @return Generated by index column alias. */ - private static String column(int idx) { + private static String columnAlias(int idx) { return COLUMN_PREFIX + idx; } @@ -64,29 +67,34 @@ public class GridSqlQuerySplitter { mapQry.clearSelect(); + List<GridSqlElement> mapExps = new ArrayList<>(srcQry.allExpressions()); + + GridSqlElement[] rdcExps = new GridSqlElement[srcQry.select().size()]; + + for (int i = 0, len = mapExps.size(); i < len; i++) + splitSelectExpression(mapExps, rdcExps, i); + List<GridSqlAlias> aliases = new ArrayList<>(srcQry.allExpressions().size()); int idx = 0; - for (GridSqlElement exp : srcQry.allExpressions()) { // Add all expressions to select clause. + for (GridSqlElement exp : mapExps) { // Add all expressions to select clause. if (exp instanceof GridSqlColumn) - exp = new GridSqlAlias(((GridSqlColumn)exp).columnName(), exp); + exp = alias(((GridSqlColumn)exp).columnName(), exp); else if (!(exp instanceof GridSqlAlias)) - exp = new GridSqlAlias(column(idx), exp); + exp = alias(columnAlias(idx), exp); aliases.add((GridSqlAlias)exp); mapQry.addSelectExpression(exp); idx++; - - assert aliases.size() == idx; } mapQry.clearGroups(); for (int col : srcQry.groupColumns()) - mapQry.addGroupExpression(new GridSqlColumn(null, null, aliases.get(col).alias())); + mapQry.addGroupExpression(column(aliases.get(col).alias())); mapQry.clearSort(); // TODO sort support @@ -94,12 +102,12 @@ public class GridSqlQuerySplitter { GridSqlSelect rdcQry = new GridSqlSelect(); for (int i = 0; i < srcQry.select().size(); i++) - rdcQry.addSelectExpression(new GridSqlColumn(null, null, aliases.get(i).alias())); + rdcQry.addSelectExpression(column(aliases.get(i).alias())); rdcQry.from(new GridSqlTable(null, table(0))); for (int col : srcQry.groupColumns()) - rdcQry.addGroupExpression(new GridSqlColumn(null, null, aliases.get(col).alias())); + rdcQry.addGroupExpression(column(aliases.get(col).alias())); GridCacheTwoStepQuery res = new GridCacheTwoStepQuery(rdcQry.getSQL()); @@ -107,4 +115,127 @@ public class GridSqlQuerySplitter { return res; } + + /** + * @param exp Expression. + * @param idx Index in select. + * @return Natural or generated alias. + */ + private static String alias(GridSqlElement exp, int idx) { + if (exp instanceof GridSqlColumn) + return ((GridSqlColumn)exp).columnName(); + + if (exp instanceof GridSqlAlias) + return ((GridSqlAlias)exp).alias(); + + return columnAlias(idx); + } + + /** + * @param mapSelect Selects for map query. + * @param rdcSelect Selects for reduce query. + * @param idx Index. + */ + private static void splitSelectExpression(List<GridSqlElement> mapSelect, GridSqlElement[] rdcSelect, int idx) { + assert idx < rdcSelect.length; + + GridSqlElement el = mapSelect.get(idx); + + GridSqlAlias alias = null; + + if (el instanceof GridSqlAlias) { // Unwrap from alias. + alias = (GridSqlAlias)el; + el = alias.child(); + } + + if (el instanceof GridSqlAggregateFunction) { + GridSqlAggregateFunction agg = (GridSqlAggregateFunction)el; + + switch (agg.type()) { + case AVG: // Split AVG(x) into distributed SUM( AVG(x)*COUNT(x) )/SUM( COUNT(x) ). + //-- COUNT(x) map + GridSqlElement cntMap = aggregate(agg.distinct(), COUNT).addChild(agg.child()); // Add function argument. + + // Add generated alias to COUNT(x). + // Using size as index since COUNT will be added as the last select element to the map query. + cntMap = alias(columnAlias(mapSelect.size()), cntMap); + + mapSelect.add(cntMap); + + //-- AVG(x) map + GridSqlElement avgMap = aggregate(agg.distinct(), AVG).addChild(agg.child()); // Add function argument. + + // Add generated alias to AVG(x). + avgMap = alias(columnAlias(idx), avgMap); + + mapSelect.set(idx, avgMap); + + //-- SUM( AVG(x)*COUNT(x) )/SUM( COUNT(x) ) reduce + GridSqlElement sumUpRdc = aggregate(false, SUM).addChild( + op(GridSqlOperationType.MULTIPLY, + column(((GridSqlAlias)avgMap).alias()), + column(((GridSqlAlias)cntMap).alias()))); + + GridSqlElement sumDownRdc = aggregate(false, SUM).addChild( + column(((GridSqlAlias)cntMap).alias())); + + GridSqlElement rdc = op(GridSqlOperationType.DIVIDE, sumUpRdc, sumDownRdc); + + if (alias != null) // Add initial alias if it was set. + rdc = alias(alias.alias(), rdc); + + rdcSelect[idx] = rdc; + + break; + + case COUNT_ALL: + case COUNT: + case MAX: + case MIN: + case SUM: + case GROUP_CONCAT: + default: + throw new IgniteException("Unsupported aggregate: " + agg.type()); + } + } + else if (alias == null) { + + } + } + + /** + * @param distinct Distinct. + * @param type Type. + * @return Aggregate function. + */ + private static GridSqlAggregateFunction aggregate(boolean distinct, GridSqlFunctionType type) { + return new GridSqlAggregateFunction(distinct, type); + } + + /** + * @param name Column name. + * @return Column. + */ + private static GridSqlColumn column(String name) { + return new GridSqlColumn(null, name, name); + } + + /** + * @param alias Alias. + * @param child Child. + * @return Alias. + */ + private static GridSqlAlias alias(String alias, GridSqlElement child) { + return new GridSqlAlias(alias, child); + } + + /** + * @param type Type. + * @param left Left expression. + * @param right Right expression. + * @return Binary operator. + */ + private static GridSqlOperation op(GridSqlOperationType type, GridSqlElement left, GridSqlElement right) { + return new GridSqlOperation(type, left, right); + } }