1 29 30 package com.caucho.quercus.lib.db; 31 32 import com.caucho.quercus.QuercusModuleException; 33 import com.caucho.quercus.annotation.Optional; 34 import com.caucho.quercus.env.BooleanValue; 35 import com.caucho.quercus.env.Env; 36 import com.caucho.quercus.env.StringBuilderValue; 37 import com.caucho.quercus.env.StringValue; 38 import com.caucho.quercus.env.StringValueImpl; 39 import com.caucho.quercus.env.Value; 40 import com.caucho.util.L10N; 41 import com.caucho.util.LruCache; 42 43 import java.io.Closeable ; 44 import java.sql.*; 45 import java.util.logging.Level ; 46 import java.util.logging.Logger ; 47 48 51 public abstract class JdbcConnectionResource implements Closeable { 52 private static final L10N L = new L10N(JdbcConnectionResource.class); 53 private static final Logger log 54 = Logger.getLogger(JdbcConnectionResource.class.getName()); 55 56 private static LruCache<TableKey,JdbcTableMetaData> _tableMetadataMap 57 = new LruCache<TableKey,JdbcTableMetaData>(256); 58 59 private Connection _conn; 60 private Statement _stmt; 62 63 private DatabaseMetaData _dmd; 64 65 private JdbcResultResource _rs; 66 private int _affectedRows; 67 68 private String _errorMessage = ""; 69 private int _errorCode; 70 private boolean _fieldCount = false; 71 private SQLWarning _warnings; 72 73 private Env _env; 74 private String _host; 75 private String _dbname; 76 private int _port; 77 private String _userName; 78 private String _password; 79 private String _driver; 80 private String _url; 81 82 private boolean _connected; 83 84 public JdbcConnectionResource(Env env) 85 { 86 _env = env; 87 } 88 89 92 public String error() 93 { 94 if (isConnected()) 95 return getErrorMessage(); 96 else 97 return null; 98 } 99 100 public boolean isConnected() 101 { 102 return _connected; 103 } 104 105 public Env getEnv() 106 { 107 return _env; 108 } 109 110 public String getHost() 111 { 112 return _host; 113 } 114 115 public String getUserName() 116 { 117 return _userName; 118 } 119 120 public String getPassword() 121 { 122 return _password; 123 } 124 125 public String getDbName() 126 { 127 return _dbname; 128 } 129 130 public int getPort() 131 { 132 return _port; 133 } 134 135 public String getDriver() 136 { 137 return _driver; 138 } 139 140 public String getUrl() 141 { 142 return _url; 143 } 144 145 154 protected void setConnection(String host, 155 String userName, 156 String password, 157 String dbname, 158 int port, 159 Connection conn, 160 String driver, 161 String url) 162 { 163 _host = host; 164 _userName = userName; 165 _password = password; 166 _dbname = dbname; 167 _port = port; 168 169 _conn = conn; 170 171 _driver = driver; 172 173 _url = url; 174 175 if (conn != null) { 176 _connected = true; 177 178 _env.addClose(this); 179 } 180 } 181 182 185 protected abstract boolean connectInternal(Env env, 186 @Optional("localhost") String host, 187 @Optional String userName, 188 @Optional String password, 189 @Optional String dbname, 190 @Optional int port, 191 @Optional String socket, 192 @Optional int flags, 193 @Optional String driver, 194 @Optional String url); 195 196 202 protected StringBuilderValue realEscapeString(StringValue str) 203 { 204 StringBuilderValue buf = new StringBuilderValue(str.length()); 205 206 final int strLength = str.length(); 207 208 for (int i = 0; i < strLength; i++) { 209 char c = str.charAt(i); 210 211 switch (c) { 212 case '\u0000': 213 buf.append('\\'); 214 buf.append('\u0000'); 215 break; 216 case '\n': 217 buf.append('\\'); 218 buf.append('n'); 219 break; 220 case '\r': 221 buf.append('\\'); 222 buf.append('r'); 223 break; 224 case '\\': 225 buf.append('\\'); 226 buf.append('\\'); 227 break; 228 case '\'': 229 buf.append('\\'); 230 buf.append('\''); 231 break; 232 case '"': 233 buf.append('\\'); 234 buf.append('\"'); 235 break; 236 case '\032': 237 buf.append('\\'); 238 buf.append('Z'); 239 break; 240 default: 241 buf.append(c); 242 break; 243 } 244 } 245 246 return buf; 247 } 248 249 252 public int getAffectedRows() 253 { 254 return _affectedRows; 255 } 256 257 public void setAffectedRows(int i) 258 { 259 _affectedRows = i; 260 } 261 262 265 public int getFieldCount() 266 { 267 if (_rs == null) { 268 return 0; 269 } else { 270 return _rs.getFieldCount(); 271 } 272 } 273 274 277 protected JdbcResultResource getCatalogs() 278 { 279 clearErrors(); 280 281 try { 282 if (_dmd == null) 283 _dmd = _conn.getMetaData(); 284 285 ResultSet rs = _dmd.getCatalogs(); 286 287 if (rs != null) 288 return createResult(_stmt, rs); 289 else 290 return null; 291 } catch (SQLException e) { 292 saveErrors(e); 293 log.log(Level.WARNING, e.toString(), e); 294 return null; 295 } 296 } 297 298 301 protected Value getCatalog() 302 { 303 clearErrors(); 304 305 try { 306 return new StringValueImpl(_conn.getCatalog()); 307 } catch (SQLException e) { 308 saveErrors(e); 309 log.log(Level.WARNING, e.toString(), e); 310 return BooleanValue.FALSE; 311 } 312 } 313 314 320 public String getCharacterSetName() 321 { 322 return "latin1"; 323 } 324 325 328 public String getClientEncoding() 329 { 330 return getCharacterSetName(); 331 } 332 333 337 public String getClientInfo() 338 { 339 try { 340 if (_dmd == null) 341 _dmd = _conn.getMetaData(); 342 343 return _dmd.getDatabaseProductVersion(); 344 } catch (SQLException e) { 345 log.log(Level.FINE, e.toString(), e); 346 return null; 347 } 348 } 349 350 353 public Connection getConnection() 354 { 355 if (_conn != null) 356 return _conn; 357 else if (_errorMessage != null) 358 throw new QuercusModuleException(_errorMessage); 359 else 360 throw new QuercusModuleException(L.l("Connection is not available")); 361 } 362 363 367 protected Connection getJavaConnection() 368 throws SQLException 369 { 370 return _env.getQuercus().getConnection(_conn); 371 } 372 373 376 public String getURL() 377 { 378 return _url; 380 } 381 382 385 public int getErrorCode() 386 { 387 return _errorCode; 388 } 389 390 393 public String getErrorMessage() 394 { 395 return _errorMessage; 396 } 397 398 404 public String getHostInfo() 405 throws SQLException 406 { 407 if (_dmd == null) 408 _dmd = _conn.getMetaData(); 409 410 return _dmd.getURL(); 411 } 412 413 418 public String getServerInfo() 419 throws SQLException 420 { 421 return getMetaData().getDatabaseProductVersion(); 422 } 423 424 427 public JdbcTableMetaData getTableMetaData(String catalog, 428 String schema, 429 String table) 430 throws SQLException 431 { 432 TableKey key = new TableKey(getURL(), catalog, schema, table); 433 434 JdbcTableMetaData tableMd = _tableMetadataMap.get(key); 436 437 if (tableMd != null && tableMd.isValid()) 438 return tableMd; 439 440 tableMd = new JdbcTableMetaData(catalog, schema, table, getMetaData()); 441 442 _tableMetadataMap.put(key, tableMd); 443 444 return tableMd; 445 } 446 447 private DatabaseMetaData getMetaData() 448 throws SQLException 449 { 450 if (_dmd == null) 451 _dmd = _conn.getMetaData(); 452 453 return _dmd; 454 } 455 456 static int infoToVersion(String info) 457 { 458 String [] result = info.split("[.a-z-]"); 459 460 if (result.length < 3) 461 return 0; 462 463 return (Integer.parseInt(result[0]) * 10000 + 464 Integer.parseInt(result[1]) * 100 + 465 Integer.parseInt(result[2])); 466 } 467 468 471 public boolean close(Env env) 472 { 473 if (_connected) { 474 _connected = false; 475 env.removeClose(this); 476 close(); 477 } 478 479 return true; 480 } 481 482 public JdbcConnectionResource validateConnection() 483 { 484 if (! _connected) { 485 throw _env.errorException(L.l("Connection is not properly initialized {0}\nDriver {1}", 486 _url, _driver)); 487 } 488 489 return this; 490 } 491 492 495 protected JdbcResultResource realQuery(String sql) 496 { 497 clearErrors(); 498 499 _rs = null; 500 501 Statement stmt = null; 502 503 try { 504 stmt = getConnection().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, 505 ResultSet.CONCUR_READ_ONLY); 506 stmt.setEscapeProcessing(false); 508 if (stmt.execute(sql)) { 509 ResultSet rs = stmt.getResultSet(); 510 _rs = createResult(stmt, rs); 511 _affectedRows = 0; 512 _warnings = stmt.getWarnings(); 513 } else { 514 519 521 keepResourceValues(stmt); 523 524 _affectedRows = 0; 525 _affectedRows = stmt.getUpdateCount(); 526 if (_rs != null) 527 _rs.setAffectedRows(_affectedRows); 528 _warnings = stmt.getWarnings(); 529 530 if (!keepStatementOpen()) { 532 stmt.close(); 533 } 534 } 535 } catch (DataTruncation truncationError) { 536 try { 537 _affectedRows = stmt.getUpdateCount(); 538 _warnings = stmt.getWarnings(); 539 } catch (SQLException e) { 540 saveErrors(e); 541 log.log(Level.WARNING, e.toString(), e); 542 return null; 543 } 544 } catch (SQLException e) { 545 546 saveErrors(e); 547 548 if (keepStatementOpen()) { 550 keepResourceValues(stmt); 551 } else { 552 log.log(Level.WARNING, e.toString(), e); 553 return null; 554 } 555 } 556 557 return _rs; 558 } 559 560 563 protected JdbcResultResource createResult(Statement stmt, 564 ResultSet rs) 565 { 566 return new JdbcResultResource(stmt, rs, this); 567 } 568 569 570 573 public boolean setAutoCommit(boolean mode) 574 { 575 clearErrors(); 576 577 try { 578 _conn.setAutoCommit(mode); 579 } catch (SQLException e) { 580 saveErrors(e); 581 log.log(Level.WARNING, e.toString(), e); 582 return false; 583 } 584 585 return true; 586 } 587 588 591 public boolean commit() 592 { 593 clearErrors(); 594 595 try { 596 _conn.commit(); 597 } catch (SQLException e) { 598 saveErrors(e); 599 log.log(Level.WARNING, e.toString(), e); 600 return false; 601 } 602 603 return true; 604 } 605 606 612 public boolean rollback() 613 { 614 clearErrors(); 615 616 try { 617 _conn.rollback(); 618 } catch (SQLException e) { 619 saveErrors(e); 620 log.log(Level.WARNING, e.toString(), e); 621 return false; 622 } 623 624 return true; 625 } 626 629 public void setCatalog(String name) 630 throws SQLException 631 { 632 clearErrors(); 633 634 _conn.setCatalog(name); 635 } 636 637 640 public Object toObject() 641 { 642 return null; 643 } 644 645 648 public String toString() 649 { 650 return _conn.toString(); 651 } 652 653 656 public void close() 657 { 658 try { 659 Statement stmt = _stmt; 660 _stmt = null; 661 662 if (stmt != null) 663 stmt.close(); 664 } catch (SQLException e) { 665 log.log(Level.FINER, e.toString(), e); 666 } 667 668 try { 669 Connection conn = _conn; 670 673 if (conn != null) 674 conn.close(); 675 } catch (SQLException e) { 676 log.log(Level.FINER, e.toString(), e); 677 } 678 } 679 680 684 protected void keepResourceValues(Statement stmt) 685 { 686 return; 687 } 688 689 693 protected boolean keepStatementOpen() 694 { 695 return false; 696 } 697 698 701 protected JdbcResultResource getResultResource() 702 { 703 return _rs; 704 } 705 706 709 protected void setResultResource(JdbcResultResource rs) 710 { 711 _rs = rs; 712 } 713 714 719 protected SQLWarning getWarnings() 720 { 721 return _warnings; 722 } 723 724 727 public boolean ping() 728 { 729 try { 730 731 return isConnected() && ! getConnection().isClosed(); 732 733 } catch (SQLException e) { 734 log.log(Level.FINE, e.toString(), e); 735 return false; 736 } 737 } 738 739 744 protected void setWarnings(SQLWarning warnings) 745 { 746 _warnings = warnings; 747 } 748 749 protected void clearErrors() 750 { 751 _errorMessage = null; 752 _errorCode = 0; 753 _warnings = null; 754 } 755 756 protected void saveErrors(SQLException e) 757 { 758 _errorMessage = e.getMessage(); 759 _errorCode = e.getErrorCode(); 760 } 761 762 static class TableKey { 763 private final String _url; 764 private final String _catalog; 765 private final String _schema; 766 private final String _table; 767 768 TableKey(String url, String catalog, String schema, String table) 769 { 770 _url = url; 771 _catalog = catalog; 772 _schema = schema; 773 _table = table; 774 } 775 776 public int hashCode() 777 { 778 int hash = 37; 779 780 if (_catalog != null) 781 hash = 65537 * hash + _catalog.hashCode(); 782 783 if (_schema != null) 784 hash = 65537 * hash + _schema.hashCode(); 785 786 if (_table != null) 787 hash = 65537 * hash + _table.hashCode(); 788 789 return hash; 790 } 791 792 public boolean equals(Object o) 793 { 794 if (this == o) 795 return true; 796 else if (! (o instanceof TableKey)) 797 return false; 798 799 TableKey key = (TableKey) o; 800 801 if (_url != key._url) 802 return false; 803 804 if ((_catalog == null) != (key._catalog == null)) 805 return false; 806 else if (_catalog != null && ! _catalog.equals(key._catalog)) 807 return false; 808 809 if ((_schema == null) != (key._schema == null)) 810 return false; 811 else if (_schema != null && ! _schema.equals(key._schema)) 812 return false; 813 814 if ((_table == null) != (key._table == null)) 815 return false; 816 else if (_table != null && ! _table.equals(key._table)) 817 return false; 818 819 return true; 820 } 821 } 822 } 823 824 | Popular Tags |