1 29 30 package com.caucho.db.sql; 31 32 import com.caucho.db.store.BlobInputStream; 33 import com.caucho.db.store.Store; 34 import com.caucho.db.table.Column; 35 import com.caucho.db.table.TableIterator; 36 import com.caucho.sql.SQLExceptionWrapper; 37 import com.caucho.util.CharBuffer; 38 import com.caucho.util.FreeList; 39 import com.caucho.util.IntArray; 40 import com.caucho.util.L10N; 41 import com.caucho.util.QDate; 42 import com.caucho.vfs.TempBuffer; 43 44 import java.io.IOException ; 45 import java.sql.Blob ; 46 import java.sql.Clob ; 47 import java.sql.SQLException ; 48 49 public class SelectResult { 50 private static final L10N L = new L10N(SelectResult.class); 51 52 private static final FreeList<SelectResult> _freeList = 53 new FreeList<SelectResult>(32); 54 55 private static final int SIZE_BITS = 13; 56 private static final int SIZE_MASK = 8192 - 1; 57 58 private static QDate _date = new QDate(); 59 60 private CharBuffer _cb = new CharBuffer(); 61 private byte []_blob = new byte[128]; 62 63 private Expr []_exprs; 64 private Store []_stores = new Store[32]; 65 66 private TableIterator []_rows = new TableIterator[16]; 67 68 private Order _order; 69 private IntArray _orderIndex; 70 71 private TempBuffer []_tempBuffers = new TempBuffer[128]; 72 private byte [][]_buffers = new byte[128][]; 73 private int _length; 74 private int _rowCount; 75 76 private int _row; 77 78 private int _offset; 79 private int _rowOffset; 80 private int _columnOffset; 81 private int _column; 82 83 private boolean _wasNull; 84 85 private SelectResult() 86 { 87 } 88 89 public static SelectResult create(Expr []exprs, Order order) 90 { 91 SelectResult rs = _freeList.allocate(); 92 93 if (rs == null) 94 rs = new SelectResult(); 95 96 rs.init(exprs, order); 97 98 return rs; 99 } 100 101 104 TableIterator []initRows(FromItem []fromItems) 105 { 106 if (_rows.length < fromItems.length) 107 _rows = new TableIterator[fromItems.length]; 108 109 for (int i = 0; i < fromItems.length; i++) { 110 if (_rows[i] == null) 111 _rows[i] = new TableIterator(); 112 _rows[i].init(fromItems[i].getTable()); 113 } 114 115 return _rows; 116 } 117 118 121 private void init(Expr []exprs, Order order) 122 { 123 _exprs = exprs; 124 _order = order; 125 126 if (order != null) 127 _orderIndex = new IntArray(); 128 129 if (_stores.length < _exprs.length) { 130 _stores = new Store[exprs.length]; 131 } 132 133 for (int i = 0; i < exprs.length; i++) 134 _stores[i] = exprs[i].getTable(); 135 136 _length = 0; 137 _rowCount = 0; 138 } 139 140 void initRead() 141 throws SQLException 142 { 143 if (_order != null) 144 _order.sort(this, _orderIndex); 145 146 _row = -1; 147 _offset = 0; 148 _column = 0; 149 _rowOffset = 0; 150 _columnOffset = 0; 151 } 152 153 156 public boolean next() 157 throws SQLException 158 { 159 if (++_row < _rowCount) { 160 if (_orderIndex != null) { 161 _offset = _orderIndex.get(_row); 162 } 163 else if (_row != 0) { 164 _offset = _columnOffset; 165 skipColumns(_exprs.length - _column); 166 } 167 168 _column = 0; 169 _rowOffset = _offset; 170 _columnOffset = _rowOffset; 171 172 return true; 173 } 174 else 175 return false; 176 } 177 178 181 public Expr []getExprs() 182 { 183 return _exprs; 184 } 185 186 189 public int findColumnIndex(String name) 190 throws SQLException 191 { 192 for (int i = 0; i < _exprs.length; i++) { 193 if (_exprs[i].getName().equals(name)) 194 return i + 1; 195 } 196 197 throw new SQLException (L.l("column `{0}' does not exist.", name)); 198 } 199 200 203 public String getString(int index) 204 throws SQLException 205 { 206 _wasNull = false; 207 208 setColumn(index); 209 210 int type = read(); 211 switch (type) { 212 case Column.NONE: 213 _wasNull = true; 214 return null; 215 216 case Column.INT: 217 { 218 int value = ((read() << 24) + 219 (read() << 16) + 220 (read() << 8) + 221 (read())); 222 223 return String.valueOf(value); 224 } 225 226 case Column.LONG: 227 { 228 long value = (((long) read() << 56) + 229 ((long) read() << 48) + 230 ((long) read() << 40) + 231 ((long) read() << 32) + 232 ((long) read() << 24) + 233 ((long) read() << 16) + 234 ((long) read() << 8) + 235 ((long) read())); 236 237 return String.valueOf(value); 238 } 239 240 case Column.DOUBLE: 241 { 242 long value = (((long) read() << 56) + 243 ((long) read() << 48) + 244 ((long) read() << 40) + 245 ((long) read() << 32) + 246 ((long) read() << 24) + 247 ((long) read() << 16) + 248 ((long) read() << 8) + 249 ((long) read())); 250 251 return String.valueOf(Double.longBitsToDouble(value)); 252 } 253 254 case Column.DATE: 255 { 256 long value = (((long) read() << 56) + 257 ((long) read() << 48) + 258 ((long) read() << 40) + 259 ((long) read() << 32) + 260 ((long) read() << 24) + 261 ((long) read() << 16) + 262 ((long) read() << 8) + 263 ((long) read())); 264 265 return QDate.formatISO8601(value); 266 } 267 268 case Column.VARCHAR: 269 return readString(); 270 271 case Column.BLOB: 272 return readBlobString(); 273 274 default: 275 throw new RuntimeException ("unknown column type:" + type + " column:" + index); 276 } 277 } 278 279 282 public int getInt(int index) 283 throws SQLException 284 { 285 _wasNull = false; 286 setColumn(index); 287 288 int type = read(); 289 switch (type) { 290 case Column.NONE: 291 _wasNull = true; 292 return 0; 293 294 case Column.INT: 295 { 296 int value = ((read() << 24) + 297 (read() << 16) + 298 (read() << 8) + 299 (read())); 300 301 return value; 302 } 303 304 case Column.LONG: 305 case Column.DATE: 306 { 307 long value = (((long) read() << 56) + 308 ((long) read() << 48) + 309 ((long) read() << 40) + 310 ((long) read() << 32) + 311 ((long) read() << 24) + 312 ((long) read() << 16) + 313 ((long) read() << 8) + 314 ((long) read())); 315 316 return (int) value; 317 } 318 319 case Column.DOUBLE: 320 { 321 long value = (((long) read() << 56) + 322 ((long) read() << 48) + 323 ((long) read() << 40) + 324 ((long) read() << 32) + 325 ((long) read() << 24) + 326 ((long) read() << 16) + 327 ((long) read() << 8) + 328 ((long) read())); 329 330 return (int) Double.longBitsToDouble(value); 331 } 332 333 case Column.VARCHAR: 334 return Integer.parseInt(readString()); 335 336 case Column.BLOB: 337 return Integer.parseInt(readBlobString()); 338 339 default: 340 return 0; 341 } 342 } 343 344 347 public long getLong(int index) 348 throws SQLException 349 { 350 _wasNull = false; 351 setColumn(index); 352 353 int type = read(); 354 switch (type) { 355 case Column.NONE: 356 _wasNull = true; 357 return 0; 358 359 case Column.INT: 360 { 361 int value = ((read() << 24) + 362 (read() << 16) + 363 (read() << 8) + 364 (read())); 365 366 return value; 367 } 368 369 case Column.LONG: 370 case Column.DATE: 371 { 372 long value = (((long) read() << 56) + 373 ((long) read() << 48) + 374 ((long) read() << 40) + 375 ((long) read() << 32) + 376 ((long) read() << 24) + 377 ((long) read() << 16) + 378 ((long) read() << 8) + 379 ((long) read())); 380 381 return value; 382 } 383 384 case Column.DOUBLE: 385 { 386 long value = (((long) read() << 56) + 387 ((long) read() << 48) + 388 ((long) read() << 40) + 389 ((long) read() << 32) + 390 ((long) read() << 24) + 391 ((long) read() << 16) + 392 ((long) read() << 8) + 393 ((long) read())); 394 395 return (long) Double.longBitsToDouble(value); 396 } 397 398 case Column.VARCHAR: 399 return Long.parseLong(readString()); 400 401 case Column.BLOB: 402 return Long.parseLong(readBlobString()); 403 404 default: 405 return 0; 406 } 407 } 408 409 412 public double getDouble(int index) 413 throws SQLException 414 { 415 _wasNull = false; 416 setColumn(index); 417 418 int type = read(); 419 switch (type) { 420 case Column.NONE: 421 _wasNull = true; 422 return 0; 423 424 case Column.INT: 425 { 426 int value = ((read() << 24) + 427 (read() << 16) + 428 (read() << 8) + 429 (read())); 430 431 return value; 432 } 433 434 case Column.LONG: 435 case Column.DATE: 436 { 437 long value = (((long) read() << 56) + 438 ((long) read() << 48) + 439 ((long) read() << 40) + 440 ((long) read() << 32) + 441 ((long) read() << 24) + 442 ((long) read() << 16) + 443 ((long) read() << 8) + 444 ((long) read())); 445 446 return value; 447 } 448 449 case Column.DOUBLE: 450 { 451 long value = (((long) read() << 56) + 452 ((long) read() << 48) + 453 ((long) read() << 40) + 454 ((long) read() << 32) + 455 ((long) read() << 24) + 456 ((long) read() << 16) + 457 ((long) read() << 8) + 458 ((long) read())); 459 460 return Double.longBitsToDouble(value); 461 } 462 463 case Column.VARCHAR: 464 return Double.parseDouble(readString()); 465 466 case Column.BLOB: 467 return Double.parseDouble(readBlobString()); 468 469 default: 470 return 0; 471 } 472 } 473 474 public long getDate(int index) 475 throws SQLException 476 { 477 _wasNull = false; 478 setColumn(index); 479 480 int type = read(); 481 switch (type) { 482 case Column.NONE: 483 _wasNull = true; 484 return 0; 485 486 case Column.LONG: 487 case Column.DATE: 488 { 489 long value = (((long) read() << 56) + 490 ((long) read() << 48) + 491 ((long) read() << 40) + 492 ((long) read() << 32) + 493 ((long) read() << 24) + 494 ((long) read() << 16) + 495 ((long) read() << 8) + 496 ((long) read())); 497 498 return value; 499 } 500 501 case Column.VARCHAR: 502 { 503 String value = readString(); 504 505 synchronized (_date) { 506 try { 507 return _date.parseDate(value); 508 } catch (Exception e) { 509 throw new SQLExceptionWrapper(e); 510 } 511 } 512 } 513 514 case Column.BLOB: 515 { 516 String value = readBlobString(); 517 518 synchronized (_date) { 519 try { 520 return _date.parseDate(value); 521 } catch (Exception e) { 522 throw new SQLExceptionWrapper(e); 523 } 524 } 525 } 526 527 default: 528 throw new SQLException ("unknown type: " + type); 529 } 530 } 531 532 535 public Blob getBlob(int index) 536 throws SQLException 537 { 538 _wasNull = false; 539 540 setColumn(index); 541 542 int type = read(); 543 switch (type) { 544 case Column.NONE: 545 _wasNull = true; 546 return null; 547 548 case Column.BLOB: 549 return getBlob(); 550 551 default: 552 throw new RuntimeException ("column can't be retrieved as a blob:" + type + " column:" + index); 553 } 554 } 555 556 559 public Clob getClob(int index) 560 throws SQLException 561 { 562 _wasNull = false; 563 564 setColumn(index); 565 566 int type = read(); 567 switch (type) { 568 case Column.NONE: 569 _wasNull = true; 570 return null; 571 572 case Column.BLOB: 573 return getClob(); 574 575 default: 576 throw new RuntimeException ("column can't be retrieved as a clob:" + type + " column:" + index); 577 } 578 } 579 580 583 public boolean wasNull() 584 { 585 return _wasNull; 586 } 587 588 591 private String readString() 592 throws SQLException 593 { 594 int length = ((read() << 24) + 595 (read() << 16) + 596 (read() << 8) + 597 (read())); 598 599 int len = length >> 1; 600 601 CharBuffer cb = _cb; 602 cb.ensureCapacity(len); 603 char []cBuf = cb.getBuffer(); 604 int cLen = 0; 605 606 for (; len > 0; len--) { 607 int ch1 = read(); 608 int ch2 = read(); 609 610 cBuf[cLen++] = (char) (((ch1 & 0xff) << 8) + (ch2 & 0xff)); 611 } 612 613 return new String (cBuf, 0, cLen); 614 } 615 616 619 private Blob getBlob() 620 throws SQLException 621 { 622 BlobImpl blob = new BlobImpl(); 623 624 blob.setStore(_stores[_column]); 625 626 byte []inode = blob.getInode(); 627 628 for (int i = 0; i < 128; i++) 629 inode[i] = (byte) read(); 630 631 return blob; 632 } 633 634 637 private Clob getClob() 638 throws SQLException 639 { 640 ClobImpl clob = new ClobImpl(); 641 642 clob.setStore(_stores[_column]); 643 644 byte []inode = clob.getInode(); 645 646 for (int i = 0; i < 128; i++) 647 inode[i] = (byte) read(); 648 649 return clob; 650 } 651 652 655 private String readBlobString() 656 throws SQLException 657 { 658 read(_blob, 0, 128); 659 660 CharBuffer cb = _cb; 661 cb.clear(); 662 663 BlobInputStream is = null; 664 try { 665 is = new BlobInputStream(_stores[_column], _blob, 0); 666 667 int ch; 668 while ((ch = is.read()) >= 0) { 669 if (ch < 0x80) 670 cb.append((char) ch); 671 } 672 } catch (IOException e) { 673 throw new SQLExceptionWrapper(e); 674 } 675 676 return cb.toString(); 677 } 678 679 682 private void setColumn(int column) 683 { 684 if (column < _column) { 685 _offset = _rowOffset; 686 skipColumns(column); 687 } 688 else { 689 _offset = _columnOffset; 690 skipColumns(column - _column); 691 } 692 693 _column = column; 694 _columnOffset = _offset; 695 } 696 697 700 void setRow(int rowOffset) 701 { 702 _rowOffset = rowOffset; 703 _offset = rowOffset; 704 _column = 0; 705 _columnOffset = rowOffset; 706 } 707 708 711 private void skipColumns(int count) 712 { 713 for (; count > 0; count--) { 714 int type = read(); 715 int sublen; 716 717 switch (type) { 718 case Column.NONE: 719 break; 720 721 case Column.VARCHAR: 722 int l0 = read(); 723 int l1 = read(); 724 int l2 = read(); 725 int l3 = read(); 726 727 sublen = ((l0 << 24) + 728 (l1 << 16) + 729 (l2 << 8) + 730 (l3)); 731 732 _offset += sublen; 733 break; 734 735 case Column.INT: 736 _offset += 4; 737 break; 738 case Column.LONG: 739 case Column.DOUBLE: 740 case Column.DATE: 741 _offset += 8; 742 break; 743 744 case Column.BLOB: 745 _offset += 128; 746 break; 747 748 default: 749 throw new RuntimeException ("Unknown column: " + type); 750 } 751 } 752 } 753 754 757 public void startRow() 758 { 759 if (_orderIndex != null) 760 _orderIndex.add(_length); 761 762 _rowCount++; 763 } 764 765 768 public void writeNull() 769 { 770 write(Column.NONE); 771 } 772 773 776 public void writeString(String s) 777 { 778 write(Column.VARCHAR); 779 int stringLength = s.length(); 780 int length = 2 * stringLength; 781 write(length >> 24); 782 write(length >> 16); 783 write(length >> 8); 784 write(length); 785 786 for (int i = 0; i < stringLength; i++) { 787 char ch = s.charAt(i); 788 789 write(ch << 8); 790 write(ch); 791 } 792 } 793 794 797 public void writeString(byte []buffer, int offset, int stringLength) 798 { 799 int rLength = _length; 800 801 int rOffset = rLength & SIZE_MASK; 802 int rBlockId = rLength >> SIZE_BITS; 803 804 if (_buffers[rBlockId] == null) { 805 TempBuffer tempBuffer = TempBuffer.allocate(); 806 _tempBuffers[rBlockId] = tempBuffer; 807 _buffers[rBlockId] = tempBuffer.getBuffer(); 808 } 809 810 byte []rBuffer = _buffers[rBlockId]; 811 rBuffer[rOffset] = Column.VARCHAR; 812 813 int length = 2 * stringLength; 814 815 if (rOffset + 5 < rBuffer.length) { 816 rBuffer[rOffset + 1] = (byte) (length >> 24); 817 rBuffer[rOffset + 2] = (byte) (length >> 16); 818 rBuffer[rOffset + 3] = (byte) (length >> 8); 819 rBuffer[rOffset + 4] = (byte) length; 820 821 if (rOffset + 5 + length < rBuffer.length) { 822 System.arraycopy(buffer, offset, rBuffer, rOffset + 5, length); 823 824 _length = rLength + 5 + length; 825 } 826 else { 827 _length = rLength + 5; 828 write(buffer, offset, length); 829 } 830 } 831 else { 832 _length = rLength + 1; 833 834 write(length >> 24); 835 write(length >> 16); 836 write(length >> 8); 837 write(length); 838 839 write(buffer, offset, length); 840 } 841 } 842 843 846 public void writeBlock(int code, byte []buffer, int offset, int length) 847 { 848 write(code); 849 write(buffer, offset, length); 850 } 851 852 855 public void writeDouble(double dValue) 856 { 857 write(Column.DOUBLE); 858 859 long value = Double.doubleToLongBits(dValue); 860 861 write((int) (value >> 56)); 862 write((int) (value >> 48)); 863 write((int) (value >> 40)); 864 write((int) (value >> 32)); 865 write((int) (value >> 24)); 866 write((int) (value >> 16)); 867 write((int) (value >> 8)); 868 write((int) value); 869 } 870 871 874 public void writeLong(long value) 875 { 876 write(Column.LONG); 877 write((int) (value >> 56)); 878 write((int) (value >> 48)); 879 write((int) (value >> 40)); 880 write((int) (value >> 32)); 881 write((int) (value >> 24)); 882 write((int) (value >> 16)); 883 write((int) (value >> 8)); 884 write((int) value); 885 } 886 887 890 public void writeDate(long value) 891 { 892 write(Column.DATE); 893 write((int) (value >> 56)); 894 write((int) (value >> 48)); 895 write((int) (value >> 40)); 896 write((int) (value >> 32)); 897 write((int) (value >> 24)); 898 write((int) (value >> 16)); 899 write((int) (value >> 8)); 900 write((int) value); 901 } 902 903 906 public void writeInt(int value) 907 { 908 write(Column.INT); 909 write(value >> 24); 910 write(value >> 16); 911 write(value >> 8); 912 write(value); 913 } 914 915 918 public void writeBlob(byte []buffer, int offset) 919 { 920 write(Column.BLOB); 921 922 write(buffer, offset, 128); 923 } 924 925 928 private void seek(int offset) 929 { 930 _offset = offset; 931 } 932 933 936 private int read() 937 { 938 int offset = _offset; 939 940 if (_length <= offset) 941 return -1; 942 943 _offset = offset + 1; 944 945 byte []buf = _buffers[offset >> SIZE_BITS]; 946 947 return buf[offset & SIZE_MASK] & 0xff; 948 } 949 950 953 private int read(byte []buffer, int bufOffset, int bufLength) 954 { 955 int offset = _offset; 956 int length = _length; 957 byte [][]buffers = _buffers; 958 959 for (int i = bufLength; i > 0; i--) { 960 if (length <= offset) { 961 _offset = offset; 962 return -1; 963 } 964 965 byte []buf = buffers[offset >> SIZE_BITS]; 966 967 buffer[bufOffset] = buf[offset & SIZE_MASK]; 968 969 offset++; 970 bufOffset++; 971 } 972 973 _offset = offset; 974 975 return bufLength; 976 } 977 978 981 public void write(int value) 982 { 983 int length = _length; 984 int rOffset = length & SIZE_MASK; 985 int blockId = length >> SIZE_BITS; 986 987 byte []buffer = _buffers[blockId]; 988 989 if (buffer == null) { 990 TempBuffer tempBuffer = TempBuffer.allocate(); 991 _tempBuffers[blockId] = tempBuffer; 992 _buffers[blockId] = tempBuffer.getBuffer(); 993 994 buffer = _buffers[blockId]; 995 } 996 997 buffer[rOffset] = (byte) value; 998 999 _length = length + 1; 1000 } 1001 1002 1005 public void write(byte []buffer, int offset, int length) 1006 { 1007 int rLength = _length; 1008 1009 while (length > 0) { 1010 int rOffset = rLength & SIZE_MASK; 1011 1012 int rBufferId = rLength >> SIZE_BITS; 1013 1014 if (rOffset == 0) { 1015 TempBuffer tempBuffer = TempBuffer.allocate(); 1016 _tempBuffers[rBufferId] = tempBuffer; 1017 _buffers[rBufferId] = tempBuffer.getBuffer(); 1018 } 1019 1020 byte []rBuffer = _buffers[rBufferId]; 1021 1022 int sublen = rBuffer.length - rOffset; 1023 1024 if (length < sublen) 1025 sublen = length; 1026 1027 System.arraycopy(buffer, offset, rBuffer, rOffset, sublen); 1028 1029 length -= sublen; 1030 offset += sublen; 1031 rLength += sublen; 1032 } 1033 1034 _length = rLength; 1035 } 1036 1037 public void close() 1038 { 1039 for (int i = 0; i < _buffers.length; i++) { 1040 TempBuffer buffer = _tempBuffers[i]; 1041 1042 if (buffer != null) 1043 TempBuffer.free(buffer); 1044 1045 _tempBuffers[i] = null; 1046 _buffers[i] = null; 1047 } 1048 1049 _order = null; 1050 _orderIndex = null; 1051 1052 _freeList.free(this); 1053 } 1054} 1055 | Popular Tags |