1 package net.sourceforge.phpdt.sql.sql;
3 import java.io.ByteArrayOutputStream;
5 import java.io.InputStream;
8 import java.net.URLClassLoader;
9 import java.sql.Connection;
10 import java.sql.DatabaseMetaData;
11 import java.sql.Driver;
12 import java.sql.ResultSet;
13 import java.sql.ResultSetMetaData;
14 import java.sql.SQLException;
15 import java.sql.Statement;
16 import java.util.ArrayList;
17 import java.util.Hashtable;
18 import java.util.List;
19 import java.util.Properties;
20 import java.util.StringTokenizer;
21 import java.util.Vector;
23 import org.apache.xml.utils.IntVector;
25 import net.sourceforge.phpdt.sql.bookmarks.Bookmark;
26 import net.sourceforge.phpdt.sql.sql.metadata.MetaDataJDBCInterface;
27 import net.sourceforge.phpdt.sql.sql.metadata.ObjectMetaData;
28 import net.sourceforge.phpdt.sql.view.LogProxy;
29 import net.sourceforge.phpdt.sql.view.bookmark.TableNode;
30 import net.sourceforge.phpdt.sql.view.bookmark.TreeNode;
34 * MultiSQLServer is a Singleton, used as a interface with the sql drivers
35 * Use MultiSQLServer.getInstance() to get the object
37 public class MultiSQLServer implements ConnectionEstablisher {
38 private static final int STREAM = 1024 * 2;
39 public static final String USERNAME = "user"; //$NON-NLS-1$
40 public static final String PASSWORD = "password"; //$NON-NLS-1$
41 private static MultiSQLServer instance = null;
42 private Hashtable classLoaderCache = new Hashtable();
43 boolean running = true;
45 public MultiSQLServer() {
48 public synchronized static MultiSQLServer getInstance() {
49 if (instance == null) {
50 instance = new MultiSQLServer();
55 public void commit(Connection con) {
56 LogProxy log = LogProxy.getInstance();
59 } catch (SQLException e) {
60 log.addText(LogProxy.ERROR, "Error commiting: " + e, e); //$NON-NLS-1$
64 public void rollback(Connection con) {
65 LogProxy log = LogProxy.getInstance();
68 } catch (SQLException e) {
69 log.addText(LogProxy.ERROR, "Error rolling back: " + e, e); //$NON-NLS-1$
73 public void setAutoCommit(Connection con, boolean enabled) {
74 LogProxy log = LogProxy.getInstance();
77 con.setAutoCommit(enabled);
79 log.addText(LogProxy.ERROR, "Please connect before setting autocommit"); //$NON-NLS-1$
81 } catch (SQLException e) {
82 log.addText(LogProxy.ERROR, "Error setting autocommit: " + e, e); //$NON-NLS-1$
86 public void disconnect(Bookmark b, Connection con) {
87 LogProxy log = LogProxy.getInstance();
90 b.setConnection(null);
91 log.addText(LogProxy.RESULTS, "Disconnected from: " + b.getName()); //$NON-NLS-1$
92 } catch (Exception e) {
95 "Error Disonnecting to: " + b.getName() + ":" + e.toString(), e); //$NON-NLS-1$ //$NON-NLS-2$
99 public void dumpDatabaseData(Connection con) {
100 LogProxy log = LogProxy.getInstance();
102 DatabaseMetaData meta = con.getMetaData();
103 log.addText(LogProxy.WARNING, "[METADATA] Database type: " + meta.getDatabaseProductName()); //$NON-NLS-1$
104 if (meta.supportsCatalogsInDataManipulation()) {
105 log.addText(LogProxy.WARNING, "[METADATA] Database does support catalog in data manipulation"); //$NON-NLS-1$
107 log.addText(LogProxy.WARNING, "[METADATA] Database does not support catalog in data manipulation"); //$NON-NLS-1$
109 if (meta.supportsSchemasInDataManipulation()) {
110 log.addText(LogProxy.WARNING, "[METADATA] Database does support schema in data manipulation"); //$NON-NLS-1$
112 log.addText(LogProxy.WARNING, "[METADATA] Database does not support schema in data manipulation"); //$NON-NLS-1$
114 if (meta.supportsCatalogsInTableDefinitions()) {
115 log.addText(LogProxy.WARNING, "[METADATA] Database does support catalogs in table definitions"); //$NON-NLS-1$
117 log.addText(LogProxy.WARNING, "[METADATA] Database does not support catalogs in table definitions"); //$NON-NLS-1$
119 log.addText(LogProxy.WARNING, "[METADATA] Catalog Separator: " + meta.getCatalogSeparator()); //$NON-NLS-1$
120 log.addText(LogProxy.WARNING, "[METADATA] Catalog Term: " + meta.getCatalogTerm()); //$NON-NLS-1$
121 ResultSet set = meta.getCatalogs();
122 ArrayList catalogList = new ArrayList();
123 catalogList.add(null);
125 catalogList.add(set.getString(1));
128 StringBuffer catalogOutput = new StringBuffer();
129 catalogOutput.append("[CATALOG LIST] ["); //$NON-NLS-1$
130 for (int i = 0; i < catalogList.size(); i++) {
131 String name = (String) catalogList.get(i);
132 catalogOutput.append(name + ", "); //$NON-NLS-1$
134 catalogOutput.append("]"); //$NON-NLS-1$
135 log.addText(LogProxy.WARNING, catalogOutput.toString());
137 set = meta.getSchemas();
138 ArrayList schemaList = new ArrayList();
139 schemaList.add(""); //$NON-NLS-1$
141 schemaList.add(set.getString(1));
144 StringBuffer schemaOutput = new StringBuffer();
145 schemaOutput.append("[SCHEMA LIST] ["); //$NON-NLS-1$
146 for (int i = 0; i < schemaList.size(); i++) {
147 String name = (String) schemaList.get(i);
148 schemaOutput.append(name + ", "); //$NON-NLS-1$
150 schemaOutput.append("]"); //$NON-NLS-1$
151 log.addText(LogProxy.WARNING, schemaOutput.toString());
153 List tableTypes = getTableTypes(meta);
155 StringBuffer tableListOutput = new StringBuffer();
156 tableListOutput.append("[TABLE LIST] ["); //$NON-NLS-1$
157 for (int i = 0; i < tableTypes.size(); i++) {
158 String name = (String) tableTypes.get(i);
159 tableListOutput.append(name + ", "); //$NON-NLS-1$
161 tableListOutput.append("]"); //$NON-NLS-1$
162 log.addText(LogProxy.WARNING, tableListOutput.toString());
165 } catch (Exception e) {
166 log.addText(LogProxy.ERROR, e);
169 private List getTableTypes(DatabaseMetaData meta) throws SQLException {
170 ArrayList tableTypes = new ArrayList();
171 ResultSet set = meta.getTableTypes();
173 String type = set.getString(1);
175 tableTypes.add(type.trim());
184 // * @param type of the element "TABLE", "VIEW", "SEQUENCE"
187 // public Vector listElements(Connection con, String schema, String type) {
188 // LogProxy log = LogProxy.getInstance();
189 // Vector retVal = new Vector(50,5);
190 // log.addText(LogProxy.QUERY, "Retrieving list [" + type + "]"); //$NON-NLS-1$ //$NON-NLS-2$
192 // DatabaseMetaData meta = con.getMetaData();
193 // List types = getTableTypes(meta);
194 // if (types.contains(type)) {
195 // ResultSet set = meta.getTables(
196 // null, null, "%", new String[] {type}); //$NON-NLS-1$
197 // while (set.next()) {
198 // String tableSchema = set.getString("TABLE_SCHEM");
199 // tableSchema = (tableSchema == null) ? "" : tableSchema.trim();
200 // String tableName = set.getString("TABLE_NAME").trim(); //$NON-NLS-1$
201 // if (tableName.length() > 0)
202 // retVal.addElement(((tableSchema.length() > 0) ? tableSchema + "." : "") + tableName);
206 // log.addText(LogProxy.RESULTS, "Success"); //$NON-NLS-1$
208 // } catch (SQLException e) {
209 // log.addText(LogProxy.ERROR, e);
215 * Makes a connection to a JDBC driver based on the data from a bookmark
216 * @param b The Bookmark with the data needed to make the connection
217 * @return The Connection object if everything went OK
219 public Connection connect(Bookmark b) {
221 LogProxy log = LogProxy.getInstance();
222 log.addText(LogProxy.QUERY, "Connecting to: " + b.getName()); //$NON-NLS-1$
223 URL urls[] = new URL[1];
225 String driverFile = b.getDriverFile();
226 URLClassLoader loader = (URLClassLoader) classLoaderCache.get(driverFile);
227 if (loader == null) {
228 urls[0] = new File(driverFile).toURL();
229 loader = new URLClassLoader(urls);
230 classLoaderCache.put(driverFile, loader);
231 System.out.println("Creating new classloader"); //$NON-NLS-1$
233 System.out.println("Using classloader in cache"); //$NON-NLS-1$
235 Class driverClass = loader.loadClass(b.getDriver());
236 Driver driver = (Driver) driverClass.newInstance();
237 Properties props = new Properties();
238 props.put(USERNAME, b.getUsername());
239 props.put(PASSWORD, b.getPassword());
240 con = driver.connect(b.getConnect(), props);
242 throw new Exception("Error: Driver returned a null connection: " + b.toString()); //$NON-NLS-1$
244 log.addText(LogProxy.RESULTS, "Connected to: " + b.getName()); //$NON-NLS-1$
245 System.out.println("Connected"); //$NON-NLS-1$
247 } catch (Exception e) {
250 // "Error Connecting to: " + b.getName() + ":" + e.toString(), e); //$NON-NLS-1$ //$NON-NLS-2$
254 public SQLResults execute(Connection con, String s) {
255 return execute(con, s, -1, -1);
257 public SQLResults execute(Connection con, String s, int startRow, int endRow) {
258 return execute(con, s, -1, -1, Integer.MAX_VALUE);
260 public SQLResults execute(Connection con, String s, int startRow, int endRow, int maxLength) {
261 return execute(con, s, startRow, endRow, maxLength, ""); //$NON-NLS-1$
263 public SQLResults execute(Connection con, String s, int startRow, int endRow, int maxLength, String encoding) {
264 SQLResults results = new SQLResults();
266 System.out.println("Executing"); //$NON-NLS-1$
267 LogProxy log = LogProxy.getInstance();
268 log.addText(LogProxy.QUERY, "Executing Request [" + s + "]"); //$NON-NLS-1$ //$NON-NLS-2$
269 boolean metadata = false;
270 if (s.startsWith("METADATA")) { //$NON-NLS-1$
275 String table = s.substring(s.indexOf(':') + 1);
276 String query = "SELECT * FROM " + table + " WHERE (1 = 0)"; //$NON-NLS-1$ //$NON-NLS-2$
278 log.addText(LogProxy.QUERY, "Metadata Request [" + s + "]"); //$NON-NLS-1$ //$NON-NLS-2$
283 Statement stmt = con.createStatement();
284 boolean flag = stmt.execute(s);
285 results.setResultSet(flag);
287 int updates = stmt.getUpdateCount();
288 results.setUpdateCount(updates);
291 "Success: " + updates + " records updated"); //$NON-NLS-1$ //$NON-NLS-2$
295 ResultSet set = stmt.getResultSet();
296 ResultSetMetaData metaData = set.getMetaData();
297 int columnCount = metaData.getColumnCount();
298 Vector columnNames = new Vector();
299 columnNames.addElement("ColumnName"); //$NON-NLS-1$
300 columnNames.addElement("Type"); //$NON-NLS-1$
301 columnNames.addElement("Size"); //$NON-NLS-1$
302 columnNames.addElement("Nullable"); //$NON-NLS-1$
303 columnNames.addElement("AutoIncrement"); //$NON-NLS-1$
304 results.setColumnNames(columnNames);
305 for (int i = 1; i <= columnCount; i++) {
306 Vector row = new Vector();
307 row.addElement(metaData.getColumnName(i));
308 row.addElement(metaData.getColumnTypeName(i));
309 int textSize = metaData.getColumnDisplaySize(i);
310 int precision = metaData.getPrecision(i);
311 int scale = metaData.getScale(i);
312 if (scale == 0 && precision == 0) {
313 row.addElement(Integer.toString(precision));
315 row.addElement(textSize + ", " + precision + ", " + scale); //$NON-NLS-1$ //$NON-NLS-2$
317 int nullable = metaData.isNullable(i);
318 if (nullable == ResultSetMetaData.columnNoNulls) {
319 row.addElement("Not Null"); //$NON-NLS-1$
320 } else if (nullable == ResultSetMetaData.columnNullable) {
321 row.addElement("Nullable"); //$NON-NLS-1$
322 } else if (nullable == ResultSetMetaData.columnNullableUnknown) {
323 row.addElement("Nullable"); //$NON-NLS-1$
325 row.addElement("<Error>"); //$NON-NLS-1$
327 row.addElement(Boolean.toString(metaData.isAutoIncrement(i)));
330 results.setHasMore(false);
333 ResultSet set = stmt.getResultSet();
334 ResultSetMetaData metaData = set.getMetaData();
335 int columnCount = metaData.getColumnCount();
336 Vector columnNames = new Vector();
337 for (int i = 1; i <= columnCount; i++) {
338 columnNames.addElement(metaData.getColumnName(i));
340 results.setColumnNames(columnNames);
341 Vector columnTypes = new Vector();
342 for (int i = 1; i <= columnCount; i++) {
343 columnTypes.addElement(metaData.getColumnTypeName(i));
345 results.setColumnTypes(columnTypes);
346 IntVector columnSizes = new IntVector();
347 for (int i = 1; i <= columnCount; i++) {
348 columnSizes.addElement(metaData.getColumnDisplaySize(i));
350 results.setColumnSizes(columnSizes);
351 // int columnSizes[] = new int[columnCount];
352 // for (int i = 1; i <= columnCount; i++) {
353 // columnSizes[i - 1] = metaData.getColumnDisplaySize(i);
356 boolean exitEarly = false;
358 boolean disable = startRow < 1 || endRow < 1;
359 boolean start = rowCount >= startRow;
360 boolean end = rowCount <= endRow;
361 if (disable || (start && end)) {
362 Vector row = new Vector();
363 for (int i = 1; i <= columnCount; i++) {
365 if (columnSizes.elementAt(i - 1) < STREAM && columnSizes.elementAt(i - 1) < maxLength) {
366 if (encoding.equals("")) { //$NON-NLS-1$
367 value = set.getString(i);
369 value = new String(set.getBytes(i), encoding);
373 if (encoding.equals("")) { //$NON-NLS-1$
374 Reader reader = set.getCharacterStream(i);
375 StringBuffer buffer = new StringBuffer();
376 if (reader != null) {
377 int retVal = reader.read();
379 while (retVal >= 0) {
380 buffer.append((char) retVal);
381 retVal = reader.read();
383 if (count > maxLength) {
384 buffer.append("...>>>"); //$NON-NLS-1$
390 value = buffer.toString();
392 InputStream binaryStream = set.getBinaryStream(i);
393 ByteArrayOutputStream baos = new ByteArrayOutputStream();
394 if (binaryStream != null) {
395 int retVal = binaryStream.read();
397 while (retVal >= 0) {
399 retVal = binaryStream.read();
401 if (count > maxLength) {
405 binaryStream.close();
407 value = new String(baos.toByteArray(), encoding);
409 } catch (Throwable e) {
410 // hack for mysql which doesn't implement
412 value = set.getString(i);
416 row.addElement("<NULL>"); //$NON-NLS-1$
418 row.addElement(value);
424 if (!disable && (rowCount > endRow)) {
430 results.setHasMore(set.next());
432 results.setMaxSize(rowCount);
433 results.setHasMore(false);
437 log.addText(LogProxy.RESULTS, "Success: result set displayed"); //$NON-NLS-1$
440 System.out.println("Executed"); //$NON-NLS-1$
441 System.out.println();
442 } catch (Exception e) {
443 results.setIsError(true);
444 log.addText(LogProxy.ERROR, e); //$NON-NLS-1$
449 public ObjectMetaData getObjectMetadata(Connection con, TreeNode node) throws SQLException {
450 ObjectMetaData metadata = new ObjectMetaData();
451 String table = node.getName();
452 metadata.setColumns(MetaDataJDBCInterface.getColumns(con, getSchemaName(table), getTableName(table)));
453 if (node instanceof TableNode) {
454 String schema = getSchemaName(table);
455 String tableName = getTableName(table);
456 metadata.setPrimaryKeys(MetaDataJDBCInterface.getPrimaryKeys(con, schema, tableName));
457 metadata.setForeignKeys(MetaDataJDBCInterface.getForeignKeys(con, schema, tableName, true));
458 metadata.setIndexInfo(MetaDataJDBCInterface.getIndexInfo(con, schema, tableName));
463 public String getTableName(String table) {
464 StringTokenizer st = new StringTokenizer(table, "."); //$NON-NLS-1$
465 if (st.countTokens() == 2) {
467 return st.nextToken();
468 } else if (st.countTokens() == 1){
469 return st.nextToken();
473 public String getSchemaName(String table) {
474 StringTokenizer st = new StringTokenizer(table, "."); //$NON-NLS-1$
475 if (st.countTokens() == 2) {
476 return st.nextToken();