001package io.ebean.config; 002 003import io.ebean.annotation.Platform; 004import io.ebean.config.dbplatform.DbType; 005import io.ebean.config.dbplatform.IdType; 006import io.ebean.util.StringHelper; 007 008import java.util.ArrayList; 009import java.util.List; 010import java.util.Map; 011import java.util.Map.Entry; 012 013/** 014 * Configuration for DB types such as UUID, Geometry etc. 015 */ 016public class PlatformConfig { 017 018 private boolean allQuotedIdentifiers; 019 020 /** 021 * The database boolean true value (typically either 1, T, or Y). 022 */ 023 private String databaseBooleanTrue; 024 025 /** 026 * The database boolean false value (typically either 0, F or N). 027 */ 028 private String databaseBooleanFalse; 029 030 /** 031 * For DB's using sequences this is the number of sequence values prefetched. 032 */ 033 private int databaseSequenceBatchSize = 20; 034 035 /** 036 * Set for DB's that support both Sequence and Identity (and the default choice is not desired). 037 */ 038 private IdType idType; 039 040 /** 041 * The Geometry SRID value (default 4326). 042 */ 043 private int geometrySRID = 4326; 044 045 /** 046 * Setting to indicate if UUID should be stored as binary(16) or varchar(40) or native DB type (for H2 and Postgres). 047 */ 048 private DbUuid dbUuid = DbUuid.AUTO_VARCHAR; 049 050 /** 051 * Set to true to force InetAddress to map to Varchar (for Postgres rather than INET) 052 */ 053 private boolean databaseInetAddressVarchar; 054 055 /** 056 * Modify the default mapping of standard types such as default precision for DECIMAL etc. 057 */ 058 private List<CustomDbTypeMapping> customDbTypeMappings = new ArrayList<>(); 059 060 /** 061 * Construct with defaults. 062 */ 063 public PlatformConfig() { 064 065 } 066 067 /** 068 * Construct based on given config - typically for DbMigration generation with many platforms. 069 */ 070 public PlatformConfig(PlatformConfig platformConfig) { 071 this.databaseBooleanFalse = platformConfig.databaseBooleanFalse; 072 this.databaseBooleanTrue = platformConfig.databaseBooleanTrue; 073 this.databaseSequenceBatchSize = platformConfig.databaseSequenceBatchSize; 074 this.idType = platformConfig.idType; 075 this.geometrySRID = platformConfig.geometrySRID; 076 this.dbUuid = platformConfig.dbUuid; 077 } 078 079 /** 080 * Return true if all DB column and table names should use quoted identifiers. 081 */ 082 public boolean isAllQuotedIdentifiers() { 083 return allQuotedIdentifiers; 084 } 085 086 /** 087 * Set to true if all DB column and table names should use quoted identifiers. 088 */ 089 public void setAllQuotedIdentifiers(boolean allQuotedIdentifiers) { 090 this.allQuotedIdentifiers = allQuotedIdentifiers; 091 } 092 093 /** 094 * Return a value used to represent TRUE in the database. 095 * <p> 096 * This is used for databases that do not support boolean natively. 097 * </p> 098 * <p> 099 * The value returned is either a Integer or a String (e.g. "1", or "T"). 100 * </p> 101 */ 102 public String getDatabaseBooleanTrue() { 103 return databaseBooleanTrue; 104 } 105 106 /** 107 * Set the value to represent TRUE in the database. 108 * <p> 109 * This is used for databases that do not support boolean natively. 110 * </p> 111 * <p> 112 * The value set is either a Integer or a String (e.g. "1", or "T"). 113 * </p> 114 */ 115 public void setDatabaseBooleanTrue(String databaseBooleanTrue) { 116 this.databaseBooleanTrue = databaseBooleanTrue; 117 } 118 119 /** 120 * Return a value used to represent FALSE in the database. 121 */ 122 public String getDatabaseBooleanFalse() { 123 return databaseBooleanFalse; 124 } 125 126 /** 127 * Set the value used to represent FALSE in the database. 128 */ 129 public void setDatabaseBooleanFalse(String databaseBooleanFalse) { 130 this.databaseBooleanFalse = databaseBooleanFalse; 131 } 132 133 /** 134 * Return the number of DB sequence values that should be preallocated. 135 */ 136 public int getDatabaseSequenceBatchSize() { 137 return databaseSequenceBatchSize; 138 } 139 140 /** 141 * Set the number of DB sequence values that should be preallocated. 142 */ 143 public void setDatabaseSequenceBatchSize(int databaseSequenceBatchSize) { 144 this.databaseSequenceBatchSize = databaseSequenceBatchSize; 145 } 146 147 /** 148 * Return the Geometry SRID. 149 */ 150 public int getGeometrySRID() { 151 return geometrySRID; 152 } 153 154 /** 155 * Set the Geometry SRID. 156 */ 157 public void setGeometrySRID(int geometrySRID) { 158 this.geometrySRID = geometrySRID; 159 } 160 161 /** 162 * Return the DB type used to store UUID. 163 */ 164 public DbUuid getDbUuid() { 165 return dbUuid; 166 } 167 168 /** 169 * Set the DB type used to store UUID. 170 */ 171 public void setDbUuid(DbUuid dbUuid) { 172 this.dbUuid = dbUuid; 173 } 174 175 /** 176 * Return the IdType to use (or null for the default choice). 177 */ 178 public IdType getIdType() { 179 return idType; 180 } 181 182 /** 183 * Set the IdType to use (when the DB supports both SEQUENCE and IDENTITY and the default is not desired). 184 */ 185 public void setIdType(IdType idType) { 186 this.idType = idType; 187 } 188 189 /** 190 * Return true if InetAddress should map to varchar column (rather than Postgres INET). 191 */ 192 public boolean isDatabaseInetAddressVarchar() { 193 return databaseInetAddressVarchar; 194 } 195 196 /** 197 * Set to true to force InetAddress to map to varchar column. 198 */ 199 public void setDatabaseInetAddressVarchar(boolean databaseInetAddressVarchar) { 200 this.databaseInetAddressVarchar = databaseInetAddressVarchar; 201 } 202 203 /** 204 * Add a custom type mapping. 205 * <p> 206 * <pre>{@code 207 * 208 * // set the default mapping for BigDecimal.class/decimal 209 * serverConfig.addCustomMapping(DbType.DECIMAL, "decimal(18,6)"); 210 * 211 * // set the default mapping for String.class/varchar but only for Postgres 212 * serverConfig.addCustomMapping(DbType.VARCHAR, "text", Platform.POSTGRES); 213 * 214 * }</pre> 215 * 216 * @param type The DB type this mapping should apply to 217 * @param columnDefinition The column definition that should be used 218 * @param platform Optionally specify the platform this mapping should apply to. 219 */ 220 public void addCustomMapping(DbType type, String columnDefinition, Platform platform) { 221 customDbTypeMappings.add(new CustomDbTypeMapping(type, columnDefinition, platform)); 222 } 223 224 /** 225 * Add a custom type mapping that applies to all platforms. 226 * <p> 227 * <pre>{@code 228 * 229 * // set the default mapping for BigDecimal/decimal 230 * serverConfig.addCustomMapping(DbType.DECIMAL, "decimal(18,6)"); 231 * 232 * // set the default mapping for String/varchar 233 * serverConfig.addCustomMapping(DbType.VARCHAR, "text"); 234 * 235 * }</pre> 236 * 237 * @param type The DB type this mapping should apply to 238 * @param columnDefinition The column definition that should be used 239 */ 240 public void addCustomMapping(DbType type, String columnDefinition) { 241 customDbTypeMappings.add(new CustomDbTypeMapping(type, columnDefinition)); 242 } 243 244 /** 245 * Return the list of custom type mappings. 246 */ 247 public List<CustomDbTypeMapping> getCustomTypeMappings() { 248 return customDbTypeMappings; 249 } 250 251 public void loadSettings(PropertiesWrapper p) { 252 253 idType = p.getEnum(IdType.class, "idType", idType); 254 databaseSequenceBatchSize = p.getInt("databaseSequenceBatchSize", databaseSequenceBatchSize); 255 databaseBooleanTrue = p.get("databaseBooleanTrue", databaseBooleanTrue); 256 databaseBooleanFalse = p.get("databaseBooleanFalse", databaseBooleanFalse); 257 databaseInetAddressVarchar = p.getBoolean("databaseInetAddressVarchar", databaseInetAddressVarchar); 258 259 DbUuid dbUuid = p.getEnum(DbUuid.class, "dbuuid", null); 260 if (dbUuid != null) { 261 setDbUuid(dbUuid); 262 } 263 if (p.getBoolean("uuidStoreAsBinary", false)) { 264 setDbUuid(DbUuid.BINARY); 265 } 266 267 int srid = p.getInt("geometrySRID", 0); 268 if (srid > 0) { 269 setGeometrySRID(srid); 270 } 271 272 // Mapping is specified in the form: BOOLEAN=int(1);BIT=int(1); 273 String mapping = p.get("mapping"); 274 if (mapping != null && !mapping.isEmpty()) { 275 Map<String, String> map = StringHelper.delimitedToMap(mapping, ";", "="); 276 for (Entry<String, String> entry : map.entrySet()) { 277 addCustomMapping(DbType.valueOf(entry.getKey()), entry.getValue()); 278 } 279 } 280 281 boolean quotedIdentifiers = p.getBoolean("allQuotedIdentifiers", allQuotedIdentifiers); 282 if (quotedIdentifiers != allQuotedIdentifiers) { 283 // potentially also set to use matching naming convention 284 setAllQuotedIdentifiers(quotedIdentifiers); 285 } 286 } 287 288 /** 289 * Specify how UUID is stored. 290 */ 291 public enum DbUuid { 292 293 294 /** 295 * Store using native UUID in H2 and Postgres and otherwise fallback to VARCHAR(40). 296 */ 297 AUTO_VARCHAR(true, false, false), 298 299 /** 300 * Store using native UUID in H2 and Postgres and otherwise fallback to BINARY(16). 301 */ 302 AUTO_BINARY(true, true, false), 303 304 /** 305 * Store using native UUID in H2 and Postgres and otherwise fallback to BINARY(16) with optimized packing. 306 */ 307 AUTO_BINARY_OPTIMIZED(true, true, true), 308 309 /** 310 * Store using DB VARCHAR(40). 311 */ 312 VARCHAR(false, false, false), 313 314 /** 315 * Store using DB BINARY(16). 316 */ 317 BINARY(false, true, false), 318 319 /** 320 * Store using DB BINARY(16). 321 */ 322 BINARY_OPTIMIZED(false, true, true); 323 324 boolean nativeType; 325 boolean binary; 326 boolean binaryOptimized; 327 328 DbUuid(boolean nativeType, boolean binary, boolean binaryOptimized) { 329 this.nativeType = nativeType; 330 this.binary = binary; 331 this.binaryOptimized = binaryOptimized; 332 } 333 334 /** 335 * Return true if native UUID type is preferred. 336 */ 337 public boolean useNativeType() { 338 return nativeType; 339 } 340 341 /** 342 * Return true if BINARY(16) storage is preferred over VARCHAR(40). 343 */ 344 public boolean useBinary() { 345 return binary; 346 } 347 348 /** 349 * Return true, if optimized packing should be used. 350 */ 351 public boolean useBinaryOptimized() { 352 return binaryOptimized; 353 } 354 } 355}