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));