1 29 30 package com.caucho.amber.query; 31 32 import com.caucho.amber.entity.AmberEntityHome; 33 import com.caucho.amber.expr.AmberExpr; 34 import com.caucho.amber.expr.AndExpr; 35 import com.caucho.amber.expr.JoinExpr; 36 import com.caucho.amber.expr.KeyColumnExpr; 37 import com.caucho.amber.expr.LoadEntityExpr; 38 import com.caucho.amber.expr.ManyToOneJoinExpr; 39 import com.caucho.amber.type.EntityType; 40 import com.caucho.amber.type.Type; 41 import com.caucho.util.CharBuffer; 42 43 import java.sql.SQLException ; 44 import java.util.ArrayList ; 45 import java.util.Map ; 46 47 48 51 public class SelectQuery extends AbstractQuery { 52 private AbstractQuery _parentQuery; 53 54 private boolean _isDistinct; 55 56 private ArrayList <AmberExpr> _resultList; 57 private AmberExpr _where; 58 private AmberExpr _having; 59 60 private ArrayList <AmberExpr> _orderList; 61 private ArrayList <Boolean > _ascList; 62 63 private ArrayList <AmberExpr> _groupList; 64 65 private Map <AmberExpr, String > _joinFetchMap; 66 67 private String _sql; 68 69 private Class _constructorClass; 71 72 private boolean _isTableReadOnly = false; 73 private long _cacheTimeout = -1; 74 75 private boolean _hasFrom = true; 76 77 SelectQuery(String query) 78 { 79 super(query); 80 } 81 82 85 Map <AmberExpr, String > getJoinFetchMap() 86 { 87 return _joinFetchMap; 88 } 89 90 93 void setConstructorClass(Class cl) 94 { 95 _constructorClass = cl; 96 } 97 98 101 public Class getConstructorClass() 102 { 103 return _constructorClass; 104 } 105 106 109 void setHasFrom(boolean hasFrom) 110 { 111 114 _hasFrom = hasFrom; 115 } 116 117 120 void setParentQuery(AbstractQuery parent) 121 { 122 _parentQuery = parent; 123 } 124 125 128 public AbstractQuery getParentQuery() 129 { 130 return _parentQuery; 131 } 132 133 136 void setDistinct(boolean isDistinct) 137 { 138 _isDistinct = isDistinct; 139 } 140 141 144 void setResultList(ArrayList <AmberExpr> resultList) 145 { 146 _resultList = resultList; 147 } 148 149 152 public ArrayList <AmberExpr> getResultList() 153 { 154 return _resultList; 155 } 156 157 160 int getResultCount() 161 { 162 return _resultList.size(); 163 } 164 165 168 Type getResultType(int index) 169 { 170 AmberExpr expr = _resultList.get(index); 171 172 return expr.getType(); 173 } 174 175 178 void setHaving(AmberExpr expr) 179 { 180 _having = expr; 181 } 182 183 186 void setWhere(AmberExpr expr) 187 { 188 _where = expr; 189 } 190 191 194 void setGroupList(ArrayList <AmberExpr> groupList) 195 { 196 _groupList = groupList; 197 } 198 199 202 void setJoinFetchMap(Map <AmberExpr, String > joinFetchMap) 203 { 204 _joinFetchMap = joinFetchMap; 205 } 206 207 210 void setOrderList(ArrayList <AmberExpr> orderList, 211 ArrayList <Boolean > ascList) 212 { 213 _orderList = orderList; 214 _ascList = ascList; 215 } 216 217 220 public String getSQL() 221 { 222 return _sql; 223 } 224 225 228 public long getCacheMaxAge() 229 { 230 return _cacheTimeout; 231 } 232 233 236 public boolean isCacheable() 237 { 238 return 100L <= _cacheTimeout; 239 } 240 241 244 public boolean isTableReadOnly() 245 { 246 return _isTableReadOnly; 247 } 248 249 252 void init() 253 throws SQLException 254 { 255 if (_where instanceof AndExpr) { 256 AndExpr and = (AndExpr) _where; 257 258 ArrayList <AmberExpr> components = and.getComponents(); 259 260 for (int i = components.size() - 1; i >= 0; i--) { 261 AmberExpr component = components.get(i); 262 263 if (component instanceof JoinExpr) { 264 JoinExpr link = (JoinExpr) component; 265 266 if (link.bindToFromItem()) { 267 components.remove(i); 268 } 269 } 270 } 271 272 _where = and.getSingle(); 273 } 274 275 if (_having instanceof AndExpr) { 276 AndExpr and = (AndExpr) _having; 277 278 ArrayList <AmberExpr> components = and.getComponents(); 279 280 for (int i = components.size() - 1; i >= 0; i--) { 281 AmberExpr component = components.get(i); 282 283 if (component instanceof JoinExpr) { 284 JoinExpr link = (JoinExpr) component; 285 286 if (link.bindToFromItem()) { 287 components.remove(i); 288 } 289 } 290 } 291 292 _having = and.getSingle(); 293 } 294 295 for (int i = 0; i < _fromList.size(); i++) { 299 FromItem item = _fromList.get(i); 300 301 JoinExpr join = item.getJoinExpr(); 302 303 if (join == null) 304 continue; 305 306 if (getParentQuery() != null) 308 break; 309 310 FromItem joinParent = join.getJoinParent(); 311 FromItem joinTarget = join.getJoinTarget(); 312 313 boolean isTarget = item == joinTarget; 314 315 if (joinParent == null) { 316 } 317 else if (joinParent.getJoinExpr() == null 318 && joinParent == joinTarget 319 && ! usesFromData(joinParent)) { 320 _fromList.remove(joinParent); 321 322 replaceJoin(join); 323 324 item.setJoinExpr(null); 326 i = -1; 328 329 AmberExpr joinWhere = join.getWhere(); 330 331 if (joinWhere != null) 332 _where = AndExpr.create(_where, joinWhere); 333 } 334 else if (item == joinTarget 335 && ! isJoinParent(item) 336 && ! usesFromData(item)) { 337 338 boolean isManyToMany = false; 339 340 if (join instanceof ManyToOneJoinExpr) { 342 ManyToOneJoinExpr manyToOneJoinExpr; 343 manyToOneJoinExpr = (ManyToOneJoinExpr) join; 344 isManyToMany = manyToOneJoinExpr.isManyToMany(); 345 } 346 347 if (item.isOuterJoin() || exists(joinTarget) || isManyToMany) { 348 353 _fromList.remove(item); 354 355 replaceJoin(join); 356 357 i = -1; 358 359 AmberExpr joinWhere = join.getWhere(); 360 361 if (joinWhere != null) 362 _where = AndExpr.create(_where, joinWhere); 363 } 364 } 365 } 366 367 for (int i = 0; i < _fromList.size(); i++) { 368 FromItem item = _fromList.get(i); 369 370 if (item.isInnerJoin()) 371 continue; 372 373 if (item.getJoinExpr() == null) 374 continue; 375 376 boolean isFromInner = isFromInnerJoin(item); 377 378 item.setOuterJoin(! isFromInner); 379 } 380 381 _cacheTimeout = Long.MAX_VALUE / 2; 382 _isTableReadOnly = true; 383 for (FromItem item : _fromList) { 384 EntityType type = item.getTableType(); 385 386 if (type != null) { 387 long timeout = type.getCacheTimeout(); 388 389 if (timeout < _cacheTimeout) 390 _cacheTimeout = timeout; 391 392 if (! type.isReadOnly()) 393 _isTableReadOnly = false; 394 } 395 else { 396 _isTableReadOnly = false; 398 } 399 } 400 401 _sql = generateLoadSQL(); 402 } 403 404 boolean isJoinParent(FromItem item) 405 { 406 for (int i = 0; i < _fromList.size(); i++) { 407 FromItem subItem = _fromList.get(i); 408 409 if (subItem.getJoinExpr() != null && 410 subItem.getJoinExpr().getJoinParent() == item) { 411 return true; 412 } 413 } 414 415 return false; 416 } 417 418 boolean isFromInnerJoin(FromItem item) 419 { 420 return usesFrom(item, AmberExpr.IS_INNER_JOIN); 421 } 422 423 boolean usesFromData(FromItem item) 424 { 425 return usesFrom(item, AmberExpr.USES_DATA); 426 } 427 428 431 public boolean exists(FromItem item) 432 { 433 if (_where != null && _where.exists(item)) 435 return true; 436 437 if (_orderList != null) { 438 for (AmberExpr orderBy : _orderList) { 439 if (orderBy instanceof KeyColumnExpr 441 && orderBy.usesFrom(item, AmberExpr.IS_INNER_JOIN, false)) 442 return true; 443 } 444 } 445 446 if (_groupList != null) { 447 for (AmberExpr groupBy : _groupList) { 448 if (groupBy instanceof KeyColumnExpr 449 && groupBy.usesFrom(item, AmberExpr.IS_INNER_JOIN, false)) 450 return true; 451 } 452 } 453 454 if (_having != null && _having.exists(item)) 455 return true; 456 457 return false; 458 } 459 460 463 public boolean usesFrom(FromItem item, int type) 464 { 465 for (int j = 0; j < _resultList.size(); j++) { 466 AmberExpr result = _resultList.get(j); 467 468 if (result.usesFrom(item, type)) { 469 return true; 470 } 471 } 472 473 if (_where != null && _where.usesFrom(item, type)) 474 return true; 475 476 if (_orderList != null) { 477 for (int j = 0; j < _orderList.size(); j++) { 478 AmberExpr order = _orderList.get(j); 479 480 if (order.usesFrom(item, type)) { 481 return true; 482 } 483 } 484 } 485 486 if (_groupList != null) { 488 for (int j = 0; j < _groupList.size(); j++) { 489 AmberExpr group = _groupList.get(j); 490 491 if (group.usesFrom(item, AmberExpr.IS_INNER_JOIN)) { 493 return true; 494 } 495 } 496 497 if (_having != null && _having.usesFrom(item, type)) 498 return true; 499 } 500 501 return false; 502 } 503 504 void replaceJoin(JoinExpr join) 505 { 506 for (int i = 0; i < _resultList.size(); i++) { 507 AmberExpr result = _resultList.get(i); 508 509 _resultList.set(i, result.replaceJoin(join)); 510 } 511 512 if (_where != null) { 513 _where = _where.replaceJoin(join); 514 } 515 516 if (_orderList != null) { 517 for (int i = 0; i < _orderList.size(); i++) { 518 AmberExpr order = _orderList.get(i); 519 520 _orderList.set(i, order.replaceJoin(join)); 521 } 522 } 523 } 524 525 public String generateLoadSQL() 526 { 527 return generateLoadSQL(true); 528 } 529 530 550 public String generateLoadSQL(boolean fullSelect) 551 { 552 CharBuffer cb = CharBuffer.allocate(); 553 554 cb.append("select "); 555 556 if (_isDistinct) 557 cb.append(" distinct "); 558 559 for (int i = 0; i < _resultList.size(); i++) { 560 if (i != 0) 561 cb.append(", "); 562 563 AmberExpr expr = _resultList.get(i); 564 565 if ((_groupList == null) && (expr instanceof LoadEntityExpr)) 566 ((LoadEntityExpr) expr).generateSelect(cb, fullSelect); 567 else 568 expr.generateSelect(cb); 569 } 570 571 if (_hasFrom) 572 cb.append(" from "); 573 574 for (int i = 1; i < _fromList.size(); i++) { 576 FromItem item = _fromList.get(i); 577 578 if (item.isOuterJoin()) { 579 JoinExpr join = item.getJoinExpr(); 580 581 if (join == null) 582 continue; 583 584 FromItem parent = join.getJoinParent(); 585 586 int index = _fromList.indexOf(parent); 587 588 if (index < 0) 589 continue; 590 591 _fromList.remove(i); 592 593 if (index < i) 594 index++; 595 596 _fromList.add(index, item); 597 } 598 } 599 600 boolean hasJoinExpr = false; 601 boolean isFirst = true; 602 for (int i = 0; i < _fromList.size(); i++) { 603 FromItem item = _fromList.get(i); 604 605 if (getParentQuery() != null) { 607 ArrayList <FromItem> fromList = getParentQuery().getFromList(); 608 if (fromList != null) { 609 if (fromList.contains(item)) { 610 hasJoinExpr = true; 611 continue; 612 } 613 } 614 } 615 616 if (isFirst) { 617 isFirst = false; 618 } 619 else { 620 if (item.isOuterJoin()) 621 cb.append(" left outer join "); 622 else { 623 cb.append(", "); 624 625 if (item.getJoinExpr() != null) 626 hasJoinExpr = true; 627 } 628 } 629 630 cb.append(item.getTable().getName()); 631 cb.append(" "); 632 cb.append(item.getName()); 633 634 if (item.getJoinExpr() != null && item.isOuterJoin()) { 635 cb.append(" on "); 636 item.getJoinExpr().generateJoin(cb); 637 } 638 } 639 640 if (hasJoinExpr || _where != null) { 641 boolean hasExpr = false; 642 643 cb.append(" where "); 644 645 for (int i = 0; i < _fromList.size(); i++) { 646 FromItem item = _fromList.get(i); 647 AmberExpr expr = item.getJoinExpr(); 648 649 if (expr != null && ! item.isOuterJoin()) { 650 if (hasExpr) 651 cb.append(" and "); 652 hasExpr = true; 653 654 expr.generateJoin(cb); 655 } 656 } 657 658 if (_where != null) { 659 if (hasExpr) 660 cb.append(" and "); 661 hasExpr = true; 662 663 _where.generateWhere(cb); 664 } 665 } 666 667 if (_groupList != null) { 668 cb.append(" group by "); 669 670 for (int i = 0; i < _groupList.size(); i++) { 671 if (i != 0) 672 cb.append(", "); 673 674 _groupList.get(i).generateSelect(cb); 675 } 676 } 677 678 if (_having != null) { 679 boolean hasExpr = false; 680 681 cb.append(" having "); 682 683 697 698 if (_having != null) { 699 if (hasExpr) 700 cb.append(" and "); 701 hasExpr = true; 702 703 _having.generateHaving(cb); 704 } 705 } 706 707 if (_orderList != null) { 708 cb.append(" order by "); 709 710 for (int i = 0; i < _orderList.size(); i++) { 711 if (i != 0) 712 cb.append(", "); 713 714 _orderList.get(i).generateSelect(cb); 715 716 if (Boolean.FALSE.equals(_ascList.get(i))) 717 cb.append(" desc"); 718 } 719 } 720 721 return cb.toString(); 722 } 723 724 727 void registerUpdates(CachedQuery query) 728 { 729 for (int i = 0; i < _fromList.size(); i++) { 730 FromItem item = _fromList.get(i); 731 732 AmberEntityHome home = item.getEntityHome(); 733 734 CacheUpdate update = new TableCacheUpdate(query); 735 736 home.addUpdate(update); 737 } 738 } 739 740 743 public boolean invalidateTable(String table) 744 { 745 for (int i = _fromList.size() - 1; i >= 0; i--) { 746 FromItem from = _fromList.get(i); 747 748 if (table.equals(from.getTable().getName())) 749 return true; 750 } 751 752 return false; 753 } 754 755 758 public String toString() 759 { 760 return "SelectQuery[" + getQueryString() + "]"; 761 } 762 } 763 | Popular Tags |