Permalink
Browse files

feat: implement JSR-310 support in setObject

JSR-310 support is currently missing in both setObject methods in
PgPreparedStatement.

Implement JSR-310 support in PreparedStatement.setObject

Closes #476
  • Loading branch information...
marschall authored and vlsi committed Dec 29, 2015
1 parent a65b4b9 commit e52f7e3d08b45b79906474a81c49cff7e7eaa6df
@@ -55,6 +55,12 @@
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
//#if mvn.project.property.postgresql.jdbc.spec >= "JDBC4.2"
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
//#endif
import java.util.ArrayList;
import java.util.Map;
import java.util.TimeZone;
@@ -617,6 +623,11 @@ public void setObject(int parameterIndex, Object in, int targetSqlType, int scal
java.sql.Date tmpd;
if (in instanceof java.util.Date) {
tmpd = new java.sql.Date(((java.util.Date) in).getTime());
//#if mvn.project.property.postgresql.jdbc.spec >= "JDBC4.2"
} else if (in instanceof LocalDate) {
setDate(parameterIndex, (LocalDate) in);
break;
//#endif
} else {
tmpd = connection.getTimestampUtils().toDate(null, in.toString());
}
@@ -630,25 +641,51 @@ public void setObject(int parameterIndex, Object in, int targetSqlType, int scal
java.sql.Time tmpt;
if (in instanceof java.util.Date) {
tmpt = new java.sql.Time(((java.util.Date) in).getTime());
//#if mvn.project.property.postgresql.jdbc.spec >= "JDBC4.2"
} else if (in instanceof LocalTime) {
setTime(parameterIndex, (LocalTime) in);
break;
//#endif
} else {
tmpt = connection.getTimestampUtils().toTime(null, in.toString());
}
setTime(parameterIndex, tmpt);
}
break;
case Types.TIMESTAMP:
if (in instanceof java.sql.Timestamp) {
if (in instanceof PGTimestamp) {
setObject(parameterIndex, in);
} else if (in instanceof java.sql.Timestamp) {
setTimestamp(parameterIndex, (java.sql.Timestamp) in);
} else {
java.sql.Timestamp tmpts;
if (in instanceof java.util.Date) {
tmpts = new java.sql.Timestamp(((java.util.Date) in).getTime());
//#if mvn.project.property.postgresql.jdbc.spec >= "JDBC4.2"
} else if (in instanceof LocalDateTime) {
setTimestamp(parameterIndex, (LocalDateTime) in);
break;
//#endif
} else {
tmpts = connection.getTimestampUtils().toTimestamp(null, in.toString());
}
setTimestamp(parameterIndex, tmpts);
}
break;
//#if mvn.project.property.postgresql.jdbc.spec >= "JDBC4.2"
case Types.TIMESTAMP_WITH_TIMEZONE:
if (in instanceof OffsetDateTime) {
setTimestamp(parameterIndex, (OffsetDateTime) in);
} else if (in instanceof PGTimestamp) {
setObject(parameterIndex, in);
} else {
throw new PSQLException(
GT.tr("Cannot cast an instance of {0} to type {1}",
new Object[]{in.getClass().getName(), "Types.TIMESTAMP_WITH_TIMEZONE"}),
PSQLState.INVALID_PARAMETER_TYPE);
}
break;
//#endif
case Types.BIT:
setBoolean(parameterIndex, castToBoolean(in));
break;
@@ -985,6 +1022,16 @@ public void setObject(int parameterIndex, Object x) throws SQLException {
setPGobject(parameterIndex, (PGobject) x);
} else if (x instanceof Character) {
setString(parameterIndex, ((Character) x).toString());
//#if mvn.project.property.postgresql.jdbc.spec >= "JDBC4.2"
} else if (x instanceof LocalDate) {
setDate(parameterIndex, (LocalDate) x);
} else if (x instanceof LocalTime) {
setTime(parameterIndex, (LocalTime) x);
} else if (x instanceof LocalDateTime) {
setTimestamp(parameterIndex, (LocalDateTime) x);
} else if (x instanceof OffsetDateTime) {
setTimestamp(parameterIndex, (OffsetDateTime) x);
//#endif
} else if (x instanceof Map) {
setMap(parameterIndex, (Map) x);
} else {
@@ -1422,6 +1469,28 @@ public void setTimestamp(int i, Timestamp t, java.util.Calendar cal) throws SQLE
bindString(i, connection.getTimestampUtils().toString(cal, t), oid);
}

//#if mvn.project.property.postgresql.jdbc.spec >= "JDBC4.2"
private void setDate(int i, LocalDate localDate) throws SQLException {
int oid = Oid.DATE;
bindString(i, connection.getTimestampUtils().toString(localDate), oid);
}

private void setTime(int i, LocalTime localTime) throws SQLException {
int oid = Oid.TIME;
bindString(i, connection.getTimestampUtils().toString(localTime), oid);
}

private void setTimestamp(int i, LocalDateTime localDateTime) throws SQLException {
int oid = Oid.TIMESTAMP;
bindString(i, connection.getTimestampUtils().toString(localDateTime), oid);
}

private void setTimestamp(int i, OffsetDateTime offsetDateTime) throws SQLException {
int oid = Oid.TIMESTAMPTZ;
bindString(i, connection.getTimestampUtils().toString(offsetDateTime), oid);
}
//#endif

public ParameterMetaData createParameterMetaData(BaseConnection conn, int oids[])
throws SQLException {
return new PgParameterMetaData(conn, oids);
@@ -19,6 +19,15 @@
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
//#if mvn.project.property.postgresql.jdbc.spec >= "JDBC4.2"
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.chrono.IsoEra;
import java.time.temporal.ChronoField;
//#endif
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.SimpleTimeZone;
@@ -398,9 +407,9 @@ public synchronized String toString(Calendar cal, Timestamp x) {

public synchronized String toString(Calendar cal, Date x) {
if (x.getTime() == PGStatement.DATE_POSITIVE_INFINITY) {
sbuf.append("infinity");
return "infinity";
} else if (x.getTime() == PGStatement.DATE_NEGATIVE_INFINITY) {
sbuf.append("-infinity");
return "-infinity";
}

cal = setupCalendar(cal);
@@ -433,34 +442,42 @@ public synchronized String toString(Calendar cal, Time x) {

private static void appendDate(StringBuilder sb, Calendar cal) {
int l_year = cal.get(Calendar.YEAR);
int l_month = cal.get(Calendar.MONTH) + 1;
int l_day = cal.get(Calendar.DAY_OF_MONTH);
appendDate(sb, l_year, l_month, l_day);
}

private static void appendDate(StringBuilder sb, int year, int month, int day) {
// always use at least four digits for the year so very
// early years, like 2, don't get misinterpreted
//
int prevLength = sb.length();
sb.append(l_year);
sb.append(year);
int leadingZerosForYear = 4 - (sb.length() - prevLength);
if (leadingZerosForYear > 0) {
sb.insert(prevLength, ZEROS, 0, leadingZerosForYear);
}

sb.append('-');
int l_month = cal.get(Calendar.MONTH) + 1;
sb.append(NUMBERS[l_month]);
sb.append(NUMBERS[month]);
sb.append('-');
int l_day = cal.get(Calendar.DAY_OF_MONTH);
sb.append(NUMBERS[l_day]);
sb.append(NUMBERS[day]);
}

private static void appendTime(StringBuilder sb, Calendar cal, int nanos) {
int hours = cal.get(Calendar.HOUR_OF_DAY);
int minutes = cal.get(Calendar.MINUTE);
int seconds = cal.get(Calendar.SECOND);
appendTime(sb, hours, minutes, seconds, nanos);
}

private static void appendTime(StringBuilder sb, int hours, int minutes, int seconds, int nanos) {
sb.append(NUMBERS[hours]);

sb.append(':');
int minutes = cal.get(Calendar.MINUTE);
sb.append(NUMBERS[minutes]);

sb.append(':');
int seconds = cal.get(Calendar.SECOND);
sb.append(NUMBERS[seconds]);

// Add nanoseconds.
@@ -480,6 +497,10 @@ private static void appendTime(StringBuilder sb, Calendar cal, int nanos) {
private void appendTimeZone(StringBuilder sb, java.util.Calendar cal) {
int offset = (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / 1000;

appendTimeZone(sb, offset);
}

private void appendTimeZone(StringBuilder sb, int offset) {
int absoff = Math.abs(offset);
int hours = absoff / 60 / 60;
int mins = (absoff - hours * 60 * 60) / 60;
@@ -505,6 +526,103 @@ private static void appendEra(StringBuilder sb, Calendar cal) {
}
}

//#if mvn.project.property.postgresql.jdbc.spec >= "JDBC4.2"
public synchronized String toString(LocalDate localDate) {
if (LocalDate.MAX.equals(localDate)) {
return "infinity";
} else if (LocalDate.MIN.equals(localDate)) {
return "-infinity";
}

sbuf.setLength(0);

appendDate(sbuf, localDate);
appendEra(sbuf, localDate);

return sbuf.toString();
}

public synchronized String toString(LocalTime localTime) {
if (LocalTime.MAX.equals(localTime)) {
return "infinity";
} else if (LocalTime.MIN.equals(localTime)) {
return "-infinity";
}

sbuf.setLength(0);

appendTime(sbuf, localTime);

return sbuf.toString();
}


public synchronized String toString(OffsetDateTime offsetDateTime) {
if (OffsetDateTime.MAX.equals(offsetDateTime)) {
return "infinity";
} else if (OffsetDateTime.MIN.equals(offsetDateTime)) {
return "-infinity";
}

sbuf.setLength(0);

LocalDateTime localDateTime = offsetDateTime.toLocalDateTime();
LocalDate localDate = localDateTime.toLocalDate();
appendDate(sbuf, localDate);
sbuf.append(' ');
appendTime(sbuf, localDateTime.toLocalTime());
appendTimeZone(sbuf, offsetDateTime.getOffset());
appendEra(sbuf, localDate);

return sbuf.toString();
}

public synchronized String toString(LocalDateTime localDateTime) {
if (LocalDateTime.MAX.equals(localDateTime)) {
return "infinity";
} else if (LocalDateTime.MIN.equals(localDateTime)) {
return "-infinity";
}

sbuf.setLength(0);

LocalDate localDate = localDateTime.toLocalDate();
appendDate(sbuf, localDate);
sbuf.append(' ');
appendTime(sbuf, localDateTime.toLocalTime());
appendEra(sbuf, localDate);

return sbuf.toString();
}

private static void appendDate(StringBuilder sb, LocalDate localDate) {
int year = Math.abs(localDate.getYear()); // year is negative for BC dates
int month = localDate.getMonthValue();
int day = localDate.getDayOfMonth();
appendDate(sb, year, month, day);
}

private static void appendTime(StringBuilder sb, LocalTime localTime) {
int hours = localTime.getHour();
int minutes = localTime.getMinute();
int seconds = localTime.getSecond();
int nanos = localTime.getNano();
appendTime(sb, hours, minutes, seconds, nanos);
}

private void appendTimeZone(StringBuilder sb, ZoneOffset offset) {
int offsetSeconds = offset.getTotalSeconds();

appendTimeZone(sb, offsetSeconds);
}

private static void appendEra(StringBuilder sb, LocalDate localDate) {
if (localDate.get(ChronoField.ERA) == IsoEra.BCE.getValue()) {
sb.append(" BC");
}
}
//#endif

private static int skipWhitespace(char[] s, int start) {
int slen = s.length;
for (int i = start; i < slen; i++) {
@@ -600,8 +600,10 @@ public void testGetXml() throws SQLException {

/**
* Test the behavior getObject for money columns.
*
* The test is ignored as it is locale-dependent.
*/
public void testGetMoney() throws SQLException {
public void _testGetMoney() throws SQLException {
Statement stmt = _conn.createStatement();
String expected = "12.34";
stmt.executeUpdate(TestUtil.insertSQL("table1","money_column","'12.34'::float8::numeric::money"));
@@ -13,7 +13,7 @@
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({SimpleJdbc42Test.class, CustomizeDefaultFetchSizeTest.class, GetObject310Test.class})
@SuiteClasses({SimpleJdbc42Test.class, CustomizeDefaultFetchSizeTest.class, GetObject310Test.class, SetObject310Test.class})
public class Jdbc42TestSuite {

}
Oops, something went wrong.

0 comments on commit e52f7e3

Please sign in to comment.