Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,10 @@ The Databend type is mapped to Java type as follows:
| Decimal | BigDecimal |
| String | String |
| Date | LocalDate |
| TIMESTAMP | ZonedDateTime |
| TIMESTAMP_TZ | OffsetDateTime |
| Timestamp | ZonedDateTime |
| Timestamp_TZ | OffsetDateTime |
| Interval | String |
| Geometry | byte[] |
| Bitmap | byte[] |
| Array | String |
| Tuple | String |
Expand All @@ -114,24 +116,23 @@ The Databend type is mapped to Java type as follows:

### Temporal types

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

```
void setObject(int parameterIndex, Object x)
<T> T getObject(int columnIndex, Class<T> type)
```

- TIMESTAMP_TZ and TIMESTAMP map to `OffsetDateTime`, `ZonedDateTime`, `Instant` and `LocalDateTime` (TIMESTAMP_TZ can return `OffsetDateTime` but not `ZonedDateTime`).
- Date maps to `LocalDate`, and `getObject(..., LocalDate.class)` now mirrors what `getDate().toLocalDate()` returns.
- Date maps to `LocalDate`
- 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.
- `getString` return the display of default mapping type.

Timestamp/Date are also supported, note that:
old Timestamp/Date are also supported, note that:

- `getTimestamp(int, Calendar cal)` is the same as `getTimestamp(int)` (the cal is omitted) and
- `getTimestamp(int, Calendar cal)` is equivalent to `getTimestamp(int)` (the cal is omitted) and
`getObject(int, Instant.classes).toTimestamp()`
- `setTimestamp(int, Calendar cal)` is diff with `setTimestamp(int)`, the epoch is adjusted according to timezone in cal
- `setDate`/`getDate` still use the JVM timezone, and `setObject(localDate)` is equivalent to `setDate(Date.valueOf(localDate))`.
- `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())`.


# Unwrapping to Databend-specific interfaces
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,8 @@ public void setObject(int parameterIndex, Object x)
setString(parameterIndex, toTimeWithTimeZoneLiteral(x));
} else if (x instanceof Instant) {
setValueString(parameterIndex, x.toString());
} else if (x instanceof LocalDateTime) {
setValueString(parameterIndex, x.toString());
} else if (x instanceof Timestamp) {
setTimestamp(parameterIndex, (Timestamp) x);
} else if (x instanceof OffsetDateTime) {
Expand Down
37 changes: 0 additions & 37 deletions databend-jdbc/src/test/java/com/databend/jdbc/TestGeometry.java
Original file line number Diff line number Diff line change
@@ -1,42 +1,5 @@
package com.databend.jdbc;

import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKBReader;
import org.testng.Assert;
import org.testng.annotations.Test;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestGeometry {
@Test(groups = {"IT"})
public void testSelectGeometry() throws SQLException, ParseException {
try (Connection connection = Utils.createConnection();
Statement statement = connection.createStatement()
) {
statement.execute("set enable_geo_create_table=1");
statement.execute("CREATE or replace table cities ( id INT, name VARCHAR NOT NULL, location GEOMETRY);");
statement.execute("INSERT INTO cities (id, name, location) VALUES (1, 'New York', 'POINT (-73.935242 40.73061))');");
statement.execute("INSERT INTO cities (id, name, location) VALUES (2, 'Null', null);");
try (ResultSet r = statement.executeQuery("select location from cities order by id")) {
r.next();
Assert.assertEquals("{\"type\": \"Point\", \"coordinates\": [-73.935242,40.73061]}", r.getObject(1));
r.next();
Assert.assertNull(r.getObject(1));
}

// set geometry_output_format to wkb
connection.createStatement().execute("set geometry_output_format='WKB'");
try (ResultSet r = statement.executeQuery("select location from cities order by id")) {
r.next();
byte[] wkb = r.getBytes(1);
WKBReader wkbReader = new WKBReader();
Geometry geometry = wkbReader.read(wkb);
Assert.assertEquals("POINT (-73.935242 40.73061)", geometry.toText());
}
}
}
}
76 changes: 66 additions & 10 deletions databend-jdbc/src/test/java/com/databend/jdbc/TestTypes.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
package com.databend.jdbc;

import com.vdurmont.semver4j.Semver;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKBReader;
import org.testng.Assert;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.sql.*;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.*;
import java.util.Calendar;
import java.util.TimeZone;

Expand Down Expand Up @@ -185,11 +182,15 @@ public void testSetTimestamp(boolean withTz)
ps.setInt(2, 6);
ps.execute();

// 7: diff epoch, set use session tz
// 7, 8: diff epoch, set use session tz
ps.setString(1, timeStringNoTZ);
ps.setInt(2, 7);
ps.execute();

ps.setObject(1, LocalDateTime.parse(timeStringNoTZ));
ps.setInt(2, 8);
ps.execute();

r = statement.executeQuery("select a from test_ts_tz order by b");

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

// 7: set use session tz
// 7, 8: set use session tz
r.next();
o = r.getObject(1, OffsetDateTime.class);
Assert.assertEquals(o.toInstant(), Instant.parse("2021-01-12T22:30:55.123Z"));
Assert.assertEquals(o.getOffset().getTotalSeconds(), -8 * 3600);

r.next();
o = r.getObject(1, OffsetDateTime.class);
Assert.assertEquals(o.toInstant(), Instant.parse("2021-01-12T22:30:55.123Z"));
Expand Down Expand Up @@ -269,7 +275,7 @@ public void TestDate(String tz, boolean useLocalDate) throws SQLException {

PreparedStatement ps = c.prepareStatement("insert into t1 values (?)");
if (useLocalDate) {
ps.setDate(1, date);
ps.setObject(1, localDate);
} else {
ps.setDate(1, date);
}
Expand All @@ -293,4 +299,54 @@ public void TestDate(String tz, boolean useLocalDate) throws SQLException {
Assert.assertFalse(r.next());
}
}

@Test(groups = {"IT"})
public void TestInterval() throws SQLException {
try (Connection c = Utils.createConnection();
Statement s = c.createStatement()) {

s.execute("create or replace table test_interval(a interval)");

PreparedStatement ps = c.prepareStatement("insert into test_interval values (?)");
String interval = "-3 days";
ps.setString(1, interval);
ps.execute();

s.execute("SELECT * from test_interval");
ResultSet r = s.getResultSet();

Assert.assertTrue(r.next());
Assert.assertEquals(r.getString(1), interval);

Assert.assertFalse(r.next());
}
}

@Test(groups = {"IT"})
public void testSelectGeometry() throws SQLException, ParseException {
try (Connection connection = Utils.createConnection();
Statement statement = connection.createStatement()
) {
statement.execute("set enable_geo_create_table=1");
statement.execute("CREATE or replace table cities ( id INT, name VARCHAR NOT NULL, location GEOMETRY);");
statement.execute("INSERT INTO cities (id, name, location) VALUES (1, 'New York', 'POINT (-73.935242 40.73061))');");
statement.execute("INSERT INTO cities (id, name, location) VALUES (2, 'Null', null);");
try (ResultSet r = statement.executeQuery("select location from cities order by id")) {
r.next();
Assert.assertEquals("{\"type\": \"Point\", \"coordinates\": [-73.935242,40.73061]}", r.getObject(1));
r.next();
Assert.assertNull(r.getObject(1));
}

// set geometry_output_format to wkb
connection.createStatement().execute("set geometry_output_format='WKB'");
try (ResultSet r = statement.executeQuery("select location from cities order by id")) {
r.next();
byte[] wkb = r.getBytes(1);
WKBReader wkbReader = new WKBReader();
Geometry geometry = wkbReader.read(wkb);
Assert.assertEquals("POINT (-73.935242 40.73061)", geometry.toText());
}
}
}
}
Loading