1 2 12 package com.versant.core.jdbc.sql.exp; 13 14 import com.versant.core.common.Debug; 15 import com.versant.core.metadata.ClassMetaData; 16 import com.versant.core.metadata.MDStatics; 17 import com.versant.core.jdo.query.*; 18 import com.versant.core.jdbc.metadata.*; 19 import com.versant.core.jdbc.sql.SqlDriver; 20 import com.versant.core.jdbc.query.JDOQLNodeToSqlExp; 21 import com.versant.core.jdbc.fetch.FetchSpec; 22 import com.versant.core.util.CharBuf; 23 24 import java.util.Map ; 25 26 import com.versant.core.common.BindingSupportImpl; 27 28 31 public class SelectExp extends LeafExp { 32 public static final ColumnStruct[] EMPTY_COLUMS_STRUCT = new ColumnStruct[0]; 33 34 37 public SqlExp selectList; 38 41 public boolean distinct; 42 45 public boolean forUpdate; 46 49 public JdbcTable table; 50 53 public JdbcField jdbcField; 54 57 public VarNode var; 58 61 public String alias; 62 67 public SqlExp subSelectJoinExp; 68 71 public SqlExp whereExp; 72 75 public SqlExp orderByList; 76 public SqlExp resultList; 77 public SqlExp groupByList; 78 public HavingExp havingExp; 79 82 public boolean outer; 83 88 public Join joinList; 89 90 94 public int selectListStartIndex; 95 99 public int selectListFirstColEndIndex; 100 104 public int selectListEndIndex; 105 109 public int orderByStartIndex; 110 114 public int orderByEndIndex; 115 116 public int selectListCountBeforeAggregate; 117 118 public FetchSpec fetchSpec; 119 120 private static final char ALIAS_PREPEND_CONSTANT = 'x'; 121 122 public SelectExp() { 123 } 124 125 public SqlExp createInstance() { 126 return new SelectExp(); 127 } 128 129 public SqlExp getClone(SqlExp clone, Map cloneMap) { 130 SelectExp cst = (SelectExp)clone; 131 super.getClone(cst, cloneMap); 132 133 if (selectList != null) cst.selectList = createClone(selectList, cloneMap); 134 cst.distinct = distinct; 135 cst.forUpdate = forUpdate; 136 cst.table = table; 137 cst.jdbcField = jdbcField; 138 cst.var = var; 139 cst.alias = alias; 140 if (subSelectJoinExp != null) cst.subSelectJoinExp = createClone(subSelectJoinExp, cloneMap); 141 if (whereExp != null) cst.whereExp = createClone(whereExp, cloneMap); 142 if (orderByList != null) cst.orderByList = createClone(orderByList, cloneMap); 143 cst.outer = outer; 144 if (joinList != null) cst.joinList = joinList.getClone(cloneMap); 145 cst.selectListStartIndex = selectListStartIndex; 146 cst.selectListEndIndex = selectListEndIndex; 147 cst.orderByStartIndex = orderByStartIndex; 148 cst.orderByEndIndex = orderByEndIndex; 149 150 return cst; 151 } 152 153 public String toString() { 154 return super.toString() + (outer ? " OUTER " : " ") + 155 table.name + (alias == null ? "": "aliased to " + alias) + 156 (jdbcField != null ? " " + jdbcField : "") + 157 (var != null ? " " + var : ""); 158 } 159 160 163 public int getSelectListColumnCount() { 164 if (selectList == null) return 0; 165 int count = 0; 166 for (SqlExp se = selectList; se != null; se = se.next) { 167 count++; 168 } 169 count += countSelect(joinList); 170 return count; 171 } 172 173 176 public void dump(String indent) { 177 Debug.OUT.println(indent + this); 178 String is = indent + " "; 179 if (selectList != null) { 180 Debug.OUT.println(indent + "selectList"); 181 selectList.dumpList(is); 182 } 183 if (joinList != null) { 184 Debug.OUT.println(indent + "joinList"); 185 joinList.dumpList(is); 186 } 187 if (subSelectJoinExp != null) { 188 Debug.OUT.println(indent + "subSelectJoinExp"); 189 subSelectJoinExp.dump(is); 190 } 191 if (whereExp != null) { 192 Debug.OUT.println(indent + "whereExp"); 193 whereExp.dump(is); 194 } 195 if (orderByList != null) { 196 Debug.OUT.println(indent + "orderByList"); 197 orderByList.dumpList(is); 198 } 199 } 200 201 204 public void addJoin(Join join) { 205 if (joinList == null) { 206 joinList = join; 207 } else { 208 for (Join j = joinList; ;) { 209 Join next = j.next; 210 if (next == null) { 211 j.next = join; 212 return; 213 } 214 j = next; 215 } 216 } 217 } 218 219 223 public void addJoinMerge(Join aJoin) { 224 Join origJoin = aJoin; 225 if (joinList == null) { 226 joinList = aJoin; 227 } else { 228 getTailJoin(joinList).next = aJoin; 229 addJoinImp(joinList, aJoin, origJoin); 230 } 231 } 232 233 private static Join getPrevJoin(Join joinList, Join aJoin) { 234 if (joinList.next == null) { 235 throw BindingSupportImpl.getInstance().internal(""); 236 } 237 238 for (Join j = joinList;;) { 239 if (j.next == aJoin) { 240 return j; 241 } 242 j = j.next; 243 if (j == null) return null; 244 } 245 } 246 247 private static Join getTailJoin(Join joinList) { 248 for (Join j = joinList;;) { 249 if (j.next == null) return j; 250 j = j.next; 251 } 252 } 253 254 private static void addJoinImp(Join currentJoin, Join aJoinToAdd, Join origJoin) { 255 Join j = currentJoin; 256 Join restartJoin = null; 257 Join stopJoin = getTailJoin(currentJoin); 258 for (;j != null;) { 259 if (aJoinToAdd == null) { 260 break; 261 } 262 if (Join.isCurrentEqaul(j, aJoinToAdd)) { 263 266 if (origJoin.selectExp.whereExp != null) { 267 origJoin.selectExp.whereExp.replaceSelectExpRef(origJoin.selectExp, 268 j.selectExp); 269 } 270 271 Join subCurrentJoin = j.selectExp.joinList; 272 Join subJoinToAdd = aJoinToAdd.selectExp.joinList; 273 274 if (subCurrentJoin == null && subJoinToAdd == null) { 275 } else if (subJoinToAdd == null) { 276 } else if (subCurrentJoin == null) { 277 j.selectExp.joinList = aJoinToAdd.selectExp.joinList; 279 ((JoinExp)aJoinToAdd.selectExp.joinList.exp).setLeftTable(j.selectExp); 280 } else { 281 addJoinImp(subJoinToAdd, subCurrentJoin, origJoin); 282 } 283 Join tmpJoin = aJoinToAdd.next; 284 287 getPrevJoin(currentJoin, aJoinToAdd).next = aJoinToAdd.next; 288 aJoinToAdd.next = null; 289 290 aJoinToAdd = tmpJoin; 291 j = j.next; 292 } else { 293 if (j.next == stopJoin) { 294 aJoinToAdd = aJoinToAdd.next; 296 j = restartJoin; 297 } else { 298 j = j.next; 299 } 300 } 301 302 } 303 } 304 305 308 public Join addJoin(JdbcColumn[] leftCols, JdbcColumn[] rightCols, 309 SelectExp right) { 310 if (Debug.DEBUG) { 311 System.out.println("SelectExp.addJoin from " + table.name + " to " + right.table.name); 312 String join = ""; 313 if (right.outer) { 314 join = "OUTER"; 315 } else { 316 join = "INNER"; 317 } 318 System.out.println("--- SelectExp.addJoin from " 319 + leftCols[0].table.name + " -- " + join + " --> " 320 + right.table.name); 321 } 322 Join j = new Join(); 323 j.exp = createJoinExp(leftCols, rightCols, right); 324 j.selectExp = right; 325 addJoin(j); 326 return j; 327 } 328 329 334 public Join findJoin(JdbcField jdbcField) { 335 for (Join j = joinList; j != null; j = j.next) { 336 if (j.selectExp.jdbcField == jdbcField) return j; 337 } 338 return null; 339 } 340 341 344 public Join findJoin(JdbcTable table, JdbcField jdbcField) { 345 for (Join j = joinList; j != null; j = j.next) { 346 if (j.selectExp.jdbcField == jdbcField 347 && j.selectExp.table == table) return j; 348 } 349 return null; 350 } 351 352 public SelectExp findTableRecursive(JdbcTable t, JdbcField field) { 353 if (t == table && jdbcField == field) return this; 354 for (Join j = joinList; j != null; j = j.next) { 355 if (j.selectExp.table == t && j.selectExp.jdbcField == field) return j.selectExp; 356 } 357 358 for (Join j = joinList; j != null; j = j.next) { 359 SelectExp se = j.selectExp.findTableRecursive(t, field); 360 if (se != null) return se; 361 } 362 return null; 363 } 364 365 370 public Join findJoinRec(JdbcField jdbcField) { 371 for (Join j = joinList; j != null; j = j.next) { 372 if (j.selectExp.jdbcField == jdbcField) return j; 373 Join ans = j.selectExp.findJoinRec(jdbcField); 374 if (ans != null) return ans; 375 } 376 return null; 377 } 378 379 383 public Join findJoin(SelectExp se) { 384 for (Join j = joinList; j != null; j = j.next) { 385 if (j.selectExp == se) return j; 386 } 387 return null; 388 } 389 390 395 public SelectExp findTable(JdbcTable t) { 396 if (t == table) { 397 return this; 398 } 399 for (Join j = joinList; j != null; j = j.next) { 400 if (j.selectExp.table == t) { 401 return j.selectExp; 402 } 403 } 404 return null; 405 } 406 407 public SelectExp findTableRecursive(JdbcTable t) { 408 if (t == table) return this; 409 for (Join j = joinList; j != null; j = j.next) { 410 if (j.selectExp.table == t) return j.selectExp; 411 } 412 413 for (Join j = joinList; j != null; j = j.next) { 414 SelectExp se = j.selectExp.findTable(t); 415 if (se != null) return se; 416 } 417 return null; 418 } 419 420 423 public SqlExp createJoinExp(JdbcColumn[] leftCols, 424 JdbcColumn[] rightCols, SelectExp right) { 425 if (leftCols.length == 1) { 426 return new JoinExp(leftCols[0], this, 427 rightCols[0], right); 428 } else { 429 JoinExp first = new JoinExp(leftCols[0], this, rightCols[0], right); 430 int nc = leftCols.length; 431 SqlExp j = first; 432 for (int i = 1; i < nc; i++) { 433 j = j.next = new JoinExp(leftCols[i], this, rightCols[i], right); 434 } 435 return new AndJoinExp(first); 436 } 437 } 438 439 public Join getLastJoin() { 440 for (Join j = joinList; j != null; j = j.next) { 441 if (j.next == null) { 442 return j; 443 } 444 } 445 return null; 446 } 447 448 452 public int createAlias(int index) { 453 if (alias == null) { 454 if (index < 26) { 455 alias = new String (new char[]{(char)(index + 'a')}); 456 } else { 457 alias = "t" + index; 458 } 459 ++index; 460 for (Join j = joinList; j != null; j = j.next) { 461 index = j.createAlias(index); 462 } 463 for (SqlExp e = whereExp; e != null; e = e.next) { 464 index = e.createAlias(index); 465 } 466 } 467 return index; 468 } 469 470 474 public void replaceSelectExpRef(SelectExp old, SelectExp nw) { 475 if (whereExp != null) whereExp.replaceSelectExpRef(old, nw); 476 if (subSelectJoinExp != null) subSelectJoinExp.replaceSelectExpRef(old, nw); 477 } 478 479 483 public SqlExp normalize(SqlDriver driver, SelectExp sel, boolean convertExists) { 484 for (Join j = joinList; j != null; j = j.next) { 485 SelectExp se = j.selectExp; 486 se.normalize(driver, sel, convertExists); 487 if (convertExists && se.whereExp != null) { 488 j.findDeepestJoin().appendJoinExp(se.whereExp); 489 se.whereExp = null; 490 } 491 } 492 493 if (whereExp == null) return null; 494 SqlExp r = whereExp.normalize(driver, this, convertExists); 495 if (r != null) whereExp = r; 496 497 int cj = whereExp.getConvertToJoin(); 498 if (cj == SqlExp.YES || (convertExists && cj >= SqlExp.YES_DISTINCT)) { 499 boolean not = convertExists && cj == SqlExp.YES_DISTINCT_NOT; 501 SelectExp sub; 502 if (not) { 503 sub = (SelectExp)(whereExp.childList.childList); 504 } else { 505 sub = (SelectExp)(whereExp.childList); 506 } 507 if ( sub != null ) { 508 Join j = new Join(); 509 j.selectExp = sub; 510 j.exp = sub.subSelectJoinExp; 511 sub.subSelectJoinExp = null; 512 if (sub.whereExp != null) { Join jj = j; 514 for (;;jj = jj.selectExp.joinList) { 515 if (jj.selectExp.joinList == null) break; 516 } 517 jj.appendJoinExp(sub.whereExp); 518 sub.whereExp = null; 519 } 520 addJoin(j); 521 } 522 if (not) { 523 sub.outer = true; 524 whereExp = sub.getOuterJoinNotMatchedExp(); 525 } else { 526 whereExp = null; 527 } 528 if (cj >= SqlExp.YES_DISTINCT) distinct = true; 529 return null; 530 } 531 return null; 532 } 533 534 541 public void appendSQLImp(SqlDriver driver, CharBuf s, SqlExp leftSibling) { 542 boolean putOrderColsInSelect = driver.isPutOrderColsInSelect(); 544 boolean selectListAppendedWithOrderByExp = false; 545 546 ColumnStruct[] orderByStruct = createColumnStruct(orderByList); 548 549 int start = s.size(); 550 if (distinct) s.append("SELECT DISTINCT "); 551 else s.append("SELECT "); 552 selectListStartIndex = s.size(); 553 int colCount = appendFirstSelect(selectList, driver, s); 554 colCount += appendSelect(joinList, driver, s); 555 if (Debug.DEBUG) { 556 if (colCount != getSelectListColumnCount()) { 557 throw BindingSupportImpl.getInstance().internal(""); 558 } 559 } 560 561 if (orderByList != null) { 562 if (putOrderColsInSelect || (groupByList != null && driver.putOrderColsInGroupBy())) { 563 selectListAppendedWithOrderByExp = appendSelectForOrderBy(orderByList, 564 driver, s, orderByStruct); 565 } 566 } 567 568 finishSelectList(s, start); 569 selectListEndIndex = s.size(); 570 571 s.append(" FROM "); 573 driver.appendSqlFrom(table, alias, s); 574 appendFrom(joinList, driver, s); 575 576 SqlExp list = new SqlExp(); 578 SqlExp pos = list; 579 if (subSelectJoinExp != null) pos = pos.next = subSelectJoinExp; 580 if (!driver.isAnsiJoinSyntax()) { 581 findWhereExp(findWhereJoinExp(pos)); 582 } else { 583 findWhereExp(pos); 584 } 585 586 SqlExp exp = merge(list.next); 588 if (exp != null) { 589 s.append(" WHERE "); 590 exp.appendSQL(driver, s, null); 591 } 592 593 exp = groupByList; 594 int gIndex = 1; 595 if (exp != null) { 596 boolean thisDone = false; 597 s.append(" GROUP BY "); 598 for (; ;) { 599 if (gIndex > 1) { 600 s.append(','); 601 s.append(' '); 602 } 603 if (exp instanceof GroupByThisExp) { 604 if (!thisDone) { 605 thisDone = true; 606 appendFirstSelect(selectList, driver, s, selectListCountBeforeAggregate); 607 appendSelect(joinList, driver, s); 608 } 609 } else { 610 ColumnExp ce; 614 if (exp instanceof ColumnExp) { 615 ce = (ColumnExp)exp; 616 } else { 617 ce = (ColumnExp)exp.childList; 618 } 619 620 if (ce.isAliasedColumn()) { 621 exp.appendSQL(driver, s, null); 622 } else if (driver.useColumnIndexForGroupBy()) { 623 int i = findIndexInSelectList(selectList, ce.selectExp, ce.col.name); 624 if (i >= 0) { 625 s.append(i); 626 } else { 627 exp.appendSQL(driver, s, null); 628 } 629 } else { 630 exp.appendSQL(driver, s, null); 631 } 632 } 633 gIndex++; 634 if ((exp = exp.next) == null) break; 635 } 636 } 637 638 if (selectListAppendedWithOrderByExp && groupByList != null) { 640 appendGroupBy(s, orderByStruct, gIndex == 1, driver); 641 } 642 643 exp = havingExp; 644 if (exp != null) { 645 havingExp.appendSQL(driver, s, null); 646 } 647 648 exp = orderByList; 650 if (exp != null) { 651 orderByStartIndex = s.size(); 652 s.append(" ORDER BY "); 653 if (driver.isUseIndexesForOrderCols()) { 654 int index = 1; 655 boolean first = true; 656 for (; ;) { 657 if (first) { 658 first = false; 659 } else { 660 s.append(','); 661 s.append(' '); 662 } 663 ColumnExp ce; 667 if (exp instanceof ColumnExp) { 668 ce = (ColumnExp)exp; 669 } else { 670 ce = (ColumnExp)exp.childList; 671 } 672 673 if (ce.isAliasedColumn()) { 674 exp.appendSQL(driver, s, null); 675 } else { 676 ColumnStruct colStruct = orderByStruct[index - 1]; 677 int i = colStruct.indexInSelectList; 678 if (i > 0) { 679 s.append(i); 680 if (ce != exp) { OrderExp oe = (OrderExp)exp; 682 if (oe.isDesc()) s.append(" DESC"); 683 } 684 } else { 685 if (colStruct.columnNme != null) { 687 if (driver.useColAliasForAddedCols()) { 688 s.append(colStruct.alias); 689 } else { 690 s.append(colStruct.columnNme); 691 } 692 693 if (ce != exp) { OrderExp oe = (OrderExp)exp; 695 if (oe.isDesc()) s.append(" DESC"); 696 } 697 } else { 698 exp.appendSQL(driver, s, null); 699 } 700 } 701 } 702 index++; 703 if ((exp = exp.next) == null) break; 704 } 705 } else { 706 int index = 1; 708 boolean first = true; 709 for (; exp != null; exp = exp.next) { 710 if (first) { 711 first = false; 712 } else { 713 s.append(','); 714 s.append(' '); 715 } 716 ColumnExp ce; 717 if (exp instanceof ColumnExp) { 718 ce = (ColumnExp)exp; 719 } else { 720 ce = (ColumnExp)exp.childList; 721 } 722 if (ce.isAliasedColumn()) { 723 exp.appendSQL(driver, s, null); 724 } else { 725 ColumnStruct colStruct = orderByStruct[index - 1]; 726 int i = colStruct.indexInSelectList; 727 if (i > 0) { 728 exp.appendSQL(driver, s, null); 729 } else { 730 if (selectListAppendedWithOrderByExp) { 731 if (driver.useColAliasForAddedCols()) { 732 s.append(colStruct.alias); 733 } else { 734 s.append(colStruct.columnNme); 735 } 736 if (ce != exp) { OrderExp oe = (OrderExp)exp; 738 if (oe.isDesc()) s.append(" DESC"); 739 } 740 } else { 741 exp.appendSQL(driver, s, null); 742 } 743 } 744 } 745 index++; 746 } 747 } 748 orderByEndIndex = s.size(); 749 } else { 750 orderByStartIndex = orderByEndIndex = 0; 751 } 752 753 if (forUpdate && (!distinct || driver.isSelectForUpdateWithDistinctOk())) { 754 char[] a = driver.getSelectForUpdate(); 755 if (a != null) { 756 s.append(a); 757 if (driver.isSelectForUpdateAppendTable()) { 758 if (alias == null) { 759 s.append(table.name); 760 } else { 761 s.append(alias); 762 } 763 } 764 } 765 } 766 } 767 768 772 private int findIndexInSelectList(SqlExp toSearch, SelectExp se, String name) { 773 int[] indexArray = new int[2]; 774 findIndexInSelectListImp(toSearch, se, name, indexArray); 775 776 if (indexArray[1] == 0) { 777 findIndexInJoin(joinList, se, name, indexArray); 779 } 780 781 if (indexArray[1] == 1) { 782 return indexArray[0] + 1; 783 } else { 784 return -1; 785 } 786 } 787 788 private void findIndexInJoin(Join j, SelectExp exp, String name, 789 int[] index) { 790 for (; j != null; j = j.next) { 791 SelectExp se = j.selectExp; 792 findIndexInSelectListImp(se.selectList, exp, name, index); 793 794 if (index[1] == 0) { 795 findIndexInJoin(se.joinList, exp, name, index); 796 } 797 break; 798 } 799 } 800 801 private void findIndexInSelectListImp(SqlExp se, SelectExp exp, 802 String name, int[] index) { 803 for (SqlExp e = se; e != null; e = e.next, index[0]++) { 804 if (e instanceof ColumnExp) { 805 ColumnExp ce = (ColumnExp)e; 806 if (ce.selectExp == exp && ce.col.name.equals(name)) { 807 index[1] = 1; 808 return; 809 } 810 } 811 } 812 } 813 814 private static boolean isDesc(SqlExp e) { 815 return e instanceof OrderExp && ((OrderExp)e).isDesc(); 816 } 817 818 821 protected void finishSelectList(CharBuf s, int start) { 822 int sz = s.size(); 823 int n = sz - start; 824 if (n <= 7) { 825 if (start == 0) { 826 throw BindingSupportImpl.getInstance().internal("no columns in select list"); 827 } 828 s.append('1'); 829 } else { 830 s.setSize(sz - 2); } 832 } 833 834 838 private int appendSelect(Join j, SqlDriver driver, CharBuf s) { 839 int count = 0; 840 for (; j != null; j = j.next) { 841 SelectExp se = j.selectExp; 842 count += appendSelect(se.selectList, driver, s); 843 count += appendSelect(se.joinList, driver, s); 844 } 845 return count; 846 } 847 848 851 private int countSelect(Join j) { 852 int count = 0; 853 for (; j != null; j = j.next) { 854 SelectExp se = j.selectExp; 855 count += countSelect(se.selectList); 856 count += countSelect(se.joinList); 857 } 858 return count; 859 } 860 861 865 private int appendFirstSelect(SqlExp e, SqlDriver driver, CharBuf s) { 866 if (e == null) return 0; 867 int count = 1; 868 e.appendSQL(driver, s, null); 869 selectListFirstColEndIndex = s.size(); 870 s.append(','); 871 s.append(' '); 872 for (e = e.next; e != null; e = e.next) { 873 e.appendSQL(driver, s, null); 874 s.append(','); 875 s.append(' '); 876 count++; 877 } 878 return count; 879 } 880 881 private void appendFirstSelect(SqlExp e, SqlDriver driver, CharBuf s, int columnCount) { 882 if (e == null) return; 883 e.appendSQL(driver, s, null); 884 selectListFirstColEndIndex = s.size(); 885 int count = 1; 886 for (e = e.next; e != null; e = e.next) { 887 if (count++ >= columnCount) break; 888 s.append(','); 889 s.append(' '); 890 e.appendSQL(driver, s, null); 891 } 892 } 893 894 898 private int appendSelect(SqlExp e, SqlDriver driver, CharBuf s) { 899 int count = 0; 900 for (; e != null; e = e.next) { 901 count++; 902 e.appendSQL(driver, s, null); 903 s.append(','); 904 s.append(' '); 905 } 906 return count; 907 } 908 909 private int countSelect(SqlExp e) { 910 int count = 0; 911 for (; e != null; e = e.next) { 912 count++; 913 } 914 return count; 915 } 916 917 923 private boolean appendSelectForOrderBy(SqlExp e, SqlDriver driver, 924 CharBuf s, ColumnStruct[] columnStructs) { 925 boolean appended = false; 926 int c = 1; 927 for (; e != null; e = e.next) { 928 ColumnStruct colStruct = columnStructs[c - 1]; 929 if (colStruct.indexInSelectList == -1) { 930 int offset = s.size(); 931 if (e instanceof OrderExp) { 932 e.childList.appendSQL(driver, s, null); 933 } else { 934 e.appendSQL(driver, s, null); 935 } 936 colStruct.columnNme = s.toString(offset, s.size() - offset); 937 colStruct.alias = ALIAS_PREPEND_CONSTANT + "j" + c; 938 939 s.append(driver.getAliasPrepend()); 941 s.append(colStruct.alias); 942 s.append(','); 943 s.append(' '); 944 appended = true; 945 } 946 c++; 947 } 948 return appended; 949 } 950 951 private ColumnStruct[] createColumnStruct(SqlExp e) { 952 SqlExp startExp = e; 953 int count = 0; 954 for (; e != null; e = e.next) { 955 count++; 956 } 957 if (count == 0) return EMPTY_COLUMS_STRUCT; 958 ColumnStruct[] colStructs = new ColumnStruct[count]; 959 count = 0; 960 e = startExp; 961 for (; e != null; e = e.next) { 962 ColumnExp ce; 963 if (e instanceof ColumnExp) { 964 ce = (ColumnExp)e; 965 } else { 966 ce = (ColumnExp)e.childList; 967 } 968 if (ce.isAliasedColumn()) { 969 colStructs[count++] = new ColumnStruct(0); 970 } else { 971 colStructs[count++] = new ColumnStruct(findIndexInSelectList(selectList, ce.selectExp, ce.col.name)); 972 } 973 974 } 975 return colStructs; 976 } 977 978 981 private class ColumnStruct { 982 985 String alias; 986 990 String columnNme; 991 994 int indexInSelectList; 995 996 public ColumnStruct(int indexInSelectList) { 997 this.indexInSelectList = indexInSelectList; 998 } 999 } 1000 1001 1006 private void appendGroupBy(CharBuf s, ColumnStruct[] columnStructs, 1007 boolean first, SqlDriver driver) { 1008 for (int i = 0; i < columnStructs.length; i++) { 1009 ColumnStruct columnStruct = columnStructs[i]; 1010 if (columnStruct.columnNme != null) { 1011 if (first) { 1012 first = false; 1013 } else { 1014 s.append(','); 1015 } 1016 if (driver.useColAliasForAddedCols()) { 1017 s.append(columnStruct.alias); 1018 } else { 1019 s.append(columnStruct.columnNme); 1020 } 1021 } 1022 } 1023 } 1024 1025 1029 private void appendFrom(Join j, SqlDriver driver, CharBuf s) { 1030 for (; j != null; j = j.next) { 1031 SelectExp se = j.selectExp; 1032 if (j.isMerged()) continue; 1033 driver.appendSqlFromJoin(se.table, se.alias, j.exp, se.outer, s); 1034 appendFrom(se.joinList, driver, s); 1035 } 1036 } 1037 1038 1042 private SqlExp findWhereExp(SqlExp list) { 1043 SqlExp e = whereExp; 1044 if (e != null) list = list.next = e; 1045 for (Join j = joinList; j != null; j = j.next) { 1046 list = j.selectExp.findWhereExp(list); 1047 } 1048 return list; 1049 } 1050 1051 1055 private SqlExp findWhereJoinExp(SqlExp list) { 1056 for (Join j = joinList; j != null; j = j.next) { 1057 SqlExp e = j.exp; 1058 if (e != null) list = list.next = e; 1059 list = j.selectExp.findWhereJoinExp(list); 1060 } 1061 return list; 1062 } 1063 1064 1068 private SqlExp merge(SqlExp first) { 1069 if (first == null) return null; 1070 if (first.next == null) return first; 1071 for (SqlExp pos = first; pos != null;) { 1074 SqlExp e = pos.next; 1075 if (e instanceof AndExp) { 1076 pos = pos.next = e.childList; 1077 SqlExp f = pos; 1078 for (; f.next != null; f = f.next) ; 1079 f.next = e.next; 1080 } else { 1081 pos = e; 1082 } 1083 } 1084 return new AndExp(first); 1085 } 1086 1087 1091 public void setOuterRec() { 1092 outer = true; 1093 for (Join j = joinList; j != null; j = j.next) { 1094 j.selectExp.setOuterRec(); 1095 } 1096 } 1097 1098 1103 public SqlExp getOuterJoinNotMatchedExp() { 1104 if (joinList == null) { 1105 return new IsNullExp(table.pk[0].toSqlExp(this)); 1106 } else if (joinList.next == null) { 1107 return joinList.selectExp.getOuterJoinNotMatchedExp(); 1108 } else { 1109 SqlExp root = joinList.selectExp.getOuterJoinNotMatchedExp(); 1111 SqlExp p = root; 1112 for (Join j = joinList.next; ;) { 1113 p = p.next = j.selectExp.getOuterJoinNotMatchedExp(); 1114 if ((j = j.next) == null) break; 1115 } 1116 return new OrExp(root); 1117 } 1118 } 1119 1120 1125 public SqlExp getOuterJoinMatchedExp() { 1126 if (joinList == null) { 1127 return new IsNotNullExp(table.pk[0].toSqlExp(this)); 1128 } else if (joinList.next == null) { 1129 return joinList.selectExp.getOuterJoinMatchedExp(); 1130 } else { 1131 SqlExp root = joinList.selectExp.getOuterJoinMatchedExp(); 1133 SqlExp p = root; 1134 for (Join j = joinList.next; ;) { 1135 p = p.next = j.selectExp.getOuterJoinMatchedExp(); 1136 if ((j = j.next) == null) break; 1137 } 1138 return new AndExp(root); 1139 } 1140 } 1141 1142 1145 public SqlExp addOrderBy(OrderNode[] orders, boolean append) { 1146 return addOrderBy(orders, append, JDOQLNodeToSqlExp.INSTANCE); 1147 } 1148 1149 1152 public SqlExp addOrderBy(OrderNode[] orders, boolean append, 1153 JDOQLNodeToSqlExp visitor) { 1154 int len = orders.length; 1156 SqlExp oePos = null; 1157 if (append) { 1158 oePos = findTailOrderByExp(); 1159 } 1160 for (int i = 0; i < len; i++) { 1161 OrderNode on = orders[i]; 1162 SelectExp se = this; 1163 Node prevNode = null; 1164 for (Node n = on.childList; n != null; n = n.childList) { 1165 if (n instanceof FieldNode) { 1166 SelectExp oSe = se; 1167 if (prevNode != null && prevNode instanceof FieldNavNode) { 1168 JdbcField refField = (JdbcField)((FieldNavNode)prevNode).fmd.storeField; 1169 JdbcField orderByField = (JdbcField)((FieldNode)n).fmd.storeField; 1170 1171 Join join = se.findJoin(orderByField.mainTable, refField); 1172 if (join == null) { 1173 oSe = new SelectExp(); 1174 oSe.table = orderByField.mainTable; 1175 oSe.outer = true; 1176 oSe.jdbcField = refField; 1177 1178 if (refField instanceof JdbcPolyRefField) { 1179 se.addJoin(((JdbcPolyRefField)refField).refCols, oSe.table.pk, oSe); 1180 } else { 1181 se.addJoin(refField.mainTableCols, oSe.table.pk, oSe); 1182 } 1183 1184 } else { 1185 oSe = join.selectExp; 1186 } 1187 1188 } else if (prevNode == null) { 1189 JdbcField orderByField = (JdbcField)((FieldNode)n).fmd.storeField; 1191 if (orderByField.mainTable != se.table) { 1192 oSe = se.findTable(orderByField.mainTable); 1193 if (oSe == null) { 1194 oSe = new SelectExp(); 1195 oSe.table = orderByField.mainTable; 1196 oSe.outer = false; 1197 se.addJoin(se.table.pk, oSe.table.pk, oSe); 1198 } 1199 } 1200 } 1201 1202 oePos = addOrderExp( 1203 handleOrderByFieldNode((FieldNode)n, oSe, visitor), 1204 (on.order == OrderNode.ORDER_DESCENDING), 1205 oePos); 1206 } else if (n instanceof AsValueNode) { 1207 oePos = addOrderExp(new ColumnExp(((AsValueNode)n).value), 1208 (on.order == OrderNode.ORDER_DESCENDING), 1209 oePos); 1210 } else if (n instanceof ReservedFieldNode) { 1211 ColumnExp[] cExps = createColumnExpForOrdering(((ReservedFieldNode)n).getTarget(), se); 1212 for (int j = 0; j < cExps.length; j++) { 1213 oePos = addOrderExp(cExps[j], 1214 (on.order == OrderNode.ORDER_DESCENDING), 1215 oePos); 1216 } 1217 } else if (n instanceof FieldNavNode) { 1218 se = handleOrderByFieldNavNode((FieldNavNode)n, se, prevNode); 1219 } else { 1220 throw BindingSupportImpl.getInstance().internal("Invalid node in orders: " + n); 1221 } 1222 prevNode = n; 1223 } 1224 } 1225 return oePos; 1226 } 1227 1228 1231 public void prependOrderByForColumns(JdbcColumn[] columns) { 1232 SqlExp current = orderByList; 1233 1234 SqlExp oePos = null; 1235 ColumnExp[] columnExps = new ColumnExp[columns.length]; 1236 for (int i = 0; i < columnExps.length; i++) { 1237 columnExps[i] = new ColumnExp(columns[i], this, null); 1238 oePos = addOrderExp(columnExps[i], false, oePos); 1239 } 1240 1241 if (current != null) { 1242 oePos.next = current; 1243 } 1244 } 1245 1246 1249 public void appendOrderByForColumns(JdbcColumn[] columns) { 1250 SqlExp oePos = findTailOrderByExp(); 1251 for (int i = 0; i < columns.length; i++) { 1252 if (containsOrderExp(columns[i])) { 1253 continue; 1254 } 1255 oePos = addOrderExp(new ColumnExp(columns[i], this, null), false, oePos); 1256 } 1257 } 1258 1259 1262 public void appendOrderByForColumns(JdbcColumn column) { 1263 SqlExp oePos = findTailOrderByExp(); 1264 if (!containsOrderExp(column)) { 1265 oePos = addOrderExp(new ColumnExp(column, this, null), false, oePos); 1266 } 1267 } 1268 1269 1270 1273 public void appendOrderByExp(SqlExp orderExp) { 1274 SqlExp oePos = findTailOrderByExp(); 1275 if (oePos == null) { 1276 orderByList = orderExp; 1277 } else { 1278 if (oePos != orderExp) { 1279 oePos.next = orderExp; 1280 } 1281 } 1282 } 1283 1284 1287 public void appendOrderByForColumns(JdbcColumn[] columns, SelectExp se) { 1288 SqlExp oePos = findTailOrderByExp(); 1289 for (int i = 0; i < columns.length; i++) { 1290 if (containsOrderExp(columns[i])) { 1291 continue; 1292 } 1293 oePos = addOrderExp(new ColumnExp(columns[i], se, null), false, oePos); 1294 } 1295 } 1296 1297 public boolean containsOrderExp(JdbcColumn jdbcColumn) { 1298 for (SqlExp e = orderByList; e != null; e = e.next) { 1299 if (((ColumnExp)((OrderExp)e).childList).col == jdbcColumn) return true; 1300 } 1301 return false; 1302 } 1303 1304 1307 private SqlExp findTailOrderByExp() { 1308 for (SqlExp e = orderByList; e != null; e = e.next) { 1309 if (e.next == null) return e; 1310 } 1311 return null; 1312 } 1313 1314 public ColumnExp[] createColumnExpForOrdering(ClassMetaData target, 1315 SelectExp root) { 1316 JdbcColumn[] pk = ((JdbcClass)target.storeClass).table.pk; 1317 ColumnExp[] columnExps = new ColumnExp[pk.length]; 1318 for (int i = 0; i < pk.length; i++) { 1319 columnExps[i] = new ColumnExp(pk[i], root, pk[i].refField); 1320 } 1321 return columnExps; 1322 } 1323 1324 private SqlExp addOrderExp(SqlExp list, boolean desc, SqlExp oePos) { 1325 OrderExp oe = new OrderExp(list, desc); 1327 if (oePos == null) { 1328 orderByList = oe; 1329 } else { 1330 oePos.next = oe; 1331 } 1332 oePos = oe; 1333 return oePos; 1334 } 1335 1336 1339 private SelectExp handleOrderByFieldNavNode(FieldNavNode nav, SelectExp se, Node prevNode) { 1340 if (prevNode != null && prevNode instanceof FieldNavNode) { 1341 JdbcField f = (JdbcField)((FieldNavNode)prevNode).fmd.storeField; 1344 Join j = se.findJoin(f); 1345 if (j != null) return j.selectExp; 1346 1347 SelectExp next = new SelectExp(); 1349 next.jdbcField = f; 1350 ClassMetaData targetClass = ((FieldNavNode)prevNode).targetClass; 1351 next.table = ((JdbcClass)targetClass.storeClass).table; 1352 if (f instanceof JdbcPolyRefField) { 1353 se.addJoin(((JdbcPolyRefField)f).refCols, next.table.pk, next); 1354 } else { 1355 se.addJoin(f.mainTableCols, next.table.pk, next); 1356 } 1357 next.outer = f.fmd.nullValue != MDStatics.NULL_VALUE_EXCEPTION; 1358 return next; 1359 } else { 1360 return se; 1361 } 1362 } 1363 1364 private SqlExp handleOrderByFieldNode(FieldNode fn, SelectExp se, 1365 JDOQLNodeToSqlExp visitor) { 1366 if (!(fn.fmd.storeField instanceof JdbcSimpleField)) { 1367 throw BindingSupportImpl.getInstance().internal( 1368 "Only simple fields may be used in an " + 1369 "ordering statement: " + fn.fmd); 1370 } 1371 SqlExp list = visitor.toSqlExp(fn, se, null, 0, null); 1372 if (list.childList != null) { 1373 throw BindingSupportImpl.getInstance().internal( 1374 "Only single column fields may be used in an " + 1375 "ordering statement: " + fn.fmd); 1376 } 1377 return list; 1378 } 1379 1380 1385 public boolean isJoinToManyTable() { 1386 return jdbcField instanceof JdbcCollectionField; 1387 } 1388 1389 1393 public void appendToWhereExp(SqlExp e) { 1394 whereExp = SqlExp.appendWithAnd(whereExp, e); 1395 } 1396 1397 1401 public void appendToSubSelectJoinExp(SqlExp e) { 1402 subSelectJoinExp = SqlExp.appendWithAnd(subSelectJoinExp, e); 1403 } 1404 1405 1409 public static SelectExp createJoinToSuperTable(SelectExp root, JdbcField jdbcField) { 1410 return createJoinToSuperTable(root, ((JdbcClass)jdbcField.fmd.classMetaData.storeClass).table); 1411 } 1412 1413 1417 public static SelectExp createJoinToSuperTable(SelectExp root, SelectExp joinFromExp, 1418 JdbcColumn[] lJoinColumns, JdbcField jdbcField) { 1419 if (Debug.DEBUG) { 1420 JdbcRefField.isSubTableOf(root.table, jdbcField.fmd.classMetaData); 1421 } 1422 if (root.table != ((JdbcClass)jdbcField.fmd.classMetaData.storeClass).table) { 1423 Join join = joinFromExp.findJoin(jdbcField); 1424 if (join == null) { 1425 SelectExp se = new SelectExp(); 1426 se.outer = root.outer; 1427 se.table = ((JdbcClass)jdbcField.fmd.classMetaData.storeClass).table; 1428 joinFromExp.addJoin(lJoinColumns, se.table.pk, se); 1429 return se; 1430 } else { 1431 return join.selectExp; 1432 } 1433 } 1434 return root; 1435 } 1436 1437 1441 public static SelectExp createJoinToSuperTable(SelectExp root, JdbcTable table) { 1442 SelectExp se = (SelectExp)root.findTable(table); 1444 if (se == null) { 1445 se = new SelectExp(); 1446 se.outer = root.outer; 1447 se.table = table; 1448 root.addJoin(root.table.pk, se.table.pk, se); 1449 } 1450 return se; 1451 } 1452 1453 public static void dumpJoinList(SelectExp joinFromExp, String val) { 1454 System.out.println(val + "dumping joinlist"); 1455 Join j = joinFromExp.joinList; 1456 if (j == null) { 1457 System.out.println("-- no joins "); 1458 return; 1459 } 1460 for (;;) { 1461 System.out.println("j = " + j); 1462 j = j.next; 1463 if (j == null) break; 1464 } 1465 } 1466 1467 public static void dumpJoinListRec(SelectExp joinFromExp, String indent) { 1468 Join j = joinFromExp.joinList; 1469 if (j == null) { 1470 return; 1472 } 1473 for (;;) { 1474 System.out.println(indent + j); 1475 dumpJoinListRec(j.selectExp, indent + " "); 1476 j = j.next; 1477 if (j == null) break; 1478 } 1479 } 1480 1481 public static void mergeJoinList(Join j) { 1482 if (j == null) return; 1483 if (j.next == null) return; 1484 1485 for (Join nextJoin = j.next; nextJoin != null; nextJoin = nextJoin.next) { 1486 if (nextJoin.isMerged()) { 1487 continue; 1488 } 1489 if (Join.isCurrentEqaul(j, nextJoin)) { 1490 nextJoin.setMergedWith(j); 1491 continue; 1492 } 1493 } 1494 mergeJoinList(j.selectExp.joinList); 1495 mergeJoinList(j.next); 1496 } 1497 1498} 1499 | Popular Tags |