KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > internal > databaseaccess > DatabaseCall


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 // Copyright (c) 1998, 2006, Oracle. All rights reserved.
22
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 /**
37  * INTERNAL:
38  * <b>Purpose<b>: Used as an abstraction of a database invocation.
39  * A call is an SQL string or procedure call with parameters.
40  */

41 public abstract class DatabaseCall extends DatasourceCall {
42     // The result and statement are cached for cursor selects.
43
transient protected Statement statement;
44     transient protected ResultSet result;
45
46     // The call may specify that its parameters should be bound.
47
protected int usesBinding;
48
49     // Bound calls can use prepared statement caching.
50
protected int shouldCacheStatement;
51
52     // The returned fields.
53
transient protected Vector fields;
54
55     // Field matching is required for custom SQL when the fields order is not known.
56
protected boolean isFieldMatchingRequired;
57
58     // optimistic locking determination is required for batch writing
59
protected boolean hasOptimisticLock;
60     protected boolean isResultSetScrollable;
61
62     // JDK 1.2 supports various types of results set
63
protected int resultSetType;
64
65     // JDK 1.2 supports various types of concurrency on results set
66
protected int resultSetConcurrency;
67
68     //query timeout limit in seconds
69
protected int queryTimeout;
70
71     //max rows returned in the result set by the call
72
protected int maxRows;
73
74     //firstResult set into the result set by the call
75
protected int firstResult;
76
77     //contain field - value pairs for LOB fields used to the
78
//steaming operation during the writing (to the table)
79
private transient AbstractRecord contexts = null;
80     protected boolean isCursorOutputProcedure;
81
82     // This parameter is here to determine if TopLink should expect a ResultSet back from the call
83
// TopLink needs to know this information in order to call teh correct JDBC API
84
protected int returnsResultSet;
85
86     // Whether the call has to build output row
87
protected boolean shouldBuildOutputRow;
88
89     // Callable statement is required if there is an output parameter
90
protected boolean isCallableStatementRequired;
91     protected String JavaDoc 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     /**
106      * INTERNAL:
107      */

108     public void appendIn(Object JavaDoc inObject) {
109         getParameters().add(inObject);
110         getParameterTypes().add(IN);
111     }
112
113     /**
114      * INTERNAL:
115      */

116     public void appendInOut(DatabaseField inoutField) {
117         Object JavaDoc[] inOut = { inoutField, inoutField };
118         getParameters().add(inOut);
119         getParameterTypes().add(INOUT);
120     }
121
122     /**
123      * INTERNAL:
124      */

125     public void appendInOut(Object JavaDoc inValueOrField, DatabaseField outField) {
126         Object JavaDoc[] inOut = { inValueOrField, outField };
127         getParameters().add(inOut);
128         getParameterTypes().add(INOUT);
129     }
130
131     /**
132      * INTERNAL:
133      */

134     public void appendOut(DatabaseField outField) {
135         getParameters().add(outField);
136         getParameterTypes().add(OUT);
137     }
138
139     /**
140      * INTERNAL:
141      */

142     public void appendOutCursor(DatabaseField outField) {
143         getParameters().add(outField);
144         getParameterTypes().add(OUT_CURSOR);
145     }
146
147     /**
148      * Add the parameter.
149      * If using binding bind the parameter otherwise let the platform print it.
150      * The platform may also decide to bind the value.
151      */

152     public void appendParameter(Writer writer, Object JavaDoc 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     /**
161      * Bind the parameter. Binding is determined by the call and second the platform.
162      */

163     public void bindParameter(Writer writer, Object JavaDoc 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     /**
177      * Return the appropriate mechanism,
178      * with the call added as necessary.
179      */

180     public DatabaseQueryMechanism buildNewQueryMechanism(DatabaseQuery query) {
181         return new CallQueryMechanism(query, this);
182     }
183
184     /**
185      * INTERNAL:
186      * Return DatabaseRow containing output fields and values.
187      * Called only if shouldBuildOutputRow method returns true.
188      */

189     public AbstractRecord buildOutputRow(CallableStatement statement) throws SQLException {
190         AbstractRecord row = new DatabaseRecord();
191         for (int index = 0; index < parameters.size(); index++) {
192             Object JavaDoc parameter = parameters.elementAt(index);
193             if (parameter instanceof OutputParameterForCallableStatement) {
194                 OutputParameterForCallableStatement outParameter = (OutputParameterForCallableStatement)parameter;
195                 if (!outParameter.isCursor()) {
196                     Object JavaDoc 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     /**
207      * Return the appropriate mechanism,
208      * with the call added as necessary.
209      */

210     public DatabaseQueryMechanism buildQueryMechanism(DatabaseQuery query, DatabaseQueryMechanism mechanism) {
211         if (mechanism.isCallQueryMechanism() && (mechanism instanceof CallQueryMechanism)) {
212             // Must also add the call singleton...
213
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     /**
226      * INTERNAL:
227      * Returns INOUT parameter. The first parameter is value to pass in, the second DatabaseField for out.
228      */

229     protected Object JavaDoc createInOutParameter(Object JavaDoc inValue, Object JavaDoc 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         //should never happen
238
return null;
239     }
240
241     /**
242      * INTERNAL:
243      * Return the SQL string for the call.
244      */

245     public String JavaDoc getCallString() {
246         return getSQLString();
247     }
248
249     /**
250      * The fields expected by the calls result set.
251      * null means that the fields are unknown and should be built from the result set.
252      */

253     public Vector getFields() {
254         return fields;
255     }
256
257     /**
258      * INTERNAL:
259      * Unfortunately can't avoid referencing query and descriptor:
260      * the call should be performed after the translateCustomSQL (in SQLCall)
261      * in the middle of prepare method (no parameter available earlier).
262      *
263      */

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     /**
273      * INTERNAL:
274      * Return 1-based index of out cursor parameter, or -1.
275      */

276     public int getCursorOutIndex() {
277         for (int i = 0; i < getParameters().size(); i++) {
278             Object JavaDoc 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     /**
289      * get first result
290      */

291     public int getFirstResult() {
292         return this.firstResult;
293     }
294
295     /**
296      * Return the SQL string for logging purposes.
297      */

298     public String JavaDoc 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     /**
317      * Print the parameters to the write for logging purposes.
318      */

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 JavaDoc 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     /**
340      * get max rows returned from the call
341      */

342     public int getMaxRows() {
343         return this.maxRows;
344     }
345
346     /**
347      * INTERNAL
348      * Returns the fields to be used in output row.
349      */

350     public Vector getOutputRowFields() {
351         Vector fields = new Vector();
352         for (int i = 0; i < getParameters().size(); i++) {
353             Integer JavaDoc parameterType = (Integer JavaDoc)getParameterTypes().elementAt(i);
354             Object JavaDoc parameter = getParameters().elementAt(i);
355             if (parameterType == OUT) {
356                 fields.add(parameter);
357             } else if (parameterType == INOUT) {
358                 fields.add(((Object JavaDoc[])parameter)[1]);
359             }
360         }
361         return fields;
362     }
363
364     /**
365      * INTERNAL:
366      * Return the query string (SQL) of the call.
367      */

368     public String JavaDoc getQueryString() {
369         return getSQLString();
370     }
371
372     /**
373      * The result set is stored for the return value of cursor selects.
374      */

375     public ResultSet getResult() {
376         return result;
377     }
378
379     /**
380      * ADVANCED:
381      * This method returns a value that represents if the customer has set whether or not TopLink should expect
382      * the stored procedure to returning a JDBC ResultSet. The result of the method corresponds
383      * to false, true.
384      */

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     /**
402      * Return the SQL string that will be executed.
403      */

404     public String JavaDoc getSQLString() {
405         return sqlString;
406     }
407
408     /**
409      * The statement is stored for the return value of cursor selects.
410      */

411     public Statement getStatement() {
412         return statement;
413     }
414
415     /**
416      * This check is needed only when doing batch writing.
417      */

418     public boolean hasOptimisticLock() {
419         return hasOptimisticLock;
420     }
421
422     /**
423      * Callable statement is required if there is an output parameter.
424      */

425     protected boolean isCallableStatementRequired() {
426         return isCallableStatementRequired;
427     }
428
429     /**
430      * Return if the call is dynamic SQL call.
431      * This means the call has no parameters, is not using binding,
432      * is not a stored procedure (CallableStatement), or cursor.
433      * This means that a Statement, not PrepareStatement will be used for the call.
434      */

435     protected boolean isDynamicCall(AbstractSession session) {
436         return DatabaseAccessor.shouldUseDynamicStatements && (!usesBinding(session)) && (!isResultSetScrollable()) && (!hasParameters());
437     }
438
439     /**
440      * Used for Oracle result sets through procedures.
441      */

442     public boolean isCursorOutputProcedure() {
443         return isCursorOutputProcedure;
444     }
445
446     /**
447      * The return type is one of, NoReturn, ReturnOneRow or ReturnManyRows.
448      */

449     public boolean isCursorReturned() {
450         return getReturnType() == RETURN_CURSOR;
451     }
452
453     /**
454      * Return if field matching is required.
455      * Field matching is required for custom SQL statements where the result set field order is not known.
456      */

457     public boolean isFieldMatchingRequired() {
458         return isFieldMatchingRequired;
459     }
460
461     /**
462      * Return whether all the results of the call have been returned.
463      */

464     public boolean isFinished() {
465         return !isCursorReturned();
466     }
467
468     /**
469      * Return true for procedures with any output (or in/out) parameters and no cursors
470      */

471     public boolean isNonCursorOutputProcedure() {
472         return !isCursorOutputProcedure() && shouldBuildOutputRow();
473     }
474
475     public boolean isResultSetScrollable() {
476         return isResultSetScrollable;
477     }
478
479     /**
480      * Allow for the field order to be matched if required.
481      * This is required for custom SQL.
482      */

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     /**
491      * INTERNAL:
492      * Allow pre-printing of the SQL string for fully bound calls, to save from reprinting.
493      * Should be called before translation.
494      */

495     public void prepare(AbstractSession session) {
496         if (isPrepared()) {
497             return;
498         }
499
500         prepareInternal(session);
501
502         setIsPrepared(true);
503     }
504
505     /**
506      * INTERNAL:
507      * Called by prepare method only. May be overridden.
508      */

509     protected void prepareInternal(AbstractSession session) {
510         if (isCursorOutputProcedure()) {
511             // 1. If there are no OUT_CURSOR parameters - change the first OUT to OUT_CURSOR;
512
// 2. If there are multiple OUT_CURSOR parameters - throw Validation exception
513
int nFirstOutParameterIndex = -1;
514             boolean hasFoundOutCursor = false;
515             for (int index = 0; index < parameters.size(); index++) {
516                 Integer JavaDoc parameterType = (Integer JavaDoc)parameterTypes.elementAt(index);
517                 if (parameterType == DatasourceCall.OUT_CURSOR) {
518                     if (hasFoundOutCursor) {
519                         // one cursor has been already found
520
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                     // setCustomSQLArgumentType method was called when custom SQL is not used
530
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 JavaDoc parameter = getParameters().elementAt(i);
540             Integer JavaDoc parameterType = (Integer JavaDoc)getParameterTypes().elementAt(i);
541             if (parameterType == MODIFY) {
542                 // in case the field's type is not set, the parameter type is set to CUSTOM_MODIFY.
543
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                 // In case there is a type in outField, outParameter is created.
549
// During translate call, either outParameter or outField is used for
550
// creating inOut parameter.
551
setShouldBuildOutputRow(true);
552                 setIsCallableStatementRequired(true);
553                 DatabaseField outField = (DatabaseField)((Object JavaDoc[])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                     // outParameter contains all the info for registerOutputParameter call.
562
OutputParameterForCallableStatement outParameter = new OutputParameterForCallableStatement(outField, session.getPlatform());
563                     ((Object JavaDoc[])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                 // outParameter contains all the info for registerOutputParameter call.
580
OutputParameterForCallableStatement outParameter = new OutputParameterForCallableStatement(outField, session.getPlatform(), isCursor);
581                 getParameters().setElementAt(outParameter, i);
582                 // nothing to do during translate method
583
getParameterTypes().setElementAt(LITERAL, i);
584             }
585         }
586         if (this.returnsResultSet == FalseUndefinedTrue.Undefined) {
587             setReturnsResultSet(!isCallableStatementRequired());
588         }
589     }
590
591     /**
592      * INTERNAL:
593      * Prepare the JDBC statement, this may be parameterize or a call statement.
594      * If caching statements this must check for the pre-prepared statement and re-bind to it.
595      */

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     /**
615      * The fields expected by the calls result set.
616      */

617     public void setFields(Vector fields) {
618         this.fields = fields;
619     }
620
621     /**
622      * The firstResult set on the result set
623      */

624     public void setFirstResult(int firstResult) {
625         this.firstResult = firstResult;
626     }
627
628     /**
629      * This check is needed only when doing batch writing and we hit on optimistic locking.
630      */

631     public void setHasOptimisticLock(boolean hasOptimisticLock) {
632         this.hasOptimisticLock = hasOptimisticLock;
633     }
634
635     /**
636      * Callable statement is required if there is an output parameter.
637      */

638     protected void setIsCallableStatementRequired(boolean isCallableStatementRequired) {
639         this.isCallableStatementRequired = isCallableStatementRequired;
640     }
641
642     /**
643      * Used for Oracle result sets through procedures.
644      */

645     public void setIsCursorOutputProcedure(boolean isCursorOutputProcedure) {
646         this.isCursorOutputProcedure = isCursorOutputProcedure;
647     }
648
649     /**
650      * Field matching is required for custom SQL statements where the result set field order is not known.
651      */

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     /**
661      * set query max returned row size to the JDBC Statement
662      */

663     public void setMaxRows(int maxRows) {
664         this.maxRows = maxRows;
665     }
666
667     /**
668      * INTERNAL:
669      * Set the query string (SQL) of the call.
670      */

671     public void setQueryString(String JavaDoc queryString) {
672         setSQLStringInternal(queryString);
673     }
674
675     /**
676      * The result set is stored for the return value of cursor selects.
677      */

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     /**
687      * INTERNAL:
688      * Set the SQL string.
689      */

690     protected void setSQLStringInternal(String JavaDoc sqlString) {
691         this.sqlString = sqlString;
692     }
693
694     public void setResultSetType(int resultSetType) {
695         this.resultSetType = resultSetType;
696     }
697
698     /**
699      * PUBLIC:
700      * Use this method to tell TopLink that the stored procedure will be returning a JDBC ResultSet
701      */

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     /**
711      * INTERNAL:
712      * Set whether the call has to build output row
713      */

714     protected void setShouldBuildOutputRow(boolean shouldBuildOutputRow) {
715         this.shouldBuildOutputRow = shouldBuildOutputRow;
716     }
717
718     /**
719      * Bound calls can use prepared statement caching.
720      */

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     /**
730      * The statement is stored for the return value of cursor selects.
731      */

732     public void setStatement(Statement statement) {
733         this.statement = statement;
734     }
735
736     /**
737      * The call may specify that its parameters should be bound.
738      */

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     /**
748      * Set whether the call has to build output row
749      */

750     public boolean shouldBuildOutputRow() {
751         return this.shouldBuildOutputRow;
752     }
753
754     /**
755      * Bound calls can use prepared statement caching.
756      */

757     public boolean shouldCacheStatement(AbstractSession session) {
758         return shouldCacheStatement(session.getPlatform());
759     }
760
761     /**
762      * Bound calls can use prepared statement caching.
763      */

764     public boolean shouldCacheStatement(DatabasePlatform databasePlatform) {
765         //CR4272 If result set is scrollable, do not cache statement since scrollable cursor can not be used for cached statement
766
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     /**
777      * INTERNAL:
778      * Print the SQL string.
779      */

780     public String JavaDoc toString() {
781         String JavaDoc str = Helper.getShortClassName(getClass());
782         if (getSQLString() == null) {
783             return str;
784         } else {
785             return str + "(" + getSQLString() + ")";
786         }
787     }
788
789     /**
790      * INTERNAL:
791      * Allow the call to translate from the translation for predefined calls.
792      */

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 JavaDoc parameter = getParameters().elementAt(index);
801                 Object JavaDoc parameterType = getParameterTypes().elementAt(index);
802                 if (parameterType == MODIFY) {
803                     DatabaseField field = (DatabaseField)parameter;
804                     Object JavaDoc 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 JavaDoc 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 JavaDoc 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) {// Backward compatibility double check.
826
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 JavaDoc value = getValueForInParameter(parameter, translationRow, modifyRow, session, true);
840                     parametersValues.addElement(value);
841                 } else if (parameterType == INOUT) {
842                     Object JavaDoc 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     /**
854      * The call may specify that its parameters should be bound.
855      */

856     public boolean usesBinding(AbstractSession session) {
857         return usesBinding(session.getPlatform());
858     }
859
860     /**
861      * The call may specify that its parameters should be bound.
862      */

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     /**
872      * INTERNAL:
873      * Return if the locator is required for the LOB (BLOB and CLOB) writing.
874      */

875     public boolean isLOBLocatorNeeded() {
876         return contexts != null;
877     }
878
879     /**
880      * INTERNAL:
881      * Add a field - value pair for LOB field into the context.
882      */

883     public void addContext(DatabaseField field, Object JavaDoc value) {
884         if (contexts == null) {
885             contexts = new DatabaseRecord(2);
886         }
887         contexts.add(field, value);
888     }
889
890     /**
891      * INTERNAL:
892      * Return the contexts (for LOB)
893      */

894     public AbstractRecord getContexts() {
895         return contexts;
896     }
897
898     /**
899      * INTERNAL:
900      * Set the contexts (for LOB)
901      */

902     public void setContexts(AbstractRecord contexts) {
903         this.contexts = contexts;
904     }
905
906     /**
907      * PUBLIC:
908      * Used for Oracle result sets through procedures.
909      * The first OUT parameter is set as a cursor output.
910      */

911     public void useUnnamedCursorOutputAsResultSet() {
912         setIsCursorOutputProcedure(true);
913     }
914 }
915
Popular Tags