Unverified 提交 f6b2ced2 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov 提交者: GitHub

Merge pull request #1756 from katzyn/distinct_on

Fix DISTINCT ON in presence of ORDER BY
......@@ -44,7 +44,11 @@ Non-window aggregate functions are allowed in this clause.
7. QUALIFY filters rows after evaluation of window functions.
Aggregate and window functions are allowed in this clause.
8. DISTINCT removes duplicates. If DISTINCT ON is used only the specified expressions are checked for duplicates.
8. DISTINCT removes duplicates.
If DISTINCT ON is used only the specified expressions are checked for duplicates;
ORDER BY clause, if any, is used to determine preserved rows.
First row is each DISTINCT ON group is preserved.
In absence of ORDER BY preserved rows are not determined, database may choose any row from each DISTINCT ON group.
9. UNION, EXCEPT (MINUS), and INTERSECT combine the result of this query with the results of another query.
Multiple set operators (UNION, INTERSECT, MINUS, EXCEPT) are evaluated from left to right.
......
......@@ -148,7 +148,7 @@ Reference:
<b><a href="features.html#connection_modes">Embedded</a></b><br />
<code>jdbc:h2:~/test</code> 'test' in the user home directory<br />
<code>jdbc:h2:/data/test</code> 'test' in the directory /data<br />
<code>jdbc:h2:test</code> in the current(!) working directory<br />
<code>jdbc:h2:./test</code> in the current(!) working directory<br />
</p><p>
<b><a href="features.html#in_memory_databases">In-Memory</a></b><br />
<code>jdbc:h2:mem:test</code> multiple connections in one process<br />
......
......@@ -136,15 +136,15 @@ In Build.java, comment "-Xdoclint:none", but don't commit that change.
# http://central.sonatype.org/pages/ossrh-guide.html
# http://central.sonatype.org/pages/manual-staging-bundle-creation-and-deployment.html
# https://oss.sonatype.org/#welcome - Log In "t..."
# sometimes this doesn't work reliably and you will have to retry
# sometimes this doesn't work reliably and you will have to retry
# - Staging Upload
# - Upload Mode: Artifact Bundle, Select Bundle to Upload... - /data/h2database/.../h2/.../bundle.jar
# - Upload Bundle
# - Staging Repositories - Refresh - select comh2database-<...> - Release - Confirm
# - Staging Repositories - Refresh - select comh2database-<...> - Release - Confirm
# - Staging Upload
# - Upload Mode: Artifact Bundle, Select Bundle to Upload... - /data/h2database/.../h2-mvstore/.../bundle.jar
# - Upload Bundle
# - Staging Repositories - Refresh - select comh2database-<...> - Release - Confirm
# - Staging Repositories - Refresh - select comh2database-<...> - Release - Confirm
Update statistics.
......
......@@ -1825,7 +1825,7 @@ public class Select extends Query {
@Override
public boolean allowGlobalConditions() {
return offsetExpr == null && (limitExpr == null || sort == null);
return offsetExpr == null && (limitExpr == null && distinctExpressions == null || sort == null);
}
public SortOrder getSortOrder() {
......
......@@ -56,7 +56,12 @@ class MVSortedTempResult extends MVTempResult {
* {@link #contains(Value[])} method is invoked. Only the root result should
* have an index if required.
*/
private MVMap<ValueRow, Boolean> index;
private MVMap<ValueRow, Object> index;
/**
* Used for DISTINCT ON in presence of ORDER BY.
*/
private ValueDataType orderedDistinctOnType;
/**
* Cursor for the {@link #next()} method.
......@@ -172,7 +177,11 @@ class MVSortedTempResult extends MVTempResult {
if (distinct && length != visibleColumnCount || distinctIndexes != null) {
int count = distinctIndexes != null ? distinctIndexes.length : visibleColumnCount;
ValueDataType distinctType = new ValueDataType(database, new int[count]);
Builder<ValueRow, Boolean> indexBuilder = new MVMap.Builder<ValueRow, Boolean>().keyType(distinctType);
Builder<ValueRow, Object> indexBuilder = new MVMap.Builder<ValueRow, Object>().keyType(distinctType);
if (distinctIndexes != null && sort != null) {
indexBuilder.valueType(keyType);
orderedDistinctOnType = keyType;
}
index = store.openMap("idx", indexBuilder);
}
}
......@@ -189,8 +198,21 @@ class MVSortedTempResult extends MVTempResult {
newValues[i] = values[distinctIndexes[i]];
}
ValueRow distinctRow = ValueRow.get(newValues);
if (index.putIfAbsent(distinctRow, true) != null) {
return rowCount;
if (orderedDistinctOnType == null) {
if (index.putIfAbsent(distinctRow, true) != null) {
return rowCount;
}
} else {
ValueRow previous = (ValueRow) index.get(distinctRow);
if (previous == null) {
index.put(distinctRow, key);
} else if (orderedDistinctOnType.compare(previous, key) > 0) {
map.remove(previous);
rowCount--;
index.put(distinctRow, key);
} else {
return rowCount;
}
}
} else if (expressions.length != visibleColumnCount) {
ValueRow distinctRow = ValueRow.get(Arrays.copyOf(values, visibleColumnCount));
......
......@@ -316,7 +316,8 @@ public class LocalResultImpl implements LocalResult {
if (isAnyDistinct()) {
if (distinctRows != null) {
ValueRow array = getDistinctRow(values);
if (!distinctRows.containsKey(array)) {
Value[] previous = distinctRows.get(array);
if (previous == null || sort != null && sort.compare(previous, values) > 0) {
distinctRows.put(array, values);
}
rowCount = distinctRows.size();
......
......@@ -144,6 +144,42 @@ SELECT DISTINCT ON(C1) C2 FROM TEST ORDER BY C1;
> 4
> rows (ordered): 3
SELECT DISTINCT ON(C1) C1, C4, C5 FROM TEST ORDER BY C1, C5;
> C1 C4 C5
> -- -- --
> 1 4 5
> 2 8 9
> 3 1 1
> rows (ordered): 3
SELECT DISTINCT ON(C1) C1, C4, C5 FROM TEST ORDER BY C1, C5 DESC;
> C1 C4 C5
> -- -- --
> 1 6 7
> 2 8 9
> 3 1 1
> rows (ordered): 3
SELECT T1.C1, T2.C5 FROM TEST T1 JOIN (
SELECT DISTINCT ON(C1) C1, C4, C5 FROM TEST ORDER BY C1, C5
) T2 ON T1.C4 = T2.C4 ORDER BY T1.C1;
> C1 C5
> -- --
> 1 5
> 2 9
> 3 1
> rows (ordered): 3
SELECT T1.C1, T2.C5 FROM TEST T1 JOIN (
SELECT DISTINCT ON(C1) C1, C4, C5 FROM TEST ORDER BY C1, C5 DESC
) T2 ON T1.C4 = T2.C4 ORDER BY T1.C1;
> C1 C5
> -- --
> 1 7
> 2 9
> 3 1
> rows (ordered): 3
EXPLAIN SELECT DISTINCT ON(C1) C2 FROM TEST ORDER BY C1;
>> SELECT DISTINCT ON(C1) C2 FROM PUBLIC.TEST /* PUBLIC.TEST.tableScan */ ORDER BY =C1
......
......@@ -809,4 +809,4 @@ preserves masking holder unboxing avert iae transformed subtle reevaluate exclus
presorted inclusion contexts aax mwd percentile cont interpolate mwa hypothetical regproc childed listagg foreground
isodow isoyear psql
waiters
\ No newline at end of file
waiters reliably httpsdocs privileged
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论