1 22 23 package org.xquark.mediator.plan; 24 25 import java.util.ArrayList ; 26 27 import org.xquark.mediator.DOMUtils.DOMUtils; 28 import org.xquark.mediator.DOMUtils.SortedKeyMap; 29 import org.xquark.mediator.DOMUtils.Tuple; 30 import org.xquark.mediator.decomposer.Utils; 31 import org.xquark.mediator.runtime.MediatorException; 32 import org.xquark.xml.xdbc.XMLDBCException; 33 import org.xquark.xquery.parser.ListOpCompExpression; 34 import org.xquark.xquery.parser.util.Constants; 35 36 37 public class OpSortMerge extends OpBin { 38 private static final String RCSRevision = "$Revision: 1.15 $"; 42 private static final String RCSName = "$Name: $"; 43 private ArrayList restrictions = null; 50 51 public OpSortMerge(ExecutionPlan plan, Operator[] children, ArrayList restrictions) throws MediatorException { 52 super(plan, null, children); 53 this.restrictions = restrictions; 54 init(); 55 } 56 57 public OpSortMerge(ExecutionPlan plan, Operator left, Operator right, ArrayList restrictions) throws MediatorException { 58 super(plan, null, left, right); 59 this.restrictions = restrictions; 60 init(); 61 } 62 63 private void init() throws MediatorException { 64 ArrayList childpaths1 = getLeftAlgebra().getPathsList(); 67 ArrayList childpaths2 = getRightAlgebra().getPathsList(); 68 size = getLeftAlgebra().getSize() + getRightAlgebra().getSize(); 69 70 80 idsize = getLeftAlgebra().getIdSize() + getRightAlgebra().getIdSize(); 84 92 ordertype = ORDER_PARALLELIZATION; 93 94 if (restrictions != null) { 95 for (int i = 0; i < restrictions.size(); i++) { 96 int typ = ((ListOpCompExpression) restrictions.get(i)).getOperator(); 97 if (typ != Constants.EQ_COMPOP) { 98 if (i != restrictions.size() - 1) 99 throw new MediatorException("Incorrect restriction type, not yet supported"); 100 if (typ != Constants.LEQ_COMPOP && typ != Constants.LT_COMPOP && typ != Constants.GEQ_COMPOP && typ != Constants.GT_COMPOP) 101 throw new MediatorException("Incorrect restriction type, not yet supported"); 102 } 103 } 104 } 105 } 106 107 public ArrayList getRestrictions() { 108 return this.restrictions; 109 } 110 111 115 public void accept(OperatorVisitor visitor) throws MediatorException { 116 visitor.visit(this); 117 } 118 119 125 protected ResultSet getResultSet(DynamicContext context, OperatorRunnable[] children) throws MediatorException { 126 try { 127 return new SortMergeResultSet(this, context, children); 128 } catch (XMLDBCException e) { 129 throw new MediatorException("Can't construct " + getClass() + ": " + e.getMessage()); 131 } 132 } 133 134 143 145 149 public String toCompleteString(int indent) { 150 StringBuffer buf = new StringBuffer (); 151 buf.append(Utils.makeIndent(indent) + "<" + getClass().getName() + " isLet=\"" + islet + "\" valueDepends=\"" + valueDepends + "\" whereDepends=\"" + whereDepends + "\">\n") ; 152 buf.append(Utils.makeIndent(indent + 1) + "<Expression>\n"); 153 buf.append(Utils.makeIndent(indent + 2) + expression + "\n"); 154 buf.append(Utils.makeIndent(indent + 1) + "</Expression>\n"); 155 if (paths != null) { 163 buf.append(Utils.makeIndent(indent + 1) + "<Paths>\n"); 164 for (int i = 0; i < paths.size(); i++) { 165 buf.append(Utils.makeIndent(indent + 2) + "<Path>" + paths.get(i) + "</Path>\n"); 166 } 167 buf.append(Utils.makeIndent(indent + 1) + "</Paths>\n"); 168 } 169 if (restrictions != null) { 170 buf.append(Utils.makeIndent(indent + 1) + "<Restrictions>\n"); 171 for (int i = 0; i < restrictions.size(); i++) { 172 buf.append(Utils.makeIndent(indent + 2) + "<Restriction>" + restrictions.get(i) + "</Restriction>\n"); 173 } 174 buf.append(Utils.makeIndent(indent + 1) + "</Restrictions>\n"); 175 } 176 buf.append(Utils.makeIndent(indent + 1) + "<Elements>\n"); 177 for (int i = 0; i < childrenOperator.length; i++) { 178 buf.append(Utils.makeIndent(indent + 2) + "<Element" + (i + 1) + ">\n"); 179 buf.append(childrenOperator[i].toCompleteString(indent + 3)); 180 buf.append(Utils.makeIndent(indent + 2) + "</Element" + (i + 1) + ">\n"); 181 } 182 buf.append(Utils.makeIndent(indent + 1) + "</Elements>\n"); 183 buf.append(Utils.makeIndent(indent) + "</" + getClass().getName() + ">\n"); 184 return buf.toString(); 185 } 186 187 } 188 189 class SortMergeResultSet extends BinResultSet { 190 private static final String RCSRevision = "$Revision: 1.15 $"; 194 private static final String RCSName = "$Name: $"; 195 private int size = 0; 196 private Tuple left = null; 197 private Tuple right = null; 198 private Tuple nextright = null; 199 private ArrayList leftstrings = null; 200 private ArrayList rightstrings = null; 201 private ArrayList leftbuffer = null; 202 private ArrayList rightbuffer = null; 203 private int operatorNEQ = 0; boolean hasIndex = false; 205 private SortedKeyMap tm0 = null; 206 private SortedKeyMap tm1 = null; 207 208 214 public SortMergeResultSet(OpSortMerge operator, DynamicContext context, OperatorRunnable[] children) throws XMLDBCException { 215 super(operator, context, children); 216 size = operator.getRestrictions().size(); 217 leftstrings = new ArrayList (size); 218 rightstrings = new ArrayList (size); 219 for (int i = 0; i < size; i++) { 220 leftstrings.add(((ListOpCompExpression) operator.getRestrictions().get(i)).getExpression1().getStringValue()); 221 rightstrings.add(((ListOpCompExpression) operator.getRestrictions().get(i)).getExpression2().getStringValue()); 222 } 223 if (operator.getRestrictions() != null && !operator.getRestrictions().isEmpty()) 224 operatorNEQ = ((ListOpCompExpression) operator.getRestrictions().get(size - 1)).getOperator(); 225 leftbuffer = new ArrayList (); 226 rightbuffer = new ArrayList (); 227 228 } 229 230 239 protected void evaluate(boolean non_blocking) throws MediatorException { 240 241 243 Tuple leftfront = null; 244 Tuple rightfront = null; 245 if (hasIndex || (children[0] != null && children[0].getOperator().getIndexSpec(0) != null && children[1] != null && children[1].getOperator().getIndexSpec(0) != null)) { 247 if (!hasIndex) { 248 if (!children[0].getResultSet().hasNext() || !children[1].getResultSet().hasNext()) { 249 setFinishedWhenEmpty(); 250 children[0].getResultSet().close(); 251 children[1].getResultSet().close(); 252 return; 253 } 254 while (children[0].getResultSet().hasNext()) 255 children[0].getResultSet().next(); 256 tm0 = children[0].getResultSet().getIndex(0); 257 tm0.makeIterator(); 258 children[0].getResultSet().close(); 259 while (children[1].getResultSet().hasNext()) 260 children[1].getResultSet().next(); 261 tm1 = children[1].getResultSet().getIndex(0); 262 tm1.makeIterator(); 263 children[1].getResultSet().close(); 264 hasIndex = true; 265 } 266 if (operatorNEQ == 0) { 267 while (true) { 268 if (left == null || right == null) 269 if (!tm0.hasNext() || !tm1.hasNext()) { 270 setFinishedWhenEmpty(); 271 children[0].getResultSet().close(); 272 children[1].getResultSet().close(); 273 return; 274 } 275 if (left == null) { 277 left = tm0.next(); 278 } 279 if (right == null) { 280 right = tm1.next(); 281 } 282 while (left != null && right != null) { 283 int num = 0; 284 while (num < size) { 285 int res = DOMUtils.simpleCompareNodeValue(left.getPath((String ) leftstrings.get(num)),right.getPath((String ) rightstrings.get(num))); 286 if (res == 0) 287 num++; 288 else { 289 if (res < 0) { 290 if (tm0.hasNext()) { 291 left = tm0.next(); 292 } else 293 left = null; 294 } else if (res > 0) { 295 if (tm1.hasNext()) { 296 right = tm1.next(); 297 } else 298 right = null; 299 } 300 break; 301 } 302 } 303 if (num == size) 304 break; 305 } 306 if (left == null || right == null) { 307 setFinishedWhenEmpty(); 308 children[0].getResultSet().close(); 309 children[1].getResultSet().close(); 310 return; 311 } 312 leftbuffer.clear(); 314 leftbuffer.add(left); 315 rightbuffer.clear(); 316 rightbuffer.add(right); 317 while (true) { 319 leftfront = null; 320 if (tm0.hasNext()) { 321 leftfront = tm0.next(); 322 int num = 0; 323 while (num < size) { 324 int res = DOMUtils.simpleCompareNodeValue(left.getPath((String ) leftstrings.get(num)),leftfront.getPath((String ) leftstrings.get(num))); 325 if (res == 0) 326 num++; 327 else 328 break; 329 } 330 if (num == size) { 331 leftbuffer.add(leftfront); 332 left = leftfront; 333 } else 334 break; 335 } else 336 break; 337 338 } 339 while (true) { 341 rightfront = null; 342 if (tm1.hasNext()) { 343 rightfront = tm1.next(); 344 int num = 0; 345 while (num < size) { 346 int res = DOMUtils.simpleCompareNodeValue(right.getPath((String ) rightstrings.get(num)), rightfront.getPath((String ) rightstrings.get(num))); 347 if (res == 0) 348 num++; 349 else 350 break; 351 } 352 if (num == size) { 353 rightbuffer.add(rightfront); 354 right = rightfront; 355 } else { 356 break; 357 } 358 } else 359 break; 360 } 361 for (int i = 0; i < leftbuffer.size(); i++) { 363 for (int j = 0; j < rightbuffer.size(); j++) { 364 this.buftuples.add(((Tuple) leftbuffer.get(i)).merge((Tuple) rightbuffer.get(j), operator)); 365 } 366 } 367 left = leftfront; 368 right = rightfront; 369 if (non_blocking) { 370 if ((buftuples != null) && (!buftuples.isEmpty())) 371 break; 372 } 373 } 374 } else { 376 while (true) { 377 if (!tm0.hasNext()) { 378 setFinishedWhenEmpty(); 379 children[0].getResultSet().close(); 380 children[1].getResultSet().close(); 381 return; 382 } else if (right == null && nextright == null && !tm1.hasNext() && rightbuffer.isEmpty()) { 383 setFinishedWhenEmpty(); 384 children[0].getResultSet().close(); 385 children[1].getResultSet().close(); 386 return; 387 } 388 int num; 389 if (left == null) { 391 left = tm0.next(); 392 } else { 393 leftfront = tm0.next(); 394 num = 0; 395 while (num < size - 1) { 396 int res = DOMUtils.simpleCompareNodeValue(left.getPath((String ) leftstrings.get(num)), leftfront.getPath((String ) leftstrings.get(num))); 397 if (res == 0) 398 num++; 399 else 400 break; 401 } 402 if (num != size - 1) { 403 rightbuffer.clear(); 404 } 405 left = leftfront; 406 } 407 if (right == null) { 408 if (nextright != null) { 409 right = nextright; 410 nextright = null; 411 } else if (tm1.hasNext()) { 412 right = tm1.next(); 413 } 414 } 415 boolean added = false; 417 while (right != null) { 418 num = 0; 419 while (num < size) { 420 int res = DOMUtils.simpleCompareNodeValue(left.getPath((String ) leftstrings.get(num)), right.getPath((String ) rightstrings.get(num))); 421 if (num != size - 1) { 422 if (res == 0) 423 num++; 424 else { 425 if (res < 0) { 426 num = size + 1; 427 break; 428 } else if (res > 0) { 429 if (tm1.hasNext()) { 430 right = tm1.next(); 431 } else 432 right = null; 433 } 434 break; 435 } 436 } else { 437 if ((res == 0 && (operatorNEQ == Constants.GEQ_COMPOP || operatorNEQ == Constants.LEQ_COMPOP)) || (res < 0 && (operatorNEQ == Constants.LT_COMPOP || operatorNEQ == Constants.LEQ_COMPOP)) || (res > 0 && (operatorNEQ == Constants.GEQ_COMPOP || operatorNEQ == Constants.GT_COMPOP))) { 438 num++; 439 } else { 440 num = size + 1; 441 break; 442 } 443 } 444 } 445 if (num == size) { 446 added = true; 447 rightbuffer.add(right); 448 break; 449 } 450 if (num > size) 451 break; 452 } 453 454 if (rightbuffer.isEmpty()) { 455 continue; 456 } 457 if (added) { 459 rightfront = nextright; 460 while (true) { 461 if (rightfront == null) 462 if (tm1.hasNext()) { 463 rightfront = tm1.next(); 464 } 465 if (rightfront != null) { 466 num = 0; 467 while (num < size) { 468 if (num != size - 1) { 469 int res = DOMUtils.simpleCompareNodeValue(right.getPath((String ) rightstrings.get(num)), rightfront.getPath((String ) rightstrings.get(num))); 470 if (res == 0) 471 num++; 472 else { 473 nextright = rightfront; 474 rightfront = null; 475 break; 476 } 477 } else { 478 int res = DOMUtils.simpleCompareNodeValue(left.getPath((String ) leftstrings.get(num)), rightfront.getPath((String ) rightstrings.get(num))); 479 if ((res == 0 && (operatorNEQ == Constants.GEQ_COMPOP || operatorNEQ == Constants.LEQ_COMPOP)) || (res < 0 && (operatorNEQ == Constants.LT_COMPOP || operatorNEQ == Constants.LEQ_COMPOP)) || (res > 0 && (operatorNEQ == Constants.GEQ_COMPOP || operatorNEQ == Constants.GT_COMPOP))) 480 num++; 481 else { 482 nextright = rightfront; 483 rightfront = null; 484 break; 485 } 486 } 487 } 488 if (num == size) { 489 rightbuffer.add(rightfront); 490 right = rightfront; 491 rightfront = null; 492 } else { 493 break; 494 } 495 } else 496 break; 497 } 498 right = rightfront; 499 } 500 for (int j = 0; j < rightbuffer.size(); j++) { 502 this.buftuples.add(left.merge((Tuple) rightbuffer.get(j), operator)); 503 } 504 if (non_blocking) { 505 if ((buftuples != null) && (!buftuples.isEmpty())) 506 break; 507 } 508 } 509 } 510 if (left == null || right == null) 511 if (!tm0.hasNext() || (!tm1.hasNext()) && operatorNEQ == 0) { 512 setFinishedWhenEmpty(); 513 children[0].getResultSet().close(); 514 children[1].getResultSet().close(); 515 return; 516 } 517 return; 518 } 519 if (operatorNEQ == 0) { 521 while (true) { 522 if (left == null || right == null) 523 if (children[0] == null || !children[0].getResultSet().hasNext() || children[1] == null || !children[1].getResultSet().hasNext()) { 524 setFinishedWhenEmpty(); 525 children[0].getResultSet().close(); 526 children[1].getResultSet().close(); 527 return; 528 } 529 if (left == null) { 531 left = children[0].getResultSet().next(); 532 } 533 if (right == null) { 534 right = children[1].getResultSet().next(); 535 } 536 while (left != null && right != null) { 537 int num = 0; 538 while (num < size) { 539 int res = DOMUtils.simpleCompareNodeValue(left.getPath((String ) leftstrings.get(num)), right.getPath((String ) rightstrings.get(num))); 540 if (res == 0) 541 num++; 542 else { 543 if (res < 0) { 544 if (children[0].getResultSet().hasNext()) { 545 left = children[0].getResultSet().next(); 546 } else 547 left = null; 548 } else if (res > 0) { 549 if (children[1].getResultSet().hasNext()) { 550 right = children[1].getResultSet().next(); 551 } else 552 right = null; 553 } 554 break; 555 } 556 } 557 if (num == size) 558 break; 559 } 560 if (left == null || right == null) { 561 setFinishedWhenEmpty(); 562 children[0].getResultSet().close(); 563 children[1].getResultSet().close(); 564 return; 565 } 566 leftbuffer.clear(); 568 leftbuffer.add(left); 569 rightbuffer.clear(); 570 rightbuffer.add(right); 571 while (true) { 573 leftfront = null; 574 if (children[0].getResultSet().hasNext()) { 575 leftfront = children[0].getResultSet().next(); 576 int num = 0; 577 while (num < size) { 578 int res = DOMUtils.simpleCompareNodeValue(left.getPath((String ) leftstrings.get(num)), leftfront.getPath((String ) leftstrings.get(num))); 579 if (res == 0) 580 num++; 581 else 582 break; 583 } 584 if (num == size) { 585 leftbuffer.add(leftfront); 586 left = leftfront; 587 } else 588 break; 589 } else 590 break; 591 592 } 593 while (true) { 595 rightfront = null; 596 if (children[1].getResultSet().hasNext()) { 597 rightfront = children[1].getResultSet().next(); 598 int num = 0; 599 while (num < size) { 600 int res = DOMUtils.simpleCompareNodeValue(right.getPath((String ) rightstrings.get(num)), rightfront.getPath((String ) rightstrings.get(num))); 601 if (res == 0) 602 num++; 603 else 604 break; 605 } 606 if (num == size) { 607 rightbuffer.add(rightfront); 608 right = rightfront; 609 } else { 610 break; 611 } 612 } else 613 break; 614 } 615 for (int i = 0; i < leftbuffer.size(); i++) { 617 for (int j = 0; j < rightbuffer.size(); j++) { 618 this.buftuples.add(((Tuple) leftbuffer.get(i)).merge((Tuple) rightbuffer.get(j), operator)); 619 } 620 } 621 left = leftfront; 622 right = rightfront; 623 if (non_blocking) { 624 if ((buftuples != null) && (!buftuples.isEmpty())) 625 break; 626 } 627 } 628 } else { 630 while (true) { 631 if (!children[0].getResultSet().hasNext()) { 632 setFinishedWhenEmpty(); 633 children[0].getResultSet().close(); 634 children[1].getResultSet().close(); 635 return; 636 } else if (right == null && nextright == null && !children[1].getResultSet().hasNext() && rightbuffer.isEmpty()) { 637 setFinishedWhenEmpty(); 638 children[0].getResultSet().close(); 639 children[1].getResultSet().close(); 640 return; 641 } 642 int num; 643 if (left == null) { 645 left = children[0].getResultSet().next(); 646 } else { 647 leftfront = children[0].getResultSet().next(); 648 num = 0; 649 while (num < size - 1) { 650 int res = DOMUtils.simpleCompareNodeValue(left.getPath((String ) leftstrings.get(num)), leftfront.getPath((String ) leftstrings.get(num))); 651 if (res == 0) 652 num++; 653 else 654 break; 655 } 656 if (num != size - 1) { 657 rightbuffer.clear(); 658 } 659 left = leftfront; 660 } 661 if (right == null) { 662 if (nextright != null) { 663 right = nextright; 664 nextright = null; 665 } else if (children[1].getResultSet().hasNext()) { 666 right = children[1].getResultSet().next(); 667 } 668 } 669 boolean added = false; 671 while (right != null) { 672 num = 0; 673 while (num < size) { 674 int res = DOMUtils.simpleCompareNodeValue(left.getPath((String ) leftstrings.get(num)), right.getPath((String ) rightstrings.get(num))); 675 if (num != size - 1) { 676 if (res == 0) 677 num++; 678 else { 679 if (res < 0) { 680 num = size + 1; 681 break; 682 } else if (res > 0) { 683 if (children[1].getResultSet().hasNext()) { 684 right = children[1].getResultSet().next(); 685 } else 686 right = null; 687 } 688 break; 689 } 690 } else { 691 if ((res == 0 && (operatorNEQ == Constants.GEQ_COMPOP || operatorNEQ == Constants.LEQ_COMPOP)) || (res < 0 && (operatorNEQ == Constants.LT_COMPOP || operatorNEQ == Constants.LEQ_COMPOP)) || (res > 0 && (operatorNEQ == Constants.GEQ_COMPOP || operatorNEQ == Constants.GT_COMPOP))) { 692 num++; 693 } else { 694 num = size + 1; 695 break; 696 } 697 } 698 } 699 if (num == size) { 700 added = true; 701 rightbuffer.add(right); 702 break; 703 } 704 if (num > size) 705 break; 706 } 707 708 if (rightbuffer.isEmpty()) { 709 continue; 710 } 711 if (added) { 713 rightfront = nextright; 714 while (true) { 715 if (rightfront == null) 716 if (children[1].getResultSet().hasNext()) { 717 rightfront = children[1].getResultSet().next(); 718 } 719 if (rightfront != null) { 720 num = 0; 721 while (num < size) { 722 if (num != size - 1) { 723 int res = DOMUtils.simpleCompareNodeValue(right.getPath((String ) rightstrings.get(num)), rightfront.getPath((String ) rightstrings.get(num))); 724 if (res == 0) 725 num++; 726 else { 727 nextright = rightfront; 728 rightfront = null; 729 break; 730 } 731 } else { 732 int res = DOMUtils.simpleCompareNodeValue(left.getPath((String ) leftstrings.get(num)), rightfront.getPath((String ) rightstrings.get(num))); 733 if ((res == 0 && (operatorNEQ == Constants.GEQ_COMPOP || operatorNEQ == Constants.LEQ_COMPOP)) || (res < 0 && (operatorNEQ == Constants.LT_COMPOP || operatorNEQ == Constants.LEQ_COMPOP)) || (res > 0 && (operatorNEQ == Constants.GEQ_COMPOP || operatorNEQ == Constants.GT_COMPOP))) 734 num++; 735 else { 736 nextright = rightfront; 737 rightfront = null; 738 break; 739 } 740 } 741 } 742 if (num == size) { 743 rightbuffer.add(rightfront); 744 right = rightfront; 745 rightfront = null; 746 } else { 747 break; 748 } 749 } else 750 break; 751 } 752 right = rightfront; 753 } 754 for (int j = 0; j < rightbuffer.size(); j++) { 756 this.buftuples.add(left.merge((Tuple) rightbuffer.get(j), operator)); 757 } 758 if (non_blocking) { 759 if ((buftuples != null) && (!buftuples.isEmpty())) 760 break; 761 } 762 } 763 } 764 if (left == null || right == null) 765 if (!children[0].getResultSet().hasNext() || (!children[1].getResultSet().hasNext()) && operatorNEQ == 0) { 766 setFinishedWhenEmpty(); 767 children[0].getResultSet().close(); 768 children[1].getResultSet().close(); 769 return; 770 } 771 } 772 } 773 | Popular Tags |