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