1 5 package org.h2.result; 6 7 import java.sql.ResultSet ; 8 import java.sql.ResultSetMetaData ; 9 import java.sql.SQLException ; 10 11 import org.h2.engine.Database; 12 import org.h2.engine.Session; 13 import org.h2.expression.Expression; 14 import org.h2.expression.ExpressionColumn; 15 import org.h2.message.Message; 16 import org.h2.table.Column; 17 import org.h2.util.ObjectArray; 18 import org.h2.util.ValueHashMap; 19 import org.h2.value.DataType; 20 import org.h2.value.Value; 21 import org.h2.value.ValueArray; 22 23 25 public class LocalResult implements ResultInterface { 26 27 private int maxMemoryRows; 28 private Session session; 29 private int visibleColumnCount; 30 private Expression[] expressions; 31 private int rowId, rowCount; 32 private ObjectArray rows; 33 private SortOrder sort; 34 private ValueHashMap distinctRows; 35 private Value[] currentRow; 36 private int[] displaySizes; 37 private int offset, limit; 38 private ResultDiskBuffer disk; 39 private int diskOffset; 40 private boolean isUpdateCount; 41 private int updateCount; 42 43 public static LocalResult read(Session session, ResultSet rs) throws SQLException { 44 ResultSetMetaData meta = rs.getMetaData(); 45 int columnCount = meta.getColumnCount(); 46 ObjectArray cols = new ObjectArray(); 47 int[] types = new int[columnCount]; 48 Database db = session == null ? null : session.getDatabase(); 49 for (int i = 0; i < columnCount; i++) { 50 String name = meta.getColumnLabel(i + 1); 51 int type = DataType.convertSQLTypeToValueType(meta.getColumnType(i + 1)); 52 types[i] = type; 53 int precision = meta.getPrecision(i + 1); 54 int scale = meta.getScale(i + 1); 55 Column col = new Column(name, type, precision, scale); 56 Expression expr = new ExpressionColumn(db, null, col); 57 cols.add(expr); 58 } 59 LocalResult result = new LocalResult(session, cols, columnCount); 60 while (rs.next()) { 61 Value[] list = new Value[columnCount]; 62 for (int j = 0; j < columnCount; j++) { 63 list[j] = DataType.readValue(session, rs, j + 1, types[j]); 64 } 65 result.addRow(list); 66 } 67 result.done(); 68 return result; 69 } 70 71 public LocalResult(int updateCount) { 72 this.isUpdateCount = true; 73 this.updateCount = updateCount; 74 } 75 76 public LocalResult createShallowCopy(Session session) { 77 LocalResult copy = new LocalResult(0); 78 copy.maxMemoryRows = this.maxMemoryRows; 79 copy.session = session; 80 copy.visibleColumnCount = this.visibleColumnCount; 81 copy.expressions = this.expressions; 82 copy.rowId = -1; 83 copy.rowCount = this.rowCount; 84 copy.rows = this.rows; 85 copy.sort = this.sort; 86 copy.distinctRows = this.distinctRows; 87 copy.currentRow = null; 88 copy.displaySizes = this.displaySizes; 89 copy.offset = 0; 90 copy.limit = 0; 91 copy.disk = this.disk; 92 copy.diskOffset = this.diskOffset; 93 copy.isUpdateCount = this.isUpdateCount; 94 copy.updateCount = this.updateCount; 95 return copy; 96 } 97 98 public boolean isUpdateCount() { 99 return isUpdateCount; 100 } 101 102 public int getUpdateCount() { 103 return updateCount; 104 } 105 106 public LocalResult(Session session, ObjectArray cols, int visibleColumnCount) { 107 this.session = session; 108 if(session == null) { 109 this.maxMemoryRows = Integer.MAX_VALUE; 110 } else { 111 this.maxMemoryRows = session.getDatabase().getMaxMemoryRows(); 112 } 113 this.expressions = new Expression[cols.size()]; 114 cols.toArray(expressions); 115 this.displaySizes = new int[cols.size()]; 116 rows = new ObjectArray(); 117 this.visibleColumnCount = visibleColumnCount; 118 rowId = -1; 119 } 120 121 public void setSortOrder(SortOrder sort) { 122 this.sort = sort; 123 } 124 125 public void setDistinct() { 126 distinctRows = new ValueHashMap(session.getDatabase()); 129 } 130 131 public void removeDistinct(Value[] values) throws SQLException { 132 if(distinctRows == null) { 133 throw Message.getInternalError(); 134 } 135 ValueArray array = ValueArray.get(values); 136 distinctRows.remove(array); 137 rowCount = distinctRows.size(); 138 } 139 140 public boolean containsDistinct(Value[] values) throws SQLException { 141 if(distinctRows == null) { 142 throw Message.getInternalError(); 143 } 144 ValueArray array = ValueArray.get(values); 145 return distinctRows.get(array) != null; 146 } 147 148 public void reset() throws SQLException { 149 rowId = -1; 150 if (disk != null) { 151 disk.reset(); 152 if(diskOffset > 0) { 153 for(int i=0; i<diskOffset; i++) { 154 disk.next(); 155 } 156 } 157 } 158 } 159 160 public Value[] currentRow() { 161 return currentRow; 162 } 163 164 public boolean next() throws SQLException { 165 if (rowId < rowCount) { 166 rowId++; 167 if (rowId < rowCount) { 168 if (disk != null) { 169 currentRow = disk.next(); 170 } else { 171 currentRow = (Value[]) rows.get(rowId); 172 } 173 return true; 174 } 175 currentRow = null; 176 } 177 return false; 178 } 179 180 public int getRowId() { 181 return rowId; 182 } 183 184 public void addRow(Value[] values) throws SQLException { 185 for(int i=0; i<values.length; i++) { 186 Value v = values[i]; 188 int size = v.getDisplaySize(); 189 displaySizes[i] = Math.max(displaySizes[i], size); 190 } 191 if (distinctRows != null) { 192 ValueArray array = ValueArray.get(values); 193 distinctRows.put(array, values); 194 rowCount = distinctRows.size(); 195 return; 196 } 197 rows.add(values); 198 rowCount++; 199 if (rows.size() > maxMemoryRows && session.getDatabase().isPersistent()) { 200 if (disk == null) { 201 disk = new ResultDiskBuffer(session, sort, values.length); 202 } 203 addRowsToDisk(); 204 } 205 } 206 207 private void addRowsToDisk() throws SQLException { 208 disk.addRows(rows); 209 rows.clear(); 210 } 211 212 public int getVisibleColumnCount() { 213 return visibleColumnCount; 214 } 215 216 public void done() throws SQLException { 217 if (distinctRows != null) { 218 rows = distinctRows.values(); 219 distinctRows = null; 220 } 221 if (disk != null) { 222 addRowsToDisk(); 223 disk.done(); 224 } else { 225 if (sort != null) { 226 sort.sort(rows); 227 } 228 } 229 applyOffset(); 230 applyLimit(); 231 reset(); 232 } 233 234 public int getRowCount() { 235 return rowCount; 236 } 237 238 public void setLimit(int limit) { 239 this.limit = limit; 240 } 241 242 private void applyLimit() { 243 if(limit <=0 ) { 244 return; 245 } 246 if(disk == null) { 247 if(rows.size() > limit) { 248 rows.removeRange(limit, rows.size()); 249 rowCount = limit; 250 } 251 } else { 252 if(limit < rowCount) { 253 rowCount = limit; 254 } 255 } 256 } 257 258 public void close() { 259 if (disk != null) { 260 disk.close(); 261 disk = null; 262 } 263 } 264 265 public String getAlias(int i) { 266 return expressions[i].getAlias(); 267 } 268 269 public String getTableName(int i) { 270 return expressions[i].getTableName(); 271 } 272 273 public String getSchemaName(int i) { 274 return expressions[i].getSchemaName(); 275 } 276 277 public int getDisplaySize(int i) { 278 return displaySizes[i]; 279 } 280 281 public String getColumnName(int i) { 282 return expressions[i].getColumnName(); 283 } 284 285 public int getColumnType(int i) { 286 return expressions[i].getType(); 287 } 288 289 public long getColumnPrecision(int i) { 290 return expressions[i].getPrecision(); 291 } 292 293 public int getNullable(int i) { 294 return expressions[i].getNullable(); 295 } 296 297 public boolean isAutoIncrement(int i) { 298 return expressions[i].isAutoIncrement(); 299 } 300 301 public int getColumnScale(int i) { 302 return expressions[i].getScale(); 303 } 304 305 public void setOffset(int offset) { 306 this.offset = offset; 307 } 308 309 private void applyOffset() { 310 if(offset <=0) { 311 return; 312 } 313 if(disk == null) { 314 if(offset >= rows.size()) { 315 rows.clear(); 316 rowCount = 0; 317 } else { 318 int remove = Math.min(offset, rows.size()); 320 rows.removeRange(0, remove); 321 rowCount -= remove; 322 } 323 } else { 324 if(offset >= rowCount) { 325 rowCount = 0; 326 } else { 327 diskOffset = offset; 328 rowCount -= offset; 329 } 330 } 331 } 332 333 } 334 | Popular Tags |