1 28 29 package com.caucho.db.sql; 30 31 import com.caucho.db.ResultSetImpl; 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.L10N; 40 import com.caucho.util.QDate; 41 import com.caucho.vfs.ReadStream; 42 import com.caucho.vfs.TempBuffer; 43 import com.caucho.vfs.TempStream; 44 import com.caucho.vfs.WriteStream; 45 46 import java.io.IOException ; 47 import java.sql.SQLException ; 48 49 public class SelectResultSetImpl extends ResultSetImpl { 50 private static final L10N L = new L10N(SelectResultSetImpl.class); 51 52 private static final FreeList<SelectResultSetImpl> _freeList = 53 new FreeList<SelectResultSetImpl>(16); 54 55 private final WriteStream _ws; 56 private final TempBuffer _buf; 57 private final ReadStream _rs; 58 private final byte []_buffer; 59 private final CharBuffer _cb; 60 private final TempStream _ts; 61 62 private static QDate _date = new QDate(); 63 64 private Expr []_exprs; 65 private int []_types = new int[32]; 66 private int []_offsets = new int[32]; 67 private int []_lengths = new int[32]; 68 private Store []_stores = new Store[32]; 69 70 private TableIterator []_rows; 71 private int _rowLength; 72 73 private int _lastColumn; 74 75 private SelectResultSetImpl() 76 { 77 _ws = new WriteStream(); 78 _ws.setReuseBuffer(true); 79 _ts = new TempStream(); 80 _rs = new ReadStream(); 81 _rs.setReuseBuffer(true); 82 _buf = TempBuffer.allocate(); 83 _buffer = _buf.getBuffer(); 84 _cb = new CharBuffer(); 85 86 _rows = new TableIterator[0]; 87 } 88 89 public static SelectResultSetImpl create(Expr []exprs) 90 { 91 SelectResultSetImpl rs = _freeList.allocate(); 92 93 if (rs == null) 94 rs = new SelectResultSetImpl(); 95 96 rs.init(exprs); 97 98 return rs; 99 } 100 101 TableIterator []initRows(FromItem []fromItems) 102 { 103 if (_rows.length < fromItems.length) 104 _rows = new TableIterator[fromItems.length]; 105 106 for (int i = 0; i < fromItems.length; i++) { 107 if (_rows[i] == null) 108 _rows[i] = new TableIterator(); 109 _rows[i].init(fromItems[i].getTable()); 110 } 111 112 return _rows; 113 } 114 115 116 private void init(Expr []exprs) 117 { 118 _exprs = exprs; 119 120 if (_offsets.length < _exprs.length) { 121 _offsets = new int[exprs.length]; 122 _lengths = new int[exprs.length]; 123 _types = new int[exprs.length]; 124 _stores = new Store[exprs.length]; 125 } 126 127 for (int i = 0; i < exprs.length; i++) { 128 _stores[i] = exprs[i].getTable(); 129 } 130 } 131 132 void initRead() 133 throws IOException 134 { 135 _ts.openRead(_rs, true); 136 } 137 138 WriteStream getWriteStream() 139 { 140 _ts.openWrite(); 141 _ws.init(_ts); 142 143 return _ws; 144 } 145 146 public boolean next() 147 throws SQLException 148 { 149 try { 150 ReadStream rs = _rs; 151 152 _lastColumn = 0; 153 154 int hasData = rs.read(); 155 if (hasData <= 0) 156 return false; 157 158 int length = 0; 159 int fields = _exprs.length; 160 161 byte []buffer = _buffer; 162 for (int i = 0; i < fields; i++) { 163 int type = rs.read(); 164 165 int sublen = 0; 166 167 switch (type) { 168 case Column.NONE: 169 sublen = -1; 170 break; 171 172 case Column.VARCHAR: 173 int l0 = rs.read(); 174 int l1 = rs.read(); 175 int l2 = rs.read(); 176 int l3 = rs.read(); 177 178 sublen = ((l0 << 24) + 179 (l1 << 16) + 180 (l2 << 8) + 181 (l3)); 182 break; 183 184 case Column.INT: 185 sublen = 4; 186 break; 187 case Column.LONG: 188 case Column.DOUBLE: 189 case Column.DATE: 190 sublen = 8; 191 break; 192 193 case Column.BLOB: 194 sublen = 128; 195 break; 196 197 default: 198 throw new SQLException ("Unknown column: " + type); 199 } 200 201 _types[i] = type; 202 _offsets[i] = length; 203 _lengths[i] = sublen; 204 205 if (sublen > 0) { 206 rs.read(buffer, length, sublen); 207 208 length += sublen; 209 } 210 } 211 212 return true; 213 } catch (IOException e) { 214 throw new SQLExceptionWrapper(e); 215 } 216 } 217 218 221 public int findColumnIndex(String name) 222 throws SQLException 223 { 224 for (int i = 0; i < _exprs.length; i++) { 225 if (_exprs[i].getName().equals(name)) 226 return i + 1; 227 } 228 229 throw new SQLException (L.l("column `{0}' does not exist.", name)); 230 } 231 232 235 public String getString(int index) 236 throws SQLException 237 { 238 _lastColumn = index; 239 240 byte []buffer = _buffer; 241 int offset = _offsets[index]; 242 int length = _lengths[index]; 243 244 switch (_types[index]) { 245 case Column.NONE: 246 return null; 247 248 case Column.INT: 249 { 250 int value = (((buffer[offset] & 0xff) << 24) + 251 ((buffer[offset + 1] & 0xff) << 16) + 252 ((buffer[offset + 2] & 0xff) << 8) + 253 ((buffer[offset + 3] & 0xff))); 254 255 return String.valueOf(value); 256 } 257 258 case Column.LONG: 259 { 260 long value = (((buffer[offset + 0] & 0xffL) << 56) + 261 ((buffer[offset + 1] & 0xffL) << 48) + 262 ((buffer[offset + 2] & 0xffL) << 40) + 263 ((buffer[offset + 3] & 0xffL) << 32) + 264 ((buffer[offset + 4] & 0xffL) << 24) + 265 ((buffer[offset + 5] & 0xffL) << 16) + 266 ((buffer[offset + 6] & 0xffL) << 8) + 267 ((buffer[offset + 7] & 0xffL))); 268 return String.valueOf(value); 269 } 270 271 case Column.DOUBLE: 272 { 273 long value = (((buffer[offset + 0] & 0xffL) << 56) + 274 ((buffer[offset + 1] & 0xffL) << 48) + 275 ((buffer[offset + 2] & 0xffL) << 40) + 276 ((buffer[offset + 3] & 0xffL) << 32) + 277 ((buffer[offset + 4] & 0xffL) << 24) + 278 ((buffer[offset + 5] & 0xffL) << 16) + 279 ((buffer[offset + 6] & 0xffL) << 8) + 280 ((buffer[offset + 7] & 0xffL))); 281 return String.valueOf(Double.longBitsToDouble(value)); 282 } 283 284 case Column.DATE: 285 { 286 long value = (((buffer[offset + 0] & 0xffL) << 56) + 287 ((buffer[offset + 1] & 0xffL) << 48) + 288 ((buffer[offset + 2] & 0xffL) << 40) + 289 ((buffer[offset + 3] & 0xffL) << 32) + 290 ((buffer[offset + 4] & 0xffL) << 24) + 291 ((buffer[offset + 5] & 0xffL) << 16) + 292 ((buffer[offset + 6] & 0xffL) << 8) + 293 ((buffer[offset + 7] & 0xffL))); 294 return QDate.formatGMT(value); 295 } 296 297 case Column.VARCHAR: 298 return getStringValue(index); 299 300 case Column.BLOB: 301 return getBlobString(index); 302 303 default: 304 return null; 305 } 306 } 307 308 311 private String getStringValue(int index) 312 throws SQLException 313 { 314 _lastColumn = index; 315 316 int length = _lengths[index]; 317 int offset = _offsets[index]; 318 319 if (length < 0) 320 return null; 321 322 CharBuffer cb = _cb; 323 cb.clear(); 324 325 byte []buffer = _buffer; 326 for (; length > 0; length--) { 327 cb.append((char) buffer[offset++]); 328 } 329 330 return cb.toString(); 331 } 332 333 336 private String getBlobString(int index) 337 throws SQLException 338 { 339 _lastColumn = index; 340 341 int offset = _offsets[index]; 342 343 CharBuffer cb = _cb; 344 cb.clear(); 345 346 BlobInputStream is = null; 347 try { 348 is = new BlobInputStream(_stores[index], _buffer, offset); 349 350 int ch; 351 while ((ch = is.read()) >= 0) { 352 if (ch < 0x80) 353 cb.append((char) ch); 354 } 355 } catch (IOException e) { 356 throw new SQLExceptionWrapper(e); 357 } 358 359 return cb.toString(); 360 } 361 362 public int getInt(int index) 363 throws SQLException 364 { 365 _lastColumn = index; 366 367 byte []buffer = _buffer; 368 int offset = _offsets[index]; 369 int length = _lengths[index]; 370 371 switch (_types[index]) { 372 case Column.NONE: 373 return 0; 374 375 case Column.INT: 376 return (((buffer[offset + 0] & 0xff) << 24) + 377 ((buffer[offset + 1] & 0xff) << 16) + 378 ((buffer[offset + 2] & 0xff) << 8) + 379 ((buffer[offset + 3] & 0xff))); 380 381 case Column.LONG: 382 { 383 long value = (((buffer[offset + 0] & 0xffL) << 56) + 384 ((buffer[offset + 1] & 0xffL) << 48) + 385 ((buffer[offset + 2] & 0xffL) << 40) + 386 ((buffer[offset + 3] & 0xffL) << 32) + 387 ((buffer[offset + 4] & 0xffL) << 24) + 388 ((buffer[offset + 5] & 0xffL) << 16) + 389 ((buffer[offset + 6] & 0xffL) << 8) + 390 ((buffer[offset + 7] & 0xffL))); 391 return (int) value; 392 } 393 394 case Column.DOUBLE: 395 { 396 long value = (((buffer[offset + 0] & 0xffL) << 56) + 397 ((buffer[offset + 1] & 0xffL) << 48) + 398 ((buffer[offset + 2] & 0xffL) << 40) + 399 ((buffer[offset + 3] & 0xffL) << 32) + 400 ((buffer[offset + 4] & 0xffL) << 24) + 401 ((buffer[offset + 5] & 0xffL) << 16) + 402 ((buffer[offset + 6] & 0xffL) << 8) + 403 ((buffer[offset + 7] & 0xffL))); 404 return (int) Double.longBitsToDouble(value); 405 } 406 407 case Column.VARCHAR: 408 return Integer.parseInt(getString(index)); 409 410 default: 411 return 0; 412 } 413 } 414 415 public long getLong(int index) 416 throws SQLException 417 { 418 _lastColumn = index; 419 420 byte []buffer = _buffer; 421 int offset = _offsets[index]; 422 int length = _lengths[index]; 423 424 switch (_types[index]) { 425 case Column.NONE: 426 return 0; 427 428 case Column.INT: 429 return (((buffer[offset] & 0xff) << 24) + 430 ((buffer[offset + 1] & 0xff) << 16) + 431 ((buffer[offset + 2] & 0xff) << 8) + 432 ((buffer[offset + 3] & 0xff))); 433 434 case Column.LONG: 435 case Column.DATE: 436 { 437 long value = (((buffer[offset + 0] & 0xffL) << 56) + 438 ((buffer[offset + 1] & 0xffL) << 48) + 439 ((buffer[offset + 2] & 0xffL) << 40) + 440 ((buffer[offset + 3] & 0xffL) << 32) + 441 ((buffer[offset + 4] & 0xffL) << 24) + 442 ((buffer[offset + 5] & 0xffL) << 16) + 443 ((buffer[offset + 6] & 0xffL) << 8) + 444 ((buffer[offset + 7] & 0xffL))); 445 return value; 446 } 447 448 case Column.DOUBLE: 449 { 450 long value = (((buffer[offset + 0] & 0xffL) << 56) + 451 ((buffer[offset + 1] & 0xffL) << 48) + 452 ((buffer[offset + 2] & 0xffL) << 40) + 453 ((buffer[offset + 3] & 0xffL) << 32) + 454 ((buffer[offset + 4] & 0xffL) << 24) + 455 ((buffer[offset + 5] & 0xffL) << 16) + 456 ((buffer[offset + 6] & 0xffL) << 8) + 457 ((buffer[offset + 7] & 0xffL))); 458 return (long) Double.longBitsToDouble(value); 459 } 460 461 case Column.VARCHAR: 462 return Long.parseLong(getString(index)); 463 464 default: 465 return 0; 466 } 467 } 468 469 472 public double getDouble(int index) 473 throws SQLException 474 { 475 _lastColumn = index; 476 477 byte []buffer = _buffer; 478 int offset = _offsets[index]; 479 int length = _lengths[index]; 480 481 switch (_types[index]) { 482 case Column.NONE: 483 return 0; 484 485 case Column.INT: 486 return (((buffer[offset + 0] & 0xff) << 24) + 487 ((buffer[offset + 1] & 0xff) << 16) + 488 ((buffer[offset + 2] & 0xff) << 8) + 489 ((buffer[offset + 3] & 0xff))); 490 491 case Column.LONG: 492 { 493 long value = (((buffer[offset + 0] & 0xffL) << 56) + 494 ((buffer[offset + 1] & 0xffL) << 48) + 495 ((buffer[offset + 2] & 0xffL) << 40) + 496 ((buffer[offset + 3] & 0xffL) << 32) + 497 ((buffer[offset + 4] & 0xffL) << 24) + 498 ((buffer[offset + 5] & 0xffL) << 16) + 499 ((buffer[offset + 6] & 0xffL) << 8) + 500 ((buffer[offset + 7] & 0xffL))); 501 return value; 502 } 503 504 case Column.DOUBLE: 505 { 506 long value = (((buffer[offset + 0] & 0xffL) << 56) + 507 ((buffer[offset + 1] & 0xffL) << 48) + 508 ((buffer[offset + 2] & 0xffL) << 40) + 509 ((buffer[offset + 3] & 0xffL) << 32) + 510 ((buffer[offset + 4] & 0xffL) << 24) + 511 ((buffer[offset + 5] & 0xffL) << 16) + 512 ((buffer[offset + 6] & 0xffL) << 8) + 513 ((buffer[offset + 7] & 0xffL))); 514 return Double.longBitsToDouble(value); 515 } 516 517 case Column.VARCHAR: 518 return Double.parseDouble(getString(index)); 519 520 default: 521 return 0; 522 } 523 } 524 525 public long getDate(int index) 526 throws SQLException 527 { 528 _lastColumn = index; 529 530 byte []buffer = _buffer; 531 int offset = _offsets[index]; 532 int length = _lengths[index]; 533 534 switch (_types[index]) { 535 case Column.NONE: 536 return 0; 537 538 case Column.LONG: 539 case Column.DATE: 540 { 541 long value = (((buffer[offset + 0] & 0xffL) << 56) + 542 ((buffer[offset + 1] & 0xffL) << 48) + 543 ((buffer[offset + 2] & 0xffL) << 40) + 544 ((buffer[offset + 3] & 0xffL) << 32) + 545 ((buffer[offset + 4] & 0xffL) << 24) + 546 ((buffer[offset + 5] & 0xffL) << 16) + 547 ((buffer[offset + 6] & 0xffL) << 8) + 548 ((buffer[offset + 7] & 0xffL))); 549 return value; 550 } 551 552 case Column.VARCHAR: 553 case Column.BLOB: 554 { 555 String value = getString(index); 556 557 if (value == null) 558 return 0; 559 560 synchronized (_date) { 561 try { 562 return _date.parseDate(value); 563 } catch (Exception e) { 564 throw new SQLExceptionWrapper(e); 565 } 566 } 567 } 568 569 default: 570 throw new SQLException ("unknown type:" + _types[index]); 571 } 572 } 573 574 577 public boolean wasNull() 578 { 579 if (_lastColumn < 0) 580 return false; 581 else 582 return _lengths[_lastColumn] < 0; 583 } 584 585 public void close() 586 { 587 _freeList.free(this); 588 } 589 } 590 | Popular Tags |