001: package jimm.datavision.source.sql;
002:
003: import jimm.datavision.source.Table;
004: import jimm.datavision.source.Column;
005: import java.util.HashMap;
006: import java.util.Iterator;
007: import java.sql.*;
008:
009: /**
010: * Represents a database table.
011: *
012: * @author Jim Menard, <a href="mailto:jimm@io.com">jimm@io.com</a>
013: */
014: public class SQLTable extends Table {
015:
016: protected DatabaseMetaData dbmd;
017: protected HashMap colCacheMap;
018:
019: /**
020: * Constructor.
021: *
022: * @param database the database in which this table resides
023: * @param name the table's name
024: * @param dbmd database metadata information
025: */
026: public SQLTable(Database database, String name,
027: DatabaseMetaData dbmd) {
028: super (database, name);
029: this .dbmd = dbmd;
030: }
031:
032: public Column findColumn(Object colIdObj) {
033: if (dbmd != null)
034: loadColumns();
035:
036: String colId = colIdObj.toString();
037:
038: // First try a simple exact match using colCacheMap. This will often
039: // fail the first time, but after we have found a column using the quite
040: // convoluted search below we store the column in colCacheMap.
041: Column col = (Column) colCacheMap.get(colId);
042: if (col != null)
043: return col;
044:
045: boolean caseSensitive = dataSource.getReport()
046: .caseSensitiveDatabaseNames();
047:
048: String schemaName = null;
049: int pos = colId.indexOf('.');
050: if (pos >= 0) {
051: schemaName = colId.substring(0, pos);
052: colId = colId.substring(pos + 1);
053: }
054:
055: if (!caseSensitive) {
056: if (schemaName != null)
057: schemaName = schemaName.toLowerCase();
058: colId = colId.toLowerCase();
059: }
060:
061: // First try with table's schema name, if any.
062: if (schemaName != null) {
063: String target = schemaName + '.' + colId;
064: for (Iterator iter = columns.keySet().iterator(); iter
065: .hasNext();) {
066: String key = (String) iter.next();
067: if (caseSensitive) {
068: if (key.equals(target)) {
069: col = (Column) columns.get(key);
070: colCacheMap.put(colId, col); // Store in cache
071: return col;
072: }
073: } else {
074: if (key.toLowerCase().equals(target.toLowerCase())) {
075: col = (Column) columns.get(key);
076: colCacheMap.put(colId, col); // Store in cache
077: return col;
078: }
079: }
080: }
081: }
082:
083: // Now try with database's schema name if it's different from the
084: // table's schema name.
085: if (name != null && !name.equals(schemaName)) {
086: String target = name + '.' + colId;
087: for (Iterator iter = columns.keySet().iterator(); iter
088: .hasNext();) {
089: String key = (String) iter.next();
090: if (caseSensitive) {
091: if (key.equals(target)) {
092: col = (Column) columns.get(key);
093: colCacheMap.put(colId, col); // Store in cache
094: return col;
095: }
096: } else {
097: if (key.toLowerCase().equals(target.toLowerCase())) {
098: col = (Column) columns.get(key);
099: colCacheMap.put(colId, col); // Store in cache
100: return col;
101: }
102: }
103: }
104: }
105:
106: // Finally, try with no schema name.
107: String target = colId;
108: for (Iterator iter = columns.keySet().iterator(); iter
109: .hasNext();) {
110: String key = (String) iter.next();
111: if (caseSensitive) {
112: if (key.equals(target))
113: return (Column) columns.get(key);
114: } else {
115: if (key.toLowerCase().equals(target.toLowerCase()))
116: return (Column) columns.get(key);
117: }
118: }
119:
120: return null;
121: }
122:
123: public Iterator columns() {
124: if (dbmd != null)
125: loadColumns();
126: return super .columns();
127: }
128:
129: protected void loadColumns() {
130: colCacheMap = new HashMap();
131:
132: String schemaName = null;
133: String tableName = name;
134: int pos = name.indexOf('.');
135: if (pos >= 0) {
136: schemaName = name.substring(0, pos);
137: tableName = name.substring(pos + 1);
138: }
139:
140: loadColumnsUsing(((Database) dataSource).getName(), tableName);
141: if (schemaName != null && columns.isEmpty())
142: loadColumnsUsing(schemaName, tableName);
143: if (columns.isEmpty())
144: loadColumnsUsing(null, tableName);
145:
146: dbmd = null;
147: }
148:
149: protected void loadColumnsUsing(String schemaName, String tableName) {
150: ResultSet rset = null;
151: try {
152: // The last two args should be able to be null, but some users have
153: // reported that their drivers barf unless I use the "%" wildcard.
154: // (That's ancient history; I'm not sure if it is still true.
155: // However, rough timing indicates that there's not much of a
156: // performance difference in either case.)
157: rset = dbmd.getColumns(null, schemaName, tableName, "%");
158:
159: while (rset.next()) {
160: SQLColumn col = new SQLColumn(this , rset.getString(
161: "COLUMN_NAME").trim(), rset.getInt("DATA_TYPE"));
162: addColumn(col);
163: }
164: } catch (SQLException e) {
165: } finally {
166: try {
167: if (rset != null)
168: rset.close();
169: } catch (SQLException e2) {
170: }
171: }
172: }
173:
174: }
|