1 17 package org.apache.ldap.server.db; 18 19 20 import org.apache.ldap.common.filter.*; 21 22 import javax.naming.NamingException ; 23 import javax.naming.directory.SearchControls ; 24 import java.math.BigInteger ; 25 import java.util.ArrayList ; 26 27 28 34 public class DefaultOptimizer implements Optimizer 35 { 36 37 private static final BigInteger MAX = BigInteger.valueOf( Integer.MAX_VALUE ); 38 39 private Database db; 40 41 42 47 public DefaultOptimizer( Database db ) 48 { 49 this.db = db; 50 } 51 52 53 61 public void annotate( ExprNode node ) throws NamingException 62 { 63 BigInteger count = MAX; 65 66 78 79 if ( node instanceof ScopeNode ) 80 { 81 count = getScopeScan( ( ScopeNode ) node ); 82 } 83 else if ( node instanceof AssertionNode ) 84 { 85 90 } 91 else if ( node.isLeaf() ) 92 { 93 LeafNode leaf = ( LeafNode ) node; 94 95 switch ( leaf.getAssertionType() ) 96 { 97 case( LeafNode.APPROXIMATE ): 98 99 count = getEqualityScan( ( SimpleNode ) leaf ); 100 break; 101 case( LeafNode.EQUALITY ): 102 count = getEqualityScan( ( SimpleNode ) leaf ); 103 break; 104 case( LeafNode.EXTENSIBLE ): 105 106 count = getFullScan( leaf ); 107 break; 108 case( LeafNode.GREATEREQ ): 109 count = getGreaterLessScan( ( SimpleNode ) leaf, true ); 110 break; 111 case( LeafNode.LESSEQ ): 112 count = getGreaterLessScan( ( SimpleNode ) leaf, false ); 113 break; 114 case( LeafNode.PRESENCE ): 115 count = getPresenceScan( ( PresenceNode ) leaf ); 116 break; 117 case( LeafNode.SUBSTRING ): 118 119 count = getFullScan( leaf ); 120 break; 121 default: 122 throw new IllegalArgumentException ( "Unrecognized leaf node" ); 123 } 124 } 125 else 129 { 130 BranchNode bnode = ( BranchNode ) node; 131 132 switch( bnode.getOperator() ) 133 { 134 case( BranchNode.AND ): 135 count = getConjunctionScan( bnode ); 136 break; 137 case( BranchNode.NOT ): 138 count = getNegationScan( bnode ); 139 break; 140 case( BranchNode.OR ): 141 count = getDisjunctionScan( bnode ); 142 break; 143 default: 144 throw new IllegalArgumentException ( 145 "Unrecognized branch node type" ); 146 } 147 } 148 149 if ( count.compareTo( BigInteger.ZERO ) < 0 ) 151 { 152 count = MAX; 153 } 154 155 node.set( "count", count ); 156 } 157 158 159 170 private BigInteger getConjunctionScan( BranchNode node ) throws NamingException 171 { 172 BigInteger count = BigInteger.valueOf( Integer.MAX_VALUE ); 173 ArrayList children = node.getChildren(); 174 175 for ( int ii = 0; ii < children.size(); ii++ ) 176 { 177 ExprNode child = ( ExprNode ) children.get( ii ); 178 annotate( child ); 179 count = ( ( BigInteger ) child.get( "count" ) ).min( count ); 180 } 181 182 return count; 183 } 184 185 186 200 private BigInteger getNegationScan( BranchNode node ) throws NamingException 201 { 202 ExprNode onlyChild = ( ExprNode ) node.getChildren().get( 0 ); 203 204 annotate( onlyChild ); 205 206 if ( onlyChild.isLeaf() 207 && ! ( onlyChild instanceof ScopeNode ) 208 && ! ( onlyChild instanceof AssertionNode ) 209 && ! ( onlyChild instanceof PresenceNode ) ) 210 { 211 LeafNode leaf = ( LeafNode ) onlyChild; 212 Index idx = db.getUserIndex( leaf.getAttribute() ); 213 return BigInteger.valueOf( idx.count() ); 214 } 215 216 return BigInteger.valueOf( db.count() ); 217 } 218 219 220 229 private BigInteger getDisjunctionScan( BranchNode node ) throws NamingException 230 { 231 ArrayList children = node.getChildren(); 232 BigInteger total = BigInteger.ZERO; 233 234 for ( int ii = 0; ii < children.size(); ii++ ) 235 { 236 ExprNode child = ( ExprNode ) children.get( ii ); 237 annotate( child ); 238 total = total.add( ( BigInteger ) child.get( "count" ) ); 239 } 240 241 return total; 242 } 243 244 245 253 private BigInteger getEqualityScan( SimpleNode node ) 254 throws NamingException 255 { 256 if ( db.hasUserIndexOn( node.getAttribute() ) ) 257 { 258 Index idx = db.getUserIndex( node.getAttribute() ); 259 return BigInteger.valueOf( idx.count( node.getValue() ) ); 260 } 261 262 return MAX; 264 } 265 266 267 276 private BigInteger getGreaterLessScan( SimpleNode node, 277 boolean isGreaterThan ) throws NamingException 278 { 279 if ( db.hasUserIndexOn( node.getAttribute() ) ) 280 { 281 Index idx = db.getUserIndex( node.getAttribute() ); 282 int count = idx.count( node.getValue(), isGreaterThan ); 283 return BigInteger.valueOf( count ); 284 } 285 286 return MAX; 288 } 289 290 291 300 private BigInteger getFullScan( LeafNode node ) 301 throws NamingException 302 { 303 if ( db.hasUserIndexOn( node.getAttribute() ) ) 304 { 305 Index idx = db.getUserIndex( node.getAttribute() ); 306 int count = idx.count(); 307 return BigInteger.valueOf( count ); 308 } 309 310 return MAX; 311 } 312 313 314 322 private BigInteger getPresenceScan( PresenceNode node ) throws NamingException 323 { 324 if ( db.hasUserIndexOn( node.getAttribute() ) ) 325 { 326 Index idx = db.getExistanceIndex(); 327 int count = idx.count( node.getAttribute() ); 328 return BigInteger.valueOf( count ); 329 } 330 331 return MAX; 332 } 333 334 335 342 private BigInteger getScopeScan( ScopeNode node ) throws NamingException 343 { 344 switch ( node.getScope() ) 345 { 346 case ( SearchControls.OBJECT_SCOPE ): 347 return BigInteger.ONE; 348 case ( SearchControls.ONELEVEL_SCOPE ): 349 BigInteger id = db.getEntryId( node.getBaseDn() ); 350 return BigInteger.valueOf( db.getChildCount( id ) ); 351 case ( SearchControls.SUBTREE_SCOPE ): 352 return BigInteger.valueOf( db.count() ); 353 default: 354 throw new IllegalArgumentException ( "Unrecognized search scope " 355 + "value for filter scope node" ); 356 } 357 } 358 } 359 | Popular Tags |