Skip to content

Commit

Permalink
keep old String API, add in new binary API
Browse files Browse the repository at this point in the history
  • Loading branch information
davecramer committed Feb 23, 2024
1 parent 5ecd407 commit a572a0d
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 23 deletions.
4 changes: 2 additions & 2 deletions pgjdbc/src/main/java/org/postgresql/jdbc/PgResultSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ public int getConcurrency() throws SQLException {
if (isBinary(i)) {
return getTimestampUtils().toOffsetTimeBin(value);
} else {
return getTimestampUtils().toOffsetTime(castNonNull(getString(i)));
return getTimestampUtils().toOffsetTime(castNonNull(getRawValue(i)));
}
}

Expand Down Expand Up @@ -765,7 +765,7 @@ public int getConcurrency() throws SQLException {
return getTimestampUtils().toLocalDate(value);
}
if (oid == Oid.TIMESTAMP) {
return getTimestampUtils().toLocalDateTime(castNonNull(getString(i))).toLocalDate();
return getTimestampUtils().toLocalDateTime(castNonNull(getRawValue(i))).toLocalDate();
}
}

Expand Down
129 changes: 108 additions & 21 deletions pgjdbc/src/main/java/org/postgresql/jdbc/TimestampUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.checkerframework.checker.nullness.qual.PolyNull;

import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.sql.Date;
import java.sql.SQLException;
import java.sql.Time;
Expand Down Expand Up @@ -72,6 +73,11 @@ public class TimestampUtils {

private static final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone(ZoneOffset.UTC);

private static final byte []INFINITY = "infinity".getBytes();
private static final byte []NEGATIVE_INFINITY = "-infinity".getBytes();

private static final byte [] MAX_OFFSET = "24:00:00".getBytes();

private @Nullable TimeZone prevDefaultZoneFieldValue;
private @Nullable TimeZone defaultTimeZoneCache;

Expand Down Expand Up @@ -394,12 +400,30 @@ ParsedTimestamp parseDate(byte[]dateBytes) {
return parsedTimestamp;
}

/**
* Parse a string and return a timestamp representing its value.
*
* @param cal calendar to be used to parse the input string
* @param s The ISO formated date string to parse.
* @return null if s is null or a timestamp of the parsed string s.
* @throws SQLException if there is a problem parsing s.
*/
public @PolyNull Timestamp toTimestamp(@Nullable Calendar cal,
@PolyNull String s) throws SQLException {
try (ResourceLock ignore = lock.obtain()) {
if (s == null) {
return null;
}
return toTimestamp(cal, s.getBytes(StandardCharsets.UTF_8));
}
}

/**
* Parse a string and return a timestamp representing its value.
*
* @param cal calendar to be used to parse the input string
* @param bytes The ISO formated date string to parse.
* @return null if bytes is null or a timestamp of the parsed bytes bytes.
* @return null if bytes is null or a timestamp of the parsed bytes.
* @throws SQLException if there is a problem parsing s.
*/
public @PolyNull Timestamp toTimestamp(@Nullable Calendar cal,
Expand All @@ -413,11 +437,11 @@ ParsedTimestamp parseDate(byte[]dateBytes) {
int blen = bytes.length;

// convert postgres's infinity values to internal infinity magic value
if (bytes[0] == 'i' && Arrays.equals(bytes, "infinity".getBytes())) {
if (bytes[0] == 'i' && Arrays.equals(bytes,INFINITY)) {
return new Timestamp(PGStatement.DATE_POSITIVE_INFINITY);
}

if (bytes[0] == '-' && Arrays.equals(bytes,"-infinity".getBytes())) {
if (bytes[0] == '-' && Arrays.equals(bytes,NEGATIVE_INFINITY)) {
return new Timestamp(PGStatement.DATE_NEGATIVE_INFINITY);
}

Expand Down Expand Up @@ -503,39 +527,63 @@ public OffsetTime toOffsetTimeBin(byte[] bytes) throws PSQLException {
if (s == null) {
return null;
}
return toOffsetTime(s.getBytes(StandardCharsets.UTF_8));
}

if (s.startsWith("24:00:00")) {
return OffsetTime.MAX;
/**
* Parse a string and return a OffsetTime representing its value.
*
* @param bytes The ISO time formatted array of bytes time to parse.
* @return null if bytes are null or a OffsetTime of the parsed string .
* @throws SQLException if there is a problem parsing s.
*/
public @PolyNull OffsetTime toOffsetTime(byte @PolyNull []bytes) throws SQLException {
if (bytes == null) {
return null;
}
for ( int i = 0; i < 8; i++ ) {
if (bytes[i] == MAX_OFFSET[i] && i == 7) {
return OffsetTime.MAX;
}
}

final ParsedTimestamp ts = parseBackendTimestamp(s.getBytes());
final ParsedTimestamp ts = parseBackendTimestamp(bytes);
return OffsetTime.of(ts.hour, ts.minute, ts.second, ts.nanos, ts.offset);
}

/**
* @param s The ISO formatted date string to parse.
* @return null if s is null or a LocalDateTime of the parsed string s.
* @throws SQLException if there is a problem parsing s.
*/
public @PolyNull LocalDateTime toLocalDateTime(@PolyNull String s) throws SQLException {
if (s == null) {
return null;
}
return toLocalDateTime(s.getBytes(StandardCharsets.UTF_8));
}

/**
* Parse a string and return a LocalDateTime representing its value.
*
* @param s The ISO formatted date string to parse.
* @param bytes The ISO formatted date string to parse.
* @return null if s is null or a LocalDateTime of the parsed string s.
* @throws SQLException if there is a problem parsing s.
*/
public @PolyNull LocalDateTime toLocalDateTime(@PolyNull String s) throws SQLException {
if (s == null) {
public @PolyNull LocalDateTime toLocalDateTime(byte @PolyNull []bytes) throws SQLException {
if (bytes == null) {
return null;
}

int slen = s.length();

// convert postgres's infinity values to internal infinity magic value
if (slen == 8 && "infinity".equals(s)) {
if (bytes[0] == 'i' && Arrays.equals(INFINITY, bytes)) {
return LocalDateTime.MAX;
}

if (slen == 9 && "-infinity".equals(s)) {
if (bytes[0] == '-' && Arrays.equals(NEGATIVE_INFINITY, bytes)) {
return LocalDateTime.MIN;
}

ParsedTimestamp ts = parseBackendTimestamp(s.getBytes());
ParsedTimestamp ts = parseBackendTimestamp(bytes);

// intentionally ignore time zone
// 2004-10-19 10:23:54+03:00 is 2004-10-19 10:23:54 locally
Expand Down Expand Up @@ -565,6 +613,21 @@ public OffsetDateTime toOffsetDateTime(Time t) {
/**
* Parse a string and return a OffsetDateTime representing its value.
*
* @param s The ISO formatted date string to parse.
* @return null if s is null or a OffsetDateTime of the parsed string s.
* @throws SQLException if there is a problem parsing s.
*/
public @PolyNull OffsetDateTime toOffsetDateTime(
@PolyNull String s) throws SQLException {
if (s == null) {
return null;
}
return toOffsetDateTime(s.getBytes(StandardCharsets.UTF_8));
}

/**
* Parse an array of bytes and return a OffsetDateTime representing its value.
*
* @param bytes The ISO formatted date string to parse.
* @return null if s is null or a OffsetDateTime of the parsed string s.
* @throws SQLException if there is a problem parsing s.
Expand All @@ -577,11 +640,11 @@ public OffsetDateTime toOffsetDateTime(Time t) {
}

// convert postgres's infinity values to internal infinity magic value
if (bytes[0] == 'i' && Arrays.equals("infinity".getBytes(), bytes)) {
if (bytes[0] == 'i' && Arrays.equals(INFINITY, bytes)) {
return OffsetDateTime.MAX;
}

if (bytes[0] == '-' && Arrays.equals("-infinity".getBytes(), bytes)) {
if (bytes[0] == '-' && Arrays.equals(NEGATIVE_INFINITY, bytes)) {
return OffsetDateTime.MIN;
}

Expand Down Expand Up @@ -616,6 +679,17 @@ public OffsetDateTime toOffsetDateTimeBin(byte[] bytes) throws PSQLException {
return OffsetDateTime.ofInstant(instant, ZoneOffset.UTC);
}

public @PolyNull Time toTime(
@Nullable Calendar cal, @PolyNull String s) throws SQLException {
try (ResourceLock ignore = lock.obtain()) {
// 1) Parse backend string
if (s == null) {
return null;
}
return toTime(cal, s.getBytes(StandardCharsets.UTF_8));
}
}

public @PolyNull Time toTime(
@Nullable Calendar cal, byte @PolyNull []bytes) throws SQLException {

Expand Down Expand Up @@ -663,16 +737,29 @@ public OffsetDateTime toOffsetDateTimeBin(byte[] bytes) throws PSQLException {
}
}

public @PolyNull Date toDate(@Nullable Calendar cal,
@PolyNull String s) throws SQLException {
try (ResourceLock ignore = lock.obtain()) {
// 1) Parse backend string
Timestamp timestamp = toTimestamp(cal, s);

if (timestamp == null) {
return null;
}
return toDate(cal, s.getBytes(StandardCharsets.UTF_8));

Check failure on line 749 in pgjdbc/src/main/java/org/postgresql/jdbc/TimestampUtils.java

View workflow job for this annotation

GitHub Actions / CheckerFramework

[Task :postgresql:compileJava] [dereference.of.nullable] dereference of possibly-null reference s return toDate(cal, s.getBytes(StandardCharsets.UTF_8)); ^

Check failure on line 749 in pgjdbc/src/main/java/org/postgresql/jdbc/TimestampUtils.java

View workflow job for this annotation

GitHub Actions / CheckerFramework

[Task :postgresql:compileJava] [dereference.of.nullable] dereference of possibly-null reference s return toDate(cal, s.getBytes(StandardCharsets.UTF_8)); ^
}
}

public @PolyNull Date toDate(@Nullable Calendar cal,
byte @PolyNull []dateBytes) throws SQLException {
try (ResourceLock ignore = lock.obtain()) {
if (dateBytes == null) {
return null;
}
if (dateBytes[0] == 'i' && Arrays.equals("infinity".getBytes(), dateBytes)) {
if (dateBytes[0] == 'i' && Arrays.equals(INFINITY, dateBytes)) {
return new Date(PGStatement.DATE_POSITIVE_INFINITY);
}
if (dateBytes[0] == '-' && Arrays.equals("-infinity".getBytes(), dateBytes)) {
if (dateBytes[0] == '-' && Arrays.equals(NEGATIVE_INFINITY, dateBytes)) {
return new Date(PGStatement.DATE_NEGATIVE_INFINITY);
}
if ( cal == null ) {
Expand Down Expand Up @@ -716,10 +803,10 @@ public OffsetDateTime toOffsetDateTimeBin(byte[] bytes) throws PSQLException {
if (dateBytes == null) {
return null;
}
if (dateBytes[0] == 'i' && Arrays.equals("infinity".getBytes(), dateBytes)) {
if (dateBytes[0] == 'i' && Arrays.equals(INFINITY, dateBytes)) {
return LocalDateTime.MAX.toLocalDate();
}
if (dateBytes[0] == '-' && Arrays.equals("-infinity".getBytes(), dateBytes)) {
if (dateBytes[0] == '-' && Arrays.equals(NEGATIVE_INFINITY, dateBytes)) {
return LocalDateTime.MIN.toLocalDate();
}
ParsedTimestamp pt = parseDate(dateBytes);
Expand Down

0 comments on commit a572a0d

Please sign in to comment.