1 22 23 package org.xquark.extractor.mysql; 24 25 import java.util.*; 26 27 import org.xquark.extractor.algebra.*; 28 import org.xquark.extractor.algebra.Constants; 29 import org.xquark.extractor.common.*; 30 import org.xquark.extractor.runtime.IDProvider; 31 32 48 public class MysqlRemoveSubQueries extends DefaultCompleteVisitor { 49 50 private static final String RCSRevision = "$Revision: 1.26 $"; 51 private static final String RCSName = "$Name: $"; 52 53 protected Expression _rewrittenQuery; 54 protected Mapper _topMapper; protected FindQuerySignatureVisitor _keyNodesFinder = new FindQuerySignatureVisitor(); 56 protected SplitPredicateVisitor _splitVisitor = null; protected RemoveAggregateFunctionVisitor _removeAggrVisitor = null; protected RenameAttributeExpressionVisitor _renameVisitor = null; 59 protected ForeignAttributeGrabber _foreignAttributeGrabber = null; 60 protected AttributeGrabber _attributeGrabber = null; 61 protected RestrictionVisitor _restrictionVisitor = new RestrictionVisitor(); 62 protected AddKeys _addKeysVisitor = new AddKeys(); 63 protected Stack _subQueryStack = new Stack(); 64 protected IDProvider _attIDProvider = null; 65 protected IDProvider _relIDProvider = null; 66 67 public MysqlRemoveSubQueries(IDProvider attIDProvider, IDProvider relIDProvider) { 68 _attIDProvider = attIDProvider; 69 _relIDProvider = relIDProvider; 70 } 71 72 public void reinit(Expression query) { 73 _rewrittenQuery = query; 74 _topMapper = query.getMapper(); 75 } 76 77 public Expression getRewrittenQuery() { 78 return _rewrittenQuery; 79 } 80 81 public void setRewrittenQuery(SubQueryNode query) { 82 switch (query._type) { 83 case SubQueryNode.TYPE_MAIN : 84 ((Expression) query._query).setMapper(_topMapper); 85 if (query._referringNode == null) 86 _rewrittenQuery = (Expression) query._query; 87 else 88 _rewrittenQuery = query._referringNode; 89 break; 90 case SubQueryNode.TYPE_FROM : 91 if (query._renamedQuery == null) 94 ((UnaryOperator) query._referringNode).setOperand((Expression) query._query); 95 break; 96 default : 97 } 98 } 100 101 public void visit(UnOpProject arg) { 102 browseProjection(arg, SubQueryNode.CONTEXT_PROJECT); 104 } 106 107 public void visit(UnOpAggregate arg) { 108 browseProjection(arg, SubQueryNode.CONTEXT_AGGR); 110 } 112 113 private void browseProjection(UnOpProject arg, byte context) { 114 SubQueryNode query = null; 115 116 SubQueryNode parentQuery = null; 117 if (_subQueryStack.isEmpty()) 118 query = new SubQueryNode(arg); 119 else { 120 parentQuery = (SubQueryNode) _subQueryStack.peek(); 121 122 if (parentQuery.getType() == SubQueryNode.TYPE_PREDICATE_EXIST) 123 query = (SubQueryNode) _subQueryStack.peek(); 124 else 125 query = new SubQueryNode(arg, context); 126 } 127 128 if (query != null) 129 query.setBrowsingStep(SubQueryNode.STEP_OPERAND); 130 131 arg.getOperand().accept(this); 132 133 if (query != null) 134 query.setBrowsingStep(SubQueryNode.STEP_ITEMS); 135 136 List list = arg.getParameterList(); 137 if (null != list) { 138 for (int i = 0; i < list.size(); i++) { 139 query.setCurrent((Expression) list.get(i)); 140 query.getCurrent().accept(this); 141 } 142 } 143 144 if (query != parentQuery) 145 setRewrittenQuery(query.rewrite()); 146 } 147 148 public void visit(UnOpRestrict arg) { 149 SubQueryNode query = (SubQueryNode) _subQueryStack.peek(); 151 152 query.setBrowsingStep(SubQueryNode.STEP_PREDICATES); 153 List list = arg.getPredicateList(); 154 if (null != list) { 155 for (int i = 0; i < list.size(); i++) { 156 query.setCurrent((Expression) list.get(i)); 157 query.getCurrent().accept(this); 158 } 159 } 160 161 query.setBrowsingStep(SubQueryNode.STEP_OPERAND); 162 arg.getOperand().accept(this); 163 164 } 166 167 public void visit(Join arg) { 168 SubQueryNode query = (SubQueryNode) _subQueryStack.peek(); 170 171 query.setBrowsingStep(SubQueryNode.STEP_PREDICATES); 172 List list = arg.getPredicateList(); 173 if (null != list) { 174 for (int i = 0; i < list.size(); i++) { 175 query.setCurrent((Expression) list.get(i)); 176 query.getCurrent().accept(this); 177 } 178 } 179 180 query.setBrowsingStep(SubQueryNode.STEP_OPERAND); 181 list = arg.getOperandList(); 182 if (null != list) { 183 for (int i = 0; i < list.size(); i++) { 184 query.setCurrent((Expression) list.get(i)); 185 query.getCurrent().accept(this); 186 } 187 } 188 189 } 191 192 public void visit(BinOpCompareAny arg) { 193 if (!(arg.getRightOperand() instanceof LitList)) { 194 SubQueryNode query = new SubQueryNode((Relation) arg.getRightOperand(), SubQueryNode.CONTEXT_ANY); 195 super.visit((BinaryAtomicOp) arg); 196 query.rewrite(); 197 } 198 } 200 201 public void visit(UnOpExists arg) { 202 SubQueryNode query = new SubQueryNode((Relation) arg.getOperand(), SubQueryNode.CONTEXT_EXIST); 203 super.visit((UnaryAtomicOp) arg); 204 query.rewrite(); 205 } 206 207 221 236 237 protected SubQueryNode transformSubquery(SubQueryNode query) { 238 return query; 240 } 241 252 protected RenameRelation createOuterJoin(Expression mainRelation, List newRelationPredicates, InnerRelationInfo subQuery, boolean distinct, boolean mainIsAggregate) { 253 254 256 257 Expression retRelation = null; 258 if (subQuery._keys == null) { retRelation = subQuery._relation; 260 if (newRelationPredicates == null) 261 newRelationPredicates = subQuery._predicates; 262 else 263 newRelationPredicates.addAll(subQuery._predicates); 264 } else if (subQuery._predicates.isEmpty()) { if (mainRelation instanceof Join) { Join join = (Join) mainRelation; 267 if (subQuery._relation instanceof Join) { 268 Join subJoin = (Join) subQuery._relation; 269 join.addOperandList(subJoin.getOperandList()); 270 join.addPredicateList(subJoin.getPredicateList()); 271 } else { 272 join.addOperand(subQuery._relation); 273 } 274 retRelation = mainRelation; 275 } else { 276 if (subQuery._relation instanceof Join) { 277 Join join = (Join) subQuery._relation; 278 join.addOperand(mainRelation); 279 retRelation = join; 280 } else { 281 List operands = new ArrayList(2); 282 operands.add(mainRelation); 283 operands.add(subQuery._relation); 284 retRelation = new Join(operands, Collections.EMPTY_LIST); 285 } 286 } 287 } else { 288 if (subQuery._relation instanceof Join) { 289 boolean canUseAJoin = false; 293 if (subQuery._havingClauses != null) { 294 Expression predicate = (Expression) subQuery._havingClauses.get(0); 295 if (predicate instanceof BinOpCompare) { 296 BinOpCompare comp = (BinOpCompare) predicate; 297 if (comp.getRightOperand() instanceof LitInteger) { 298 canUseAJoin = ((LitInteger) comp.getRightOperand()).getValue().intValue() == 0 && comp.getOperator() == Constants.GT_COMPOP && comp.getLeftOperand() instanceof FunAggregate && ((FunAggregate) comp.getLeftOperand()).getOperator() == FunAggregate.COUNT; 299 } else if (comp.getLeftOperand() instanceof LitInteger) { 300 canUseAJoin = ((LitInteger) comp.getLeftOperand()).getValue().intValue() == 0 && comp.getOperator() == Constants.LT_COMPOP && comp.getRightOperand() instanceof FunAggregate && ((FunAggregate) comp.getRightOperand()).getOperator() == FunAggregate.COUNT; 301 } 302 } 303 } 304 if (canUseAJoin) { 305 Join join = (Join) subQuery._relation; 306 if (mainRelation instanceof Join) { 307 join.addOperandList(((Join) mainRelation).getOperandList()); 308 join.addPredicateList(((Join) mainRelation).getPredicateList()); } else 310 join.addOperand(mainRelation); 311 join.addPredicateList(subQuery._predicates); 312 retRelation = join; 313 } else 314 throw new SqlWrapperException(MessageLibrary.getMessage("T_N_SUP_QUERY", "MySQL: joins in inner query")); 315 320 } else retRelation = new BinOpOuterJoin(mainRelation, subQuery._relation, Constants.LEFT_OUTER_JOIN, subQuery._predicates); 325 } 326 327 331 332 if (newRelationPredicates != null) 333 retRelation = new UnOpRestrict(retRelation, newRelationPredicates); 334 335 336 if (subQuery._keys != null) 337 retRelation = new UnOpGroup(retRelation, subQuery._keys); 338 339 340 if (subQuery._havingClauses != null && !subQuery._havingClauses.isEmpty()) 341 retRelation = new UnOpRestrict(retRelation, subQuery._havingClauses, true); 342 343 344 if (mainIsAggregate) { 345 List proj2Items = null; 349 350 UnOpProject proj1 = null; 351 if (subQuery.hasAggregate()) 352 proj1 = new UnOpAggregate(retRelation, subQuery._items, distinct, _attIDProvider); 353 else 354 proj1 = new UnOpProject(retRelation, subQuery._items, distinct, _attIDProvider); 355 356 RenameRelation rel1 = new RenameRelation(proj1, _relIDProvider); 357 358 proj2Items = processAggregateItems(proj1, rel1); 359 360 361 retRelation = new UnOpAggregate(rel1, proj2Items, false, _attIDProvider); 363 } else { 364 365 retRelation = new UnOpAggregate(retRelation, subQuery._items, distinct, _attIDProvider); 366 } 367 subQuery._alias.setOperand(retRelation); 368 369 return subQuery._alias; 371 } 372 373 private List processAggregateItems(UnOpProject proj1, RenameRelation rel1) { 374 List aggrItemList = proj1.getItemList(); 375 376 if (_removeAggrVisitor == null) 378 _removeAggrVisitor = new RemoveAggregateFunctionVisitor(); 379 else 380 _removeAggrVisitor.reinit(); 381 382 List aggrItems = new ArrayList(); 383 ListIterator lit = aggrItemList.listIterator(); 384 Expression item = null; 385 while (lit.hasNext()) { 386 item = (Expression) lit.next(); 387 _removeAggrVisitor.newItem(); 388 item.accept(_removeAggrVisitor); 389 if (_removeAggrVisitor.aggregateFound()) { 390 lit.remove(); 391 aggrItems.add(item); 392 } 393 } 394 395 List proj2Items = null; 397 try { 398 proj2Items = AlgebraTools.clone(aggrItemList); 399 } catch (CloneNotSupportedException e) { 400 throw new InternalErrorException(MessageLibrary.getMessage("IE_ERR", "Could not clone item list")); 401 } 402 403 405 Iterator it = _removeAggrVisitor.getCollectedItems().iterator(); 406 FunAggregate funAggr = null; 407 AttributeExpression att = null; 408 409 while (it.hasNext()) { 410 item = (Expression) it.next(); 411 funAggr = (FunAggregate) item.getFather(); item = proj1.addItem(item); att = new AttributeExpression(rel1, item.getName()); 414 att.setUnderlyingExpr(item); 415 funAggr.setOperand(att); } 417 418 proj2Items.addAll(aggrItems); 419 420 return proj2Items; 421 } 422 423 429 protected List pickOutPredicates(Expression tree, boolean blockOnProject) { 430 List retVal = new ArrayList(); 432 433 434 List joinPredicateList = new ArrayList(); 435 _restrictionVisitor.reinit(true, blockOnProject); 436 tree.accept(_restrictionVisitor); 437 List restrictionList = _restrictionVisitor.getRestrictions(); 438 439 440 UnOpRestrict restrict = null; 441 Join join = null; 442 Set vti = null; 443 444 Expression expr; 445 for (int i = 0; i < restrictionList.size(); i++) { 446 expr = (Expression) restrictionList.get(i); 447 448 if (expr instanceof UnOpRestrict) { 449 restrict = (UnOpRestrict) expr; 450 retVal.addAll(restrict.getPredicateList()); 451 452 Expression father = restrict.getFather(); 453 if (father != null) 454 father.replaceChild(restrict, restrict.getOperand()); 455 } else if (expr instanceof Join) { 456 join = (Join) expr; 457 if (join.getPredicateList() != null) { 458 retVal.addAll(join.getPredicateList()); 459 join.getPredicateList().clear(); 460 } 461 } else 462 Debug.nyi("pickOutPredicates(Expression tree)"); 463 } 464 465 return retVal; 467 } 468 469 479 480 protected class SubQueryNode { 481 482 public static final byte CONTEXT_PROJECT = 0; 483 public static final byte CONTEXT_AGGR = 1; 484 public static final byte CONTEXT_ANY = 2; 485 public static final byte CONTEXT_EXIST = 3; 486 487 488 public static final byte TYPE_MAIN = 0; 489 public static final byte TYPE_SELECT_AGGR = 1; 490 public static final byte TYPE_PREDICATE_AGGR = 2; 491 public static final byte TYPE_PREDICATE_EXIST = 3; 492 public static final byte TYPE_PREDICATE_ANY = 4; 493 public static final byte TYPE_FROM = 5; 495 496 public static final byte STEP_NONE = 0; 497 public static final byte STEP_ITEMS = 1; 498 public static final byte STEP_PREDICATES = 2; 499 public static final byte STEP_OPERAND = 3; 500 public static final byte STEP_DONE = 4; 501 502 public byte _type = TYPE_MAIN; 503 504 public byte _browsingStep = STEP_NONE; 505 506 507 private Expression _current; 508 509 512 private Expression _anchor = null; 513 514 517 private UnaryOperator _renamedQuery = null; 518 519 522 private Expression _referringNode = null; 523 524 527 private Relation _query = null; 528 529 532 private List _subQueryList = new ArrayList(); 533 534 public SubQueryNode(Expression mainQuery) { 535 _type = TYPE_MAIN; 536 _query = (UnaryAlgebra) mainQuery; 537 _referringNode = mainQuery.getFather(); 538 539 _subQueryStack.push(this); 541 } 542 543 544 public SubQueryNode(Relation root, byte context) { 545 SubQueryNode parentQuery = (SubQueryNode) _subQueryStack.peek(); 546 547 _anchor = parentQuery.getCurrent(); 548 Expression subQuery = (Expression) root; 549 _referringNode = subQuery.getFather(); 550 551 552 switch (context) { 553 case CONTEXT_PROJECT : 554 555 _type = TYPE_FROM; _query = root; 559 if (_referringNode instanceof RenameRelation) { 560 _renamedQuery = (UnaryOperator) subQuery.getFather(); 561 _referringNode = _renamedQuery.getFather(); 562 } 563 564 break; 565 566 case CONTEXT_AGGR : 567 568 switch (parentQuery.getBrowsingStep()) { 569 case STEP_ITEMS : 570 _type = TYPE_SELECT_AGGR; 571 _renamedQuery = (UnaryOperator) _referringNode; 572 _referringNode = _renamedQuery.getFather(); 573 break; 575 case STEP_PREDICATES : 576 _type = TYPE_PREDICATE_AGGR; break; 578 default : 579 _type = TYPE_FROM; } 581 _query = root; 583 584 break; 585 586 case CONTEXT_ANY : 587 588 _type = TYPE_PREDICATE_ANY; 589 if (root instanceof RenameRelation) { 591 _renamedQuery = (UnaryOperator) subQuery; 592 _query = (UnaryAlgebra) ((RenameRelation) root).getOperand(); 593 } else 594 _query = root; 595 596 break; 597 case CONTEXT_EXIST : 598 599 _type = TYPE_PREDICATE_EXIST; 600 if (root instanceof RenameRelation) { 602 _renamedQuery = (UnaryOperator) subQuery; 603 _query = (UnaryAlgebra) ((RenameRelation) root).getOperand(); 604 } else 605 _query = root; 606 break; 607 608 default : 609 break; 610 } 611 612 if (_referringNode == null) { 614 switch (_type) { 615 case TYPE_PREDICATE_ANY : 616 case TYPE_PREDICATE_EXIST : 617 case TYPE_FROM : 618 _referringNode = new RenameRelation((Expression) _query, _relIDProvider); 619 break; 620 621 default : 622 Debug.nyi("Aggregates should have surrounding RenameItem."); 623 } 624 } 625 626 canonize(); 628 629 if (_type != TYPE_FROM) 631 parentQuery.addSubQuery(this); 632 633 _subQueryStack.push(this); 635 } 636 637 640 private void canonize() { 641 642 646 switch (_type) { 647 case TYPE_PREDICATE_ANY : 648 653 UnOpProject subQueryProjection = (UnOpProject) _query; 655 BinOpCompareAny original = (BinOpCompareAny) _referringNode; 656 Expression scalarExpr1 = original.getLeftOperand(); 658 Expression attExpr2 = (Expression) subQueryProjection.getItemList().get(0); 659 if (attExpr2 instanceof RenameItem) 660 attExpr2 = ((RenameItem)attExpr2).getOperand(); 661 BinOpCompare newPredicate = new BinOpCompare(original.getOperator(), scalarExpr1, attExpr2); 662 663 664 Set refAtts = new HashSet(); 665 if (scalarExpr1 instanceof AttributeExpression) 666 refAtts.add(scalarExpr1); 667 if (_attributeGrabber == null) 668 _attributeGrabber = new AttributeGrabber(); 669 else 670 _attributeGrabber.reinit(); 671 attExpr2.accept(_attributeGrabber); 672 refAtts.add(_attributeGrabber.getAttributeExpression()); 673 newPredicate.setReferredAttributes(refAtts); 674 675 676 _keyNodesFinder.reinit(); 677 subQueryProjection.accept(_keyNodesFinder); 678 PredicateHolder restrict = _keyNodesFinder.getRestriction(); 679 if (restrict == null) { Expression relation = _keyNodesFinder.getRelation(); 681 relation.getFather().replaceChild(relation, new UnOpRestrict(relation, newPredicate)); 682 } else { 683 restrict.addPredicate(newPredicate); 684 } 685 686 687 _type = TYPE_PREDICATE_EXIST; 688 _query = (Relation) subQueryProjection.getOperand(); 689 _referringNode = new UnOpExists((Expression) _query); break; 691 692 case TYPE_PREDICATE_EXIST : 693 694 if (_anchor instanceof UnOpNot) { 696 UnOpExists exists = (UnOpExists) _referringNode; 697 exists.setNot(exists.getNot() ? false : true); 700 } 701 702 703 if (_query instanceof UnOpProject) { 704 UnOpProject project = (UnOpProject) _query; 705 _query = (Relation) project.getOperand(); 706 if (_referringNode != null) 707 _referringNode.replaceChild(project, (Expression) _query); 708 else if (_renamedQuery != null) 709 _renamedQuery.setOperand((Expression) _query); 710 } 711 break; 712 713 default : 714 } 715 } 716 717 public SubQueryNode rewrite() { 718 719 if (_subQueryList.isEmpty()) { 722 _keyNodesFinder.reinit(); 723 ((Expression) _query).accept(_keyNodesFinder); 724 725 if (_keyNodesFinder.getRestriction() instanceof UnOpRestrict) { 726 UnOpRestrict restrict = (UnOpRestrict) _keyNodesFinder.getRestriction(); 727 if (_keyNodesFinder.getRelation() instanceof DummyTable) { 728 729 UnOpProject innerProject = null; 730 try { 731 innerProject = (UnOpProject) _keyNodesFinder.getProjection().clone(); 732 } catch (CloneNotSupportedException ex) { 733 throw new SqlWrapperException(ex.getMessage(), ex); 734 } 735 736 737 RenameRelation rename = new RenameRelation(innerProject, _relIDProvider); 738 739 740 DummyTable dummy = (DummyTable) _keyNodesFinder.getRelation(); 741 dummy.getFather().replaceChild(dummy, rename); 742 innerProject.setOperand(dummy); 743 } 744 } 745 } else { ListIterator it = _subQueryList.listIterator(); 747 SubQueryNode subQuery = null, lastSubQuery = null; 748 InnerRelationInfo relation = null; 749 List subRelations = new ArrayList(); 750 List aggrPairs = null; 751 List aggrItems = null; 753 754 while (it.hasNext()) { 756 subQuery = (SubQueryNode) it.next(); 757 758 switch (subQuery.getType()) { 759 case TYPE_SELECT_AGGR : 760 ((UnOpProject) subQuery._anchor.getFather()).removeItem(subQuery._anchor); 761 if (aggrItems == null) 762 aggrItems = new ArrayList(); 763 aggrItems.add(subQuery._anchor); 764 break; 765 766 case TYPE_PREDICATE_AGGR : 767 if (lastSubQuery != null && subQuery._anchor == lastSubQuery._anchor) { 768 if (aggrPairs == null) 769 aggrPairs = new ArrayList(); 770 it.remove(); 771 it.previous(); 772 it.remove(); 773 aggrPairs.add(new AggregatePair(lastSubQuery, subQuery)); 774 } 775 776 ((PredicateHolder) subQuery._anchor.getFather()).removePredicate(subQuery._anchor); 777 break; 778 779 case TYPE_PREDICATE_ANY : case TYPE_PREDICATE_EXIST : 781 if (subQuery._anchor instanceof BinOpBoolean && ((BinOpBoolean) subQuery._anchor).getOperator() == Constants.OR) 782 throw new SqlWrapperException(MessageLibrary.getMessage("T_N_SUP_QUERY", "MySQL: multiple existential predicates in OR predicate")); 783 784 785 ((PredicateHolder) subQuery._anchor.getFather()).removePredicate(subQuery._anchor); 786 break; 787 788 default : 789 } 790 lastSubQuery = subQuery; 791 } 792 793 794 boolean distinct = false, mainIsAggregate = _query instanceof UnOpAggregate; 795 UnOpProject projection = null; 796 Expression mainRelation = (Expression) _query; 797 if (_query instanceof UnOpProject) { projection = (UnOpProject) _query; 799 distinct = projection.getDistinct(); 800 mainRelation = ((UnaryOperator) mainRelation).getOperand(); 801 } 802 803 AggregatePair aggrPair = null; 809 RenameRelation queryAlias = null; 810 if (aggrPairs != null && projection != null) { 811 queryAlias = new RenameRelation((Expression) _query, _relIDProvider); 813 BinaryOperator predicate = null; 814 UnOpRestrict restrict = new UnOpRestrict(queryAlias); 815 UnOpProject proj = null; 816 try { 817 proj = new UnOpProject(restrict, AlgebraTools.clone(projection.getItemList()), distinct, _attIDProvider); } catch (CloneNotSupportedException e) { 819 throw new InternalErrorException(MessageLibrary.getMessage("IE_ERR", "Could not clone item list")); 820 } 821 822 InnerRelationInfo in1, in2; 823 824 for (int i = 0; i < aggrPairs.size(); i++) { 825 aggrPair = (AggregatePair) aggrPairs.get(i); 826 aggrPair.subQuery1._renamedQuery = new RenameItem((Expression) aggrPair.subQuery1._query, _attIDProvider); 828 in1 = processSelectAggr(aggrPair.subQuery1); 829 subRelations.add(in1); 830 aggrPair.subQuery2._renamedQuery = new RenameItem((Expression) aggrPair.subQuery2._query, _attIDProvider); 831 in2 = processSelectAggr(aggrPair.subQuery2); 832 subRelations.add(in2); 833 834 predicate = (BinaryOperator) aggrPair.subQuery1._anchor; 836 AttributeExpression att1 = null, att2 = null; 838 att1 = new AttributeExpression(queryAlias, aggrPair.subQuery1._renamedQuery.getName()); 839 att1.setUnderlyingExpr((Expression) in1._aggrItems.get(0)); 840 predicate.setLeftOperand(att1); 841 842 att2 = new AttributeExpression(queryAlias, aggrPair.subQuery2._renamedQuery.getName()); 843 att2.setUnderlyingExpr((Expression) in2._aggrItems.get(0)); 844 predicate.setRightOperand(att2); 845 restrict.addPredicate(predicate); 846 } 847 848 if (_renameVisitor == null) 850 _renameVisitor = new RenameAttributeExpressionVisitor(); 851 _renameVisitor.reinit(queryAlias); 852 proj.accept(_renameVisitor); 853 854 RenameItem ri = null; 856 AttributeExpression ae = null; 857 for (int i = 0; i < aggrItems.size(); i++) { 858 ri = (RenameItem) aggrItems.get(i); 859 ae = new AttributeExpression(queryAlias, ri.getName()); 860 ae.setUnderlyingExpr((Expression) ((UnOpAggregate) ri.getOperand()).getItemList().get(0)); 861 proj.addItem(ae); 862 } 863 864 _query = proj; 865 } 866 867 Iterator it2 = _subQueryList.iterator(); 869 while (it2.hasNext()) { 870 subQuery = (SubQueryNode) it2.next(); 871 872 switch (subQuery.getType()) { 873 case TYPE_PREDICATE_AGGR : 874 relation = processPredicateAggr(subQuery); 875 break; 876 case TYPE_PREDICATE_EXIST : 877 relation = processExist(subQuery); 878 if (_query instanceof UnOpProject) 880 projection = (UnOpProject) _query; 881 break; 882 case TYPE_SELECT_AGGR : 883 relation = processSelectAggr(subQuery); 884 break; 885 886 default : 887 throw new InternalErrorException(MessageLibrary.getMessage("IE_ERR", "The subquery type " + subQuery.getType() + " should not occur at such a stage of rewritting.")); 888 } 889 subRelations.add(relation); 890 } 891 892 893 subRelations = partitionSubQueriesByRelation(subRelations); 894 895 896 _addKeysVisitor.reinit(); 899 mainRelation.accept(_addKeysVisitor); 900 List keys = ((Relation) mainRelation).getKeys(); 901 902 903 buildItemLists(subRelations, projection.getItemList(), ((Relation) mainRelation).visibleTableInstances(), keys, _referringNode instanceof UnOpSort ? (UnOpSort) _referringNode : null); 904 905 906 RenameRelation outerJoin = null; 907 908 for (int i = 0; i < subRelations.size(); i++) { 909 relation = (InnerRelationInfo) subRelations.get(i); 910 911 912 if (i == 0) { 913 914 List mainRelationPredicates = pickOutPredicates(mainRelation, true); 915 if (mainRelation instanceof UnOpRestrict) 916 mainRelation = ((UnOpRestrict) mainRelation).getOperand(); 918 outerJoin = createOuterJoin(mainRelation, mainRelationPredicates, relation, distinct, mainIsAggregate); 919 } else 920 outerJoin = createOuterJoin(outerJoin, null, relation, distinct, mainIsAggregate); 921 } 922 923 if (queryAlias == null) 924 _query = (Relation) outerJoin.getOperand(); 925 else 926 queryAlias.setOperand(outerJoin.getOperand()); 927 } 928 929 _subQueryStack.pop(); 931 932 if (_subQueryStack.isEmpty()) { 934 if (_referringNode != null) { 935 ((UnaryOperator) _referringNode).setOperand((Expression) _query); 936 } else if (_renamedQuery != null) { 937 _renamedQuery.setOperand((Expression) _query); 938 } 939 } 940 941 return this; 942 } 943 944 private void buildItemLists(List subRelations, List mainRelationItems, Set mainRelations, List keys, UnOpSort mainSort) { 945 InnerRelationInfo relation; 946 947 relation = (InnerRelationInfo) subRelations.get(0); 949 relation._items = mainRelationItems; 950 951 InnerRelationInfo underRelation = null; 952 for (int i = 1; i < subRelations.size(); i++) { 953 relation = (InnerRelationInfo) subRelations.get(i); 954 underRelation = (InnerRelationInfo) subRelations.get(i - 1); 955 relation._items = new ArrayList(); 956 try { 957 AlgebraTools.cloneCopyExpressionsWithoutDoubles(underRelation._items, relation._items); 958 AlgebraTools.cloneCopyExpressionsWithoutDoubles(underRelation._aggrItems, relation._items); 959 } catch (CloneNotSupportedException e) { 960 throw new InternalErrorException(MessageLibrary.getMessage("IE_ERR", "Could not clone item lists")); 961 } 962 } 963 964 967 relation = (InnerRelationInfo) subRelations.get(subRelations.size() - 1); 969 relation._alias = new RenameRelation(_relIDProvider); 970 relation._keys = keys; 971 972 for (int i = subRelations.size() - 1; i > 0; i--) { 973 relation = (InnerRelationInfo) subRelations.get(i); 974 underRelation = (InnerRelationInfo) subRelations.get(i - 1); 975 976 if (_foreignAttributeGrabber == null) 978 _foreignAttributeGrabber = new ForeignAttributeGrabber(); 979 980 Collection vti = ((Relation) relation._relation).visibleTableInstances(); 981 _foreignAttributeGrabber.reinit(vti); 982 AlgebraTools.applyVisitorOnCollection(_foreignAttributeGrabber, relation._havingClauses); 983 AlgebraTools.applyVisitorOnCollection(_foreignAttributeGrabber, relation._predicates); 984 if (mainSort != null) AlgebraTools.applyVisitorOnCollection(_foreignAttributeGrabber, mainSort.getSortSpecificationList()); 986 987 try { 989 AlgebraTools.cloneCopyExpressionsWithoutDoubles(_foreignAttributeGrabber.getAttributeList(), underRelation._items); 990 AlgebraTools.cloneCopyExpressionsWithoutDoubles(keys, underRelation._items); 991 underRelation._keys = AlgebraTools.clone(relation._keys); 992 } catch (CloneNotSupportedException e) { 993 throw new InternalErrorException(MessageLibrary.getMessage("IE_ERR", "Could not clone item lists")); 994 } 995 996 if (_renameVisitor == null) 998 _renameVisitor = new RenameAttributeExpressionVisitor(); 999 1000 underRelation._alias = new RenameRelation(_relIDProvider); 1001 _renameVisitor.reinit(vti, underRelation._alias, true, true); 1002 1003 if (mainSort != null) { 1005 AlgebraTools.applyVisitorOnCollection(_renameVisitor, mainSort.getSortSpecificationList()); 1006 mainSort = null; } 1008 AlgebraTools.applyVisitorOnCollection(_renameVisitor, relation._keys, false); 1009 AlgebraTools.applyVisitorOnCollection(_renameVisitor, relation._items, false); AlgebraTools.applyVisitorOnCollection(_renameVisitor, relation._predicates, false); 1011 AlgebraTools.applyVisitorOnCollection(_renameVisitor, relation._havingClauses, false); 1012 1013 relation._items.addAll(relation._aggrItems); 1015 } 1016 relation = (InnerRelationInfo) subRelations.get(0); 1018 relation._items.addAll(relation._aggrItems); 1019 } 1020 1021 private InnerRelationInfo processSelectAggr(SubQueryNode subQuery) { 1022 List itemList = ((UnOpAggregate) subQuery._query).getItemList(); 1024 RenameItem item = (RenameItem) itemList.get(0); 1025 item.setName(subQuery._renamedQuery.getName()); 1026 subQuery._renamedQuery.setOperand(item.getOperand()); 1027 1028 return new InnerRelationInfo(itemList, ((UnOpAggregate) subQuery._query).getOperand()); 1029 } 1030 1031 private InnerRelationInfo processExist(SubQueryNode subQuery) { 1032 1033 Set outerTables = _query.visibleTableInstances(); 1034 List projectAttributes = new ArrayList(); 1035 1036 1042 PredicateHolder holder = (PredicateHolder) subQuery._anchor.getFather(); 1043 Iterator it = holder.getPredicateList().iterator(), it2 = null; 1044 Expression predicate = null; 1045 AttributeExpression att = null, outerAtt = null; 1046 int nbOatt = 0, i = 0; 1047 1048 while (it.hasNext()) { 1049 predicate = (Expression) it.next(); 1050 it2 = predicate.getReferredAttributes().iterator(); 1051 outerAtt = null; 1052 i = nbOatt = 0; 1053 while (it2.hasNext()) { 1054 att = (AttributeExpression) it2.next(); 1055 i++; 1056 if (outerTables.contains(att.getTableInstance())) { 1057 nbOatt++; 1058 outerAtt = att; 1059 } 1060 } 1061 1062 try { 1063 if (i == 2 && nbOatt == 1) 1064 projectAttributes.add(outerAtt.clone()); 1065 } catch (CloneNotSupportedException ex) { 1066 throw new SqlWrapperException(ex.getMessage(), ex); 1067 } 1068 } 1069 1070 1072 ExternalJoinInfo sortInfo = sortSubQueryPredicates((Expression) subQuery._query, outerTables); 1073 1074 1077 if (!sortInfo._externalTables.isEmpty()) { 1078 if (_type != TYPE_PREDICATE_EXIST) 1079 throw new InternalErrorException(MessageLibrary.getMessage("IE_ERR", "External join predicate should not occur out of exist subquery")); 1080 1081 List renamedExternalTables = null; 1083 1084 try { 1085 renamedExternalTables = AlgebraTools.clone(sortInfo._externalTables); 1086 } catch (CloneNotSupportedException ex) { 1087 throw new SqlWrapperException(ex.getMessage(), ex); 1088 } 1089 1090 RenameRelation rTable = null, oTable = null; 1092 List keys = null; 1093 AttributeExpression rAtt = null, oAtt; 1094 1095 int len = renamedExternalTables.size(); 1096 RenameAttributeExpressionVisitor renameVisitor = new RenameAttributeExpressionVisitor(); 1097 1098 1099 if (!(_query instanceof UnOpRestrict)) 1100 _query = new UnOpRestrict((Expression) _query, new ArrayList()); 1101 1102 for (i = 0; i < len; i++) { 1103 oTable = (RenameRelation) sortInfo._externalTables.get(i); 1104 rTable = (RenameRelation) renamedExternalTables.get(i); 1105 rTable.setName(_relIDProvider); 1106 1107 keys = oTable.getKeys(); 1109 if (keys == null) { 1110 _addKeysVisitor.reinit(); 1111 oTable.accept(_addKeysVisitor); 1112 keys = oTable.getKeys(); } 1114 1115 1116 it = keys.iterator(); 1117 Object o; 1118 while (it.hasNext()) { 1119 o = it.next(); 1120 if (o instanceof RenameItem) 1121 oAtt = (AttributeExpression) ((RenameItem) o).getOperand(); 1122 else 1123 oAtt = (AttributeExpression) o; 1124 oAtt.setTableInstance(oTable); 1125 rAtt = new AttributeExpression(rTable, oAtt.getName()); 1126 rAtt.setUnderlyingExpr(oAtt.getUnderlyinExpr()); 1127 projectAttributes.add(rAtt); 1128 rAtt = new AttributeExpression(rTable, oAtt.getName()); 1131 rAtt.setUnderlyingExpr(oAtt.getUnderlyinExpr()); 1132 ((UnOpRestrict) _query).addPredicate(new BinOpCompare(Constants.EQ_COMPOP, rAtt, oAtt)); 1133 } 1134 1135 1136 renameVisitor.reinit(new ArrayList(Collections.singletonList(oTable)), rTable); 1137 AlgebraTools.applyVisitorOnCollection(renameVisitor, sortInfo._externalJoinPredicates, false); 1138 } 1139 1140 1141 Expression outerTable = (Expression) outerTables.iterator().next(); 1142 Join join = null; 1143 if (outerTable.getFather() instanceof Join) { 1144 join = (Join) outerTable.getFather(); 1145 } else { 1146 renamedExternalTables.add(outerTable); join = new Join(); 1148 outerTable.getFather().replaceChild(outerTable, join); 1149 } 1150 join.addOperandList(renamedExternalTables); 1151 } 1152 1153 if (!projectAttributes.isEmpty()) { 1155 UnOpProject project = null; 1156 if (_query instanceof UnOpProject) 1157 project = (UnOpProject) _query; 1158 else 1159 project = new UnOpProject((Expression) _query, _attIDProvider); 1160 _referringNode.replaceChild((Expression) _query, project); 1161 _query = project; 1162 project.addItemList(projectAttributes); 1163 } 1164 1165 1166 AttributeExpression innerTupleRepresentative = null; 1167 try { 1168 innerTupleRepresentative = (AttributeExpression) findNonNullAttribute(subQuery._query.providedTableInstances()).clone(); 1169 } catch (CloneNotSupportedException ex) { 1170 throw new SqlWrapperException(ex.getMessage(), ex); 1171 } 1172 1173 BinOpCompare having = new BinOpCompare(((UnOpExists) subQuery._referringNode).getNot() ? Constants.EQ_COMPOP : Constants.GT_COMPOP, new FunAggregate(FunAggregate.COUNT, innerTupleRepresentative, 1174 false), new LitInteger(0)); 1176 1177 1178 ((PredicateHolder) subQuery._anchor.getFather()).removePredicate(subQuery._anchor); 1179 1180 return new InnerRelationInfo((Expression) subQuery._query, new ArrayList(Collections.singletonList(having))); 1181 } 1182 1183 1187 private InnerRelationInfo processPredicateAggr(SubQueryNode subQuery) { 1188 1189 Expression aggr = ((RenameItem) ((UnOpAggregate) subQuery._query).getItemList().get(0)).getOperand(); 1190 subQuery._referringNode.replaceChild((Expression) subQuery._query, aggr); 1192 1193 return new InnerRelationInfo(((UnOpAggregate) subQuery._query).getOperand(), new ArrayList(Collections.singletonList(subQuery._anchor))); 1194 } 1195 1196 1203 private List partitionSubQueriesByRelation(List subQueryList) { 1204 ArrayList ret = new ArrayList(); 1205 1206 int size; 1207 Iterator it = subQueryList.iterator(); 1208 InnerRelationInfo sub1, sub2; 1209 int i; 1210 1211 1212 while (it.hasNext()) { 1213 size = ret.size(); sub1 = (InnerRelationInfo) it.next(); 1215 1216 1217 for (i = 0; i < size; i++) { 1218 sub2 = (InnerRelationInfo) ret.get(i); 1219 if (sub2.merge(sub1)) 1220 break; 1221 } 1222 1223 if (i == size) { 1224 ret.add(sub1); 1225 } 1226 } 1227 return ret; 1228 } 1229 1230 public byte getBrowsingStep() { 1231 return _browsingStep; 1232 } 1233 1234 public byte getType() { 1235 return _type; 1236 } 1237 1238 public void setType(byte type) { 1239 _type = type; 1240 } 1241 1242 public void setBrowsingStep(byte b) { 1243 _browsingStep = b; 1244 } 1245 1246 public void addSubQuery(SubQueryNode subQuery) { 1247 _subQueryList.add(subQuery); 1248 } 1249 1250 public Expression getCurrent() { 1251 return _current; 1252 } 1253 1254 public void setCurrent(Expression _current) { 1255 this._current = _current; 1256 } 1257 } 1258 1259 protected class InnerRelationInfo { 1260 private boolean _hasAggregate = false; public List _aggrItems = null; public List _items = null; public Expression _relation = null; 1264 public List _havingClauses = null; 1265 public List _predicates = null; public List _keys = null; 1267 public RenameRelation _alias = null; 1268 1269 public InnerRelationInfo(List items, Expression relation) { 1270 this(relation, items, null); 1271 _hasAggregate = true; 1272 } 1273 1274 public InnerRelationInfo(Expression relation, List havingClauses) { 1275 this(relation, new ArrayList(), havingClauses); 1276 } 1277 1278 private InnerRelationInfo(Expression relation, List items, List havingClauses) { 1279 _aggrItems = items; 1280 _havingClauses = havingClauses; 1281 prepare(relation); removeStarCounts(); 1283 } 1284 1285 public boolean hasAggregate() { 1286 return _hasAggregate; 1287 } 1288 1289 1297 private void prepare(Expression relation) { 1298 1299 _predicates = pickOutPredicates(relation, false); 1300 while (relation instanceof UnOpRestrict && !(((UnOpRestrict) relation).getOperand() instanceof UnOpGroup)) relation = ((UnOpRestrict) relation).getOperand(); 1303 1304 rename(relation); 1305 } 1306 1307 private void removeStarCounts() { 1308 if (_aggrItems != null) { 1309 FunAggregate aggrFunc = null; 1310 AttributeExpression tupleRepresentative = null; 1311 for (int i = 0; i < _aggrItems.size(); i++) { 1312 aggrFunc = (FunAggregate) ((RenameItem) _aggrItems.get(i)).getOperand(); 1313 if (aggrFunc.getOperator() == FunAggregate.COUNT && !(aggrFunc.getOperand() instanceof AttributeExpression)) { 1314 if (tupleRepresentative == null) 1315 tupleRepresentative = (AttributeExpression) findNonNullAttribute(((Relation) _relation).providedTableInstances()); 1316 aggrFunc.setOperand(tupleRepresentative); 1318 } 1319 } 1320 } 1321 } 1322 1323 public void rename(Expression relation) { 1324 1325 if (relation instanceof RenameRelation || relation instanceof Join) _relation = relation; 1327 else { 1328 _relation = new RenameRelation(relation, _relIDProvider); 1329 1330 1331 if (_renameVisitor == null) 1332 _renameVisitor = new RenameAttributeExpressionVisitor(); 1333 _renameVisitor.reinit(((Relation) relation).visibleTableInstances(), (RenameRelation) _relation); 1334 1335 1336 if (_aggrItems != null) 1337 AlgebraTools.applyVisitorOnCollection(_renameVisitor, _aggrItems, false); 1338 1339 1340 if (_predicates != null) 1341 AlgebraTools.applyVisitorOnCollection(_renameVisitor, _predicates, false); 1342 1343 1344 if (_havingClauses != null) 1345 AlgebraTools.applyVisitorOnCollection(_renameVisitor, _havingClauses, false); 1346 } 1347 } 1348 1349 1350 public boolean merge(InnerRelationInfo merged) { 1351 if (_relation.deepEquals(merged._relation) && AlgebraTools.areExprListEquivalent(_predicates, merged._predicates)) { 1353 1354 RenameRelation rename = (RenameRelation) ((Relation) _relation).providedTableInstances().iterator().next(); 1356 if (_renameVisitor == null) 1357 _renameVisitor = new RenameAttributeExpressionVisitor(); 1358 _renameVisitor.reinit(((Relation) merged._relation).providedTableInstances(), rename); 1359 1360 1361 if (merged._aggrItems != null) { 1362 1363 AlgebraTools.applyVisitorOnCollection(_renameVisitor, merged._aggrItems, false); 1364 if (_aggrItems == null) 1365 _aggrItems = merged._aggrItems; 1366 else 1367 _aggrItems.addAll(merged._aggrItems); 1368 } 1369 1370 if (merged._havingClauses != null) { 1371 if (_havingClauses == null) 1372 _havingClauses = merged._havingClauses; 1373 else if (!AlgebraTools.areExprListEquivalent(_havingClauses, merged._havingClauses)) { 1374 _havingClauses = new ArrayList(_havingClauses); 1376 AlgebraTools.applyVisitorOnCollection(_renameVisitor, merged._havingClauses, false); 1377 _havingClauses.addAll(merged._havingClauses); 1378 } 1379 } 1380 return true; 1381 } else 1382 return false; 1383 } 1384 } 1385 1386 1390 1391 protected class FindQuerySignatureVisitor extends DefaultSimpleVisitor { 1392 private static final String RCSRevision = "$Revision: 1.26 $"; 1393 private static final String RCSName = "$Name: $"; 1394 1395 private UnOpProject project = null; 1396 private PredicateHolder restrict = null; 1397 private Expression relation = null; 1399 public FindQuerySignatureVisitor() { 1400 } 1401 1402 public void reinit() { 1403 project = null; 1404 restrict = null; 1405 relation = null; 1406 } 1407 1408 public UnOpProject getProjection() { 1409 return project; 1410 } 1411 1412 public PredicateHolder getRestriction() { 1413 return restrict; 1414 } 1415 1416 public Expression getRelation() { 1417 return relation; 1418 } 1419 1420 public void visit(UnOpProject arg) { 1421 super.visit((UnaryOperator) arg); 1422 project = arg; 1423 } 1424 1425 public void visit(UnOpRestrict arg) { 1426 super.visit((UnaryOperator) arg); 1427 restrict = arg; 1428 } 1429 1430 public void visit(Join arg) { 1431 restrict = arg; 1432 relation = arg; 1433 } 1434 1435 public void visit(Table arg) { 1436 relation = arg; 1437 } 1438 1439 public void visit(DummyTable arg) { 1440 relation = arg; 1441 } 1442 1443 public void visit(BinaryAlgebra arg) { 1444 relation = arg; 1445 } 1446 1447 public void visit(BinOpOuterJoin arg) { 1448 relation = arg; 1449 } 1450 } 1451 1452 protected class RemoveAggregateFunctionVisitor extends DefaultSimpleVisitor { 1453 private static final String RCSRevision = "$Revision: 1.26 $"; 1454 private static final String RCSName = "$Name: $"; 1455 1456 private List _collectedItems = new ArrayList(); 1457 private boolean _aggrFound = false; 1458 1459 public void reinit() { 1460 _collectedItems.clear(); 1461 _aggrFound = false; 1462 } 1463 1464 public List getCollectedItems() { 1465 return _collectedItems; 1466 } 1467 1468 public boolean aggregateFound() { 1469 return _aggrFound; 1470 } 1471 1472 public void newItem() { 1473 _aggrFound = false; 1474 } 1475 1476 public void visit(FunAggregate arg) { 1477 super.visit(arg); 1478 _aggrFound = true; 1479 _collectedItems.add(arg.getOperand()); 1480 } 1481 } 1482 1483 protected ExternalJoinInfo sortSubQueryPredicates(Expression subQuery, Set outerTables) { 1484 1486 ExternalJoinInfo ret = new ExternalJoinInfo(); 1487 1488 1489 _restrictionVisitor.reinit(); 1490 subQuery.accept(_restrictionVisitor); 1491 List restrictionList = _restrictionVisitor.getRestrictions(); 1492 1493 1494 List predicateList = null; 1495 1496 Set innerTables = ((Relation) subQuery).visibleTableInstances(); 1497 1499 for (int i = 0; i < restrictionList.size(); i++) { 1500 Expression expr = (Expression) restrictionList.get(i); 1501 predicateList = ((PredicateHolder) expr).getPredicateList(); 1502 1503 predicateList = splitPredicateList(predicateList); 1505 1506 Expression predicate = null; 1507 Set allTables = null; 1508 Iterator it = predicateList.iterator(); 1509 1510 while (it.hasNext()) { 1511 predicate = (Expression) it.next(); 1512 allTables = predicate.getReferredTableInstances(); 1514 1516 allTables.removeAll(innerTables); 1518 allTables.removeAll(outerTables); 1519 1520 if (!allTables.isEmpty()) { 1522 ret._externalTables.addAll(allTables); 1523 ret._externalJoinPredicates.add(predicate); 1524 } 1525 } 1526 } 1527 1528 return ret; 1530 } 1531 1532 protected class ExternalJoinInfo { 1533 public List _externalTables = new ArrayList(); 1534 public List _externalJoinPredicates = new ArrayList(); 1535 } 1536 1537 protected class AggregatePair { 1538 public SubQueryNode subQuery1 = null; 1539 public SubQueryNode subQuery2 = null; 1540 public AggregatePair(SubQueryNode subQuery1, SubQueryNode subQuery2) { 1541 this.subQuery1 = subQuery1; 1542 this.subQuery2 = subQuery2; 1543 } 1544 } 1545 1546 1550 private AttributeExpression findNonNullAttribute(Set relations) { 1551 1552 Iterator it = relations.iterator(), itColumns; 1553 AttributeExpression attExp = null; 1554 1555 while (it.hasNext() && attExp == null) { 1556 attExp = ((Relation) it.next()).findNonNullAttribute(); 1557 } 1558 1559 Debug.assertTrue(attExp != null, "Impossible to rewrite query because all relation attributes are nullable."); 1560 1561 return attExp; 1562 } 1563 1564 1568 private List splitPredicateList(List predicateList) { 1569 int len = predicateList.size(); 1570 1571 if (_splitVisitor == null) 1572 _splitVisitor = new SplitPredicateVisitor(); 1573 else 1574 _splitVisitor.reinit(); 1575 1576 AlgebraTools.applyVisitorOnCollection(_splitVisitor, predicateList); 1577 1578 return _splitVisitor.getPredicateList(); 1579 } 1580 1581 protected class SplitPredicateVisitor extends DefaultAlgebraVisitor { 1582 private static final String RCSRevision = "$Revision: 1.26 $"; 1583 private static final String RCSName = "$Name: $"; 1584 1585 private List _predicates = null; 1586 1587 public SplitPredicateVisitor() { 1588 reinit(); 1589 } 1590 1591 public void reinit() { 1592 _predicates = new ArrayList(); 1593 } 1594 1595 public List getPredicateList() { 1596 return _predicates; 1597 } 1598 1599 public void visit(BinOpBoolean arg) { 1600 if (arg.getOperator() == Constants.AND) { 1602 arg.getLeftOperand().accept(this); 1603 arg.getRightOperand().accept(this); 1604 } else 1605 _predicates.add(arg); 1606 } 1607 1608 public void visit(Expression arg) { 1609 _predicates.add(arg); 1611 } 1612 } 1613 1614 protected class ForeignAttributeGrabber extends DefaultCompleteVisitor { 1615 1616 private List attList = new ArrayList(); 1617 private Collection _relations; 1618 1619 public void reinit(Collection renameRelations) { 1620 _relations = renameRelations; 1621 attList.clear(); 1622 } 1623 1624 public List getAttributeList() { 1625 return attList; 1626 } 1627 1628 public void visit(AttributeExpression arg) { 1629 if (!_relations.contains(arg.getTableInstance())) 1630 attList.add(arg); 1631 } 1632 } 1633 1634 protected class AttributeGrabber extends DefaultSimpleVisitor { 1635 1636 private AttributeExpression att = null; 1637 1638 public void reinit() {att = null;} 1639 1640 public AttributeExpression getAttributeExpression() { 1641 return att; 1642 } 1643 1644 public void visit(AttributeExpression arg) { 1645 att = arg; 1646 } 1647 } 1648 1649} 1650 | Popular Tags |