1 21 package oracle.toplink.essentials.internal.databaseaccess; 23 24 import java.util.*; 25 import java.sql.*; 26 import java.io.*; 27 import oracle.toplink.essentials.internal.helper.*; 28 import oracle.toplink.essentials.sessions.DatabaseRecord; 29 import oracle.toplink.essentials.queryframework.*; 30 import oracle.toplink.essentials.exceptions.*; 31 import oracle.toplink.essentials.internal.queryframework.*; 32 import oracle.toplink.essentials.internal.expressions.ParameterExpression; 33 import oracle.toplink.essentials.internal.sessions.AbstractRecord; 34 import oracle.toplink.essentials.internal.sessions.AbstractSession; 35 36 41 public abstract class DatabaseCall extends DatasourceCall { 42 transient protected Statement statement; 44 transient protected ResultSet result; 45 46 protected int usesBinding; 48 49 protected int shouldCacheStatement; 51 52 transient protected Vector fields; 54 55 protected boolean isFieldMatchingRequired; 57 58 protected boolean hasOptimisticLock; 60 protected boolean isResultSetScrollable; 61 62 protected int resultSetType; 64 65 protected int resultSetConcurrency; 67 68 protected int queryTimeout; 70 71 protected int maxRows; 73 74 protected int firstResult; 76 77 private transient AbstractRecord contexts = null; 80 protected boolean isCursorOutputProcedure; 81 82 protected int returnsResultSet; 85 86 protected boolean shouldBuildOutputRow; 88 89 protected boolean isCallableStatementRequired; 91 protected String sqlString; 92 93 public DatabaseCall() { 94 this.usesBinding = FalseUndefinedTrue.Undefined; 95 this.shouldCacheStatement = FalseUndefinedTrue.Undefined; 96 this.isFieldMatchingRequired = false; 97 this.returnType = RETURN_MANY_ROWS; 98 this.queryTimeout = 0; 99 this.maxRows = 0; 100 this.isCursorOutputProcedure = false; 101 this.shouldBuildOutputRow = false; 102 this.returnsResultSet = FalseUndefinedTrue.Undefined; 103 } 104 105 108 public void appendIn(Object inObject) { 109 getParameters().add(inObject); 110 getParameterTypes().add(IN); 111 } 112 113 116 public void appendInOut(DatabaseField inoutField) { 117 Object [] inOut = { inoutField, inoutField }; 118 getParameters().add(inOut); 119 getParameterTypes().add(INOUT); 120 } 121 122 125 public void appendInOut(Object inValueOrField, DatabaseField outField) { 126 Object [] inOut = { inValueOrField, outField }; 127 getParameters().add(inOut); 128 getParameterTypes().add(INOUT); 129 } 130 131 134 public void appendOut(DatabaseField outField) { 135 getParameters().add(outField); 136 getParameterTypes().add(OUT); 137 } 138 139 142 public void appendOutCursor(DatabaseField outField) { 143 getParameters().add(outField); 144 getParameterTypes().add(OUT_CURSOR); 145 } 146 147 152 public void appendParameter(Writer writer, Object parameter, AbstractSession session) { 153 if (usesBinding == FalseUndefinedTrue.True) { 154 bindParameter(writer, parameter); 155 } else { 156 session.getPlatform().appendParameter(this, writer, parameter); 157 } 158 } 159 160 163 public void bindParameter(Writer writer, Object parameter) { 164 if (parameter instanceof Vector) { 165 throw QueryException.inCannotBeParameterized(getQuery()); 166 } 167 168 try { 169 writer.write("?"); 170 } catch (IOException exception) { 171 throw ValidationException.fileError(exception); 172 } 173 getParameters().addElement(parameter); 174 } 175 176 180 public DatabaseQueryMechanism buildNewQueryMechanism(DatabaseQuery query) { 181 return new CallQueryMechanism(query, this); 182 } 183 184 189 public AbstractRecord buildOutputRow(CallableStatement statement) throws SQLException { 190 AbstractRecord row = new DatabaseRecord(); 191 for (int index = 0; index < parameters.size(); index++) { 192 Object parameter = parameters.elementAt(index); 193 if (parameter instanceof OutputParameterForCallableStatement) { 194 OutputParameterForCallableStatement outParameter = (OutputParameterForCallableStatement)parameter; 195 if (!outParameter.isCursor()) { 196 Object value = statement.getObject(index + 1); 197 DatabaseField field = outParameter.getOutputField(); 198 row.put(field, value); 199 } 200 } 201 } 202 203 return row; 204 } 205 206 210 public DatabaseQueryMechanism buildQueryMechanism(DatabaseQuery query, DatabaseQueryMechanism mechanism) { 211 if (mechanism.isCallQueryMechanism() && (mechanism instanceof CallQueryMechanism)) { 212 CallQueryMechanism callMechanism = ((CallQueryMechanism)mechanism); 214 if (!callMechanism.hasMultipleCalls()) { 215 callMechanism.addCall(callMechanism.getCall()); 216 callMechanism.setCall(null); 217 } 218 callMechanism.addCall(this); 219 return mechanism; 220 } else { 221 return buildNewQueryMechanism(query); 222 } 223 } 224 225 229 protected Object createInOutParameter(Object inValue, Object outParameter, AbstractSession session) { 230 if (outParameter instanceof OutputParameterForCallableStatement) { 231 return new InOutputParameterForCallableStatement(inValue, (OutputParameterForCallableStatement)outParameter); 232 } 233 if (outParameter instanceof DatabaseField) { 234 return new InOutputParameterForCallableStatement(inValue, (DatabaseField)outParameter, session.getPlatform()); 235 } 236 237 return null; 239 } 240 241 245 public String getCallString() { 246 return getSQLString(); 247 } 248 249 253 public Vector getFields() { 254 return fields; 255 } 256 257 264 protected DatabaseField getFieldWithTypeFromDescriptor(DatabaseField outField) { 265 if (getQuery().getDescriptor() != null) { 266 return getQuery().getDescriptor().getTypedField(outField); 267 } else { 268 return null; 269 } 270 } 271 272 276 public int getCursorOutIndex() { 277 for (int i = 0; i < getParameters().size(); i++) { 278 Object parameter = getParameters().elementAt(i); 279 if (parameter instanceof OutputParameterForCallableStatement) { 280 if (((OutputParameterForCallableStatement)parameter).isCursor()) { 281 return i + 1; 282 } 283 } 284 } 285 return -1; 286 } 287 288 291 public int getFirstResult() { 292 return this.firstResult; 293 } 294 295 298 public String getLogString(Accessor accessor) { 299 if (hasParameters()) { 300 StringWriter writer = new StringWriter(); 301 writer.write(getSQLString()); 302 writer.write(Helper.cr()); 303 if (hasParameters()) { 304 AbstractSession session = null; 305 if (getQuery() != null) { 306 session = getQuery().getSession(); 307 } 308 appendLogParameters(getParameters(), accessor, writer, session); 309 } 310 return writer.toString(); 311 } else { 312 return getSQLString(); 313 } 314 } 315 316 319 public static void appendLogParameters(Collection parameters, Accessor accessor, StringWriter writer, AbstractSession session) { 320 writer.write("\tbind => ["); 321 for (Iterator paramsEnum = parameters.iterator(); paramsEnum.hasNext();) { 322 Object parameter = paramsEnum.next(); 323 if (parameter instanceof DatabaseField) { 324 writer.write("null"); 325 } else { 326 if (session != null) { 327 parameter = session.getPlatform().convertToDatabaseType(parameter); 328 } 329 writer.write(String.valueOf(parameter)); 330 } 331 if (paramsEnum.hasNext()) { 332 writer.write(", "); 333 } else { 334 writer.write("]"); 335 } 336 } 337 } 338 339 342 public int getMaxRows() { 343 return this.maxRows; 344 } 345 346 350 public Vector getOutputRowFields() { 351 Vector fields = new Vector(); 352 for (int i = 0; i < getParameters().size(); i++) { 353 Integer parameterType = (Integer )getParameterTypes().elementAt(i); 354 Object parameter = getParameters().elementAt(i); 355 if (parameterType == OUT) { 356 fields.add(parameter); 357 } else if (parameterType == INOUT) { 358 fields.add(((Object [])parameter)[1]); 359 } 360 } 361 return fields; 362 } 363 364 368 public String getQueryString() { 369 return getSQLString(); 370 } 371 372 375 public ResultSet getResult() { 376 return result; 377 } 378 379 385 public boolean getReturnsResultSet() { 386 if (returnsResultSet == FalseUndefinedTrue.Undefined) { 387 return !shouldBuildOutputRow(); 388 } else { 389 return returnsResultSet == FalseUndefinedTrue.True; 390 } 391 } 392 393 public int getResultSetConcurrency() { 394 return resultSetConcurrency; 395 } 396 397 public int getResultSetType() { 398 return resultSetType; 399 } 400 401 404 public String getSQLString() { 405 return sqlString; 406 } 407 408 411 public Statement getStatement() { 412 return statement; 413 } 414 415 418 public boolean hasOptimisticLock() { 419 return hasOptimisticLock; 420 } 421 422 425 protected boolean isCallableStatementRequired() { 426 return isCallableStatementRequired; 427 } 428 429 435 protected boolean isDynamicCall(AbstractSession session) { 436 return DatabaseAccessor.shouldUseDynamicStatements && (!usesBinding(session)) && (!isResultSetScrollable()) && (!hasParameters()); 437 } 438 439 442 public boolean isCursorOutputProcedure() { 443 return isCursorOutputProcedure; 444 } 445 446 449 public boolean isCursorReturned() { 450 return getReturnType() == RETURN_CURSOR; 451 } 452 453 457 public boolean isFieldMatchingRequired() { 458 return isFieldMatchingRequired; 459 } 460 461 464 public boolean isFinished() { 465 return !isCursorReturned(); 466 } 467 468 471 public boolean isNonCursorOutputProcedure() { 472 return !isCursorOutputProcedure() && shouldBuildOutputRow(); 473 } 474 475 public boolean isResultSetScrollable() { 476 return isResultSetScrollable; 477 } 478 479 483 public void matchFieldOrder(ResultSet resultSet, DatabaseAccessor accessor, AbstractSession session) { 484 if ((getFields() != null) && (!isFieldMatchingRequired())) { 485 return; 486 } 487 setFields(accessor.buildSortedFields(getFields(), resultSet, session)); 488 } 489 490 495 public void prepare(AbstractSession session) { 496 if (isPrepared()) { 497 return; 498 } 499 500 prepareInternal(session); 501 502 setIsPrepared(true); 503 } 504 505 509 protected void prepareInternal(AbstractSession session) { 510 if (isCursorOutputProcedure()) { 511 int nFirstOutParameterIndex = -1; 514 boolean hasFoundOutCursor = false; 515 for (int index = 0; index < parameters.size(); index++) { 516 Integer parameterType = (Integer )parameterTypes.elementAt(index); 517 if (parameterType == DatasourceCall.OUT_CURSOR) { 518 if (hasFoundOutCursor) { 519 throw ValidationException.multipleCursorsNotSupported(toString()); 521 } else { 522 hasFoundOutCursor = true; 523 } 524 } else if (parameterType == DatasourceCall.OUT) { 525 if (nFirstOutParameterIndex == -1) { 526 nFirstOutParameterIndex = index; 527 } 528 } else if (parameterType == null) { 529 throw ValidationException.wrongUsageOfSetCustomArgumentTypeMethod(toString()); 531 } 532 } 533 if (!hasFoundOutCursor && (nFirstOutParameterIndex >= 0)) { 534 parameterTypes.setElementAt(DatasourceCall.OUT_CURSOR, nFirstOutParameterIndex); 535 } 536 } 537 538 for (int i = 0; i < getParameters().size(); i++) { 539 Object parameter = getParameters().elementAt(i); 540 Integer parameterType = (Integer )getParameterTypes().elementAt(i); 541 if (parameterType == MODIFY) { 542 DatabaseField field = (DatabaseField)parameter; 544 if ((field.getType() == null) || session.getPlatform().shouldUseCustomModifyForCall(field)) { 545 getParameterTypes().setElementAt(CUSTOM_MODIFY, i); 546 } 547 } else if (parameterType == INOUT) { 548 setShouldBuildOutputRow(true); 552 setIsCallableStatementRequired(true); 553 DatabaseField outField = (DatabaseField)((Object [])parameter)[1]; 554 if (outField.getType() == null) { 555 DatabaseField typeOutField = getFieldWithTypeFromDescriptor(outField); 556 if (typeOutField != null) { 557 outField = (DatabaseField)typeOutField.clone(); 558 } 559 } 560 if (outField.getType() != null) { 561 OutputParameterForCallableStatement outParameter = new OutputParameterForCallableStatement(outField, session.getPlatform()); 563 ((Object [])parameter)[1] = outParameter; 564 } 565 } else if ((parameterType == OUT) || (parameterType == OUT_CURSOR)) { 566 boolean isCursor = parameterType == OUT_CURSOR; 567 if (!isCursor) { 568 setShouldBuildOutputRow(true); 569 } 570 setIsCallableStatementRequired(true); 571 DatabaseField outField = (DatabaseField)parameter; 572 if (outField.getType() == null) { 573 DatabaseField typeOutField = getFieldWithTypeFromDescriptor(outField); 574 if (typeOutField != null) { 575 outField = (DatabaseField)typeOutField.clone(); 576 } 577 } 578 579 OutputParameterForCallableStatement outParameter = new OutputParameterForCallableStatement(outField, session.getPlatform(), isCursor); 581 getParameters().setElementAt(outParameter, i); 582 getParameterTypes().setElementAt(LITERAL, i); 584 } 585 } 586 if (this.returnsResultSet == FalseUndefinedTrue.Undefined) { 587 setReturnsResultSet(!isCallableStatementRequired()); 588 } 589 } 590 591 596 public Statement prepareStatement(DatabaseAccessor accessor, AbstractRecord translationRow, AbstractSession session) throws SQLException { 597 Statement statement = accessor.prepareStatement(this, session); 598 599 if (getMaxRows() > 0) { 600 statement.setMaxRows(getMaxRows()); 601 } 602 603 if (!hasParameters()) { 604 return statement; 605 } 606 607 for (int index = 0; index < getParameters().size(); index++) { 608 session.getPlatform().setParameterValueInDatabaseCall(this.getParameters(), (PreparedStatement)statement, index, session); 609 } 610 611 return statement; 612 } 613 614 617 public void setFields(Vector fields) { 618 this.fields = fields; 619 } 620 621 624 public void setFirstResult(int firstResult) { 625 this.firstResult = firstResult; 626 } 627 628 631 public void setHasOptimisticLock(boolean hasOptimisticLock) { 632 this.hasOptimisticLock = hasOptimisticLock; 633 } 634 635 638 protected void setIsCallableStatementRequired(boolean isCallableStatementRequired) { 639 this.isCallableStatementRequired = isCallableStatementRequired; 640 } 641 642 645 public void setIsCursorOutputProcedure(boolean isCursorOutputProcedure) { 646 this.isCursorOutputProcedure = isCursorOutputProcedure; 647 } 648 649 652 public void setIsFieldMatchingRequired(boolean isFieldMatchingRequired) { 653 this.isFieldMatchingRequired = isFieldMatchingRequired; 654 } 655 656 public void setIsResultSetScrollable(boolean isResultSetScrollable) { 657 this.isResultSetScrollable = isResultSetScrollable; 658 } 659 660 663 public void setMaxRows(int maxRows) { 664 this.maxRows = maxRows; 665 } 666 667 671 public void setQueryString(String queryString) { 672 setSQLStringInternal(queryString); 673 } 674 675 678 public void setResult(ResultSet result) { 679 this.result = result; 680 } 681 682 public void setResultSetConcurrency(int resultSetConcurrency) { 683 this.resultSetConcurrency = resultSetConcurrency; 684 } 685 686 690 protected void setSQLStringInternal(String sqlString) { 691 this.sqlString = sqlString; 692 } 693 694 public void setResultSetType(int resultSetType) { 695 this.resultSetType = resultSetType; 696 } 697 698 702 public void setReturnsResultSet(boolean returnsResultSet) { 703 if (returnsResultSet) { 704 this.returnsResultSet = FalseUndefinedTrue.True; 705 } else { 706 this.returnsResultSet = FalseUndefinedTrue.False; 707 } 708 } 709 710 714 protected void setShouldBuildOutputRow(boolean shouldBuildOutputRow) { 715 this.shouldBuildOutputRow = shouldBuildOutputRow; 716 } 717 718 721 public void setShouldCacheStatement(boolean shouldCacheStatement) { 722 if (shouldCacheStatement) { 723 this.shouldCacheStatement = FalseUndefinedTrue.True; 724 } else { 725 this.shouldCacheStatement = FalseUndefinedTrue.False; 726 } 727 } 728 729 732 public void setStatement(Statement statement) { 733 this.statement = statement; 734 } 735 736 739 public void setUsesBinding(boolean usesBinding) { 740 if (usesBinding) { 741 this.usesBinding = FalseUndefinedTrue.True; 742 } else { 743 this.usesBinding = FalseUndefinedTrue.False; 744 } 745 } 746 747 750 public boolean shouldBuildOutputRow() { 751 return this.shouldBuildOutputRow; 752 } 753 754 757 public boolean shouldCacheStatement(AbstractSession session) { 758 return shouldCacheStatement(session.getPlatform()); 759 } 760 761 764 public boolean shouldCacheStatement(DatabasePlatform databasePlatform) { 765 if (isResultSetScrollable()) { 767 return false; 768 } 769 if (shouldCacheStatement == FalseUndefinedTrue.Undefined) { 770 return databasePlatform.shouldCacheAllStatements(); 771 } else { 772 return shouldCacheStatement == FalseUndefinedTrue.True; 773 } 774 } 775 776 780 public String toString() { 781 String str = Helper.getShortClassName(getClass()); 782 if (getSQLString() == null) { 783 return str; 784 } else { 785 return str + "(" + getSQLString() + ")"; 786 } 787 } 788 789 793 public void translate(AbstractRecord translationRow, AbstractRecord modifyRow, AbstractSession session) { 794 if (!isPrepared()) { 795 throw ValidationException.cannotTranslateUnpreparedCall(toString()); 796 } 797 if (usesBinding(session)) { 798 Vector parametersValues = new Vector(); 799 for (int index = 0; index < getParameters().size(); index++) { 800 Object parameter = getParameters().elementAt(index); 801 Object parameterType = getParameterTypes().elementAt(index); 802 if (parameterType == MODIFY) { 803 DatabaseField field = (DatabaseField)parameter; 804 Object value = modifyRow.get(field); 805 if (value == null) { 806 value = modifyRow.getField(field); 807 } 808 parametersValues.addElement(value); 809 } else if (parameterType == CUSTOM_MODIFY) { 810 DatabaseField field = (DatabaseField)parameter; 811 Object value = modifyRow.get(field); 812 value = session.getPlatform().getCustomModifyValueForCall(this, value, field, true); 813 if (value == null) { 814 value = modifyRow.getField(field); 815 } 816 parametersValues.addElement(value); 817 } else if (parameterType == TRANSLATION) { 818 Object value = null; 819 DatabaseField field = null; 820 if (parameter instanceof ParameterExpression) { 821 value = ((ParameterExpression)parameter).getValue(translationRow, session); 822 } else { 823 field = (DatabaseField)parameter; 824 value = translationRow.get(field); 825 if (value == null) { value = modifyRow.get(field); 827 } 828 } 829 if (value instanceof Vector) { 830 throw QueryException.inCannotBeParameterized(getQuery()); 831 } 832 if ((value == null) && (field != null)) { 833 value = translationRow.getField(field); 834 } 835 parametersValues.addElement(value); 836 } else if (parameterType == LITERAL) { 837 parametersValues.addElement(parameter); 838 } else if (parameterType == IN) { 839 Object value = getValueForInParameter(parameter, translationRow, modifyRow, session, true); 840 parametersValues.addElement(value); 841 } else if (parameterType == INOUT) { 842 Object value = getValueForInOutParameter(parameter, translationRow, modifyRow, session); 843 parametersValues.addElement(value); 844 } 845 } 846 setParameters(parametersValues); 847 return; 848 } 849 850 translateQueryString(translationRow, modifyRow, session); 851 } 852 853 856 public boolean usesBinding(AbstractSession session) { 857 return usesBinding(session.getPlatform()); 858 } 859 860 863 public boolean usesBinding(DatabasePlatform databasePlatform) { 864 if (usesBinding == FalseUndefinedTrue.Undefined) { 865 return databasePlatform.shouldBindAllParameters(); 866 } else { 867 return usesBinding == FalseUndefinedTrue.True; 868 } 869 } 870 871 875 public boolean isLOBLocatorNeeded() { 876 return contexts != null; 877 } 878 879 883 public void addContext(DatabaseField field, Object value) { 884 if (contexts == null) { 885 contexts = new DatabaseRecord(2); 886 } 887 contexts.add(field, value); 888 } 889 890 894 public AbstractRecord getContexts() { 895 return contexts; 896 } 897 898 902 public void setContexts(AbstractRecord contexts) { 903 this.contexts = contexts; 904 } 905 906 911 public void useUnnamedCursorOutputAsResultSet() { 912 setIsCursorOutputProcedure(true); 913 } 914 } 915 | Popular Tags |