1 23 24 package org.objectweb.medor.optim.rdb; 25 26 import org.objectweb.medor.api.Field; 27 import org.objectweb.medor.api.MedorException; 28 import org.objectweb.medor.api.TupleStructure; 29 import org.objectweb.medor.datasource.api.DataStore; 30 import org.objectweb.medor.expression.api.Expression; 31 import org.objectweb.medor.expression.api.Operator; 32 import org.objectweb.medor.expression.api.Operand; 33 import org.objectweb.medor.expression.lib.And; 34 import org.objectweb.medor.filter.api.FieldOperand; 35 import org.objectweb.medor.filter.jorm.lib.CompositePName; 36 import org.objectweb.medor.filter.jorm.lib.SinglePName; 37 import org.objectweb.medor.filter.lib.MemberOf; 38 import org.objectweb.medor.optim.api.RewriteRule; 39 import org.objectweb.medor.optim.lib.BasicRule; 40 import org.objectweb.medor.query.api.CalculatedField; 41 import org.objectweb.medor.query.api.FilteredQueryTree; 42 import org.objectweb.medor.query.api.NestedField; 43 import org.objectweb.medor.query.api.PropagatedField; 44 import org.objectweb.medor.query.api.QueryLeaf; 45 import org.objectweb.medor.query.api.QueryNode; 46 import org.objectweb.medor.query.api.QueryTree; 47 import org.objectweb.medor.query.api.QueryTreeField; 48 import org.objectweb.medor.query.rdb.api.QualifiedTable; 49 import org.objectweb.medor.query.rdb.api.RdbExpField; 50 import org.objectweb.medor.query.rdb.api.RdbExpQueryLeaf; 51 import org.objectweb.medor.query.rdb.lib.BasicQualifiedTable; 52 import org.objectweb.medor.query.rdb.lib.BasicRdbExpQueryLeaf; 53 54 import java.util.ArrayList ; 55 56 63 public class GroupSameDBRule extends BasicRule implements RewriteRule { 64 71 protected class RdbQuery { 72 public ArrayList fields; 73 public ArrayList tables; 74 public Expression exp; 75 public DataStore ds; 76 80 public ArrayList tableIds; 81 public boolean hasSubQuery; 82 public ArrayList subQueries; 83 } 84 85 92 private class SplitQueries { 93 97 public ArrayList outerQts; 98 108 public ArrayList subQts; 109 } 110 111 121 public QueryTree rewrite(QueryTree qt, QueryNode parent) 122 throws MedorException { 123 RdbQuery rq = recurseRewrite(qt); 125 debug("end of recurse"); 126 if (rq != null) { 127 debug("building RdbLeaf"); 128 return buildRdbLeaf(rq, qt); 129 } 130 else 131 return qt; 132 } 133 134 140 private RdbQuery recurseRewrite(QueryTree qt) throws MedorException { 141 if (qt instanceof RdbExpQueryLeaf) { 143 debug("RdbExpQueryLeaf: START " + qt.getName()); 145 RdbQuery rq = new RdbQuery(); 146 Field[] lf = qt.getTupleStructure().getFields(); 147 rq.fields = new ArrayList (lf.length); 148 for (int i = 0; i < lf.length; i++) { 149 rq.fields.add(lf[i]); 150 } 151 QualifiedTable[] lqt = ((RdbExpQueryLeaf) qt).getQualifiedTables(); 152 rq.tables = new ArrayList (lqt.length); 153 rq.tableIds = new ArrayList (lqt.length); 154 for (int i = 0; i < lqt.length; i++) { 155 rq.tables.add(lqt[i]); 156 if (lqt[i].getAliasName() != null) 157 rq.tableIds.add(lqt[i].getAliasName()); 158 else 159 rq.tableIds.add(lqt[i].getTableName()); 160 } 161 rq.exp = ((RdbExpQueryLeaf) qt).getQueryFilter(); 162 rq.ds = ((RdbExpQueryLeaf) qt).getDataStore(); 163 debug("RdbExpQueryLeaf: END " + qt.getName()); 164 return rq; 165 } 166 else if (qt instanceof QueryLeaf) { 167 debug("QueryLeaf: " + qt); 168 return null; 169 } 170 else if (memberOfInExpression(((QueryNode) qt).getQueryFilter())) { 172 debug("QueryNode with MemberOf: " + qt); 174 SplitQueries split = splitQueries(qt); 175 debug("splitQueries done"); 176 debug("Structure of split: " 177 + "Left: " + split.outerQts.size() 178 + " Right: " + split.subQts.size() 179 ); 180 RdbQuery workRq = 182 exploreQueryTrees((QueryTree[]) split.outerQts.toArray( 183 new QueryTree[0]) 184 ); 185 debug("recursive exploreQueryTrees done"); 186 workRq.hasSubQuery = true; 187 if (noCalculation(qt)) { 188 debug("noCalculation: => continue"); 189 if (workRq.exp == null) { 191 workRq.exp = ((QueryNode) qt).getQueryFilter(); 192 } 193 else { 194 workRq.exp = 195 new And(workRq.exp, ((QueryNode) qt).getQueryFilter()); 196 } 197 workRq.subQueries = new ArrayList (); 199 debug("number of subqueries: " + split.subQts.size()); 200 for (int i = 0; i < split.subQts.size(); i++) { 201 RdbQuery innerRq = 202 exploreQueryTrees((QueryTree[]) 203 ((ArrayList ) split.subQts.get(i)).toArray( 204 new QueryTree[0]) 205 ); 206 workRq.subQueries.add(innerRq); 207 } 208 209 } 210 else { 211 createLeafAndUpdateLinks(workRq, qt); 212 workRq = null; 213 } 214 return workRq; 215 } 216 else { 217 debug("QueryNode without MemberOf: " + qt); 219 QueryTree[] children = ((QueryNode) qt).getChildren(); 220 RdbQuery workRq = exploreQueryTrees(children); 222 if (noCalculation(qt)) { 223 debug("noCalculation: => continue"); 224 if (workRq.exp == null) { 226 workRq.exp = ((QueryNode) qt).getQueryFilter(); 227 } 228 else { 229 workRq.exp = 230 new And(workRq.exp, ((QueryNode) qt).getQueryFilter()); 231 } 232 } 233 else { 234 createLeafAndUpdateLinks(workRq, qt); 235 workRq = null; 236 } 237 debug("QueryNode: END"); 238 return workRq; 239 } 240 } 241 242 251 private void createLeafAndUpdateLinks(RdbQuery workRq, QueryTree qt) 252 throws MedorException { 253 debug("Has calculated field: => stop, create RdbExpQL and link"); 254 RdbExpQueryLeaf ql = buildRdbLeaf(workRq, qt); 255 257 Field[] fs = qt.getTupleStructure().getFields(); 259 TupleStructure ts = ql.getTupleStructure(); 260 for (int i = 0; i < fs.length; i++) { 261 if (fs[i] instanceof PropagatedField) { 262 if (ts.contains(fs[i].getName())) { 263 debug("Replace in the PropagatedField " + fs[i].getName()); 264 ((QueryNode) qt).updatePropagatedField( 265 fs[i].getName(), 266 new QueryTreeField[]{ 267 (QueryTreeField) ts.getField( 268 fs[i].getName())}); 269 } 270 else 271 debug("Do not replace in the PropagatedField " + fs[i].getName()); 272 } 273 else if (fs[i] instanceof CalculatedField) { 274 debug("Try to replace in the CalculatedField " + fs[i].getName()); 275 Expression e = 276 ((CalculatedField) fs[i]).getExpression(); 277 if (replaceInFilter(e, ts)) 278 ((QueryNode) qt).updateCalculatedField( 279 fs[i].getName(), e); 280 } 281 else if (fs[i] instanceof NestedField) { 282 debug("Replace in the NestedField " + fs[i].getName()); 283 throw new MedorException("Unmanaged Nested Field"); 284 } 285 } 286 if (qt instanceof FilteredQueryTree) { 288 debug("Try to replace in the filter "); 289 Expression e = ((FilteredQueryTree) qt).getQueryFilter(); 290 if (replaceInFilter(e, ts)) 291 ((FilteredQueryTree) qt).setQueryFilter(e); 292 } 293 } 294 295 302 private RdbQuery exploreQueryTrees(QueryTree[] qts) throws MedorException { 303 boolean first = true; 304 RdbQuery workRq = null; 305 for (int i = 0; i < qts.length; i++) { 306 RdbQuery currentRq = recurseRewrite(qts[i]); 307 if (first) { 308 debug("first"); 309 workRq = currentRq; 310 first = false; 311 } 312 else if (workRq.ds != null && 313 workRq.ds.isSameAs(currentRq.ds)) { debug("Same store => merging"); 315 mergeRdbQueries(workRq, currentRq); 316 } 317 else { 318 throw new MedorException( 319 "Impossible to group two nodes with different data stores"); 320 } 321 } 322 return workRq; 323 } 324 325 335 private boolean replaceInFilter(Expression e, TupleStructure ts) 336 throws MedorException { 337 ArrayList al = new ArrayList (); 338 al.add(e); 339 boolean isModified = false; 340 while (!al.isEmpty()) { 341 Expression ex = (Expression) al.remove(0); 342 if (ex instanceof Operator) { 343 for (int i = 0; i < ((Operator) ex).getOperandNumber(); i++) { 344 al.add(((Operator) ex).getExpression(i)); 345 } 346 } 347 else if (ex instanceof FieldOperand) { 348 FieldOperand fo = (FieldOperand) ex; 349 if (ts.contains(fo.getField().getName())) { 350 debug("Replace in the FieldOperand: " + fo.getField().getName()); 351 fo.setField(ts.getField(fo.getField().getName())); 352 isModified = true; 353 } 354 else 355 debug("Do not replace in the FieldOperand: " + fo.getField().getName()); 356 } 357 } 358 return isModified; 359 } 360 361 370 private boolean noCalculation(QueryTree qt) { 371 debug("Testing for calculated fields: "); 372 Field[] qtf = qt.getTupleStructure().getFields(); 373 for (int i = 0; i < qtf.length; i++) { 374 if (qtf[i] instanceof CalculatedField) { 375 debug("found"); 376 return false; 377 } 378 } 379 debug("not found"); 380 return true; 381 } 382 383 390 private void mergeRdbQueries(RdbQuery into, RdbQuery other) { 391 for (int i = 0; i < other.fields.size(); i++) { 392 into.fields.add(other.fields.get(i)); 393 } 394 QualifiedTable qt; 395 for (int i = 0; i < other.tables.size(); i++) { 396 qt = (QualifiedTable) other.tables.get(i); 397 if (into.tables.contains(qt)) { 398 QualifiedTable qt1 = 401 new BasicQualifiedTable(qt.getTableName(), 402 qt.getAliasName()); 403 for (int j = 0; j < other.fields.size(); j++) { 404 if (((RdbExpField) other.fields.get(j)).getTable() == qt) 405 ((RdbExpField) other.fields.get(j)).setTable(qt1); 406 } 407 qt = qt1; 408 } 409 if (qt.getAliasName() != null) { 412 if (into.tableIds.contains(qt.getAliasName())) 413 qt.setAliasName(generateAlias(into.tableIds, 414 qt.getAliasName())); 415 } 416 else if (into.tableIds.contains(qt.getTableName())) 417 qt.setAliasName(generateAlias(into.tableIds, 418 qt.getTableName())); 419 into.tables.add(qt); 420 } 421 if (into.exp == null) into.exp = other.exp; 423 else if (other.exp != null) into.exp = new And(into.exp, other.exp); 425 } 426 427 436 private String generateAlias(ArrayList tableIds, String root) { 437 root += "_"; 438 int i = 1; 439 while (tableIds.contains(root + i)) { 440 i++; 441 } 442 root += i; 443 tableIds.add(root); 444 return root; 445 } 446 447 453 private boolean memberOfInExpression(Expression e) { 454 debug("entering memberOfInExpression"); 455 if (e instanceof MemberOf) 456 return true; 457 else if (e instanceof Operator) { 458 Operator op = (Operator) e; 459 boolean found = false; 460 for (int i = 0; i < op.getOperandNumber(); i++) { 461 if (memberOfInExpression(op.getExpression(i))) { 462 found = true; 463 break; 464 } 465 } 466 return found; 467 } 468 return false; 469 } 470 471 479 private RdbExpQueryLeaf buildRdbLeaf(RdbQuery rq, QueryTree qt) 480 throws MedorException { 481 RdbExpQueryLeaf ql; 482 if (rq.hasSubQuery) { 483 ql = new BasicRdbExpQueryLeaf( 484 rq.ds, 485 (QualifiedTable[]) rq.tables.toArray(new QualifiedTable[0]), 486 qt.getName() 487 ); 488 ql.setQueryFilter(rq.exp); 489 for (int i = 0; i < rq.fields.size(); i++) { 490 ql.addRdbField((RdbExpField) rq.fields.get(i)); 491 } 492 for (int i = 0; i < rq.subQueries.size(); i++) { 493 BasicRdbExpQueryLeaf subql = new BasicRdbExpQueryLeaf( 494 rq.ds, 495 (QualifiedTable[]) 496 ((RdbQuery) rq.subQueries.get(i)).tables.toArray( 497 new QualifiedTable[0]), 498 qt.getName()); 499 replaceInFilter(ql.getQueryFilter(), subql.getTupleStructure()); 500 } 501 } 502 else { 503 ql = new BasicRdbExpQueryLeaf( 504 rq.ds, 505 (QualifiedTable[]) rq.tables.toArray(new QualifiedTable[0]), 506 qt.getName()); 507 ql.setQueryFilter(rq.exp); 509 for (int i = 0; i < rq.fields.size(); i++) { 510 ql.addRdbField((RdbExpField) rq.fields.get(i)); 511 } 512 } 513 514 return ql; 515 } 516 517 524 private SplitQueries splitQueries(QueryTree qt) { 525 SplitQueries split = new SplitQueries(); 526 split.outerQts = new ArrayList (); 527 split.subQts = new ArrayList (); 528 Expression e = ((QueryNode) qt).getQueryFilter(); 529 return recurseSplit(split, e); 530 } 531 532 540 private SplitQueries recurseSplit(SplitQueries split, Expression e) { 541 if (e instanceof FieldOperand) { 542 QueryTreeField f = (QueryTreeField) ((FieldOperand) e).getField(); 543 QueryTree qtf = f.getQueryTree(); 544 if (!split.outerQts.contains(qtf)) 545 split.outerQts.add(qtf); 546 } 547 else if ((e instanceof CompositePName) || 548 (e instanceof SinglePName) || 549 (e instanceof Operand)) { 550 return split; 551 } 552 else if (e instanceof MemberOf) { 553 debug("splitting MemberOf"); 554 MemberOf mo = (MemberOf) e; 555 int moSize = mo.getOperandNumber() / 2; 556 for (int i = 0; i < moSize; i++) { 558 if (((MemberOf) e).getExpression(i) instanceof FieldOperand) { 559 QueryTreeField fLeft = 560 (QueryTreeField) 561 ((FieldOperand) 562 ((MemberOf) e).getExpression(i)).getField(); 563 QueryTree qtfLeft = fLeft.getQueryTree(); 564 debug("Left node is " + qtfLeft.getName()); 565 if (!split.outerQts.contains(qtfLeft)) 566 split.outerQts.add(qtfLeft); 567 } 568 } 569 ArrayList newSub = null; 570 for (int i = 0; i < moSize; i++) { 571 QueryTreeField fRight = 572 (QueryTreeField) 573 ((FieldOperand) 574 ((MemberOf) e).getExpression(i + moSize)).getField(); 575 QueryTree qtfRight = fRight.getQueryTree(); 576 debug("Right node is " + qtfRight.getName()); 577 if (split.outerQts.contains(qtfRight)) 579 split.outerQts.remove(qtfRight); 580 boolean isInSub = false; 583 for (int j = 0; j < split.subQts.size(); j++) { 584 if (((ArrayList ) split.subQts.get(j)).contains(qtfRight)) { 585 isInSub = true; 586 break; 587 } 588 } 589 debug("found in subqueries:" + isInSub); 590 if (!isInSub) { 591 if (newSub == null) 592 newSub = new ArrayList (1); 593 newSub.add(qtfRight); 594 } 595 } 596 if (newSub != null) 597 split.subQts.add(newSub); 598 return split; 599 } 600 else if (e instanceof Operator) { 601 Operator op = (Operator) e; 602 for (int i = 0; i < op.getOperandNumber(); i++) { 603 split = recurseSplit(split, op.getExpression(i)); 604 } 605 return split; 606 } 607 608 return split; 609 } 610 611 private static final void debug(String msg) { 612 } 614 } 615 | Popular Tags |