001package io.ebean.config.dbplatform; 002 003import io.ebean.config.PlatformConfig; 004 005import java.util.EnumMap; 006import java.util.Map; 007 008/** 009 * Used to map bean property types to DB specific types for DDL generation. 010 */ 011public class DbPlatformTypeMapping { 012 013 /** 014 * Boolean type used for logical model. 015 */ 016 private static class BooleanLogicalType extends DbPlatformType { 017 BooleanLogicalType() { 018 super("boolean", false); 019 } 020 @Override 021 protected void renderLengthScale(int deployLength, int deployScale, StringBuilder sb) { 022 // do not have length - even if platform boolean type does like integer(1) 023 } 024 } 025 026 private static final DbPlatformTypeLookup lookup = new DbPlatformTypeLookup(); 027 028 private static final DbPlatformType BOOLEAN_LOGICAL = new BooleanLogicalType(); 029 030 private static final DbPlatformType INET_NATIVE = new DbPlatformType("inet", false); 031 private static final DbPlatformType INET_VARCHAR = new DbPlatformType("varchar", 50); 032 private static final DbPlatformType CIDR_NATIVE = new DbPlatformType("cidr", false); 033 private static final DbPlatformType CIDR_VARCHAR = new DbPlatformType("varchar", 50); 034 035 private static final DbPlatformType UUID_NATIVE = new DbPlatformType("uuid", false); 036 @SuppressWarnings("unused") 037 private static final DbPlatformType UUID_PLACEHOLDER = new DbPlatformType("uuidPlaceholder"); 038 private static final DbPlatformType JSON_CLOB_PLACEHOLDER = new DbPlatformType("jsonClobPlaceholder"); 039 private static final DbPlatformType JSON_BLOB_PLACEHOLDER = new DbPlatformType("jsonBlobPlaceholder"); 040 private static final DbPlatformType JSON_VARCHAR_PLACEHOLDER = new DbPlatformType("jsonVarcharPlaceholder"); 041 042 private static final DbPlatformType POINT = new DbPlatformType("point"); 043 private static final DbPlatformType POLYGON = new DbPlatformType("polygon"); 044 private static final DbPlatformType LINESTRING = new DbPlatformType("linestring"); 045 private static final DbPlatformType MULTIPOINT = new DbPlatformType("multipoint"); 046 private static final DbPlatformType MULTILINESTRING = new DbPlatformType("multilinestring"); 047 private static final DbPlatformType MULTIPOLYGON = new DbPlatformType("multipolygon"); 048 049 private final Map<DbType, DbPlatformType> typeMap = new EnumMap<>(DbType.class); 050 051 /** 052 * Return the DbTypeMap with standard (not platform specific) types. 053 * <p> 054 * This has some extended JSON types (JSON, JSONB, JSONVarchar, JSONClob, JSONBlob). 055 * These types get translated to specific database platform types during DDL generation. 056 */ 057 public static DbPlatformTypeMapping logicalTypes() { 058 return new DbPlatformTypeMapping(true); 059 } 060 061 public DbPlatformTypeMapping() { 062 loadDefaults(false); 063 } 064 065 private DbPlatformTypeMapping(boolean logicalTypes) { 066 loadDefaults(logicalTypes); 067 } 068 069 /** 070 * Load the standard types. These can be overridden by DB specific platform. 071 */ 072 private void loadDefaults(boolean logicalTypes) { 073 074 put(DbType.BOOLEAN, BOOLEAN_LOGICAL); 075 put(DbType.BIT); 076 put(DbType.INTEGER); 077 put(DbType.BIGINT); 078 put(DbType.DOUBLE); 079 put(DbType.SMALLINT); 080 put(DbType.TINYINT); 081 put(DbType.BLOB); 082 put(DbType.CLOB); 083 put(DbType.ARRAY); 084 put(DbType.DATE); 085 put(DbType.TIME); 086 put(DbType.TIMESTAMP); 087 put(DbType.LONGVARBINARY); 088 put(DbType.LONGVARCHAR); 089 // most commonly real maps to db float 090 put(DbType.REAL, new DbPlatformType("float")); 091 092 put(DbType.POINT, POINT); 093 put(DbType.POLYGON, POLYGON); 094 put(DbType.LINESTRING, LINESTRING); 095 put(DbType.MULTIPOINT, MULTIPOINT); 096 put(DbType.MULTILINESTRING, MULTILINESTRING); 097 put(DbType.MULTIPOLYGON, MULTIPOLYGON); 098 099 if (logicalTypes) { 100 // keep it logical for 2 layer DDL generation 101 put(DbType.VARCHAR, new DbPlatformType("varchar")); 102 put(DbType.DECIMAL, new DbPlatformType("decimal")); 103 put(DbType.VARBINARY, new DbPlatformType("varbinary")); 104 put(DbType.BINARY, new DbPlatformType("binary")); 105 put(DbType.CHAR, new DbPlatformType("char")); 106 107 put(DbType.HSTORE, new DbPlatformType("hstore", false)); 108 put(DbType.JSON, new DbPlatformType("json", false)); 109 put(DbType.JSONB, new DbPlatformType("jsonb", false)); 110 put(DbType.JSONCLOB, new DbPlatformType("jsonclob")); 111 put(DbType.JSONBLOB, new DbPlatformType("jsonblob")); 112 put(DbType.JSONVARCHAR, new DbPlatformType("jsonvarchar", 1000)); 113 put(DbType.UUID, UUID_NATIVE); 114 put(DbType.INET, INET_NATIVE); 115 put(DbType.CIDR, CIDR_NATIVE); 116 117 } else { 118 put(DbType.VARCHAR, new DbPlatformType("varchar", 255)); 119 put(DbType.DECIMAL, new DbPlatformType("decimal", 16, 3)); 120 put(DbType.VARBINARY, new DbPlatformType("varbinary", 255)); 121 put(DbType.BINARY, new DbPlatformType("binary", 255)); 122 put(DbType.CHAR, new DbPlatformType("char", 1)); 123 124 put(DbType.JSON, JSON_CLOB_PLACEHOLDER); // Postgres maps this to JSON 125 put(DbType.JSONB, JSON_CLOB_PLACEHOLDER); // Postgres maps this to JSONB 126 put(DbType.JSONCLOB, JSON_CLOB_PLACEHOLDER); 127 put(DbType.JSONBLOB, JSON_BLOB_PLACEHOLDER); 128 put(DbType.JSONVARCHAR, JSON_VARCHAR_PLACEHOLDER); 129 // default to native UUID and override on platform configure() 130 put(DbType.UUID, UUID_NATIVE); 131 put(DbType.INET, INET_VARCHAR); 132 put(DbType.CIDR, CIDR_VARCHAR); 133 } 134 } 135 136 /** 137 * Lookup the platform specific DbType given the standard sql type name. 138 */ 139 public DbPlatformType lookup(String name, boolean withScale) { 140 141 DbType type = lookup.byName(name); 142 if (type == null) { 143 throw new IllegalArgumentException("Unknown type [" + name + "] - not standard sql type"); 144 } 145 // handle JSON types mapped to clob, blob and varchar 146 switch (type) { 147 case JSONBLOB: 148 return get(DbType.BLOB); 149 case JSONCLOB: 150 return get(DbType.CLOB); 151 case JSONVARCHAR: 152 return get(DbType.VARCHAR); 153 case JSON: 154 return getJsonType(DbType.JSON, withScale); 155 case JSONB: 156 return getJsonType(DbType.JSONB, withScale); 157 default: 158 return get(type); 159 } 160 } 161 162 private DbPlatformType getJsonType(DbType type, boolean withScale) { 163 164 DbPlatformType dbType = get(type); 165 if (dbType == JSON_CLOB_PLACEHOLDER) { 166 // if we have scale that implies this maps to varchar 167 return withScale ? get(DbType.VARCHAR) : get(DbType.CLOB); 168 } 169 if (dbType == JSON_BLOB_PLACEHOLDER) { 170 return get(DbType.BLOB); 171 } 172 if (dbType == JSON_VARCHAR_PLACEHOLDER) { 173 return get(DbType.VARCHAR); 174 } 175 // Postgres has specific type 176 return get(type); 177 } 178 179 /** 180 * Override the type for a given JDBC type. 181 */ 182 private void put(DbType type) { 183 typeMap.put(type, type.createPlatformType()); 184 } 185 186 /** 187 * Override the type for a given JDBC type. 188 */ 189 public void put(DbType type, DbPlatformType platformType) { 190 typeMap.put(type, platformType); 191 } 192 193 /** 194 * Return the type for a given jdbc type. 195 */ 196 public DbPlatformType get(int jdbcType) { 197 return get(lookup.byId(jdbcType)); 198 } 199 200 /** 201 * Return the type for a given jdbc type. 202 */ 203 public DbPlatformType get(DbType dbType) { 204 return typeMap.get(dbType); 205 } 206 207 /** 208 * Map the UUID appropriately based on native DB support and DatabaseConfig.DbUuid. 209 */ 210 public void config(boolean nativeUuidType, PlatformConfig.DbUuid dbUuid) { 211 if (nativeUuidType && dbUuid.useNativeType()) { 212 // native UUID already set by default 213 } else if (dbUuid.useBinary()) { 214 put(DbType.UUID, get(DbType.BINARY).withLength(16)); 215 } else { 216 put(DbType.UUID, get(DbType.VARCHAR).withLength(40)); 217 } 218 } 219}