1 65 66 67 package org.hsqldb; 68 69 import org.hsqldb.index.RowIterator; 70 import org.hsqldb.lib.ArrayUtil; 71 import org.hsqldb.lib.HashMappedList; 72 73 78 88 final class TableFilter { 89 90 static final int CONDITION_NONE = -1; static final int CONDITION_UNORDERED = 0; static final int CONDITION_START_END = 1; static final int CONDITION_START = 2; static final int CONDITION_END = 3; static final int CONDITION_OUTER = 4; Table filterTable; 97 private String tableAlias; 98 HashMappedList columnAliases; 99 Index filterIndex; 100 private Object [] emptyData; 101 boolean[] usedColumns; 102 private Expression eStart, eEnd; 103 104 Expression eAnd; 106 107 boolean isOuterJoin; boolean isAssigned; boolean isMultiFindFirst; Expression[] findFirstExpressions; 113 private RowIterator it; 115 Object [] currentData; 116 Row currentRow; 117 118 Object [] currentJoinData; 120 121 boolean nonJoinIsNull; 124 125 boolean isCurrentOuter; 127 128 136 TableFilter(Table t, String alias, HashMappedList columnList, 137 boolean outerjoin) { 138 139 filterTable = t; 140 tableAlias = alias == null ? t.getName().name 141 : alias; 142 columnAliases = columnList; 143 isOuterJoin = outerjoin; 144 emptyData = filterTable.getEmptyRowData(); 145 usedColumns = filterTable.getNewColumnCheckList(); 146 } 147 148 153 String getName() { 154 return tableAlias; 155 } 156 157 162 Table getTable() { 163 return filterTable; 164 } 165 166 173 static int getConditionType(Expression e) { 174 175 int exprType = e.getType(); 176 177 switch (exprType) { 178 179 case Expression.NOT_EQUAL : 180 case Expression.LIKE : 181 return CONDITION_UNORDERED; 182 183 case Expression.IN : { 184 return e.isQueryCorrelated ? CONDITION_NONE 185 : CONDITION_UNORDERED; 186 } 187 case Expression.IS_NULL : 188 case Expression.EQUAL : { 189 return CONDITION_START_END; 190 } 191 case Expression.BIGGER : 192 case Expression.BIGGER_EQUAL : { 193 return CONDITION_START; 194 } 195 case Expression.SMALLER : 196 case Expression.SMALLER_EQUAL : { 197 return CONDITION_END; 198 } 199 default : { 200 201 return CONDITION_NONE; 203 } 204 } 205 } 206 207 295 303 void setConditions(Session session, 304 Expression condition) throws HsqlException { 305 306 setCondition(session, condition); 307 308 if (filterIndex == null) { 309 filterIndex = filterTable.getPrimaryIndex(); 310 } 311 312 if (filterIndex.getVisibleColumns() == 1 || eStart == null 313 || eAnd == null || eStart.exprType != Expression.EQUAL) { 314 return; 315 } 316 317 boolean[] check = filterTable.getNewColumnCheckList(); 318 Expression[] expr = new Expression[check.length]; 319 int colindex = eStart.getArg().getColumnNr(); 320 321 check[colindex] = true; 322 expr[colindex] = eStart.getArg2(); 323 324 eAnd.getEquiJoinColumns(this, check, expr); 325 326 if (ArrayUtil.containsAllTrueElements(check, filterIndex.colCheck)) { 327 isMultiFindFirst = true; 328 findFirstExpressions = expr; 329 } 330 } 331 332 private void setCondition(Session session, 333 Expression e) throws HsqlException { 334 335 int type = e.getType(); 336 Expression e1 = e.getArg(); 337 Expression e2 = e.getArg2(); 338 339 isAssigned = true; 340 341 if (type == Expression.AND) { 342 setCondition(session, e1); 343 setCondition(session, e2); 344 345 return; 346 } 347 348 if (type == Expression.OR && isOuterJoin && e.isInJoin 349 && e.outerFilter == this) { 350 addAndCondition(e); 351 e.setTrue(); 352 353 return; 354 } 355 356 int conditionType = getConditionType(e); 357 358 if (conditionType == CONDITION_NONE) { 359 360 return; 362 } 363 364 if (e1.getFilter() == this && e2.getFilter() == this) { 366 conditionType = CONDITION_UNORDERED; 367 } else if (e1.getFilter() == this) { 368 if (!e.isInJoin && isOuterJoin) { 369 370 return; 372 } 373 374 } else if ((e2.getFilter() == this) 376 && (conditionType != CONDITION_UNORDERED)) { 377 378 e.swapCondition(); 380 setCondition(session, e); 381 382 return; 383 } else if (e1.outerFilter == this) { 384 385 conditionType = CONDITION_OUTER; 387 } else { 388 389 return; 391 } 392 393 if (!e2.isResolved()) { 395 return; 396 } 397 398 if (e1.outerFilter != null && e1.outerFilter != this) { 400 return; 401 } 402 403 if (conditionType == CONDITION_UNORDERED) { 404 addAndCondition(e); 405 406 return; 407 } 408 409 if (conditionType == CONDITION_OUTER) { 410 addAndCondition(e); 411 412 return; 413 } 414 415 int i = e1.getColumnNr(); 416 Index index = filterTable.getIndexForColumn(session, i); 417 418 if (index == null || (filterIndex != index && filterIndex != null)) { 419 addAndCondition(e); 420 421 return; 422 } 423 424 filterIndex = index; 425 426 switch (conditionType) { 427 428 case CONDITION_START_END : { 429 430 if ((eStart != null) || (eEnd != null)) { 432 addAndCondition(e); 433 434 return; 435 } 436 437 eStart = new Expression(e); 438 eEnd = eStart; 439 440 break; 441 } 442 case CONDITION_START : { 443 444 if (eStart != null) { 446 addAndCondition(e); 447 448 return; 449 } 450 451 eStart = new Expression(e); 452 453 break; 454 } 455 case CONDITION_END : { 456 457 if (eEnd != null) { 459 addAndCondition(e); 460 461 return; 462 } 463 464 eEnd = new Expression(e); 465 466 break; 467 } 468 } 469 470 e.setTrue(); 471 } 472 473 480 boolean findFirst(Session session) throws HsqlException { 481 482 nonJoinIsNull = false; 483 isCurrentOuter = false; 484 485 if (filterIndex == null) { 486 filterIndex = filterTable.getPrimaryIndex(); 487 } 488 489 if (isMultiFindFirst) { 490 boolean convertible = true; 491 int[] types = filterTable.getColumnTypes(); 492 493 currentJoinData = filterTable.getEmptyRowData(); 494 495 for (int i = 0; i < findFirstExpressions.length; i++) { 496 Expression e = findFirstExpressions[i]; 497 498 if (e != null) { 499 Object value = e.getValue(session); 500 501 if (Column.compareToTypeRange(value, types[i]) != 0) { 502 convertible = false; 503 504 break; 505 } 506 507 value = Column.convertObject(value, types[i]); 508 currentJoinData[i] = e.getValue(session, types[i]); 509 } 510 } 511 512 it = convertible 513 ? filterIndex.findFirstRow(session, currentJoinData) 514 : filterIndex.emptyIterator(); 515 516 if (!it.hasNext()) { 517 ArrayUtil.clearArray(ArrayUtil.CLASS_CODE_OBJECT, 518 currentJoinData, 0, 519 currentJoinData.length); 520 } 521 } else if (eStart == null) { 522 it = eEnd == null ? filterIndex.firstRow(session) 523 : filterIndex.findFirstRowNotNull(session); 524 } else { 525 Object value = eStart.getArg2().getValue(session); 526 int valuetype = eStart.getArg2().getDataType(); 527 int targettype = eStart.getArg().getDataType(); 528 529 it = getFirstIterator(session, eStart.getType(), value, 530 valuetype, filterIndex, targettype); 531 } 532 533 while (true) { 534 currentRow = it.next(); 535 536 if (currentRow == null) { 537 break; 538 } 539 540 currentData = currentRow.getData(); 541 542 if (!(eEnd == null || eEnd.testCondition(session))) { 543 break; 544 } 545 546 if (eAnd == null || eAnd.testCondition(session)) { 547 return true; 548 } 549 } 550 551 currentRow = null; 552 currentData = emptyData; 553 554 return false; 555 } 556 557 static RowIterator getFirstIterator(Session session, int eType, 558 Object value, int valueType, 559 Index index, 560 int targetType) throws HsqlException { 561 562 RowIterator it; 563 int range = 0; 564 565 if (targetType != valueType) { 566 range = Column.compareToTypeRange(value, targetType); 567 } 568 569 if (range == 0) { 570 value = Column.convertObject(value, targetType); 571 it = index.findFirstRow(session, value, eType); 572 } else { 573 switch (eType) { 574 575 case Expression.BIGGER_EQUAL : 576 case Expression.BIGGER : 577 if (range < 0) { 578 it = index.findFirstRowNotNull(session); 579 580 break; 581 } 582 default : 583 it = index.emptyIterator(); 584 } 585 } 586 587 return it; 588 } 589 590 597 boolean next(Session session) throws HsqlException { 598 599 boolean result = false; 600 601 nonJoinIsNull = false; 602 isCurrentOuter = false; 603 604 while (true) { 605 currentRow = it.next(); 606 607 if (currentRow == null) { 608 break; 609 } 610 611 currentData = currentRow.getData(); 612 613 if (!(eEnd == null || eEnd.testCondition(session))) { 614 break; 615 } 616 617 if (eAnd == null || eAnd.testCondition(session)) { 618 result = true; 619 620 break; 621 } 622 } 623 624 if (result) { 625 return true; 626 } 627 628 currentRow = null; 629 currentData = emptyData; 630 631 return false; 632 } 633 634 boolean nextOuter(Session session) throws HsqlException { 635 636 nonJoinIsNull = false; 637 isCurrentOuter = true; 638 currentData = emptyData; 639 currentRow = null; 640 641 return eAnd == null || (eAnd.getFilter() != this && eAnd.isInJoin) 642 || eAnd.testCondition(session); 643 } 644 645 652 private void addAndCondition(Expression e) { 653 654 Expression e2 = new Expression(e); 655 656 if (eAnd == null) { 657 eAnd = e2; 658 } else { 659 Expression and = new Expression(Expression.AND, eAnd, e2); 660 661 eAnd = and; 662 } 663 664 e.setTrue(); 665 } 666 667 671 void setAsCheckFilter() { 672 filterIndex = null; 673 } 674 675 677 685 public String describe(Session session) { 686 687 StringBuffer sb; 688 String temp; 689 Index index; 690 Index primaryIndex; 691 int[] primaryKey; 692 boolean hidden; 693 boolean fullScan; 694 695 sb = new StringBuffer (); 696 index = filterIndex; 697 primaryIndex = filterTable.getPrimaryIndex(); 698 primaryKey = filterTable.getPrimaryKey(); 699 hidden = false; 700 fullScan = (eStart == null && eEnd == null); 701 702 if (index == null) { 703 index = primaryIndex; 704 } 705 706 if (index == primaryIndex && primaryKey.length == 0) { 707 hidden = true; 708 fullScan = true; 709 } 710 711 sb.append(super.toString()).append('\n'); 712 sb.append("table=[").append(filterTable.getName().name).append("]\n"); 713 sb.append("alias=[").append(tableAlias).append("]\n"); 714 sb.append("access=[").append(fullScan ? "FULL SCAN" 715 : "INDEX PRED").append("]\n"); 716 sb.append("index=["); 717 sb.append(index == null ? "NONE" 718 : index.getName() == null ? "UNNAMED" 719 : index.getName() 720 .name); 721 sb.append(hidden ? "[HIDDEN]]\n" 722 : "]\n"); 723 sb.append("isOuterJoin=[").append(isOuterJoin).append("]\n"); 724 725 temp = eStart == null ? "null" 726 : eStart.describe(session); 727 728 sb.append("eStart=[").append(temp).append("]\n"); 729 730 temp = eEnd == null ? "null" 731 : eEnd.describe(session); 732 733 sb.append("eEnd=[").append(temp).append("]\n"); 734 735 temp = eAnd == null ? "null" 736 : eAnd.describe(session); 737 738 sb.append("eAnd=[").append(temp).append("]"); 739 740 return sb.toString(); 741 } 742 } 743 | Popular Tags |