1 21 22 package org.apache.derby.impl.sql.compile; 23 24 import org.apache.derby.iapi.reference.ClassName; 25 26 import org.apache.derby.iapi.services.sanity.SanityManager; 27 import org.apache.derby.iapi.services.classfile.VMOpcode; 28 import org.apache.derby.iapi.services.compiler.MethodBuilder; 29 import org.apache.derby.iapi.services.context.ContextManager; 30 31 import org.apache.derby.iapi.error.StandardException; 32 33 import org.apache.derby.iapi.sql.compile.NodeFactory; 34 import org.apache.derby.iapi.sql.compile.Optimizable; 35 import org.apache.derby.iapi.sql.compile.OptimizablePredicate; 36 import org.apache.derby.iapi.sql.compile.OptimizablePredicateList; 37 import org.apache.derby.iapi.sql.compile.Optimizer; 38 import org.apache.derby.iapi.sql.compile.CostEstimate; 39 import org.apache.derby.iapi.sql.compile.RowOrdering; 40 import org.apache.derby.iapi.sql.compile.C_NodeTypes; 41 42 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor; 43 44 import org.apache.derby.iapi.reference.SQLState; 45 46 import org.apache.derby.iapi.types.DataTypeDescriptor; 47 48 import org.apache.derby.iapi.util.JBitSet; 49 import org.apache.derby.iapi.util.ReuseFactory; 50 51 import java.sql.Types ; 52 53 import java.util.BitSet ; 54 55 60 61 public class IntersectOrExceptNode extends SetOperatorNode 62 { 63 79 80 private int opType; 81 public static final int INTERSECT_OP = 1; 82 public static final int EXCEPT_OP = 2; 83 84 85 86 private boolean addNewNodesCalled; 87 88 private int[] intermediateOrderByColumns; private int[] intermediateOrderByDirection; 91 101 102 public void init( Object opType, 103 Object leftResult, 104 Object rightResult, 105 Object all, 106 Object tableProperties) 107 throws StandardException 108 { 109 super.init( leftResult, rightResult, all, tableProperties); 110 this.opType = ((Integer ) opType).intValue(); 111 } 112 113 private int getOpType() 114 { 115 return opType; 116 } 117 118 130 131 public ResultSetNode preprocess(int numTables, 132 GroupByList gbl, 133 FromList fromList) 134 throws StandardException 135 { 136 146 intermediateOrderByColumns = new int[ getResultColumns().size()]; 147 intermediateOrderByDirection = new int[ intermediateOrderByColumns.length]; 148 153 if( orderByList != null) 154 { 155 BitSet colsOrdered = new BitSet( intermediateOrderByColumns.length); 156 int orderByListSize = orderByList.size(); 157 int intermediateOrderByIdx = 0; 158 for( int i = 0; i < orderByListSize; i++) 159 { 160 if( colsOrdered.get(i)) 161 continue; 162 OrderByColumn orderByColumn = orderByList.getOrderByColumn(i); 163 intermediateOrderByDirection[intermediateOrderByIdx] = orderByColumn.isAscending() ? 1 : -1; 164 int columnIdx = orderByColumn.getResultColumn().getColumnPosition() - 1; 165 intermediateOrderByColumns[intermediateOrderByIdx] = columnIdx; 166 colsOrdered.set( columnIdx); 167 intermediateOrderByIdx++; 168 } 169 for( int i = 0; i < intermediateOrderByColumns.length; i++) 170 { 171 if( ! colsOrdered.get(i)) 172 { 173 intermediateOrderByDirection[intermediateOrderByIdx] = 1; 174 intermediateOrderByColumns[intermediateOrderByIdx] = i; 175 intermediateOrderByIdx++; 176 } 177 } 178 orderByList = null; } 180 else { 182 for( int i = 0; i < intermediateOrderByColumns.length; i++) 185 { 186 intermediateOrderByDirection[i] = 1; 187 intermediateOrderByColumns[i] = i; 188 } 189 } 190 pushOrderingDown( leftResultSet); 191 pushOrderingDown( rightResultSet); 192 193 return super.preprocess( numTables, gbl, fromList); 194 } 196 private void pushOrderingDown( ResultSetNode rsn) 197 throws StandardException 198 { 199 ContextManager cm = getContextManager(); 200 NodeFactory nf = getNodeFactory(); 201 OrderByList orderByList = (OrderByList) nf.getNode( C_NodeTypes.ORDER_BY_LIST, cm); 202 for( int i = 0; i < intermediateOrderByColumns.length; i++) 203 { 204 OrderByColumn orderByColumn = (OrderByColumn) 205 nf.getNode( C_NodeTypes.ORDER_BY_COLUMN, 206 nf.getNode(C_NodeTypes.INT_CONSTANT_NODE, 207 ReuseFactory.getInteger( intermediateOrderByColumns[i] + 1), 208 cm), 209 cm); 210 if( intermediateOrderByDirection[i] < 0) 211 orderByColumn.setDescending(); 212 orderByList.addOrderByColumn( orderByColumn); 213 } 214 orderByList.bindOrderByColumns( rsn); 215 rsn.pushOrderByList( orderByList); 216 } 218 221 public CostEstimate estimateCost( OptimizablePredicateList predList, 222 ConglomerateDescriptor cd, 223 CostEstimate outerCost, 224 Optimizer optimizer, 225 RowOrdering rowOrdering) 226 throws StandardException 227 { 228 leftResultSet = optimizeSource( 229 optimizer, 230 leftResultSet, 231 (PredicateList) null, 232 outerCost); 233 234 rightResultSet = optimizeSource( 235 optimizer, 236 rightResultSet, 237 (PredicateList) null, 238 outerCost); 239 240 CostEstimate costEstimate = getCostEstimate(optimizer); 241 CostEstimate leftCostEstimate = leftResultSet.getCostEstimate(); 242 CostEstimate rightCostEstimate = rightResultSet.getCostEstimate(); 243 costEstimate.setCost( leftCostEstimate.getEstimatedCost() + rightCostEstimate.getEstimatedCost(), 245 getRowCountEstimate( leftCostEstimate.rowCount(), 246 rightCostEstimate.rowCount()), 247 getSingleScanRowCountEstimate( leftCostEstimate.singleScanRowCount(), 248 rightCostEstimate.singleScanRowCount())); 249 250 return costEstimate; 251 } 253 258 public Optimizable modifyAccessPath(JBitSet outerTables) throws StandardException 259 { 260 Optimizable retOptimizable; 261 retOptimizable = super.modifyAccessPath(outerTables); 262 263 264 if (addNewNodesCalled) 265 { 266 return retOptimizable; 267 } 268 return (Optimizable) addNewNodes(); 269 } 270 271 276 public ResultSetNode modifyAccessPaths() throws StandardException 277 { 278 ResultSetNode retRSN; 279 retRSN = super.modifyAccessPaths(); 280 281 282 if (addNewNodesCalled) 283 { 284 return retRSN; 285 } 286 return addNewNodes(); 287 } 288 289 298 private ResultSetNode addNewNodes() 299 throws StandardException 300 { 301 302 if (addNewNodesCalled) 303 { 304 return this; 305 } 306 307 addNewNodesCalled = true; 308 309 if( orderByList == null) 310 return this; 311 return (ResultSetNode) getNodeFactory().getNode( C_NodeTypes.ORDER_BY_NODE, 313 this, 314 orderByList, 315 tableProperties, 316 getContextManager()); 317 } 319 324 public void generate( ActivationClassBuilder acb, 325 MethodBuilder mb) 326 throws StandardException 327 { 328 329 332 assignResultSetNumber(); 333 334 costEstimate = getFinalCostEstimate(); 336 337 339 352 353 acb.pushGetResultSetFactoryExpression(mb); 355 getLeftResultSet().generate( acb, mb); 356 getRightResultSet().generate( acb, mb); 357 358 acb.pushThisAsActivation(mb); 359 mb.push(resultSetNumber); 360 mb.push( costEstimate.getEstimatedRowCount()); 361 mb.push( costEstimate.getEstimatedCost()); 362 mb.push( getOpType()); 363 mb.push( all); 364 mb.push( getCompilerContext().addSavedObject( intermediateOrderByColumns)); 365 mb.push( getCompilerContext().addSavedObject( intermediateOrderByDirection)); 366 367 mb.callMethod(VMOpcode.INVOKEINTERFACE, 368 (String ) null, 369 "getSetOpResultSet", 370 ClassName.NoPutResultSet, 10); 371 } 373 383 public CostEstimate getFinalCostEstimate() 384 throws StandardException 385 { 386 if (finalCostEstimate != null) 387 return finalCostEstimate; 388 389 CostEstimate leftCE = leftResultSet.getFinalCostEstimate(); 390 CostEstimate rightCE = rightResultSet.getFinalCostEstimate(); 391 392 finalCostEstimate = getNewCostEstimate(); 393 finalCostEstimate.setCost( 394 leftCE.getEstimatedCost() + rightCE.getEstimatedCost(), 395 getRowCountEstimate(leftCE.rowCount(), rightCE.rowCount()), 396 getSingleScanRowCountEstimate(leftCE.singleScanRowCount(), 397 rightCE.singleScanRowCount())); 398 399 return finalCostEstimate; 400 } 401 402 String getOperatorName() 403 { 404 switch( opType) 405 { 406 case INTERSECT_OP: 407 return "INTERSECT"; 408 409 case EXCEPT_OP: 410 return "EXCEPT"; 411 } 412 if( SanityManager.DEBUG) 413 SanityManager.THROWASSERT( "Invalid intersectOrExcept opType: " + opType); 414 return "?"; 415 } 416 417 double getRowCountEstimate( double leftRowCount, double rightRowCount) 418 { 419 switch( opType) 420 { 421 case INTERSECT_OP: 422 return Math.min( leftRowCount, rightRowCount)/2; 425 426 case EXCEPT_OP: 427 return (leftRowCount + Math.max(0, leftRowCount - rightRowCount))/2; 431 } 432 if( SanityManager.DEBUG) 433 SanityManager.THROWASSERT( "Invalid intersectOrExcept opType: " + opType); 434 return 1.0; 435 } 437 double getSingleScanRowCountEstimate( double leftSingleScanRowCount, double rightSingleScanRowCount) 438 { 439 return getRowCountEstimate( leftSingleScanRowCount, rightSingleScanRowCount); 440 } 441 } 442 | Popular Tags |