1 21 22 package org.apache.derby.impl.sql.compile; 23 24 import org.apache.derby.iapi.services.context.ContextManager; 25 26 import org.apache.derby.iapi.services.compiler.MethodBuilder; 27 28 import org.apache.derby.iapi.services.sanity.SanityManager; 29 30 import org.apache.derby.iapi.error.StandardException; 31 32 import org.apache.derby.iapi.sql.compile.Optimizable; 33 import org.apache.derby.iapi.sql.compile.OptimizablePredicate; 34 import org.apache.derby.iapi.sql.compile.OptimizablePredicateList; 35 import org.apache.derby.iapi.sql.compile.Optimizer; 36 import org.apache.derby.iapi.sql.compile.CostEstimate; 37 import org.apache.derby.iapi.sql.compile.C_NodeTypes; 38 39 import org.apache.derby.iapi.sql.dictionary.DataDictionary; 40 41 import org.apache.derby.iapi.sql.Activation; 42 import org.apache.derby.iapi.sql.ResultSet; 43 44 import org.apache.derby.iapi.error.StandardException; 45 46 import org.apache.derby.impl.sql.compile.ActivationClassBuilder; 47 48 import org.apache.derby.iapi.util.JBitSet; 49 50 import java.util.Properties ; 51 52 59 60 public class HalfOuterJoinNode extends JoinNode 61 { 62 private boolean rightOuterJoin; 63 private boolean transformed = false; 64 65 78 79 public void init( 80 Object leftResult, 81 Object rightResult, 82 Object onClause, 83 Object usingClause, 84 Object rightOuterJoin, 85 Object tableProperties) 86 throws StandardException 87 { 88 super.init( 89 leftResult, 90 rightResult, 91 onClause, 92 usingClause, 93 null, 94 tableProperties, 95 null); 96 this.rightOuterJoin = ((Boolean ) rightOuterJoin).booleanValue(); 97 98 102 flattenableJoin = false; 103 } 104 105 108 109 114 115 public boolean pushOptPredicate(OptimizablePredicate optimizablePredicate) 116 throws StandardException 117 { 118 125 FromTable leftFromTable = (FromTable) leftResultSet; 126 if (leftFromTable.getReferencedTableMap().contains(optimizablePredicate.getReferencedMap())) 127 return leftFromTable.pushOptPredicate(optimizablePredicate); 128 return false; 129 } 130 131 137 138 public String toString() 139 { 140 if (SanityManager.DEBUG) 141 { 142 return "rightOuterJoin: " + rightOuterJoin + "\n" + 143 "transformed: " + transformed + "\n" + 144 super.toString(); 145 } 146 else 147 { 148 return ""; 149 } 150 } 151 152 176 public ResultSetNode preprocess(int numTables, 177 GroupByList gbl, 178 FromList fromList) 179 throws StandardException 180 { 181 ResultSetNode newTreeTop; 182 183 184 if (rightOuterJoin) 185 { 186 189 if (SanityManager.DEBUG) 190 { 191 SanityManager.ASSERT(! transformed, 192 "Attempting to transform a right outer join multiple times"); 193 } 194 195 ResultSetNode tmp = leftResultSet; 196 197 leftResultSet = rightResultSet; 198 rightResultSet = tmp; 199 transformed = true; 200 } 201 202 newTreeTop = super.preprocess(numTables, gbl, fromList); 203 204 return newTreeTop; 205 } 206 207 218 public void pushExpressions(PredicateList outerPredicateList) 219 throws StandardException 220 { 221 FromTable leftFromTable = (FromTable) leftResultSet; 222 FromTable rightFromTable = (FromTable) rightResultSet; 223 224 228 pushExpressionsToLeft(outerPredicateList); 229 230 235 for (int index = joinPredicates.size() - 1; index >= 0; index --) 237 { 238 Predicate predicate; 239 240 predicate = (Predicate) joinPredicates.elementAt(index); 241 if (! predicate.getPushable()) 242 { 243 continue; 244 } 245 246 getRightPredicateList().addPredicate(predicate); 247 248 249 joinPredicates.removeElementAt(index); 250 } 251 252 253 PredicateList noPredicates = 254 (PredicateList) getNodeFactory().getNode( 255 C_NodeTypes.PREDICATE_LIST, 256 getContextManager()); 257 leftFromTable.pushExpressions(getLeftPredicateList()); 258 rightFromTable.pushExpressions(noPredicates); 259 } 260 261 267 public boolean LOJ_reorderable(int numTables) 268 throws StandardException 269 { 270 boolean anyChange = false; 271 272 ResultSetNode logicalLeftResultSet; ResultSetNode logicalRightResultSet; 275 if (rightOuterJoin) 278 { logicalLeftResultSet = rightResultSet; 280 logicalRightResultSet = leftResultSet; 281 } 282 else 283 { 284 logicalLeftResultSet = leftResultSet; 285 logicalRightResultSet = rightResultSet; 286 } 287 288 super.normExpressions(); 290 291 if (logicalLeftResultSet instanceof FromBaseTable && 293 logicalRightResultSet instanceof FromBaseTable) 294 return anyChange; 295 296 if (logicalLeftResultSet instanceof HalfOuterJoinNode) 300 { 301 anyChange = ((HalfOuterJoinNode)logicalLeftResultSet).LOJ_reorderable(numTables) || anyChange; 302 } 303 else if (!(logicalLeftResultSet instanceof FromBaseTable)) 304 { return anyChange; 312 } 313 314 if (logicalRightResultSet instanceof HalfOuterJoinNode) 315 { 316 anyChange = ((HalfOuterJoinNode)logicalRightResultSet).LOJ_reorderable(numTables) || anyChange; 317 } 318 else if (!(logicalRightResultSet instanceof FromBaseTable)) 319 { return anyChange; 321 } 322 323 if (rightOuterJoin || (logicalRightResultSet instanceof HalfOuterJoinNode && 328 ((HalfOuterJoinNode)logicalRightResultSet).rightOuterJoin)) 329 { 330 return LOJ_bindResultColumns(anyChange); 331 } 332 333 JBitSet NPReferencedTableMap; JBitSet RPReferencedTableMap; 339 RPReferencedTableMap = logicalLeftResultSet.LOJgetReferencedTables(numTables); 340 NPReferencedTableMap = logicalRightResultSet.LOJgetReferencedTables(numTables); 341 342 if ((RPReferencedTableMap == null || NPReferencedTableMap == null) && 343 anyChange) 344 { 345 return LOJ_bindResultColumns(anyChange); 346 } 347 348 355 BinaryRelationalOperatorNode equals; 358 ValueNode leftCol; 359 ValueNode rightCol; 360 AndNode and; 361 ValueNode left; 362 ValueNode vn = joinClause; 363 while (vn instanceof AndNode) 364 { 365 and = (AndNode) vn; 366 left = and.getLeftOperand(); 367 368 if (left instanceof RelationalOperator && 371 ((ValueNode)left).isBinaryEqualsOperatorNode()) 372 { 373 equals = (BinaryRelationalOperatorNode) left; 374 leftCol = equals.getLeftOperand(); 375 rightCol = equals.getRightOperand(); 376 377 if (!( leftCol instanceof ColumnReference && rightCol instanceof ColumnReference)) 378 return LOJ_bindResultColumns(anyChange); 379 380 boolean refCheck = false; 381 boolean leftOperandCheck = false; 382 383 if (RPReferencedTableMap.get(((ColumnReference)leftCol).getTableNumber())) 384 { 385 refCheck = true; 386 leftOperandCheck = true; 387 } 388 else if (NPReferencedTableMap.get(((ColumnReference)leftCol).getTableNumber())) 389 { 390 refCheck = true; 391 } 392 393 if (refCheck == false) 394 return LOJ_bindResultColumns(anyChange); 395 396 refCheck = false; 397 if (leftOperandCheck == false && RPReferencedTableMap.get(((ColumnReference)rightCol).getTableNumber())) 398 { 399 refCheck = true; 400 } 401 else if (leftOperandCheck == true && NPReferencedTableMap.get(((ColumnReference)rightCol).getTableNumber())) 402 { 403 refCheck = true; 404 } 405 406 if (refCheck == false) 407 return LOJ_bindResultColumns(anyChange); 408 } 409 else return LOJ_bindResultColumns(anyChange); 411 vn = and.getRightOperand(); 412 } 413 414 boolean push = false; 417 if (logicalRightResultSet instanceof HalfOuterJoinNode) 420 { 421 JBitSet logicalNPRefTableMap = ((HalfOuterJoinNode)logicalRightResultSet).LOJgetNPReferencedTables(numTables); 423 424 vn = joinClause; 428 push = true; 429 while (vn instanceof AndNode) 430 { 431 and = (AndNode) vn; 432 left = and.getLeftOperand(); 433 equals = (BinaryRelationalOperatorNode) left; 434 leftCol = equals.getLeftOperand(); 435 rightCol = equals.getRightOperand(); 436 437 if (logicalNPRefTableMap.get(((ColumnReference)leftCol).getTableNumber()) || 438 logicalNPRefTableMap.get(((ColumnReference)rightCol).getTableNumber())) 439 { 440 push = false; 441 break; 442 } 443 444 vn = and.getRightOperand(); 445 } 446 } 447 448 if (push) 450 { 451 if (super.subqueryList.size() != 0 || 454 ((JoinNode)logicalRightResultSet).subqueryList.size() != 0 || 455 super.joinPredicates.size() != 0 || 456 ((JoinNode)logicalRightResultSet).joinPredicates.size() != 0 || 457 super.usingClause != null || 458 ((JoinNode)logicalRightResultSet).usingClause != null) 459 return LOJ_bindResultColumns(anyChange); 461 anyChange = true; 463 ResultSetNode tmp = logicalLeftResultSet; 464 ResultSetNode LChild, RChild; 465 466 481 LChild = ((HalfOuterJoinNode)logicalRightResultSet).leftResultSet; 483 RChild = ((HalfOuterJoinNode)logicalRightResultSet).rightResultSet; 484 485 ((HalfOuterJoinNode)logicalRightResultSet).rightResultSet = LChild; 486 ((HalfOuterJoinNode)logicalRightResultSet).leftResultSet = tmp; 487 488 vn = joinClause; 490 joinClause = ((HalfOuterJoinNode)logicalRightResultSet).joinClause; 491 ((HalfOuterJoinNode)logicalRightResultSet).joinClause = vn; 492 493 502 FromList localFromList = (FromList) getNodeFactory().getNode( 503 C_NodeTypes.FROM_LIST, 504 getNodeFactory().doJoinOrderOptimization(), 505 getContextManager()); 506 507 leftResultSet = logicalRightResultSet; 509 rightResultSet = RChild; 510 511 ((HalfOuterJoinNode)leftResultSet).resultColumns = null; 513 ((JoinNode)leftResultSet).bindResultColumns(localFromList); 515 boolean localChange = ((HalfOuterJoinNode)leftResultSet).LOJ_reorderable(numTables); 517 518 return LOJ_bindResultColumns(anyChange); 520 } 521 522 return LOJ_bindResultColumns(anyChange); 523 } 524 525 public boolean LOJ_bindResultColumns(boolean anyChange) 528 throws StandardException 529 { 530 if (anyChange) 531 { 532 this.resultColumns = null; 533 FromList localFromList = (FromList) getNodeFactory().getNode(C_NodeTypes.FROM_LIST, 534 getNodeFactory().doJoinOrderOptimization(), 535 getContextManager()); 536 ((JoinNode)this).bindResultColumns(localFromList); 537 } 538 return anyChange; 539 } 540 541 542 553 public FromTable transformOuterJoins(ValueNode predicateTree, int numTables) 554 throws StandardException 555 { 556 ResultSetNode innerRS; 557 558 if (predicateTree == null) 559 { 560 563 leftResultSet.notFlattenableJoin(); 564 rightResultSet.notFlattenableJoin(); 565 return this; 566 } 567 568 super.transformOuterJoins(predicateTree, numTables); 569 570 JBitSet innerMap = new JBitSet(numTables); 571 if (rightOuterJoin) 572 { 573 if (SanityManager.DEBUG) 574 { 575 SanityManager.ASSERT(! transformed, 576 "right OJ not expected to be transformed into left OJ yet"); 577 } 578 innerRS = leftResultSet; 579 } 580 else 581 { 582 innerRS = rightResultSet; 583 } 584 585 innerRS.fillInReferencedTableMap(innerMap); 586 587 590 ValueNode vn = predicateTree; 591 while (vn instanceof AndNode) 592 { 593 AndNode and = (AndNode) vn; 594 ValueNode left = and.getLeftOperand(); 595 596 597 if (left.isInstanceOf(C_NodeTypes.IS_NULL_NODE)) 598 { 599 vn = and.getRightOperand(); 600 continue; 601 } 602 603 604 if (left instanceof RelationalOperator) 605 { 606 JBitSet refMap = new JBitSet(numTables); 607 609 if (! (left.categorize(refMap, true))) 610 { 611 vn = and.getRightOperand(); 612 continue; 613 } 614 615 620 for (int bit = 0; bit < numTables; bit++) 621 { 622 if (refMap.get(bit) && innerMap.get(bit)) 623 { 624 JoinNode ij = (JoinNode) 626 getNodeFactory().getNode( 627 C_NodeTypes.JOIN_NODE, 628 leftResultSet, 629 rightResultSet, 630 joinClause, 631 null, 632 resultColumns, 633 null, 634 null, 635 getContextManager()); 636 ij.setTableNumber(tableNumber); 637 ij.setSubqueryList(subqueryList); 638 ij.setAggregateVector(aggregateVector); 639 return ij; 640 } 641 } 642 } 643 644 vn = and.getRightOperand(); 645 } 646 647 650 leftResultSet.notFlattenableJoin(); 651 rightResultSet.notFlattenableJoin(); 652 653 return this; 654 } 655 656 657 protected void adjustNumberOfRowsReturned(CostEstimate costEstimate) 658 { 659 664 CostEstimate outerCost = getLeftResultSet().getCostEstimate(); 665 666 if (costEstimate.rowCount() < outerCost.rowCount()) 667 { 668 costEstimate.setCost(costEstimate.getEstimatedCost(), 669 outerCost.rowCount(), 670 outerCost.rowCount()); 671 } 672 } 673 674 679 public void generate(ActivationClassBuilder acb, 680 MethodBuilder mb) 681 throws StandardException 682 { 683 686 if (SanityManager.DEBUG) 687 { 688 SanityManager.ASSERT(rightOuterJoin == transformed, 689 "rightOuterJoin (" + rightOuterJoin + 690 ") is expected to equal transformed (" + transformed + ")"); 691 } 692 super.generateCore(acb, mb, LEFTOUTERJOIN); 693 } 694 695 709 protected int addOuterJoinArguments(ActivationClassBuilder acb, 710 MethodBuilder mb) 711 throws StandardException 712 { 713 714 rightResultSet.getResultColumns().generateNulls(acb, mb); 715 716 717 mb.push(rightOuterJoin); 718 719 return 2; 720 } 721 722 725 protected int getNumJoinArguments() 726 { 727 728 return super.getNumJoinArguments() + 2; 729 } 730 731 protected void oneRowRightSide(ActivationClassBuilder acb, 732 MethodBuilder mb) 733 { 734 mb.push(false); 736 mb.push(false); } 738 739 745 ResultSetNode getLogicalLeftResultSet() 746 { 747 if (rightOuterJoin) 748 { 749 return rightResultSet; 750 } 751 else 752 { 753 return leftResultSet; 754 } 755 } 756 757 763 ResultSetNode getLogicalRightResultSet() 764 { 765 if (rightOuterJoin) 766 { 767 return leftResultSet; 768 } 769 else 770 { 771 return rightResultSet; 772 } 773 } 774 775 779 public boolean isRightOuterJoin() 780 { 781 return rightOuterJoin; 782 } 783 784 public JBitSet LOJgetNPReferencedTables(int numTables) 786 throws StandardException 787 { 788 if (rightOuterJoin && !transformed) 789 return (JBitSet) leftResultSet.LOJgetReferencedTables(numTables); 790 else 791 return (JBitSet) rightResultSet.LOJgetReferencedTables(numTables); 792 } 793 } 794 | Popular Tags |