1 19 20 package org.apache.cayenne.dba; 21 22 import java.io.Serializable ; 23 import java.math.BigInteger ; 24 import java.sql.DatabaseMetaData ; 25 import java.sql.ResultSet ; 26 import java.sql.SQLException ; 27 import java.sql.Types ; 28 import java.util.ArrayList ; 29 import java.util.Calendar ; 30 import java.util.HashMap ; 31 import java.util.Iterator ; 32 import java.util.List ; 33 import java.util.Map ; 34 import java.util.Set ; 35 36 import org.apache.cayenne.util.Util; 37 38 45 public class TypesMapping { 46 47 public static final int NOT_DEFINED = Integer.MAX_VALUE; 50 51 public static final String SQL_ARRAY = "ARRAY"; 53 public static final String SQL_BIGINT = "BIGINT"; 54 public static final String SQL_BINARY = "BINARY"; 55 public static final String SQL_BIT = "BIT"; 56 public static final String SQL_BLOB = "BLOB"; 57 58 61 public static final String SQL_BOOLEAN = "BOOLEAN"; 62 63 public static final String SQL_CLOB = "CLOB"; 64 public static final String SQL_CHAR = "CHAR"; 65 public static final String SQL_DATE = "DATE"; 66 public static final String SQL_DECIMAL = "DECIMAL"; 67 public static final String SQL_DOUBLE = "DOUBLE"; 68 public static final String SQL_FLOAT = "FLOAT"; 69 public static final String SQL_INTEGER = "INTEGER"; 70 public static final String SQL_LONGVARCHAR = "LONGVARCHAR"; 71 public static final String SQL_LONGVARBINARY = "LONGVARBINARY"; 72 public static final String SQL_NUMERIC = "NUMERIC"; 73 public static final String SQL_REAL = "REAL"; 74 public static final String SQL_SMALLINT = "SMALLINT"; 75 public static final String SQL_TINYINT = "TINYINT"; 76 public static final String SQL_TIME = "TIME"; 77 public static final String SQL_TIMESTAMP = "TIMESTAMP"; 78 public static final String SQL_VARBINARY = "VARBINARY"; 79 public static final String SQL_VARCHAR = "VARCHAR"; 80 public static final String SQL_OTHER = "OTHER"; 81 82 public static final String JAVA_LONG = "java.lang.Long"; 84 public static final String JAVA_BYTES = "byte[]"; 85 public static final String JAVA_BOOLEAN = "java.lang.Boolean"; 86 public static final String JAVA_STRING = "java.lang.String"; 87 public static final String JAVA_SQLDATE = "java.sql.Date"; 88 public static final String JAVA_UTILDATE = "java.util.Date"; 89 public static final String JAVA_BIGDECIMAL = "java.math.BigDecimal"; 90 public static final String JAVA_DOUBLE = "java.lang.Double"; 91 public static final String JAVA_FLOAT = "java.lang.Float"; 92 public static final String JAVA_INTEGER = "java.lang.Integer"; 93 public static final String JAVA_SHORT = "java.lang.Short"; 94 public static final String JAVA_BYTE = "java.lang.Byte"; 95 public static final String JAVA_TIME = "java.sql.Time"; 96 public static final String JAVA_TIMESTAMP = "java.sql.Timestamp"; 97 public static final String JAVA_BLOB = "java.sql.Blob"; 98 99 102 private static final Map sqlStringType = new HashMap (); 103 104 107 private static final Map sqlEnumType = new HashMap (); 108 109 112 private static final Map sqlEnumJava = new HashMap (); 113 114 117 private static final Map javaSqlEnum = new HashMap (); 118 119 static { 120 sqlStringType.put(SQL_ARRAY, new Integer (Types.ARRAY)); 121 sqlStringType.put(SQL_BIGINT, new Integer (Types.BIGINT)); 122 sqlStringType.put(SQL_BINARY, new Integer (Types.BINARY)); 123 sqlStringType.put(SQL_BIT, new Integer (Types.BIT)); 124 sqlStringType.put(SQL_BLOB, new Integer (Types.BLOB)); 125 sqlStringType.put(SQL_BOOLEAN, new Integer (Types.BOOLEAN)); 126 sqlStringType.put(SQL_CLOB, new Integer (Types.CLOB)); 127 sqlStringType.put(SQL_CHAR, new Integer (Types.CHAR)); 128 sqlStringType.put(SQL_DATE, new Integer (Types.DATE)); 129 sqlStringType.put(SQL_DECIMAL, new Integer (Types.DECIMAL)); 130 sqlStringType.put(SQL_DOUBLE, new Integer (Types.DOUBLE)); 131 sqlStringType.put(SQL_FLOAT, new Integer (Types.FLOAT)); 132 sqlStringType.put(SQL_INTEGER, new Integer (Types.INTEGER)); 133 sqlStringType.put(SQL_LONGVARCHAR, new Integer (Types.LONGVARCHAR)); 134 sqlStringType.put(SQL_LONGVARBINARY, new Integer (Types.LONGVARBINARY)); 135 sqlStringType.put(SQL_NUMERIC, new Integer (Types.NUMERIC)); 136 sqlStringType.put(SQL_REAL, new Integer (Types.REAL)); 137 sqlStringType.put(SQL_SMALLINT, new Integer (Types.SMALLINT)); 138 sqlStringType.put(SQL_TINYINT, new Integer (Types.TINYINT)); 139 sqlStringType.put(SQL_TIME, new Integer (Types.TIME)); 140 sqlStringType.put(SQL_TIMESTAMP, new Integer (Types.TIMESTAMP)); 141 sqlStringType.put(SQL_VARBINARY, new Integer (Types.VARBINARY)); 142 sqlStringType.put(SQL_VARCHAR, new Integer (Types.VARCHAR)); 143 sqlStringType.put(SQL_OTHER, new Integer (Types.OTHER)); 144 145 sqlEnumType.put(new Integer (Types.ARRAY), SQL_ARRAY); 146 sqlEnumType.put(new Integer (Types.BIGINT), SQL_BIGINT); 147 sqlEnumType.put(new Integer (Types.BINARY), SQL_BINARY); 148 sqlEnumType.put(new Integer (Types.BIT), SQL_BIT); 149 sqlEnumType.put(new Integer (Types.BOOLEAN), SQL_BOOLEAN); 150 sqlEnumType.put(new Integer (Types.BLOB), SQL_BLOB); 151 sqlEnumType.put(new Integer (Types.CLOB), SQL_CLOB); 152 sqlEnumType.put(new Integer (Types.CHAR), SQL_CHAR); 153 sqlEnumType.put(new Integer (Types.DATE), SQL_DATE); 154 sqlEnumType.put(new Integer (Types.DECIMAL), SQL_DECIMAL); 155 sqlEnumType.put(new Integer (Types.DOUBLE), SQL_DOUBLE); 156 sqlEnumType.put(new Integer (Types.FLOAT), SQL_FLOAT); 157 sqlEnumType.put(new Integer (Types.INTEGER), SQL_INTEGER); 158 sqlEnumType.put(new Integer (Types.LONGVARCHAR), SQL_LONGVARCHAR); 159 sqlEnumType.put(new Integer (Types.LONGVARBINARY), SQL_LONGVARBINARY); 160 sqlEnumType.put(new Integer (Types.NUMERIC), SQL_NUMERIC); 161 sqlEnumType.put(new Integer (Types.REAL), SQL_REAL); 162 sqlEnumType.put(new Integer (Types.SMALLINT), SQL_SMALLINT); 163 sqlEnumType.put(new Integer (Types.TINYINT), SQL_TINYINT); 164 sqlEnumType.put(new Integer (Types.TIME), SQL_TIME); 165 sqlEnumType.put(new Integer (Types.TIMESTAMP), SQL_TIMESTAMP); 166 sqlEnumType.put(new Integer (Types.VARBINARY), SQL_VARBINARY); 167 sqlEnumType.put(new Integer (Types.VARCHAR), SQL_VARCHAR); 168 sqlEnumType.put(new Integer (Types.OTHER), SQL_OTHER); 169 170 sqlEnumJava.put(new Integer (Types.BIGINT), JAVA_LONG); 171 sqlEnumJava.put(new Integer (Types.BINARY), JAVA_BYTES); 172 sqlEnumJava.put(new Integer (Types.BIT), JAVA_BOOLEAN); 173 sqlEnumJava.put(new Integer (Types.BOOLEAN), JAVA_BOOLEAN); 174 sqlEnumJava.put(new Integer (Types.BLOB), JAVA_BYTES); 175 sqlEnumJava.put(new Integer (Types.CLOB), JAVA_STRING); 176 sqlEnumJava.put(new Integer (Types.CHAR), JAVA_STRING); 177 sqlEnumJava.put(new Integer (Types.DATE), JAVA_UTILDATE); 178 sqlEnumJava.put(new Integer (Types.DECIMAL), JAVA_BIGDECIMAL); 179 sqlEnumJava.put(new Integer (Types.DOUBLE), JAVA_DOUBLE); 180 sqlEnumJava.put(new Integer (Types.FLOAT), JAVA_FLOAT); 181 sqlEnumJava.put(new Integer (Types.INTEGER), JAVA_INTEGER); 182 sqlEnumJava.put(new Integer (Types.LONGVARCHAR), JAVA_STRING); 183 sqlEnumJava.put(new Integer (Types.LONGVARBINARY), JAVA_BYTES); 184 sqlEnumJava.put(new Integer (Types.NUMERIC), JAVA_BIGDECIMAL); 185 sqlEnumJava.put(new Integer (Types.REAL), JAVA_FLOAT); 186 sqlEnumJava.put(new Integer (Types.SMALLINT), JAVA_SHORT); 187 sqlEnumJava.put(new Integer (Types.TINYINT), JAVA_BYTE); 188 sqlEnumJava.put(new Integer (Types.TIME), JAVA_UTILDATE); 189 sqlEnumJava.put(new Integer (Types.TIMESTAMP), JAVA_UTILDATE); 190 sqlEnumJava.put(new Integer (Types.VARBINARY), JAVA_BYTES); 191 sqlEnumJava.put(new Integer (Types.VARCHAR), JAVA_STRING); 192 193 javaSqlEnum.put(JAVA_LONG, new Integer (Types.BIGINT)); 194 javaSqlEnum.put(JAVA_BYTES, new Integer (Types.BINARY)); 195 javaSqlEnum.put(JAVA_BOOLEAN, new Integer (Types.BIT)); 196 javaSqlEnum.put(JAVA_STRING, new Integer (Types.VARCHAR)); 197 javaSqlEnum.put(JAVA_SQLDATE, new Integer (Types.DATE)); 198 javaSqlEnum.put(JAVA_TIMESTAMP, new Integer (Types.TIMESTAMP)); 199 javaSqlEnum.put(JAVA_BIGDECIMAL, new Integer (Types.DECIMAL)); 200 javaSqlEnum.put(JAVA_DOUBLE, new Integer (Types.DOUBLE)); 201 javaSqlEnum.put(JAVA_FLOAT, new Integer (Types.FLOAT)); 202 javaSqlEnum.put(JAVA_INTEGER, new Integer (Types.INTEGER)); 203 javaSqlEnum.put(JAVA_SHORT, new Integer (Types.SMALLINT)); 204 javaSqlEnum.put(JAVA_BYTE, new Integer (Types.TINYINT)); 205 javaSqlEnum.put(JAVA_TIME, new Integer (Types.TIME)); 206 javaSqlEnum.put(JAVA_TIMESTAMP, new Integer (Types.TIMESTAMP)); 207 208 javaSqlEnum.put("byte", new Integer (Types.TINYINT)); 210 javaSqlEnum.put("int", new Integer (Types.INTEGER)); 211 javaSqlEnum.put("short", new Integer (Types.SMALLINT)); 212 javaSqlEnum.put("char", new Integer (Types.CHAR)); 213 javaSqlEnum.put("double", new Integer (Types.DOUBLE)); 214 javaSqlEnum.put("long", new Integer (Types.BIGINT)); 215 javaSqlEnum.put("float", new Integer (Types.FLOAT)); 216 javaSqlEnum.put("boolean", new Integer (Types.BIT)); 217 } 218 219 223 public static boolean supportsLength(int type) { 224 return type == Types.BINARY 225 || type == Types.CHAR 226 || type == Types.DECIMAL 227 || type == Types.DOUBLE 228 || type == Types.FLOAT 229 || type == Types.NUMERIC 230 || type == Types.REAL 231 || type == Types.VARBINARY 232 || type == Types.VARCHAR; 233 } 234 235 238 public static boolean isNumeric(int type) { 239 return type == Types.BIGINT 240 || type == Types.BIT 241 || type == Types.DECIMAL 242 || type == Types.DOUBLE 243 || type == Types.FLOAT 244 || type == Types.INTEGER 245 || type == Types.NUMERIC 246 || type == Types.REAL 247 || type == Types.SMALLINT 248 || type == Types.TINYINT; 249 } 250 251 254 public static boolean isDecimal(int type) { 255 return type == Types.DECIMAL 256 || type == Types.DOUBLE 257 || type == Types.FLOAT 258 || type == Types.REAL 259 || type == Types.NUMERIC; 260 } 261 262 263 public static String [] getDatabaseTypes() { 264 Set keys = sqlStringType.keySet(); 265 int len = keys.size(); 266 String [] types = new String [len]; 267 268 Iterator it = keys.iterator(); 269 for (int i = 0; i < len; i++) { 270 types[i] = (String ) it.next(); 271 } 272 273 return types; 274 } 275 276 280 protected static String pickDataType(int jdbcType, TypeInfo[] alts) { 281 int len = alts.length; 282 283 if (len == 0) 284 return null; 285 286 if (len == 1) 287 return alts[0].name; 288 289 291 String jdbcName = getSqlNameByType(jdbcType).toUpperCase(); 292 293 for (int i = 0; i < len; i++) { 295 if (jdbcName.equalsIgnoreCase(alts[i].name)) 296 return alts[i].name; 297 } 298 299 long maxPrec = 0; 301 for (int i = 0; i < len; i++) { 302 if (maxPrec < alts[i].precision) { 303 maxPrec = alts[i].precision; 304 } 305 } 306 307 List list = new ArrayList (); 308 for (int i = 0; i < len; i++) { 309 if (maxPrec == alts[i].precision) { 310 list.add(alts[i]); 311 } 312 } 313 314 int slen = list.size(); 316 if (slen == 1) 317 return ((TypeInfo) list.get(0)).name; 318 319 for (int i = 0; i < slen; i++) { 321 String uppercase = ((TypeInfo) list.get(i)).name.toUpperCase(); 322 if (uppercase.startsWith(jdbcName) || uppercase.endsWith(jdbcName)) 323 return ((TypeInfo) list.get(i)).name; 324 } 325 326 for (int i = 0; i < slen; i++) { 328 String uppercase = ((TypeInfo) list.get(i)).name.toUpperCase(); 329 330 if (uppercase.indexOf(jdbcName) >= 0) 331 return ((TypeInfo) list.get(i)).name; 332 } 333 334 return ((TypeInfo) list.get(0)).name; 336 } 337 338 341 public static int getSqlTypeByName(String typeName) { 342 Integer tmp = (Integer ) sqlStringType.get(typeName); 343 return (null == tmp) ? NOT_DEFINED : tmp.intValue(); 344 } 345 346 349 public static String getSqlNameByType(int type) { 350 return (String ) sqlEnumType.get(new Integer (type)); 351 } 352 353 359 public static int getSqlTypeByJava(String className) { 360 if (className == null) { 361 return NOT_DEFINED; 362 } 363 364 Integer type = (Integer ) javaSqlEnum.get(className); 365 if (type != null) { 366 return type.intValue(); 367 } 368 369 371 Class aClass; 372 try { 373 aClass = Util.getJavaClass(className); 374 } 375 catch (Throwable th) { 376 return NOT_DEFINED; 377 } 378 379 return getSqlTypeByJava(aClass); 380 } 381 382 387 public static int getSqlTypeByJava(Class javaClass) { 388 if (javaClass == null) { 389 return NOT_DEFINED; 390 } 391 392 Class aClass = javaClass; 394 while (aClass != null) { 395 396 String name; 397 398 if (aClass.isArray()) { 399 name = aClass.getComponentType().getName() + "[]"; 400 } 401 else { 402 name = aClass.getName(); 403 } 404 405 Object type = javaSqlEnum.get(name); 406 if (type != null) { 407 return ((Number ) type).intValue(); 408 } 409 410 aClass = aClass.getSuperclass(); 411 } 412 413 if (javaClass.isArray()) { 415 416 Class elementType = javaClass.getComponentType(); 417 if (Character .class.isAssignableFrom(elementType) 418 || Character.TYPE.isAssignableFrom(elementType)) { 419 return Types.VARCHAR; 420 } 421 else if (Byte .class.isAssignableFrom(elementType) 422 || Byte.TYPE.isAssignableFrom(elementType)) { 423 return Types.VARBINARY; 424 } 425 } 426 427 if (Calendar .class.isAssignableFrom(javaClass)) { 428 return Types.TIMESTAMP; 429 } 430 else if (BigInteger .class.isAssignableFrom(javaClass)) { 431 return Types.BIGINT; 432 } 433 else if (Serializable .class.isAssignableFrom(javaClass)) { 436 return Types.VARBINARY; 437 } 438 439 return NOT_DEFINED; 440 } 441 442 447 public static String getJavaBySqlType(int type) { 448 return (String ) sqlEnumJava.get(new Integer (type)); 449 } 450 451 456 public static String getJavaBySqlType(int type, int length, int precision) { 457 458 if (type == Types.NUMERIC && precision == 0) { 459 type = Types.INTEGER; 460 } 461 return (String ) sqlEnumJava.get(new Integer (type)); 462 } 463 464 468 protected Map databaseTypes = new HashMap (); 469 470 public TypesMapping(DatabaseMetaData metaData) throws SQLException { 471 ResultSet rs = metaData.getTypeInfo(); 473 474 try { 475 while (rs.next()) { 476 TypeInfo info = new TypeInfo(); 477 info.name = rs.getString("TYPE_NAME"); 478 info.jdbcType = rs.getInt("DATA_TYPE"); 479 info.precision = rs.getLong("PRECISION"); 480 481 Integer key = new Integer (info.jdbcType); 482 List infos = (List ) databaseTypes.get(key); 483 484 if (infos == null) { 485 infos = new ArrayList (); 486 databaseTypes.put(key, infos); 487 } 488 489 infos.add(info); 490 } 491 } 492 finally { 493 rs.close(); 494 } 495 496 498 Integer ts = new Integer (Types.TIMESTAMP); 500 Integer dt = new Integer (Types.DATE); 501 List tsInfo = (List ) databaseTypes.get(ts); 502 List dtInfo = (List ) databaseTypes.get(dt); 503 504 if (tsInfo != null && dtInfo == null) 505 databaseTypes.put(dt, tsInfo); 506 507 if (dtInfo != null && tsInfo == null) 508 databaseTypes.put(ts, dtInfo); 509 510 Integer clob = new Integer (Types.CLOB); 512 Integer lvc = new Integer (Types.LONGVARCHAR); 513 List clobInfo = (List ) databaseTypes.get(clob); 514 List lvcInfo = (List ) databaseTypes.get(lvc); 515 516 if (clobInfo != null && lvcInfo == null) 517 databaseTypes.put(lvc, clobInfo); 518 519 if (lvcInfo != null && clobInfo == null) 520 databaseTypes.put(clob, lvcInfo); 521 522 Integer blob = new Integer (Types.BLOB); 524 Integer lvb = new Integer (Types.LONGVARBINARY); 525 List blobInfo = (List ) databaseTypes.get(blob); 526 List lvbInfo = (List ) databaseTypes.get(lvb); 527 528 if (blobInfo != null && lvbInfo == null) 529 databaseTypes.put(lvb, blobInfo); 530 531 if (lvbInfo != null && blobInfo == null) 532 databaseTypes.put(blob, lvbInfo); 533 } 534 535 536 static class TypeInfo { 537 538 String name; 539 int jdbcType; 540 long precision; 541 542 public String toString() { 543 StringBuffer buf = new StringBuffer (); 544 buf.append("[ TypeInfo: ").append(name); 545 buf.append("\n JDBC Type: ").append( 546 TypesMapping.getSqlNameByType(jdbcType)); 547 buf.append("\n Precision: ").append(precision); 548 buf.append("\n]"); 549 return buf.toString(); 550 } 551 } 552 553 } 554 | Popular Tags |