1 21 22 package org.apache.derby.iapi.types; 23 24 import org.apache.derby.iapi.reference.SQLState; 25 26 import org.apache.derby.iapi.services.io.ArrayInputStream; 27 import org.apache.derby.iapi.services.io.FormatableBitSet; 28 import org.apache.derby.iapi.services.io.NewByteArrayInputStream; 29 30 import org.apache.derby.iapi.types.DataTypeDescriptor; 31 import org.apache.derby.iapi.types.DataValueDescriptor; 32 import org.apache.derby.iapi.types.TypeId; 33 import org.apache.derby.iapi.types.BitDataValue; 34 import org.apache.derby.iapi.types.DataValueDescriptor; 35 import org.apache.derby.iapi.types.ConcatableDataValue; 36 import org.apache.derby.iapi.types.VariableSizeDataValue; 37 import org.apache.derby.iapi.error.StandardException; 38 39 import org.apache.derby.iapi.services.io.FormatIdUtil; 40 import org.apache.derby.iapi.services.io.StoredFormatIds; 41 import org.apache.derby.iapi.services.io.StreamStorable; 42 import org.apache.derby.iapi.services.io.FormatIdInputStream; 43 44 import org.apache.derby.iapi.services.sanity.SanityManager; 45 46 import org.apache.derby.iapi.types.BooleanDataValue; 47 import org.apache.derby.iapi.types.StringDataValue; 48 import org.apache.derby.iapi.types.NumberDataValue; 49 50 import org.apache.derby.iapi.services.cache.ClassSize; 51 import org.apache.derby.iapi.util.StringUtil; 52 53 import org.apache.derby.iapi.types.SQLInteger; 54 55 import java.io.ObjectOutput ; 56 import java.io.ObjectInput ; 57 import java.io.IOException ; 58 import java.io.InputStream ; 59 60 import java.sql.ResultSet ; 61 import java.sql.SQLException ; 62 import java.sql.PreparedStatement ; 63 64 103 abstract class SQLBinary 104 extends DataType implements BitDataValue 105 { 106 107 static final byte PAD = (byte) 0x20; 108 109 private static final int BASE_MEMORY_USAGE = ClassSize.estimateBaseFromCatalog( SQLBinary.class); 110 111 public int estimateMemoryUsage() 112 { 113 if (dataValue == null) { 114 if (streamValueLength>=0) { 115 return BASE_MEMORY_USAGE + streamValueLength; 116 } else { 117 return getMaxMemoryUsage(); 118 } 119 } else { 120 return BASE_MEMORY_USAGE + dataValue.length; 121 } 122 } 124 125 128 abstract int getMaxMemoryUsage(); 129 130 133 byte[] dataValue; 134 135 140 InputStream stream; 141 142 151 int streamValueLength; 152 153 156 SQLBinary() 157 { 158 } 159 160 SQLBinary(byte[] val) 161 { 162 dataValue = val; 163 } 164 165 166 public final void setValue(byte[] theValue) 167 { 168 dataValue = theValue; 169 stream = null; 170 streamValueLength = -1; 171 } 172 173 179 public final String getString() throws StandardException 180 { 181 if (getValue() == null) 182 return null; 183 else if (dataValue.length * 2 < 0) { 185 throw StandardException.newException(SQLState.LANG_STRING_TRUNCATION, getTypeName(), 186 "", 187 String.valueOf(Integer.MAX_VALUE)); 188 } 189 else 190 { 191 return org.apache.derby.iapi.util.StringUtil.toHexString(dataValue, 0, dataValue.length); 192 } 193 } 194 195 196 199 public final InputStream getStream() 200 { 201 return (stream); 202 } 203 204 208 public final byte[] getBytes() throws StandardException 209 { 210 return getValue(); 211 } 212 213 byte[] getValue() throws StandardException 214 { 215 try 216 { 217 if ((dataValue == null) && (stream != null)) { 218 219 if (stream instanceof FormatIdInputStream) { 220 readExternal((FormatIdInputStream) stream); 221 } 222 else { 223 readExternal(new FormatIdInputStream(stream)); 224 } 225 stream = null; 226 streamValueLength = -1; 227 228 } 229 } 230 catch (IOException ioe) 231 { 232 throw StandardException.newException(SQLState.LANG_STREAMING_COLUMN_I_O_EXCEPTION, ioe, getTypeName()); 233 } 234 return dataValue; 235 } 236 237 242 public final int getLength() throws StandardException 243 { 244 if (stream != null) { 245 246 if (streamValueLength != -1) 247 return streamValueLength; 248 } 249 250 return (getBytes() == null) ? 0 : getBytes().length; 251 } 252 253 256 257 258 262 public final boolean isNull() 263 { 264 return (dataValue == null) && (stream == null); 265 } 266 267 273 public final void writeExternal(ObjectOutput out) throws IOException 274 { 275 276 int len = dataValue.length; 277 if (len <= 31) 278 { 279 out.write((byte) (0x80 | (len & 0xff))); 280 } 281 else if (len <= 0xFFFF) 282 { 283 out.write((byte) 0xA0); 284 out.writeShort((short) len); 285 } 286 else 287 { 288 out.write((byte) 0xC0); 289 out.writeInt(len); 290 291 } 292 out.write(dataValue, 0, dataValue.length); 293 } 294 295 301 public final void readExternal(ObjectInput in) throws IOException 302 { 303 stream = null; 306 streamValueLength = -1; 307 308 309 int len = SQLBinary.readBinaryLength(in); 310 311 if (len != 0) 312 { 313 dataValue = new byte[len]; 314 in.readFully(dataValue); 315 } 316 else 317 { 318 readFromStream((InputStream) in); 319 } 320 } 321 public final void readExternalFromArray(ArrayInputStream in) throws IOException 322 { 323 stream = null; 326 streamValueLength = -1; 327 328 int len = SQLBinary.readBinaryLength(in); 329 330 if (len != 0) 331 { 332 dataValue = new byte[len]; 333 in.readFully(dataValue); 334 } 335 else 336 { 337 readFromStream(in); 338 } 339 } 340 341 346 private static int readBinaryLength(ObjectInput in) throws IOException { 347 348 int bl = in.read(); 349 if (bl == -1) 350 throw new java.io.EOFException (); 351 352 byte li = (byte) bl; 353 354 int len; 355 if ((li & ((byte) 0x80)) != 0) 356 { 357 if (li == ((byte) 0xC0)) 358 { 359 len = in.readInt(); 360 } 361 else if (li == ((byte) 0xA0)) 362 { 363 len = in.readUnsignedShort(); 364 } 365 else 366 { 367 len = li & 0x1F; 368 } 369 } 370 else 371 { 372 373 int v2 = in.read(); 375 int v3 = in.read(); 376 int v4 = in.read(); 377 if (v2 == -1 || v3 == -1 || v4 == -1) 378 throw new java.io.EOFException (); 379 int lenInBits = (((bl & 0xff) << 24) | ((v2 & 0xff) << 16) | ((v3 & 0xff) << 8) | (v4 & 0xff)); 380 381 len = lenInBits / 8; 382 if ((lenInBits % 8) != 0) 383 len++; 384 } 385 return len; 386 } 387 388 393 private void readFromStream(InputStream in) throws IOException { 394 395 dataValue = null; byte[] tmpData = new byte[32 * 1024]; 397 398 int off = 0; 399 for (;;) { 400 401 int len = in.read(tmpData, off, tmpData.length - off); 402 if (len == -1) 403 break; 404 off += len; 405 406 int available = Math.max(1, in.available()); 407 int extraSpace = available - (tmpData.length - off); 408 if (extraSpace > 0) 409 { 410 int size = tmpData.length * 2; 412 if (extraSpace > tmpData.length) 413 size += extraSpace; 414 415 byte[] grow = new byte[size]; 416 System.arraycopy(tmpData, 0, grow, 0, off); 417 tmpData = grow; 418 } 419 } 420 421 dataValue = new byte[off]; 422 System.arraycopy(tmpData, 0, dataValue, 0, off); 423 } 424 425 428 public final void restoreToNull() 429 { 430 dataValue = null; 431 stream = null; 432 streamValueLength = -1; 433 } 434 435 438 public final boolean compare(int op, 439 DataValueDescriptor other, 440 boolean orderedNulls, 441 boolean unknownRV) 442 throws StandardException 443 { 444 if (!orderedNulls) { 446 if (SanityManager.DEBUG) 447 { 448 int otherTypeFormatId = other.getTypeFormatId(); 449 if (!((StoredFormatIds.SQL_BIT_ID == otherTypeFormatId) 450 || (StoredFormatIds.SQL_VARBIT_ID == otherTypeFormatId) 451 || (StoredFormatIds.SQL_LONGVARBIT_ID == otherTypeFormatId) 452 453 || (StoredFormatIds.SQL_CHAR_ID == otherTypeFormatId) 454 || (StoredFormatIds.SQL_VARCHAR_ID == otherTypeFormatId) 455 || (StoredFormatIds.SQL_LONGVARCHAR_ID == otherTypeFormatId) 456 457 || ((StoredFormatIds.SQL_BLOB_ID == otherTypeFormatId) 458 && (StoredFormatIds.SQL_BLOB_ID == getTypeFormatId())) 459 )) 460 SanityManager.THROWASSERT( 461 "Some fool passed in a "+ other.getClass().getName() + ", " 462 + otherTypeFormatId + " to SQLBinary.compare()"); 463 } 464 String otherString = other.getString(); 465 if (this.getString() == null || otherString == null) 466 return unknownRV; 467 } 468 469 return super.compare(op, other, orderedNulls, unknownRV); 470 } 471 472 475 public final int compare(DataValueDescriptor other) throws StandardException 476 { 477 478 481 if (typePrecedence() < other.typePrecedence()) 482 { 483 return - (other.compare(this)); 484 } 485 486 489 if (this.isNull() || other.isNull()) 490 { 491 if (!isNull()) 492 return -1; 493 if (!other.isNull()) 494 return 1; 495 return 0; } 497 498 return SQLBinary.compare(getBytes(), other.getBytes()); 499 } 500 501 504 505 510 public final Object cloneObject() 511 { 512 if (stream == null) 513 return getClone(); 514 SQLBinary self = (SQLBinary) getNewNull(); 515 self.setValue(stream, streamValueLength); 516 return self; 517 } 518 519 522 523 524 public final DataValueDescriptor getClone() 525 { 526 try 527 { 528 DataValueDescriptor cloneDVD = getNewNull(); 529 cloneDVD.setValue(getValue()); 530 return cloneDVD; 531 } 532 catch (StandardException se) 533 { 534 if (SanityManager.DEBUG) 535 SanityManager.THROWASSERT("Unexpected exception " + se); 536 return null; 537 } 538 } 539 540 543 544 547 public final InputStream returnStream() 548 { 549 return stream; 550 } 551 552 559 public final void setStream(InputStream newStream) 560 { 561 this.dataValue = null; 562 this.stream = newStream; 563 streamValueLength = -1; 564 } 565 566 public final void loadStream() throws StandardException 567 { 568 getValue(); 569 } 570 571 574 575 boolean objectNull(Object o) 576 { 577 if (o == null) 578 { 579 setToNull(); 580 return true; 581 } 582 return false; 583 } 584 585 590 public final void setValue(InputStream theStream, int valueLength) 591 { 592 dataValue = null; 593 stream = theStream; 594 this.streamValueLength = valueLength; 595 } 596 597 protected final void setFrom(DataValueDescriptor theValue) throws StandardException { 598 599 if (theValue instanceof SQLBinary) 600 { 601 SQLBinary theValueBinary = (SQLBinary) theValue; 602 dataValue = theValueBinary.dataValue; 603 stream = theValueBinary.stream; 604 streamValueLength = theValueBinary.streamValueLength; 605 } 606 else 607 { 608 setValue(theValue.getBytes()); 609 } 610 } 611 612 615 616 627 628 public final BooleanDataValue equals(DataValueDescriptor left, 629 DataValueDescriptor right) 630 throws StandardException 631 { 632 boolean isEqual; 633 634 if (left.isNull() || right.isNull()) 635 { 636 isEqual = false; 637 } 638 else 639 { 640 isEqual = SQLBinary.compare(left.getBytes(), right.getBytes()) == 0; 641 } 642 643 return SQLBoolean.truthValue(left, 644 right, 645 isEqual); 646 } 647 648 660 661 public final BooleanDataValue notEquals(DataValueDescriptor left, 662 DataValueDescriptor right) 663 throws StandardException 664 { 665 boolean isNotEqual; 666 667 if (left.isNull() || right.isNull()) 668 { 669 isNotEqual = false; 670 } 671 else 672 { 673 isNotEqual = SQLBinary.compare(left.getBytes(), right.getBytes()) != 0; 674 } 675 676 return SQLBoolean.truthValue(left, 677 right, 678 isNotEqual); 679 } 680 681 693 694 public final BooleanDataValue lessThan(DataValueDescriptor left, 695 DataValueDescriptor right) 696 throws StandardException 697 { 698 boolean isLessThan; 699 700 if (left.isNull() || right.isNull()) 701 { 702 isLessThan = false; 703 } 704 else 705 { 706 isLessThan = SQLBinary.compare(left.getBytes(), right.getBytes()) < 0; 707 } 708 709 return SQLBoolean.truthValue(left, 710 right, 711 isLessThan); 712 } 713 714 726 727 public final BooleanDataValue greaterThan(DataValueDescriptor left, 728 DataValueDescriptor right) 729 throws StandardException 730 { 731 boolean isGreaterThan = false; 732 733 if (left.isNull() || right.isNull()) 734 { 735 isGreaterThan = false; 736 } 737 else 738 { 739 isGreaterThan = SQLBinary.compare(left.getBytes(), right.getBytes()) > 0; 740 } 741 742 return SQLBoolean.truthValue(left, 743 right, 744 isGreaterThan); 745 } 746 747 759 760 public final BooleanDataValue lessOrEquals(DataValueDescriptor left, 761 DataValueDescriptor right) 762 throws StandardException 763 { 764 boolean isLessEquals = false; 765 766 if (left.isNull() || right.isNull()) 767 { 768 isLessEquals = false; 769 } 770 else 771 { 772 isLessEquals = SQLBinary.compare(left.getBytes(), right.getBytes()) <= 0; 773 } 774 775 return SQLBoolean.truthValue(left, 776 right, 777 isLessEquals); 778 } 779 780 792 793 public final BooleanDataValue greaterOrEquals(DataValueDescriptor left, 794 DataValueDescriptor right) 795 throws StandardException 796 { 797 boolean isGreaterEquals = false; 798 799 if (left.isNull() || right.isNull()) 800 { 801 isGreaterEquals = false; 802 } 803 else 804 { 805 isGreaterEquals = SQLBinary.compare(left.getBytes(), right.getBytes()) >= 0; 806 } 807 808 return SQLBoolean.truthValue(left, 809 right, 810 isGreaterEquals); 811 } 812 813 814 827 828 public final NumberDataValue charLength(NumberDataValue result) 829 throws StandardException 830 { 831 if (result == null) 832 { 833 result = new SQLInteger(); 834 } 835 836 if (this.isNull()) 837 { 838 result.setToNull(); 839 return result; 840 } 841 842 843 result.setValue(getValue().length); 844 return result; 845 } 846 847 852 public final BitDataValue concatenate( 853 BitDataValue left, 854 BitDataValue right, 855 BitDataValue result) 856 throws StandardException 857 { 858 if (left.isNull() || right.isNull()) 859 { 860 result.setToNull(); 861 return result; 862 } 863 864 byte[] leftData = left.getBytes(); 865 byte[] rightData = right.getBytes(); 866 867 byte[] concatData = new byte[leftData.length + rightData.length]; 868 869 System.arraycopy(leftData, 0, concatData, 0, leftData.length); 870 System.arraycopy(rightData, 0, concatData, leftData.length, rightData.length); 871 872 873 result.setValue(concatData); 874 return result; 875 } 876 877 878 891 public final ConcatableDataValue substring( 892 NumberDataValue start, 893 NumberDataValue length, 894 ConcatableDataValue result, 895 int maxLen) 896 throws StandardException 897 { 898 int startInt; 899 int lengthInt; 900 BitDataValue varbitResult; 901 902 if (result == null) 903 { 904 result = new SQLVarbit(); 905 } 906 907 varbitResult = (BitDataValue) result; 908 909 914 if (this.isNull() || start.isNull() || (length != null && length.isNull())) 915 { 916 varbitResult.setToNull(); 917 return varbitResult; 918 } 919 920 startInt = start.getInt(); 921 922 if (length != null) 924 { 925 lengthInt = length.getInt(); 926 } 927 else lengthInt = getLength() - startInt + 1; 928 929 933 if ((startInt <= 0 || lengthInt < 0 || startInt > getLength() || 934 lengthInt > getLength() - startInt + 1)) 935 throw StandardException.newException(SQLState.LANG_SUBSTR_START_OR_LEN_OUT_OF_RANGE); 936 937 if (lengthInt < 0) 939 { 940 varbitResult.setToNull(); 941 return varbitResult; 942 } 943 944 945 if (startInt < 0) 946 { 947 startInt += getLength(); 948 if (startInt < 0) 949 { 950 lengthInt += startInt; 951 startInt = 0; 952 } 953 if (lengthInt + startInt > 0) 954 { 955 lengthInt += startInt; 956 } 957 else 958 { 959 lengthInt = 0; 960 } 961 } 962 else if (startInt > 0) 963 { 964 965 startInt--; 966 } 967 968 972 if (lengthInt == 0 || 973 lengthInt <= 0 - startInt || 974 startInt > getLength()) 975 { 976 varbitResult.setValue(new byte[0]); 977 return varbitResult; 978 } 979 980 if (lengthInt >= getLength() - startInt) 981 { 982 byte[] substring = new byte[dataValue.length - startInt]; 983 System.arraycopy(dataValue, startInt, substring, 0, substring.length); 984 varbitResult.setValue(substring); 985 } 986 else 987 { 988 byte[] substring = new byte[lengthInt]; 989 System.arraycopy(dataValue, startInt, substring, 0, substring.length); 990 varbitResult.setValue(substring); 991 } 992 993 return varbitResult; 994 } 995 996 1003 public final void checkHostVariable(int declaredLength) throws StandardException 1004 { 1005 int variableLength = -1; 1007 if (stream == null) 1008 { 1009 if (dataValue != null) 1010 variableLength = dataValue.length; 1011 } 1012 else 1013 { 1014 variableLength = streamValueLength; 1015 } 1016 1017 if (variableLength != -1 && variableLength > declaredLength) 1018 throw StandardException.newException(SQLState.LANG_STRING_TRUNCATION, getTypeName(), 1019 "XX-RESOLVE-XX", 1020 String.valueOf(declaredLength)); 1021 } 1022 1023 1026 1027 public final String toString() 1028 { 1029 if (dataValue == null) 1030 { 1031 if (stream == null) 1032 { 1033 return "NULL"; 1034 } 1035 else 1036 { 1037 if (SanityManager.DEBUG) 1038 SanityManager.THROWASSERT( 1039 "value is null, stream is not null"); 1040 return ""; 1041 } 1042 } 1043 else 1044 { 1045 return org.apache.derby.iapi.util.StringUtil.toHexString(dataValue, 0, dataValue.length); 1046 } 1047 } 1048 1049 1052 public final int hashCode() 1053 { 1054 try { 1055 if (getValue() == null) 1056 { 1057 return 0; 1058 } 1059 } 1060 catch (StandardException se) 1061 { 1062 if (SanityManager.DEBUG) 1063 SanityManager.THROWASSERT("Unexpected exception " + se); 1064 return 0; 1065 } 1066 1067 1068 byte[] bytes = dataValue; 1069 int hashcode = 0; 1070 1071 for (int index = 0 ; index < bytes.length; index++) 1073 { 1074 byte bv = bytes[index]; 1075 if (bv != SQLBinary.PAD) 1076 hashcode += bytes[index]; 1077 } 1078 1079 return hashcode; 1080 } 1081 private static int compare(byte[] left, byte[] right) { 1082 1083 int minLen = left.length; 1084 byte[] longer = right; 1085 if (right.length < minLen) { 1086 minLen = right.length; 1087 longer = left; 1088 } 1089 1090 for (int i = 0; i < minLen; i++) { 1091 1092 int lb = left[i] & 0xff; 1093 int rb = right[i] & 0xff; 1094 1095 if (lb == rb) 1096 continue; 1097 1098 return lb - rb; 1099 } 1100 1101 1103 for (int i = minLen; i < longer.length; i++) { 1106 byte nb = longer[i]; 1107 if (nb == SQLBinary.PAD) 1108 continue; 1109 1110 if (left == longer) 1112 return 1; 1113 return -1; 1114 } 1115 1116 return 0; 1117 1118 } 1119 1120 1123 public void setInto(PreparedStatement ps, int position) throws SQLException , StandardException { 1124 1125 ps.setBytes(position, getBytes()); 1126 } 1127} 1128 | Popular Tags |