package org.rakam.util; import org.rakam.collection.FieldType; import java.sql.Types; import java.util.Arrays; import java.util.Map; import java.util.Objects; import java.util.function.Function; import java.util.stream.Collectors; import static java.lang.String.format; public class JDBCUtil { private static final Map<String, FieldType> REVERSE_TYPE_MAP = Arrays.asList(FieldType.values()).stream() .collect(Collectors.toMap(JDBCUtil::toSql, a -> a)); public static FieldType getType(String name) { FieldType fieldType = REVERSE_TYPE_MAP.get(name.toUpperCase()); if(fieldType == null) { throw new IllegalArgumentException(String.format("type %s couldn't recognized.", name)); } return fieldType; } public static String toSql(FieldType type) { switch (type) { case INTEGER: return "INT"; case DECIMAL: return "DECIMAL"; case LONG: return "BIGINT"; case STRING: return "VARCHAR"; case BINARY: return "VARBINARY"; case BOOLEAN: case DATE: case TIME: case TIMESTAMP: return type.name(); case DOUBLE: return "DOUBLE"; default: if (type.isArray()) { return "ARRAY<" + toSql(type.getArrayElementType()) + ">"; } if (type.isMap()) { return "MAP<VARCHAR, " + toSql(type.getMapValueType()) + ">"; } throw new IllegalStateException("sql type couldn't converted to fieldtype"); } } public static FieldType fromSql(int sqlType, String typeName) { return fromSql(sqlType, typeName, name -> { if (name.startsWith("_")) { if (name.startsWith("_int")) { return FieldType.ARRAY_LONG; } if (name.equals("_bool")) { return FieldType.ARRAY_BOOLEAN; } if (name.equals("_text") || name.equals("_varchar")) { return FieldType.ARRAY_STRING; } if (name.startsWith("_float")) { return FieldType.ARRAY_DOUBLE; } } if (name.equals("jsonb")) { return FieldType.MAP_STRING; } if (name.equals("json")) { return FieldType.STRING; } if (name.equals("unknown")) { return FieldType.STRING; } throw new UnsupportedOperationException(format("type '%s' is not supported.", typeName)); }); } public static FieldType fromSql(int sqlType, String typeName, Function<String, FieldType> arrayTypeNameMapper) { switch (sqlType) { case Types.VARBINARY: case Types.BINARY: case Types.LONGVARBINARY: return FieldType.BINARY; case Types.BIGINT: case Types.REAL: return FieldType.LONG; case Types.TINYINT: case Types.INTEGER: case Types.SMALLINT: return FieldType.INTEGER; case Types.DECIMAL: return FieldType.DECIMAL; case Types.BOOLEAN: case Types.BIT: return FieldType.BOOLEAN; case Types.DATE: return FieldType.DATE; case Types.TIMESTAMP: case Types.TIMESTAMP_WITH_TIMEZONE: return FieldType.TIMESTAMP; case Types.TIME: case Types.TIME_WITH_TIMEZONE: return FieldType.TIME; case Types.DOUBLE: case Types.FLOAT: case Types.NUMERIC: return FieldType.DOUBLE; case Types.LONGVARCHAR: case Types.NVARCHAR: case Types.LONGNVARCHAR: case Types.VARCHAR: return FieldType.STRING; case Types.OTHER: if(typeName.equals("citext")) { return FieldType.STRING; } if(typeName.equals("jsonb")) { return FieldType.MAP_STRING; } if(typeName.equals("json")) { return FieldType.STRING; } default: return arrayTypeNameMapper.apply(typeName); } } }