提交 acd95c24 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Convert results to distinct where needed in safe way

上级 edf9f2d7
...@@ -2535,7 +2535,7 @@ public class Parser { ...@@ -2535,7 +2535,7 @@ public class Parser {
} }
currentSelect = temp; currentSelect = temp;
if (readIf(DISTINCT)) { if (readIf(DISTINCT)) {
command.setDistinct(true); command.setDistinct();
} else { } else {
readIf(ALL); readIf(ALL);
} }
......
...@@ -255,13 +255,17 @@ public abstract class Query extends Prepared { ...@@ -255,13 +255,17 @@ public abstract class Query extends Prepared {
/** /**
* Set the distinct flag. * Set the distinct flag.
*
* @param b the new value
*/ */
public void setDistinct(boolean b) { public void setDistinct() {
distinct = b; distinct = true;
} }
/**
* Set the distinct flag only if it is possible, may be used as a possible
* optimization only.
*/
public abstract void setDistinctIfPossible();
public boolean isDistinct() { public boolean isDistinct() {
return distinct; return distinct;
} }
......
...@@ -247,6 +247,13 @@ public class Select extends Query { ...@@ -247,6 +247,13 @@ public class Select extends Query {
return orderList != null || sort != null; return orderList != null || sort != null;
} }
@Override
public void setDistinctIfPossible() {
if (!distinct && offsetExpr == null && limitExpr == null) {
setDistinct();
}
}
/** /**
* Add a condition to the list of conditions. * Add a condition to the list of conditions.
* *
...@@ -667,9 +674,6 @@ public class Select extends Query { ...@@ -667,9 +674,6 @@ public class Select extends Query {
result = createLocalResult(result); result = createLocalResult(result);
result.setDistinct(); result.setDistinct();
} }
if (randomAccessResult) {
result = createLocalResult(result);
}
if (isGroupQuery && !isGroupSortedQuery) { if (isGroupQuery && !isGroupSortedQuery) {
result = createLocalResult(result); result = createLocalResult(result);
} }
...@@ -724,8 +728,12 @@ public class Select extends Query { ...@@ -724,8 +728,12 @@ public class Select extends Query {
if (limitRows > 0) { if (limitRows > 0) {
lazyResult.setLimit(limitRows); lazyResult.setLimit(limitRows);
} }
if (randomAccessResult) {
return convertToDistinct(lazyResult);
} else {
return lazyResult; return lazyResult;
} }
}
if (offsetExpr != null) { if (offsetExpr != null) {
result.setOffset(offsetExpr.getValue(session).getInt()); result.setOffset(offsetExpr.getValue(session).getInt());
} }
...@@ -734,6 +742,9 @@ public class Select extends Query { ...@@ -734,6 +742,9 @@ public class Select extends Query {
} }
if (result != null) { if (result != null) {
result.done(); result.done();
if (randomAccessResult && !distinct) {
result = convertToDistinct(result);
}
if (target != null) { if (target != null) {
while (result.next()) { while (result.next()) {
target.addRow(result.currentRow()); target.addRow(result.currentRow());
...@@ -761,6 +772,18 @@ public class Select extends Query { ...@@ -761,6 +772,18 @@ public class Select extends Query {
visibleColumnCount); visibleColumnCount);
} }
private LocalResult convertToDistinct(ResultInterface result) {
LocalResult distinctResult = new LocalResult(session, expressionArray, visibleColumnCount);
distinctResult.setDistinct();
result.reset();
while (result.next()) {
distinctResult.addRow(result.currentRow());
}
result.close();
distinctResult.done();
return distinctResult;
}
private void expandColumnList() { private void expandColumnList() {
Database db = session.getDatabase(); Database db = session.getDatabase();
......
...@@ -125,6 +125,11 @@ public class SelectUnion extends Query { ...@@ -125,6 +125,11 @@ public class SelectUnion extends Query {
return orderList != null || sort != null; return orderList != null || sort != null;
} }
@Override
public void setDistinctIfPossible() {
setDistinct();
}
private Value[] convert(Value[] values, int columnCount) { private Value[] convert(Value[] values, int columnCount) {
Value[] newValues; Value[] newValues;
if (columnCount == values.length) { if (columnCount == values.length) {
...@@ -210,8 +215,8 @@ public class SelectUnion extends Query { ...@@ -210,8 +215,8 @@ public class SelectUnion extends Query {
result.setSortOrder(sort); result.setSortOrder(sort);
} }
if (distinct) { if (distinct) {
left.setDistinct(true); left.setDistinctIfPossible();
right.setDistinct(true); right.setDistinctIfPossible();
result.setDistinct(); result.setDistinct();
} }
if (randomAccessResult) { if (randomAccessResult) {
...@@ -220,15 +225,15 @@ public class SelectUnion extends Query { ...@@ -220,15 +225,15 @@ public class SelectUnion extends Query {
switch (unionType) { switch (unionType) {
case UNION: case UNION:
case EXCEPT: case EXCEPT:
left.setDistinct(true); left.setDistinctIfPossible();
right.setDistinct(true); right.setDistinctIfPossible();
result.setDistinct(); result.setDistinct();
break; break;
case UNION_ALL: case UNION_ALL:
break; break;
case INTERSECT: case INTERSECT:
left.setDistinct(true); left.setDistinctIfPossible();
right.setDistinct(true); right.setDistinctIfPossible();
break; break;
default: default:
DbException.throwInternalError("type=" + unionType); DbException.throwInternalError("type=" + unionType);
......
...@@ -43,9 +43,7 @@ public class ConditionInSelect extends Condition { ...@@ -43,9 +43,7 @@ public class ConditionInSelect extends Condition {
@Override @Override
public Value getValue(Session session) { public Value getValue(Session session) {
query.setSession(session); query.setSession(session);
if (!query.hasOrder()) { query.setDistinctIfPossible();
query.setDistinct(true);
}
ResultInterface rows = query.query(0); ResultInterface rows = query.query(0);
Value l = left.getValue(session); Value l = left.getValue(session);
if (!rows.hasNext()) { if (!rows.hasNext()) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论