1 5 package org.h2.store; 6 7 import java.math.BigDecimal ; 8 import java.sql.Date ; 9 import java.sql.SQLException ; 10 import java.sql.Time ; 11 import java.sql.Timestamp ; 12 13 import org.h2.engine.Constants; 14 import org.h2.message.Message; 15 import org.h2.util.MathUtils; 16 import org.h2.value.Value; 17 import org.h2.value.ValueArray; 18 import org.h2.value.ValueBoolean; 19 import org.h2.value.ValueByte; 20 import org.h2.value.ValueBytes; 21 import org.h2.value.ValueDate; 22 import org.h2.value.ValueDecimal; 23 import org.h2.value.ValueDouble; 24 import org.h2.value.ValueFloat; 25 import org.h2.value.ValueInt; 26 import org.h2.value.ValueJavaObject; 27 import org.h2.value.ValueLob; 28 import org.h2.value.ValueLong; 29 import org.h2.value.ValueNull; 30 import org.h2.value.ValueShort; 31 import org.h2.value.ValueString; 32 import org.h2.value.ValueStringIgnoreCase; 33 import org.h2.value.ValueTime; 34 import org.h2.value.ValueTimestamp; 35 import org.h2.value.ValueUuid; 36 37 40 public abstract class DataPage { 41 42 static final boolean CHECKSUM = true; 43 protected DataHandler handler; 44 protected byte[] data; 45 protected int pos; 46 47 public static DataPage create(DataHandler handler, int capacity) { 48 if(handler.getTextStorage()) { 49 return new DataPageText(handler, new byte[capacity]); 50 } else { 51 return new DataPageBinary(handler, new byte[capacity]); 52 } 53 } 54 55 public static DataPage create(DataHandler handler, byte[] buff) { 56 if(handler.getTextStorage()) { 57 return new DataPageText(handler, buff); 58 } else { 59 return new DataPageBinary(handler, buff); 60 } 61 } 62 63 protected DataPage(DataHandler handler, int capacity) { 64 this(handler, new byte[capacity]); 65 } 66 67 protected DataPage(DataHandler handler, byte[] data) { 68 this.handler = handler; 69 this.data = data; 70 } 71 72 public void checkCapacity(int plus) { 73 if (pos + plus >= data.length) { 74 byte[] d = new byte[(data.length+plus) * 2]; 75 System.arraycopy(data, 0, d, 0, data.length); 77 data = d; 78 } 79 } 80 81 public abstract void updateChecksum(); 82 public abstract void check(int len) throws SQLException ; 83 public abstract int getFillerLength(); 84 public abstract void setInt(int pos, int x); 85 86 public int length() { 87 return pos; 88 } 89 90 public byte[] getBytes() { 91 return data; 92 } 93 94 public void reset() { 95 pos = 0; 96 } 97 98 public void writeDataPageNoSize(DataPage page) { 99 checkCapacity(page.pos); 100 int len = page.pos - getFillerLength(); 102 System.arraycopy(page.data, 0, data, pos, len); 103 pos += len; 104 } 105 106 public DataPage readDataPageNoSize() { 107 int len = data.length - pos; 108 DataPage page = DataPage.create(handler, len); 109 System.arraycopy(data, pos, page.data, 0, len); 110 page.pos = len; 111 return page; 112 } 113 114 public void write(byte[] buff, int off, int len) { 115 checkCapacity(len); 116 System.arraycopy(buff, 0, data, pos, len); 117 pos += len; 118 } 119 120 public void read(byte[] buff, int off, int len) { 121 System.arraycopy(data, pos, buff, off, len); 122 pos += len; 123 } 124 125 public void writeByte(byte x) { 126 data[pos++] = x; 127 } 128 129 public int readByte() { 130 return data[pos++]; 131 } 132 133 public abstract void writeInt(int x); 134 public abstract int readInt(); 135 public abstract int getIntLen(); 136 public abstract int getLongLen(long x); 137 public abstract int getStringLen(String s); 138 public abstract String readString(); 139 public abstract void writeString(String s); 140 141 public long readLong() { 142 return ((long)(readInt()) << 32) + (readInt() & 0xffffffffL); 143 } 144 145 public void writeLong(long x) { 146 writeInt((int)(x >>> 32)); 147 writeInt((int)x); 148 } 149 150 public void writeValue(Value v) throws SQLException { 151 if(Constants.CHECK) { 152 checkCapacity(8); 153 } 154 if (v == ValueNull.INSTANCE) { 156 data[pos++] = '-'; 157 return; 158 } 159 int start = pos; 160 data[pos++] = (byte)(v.getType() + 'a'); 161 switch (v.getType()) { 162 case Value.BOOLEAN: 163 case Value.BYTE: 164 case Value.SHORT: 165 case Value.INT: 166 writeInt(v.getInt()); 167 break; 168 case Value.LONG: 169 writeLong(v.getLong()); 170 break; 171 case Value.DECIMAL: 172 String s = v.getString(); 173 writeString(s); 174 break; 175 case Value.TIME: 176 writeLong(v.getTimeNoCopy().getTime()); 177 break; 178 case Value.DATE: 179 writeLong(v.getDateNoCopy().getTime()); 180 break; 181 case Value.TIMESTAMP: { 182 Timestamp ts = v.getTimestampNoCopy(); 183 writeLong(ts.getTime()); 184 writeInt(ts.getNanos()); 185 break; 186 } 187 case Value.JAVA_OBJECT: 188 case Value.BYTES: { 189 byte[] b = v.getBytesNoCopy(); 190 writeInt(b.length); 191 write(b, 0, b.length); 192 break; 193 } 194 case Value.UUID: { 195 ValueUuid uuid = (ValueUuid)v; 196 writeLong(uuid.getHigh()); 197 writeLong(uuid.getLow()); 198 break; 199 } 200 case Value.STRING: 201 case Value.STRING_IGNORECASE: 202 writeString(v.getString()); 203 break; 204 case Value.DOUBLE: 205 writeLong(Double.doubleToLongBits(v.getDouble())); 206 break; 207 case Value.FLOAT: 208 writeInt(Float.floatToIntBits(v.getFloat())); 209 break; 210 case Value.BLOB: 211 case Value.CLOB: { 212 ValueLob lob = (ValueLob)v; 213 lob.convertToFileIfRequired(handler); 214 byte[] small = lob.getSmall(); 215 if(small == null) { 216 writeInt(-2); 218 writeInt(lob.getTableId()); 219 writeInt(lob.getObjectId()); 220 writeLong(lob.getPrecision()); 221 writeByte((byte)(lob.useCompression() ? 1 : 0)); } else { 223 writeInt(small.length); 224 write(small, 0, small.length); 225 } 226 break; 227 } 228 case Value.ARRAY: { 229 Value[] list = ((ValueArray)v).getList(); 230 writeInt(list.length); 231 for(int i=0; i<list.length; i++) { 232 writeValue(list[i]); 233 } 234 break; 235 } 236 default: 237 throw Message.getInternalError("type=" + v.getType()); 238 } 239 if(Constants.CHECK2) { 240 if(pos - start != getValueLen(v)) { 241 throw Message.getInternalError("value size error: got " + (pos-start) + " expected " + getValueLen(v)); 242 } 243 } 244 } 245 246 public int getValueLen(Value v) throws SQLException { 247 if (v == ValueNull.INSTANCE) { 248 return 1; 249 } 250 switch (v.getType()) { 251 case Value.BOOLEAN: 252 case Value.BYTE: 253 case Value.SHORT: 254 case Value.INT: 255 return 1 + getIntLen(); 256 case Value.LONG: 257 return 1 + getLongLen(v.getLong()); 258 case Value.DOUBLE: 259 return 1 + getLongLen(Double.doubleToLongBits(v.getDouble())); 260 case Value.FLOAT: 261 return 1 + getIntLen(); 262 case Value.STRING: 263 case Value.STRING_IGNORECASE: 264 case Value.DECIMAL: 265 return 1 + getStringLen(v.getString()); 266 case Value.JAVA_OBJECT: 267 case Value.BYTES: { 268 int len = v.getBytesNoCopy().length; 269 return 1 + getIntLen() + len; 270 } 271 case Value.UUID: { 272 ValueUuid uuid = (ValueUuid) v; 273 return 1 + getLongLen(uuid.getHigh()) + getLongLen(uuid.getLow()); 274 } 275 case Value.TIME: 276 return 1 + getLongLen(v.getTimeNoCopy().getTime()); 277 case Value.DATE: 278 return 1 + getLongLen(v.getDateNoCopy().getTime()); 279 case Value.TIMESTAMP: { 280 Timestamp ts = v.getTimestampNoCopy(); 281 return 1 + getLongLen(ts.getTime()) + getIntLen(); 282 } 283 case Value.BLOB: 284 case Value.CLOB:{ 285 int len = 1; 286 ValueLob lob = (ValueLob)v; 287 lob.convertToFileIfRequired(handler); 288 byte[] small = lob.getSmall(); 289 if(small != null) { 290 len += getIntLen() + small.length; 291 } else { 292 len += getIntLen() + getIntLen() + getIntLen() + getLongLen(lob.getPrecision()) + 1; 293 } 294 return len; 295 } 296 case Value.ARRAY: { 297 Value[] list = ((ValueArray)v).getList(); 298 int len = 1 + getIntLen(); 299 for(int i=0; i<list.length; i++) { 300 len += getValueLen(list[i]); 301 } 302 return len; 303 } 304 default: 305 throw Message.getInternalError("type=" + v.getType()); 306 } 307 } 308 309 public Value readValue() throws SQLException { 310 int type = data[pos++]; 311 if(type == '-') { 312 return ValueNull.INSTANCE; 313 } 314 type = (type - 'a'); 315 switch (type) { 316 case Value.BOOLEAN: 317 return ValueBoolean.get(readInt() == 1); 318 case Value.BYTE: 319 return ValueByte.get((byte)readInt()); 320 case Value.SHORT: 321 return ValueShort.get((short)readInt()); 322 case Value.INT: 323 return ValueInt.get(readInt()); 324 case Value.LONG: 325 return ValueLong.get(readLong()); 326 case Value.DECIMAL: 327 return ValueDecimal.get(new BigDecimal (readString())); 328 case Value.DATE: 329 return ValueDate.getNoCopy(new Date (readLong())); 330 case Value.TIME: 331 return ValueTime.get(new Time (readLong())); 333 case Value.TIMESTAMP: { 334 Timestamp ts = new Timestamp (readLong()); 335 ts.setNanos(readInt()); 336 return ValueTimestamp.getNoCopy(ts); 337 } 338 case Value.JAVA_OBJECT: { 339 int len = readInt(); 340 byte[] b = new byte[len]; 341 read(b, 0, len); 342 return ValueJavaObject.getNoCopy(b); 343 } 344 case Value.BYTES: { 345 int len = readInt(); 346 byte[] b = new byte[len]; 347 read(b, 0, len); 348 return ValueBytes.getNoCopy(b); 349 } 350 case Value.UUID: 351 return ValueUuid.get(readLong(), readLong()); 352 case Value.STRING: 353 return ValueString.get(readString()); 354 case Value.STRING_IGNORECASE: 355 return ValueStringIgnoreCase.get(readString()); 356 case Value.DOUBLE: 357 return ValueDouble.get(Double.longBitsToDouble(readLong())); 358 case Value.FLOAT: 359 return ValueFloat.get(Float.intBitsToFloat(readInt())); 360 case Value.BLOB: 361 case Value.CLOB: { 362 int smallLen = readInt(); 363 if(smallLen >= 0) { 364 byte[] small = new byte[smallLen]; 365 read(small, 0, smallLen); 366 return ValueLob.createSmallLob(type, small); 367 } else { 368 int tableId = readInt(); 369 int objectId = readInt(); 370 long precision = 0; 371 boolean compression = false; 372 if(smallLen == -2) { 374 precision = readLong(); 375 compression = readByte() == 1; 376 } 377 return ValueLob.open(type, handler, tableId, objectId, precision, compression); 378 } 379 } 380 case Value.ARRAY: { 381 int len = readInt(); 382 Value[] list = new Value[len]; 383 for(int i=0; i<len; i++) { 384 list[i] = readValue(); 385 } 386 return ValueArray.get(list); 387 } 388 default: 389 throw Message.getInternalError("type=" + type); 390 } 391 } 392 393 public abstract void fill(int len); 394 395 public void fillAligned() { 396 fill(MathUtils.roundUp(pos+2, Constants.FILE_BLOCK_SIZE)); 399 } 400 401 public void setPos(int pos) { 402 this.pos = pos; 403 } 404 405 } 406 | Popular Tags |