提交 056d9419 编写于 作者: T terrymanu

fixed #341

上级 16d07c37
## 1.5.2
### 功能提升
1. [ISSUE #335](https://github.com/dangdangdotcom/sharding-jdbc/issues/335) 支持GROUP BY + 自定义函数的SQL
1. [ISSUE #341](https://github.com/dangdangdotcom/sharding-jdbc/issues/341) 支持Oracle中的ORDER BY xxx NULLS FIRST | LAST 语句
### 缺陷修正
1. [ISSUE #334](https://github.com/dangdangdotcom/sharding-jdbc/issues/334) 解析有函数的ORDER BY会将后面的ASC, DESC解析到OrderItem的name属性中
1. [ISSUE #335](https://github.com/dangdangdotcom/sharding-jdbc/issues/335) 支持GROUP BY + 自定义函数的SQL
1. [ISSUE #335](https://github.com/dangdangdotcom/sharding-jdbc/issues/339) 使用表全名关联的JOIN解析不正确
## 1.5.1
......
......@@ -18,7 +18,6 @@
package com.dangdang.ddframe.rdb.sharding.merger;
import com.dangdang.ddframe.rdb.sharding.constant.DatabaseType;
import com.dangdang.ddframe.rdb.sharding.constant.OrderType;
import com.dangdang.ddframe.rdb.sharding.merger.groupby.GroupByMemoryResultSetMerger;
import com.dangdang.ddframe.rdb.sharding.merger.groupby.GroupByStreamResultSetMerger;
import com.dangdang.ddframe.rdb.sharding.merger.iterator.IteratorStreamResultSetMerger;
......@@ -79,13 +78,13 @@ public final class MergeEngine {
private ResultSetMerger build() throws SQLException {
if (!selectStatement.getGroupByItems().isEmpty() || !selectStatement.getAggregationSelectItems().isEmpty()) {
if (selectStatement.isSameGroupByAndOrderByItems()) {
return new GroupByStreamResultSetMerger(columnLabelIndexMap, resultSets, selectStatement, getNullOrderType());
return new GroupByStreamResultSetMerger(columnLabelIndexMap, resultSets, selectStatement);
} else {
return new GroupByMemoryResultSetMerger(columnLabelIndexMap, resultSets, selectStatement, getNullOrderType());
return new GroupByMemoryResultSetMerger(columnLabelIndexMap, resultSets, selectStatement);
}
}
if (!selectStatement.getOrderByItems().isEmpty()) {
return new OrderByStreamResultSetMerger(resultSets, selectStatement.getOrderByItems(), getNullOrderType());
return new OrderByStreamResultSetMerger(resultSets, selectStatement.getOrderByItems());
}
return new IteratorStreamResultSetMerger(resultSets);
}
......@@ -97,11 +96,4 @@ public final class MergeEngine {
}
return result;
}
private OrderType getNullOrderType() {
if (DatabaseType.MySQL == databaseType || DatabaseType.Oracle == databaseType || DatabaseType.H2 == databaseType) {
return OrderType.ASC;
}
return OrderType.DESC;
}
}
......@@ -17,7 +17,6 @@
package com.dangdang.ddframe.rdb.sharding.merger.groupby;
import com.dangdang.ddframe.rdb.sharding.constant.OrderType;
import com.dangdang.ddframe.rdb.sharding.merger.common.AbstractMemoryResultSetMerger;
import com.dangdang.ddframe.rdb.sharding.merger.common.MemoryResultSetRow;
import com.dangdang.ddframe.rdb.sharding.merger.groupby.aggregation.AggregationUnit;
......@@ -47,15 +46,12 @@ public final class GroupByMemoryResultSetMerger extends AbstractMemoryResultSetM
private final SelectStatement selectStatement;
private final OrderType nullOrderType;
private final Iterator<MemoryResultSetRow> memoryResultSetRows;
public GroupByMemoryResultSetMerger(
final Map<String, Integer> labelAndIndexMap, final List<ResultSet> resultSets, final SelectStatement selectStatement, final OrderType nullOrderType) throws SQLException {
final Map<String, Integer> labelAndIndexMap, final List<ResultSet> resultSets, final SelectStatement selectStatement) throws SQLException {
super(labelAndIndexMap);
this.selectStatement = selectStatement;
this.nullOrderType = nullOrderType;
memoryResultSetRows = init(resultSets);
}
......@@ -124,7 +120,7 @@ public final class GroupByMemoryResultSetMerger extends AbstractMemoryResultSetM
private List<MemoryResultSetRow> getMemoryResultSetRows(final Map<GroupByValue, MemoryResultSetRow> dataMap) {
List<MemoryResultSetRow> result = new ArrayList<>(dataMap.values());
Collections.sort(result, new GroupByRowComparator(selectStatement, nullOrderType));
Collections.sort(result, new GroupByRowComparator(selectStatement));
return result;
}
......
......@@ -17,7 +17,6 @@
package com.dangdang.ddframe.rdb.sharding.merger.groupby;
import com.dangdang.ddframe.rdb.sharding.constant.OrderType;
import com.dangdang.ddframe.rdb.sharding.merger.common.MemoryResultSetRow;
import com.dangdang.ddframe.rdb.sharding.merger.util.ResultSetUtil;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.OrderItem;
......@@ -38,8 +37,6 @@ public final class GroupByRowComparator implements Comparator<MemoryResultSetRow
private final SelectStatement selectStatement;
private final OrderType nullOrderType;
@Override
public int compare(final MemoryResultSetRow o1, final MemoryResultSetRow o2) {
if (!selectStatement.getOrderByItems().isEmpty()) {
......@@ -54,7 +51,7 @@ public final class GroupByRowComparator implements Comparator<MemoryResultSetRow
Preconditions.checkState(null == orderValue1 || orderValue1 instanceof Comparable, "Order by value must implements Comparable");
Object orderValue2 = o2.getCell(each.getIndex());
Preconditions.checkState(null == orderValue2 || orderValue2 instanceof Comparable, "Order by value must implements Comparable");
int result = ResultSetUtil.compareTo((Comparable) orderValue1, (Comparable) orderValue2, each.getType(), nullOrderType);
int result = ResultSetUtil.compareTo((Comparable) orderValue1, (Comparable) orderValue2, each.getType(), each.getNullOrderType());
if (0 != result) {
return result;
}
......
......@@ -17,7 +17,6 @@
package com.dangdang.ddframe.rdb.sharding.merger.groupby;
import com.dangdang.ddframe.rdb.sharding.constant.OrderType;
import com.dangdang.ddframe.rdb.sharding.merger.groupby.aggregation.AggregationUnit;
import com.dangdang.ddframe.rdb.sharding.merger.groupby.aggregation.AggregationUnitFactory;
import com.dangdang.ddframe.rdb.sharding.merger.orderby.OrderByStreamResultSetMerger;
......@@ -52,8 +51,8 @@ public final class GroupByStreamResultSetMerger extends OrderByStreamResultSetMe
private List<?> currentGroupByValues;
public GroupByStreamResultSetMerger(
final Map<String, Integer> labelAndIndexMap, final List<ResultSet> resultSets, final SelectStatement selectStatement, final OrderType nullOrderType) throws SQLException {
super(resultSets, selectStatement.getOrderByItems(), nullOrderType);
final Map<String, Integer> labelAndIndexMap, final List<ResultSet> resultSets, final SelectStatement selectStatement) throws SQLException {
super(resultSets, selectStatement.getOrderByItems());
this.labelAndIndexMap = labelAndIndexMap;
this.selectStatement = selectStatement;
currentRow = new ArrayList<>(labelAndIndexMap.size());
......
......@@ -17,7 +17,6 @@
package com.dangdang.ddframe.rdb.sharding.merger.orderby;
import com.dangdang.ddframe.rdb.sharding.constant.OrderType;
import com.dangdang.ddframe.rdb.sharding.merger.common.AbstractStreamResultSetMerger;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.OrderItem;
import lombok.AccessLevel;
......@@ -42,21 +41,18 @@ public class OrderByStreamResultSetMerger extends AbstractStreamResultSetMerger
private final Queue<OrderByValue> orderByValuesQueue;
private final OrderType nullOrderType;
private boolean isFirstNext;
public OrderByStreamResultSetMerger(final List<ResultSet> resultSets, final List<OrderItem> orderByItems, final OrderType nullOrderType) throws SQLException {
public OrderByStreamResultSetMerger(final List<ResultSet> resultSets, final List<OrderItem> orderByItems) throws SQLException {
this.orderByItems = orderByItems;
this.orderByValuesQueue = new PriorityQueue<>(resultSets.size());
this.nullOrderType = nullOrderType;
orderResultSetsToQueue(resultSets);
isFirstNext = true;
}
private void orderResultSetsToQueue(final List<ResultSet> resultSets) throws SQLException {
for (ResultSet each : resultSets) {
OrderByValue orderByValue = new OrderByValue(each, orderByItems, nullOrderType);
OrderByValue orderByValue = new OrderByValue(each, orderByItems);
if (orderByValue.next()) {
orderByValuesQueue.offer(orderByValue);
}
......
......@@ -17,7 +17,6 @@
package com.dangdang.ddframe.rdb.sharding.merger.orderby;
import com.dangdang.ddframe.rdb.sharding.constant.OrderType;
import com.dangdang.ddframe.rdb.sharding.merger.util.ResultSetUtil;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.OrderItem;
import com.google.common.base.Preconditions;
......@@ -43,8 +42,6 @@ public final class OrderByValue implements Comparable<OrderByValue> {
private final List<OrderItem> orderByItems;
private final OrderType nullOrderType;
private List<Comparable<?>> orderValues;
/**
......@@ -73,7 +70,7 @@ public final class OrderByValue implements Comparable<OrderByValue> {
public int compareTo(final OrderByValue o) {
for (int i = 0; i < orderByItems.size(); i++) {
OrderItem thisOrderBy = orderByItems.get(i);
int result = ResultSetUtil.compareTo(orderValues.get(i), o.orderValues.get(i), thisOrderBy.getType(), nullOrderType);
int result = ResultSetUtil.compareTo(orderValues.get(i), o.orderValues.get(i), thisOrderBy.getType(), thisOrderBy.getNullOrderType());
if (0 != result) {
return result;
}
......
......@@ -41,29 +41,34 @@ public final class OrderItem {
private final OrderType type;
private final OrderType nullOrderType;
private int index = -1;
private Optional<String> alias;
public OrderItem(final String name, final OrderType type, final Optional<String> alias) {
public OrderItem(final String name, final OrderType type, final OrderType nullOrderType, final Optional<String> alias) {
this.owner = Optional.absent();
this.name = Optional.of(name);
this.type = type;
this.nullOrderType = nullOrderType;
this.alias = alias;
}
public OrderItem(final String owner, final String name, final OrderType type, final Optional<String> alias) {
public OrderItem(final String owner, final String name, final OrderType type, final OrderType nullOrderType, final Optional<String> alias) {
this.owner = Optional.of(owner);
this.name = Optional.of(name);
this.type = type;
this.nullOrderType = nullOrderType;
this.alias = alias;
}
public OrderItem(final int index, final OrderType type) {
public OrderItem(final int index, final OrderType type, final OrderType nullOrderType) {
owner = Optional.absent();
name = Optional.absent();
this.index = index;
this.type = type;
this.nullOrderType = nullOrderType;
alias = Optional.absent();
}
......
......@@ -18,6 +18,7 @@
package com.dangdang.ddframe.rdb.sharding.parsing.parser.dialect.mysql;
import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
import com.dangdang.ddframe.rdb.sharding.constant.OrderType;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.dialect.mysql.MySQLKeyword;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.dialect.oracle.OracleKeyword;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.DefaultKeyword;
......@@ -207,6 +208,11 @@ public final class MySQLSelectParser extends AbstractSelectParser {
return new Keyword[] {DefaultKeyword.WITH, MySQLKeyword.ROLLUP};
}
@Override
protected OrderType getNullOrderType() {
return OrderType.ASC;
}
@Override
protected Keyword[] getUnsupportedKeywordsRest() {
return new Keyword[] {DefaultKeyword.PROCEDURE, DefaultKeyword.INTO};
......
......@@ -18,12 +18,14 @@
package com.dangdang.ddframe.rdb.sharding.parsing.parser.dialect.oracle;
import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
import com.dangdang.ddframe.rdb.sharding.constant.OrderType;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.dialect.oracle.OracleKeyword;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.DefaultKeyword;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.Keyword;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.Symbol;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.AbstractSQLParser;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.context.selectitem.SelectItem;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.exception.SQLParsingException;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.exception.SQLParsingUnsupportedException;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.statement.dql.select.AbstractSelectParser;
import com.dangdang.ddframe.rdb.sharding.parsing.parser.statement.dql.select.SelectStatement;
......@@ -269,12 +271,16 @@ public final class OracleSelectParser extends AbstractSelectParser {
}
@Override
protected void skipAfterOrderByItem(final SelectStatement selectStatement) {
// TODO support order for null
if (getSqlParser().skipIfEqual(OracleKeyword.NULLS)) {
if (!getSqlParser().skipIfEqual(OracleKeyword.FIRST, OracleKeyword.LAST)) {
throw new SQLParsingUnsupportedException(getSqlParser().getLexer().getCurrentToken().getType());
}
protected OrderType getNullOrderType() {
if (!getSqlParser().skipIfEqual(OracleKeyword.NULLS)) {
return OrderType.ASC;
}
if (getSqlParser().skipIfEqual(OracleKeyword.FIRST)) {
return OrderType.ASC;
}
if (getSqlParser().skipIfEqual(OracleKeyword.LAST)) {
return OrderType.DESC;
}
throw new SQLParsingException(getSqlParser().getLexer());
}
}
......@@ -18,6 +18,7 @@
package com.dangdang.ddframe.rdb.sharding.parsing.parser.dialect.postgresql;
import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
import com.dangdang.ddframe.rdb.sharding.constant.OrderType;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.dialect.postgresql.PostgreSQLKeyword;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.DefaultKeyword;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.Keyword;
......@@ -143,6 +144,11 @@ public final class PostgreSQLSelectParser extends AbstractSelectParser {
getSqlParser().skipIfEqual(PostgreSQLKeyword.NOWAIT);
}
@Override
protected OrderType getNullOrderType() {
return OrderType.DESC;
}
@Override
protected Keyword[] getUnsupportedKeywordsRest() {
return new Keyword[] {PostgreSQLKeyword.WINDOW, DefaultKeyword.FETCH};
......
......@@ -18,6 +18,7 @@
package com.dangdang.ddframe.rdb.sharding.parsing.parser.dialect.sqlserver;
import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
import com.dangdang.ddframe.rdb.sharding.constant.OrderType;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.dialect.sqlserver.SQLServerKeyword;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.DefaultKeyword;
import com.dangdang.ddframe.rdb.sharding.parsing.lexer.token.Literals;
......@@ -184,4 +185,9 @@ public final class SQLServerSelectParser extends AbstractSelectParser {
}
super.parseJoinTable(selectStatement);
}
@Override
protected OrderType getNullOrderType() {
return OrderType.DESC;
}
}
......@@ -307,14 +307,15 @@ public abstract class AbstractSelectParser implements SQLStatementParser {
OrderItem orderItem;
if (sqlExpression instanceof SQLPropertyExpression) {
SQLPropertyExpression sqlPropertyExpression = (SQLPropertyExpression) sqlExpression;
orderItem = new OrderItem(SQLUtil.getExactlyValue(sqlPropertyExpression.getOwner().getName()), SQLUtil.getExactlyValue(sqlPropertyExpression.getName()), orderByType,
orderItem = new OrderItem(SQLUtil.getExactlyValue(sqlPropertyExpression.getOwner().getName()), SQLUtil.getExactlyValue(sqlPropertyExpression.getName()), orderByType, getNullOrderType(),
getAlias(SQLUtil.getExactlyValue(sqlPropertyExpression.getOwner() + "." + SQLUtil.getExactlyValue(sqlPropertyExpression.getName())), selectStatement));
} else if (sqlExpression instanceof SQLIdentifierExpression) {
SQLIdentifierExpression sqlIdentifierExpression = (SQLIdentifierExpression) sqlExpression;
orderItem = new OrderItem(SQLUtil.getExactlyValue(sqlIdentifierExpression.getName()), orderByType, getAlias(SQLUtil.getExactlyValue(sqlIdentifierExpression.getName()), selectStatement));
orderItem = new OrderItem(
SQLUtil.getExactlyValue(sqlIdentifierExpression.getName()), orderByType, getNullOrderType(), getAlias(SQLUtil.getExactlyValue(sqlIdentifierExpression.getName()), selectStatement));
} else if (sqlExpression instanceof SQLIgnoreExpression) {
SQLIgnoreExpression sqlIgnoreExpression = (SQLIgnoreExpression) sqlExpression;
orderItem = new OrderItem(sqlIgnoreExpression.getExpression(), orderByType, getAlias(sqlIgnoreExpression.getExpression(), selectStatement));
orderItem = new OrderItem(sqlIgnoreExpression.getExpression(), orderByType, getNullOrderType(), getAlias(sqlIgnoreExpression.getExpression(), selectStatement));
} else {
return;
}
......@@ -359,26 +360,24 @@ public abstract class AbstractSelectParser implements SQLStatementParser {
}
OrderItem result;
if (sqlExpression instanceof SQLNumberExpression) {
result = new OrderItem(((SQLNumberExpression) sqlExpression).getNumber().intValue(), orderByType);
result = new OrderItem(((SQLNumberExpression) sqlExpression).getNumber().intValue(), orderByType, getNullOrderType());
} else if (sqlExpression instanceof SQLIdentifierExpression) {
result = new OrderItem(SQLUtil.getExactlyValue(((SQLIdentifierExpression) sqlExpression).getName()),
orderByType, getAlias(SQLUtil.getExactlyValue(((SQLIdentifierExpression) sqlExpression).getName()), selectStatement));
orderByType, getNullOrderType(), getAlias(SQLUtil.getExactlyValue(((SQLIdentifierExpression) sqlExpression).getName()), selectStatement));
} else if (sqlExpression instanceof SQLPropertyExpression) {
SQLPropertyExpression sqlPropertyExpression = (SQLPropertyExpression) sqlExpression;
result = new OrderItem(SQLUtil.getExactlyValue(sqlPropertyExpression.getOwner().getName()), SQLUtil.getExactlyValue(sqlPropertyExpression.getName()), orderByType,
result = new OrderItem(SQLUtil.getExactlyValue(sqlPropertyExpression.getOwner().getName()), SQLUtil.getExactlyValue(sqlPropertyExpression.getName()), orderByType, getNullOrderType(),
getAlias(SQLUtil.getExactlyValue(sqlPropertyExpression.getOwner().getName()) + "." + SQLUtil.getExactlyValue(sqlPropertyExpression.getName()), selectStatement));
} else if (sqlExpression instanceof SQLIgnoreExpression) {
SQLIgnoreExpression sqlIgnoreExpression = (SQLIgnoreExpression) sqlExpression;
result = new OrderItem(sqlIgnoreExpression.getExpression(), orderByType, getAlias(sqlIgnoreExpression.getExpression(), selectStatement));
result = new OrderItem(sqlIgnoreExpression.getExpression(), orderByType, getNullOrderType(), getAlias(sqlIgnoreExpression.getExpression(), selectStatement));
} else {
throw new SQLParsingException(sqlParser.getLexer());
}
skipAfterOrderByItem(selectStatement);
return result;
}
protected void skipAfterOrderByItem(final SelectStatement selectStatement) {
}
protected abstract OrderType getNullOrderType();
private Optional<String> getAlias(final String name, final SelectStatement selectStatement) {
if (selectStatement.isContainStar()) {
......
......@@ -81,7 +81,7 @@ public final class MergeEngineTest {
@Test
public void assertBuildOrderByStreamResultSetMerger() throws SQLException {
selectStatement.getOrderByItems().add(new OrderItem(1, OrderType.DESC));
selectStatement.getOrderByItems().add(new OrderItem(1, OrderType.DESC, OrderType.ASC));
mergeEngine = new MergeEngine(DatabaseType.MySQL, resultSets, selectStatement);
assertThat(mergeEngine.merge(), instanceOf(OrderByStreamResultSetMerger.class));
}
......@@ -89,7 +89,7 @@ public final class MergeEngineTest {
@Test
public void assertBuildOrderByStreamResultSetMergerWithLimit() throws SQLException {
selectStatement.setLimit(new Limit(true));
selectStatement.getOrderByItems().add(new OrderItem(1, OrderType.DESC));
selectStatement.getOrderByItems().add(new OrderItem(1, OrderType.DESC, OrderType.ASC));
mergeEngine = new MergeEngine(DatabaseType.MySQL, resultSets, selectStatement);
ResultSetMerger actual = mergeEngine.merge();
assertThat(actual, instanceOf(LimitDecoratorResultSetMerger.class));
......@@ -98,8 +98,8 @@ public final class MergeEngineTest {
@Test
public void assertBuildGroupByStreamResultSetMerger() throws SQLException {
selectStatement.getGroupByItems().add(new OrderItem(1, OrderType.DESC));
selectStatement.getOrderByItems().add(new OrderItem(1, OrderType.DESC));
selectStatement.getGroupByItems().add(new OrderItem(1, OrderType.DESC, OrderType.ASC));
selectStatement.getOrderByItems().add(new OrderItem(1, OrderType.DESC, OrderType.ASC));
mergeEngine = new MergeEngine(DatabaseType.MySQL, resultSets, selectStatement);
assertThat(mergeEngine.merge(), instanceOf(GroupByStreamResultSetMerger.class));
}
......@@ -107,8 +107,8 @@ public final class MergeEngineTest {
@Test
public void assertBuildGroupByStreamResultSetMergerWithLimit() throws SQLException {
selectStatement.setLimit(new Limit(true));
selectStatement.getGroupByItems().add(new OrderItem(1, OrderType.DESC));
selectStatement.getOrderByItems().add(new OrderItem(1, OrderType.DESC));
selectStatement.getGroupByItems().add(new OrderItem(1, OrderType.DESC, OrderType.ASC));
selectStatement.getOrderByItems().add(new OrderItem(1, OrderType.DESC, OrderType.ASC));
mergeEngine = new MergeEngine(DatabaseType.MySQL, resultSets, selectStatement);
ResultSetMerger actual = mergeEngine.merge();
assertThat(actual, instanceOf(LimitDecoratorResultSetMerger.class));
......@@ -117,7 +117,7 @@ public final class MergeEngineTest {
@Test
public void assertBuildGroupByMemoryResultSetMerger() throws SQLException {
selectStatement.getGroupByItems().add(new OrderItem(1, OrderType.DESC));
selectStatement.getGroupByItems().add(new OrderItem(1, OrderType.DESC, OrderType.ASC));
mergeEngine = new MergeEngine(DatabaseType.MySQL, resultSets, selectStatement);
assertThat(mergeEngine.merge(), instanceOf(GroupByMemoryResultSetMerger.class));
}
......@@ -125,7 +125,7 @@ public final class MergeEngineTest {
@Test
public void assertBuildGroupByMemoryResultSetMergerWithLimit() throws SQLException {
selectStatement.setLimit(new Limit(true));
selectStatement.getGroupByItems().add(new OrderItem(1, OrderType.DESC));
selectStatement.getGroupByItems().add(new OrderItem(1, OrderType.DESC, OrderType.ASC));
mergeEngine = new MergeEngine(DatabaseType.MySQL, resultSets, selectStatement);
ResultSetMerger actual = mergeEngine.merge();
assertThat(actual, instanceOf(LimitDecoratorResultSetMerger.class));
......
......@@ -67,8 +67,8 @@ public final class GroupByMemoryResultSetMergerTest {
aggregationSelectItem2.getDerivedAggregationSelectItems().add(derivedAggregationSelectItem2);
selectStatement.getItems().add(aggregationSelectItem1);
selectStatement.getItems().add(aggregationSelectItem2);
selectStatement.getGroupByItems().add(new OrderItem(3, OrderType.ASC));
selectStatement.getOrderByItems().add(new OrderItem(3, OrderType.DESC));
selectStatement.getGroupByItems().add(new OrderItem(3, OrderType.ASC, OrderType.ASC));
selectStatement.getOrderByItems().add(new OrderItem(3, OrderType.DESC, OrderType.ASC));
}
private ResultSet mockResultSet() throws SQLException {
......
......@@ -41,9 +41,9 @@ public final class GroupByRowComparatorTest {
MemoryResultSetRow o1 = new MemoryResultSetRow(mockResult("1", "2"));
MemoryResultSetRow o2 = new MemoryResultSetRow(mockResult("3", "4"));
SelectStatement selectStatement = new SelectStatement();
selectStatement.getOrderByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.ASC), new OrderItem(2, OrderType.ASC)));
selectStatement.getGroupByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.DESC), new OrderItem(2, OrderType.DESC)));
GroupByRowComparator groupByRowComparator = new GroupByRowComparator(selectStatement, OrderType.ASC);
selectStatement.getOrderByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.ASC, OrderType.ASC), new OrderItem(2, OrderType.ASC, OrderType.ASC)));
selectStatement.getGroupByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.DESC, OrderType.ASC), new OrderItem(2, OrderType.DESC, OrderType.ASC)));
GroupByRowComparator groupByRowComparator = new GroupByRowComparator(selectStatement);
assertTrue(groupByRowComparator.compare(o1, o2) < 0);
}
......@@ -52,9 +52,9 @@ public final class GroupByRowComparatorTest {
MemoryResultSetRow o1 = new MemoryResultSetRow(mockResult("1", "2"));
MemoryResultSetRow o2 = new MemoryResultSetRow(mockResult("3", "4"));
SelectStatement selectStatement = new SelectStatement();
selectStatement.getOrderByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.DESC), new OrderItem(2, OrderType.DESC)));
selectStatement.getGroupByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.ASC), new OrderItem(2, OrderType.ASC)));
GroupByRowComparator groupByRowComparator = new GroupByRowComparator(selectStatement, OrderType.ASC);
selectStatement.getOrderByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.DESC, OrderType.ASC), new OrderItem(2, OrderType.DESC, OrderType.ASC)));
selectStatement.getGroupByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.ASC, OrderType.ASC), new OrderItem(2, OrderType.ASC, OrderType.ASC)));
GroupByRowComparator groupByRowComparator = new GroupByRowComparator(selectStatement);
assertTrue(groupByRowComparator.compare(o1, o2) > 0);
}
......@@ -63,9 +63,9 @@ public final class GroupByRowComparatorTest {
MemoryResultSetRow o1 = new MemoryResultSetRow(mockResult("1", "2"));
MemoryResultSetRow o2 = new MemoryResultSetRow(mockResult("1", "2"));
SelectStatement selectStatement = new SelectStatement();
selectStatement.getOrderByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.ASC), new OrderItem(2, OrderType.DESC)));
selectStatement.getGroupByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.DESC), new OrderItem(2, OrderType.ASC)));
GroupByRowComparator groupByRowComparator = new GroupByRowComparator(selectStatement, OrderType.ASC);
selectStatement.getOrderByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.ASC, OrderType.ASC), new OrderItem(2, OrderType.DESC, OrderType.ASC)));
selectStatement.getGroupByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.DESC, OrderType.ASC), new OrderItem(2, OrderType.ASC, OrderType.ASC)));
GroupByRowComparator groupByRowComparator = new GroupByRowComparator(selectStatement);
assertThat(groupByRowComparator.compare(o1, o2), is(0));
}
......@@ -74,8 +74,8 @@ public final class GroupByRowComparatorTest {
MemoryResultSetRow o1 = new MemoryResultSetRow(mockResult("1", "2"));
MemoryResultSetRow o2 = new MemoryResultSetRow(mockResult("3", "4"));
SelectStatement selectStatement = new SelectStatement();
selectStatement.getGroupByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.ASC), new OrderItem(2, OrderType.ASC)));
GroupByRowComparator groupByRowComparator = new GroupByRowComparator(selectStatement, OrderType.ASC);
selectStatement.getGroupByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.ASC, OrderType.ASC), new OrderItem(2, OrderType.ASC, OrderType.ASC)));
GroupByRowComparator groupByRowComparator = new GroupByRowComparator(selectStatement);
assertTrue(groupByRowComparator.compare(o1, o2) < 0);
}
......@@ -84,8 +84,8 @@ public final class GroupByRowComparatorTest {
MemoryResultSetRow o1 = new MemoryResultSetRow(mockResult("1", "2"));
MemoryResultSetRow o2 = new MemoryResultSetRow(mockResult("3", "4"));
SelectStatement selectStatement = new SelectStatement();
selectStatement.getGroupByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.DESC), new OrderItem(2, OrderType.DESC)));
GroupByRowComparator groupByRowComparator = new GroupByRowComparator(selectStatement, OrderType.ASC);
selectStatement.getGroupByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.DESC, OrderType.ASC), new OrderItem(2, OrderType.DESC, OrderType.ASC)));
GroupByRowComparator groupByRowComparator = new GroupByRowComparator(selectStatement);
assertTrue(groupByRowComparator.compare(o1, o2) > 0);
}
......@@ -94,8 +94,8 @@ public final class GroupByRowComparatorTest {
MemoryResultSetRow o1 = new MemoryResultSetRow(mockResult("1", "2"));
MemoryResultSetRow o2 = new MemoryResultSetRow(mockResult("1", "2"));
SelectStatement selectStatement = new SelectStatement();
selectStatement.getGroupByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.ASC), new OrderItem(2, OrderType.DESC)));
GroupByRowComparator groupByRowComparator = new GroupByRowComparator(selectStatement, OrderType.ASC);
selectStatement.getGroupByItems().addAll(Arrays.asList(new OrderItem(1, OrderType.ASC, OrderType.ASC), new OrderItem(2, OrderType.DESC, OrderType.ASC)));
GroupByRowComparator groupByRowComparator = new GroupByRowComparator(selectStatement);
assertThat(groupByRowComparator.compare(o1, o2), is(0));
}
......
......@@ -69,8 +69,8 @@ public final class GroupByStreamResultSetMergerTest {
aggregationSelectItem2.getDerivedAggregationSelectItems().add(derivedAggregationSelectItem2);
selectStatement.getItems().add(aggregationSelectItem1);
selectStatement.getItems().add(aggregationSelectItem2);
selectStatement.getGroupByItems().add(new OrderItem(3, OrderType.ASC));
selectStatement.getOrderByItems().add(new OrderItem(3, OrderType.ASC));
selectStatement.getGroupByItems().add(new OrderItem(3, OrderType.ASC, OrderType.ASC));
selectStatement.getOrderByItems().add(new OrderItem(3, OrderType.ASC, OrderType.ASC));
}
private ResultSet mockResultSet() throws SQLException {
......
......@@ -47,7 +47,7 @@ public final class GroupByValueTest {
@Test
public void assertGetGroupByValues() throws SQLException {
List<?> actual = new GroupByValue(resultSet, Arrays.asList(new OrderItem(1, OrderType.ASC), new OrderItem(3, OrderType.DESC))).getGroupValues();
List<?> actual = new GroupByValue(resultSet, Arrays.asList(new OrderItem(1, OrderType.ASC, OrderType.ASC), new OrderItem(3, OrderType.DESC, OrderType.ASC))).getGroupValues();
List<?> expected = Arrays.asList("1", "3");
assertTrue(actual.equals(expected));
}
......
......@@ -54,7 +54,7 @@ public final class OrderByStreamResultSetMergerTest {
when(resultSet.getMetaData()).thenReturn(resultSetMetaData);
resultSets = Lists.newArrayList(resultSet, mock(ResultSet.class), mock(ResultSet.class));
selectStatement = new SelectStatement();
selectStatement.getOrderByItems().add(new OrderItem(1, OrderType.ASC));
selectStatement.getOrderByItems().add(new OrderItem(1, OrderType.ASC, OrderType.ASC));
}
@Test
......
......@@ -54,11 +54,11 @@ public final class OrderByValueTest {
@Test
public void assertCompareToForAsc() throws SQLException {
OrderByValue orderByValue1 = new OrderByValue(resultSet1, Arrays.asList(new OrderItem(1, OrderType.ASC), new OrderItem(2, OrderType.ASC)), OrderType.ASC);
OrderByValue orderByValue1 = new OrderByValue(resultSet1, Arrays.asList(new OrderItem(1, OrderType.ASC, OrderType.ASC), new OrderItem(2, OrderType.ASC, OrderType.ASC)));
assertTrue(orderByValue1.next());
when(resultSet2.getObject(1)).thenReturn("3");
when(resultSet2.getObject(2)).thenReturn("4");
OrderByValue orderByValue2 = new OrderByValue(resultSet2, Arrays.asList(new OrderItem(1, OrderType.ASC), new OrderItem(2, OrderType.ASC)), OrderType.ASC);
OrderByValue orderByValue2 = new OrderByValue(resultSet2, Arrays.asList(new OrderItem(1, OrderType.ASC, OrderType.ASC), new OrderItem(2, OrderType.ASC, OrderType.ASC)));
assertTrue(orderByValue2.next());
assertTrue(orderByValue1.compareTo(orderByValue2) < 0);
assertFalse(orderByValue1.getResultSet().next());
......@@ -67,11 +67,11 @@ public final class OrderByValueTest {
@Test
public void assertCompareToForDesc() throws SQLException {
OrderByValue orderByValue1 = new OrderByValue(resultSet1, Arrays.asList(new OrderItem(1, OrderType.DESC), new OrderItem(2, OrderType.DESC)), OrderType.ASC);
OrderByValue orderByValue1 = new OrderByValue(resultSet1, Arrays.asList(new OrderItem(1, OrderType.DESC, OrderType.ASC), new OrderItem(2, OrderType.DESC, OrderType.ASC)));
assertTrue(orderByValue1.next());
when(resultSet2.getObject(1)).thenReturn("3");
when(resultSet2.getObject(2)).thenReturn("4");
OrderByValue orderByValue2 = new OrderByValue(resultSet2, Arrays.asList(new OrderItem(1, OrderType.DESC), new OrderItem(2, OrderType.DESC)), OrderType.ASC);
OrderByValue orderByValue2 = new OrderByValue(resultSet2, Arrays.asList(new OrderItem(1, OrderType.DESC, OrderType.ASC), new OrderItem(2, OrderType.DESC, OrderType.ASC)));
assertTrue(orderByValue2.next());
assertTrue(orderByValue1.compareTo(orderByValue2) > 0);
assertFalse(orderByValue1.getResultSet().next());
......@@ -80,11 +80,11 @@ public final class OrderByValueTest {
@Test
public void assertCompareToWhenEqual() throws SQLException {
OrderByValue orderByValue1 = new OrderByValue(resultSet1, Arrays.asList(new OrderItem(1, OrderType.ASC), new OrderItem(2, OrderType.DESC)), OrderType.ASC);
OrderByValue orderByValue1 = new OrderByValue(resultSet1, Arrays.asList(new OrderItem(1, OrderType.ASC, OrderType.ASC), new OrderItem(2, OrderType.DESC, OrderType.ASC)));
assertTrue(orderByValue1.next());
when(resultSet2.getObject(1)).thenReturn("1");
when(resultSet2.getObject(2)).thenReturn("2");
OrderByValue orderByValue2 = new OrderByValue(resultSet2, Arrays.asList(new OrderItem(1, OrderType.ASC), new OrderItem(2, OrderType.DESC)), OrderType.ASC);
OrderByValue orderByValue2 = new OrderByValue(resultSet2, Arrays.asList(new OrderItem(1, OrderType.ASC, OrderType.ASC), new OrderItem(2, OrderType.DESC, OrderType.ASC)));
assertTrue(orderByValue2.next());
assertThat(orderByValue1.compareTo(orderByValue2), is(0));
assertFalse(orderByValue1.getResultSet().next());
......
......@@ -131,7 +131,8 @@ public abstract class AbstractBaseParseSQLTest extends AbstractBaseParseTest {
Iterator<OrderItem> orderByColumns = getExpectedOrderByColumns().iterator();
for (OrderItem each : actual.getOrderByItems()) {
OrderItem expectedOrderItem = orderByColumns.next();
assertTrue(new ReflectionEquals(expectedOrderItem).matches(each));
// TODO assert nullOrderType
assertTrue(new ReflectionEquals(expectedOrderItem, "nullOrderType").matches(each));
}
assertFalse(orderByColumns.hasNext());
}
......@@ -140,7 +141,8 @@ public abstract class AbstractBaseParseSQLTest extends AbstractBaseParseTest {
Iterator<OrderItem> groupByColumns = getExpectedGroupByColumns().iterator();
for (OrderItem each : actual.getGroupByItems()) {
OrderItem groupByColumn = groupByColumns.next();
assertTrue(new ReflectionEquals(groupByColumn).matches(each));
// TODO assert nullOrderType
assertTrue(new ReflectionEquals(groupByColumn, "nullOrderType").matches(each));
}
assertFalse(groupByColumns.hasNext());
}
......
......@@ -46,12 +46,15 @@ public class ParserJAXBHelper {
@Override
public OrderItem apply(final OrderByColumn input) {
if (Strings.isNullOrEmpty(input.getName())) {
return new OrderItem(input.getIndex(), OrderType.valueOf(input.getOrderByType().toUpperCase()));
// TODO nullOrderType should config in xml
return new OrderItem(input.getIndex(), OrderType.valueOf(input.getOrderByType().toUpperCase()), OrderType.ASC);
}
if (Strings.isNullOrEmpty(input.getOwner())) {
return new OrderItem(input.getName(), OrderType.valueOf(input.getOrderByType().toUpperCase()), Optional.fromNullable(input.getAlias()));
// TODO nullOrderType should config in xml
return new OrderItem(input.getName(), OrderType.valueOf(input.getOrderByType().toUpperCase()), OrderType.ASC, Optional.fromNullable(input.getAlias()));
}
return new OrderItem(input.getOwner(), input.getName(), OrderType.valueOf(input.getOrderByType().toUpperCase()), Optional.fromNullable(input.getAlias()));
// TODO nullOrderType should config in xml
return new OrderItem(input.getOwner(), input.getName(), OrderType.valueOf(input.getOrderByType().toUpperCase()), OrderType.ASC, Optional.fromNullable(input.getAlias()));
}
});
result.getOrderByItems().addAll(orderItems);
......@@ -62,9 +65,11 @@ public class ParserJAXBHelper {
@Override
public OrderItem apply(final GroupByColumn input) {
if (null == input.getOwner()) {
return new OrderItem(input.getName(), OrderType.valueOf(input.getOrderByType().toUpperCase()), Optional.fromNullable(input.getAlias()));
// TODO nullOrderType should config in xml
return new OrderItem(input.getName(), OrderType.valueOf(input.getOrderByType().toUpperCase()), OrderType.ASC, Optional.fromNullable(input.getAlias()));
}
return new OrderItem(input.getOwner(), input.getName(), OrderType.valueOf(input.getOrderByType().toUpperCase()), Optional.fromNullable(input.getAlias()));
// TODO nullOrderType should config in xml
return new OrderItem(input.getOwner(), input.getName(), OrderType.valueOf(input.getOrderByType().toUpperCase()), OrderType.ASC, Optional.fromNullable(input.getAlias()));
}
}));
}
......
......@@ -38,16 +38,16 @@ public final class SelectStatementTest {
@Test
public void assertIsSameGroupByAndOrderByItemsWhenSame() throws SQLException {
SelectStatement actual = new SelectStatement();
actual.getOrderByItems().add(new OrderItem("col", OrderType.ASC, Optional.<String>absent()));
actual.getGroupByItems().add(new OrderItem("col", OrderType.ASC, Optional.<String>absent()));
actual.getOrderByItems().add(new OrderItem("col", OrderType.ASC, OrderType.ASC, Optional.<String>absent()));
actual.getGroupByItems().add(new OrderItem("col", OrderType.ASC, OrderType.ASC, Optional.<String>absent()));
assertTrue(actual.isSameGroupByAndOrderByItems());
}
@Test
public void assertIsSameGroupByAndOrderByItemsWhenDifferent() throws SQLException {
SelectStatement actual = new SelectStatement();
actual.getOrderByItems().add(new OrderItem("order_col", OrderType.ASC, Optional.<String>absent()));
actual.getGroupByItems().add(new OrderItem("group_col", OrderType.ASC, Optional.<String>absent()));
actual.getOrderByItems().add(new OrderItem("order_col", OrderType.ASC, OrderType.ASC, Optional.<String>absent()));
actual.getGroupByItems().add(new OrderItem("group_col", OrderType.ASC, OrderType.ASC, Optional.<String>absent()));
assertFalse(actual.isSameGroupByAndOrderByItems());
}
}
......@@ -150,8 +150,8 @@ public final class SQLRewriteEngineTest {
selectStatement.setLimit(new Limit(true));
selectStatement.getLimit().setOffset(new LimitValue(2, -1));
selectStatement.getLimit().setRowCount(new LimitValue(2, -1));
selectStatement.getOrderByItems().add(new OrderItem("x", "id", OrderType.ASC, Optional.<String>absent()));
selectStatement.getGroupByItems().add(new OrderItem("x", "id", OrderType.DESC, Optional.<String>absent()));
selectStatement.getOrderByItems().add(new OrderItem("x", "id", OrderType.ASC, OrderType.ASC, Optional.<String>absent()));
selectStatement.getGroupByItems().add(new OrderItem("x", "id", OrderType.DESC, OrderType.ASC, Optional.<String>absent()));
selectStatement.getSqlTokens().add(new TableToken(17, "table_x"));
selectStatement.getSqlTokens().add(new OffsetToken(33, 2));
selectStatement.getSqlTokens().add(new RowCountToken(36, 2));
......@@ -167,8 +167,8 @@ public final class SQLRewriteEngineTest {
selectStatement.getSqlTokens().add(new TableToken(68, "table_x"));
selectStatement.getSqlTokens().add(new OffsetToken(119, 2));
selectStatement.getSqlTokens().add(new RowCountToken(98, 4));
selectStatement.getOrderByItems().add(new OrderItem("x", "id", OrderType.ASC, Optional.<String>absent()));
selectStatement.getGroupByItems().add(new OrderItem("x", "id", OrderType.DESC, Optional.<String>absent()));
selectStatement.getOrderByItems().add(new OrderItem("x", "id", OrderType.ASC, OrderType.ASC, Optional.<String>absent()));
selectStatement.getGroupByItems().add(new OrderItem("x", "id", OrderType.DESC, OrderType.ASC, Optional.<String>absent()));
SQLRewriteEngine rewriteEngine = new SQLRewriteEngine(shardingRule,
"SELECT * FROM (SELECT row_.*, rownum rownum_ FROM (SELECT x.id FROM table_x x) row_ WHERE rownum<=4) t WHERE t.rownum_>2", selectStatement);
assertThat(rewriteEngine.rewrite(true).toSQL(tableTokens),
......@@ -183,8 +183,8 @@ public final class SQLRewriteEngineTest {
selectStatement.getSqlTokens().add(new TableToken(85, "table_x"));
selectStatement.getSqlTokens().add(new OffsetToken(123, 2));
selectStatement.getSqlTokens().add(new RowCountToken(26, 4));
selectStatement.getOrderByItems().add(new OrderItem("x", "id", OrderType.ASC, Optional.<String>absent()));
selectStatement.getGroupByItems().add(new OrderItem("x", "id", OrderType.DESC, Optional.<String>absent()));
selectStatement.getOrderByItems().add(new OrderItem("x", "id", OrderType.ASC, OrderType.ASC, Optional.<String>absent()));
selectStatement.getGroupByItems().add(new OrderItem("x", "id", OrderType.DESC, OrderType.ASC, Optional.<String>absent()));
SQLRewriteEngine rewriteEngine = new SQLRewriteEngine(shardingRule,
"SELECT * FROM (SELECT TOP(4) row_number() OVER (ORDER BY x.id) AS rownum_, x.id FROM table_x x) AS row_ WHERE row_.rownum_>2", selectStatement);
assertThat(rewriteEngine.rewrite(true).toSQL(tableTokens),
......@@ -233,8 +233,8 @@ public final class SQLRewriteEngineTest {
@Test
public void assertRewriteForDerivedOrderBy() {
selectStatement.setGroupByLastPosition(61);
selectStatement.getOrderByItems().add(new OrderItem("x", "id", OrderType.ASC, Optional.<String>absent()));
selectStatement.getOrderByItems().add(new OrderItem("x", "name", OrderType.DESC, Optional.<String>absent()));
selectStatement.getOrderByItems().add(new OrderItem("x", "id", OrderType.ASC, OrderType.ASC, Optional.<String>absent()));
selectStatement.getOrderByItems().add(new OrderItem("x", "name", OrderType.DESC, OrderType.ASC, Optional.<String>absent()));
selectStatement.getSqlTokens().add(new TableToken(25, "table_x"));
selectStatement.getSqlTokens().add(new OrderByToken(61));
SQLRewriteEngine rewriteEngine = new SQLRewriteEngine(shardingRule, "SELECT x.id, x.name FROM table_x x GROUP BY x.id, x.name DESC", selectStatement);
......
......@@ -15,4 +15,16 @@
<data expected="select_order_by/SelectForAlias.xml" />
</sharding-rule>
</sql>
<!-- // TODO add null data -->
<sql id="assertSelectWithOrderByForNullsFirst">
<sharding-rule value="tbl">
<data expected="select_order_by/SelectForAlias.xml" />
</sharding-rule>
</sql>
<!-- // TODO add null data -->
<sql id="assertSelectWithOrderByForNullsLast">
<sharding-rule value="tbl">
<data expected="select_order_by/SelectForAlias.xml" />
</sharding-rule>
</sql>
</sqls>
......@@ -29,4 +29,24 @@
<order-by-column owner="o" name="order_id" alias="gen_order_id_" order-by-type="ASC" />
</order-by-columns>
</assert>
<!-- //TODO add order-by-null-type -->
<assert id="assertSelectWithOrderByForNullsFirst">
<tables>
<table name="t_order" alias="o" />
</tables>
<order-by-columns>
<order-by-column owner="o" name="order_id" alias="gen_order_id_" order-by-type="ASC" />
</order-by-columns>
</assert>
<!-- //TODO add order-by-null-type -->
<assert id="assertSelectWithOrderByForNullsLast">
<tables>
<table name="t_order" alias="o" />
</tables>
<order-by-columns>
<order-by-column owner="o" name="order_id" alias="gen_order_id_" order-by-type="DESC" />
</order-by-columns>
</assert>
</asserts>
......@@ -3,4 +3,6 @@
<sql id="assertSelectWithOrderBy" value="SELECT * FROM t_order o ORDER BY o.order_id, 2 DESC" />
<sql id="assertSelectWithOrderByForIndex" value="SELECT i.* FROM t_order o, t_order_item i WHERE o.order_id = i.order_id AND o.status = 'init' ORDER BY o.order_id DESC, 1" />
<sql id="assertSelectWithOrderByForAlias" value="SELECT o.order_id as gen_order_id_ FROM t_order o ORDER BY o.order_id" />
<sql id="assertSelectWithOrderByForNullsFirst" value="SELECT o.order_id as gen_order_id_ FROM t_order o ORDER BY o.order_id NULLS FIRST" type="Oracle" />
<sql id="assertSelectWithOrderByForNullsLast" value="SELECT o.order_id as gen_order_id_ FROM t_order o ORDER BY o.order_id DESC NULLS LAST" type="Oracle" />
</sqls>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册