1 5 package org.h2.table; 6 7 import java.sql.Connection ; 8 import java.sql.DatabaseMetaData ; 9 import java.sql.DriverManager ; 10 import java.sql.PreparedStatement ; 11 import java.sql.ResultSet ; 12 import java.sql.ResultSetMetaData ; 13 import java.sql.SQLException ; 14 import java.sql.Statement ; 15 import java.util.HashMap ; 16 17 import org.h2.engine.Session; 18 import org.h2.index.Index; 19 import org.h2.index.IndexType; 20 import org.h2.index.LinkedIndex; 21 import org.h2.message.Message; 22 import org.h2.result.Row; 23 import org.h2.schema.Schema; 24 import org.h2.util.JdbcUtils; 25 import org.h2.util.ObjectArray; 26 import org.h2.util.StringUtils; 27 import org.h2.value.DataType; 28 29 32 33 public class TableLink extends Table { 34 35 private String driver, url, user, password, originalTable; 36 private Connection conn; 37 private HashMap prepared = new HashMap (); 38 private ObjectArray indexes = new ObjectArray(); 39 40 public TableLink(Schema schema, int id, String name, String driver, String url, 41 String user, String password, String originalTable) throws SQLException { 42 super(schema, id, name, false); 43 this.driver = driver; 44 this.url = url; 45 this.user = user; 46 this.password = password; 47 this.originalTable = originalTable; 48 try { 49 database.loadClass(driver); 50 } catch(ClassNotFoundException e) { 51 throw Message.getSQLException(Message.CLASS_NOT_FOUND_1, new String []{driver}, e); 52 } 53 conn = DriverManager.getConnection(url, user, password); 54 DatabaseMetaData meta = conn.getMetaData(); 55 boolean storesLowerCase = meta.storesLowerCaseIdentifiers(); 56 ResultSet rs = meta.getColumns(null, null, originalTable, null); 57 int i=0; 58 ObjectArray columnList = new ObjectArray(); 59 HashMap columnMap = new HashMap (); 60 while(rs.next()) { 61 String n = rs.getString("COLUMN_NAME"); 62 if(storesLowerCase && n.equals(StringUtils.toLowerEnglish(n))) { 63 n = StringUtils.toUpperEnglish(n); 64 } 65 int sqlType = rs.getInt("DATA_TYPE"); 66 long precision = rs.getInt("COLUMN_SIZE"); 67 int scale = rs.getInt("DECIMAL_DIGITS"); 68 int type = DataType.convertSQLTypeToValueType(sqlType); 69 precision = Math.max(precision, DataType.getDataType(type).defaultPrecision); 70 Column col = new Column(n, type, precision, scale); 71 col.setTable(this, i++); 72 columnList.add(col); 73 columnMap.put(n, col); 74 } 75 if(columnList.size()==0) { 76 Statement stat = null; 77 try { 78 stat = conn.createStatement(); 79 rs = stat.executeQuery("SELECT * FROM " + originalTable + " T WHERE 1=0"); 80 ResultSetMetaData rsm = rs.getMetaData(); 81 for(i=0; i<rsm.getColumnCount();) { 82 String n = rsm.getColumnName(i+1); 83 if(storesLowerCase && n.equals(StringUtils.toLowerEnglish(n))) { 84 n = StringUtils.toUpperEnglish(n); 85 } 86 int sqlType = rsm.getColumnType(i+1); 87 long precision = rsm.getPrecision(i+1); 88 int scale = rsm.getScale(i+1); 89 int type = DataType.convertSQLTypeToValueType(sqlType); 90 precision = Math.max(precision, DataType.getDataType(type).defaultPrecision); 91 Column col = new Column(n, type, precision, scale); 92 col.setTable(this, i++); 93 columnList.add(col); 94 columnMap.put(n, col); 95 } 96 } catch(SQLException e) { 97 throw Message.getSQLException(Message.TABLE_OR_VIEW_NOT_FOUND_1, new String []{originalTable}, e); 98 } finally { 99 JdbcUtils.closeSilently(stat); 100 } 101 } 102 Column[] cols = new Column[columnList.size()]; 103 columnList.toArray(cols); 104 setColumns(cols); 105 Index index = new LinkedIndex(this, id, cols, IndexType.createNonUnique(false)); 106 indexes.add(index); 107 rs = meta.getPrimaryKeys(null, null, originalTable); 108 String pkName = ""; 109 ObjectArray list; 110 if (rs.next()) { 111 list = new ObjectArray(); 113 do { 114 int idx = rs.getInt("KEY_SEQ"); 115 if(pkName == null) { 116 pkName = rs.getString("PK_NAME"); 117 } 118 while (list.size() < idx) { 119 list.add(null); 120 } 121 String col = rs.getString("COLUMN_NAME"); 122 Column column = (Column) columnMap.get(col); 123 list.set(idx - 1, column); 124 } while (rs.next()); 125 addIndex(list, IndexType.createPrimaryKey(false, false)); 126 } 127 try { 128 rs = meta.getIndexInfo(null, null, originalTable, false, false); 129 } catch(SQLException e) { 130 rs = null; 132 } 133 String indexName = null; 134 list = new ObjectArray(); 135 IndexType indexType = null; 136 while (rs != null && rs.next()) { 137 String newIndex = rs.getString("INDEX_NAME"); 138 if (pkName.equals(newIndex)) { 139 continue; 140 } 141 if (indexName != null && !indexName.equals(newIndex)) { 142 addIndex(list, indexType); 143 indexName = null; 144 } 145 if (indexName == null) { 146 indexName = newIndex; 147 list.clear(); 148 } 149 boolean unique = !rs.getBoolean("NON_UNIQUE"); 150 indexType = unique ? IndexType.createUnique(false, false): IndexType.createNonUnique(false); 151 String col = rs.getString("COLUMN_NAME"); 152 Column column = (Column) columnMap.get(col); 153 list.add(column); 154 } 155 if (indexName != null) { 156 addIndex(list, indexType); 157 } 158 } 159 160 private void addIndex(ObjectArray list, IndexType indexType) { 161 Column[] cols = new Column[list.size()]; 162 list.toArray(cols); 163 Index index = new LinkedIndex(this, 0, cols, indexType); 164 indexes.add(index); 165 } 166 167 public String getCreateSQL() { 168 StringBuffer buff = new StringBuffer (); 169 buff.append("CREATE LINKED TABLE "); 170 buff.append(getSQL()); 171 if(comment != null) { 172 buff.append(" COMMENT "); 173 buff.append(StringUtils.quoteStringSQL(comment)); 174 } 175 buff.append("("); 176 buff.append(StringUtils.quoteStringSQL(driver)); 177 buff.append(", "); 178 buff.append(StringUtils.quoteStringSQL(url)); 179 buff.append(", "); 180 buff.append(StringUtils.quoteStringSQL(user)); 181 buff.append(", "); 182 buff.append(StringUtils.quoteStringSQL(password)); 183 buff.append(", "); 184 buff.append(StringUtils.quoteStringSQL(originalTable)); 185 buff.append(")"); 186 return buff.toString(); 187 } 188 189 public Index addIndex(Session session, String indexName, int indexId, Column[] cols, IndexType indexType, int headPos, String comment) throws SQLException { 190 throw Message.getUnsupportedException(); 191 } 192 193 public void lock(Session session, boolean exclusive) throws SQLException { 194 } 196 197 public boolean isLockedExclusively() { 198 return false; 199 } 200 201 public Index getScanIndex(Session session) { 202 return (Index) indexes.get(0); 203 } 204 205 public void removeRow(Session session, Row row) throws SQLException { 206 getScanIndex(session).remove(session, row); 207 } 208 209 public void addRow(Session session, Row row) throws SQLException { 210 getScanIndex(session).add(session, row); 211 } 212 213 public void close(Session session) throws SQLException { 214 if(conn != null) { 215 try { 216 conn.close(); 217 } finally { 218 conn = null; 219 } 220 } 221 } 222 223 public int getRowCount() throws SQLException { 224 PreparedStatement prep = getPreparedStatement("SELECT COUNT(*) FROM "+originalTable); 225 ResultSet rs = prep.executeQuery(); 226 rs.next(); 227 int count = rs.getInt(1); 228 rs.close(); 229 return count; 230 } 231 232 public String getOriginalTable() { 233 return originalTable; 234 } 235 236 public PreparedStatement getPreparedStatement(String sql) throws SQLException { 237 PreparedStatement prep = (PreparedStatement ) prepared.get(sql); 238 if(prep==null) { 239 prep = conn.prepareStatement(sql); 240 prepared.put(sql, prep); 241 } 242 return prep; 243 } 244 245 public void unlock(Session s) { 246 } 248 249 public void checkRename() throws SQLException { 250 } 251 252 public void checkSupportAlter() throws SQLException { 253 throw Message.getUnsupportedException(); 254 } 255 256 public void truncate(Session session) throws SQLException { 257 throw Message.getUnsupportedException(); 258 } 259 260 public boolean canGetRowCount() { 261 return true; 262 } 263 264 public boolean canDrop() { 265 return true; 266 } 267 268 public String getTableType() { 269 return Table.TABLE_LINK; 270 } 271 272 public void removeChildrenAndResources(Session session) throws SQLException { 273 super.removeChildrenAndResources(session); 274 close(session); 275 driver = null; 276 url = user = password = originalTable = null; 277 conn = null; 278 prepared = null; 279 invalidate(); 280 } 281 282 public ObjectArray getIndexes() { 283 return indexes; 284 } 285 286 public long getMaxDataModificationId() { 287 return Long.MAX_VALUE; 289 } 290 291 public Index getUniqueIndex() { 292 for(int i=0; i<indexes.size(); i++) { 293 Index idx = (Index) indexes.get(i); 294 if(idx.getIndexType().isUnique()) { 295 return idx; 296 } 297 } 298 return null; 299 } 300 301 } 302 | Popular Tags |