1 23 24 30 31 package com.sun.jdo.spi.persistence.support.sqlstore.sql; 32 33 import com.sun.jdo.api.persistence.support.JDOFatalInternalException; 34 import com.sun.jdo.spi.persistence.support.sqlstore.ActionDesc; 35 import com.sun.jdo.spi.persistence.support.sqlstore.RetrieveDesc; 36 import com.sun.jdo.spi.persistence.support.sqlstore.SQLStoreManager; 37 import com.sun.jdo.spi.persistence.support.sqlstore.model.ClassDesc; 38 import com.sun.jdo.spi.persistence.support.sqlstore.model.LocalFieldDesc; 39 import com.sun.jdo.spi.persistence.support.sqlstore.sql.concurrency.Concurrency; 40 import com.sun.jdo.spi.persistence.support.sqlstore.sql.constraint.Constraint; 41 import com.sun.jdo.spi.persistence.support.sqlstore.sql.constraint.ConstraintFieldName; 42 import com.sun.jdo.spi.persistence.support.sqlstore.sql.generator.SelectQueryPlan; 43 import com.sun.jdo.spi.persistence.utility.FieldTypeEnumeration; 44 import com.sun.jdo.spi.persistence.utility.I18NHelper; 45 import com.sun.jdo.spi.persistence.utility.ParameterInfo; 46 47 import java.util.ArrayList ; 48 import java.util.Iterator ; 49 import java.util.ResourceBundle ; 50 51 53 public class RetrieveDescImpl extends Object implements RetrieveDesc, Cloneable { 54 55 private static final int OPINFO_FIELD_DISALLOWED = 0x01; 57 private static final int OPINFO_FIELD_REQUIRED = 0x02; 59 private static final int OPINFO_VAL_DISALLOWED = 0x04; 61 private static final int OPINFO_VAL_REQUIRED = 0x08; 63 private static final int OPINFO_VAL_IS_PCOUNT = 0x10; 65 private static final int OPINFO_ILLEGAL = 0x20; 67 private static final int OPINFO_NO_OPERATION = 0x40; 69 70 public static final int OPT_PROJECTION = 0x1; 72 73 public static final int OPT_DISTINCT = 0x2; 75 76 public static final int OPT_FOR_UPDATE = 0x4; 78 79 public static final int OPT_AVG = 0x08; 81 82 public static final int OPT_MIN = 0x10; 84 85 public static final int OPT_MAX = 0x20; 87 88 public static final int OPT_SUM = 0x40; 90 91 public static final int OPT_COUNT = 0x80; 93 94 public static final int OPT_COUNT_PC = 0x100; 96 97 public static final int OPT_AGGREGATE = OPT_AVG + OPT_MIN + OPT_MAX + 98 OPT_SUM + OPT_COUNT + OPT_COUNT_PC; 99 100 101 public static final int OPT_AGGREGATE_NON_COUNT_PC = OPT_AGGREGATE - OPT_COUNT_PC; 102 103 104 public static final int OPT_ADD_FETCHGROUPS = 0x200; 106 111 public static final int OPT_ADD_KEYS_ONLY = 0x400; 113 120 public static final int OPT_DISABLE_RELATIONSHIP_PREFETCH = 0x800; 122 123 public static final int OPT_VERIFY = 0x1000; 125 126 private ArrayList fields; 127 128 129 private Constraint constraint; 130 131 132 private int options; 133 134 135 private Class pcClass; 136 137 138 private ClassDesc config; 139 140 141 private SelectQueryPlan plan; 142 143 147 private Object navigationalId; 148 149 150 private int aggregateResultType = FieldTypeEnumeration.NOT_ENUMERATED; 151 152 155 private final static ResourceBundle messages = I18NHelper.loadBundle( 156 "com.sun.jdo.spi.persistence.support.sqlstore.Bundle", RetrieveDescImpl.class.getClassLoader()); 158 159 public RetrieveDescImpl(Class pcClass, ClassDesc config) { 160 super(); 161 162 this.pcClass = pcClass; 163 this.config = config; 164 fields = new ArrayList (); 165 constraint = new Constraint(); 166 } 167 168 182 public void addResult(String name, 183 RetrieveDesc foreignConstraint, 184 boolean projection) { 185 ConstraintFieldName cfName = new ConstraintFieldName(name, foreignConstraint); 186 187 if (projection) { 188 if ((options & OPT_PROJECTION) > 0) { 189 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 190 "sqlstore.retrievedesc.toomanyprojections")); } 192 193 if (foreignConstraint != null) { 196 ((RetrieveDescImpl) foreignConstraint).options |= OPT_PROJECTION; 197 } else { 198 cfName.setProjection(); 199 200 } 204 } 205 fields.add(cfName); 206 } 207 208 227 public void addResult(int opCode, int aggregateResultType) { 228 switch (opCode) { 229 case ActionDesc.OP_DISTINCT: 230 options = options | OPT_DISTINCT; 231 break; 232 case ActionDesc.OP_AVG: 233 options = options | OPT_AVG; 234 break; 235 case ActionDesc.OP_MIN: 236 options = options | OPT_MIN; 237 break; 238 case ActionDesc.OP_MAX: 239 options = options | OPT_MAX; 240 break; 241 case ActionDesc.OP_SUM: 242 options = options | OPT_SUM; 243 break; 244 case ActionDesc.OP_COUNT: 245 options = options | OPT_COUNT; 246 break; 247 case ActionDesc.OP_COUNT_PC: 248 options = options | OPT_COUNT_PC; 249 break; 250 default: 251 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 252 "core.constraint.illegalop", "" + opCode)); } 254 255 if (aggregateResultType != FieldTypeEnumeration.NOT_ENUMERATED) { 256 if (this.aggregateResultType == FieldTypeEnumeration.NOT_ENUMERATED) { 257 this.aggregateResultType = aggregateResultType; 258 } else { 259 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 261 "sqlstore.retrievedesc.toomanyresulttypes")); } 263 } 264 } 265 266 273 public void addPrefetchedField(String name, RetrieveDesc foreignConstraint) { 274 fields.add(new ConstraintFieldName(name, foreignConstraint, true)); 275 } 276 277 280 public void setPrefetchEnabled(boolean prefetchEnabled) { 281 if (!prefetchEnabled) { 282 options |= OPT_DISABLE_RELATIONSHIP_PREFETCH; 283 } else { 284 } 286 } 287 288 298 public void addConstraint(String name, 299 RetrieveDesc foreignConstraint) { 300 if (name == null) { 301 constraint.addField(null, foreignConstraint); 302 } else { 303 constraint.addForeignField(name, foreignConstraint); 304 } 305 } 306 307 314 public void addConstraint(String name, int operation, 315 RetrieveDesc foreignConstraint, String foreignName) { 316 constraint.addField(foreignName, foreignConstraint); 317 constraint.addField(name, null); 318 constraint.addOperation(operation); 319 } 320 321 341 public void addConstraint(String name, 342 int operation, 343 Object value) { 344 int info = getOperationInfo(operation); 345 346 if ((info & OPINFO_ILLEGAL) > 0) { 347 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 348 "core.constraint.illegalop", "" + operation)); } else if ((info & OPINFO_FIELD_REQUIRED) > 0 && name == null) { 350 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 351 "core.constraint.fieldrequired", "" + operation)); } else if ((info & OPINFO_FIELD_DISALLOWED) > 0 && name != null) { 353 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 354 "core.constraint.fielddisallowed", "" + operation)); } else if ((info & OPINFO_VAL_REQUIRED) > 0 && value == null) { 356 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 357 "core.constraint.valrequired", "" + operation)); } else if ((info & OPINFO_VAL_DISALLOWED) > 0 && value != null) { 359 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 360 "core.constraint.valdisallowed", "" + operation)); } 362 if ((info & OPINFO_VAL_IS_PCOUNT) > 0) { 363 if (name != null) { 364 constraint.addField(name, null); 365 } 366 addValueConstraint(name, value); 367 } else { 368 switch (operation) { 369 case RetrieveDescImpl.OP_PARAMETER: 370 addParameterConstraint(value); 371 break; 372 case ActionDesc.OP_IN: 373 case ActionDesc.OP_NOTIN: 374 constraint.addConstraintFieldSubQuery(name,(ActionDesc) value); 375 break; 376 default: 377 if (value != null) { 378 addValueConstraint(name, value); 379 } 380 if (name != null) { 381 constraint.addField(name, null); 382 } 383 break; 384 } 385 } 386 if ((info & OPINFO_NO_OPERATION) == 0) { 387 constraint.addOperation(operation); 388 } 389 } 390 391 398 public void addParameterConstraints(LocalFieldDesc[] fields, int startIndex) { 399 for (int i = 0; i < fields.length; i++) { 400 LocalFieldDesc field = fields[i]; 401 addParameterConstraint(field, i + startIndex); 402 } 403 } 404 405 411 public void addParameterConstraint(LocalFieldDesc field, int index) { 412 String fieldName = field.getName(); 414 int type = field.getEnumType(); 415 416 addConstraint(null, ActionDesc.OP_PARAMETER,new ParameterInfo(index, type, fieldName)); 417 addConstraint(fieldName, ActionDesc.OP_FIELD, null); 418 addConstraint(null, ActionDesc.OP_EQ, null); 419 } 420 421 430 private void addValueConstraint(String name, Object value) { 431 constraint.addValue(value, getLocalFieldDesc(name)); 432 } 433 434 445 private void addParameterConstraint(Object value) { 446 if (value instanceof ParameterInfo) { 447 ParameterInfo parameterInfo = (ParameterInfo)value; 448 constraint.addParamIndex(parameterInfo.getIndex(), parameterInfo.getType(), 449 getLocalFieldDesc(parameterInfo.getAssociatedField())); 450 } else { 451 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 452 "core.constraint.illegalParameterInfo")); } 454 } 455 456 464 private LocalFieldDesc getLocalFieldDesc(String name) { 465 return name == null ? null : config.getLocalFieldDesc(name); 466 } 467 468 493 private static int getOperationInfo(int operation) { 494 int info; 495 switch (operation) { 496 case ActionDesc.OP_ABS: 497 info = OPINFO_VAL_DISALLOWED; 498 break; 499 case ActionDesc.OP_ADD: 500 info = 0; 501 break; 502 case ActionDesc.OP_AND: 503 info = 0; 504 break; 505 case ActionDesc.OP_FIELD: 506 info = OPINFO_FIELD_REQUIRED | OPINFO_VAL_DISALLOWED | OPINFO_NO_OPERATION; 507 break; 508 case ActionDesc.OP_BETWEEN: 509 info = 0; 510 break; 511 case ActionDesc.OP_DIV: 512 info = 0; 513 break; 514 case ActionDesc.OP_EQ: 515 info = 0; 516 break; 517 case ActionDesc.OP_NE: 518 info = 0; 519 break; 520 case ActionDesc.OP_EQUIJOIN: 521 info = 0; 522 break; 523 case ActionDesc.OP_NOT: 524 info = OPINFO_FIELD_DISALLOWED | OPINFO_VAL_DISALLOWED; 525 break; 526 case ActionDesc.OP_GE: 527 info = 0; 528 break; 529 case ActionDesc.OP_GT: 530 info = 0; 531 break; 532 case ActionDesc.OP_IN: 533 case ActionDesc.OP_NOTIN: 534 info = OPINFO_FIELD_REQUIRED | OPINFO_VAL_REQUIRED; 535 break; 536 case ActionDesc.OP_LE: 537 info = 0; 538 break; 539 case ActionDesc.OP_LEFTJOIN: 540 info = 0; 541 break; 542 case ActionDesc.OP_LENGTH: 543 info = OPINFO_VAL_DISALLOWED; 544 break; 545 case ActionDesc.OP_LIKE: 546 info = 0; 547 break; 548 case ActionDesc.OP_LIKE_ESCAPE: 549 info = 0; 550 break; 551 case ActionDesc.OP_LT: 552 info = 0; 553 break; 554 case ActionDesc.OP_LTRIM: 555 info = OPINFO_VAL_DISALLOWED; 556 break; 557 case ActionDesc.OP_MUL: 558 info = 0; 559 break; 560 case ActionDesc.OP_OR: 561 info = 0; 562 break; 563 case ActionDesc.OP_ORDERBY: 564 info = 0; 565 break; 566 case ActionDesc.OP_ORDERBY_DESC: 567 info = 0; 568 break; 569 case ActionDesc.OP_PARAMETER_COUNT: 570 info = OPINFO_FIELD_DISALLOWED | OPINFO_VAL_REQUIRED | OPINFO_VAL_IS_PCOUNT | OPINFO_NO_OPERATION; 571 break; 572 case ActionDesc.OP_RIGHTJOIN: 573 info = 0; 574 break; 575 case ActionDesc.OP_RTRIM: 576 info = OPINFO_VAL_DISALLOWED; 577 break; 578 case ActionDesc.OP_SQRT: 579 info = OPINFO_VAL_DISALLOWED; 580 break; 581 case ActionDesc.OP_SUB: 582 info = 0; 583 break; 584 case ActionDesc.OP_SUBSTRING: 585 info = 0; 586 break; 587 case ActionDesc.OP_POSITION: 588 info = 0; 589 break; 590 case ActionDesc.OP_POSITION_START: 591 info = 0; 592 break; 593 case ActionDesc.OP_MAYBE_NULL: 594 info = OPINFO_FIELD_REQUIRED; 595 break; 596 case ActionDesc.OP_CONCAT: 597 info = 0; 598 break; 599 case ActionDesc.OP_VALUE: 600 info = OPINFO_FIELD_DISALLOWED | OPINFO_VAL_REQUIRED | OPINFO_NO_OPERATION; 601 break; 602 case ActionDesc.OP_PARAMETER: 603 info = OPINFO_FIELD_DISALLOWED | OPINFO_VAL_REQUIRED | OPINFO_NO_OPERATION; 604 break; 605 case OP_NULL: 606 case OP_NOTNULL: 607 info = 0; 608 break; 609 case ActionDesc.OP_MOD: 610 info = 0; 611 break; 612 default: 613 info = OPINFO_ILLEGAL; 614 break; 615 } 616 return info; 617 } 618 619 626 public synchronized SelectQueryPlan buildQueryPlan(SQLStoreManager store, 627 Concurrency concurrency) { 628 629 if (plan == null) { 630 631 handleProjection(); 632 633 plan = SelectQueryPlan.newInstance(this, store, concurrency); 634 635 plan.build(); 636 637 ArrayList statements = plan.getStatements(); 639 640 if (statements.size() > 1) { 642 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 643 "sqlstore.retrievedesc.stmntsnotjoined")); } 645 } 646 return plan; 647 } 648 649 660 private void handleProjection() { 661 final int queryOptions = options & (OPT_AGGREGATE | OPT_DISABLE_RELATIONSHIP_PREFETCH); 664 RetrieveDescImpl projectedDesc = distributeQueryOptions( 665 queryOptions, aggregateResultType); 666 667 if (projectedDesc == null) { 668 options |= OPT_PROJECTION; 670 setFetchGroupOptions(queryOptions); 672 } 673 } 674 675 695 private RetrieveDescImpl distributeQueryOptions(int queryOptions, 696 int aggregateResultType) { 697 RetrieveDescImpl projectedDesc = null; 698 699 if ((options & OPT_PROJECTION) > 0) { 700 setFetchGroupOptions(queryOptions); 703 this.aggregateResultType = aggregateResultType; 704 projectedDesc = this; 705 } 706 707 options |= queryOptions; 709 710 for (int i = 0; i < fields.size(); i++) { 712 ConstraintFieldName cfn = (ConstraintFieldName) fields.get(i); 713 714 if (cfn.isProjection()) { 715 this.aggregateResultType = aggregateResultType; 718 projectedDesc = this; 719 } else if (cfn.desc != null) { 720 projectedDesc = ((RetrieveDescImpl) cfn.desc).distributeQueryOptions( 721 queryOptions, aggregateResultType); 722 } 723 } 724 725 return projectedDesc; 726 } 727 728 744 private void setFetchGroupOptions(int queryOptions) { 745 746 if ((queryOptions & OPT_AGGREGATE_NON_COUNT_PC) == 0) { 747 options |= OPT_ADD_FETCHGROUPS; 750 751 if (queryOptions == OPT_COUNT_PC) { 752 options |= OPT_ADD_KEYS_ONLY; 753 } 754 } 755 } 756 757 765 public void setNavigationalId(Object navigationalId) { 766 this.navigationalId = navigationalId; 767 } 768 769 777 public Object getNavigationalId() { 778 return navigationalId; 779 } 780 781 788 public void setOption(int option) { 789 this.options |= option; 790 } 791 792 795 public int getAggregateResultType() { 796 return aggregateResultType; 797 } 798 799 804 public int getOptions() { 805 return options; 806 } 807 808 public SelectQueryPlan getPlan() { 809 return plan; 810 } 811 812 public ClassDesc getConfig() { 813 return config; 814 } 815 816 public void setPlan(SelectQueryPlan plan) { 817 this.plan = plan; 818 } 819 820 public Class getPersistenceCapableClass() { 821 return pcClass; 822 } 823 824 public Constraint getConstraint() { 825 return constraint; 826 } 827 828 public Iterator getFields() { 829 return fields.iterator(); 830 } 831 832 public Object clone() { 833 try { 834 RetrieveDescImpl clone = (RetrieveDescImpl) super.clone(); 835 clone.fields = new ArrayList (); 836 clone.constraint = new Constraint(); 837 838 return clone; 839 } catch (CloneNotSupportedException e) { 840 return null; 844 } 845 } 846 847 } 848 | Popular Tags |