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);
 
  90     public Vector getSchemas(Connection con) {
 
  92         Vector schemaList = new Vector();
 
  94             DatabaseMetaData meta = con.getMetaData();
 
  95             set = meta.getSchemas();
 
  97                 schemaList.add(set.getString("TABLE_SCHEM")); //$NON-NLS-1$
 
 100         } catch (SQLException e) {
 
 101             LogProxy log = LogProxy.getInstance();
 
 102             log.addText(LogProxy.ERROR, e);
 
 107      * Makes a connection to a JDBC driver based on the data from a bookmark
 
 109      *     The Bookmark with the data needed to make the connection
 
 110      * @param passwordFinder - 
 
 111      *     A utility class that can be invoked if the bookmark does not 
 
 113      * @return The Connection object if everything went OK
 
 115     public Connection connect(Bookmark bookmark, PasswordFinder passwordFinder)
 
 116         throws ConnectionException {
 
 118         String password = bookmark.getPassword();
 
 119         if (bookmark.getPromptForPassword()) {
 
 120             password = passwordFinder.getPassword();
 
 121             if (passwordFinder.isPasswordMeantToBeSaved()) {
 
 122                 bookmark.setPassword(password);
 
 126         if (password != null) {
 
 127             con = connect(bookmark, password);
 
 131         // Set the autoCommit state of the bookmark to the default on new connections
 
 132                 bookmark.setAutoCommit(bookmark.getDefaultAutoCommit());
 
 133                 // Set the autoCommit state of the JDBC connection to the bookmark autoCommit statec
 
 134         setAutoCommit(con, bookmark.isAutoCommit());
 
 138     private Connection connect(Bookmark bookmark, String password)
 
 139         throws ConnectionException {
 
 140         LogProxy log = LogProxy.getInstance();
 
 141         log.addText(LogProxy.QUERY, "Connecting to: " + bookmark.getName()); //$NON-NLS-1$
 
 143                 JDBCDriver jdbcDriver = bookmark.getJDBCDriver();
 
 144             Driver driver = jdbcDriver.getDriver();
 
 145             Connection connection = null;
 
 146             if (driver != null) {
 
 147                     Properties props = new Properties();
 
 148                     props.put(USERNAME, bookmark.getUsername());
 
 149                     props.put(PASSWORD, password);
 
 151                         driver.connect(bookmark.getConnect(), props);
 
 152                     if (connection == null) {
 
 153                         throw new ConnectionException("Error: Driver returned a null connection: " + bookmark.toString()); //$NON-NLS-1$
 
 156                     DatabaseMetaData metaData = connection.getMetaData();
 
 157                     jdbcDriver.setName(metaData.getDriverName());
 
 158                     jdbcDriver.setVersion(metaData.getDriverVersion());
 
 159                     log.addText(LogProxy.RESULTS, "Connected to: " + bookmark.getName()); //$NON-NLS-1$
 
 160                     System.out.println("Connected"); //$NON-NLS-1$
 
 163         } catch (SQLException e) {
 
 164             throw new ConnectionException(e);
 
 167         public SQLResults execute(Connection con, String s) throws SQLException {
 
 168                 return execute(con, s, -1, -1);
 
 170         public SQLResults execute(Connection con, String s, int startRow, int endRow) throws SQLException {
 
 171                 return execute(con, s, -1, -1, Integer.MAX_VALUE);
 
 174         public SQLResults execute(Connection con, String s, int startRow, int endRow, int maxLength) throws SQLException {
 
 175                 return execute(con, s, startRow, endRow, maxLength, ""); //$NON-NLS-1$
 
 178         public SQLResults execute(
 
 185                 throws SQLException {
 
 187                 SQLResults results = new SQLResults();
 
 189                 System.out.println("Executing"); //$NON-NLS-1$
 
 190                 LogProxy log = LogProxy.getInstance();
 
 191                 log.addText(LogProxy.QUERY, "Executing Request [" + s + "]"); //$NON-NLS-1$ //$NON-NLS-2$
 
 192                 boolean metadata = false;
 
 193                 if (s.startsWith("METADATA")) { //$NON-NLS-1$
 
 198                         String table = s.substring(s.indexOf(':') + 1);
 
 199                         String query = "SELECT * FROM " + table + " WHERE (1 = 0)"; //$NON-NLS-1$ //$NON-NLS-2$
 
 201                         log.addText(LogProxy.QUERY, "Metadata Request [" + s + "]"); //$NON-NLS-1$ //$NON-NLS-2$
 
 206                 Statement stmt = con.createStatement();
 
 207                 boolean flag = stmt.execute(s);
 
 208                 results.setResultSet(flag);
 
 210                         genMetadataResultSet(results, stmt);
 
 214                         int updates = stmt.getUpdateCount();
 
 215                         results.setUpdateCount(updates);
 
 216                         log.addText(LogProxy.RESULTS, "Success: " + updates + " records updated"); //$NON-NLS-1$ //$NON-NLS-2$
 
 219                         ResultSet set = stmt.getResultSet();
 
 220                         ResultSetMetaData metaData = set.getMetaData();
 
 221                         int columnCount = metaData.getColumnCount();
 
 222                         Vector columnNames = new Vector();
 
 223                         for (int i = 1; i <= columnCount; i++) {
 
 224                                 columnNames.addElement(metaData.getColumnName(i));
 
 226                         results.setColumnNames(columnNames);
 
 227                         Vector columnTypes = new Vector();
 
 228                         for (int i = 1; i <= columnCount; i++) {
 
 229                                 columnTypes.addElement(metaData.getColumnTypeName(i));
 
 231                         results.setColumnTypes(columnTypes);
 
 232                         int columnSizes[] = new int[columnCount];
 
 233                         for (int i = 1; i <= columnCount; i++) {
 
 234                                 columnSizes[i - 1] = metaData.getColumnDisplaySize(i);
 
 237                         boolean exitEarly = false;
 
 239                                 boolean disable = startRow < 1 || endRow < 1;
 
 240                                 boolean start = rowCount >= startRow;
 
 241                                 boolean end = rowCount <= endRow;
 
 242                                 if (disable || (start && end)) {
 
 243                                         Vector row = new Vector();
 
 244                                         for (int i = 1; i <= columnCount; i++) {
 
 246                                                 if (columnSizes[i - 1] < STREAM
 
 247                                                         && columnSizes[i - 1] < maxLength) {
 
 248                                                         if (encoding.equals("")) { //$NON-NLS-1$
 
 249                                                                 value = set.getString(i);
 
 253                                                                                 new String(set.getBytes(i), encoding);
 
 254                                                                 } catch (UnsupportedEncodingException e) {
 
 255                                                                         log.addText(LogProxy.ERROR, "Error Unsupported encoding " + encoding.toString() + ":" + e.toString(), e); //$NON-NLS-1$ //$NON-NLS-2$
 
 256                                                                         value = new String(set.getBytes(i));
 
 261                                                                 if (encoding.equals("")) { //$NON-NLS-1$
 
 262                                                                         Reader reader = set.getCharacterStream(i);
 
 263                                                                         StringBuffer buffer = new StringBuffer();
 
 264                                                                         if (reader != null) {
 
 265                                                                                 int retVal = reader.read();
 
 267                                                                                 while (retVal >= 0) {
 
 268                                                                                         buffer.append((char) retVal);
 
 269                                                                                         retVal = reader.read();
 
 271                                                                                         if (count > maxLength) {
 
 272                                                                                                 buffer.append("...>>>"); //$NON-NLS-1$
 
 278                                                                         value = buffer.toString();
 
 280                                                                         InputStream binaryStream =
 
 281                                                                                 set.getBinaryStream(i);
 
 282                                                                         ByteArrayOutputStream baos =
 
 283                                                                                 new ByteArrayOutputStream();
 
 284                                                                         if (binaryStream != null) {
 
 285                                                                                 int retVal = binaryStream.read();
 
 287                                                                                 while (retVal >= 0) {
 
 289                                                                                         retVal = binaryStream.read();
 
 291                                                                                         if (count > maxLength) {
 
 295                                                                                 binaryStream.close();
 
 302                                                         } catch (Throwable e) {
 
 303                                                                 // hack for mysql which doesn't implement
 
 305                                                                 value = set.getString(i);
 
 309                                                         row.addElement("<NULL>"); //$NON-NLS-1$
 
 311                                                         row.addElement(value);
 
 317                                 if (!disable && (rowCount > endRow)) {
 
 323                                 results.setHasMore(set.next());
 
 325                                 results.setMaxSize(rowCount);
 
 326                                 results.setHasMore(false);
 
 330                 log.addText(LogProxy.RESULTS, "Success: result set displayed"); //$NON-NLS-1$
 
 332                 System.out.println("Executed"); //$NON-NLS-1$
 
 333                 System.out.println();
 
 336         private void genMetadataResultSet(SQLResults results, Statement stmt)
 
 337                 throws SQLException {
 
 338                 ResultSet set = stmt.getResultSet();
 
 339                 ResultSetMetaData metaData = set.getMetaData();
 
 340                 int columnCount = metaData.getColumnCount();
 
 341                 Vector columnNames = new Vector();
 
 342                 columnNames.addElement("ColumnName"); //$NON-NLS-1$
 
 343                 columnNames.addElement("Type"); //$NON-NLS-1$
 
 344                 columnNames.addElement("Size"); //$NON-NLS-1$
 
 345                 columnNames.addElement("Nullable"); //$NON-NLS-1$
 
 346                 columnNames.addElement("AutoIncrement"); //$NON-NLS-1$
 
 347                 results.setColumnNames(columnNames);
 
 348                 for (int i = 1; i <= columnCount; i++) {
 
 349                         Vector row = new Vector();
 
 350                         row.addElement(metaData.getColumnName(i));
 
 351                         row.addElement(metaData.getColumnTypeName(i));
 
 352                         int textSize = metaData.getColumnDisplaySize(i);
 
 353                         int precision = metaData.getPrecision(i);
 
 354                         int scale = metaData.getScale(i);
 
 355                         if (scale == 0 && precision == 0) {
 
 356                                 row.addElement(Integer.toString(precision));
 
 358                                 row.addElement(textSize + ", " + precision + ", " + scale); //$NON-NLS-1$ //$NON-NLS-2$
 
 360                         int nullable = metaData.isNullable(i);
 
 361                         if (nullable == ResultSetMetaData.columnNoNulls) {
 
 362                                 row.addElement("Not Null"); //$NON-NLS-1$
 
 363                         } else if (nullable == ResultSetMetaData.columnNullable) {
 
 364                                 row.addElement("Nullable"); //$NON-NLS-1$
 
 366                                 nullable == ResultSetMetaData.columnNullableUnknown) {
 
 367                                 row.addElement("Nullable"); //$NON-NLS-1$
 
 369                                 row.addElement("<Error>"); //$NON-NLS-1$
 
 372                                 (metaData.isAutoIncrement(i)
 
 378                 results.setHasMore(false);
 
 383          * Returns an ObjectMetadata object got from the connection 'con' using the name and schema of the node.
 
 387          * @throws SQLException
 
 389         public ObjectMetaData getObjectMetadata(Connection con, TreeNode node) throws SQLException {
 
 390                 ObjectMetaData metadata = new ObjectMetaData();
 
 391                 if (!(node instanceof Entity)) return metadata;
 
 393                 String schema = ((Entity)node).getSchema();
 
 394                 String tableName = node.getName();
 
 396                 if (schema.length() == 0) schema = null;
 
 397                 metadata.setColumns(MetaDataJDBCInterface.getColumns(con, schema, tableName));
 
 398                 if (node instanceof EntityNode && ((EntityNode) node).isTable()) {
 
 399                         metadata.setPrimaryKeys(MetaDataJDBCInterface.getPrimaryKeys(con, schema, tableName));
 
 400                         metadata.setForeignKeys(MetaDataJDBCInterface.getForeignKeys(con, schema, tableName, true));
 
 401                         metadata.setIndexInfo(MetaDataJDBCInterface.getIndexInfo(con, schema, tableName));
 
 402                         metadata.setBestRowId(MetaDataJDBCInterface.getBestRowId(con, schema, tableName));