source: src/main/java/weka/gui/sql/ResultSetHelper.java @ 25

Last change on this file since 25 was 4, checked in by gnappo, 14 years ago

Import di weka.

File size: 10.7 KB
Line 
1/*
2 *    This program is free software; you can redistribute it and/or modify
3 *    it under the terms of the GNU General Public License as published by
4 *    the Free Software Foundation; either version 2 of the License, or
5 *    (at your option) any later version.
6 *
7 *    This program is distributed in the hope that it will be useful,
8 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 *    GNU General Public License for more details.
11 *
12 *    You should have received a copy of the GNU General Public License
13 *    along with this program; if not, write to the Free Software
14 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17/*
18 * ResultSetHelper.java
19 * Copyright (C) 2005 University of Waikato, Hamilton, New Zealand
20 *
21 */
22
23
24package weka.gui.sql;
25
26import java.sql.ResultSet;
27import java.sql.ResultSetMetaData;
28import java.sql.Types;
29import java.util.Vector;
30
31/**
32 * Represents an extended JTable, containing a table model based on a ResultSet
33 * and the corresponding query.
34 *
35 * @author      FracPete (fracpete at waikato dot ac dot nz)
36 * @version     $Revision: 5324 $
37 */
38public class ResultSetHelper {
39 
40  /** the resultset to work on. */
41  protected ResultSet m_ResultSet;
42
43  /** whether we initialized. */
44  protected boolean m_Initialized = false;
45
46  /** the maximum number of rows to retrieve. */
47  protected int m_MaxRows = 0;
48
49  /** the number of columns. */
50  protected int m_ColumnCount = 0;
51
52  /** the number of rows. */
53  protected int m_RowCount = 0;
54
55  /** the column names. */
56  protected String[] m_ColumnNames = null;
57
58  /** whether a column is numeric. */
59  protected boolean[] m_NumericColumns = null;
60
61  /** the class for each column. */
62  protected Class[] m_ColumnClasses = null;
63
64  /**
65   * initializes the helper, with unlimited number of rows.
66   *
67   * @param rs        the resultset to work on
68   */
69  public ResultSetHelper(ResultSet rs) {
70    this(rs, 0);
71  }
72
73  /**
74   * initializes the helper, with the given maximum number of rows (less than
75   * 1 means unlimited).
76   *
77   * @param rs        the resultset to work on
78   * @param max       the maximum number of rows to retrieve
79   */
80  public ResultSetHelper(ResultSet rs, int max) {
81    super();
82
83    m_ResultSet = rs;
84    m_MaxRows   = max;
85  }
86
87  /**
88   * initializes, i.e. reads the data, etc.
89   */
90  protected void initialize() {
91    ResultSetMetaData     meta;
92    int                   i;
93   
94    if (m_Initialized)
95      return;
96   
97    try {
98      meta = m_ResultSet.getMetaData();
99
100      // columns names
101      m_ColumnNames = new String[meta.getColumnCount()];
102      for (i = 1; i <= meta.getColumnCount(); i++)
103        m_ColumnNames[i - 1] = meta.getColumnName(i);
104     
105      // numeric columns
106      m_NumericColumns = new boolean[meta.getColumnCount()];
107      for (i = 1; i <= meta.getColumnCount(); i++)
108        m_NumericColumns[i - 1] = typeIsNumeric(meta.getColumnType(i));
109
110      // column classes
111      m_ColumnClasses = new Class[meta.getColumnCount()];
112      for (i = 1; i <= meta.getColumnCount(); i++) {
113        try {
114          m_ColumnClasses[i - 1] = typeToClass(meta.getColumnType(i));
115        }
116        catch (Exception ex) {
117          m_ColumnClasses[i - 1] = String.class;
118        }
119      }
120
121      // dimensions
122      m_ColumnCount = meta.getColumnCount();
123
124      // if the JDBC driver doesn't support scrolling we can't determine
125      // the row count here
126      if (m_ResultSet.getType() == ResultSet.TYPE_FORWARD_ONLY) {
127        m_RowCount = -1;
128      }
129      else {
130        m_RowCount = 0;
131        m_ResultSet.first();
132        if (m_MaxRows > 0) {
133          try {
134            m_ResultSet.absolute(m_MaxRows);
135            m_RowCount = m_ResultSet.getRow();
136          }
137          catch (Exception ex) {
138            // ignore it
139          }
140        }
141        else {
142          m_ResultSet.last();
143          m_RowCount = m_ResultSet.getRow();
144        }
145
146        // sometimes, e.g. with a "desc <table>", we can't use absolute(int)
147        // and getRow()???
148        try {
149          if ( (m_RowCount == 0) && (m_ResultSet.first()) ) {
150            m_RowCount = 1;
151            while (m_ResultSet.next()) {
152              m_RowCount++;
153              if (m_ResultSet.getRow() == m_MaxRows)
154                break;
155            };
156          }
157        }
158        catch (Exception e) {
159          // ignore it
160        }
161      }
162
163      m_Initialized = true;
164    }
165    catch (Exception ex) {
166      // ignore it
167    }
168  }
169
170  /**
171   * the underlying resultset.
172   *
173   * @return            the resultset
174   */
175  public ResultSet getResultSet() {
176    return m_ResultSet;
177  }
178
179  /**
180   * returns the number of columns in the resultset.
181   *
182   * @return            the number of columns
183   */
184  public int getColumnCount() {
185    initialize();
186
187    return m_ColumnCount;
188  }
189
190  /**
191   * returns the number of rows in the resultset. If -1 then the number of
192   * rows couldn't be determined, i.e., the cursors aren't scrollable.
193   *
194   * @return            the number of rows, -1 if it wasn't possible to
195   *                    determine
196   */
197  public int getRowCount() {
198    initialize();
199
200    return m_RowCount;
201  }
202
203  /**
204   * returns an array with the names of the columns in the resultset.
205   *
206   * @return            the column names
207   */
208  public String[] getColumnNames() {
209    initialize();
210
211    return m_ColumnNames;
212  }
213
214  /**
215   * returns an array that indicates whether a column is numeric or nor.
216   *
217   * @return            the numeric columns
218   */
219  public boolean[] getNumericColumns() {
220    initialize();
221
222    return m_NumericColumns;
223  }
224
225  /**
226   * returns the classes for the columns.
227   *
228   * @return            the column classes
229   */
230  public Class[] getColumnClasses() {
231    initialize();
232
233    return m_ColumnClasses;
234  }
235
236  /**
237   * whether a limit on the rows to retrieve was set.
238   *
239   * @return            true if there's a limit
240   */
241  public boolean hasMaxRows() {
242    return (m_MaxRows > 0);
243  }
244
245  /**
246   * the maximum number of rows to retrieve, less than 1 means unlimited.
247   *
248   * @return            the maximum number of rows
249   */
250  public int getMaxRows() {
251    return m_MaxRows;
252  }
253
254  /**
255   * returns an 2-dimensional array with the content of the resultset, the first
256   * dimension is the row, the second the column (i.e., getCells()[y][x]).
257   * Note: the data is not cached! It is always retrieved anew.
258   *
259   * @return            the data
260   */
261  public Object[][] getCells() {
262    int                 i;
263    int                 n;
264    Vector<Object[]>    result;
265    Object[]            row;
266    int                 rowCount;
267    boolean             proceed;
268   
269    initialize();
270
271    result = new Vector<Object[]>();
272
273    try {
274     
275      // do know the number of rows?
276      rowCount = getRowCount();
277      if (rowCount == -1) {
278        rowCount = getMaxRows();
279        proceed  = m_ResultSet.next();
280      }
281      else {
282        proceed = m_ResultSet.first();
283      }
284     
285      if (proceed) {
286        i = 0;
287        while (true) {
288          row = new Object[getColumnCount()];
289          result.add(row);
290
291          for (n = 0; n < getColumnCount(); n++) {
292            try {
293              // to get around byte arrays when using getObject(int)
294              if (getColumnClasses()[n] == String.class)
295                row[n] = m_ResultSet.getString(n + 1);
296              else
297                row[n] = m_ResultSet.getObject(n + 1);
298            }
299            catch (Exception e) {
300              row[n] = null;
301            }
302          }
303
304          // get next row, if possible
305          if (i == rowCount - 1) {
306            break;
307          }
308          else {
309            // no more rows -> exit
310            if (!m_ResultSet.next())
311              break;
312          }
313
314          i++;
315        }
316      }
317    }
318    catch (Exception e) {
319      e.printStackTrace();
320    }
321
322    return result.toArray(new Object[result.size()][getColumnCount()]);
323  }
324
325  /**
326   * Returns the class associated with a SQL type.
327   *
328   * @param type the SQL type
329   * @return the Java class corresponding with the type
330   */
331  public static Class typeToClass(int type) {
332    Class     result;
333   
334    switch (type) {
335      case Types.BIGINT :
336        result = Long.class;
337        break;
338      case Types.BINARY:
339        result = String.class;
340      case Types.BIT:
341        result = Boolean.class;
342        break;
343      case Types.CHAR:
344        result = Character.class;
345        break;
346      case Types.DATE:
347        result = java.sql.Date.class;
348        break;
349      case Types.DECIMAL:
350        result = Double.class;
351        break;
352      case Types.DOUBLE:
353        result = Double.class;
354        break;
355      case Types.FLOAT:
356        result = Float.class;
357        break;
358      case Types.INTEGER:
359        result = Integer.class;
360        break;
361      case Types.LONGVARBINARY:
362        result = String.class;
363        break;
364      case Types.LONGVARCHAR:
365        result = String.class;
366        break;
367      case Types.NULL:
368        result = String.class;
369        break;
370      case Types.NUMERIC:
371        result = Double.class;
372        break;
373      case Types.OTHER:
374        result = String.class;
375        break;
376      case Types.REAL:
377        result = Double.class;
378        break;
379      case Types.SMALLINT:
380        result = Short.class;
381        break;
382      case Types.TIME:
383        result = java.sql.Time.class;
384        break;
385      case Types.TIMESTAMP:
386        result = java.sql.Timestamp.class;
387        break;
388      case Types.TINYINT:
389        result = Short.class;
390        break;
391      case Types.VARBINARY:
392        result = String.class;
393        break;
394      case Types.VARCHAR:
395        result = String.class;
396        break;
397      default:
398        result = null;
399    }
400
401    return result;
402  }
403
404  /**
405   * returns whether the SQL type is numeric (and therefore the justification
406   * should be right).
407   *
408   * @param type      the SQL type
409   * @return          whether the given type is numeric
410   */
411  public static boolean typeIsNumeric(int type) {
412    boolean     result;
413   
414    switch (type) {
415      case Types.BIGINT :
416        result = true;
417        break;
418      case Types.BINARY:
419        result = false;
420      case Types.BIT:
421        result = false;
422        break;
423      case Types.CHAR:
424        result = false;
425        break;
426      case Types.DATE:
427        result = false;
428        break;
429      case Types.DECIMAL:
430        result = true;
431        break;
432      case Types.DOUBLE:
433        result = true;
434        break;
435      case Types.FLOAT:
436        result = true;
437        break;
438      case Types.INTEGER:
439        result = true;
440        break;
441      case Types.LONGVARBINARY:
442        result = false;
443        break;
444      case Types.LONGVARCHAR:
445        result = false;
446        break;
447      case Types.NULL:
448        result = false;
449        break;
450      case Types.NUMERIC:
451        result = true;
452        break;
453      case Types.OTHER:
454        result = false;
455        break;
456      case Types.REAL:
457        result = true;
458        break;
459      case Types.SMALLINT:
460        result = true;
461        break;
462      case Types.TIME:
463        result = false;
464        break;
465      case Types.TIMESTAMP:
466        result = true;
467        break;
468      case Types.TINYINT:
469        result = true;
470        break;
471      case Types.VARBINARY:
472        result = false;
473        break;
474      case Types.VARCHAR:
475        result = false;
476        break;
477      default:
478        result = false;
479    }
480
481    return result;
482  }
483}
Note: See TracBrowser for help on using the repository browser.