1 29 30 package com.caucho.jdbc; 31 32 import com.caucho.util.L10N; 33 import com.caucho.util.Log; 34 35 import javax.sql.DataSource ; 36 import java.sql.Connection ; 37 import java.sql.DatabaseMetaData ; 38 import java.sql.ResultSet ; 39 import java.sql.SQLException ; 40 import java.sql.Types ; 41 import java.util.logging.Level ; 42 import java.util.logging.Logger ; 43 44 47 public class JdbcMetaData { 48 private static final L10N L = new L10N(JdbcMetaData.class); 49 private static final Logger log = Log.open(JdbcMetaData.class); 50 51 private DataSource _ds; 52 53 56 protected JdbcMetaData(DataSource ds) 57 { 58 _ds = ds; 59 } 60 61 64 public static JdbcMetaData create(DataSource ds) 65 { 66 Connection conn = null; 67 68 try { 69 conn = ds.getConnection(); 70 71 DatabaseMetaData md = conn.getMetaData(); 72 73 String name = md.getDatabaseProductName(); 74 75 log.fine(L.l("Database '{0}' metadata.", name)); 76 77 if ("oracle".equalsIgnoreCase(name)) 78 return new OracleMetaData(ds); 79 else if ("resin".equalsIgnoreCase(name)) 80 return new ResinMetaData(ds); 81 else if ("postgres".equalsIgnoreCase(name) || 82 "PostgreSQL".equalsIgnoreCase(name)) 83 return new PostgresMetaData(ds); 84 else if ("mysql".equalsIgnoreCase(name)) 85 return new MysqlMetaData(ds); 86 else if ("Microsoft SQL Server".equalsIgnoreCase(name)) 87 return new SqlServerMetaData(ds); 88 else { 89 log.fine(name + " is an unknown database type"); 90 return new JdbcMetaData(ds); 91 } 92 } catch (SQLException e) { 93 log.log(Level.FINE, e.toString(), e); 94 return new JdbcMetaData(ds); 95 } finally { 96 try { 97 if (conn != null) conn.close(); 98 } catch (SQLException e) { 99 } 100 } 101 } 102 103 106 public String getDatabaseName() 107 { 108 Connection conn = null; 109 110 try { 111 conn = getConnection(); 112 113 DatabaseMetaData md = conn.getMetaData(); 114 115 return md.getDatabaseProductName(); 116 } catch (SQLException e) { 117 log.log(Level.WARNING, e.toString(), e); 118 return "unknown"; 119 } finally { 120 try { 121 if (conn != null) conn.close(); 122 } catch (SQLException e) { 123 } 124 } 125 } 126 127 130 public String getBlobType() 131 { 132 Connection conn = null; 133 134 try { 135 conn = getConnection(); 136 137 DatabaseMetaData md = conn.getMetaData(); 138 ResultSet rs; 139 140 rs = md.getTypeInfo(); 141 try { 142 while (rs.next()) { 143 if (rs.getShort("DATA_TYPE") == Types.BLOB) { 144 return rs.getString("TYPE_NAME"); 145 } 146 } 147 } finally { 148 rs.close(); 149 } 150 151 rs = md.getTypeInfo(); 152 try { 153 while (rs.next()) { 154 int dataType = rs.getShort("DATA_TYPE"); 155 156 if (rs.getShort("DATA_TYPE") == Types.LONGVARBINARY) { 157 return rs.getString("TYPE_NAME"); 158 } 159 } 160 } finally { 161 rs.close(); 162 } 163 164 rs = md.getTypeInfo(); 165 try { 166 while (rs.next()) { 167 if (rs.getShort("DATA_TYPE") == Types.BINARY) { 168 return rs.getString("TYPE_NAME"); 169 } 170 } 171 } finally { 172 rs.close(); 173 } 174 175 rs = md.getTypeInfo(); 176 try { 177 while (rs.next()) { 178 if (rs.getShort("DATA_TYPE") == Types.VARBINARY) { 179 return rs.getString("TYPE_NAME"); 180 } 181 } 182 } finally { 183 rs.close(); 184 } 185 } catch (SQLException e) { 186 log.log(Level.FINE, e.toString(), e); 187 } finally { 188 try { 189 if (conn != null) 190 conn.close(); 191 } catch (Exception e) { 192 } 193 } 194 195 return null; 196 } 197 198 201 public boolean isTruncateBlobBeforeDelete() 202 { 203 return false; 204 } 205 206 209 public boolean supportsGetGeneratedKeys() 210 { 211 try { 212 Connection conn = getConnection(); 213 214 try { 215 DatabaseMetaData metaData = conn.getMetaData(); 216 217 return metaData.supportsGetGeneratedKeys(); 218 } finally { 219 conn.close(); 220 } 221 } catch (SQLException e) { 222 throw new RuntimeException (e); 223 } 224 } 225 226 229 public String getLongType() 230 { 231 Connection conn = null; 232 233 try { 234 conn = getConnection(); 235 236 DatabaseMetaData md = conn.getMetaData(); 237 ResultSet rs; 238 239 rs = md.getTypeInfo(); 240 try { 241 while (rs.next()) { 242 if (rs.getShort("DATA_TYPE") == Types.BIGINT) { 243 return rs.getString("TYPE_NAME"); 244 } 245 } 246 } finally { 247 rs.close(); 248 } 249 } catch (SQLException e) { 250 log.log(Level.FINE, e.toString(), e); 251 } finally { 252 try { 253 if (conn != null) conn.close(); 254 } catch (SQLException e) { 255 } 256 } 257 258 return null; 259 } 260 261 264 public boolean supportsIdentity() 265 { 266 return false; 267 } 268 269 272 public String createIdentitySQL(String sqlType) 273 { 274 throw new UnsupportedOperationException (getClass().getName()); 275 } 276 277 280 public boolean supportsSequences() 281 { 282 return false; 283 } 284 285 288 public String createSequenceSQL(String name, int size) 289 { 290 throw new UnsupportedOperationException (getClass().getName()); 291 } 292 293 296 public String selectSequenceSQL(String name) 297 { 298 throw new UnsupportedOperationException (getClass().getName()); 299 } 300 301 304 public String testSequenceSQL(String name) 305 { 306 return selectSequenceSQL(name) + " WHERE 1=0"; 307 } 308 309 312 public String generateBoolean(String term) 313 { 314 return term; 315 } 316 317 320 public String limit(String sql, int max) 321 { 322 return sql; 323 } 324 328 public String getCreateColumnSQL(int sqlType, int length, int precision, int scale) 329 { 330 String type = null; 331 332 switch (sqlType) { 333 case Types.BOOLEAN: 334 type = getCreateColumnSQLImpl(sqlType, length, precision, scale); 335 if (type == null) 336 type = getCreateColumnSQLImpl(Types.BIT, length, precision, scale); 337 break; 338 339 case Types.DATE: 340 type = getCreateColumnSQLImpl(sqlType, length, precision, scale); 341 if (type == null) 342 type = getCreateColumnSQLImpl(Types.TIMESTAMP, length, precision, scale); 343 break; 344 345 case Types.TIME: 346 type = getCreateColumnSQLImpl(sqlType, length, precision, scale); 347 if (type == null) 348 type = getCreateColumnSQLImpl(Types.TIMESTAMP, length, precision, scale); 349 break; 350 351 case Types.DOUBLE: 352 type = getCreateColumnSQLImpl(Types.DOUBLE, length, precision, scale); 353 break; 354 355 case Types.NUMERIC: 356 type = getCreateColumnSQLImpl(Types.NUMERIC, length, precision, scale); 357 break; 358 359 default: 360 type = getCreateColumnSQLImpl(sqlType, length, precision, scale); 361 break; 362 } 363 364 if (type == null) 365 type = getDefaultCreateTableSQL(sqlType, length, precision, scale); 366 367 return type; 368 } 369 370 373 protected String getCreateColumnSQLImpl(int sqlType, int length, int precision, int scale) 374 { 375 Connection conn = null; 376 377 try { 378 conn = getConnection(); 379 380 DatabaseMetaData md = conn.getMetaData(); 381 ResultSet rs; 382 383 rs = md.getTypeInfo(); 384 385 try { 386 while (rs.next()) { 387 if (rs.getShort("DATA_TYPE") == sqlType) { 388 String typeName = rs.getString("TYPE_NAME"); 389 String params = rs.getString("CREATE_PARAMS"); 390 391 if (params == null || params.equals("")) 392 return typeName; 393 else if (params.startsWith("(M)")) { 394 if (length > 0) 395 return typeName + "(" + length + ")"; 396 else 397 return typeName; 398 } 399 else if (params.startsWith("(M,D)") || params.equals("precision,scale")) { 400 if (precision > 0) { 401 typeName += "(" + precision; 402 if (scale > 0) { 403 typeName += "," + scale; 404 } 405 typeName += ")"; 406 } 407 return typeName; 408 } 409 else if (params.startsWith("(")) { 410 int tail = params.indexOf(')'); 411 412 if (tail > 0) { 413 String value = params.substring(1, tail); 414 boolean isConstant = true; 415 416 for (int i = 0; i < value.length(); i++) { 417 if (value.charAt(i) >= 'a' && value.charAt(i) <= 'z') 418 isConstant = false; 419 else if (value.charAt(i) >= 'A' && value.charAt(i) <= 'Z') 420 isConstant = false; 421 } 422 423 if (isConstant) 424 return typeName + "(" + value + ")"; 425 } 426 427 return typeName; 428 } 429 else { 430 return typeName; 431 } 432 } 433 } 434 } finally { 435 rs.close(); 436 } 437 } catch (Throwable e) { 438 log.log(Level.FINE, e.toString(), e); 439 } finally { 440 try { 441 if (conn != null) 442 conn.close(); 443 } catch (Exception e) { 444 } 445 } 446 447 return null; 448 } 449 450 protected String getDefaultCreateTableSQL(int sqlType, int length, int precision, int scale) 451 { 452 switch (sqlType) { 453 case java.sql.Types.BOOLEAN: 454 return "CHAR"; 455 case java.sql.Types.BIT: 456 case java.sql.Types.TINYINT: 457 case java.sql.Types.SMALLINT: 458 case java.sql.Types.INTEGER: 459 case java.sql.Types.BIGINT: 460 return "INTEGER"; 461 case java.sql.Types.NUMERIC: 462 case java.sql.Types.DECIMAL: 463 String typeString = "NUMERIC"; 464 if (precision > 0) { 465 typeString += "(" + precision; 466 if (scale > 0) { 467 typeString += "," + scale; 468 } 469 typeString += ")"; 470 } 471 return typeString; 472 case java.sql.Types.DOUBLE: 473 case java.sql.Types.FLOAT: 474 return "DOUBLE"; 475 case java.sql.Types.CHAR: 476 return "CHAR"; 477 case java.sql.Types.DATE: 478 case java.sql.Types.TIME: 479 case java.sql.Types.TIMESTAMP: 480 return "TIMESTAMP"; 481 default: 482 return "VARCHAR(" + length + ")"; 483 } 484 } 485 486 489 protected Connection getConnection() 490 throws SQLException 491 { 492 return _ds.getConnection(); 493 } 494 } 495 | Popular Tags |