Skip to content

Commit 08e662d

Browse files
authored
Merge pull request #371 from youngsofun/ts
feat: support set LocalDateTime.
2 parents a886510 + 95f4f50 commit 08e662d

File tree

4 files changed

+77
-55
lines changed

4 files changed

+77
-55
lines changed

README.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,10 @@ The Databend type is mapped to Java type as follows:
104104
| Decimal | BigDecimal |
105105
| String | String |
106106
| Date | LocalDate |
107-
| TIMESTAMP | ZonedDateTime |
108-
| TIMESTAMP_TZ | OffsetDateTime |
107+
| Timestamp | ZonedDateTime |
108+
| Timestamp_TZ | OffsetDateTime |
109+
| Interval | String |
110+
| Geometry | byte[] |
109111
| Bitmap | byte[] |
110112
| Array | String |
111113
| Tuple | String |
@@ -114,24 +116,23 @@ The Databend type is mapped to Java type as follows:
114116

115117
### Temporal types
116118

117-
we recommend using `java.time` to avoid ambiguity and letting the driver format values via these APIs:
119+
we recommend using `java.time` to avoid ambiguity and set/get values via these APIs:
118120

119121
```
120122
void setObject(int parameterIndex, Object x)
121123
<T> T getObject(int columnIndex, Class<T> type)
122124
```
123125

124126
- TIMESTAMP_TZ and TIMESTAMP map to `OffsetDateTime`, `ZonedDateTime`, `Instant` and `LocalDateTime` (TIMESTAMP_TZ can return `OffsetDateTime` but not `ZonedDateTime`).
125-
- Date maps to `LocalDate`, and `getObject(..., LocalDate.class)` now mirrors what `getDate().toLocalDate()` returns.
127+
- Date maps to `LocalDate`
126128
- When parameters do not contain a timezone, Databend uses the session timezone (not the JVM zone) when storing/returning dates on databend-jdbc ≥ 0.4.3 AND databend-query ≥1.2.844.
127-
- `getString` return the display of default mapping type.
128129

129-
Timestamp/Date are also supported, note that:
130+
old Timestamp/Date are also supported, note that:
130131

131-
- `getTimestamp(int, Calendar cal)` is the same as `getTimestamp(int)` (the cal is omitted) and
132+
- `getTimestamp(int, Calendar cal)` is equivalent to `getTimestamp(int)` (the cal is omitted) and
132133
`getObject(int, Instant.classes).toTimestamp()`
133134
- `setTimestamp(int, Calendar cal)` is diff with `setTimestamp(int)`, the epoch is adjusted according to timezone in cal
134-
- `setDate`/`getDate` still use the JVM timezone, and `setObject(localDate)` is equivalent to `setDate(Date.valueOf(localDate))`.
135+
- `setDate`/`getDate` still use the JVM timezone, `getDate(1)` is equivalent to `Date.valueOf(getObject(1, LocalDate.class))`, `setDate(1, date)` is equivalent to `setObject(1, date.toLocalDate())`.
135136

136137

137138
# Unwrapping to Databend-specific interfaces

databend-jdbc/src/main/java/com/databend/jdbc/DatabendPreparedStatement.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,8 @@ public void setObject(int parameterIndex, Object x)
554554
setString(parameterIndex, toTimeWithTimeZoneLiteral(x));
555555
} else if (x instanceof Instant) {
556556
setValueString(parameterIndex, x.toString());
557+
} else if (x instanceof LocalDateTime) {
558+
setValueString(parameterIndex, x.toString());
557559
} else if (x instanceof Timestamp) {
558560
setTimestamp(parameterIndex, (Timestamp) x);
559561
} else if (x instanceof OffsetDateTime) {
Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,5 @@
11
package com.databend.jdbc;
22

3-
import org.locationtech.jts.geom.Geometry;
4-
import org.locationtech.jts.io.ParseException;
5-
import org.locationtech.jts.io.WKBReader;
6-
import org.testng.Assert;
7-
import org.testng.annotations.Test;
8-
9-
import java.sql.Connection;
10-
import java.sql.ResultSet;
11-
import java.sql.SQLException;
12-
import java.sql.Statement;
13-
143
public class TestGeometry {
15-
@Test(groups = {"IT"})
16-
public void testSelectGeometry() throws SQLException, ParseException {
17-
try (Connection connection = Utils.createConnection();
18-
Statement statement = connection.createStatement()
19-
) {
20-
statement.execute("set enable_geo_create_table=1");
21-
statement.execute("CREATE or replace table cities ( id INT, name VARCHAR NOT NULL, location GEOMETRY);");
22-
statement.execute("INSERT INTO cities (id, name, location) VALUES (1, 'New York', 'POINT (-73.935242 40.73061))');");
23-
statement.execute("INSERT INTO cities (id, name, location) VALUES (2, 'Null', null);");
24-
try (ResultSet r = statement.executeQuery("select location from cities order by id")) {
25-
r.next();
26-
Assert.assertEquals("{\"type\": \"Point\", \"coordinates\": [-73.935242,40.73061]}", r.getObject(1));
27-
r.next();
28-
Assert.assertNull(r.getObject(1));
29-
}
304

31-
// set geometry_output_format to wkb
32-
connection.createStatement().execute("set geometry_output_format='WKB'");
33-
try (ResultSet r = statement.executeQuery("select location from cities order by id")) {
34-
r.next();
35-
byte[] wkb = r.getBytes(1);
36-
WKBReader wkbReader = new WKBReader();
37-
Geometry geometry = wkbReader.read(wkb);
38-
Assert.assertEquals("POINT (-73.935242 40.73061)", geometry.toText());
39-
}
40-
}
41-
}
425
}

databend-jdbc/src/test/java/com/databend/jdbc/TestTypes.java

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
package com.databend.jdbc;
22

33
import com.vdurmont.semver4j.Semver;
4+
import org.locationtech.jts.geom.Geometry;
5+
import org.locationtech.jts.io.ParseException;
6+
import org.locationtech.jts.io.WKBReader;
47
import org.testng.Assert;
58
import org.testng.annotations.BeforeSuite;
69
import org.testng.annotations.BeforeTest;
710
import org.testng.annotations.DataProvider;
811
import org.testng.annotations.Test;
912

1013
import java.sql.*;
11-
import java.time.Instant;
12-
import java.time.LocalDate;
13-
import java.time.LocalDateTime;
14-
import java.time.OffsetDateTime;
15-
import java.time.ZoneId;
16-
import java.time.ZoneOffset;
17-
import java.time.ZonedDateTime;
14+
import java.time.*;
1815
import java.util.Calendar;
1916
import java.util.TimeZone;
2017

@@ -185,11 +182,15 @@ public void testSetTimestamp(boolean withTz)
185182
ps.setInt(2, 6);
186183
ps.execute();
187184

188-
// 7: diff epoch, set use session tz
185+
// 7, 8: diff epoch, set use session tz
189186
ps.setString(1, timeStringNoTZ);
190187
ps.setInt(2, 7);
191188
ps.execute();
192189

190+
ps.setObject(1, LocalDateTime.parse(timeStringNoTZ));
191+
ps.setInt(2, 8);
192+
ps.execute();
193+
193194
r = statement.executeQuery("select a from test_ts_tz order by b");
194195

195196
ZoneId sessionZoneId = ZoneId.of("America/Los_Angeles");
@@ -226,7 +227,12 @@ public void testSetTimestamp(boolean withTz)
226227
Assert.assertEquals(o.toInstant(), offsetDateTime.toInstant());
227228
Assert.assertEquals(o.getOffset().getTotalSeconds(), expOffsetForUTC);
228229

229-
// 7: set use session tz
230+
// 7, 8: set use session tz
231+
r.next();
232+
o = r.getObject(1, OffsetDateTime.class);
233+
Assert.assertEquals(o.toInstant(), Instant.parse("2021-01-12T22:30:55.123Z"));
234+
Assert.assertEquals(o.getOffset().getTotalSeconds(), -8 * 3600);
235+
230236
r.next();
231237
o = r.getObject(1, OffsetDateTime.class);
232238
Assert.assertEquals(o.toInstant(), Instant.parse("2021-01-12T22:30:55.123Z"));
@@ -269,7 +275,7 @@ public void TestDate(String tz, boolean useLocalDate) throws SQLException {
269275

270276
PreparedStatement ps = c.prepareStatement("insert into t1 values (?)");
271277
if (useLocalDate) {
272-
ps.setDate(1, date);
278+
ps.setObject(1, localDate);
273279
} else {
274280
ps.setDate(1, date);
275281
}
@@ -293,4 +299,54 @@ public void TestDate(String tz, boolean useLocalDate) throws SQLException {
293299
Assert.assertFalse(r.next());
294300
}
295301
}
302+
303+
@Test(groups = {"IT"})
304+
public void TestInterval() throws SQLException {
305+
try (Connection c = Utils.createConnection();
306+
Statement s = c.createStatement()) {
307+
308+
s.execute("create or replace table test_interval(a interval)");
309+
310+
PreparedStatement ps = c.prepareStatement("insert into test_interval values (?)");
311+
String interval = "-3 days";
312+
ps.setString(1, interval);
313+
ps.execute();
314+
315+
s.execute("SELECT * from test_interval");
316+
ResultSet r = s.getResultSet();
317+
318+
Assert.assertTrue(r.next());
319+
Assert.assertEquals(r.getString(1), interval);
320+
321+
Assert.assertFalse(r.next());
322+
}
323+
}
324+
325+
@Test(groups = {"IT"})
326+
public void testSelectGeometry() throws SQLException, ParseException {
327+
try (Connection connection = Utils.createConnection();
328+
Statement statement = connection.createStatement()
329+
) {
330+
statement.execute("set enable_geo_create_table=1");
331+
statement.execute("CREATE or replace table cities ( id INT, name VARCHAR NOT NULL, location GEOMETRY);");
332+
statement.execute("INSERT INTO cities (id, name, location) VALUES (1, 'New York', 'POINT (-73.935242 40.73061))');");
333+
statement.execute("INSERT INTO cities (id, name, location) VALUES (2, 'Null', null);");
334+
try (ResultSet r = statement.executeQuery("select location from cities order by id")) {
335+
r.next();
336+
Assert.assertEquals("{\"type\": \"Point\", \"coordinates\": [-73.935242,40.73061]}", r.getObject(1));
337+
r.next();
338+
Assert.assertNull(r.getObject(1));
339+
}
340+
341+
// set geometry_output_format to wkb
342+
connection.createStatement().execute("set geometry_output_format='WKB'");
343+
try (ResultSet r = statement.executeQuery("select location from cities order by id")) {
344+
r.next();
345+
byte[] wkb = r.getBytes(1);
346+
WKBReader wkbReader = new WKBReader();
347+
Geometry geometry = wkbReader.read(wkb);
348+
Assert.assertEquals("POINT (-73.935242 40.73061)", geometry.toText());
349+
}
350+
}
351+
}
296352
}

0 commit comments

Comments
 (0)