1 2 12 package com.versant.core.jdbc.query; 13 14 import com.versant.core.common.Debug; 15 import com.versant.core.jdo.QueryDetails; 16 import com.versant.core.common.CmdBitSet; 17 import com.versant.core.metadata.*; 18 import com.versant.core.jdo.query.*; 19 import com.versant.core.jdbc.FgDs; 20 import com.versant.core.jdbc.JdbcStorageManager; 21 import com.versant.core.jdbc.ProjectionQueryDecoder; 22 import com.versant.core.jdbc.metadata.JdbcClass; 23 import com.versant.core.jdbc.metadata.JdbcColumn; 24 import com.versant.core.jdbc.metadata.JdbcField; 25 import com.versant.core.jdbc.metadata.JdbcFetchGroup; 26 import com.versant.core.jdbc.sql.SqlDriver; 27 import com.versant.core.jdbc.sql.exp.*; 28 29 import com.versant.core.common.BindingSupportImpl; 30 31 37 public final class JdbcJDOQLCompiler { 38 39 private final JdbcStorageManager sm; 40 private final ModelMetaData jmd; 41 private final JDOQLNodeToSqlExp visitor; 42 43 private ClassMetaData cmd; 45 private ParamNode[] params; 46 private OrderNode[] orders; 47 private UnaryNode filter; 48 private ResultNode resultNode; 49 private GroupingNode groupingNode; 50 private QueryParser qParser; 51 private SelectExp candidateSelectExp; 52 53 public JdbcJDOQLCompiler(JdbcStorageManager sm) { 54 this.sm = sm; 55 this.jmd = sm.getJmd(); 56 visitor = new JDOQLNodeToSqlExp(this); 57 } 58 59 63 public void reinit() { 64 cmd = null; 65 params = null; 66 orders = null; 67 filter = null; 68 qParser = null; 69 resultNode = null; 70 groupingNode = null; 71 candidateSelectExp = null; 72 } 73 74 public QueryParser getQParser() { 75 return qParser; 76 } 77 78 public JDOQLNodeToSqlExp getVisitor() { 79 return visitor; 80 } 81 82 85 public JdbcCompiledQuery compile(QueryDetails q) { 86 87 cmd = jmd.getClassMetaData(q.getCandidateClass()); 88 if (cmd == null) { 89 throw BindingSupportImpl.getInstance().invalidOperation( 90 "Class " + 91 q.getCandidateClass().getName() + " not found in meta data"); 92 } 93 94 return compileImp(q); 95 } 96 97 100 public SqlExp compileParallelFetch(QueryDetails q) { 101 cmd = jmd.getClassMetaData(q.getCandidateClass()); 102 if (cmd == null) { 103 throw BindingSupportImpl.getInstance().invalidOperation( 104 "Class " + 105 q.getCandidateClass().getName() + " not found in meta data"); 106 } 107 return compileParallelFetchImp(q); 108 } 109 110 private JdbcCompiledQuery compileImp(QueryDetails q) { 111 JdbcCompiledQuery cq = new JdbcCompiledQuery(cmd, q); 112 113 qParser = new QueryParser(jmd); 114 115 try { 116 qParser.parse(q); 117 118 resolveVarNodes(qParser); 119 params = qParser.getParams(); 120 orders = qParser.getOrders(); 121 filter = qParser.getFilter(); 122 resultNode = qParser.getResultNode(); 123 groupingNode = qParser.getGroupingNode(); 124 } catch (Exception e) { 125 if (BindingSupportImpl.getInstance().isOwnException(e)) { 126 throw (RuntimeException )e; 127 } else { 128 throw BindingSupportImpl.getInstance().invalidOperation(e.getMessage(), e); 129 } 130 } catch (TokenMgrError e) { 131 throw BindingSupportImpl.getInstance().invalidOperation(e.getMessage(), e); 132 } 133 134 candidateSelectExp = new SelectExp(); 136 JdbcClass jdbcClass = (JdbcClass)cmd.storeClass; 137 candidateSelectExp.table = jdbcClass.table; 138 139 FetchGroup fg = cmd.fetchGroups[q.getFetchGroupIndex()]; 140 141 for (FetchGroup supg = fg.superFetchGroup; supg != null; 143 supg = supg.superFetchGroup) { 144 JdbcClass sc = (JdbcClass)supg.classMetaData.storeClass; 145 146 if (sc.table != candidateSelectExp.table) { 147 SelectExp se = candidateSelectExp.findTable(sc.table); 149 if (se == null) { 150 se = new SelectExp(); 151 se.table = sc.table; 152 candidateSelectExp.addJoin(candidateSelectExp.table.pk, 153 se.table.pk, se); 154 } 155 } 156 } 157 158 if (filter != null) { 159 candidateSelectExp.whereExp = visitor.toSqlExp(filter, 160 candidateSelectExp, null, 0, null); 161 } 164 165 if (cmd.isInHeirachy()) addSubclassFilter(candidateSelectExp, cq); 167 168 if (Debug.DEBUG) { 169 Debug.OUT.println("\n* SQL tree:"); 170 candidateSelectExp.dump(""); 171 } 172 173 SqlDriver driver = sm.getSqlDriver(); 174 175 176 FgDs fgDs = cq.fgDs = ((JdbcFetchGroup)fg.storeFetchGroup).getFgDs(cq.isIncludeSubclasses(), false); 177 SqlExp orderByFromCrossJoin = null; 178 if (resultNode == null) { 179 candidateSelectExp.normalize(driver, null, driver.isConvertExistsToDistinctJoin()); 180 if (Debug.DEBUG) { 181 Debug.OUT.println("\n* Normalized SQL tree:"); 182 candidateSelectExp.dump(""); 183 } 184 185 cq.process(); 186 sm.addSelectFetchGroup(candidateSelectExp, 188 fg, cq.isIncludeSubclasses(), fgDs, cq.isCrossJoinAllowed()); 189 190 addPrimaryKey(candidateSelectExp); 191 192 cq.setSelectColumnCount( 193 candidateSelectExp.getSelectListColumnCount()); 194 orderByFromCrossJoin = candidateSelectExp.orderByList; 195 candidateSelectExp.orderByList = null; 196 } else { 197 processNode(resultNode, "Result"); 198 processNode(groupingNode, "Grouping"); 199 if (groupingNode != null && groupingNode.havingNode != null) { 200 processNode(groupingNode.havingNode, "Having"); 201 } 202 ProjectionQueryDecoder decoder = new ProjectionQueryDecoder(resultNode, driver); 203 204 cq.setProjectionDecoder(decoder); 205 cq.setGroupingNode(groupingNode); 206 cq.process(); 207 208 215 216 boolean convertExistBecauseOfVarInProjection = resultNode.processForVarNodes(); 217 candidateSelectExp.normalize(driver, null, convertExistBecauseOfVarInProjection 218 || driver.isConvertExistsToDistinctJoin()); 219 220 if (resultNode.isDistinct()) { 221 candidateSelectExp.distinct = true; 222 } 223 224 if (Debug.DEBUG) { 225 Debug.OUT.println("\n* Normalized SQL tree:"); 226 candidateSelectExp.dump(""); 227 } 228 229 if (decoder.containsThis()) { 230 SqlExp tail = sm.addSelectFetchGroup(candidateSelectExp, 231 fg, cq.isIncludeSubclasses(), fgDs, false); 232 addPrimaryKey(candidateSelectExp); 233 cq.setSelectColumnCount(candidateSelectExp.selectListCountBeforeAggregate 234 = candidateSelectExp.getSelectListColumnCount()); 235 tail.next = visitor.toSqlExp(resultNode, candidateSelectExp, null, 236 0, null); 237 } else { 238 candidateSelectExp.selectList = visitor.toSqlExp(resultNode, 239 candidateSelectExp, null, 0, null); 240 } 241 242 } 243 244 candidateSelectExp.groupByList = getGroupingExp(); 245 if (groupingNode != null) { 246 if (groupingNode.havingNode == null) { 247 candidateSelectExp.havingExp = null; 248 } else { 249 candidateSelectExp.havingExp = new HavingExp(visitor.toSqlExp( 250 groupingNode.havingNode, candidateSelectExp, null, 0, 251 null)); 252 } 253 } 254 255 reOrderJoinExp(cmd.fetchGroups[q.getFetchGroupIndex()], candidateSelectExp); 256 257 if (orders != null) { 259 addOrderBy(candidateSelectExp); 260 } 261 262 if (Debug.DEBUG) { 263 Debug.OUT.println("\n* Finished SQL tree:"); 264 candidateSelectExp.dump(""); 265 } 266 267 271 if (cq.isContainsThis()) { 272 if (cq.isParColFetchEnabled() || cq.isCrossJoinAllowed()) { 273 candidateSelectExp.appendOrderByForColumns(((JdbcClass)cmd.storeClass).table.pk); 274 } 275 } 276 277 280 if (orderByFromCrossJoin != null) { 281 candidateSelectExp.appendOrderByExp(orderByFromCrossJoin); 282 } 283 284 SelectExp.mergeJoinList(candidateSelectExp.joinList); 286 287 doFinalSql(cq.getSqlStruct(), candidateSelectExp, driver); 288 289 if (params != null) compileParams(qParser, cq.getSqlStruct()); 291 292 if (Debug.DEBUG) { 293 Debug.OUT.println("\nParams:"); 294 dumpParams(cq, cq.getParamList()); 295 } 296 297 final CmdBitSet bits = qParser.getCmds(); 298 int[] a = q.getExtraEvictClasses(); 299 if (a != null) { 300 for (int i = a.length - 1; i >= 0; i--) { 301 bits.add(jmd.classes[a[i]]); 302 } 303 } 304 cq.setFilterClsIndexs(bits.toArray()); 305 cq.setCacheable(bits.isCacheble() && !q.isRandomAccess()); 306 cq.setEvictionClassBits(bits.getBits()); 307 cq.setEvictionClassIndexes(bits.getIndexes()); 308 return cq; 309 } 310 311 314 private void resolveVarNodes(QueryParser qParser) { 315 VarNode[] vars = qParser.getVars(); 316 if (vars == null || vars.length == 0) { 317 return; 318 } 319 for (int i = 0; i < vars.length; i++) { 320 VarNode var = vars[i]; 321 ClassMetaData vcmd = var.getCmd(); 322 if (vcmd == null) { 323 continue; 324 } 325 SelectExp se = new SelectExp(); 326 se.table = ((JdbcClass)vcmd.storeClass).table; 327 se.var = var; 328 if (vcmd.pcSuperMetaData != null) { 329 se.whereExp = 332 ((JdbcClass)vcmd.storeClass).getCheckClassIdExp(se); 333 } 334 var.setStoreExtent(se); 335 } 336 } 337 338 public static void reOrderJoinExp(FetchGroup fg, SelectExp se) { 339 Join current = se.joinList; 340 FetchGroupField[] fgfs = fg.fields; 341 for (int i = 0; i < fgfs.length; i++) { 342 FetchGroupField fgf = fgfs[i]; 343 344 if (fgf.fmd.category != MDStatics.CATEGORY_REF) continue; 345 Join join = se.findJoin((JdbcField)fgf.fmd.storeField); 346 if (join != null) { 347 if (join == current) { 348 current = current.next; 349 } else { 350 Join beforeToMove = findJoinBefore(join, 351 se.joinList); 352 Join beforeCurrent = findJoinBefore(current, 353 se.joinList); 354 355 if (beforeToMove.next != join) { 356 throw new RuntimeException ("before.next != join"); 357 } 358 359 beforeToMove.next = join.next; 360 join.next = current; 361 if (beforeCurrent != null) beforeCurrent.next = join; 362 if (current == se.joinList) { 363 se.joinList = join; 364 } 365 } 366 } 367 } 368 } 369 370 private SqlExp getGroupingExp() { 371 SqlExp gpExp = null; 372 if (groupingNode != null) { 373 gpExp = visitor.toSqlExp(groupingNode, candidateSelectExp, null, 0, 374 null); 375 } 376 return gpExp; 377 } 378 379 private void processNode(Node node, String info) { 380 if (node == null) return; 381 if (Debug.DEBUG) { 382 Debug.OUT.println("\n* " + info + ": " + node); 383 Debug.OUT.println("\n* Parsed tree:"); 384 node.dump(""); 385 } 386 387 node.normalize(); 388 if (Debug.DEBUG) { 389 Debug.OUT.println("\n* Normalized tree:"); 390 node.dump(""); 391 } 392 393 node.resolve(qParser, cmd, false); 394 if (Debug.DEBUG) { 395 Debug.OUT.println("\n* Resolved tree:"); 396 node.dump(""); 397 } 398 399 node.normalize(); 400 if (Debug.DEBUG) { 401 Debug.OUT.println("\n* Second normalized tree:"); 402 node.dump(""); 403 } 404 } 405 406 private SqlExp compileParallelFetchImp(QueryDetails q) { 407 JdbcCompiledQuery cq = new JdbcCompiledQuery(cmd, q); 408 qParser = new QueryParser(jmd); 409 410 try { 411 qParser.parse(q); 412 resolveVarNodes(qParser); 413 params = qParser.getParams(); 414 orders = qParser.getOrders(); 415 filter = qParser.getFilter(); 416 } catch (Exception e) { 417 if( BindingSupportImpl.getInstance().isOwnException(e) ) 418 { 419 throw (RuntimeException ) e; 420 } 421 else 422 { 423 throw BindingSupportImpl.getInstance().invalidOperation(e.getMessage(), e); 424 } 425 } catch (TokenMgrError e) { 426 throw BindingSupportImpl.getInstance().invalidOperation(e.getMessage(), e); 427 } 428 429 if (filter != null) { 430 filter.normalize(); 431 if (Debug.DEBUG) { 432 Debug.OUT.println("\n* Normalized tree:"); 433 filter.dump(""); 434 } 435 } 436 437 candidateSelectExp = new SelectExp(); 439 JdbcClass jdbcClass = (JdbcClass)cmd.storeClass; 440 candidateSelectExp.table = jdbcClass.table; 441 442 FetchGroup fg = cmd.fetchGroups[q.getFetchGroupIndex()]; 443 for (FetchGroup supg = fg.superFetchGroup; supg != null; 445 supg = supg.superFetchGroup) { 446 JdbcClass sc = (JdbcClass)supg.classMetaData.storeClass; 447 448 if (sc.table != candidateSelectExp.table) { 449 SelectExp se = candidateSelectExp.findTable(sc.table); 451 if (se == null) { 452 se = new SelectExp(); 453 se.table = sc.table; 454 candidateSelectExp.addJoin(candidateSelectExp.table.pk, 455 se.table.pk, se); 456 } 457 } 458 } 459 460 if (filter != null) { 461 candidateSelectExp.whereExp = visitor.toSqlExp(filter, 462 candidateSelectExp, null, 0, null); 463 } 464 465 if (cmd.isInHeirachy()) addSubclassFilter(candidateSelectExp, cq); 467 468 if (Debug.DEBUG) { 469 Debug.OUT.println("\n* SQL tree:"); 470 candidateSelectExp.dump(""); 471 } 472 473 SqlDriver driver = sm.getSqlDriver(); 474 candidateSelectExp.normalize(driver, null, driver.isConvertExistsToDistinctJoin()); 475 if (Debug.DEBUG) { 476 Debug.OUT.println("\n* Normalized SQL tree:"); 477 candidateSelectExp.dump(""); 478 } 479 480 reOrderJoinExp(cmd.fetchGroups[q.getFetchGroupIndex()], candidateSelectExp); 481 482 if (orders != null) { 484 addOrderBy(candidateSelectExp); 485 } 486 487 if (Debug.DEBUG) { 488 Debug.OUT.println("\n* Finished SQL tree:"); 489 candidateSelectExp.dump(""); 490 } 491 492 candidateSelectExp.appendOrderByForColumns(((JdbcClass)cmd.storeClass).table.pk); 493 494 if (Debug.DEBUG) { 495 Debug.OUT.println("\nSQL:\n" + cq.getSqlbuf()); 496 } 497 return candidateSelectExp; 498 } 499 500 public static void doFinalSql(SqlStruct sqlStruct, SelectExp root, 501 SqlDriver driver) { 502 int aliasCount = root.createAlias(0); 504 if (aliasCount == 1) { 505 root.alias = null; 506 sqlStruct.setFirstTableOrAlias(root.table.name); 507 } else { 508 sqlStruct.setFirstTableOrAlias(root.alias); 509 } 510 511 root.appendSQL(driver, sqlStruct.getSqlbuf(), null); 512 sqlStruct.setSelectListRange(root.distinct, root.selectListStartIndex, 513 root.selectListFirstColEndIndex, root.selectListEndIndex); 514 sqlStruct.setOrderByRange(root.orderByStartIndex, root.orderByEndIndex); 515 516 sqlStruct.getSqlbuf().append(' '); 518 519 if (Debug.DEBUG) { 520 System.out.println("\nSQL:\n" + sqlStruct.getSqlbuf()); 521 } 522 } 523 524 public static Join findJoinBefore(Join aJoin, Join root) { 525 for (Join join = root; join != null; join = join.next) { 526 if (join.next == aJoin) return join; 527 } 528 return null; 529 } 530 531 private void addSubclassFilter(SelectExp root, JdbcCompiledQuery cq) { 532 if (((JdbcClass)cmd.storeClass).classIdCol != null) { 534 if (cq.isIncludeSubclasses() && cmd.pcSuperMetaData == null) return; 535 if (cq.isIncludeSubclasses() 536 && ((JdbcClass)cmd.storeClass).inheritance == JdbcClass.INHERITANCE_VERTICAL) { 537 return; 538 } 539 addClassIdFilter(root, cq); 540 } else { 541 if (!cq.isIncludeSubclasses()) { 542 if (cmd.pcSubclasses == null) return; 543 for (int i = 0; i < cmd.pcSubclasses.length; i++) { 545 ClassMetaData pcSubclass = cmd.pcSubclasses[i]; 546 547 SelectExp se = root.findTable(((JdbcClass)pcSubclass.storeClass).table); 548 if (se == null) { 549 se = new SelectExp(); 550 se.outer = true; 551 se.table = ((JdbcClass)pcSubclass.storeClass).table; 552 553 SqlExp colExp = ((JdbcClass)pcSubclass.storeClass).table.pk[0].toSqlExp(se); 554 555 root.appendToWhereExp(new IsNullExp(colExp)); 556 root.addJoin(root.table.pk, se.table.pk, se); 557 } 558 } 559 } 560 } 561 562 } 563 564 private void addClassIdFilter(SelectExp root, JdbcCompiledQuery cq) { 565 JdbcColumn cidcol = ((JdbcClass)cmd.storeClass).classIdCol; 567 SelectExp se = root.findTable(cidcol.table); 568 if (se == null) { 569 throw BindingSupportImpl.getInstance().invalidOperation( 570 "Table for classId column not in SelectExp"); 571 } 572 SqlExp cidexp = cidcol.toSqlExp(se); 573 if (cidexp.next != null) { 574 throw BindingSupportImpl.getInstance().invalidOperation( 575 "Compound classId columns not implemented"); 576 } 577 578 SqlExp fe; 579 if (!cq.isIncludeSubclasses() || cmd.pcSubclasses == null) { 580 fe = new BinaryOpExp(cidexp, BinaryOpExp.EQUAL, 582 cidcol.createClassIdLiteralExp(((JdbcClass)cmd.storeClass).jdbcClassId)); 583 } else { 584 cidexp.next = createClassIdLiteralExp(cmd); 586 fe = new InExp(cidexp); 587 } 588 589 if (root.whereExp == null) { 591 root.whereExp = fe; 592 } else if (root.whereExp instanceof AndExp) { 593 root.whereExp.append(fe); 594 } else { 595 root.whereExp.next = fe; 596 root.whereExp = new AndExp(root.whereExp); 597 } 598 } 599 600 604 private SqlExp createClassIdLiteralExp(ClassMetaData cmd) { 605 SqlExp e = ((JdbcClass)cmd.storeClass).classIdCol.createClassIdLiteralExp( 606 ((JdbcClass)cmd.storeClass).jdbcClassId); 607 ClassMetaData[] a = cmd.pcSubclasses; 608 if (a != null) { 609 SqlExp p = e; 610 for (int i = a.length - 1; i >= 0; i--) { 611 SqlExp q = createClassIdLiteralExp(a[i]); 612 for (; p.next != null; p = p.next) ; 613 p = p.next = q; 614 } 615 } 616 return e; 617 } 618 619 private SqlExp addOrderBy(SelectExp root) { 620 int len = orders.length; 621 for (int i = 0; i < len; i++) orders[i].resolve(qParser, cmd, true); 622 return root.addOrderBy(orders, false, visitor); 623 } 624 625 private void addPrimaryKey(SelectExp root) { 626 JdbcColumn[] pk = root.table.pkSimpleCols; 627 ColumnExp list = new ColumnExp(pk[0], root, null); 628 SqlExp pos = list; 629 int n = pk.length; 630 for (int i = 1; i < n; i++) { 631 pos = pos.next = new ColumnExp(pk[i], root, 632 null); 633 } 634 pos.next = root.selectList; 635 root.selectList = list; 636 } 637 638 644 public static void compileParams(QueryParser qParser, SqlStruct sqlStruct) { 645 if (qParser.getParams() == null) return; 646 SqlStruct.Param list = null; 647 SqlStruct.Param pos = null; 648 ParamNode[] params = qParser.getParams(); 649 int np = params.length; 650 for (int i = 0; i < np; i++) { 651 ParamNode p = params[i]; 652 SqlParamUsage usage = (SqlParamUsage)p.usageList; 653 if (usage == null) continue; 654 655 for (; usage != null; usage = usage.next) { 656 657 SqlStruct.Param param = new SqlStruct.Param(p.getIdentifier()); 659 if (pos == null) { 660 pos = list = param; 661 } else { 662 pos = pos.next = param; 663 } 664 665 param.declaredParamIndex = i; 667 JdbcField jdbcField = usage.jdbcField; 668 if (jdbcField == null) { 669 param.classIndex = usage.classIndex; 670 param.fieldNo = -1; 671 param.javaTypeCode = usage.javaTypeCode; 672 if (param.javaTypeCode == 0) { 673 p.resolve(qParser, null, false); 674 param.javaTypeCode = MDStaticUtils.toTypeCode( 675 p.getCls()); 676 } 677 param.jdbcType = usage.jdbcType; 678 param.col = usage.col; 679 } else { 680 param.classIndex = jdbcField.fmd.classMetaData.index; 681 param.fieldNo = jdbcField.stateFieldNo; 682 param.col = usage.col; 683 } 684 param.mod = usage.mod; 685 686 if (usage.expCount > 0) { 688 SqlStruct.CharSpan cspos = null; 689 SqlStruct.CharSpan[] a 690 = new SqlStruct.CharSpan[usage.expCount]; 691 boolean multicol = usage.expCount > 1; 692 int j = 0; 693 int removeCount = 0; 694 for (SqlExp e = usage.expList; j < a.length; j++) { 695 SqlStruct.CharSpan cs = a[j] = 696 new SqlStruct.CharSpan(); 697 if (multicol && mustBeRemovedIfNull(e)) { 698 if (++removeCount == a.length) { 699 multicol = false; 702 e = usage.expList; 703 j = -1; 704 cspos = null; 705 continue; 706 } 707 cs.firstCharIndex = e.getPreFirstCharIndex(); 708 if (e.next == null) { cs.lastCharIndex = e.getLastCharIndex(); 710 for (int k = j - 1; k >= 0; k--) { 712 if (a[k].type != SqlStruct.CharSpan.TYPE_REMOVE) { 713 a[k + 1].firstCharIndex -= 4; break; 715 } 716 } 717 } else { cs.lastCharIndex = e.next.getPreFirstCharIndex(); 719 } 720 cs.type = SqlStruct.CharSpan.TYPE_REMOVE; 721 } else { 722 cs.firstCharIndex = e.getFirstCharIndex(); 723 cs.lastCharIndex = e.getLastCharIndex(); 724 cs.type = e.isNegative() 725 ? SqlStruct.CharSpan.TYPE_NOT_NULL 726 : SqlStruct.CharSpan.TYPE_NULL; 727 } 728 729 if (cspos == null) { 730 cspos = param.charSpanList = cs; 731 param.firstCharIndex = cs.firstCharIndex; 732 } else { 733 cspos = cspos.next = cs; 734 } 735 736 e = e.next; 737 } 738 } else { 739 param.firstCharIndex = usage.expList.getFirstCharIndex(); 740 } 741 } 742 } 743 if (list != null) sqlStruct.setParamList(sortParams(list)); 744 } 745 746 750 private static boolean mustBeRemovedIfNull(SqlExp e) { 751 if (!e.isNegative() && e.childList instanceof ColumnExp) { 752 ColumnExp ce = (ColumnExp)e.childList; 753 return !ce.col.isForUpdate(); 754 } 755 return false; 756 } 757 758 761 private static SqlStruct.Param sortParams(SqlStruct.Param list) { 762 if (list.next == null) return list; 763 for (; ;) { 765 boolean changed = false; 766 SqlStruct.Param p0 = null; 767 for (SqlStruct.Param p1 = list; ;) { 768 SqlStruct.Param p2 = p1.next; 769 if (p2 == null) break; 770 if (p1.firstCharIndex > p2.firstCharIndex) { 771 p1.next = p2.next; 773 p2.next = p1; 774 if (p0 == null) { 775 list = p2; 776 } else { 777 p0.next = p2; 778 } 779 p0 = p2; 780 changed = true; 781 } else { 782 p0 = p1; 783 p1 = p2; 784 } 785 } 786 if (!changed) return list; 787 } 788 } 789 790 private void dumpParams(JdbcCompiledQuery cq, SqlStruct.Param p) { 791 for (; p != null; p = p.next) { 792 if (Debug.DEBUG) { 793 Debug.OUT.println("Param " + p.declaredParamIndex + 794 " firstCharIndex " + p.firstCharIndex); 795 } 796 for (SqlStruct.CharSpan s = p.charSpanList; s != null; s = s.next) { 797 if (Debug.DEBUG) { 798 String ts; 799 switch (s.type) { 800 case SqlStruct.CharSpan.TYPE_NULL: 801 ts = "NULL"; 802 break; 803 case SqlStruct.CharSpan.TYPE_NOT_NULL: 804 ts = "NOT_NULL"; 805 break; 806 case SqlStruct.CharSpan.TYPE_REMOVE: 807 ts = "REMOVE"; 808 break; 809 default: 810 ts = "Unknown(" + s.type + ")"; 811 } 812 Debug.OUT.println(" CharSpan " + s.firstCharIndex + " to " + 813 s.lastCharIndex + " " + ts + " = '" + 814 cq.getSqlbuf().toString(s.firstCharIndex, 815 s.lastCharIndex - s.firstCharIndex) + "'"); 816 } 817 } 818 } 819 } 820 821 public ModelMetaData getJmd() { 822 return jmd; 823 } 824 825 829 public SelectExp getCandidateSelectExp() { 830 return candidateSelectExp; 831 } 832 } 833 | Popular Tags |