1 package com.quantum.sql;
 
   3 import java.io.ByteArrayOutputStream;
 
   4 import java.io.InputStream;
 
   6 import java.io.UnsupportedEncodingException;
 
   7 import java.sql.Connection;
 
   8 import java.sql.DatabaseMetaData;
 
   9 import java.sql.Driver;
 
  10 import java.sql.ResultSet;
 
  11 import java.sql.ResultSetMetaData;
 
  12 import java.sql.SQLException;
 
  13 import java.sql.Statement;
 
  14 import java.util.Properties;
 
  15 import java.util.Vector;
 
  17 import com.quantum.model.Bookmark;
 
  18 import com.quantum.model.ConnectionException;
 
  19 import com.quantum.model.Entity;
 
  20 import com.quantum.model.JDBCDriver;
 
  21 import com.quantum.model.PasswordFinder;
 
  22 import com.quantum.sql.metadata.MetaDataJDBCInterface;
 
  23 import com.quantum.sql.metadata.ObjectMetaData;
 
  24 import com.quantum.view.LogProxy;
 
  25 import com.quantum.view.bookmark.EntityNode;
 
  26 import com.quantum.view.bookmark.TreeNode;
 
  30  * MultiSQLServer is a Singleton, used  as a interface with the sql drivers.
 
  31  * Use MultiSQLServer.getInstance() to get the object.
 
  33 public class MultiSQLServer implements ConnectionEstablisher {
 
  34     private static final int STREAM = 1024 * 2;
 
  35     public static final String USERNAME = "user"; //$NON-NLS-1$
 
  36     public static final String PASSWORD = "password"; //$NON-NLS-1$
 
  37     private static MultiSQLServer instance = null;
 
  38     boolean running = true;
 
  40     private MultiSQLServer() {
 
  42     public synchronized static MultiSQLServer getInstance() {
 
  43         if (instance == null) {
 
  44             instance = new MultiSQLServer();
 
  49     public void commit(Connection con) {
 
  50         LogProxy log = LogProxy.getInstance();
 
  53         } catch (SQLException e) {
 
  54             log.addText(LogProxy.ERROR, "Error commiting: " + e, e); //$NON-NLS-1$
 
  58     public void rollback(Connection con) {
 
  59         LogProxy log = LogProxy.getInstance();
 
  62         } catch (SQLException e) {
 
  63             log.addText(LogProxy.ERROR, "Error rolling back: " + e, e); //$NON-NLS-1$
 
  67     public void setAutoCommit(Connection con, boolean enabled) {
 
  68         LogProxy log = LogProxy.getInstance();
 
  71                 con.setAutoCommit(enabled);
 
  73                 log.addText(LogProxy.ERROR, "Please connect before setting autocommit"); //$NON-NLS-1$
 
  75         } catch (SQLException e) {
 
  76             log.addText(LogProxy.ERROR, "Error setting autocommit: " + e, e); //$NON-NLS-1$
 
  80     public void disconnect(Connection connection) throws ConnectionException {
 
  82             if (connection != null) {
 
  85         } catch (SQLException e) {
 
  86             throw new ConnectionException(e);
 
  91      * Makes a connection to a JDBC driver based on the data from a bookmark
 
  93      *     The Bookmark with the data needed to make the connection
 
  94      * @param passwordFinder - 
 
  95      *     A utility class that can be invoked if the bookmark does not 
 
  97      * @return The Connection object if everything went OK
 
  99     public Connection connect(Bookmark bookmark, PasswordFinder passwordFinder)
 
 100         throws ConnectionException {
 
 102         String password = bookmark.getPassword();
 
 103         if (bookmark.getPromptForPassword()) {
 
 104             password = passwordFinder.getPassword();
 
 105             if (passwordFinder.isPasswordMeantToBeSaved()) {
 
 106                 bookmark.setPassword(password);
 
 110         if (password != null) {
 
 111             Connection connection = connect(bookmark, password);
 
 112             if (connection != null) {
 
 113                         // Set the autoCommit state of the bookmark to the default on new connections
 
 114                                 bookmark.setAutoCommit(bookmark.getDefaultAutoCommit());
 
 115                                 // Set the autoCommit state of the JDBC connection to the bookmark autoCommit statec
 
 116                         setAutoCommit(connection, bookmark.isAutoCommit());
 
 124     private Connection connect(Bookmark bookmark, String password)
 
 125         throws ConnectionException {
 
 126         LogProxy log = LogProxy.getInstance();
 
 127         log.addText(LogProxy.QUERY, "Connecting to: " + bookmark.getName()); //$NON-NLS-1$
 
 129                 JDBCDriver jdbcDriver = bookmark.getJDBCDriver();
 
 130             Driver driver = jdbcDriver.getDriver();
 
 131             Connection connection = null;
 
 132             if (driver != null) {
 
 133                     Properties props = new Properties();
 
 134                     props.put(USERNAME, bookmark.getUsername());
 
 135                     props.put(PASSWORD, password);
 
 137                         driver.connect(bookmark.getConnect(), props);
 
 138                     if (connection == null) {
 
 139                         throw new ConnectionException("Error: Driver returned a null connection: " + bookmark.toString()); //$NON-NLS-1$
 
 142                     DatabaseMetaData metaData = connection.getMetaData();
 
 143                     jdbcDriver.setName(metaData.getDriverName());
 
 144                     jdbcDriver.setVersion(metaData.getDriverVersion());
 
 145                     log.addText(LogProxy.RESULTS, "Connected to: " + bookmark.getName()); //$NON-NLS-1$
 
 146                     System.out.println("Connected"); //$NON-NLS-1$
 
 149         } catch (SQLException e) {
 
 150             throw new ConnectionException(e);
 
 153         public SQLResults execute(Connection con, String s) throws SQLException {
 
 154                 return execute(con, s, -1, -1);
 
 156         public SQLResults execute(Connection con, String s, int startRow, int endRow) throws SQLException {
 
 157                 return execute(con, s, -1, -1, Integer.MAX_VALUE);
 
 160         public SQLResults execute(Connection con, String s, int startRow, int endRow, int maxLength) throws SQLException {
 
 161                 return execute(con, s, startRow, endRow, maxLength, ""); //$NON-NLS-1$
 
 164         public SQLResults execute(
 
 171                 throws SQLException {
 
 173                 SQLResults results = new SQLResults();
 
 175                 long startTime = System.currentTimeMillis();
 
 176                 System.out.println("Executing"); //$NON-NLS-1$
 
 177                 LogProxy log = LogProxy.getInstance();
 
 178                 log.addText(LogProxy.QUERY, "Executing Request [" + s + "]"); //$NON-NLS-1$ //$NON-NLS-2$
 
 179                 boolean metadata = false;
 
 180                 if (s.startsWith("METADATA")) { //$NON-NLS-1$
 
 185                         String table = s.substring(s.indexOf(':') + 1);
 
 186                         String query = "SELECT * FROM " + table + " WHERE (1 = 0)"; //$NON-NLS-1$ //$NON-NLS-2$
 
 188                         log.addText(LogProxy.QUERY, "Metadata Request [" + s + "]"); //$NON-NLS-1$ //$NON-NLS-2$
 
 193                 Statement stmt = con.createStatement();
 
 194                 boolean flag = stmt.execute(s);
 
 195                 results.setResultSet(flag);
 
 197                         genMetadataResultSet(results, stmt);
 
 201                         int updates = stmt.getUpdateCount();
 
 202                         results.setUpdateCount(updates);
 
 203                         log.addText(LogProxy.RESULTS, "Success: " + updates + " records updated"); //$NON-NLS-1$ //$NON-NLS-2$
 
 206                         ResultSet set = stmt.getResultSet();
 
 207                         ResultSetMetaData metaData = set.getMetaData();
 
 208                         int columnCount = metaData.getColumnCount();
 
 209                         Vector columnNames = new Vector();
 
 210                         for (int i = 1; i <= columnCount; i++) {
 
 211                                 columnNames.addElement(metaData.getColumnName(i));
 
 213                         results.setColumnNames(columnNames);
 
 214                         Vector columnTypes = new Vector();
 
 215                         for (int i = 1; i <= columnCount; i++) {
 
 216                                 columnTypes.addElement(metaData.getColumnTypeName(i));
 
 218                         results.setColumnTypes(columnTypes);
 
 219                         int columnSizes[] = new int[columnCount];
 
 220                         for (int i = 1; i <= columnCount; i++) {
 
 221                                 columnSizes[i - 1] = metaData.getColumnDisplaySize(i);
 
 224                         boolean exitEarly = false;
 
 226                                 boolean disable = startRow < 1 || endRow < 1;
 
 227                                 boolean start = rowCount >= startRow;
 
 228                                 boolean end = rowCount <= endRow;
 
 229                                 if (disable || (start && end)) {
 
 230                                         Vector row = new Vector();
 
 231                                         for (int i = 1; i <= columnCount; i++) {
 
 233                                                 if (columnSizes[i - 1] < STREAM
 
 234                                                         && columnSizes[i - 1] < maxLength) {
 
 235                                                         if (encoding.equals("")) { //$NON-NLS-1$
 
 236                                                                 value = set.getString(i);
 
 240                                                                                 new String(set.getBytes(i), encoding);
 
 241                                                                 } catch (UnsupportedEncodingException e) {
 
 242                                                                         log.addText(LogProxy.ERROR, "Error Unsupported encoding " + encoding.toString() + ":" + e.toString(), e); //$NON-NLS-1$ //$NON-NLS-2$
 
 243                                                                         value = new String(set.getBytes(i));
 
 248                                                                 if (encoding.equals("")) { //$NON-NLS-1$
 
 249                                                                         Reader reader = set.getCharacterStream(i);
 
 250                                                                         StringBuffer buffer = new StringBuffer();
 
 251                                                                         if (reader != null) {
 
 252                                                                                 int retVal = reader.read();
 
 254                                                                                 while (retVal >= 0) {
 
 255                                                                                         buffer.append((char) retVal);
 
 256                                                                                         retVal = reader.read();
 
 258                                                                                         if (count > maxLength) {
 
 259                                                                                                 buffer.append("...>>>"); //$NON-NLS-1$
 
 265                                                                         value = buffer.toString();
 
 267                                                                         InputStream binaryStream =
 
 268                                                                                 set.getBinaryStream(i);
 
 269                                                                         ByteArrayOutputStream baos =
 
 270                                                                                 new ByteArrayOutputStream();
 
 271                                                                         if (binaryStream != null) {
 
 272                                                                                 int retVal = binaryStream.read();
 
 274                                                                                 while (retVal >= 0) {
 
 276                                                                                         retVal = binaryStream.read();
 
 278                                                                                         if (count > maxLength) {
 
 282                                                                                 binaryStream.close();
 
 289                                                         } catch (Throwable e) {
 
 290                                                                 // hack for mysql which doesn't implement
 
 292                                                                 value = set.getString(i);
 
 296                                                         row.addElement("<NULL>"); //$NON-NLS-1$
 
 298                                                         row.addElement(value);
 
 304                                 if (!disable && (rowCount > endRow)) {
 
 310                                 results.setHasMore(set.next());
 
 312                                 results.setMaxSize(rowCount);
 
 313                                 results.setHasMore(false);
 
 317                 log.addText(LogProxy.RESULTS, "Success: result set displayed"); //$NON-NLS-1$
 
 319                 results.setTime(System.currentTimeMillis() - startTime);
 
 320                 System.out.println("Executed"); //$NON-NLS-1$
 
 321                 System.out.println();
 
 324         private void genMetadataResultSet(SQLResults results, Statement stmt)
 
 325                 throws SQLException {
 
 326                 ResultSet set = stmt.getResultSet();
 
 327                 ResultSetMetaData metaData = set.getMetaData();
 
 328                 int columnCount = metaData.getColumnCount();
 
 329                 Vector columnNames = new Vector();
 
 330                 columnNames.addElement("ColumnName"); //$NON-NLS-1$
 
 331                 columnNames.addElement("Type"); //$NON-NLS-1$
 
 332                 columnNames.addElement("Size"); //$NON-NLS-1$
 
 333                 columnNames.addElement("Nullable"); //$NON-NLS-1$
 
 334                 columnNames.addElement("AutoIncrement"); //$NON-NLS-1$
 
 335                 results.setColumnNames(columnNames);
 
 336                 for (int i = 1; i <= columnCount; i++) {
 
 337                         Vector row = new Vector();
 
 338                         row.addElement(metaData.getColumnName(i));
 
 339                         row.addElement(metaData.getColumnTypeName(i));
 
 340                         int textSize = metaData.getColumnDisplaySize(i);
 
 341                         int precision = metaData.getPrecision(i);
 
 342                         int scale = metaData.getScale(i);
 
 343                         if (scale == 0 && precision == 0) {
 
 344                                 row.addElement(Integer.toString(precision));
 
 346                                 row.addElement(textSize + ", " + precision + ", " + scale); //$NON-NLS-1$ //$NON-NLS-2$
 
 348                         int nullable = metaData.isNullable(i);
 
 349                         if (nullable == ResultSetMetaData.columnNoNulls) {
 
 350                                 row.addElement("Not Null"); //$NON-NLS-1$
 
 351                         } else if (nullable == ResultSetMetaData.columnNullable) {
 
 352                                 row.addElement("Nullable"); //$NON-NLS-1$
 
 354                                 nullable == ResultSetMetaData.columnNullableUnknown) {
 
 355                                 row.addElement("Nullable"); //$NON-NLS-1$
 
 357                                 row.addElement("<Error>"); //$NON-NLS-1$
 
 360                                 (metaData.isAutoIncrement(i)
 
 366                 results.setHasMore(false);
 
 371          * Returns an ObjectMetadata object got from the connection 'con' using the name and schema of the node.
 
 375          * @throws SQLException
 
 377         public ObjectMetaData getObjectMetadata(Connection con, TreeNode node) throws SQLException {
 
 378                 ObjectMetaData metadata = new ObjectMetaData();
 
 379                 if (!(node instanceof Entity)) return metadata;
 
 381                 String schema = ((Entity)node).getSchema();
 
 382                 String tableName = node.getName();
 
 384                 if (schema.length() == 0) schema = null;
 
 385                 metadata.setColumns(MetaDataJDBCInterface.getColumns(con, schema, tableName));
 
 386                 if (node instanceof EntityNode && ((EntityNode) node).isTable()) {
 
 387                         metadata.setPrimaryKeys(MetaDataJDBCInterface.getPrimaryKeys(con, schema, tableName));
 
 388                         metadata.setForeignKeys(MetaDataJDBCInterface.getForeignKeys(con, schema, tableName, true));
 
 389                         metadata.setIndexInfo(MetaDataJDBCInterface.getIndexInfo(con, schema, tableName));
 
 390                         metadata.setBestRowId(MetaDataJDBCInterface.getBestRowId(con, schema, tableName));