// Path: src/main/java/com/pgasync/SqlException.java
// public class SqlException extends RuntimeException {
// 
//     private static final long serialVersionUID = 1L;
//     private static final int MAX_CAUSE_DEPTH = 100;
// 
//     final String code;
// 
//     public SqlException(String level, String code, String message) {
//         super(level + ": SQLSTATE=" + code + ", MESSAGE=" + message);
//         this.code = code;
//     }
// 
//     public SqlException(String message) {
//         super(message);
//         this.code = null;
//     }
// 
//     public SqlException(Throwable cause) {
//         super(cause);
//         this.code = null;
//     }
// 
//     public String getCode() {
//         return code;
//     }
// 
//     @FunctionalInterface
//     public interface CheckedRunnable {
// 
//         void run() throws Exception;
//     }
// 
//     public static boolean ifCause(Throwable th, Consumer<SqlException> action, CheckedRunnable others) throws Exception {
//         int depth = 1;
//         while (depth++ < MAX_CAUSE_DEPTH && th != null && !(th instanceof SqlException)) {
//             th = th.getCause();
//         }
//         if (th instanceof SqlException) {
//             action.accept((SqlException) th);
//             return true;
//         } else {
//             others.run();
//             return false;
//         }
//     }
// }
// 
// Path: src/main/java/com/github/pgasync/Oid.java
// public enum Oid {
// 
//     UNSPECIFIED(0),
//     INT2(21),
//     INT2_ARRAY(1005),
//     INT4(23),
//     INT4_ARRAY(1007),
//     INT8(20),
//     INT8_ARRAY(1016),
//     TEXT(25),
//     TEXT_ARRAY(1009),
//     NUMERIC(1700),
//     NUMERIC_ARRAY(1231),
//     FLOAT4(700),
//     FLOAT4_ARRAY(1021),
//     FLOAT8(701),
//     FLOAT8_ARRAY(1022),
//     BOOL(16),
//     BOOL_ARRAY(1000),
//     DATE(1082),
//     DATE_ARRAY(1182),
//     TIME(1083),
//     TIME_ARRAY(1183),
//     TIMETZ(1266),
//     TIMETZ_ARRAY(1270),
//     TIMESTAMP(1114),
//     TIMESTAMP_ARRAY(1115),
//     TIMESTAMPTZ(1184),
//     TIMESTAMPTZ_ARRAY(1185),
//     BYTEA(17),
//     BYTEA_ARRAY(1001),
//     VARCHAR(1043),
//     VARCHAR_ARRAY(1015),
//     OID(26),
//     OID_ARRAY(1028),
//     BPCHAR(1042),
//     BPCHAR_ARRAY(1014),
//     MONEY(790),
//     MONEY_ARRAY(791),
//     NAME(19),
//     NAME_ARRAY(1003),
//     BIT(1560),
//     BIT_ARRAY(1561),
//     VOID(2278),
//     INTERVAL(1186),
//     INTERVAL_ARRAY(1187),
//     CHAR(18),
//     CHAR_ARRAY(1002),
//     VARBIT(1562),
//     VARBIT_ARRAY(1563),
//     UUID(2950),
//     UUID_ARRAY(2951),
//     XML(142),
//     XML_ARRAY(143),
//     POINT(600),
//     BOX(603),
//     // Added
//     JSON(114),
//     JSONB(3802),
//     HSTORE(33670)
//     ;
// 
//     final int id;
// 
//     Oid(int id) {
//         this.id = id;
//     }
// 
//     public int getId() {
//         return id;
//     }
// 
//     public static Oid valueOfId(int id) {
//         for (Oid oid : values()) {
//             if (oid.id == id) {
//                 return oid;
//             }
//         }
//         return Oid.UNSPECIFIED;
//     }
// }


import com.pgasync.SqlException;
import com.github.pgasync.Oid;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE;
import static java.time.format.DateTimeFormatter.ISO_LOCAL_TIME;
package com.github.pgasync.conversion;




/**
 * @author Antti Laisi
 * <p>
 * TODO: Add support for Java 8 temporal types.
 */
class TemporalConversions {

    private static final DateTimeFormatter TIMESTAMP_FORMAT = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .append(ISO_LOCAL_DATE)
            .appendLiteral(' ')
            .append(ISO_LOCAL_TIME)
            .toFormatter();

    private static final DateTimeFormatter TIMESTAMPZ_FORMAT = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .append(ISO_LOCAL_DATE)
            .appendLiteral(' ')
            .append(ISO_LOCAL_TIME)
            .appendOffset("+HH:mm", "")
            .toFormatter();

    private static final DateTimeFormatter TIMEZ_FORMAT = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .append(ISO_LOCAL_TIME)
            .appendOffset("+HH:mm", "")
            .toFormatter();

    static Date toDate(Oid oid, String value) {
        switch (oid) {
            case UNSPECIFIED: // fallthrough
            case DATE:
                try {
                    return Date.valueOf(LocalDate.parse(value, ISO_LOCAL_DATE));
                } catch (DateTimeParseException e) {
// Path: src/main/java/com/pgasync/SqlException.java
// public class SqlException extends RuntimeException {
// 
//     private static final long serialVersionUID = 1L;
//     private static final int MAX_CAUSE_DEPTH = 100;
// 
//     final String code;
// 
//     public SqlException(String level, String code, String message) {
//         super(level + ": SQLSTATE=" + code + ", MESSAGE=" + message);
//         this.code = code;
//     }
// 
//     public SqlException(String message) {
//         super(message);
//         this.code = null;
//     }
// 
//     public SqlException(Throwable cause) {
//         super(cause);
//         this.code = null;
//     }
// 
//     public String getCode() {
//         return code;
//     }
// 
//     @FunctionalInterface
//     public interface CheckedRunnable {
// 
//         void run() throws Exception;
//     }
// 
//     public static boolean ifCause(Throwable th, Consumer<SqlException> action, CheckedRunnable others) throws Exception {
//         int depth = 1;
//         while (depth++ < MAX_CAUSE_DEPTH && th != null && !(th instanceof SqlException)) {
//             th = th.getCause();
//         }
//         if (th instanceof SqlException) {
//             action.accept((SqlException) th);
//             return true;
//         } else {
//             others.run();
//             return false;
//         }
//     }
// }
// 
// Path: src/main/java/com/github/pgasync/Oid.java
// public enum Oid {
// 
//     UNSPECIFIED(0),
//     INT2(21),
//     INT2_ARRAY(1005),
//     INT4(23),
//     INT4_ARRAY(1007),
//     INT8(20),
//     INT8_ARRAY(1016),
//     TEXT(25),
//     TEXT_ARRAY(1009),
//     NUMERIC(1700),
//     NUMERIC_ARRAY(1231),
//     FLOAT4(700),
//     FLOAT4_ARRAY(1021),
//     FLOAT8(701),
//     FLOAT8_ARRAY(1022),
//     BOOL(16),
//     BOOL_ARRAY(1000),
//     DATE(1082),
//     DATE_ARRAY(1182),
//     TIME(1083),
//     TIME_ARRAY(1183),
//     TIMETZ(1266),
//     TIMETZ_ARRAY(1270),
//     TIMESTAMP(1114),
//     TIMESTAMP_ARRAY(1115),
//     TIMESTAMPTZ(1184),
//     TIMESTAMPTZ_ARRAY(1185),
//     BYTEA(17),
//     BYTEA_ARRAY(1001),
//     VARCHAR(1043),
//     VARCHAR_ARRAY(1015),
//     OID(26),
//     OID_ARRAY(1028),
//     BPCHAR(1042),
//     BPCHAR_ARRAY(1014),
//     MONEY(790),
//     MONEY_ARRAY(791),
//     NAME(19),
//     NAME_ARRAY(1003),
//     BIT(1560),
//     BIT_ARRAY(1561),
//     VOID(2278),
//     INTERVAL(1186),
//     INTERVAL_ARRAY(1187),
//     CHAR(18),
//     CHAR_ARRAY(1002),
//     VARBIT(1562),
//     VARBIT_ARRAY(1563),
//     UUID(2950),
//     UUID_ARRAY(2951),
//     XML(142),
//     XML_ARRAY(143),
//     POINT(600),
//     BOX(603),
//     // Added
//     JSON(114),
//     JSONB(3802),
//     HSTORE(33670)
//     ;
// 
//     final int id;
// 
//     Oid(int id) {
//         this.id = id;
//     }
// 
//     public int getId() {
//         return id;
//     }
// 
//     public static Oid valueOfId(int id) {
//         for (Oid oid : values()) {
//             if (oid.id == id) {
//                 return oid;
//             }
//         }
//         return Oid.UNSPECIFIED;
//     }
// }


// Path: src/main/java/com/github/pgasync/conversion/TemporalConversions.java
import com.pgasync.SqlException;
import com.github.pgasync.Oid;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE;
import static java.time.format.DateTimeFormatter.ISO_LOCAL_TIME;

package com.github.pgasync.conversion;




/**
 * @author Antti Laisi
 * <p>
 * TODO: Add support for Java 8 temporal types.
 */
class TemporalConversions {

    private static final DateTimeFormatter TIMESTAMP_FORMAT = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .append(ISO_LOCAL_DATE)
            .appendLiteral(' ')
            .append(ISO_LOCAL_TIME)
            .toFormatter();

    private static final DateTimeFormatter TIMESTAMPZ_FORMAT = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .append(ISO_LOCAL_DATE)
            .appendLiteral(' ')
            .append(ISO_LOCAL_TIME)
            .appendOffset("+HH:mm", "")
            .toFormatter();

    private static final DateTimeFormatter TIMEZ_FORMAT = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .append(ISO_LOCAL_TIME)
            .appendOffset("+HH:mm", "")
            .toFormatter();

    static Date toDate(Oid oid, String value) {
        switch (oid) {
            case UNSPECIFIED: // fallthrough
            case DATE:
                try {
                    return Date.valueOf(LocalDate.parse(value, ISO_LOCAL_DATE));
                } catch (DateTimeParseException e) {
                    throw new SqlException("Invalid date: " + value);