Skip to content

Commit a0046c6

Browse files
feat: supported date32, datetime64, timestamp64, interval64
1 parent 5f7959f commit a0046c6

File tree

10 files changed

+436
-136
lines changed

10 files changed

+436
-136
lines changed

bom/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
<properties>
1717
<ydb-auth-api.version>1.0.0</ydb-auth-api.version>
18-
<ydb-proto-api.version>1.6.4</ydb-proto-api.version>
18+
<ydb-proto-api.version>1.7.0</ydb-proto-api.version>
1919
<yc-auth.version>2.2.0</yc-auth.version>
2020
</properties>
2121

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package tech.ydb.query;
2+
3+
import java.time.Duration;
4+
import java.time.Instant;
5+
import java.time.LocalDate;
6+
import java.time.LocalDateTime;
7+
8+
import org.junit.Assert;
9+
import org.junit.ClassRule;
10+
import org.junit.Test;
11+
12+
import tech.ydb.common.transaction.TxMode;
13+
import tech.ydb.query.tools.QueryReader;
14+
import tech.ydb.query.tools.SessionRetryContext;
15+
import tech.ydb.table.query.Params;
16+
import tech.ydb.table.result.ResultSetReader;
17+
import tech.ydb.table.values.PrimitiveValue;
18+
import tech.ydb.test.junit4.GrpcTransportRule;
19+
20+
/**
21+
* @author Kirill Kurdyukov
22+
*/
23+
public class ValueReadTest {
24+
25+
@ClassRule
26+
public final static GrpcTransportRule ydbTransport = new GrpcTransportRule();
27+
28+
private final SessionRetryContext CTX = SessionRetryContext.create(QueryClient.newClient(ydbTransport).build()).build();
29+
30+
// @Test TODO
31+
public void date32datetime64timestamp64interval64() {
32+
date32datetime64timestamp64interval64Assert(
33+
LocalDate.of(988, 2, 6),
34+
LocalDateTime.of(988, 2, 7, 12, 30, 0),
35+
Instant.parse("0998-06-02T12:30:00.678901Z"),
36+
Duration.parse("-PT2S")
37+
);
38+
39+
// date32datetime64timestamp64interval64Assert(
40+
// LocalDate.MIN,
41+
// LocalDateTime.MIN,
42+
// Instant.MIN,
43+
// Duration.ZERO
44+
// );
45+
46+
47+
QueryReader reader = CTX.supplyResult(
48+
s -> QueryReader.readFrom(s.createQuery("SELECT " +
49+
" Date32('998-06-02') AS c1,\n" +
50+
" Datetime64('0998-06-02T12:30:00Z') AS c2,\n" +
51+
" Timestamp64('0998-06-02T12:30:00.678901Z') AS c3,\n" +
52+
" Interval64('-PT2S') AS c4;", TxMode.NONE))
53+
).join().getValue();
54+
55+
ResultSetReader resultSetReader = reader.getResultSet(0);
56+
57+
Assert.assertTrue(resultSetReader.next());
58+
Assert.assertEquals(LocalDate.parse("0998-06-02"), resultSetReader.getColumn(0).getDate32());
59+
Assert.assertEquals(LocalDateTime.parse("0998-06-02T12:30:00"), resultSetReader.getColumn(1).getDatetime64());
60+
Assert.assertEquals(Instant.parse("0998-06-02T12:30:00.678901Z"), resultSetReader.getColumn(2).getTimestamp64());
61+
Assert.assertEquals(Duration.parse("-PT2S"), resultSetReader.getColumn(3).getInterval64());
62+
}
63+
64+
private void date32datetime64timestamp64interval64Assert(LocalDate date32, LocalDateTime datetime64,
65+
Instant timestamp64, Duration interval64) {
66+
QueryReader reader = CTX.supplyResult(
67+
s -> QueryReader.readFrom(s.createQuery("" +
68+
"DECLARE $date32 AS Date32;\n" +
69+
"DECLARE $datetime64 AS Datetime64;\n" +
70+
"DECLARE $timestamp64 AS Timestamp64;\n" +
71+
"DECLARE $interval64 AS Instant64;\n" +
72+
"SELECT $date32, $datetime64, $timestamp64, $interval64;",
73+
TxMode.SERIALIZABLE_RW,
74+
Params.of(
75+
"$date32", PrimitiveValue.newDate32(date32),
76+
"$datetime64", PrimitiveValue.newDatetime64(datetime64),
77+
"$timestamp64", PrimitiveValue.newTimestamp64(timestamp64),
78+
"$interval64", PrimitiveValue.newInterval64(interval64)
79+
)
80+
))
81+
).join().getValue();
82+
83+
ResultSetReader resultSetReader = reader.getResultSet(0);
84+
85+
Assert.assertTrue(resultSetReader.next());
86+
Assert.assertEquals(date32, resultSetReader.getColumn(0).getDate32());
87+
Assert.assertEquals(datetime64, resultSetReader.getColumn(1).getDatetime64());
88+
Assert.assertEquals(timestamp64, resultSetReader.getColumn(2).getTimestamp64());
89+
Assert.assertEquals(interval64, resultSetReader.getColumn(3).getInterval64());
90+
}
91+
}

table/src/main/java/tech/ydb/table/result/PrimitiveReader.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ public interface PrimitiveReader {
4646

4747
Duration getInterval();
4848

49+
LocalDate getDate32();
50+
51+
LocalDateTime getDatetime64();
52+
53+
Instant getTimestamp64();
54+
55+
Duration getInterval64();
56+
4957
ZonedDateTime getTzDate();
5058

5159
ZonedDateTime getTzDatetime();

table/src/main/java/tech/ydb/table/result/impl/AbstractValueReader.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,24 @@ public Duration getInterval() {
116116
throw error("getInterval");
117117
}
118118

119+
@Override
120+
public LocalDate getDate32() {
121+
throw error("getDate32");
122+
}
123+
124+
public LocalDateTime getDatetime64() {
125+
throw error("getDatetime64");
126+
}
127+
128+
@Override
129+
public Instant getTimestamp64() {
130+
throw error("getTimestamp64");
131+
}
132+
133+
public Duration getInterval64() {
134+
throw error("getInterval64");
135+
}
136+
119137
@Override
120138
public ZonedDateTime getTzDate() {
121139
throw error("getTzDate");

table/src/main/java/tech/ydb/table/result/impl/ProtoPrimitiveValueReader.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,30 @@ public Duration getInterval() {
139139
return ProtoValue.toInterval(value);
140140
}
141141

142+
@Override
143+
public LocalDate getDate32() {
144+
checkPrimitive(PrimitiveTypeId.DATE32);
145+
return ProtoValue.toDate32(value);
146+
}
147+
148+
@Override
149+
public LocalDateTime getDatetime64() {
150+
checkPrimitive(PrimitiveTypeId.DATETIME64);
151+
return ProtoValue.toDatetime64(value);
152+
}
153+
154+
@Override
155+
public Instant getTimestamp64() {
156+
checkPrimitive(PrimitiveTypeId.TIMESTAMP64);
157+
return ProtoValue.toTimestamp64(value);
158+
}
159+
160+
@Override
161+
public Duration getInterval64() {
162+
checkPrimitive(PrimitiveTypeId.INTERVAL64);
163+
return ProtoValue.toInterval64(value);
164+
}
165+
142166
@Override
143167
public ZonedDateTime getTzDate() {
144168
checkPrimitive(PrimitiveTypeId.TZ_DATE);

table/src/main/java/tech/ydb/table/values/PrimitiveType.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,20 @@ public enum PrimitiveType implements Type {
5858
/** JSON in an indexed binary representation. Doesn't support matching, can't be used in the primary key */
5959
JsonDocument(ProtoType.getJsonDocument()),
6060
/** A binary representation of a real number with an accuracy of up to 38 digits.
61-
* Acceptable values: positive numbers from 1×10-130 up to 1×10126–1,
62-
* negative numbers from -1×10126–1 to -1×10-130, and 0.
63-
* Compatible with the Number type in AWS DynamoDB.
64-
* It's not recommended for ydb-native applications.
65-
*/
66-
DyNumber(ProtoType.getDyNumber());
61+
* Acceptable values: positive numbers from 1×10-130 up to 1×10126–1,
62+
* negative numbers from -1×10126–1 to -1×10-130, and 0.
63+
* Compatible with the Number type in AWS DynamoDB.
64+
* It's not recommended for ydb-native applications.
65+
*/
66+
DyNumber(ProtoType.getDyNumber()),
67+
68+
Date32(ProtoType.getDate32()),
69+
70+
Datetime64(ProtoType.getDatetime64()),
71+
72+
Timestamp64(ProtoType.getTimestamp64()),
73+
74+
Interval64(ProtoType.getInterval64());
6775

6876
private final ValueProtos.Type pbType;
6977

table/src/main/java/tech/ydb/table/values/PrimitiveValue.java

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import tech.ydb.table.values.proto.ProtoValue;
2323

2424

25-
2625
/**
2726
* @author Sergey Polovko
2827
*/
@@ -63,8 +62,8 @@ public long getInt64() {
6362
}
6463

6564
/** JVM does not support unsigned long, be careful when using this method
66-
for numbers greater than Long.MAX_VALUE.For correct work you can use wrappers
67-
like {@link com.google.common.primitives.UnsignedLong#fromLongBits(long) UnsignedLong }
65+
for numbers greater than Long.MAX_VALUE.For correct work you can use wrappers
66+
like {@link com.google.common.primitives.UnsignedLong#fromLongBits(long) UnsignedLong }
6867
* @return signed long value corresponding to a bit representation of unsigned.*/
6968
public long getUint64() {
7069
throw new IllegalStateException("expected Uint64, but was " + getClass().getSimpleName());
@@ -164,6 +163,22 @@ public ZonedDateTime getTzTimestamp() {
164163
throw new IllegalStateException("expected TzTimestamp, but was " + getClass().getSimpleName());
165164
}
166165

166+
public LocalDate getDate32() {
167+
throw new IllegalStateException("expected Date32, but was " + getClass().getSimpleName());
168+
}
169+
170+
public LocalDateTime getDatetime64() {
171+
throw new IllegalStateException("expected Datetime64, but was " + getClass().getSimpleName());
172+
}
173+
174+
public Instant getTimestamp64() {
175+
throw new IllegalStateException("expected Timestamp64, but was " + getClass().getSimpleName());
176+
}
177+
178+
public Duration getInterval64() {
179+
throw new IllegalStateException("expected Interval64, but was " + getClass().getSimpleName());
180+
}
181+
167182
// -- constructors --
168183

169184
public static PrimitiveValue newBool(boolean value) {
@@ -274,6 +289,19 @@ public static PrimitiveValue newDate(Instant value) {
274289
return newDate(TimeUnit.SECONDS.toDays(value.getEpochSecond()));
275290
}
276291

292+
public static PrimitiveValue newDate32(long daysSinceEpoch) {
293+
return new InstantValue(PrimitiveType.Date32, TimeUnit.DAYS.toMicros(daysSinceEpoch));
294+
}
295+
296+
public static PrimitiveValue newDate32(LocalDate value) {
297+
return newDate32(value.toEpochDay());
298+
}
299+
300+
public static PrimitiveValue newDate32(Instant value) {
301+
return newDate32(TimeUnit.SECONDS.toDays(value.getEpochSecond()));
302+
}
303+
304+
277305
public static PrimitiveValue newDatetime(long secondsSinceEpoch) {
278306
if (secondsSinceEpoch < 0) {
279307
throw new IllegalArgumentException("negative secondsSinceEpoch: " + secondsSinceEpoch);
@@ -289,6 +317,18 @@ public static PrimitiveValue newDatetime(LocalDateTime value) {
289317
return newDatetime(value.toEpochSecond(ZoneOffset.UTC));
290318
}
291319

320+
public static PrimitiveValue newDatetime64(long secondsSinceEpoch) {
321+
return new InstantValue(PrimitiveType.Datetime64, TimeUnit.SECONDS.toMicros(secondsSinceEpoch));
322+
}
323+
324+
public static PrimitiveValue newDatetime64(Instant value) {
325+
return newDatetime64(value.getEpochSecond());
326+
}
327+
328+
public static PrimitiveValue newDatetime64(LocalDateTime value) {
329+
return newDatetime64(value.toEpochSecond(ZoneOffset.UTC));
330+
}
331+
292332
public static PrimitiveValue newTimestamp(long microsSinceEpoch) {
293333
if (microsSinceEpoch < 0) {
294334
throw new IllegalArgumentException("microsSinceEpoch value is before "
@@ -317,14 +357,32 @@ public static PrimitiveValue newTimestamp(Instant value) {
317357
return new InstantValue(PrimitiveType.Timestamp, micros);
318358
}
319359

360+
public static PrimitiveValue newTimestamp64(long microsSinceEpoch) {
361+
return new InstantValue(PrimitiveType.Timestamp, microsSinceEpoch);
362+
}
363+
364+
public static PrimitiveValue newTimestamp64(Instant value) {
365+
long micros = TimeUnit.SECONDS.toMicros(value.getEpochSecond()) +
366+
TimeUnit.NANOSECONDS.toMicros(value.getNano());
367+
return new InstantValue(PrimitiveType.Timestamp, micros);
368+
}
369+
320370
public static PrimitiveValue newInterval(long micros) {
321-
return new IntervalValue(micros);
371+
return new IntervalValue(PrimitiveType.Interval, micros);
322372
}
323373

324374
public static PrimitiveValue newInterval(Duration value) {
325375
return newInterval(TimeUnit.NANOSECONDS.toMicros(value.toNanos()));
326376
}
327377

378+
public static PrimitiveValue newInterval64(long micros) {
379+
return new IntervalValue(PrimitiveType.Interval64, micros);
380+
}
381+
382+
public static PrimitiveValue newInterval64(Duration value) {
383+
return newInterval(TimeUnit.NANOSECONDS.toMicros(value.toNanos()));
384+
}
385+
328386
public static PrimitiveValue newTzDate(ZonedDateTime dateTime) {
329387
return new TzDatetime(PrimitiveType.TzDate, dateTime);
330388
}

table/src/main/java/tech/ydb/table/values/proto/ProtoType.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ public class ProtoType {
6262
private static final ValueProtos.Type TZ_TIMESTAMP = primitiveType(PrimitiveTypeId.TZ_TIMESTAMP);
6363
private static final ValueProtos.Type JSON_DOCUMENT = primitiveType(PrimitiveTypeId.JSON_DOCUMENT);
6464
private static final ValueProtos.Type DYNUMBER = primitiveType(PrimitiveTypeId.DYNUMBER);
65+
private static final ValueProtos.Type DATE32 = primitiveType(PrimitiveTypeId.DATE32);
66+
private static final ValueProtos.Type DATETIME64 = primitiveType(PrimitiveTypeId.DATETIME64);
67+
private static final ValueProtos.Type TIMESTAMP64 = primitiveType(PrimitiveTypeId.TIMESTAMP64);
68+
private static final ValueProtos.Type INTERVAL64 = primitiveType(PrimitiveTypeId.INTERVAL64);
6569

6670
private ProtoType() { }
6771

@@ -171,6 +175,22 @@ public static ValueProtos.Type getDyNumber() {
171175
return DYNUMBER;
172176
}
173177

178+
public static ValueProtos.Type getDate32() {
179+
return DATE32;
180+
}
181+
182+
public static ValueProtos.Type getDatetime64() {
183+
return DATETIME64;
184+
}
185+
186+
public static ValueProtos.Type getTimestamp64() {
187+
return TIMESTAMP64;
188+
}
189+
190+
public static ValueProtos.Type getInterval64() {
191+
return INTERVAL64;
192+
}
193+
174194
public static ValueProtos.Type getDecimal(int precision, int scale) {
175195
ValueProtos.Type.Builder builder = ValueProtos.Type.newBuilder();
176196
builder.getDecimalTypeBuilder()

0 commit comments

Comments
 (0)