1 5 package org.h2.value; 6 7 import java.io.ByteArrayInputStream ; 8 import java.io.InputStream ; 9 import java.io.Reader ; 10 import java.lang.ref.WeakReference ; 11 import java.math.BigDecimal ; 12 import java.sql.Date ; 13 import java.sql.PreparedStatement ; 14 import java.sql.SQLException ; 15 import java.sql.Time ; 16 import java.sql.Timestamp ; 17 import java.sql.Types ; 18 19 import org.h2.engine.Constants; 20 import org.h2.engine.Mode; 21 import org.h2.message.Message; 22 import org.h2.store.DataHandler; 23 import org.h2.tools.SimpleResultSet; 24 import org.h2.util.ByteUtils; 25 import org.h2.util.IOUtils; 26 import org.h2.util.MathUtils; 27 import org.h2.util.StringUtils; 28 29 32 public abstract class Value { 33 34 36 public static final int UNKNOWN = -1; 38 public static final int NULL = 0, BOOLEAN = 1, BYTE = 2, SHORT = 3, INT = 4, LONG = 5, DECIMAL = 6; 39 public static final int DOUBLE = 7, FLOAT = 8, TIME = 9, DATE = 10, TIMESTAMP = 11, BYTES = 12; 40 public static final int STRING = 13, STRING_IGNORECASE = 14, BLOB = 15, CLOB = 16; 41 public static final int ARRAY = 17, RESULT_SET = 18, JAVA_OBJECT = 19, UUID = 20; 42 43 public static final int TYPE_COUNT = UUID + 1; 44 45 private static WeakReference weakCache = new WeakReference (null); 46 51 private static final BigDecimal MAX_LONG_DECIMAL = new BigDecimal ("" + Long.MAX_VALUE); 52 53 private static final BigDecimal MIN_LONG_DECIMAL = new BigDecimal ("" + Long.MIN_VALUE); 54 55 static Value cache(Value v) { 56 if (Constants.OBJECT_CACHE) { 57 Value[] cache = (Value[]) weakCache.get(); 58 int hash = v.hashCode(); 59 if (cache == null) { 60 cache = new Value[Constants.OBJECT_CACHE_SIZE]; 61 weakCache = new WeakReference (cache); 62 } 63 int index = hash & (Constants.OBJECT_CACHE_SIZE - 1); 64 Value cached = cache[index]; 65 if (cached != null) { 66 if (cached.getType() == v.getType() && v.isEqual(cached)) { 67 return cached; 69 } 70 } 71 cache[index] = v; 75 } 76 return v; 77 } 78 79 public abstract String getSQL(); 80 public abstract int getType(); 81 public abstract long getPrecision(); 82 public abstract int getDisplaySize(); 83 public abstract String getString() throws SQLException ; 84 protected abstract int compareSecure(Value v, CompareMode mode) throws SQLException ; 86 protected abstract boolean isEqual(Value v); 87 public abstract Object getObject() throws SQLException ; 88 public abstract void set(PreparedStatement prep, int parameterIndex) throws SQLException ; 89 90 public Boolean getBoolean() throws SQLException { 91 return ((ValueBoolean) convertTo(Value.BOOLEAN)).getBoolean(); 92 } 93 94 public Date getDate() throws SQLException { 95 return ((ValueDate) convertTo(Value.DATE)).getDate(); 96 } 97 98 public Date getDateNoCopy() throws SQLException { 99 return ((ValueDate) convertTo(Value.DATE)).getDateNoCopy(); 100 } 101 102 public Time getTime() throws SQLException { 103 return ((ValueTime) convertTo(Value.TIME)).getTime(); 104 } 105 106 public Time getTimeNoCopy() throws SQLException { 107 return ((ValueTime) convertTo(Value.TIME)).getTimeNoCopy(); 108 } 109 110 public Timestamp getTimestamp() throws SQLException { 111 return ((ValueTimestamp) convertTo(Value.TIMESTAMP)).getTimestamp(); 112 } 113 114 public Timestamp getTimestampNoCopy() throws SQLException { 115 return ((ValueTimestamp) convertTo(Value.TIMESTAMP)).getTimestampNoCopy(); 116 } 117 118 public byte[] getBytes() throws SQLException { 119 return ((ValueBytes) convertTo(Value.BYTES)).getBytes(); 120 } 121 122 public byte[] getBytesNoCopy() throws SQLException { 123 return ((ValueBytes) convertTo(Value.BYTES)).getBytesNoCopy(); 124 } 125 126 public byte getByte() throws SQLException { 127 return ((ValueByte) convertTo(Value.BYTE)).getByte(); 128 } 129 130 public short getShort() throws SQLException { 131 return ((ValueShort) convertTo(Value.SHORT)).getShort(); 132 } 133 134 public BigDecimal getBigDecimal() throws SQLException { 135 return ((ValueDecimal) convertTo(Value.DECIMAL)).getBigDecimal(); 136 } 137 138 public double getDouble() throws SQLException { 139 return ((ValueDouble) convertTo(Value.DOUBLE)).getDouble(); 140 } 141 142 public float getFloat() throws SQLException { 143 return ((ValueFloat) convertTo(Value.FLOAT)).getFloat(); 144 } 145 146 public int getInt() throws SQLException { 147 return ((ValueInt) convertTo(Value.INT)).getInt(); 148 } 149 150 public long getLong() throws SQLException { 151 return ((ValueLong) convertTo(Value.LONG)).getLong(); 152 } 153 154 public InputStream getInputStream() throws SQLException { 155 return new ByteArrayInputStream (getBytesNoCopy()); 156 } 157 158 public Reader getReader() throws SQLException { 159 return IOUtils.getReader(getString()); 160 } 161 162 public Value add(Value v) throws SQLException { 163 throw Message.getUnsupportedException(); 164 } 165 166 public int getSignum() throws SQLException { 167 throw Message.getUnsupportedException(); 168 } 169 170 public Value negate() throws SQLException { 171 throw Message.getUnsupportedException(); 172 } 173 174 public Value subtract(Value v) throws SQLException { 175 throw Message.getUnsupportedException(); 176 } 177 178 public Value divide(Value v) throws SQLException { 179 throw Message.getUnsupportedException(); 180 } 181 182 public Value multiply(Value v) throws SQLException { 183 throw Message.getUnsupportedException(); 184 } 185 186 public static int getHigherOrder(int t1, int t2) throws SQLException { 187 if(t1 == t2) { 188 if(t1 == Value.UNKNOWN) { 189 throw Message.getSQLException(Message.UNKNOWN_DATA_TYPE_1, "?, ?"); 190 } 191 return t1; 192 } 193 int type = Math.max(t1, t2); 194 switch(type) { 195 case Value.STRING: 196 case Value.STRING_IGNORECASE: { 197 int b = Math.min(t1, t2); 198 switch(b) { 199 case Value.BLOB: 200 case Value.BYTES: 201 case Value.DATE: 202 case Value.JAVA_OBJECT: 203 case Value.TIME: 204 case Value.TIMESTAMP: 205 case Value.UUID: 206 return b; 207 } 208 } 209 } 210 return type; 211 } 212 213 public Value convertTo(int type) throws SQLException { 214 if (getType() == type) { 217 return this; 218 } 219 switch (type) { 221 case BOOLEAN: { 222 switch (getType()) { 223 case BYTE: 224 case SHORT: 225 case INT: 226 case LONG: 227 case DECIMAL: 228 case DOUBLE: 229 case FLOAT: 230 return ValueBoolean.get(getSignum() != 0); 231 case TIME: 232 case DATE: 233 case TIMESTAMP: 234 case BYTES: 235 case JAVA_OBJECT: 236 case UUID: 237 throw Message.getSQLException(Message.DATA_CONVERSION_ERROR_1, getString()); 238 } 239 break; 240 } 241 case BYTE: { 242 switch (getType()) { 243 case BOOLEAN: 244 return ValueByte.get(getBoolean().booleanValue() ? (byte)1 : (byte)0); 245 case SHORT: 246 return ValueByte.get(convertToByte(getShort())); 247 case INT: 248 return ValueByte.get(convertToByte(getInt())); 249 case LONG: 250 return ValueByte.get(convertToByte(getLong())); 251 case DECIMAL: 252 return ValueByte.get(convertToByte(convertToLong(getBigDecimal()))); 253 case DOUBLE: 254 return ValueByte.get(convertToByte(convertToLong(getDouble()))); 255 case FLOAT: 256 return ValueByte.get(convertToByte(convertToLong(getFloat()))); 257 } 258 break; 259 } 260 case SHORT: { 261 switch (getType()) { 262 case BOOLEAN: 263 return ValueShort.get(getBoolean().booleanValue() ? (short)1 : (short)0); 264 case BYTE: 265 return ValueShort.get(getByte()); 266 case INT: 267 return ValueShort.get(convertToShort(getInt())); 268 case LONG: 269 return ValueShort.get(convertToShort(getLong())); 270 case DECIMAL: 271 return ValueShort.get(convertToShort(convertToLong(getBigDecimal()))); 272 case DOUBLE: 273 return ValueShort.get(convertToShort(convertToLong(getDouble()))); 274 case FLOAT: 275 return ValueShort.get(convertToShort(convertToLong(getFloat()))); 276 } 277 break; 278 } 279 case INT: { 280 switch (getType()) { 281 case BOOLEAN: 282 return ValueInt.get(getBoolean().booleanValue() ? 1 : 0); 283 case BYTE: 284 return ValueInt.get(getByte()); 285 case SHORT: 286 return ValueInt.get(getShort()); 287 case LONG: 288 return ValueInt.get(convertToInt(getLong())); 289 case DECIMAL: 290 return ValueInt.get(convertToInt(convertToLong(getBigDecimal()))); 291 case DOUBLE: 292 return ValueInt.get(convertToInt(convertToLong(getDouble()))); 293 case FLOAT: 294 return ValueInt.get(convertToInt(convertToLong(getFloat()))); 295 } 296 break; 297 } 298 case LONG: { 299 switch (getType()) { 300 case BOOLEAN: 301 return ValueLong.get(getBoolean().booleanValue() ? 1 : 0); 302 case BYTE: 303 return ValueLong.get(getByte()); 304 case SHORT: 305 return ValueLong.get(getShort()); 306 case INT: 307 return ValueLong.get(getInt()); 308 case DECIMAL: 309 return ValueLong.get(convertToLong(getBigDecimal())); 310 case DOUBLE: 311 return ValueLong.get(convertToLong(getDouble())); 312 case FLOAT: 313 return ValueLong.get(convertToLong(getFloat())); 314 } 315 break; 316 } 317 case DECIMAL: { 318 switch (getType()) { 320 case BOOLEAN: 321 return ValueDecimal.get(new BigDecimal (getBoolean().booleanValue() ? "1" : "0")); 322 case BYTE: 323 return ValueDecimal.get(new BigDecimal ("" + getByte())); 324 case SHORT: 325 return ValueDecimal.get(new BigDecimal ("" + getShort())); 326 case INT: 327 return ValueDecimal.get(new BigDecimal ("" + getInt())); 328 case LONG: 329 return ValueDecimal.get(new BigDecimal ("" + getLong())); 330 case DOUBLE: { 331 double d = getDouble(); 332 if(Double.isInfinite(d) || Double.isNaN(d)) { 333 throw Message.getSQLException(Message.DATA_CONVERSION_ERROR_1, ""+d); 334 } 335 return ValueDecimal.get(new BigDecimal (d)); 336 } 337 case FLOAT: { 338 float f = getFloat(); 339 if(Float.isInfinite(f) || Float.isNaN(f)) { 340 throw Message.getSQLException(Message.DATA_CONVERSION_ERROR_1, ""+f); 341 } 342 return ValueDecimal.get(new BigDecimal (f)); 343 } 344 } 345 break; 346 } 347 case DOUBLE: { 348 switch (getType()) { 349 case BOOLEAN: 350 return ValueDouble.get(getBoolean().booleanValue() ? 1 : 0); 351 case BYTE: 352 return ValueDouble.get(getByte()); 353 case SHORT: 354 return ValueDouble.get(getShort()); 355 case INT: 356 return ValueDouble.get(getInt()); 357 case LONG: 358 return ValueDouble.get(getLong()); 359 case DECIMAL: 360 return ValueDouble.get(getBigDecimal().doubleValue()); 361 case FLOAT: 362 return ValueDouble.get(getFloat()); 363 } 364 break; 365 } 366 case FLOAT: { 367 switch (getType()) { 368 case BOOLEAN: 369 return ValueFloat.get(getBoolean().booleanValue() ? 1 : 0); 370 case BYTE: 371 return ValueFloat.get(getByte()); 372 case SHORT: 373 return ValueFloat.get(getShort()); 374 case INT: 375 return ValueFloat.get(getInt()); 376 case LONG: 377 return ValueFloat.get(getLong()); 378 case DECIMAL: 379 return ValueFloat.get(getBigDecimal().floatValue()); 380 case DOUBLE: 381 return ValueFloat.get((float)getDouble()); 382 } 383 break; 384 } 385 case DATE: { 386 switch (getType()) { 387 case TIME: 388 return ValueDate.get(new Date (getTimeNoCopy().getTime())); 389 case TIMESTAMP: 390 return ValueDate.get(new Date (getTimestampNoCopy().getTime())); 391 } 392 break; 393 } 394 case TIME: { 395 switch (getType()) { 396 case DATE: 397 return ValueTime.get(new Time (getDateNoCopy().getTime())); 399 case TIMESTAMP: 400 return ValueTime.get(new Time (getTimestampNoCopy().getTime())); 402 } 403 break; 404 } 405 case TIMESTAMP: { 406 switch (getType()) { 407 case TIME: 408 return ValueTimestamp.getNoCopy(new Timestamp (getTimeNoCopy().getTime())); 409 case DATE: 410 return ValueTimestamp.getNoCopy(new Timestamp (getDateNoCopy().getTime())); 411 } 412 break; 413 } 414 case BYTES: { 415 switch(getType()) { 416 case JAVA_OBJECT: 417 case BLOB: 418 case UUID: 419 return ValueBytes.getNoCopy(getBytesNoCopy()); 420 } 421 break; 422 } 423 case JAVA_OBJECT: { 424 switch(getType()) { 425 case BYTES: 426 case BLOB: 427 return ValueBytes.getNoCopy(getBytesNoCopy()); 428 } 429 break; 430 } 431 case BLOB: { 432 switch(getType()) { 433 case BYTES: 434 return ValueLob.createSmallLob(Value.BLOB, getBytesNoCopy()); 435 } 436 break; 437 } 438 case UUID: { 439 switch(getType()) { 440 case BYTES: 441 return ValueUuid.get(getBytesNoCopy()); 442 } 443 } 444 } 445 String s = getString(); 447 try { 448 switch (type) { 449 case NULL: 450 return ValueNull.INSTANCE; 451 case BOOLEAN: { 452 if (s.equalsIgnoreCase("true") || s.equalsIgnoreCase("t") || s.equalsIgnoreCase("yes") || s.equalsIgnoreCase("y")) { 453 return ValueBoolean.get(true); 454 } else if (s.equalsIgnoreCase("false") || s.equalsIgnoreCase("f") || s.equalsIgnoreCase("no") || s.equalsIgnoreCase("n")) { 455 return ValueBoolean.get(false); 456 } else { 457 return ValueBoolean.get(new BigDecimal (s).signum() != 0); 459 } 460 } 461 case BYTE: 462 return ValueByte.get(MathUtils.decodeByte(s.trim())); 463 case SHORT: 464 return ValueShort.get(MathUtils.decodeShort(s.trim())); 465 case INT: 466 return ValueInt.get(MathUtils.decodeInt(s.trim())); 467 case LONG: 468 return ValueLong.get(MathUtils.decodeLong(s.trim())); 469 case DECIMAL: 470 return ValueDecimal.get(new BigDecimal (s.trim())); 471 case TIME: 472 return ValueTime.get(ValueTime.parseTime(s.trim())); 473 case DATE: 474 return ValueDate.get(ValueDate.parseDate(s.trim())); 475 case TIMESTAMP: 476 return ValueTimestamp.get(ValueTimestamp.parseTimestamp(s.trim())); 477 case BYTES: 478 return ValueBytes.getNoCopy(ByteUtils.convertStringToBytes(s.trim())); 479 case JAVA_OBJECT: 480 return ValueJavaObject.getNoCopy(ByteUtils.convertStringToBytes(s.trim())); 481 case STRING: 482 return ValueString.get(s); 483 case STRING_IGNORECASE: 484 return ValueStringIgnoreCase.get(s); 485 case DOUBLE: 486 return ValueDouble.get(Double.parseDouble(s.trim())); 487 case FLOAT: 488 return ValueFloat.get(Float.parseFloat(s.trim())); 489 case CLOB: 490 return ValueLob.createSmallLob(CLOB, StringUtils.utf8Encode(s)); 491 case BLOB: 492 return ValueLob.createSmallLob(BLOB, ByteUtils.convertStringToBytes(s.trim())); 493 case ARRAY: 494 return ValueArray.get(new Value[]{ValueString.get(s)}); 495 case RESULT_SET: { 496 SimpleResultSet rs = new SimpleResultSet(); 497 rs.addColumn("X", Types.VARCHAR, s.length(), 0); 498 rs.addRow(new String []{s}); 499 return ValueResultSet.get(rs); 500 } 501 case UUID: 502 return ValueUuid.get(s); 503 default: 504 throw Message.getInternalError("type=" + type); 505 } 506 } catch (NumberFormatException e) { 507 throw Message.getSQLException(Message.DATA_CONVERSION_ERROR_1, new String [] { s }, e); 508 } 509 } 510 511 public final int compareTypeSave(Value v, CompareMode mode) throws SQLException { 512 if (this == ValueNull.INSTANCE) { 513 return v == ValueNull.INSTANCE ? 0 : -1; 514 } else if (v == ValueNull.INSTANCE) { 515 return 1; 516 } 517 return compareSecure(v, mode); 518 } 519 520 public final boolean compareEqual(Value v) throws SQLException { 521 if (this == ValueNull.INSTANCE) { 522 return v == ValueNull.INSTANCE; 523 } else if (v == ValueNull.INSTANCE) { 524 return false; 525 } 526 if (getType() == v.getType()) { 527 return isEqual(v); 528 } 529 int t2 = Value.getHigherOrder(getType(), v.getType()); 530 return convertTo(t2).isEqual(v.convertTo(t2)); 531 } 532 533 public final int compareTo(Value v, CompareMode mode) throws SQLException { 534 if (this == ValueNull.INSTANCE) { 535 return v == ValueNull.INSTANCE ? 0 : -1; 536 } else if (v == ValueNull.INSTANCE) { 537 return 1; 538 } 539 if (getType() == v.getType()) { 540 return compareSecure(v, mode); 541 } 542 int t2 = Value.getHigherOrder(getType(), v.getType()); 543 return convertTo(t2).compareSecure(v.convertTo(t2), mode); 544 } 545 546 public int getScale() { 547 return 0; 548 } 549 550 public Value convertScale(boolean onlyToSmallerScale, int targetScale) throws SQLException { 551 return this; 552 } 553 554 public Value convertPrecision(long precision) throws SQLException { 555 return this; 556 } 557 558 private byte convertToByte(long x) throws SQLException { 559 if (x > Byte.MAX_VALUE || x < Byte.MIN_VALUE) { 560 throw Message.getSQLException(Message.NUMERIC_VALUE_OUT_OF_RANGE); 561 } 562 return (byte) x; 563 } 564 565 private short convertToShort(long x) throws SQLException { 566 if (x > Short.MAX_VALUE || x < Short.MIN_VALUE) { 567 throw Message.getSQLException(Message.NUMERIC_VALUE_OUT_OF_RANGE); 568 } 569 return (short) x; 570 } 571 572 private int convertToInt(long x) throws SQLException { 573 if (x > Integer.MAX_VALUE || x < Integer.MIN_VALUE) { 574 throw Message.getSQLException(Message.NUMERIC_VALUE_OUT_OF_RANGE); 575 } 576 return (int) x; 577 } 578 579 private long convertToLong(double x) throws SQLException { 580 if (x > Long.MAX_VALUE || x < Long.MIN_VALUE) { 581 throw Message.getSQLException(Message.NUMERIC_VALUE_OUT_OF_RANGE); 583 } 584 if(Mode.getCurrentMode().roundWhenConvertToLong) { 585 return Math.round(x); 586 } else { 587 return (long) x; 588 } 589 } 590 591 private long convertToLong(BigDecimal x) throws SQLException { 592 if (x.compareTo(MAX_LONG_DECIMAL) > 0 || x.compareTo(Value.MIN_LONG_DECIMAL) < 0) { 593 throw Message.getSQLException(Message.NUMERIC_VALUE_OUT_OF_RANGE); 594 } 595 if(Mode.getCurrentMode().roundWhenConvertToLong) { 596 return Math.round(x.doubleValue()); 597 } else { 598 return x.longValue(); 599 } 600 } 601 602 public Value link(DataHandler handler, int tableId) throws SQLException { 603 return this; 604 } 605 606 public boolean isLinked() { 607 return false; 608 } 609 610 public void unlink(DataHandler handler) throws SQLException { 611 } 612 613 } 614 | Popular Tags |