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

Merge pull request #1484 from katzyn/misc

New tests, reimplemented EXCLUDE clause, and assorted changes
......@@ -6,6 +6,8 @@
package org.h2.expression;
import static org.h2.util.DateTimeUtils.NANOS_PER_DAY;
import static org.h2.util.DateTimeUtils.NANOS_PER_HOUR;
import static org.h2.util.DateTimeUtils.NANOS_PER_MINUTE;
import static org.h2.util.DateTimeUtils.absoluteDayFromDateValue;
import static org.h2.util.DateTimeUtils.dateAndTimeFromValue;
import static org.h2.util.DateTimeUtils.dateTimeToValue;
......@@ -168,8 +170,8 @@ public class IntervalOperation extends Expression {
if (negative) {
diff = -diff;
}
return ValueInterval.from(IntervalQualifier.HOUR_TO_SECOND, negative, diff / 3_600_000_000_000L,
diff % 3_600_000_000_000L);
return ValueInterval.from(IntervalQualifier.HOUR_TO_SECOND, negative, diff / NANOS_PER_HOUR,
diff % NANOS_PER_HOUR);
} else if (lType == Value.DATE && rType == Value.DATE) {
long diff = absoluteDayFromDateValue(((ValueDate) l).getDateValue())
- absoluteDayFromDateValue(((ValueDate) r).getDateValue());
......@@ -184,7 +186,7 @@ public class IntervalOperation extends Expression {
l = l.convertTo(Value.TIMESTAMP_TZ);
r = r.convertTo(Value.TIMESTAMP_TZ);
diff = diff.add(BigInteger.valueOf((((ValueTimestampTimeZone) r).getTimeZoneOffsetMins()
- ((ValueTimestampTimeZone) l).getTimeZoneOffsetMins()) * 60_000_000_000L));
- ((ValueTimestampTimeZone) l).getTimeZoneOffsetMins()) * NANOS_PER_MINUTE));
}
return IntervalUtils.intervalFromAbsolute(IntervalQualifier.DAY_TO_SECOND, diff);
}
......
......@@ -25,10 +25,10 @@ abstract class AggregateData {
static AggregateData create(AggregateType aggregateType, boolean distinct) {
switch (aggregateType) {
case COUNT_ALL:
return new AggregateDataCountAll();
return new AggregateDataCount(true);
case COUNT:
if (!distinct) {
return new AggregateDataCount();
return new AggregateDataCount(false);
}
break;
case GROUP_CONCAT:
......
......@@ -11,14 +11,21 @@ import org.h2.value.ValueLong;
import org.h2.value.ValueNull;
/**
* Data stored while calculating an aggregate.
* Data stored while calculating a COUNT aggregate.
*/
class AggregateDataCount extends AggregateData {
private final boolean all;
private long count;
AggregateDataCount(boolean all) {
this.all = all;
}
@Override
void add(Database database, int dataType, Value v) {
if (v != ValueNull.INSTANCE) {
if (all || v != ValueNull.INSTANCE) {
count++;
}
}
......
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.expression.aggregate;
import org.h2.engine.Database;
import org.h2.value.Value;
import org.h2.value.ValueLong;
/**
* Data stored while calculating a COUNT(*) aggregate.
*/
class AggregateDataCountAll extends AggregateData {
private long count;
@Override
void add(Database database, int dataType, Value v) {
count++;
}
@Override
Value getValue(Database database, int dataType) {
return ValueLong.get(count).convertTo(dataType);
}
}
......@@ -6,7 +6,6 @@
package org.h2.expression.aggregate;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.Iterator;
import java.util.NoSuchElementException;
......@@ -28,6 +27,8 @@ public final class WindowFrame {
final ArrayList<Value[]> orderedRows;
int cursor;
Itr(ArrayList<Value[]> orderedRows) {
this.orderedRows = orderedRows;
}
......@@ -39,11 +40,9 @@ public final class WindowFrame {
}
private static final class PlainItr extends Itr {
private static class PlainItr extends Itr {
private final int endIndex;
private int cursor;
final int endIndex;
PlainItr(ArrayList<Value[]> orderedRows, int startIndex, int endIndex) {
super(orderedRows);
......@@ -66,11 +65,9 @@ public final class WindowFrame {
}
private static final class PlainReverseItr extends Itr {
private final int startIndex;
private static class PlainReverseItr extends Itr {
private int cursor;
final int startIndex;
PlainReverseItr(ArrayList<Value[]> orderedRows, int startIndex, int endIndex) {
super(orderedRows);
......@@ -93,58 +90,92 @@ public final class WindowFrame {
}
private static abstract class AbstractBitSetItr extends Itr {
private static class BiItr extends PlainItr {
final BitSet set;
final int end1, start1;
int cursor;
BiItr(ArrayList<Value[]> orderedRows, int startIndex1, int endIndex1, int startIndex2, int endIndex2) {
super(orderedRows, startIndex1, endIndex2);
end1 = endIndex1;
start1 = startIndex2;
}
AbstractBitSetItr(ArrayList<Value[]> orderedRows, BitSet set) {
super(orderedRows);
this.set = set;
@Override
public Value[] next() {
if (cursor > endIndex) {
throw new NoSuchElementException();
}
Value[] r = orderedRows.get(cursor);
cursor = cursor != end1 ? cursor + 1 : start1;
return r;
}
}
private static class BiReverseItr extends PlainReverseItr {
final int end1, start1;
BiReverseItr(ArrayList<Value[]> orderedRows, int startIndex1, int endIndex1, int startIndex2, int endIndex2) {
super(orderedRows, startIndex1, endIndex2);
end1 = endIndex1;
start1 = startIndex2;
}
@Override
public final boolean hasNext() {
return cursor >= 0;
public Value[] next() {
if (cursor < startIndex) {
throw new NoSuchElementException();
}
Value[] r = orderedRows.get(cursor);
cursor = cursor != start1 ? cursor - 1 : end1;
return r;
}
}
private static final class BitSetItr extends AbstractBitSetItr {
private static final class TriItr extends BiItr {
private final int end2, start2;
BitSetItr(ArrayList<Value[]> orderedRows, BitSet set) {
super(orderedRows, set);
cursor = set.nextSetBit(0);
TriItr(ArrayList<Value[]> orderedRows, int startIndex1, int endIndex1, int startIndex2, int endIndex2,
int startIndex3, int endIndex3) {
super(orderedRows, startIndex1, endIndex1, startIndex2, endIndex3);
end2 = endIndex2;
start2 = startIndex3;
}
@Override
public Value[] next() {
if (cursor < 0) {
if (cursor > endIndex) {
throw new NoSuchElementException();
}
Value[] result = orderedRows.get(cursor);
cursor = set.nextSetBit(cursor + 1);
return result;
Value[] r = orderedRows.get(cursor);
cursor = cursor != end1 ? cursor != end2 ? cursor + 1 : start2 : start1;
return r;
}
}
private static final class BitSetReverseItr extends AbstractBitSetItr {
private static final class TriReverseItr extends BiReverseItr {
private final int end2, start2;
BitSetReverseItr(ArrayList<Value[]> orderedRows, BitSet set) {
super(orderedRows, set);
cursor = set.length() - 1;
TriReverseItr(ArrayList<Value[]> orderedRows, int startIndex1, int endIndex1, int startIndex2, int endIndex2,
int startIndex3, int endIndex3) {
super(orderedRows, startIndex1, endIndex1, startIndex2, endIndex3);
end2 = endIndex2;
start2 = startIndex3;
}
@Override
public Value[] next() {
if (cursor < 0) {
if (cursor < startIndex) {
throw new NoSuchElementException();
}
Value[] result = orderedRows.get(cursor);
cursor = set.previousSetBit(cursor - 1);
return result;
Value[] r = orderedRows.get(cursor);
cursor = cursor != start1 ? cursor != start2 ? cursor - 1 : end2 : end1;
return r;
}
}
......@@ -179,7 +210,29 @@ public final class WindowFrame {
public static Iterator<Value[]> iterator(WindowFrame frame, Session session, ArrayList<Value[]> orderedRows,
SortOrder sortOrder, int currentRow, boolean reverse) {
return frame != null ? frame.iterator(session, orderedRows, sortOrder, currentRow, reverse)
: reverse ? new PlainReverseItr(orderedRows, 0, currentRow) : new PlainItr(orderedRows, 0, currentRow);
: plainIterator(orderedRows, 0, currentRow, reverse);
}
private static Iterator<Value[]> plainIterator(ArrayList<Value[]> orderedRows, int startIndex, int endIndex,
boolean reverse) {
if (endIndex < startIndex) {
return Collections.emptyIterator();
}
return reverse ? new PlainReverseItr(orderedRows, startIndex, endIndex)
: new PlainItr(orderedRows, startIndex, endIndex);
}
private static Iterator<Value[]> biIterator(ArrayList<Value[]> orderedRows, int startIndex1, int endIndex1,
int startIndex2, int endIndex2, boolean reverse) {
return reverse ? new BiReverseItr(orderedRows, startIndex1, endIndex1, startIndex2, endIndex2)
: new BiItr(orderedRows, startIndex1, endIndex1, startIndex2, endIndex2);
}
private static Iterator<Value[]> triIterator(ArrayList<Value[]> orderedRows, int startIndex1, int endIndex1,
int startIndex2, int endIndex2, int startIndex3, int endIndex3, boolean reverse) {
return reverse ? new TriReverseItr(orderedRows, startIndex1, endIndex1, startIndex2, endIndex2, //
startIndex3, endIndex3)
: new TriItr(orderedRows, startIndex1, endIndex1, startIndex2, endIndex2, startIndex3, endIndex3);
}
private static int toGroupStart(ArrayList<Value[]> orderedRows, SortOrder sortOrder, int offset, int minOffset) {
......@@ -317,11 +370,9 @@ public final class WindowFrame {
if (endIndex >= size) {
endIndex = size - 1;
}
if (exclusion != WindowFrameExclusion.EXCLUDE_NO_OTHERS) {
return complexIterator(orderedRows, sortOrder, currentRow, startIndex, endIndex, reverse);
}
return reverse ? new PlainReverseItr(orderedRows, startIndex, endIndex)
: new PlainItr(orderedRows, startIndex, endIndex);
return exclusion != WindowFrameExclusion.EXCLUDE_NO_OTHERS
? complexIterator(orderedRows, sortOrder, currentRow, startIndex, endIndex, reverse)
: plainIterator(orderedRows, startIndex, endIndex, reverse);
}
private int getIndex(Session session, ArrayList<Value[]> orderedRows, SortOrder sortOrder, int currentRow,
......@@ -468,29 +519,60 @@ public final class WindowFrame {
private Iterator<Value[]> complexIterator(ArrayList<Value[]> orderedRows, SortOrder sortOrder, int currentRow,
int startIndex, int endIndex, boolean reverse) {
int size = orderedRows.size();
BitSet set = new BitSet(size);
set.set(startIndex, endIndex + 1);
switch (exclusion) {
case EXCLUDE_CURRENT_ROW:
set.clear(currentRow);
break;
case EXCLUDE_GROUP:
case EXCLUDE_TIES: {
if (exclusion == WindowFrameExclusion.EXCLUDE_CURRENT_ROW) {
if (currentRow < startIndex || currentRow > endIndex) {
// Nothing to exclude
} else if (currentRow == startIndex) {
startIndex++;
} else if (currentRow == endIndex) {
endIndex--;
} else {
return biIterator(orderedRows, startIndex, currentRow - 1, currentRow + 1, endIndex, reverse);
}
} else {
// Do not include previous rows if they are not in the range
int exStart = toGroupStart(orderedRows, sortOrder, currentRow, startIndex);
// Do not include next rows if they are not in the range
int exEnd = toGroupEnd(orderedRows, sortOrder, currentRow, endIndex);
set.clear(exStart, exEnd + 1);
if (exclusion == WindowFrameExclusion.EXCLUDE_TIES) {
set.set(currentRow);
boolean includeCurrentRow = exclusion == WindowFrameExclusion.EXCLUDE_TIES;
if (includeCurrentRow) {
// Simplify exclusion if possible
if (currentRow == exStart) {
exStart++;
includeCurrentRow = false;
} else if (currentRow == exEnd) {
exEnd--;
includeCurrentRow = false;
}
}
if (exStart > exEnd || exEnd < startIndex || exStart > endIndex) {
// Empty range or nothing to exclude
} else if (includeCurrentRow) {
if (startIndex == exStart) {
if (endIndex == exEnd) {
return Collections.singleton(orderedRows.get(currentRow)).iterator();
} else {
return biIterator(orderedRows, currentRow, currentRow, exEnd + 1, endIndex, reverse);
}
} else {
if (endIndex == exEnd) {
return biIterator(orderedRows, startIndex, exStart - 1, currentRow, currentRow, reverse);
} else {
return triIterator(orderedRows, startIndex, exStart - 1, currentRow, currentRow, exEnd + 1,
endIndex, reverse);
}
}
} else {
if (startIndex >= exStart) {
startIndex = exEnd + 1;
} else if (endIndex <= exEnd) {
endIndex = exStart - 1;
} else {
return biIterator(orderedRows, startIndex, exStart - 1, exEnd + 1, endIndex, reverse);
}
}
}
//$FALL-THROUGH$
default:
}
if (set.isEmpty()) {
return Collections.emptyIterator();
}
return reverse ? new BitSetReverseItr(orderedRows, set) : new BitSetItr(orderedRows, set);
return plainIterator(orderedRows, startIndex, endIndex, reverse);
}
/**
......
......@@ -653,7 +653,9 @@ public class TestScript extends TestDb {
}
} else {
addWriteResultError("<nothing>", s);
putBack(compare);
if (compare != null) {
putBack(compare);
}
}
write(s);
}
......
......@@ -350,6 +350,23 @@ SELECT *, ARRAY_AGG(ID) OVER (ORDER BY ID RANGE BETWEEN 1 FOLLOWING AND 2 FOLLOW
> 8 9 null
> rows: 4
SELECT *,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN 0 PRECEDING AND 0 FOLLOWING) N,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE TIES) T,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN 1 PRECEDING AND 0 FOLLOWING EXCLUDE TIES) T1
FROM TEST;
> ID VALUE N T T1
> -- ----- --------- --- ------------
> 1 1 (1, 2) (1) (1)
> 2 1 (1, 2) (2) (2)
> 3 5 (3) (3) (1, 2, 3)
> 4 8 (4, 5, 6) (4) (3, 4)
> 5 8 (4, 5, 6) (5) (3, 5)
> 6 8 (4, 5, 6) (6) (3, 6)
> 7 9 (7, 8) (7) (4, 5, 6, 7)
> 8 9 (7, 8) (8) (4, 5, 6, 8)
> rows: 8
SELECT *,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) U_P,
ARRAY_AGG(ID) OVER (ORDER BY VALUE GROUPS BETWEEN 2 PRECEDING AND 1 PRECEDING) P,
......@@ -384,6 +401,54 @@ SELECT *,
> 8 9 (4, 5, 6, 7, 8) (7, 8)
> rows: 8
SELECT ID, VALUE,
ARRAY_AGG(ID) OVER (ORDER BY VALUE ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING EXCLUDE GROUP) G,
ARRAY_AGG(ID) OVER (ORDER BY VALUE ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING EXCLUDE TIES) T
FROM TEST;
> ID VALUE G T
> -- ----- ------------ ---------------
> 1 1 (3) (1, 3)
> 2 1 (3, 4) (2, 3, 4)
> 3 5 (1, 2, 4, 5) (1, 2, 3, 4, 5)
> 4 8 (2, 3) (2, 3, 4)
> 5 8 (3, 7) (3, 5, 7)
> 6 8 (7, 8) (6, 7, 8)
> 7 9 (5, 6) (5, 6, 7)
> 8 9 (6) (6, 8)
> rows: 8
SELECT ID, VALUE, ARRAY_AGG(ID) OVER(ORDER BY VALUE ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWING EXCLUDE GROUP) G
FROM TEST ORDER BY ID FETCH FIRST 3 ROWS ONLY;
> ID VALUE G
> -- ----- ------
> 1 1 (3)
> 2 1 (3, 4)
> 3 5 (4, 5)
> rows (ordered): 3
SELECT ID, VALUE, ARRAY_AGG(ID) OVER(ORDER BY VALUE ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING EXCLUDE GROUP) G
FROM TEST ORDER BY ID FETCH FIRST 3 ROWS ONLY;
> ID VALUE G
> -- ----- ------
> 1 1 null
> 2 1 null
> 3 5 (1, 2)
> rows (ordered): 3
SELECT ID, VALUE, ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN 2 PRECEDING AND 1 PRECEDING) A
FROM TEST;
> ID VALUE A
> -- ----- ---------
> 1 1 null
> 2 1 null
> 3 5 null
> 4 8 null
> 5 8 null
> 6 8 null
> 7 9 (4, 5, 6)
> 8 9 (4, 5, 6)
> rows: 8
SELECT *, ARRAY_AGG(ID) OVER (ORDER BY ID RANGE BETWEEN CURRENT ROW AND 1 PRECEDING) FROM TEST;
> exception SYNTAX_ERROR_1
......@@ -430,5 +495,33 @@ SELECT *, ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN 1 FOLLOWING AND 2 FOL
> 8 4 null
> rows: 8
SELECT ID, VALUE, ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN 2 PRECEDING AND 1 PRECEDING EXCLUDE CURRENT ROW) A
FROM TEST;
> ID VALUE A
> -- ----- ------------
> 1 1 null
> 2 1 null
> 3 2 (1, 2)
> 4 2 (1, 2)
> 5 3 (1, 2, 3, 4)
> 6 3 (1, 2, 3, 4)
> 7 4 (3, 4, 5, 6)
> 8 4 (3, 4, 5, 6)
> rows: 8
SELECT ID, VALUE, ARRAY_AGG(ID) OVER (ORDER BY VALUE RANGE BETWEEN 1 FOLLOWING AND 1 FOLLOWING EXCLUDE CURRENT ROW) A
FROM TEST;
> ID VALUE A
> -- ----- ------
> 1 1 (3, 4)
> 2 1 (3, 4)
> 3 2 (5, 6)
> 4 2 (5, 6)
> 5 3 (7, 8)
> 6 3 (7, 8)
> 7 4 null
> 8 4 null
> rows: 8
DROP TABLE TEST;
> ok
......@@ -146,5 +146,76 @@ SELECT ID, CATEGORY,
> 3 1 1 1
> rows: 3
SELECT ID, CATEGORY,
NTH_VALUE(CATEGORY, 2) FROM LAST OVER (ORDER BY CATEGORY RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) C,
NTH_VALUE(CATEGORY, 2) FROM LAST OVER (ORDER BY CATEGORY RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW)
FROM TEST OFFSET 10 ROWS;
> ID CATEGORY C NTH_VALUE(CATEGORY, 2) FROM LAST OVER (ORDER BY CATEGORY RANGE BETWEEN CURRENT_ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW)
> -- -------- ---- -------------------------------------------------------------------------------------------------------------------------------
> 11 3 4 4
> 12 4 4 null
> 13 4 null null
> rows: 3
SELECT ID, CATEGORY,
NTH_VALUE(CATEGORY, 2) FROM LAST OVER (ORDER BY CATEGORY RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW) C
FROM TEST OFFSET 10 ROWS;
> ID CATEGORY C
> -- -------- -
> 11 3 4
> 12 4 3
> 13 4 3
> rows: 3
SELECT ID, CATEGORY,
NTH_VALUE(CATEGORY, 1) OVER (ORDER BY CATEGORY RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE GROUP) F1,
NTH_VALUE(CATEGORY, 2) OVER (ORDER BY CATEGORY RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE GROUP) F2,
NTH_VALUE(CATEGORY, 5) OVER (ORDER BY CATEGORY RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE GROUP) F5,
NTH_VALUE(CATEGORY, 5) FROM LAST OVER (ORDER BY CATEGORY RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE GROUP) L5,
NTH_VALUE(CATEGORY, 2) FROM LAST OVER (ORDER BY CATEGORY RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE GROUP) L2,
NTH_VALUE(CATEGORY, 1) FROM LAST OVER (ORDER BY CATEGORY RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE GROUP) L1
FROM TEST ORDER BY ID;
> ID CATEGORY F1 F2 F5 L5 L2 L1
> -- -------- -- -- -- -- -- --
> 1 1 2 2 3 3 4 4
> 2 1 2 2 3 3 4 4
> 3 1 2 2 3 3 4 4
> 4 1 2 2 3 3 4 4
> 5 1 2 2 3 3 4 4
> 6 1 2 2 3 3 4 4
> 7 2 1 1 1 3 4 4
> 8 2 1 1 1 3 4 4
> 9 3 1 1 1 1 4 4
> 10 3 1 1 1 1 4 4
> 11 3 1 1 1 1 4 4
> 12 4 1 1 1 2 3 3
> 13 4 1 1 1 2 3 3
> rows (ordered): 13
SELECT ID, CATEGORY,
NTH_VALUE(CATEGORY, 1) OVER (ORDER BY CATEGORY RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE TIES) F1,
NTH_VALUE(CATEGORY, 2) OVER (ORDER BY CATEGORY RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE TIES) F2,
NTH_VALUE(CATEGORY, 5) OVER (ORDER BY CATEGORY RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE TIES) F5,
NTH_VALUE(CATEGORY, 5) FROM LAST OVER (ORDER BY CATEGORY RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE TIES) L5,
NTH_VALUE(CATEGORY, 2) FROM LAST OVER (ORDER BY CATEGORY RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE TIES) L2,
NTH_VALUE(CATEGORY, 1) FROM LAST OVER (ORDER BY CATEGORY RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE TIES) L1
FROM TEST ORDER BY ID;
> ID CATEGORY F1 F2 F5 L5 L2 L1
> -- -------- -- -- -- -- -- --
> 1 1 1 2 3 3 4 4
> 2 1 1 2 3 3 4 4
> 3 1 1 2 3 3 4 4
> 4 1 1 2 3 3 4 4
> 5 1 1 2 3 3 4 4
> 6 1 1 2 3 3 4 4
> 7 2 1 1 1 3 4 4
> 8 2 1 1 1 3 4 4
> 9 3 1 1 1 2 4 4
> 10 3 1 1 1 2 4 4
> 11 3 1 1 1 2 4 4
> 12 4 1 1 1 2 3 4
> 13 4 1 1 1 2 3 4
> rows (ordered): 13
DROP TABLE TEST;
> ok
......@@ -797,6 +797,6 @@ xym normalizes coord setz xyzm geometrycollection multipolygon mixup rings polyg
pointzm pointz pointm dimensionality redefine forum measures
mpg casted pzm mls constrained subtypes complains
ranks rno dro rko precede cume reopens preceding unbounded rightly itr lag maximal tiles tile ntile signify
partitioned
partitioned tri
discard enhancements nolock
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论