added docs for some functions
[phpeclipse.git] / archive / net.sourceforge.phpeclipse.sql / src / net / sourceforge / phpdt / sql / sql / MultiSQLServer.java
1 package net.sourceforge.phpdt.sql.sql;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.File;
5 import java.io.InputStream;
6 import java.io.PrintWriter;
7 import java.io.Reader;
8 import java.io.StringWriter;
9 import java.net.URL;
10 import java.net.URLClassLoader;
11 import java.sql.Connection;
12 import java.sql.DatabaseMetaData;
13 import java.sql.Driver;
14 import java.sql.ResultSet;
15 import java.sql.ResultSetMetaData;
16 import java.sql.SQLException;
17 import java.sql.Statement;
18 import java.util.ArrayList;
19 import java.util.Hashtable;
20 import java.util.Properties;
21 import java.util.Vector;
22
23 import net.sourceforge.phpdt.sql.IConstants;
24 import net.sourceforge.phpdt.sql.adapters.AdapterFactory;
25 import net.sourceforge.phpdt.sql.adapters.DatabaseAdapter;
26 import net.sourceforge.phpdt.sql.adapters.NoSuchAdapterException;
27 import net.sourceforge.phpdt.sql.bookmarks.Bookmark;
28 import net.sourceforge.phpdt.sql.view.LogConstants;
29 import net.sourceforge.phpdt.sql.view.LogProxy;
30
31 public class MultiSQLServer extends Thread implements IConstants, LogConstants {
32   private static final int STREAM = 1024 * 2;
33   public static final String USERNAME = "user";
34   public static final String PASSWORD = "password";
35   private static MultiSQLServer instance = null;
36   private Hashtable classLoaderCache = new Hashtable();
37   private Connection con = null;
38   boolean running = true;
39   private Bookmark current = null;
40   private MultiSQLServer() {
41     //start();
42   }
43   public synchronized static MultiSQLServer getInstance() {
44     if (instance == null) {
45       instance = new MultiSQLServer();
46     }
47     return instance;
48   }
49   
50   public Bookmark getConnected() {
51     return current;
52   }
53
54   public void commit() {
55     LogProxy log = LogProxy.getInstance();
56     try {
57       con.commit();
58     } catch (SQLException e) {
59       log.addText(ERROR, "Error commiting: " + e);
60       StringWriter writer = new StringWriter();
61       e.printStackTrace(new PrintWriter(writer));
62       log.addText(ERROR, writer.toString());
63     }
64   }
65
66   public void rollback() {
67     LogProxy log = LogProxy.getInstance();
68     try {
69       con.rollback();
70     } catch (SQLException e) {
71       log.addText(ERROR, "Error rolling back: " + e);
72       StringWriter writer = new StringWriter();
73       e.printStackTrace(new PrintWriter(writer));
74       log.addText(ERROR, writer.toString());
75     }
76   }
77
78   public void setAutoCommit(boolean enabled) {
79     LogProxy log = LogProxy.getInstance();
80     try {
81       if (con != null) {
82         con.setAutoCommit(enabled);
83       } else {
84         log.addText(ERROR, "Please connect before setting autocommit");
85       }
86     } catch (SQLException e) {
87       log.addText(ERROR, "Error setting autocommit: " + e);
88       StringWriter writer = new StringWriter();
89       e.printStackTrace(new PrintWriter(writer));
90       log.addText(ERROR, writer.toString());
91     }
92   }
93
94   public DatabaseAdapter getCurrentAdapter() {
95     LogProxy log = LogProxy.getInstance();
96     try {
97       AdapterFactory factory = AdapterFactory.getInstance();
98       return factory.getAdapter(current.getType());
99     } catch (NoSuchAdapterException e) {
100       log.addText(
101         ERROR,
102         "Invalid database type: ->" + current.getType() + "<-");
103     }
104     return null;
105   }
106   public void disconnect(Bookmark b) {
107     current = null;
108     LogProxy log = LogProxy.getInstance();
109
110     try {
111       con.close();
112       con = null;
113       log.addText(RESULTS, "Disconnected from: " + b.getName());
114     } catch (Exception e) {
115       log.addText(
116         ERROR,
117         "Error Disonnecting to: " + b.getName() + ":" + e.toString());
118       StringWriter writer = new StringWriter();
119       e.printStackTrace(new PrintWriter(writer));
120       log.addText(ERROR, writer.toString());
121
122     }
123   }
124   public void shutdown() {
125     LogProxy log = LogProxy.getInstance();
126     try {
127       if (con != null) {
128         con.close();
129       }
130       con = null;
131     } catch (SQLException e) {
132       StringWriter writer = new StringWriter();
133       e.printStackTrace(new PrintWriter(writer));
134       log.addText(ERROR, writer.toString());
135     }
136   }
137
138   public void dumpDatabaseData() {
139     LogProxy log = LogProxy.getInstance();
140     try {
141       DatabaseMetaData metadata = con.getMetaData();
142       log.addText(
143         WARNING,
144         "[METADATA] Database type: " + metadata.getDatabaseProductName());
145       if (metadata.supportsCatalogsInDataManipulation()) {
146         log.addText(
147           WARNING,
148           "[METADATA] Database does support catalog in data manipulation");
149       } else {
150         log.addText(
151           WARNING,
152           "[METADATA] Database does not support catalog in data manipulation");
153       }
154       if (metadata.supportsSchemasInDataManipulation()) {
155         log.addText(
156           WARNING,
157           "[METADATA] Database does support schema in data manipulation");
158       } else {
159         log.addText(
160           WARNING,
161           "[METADATA] Database does not support schema in data manipulation");
162       }
163       if (metadata.supportsCatalogsInTableDefinitions()) {
164         log.addText(
165           WARNING,
166           "[METADATA] Database does support catalogs in table definitions");
167       } else {
168         log.addText(
169           WARNING,
170           "[METADATA] Database does not support catalogs in table definitions");
171       }
172       log.addText(
173         WARNING,
174         "[METADATA] Catalog Separator: " + metadata.getCatalogSeparator());
175       log.addText(
176         WARNING,
177         "[METADATA] Catalog Term: " + metadata.getCatalogTerm());
178       ResultSet set = metadata.getCatalogs();
179       ArrayList catalogList = new ArrayList();
180       catalogList.add(null);
181       while (set.next()) {
182         catalogList.add(set.getString(1));
183       }
184       set.close();
185       StringBuffer catalogOutput = new StringBuffer();
186       catalogOutput.append("[CATALOG LIST] [");
187       for (int i = 0; i < catalogList.size(); i++) {
188         String name = (String) catalogList.get(i);
189         catalogOutput.append(name + ", ");
190       }
191       catalogOutput.append("]");
192       log.addText(WARNING, catalogOutput.toString());
193
194       set = metadata.getSchemas();
195       ArrayList schemaList = new ArrayList();
196       schemaList.add("");
197       while (set.next()) {
198         schemaList.add(set.getString(1));
199       }
200       set.close();
201       StringBuffer schemaOutput = new StringBuffer();
202       schemaOutput.append("[SCHEMA LIST] [");
203       for (int i = 0; i < schemaList.size(); i++) {
204         String name = (String) schemaList.get(i);
205         schemaOutput.append(name + ", ");
206       }
207       schemaOutput.append("]");
208       log.addText(WARNING, schemaOutput.toString());
209
210       ArrayList tableTypes = new ArrayList();
211       set = metadata.getTableTypes();
212       while (set.next()) {
213         tableTypes.add(set.getString(1));
214       }
215       set.close();
216
217       StringBuffer tableListOutput = new StringBuffer();
218       tableListOutput.append("[TABLE LIST] [");
219       for (int i = 0; i < tableTypes.size(); i++) {
220         String name = (String) tableTypes.get(i);
221         tableListOutput.append(name + ", ");
222       }
223       tableListOutput.append("]");
224       log.addText(WARNING, tableListOutput.toString());
225
226     } catch (Exception e) {
227       log.addText(ERROR, "Error occured: " + e);
228       StringWriter writer = new StringWriter();
229       e.printStackTrace(new PrintWriter(writer));
230       log.addText(ERROR, writer.toString());
231     }
232   }
233   /**
234    * type = "TABLE" "VIEW" "SEQUENCE"
235    */
236   public Vector listTables(String schema, String type) {
237     LogProxy log = LogProxy.getInstance();
238     Vector retVal = new Vector();
239     log.addText(QUERY, "Retrieving list [" + type + "]");
240     try {
241       DatabaseMetaData meta = con.getMetaData();
242       ResultSet set = meta.getTableTypes();
243       int columnCount = set.getMetaData().getColumnCount();
244       if (DEBUG) {
245         for (int i = 1; i <= columnCount; i++) {
246           System.out.print(set.getMetaData().getColumnName(i) + "\t");
247         }
248         System.out.println();
249         while (set.next()) {
250           for (int i = 1; i <= columnCount; i++) {
251             System.out.print(set.getString(i) + "\t");
252           }
253           System.out.println();
254         }
255       }
256       Vector types = new Vector();
257       set = meta.getTableTypes();
258       while (set.next()) {
259         types.add(set.getString(1));
260       }
261       set.close();
262       if (types.contains(type)) {
263         set = meta.getTables(null, schema, "%", new String[] { type });
264         while (set.next()) {
265           String name = set.getString("TABLE_NAME");
266           String tableType = set.getString("TABLE_TYPE");
267           //System.out.println(name + ":" + tableType);
268           retVal.addElement(name);
269         }
270         set.close();
271       }
272       log.addText(RESULTS, "Success");
273     } catch (SQLException e) {
274       log.addText(ERROR, "Error occured: " + e);
275       StringWriter writer = new StringWriter();
276       e.printStackTrace(new PrintWriter(writer));
277       log.addText(ERROR, writer.toString());
278     }
279     return retVal;
280   }
281   public boolean connect(Bookmark b) {
282     LogProxy log = LogProxy.getInstance();
283     log.addText(QUERY, "Connecting to: " + b.getName());
284     URL urls[] = new URL[1];
285     try {
286       String driverFile = b.getDriverFile();
287       URLClassLoader loader = (URLClassLoader) classLoaderCache.get(driverFile);
288       if (loader == null) {
289         urls[0] = new File(driverFile).toURL();
290         loader = new URLClassLoader(urls);
291         classLoaderCache.put(driverFile, loader);
292         if (DEBUG) {
293           System.out.println("Creating new classloader");
294         }
295       } else {
296         if (DEBUG) {
297           System.out.println("Using classloader in cache");
298         }
299       }
300       Class driverClass = loader.loadClass(b.getDriver());
301       Driver driver = (Driver) driverClass.newInstance();
302       Properties props = new Properties();
303       props.put(USERNAME, b.getUsername());
304       props.put(PASSWORD, b.getPassword());
305       con = driver.connect(b.getConnect(), props);
306       if (con == null) {
307         throw new Exception(
308           "Error: Driver returned a null connection: " + b.toString());
309       }
310       current = b;
311       log.addText(RESULTS, "Connected to: " + b.getName());
312       if (DEBUG) {
313         System.out.println("Connected");
314       }
315       return true;
316     } catch (Exception e) {
317       log.addText(
318         ERROR,
319         "Error Connecting to: " + b.getName() + ":" + e.toString());
320       StringWriter writer = new StringWriter();
321       e.printStackTrace(new PrintWriter(writer));
322       log.addText(ERROR, writer.toString());
323     }
324     return false;
325   }
326   public SQLResults execute(String s) {
327     return execute(s, -1, -1);
328   }
329   public SQLResults execute(String s, int startRow, int endRow) {
330     return execute(s, -1, -1, Integer.MAX_VALUE);
331   }
332   public SQLResults execute(
333     String s,
334     int startRow,
335     int endRow,
336     int maxLength) {
337     return execute(s, startRow, endRow, maxLength, "");
338   }
339   public SQLResults execute(
340     String s,
341     int startRow,
342     int endRow,
343     int maxLength,
344     String encoding) {
345     SQLResults results = new SQLResults();
346
347     if (DEBUG) {
348       System.out.println("Executing");
349     }
350     LogProxy log = LogProxy.getInstance();
351     log.addText(QUERY, "Executing Request [" + s + "]");
352     boolean metadata = false;
353     if (s.startsWith("METADATA")) {
354       metadata = true;
355     }
356     if (metadata) {
357       results.setQuery(s);
358       String table = s.substring(s.indexOf(':') + 1);
359       String schema = current.getSchema();
360       String query = "SELECT * FROM " + schema + "." + table;
361       if (schema.equals("")) {
362         query = "SELECT * FROM " + table;
363       }
364       s = query;
365       log.addText(QUERY, "Metadata Request [" + s + "]");
366     } else {
367       results.setQuery(s);
368     }
369     try {
370       Statement stmt = con.createStatement();
371       boolean flag = stmt.execute(s);
372       results.setResultSet(flag);
373       if (!flag) {
374         int updates = stmt.getUpdateCount();
375         results.setUpdateCount(updates);
376         log.addText(RESULTS, "Success: " + updates + " records updated");
377
378       } else {
379         if (metadata) {
380           ResultSet set = stmt.getResultSet();
381           ResultSetMetaData metaData = set.getMetaData();
382           int columnCount = metaData.getColumnCount();
383           Vector columnNames = new Vector();
384           columnNames.addElement("ColumnName");
385           columnNames.addElement("Type");
386           columnNames.addElement("Size");
387           columnNames.addElement("Nullable");
388           columnNames.addElement("AutoIncrement");
389           results.setColumnNames(columnNames);
390           for (int i = 1; i <= columnCount; i++) {
391             Vector row = new Vector();
392             row.addElement(metaData.getColumnName(i));
393             row.addElement(metaData.getColumnTypeName(i));
394             int textSize = metaData.getColumnDisplaySize(i);
395             int precision = metaData.getPrecision(i);
396             int scale = metaData.getScale(i);
397             if (scale == 0 && precision == 0) {
398               row.addElement(Integer.toString(precision));
399             } else {
400               row.addElement(textSize + ", " + precision + ", " + scale);
401             }
402             int nullable = metaData.isNullable(i);
403             if (nullable == metaData.columnNoNulls) {
404               row.addElement("Not Null");
405             } else if (nullable == metaData.columnNullable) {
406               row.addElement("Nullable");
407             } else if (nullable == metaData.columnNullableUnknown) {
408               row.addElement("Nullable");
409             } else {
410               row.addElement("<Error>");
411             }
412             row.addElement(new Boolean(metaData.isAutoIncrement(i)).toString());
413             results.addRow(row);
414           }
415           results.setHasMore(false);
416         } else {
417           ResultSet set = stmt.getResultSet();
418           ResultSetMetaData metaData = set.getMetaData();
419           int columnCount = metaData.getColumnCount();
420           Vector columnNames = new Vector();
421           for (int i = 1; i <= columnCount; i++) {
422             columnNames.addElement(metaData.getColumnName(i));
423           }
424           results.setColumnNames(columnNames);
425           Vector columnTypes = new Vector();
426           for (int i = 1; i <= columnCount; i++) {
427             columnTypes.addElement(metaData.getColumnTypeName(i));
428           }
429           results.setColumnsTypes(columnTypes);
430           int columnSizes[] = new int[columnCount];
431           for (int i = 1; i <= columnCount; i++) {
432             columnSizes[i - 1] = metaData.getColumnDisplaySize(i);
433           }
434           int rowCount = 1;
435           boolean exitEarly = false;
436           while (set.next()) {
437             boolean disable = startRow < 1 || endRow < 1;
438             boolean start = rowCount >= startRow;
439             boolean end = rowCount <= endRow;
440             if (disable || (start && end)) {
441               Vector row = new Vector();
442               for (int i = 1; i <= columnCount; i++) {
443                 String value;
444                 if (columnSizes[i - 1] < STREAM
445                   && columnSizes[i - 1] < maxLength) {
446                   if (encoding.equals("")) {
447                     value = set.getString(i);
448                   } else {
449                     value = new String(set.getBytes(i), encoding);
450                   }
451                 } else {
452                   try {
453                     if (encoding.equals("")) {
454                       Reader reader = set.getCharacterStream(i);
455                       StringBuffer buffer = new StringBuffer();
456                       if (reader != null) {
457                         int retVal = reader.read();
458                         int count = 0;
459                         while (retVal >= 0) {
460                           buffer.append((char) retVal);
461                           retVal = reader.read();
462                           count++;
463                           if (count > maxLength) {
464                             buffer.append("...>>>");
465                             break;
466                           }
467                         }
468                         reader.close();
469                       }
470                       value = buffer.toString();
471                     } else {
472                       InputStream binaryStream = set.getBinaryStream(i);
473                       ByteArrayOutputStream baos = new ByteArrayOutputStream();
474                       if (binaryStream != null) {
475                         int retVal = binaryStream.read();
476                         int count = 0;
477                         while (retVal >= 0) {
478                           baos.write(retVal);
479                           retVal = binaryStream.read();
480                           count++;
481                           if (count > maxLength) {
482                             break;
483                           }
484                         }
485                         binaryStream.close();
486                       }
487                       value = new String(baos.toByteArray(), encoding);
488                     }
489                   } catch (Throwable e) {
490                     // hack for mysql which doesn't implement
491                     // character streams
492                     value = set.getString(i);
493                   }
494                 }
495                 if (set.wasNull()) {
496                   row.addElement("<NULL>");
497                 } else {
498                   row.addElement(value);
499                 }
500               }
501               results.addRow(row);
502             }
503             rowCount++;
504             if (!disable && (rowCount > endRow)) {
505               exitEarly = true;
506               break;
507             }
508           }
509           if (exitEarly) {
510             results.setHasMore(set.next());
511           } else {
512             results.setMaxSize(rowCount);
513             results.setHasMore(false);
514           }
515         }
516         log.addText(RESULTS, "Success: result set displayed");
517       }
518       stmt.close();
519       if (DEBUG) {
520         System.out.println("Executed");
521         System.out.println();
522       }
523     } catch (Exception e) {
524       results.setIsError(true);
525       log.addText(ERROR, "Error occured: " + e);
526       StringWriter writer = new StringWriter();
527       e.printStackTrace(new PrintWriter(writer));
528       log.addText(ERROR, writer.toString());
529     }
530     return results;
531   }
532 }