1 19 20 package org.netbeans.modules.db.sql.execute; 21 22 import java.io.IOException ; 23 import java.io.InputStream ; 24 import java.io.Reader ; 25 import java.math.BigDecimal ; 26 import java.sql.Blob ; 27 import java.sql.Clob ; 28 import java.sql.ResultSet ; 29 import java.sql.ResultSetMetaData ; 30 import java.sql.SQLException ; 31 import java.sql.Time ; 32 import java.sql.Timestamp ; 33 import java.sql.Types ; 34 import java.util.ArrayList ; 35 import java.util.Date ; 36 import java.util.HashMap ; 37 import java.util.List ; 38 import java.util.Map ; 39 40 45 public class ResultSetTableModelSupport { 46 47 51 static final Map <Integer ,ColumnTypeDef> TYPE_TO_DEF = new HashMap <Integer ,ColumnTypeDef>(); 52 53 57 private static ColumnTypeDef DEFAULT_COLUMN_DEF; 58 59 static { 60 62 ColumnTypeDef booleanTypeDef = new GenericWritableColumnDef(Boolean .class); 63 64 TYPE_TO_DEF.put(Integer.valueOf(Types.BOOLEAN), booleanTypeDef); 65 TYPE_TO_DEF.put(Integer.valueOf(Types.BIT), booleanTypeDef); 66 67 ColumnTypeDef integerTypeDef = new GenericWritableColumnDef(Integer .class); 68 69 TYPE_TO_DEF.put(Integer.valueOf(Types.TINYINT), integerTypeDef); 70 TYPE_TO_DEF.put(Integer.valueOf(Types.SMALLINT), integerTypeDef); 71 TYPE_TO_DEF.put(Integer.valueOf(Types.INTEGER), integerTypeDef); 72 73 ColumnTypeDef charTypeDef = new GenericWritableColumnDef(String .class); 74 75 TYPE_TO_DEF.put(Integer.valueOf(Types.CHAR), charTypeDef); 76 TYPE_TO_DEF.put(Integer.valueOf(Types.VARCHAR), charTypeDef); 77 78 ColumnTypeDef longTypeDef = new GenericWritableColumnDef(Long .class); 79 80 TYPE_TO_DEF.put(Integer.valueOf(Types.BIGINT), longTypeDef); 81 82 ColumnTypeDef floatTypeDef = new GenericWritableColumnDef(Double .class); 83 84 TYPE_TO_DEF.put(Integer.valueOf(Types.FLOAT), floatTypeDef); 85 TYPE_TO_DEF.put(Integer.valueOf(Types.DOUBLE), floatTypeDef); 86 87 ColumnTypeDef decimalTypeDef = new GenericWritableColumnDef(BigDecimal .class); 88 89 TYPE_TO_DEF.put(Integer.valueOf(Types.REAL), decimalTypeDef); 90 TYPE_TO_DEF.put(Integer.valueOf(Types.NUMERIC), decimalTypeDef); 91 TYPE_TO_DEF.put(Integer.valueOf(Types.DECIMAL), decimalTypeDef); 92 93 ColumnTypeDef dateTypeDef = new GenericWritableColumnDef(Date .class); 94 95 TYPE_TO_DEF.put(Integer.valueOf(Types.DATE), dateTypeDef); 96 97 99 ColumnTypeDef timeTypeDef = new ColumnTypeDef() { 100 public boolean isWritable() { 101 return true; 102 } 103 public Class getColumnClass() { 104 return Time .class; 105 } 106 public Object getColumnValue(ResultSet rs, int column) throws SQLException , IOException { 107 return rs.getTime(column); 108 } 109 }; 110 111 TYPE_TO_DEF.put(Integer.valueOf(Types.TIME), timeTypeDef); 112 113 116 TYPE_TO_DEF.put(Integer.valueOf(Types.TIMESTAMP), new ColumnTypeDef() { 117 public boolean isWritable() { 118 return true; 119 } 120 public Class getColumnClass() { 121 return Timestamp .class; 122 } 123 public Object getColumnValue(ResultSet rs, int column) throws SQLException , IOException { 124 return rs.getTimestamp(column); 125 } 126 }); 127 128 131 ColumnTypeDef binaryTypeDef = new ColumnTypeDef() { 132 public boolean isWritable() { 133 return false; 134 } 135 public Class getColumnClass() { 136 return Object .class; 137 } 138 public Object getColumnValue(ResultSet rs, int column) throws SQLException , IOException { 139 return BinaryColumnValue.forBinaryColumn(rs, column); 140 } 141 }; 142 143 TYPE_TO_DEF.put(Integer.valueOf(Types.BINARY), binaryTypeDef); 144 TYPE_TO_DEF.put(Integer.valueOf(Types.VARBINARY), binaryTypeDef); 145 TYPE_TO_DEF.put(Integer.valueOf(Types.LONGVARBINARY), binaryTypeDef); 146 147 150 ColumnTypeDef blobTypeDef = new ColumnTypeDef() { 151 public boolean isWritable() { 152 return false; 153 } 154 public Class getColumnClass() { 155 return Object .class; 156 } 157 public Object getColumnValue(ResultSet rs, int column) throws SQLException , IOException { 158 return BinaryColumnValue.forBlobColumn(rs, column); 159 } 160 }; 161 162 TYPE_TO_DEF.put(Integer.valueOf(Types.BLOB), blobTypeDef); 163 164 167 ColumnTypeDef longVarCharTypeDef = new ColumnTypeDef() { 168 public boolean isWritable() { 169 return false; 170 } 171 public Class getColumnClass() { 172 return Object .class; 173 } 174 public Object getColumnValue(ResultSet rs, int column) throws SQLException , IOException { 175 return LongVarCharColumnValue.forCharColumn(rs, column); 176 } 177 }; 178 179 TYPE_TO_DEF.put(Integer.valueOf(Types.LONGVARCHAR), longVarCharTypeDef); 180 181 184 ColumnTypeDef clobTypeDef = new ColumnTypeDef() { 185 public boolean isWritable() { 186 return false; 187 } 188 public Class getColumnClass() { 189 return Object .class; 190 } 191 public Object getColumnValue(ResultSet rs, int column) throws SQLException , IOException { 192 return LongVarCharColumnValue.forClobColumn(rs, column); 193 } 194 }; 195 196 TYPE_TO_DEF.put(Integer.valueOf(Types.CLOB), clobTypeDef); 197 198 200 ColumnTypeDef otherTypeDef = new ColumnTypeDef() { 201 public boolean isWritable() { 202 return false; 203 } 204 public Class getColumnClass() { 205 return Object .class; 206 } 207 public Object getColumnValue(ResultSet rs, int column) throws SQLException { 208 return rs.getObject(column); 209 } 210 }; 211 212 TYPE_TO_DEF.put(Integer.valueOf(Types.NULL), otherTypeDef); 213 TYPE_TO_DEF.put(Integer.valueOf(Types.OTHER), otherTypeDef); 214 TYPE_TO_DEF.put(Integer.valueOf(Types.JAVA_OBJECT), otherTypeDef); 215 TYPE_TO_DEF.put(Integer.valueOf(Types.DISTINCT), otherTypeDef); 216 TYPE_TO_DEF.put(Integer.valueOf(Types.STRUCT), otherTypeDef); 217 TYPE_TO_DEF.put(Integer.valueOf(Types.ARRAY), otherTypeDef); 218 TYPE_TO_DEF.put(Integer.valueOf(Types.REF), otherTypeDef); 219 TYPE_TO_DEF.put(Integer.valueOf(Types.DATALINK), otherTypeDef); 220 } 221 222 225 private interface ColumnTypeDef { 226 227 230 public boolean isWritable(); 231 232 235 public Class getColumnClass(); 236 237 240 public Object getColumnValue(ResultSet rs, int column) throws SQLException , IOException ; 241 } 242 243 246 private static final class GenericWritableColumnDef implements ColumnTypeDef { 247 248 private Class columnClass; 249 250 public GenericWritableColumnDef(Class columnClass) { 251 this.columnClass = columnClass; 252 } 253 254 public boolean isWritable() { 255 return true; 256 } 257 258 public Class getColumnClass() { 259 return columnClass; 260 } 261 262 public Object getColumnValue(ResultSet rs, int column) throws SQLException , IOException { 263 return rs.getObject(column); 264 } 265 } 266 267 271 private static final class DefaultColumnDef implements ColumnTypeDef { 272 273 public boolean isWritable() { 274 return false; 275 } 276 277 public Class getColumnClass() { 278 return Object .class; 279 } 280 281 public Object getColumnValue(ResultSet rs, int column) throws SQLException , IOException { 282 return rs.getObject(column); 283 } 284 } 285 286 290 private static final class LongVarCharColumnValue { 291 292 private static final int COUNT = 100; 293 294 private String data; 295 296 public static LongVarCharColumnValue forCharColumn(ResultSet rs, int column) throws SQLException , IOException { 297 Reader reader = rs.getCharacterStream(column); 298 if (reader == null) { 299 return null; 300 } 301 try { 302 return new LongVarCharColumnValue(reader); 303 } finally { 304 reader.close(); 305 } 306 } 307 308 public static LongVarCharColumnValue forClobColumn(ResultSet rs, int column) throws SQLException , IOException { 309 Clob clob = rs.getClob(column); 310 if (clob == null) { 311 return null; 312 } 313 Reader reader = clob.getCharacterStream(); 314 if (reader == null) { 315 return null; 316 } 317 try { 318 return new LongVarCharColumnValue(reader); 319 } finally { 320 reader.close(); 321 } 322 } 323 324 private LongVarCharColumnValue(Reader reader) throws SQLException , IOException { 325 char[] charData = new char[COUNT]; 326 int read = reader.read(charData, 0, charData.length); 327 328 if (read >= 0) { 329 data = new String (charData, 0, read); 330 331 if (reader.read() != -1) { 333 data += "..."; } 335 } else { 336 data = ""; } 338 } 339 340 public String toString() { 341 return data; 342 } 343 } 344 345 349 private static final class BinaryColumnValue { 350 351 private static final int COUNT = 100; 352 353 private String data; 354 355 public static BinaryColumnValue forBinaryColumn(ResultSet rs, int column) throws SQLException , IOException { 356 InputStream input = rs.getBinaryStream(column); 357 if (input == null) { 358 return null; 359 } 360 try { 361 return new BinaryColumnValue(input); 362 } finally { 363 input.close(); 364 } 365 } 366 367 public static BinaryColumnValue forBlobColumn(ResultSet rs, int column) throws SQLException , IOException { 368 Blob blob = rs.getBlob(column); 369 if (blob == null) { 370 return null; 371 } 372 InputStream input = blob.getBinaryStream(); 373 if (input == null) { 374 return null; 375 } 376 try { 377 return new BinaryColumnValue(input); 378 } finally { 379 input.close(); 380 } 381 } 382 383 private BinaryColumnValue(InputStream input) throws SQLException , IOException { 384 byte[] byteData = new byte[COUNT]; 385 int read = input.read(byteData, 0, byteData.length); 386 387 if (read > 0) { 388 StringBuffer buffer = new StringBuffer (2 + 2 * read); 389 390 buffer.append("0x"); for (int i = 0; i < read; i++) { 392 int b = byteData[i]; 393 if (b < 0) { 394 b += 256; 395 } 396 if (b < 16) { 397 buffer.append('0'); 398 } 399 buffer.append(Integer.toHexString(b).toUpperCase()); 400 } 401 402 if (input.read() != -1) { 404 buffer.append("..."); } 406 407 data = buffer.toString(); 408 } else { 409 data = ""; } 411 } 412 413 public String toString() { 414 return data; 415 } 416 } 417 418 421 static ColumnTypeDef getColumnTypeDef(int type) { 422 ColumnTypeDef result = (ColumnTypeDef)TYPE_TO_DEF.get(Integer.valueOf(type)); 423 if (result != null) { 424 return result; 425 } 426 427 synchronized (ResultSetTableModelSupport.class) { 428 if (DEFAULT_COLUMN_DEF == null) { 429 DEFAULT_COLUMN_DEF = new DefaultColumnDef(); 430 } 431 return DEFAULT_COLUMN_DEF; 432 } 433 } 434 435 439 public static List <ColumnDef> createColumnDefs(ResultSetMetaData rsmd) throws SQLException { 440 int count = rsmd.getColumnCount(); 441 List <ColumnDef> columns = new ArrayList <ColumnDef>(count); 442 443 for (int i = 1; i <= count; i++) { 444 if (Thread.currentThread().isInterrupted()) { 445 return null; 446 } 447 448 int type = rsmd.getColumnType(i); 449 ColumnTypeDef ctd = getColumnTypeDef(type); 450 451 453 boolean writable = false; 455 try { 456 writable = rsmd.isWritable(i) && ctd.isWritable(); 457 } catch (SQLException e) { 458 } 460 461 ColumnDef column = new ColumnDef( 462 rsmd.getColumnName(i), 463 writable, 464 ctd.getColumnClass()); 465 466 columns.add(column); 467 } 468 return columns; 469 } 470 471 public static List <List <Object >> retrieveRows(ResultSet rs, ResultSetMetaData rsmd, FetchLimitHandler handler) throws SQLException , IOException { 472 List <List <Object >> rows = new ArrayList <List <Object >>(); 473 int columnCount = rsmd.getColumnCount(); 474 int fetchLimit = handler.getFetchLimit(); 475 476 while (rs.next()) { 477 if (Thread.currentThread().isInterrupted()) { 478 return null; 479 } 480 481 int fetchCount = rows.size(); 482 if (fetchLimit > 0 && fetchCount >= fetchLimit) { 483 fetchLimit = handler.fetchLimitReached(fetchCount); 484 if (fetchLimit != 0 && fetchLimit <= fetchCount) { 485 break; 486 } 487 } 488 489 List <Object > row = new ArrayList <Object >(); 490 for (int i = 1; i <= columnCount; i++) { 491 if (Thread.currentThread().isInterrupted()) { 492 return null; 493 } 494 495 int type = rsmd.getColumnType(i); 496 ColumnTypeDef ctd = getColumnTypeDef(type); 497 Object value = ctd.getColumnValue(rs, i); 498 row.add(value != null ? value : NullValue.getDefault()); 499 } 500 rows.add(row); 501 } 502 return rows; 503 } 504 } 505 | Popular Tags |