1 22 23 package org.xquark.extractor.algebra; 24 25 import java.util.*; 26 27 import org.xquark.extractor.common.Debug; 28 import org.xquark.extractor.common.SqlWrapperException; 29 import org.xquark.xquery.parser.XQueryExpression; 30 31 36 public final class RemoveIntermediateProjectVisitor extends DefaultCompleteVisitor { 37 private static final String RCSRevision = "$Revision: 1.7 $"; 38 private static final String RCSName = "$Name: $"; 39 40 private TopDownReplacer _topDownReplacer; 41 private ReplaceTractor _replaceTractor; 42 43 private Stack _scopeStack = new Stack(); 44 45 private RemoveProjectVoteVisitor _voteVisitor = new RemoveProjectVoteVisitor(); 46 47 public void reinit() { 48 _scopeStack.clear(); 49 _voteVisitor.reinit(); 50 createScope(); 51 } 52 53 public RemoveIntermediateProjectVisitor() { 54 } 55 56 public TopDownReplacer getReplacerInstance() { 57 if (null == _topDownReplacer) { 58 _topDownReplacer = new TopDownReplacer(); 59 } 60 return _topDownReplacer; 61 } 62 63 public ReplaceTractor getTractorInstance() { 64 if (null == _replaceTractor) { 65 _replaceTractor = new ReplaceTractor(); 66 } 67 return _replaceTractor; 68 } 69 70 private boolean isDeletePermitted() { 71 boolean retVal = ((Scope) _scopeStack.peek())._deletePermited; 73 return retVal; 75 } 76 77 private void permitDelete(Expression node, boolean permit) { 78 Scope currentScope = (Scope) _scopeStack.peek(); 80 currentScope._deletePermited = permit; 81 currentScope._node = node; 82 } 84 85 private Expression currentPermiter() { 86 Scope currentScope = (Scope) _scopeStack.peek(); 88 Debug.assertTrue(currentScope._deletePermited, "currentScope._deletePermited"); 89 return currentScope._node; 91 } 92 93 private void createScope() { 94 _scopeStack.push(new Scope()); 95 } 96 97 private Scope currentScope() { 98 return (Scope) _scopeStack.peek(); 99 } 100 101 private void leaveScope() { 102 RenameRelation rr = currentScope()._unresolvedRenameRelation; 104 if (null != rr) 105 removeUnresolvedRename(rr); 106 107 _scopeStack.pop(); 108 } 110 111 private void removeUnresolvedRename(RenameRelation rr) { 112 if (null != rr.getFather() && !(rr.getOperand() instanceof Table)) { 113 114 116 HashMap map = new HashMap(); 117 Object tableInstance = null; 118 Set vtis = rr.visibleTableInstances(); 119 int visibleTableInstancesNumber = vtis.size(); 120 121 if (0 == visibleTableInstancesNumber) { 122 Debug.assertTrue(false, "internal logic error"); 123 } else if (1 == visibleTableInstancesNumber) { 124 tableInstance = (Expression) vtis.toArray()[0]; 125 if (!(tableInstance instanceof RenameRelation)) { 126 tableInstance = new NullPointer(); 127 } 128 map.put(rr, tableInstance); 129 } else { 130 Debug.nyi("remove RenameRelation"); 131 } 132 133 134 TopDownReplacer replacer = getReplacerInstance(); 135 replacer.setReplaceMap(map); 136 137 ReplaceTractor tractor = getTractorInstance(); 138 tractor.setVisitor(replacer); 139 tractor.setEndNode(currentPermiter()); 140 142 Expression father = rr.getFather(); 143 boolean replaced = father.replaceChild(rr, rr.getOperand()); 144 Debug.assertTrue(replaced, "replaced"); 145 rr.setFather(null); 146 father.accept(tractor); 148 } 149 } 150 151 153 public void visit(BinaryAlgebra arg) throws SqlWrapperException { 154 156 157 createScope(); 158 arg.getLeftOperand().accept(this); 159 leaveScope(); 160 161 createScope(); 162 arg.getRightOperand().accept(this); 163 leaveScope(); 164 165 } 167 168 public void visit(BinaryAtomicOp arg) throws SqlWrapperException { 169 171 createScope(); 172 arg.getLeftOperand().accept(this); 173 leaveScope(); 174 175 createScope(); 176 arg.getRightOperand().accept(this); 177 leaveScope(); 178 179 } 181 182 public void visit(BinOpOuterJoin arg) throws SqlWrapperException { 183 185 arg.getLeftOperand().accept(this); 186 arg.getRightOperand().accept(this); 187 188 } 190 191 public void visit(SortSpecification arg) throws SqlWrapperException { 192 Expression sortExpr = arg.getSortExpression(); 194 sortExpr.accept(this); 195 } 197 198 public void visit(RenameRelation arg) throws SqlWrapperException { 199 201 203 if (!(arg.getOperand() instanceof Table || arg.getOperand() instanceof UnOpProject)) { 204 207 currentScope()._unresolvedRenameRelation = arg; 208 } 210 211 Expression operand = arg.getOperand(); 212 operand.accept(this); 213 214 } 216 217 public void visit(Table arg) throws SqlWrapperException { 218 220 } 222 223 public void visit(Join arg) throws SqlWrapperException { 224 226 List list = arg.getPredicateList(); 227 if (null != list) { 228 Expression expr = null; 229 for (int i = 0; i < list.size(); i++) { 230 expr = (Expression) list.get(i); 231 createScope(); 232 expr.accept(this); 233 leaveScope(); 234 } 235 } 236 237 list = arg.getOperands(); 238 Debug.assertTrue(null != list, "null!=list"); 239 Expression expr = null; 240 for (int i = 0; i < list.size(); i++) { 241 expr = (Expression) list.get(i); 242 expr.accept(this); 243 } 244 245 } 247 248 public void visit(UnaryAlgebra arg) throws SqlWrapperException { 249 251 List list = arg.getParameterList(); 252 if (null != list) { 253 Expression expr = null; 254 for (int i = 0; i < list.size(); i++) { 255 expr = (Expression) list.get(i); 256 createScope(); 257 expr.accept(this); 258 leaveScope(); 259 } 260 } 261 262 Expression operand = arg.getOperand(); 263 if (isDeletePermitted()) { 264 265 List opposers = vote(arg.getParameterList()); 266 if (null == opposers || opposers.isEmpty()) { 267 268 } else { 269 permitDelete(arg, false); 270 } 271 } 272 operand.accept(this); 273 274 } 276 277 public void visit(UnaryAtomicOp arg) throws SqlWrapperException { 278 arg.getOperand().accept(this); 280 } 282 283 public void visit(UnOpAggregate arg) throws SqlWrapperException { 284 286 Expression operand = arg.getOperand(); 287 288 289 createScope(); 290 List opposers = vote(arg.getItemList()); 291 if (null == opposers || opposers.isEmpty()) { 292 permitDelete(arg, true); 293 } 295 operand.accept(this); 296 leaveScope(); 297 298 List itemList = arg.getItemList(); 299 Expression item = null; 300 ; 301 for (int i = 0; i < itemList.size(); i++) { 302 createScope(); 303 item = (Expression) itemList.get(i); 304 item.accept(this); 305 leaveScope(); 306 } 307 308 } 310 311 public void visit(UnOpExists arg) throws SqlWrapperException { 312 createScope(); 314 boolean doSpecial = false; 315 Expression op = arg.getOperand(); 316 if (op instanceof UnOpProject) { 317 if (((UnOpProject)op).getOperand() instanceof Join) 318 doSpecial = true; 319 } 320 if (doSpecial) 322 permitDelete(arg, false); 323 else 324 permitDelete(arg, true); 325 arg.getOperand().accept(this); 326 leaveScope(); 327 } 329 330 public void visit(UnOpProject arg) throws SqlWrapperException { 331 333 Expression operand = arg.getOperand(); 334 335 336 createScope(); 338 341 List opposers = vote(arg.getItemList()); 342 if (null == opposers || opposers.isEmpty()) { 343 permitDelete(arg, true); 344 } 346 operand.accept(this); 347 leaveScope(); 348 349 350 List itemList = arg.getItemList(); 352 Expression item = null; 353 boolean hasAggregateItem = false; 354 if (itemList != null) 355 for (int i = 0; i < itemList.size(); i++) { 356 createScope(); 357 item = (Expression) itemList.get(i); 358 item.accept(this); 359 hasAggregateItem = (item instanceof RenameItem && ((RenameItem)item).getOperand() instanceof UnOpAggregate); 361 leaveScope(); 362 } 363 364 365 if (isDeletePermitted()) { 366 if (currentPermiter() instanceof UnOpAggregate) { 367 if (!hasAggregateItem) { 369 if (!arg.getDistinct()) { 370 removeProject(arg, currentPermiter()); 371 } else { 372 375 if (1 == arg.getItemList().size()) { 376 removeProject(arg, currentPermiter()); 377 ((UnOpAggregate) currentPermiter()).distinctAggregation(); 378 379 } else { 380 Debug.nyi("1 != arg.getItemList().size()"); 381 } 382 } 383 } 384 } else if (!arg.getDistinct()) { 385 removeProject(arg, currentPermiter()); 386 } 387 } 388 389 } 391 392 private void removeProject(UnOpProject project, Expression permittingNode) { 393 395 HashMap map = makeMap(project); 397 398 399 TopDownReplacer replacer = getReplacerInstance(); 400 replacer.setReplaceMap(map); 401 402 ReplaceTractor tractor = getTractorInstance(); 403 tractor.setVisitor(replacer); 404 tractor.setEndNode(currentPermiter()); 405 407 Expression father = project.getFather(); 408 409 boolean replaced = father.replaceChild(project, project.getOperand()); 410 Debug.assertTrue(replaced, "replaced"); 411 412 project.setFather(null); 413 father.accept(tractor); 415 416 } 418 419 private List vote(List exprList) { 420 return null; 421 } 434 435 private HashMap makeMap(UnOpProject arg) { 436 438 HashMap retVal = new HashMap(); 439 List itemList = arg.getItemList(); 440 Expression item = null; 441 String attrName = null; 442 AttributeExpression attrExpr = null; 443 Expression replacer = null; 444 XQueryExpression originalXExpr = null; 445 446 if (itemList != null) 447 for (int i = 0; i < itemList.size(); i++) { 448 item = (Expression) itemList.get(i); 449 attrName = item.getName(); 450 attrExpr = new AttributeExpression(null, attrName); 451 452 455 replacer = findReplacer(item); 456 retVal.put(attrExpr, replacer); 457 } 458 459 460 Set vtiSet = arg.visibleTableInstances(); 461 if (1 == vtiSet.size()) { 462 Expression vti = (Expression) vtiSet.toArray()[0]; 463 if (vti instanceof RenameRelation) { 464 attrExpr = new AttributeExpression(null, "*"); 465 replacer = new AttributeExpression((RenameRelation) vti, "*"); 466 retVal.put(attrExpr, replacer); 467 } 468 } 469 470 return retVal; 472 } 473 474 private Expression findReplacer(Expression item) { 475 477 Expression retVal = null; 478 479 if (item instanceof RenameItem) { 480 retVal = ((RenameItem) item).getOperand(); 481 retVal = findReplacer(retVal); 482 } 483 else { 492 retVal = item; 493 } 495 496 return retVal; 498 } 499 500 class Scope { 501 private static final String RCSRevision = "$Revision: 1.7 $"; 502 private static final String RCSName = "$Name: $"; 503 504 boolean _deletePermited = false; 505 Expression _node = null; 506 RenameRelation _unresolvedRenameRelation = null; 507 Scope() { 508 } 509 Scope(Expression node, boolean deletePermited) { 510 _node = node; 511 _deletePermited = deletePermited; 512 } 513 } 514 515 final class ReplaceTractor extends BottomUpTractor { 516 ReplaceTractor() { 517 super(); 518 } 519 520 public void visit(RenameRelation arg) throws SqlWrapperException { 521 523 524 Map map = ((TopDownReplacer) getVisitor()).getReplaceMap(); 525 526 HashMap newMap = new HashMap(); 527 Set keySet = map.keySet(); 528 Iterator iter = keySet.iterator(); 529 AttributeExpression item = null; 530 Object value = null; 531 while (iter.hasNext()) { 532 item = (AttributeExpression) iter.next(); 533 value = map.get(item); 534 535 item.setTableInstance(arg); 536 newMap.put(item, value); 537 } 538 539 ((TopDownReplacer) getVisitor()).setReplaceMap(newMap); 540 541 543 544 Expression father = arg.getFather(); 545 boolean replaced = father.replaceChild(arg, arg.getOperand()); 546 Debug.assertTrue(replaced, "replaced"); 547 arg.setFather(null); 548 550 if (getEndNode() != arg) { 551 father.accept(this); 552 } 553 554 } 556 557 public void visit(UnOpProject arg) throws SqlWrapperException { 558 560 List list = arg.getParameterList(); 561 562 if (null != list) { 563 treat(list); 564 } 565 566 UnOpSort sort = arg.getAssociatedSort(); 567 if (null != sort) { 568 SortSpecification spec = null; 569 list = sort.getSortSpecificationList(); 570 treat(list); 571 } 572 573 visitFather(arg); 574 575 } 577 } 578 } 579 | Popular Tags |