1 21 22 package org.apache.derby.iapi.types; 23 24 import java.io.IOException ; 25 import java.io.ObjectInput ; 26 import java.io.ObjectOutput ; 27 import java.sql.ResultSet ; 28 import java.sql.SQLException ; 29 import java.sql.Types ; 30 31 import org.apache.derby.iapi.error.StandardException; 32 import org.apache.derby.iapi.reference.SQLState; 33 import org.apache.derby.iapi.services.io.ArrayInputStream; 34 import org.apache.derby.iapi.services.io.StoredFormatIds; 35 import org.apache.derby.iapi.services.sanity.SanityManager; 36 37 52 53 abstract class BinaryDecimal extends NumberDataType 54 implements VariableSizeDataValue 55 { 56 59 private static final byte[] ONE_2C = {(byte) 0x01}; 60 61 64 protected byte[] data2c; 65 66 69 protected int sqlScale; 70 71 72 BinaryDecimal() { 73 } 74 75 78 79 84 public final int typeToBigDecimal() 85 { 86 return java.sql.Types.DECIMAL; 87 } 88 89 90 public final int typePrecedence() 91 { 92 return TypeId.DECIMAL_PRECEDENCE; 93 } 94 95 98 public final String getTypeName() { 99 return TypeId.DECIMAL_NAME; 100 } 101 102 107 public final int getTypeFormatId() { 108 return StoredFormatIds.SQL_DECIMAL_ID; 109 } 110 111 114 115 118 public boolean isNull() 119 { 120 return data2c == null; 121 } 122 123 public void restoreToNull() 124 { 125 data2c = null; 126 } 127 128 132 protected boolean isNegative() { 133 return !isNull() && ((data2c[0] & 0x80) != 0); 134 } 135 136 137 140 141 144 public void setValue(long theValue) 145 { 146 byte[] rd = data2c; 147 if (rd == null || rd.length < 8) 148 rd = new byte[8]; 149 150 rd[0] = (byte)(theValue >>> 56); 151 rd[1] = (byte)(theValue >>> 48); 152 rd[2] = (byte)(theValue >>> 40); 153 rd[3] = (byte)(theValue >>> 32); 154 rd[4] = (byte)(theValue >>> 24); 155 rd[5] = (byte)(theValue >>> 16); 156 rd[6] = (byte)(theValue >>> 8); 157 rd[7] = (byte) theValue; 158 159 if (SanityManager.DEBUG) 160 { 161 data2c = rd; 162 sqlScale = 0; 163 try { 164 if (theValue != getLong()) 165 SanityManager.THROWASSERT("BinaryDecimal invalid long conversion before reduce in " 166 + theValue + " out " + getLong()); 167 } 168 catch (StandardException se) 169 { 170 SanityManager.THROWASSERT(se.toString()); 171 } 172 } 173 174 data2c = BinaryDecimal.reduceBytes2c(rd, 0, 8); 175 sqlScale = 0; 176 177 if (SanityManager.DEBUG) 178 { 179 try { 180 if (theValue != getLong()) 181 SanityManager.THROWASSERT("BinaryDecimal invalid long conversion after reduce in " 182 + theValue + " out " + getLong()); 183 } 184 catch (StandardException se) 185 { 186 SanityManager.THROWASSERT(se.toString()); 187 } 188 } 189 } 190 191 196 public final void setValue(int theValue) 197 { 198 byte[] rd = data2c; 199 if (rd == null || rd.length < 4) 200 rd = new byte[4]; 201 202 rd[0] = (byte)(theValue >>> 24); 203 rd[1] = (byte)(theValue >>> 16); 204 rd[2] = (byte)(theValue >>> 8); 205 rd[3] = (byte) theValue; 206 207 data2c = BinaryDecimal.reduceBytes2c(rd, 0, 4); 208 sqlScale = 0; 209 } 210 211 214 public void setValue(boolean theValue) 215 { 216 int intValue = theValue ? 1 : 0; 217 setValue(intValue); 218 } 219 220 225 public final void setValue(double theValue) throws StandardException 226 { 227 setCoreValue(NumberDataType.normalizeDOUBLE(theValue)); 228 } 229 230 234 public final void setValue(float theValue) 235 throws StandardException 236 { 237 setCoreValue((double)NumberDataType.normalizeREAL(theValue)); 238 } 239 240 private void setCoreValue(double theValue) throws StandardException { 241 setValue(Double.toString(theValue)); 242 } 243 244 250 public void setValue(Number theValue) throws StandardException 251 { 252 if (SanityManager.ASSERT) 253 { 254 if (theValue != null && 255 !(theValue instanceof java.lang.Long )) 256 SanityManager.THROWASSERT("BinaryDecimal.setValue(Number) passed a " + theValue.getClass()); 257 } 258 259 if (theValue == null) 260 setToNull(); 261 else 262 setValue(theValue.longValue()); 263 } 264 265 268 protected void setFrom(DataValueDescriptor dvd) throws StandardException 269 { 270 271 switch (dvd.typeToBigDecimal()) 272 { 273 case Types.CHAR: 274 case Types.DECIMAL: 276 setValue(dvd.getString()); 277 break; 278 case Types.BIGINT: 279 setValue(dvd.getLong()); 280 break; 281 default: 282 super.setFrom(dvd); 283 } 284 } 285 288 289 295 public final int getInt() throws StandardException 296 { 297 if (isNull()) 298 return 0; 299 300 try { 301 long lv = getLong(); 302 303 if ((lv >= Integer.MIN_VALUE) && (lv <= Integer.MAX_VALUE)) 304 return (int) lv; 305 306 } catch (StandardException se) { 307 } 310 311 throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "INTEGER"); 312 } 313 314 320 public final byte getByte() throws StandardException { 321 if (isNull()) 322 return (byte) 0; 323 324 try { 325 long lv = getLong(); 326 327 if ((lv >= Byte.MIN_VALUE) && (lv <= Byte.MAX_VALUE)) 328 return (byte) lv; 329 330 } catch (StandardException se) { 331 } 334 335 throw StandardException.newException( 336 SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "TINYINT"); 337 } 338 339 343 public final short getShort() throws StandardException 344 { 345 if (isNull()) 346 return (short)0; 347 348 try { 349 long lv = getLong(); 350 351 if ((lv >= Short.MIN_VALUE) && (lv <= Short.MAX_VALUE)) 352 return (short) lv; 353 354 } catch (StandardException se) { 355 } 358 359 throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "SMALLINT"); 360 } 361 362 363 366 367 379 380 public final NumberDataValue plus(NumberDataValue addend1, 381 NumberDataValue addend2, 382 NumberDataValue result) 383 throws StandardException 384 { 385 if (result == null) 386 { 387 result = (NumberDataValue) getNewNull(); 388 } 389 390 if (addend1.isNull() || addend2.isNull()) 391 { 392 result.setToNull(); 393 return result; 394 } 395 396 return plusNN(addend1, addend2, result); 397 } 398 399 402 public final NumberDataValue times(NumberDataValue left, NumberDataValue right, NumberDataValue result) 403 throws StandardException 404 { 405 if (result == null) 406 { 407 result = (NumberDataValue) getNewNull(); 408 } 409 410 if (left.isNull() || right.isNull()) 411 { 412 result.setToNull(); 413 return result; 414 } 415 return timesNN(left, right, result); 416 } 417 public NumberDataValue divide(NumberDataValue dividend, 418 NumberDataValue divisor, 419 NumberDataValue result) 420 throws StandardException 421 { 422 return divide(dividend, divisor, result, -1); 423 } 424 425 439 440 public final NumberDataValue divide(NumberDataValue dividend, 441 NumberDataValue divisor, 442 NumberDataValue result, 443 int scale) 444 throws StandardException 445 { 446 if (result == null) 447 { 448 result = (NumberDataValue) getNewNull(); 449 } 450 451 if (dividend.isNull() || divisor.isNull()) 452 { 453 result.setToNull(); 454 return result; 455 } 456 457 return divideNN(dividend, divisor, result, scale); 458 } 459 public final NumberDataValue minus(NumberDataValue left, NumberDataValue right, NumberDataValue result) 460 throws StandardException 461 { 462 if (result == null) 463 { 464 result = (NumberDataValue) getNewNull(); 465 } 466 467 if (left.isNull() || right.isNull()) 468 { 469 result.setToNull(); 470 return result; 471 } 472 473 return minusNN(left, right, result); 474 } 475 476 479 public NumberDataValue minusNN(NumberDataValue left, NumberDataValue right, NumberDataValue result) 480 throws StandardException 481 { 482 return plusNN(left, right.minus(result), result); 485 } 486 487 493 494 495 498 public abstract NumberDataValue timesNN(NumberDataValue left, 499 NumberDataValue right, NumberDataValue result) 500 throws StandardException; 501 502 508 public abstract NumberDataValue plusNN(NumberDataValue addend1, 509 NumberDataValue addend2, NumberDataValue result) 510 throws StandardException; 511 512 515 public abstract NumberDataValue divideNN(NumberDataValue dividend, 516 NumberDataValue divisor, NumberDataValue result, int scale) 517 throws StandardException; 518 519 522 523 534 private static byte[] reduceBytes2c(byte[] rd, int offset, int dataLength) 535 { 536 541 int leading; 542 for (leading = 0; leading < (dataLength - 1); leading++) 543 { 544 if (rd[offset + leading] != (byte) 0) 545 break; 546 547 if ((rd[offset + leading + 1] & 0x80) != 0) 551 break; 552 } 553 554 if (leading == 0) 555 { 556 for (; leading < (dataLength - 1); leading++) 559 { 560 564 if ((rd[offset + leading] == (byte) 0xff) && ((rd[offset + leading+1] & (byte) 0x80) != 0)) 565 continue; 566 break; 567 } 568 } 569 570 if ((leading != 0) || (rd.length != dataLength)) 571 { 572 byte[] reduced = new byte[dataLength - leading]; 573 System.arraycopy(rd, offset + leading, reduced, 0, reduced.length); 574 return reduced; 575 } 576 577 return rd; 578 } 579 580 584 public int getDecimalValueScale() 585 { 586 if (isNull()) 587 return 0; 588 589 return sqlScale; 590 } 591 592 595 596 604 public void writeExternal(ObjectOutput out) throws IOException 605 { 606 if (SanityManager.DEBUG) 608 SanityManager.ASSERT(! isNull()); 609 610 out.writeByte(sqlScale); 611 out.writeByte(data2c.length); 612 out.write(data2c); 613 } 614 615 622 public void readExternal(ObjectInput in) throws IOException 623 { 624 sqlScale = in.readUnsignedByte(); 625 int size = in.readUnsignedByte(); 626 627 635 if ((data2c == null) || size != data2c.length) 636 { 637 data2c = new byte[size]; 638 } 639 in.readFully(data2c); 640 641 } 642 public void readExternalFromArray(ArrayInputStream in) throws IOException 643 { 644 sqlScale = in.readUnsignedByte(); 645 int size = in.readUnsignedByte(); 646 647 655 if ((data2c == null) || size != data2c.length) 656 { 657 data2c = new byte[size]; 658 } 659 in.readFully(data2c); 660 } 661 662 663 664 public final int getLength() 665 { 666 return getDecimalValuePrecision(); 667 } 668 669 672 public DataValueDescriptor getClone() { 673 BinaryDecimal dvd = (BinaryDecimal) getNewNull(); 674 675 if (this.data2c != null) 676 { 677 dvd.data2c = new byte[data2c.length]; 678 System.arraycopy(data2c, 0, dvd.data2c, 0, data2c.length); 679 dvd.sqlScale = sqlScale; 680 } 681 682 return dvd; 683 } 684 685 688 public void setValueFromResultSet(ResultSet resultSet, int colNumber, boolean isNullable) throws StandardException, SQLException { 689 throw StandardException.newException(SQLState.NOT_IMPLEMENTED); 691 692 } 693 694 697 public int estimateMemoryUsage() { 698 return 0; 700 } 701 702 public int hashCode() 703 { 704 if (isNull()) 705 return 0; 706 707 try { 708 return (int) getLong(); 709 } catch (StandardException se) 710 { 711 return 0; 712 } 713 } 714 } 715 | Popular Tags |