1 23 package org.objectweb.medor.optim.jorm; 24 25 import java.util.ArrayList ; 26 import java.util.Collection ; 27 import java.util.HashMap ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.Map ; 31 32 import org.objectweb.jorm.api.PClassMapping; 33 import org.objectweb.jorm.api.PException; 34 import org.objectweb.jorm.api.PMapper; 35 import org.objectweb.jorm.mapper.rdb.adapter.RdbAdapterFactory; 36 import org.objectweb.jorm.mapper.rdb.adapter.api.JoinedTable; 37 import org.objectweb.jorm.mapper.rdb.adapter.api.RdbAdapterException; 38 import org.objectweb.jorm.mapper.rdb.lib.RdbPPolymorphicClass; 39 import org.objectweb.jorm.mapper.rdb.metainfo.RdbClassMultiMapping; 40 import org.objectweb.jorm.mapper.rdb.metainfo.RdbExternalTable; 41 import org.objectweb.jorm.mapper.rdb.metainfo.RdbGenClassMapping; 42 import org.objectweb.jorm.mapper.rdb.metainfo.RdbJoin; 43 import org.objectweb.jorm.mapper.rdb.metainfo.RdbPrimitiveElementMapping; 44 import org.objectweb.jorm.mapper.rdb.metainfo.RdbTable; 45 import org.objectweb.jorm.metainfo.api.Class; 46 import org.objectweb.jorm.metainfo.api.GenClassRef; 47 import org.objectweb.jorm.metainfo.api.NameDef; 48 import org.objectweb.jorm.metainfo.api.PrimitiveElement; 49 import org.objectweb.jorm.naming.api.PName; 50 import org.objectweb.jorm.type.api.PType; 51 import org.objectweb.medor.api.Field; 52 import org.objectweb.medor.api.MedorException; 53 import org.objectweb.medor.datasource.api.DataStore; 54 import org.objectweb.medor.datasource.lib.ConnectionFactoryDataStore; 55 import org.objectweb.medor.expression.api.BinaryLogicalOperator; 56 import org.objectweb.medor.expression.api.Comparator; 57 import org.objectweb.medor.expression.api.Expression; 58 import org.objectweb.medor.expression.api.ExpressionException; 59 import org.objectweb.medor.expression.api.MalformedExpressionException; 60 import org.objectweb.medor.expression.api.Operand; 61 import org.objectweb.medor.expression.api.Operator; 62 import org.objectweb.medor.expression.api.ParameterOperand; 63 import org.objectweb.medor.expression.api.VariableOperand; 64 import org.objectweb.medor.expression.lib.And; 65 import org.objectweb.medor.expression.lib.BasicVariableOperand; 66 import org.objectweb.medor.expression.lib.Equal; 67 import org.objectweb.medor.expression.lib.Not; 68 import org.objectweb.medor.expression.lib.NotEqual; 69 import org.objectweb.medor.expression.lib.Or; 70 import org.objectweb.medor.filter.api.FieldOperand; 71 import org.objectweb.medor.filter.jorm.lib.CompositePName; 72 import org.objectweb.medor.filter.jorm.lib.EncodePName; 73 import org.objectweb.medor.filter.jorm.lib.SinglePName; 74 import org.objectweb.medor.filter.lib.BasicFieldOperand; 75 import org.objectweb.medor.filter.lib.Count; 76 import org.objectweb.medor.filter.lib.ExpressionPrinter; 77 import org.objectweb.medor.filter.lib.IsEmpty; 78 import org.objectweb.medor.filter.lib.IsNull; 79 import org.objectweb.medor.filter.lib.MemberOf; 80 import org.objectweb.medor.optim.api.RewriteRule; 81 import org.objectweb.medor.optim.lib.PushNotInExpressionRule; 82 import org.objectweb.medor.query.api.CalculatedField; 83 import org.objectweb.medor.query.api.OrderField; 84 import org.objectweb.medor.query.api.PropagatedField; 85 import org.objectweb.medor.query.api.QueryNode; 86 import org.objectweb.medor.query.api.QueryTree; 87 import org.objectweb.medor.query.api.QueryTreeField; 88 import org.objectweb.medor.query.jorm.api.JormExtent; 89 import org.objectweb.medor.query.jorm.lib.ClassExtent; 90 import org.objectweb.medor.query.jorm.lib.PNameField; 91 import org.objectweb.medor.query.lib.BasicCalculatedField; 92 import org.objectweb.medor.query.lib.BasicOrderField; 93 import org.objectweb.medor.query.lib.Nest; 94 import org.objectweb.medor.query.lib.QueryTreePrinter; 95 import org.objectweb.medor.query.lib.SelectProject; 96 import org.objectweb.medor.query.rdb.api.QualifiedTable; 97 import org.objectweb.medor.query.rdb.api.RdbExpField; 98 import org.objectweb.medor.query.rdb.api.RdbExpQueryLeaf; 99 import org.objectweb.medor.query.rdb.api.RdbField; 100 import org.objectweb.medor.query.rdb.lib.BasicQualifiedTable; 101 import org.objectweb.medor.query.rdb.lib.BasicRdbExpQueryLeaf; 102 import org.objectweb.util.monolog.api.BasicLevel; 103 104 115 public class JormFlatten2Rdb extends JormRule { 116 117 public JormFlatten2Rdb() { 118 super("JormFlatten2Rdb"); 119 } 120 121 124 private List extents = new ArrayList (); 125 126 129 private List mappings = new ArrayList (); 130 131 134 private List subLeaves = new ArrayList (); 135 136 139 private int alias = 0; 140 141 private List joinedTables = new ArrayList (); 142 143 148 private List mofs = new ArrayList (); 149 private List mofExtents = new ArrayList (); 150 private List empties = new ArrayList (); 151 152 public QueryTree rewrite(QueryTree qt, QueryNode parent) 153 throws MedorException { 154 log.log(BasicLevel.DEBUG, "JormFlatten2Rdb: Input query tree:"); 155 QueryTreePrinter.printQueryTree(qt, log, BasicLevel.DEBUG); 156 extents.clear(); 157 mappings.clear(); 158 alias = 0; 159 joinedTables.clear(); 160 mofs.clear(); 161 mofExtents.clear(); 162 empties.clear(); 163 subLeaves.clear(); 164 Map localyReplaced = (parent == null ? null : new HashMap ()); 166 167 if (qt instanceof JormExtent) { 168 SelectProject p = new SelectProject(""); 169 Field[] fs = qt.getTupleStructure().getFields(); 170 for (int i = 0; i < fs.length; i++) { 171 Field newF = 172 p.addPropagatedField(fs[i].getName(), fs[i].getType(), 173 new QueryTreeField[]{(QueryTreeField) fs[i]}); 174 if (parent != null) { 175 localyReplaced.put(fs[i], newF); 176 } 177 } 178 186 replaceUsage(parent, localyReplaced); 187 return rewrite(p, parent); 188 } 189 QueryNode qn = (QueryNode) qt; 190 QueryTree[] children = qn.getChildren(); 191 for (int i = 0; i < children.length; i++) { 192 RdbJormExtentMapping rjem = 194 new RdbJormExtentMapping((JormExtent) children[i]); 195 rjem.outer = qn.isOuter(children[i]); 196 extents.add(children[i]); 197 mappings.add(rjem); 198 } 199 Expression filter; 200 boolean assignfilter = false; 201 try { 202 filter = qn.getQueryFilter(); 203 assignfilter = (filter != null); 204 } 205 catch (Exception e) { 206 filter = null; 207 } 208 if (debug) { 209 log.log(BasicLevel.DEBUG, "The initial structure values"); 210 for (int i = 0; i < mappings.size(); i++) { 211 log.log(BasicLevel.DEBUG, "Extent " + ((RdbJormExtentMapping) mappings.get(i)).extent.getName()); 212 log.log(BasicLevel.DEBUG, "Extent tables size " + ((RdbJormExtentMapping) mappings.get(i)).tables.size()); 213 QualifiedTable quali = ((QualifiedTable) ((RdbJormExtentMapping) mappings.get(i)).tables.get(0)); 214 log.log(BasicLevel.DEBUG, "Extent table 0 " + quali.getTableName()); 215 log.log(BasicLevel.DEBUG, "Extent table alias 0 " + quali.getAliasName()); 216 log.log(BasicLevel.DEBUG, "Join size " + ((RdbJormExtentMapping) mappings.get(i)).joins.size()); 217 220 log.log(BasicLevel.DEBUG, mappings.get(i)); 221 } 222 log.log(BasicLevel.DEBUG, "Removing useless pname equality"); 224 } 225 filter = removeUseLessPNameEquality(filter); 226 if (debug) { 227 for (int i = 0; i < mappings.size(); i++) { 228 log.log(BasicLevel.DEBUG, mappings.get(i)); 229 } 230 log.log(BasicLevel.DEBUG, "filter: " + ExpressionPrinter.e2str(filter)); 231 log.log(BasicLevel.DEBUG, "Updating the projected fields"); 232 } 233 234 DataStore ds = ((JormExtent) children[0]).getDataStore(); 236 String databasename = 237 ((JormExtent) children[0]).getPMapper().getMapperName(); 238 int idx = databasename.indexOf('.'); 239 if (idx != -1) { 240 databasename = databasename.substring(idx + 1); 241 } else { 242 databasename = RdbAdapterFactory.DATABASE_NAME_JDBC; 243 } 244 if (ds == null) { 245 Object cf = 246 ((JormExtent) children[0]).getPMapper().getConnectionFactory(); 247 ds = new ConnectionFactoryDataStore( 248 DataStore.JDBC_STORE, 249 cf.toString(), 250 new short[0], 251 cf); 252 } 253 BasicRdbExpQueryLeaf leaf = new BasicRdbExpQueryLeaf(ds, ""); 254 boolean distinctLeafForCountAll = false; 255 try { 256 leaf.setRdbAdapter(RdbAdapterFactory.getTypeConverter(databasename)); 257 } 258 catch (RdbAdapterException e) { 259 throw new MedorException( 260 "Impossible to assign the rdb adapter to the leaf", e); 261 } 262 Field[] fs = qt.getTupleStructure().getFields(); 263 for (int i = 0; i < fs.length; i++) { 264 if (fs[i] instanceof PropagatedField) { 265 QueryTreeField qtf = (QueryTreeField) 266 ((PropagatedField) fs[i]).getPreviousFields()[0]; 267 if (qtf instanceof PNameField) { 268 Count countexp = fieldUsedInCount(qtf, parent); 270 if (countexp == null) { 271 if (debug) log.log(BasicLevel.DEBUG, "Regularly used PName"); 272 CalculatedField cf = new BasicCalculatedField( 273 qtf.getName(), qtf.getType(), qtf.getQueryTree(), 274 getDecode((PNameField) qtf, leaf, true)); 275 if (debug) log.log(BasicLevel.DEBUG, "Replacing PName with calculated field (old " + fs[i] + ", new "+ cf + ")"); 276 qn.replace((QueryTreeField) fs[i], cf); 277 if (parent != null) { 278 localyReplaced.put(fs[i], cf); 279 } 280 } else { 281 if (debug) log.log(BasicLevel.DEBUG, "Found a count"); 282 283 288 JormExtent extent = (JormExtent) qtf.getQueryTree(); 289 if (debug) { 290 log.log(BasicLevel.DEBUG, "in extent " + extent.getJormName()); 291 } 292 log.log(BasicLevel.DEBUG, "Looking for NameDef of " + qtf); 293 NameDef nd = ((PNameField)qtf).getNameDef(extent); 294 if (nd.isFieldName()) { QueryTreeField newf = 296 getField(nd.getFieldName(), extent, leaf, true); 297 qn.updatePropagatedField( 298 fs[i].getName(), new QueryTreeField[]{newf}); 299 log.log(BasicLevel.DEBUG, "New field for single PName " + newf); 300 } else if (nd.isNameRef()) { Map proj = nd.getNameRef().getProjection(); 302 QueryTreeField newqtf = null; 303 QueryTreeField[] newqtfT = new QueryTreeField[proj.entrySet().size()]; 304 int j = 0; 305 for (Iterator it = proj.entrySet().iterator(); it.hasNext();) { 306 Map.Entry me = (Map.Entry ) it.next(); 307 String clafn = (String ) me.getValue(); 308 newqtf = getField(clafn, extent, leaf, true); 309 newqtfT[j] = newqtf; 310 j++; 311 } 312 log.log(BasicLevel.DEBUG, "New field for composite PName " + newqtf); 313 qn.updatePropagatedField(fs[i].getName(), newqtfT); 314 if (proj.size() > 1) { 315 log.log(BasicLevel.INFO, "Count on multiple fields: no other aggregate functions should be allowed"); 316 countexp.setCountAll(); 317 distinctLeafForCountAll = true; 320 } 321 } 322 323 } 324 } else { 325 QueryTreeField f = getField(qtf, leaf, true); 326 qn.updatePropagatedField( 327 fs[i].getName(), new QueryTreeField[]{f}); 328 } 329 } else if (fs[i] instanceof CalculatedField) { 330 Expression e = ((CalculatedField) fs[i]).getExpression(); 331 try { 332 e = updateFieldOfExpression(e, leaf, true); 333 } 334 catch (ExpressionException e1) { 335 throw new MedorException(e1); 336 } 337 qn.updateCalculatedField(fs[i].getName(), e); 338 } else { 339 throw new MedorException( 340 "Unmanaged field (" + fs[i].getName() + "): " + fs[i]); 341 } 342 } 343 351 replaceUsage(parent, localyReplaced); 352 if (debug) { 353 log.log(BasicLevel.DEBUG, "Updating the order by clause"); 354 } 355 OrderField[] ofields = qt.getOrderBy(); 356 if (ofields != null) { 357 for (int j = 0; j < ofields.length; j++) { 358 QueryTreeField f = getField(ofields[j].getField(), leaf, false); 359 ofields[j].setField(f); 360 } 361 } 362 if (debug) { 363 log.log(BasicLevel.DEBUG, "Updating the filter"); 364 } 365 try { 366 filter = updateFieldOfExpression(filter, leaf, false); 367 } 368 catch (ExpressionException e) { 369 throw new MedorException(e); 370 } 371 if (debug) { 372 log.log(BasicLevel.DEBUG, "filter: " + ExpressionPrinter.e2str(filter)); 373 } 374 if (assignfilter) { 375 qn.setQueryFilter(null); 376 } 377 leaf.setQueryFilter(filter); 378 leaf.setRootJoinedTables(joinedTables); 379 if (debug) { 380 log.log(BasicLevel.DEBUG, "joinedTables: " + joinedTables); 381 log.log(BasicLevel.DEBUG, "JormFlatten2Rdb: Query leaf expression:"); 382 log.log(BasicLevel.DEBUG, ExpressionPrinter.e2str(filter)); 383 } 384 385 RewriteRule rule = new PushNotInExpressionRule(); 388 rule.rewrite(leaf, null); 390 filter = leaf.getQueryFilter(); 391 392 splitLeaf(leaf, filter); 393 leaf.setDistinct(distinctLeafForCountAll ? true : qt.getDistinct()); 395 leaf.setIsSubquery(distinctLeafForCountAll); 397 if (ofields != null) { 399 OrderField[] leafOFields = 400 new BasicOrderField[ofields.length]; 401 for (int j = 0; j < ofields.length; j++) { 402 OrderField of = new BasicOrderField( 403 ofields[j].getField(), 404 ofields[j].getDesc() 405 ); 406 leafOFields[j] = of; 407 } 408 leaf.setOrderBy(leafOFields); 409 } 410 leaf.setQueryFilter(updateFilterWithNewLeaves(filter, leaf)); 411 log.log(BasicLevel.DEBUG, "JormFlatten2Rdb: Output query tree:"); 412 QueryTreePrinter.printQueryTree(qt, log, BasicLevel.DEBUG); 413 return qt; 414 } 415 416 417 422 public class RdbJormExtentMapping { 423 424 427 private JormExtent extent = null; 428 429 432 private boolean outer = true; 433 434 441 private List tables = new ArrayList (5); 442 443 450 private List joins = new ArrayList (5); 451 452 public RdbJormExtentMapping(JormExtent je) throws MedorException { 453 setJormExtent(je); 454 } 455 456 462 public void setJormExtent(JormExtent je) throws MedorException { 463 extent = je; 464 if (extent.getMetaObject() instanceof Class ) { 465 RdbClassMultiMapping cm = 466 (RdbClassMultiMapping) getClassMapping(extent); 467 RdbTable maintable = cm.getRdbTable(); 468 Class cl = (Class ) cm.getLinkedMO(); 469 boolean isPolymorphic = cl.isPolymorphic(); 470 String tableName = maintable.getName(); 471 String alias = ""; 472 String query = "( "; 473 if (isPolymorphic) { 474 PMapper mapper = extent.getPMapper(); 476 PClassMapping pcm = mapper.lookup(cl.getFQName()); 478 String primaryKey = ((RdbPPolymorphicClass)pcm).getPNameFields(); 479 if (je.withSubClasses()) { 480 query += cm.getRdbInheritanceQuery().getExtentQuery( 481 mapper, 482 ((ClassExtent)extent).isPrefetch(), 483 false, 484 primaryKey, 485 pcm); 486 } else { 487 RdbPPolymorphicClass polymorphicPCM = (RdbPPolymorphicClass) pcm; 488 try { 489 query += polymorphicPCM.getExtentQuery(true); 490 } catch (PException e) { 491 throw new MedorException(e); 492 } 493 } 494 query += ")"; 495 alias = getQueryAlias(tableName); 496 } else { 497 alias = getTableAlias(maintable, null); 498 } 499 QualifiedTable mainqtable = new BasicQualifiedTable( 500 (isPolymorphic?query:tableName), 501 alias, 502 isPolymorphic); 503 tables.add(mainqtable); 504 joins.add(null); 505 506 if (isPolymorphic) 508 return; 509 510 Collection etables = cm.getRdbExternalTables(); 511 Iterator tableit = etables.iterator(); 512 while (tableit.hasNext()) { 513 RdbExternalTable etable = (RdbExternalTable) tableit.next(); 514 Collection rdbJjoins = etable.getRdbJoins(); 515 Iterator joinit = rdbJjoins.iterator(); 516 if (!joinit.hasNext()) { 517 throw new MedorException( 518 "No join defined for the external table " 519 + etable.getName() + " in the extent " 520 + je.getJormName()); 521 } 522 while (joinit.hasNext()) { 523 RdbJoin j = (RdbJoin) joinit.next(); 524 Join join = new Join(j, maintable, etable); 525 joins.add(join); 526 QualifiedTable qtable = 527 new BasicQualifiedTable(etable.getName(), 528 getTableAlias(etable, j)); 529 tables.add(qtable); 530 } 531 } 532 } else if (extent.getMetaObject() instanceof GenClassRef) { 533 RdbGenClassMapping gcm = 534 (RdbGenClassMapping) getGenClassMapping(extent); 535 RdbTable maintable = gcm.getRdbTable(); 536 QualifiedTable mainqtable = new BasicQualifiedTable( 537 maintable.getName(), 538 getTableAlias(maintable, null)); 539 tables.add(mainqtable); 540 joins.add(null); 541 } 542 } 543 544 public int getJoinIndex(String joinname) throws MedorException { 545 for (int i = 1; i < joins.size(); i++) { 546 if (joinname.equals(((Join) joins.get(i)).name)) { 547 return i; 548 } 549 } 550 throw new MedorException("Join " + joinname 551 + " not found in the extent of the class " 552 + extent.getJormName()); 553 } 554 555 public String toString() { 556 StringBuffer sb = new StringBuffer (); 557 sb.append("* ExtentMapping: "); 558 sb.append(extent.getJormName()); 559 sb.append("\n"); 560 sb.append("Tables:\n"); 561 for (int i = 0; i < tables.size(); i++) { 562 QualifiedTable qt = (QualifiedTable) tables.get(i); 563 sb.append(qt.getAliasName()); 564 sb.append(" join: "); 565 if (joins.get(i) != null) { 566 sb.append(joins.get(i)); 567 } 568 sb.append("\n"); 569 } 570 return sb.toString(); 571 } 572 } 573 574 577 public class Join { 578 579 583 public String name = ""; 584 585 588 public JoinColumn[] columns = null; 589 590 599 public Join(RdbJoin j, RdbTable maintable, RdbTable externaltable) { 600 name = j.getName(); 601 List mcols = j.getPTJoinColumnNames(); 602 List ecols = j.getETJoinColumnNames(); 603 columns = new JoinColumn[ecols.size()]; 604 for (int i = 0; i < ecols.size(); i++) { 605 JoinColumn jc = new JoinColumn(); 606 jc.column1 = (String ) mcols.get(i); 607 jc.column2 = (String ) ecols.get(i); 608 RdbPrimitiveElementMapping pem = 609 (RdbPrimitiveElementMapping) maintable 610 .getPrimitiveElementMappingByCol(jc.column1); 611 PrimitiveElement pe = (PrimitiveElement) pem.getLinkedMO(); 612 jc.type = pe.getType(); 613 jc.field1 = pe.getName(); 614 pem = (RdbPrimitiveElementMapping) externaltable 615 .getPrimitiveElementMappingByCol(jc.column2); 616 if (pem != null) { 617 pe = pem.lookupPrimitiveElement(j); 618 jc.field2 = pe.getName(); 619 } 620 columns[i] = jc; 621 } 622 } 623 624 public String toString() { 625 StringBuffer sb = new StringBuffer (); 626 sb.append(name); 627 String sep = "{"; 628 for (int i = 0; i < columns.length; i++) { 629 sb.append(sep); 630 sb.append(columns[i]); 631 sep = " && "; 632 } 633 sb.append('}'); 634 return sb.toString(); 635 } 636 } 637 638 641 public class JoinColumn { 642 643 646 public PType type = null; 647 648 651 public String field1 = null; 652 653 656 public String column1 = null; 657 658 661 public String field2 = null; 662 663 666 public String column2 = null; 667 668 public String toString() { 669 return "(" + column1 + " = " + column2 + ")"; 670 } 671 } 672 673 678 public RdbJormExtentMapping getMapping(int i) { 679 return (RdbJormExtentMapping) mappings.get(i); 680 } 681 682 687 public RdbJormExtentMapping getMapping(JormExtent je) { 688 int i = extents.indexOf(je); 689 return (i == -1 ? null : (RdbJormExtentMapping) mappings.get(i)); 690 } 691 692 699 private String getTableAlias(RdbTable table, RdbJoin join) { 700 return (join == null 701 ? table.getName() + "_" + (alias++) 702 : table.getName() + "_" + (alias++) + "_" + join.getName()); 703 } 704 705 709 private String getQueryAlias(String tableName){ 710 return tableName + "_" + (alias++); 711 } 712 713 724 private Expression removeUseLessPNameEquality(Expression e) 725 throws MedorException { 726 if (e == null) { 727 return null; 728 } 729 if (e instanceof Equal) { 730 Equal eq = (Equal) e; 731 Expression left = eq.getExpression(0); 732 Expression right = eq.getExpression(1); 733 if (left instanceof FieldOperand && right instanceof FieldOperand) { 734 FieldOperand fo1 = (FieldOperand) left; 735 FieldOperand fo2 = (FieldOperand) right; 736 QueryTreeField qtf1 = (QueryTreeField) fo1.getField(); 737 QueryTreeField qtf2 = (QueryTreeField) fo2.getField(); 738 if (qtf1 instanceof PNameField & qtf2 instanceof PNameField) { 739 741 PNameField pnf1 = (PNameField) qtf1; 742 JormExtent je1 = (JormExtent) pnf1.getQueryTree(); 743 log.log(BasicLevel.DEBUG, "JormExtent: " + je1 + " " + je1.getName()); 744 log.log(BasicLevel.DEBUG, "PNameField: " + pnf1.getName()); 745 NameDef nd1 = pnf1.getNameDef(je1); 746 log.log(BasicLevel.DEBUG, "NameDef1: " + nd1); 747 748 PNameField pnf2 = (PNameField) qtf2; 749 JormExtent je2 = (JormExtent) pnf2.getQueryTree(); 750 NameDef nd2 = pnf2.getNameDef(je2); 751 log.log(BasicLevel.DEBUG, "NameDef2: " + nd2); 752 753 boolean sameTable = true; 754 if (nd1.isFieldName() && nd2.isFieldName()) { 755 sameTable = sameColumn(je1, nd1.getFieldName(), 757 je2, nd2.getFieldName(), true); 758 } else if (nd1.isNameRef() && nd2.isNameRef()) { 759 if (!nd1.getNameRef().getCompositeName().getFQName() 760 .equals( 761 nd2.getNameRef().getCompositeName().getFQName())) { 762 throw new MedorException("Bad PName equality: " + 763 "two different composite name"); 764 } 765 Map proj1 = nd1.getNameRef().getProjection(); 766 Map proj2 = nd2.getNameRef().getProjection(); 767 if (proj1.size() != proj2.size()) { 768 throw new MedorException( 769 "Bad PName equality: bad projection size"); 770 } 771 Iterator it = proj1.entrySet().iterator(); 772 while (it.hasNext() && sameTable) { 774 Map.Entry me = (Map.Entry ) it.next(); 775 String cofn = (String ) me.getKey(); 776 String clfn1 = (String ) me.getValue(); 777 String clfn2 = (String ) proj2.get(cofn); 778 sameTable = sameColumn( 779 je1, clfn1, je2, clfn2, !it.hasNext()); 780 } 781 } else { 782 throw new MedorException("Bad PName equality: " + 783 "PName structures unknwon or not same"); 784 } 785 if (sameTable) { 786 return null; 788 } 789 } 790 } 791 } else if (e instanceof BinaryLogicalOperator) { 792 Operator op = (Operator) e; 794 Expression e0 = removeUseLessPNameEquality(op.getExpression(0)); 795 Expression e1 = removeUseLessPNameEquality(op.getExpression(1)); 796 if (e0 == null && e1 != null) { 797 return e1; 799 } else if (e0 != null && e1 == null) { 800 return e0; 802 } else if (e0 == null && e1 == null) { 803 return null; 805 } else { 806 if (e0 != null && e0 != op.getExpression(0)) { 808 op.setExpression(0, e0); 809 } 810 if (e0 != null && e0 != op.getExpression(0)) { 811 op.setExpression(0, e0); 812 } 813 return op; 814 } 815 } else if (e instanceof Operator) { 816 Operator op = (Operator) e; 819 int size = op.getOperandNumber(); 820 for (int i = 0; i < size; i++) { 821 if (removeUseLessPNameEquality(op.getExpression(i)) == null) { 822 throw new MedorException( 823 "Impossible to remove the operand " + i 824 + " of operator " + e); 825 } 826 } 827 } 828 return e; 830 } 831 832 850 private boolean sameColumn(JormExtent je1, 851 String fieldname1, 852 JormExtent je2, 853 String fieldname2, 854 boolean replacetable) throws MedorException { 855 RdbPrimitiveElementMapping pem1 = 856 (RdbPrimitiveElementMapping) getPEM(je1, fieldname1); 857 RdbTable t1 = (RdbTable) pem1.getParent(); 858 RdbPrimitiveElementMapping pem2 = 859 (RdbPrimitiveElementMapping) getPEM(je2, fieldname2); 860 RdbTable t2 = (RdbTable) pem2.getParent(); 861 boolean res = t1.getName().equals(t2.getName()) 862 && t1.isColocated() 863 && t2.isColocated() 864 && pem1.getName().equals(pem2.getName()); 865 if (debug) { 866 log.log(BasicLevel.DEBUG, "Comparing field " + fieldname1 + " to " + fieldname2 867 + ": result " + res); 868 } 869 if (res && replacetable) { 870 RdbJormExtentMapping rjem1 = getMapping(je1); 871 int idx1 = getTableIndex(rjem1, pem1, unQualifiedName(fieldname1, je1)); 872 RdbJormExtentMapping rjem2 = getMapping(je2); 873 int idx2 = getTableIndex(rjem2, pem2, unQualifiedName(fieldname2, je2)); 874 if (t1 instanceof RdbExternalTable) { 875 replaceTable(rjem2, idx2, rjem1, idx1); 876 } else { 877 replaceTable(rjem1, idx1, rjem2, idx2); 878 } 879 } 880 return res; 881 } 882 883 890 private void replaceTable(RdbJormExtentMapping rjem1, 891 int idx1, 892 RdbJormExtentMapping rjem2, 893 int idx2) { 894 if (debug) { 895 log.log(BasicLevel.DEBUG, "Replacing table " 896 + idx1 + " of extent " + mappings.indexOf(rjem1) 897 + " by table " 898 + idx2 + " of extent " + mappings.indexOf(rjem2)); 899 } 900 QualifiedTable old = (QualifiedTable) rjem1.tables.get(idx1); 901 QualifiedTable neo = (QualifiedTable) rjem2.tables.get(idx2); 902 for (int i = 0; i < mappings.size(); i++) { 903 RdbJormExtentMapping r = (RdbJormExtentMapping) mappings.get(i); 904 for (int j = 0; j < r.tables.size(); j++) { 905 if (r.tables.get(j) == old) { 906 r.tables.set(j, neo); 907 } 908 } 909 } 910 } 911 912 921 private int getTableIndex(RdbJormExtentMapping rjem, 922 RdbPrimitiveElementMapping pem, 923 String fieldname) throws MedorException { 924 if (rjem.tables.size() == 1 && rjem.joins.get(0) == null) { 926 return 0; 927 } 928 Iterator it = pem.getPrimitiveElementByRdbJoin().entrySet().iterator(); 929 if (!it.hasNext()) 930 return 0; 931 RdbJoin j = null; 932 while (it.hasNext()) { 933 Map.Entry me = (Map.Entry ) it.next(); 934 if (((PrimitiveElement) me.getValue()).getName().equals(fieldname)) { 935 j = (RdbJoin) me.getKey(); 936 break; 937 } 938 } 939 if (j == null) { 940 throw new MedorException( 942 "No join found for the mapping of the column '" 943 + pem.getName() + "'"); 944 } 945 return rjem.getJoinIndex(j.getName()); 946 } 947 948 960 public Expression updateFieldOfExpression(Expression e, 961 BasicRdbExpQueryLeaf leaf, 962 boolean add) 963 throws MedorException, ExpressionException { 964 log.log(BasicLevel.DEBUG, "Entering updateFieldOfExpression for " + ExpressionPrinter.e2str(e)); 965 if (e == null) { 966 return null; 967 } 968 if ((e instanceof Equal) 969 || (e instanceof NotEqual) 970 || (e instanceof MemberOf)) { 971 Operator eq = (Operator) e; 972 Expression left = eq.getExpression(0); 973 Expression right = eq.getExpression(1); 974 if (left instanceof FieldOperand && right instanceof FieldOperand) { 975 FieldOperand fo1 = (FieldOperand) left; 976 FieldOperand fo2 = (FieldOperand) right; 977 QueryTreeField qtf1 = (QueryTreeField) fo1.getField(); 978 QueryTreeField qtf2 = (QueryTreeField) fo2.getField(); 979 if (qtf1 instanceof PNameField && qtf2 instanceof PNameField) { 980 982 PNameField pnf1 = (PNameField) qtf1; 983 JormExtent je1 = (JormExtent) pnf1.getQueryTree(); 984 NameDef nd1 = pnf1.getNameDef(je1); 985 986 PNameField pnf2 = (PNameField) qtf2; 987 JormExtent je2 = (JormExtent) pnf2.getQueryTree(); 988 NameDef nd2 = pnf2.getNameDef(je2); 989 990 if (nd1.isFieldName() && nd2.isFieldName()) { 991 if (debug) { 993 log.log(BasicLevel.DEBUG, "Replace the PName comparison: " 994 + ExpressionPrinter.e2str(e)); 995 } 996 fo1.setField(getField(nd1.getFieldName(), je1, leaf, add)); 997 fo2.setField(getField(nd2.getFieldName(), je2, leaf, add)); 998 if (debug) { 999 log.log(BasicLevel.DEBUG, "by the field comparison: " 1000 + ExpressionPrinter.e2str(e)); 1001 } 1002 if (e instanceof MemberOf) { 1003 mofs.add(e); 1004 extents.add(je2); 1005 } 1006 return e; 1007 } else if (nd1.isNameRef() && nd2.isNameRef()) { 1008 if (!nd1.getNameRef().getCompositeName().getFQName() 1009 .equals(nd2.getNameRef().getCompositeName().getFQName())) { 1010 throw new MalformedExpressionException("Bad PName " + 1011 "equality: two different composite name"); 1012 } 1013 Map proj1 = nd1.getNameRef().getProjection(); 1014 Map proj2 = nd2.getNameRef().getProjection(); 1015 if (proj1.size() != proj2.size()) { 1016 throw new MalformedExpressionException( 1017 "Bad PName equality: bad projection size"); 1018 } 1019 if (debug) { 1022 log.log(BasicLevel.DEBUG, "Replace the PName comparison: " 1023 + ExpressionPrinter.e2str(e)); 1024 } 1025 Expression res = null; 1026 Iterator it = proj1.entrySet().iterator(); 1027 ArrayList al1 = null; 1028 ArrayList al2 = null; 1029 if (e instanceof MemberOf) { 1030 al1 = new ArrayList (1); 1031 al2 = new ArrayList (1); 1032 } 1033 while (it.hasNext()) { 1034 Map.Entry me = (Map.Entry ) it.next(); 1035 String cofn = (String ) me.getKey(); 1036 String clfn1 = (String ) me.getValue(); 1037 String clfn2 = (String ) proj2.get(cofn); 1038 Field f1 = getField(clfn1, je1, leaf, add); 1039 Field f2 = getField(clfn2, je2, leaf, add); 1040 if (e instanceof Equal) { 1041 Equal equal = new Equal( 1042 new BasicFieldOperand(f1), 1043 new BasicFieldOperand(f2)); 1044 if (debug) { 1045 log.log(BasicLevel.DEBUG, "equality: " 1046 + ExpressionPrinter.e2str(equal)); 1047 } 1048 if (res == null) { 1049 res = equal; 1050 } else { 1051 res = new And(res, equal); 1052 } 1053 } else if (e instanceof NotEqual) { 1054 NotEqual notequal = new NotEqual( 1055 new BasicFieldOperand(f1), 1056 new BasicFieldOperand(f2)); 1057 if (debug) { 1058 log.log(BasicLevel.DEBUG, "not-equality: " 1059 + ExpressionPrinter.e2str(notequal)); 1060 } 1061 if (res == null) { 1062 res = notequal; 1063 } else { 1064 res = new And(res, notequal); 1065 } 1066 } else if (e instanceof MemberOf) { 1067 al1.add(new BasicFieldOperand(f1)); 1068 al2.add(new BasicFieldOperand(f2)); 1069 } 1070 } 1071 if (e instanceof MemberOf) { 1072 MemberOf memberof = new MemberOf(al1, al2); 1073 if (debug) { 1074 log.log(BasicLevel.DEBUG, "memberof: " 1075 + ExpressionPrinter.e2str(memberof)); 1076 } 1077 if (res == null) { 1078 res = memberof; 1079 } else { 1080 res = new And(res, memberof); 1081 } 1082 if (e instanceof MemberOf) { 1083 mofs.add(memberof); 1084 mofExtents.add(je2); 1085 } 1086 } 1087 if (debug) { 1088 log.log(BasicLevel.DEBUG, "by the fields comparison: " 1089 + ExpressionPrinter.e2str(res)); 1090 } 1091 return res; 1092 } else { 1093 throw new MalformedExpressionException("Bad PName " + 1094 "equality: PName structures unknwon or not same"); 1095 } 1096 } 1097 else if (e instanceof MemberOf) { 1099 if (debug) { 1100 log.log(BasicLevel.DEBUG, "MemberOf on normal fields"); 1101 } 1102 JormExtent je1 = (JormExtent) qtf1.getQueryTree(); 1103 JormExtent je2 = (JormExtent) qtf2.getQueryTree(); 1104 if (debug) { 1105 log.log(BasicLevel.DEBUG, "Replace the MemberOf: " 1106 + ExpressionPrinter.e2str(e)); 1107 } 1108 ArrayList al1 = new ArrayList (1); 1109 ArrayList al2 = new ArrayList (1); 1110 Field f1 = getField( 1111 qtf1.getName().substring(je1.getName().length() + 1), 1112 je1, leaf, add); 1113 Field f2 = getField( 1114 qtf2.getName().substring(je2.getName().length() + 1), 1115 je2, leaf, add); 1116 al1.add(new BasicFieldOperand(f1)); 1117 al2.add(new BasicFieldOperand(f2)); 1118 MemberOf memberof = new MemberOf(al1, al2); 1119 1120 if (debug) { 1121 log.log(BasicLevel.DEBUG, "by the field comparison: " 1122 + ExpressionPrinter.e2str(memberof)); 1123 } 1124 mofs.add(memberof); 1125 extents.add(je2); 1126 return memberof; 1127 } 1128 } else if (left instanceof FieldOperand && right instanceof Operand) { 1129 FieldOperand fo = (FieldOperand) left; 1130 QueryTreeField qtf = (QueryTreeField) fo.getField(); 1131 if (qtf instanceof PNameField) { 1132 return replacePNameOperandEquality(eq, leaf, add); 1133 } 1134 } else if (left instanceof Operand && right instanceof FieldOperand) { 1135 FieldOperand fo = (FieldOperand) right; 1136 QueryTreeField qtf = (QueryTreeField) fo.getField(); 1137 if (qtf instanceof PNameField) { 1138 return replacePNameOperandEquality(eq, leaf, add); 1139 } 1140 } 1141 } 1143 1144 if (e instanceof IsEmpty) { 1146 IsEmpty ie = (IsEmpty) e; 1147 FieldOperand fo = (FieldOperand) ie.getExpression(0); 1148 QueryTreeField qtf = (QueryTreeField) fo.getField(); 1149 JormExtent je = (JormExtent) qtf.getQueryTree(); 1150 String fname; 1151 if (qtf instanceof PNameField) { 1152 PNameField pnf = (PNameField) qtf; 1153 fname = pnf.getNameDef(je).getFieldName(); 1154 } else { 1155 fname = qtf.getName().substring(je.getName().length() + 1); 1156 } 1157 fo.setField(getField(fname, je, leaf, add)); 1158 empties.add(ie); 1159 } else if (e instanceof Operator) { 1160 Operator op = (Operator) e; 1161 if (debug) { 1162 log.log(BasicLevel.DEBUG, "update the operator: " + op.getOperatorString()); 1163 } 1164 int size = op.getOperandNumber(); 1165 for (int i = 0; i < size; i++) { 1166 op.setExpression(i, 1167 updateFieldOfExpression(op.getExpression(i), leaf, add)); 1168 } 1169 } else if (e instanceof FieldOperand) { 1170 Field f = ((FieldOperand) e).getField(); 1171 if (f instanceof PNameField) { 1172 Expression res = getDecode((PNameField) f, leaf, add); 1173 if (debug) { 1174 log.log(BasicLevel.DEBUG, "Replace the FieldOperand " 1175 + f.getName() + " by a decode: " 1176 + ExpressionPrinter.e2str(res)); 1177 } 1178 return res; 1179 } else { 1180 if (debug) { 1181 log.log(BasicLevel.DEBUG, 1182 "Update the FieldOperand " + f.getName()); 1183 } 1184 ((FieldOperand) e).setField(getField(f, leaf, add)); 1185 return e; 1186 } 1187 } 1188 return e; 1189 } 1190 1191 1201 public Expression getDecode(PNameField pnf, 1202 BasicRdbExpQueryLeaf leaf, 1203 boolean add) 1204 throws MedorException { 1205 if (debug) { 1206 log.log(BasicLevel.DEBUG, "(getDecode) Handling PNameField " + pnf.getName()); 1207 } 1208 JormExtent extent = (JormExtent) pnf.getQueryTree(); 1209 if (debug) { 1210 log.log(BasicLevel.DEBUG, "in extent " + extent.getJormName()); 1211 } 1212 Operand o = getPNCOperand(extent, pnf); 1213 PType type = pnf.getType(); 1214 log.log(BasicLevel.DEBUG, "Looking for NameDef of " + pnf); 1215 NameDef nd = pnf.getNameDef(extent); 1216 if (nd.isFieldName()) { 1217 return new SinglePName(new BasicFieldOperand( 1218 getField(nd.getFieldName(), extent, leaf, add)), o, type); 1219 } else if (nd.isNameRef()) { 1220 Map proj = nd.getNameRef().getProjection(); 1221 FieldOperand[] fos = new BasicFieldOperand[proj.size()]; 1222 String [] cofns = new String [proj.size()]; 1223 int counter = 0; 1224 QueryTreeField qtf = null; 1225 for (Iterator it = proj.entrySet().iterator(); it.hasNext();) { 1226 Map.Entry me = (Map.Entry ) it.next(); 1227 cofns[counter] = (String ) me.getKey(); 1228 String clafn = (String ) me.getValue(); 1229 qtf = getField(clafn, extent, leaf, add); 1230 fos[counter] = new BasicFieldOperand(qtf); 1231 counter++; 1232 } 1233 return new CompositePName(fos, cofns, o, type); 1237 } 1238 throw new MedorException("Unsupport namedef: " + nd); 1239 } 1240 1241 1250 private Expression replacePNameOperandEquality(Operator e, 1251 BasicRdbExpQueryLeaf leaf, 1252 boolean add) 1253 throws ExpressionException, MedorException { 1254 if (debug) { 1255 log.log(BasicLevel.DEBUG, "Equality between PName and a parameter"); 1256 } 1257 Expression left = e.getExpression(0); 1258 Expression right = e.getExpression(1); 1259 FieldOperand fo = null; 1260 PNameField pnf = null; 1261 Operand o = null; 1262 boolean isLeft = true; 1263 if (left instanceof FieldOperand && right instanceof Operand) { 1264 fo = (FieldOperand) left; 1265 pnf = (PNameField) fo.getField(); 1266 o = (Operand) right; 1267 isLeft = false; 1268 } else if (left instanceof Operand && right instanceof FieldOperand) { 1269 fo = (FieldOperand) right; 1270 pnf = (PNameField) fo.getField(); 1271 o = (Operand) left; 1272 } 1273 JormExtent je = (JormExtent) pnf.getQueryTree(); 1274 if (e instanceof MemberOf) { 1275 mofs.add(e); 1276 extents.add(je); 1277 } 1278 NameDef nd = pnf.getNameDef(je); 1279 VariableOperand newo; 1280 if (nd.isFieldName()) { 1281 Field f = getField(nd.getFieldName(), je, leaf, add); 1282 fo.setField(f); 1283 if (o instanceof ParameterOperand) { 1284 newo = new EncodePName(f.getType(), ((ParameterOperand) o).getName()); 1285 e.setExpression((isLeft ? 0 : 1), newo); 1286 } else { 1287 newo = new BasicVariableOperand(f.getType()); 1288 try { 1289 EncodePName.assignEncodedValue((PName) o.getObject(), newo, null); 1290 } 1291 catch (PException ex) { 1292 throw new MedorException("Impossible to encode PName", ex); 1293 } 1294 if (newo.getObject() == null) { 1295 return new IsNull(fo); 1297 } 1298 e.setExpression((isLeft ? 0 : 1), newo); 1299 } 1300 if (debug) { 1301 log.log(BasicLevel.DEBUG, 1302 "Equality between PName and a parameter: " 1303 + ExpressionPrinter.e2str(e)); 1304 } 1305 return e; 1306 } else if (nd.isNameRef()) { 1307 Expression res = null; 1308 Map proj1 = nd.getNameRef().getProjection(); 1309 Iterator it = proj1.entrySet().iterator(); 1310 while (it.hasNext()) { 1311 Map.Entry me = (Map.Entry ) it.next(); 1312 String cofn = (String ) me.getKey(); 1313 String clfn = (String ) me.getValue(); 1314 Field f = getField(clfn, je, leaf, add); 1315 if (o instanceof ParameterOperand) { 1316 newo = new EncodePName(f.getType(), ((ParameterOperand) o).getName(), cofn); 1317 } else { 1318 newo = new BasicVariableOperand(f.getType()); 1319 try { 1320 EncodePName.assignEncodedValue((PName) o.getObject(), newo, cofn); 1321 } 1322 catch (PException ex) { 1323 throw new MedorException("Impossible to encode PName", ex); 1324 } 1325 } 1326 if (e instanceof Equal) { 1327 Expression test; 1328 if (!(o instanceof ParameterOperand) && newo.getObject() == null) { 1329 test = new IsNull(new BasicFieldOperand(f)); 1331 } else { 1332 test = (isLeft 1333 ? new Equal(newo, new BasicFieldOperand(f)) 1334 : new Equal(new BasicFieldOperand(f), newo)); 1335 } 1336 if (res == null) { 1337 res = test; 1338 } else { 1339 res = new And(res, test); 1340 } 1341 } 1342 if (e instanceof MemberOf) { 1343 ArrayList al1 = new ArrayList (1); 1344 al1.add(newo); 1345 ArrayList al2 = new ArrayList (1); 1346 al2.add(new BasicFieldOperand(f)); 1347 MemberOf memberof = 1348 new MemberOf(al1, al2); 1349 if (res == null) { 1350 res = memberof; 1351 } else { 1352 res = new And(res, memberof); 1353 } 1354 } else if (e instanceof NotEqual) { 1355 NotEqual notequal = 1356 (isLeft 1357 ? new NotEqual(newo, new BasicFieldOperand(f)) 1358 : new NotEqual(new BasicFieldOperand(f), newo)); 1359 if (res == null) { 1360 res = notequal; 1361 } else { 1362 res = new Or(res, notequal); 1363 } 1364 } 1365 } 1366 if (debug) { 1367 log.log(BasicLevel.DEBUG, 1368 "Equality between PName and a parameter: " 1369 + ExpressionPrinter.e2str(res)); 1370 } 1371 return res; 1372 } else { 1373 throw new MalformedExpressionException("Bad PName " + 1374 "equality: PName structures unknwon or not same"); 1375 } 1376 } 1377 1378 1387 public QueryTreeField getField(Field old, 1388 BasicRdbExpQueryLeaf leaf, 1389 boolean add) 1390 throws MedorException { 1391 Field f = old; 1392 if (f instanceof PropagatedField) { 1393 f = ((PropagatedField) f).getPreviousFields()[0]; 1394 } 1395 QueryTree qt = ((QueryTreeField) f).getQueryTree(); 1396 if (qt == leaf) { 1397 return (QueryTreeField) f; 1398 } else if (qt instanceof JormExtent) { 1399 return getField( 1400 f.getName(), f.getType(), (JormExtent) qt, leaf, add); 1401 } else { 1402 throw new MedorException("Impossible to fetch the new field " + 1403 "corresponding to the old field: " + f.getName() 1404 + " : the query tree is not a JormExtent: " + qt); 1405 } 1406 } 1407 1408 1417 public QueryTreeField getField(String fieldname, 1418 JormExtent extent, 1419 BasicRdbExpQueryLeaf leaf, 1420 boolean add) 1421 throws MedorException { 1422 if (debug) { 1423 log.log(BasicLevel.DEBUG, "(getField-4) Handling field " + fieldname); 1424 } 1425 return getField(fieldname, 1426 getPrimitiveElement(extent, fieldname).getType(), 1427 extent, 1428 leaf, 1429 add); 1430 } 1431 1432 1445 public QueryTreeField getField(String fieldname, 1446 PType type, 1447 JormExtent extent, 1448 BasicRdbExpQueryLeaf leaf, 1449 boolean add) 1450 throws MedorException { 1451 String fqfn = qualifiedName(fieldname, extent); 1452 if (debug) { 1453 log.log(BasicLevel.DEBUG, "(getField-5) Handling field " + fieldname + " (full name: " + fqfn + ")"); 1454 Field[] leafFields = leaf.getTupleStructure().getFields(); 1455 if (leafFields.length == 0) { 1456 log.log(BasicLevel.DEBUG, "Leaf has no fields"); 1457 } 1458 for (int jj=0; jj<leafFields.length; jj++) { 1459 log.log(BasicLevel.DEBUG, "Leaf has field " + leafFields[jj].getName()); 1460 } 1461 } 1462 if (leaf.contains(fqfn)) { 1463 if (debug) { 1465 log.log(BasicLevel.DEBUG, 1466 "getField:" 1467 + " / field: " + fqfn 1468 + " / type: " + type.getJormName() 1469 + " already exists"); 1470 } 1471 return (QueryTreeField) leaf.getField(fqfn); 1472 } 1473 RdbPrimitiveElementMapping pem = 1474 (RdbPrimitiveElementMapping) getPEM(extent, fieldname); 1475 RdbJormExtentMapping rjem = getMapping(extent); 1476 int idx = getTableIndex(rjem, pem, unQualifiedName(fieldname, extent)); 1477 if (debug) { 1478 log.log(BasicLevel.DEBUG, 1479 "getField:" 1480 + " / field: " + fqfn 1481 + " / type: " + type.getJormName() 1482 + " / pem: " + pem.getName() 1483 + " / rjem: " + rjem.extent.getJormName() 1484 + " / table: " 1485 + ((QualifiedTable) rjem.tables.get(idx)).getAliasName()); 1486 } 1487 getTable(rjem, idx, leaf, false); 1488 String colName = pem.getName(); 1489 if (((QualifiedTable) rjem.tables.get(idx)).isPolymorphic()) { 1491 colName = getJORMFieldName(fieldname, extent); 1493 } 1494 RdbExpField res = leaf.addRdbField( 1495 fqfn, 1496 type, colName, 1497 (QualifiedTable) rjem.tables.get(idx)); 1498 if (!add) { 1499 leaf.removeRdbField(res); 1500 } 1501 return res; 1502 } 1503 1504 1515 private void getTable(RdbJormExtentMapping rjem, 1516 int idx, 1517 BasicRdbExpQueryLeaf leaf, 1518 boolean add) throws MedorException { 1519 QualifiedTable qt = (QualifiedTable) rjem.tables.get(idx); 1521 if (debug) { 1522 log.log(BasicLevel.DEBUG, "Looking for the table " + qt.getAliasName()); 1523 } 1524 if (leaf.containsQualifiedTable(qt)) 1525 return; 1526 if (idx != 0) { 1527 getTable(rjem, 0, leaf, add); 1529 if (debug) { 1530 log.log(BasicLevel.DEBUG, "Add the external table " + qt.getAliasName()); 1531 } 1532 leaf.addQualifiedTable(qt); 1533 addJoin(rjem, idx, leaf, add); 1534 } else { 1535 if (debug) { 1537 log.log(BasicLevel.DEBUG, "Add the main table " + qt.getAliasName()); 1538 } 1539 leaf.addQualifiedTable(qt); 1540 boolean unused = true; 1542 for (int i = 0; i < mappings.size(); i++) { 1543 RdbJormExtentMapping m = (RdbJormExtentMapping) mappings.get(i); 1544 int jdx = 1; 1546 int size = m.tables.size(); 1547 while (jdx < size && m.tables.get(jdx) != qt) { 1548 jdx++; 1549 } 1550 if (jdx < size) { 1551 unused = false; 1552 getTable(m, 0, leaf, add); 1555 addJoin(m, jdx, leaf, add); 1557 } 1558 } 1559 if (unused && !joinedTables.contains(qt)) { 1560 joinedTables.add(qt); 1561 } 1562 } 1563 } 1564 1565 1575 private void addJoin(RdbJormExtentMapping rjem, 1576 int idx, 1577 BasicRdbExpQueryLeaf leaf, 1578 boolean add) throws MedorException { 1579 BasicQualifiedTable qt = (BasicQualifiedTable) rjem.tables.get(idx); 1580 JoinedTable.Join jtj = ((JoinedTable) 1581 rjem.tables.get(0)).createChildren(qt, rjem.outer); 1582 Join j = (Join) rjem.joins.get(idx); 1583 RdbExpField f2; 1584 for (int i = 0; i < j.columns.length; i++) { 1585 JoinColumn jc = j.columns[i]; 1586 if (jc.field2 == null) { 1587 f2 = leaf.addRdbField(jc.column2, jc.type, jc.column2, qt); 1589 } else { 1590 f2 = (RdbExpField) getField(jc.field2, rjem.extent, leaf, add); 1591 } 1592 RdbField f1 = (RdbField) getField(jc.field1, rjem.extent, leaf, add); 1593 jtj.addJoinColumn(f1.getColumnName(), f2.getColumnName()); 1594 if (!add) { 1595 leaf.removeRdbField(f2); 1596 } 1597 } 1598 } 1599 1600 private String qualifiedName(String fieldname, JormExtent extent) { 1601 if (fieldname.indexOf(extent.getName() + ".") == -1) { 1602 return extent.getName() + "." + fieldname; 1603 } else 1604 return fieldname; 1605 } 1606 1607 private String unQualifiedName(String fieldname, JormExtent extent) { 1608 int idx = fieldname.indexOf(extent.getName() + "."); 1609 if (idx == -1) { 1610 if (debug) { 1611 log.log(BasicLevel.DEBUG, "Field name " + fieldname + " is already unqualified."); 1612 } 1613 return fieldname; 1614 } else if (idx == 0) { 1615 if (debug) { 1616 log.log(BasicLevel.DEBUG, "Unqualified name of field named " + fieldname + " is " + extent.getName().length() + 1); 1617 } 1618 return fieldname.substring(extent.getName().length() + 1); 1619 } else { 1620 if (debug) { 1621 log.log(BasicLevel.WARN, "Problem to unqualify field named " + fieldname); 1622 } 1623 return null; 1624 } 1625 } 1626 1627 1634 private void splitLeaf(RdbExpQueryLeaf leaf, Expression filter) throws MedorException { 1635 if (debug) { 1637 log.log(BasicLevel.DEBUG, "Creating subleaves for filter " + ExpressionPrinter.e2str(filter)); 1638 } 1639 for (int i = 0; i < mofs.size(); i++) { 1640 MemberOf mo = (MemberOf) mofs.get(i); 1641 int moSize = mo.getOperandNumber() / 2; 1642 if (debug) { 1644 for (int f = 0; f < moSize; f++) { 1645 log.log(BasicLevel.DEBUG, "- left is " 1646 + ExpressionPrinter.e2str(mo.getExpression(f))); 1647 } 1648 } 1649 for (int f = 0; f < moSize; f++) { 1650 RdbExpField fRight = (RdbExpField) 1651 ((FieldOperand) mo.getExpression(f + moSize)).getField(); 1652 if (debug) { 1653 log.log(BasicLevel.DEBUG, "- right field is " + fRight.getName()); 1654 } 1655 splitLeaf(leaf, fRight); 1656 } 1657 } 1658 for (int i = 0; i < empties.size(); i++) { 1659 IsEmpty ie = (IsEmpty) empties.get(i); 1660 FieldOperand fo = (FieldOperand) ie.getExpression(); 1661 RdbExpField field = (RdbExpField) fo.getField(); 1662 splitLeaf(leaf, field); 1663 } 1664 } 1665 1666 private void splitLeaf(RdbExpQueryLeaf leaf, RdbExpField field) throws MedorException { 1667 if (leaf.containsQualifiedTable(field.getTable())) { 1670 if (debug) { 1671 log.log(BasicLevel.DEBUG, "- split table is " + field.getTable().getTableName() + 1672 " (alias " + field.getTable().getAliasName() + ")"); 1673 QualifiedTable[] qtstmp = leaf.getQualifiedTables(); 1674 log.log(BasicLevel.DEBUG, "- before remove: " + qtstmp.length); 1675 log.log(BasicLevel.DEBUG, "-- leaf " + leaf); 1676 log.log(BasicLevel.DEBUG, "-- qt " + field.getQueryTree()); 1677 for (int ii = 0; ii < qtstmp.length; ii++) { 1678 log.log(BasicLevel.DEBUG, "--- table " + qtstmp[ii].getTableName()); 1679 } 1680 } 1681 RdbExpQueryLeaf newLeaf = new BasicRdbExpQueryLeaf(leaf.getDataStore(), ""); 1682 subLeaves.add(newLeaf); 1683 leaf.removeQualifiedTable(field.getTable()); 1685 newLeaf.addQualifiedTable(field.getTable()); 1687 newLeaf.addRdbField(field); 1688 field.setQueryLeaf(newLeaf); 1689 if (debug) { 1691 QualifiedTable[] qtstmp = leaf.getQualifiedTables(); 1692 log.log(BasicLevel.DEBUG, "- after remove: " + qtstmp.length); 1693 for (int ii = 0; ii < qtstmp.length; ii++) { 1694 log.log(BasicLevel.DEBUG, "-- table " + qtstmp[ii].getTableName()); 1695 } 1696 } 1697 } else { 1698 if (debug) { 1699 log.log(BasicLevel.DEBUG, "- split table already moved"); 1700 } 1701 RdbExpQueryLeaf rightLeaf = subleafOfFieldOperand(field); 1703 if (rightLeaf == null) throw new NullPointerException ("Should have found the leaf corresponding to field " + field); 1705 rightLeaf.addRdbField(field); 1706 field.setQueryLeaf(rightLeaf); 1707 } 1708 if (joinedTables.contains(field.getTable())) { 1709 if (debug) { 1710 log.log(BasicLevel.DEBUG, "************Removing the joined table " + 1711 field.getTable().getTableName() + "."); 1712 } 1713 joinedTables.remove(field.getTable()); 1714 } 1715 } 1716 1717 1725 private Expression updateFilterWithNewLeaves(Expression filter, 1726 RdbExpQueryLeaf leaf) { 1727 if (debug) { 1728 log.log(BasicLevel.DEBUG, "Moving part of the filter " + ExpressionPrinter.e2str(filter)); 1729 } 1730 ToBeMovedToLeaf tbm = tagFilterForMove(filter, leaf); 1731 if (debug) { 1732 log.log(BasicLevel.DEBUG, "Final filter for leaf: " + ExpressionPrinter.e2str(tbm.e)); 1733 } 1734 if (tbm.isModified) { 1735 tbm.leaf.setQueryFilter(tbm.e); 1737 return null; 1738 } else { 1739 return tbm.e; 1740 } 1741 } 1742 1743 1754 private ToBeMovedToLeaf tagFilterForMove(Expression filter, 1755 RdbExpQueryLeaf leaf) { 1756 if (filter instanceof Not) { 1757 ToBeMovedToLeaf me = 1758 tagFilterForMove(((Not) filter).getExpression(), leaf); 1759 if (me.isModified) { 1760 Expression newFilter = null; 1762 if (leaf.getQueryFilter() == null) { 1763 newFilter = new Not(me.e); 1764 } else { 1765 newFilter = new And(leaf.getQueryFilter(), new Not(me.e)); 1766 } 1767 me.leaf.setQueryFilter(newFilter); 1768 me.isModified = false; 1769 me.e = null; 1770 return me; 1771 } 1772 } else if (filter instanceof And) { 1773 if (debug) { 1774 log.log(BasicLevel.DEBUG, "Found AND " + 1775 ExpressionPrinter.e2str(filter)); 1776 log.log(BasicLevel.DEBUG, "Left side of AND: " 1777 + ExpressionPrinter.e2str(((And) filter).getExpression(0))); 1778 } 1779 ToBeMovedToLeaf mleft = tagFilterForMove(((And) filter).getExpression(0), leaf); 1780 boolean leftMoved = false; 1781 boolean rightMoved = false; 1782 if (mleft.isModified) { 1783 if (debug) { 1785 log.log(BasicLevel.DEBUG, "Moving left side to leaf " 1786 + ExpressionPrinter.e2str(mleft.e)); 1787 } 1788 leftMoved = true; 1789 mleft.leaf.setQueryFilter( 1790 ((mleft.leaf.getQueryFilter() == null) 1791 ? mleft.e 1792 : new And( 1793 mleft.leaf.getQueryFilter(), 1794 mleft.e) 1795 ) 1796 ); 1797 if (debug) { 1798 log.log(BasicLevel.DEBUG, "Filter for leaf " 1799 + mleft.leaf + " after moving left side is " 1800 + ExpressionPrinter.e2str(mleft.leaf.getQueryFilter())); 1801 } 1802 } 1803 if (debug) { 1804 log.log(BasicLevel.DEBUG, "Right side of AND: " 1805 + ExpressionPrinter.e2str(((And) filter).getExpression(1))); 1806 } 1807 ToBeMovedToLeaf mright = tagFilterForMove(((And) filter).getExpression(1), leaf); 1808 if (mright.isModified) { 1809 if (debug) { 1810 log.log(BasicLevel.DEBUG, "Moving right side to leaf " 1811 + ExpressionPrinter.e2str(mright.e)); 1812 } 1813 rightMoved = true; 1814 mright.leaf.setQueryFilter( 1815 (mright.leaf.getQueryFilter() == null 1816 ? mright.e 1817 : new And( 1818 mright.leaf.getQueryFilter(), 1819 mright.e) 1820 ) 1821 ); 1822 if (debug) { 1823 log.log(BasicLevel.DEBUG, "Filter for leaf " 1824 + mright.leaf + " after moving right side is " 1825 + ExpressionPrinter.e2str(mright.leaf.getQueryFilter())); 1826 } 1827 } 1828 if (leftMoved) { 1829 if (rightMoved) { 1830 mleft.clear(); 1832 if (debug) { 1833 log.log(BasicLevel.DEBUG, "All moved: returning empty " 1834 + ExpressionPrinter.e2str(mleft.e)); 1835 } 1836 return mleft; 1837 } else { 1838 if (debug) { 1840 log.log(BasicLevel.DEBUG, "Left moved: returning right " 1841 + ExpressionPrinter.e2str(mright.e)); 1842 } 1843 return mright; 1844 } 1845 } else { 1846 if (rightMoved) { 1847 if (debug) { 1849 log.log(BasicLevel.DEBUG, "Right moved: returning left " 1850 + ExpressionPrinter.e2str(mleft.e)); 1851 } 1852 return mleft; 1853 } else { 1854 Expression modifAnd = 1856 new And(mleft.e, mright.e); 1857 if (debug) { 1858 log.log(BasicLevel.DEBUG, "None moved: returning modified expression " 1859 + ExpressionPrinter.e2str(modifAnd)); 1860 } 1861 return new ToBeMovedToLeaf(modifAnd, false, null); 1862 } 1863 } 1864 } 1865 else if (filter instanceof Comparator) { 1867 Expression left = ((Comparator) filter).getExpression(0); 1869 Expression right = ((Comparator) filter).getExpression(1); 1870 if (left instanceof FieldOperand) { 1871 RdbExpQueryLeaf subleaf = 1873 subleafOfFieldOperand((FieldOperand) left); 1874 if (subleaf != null) { 1875 return new ToBeMovedToLeaf(filter, true, subleaf); 1877 } 1878 } 1879 if (right instanceof FieldOperand) { 1880 RdbExpQueryLeaf subleaf = 1882 subleafOfFieldOperand((FieldOperand) right); 1883 if (subleaf != null) { 1884 return new ToBeMovedToLeaf(filter, true, subleaf); 1886 } 1887 } 1888 } 1890 return new ToBeMovedToLeaf(filter, false, null); 1892 } 1893 1894 1900 private RdbExpQueryLeaf subleafOfFieldOperand(FieldOperand fo) { 1901 return subleafOfFieldOperand(fo.getField()); 1902 } 1903 1904 private RdbExpQueryLeaf subleafOfFieldOperand(Field f) { 1905 QualifiedTable qtab = ((RdbExpField) f).getTable(); 1906 for (int i = 0; i < subLeaves.size(); i++) { 1907 RdbExpQueryLeaf subleaf = 1908 (RdbExpQueryLeaf) subLeaves.get(i); 1909 QualifiedTable[] tables = subleaf.getQualifiedTables(); 1910 if (tables == null) { return null; } 1911 for (int j = 0; j < tables.length; j++) { 1912 if (qtab == tables[j]) { 1913 if (debug) { 1914 log.log(BasicLevel.DEBUG, "Found table " + qtab.getTableName() + " in leaf " + subleaf); 1915 } 1916 return subleaf; 1917 } 1918 } 1919 } 1920 return null; 1921 } 1922 1923 1932 private Count fieldUsedInCount(QueryTreeField f, QueryNode parent) { 1933 log.log(BasicLevel.DEBUG, "Entering fieldUsedInCount for " + f + "( " + f.getName() + ")"); 1934 if (parent instanceof Nest) { 1935 log.log(BasicLevel.DEBUG, "Parent node is a Nest"); 1936 Field[] pfs = parent.getTupleStructure().getFields(); 1937 for (int i = 0; i < pfs.length; i++) { 1938 Field fi = pfs[i]; 1939 log.log(BasicLevel.DEBUG, "Examining field " + fi + " (" + fi.getName() + ")"); 1940 if (fi instanceof CalculatedField) { 1941 Expression fiExp = ((CalculatedField) fi).getExpression(); 1942 if (fiExp instanceof Count) { 1943 Field countedField = 1944 ((PropagatedField) 1945 ((FieldOperand) 1946 ((Count) fiExp).getExpression()).getField()) 1947 .getPreviousFields()[0]; 1948 log.log(BasicLevel.DEBUG, "Counted field " + countedField); 1949 if (countedField.equals(f)) { 1950 log.log(BasicLevel.DEBUG, "Field " + f.getName() + " used in Count"); 1951 return (Count) fiExp; 1952 } 1953 } 1954 } 1955 } 1956 } 1957 return null; 1958 } 1959 1960 1965 private class ToBeMovedToLeaf extends ModifiedExpression { 1966 1969 RdbExpQueryLeaf leaf; 1970 1971 ToBeMovedToLeaf(Expression exp, boolean ism, RdbExpQueryLeaf leaf) { 1972 super(exp, ism); 1973 this.leaf = leaf; 1974 } 1975 1976 public void clear() { 1977 e = null; 1978 leaf = null; 1979 isModified = false; 1980 } 1981 } 1982} 1983 | Popular Tags |