Skip to content

Commit

Permalink
fix #63 derive column bug
Browse files Browse the repository at this point in the history
  • Loading branch information
gaoht committed May 6, 2016
1 parent dfb3c5c commit 180bb29
Show file tree
Hide file tree
Showing 15 changed files with 179 additions and 92 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/

package com.dangdang.ddframe.rdb.sharding.parser.result.merger;

import com.google.common.base.Optional;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;

/**
* 可排序列.
*
* @author gaohongtao.
*/
@ToString
@Getter
@RequiredArgsConstructor
public abstract class AbstractSortableColumn {

private final Optional<String> owner;

private final Optional<String> name;

private final Optional<String> alias;

private final OrderByColumn.OrderByType orderByType;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import com.dangdang.ddframe.rdb.sharding.parser.result.merger.OrderByColumn.OrderByType;
import com.google.common.base.Optional;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;

Expand All @@ -29,27 +28,24 @@
*
* @author zhangliang
*/
@RequiredArgsConstructor
@Getter
@ToString
public final class GroupByColumn implements IndexColumn {

private final String name;

private final String alias;

private final OrderByType orderByType;
@ToString(callSuper = true)
public final class GroupByColumn extends AbstractSortableColumn implements IndexColumn {

@Setter
private int columnIndex;

public GroupByColumn(final Optional<String> owner, final String name, final Optional<String> alias, final OrderByType orderByType) {
super(owner, Optional.of(name), alias, orderByType);
}

@Override
public Optional<String> getColumnLabel() {
return Optional.of(alias);
return getAlias();
}

@Override
public Optional<String> getColumnName() {
return Optional.of(name);
return getName();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public boolean groupByKeysEqualsOrderByKeys() {

@Override
public OrderByColumn apply(final GroupByColumn input) {
OrderByColumn result = new OrderByColumn(input.getName(), input.getAlias(), input.getOrderByType());
OrderByColumn result = new OrderByColumn(input.getOwner(), input.getName().get(), input.getAlias(), input.getOrderByType());
result.setColumnIndex(input.getColumnIndex());
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,41 +20,35 @@
import com.alibaba.druid.sql.ast.SQLOrderingSpecification;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.ToString;

/**
* 排序列对象.
*
* @author zhangliang
*/
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
@ToString
public final class OrderByColumn implements IndexColumn {

private final Optional<String> name;
@ToString(callSuper = true)
public final class OrderByColumn extends AbstractSortableColumn implements IndexColumn {

private final Optional<Integer> index;

private final Optional<String> alias;

private final OrderByType orderByType;

private int columnIndex;

public OrderByColumn(final String name, final String alias, final OrderByType orderByType) {
this(Optional.of(name), Optional.<Integer>absent(), Optional.fromNullable(alias), orderByType);
public OrderByColumn(final Optional<String> owner, final String name, final Optional<String> alias, final OrderByType orderByType) {
super(owner, Optional.of(name), alias, orderByType);
index = Optional.absent();
}

public OrderByColumn(final String name, final OrderByType orderByType) {
this(Optional.of(name), Optional.<Integer>absent(), Optional.<String>absent(), orderByType);
super(Optional.<String>absent(), Optional.of(name), Optional.<String>absent(), orderByType);
index = Optional.absent();
}

public OrderByColumn(final int index, final OrderByType orderByType) {
this(Optional.<String>absent(), Optional.of(index), Optional.<String>absent(), orderByType);
super(Optional.<String>absent(), Optional.<String>absent(), Optional.<String>absent(), orderByType);
this.index = Optional.of(index);
columnIndex = index;
}

Expand All @@ -68,12 +62,12 @@ public void setColumnIndex(final int index) {

@Override
public Optional<String> getColumnLabel() {
return alias;
return getAlias();
}

@Override
public Optional<String> getColumnName() {
return name;
return getName();
}

/**
Expand Down Expand Up @@ -105,14 +99,14 @@ public boolean equals(final Object o) {
return false;
}
OrderByColumn that = (OrderByColumn) o;
return orderByType == that.orderByType && (columnIndex == that.columnIndex
return getOrderByType() == that.getOrderByType() && (columnIndex == that.columnIndex
|| index.isPresent() && that.index.isPresent() && index.get().equals(that.index.get())
|| name.isPresent() && that.name.isPresent() && name.get().equals(that.name.get())
|| alias.isPresent() && that.alias.isPresent() && alias.get().equals(that.alias.get()));
|| getName().isPresent() && that.getName().isPresent() && getName().get().equals(that.getName().get())
|| getAlias().isPresent() && that.getAlias().isPresent() && getAlias().get().equals(that.getAlias().get()));
}

@Override
public int hashCode() {
return Objects.hashCode(orderByType, columnIndex);
return Objects.hashCode(getOrderByType(), columnIndex);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,10 @@ private AggregationColumn getDerivedCountColumn(final AggregationColumn avgColum
return new AggregationColumn(expression, AggregationType.COUNT, Optional.of(generateDerivedColumnAlias()), avgColumn.getOption());
}

private String generateDerivedColumnAlias() {
return String.format(SHARDING_GEN_ALIAS, ++selectItemsCount);
}

private AggregationColumn getDerivedSumColumn(final AggregationColumn avgColumn) {
String expression = avgColumn.getExpression().replaceFirst(AggregationType.AVG.toString(), AggregationType.SUM.toString());
if (avgColumn.getOption().isPresent()) {
Expand All @@ -296,16 +300,20 @@ public void addOrderByColumn(final int index, final OrderByType orderByType) {
/**
* 将排序列加入解析上下文.
*
* @param owner 列拥有者
* @param name 列名称
* @param orderByType 排序类型
*/
public void addOrderByColumn(final String name, final OrderByType orderByType) {
public void addOrderByColumn(final Optional<String> owner, final String name, final OrderByType orderByType) {
String rawName = SQLUtil.getExactlyValue(name);
String alias = null;
if (!containsSelectItem(rawName)) {
alias = generateDerivedColumnAlias();
parsedResult.getMergeContext().getOrderByColumns().add(new OrderByColumn(owner, rawName, getAlias(rawName), orderByType));
}

private Optional<String> getAlias(final String name) {
if (containsSelectItem(name)) {
return Optional.absent();
}
parsedResult.getMergeContext().getOrderByColumns().add(new OrderByColumn(rawName, alias, orderByType));
return Optional.of(generateDerivedColumnAlias());
}

private boolean containsSelectItem(final String selectItem) {
Expand All @@ -315,28 +323,42 @@ private boolean containsSelectItem(final String selectItem) {
/**
* 将分组列加入解析上下文.
*
* @param owner 列拥有者
* @param name 列名称
* @param alias 列别名
* @param orderByType 排序类型
*/
public void addGroupByColumns(final String name, final String alias, final OrderByType orderByType) {
parsedResult.getMergeContext().getGroupByColumns().add(new GroupByColumn(SQLUtil.getExactlyValue(name), alias, orderByType));
public void addGroupByColumns(final Optional<String> owner, final String name, final OrderByType orderByType) {
String rawName = SQLUtil.getExactlyValue(name);
parsedResult.getMergeContext().getGroupByColumns().add(new GroupByColumn(owner, rawName, getAlias(rawName), orderByType));
}

/**
* 生成补列别名.
*
* @return 补列的别名
*/
public String generateDerivedColumnAlias() {
return String.format(SHARDING_GEN_ALIAS, ++selectItemsCount);
}

/**
* 将当前解析的条件对象归并入解析结果.
*/
public void mergeCurrentConditionContext() {
parsedResult.getConditionContexts().add(currentConditionContext);
if (!parsedResult.getRouteContext().getTables().isEmpty()) {
parsedResult.getConditionContexts().add(currentConditionContext);
return;
}
Optional<SQLParsedResult> target = findValidParseResult();
if (!target.isPresent()) {
parsedResult.getConditionContexts().add(currentConditionContext);
return;
}
parsedResult.getRouteContext().getTables().addAll(target.get().getRouteContext().getTables());
parsedResult.getConditionContexts().addAll(target.get().getConditionContexts());
}

private Optional<SQLParsedResult> findValidParseResult() {
for (ParseContext each : subParseContext) {
each.mergeCurrentConditionContext();
if (each.getParsedResult().getRouteContext().getTables().isEmpty()) {
continue;
}
return Optional.of(each.getParsedResult());
}
return Optional.absent();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,10 @@
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlSelectGroupByExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
import com.dangdang.ddframe.rdb.sharding.parser.result.merger.AbstractSortableColumn;
import com.dangdang.ddframe.rdb.sharding.parser.result.merger.AggregationColumn;
import com.dangdang.ddframe.rdb.sharding.parser.result.merger.AggregationColumn.AggregationType;
import com.dangdang.ddframe.rdb.sharding.parser.result.merger.GroupByColumn;
import com.dangdang.ddframe.rdb.sharding.parser.result.merger.Limit;
import com.dangdang.ddframe.rdb.sharding.parser.result.merger.OrderByColumn;
import com.dangdang.ddframe.rdb.sharding.parser.result.merger.OrderByColumn.OrderByType;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
Expand Down Expand Up @@ -123,9 +122,11 @@ public boolean visit(final SQLOrderBy x) {
if (expr instanceof SQLIntegerExpr) {
getParseContext().addOrderByColumn(((SQLIntegerExpr) expr).getNumber().intValue(), orderByType);
} else if (expr instanceof SQLIdentifierExpr) {
getParseContext().addOrderByColumn(((SQLIdentifierExpr) expr).getName(), orderByType);
getParseContext().addOrderByColumn(Optional.<String>absent(), ((SQLIdentifierExpr) expr).getName(), orderByType);
} else if (expr instanceof SQLPropertyExpr) {
getParseContext().addOrderByColumn(((SQLPropertyExpr) expr).getName(), orderByType);
SQLPropertyExpr sqlPropertyExpr = (SQLPropertyExpr) expr;
getParseContext().addOrderByColumn(Optional.of(sqlPropertyExpr.getOwner().toString()), sqlPropertyExpr.getName(), orderByType);

}
}
return super.visit(x);
Expand All @@ -140,14 +141,13 @@ public boolean visit(final SQLOrderBy x) {
*/
@Override
public boolean visit(final MySqlSelectGroupByExpr x) {
String alias = getParseContext().generateDerivedColumnAlias();
OrderByType orderByType = null == x.getType() ? OrderByType.ASC : OrderByType.valueOf(x.getType());
if (x.getExpr() instanceof SQLPropertyExpr) {
SQLPropertyExpr expr = (SQLPropertyExpr) x.getExpr();
getParseContext().addGroupByColumns(expr.toString(), alias, orderByType);
getParseContext().addGroupByColumns(Optional.of(expr.getOwner().toString()), expr.getName(), orderByType);
} else if (x.getExpr() instanceof SQLIdentifierExpr) {
SQLIdentifierExpr expr = (SQLIdentifierExpr) x.getExpr();
getParseContext().addGroupByColumns(expr.getName(), alias, orderByType);
getParseContext().addGroupByColumns(Optional.<String>absent(), expr.getName(), orderByType);
}
return super.visit(x);
}
Expand Down Expand Up @@ -193,18 +193,25 @@ public void endVisit(final MySqlSelectQueryBlock x) {
derivedSelectItems.append(", ").append(derivedColumn.getExpression()).append(" AS ").append(derivedColumn.getAlias().get());
}
}
for (GroupByColumn each : getParseContext().getParsedResult().getMergeContext().getGroupByColumns()) {
derivedSelectItems.append(", ").append(each.getName()).append(" AS ").append(each.getAlias());
}
for (OrderByColumn each : getParseContext().getParsedResult().getMergeContext().getOrderByColumns()) {
if (each.getAlias().isPresent()) {
derivedSelectItems.append(", ").append(each.getName().get()).append(" AS ").append(each.getAlias().get());
}
}
appendSortableColumn(derivedSelectItems, getParseContext().getParsedResult().getMergeContext().getGroupByColumns());
appendSortableColumn(derivedSelectItems, getParseContext().getParsedResult().getMergeContext().getOrderByColumns());
if (0 != derivedSelectItems.length()) {
getSQLBuilder().buildSQL(getParseContext().getAutoGenTokenKey(), derivedSelectItems.toString());
}
super.endVisit(x);
stepOutQuery();
}

private void appendSortableColumn(final StringBuilder derivedSelectItems, final List<? extends AbstractSortableColumn> sortableColumns) {
for (AbstractSortableColumn each : sortableColumns) {
if (!each.getAlias().isPresent()) {
continue;
}
derivedSelectItems.append(", ");
if (each.getOwner().isPresent()) {
derivedSelectItems.append(each.getOwner().get()).append(".");
}
derivedSelectItems.append(each.getName().get()).append(" AS ").append(each.getAlias().get());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public void testToString() throws Exception {
MockResultSet rs = new MockResultSet<>(Arrays.asList(rs1, rs2));
assertThat(rs.next(), is(true));

GroupByColumn groupByColumn = new GroupByColumn("user_id", "", OrderByColumn.OrderByType.ASC);
GroupByColumn groupByColumn = new GroupByColumn(Optional.<String>absent(), "user_id", Optional.<String>absent(), OrderByColumn.OrderByType.ASC);
groupByColumn.setColumnIndex(1);
AggregationColumn aggregationColumn = new AggregationColumn("SUM(0)", AggregationColumn.AggregationType.SUM, Optional.<String>absent(), Optional.<String>absent());
aggregationColumn.setColumnIndex(2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public Comparable<?> apply(final Value input) {
@Override
public OrderByColumn apply(final com.dangdang.ddframe.rdb.sharding.parser.jaxb.OrderByColumn input) {
return Strings.isNullOrEmpty(input.getName()) ? new OrderByColumn(input.getIndex(), OrderByType.valueOf(input.getOrderByType().toUpperCase()))
: new OrderByColumn(input.getName(), input.getAlias(), OrderByType.valueOf(input.getOrderByType().toUpperCase()));
: new OrderByColumn(Optional.fromNullable(input.getOwner()), input.getName(), Optional.fromNullable(input.getAlias()), OrderByType.valueOf(input.getOrderByType().toUpperCase()));
}
}));
}
Expand All @@ -168,7 +168,7 @@ public OrderByColumn apply(final com.dangdang.ddframe.rdb.sharding.parser.jaxb.O

@Override
public GroupByColumn apply(final com.dangdang.ddframe.rdb.sharding.parser.jaxb.GroupByColumn input) {
return new GroupByColumn(input.getName(), input.getAlias(), OrderByType.valueOf(input.getOrderByType().toUpperCase()));
return new GroupByColumn(Optional.fromNullable(input.getOwner()), input.getName(), Optional.fromNullable(input.getAlias()), OrderByType.valueOf(input.getOrderByType().toUpperCase()));
}
}));
}
Expand Down
Loading

0 comments on commit 180bb29

Please sign in to comment.