1 21 22 package org.apache.derby.impl.sql.compile; 23 24 import org.apache.derby.iapi.services.compiler.MethodBuilder; 25 26 import org.apache.derby.iapi.services.sanity.SanityManager; 27 28 import org.apache.derby.iapi.error.StandardException; 29 30 import org.apache.derby.iapi.sql.compile.Optimizable; 31 import org.apache.derby.iapi.sql.compile.OptimizablePredicate; 32 import org.apache.derby.iapi.sql.compile.OptimizablePredicateList; 33 import org.apache.derby.iapi.sql.compile.Optimizer; 34 import org.apache.derby.iapi.sql.compile.CostEstimate; 35 import org.apache.derby.iapi.sql.compile.RowOrdering; 36 import org.apache.derby.iapi.sql.compile.C_NodeTypes; 37 38 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor; 39 40 import org.apache.derby.iapi.reference.SQLState; 41 import org.apache.derby.iapi.reference.ClassName; 42 43 import org.apache.derby.impl.sql.compile.ActivationClassBuilder; 44 45 import org.apache.derby.iapi.types.DataTypeDescriptor; 46 47 import org.apache.derby.iapi.util.JBitSet; 48 import org.apache.derby.iapi.services.classfile.VMOpcode; 49 50 56 57 public class UnionNode extends SetOperatorNode 58 { 59 60 61 private boolean addNewNodesCalled; 62 63 64 boolean tableConstructor; 65 66 67 boolean topTableConstructor; 68 69 70 81 82 public void init( 83 Object leftResult, 84 Object rightResult, 85 Object all, 86 Object tableConstructor, 87 Object tableProperties) 88 throws StandardException 89 { 90 super.init(leftResult, rightResult, all, tableProperties); 91 92 93 this.tableConstructor = ((Boolean ) tableConstructor).booleanValue(); 94 } 96 99 public void markTopTableConstructor() 100 { 101 topTableConstructor = true; 102 } 103 104 107 boolean tableConstructor() 108 { 109 return tableConstructor; 110 } 111 112 123 public void rejectParameters() throws StandardException 124 { 125 if ( ! tableConstructor()) 126 super.rejectParameters(); 127 } 128 129 140 void setTableConstructorTypes(ResultColumnList typeColumns) 141 throws StandardException 142 { 143 if (SanityManager.DEBUG) 144 { 145 SanityManager.ASSERT(resultColumns.size() <= typeColumns.size(), 146 "More columns in ResultColumnList than in base table."); 147 } 148 149 ResultSetNode rsn; 150 151 155 if (tableConstructor()) 156 { 157 158 for (rsn = this; rsn instanceof UnionNode; ) 159 { 160 UnionNode union = (UnionNode) rsn; 161 162 166 if (SanityManager.DEBUG) 167 SanityManager.ASSERT( 168 union.rightResultSet instanceof RowResultSetNode, 169 "A " + union.rightResultSet.getClass().getName() + 170 " is on the right of a union in a table constructor"); 171 172 ((RowResultSetNode) union.rightResultSet).setTableConstructorTypes( 173 typeColumns); 174 175 rsn = union.leftResultSet; 176 } 177 178 179 if (SanityManager.DEBUG) 180 SanityManager.ASSERT(rsn instanceof RowResultSetNode, 181 "A " + rsn.getClass().getName() + 182 " is at the left end of a table constructor"); 183 184 ((RowResultSetNode) rsn).setTableConstructorTypes(typeColumns); 185 } 186 } 187 188 191 192 197 public CostEstimate optimizeIt(Optimizer optimizer, 198 OptimizablePredicateList predList, 199 CostEstimate outerCost, 200 RowOrdering rowOrdering) 201 throws StandardException 202 { 203 215 216 217 218 if ((predList != null) && 230 !getCurrentAccessPath().getJoinStrategy().isHashJoin()) 231 { 232 for (int i = predList.size() - 1; i >= 0; i--) { 233 if (pushOptPredicate(predList.getOptPredicate(i))) 234 predList.removeOptPredicate(i); 235 } 236 } 237 238 updateBestPlanMap(ADD_PLAN, this); 249 250 leftResultSet = optimizeSource( 251 optimizer, 252 leftResultSet, 253 getLeftOptPredicateList(), 254 outerCost); 255 256 rightResultSet = optimizeSource( 257 optimizer, 258 rightResultSet, 259 getRightOptPredicateList(), 260 outerCost); 261 262 CostEstimate costEstimate = getCostEstimate(optimizer); 263 264 265 costEstimate.setCost(leftResultSet.getCostEstimate().getEstimatedCost(), 266 leftResultSet.getCostEstimate().rowCount(), 267 leftResultSet.getCostEstimate().singleScanRowCount() + 268 rightResultSet.getCostEstimate().singleScanRowCount()); 269 270 costEstimate.add(rightResultSet.costEstimate, costEstimate); 271 272 275 getCurrentAccessPath(). 276 getJoinStrategy(). 277 estimateCost( 278 this, 279 predList, 280 (ConglomerateDescriptor) null, 281 outerCost, 282 optimizer, 283 costEstimate 284 ); 285 286 optimizer.considerCost(this, predList, costEstimate, outerCost); 287 288 return costEstimate; 289 } 290 291 311 public void pushExpressions(PredicateList predicateList) 312 throws StandardException 313 { 314 if (leftResultSet instanceof UnionNode) 319 ((UnionNode)leftResultSet).pushExpressions(predicateList); 320 else if (leftResultSet instanceof SelectNode) 321 predicateList.pushExpressionsIntoSelect((SelectNode)leftResultSet, true); 322 323 if (rightResultSet instanceof UnionNode) 324 ((UnionNode)rightResultSet).pushExpressions(predicateList); 325 else if (rightResultSet instanceof SelectNode) 326 predicateList.pushExpressionsIntoSelect((SelectNode)rightResultSet, true); 327 } 328 329 334 public Optimizable modifyAccessPath(JBitSet outerTables) throws StandardException 335 { 336 Optimizable retOptimizable; 337 retOptimizable = super.modifyAccessPath(outerTables); 338 339 340 if (addNewNodesCalled) 341 { 342 return retOptimizable; 343 } 344 return (Optimizable) addNewNodes(); 345 } 346 347 352 public ResultSetNode modifyAccessPaths() throws StandardException 353 { 354 ResultSetNode retRSN; 355 retRSN = super.modifyAccessPaths(); 356 357 358 if (addNewNodesCalled) 359 { 360 return retRSN; 361 } 362 return addNewNodes(); 363 } 364 365 374 private ResultSetNode addNewNodes() 375 throws StandardException 376 { 377 ResultSetNode treeTop = this; 378 379 380 if (addNewNodesCalled) 381 { 382 return this; 383 } 384 385 addNewNodesCalled = true; 386 387 400 401 404 if (! all) 405 { 406 412 if (! columnTypesAndLengthsMatch()) 413 { 414 treeTop = genNormalizeResultSetNode(this, false); 415 } 416 417 treeTop = (ResultSetNode) getNodeFactory().getNode( 418 C_NodeTypes.DISTINCT_NODE, 419 treeTop.genProjectRestrict(), 420 Boolean.FALSE, 421 tableProperties, 422 getContextManager()); 423 429 ((FromTable)treeTop).setTableNumber(tableNumber); 430 treeTop.setReferencedTableMap((JBitSet) referencedTableMap.clone()); 431 all = true; 432 } 433 434 437 if (orderByList != null) 438 { 439 treeTop = (ResultSetNode) getNodeFactory().getNode( 440 C_NodeTypes.ORDER_BY_NODE, 441 treeTop, 442 orderByList, 443 tableProperties, 444 getContextManager()); 445 } 446 return treeTop; 447 } 448 449 455 456 public String toString() 457 { 458 if (SanityManager.DEBUG) 459 { 460 return "tableConstructor: " + tableConstructor + "\n" + super.toString(); 461 } 462 else 463 { 464 return ""; 465 } 466 } 467 468 475 476 public void bindExpressions(FromList fromListParam) 477 throws StandardException 478 { 479 super.bindExpressions(fromListParam); 480 481 491 if (topTableConstructor && ( ! insertSource) ) 492 { 493 497 DataTypeDescriptor[] types = 498 new DataTypeDescriptor[leftResultSet.getResultColumns().size()]; 499 500 ResultSetNode rsn; 501 int numTypes = 0; 502 503 504 for (rsn = this; rsn instanceof SetOperatorNode; ) 505 { 506 SetOperatorNode setOperator = (SetOperatorNode) rsn; 507 508 512 if (SanityManager.DEBUG) 513 SanityManager.ASSERT( 514 setOperator.rightResultSet instanceof RowResultSetNode, 515 "A " + setOperator.rightResultSet.getClass().getName() + 516 " is on the right side of a setOperator in a table constructor"); 517 518 RowResultSetNode rrsn = 519 (RowResultSetNode) setOperator.rightResultSet; 520 521 numTypes += getParamColumnTypes(types, rrsn); 522 523 rsn = setOperator.leftResultSet; 524 } 525 526 527 if (SanityManager.DEBUG) 528 SanityManager.ASSERT(rsn instanceof RowResultSetNode); 529 530 numTypes += getParamColumnTypes(types, (RowResultSetNode) rsn); 531 532 533 if (numTypes < types.length) 534 { 535 throw StandardException.newException(SQLState.LANG_TABLE_CONSTRUCTOR_ALL_PARAM_COLUMN); 536 } 537 538 543 for (rsn = this; rsn instanceof SetOperatorNode; ) 544 { 545 SetOperatorNode setOperator = (SetOperatorNode) rsn; 546 RowResultSetNode rrsn = (RowResultSetNode) setOperator.rightResultSet; 547 548 setParamColumnTypes(types, rrsn); 549 550 rsn = setOperator.leftResultSet; 551 } 552 553 setParamColumnTypes(types, (RowResultSetNode) rsn); 554 } 555 } 556 557 562 public void generate(ActivationClassBuilder acb, 563 MethodBuilder mb) 564 throws StandardException 565 { 566 570 if (SanityManager.DEBUG) 571 { 572 SanityManager.ASSERT(all, 573 "all expected to be true"); 574 } 575 576 579 assignResultSetNumber(); 580 581 costEstimate = getFinalCostEstimate(); 583 584 586 acb.pushGetResultSetFactoryExpression(mb); 588 589 590 leftResultSet.generate(acb, mb); 591 592 593 if (! resultColumns.isExactTypeAndLengthMatch(leftResultSet.getResultColumns())) 594 { 595 acb.pushGetResultSetFactoryExpression(mb); 596 mb.swap(); 597 generateNormalizationResultSet(acb, mb, 598 getCompilerContext().getNextResultSetNumber(), 599 makeResultDescription() 600 ); 601 } 602 603 rightResultSet.generate(acb, mb); 604 605 606 if (! resultColumns.isExactTypeAndLengthMatch(rightResultSet.getResultColumns())) 607 { 608 acb.pushGetResultSetFactoryExpression(mb); 609 mb.swap(); 610 generateNormalizationResultSet(acb, mb, 611 getCompilerContext().getNextResultSetNumber(), 612 makeResultDescription() 613 ); 614 } 615 616 625 626 mb.push(resultSetNumber); 627 mb.push(costEstimate.rowCount()); 628 mb.push(costEstimate.getEstimatedCost()); 629 630 mb.callMethod(VMOpcode.INVOKEINTERFACE, (String ) null, "getUnionResultSet", 631 ClassName.NoPutResultSet, 5); 632 } 633 634 642 public CostEstimate getFinalCostEstimate() 643 throws StandardException 644 { 645 if (finalCostEstimate != null) 647 return finalCostEstimate; 648 649 CostEstimate leftCE = leftResultSet.getFinalCostEstimate(); 650 CostEstimate rightCE = rightResultSet.getFinalCostEstimate(); 651 652 finalCostEstimate = getNewCostEstimate(); 653 finalCostEstimate.setCost(leftCE.getEstimatedCost(), 654 leftCE.rowCount(), 655 leftCE.singleScanRowCount() + 656 rightCE.singleScanRowCount()); 657 658 finalCostEstimate.add(rightCE, finalCostEstimate); 659 return finalCostEstimate; 660 } 661 662 String getOperatorName() 663 { 664 return "UNION"; 665 } 666 } 667 | Popular Tags |