提交 77f0beac authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Add partial support of DATE, TIME, and TIMESTAMP data types to PgServer

上级 11e20221
......@@ -26,10 +26,14 @@ import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Properties;
import java.util.TimeZone;
import org.h2.command.CommandInterface;
import org.h2.engine.ConnectionInfo;
import org.h2.engine.SysProperties;
......@@ -520,6 +524,11 @@ public class PgServerThread implements Runnable {
sendMessage();
}
private static long toPostgreSeconds(long millis) {
// TODO handle Julian/Gregorian transitions
return millis / 1000 - 946684800L;
}
private void writeDataColumn(ResultSet rs, int column, int pgType, boolean text)
throws Exception {
if (text) {
......@@ -562,7 +571,7 @@ public class PgServerThread implements Runnable {
writeInt(8);
dataOut.writeDouble(rs.getDouble(column));
break;
case PgServer.PG_TYPE_BYTEA:
case PgServer.PG_TYPE_BYTEA: {
byte[] data = rs.getBytes(column);
if (data == null) {
writeInt(-1);
......@@ -571,7 +580,40 @@ public class PgServerThread implements Runnable {
write(data);
}
break;
}
case PgServer.PG_TYPE_DATE: {
writeInt(4);
long millis = rs.getDate(column).getTime();
millis += TimeZone.getDefault().getOffset(millis);
writeInt((int) (toPostgreSeconds(millis) / 86400));
break;
}
case PgServer.PG_TYPE_TIME: {
writeInt(8);
Time t = rs.getTime(column);
long m = t.getTime();
m += TimeZone.getDefault().getOffset(m);
// double format
m /= 1000;
m = Double.doubleToLongBits(m);
// long format
// m *= 1000;
writeInt((int) (m >>> 32));
writeInt((int) m);
break;
}
case PgServer.PG_TYPE_TIMESTAMP_NO_TMZONE: {
writeInt(8);
Timestamp t = rs.getTimestamp(column);
long m = t.getTime();
m += TimeZone.getDefault().getOffset(m);
// double format
m = toPostgreSeconds(m);
m = Double.doubleToLongBits(m + t.getNanos() * 0.000000001);
writeInt((int) (m >>> 32));
writeInt((int) m);
break;
}
default: throw new IllegalStateException("output binary format is undefined");
}
}
......@@ -595,7 +637,28 @@ public class PgServerThread implements Runnable {
// plain text
byte[] data = DataUtils.newBytes(paramLen);
readFully(data);
prep.setString(col, new String(data, getEncoding()));
String str = new String(data, getEncoding());
switch (pgType) {
case PgServer.PG_TYPE_DATE: {
// Strip timezone offset
int idx = str.indexOf(' ');
if (idx > 0) {
str = str.substring(0, idx);
}
break;
}
case PgServer.PG_TYPE_TIME: {
// Strip timezone offset
int idx = str.indexOf('+');
if (idx <= 0)
idx = str.indexOf('-');
if (idx > 0) {
str = str.substring(0, idx);
}
break;
}
}
prep.setString(col, str);
} else {
// binary
switch (pgType) {
......
......@@ -7,6 +7,7 @@ package org.h2.test.unit;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
......@@ -14,6 +15,7 @@ import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Properties;
......@@ -406,10 +408,11 @@ public class TestPgServer extends TestBase {
stat.execute(
"create table test(x1 varchar, x2 int, " +
"x3 smallint, x4 bigint, x5 double, x6 float, " +
"x7 real, x8 boolean, x9 char, x10 bytea)");
"x7 real, x8 boolean, x9 char, x10 bytea, " +
"x11 date, x12 time, x13 timestamp)");
PreparedStatement ps = conn.prepareStatement(
"insert into test values (?,?,?,?,?,?,?,?,?,?)");
"insert into test values (?,?,?,?,?,?,?,?,?,?,?,?,?)");
ps.setString(1, "test");
ps.setInt(2, 12345678);
ps.setShort(3, (short) 12345);
......@@ -420,6 +423,9 @@ public class TestPgServer extends TestBase {
ps.setBoolean(8, true);
ps.setByte(9, (byte) 0xfe);
ps.setBytes(10, new byte[] { 'a', (byte) 0xfe, '\127' });
ps.setDate(11, Date.valueOf("2015-01-31"));
ps.setTime(12, Time.valueOf("20:11:15"));
ps.setTimestamp(13, Timestamp.valueOf("2001-10-30 14:16:10.111"));
ps.execute();
ResultSet rs = stat.executeQuery("select * from test");
......@@ -435,6 +441,9 @@ public class TestPgServer extends TestBase {
assertEquals((byte) 0xfe, rs.getByte(9));
assertEquals(new byte[] { 'a', (byte) 0xfe, '\127' },
rs.getBytes(10));
assertEquals(Date.valueOf("2015-01-31"), rs.getDate(11));
assertEquals(Time.valueOf("20:11:15"), rs.getTime(12));
assertEquals(Timestamp.valueOf("2001-10-30 14:16:10.111"), rs.getTimestamp(13));
conn.close();
} finally {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论