package io.vertx.pgclient.impl.codec;
import io.netty.util.collection.IntObjectHashMap;
import io.netty.util.collection.IntObjectMap;
import io.vertx.core.impl.logging.Logger;
import io.vertx.core.impl.logging.LoggerFactory;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.pgclient.data.Box;
import io.vertx.pgclient.data.Circle;
import io.vertx.pgclient.data.Line;
import io.vertx.pgclient.data.LineSegment;
import io.vertx.sqlclient.Tuple;
import io.vertx.sqlclient.data.Numeric;
import io.vertx.pgclient.data.Interval;
import io.vertx.pgclient.data.Path;
import io.vertx.pgclient.data.Point;
import io.vertx.pgclient.data.Polygon;
import io.vertx.core.buffer.Buffer;
import java.sql.JDBCType;
import java.time.*;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
enum DataType {
BOOL(16, true, Boolean.class, JDBCType.BOOLEAN, Tuple::getBoolean),
BOOL_ARRAY(1000, true, Boolean[].class, JDBCType.BOOLEAN, Tuple::getArrayOfBooleans),
INT2(21, true, Short.class, Number.class, JDBCType.SMALLINT, Tuple::getShort),
INT2_ARRAY(1005, true, Short[].class, Number[].class, JDBCType.SMALLINT, Tuple::getArrayOfShorts),
INT4(23, true, Integer.class, Number.class, JDBCType.INTEGER, Tuple::getInteger),
INT4_ARRAY(1007, true, Integer[].class, Number[].class, JDBCType.INTEGER, Tuple::getArrayOfIntegers),
INT8(20, true, Long.class, Number.class, JDBCType.BIGINT, Tuple::getLong),
INT8_ARRAY(1016, true, Long[].class, Number[].class, JDBCType.BIGINT, Tuple::getArrayOfLongs),
FLOAT4(700, true, Float.class, Number.class, JDBCType.REAL, Tuple::getFloat),
FLOAT4_ARRAY(1021, true, Float[].class, Number[].class, JDBCType.REAL, Tuple::getArrayOfFloats),
FLOAT8(701, true, Double.class, Number.class, JDBCType.DOUBLE, Tuple::getDouble),
FLOAT8_ARRAY(1022, true, Double[].class, Number[].class, JDBCType.DOUBLE, Tuple::getArrayOfDoubles),
NUMERIC(1700, false, Numeric.class, Number.class, JDBCType.NUMERIC, Tuple::getNumeric),
NUMERIC_ARRAY(1231, false, Numeric[].class, Number[].class, JDBCType.NUMERIC, Tuple::getArrayOfNumerics),
MONEY(790, true, Object.class, null),
MONEY_ARRAY(791, true, Object[].class, null),
BIT(1560, true, Object.class, JDBCType.BIT),
BIT_ARRAY(1561, true, Object[].class, JDBCType.BIT),
VARBIT(1562, true, Object.class, JDBCType.OTHER),
VARBIT_ARRAY(1563, true, Object[].class, JDBCType.BIT),
CHAR(18, true, String.class, JDBCType.BIT, Tuple::getString),
CHAR_ARRAY(1002, true, String[].class, JDBCType.CHAR, Tuple::getArrayOfStrings),
VARCHAR(1043, true, String.class, JDBCType.VARCHAR, Tuple::getString),
VARCHAR_ARRAY(1015, true, String[].class, JDBCType.VARCHAR, Tuple::getArrayOfStrings),
BPCHAR(1042, true, String.class, JDBCType.VARCHAR, Tuple::getString),
BPCHAR_ARRAY(1014, true, String[].class, JDBCType.VARCHAR, Tuple::getArrayOfStrings),
TEXT(25, true, String.class, JDBCType.LONGVARCHAR, Tuple::getString),
TEXT_ARRAY(1009, true, String[].class, JDBCType.LONGVARCHAR, Tuple::getArrayOfStrings),
NAME(19, true, String.class, JDBCType.VARCHAR, Tuple::getString),
NAME_ARRAY(1003, true, String[].class, JDBCType.VARCHAR, Tuple::getArrayOfStrings),
DATE(1082, true, LocalDate.class, JDBCType.DATE, Tuple::getLocalDate),
DATE_ARRAY(1182, true, LocalDate[].class, JDBCType.DATE, Tuple::getArrayOfLocalDates),
TIME(1083, true, LocalTime.class, JDBCType.TIME, Tuple::getLocalTime),
TIME_ARRAY(1183, true, LocalTime[].class, JDBCType.TIME, Tuple::getArrayOfLocalTimes),
TIMETZ(1266, true, OffsetTime.class, JDBCType.TIME_WITH_TIMEZONE, Tuple::getOffsetTime),
TIMETZ_ARRAY(1270, true, OffsetTime[].class, JDBCType.TIME_WITH_TIMEZONE, Tuple::getArrayOfOffsetTimes),
TIMESTAMP(1114, true, LocalDateTime.class, JDBCType.TIMESTAMP, Tuple::getLocalDateTime),
TIMESTAMP_ARRAY(1115, true, LocalDateTime[].class, JDBCType.TIMESTAMP, Tuple::getArrayOfLocalDateTimes),
TIMESTAMPTZ(1184, true, OffsetDateTime.class, JDBCType.TIMESTAMP_WITH_TIMEZONE, Tuple::getOffsetDateTime),
TIMESTAMPTZ_ARRAY(1185, true, OffsetDateTime[].class, JDBCType.TIMESTAMP_WITH_TIMEZONE, Tuple::getArrayOfOffsetDateTimes),
INTERVAL(1186, true, Interval.class, JDBCType.DATE),
INTERVAL_ARRAY(1187, true, Interval[].class, JDBCType.DATE),
BYTEA(17, true, Buffer.class, JDBCType.BINARY, Tuple::getBuffer),
BYTEA_ARRAY(1001, true, Buffer[].class, JDBCType.BINARY, Tuple::getArrayOfBuffers),
MACADDR(829, true, Object.class, JDBCType.OTHER),
INET(869, true, Object[].class, JDBCType.OTHER),
CIDR(650, true, Object.class, JDBCType.OTHER),
MACADDR8(774, true, Object[].class, JDBCType.OTHER),
UUID(2950, true, UUID.class, JDBCType.OTHER, Tuple::getUUID),
UUID_ARRAY(2951, true, UUID[].class, JDBCType.OTHER, Tuple::getArrayOfUUIDs),
JSON(114, true, Object.class, JDBCType.OTHER, Tuple::getJson),
JSON_ARRAY(199, true, Object[].class, JDBCType.OTHER, Tuple::getArrayOfJsons),
JSONB(3802, true, Object.class, JDBCType.OTHER, Tuple::getJson),
JSONB_ARRAY(3807, true, Object[].class, JDBCType.OTHER, Tuple::getArrayOfJsons),
XML(142, true, Object.class, JDBCType.OTHER),
XML_ARRAY(143, true, Object[].class, JDBCType.OTHER),
POINT(600, true, Point.class, JDBCType.OTHER),
POINT_ARRAY(1017, true, Point[].class, JDBCType.OTHER),
LINE(628, true, Line.class, JDBCType.OTHER),
LINE_ARRAY(629, true, Line[].class, JDBCType.OTHER),
LSEG(601, true, LineSegment.class, JDBCType.OTHER),
LSEG_ARRAY(1018, true, LineSegment[].class, JDBCType.OTHER),
BOX(603, true, Box.class, JDBCType.OTHER),
BOX_ARRAY(1020, true, Box[].class, JDBCType.OTHER),
PATH(602, true, Path.class, JDBCType.OTHER),
PATH_ARRAY(1019, true, Path[].class, JDBCType.OTHER),
POLYGON(604, true, Polygon.class, JDBCType.OTHER),
POLYGON_ARRAY(1027, true, Polygon[].class, JDBCType.OTHER),
CIRCLE(718, true, Circle.class, JDBCType.OTHER),
CIRCLE_ARRAY(719, true, Circle[].class, JDBCType.OTHER),
HSTORE(33670, true, Object.class, JDBCType.OTHER),
OID(26, true, Object.class, JDBCType.OTHER),
OID_ARRAY(1028, true, Object[].class, JDBCType.OTHER),
VOID(2278, true, Object.class, JDBCType.OTHER),
UNKNOWN(705, false, String.class, JDBCType.OTHER, ParamExtractor::extractUnknownType),
TS_VECTOR(3614, false, String.class, JDBCType.OTHER),
TS_VECTOR_ARRAY(3643, false, String[].class, JDBCType.OTHER),
TS_QUERY(3615, false, String.class, JDBCType.OTHER),
TS_QUERY_ARRAY(3645, false, String[].class, JDBCType.OTHER);
private static final Logger logger = LoggerFactory.getLogger(DataType.class);
private static final IntObjectMap<DataType> oidToDataType = new IntObjectHashMap<>();
private static final Map<Class<?>, DataType> encodingTypeToDataType = new HashMap<>();
final int id;
final boolean array;
final boolean supportsBinary;
final Class<?> encodingType;
final Class<?> decodingType;
final JDBCType jdbcType;
final ParamExtractor<?> ;
<T> (int id, boolean supportsBinary, Class<T> type, JDBCType jdbcType, ParamExtractor<T> paramExtractor) {
this(id, supportsBinary, type, type, jdbcType, paramExtractor);
}
<T> DataType(int id, boolean supportsBinary, Class<T> type, JDBCType jdbcType) {
this(id, supportsBinary, type, type, jdbcType, null);
}
<T> (int id, boolean supportsBinary, Class<T> encodingType, Class<?> decodingType, JDBCType jdbcType, ParamExtractor<T> paramExtractor) {
this.id = id;
this.supportsBinary = supportsBinary;
this.encodingType = encodingType;
this.decodingType = decodingType;
this.jdbcType = jdbcType;
this.array = decodingType.isArray();
this.paramExtractor = paramExtractor;
}
static DataType valueOf(int oid) {
DataType value = oidToDataType.get(oid);
if (value == null) {
logger.debug("Postgres type OID=" + oid + " not handled - using unknown type instead");
return UNKNOWN;
} else {
return value;
}
}
static DataType lookup(Class<?> type) {
DataType dataType = encodingTypeToDataType.get(type);
if (dataType == null) {
if (Buffer.class.isAssignableFrom(type)) {
return BYTEA;
}
dataType = DataType.UNKNOWN;
}
return dataType;
}
static {
for (DataType dataType : values()) {
oidToDataType.put(dataType.id, dataType);
}
encodingTypeToDataType.put(String.class, VARCHAR);
encodingTypeToDataType.put(String[].class, VARCHAR_ARRAY);
encodingTypeToDataType.put(Boolean.class, BOOL);
encodingTypeToDataType.put(Boolean[].class, BOOL_ARRAY);
encodingTypeToDataType.put(Short.class, INT2);
encodingTypeToDataType.put(Short[].class, INT2_ARRAY);
encodingTypeToDataType.put(Integer.class, INT4);
encodingTypeToDataType.put(Integer[].class, INT4_ARRAY);
encodingTypeToDataType.put(Long.class, INT8);
encodingTypeToDataType.put(Long[].class, INT8_ARRAY);
encodingTypeToDataType.put(Float.class, FLOAT4);
encodingTypeToDataType.put(Float[].class, FLOAT4_ARRAY);
encodingTypeToDataType.put(Double.class, FLOAT8);
encodingTypeToDataType.put(Double[].class, FLOAT8_ARRAY);
encodingTypeToDataType.put(LocalDate.class, DATE);
encodingTypeToDataType.put(LocalDate[].class, DATE_ARRAY);
encodingTypeToDataType.put(LocalDateTime.class, TIMESTAMP);
encodingTypeToDataType.put(LocalDateTime[].class, TIMESTAMP_ARRAY);
encodingTypeToDataType.put(OffsetDateTime.class, TIMESTAMPTZ);
encodingTypeToDataType.put(OffsetDateTime[].class, TIMESTAMPTZ_ARRAY);
encodingTypeToDataType.put(Interval.class, INTERVAL);
encodingTypeToDataType.put(Interval[].class, INTERVAL_ARRAY);
encodingTypeToDataType.put(Buffer[].class, BYTEA_ARRAY);
encodingTypeToDataType.put(UUID.class, UUID);
encodingTypeToDataType.put(UUID[].class, UUID_ARRAY);
encodingTypeToDataType.put(JsonObject.class, JSON);
encodingTypeToDataType.put(JsonObject[].class, JSON_ARRAY);
encodingTypeToDataType.put(JsonArray.class, JSON);
encodingTypeToDataType.put(JsonArray[].class, JSON_ARRAY);
encodingTypeToDataType.put(Point.class, POINT);
encodingTypeToDataType.put(Point[].class, POINT_ARRAY);
encodingTypeToDataType.put(Line.class, LINE);
encodingTypeToDataType.put(Line[].class, LINE_ARRAY);
encodingTypeToDataType.put(LineSegment.class, LSEG);
encodingTypeToDataType.put(LineSegment[].class, LSEG_ARRAY);
encodingTypeToDataType.put(Box.class, BOX);
encodingTypeToDataType.put(Box[].class, BOX_ARRAY);
encodingTypeToDataType.put(Path.class, PATH);
encodingTypeToDataType.put(Path[].class, PATH_ARRAY);
encodingTypeToDataType.put(Polygon.class, POLYGON);
encodingTypeToDataType.put(Polygon[].class, POLYGON_ARRAY);
encodingTypeToDataType.put(Circle.class, CIRCLE);
encodingTypeToDataType.put(Circle[].class, CIRCLE_ARRAY);
}
}