FileDocCategorySizeDatePackage
DatabaseCall.javaAPI DocGlassfish v2 API32726Tue May 22 16:54:20 BST 2007oracle.toplink.essentials.internal.databaseaccess

DatabaseCall

public abstract class DatabaseCall extends DatasourceCall
INTERNAL: Purpose: Used as an abstraction of a database invocation. A call is an SQL string or procedure call with parameters.

Fields Summary
protected transient Statement
statement
protected transient ResultSet
result
protected int
usesBinding
protected int
shouldCacheStatement
protected transient Vector
fields
protected boolean
isFieldMatchingRequired
protected boolean
hasOptimisticLock
protected boolean
isResultSetScrollable
protected int
resultSetType
protected int
resultSetConcurrency
protected int
queryTimeout
protected int
maxRows
protected int
firstResult
private transient oracle.toplink.essentials.internal.sessions.AbstractRecord
contexts
protected boolean
isCursorOutputProcedure
protected int
returnsResultSet
protected boolean
shouldBuildOutputRow
protected boolean
isCallableStatementRequired
protected String
sqlString
Constructors Summary
public DatabaseCall()


      
        this.usesBinding = FalseUndefinedTrue.Undefined;
        this.shouldCacheStatement = FalseUndefinedTrue.Undefined;
        this.isFieldMatchingRequired = false;
        this.returnType = RETURN_MANY_ROWS;
        this.queryTimeout = 0;
        this.maxRows = 0;
        this.isCursorOutputProcedure = false;
        this.shouldBuildOutputRow = false;
        this.returnsResultSet = FalseUndefinedTrue.Undefined;
    
Methods Summary
public voidaddContext(DatabaseField field, java.lang.Object value)
INTERNAL: Add a field - value pair for LOB field into the context.

        if (contexts == null) {
            contexts = new DatabaseRecord(2);
        }
        contexts.add(field, value);
    
public voidappendIn(java.lang.Object inObject)
INTERNAL:

        getParameters().add(inObject);
        getParameterTypes().add(IN);
    
public voidappendInOut(DatabaseField inoutField)
INTERNAL:

        Object[] inOut = { inoutField, inoutField };
        getParameters().add(inOut);
        getParameterTypes().add(INOUT);
    
public voidappendInOut(java.lang.Object inValueOrField, DatabaseField outField)
INTERNAL:

        Object[] inOut = { inValueOrField, outField };
        getParameters().add(inOut);
        getParameterTypes().add(INOUT);
    
public static voidappendLogParameters(java.util.Collection parameters, Accessor accessor, java.io.StringWriter writer, oracle.toplink.essentials.internal.sessions.AbstractSession session)
Print the parameters to the write for logging purposes.

        writer.write("\tbind => [");
        for (Iterator paramsEnum = parameters.iterator(); paramsEnum.hasNext();) {
            Object parameter = paramsEnum.next();
            if (parameter instanceof DatabaseField) {
                writer.write("null");
            } else {
                if (session != null) {
                    parameter = session.getPlatform().convertToDatabaseType(parameter);
                }
                writer.write(String.valueOf(parameter));
            }
            if (paramsEnum.hasNext()) {
                writer.write(", ");
            } else {
                writer.write("]");
            }
        }
    
public voidappendOut(DatabaseField outField)
INTERNAL:

        getParameters().add(outField);
        getParameterTypes().add(OUT);
    
public voidappendOutCursor(DatabaseField outField)
INTERNAL:

        getParameters().add(outField);
        getParameterTypes().add(OUT_CURSOR);
    
public voidappendParameter(java.io.Writer writer, java.lang.Object parameter, oracle.toplink.essentials.internal.sessions.AbstractSession session)
Add the parameter. If using binding bind the parameter otherwise let the platform print it. The platform may also decide to bind the value.

        if (usesBinding == FalseUndefinedTrue.True) {
            bindParameter(writer, parameter);
        } else {
            session.getPlatform().appendParameter(this, writer, parameter);
        }
    
public voidbindParameter(java.io.Writer writer, java.lang.Object parameter)
Bind the parameter. Binding is determined by the call and second the platform.

        if (parameter instanceof Vector) {
            throw QueryException.inCannotBeParameterized(getQuery());
        }

        try {
            writer.write("?");
        } catch (IOException exception) {
            throw ValidationException.fileError(exception);
        }
        getParameters().addElement(parameter);
    
public DatabaseQueryMechanismbuildNewQueryMechanism(DatabaseQuery query)
Return the appropriate mechanism, with the call added as necessary.

        return new CallQueryMechanism(query, this);
    
public oracle.toplink.essentials.internal.sessions.AbstractRecordbuildOutputRow(java.sql.CallableStatement statement)
INTERNAL: Return DatabaseRow containing output fields and values. Called only if shouldBuildOutputRow method returns true.

        AbstractRecord row = new DatabaseRecord();
        for (int index = 0; index < parameters.size(); index++) {
            Object parameter = parameters.elementAt(index);
            if (parameter instanceof OutputParameterForCallableStatement) {
                OutputParameterForCallableStatement outParameter = (OutputParameterForCallableStatement)parameter;
                if (!outParameter.isCursor()) {
                    Object value = statement.getObject(index + 1);
                    DatabaseField field = outParameter.getOutputField();
                    row.put(field, value);
                }
            }
        }

        return row;
    
public DatabaseQueryMechanismbuildQueryMechanism(DatabaseQuery query, DatabaseQueryMechanism mechanism)
Return the appropriate mechanism, with the call added as necessary.

        if (mechanism.isCallQueryMechanism() && (mechanism instanceof CallQueryMechanism)) {
            // Must also add the call singleton...
            CallQueryMechanism callMechanism = ((CallQueryMechanism)mechanism);
            if (!callMechanism.hasMultipleCalls()) {
                callMechanism.addCall(callMechanism.getCall());
                callMechanism.setCall(null);
            }
            callMechanism.addCall(this);
            return mechanism;
        } else {
            return buildNewQueryMechanism(query);
        }
    
protected java.lang.ObjectcreateInOutParameter(java.lang.Object inValue, java.lang.Object outParameter, oracle.toplink.essentials.internal.sessions.AbstractSession session)
INTERNAL: Returns INOUT parameter. The first parameter is value to pass in, the second DatabaseField for out.

        if (outParameter instanceof OutputParameterForCallableStatement) {
            return new InOutputParameterForCallableStatement(inValue, (OutputParameterForCallableStatement)outParameter);
        }
        if (outParameter instanceof DatabaseField) {
            return new InOutputParameterForCallableStatement(inValue, (DatabaseField)outParameter, session.getPlatform());
        }

        //should never happen
        return null;
    
public java.lang.StringgetCallString()
INTERNAL: Return the SQL string for the call.

        return getSQLString();
    
public oracle.toplink.essentials.internal.sessions.AbstractRecordgetContexts()
INTERNAL: Return the contexts (for LOB)

        return contexts;
    
public intgetCursorOutIndex()
INTERNAL: Return 1-based index of out cursor parameter, or -1.

        for (int i = 0; i < getParameters().size(); i++) {
            Object parameter = getParameters().elementAt(i);
            if (parameter instanceof OutputParameterForCallableStatement) {
                if (((OutputParameterForCallableStatement)parameter).isCursor()) {
                    return i + 1;
                }
            }
        }
        return -1;
    
protected DatabaseFieldgetFieldWithTypeFromDescriptor(DatabaseField outField)
INTERNAL: Unfortunately can't avoid referencing query and descriptor: the call should be performed after the translateCustomSQL (in SQLCall) in the middle of prepare method (no parameter available earlier).

        if (getQuery().getDescriptor() != null) {
            return getQuery().getDescriptor().getTypedField(outField);
        } else {
            return null;
        }
    
public java.util.VectorgetFields()
The fields expected by the calls result set. null means that the fields are unknown and should be built from the result set.

        return fields;
    
public intgetFirstResult()
get first result

        return this.firstResult;
    
public java.lang.StringgetLogString(Accessor accessor)
Return the SQL string for logging purposes.

        if (hasParameters()) {
            StringWriter writer = new StringWriter();
            writer.write(getSQLString());
            writer.write(Helper.cr());
            if (hasParameters()) {
                AbstractSession session = null;
                if (getQuery() != null) {
                    session = getQuery().getSession();
                }
                appendLogParameters(getParameters(), accessor, writer, session);
            }
            return writer.toString();
        } else {
            return getSQLString();
        }
    
public intgetMaxRows()
get max rows returned from the call

        return this.maxRows;
    
public java.util.VectorgetOutputRowFields()
INTERNAL Returns the fields to be used in output row.

        Vector fields = new Vector();
        for (int i = 0; i < getParameters().size(); i++) {
            Integer parameterType = (Integer)getParameterTypes().elementAt(i);
            Object parameter = getParameters().elementAt(i);
            if (parameterType == OUT) {
                fields.add(parameter);
            } else if (parameterType == INOUT) {
                fields.add(((Object[])parameter)[1]);
            }
        }
        return fields;
    
public java.lang.StringgetQueryString()
INTERNAL: Return the query string (SQL) of the call.

        return getSQLString();
    
public java.sql.ResultSetgetResult()
The result set is stored for the return value of cursor selects.

        return result;
    
public intgetResultSetConcurrency()

        return resultSetConcurrency;
    
public intgetResultSetType()

        return resultSetType;
    
public booleangetReturnsResultSet()
ADVANCED: This method returns a value that represents if the customer has set whether or not TopLink should expect the stored procedure to returning a JDBC ResultSet. The result of the method corresponds to false, true.

        if (returnsResultSet == FalseUndefinedTrue.Undefined) {
            return !shouldBuildOutputRow();
        } else {
            return returnsResultSet == FalseUndefinedTrue.True;
        }
    
public java.lang.StringgetSQLString()
Return the SQL string that will be executed.

        return sqlString;
    
public java.sql.StatementgetStatement()
The statement is stored for the return value of cursor selects.

        return statement;
    
public booleanhasOptimisticLock()
This check is needed only when doing batch writing.

        return hasOptimisticLock;
    
protected booleanisCallableStatementRequired()
Callable statement is required if there is an output parameter.

        return isCallableStatementRequired;
    
public booleanisCursorOutputProcedure()
Used for Oracle result sets through procedures.

        return isCursorOutputProcedure;
    
public booleanisCursorReturned()
The return type is one of, NoReturn, ReturnOneRow or ReturnManyRows.

        return getReturnType() == RETURN_CURSOR;
    
protected booleanisDynamicCall(oracle.toplink.essentials.internal.sessions.AbstractSession session)
Return if the call is dynamic SQL call. This means the call has no parameters, is not using binding, is not a stored procedure (CallableStatement), or cursor. This means that a Statement, not PrepareStatement will be used for the call.

        return DatabaseAccessor.shouldUseDynamicStatements && (!usesBinding(session)) && (!isResultSetScrollable()) && (!hasParameters());
    
public booleanisFieldMatchingRequired()
Return if field matching is required. Field matching is required for custom SQL statements where the result set field order is not known.

        return isFieldMatchingRequired;
    
public booleanisFinished()
Return whether all the results of the call have been returned.

        return !isCursorReturned();
    
public booleanisLOBLocatorNeeded()
INTERNAL: Return if the locator is required for the LOB (BLOB and CLOB) writing.

        return contexts != null;
    
public booleanisNonCursorOutputProcedure()
Return true for procedures with any output (or in/out) parameters and no cursors

        return !isCursorOutputProcedure() && shouldBuildOutputRow();
    
public booleanisResultSetScrollable()

        return isResultSetScrollable;
    
public voidmatchFieldOrder(java.sql.ResultSet resultSet, DatabaseAccessor accessor, oracle.toplink.essentials.internal.sessions.AbstractSession session)
Allow for the field order to be matched if required. This is required for custom SQL.

        if ((getFields() != null) && (!isFieldMatchingRequired())) {
            return;
        }
        setFields(accessor.buildSortedFields(getFields(), resultSet, session));
    
public voidprepare(oracle.toplink.essentials.internal.sessions.AbstractSession session)
INTERNAL: Allow pre-printing of the SQL string for fully bound calls, to save from reprinting. Should be called before translation.

        if (isPrepared()) {
            return;
        }

        prepareInternal(session);

        setIsPrepared(true);
    
protected voidprepareInternal(oracle.toplink.essentials.internal.sessions.AbstractSession session)
INTERNAL: Called by prepare method only. May be overridden.

        if (isCursorOutputProcedure()) {
            // 1. If there are no OUT_CURSOR parameters - change the first OUT to OUT_CURSOR;
            // 2. If there are multiple OUT_CURSOR parameters - throw Validation exception
            int nFirstOutParameterIndex = -1;
            boolean hasFoundOutCursor = false;
            for (int index = 0; index < parameters.size(); index++) {
                Integer parameterType = (Integer)parameterTypes.elementAt(index);
                if (parameterType == DatasourceCall.OUT_CURSOR) {
                    if (hasFoundOutCursor) {
                        // one cursor has been already found
                        throw ValidationException.multipleCursorsNotSupported(toString());
                    } else {
                        hasFoundOutCursor = true;
                    }
                } else if (parameterType == DatasourceCall.OUT) {
                    if (nFirstOutParameterIndex == -1) {
                        nFirstOutParameterIndex = index;
                    }
                } else if (parameterType == null) {
                    // setCustomSQLArgumentType method was called when custom SQL is not used
                    throw ValidationException.wrongUsageOfSetCustomArgumentTypeMethod(toString());
                }
            }
            if (!hasFoundOutCursor && (nFirstOutParameterIndex >= 0)) {
                parameterTypes.setElementAt(DatasourceCall.OUT_CURSOR, nFirstOutParameterIndex);
            }
        }

        for (int i = 0; i < getParameters().size(); i++) {
            Object parameter = getParameters().elementAt(i);
            Integer parameterType = (Integer)getParameterTypes().elementAt(i);
            if (parameterType == MODIFY) {
                // in case the field's type is not set, the parameter type is set to CUSTOM_MODIFY.
                DatabaseField field = (DatabaseField)parameter;
                if ((field.getType() == null) || session.getPlatform().shouldUseCustomModifyForCall(field)) {
                    getParameterTypes().setElementAt(CUSTOM_MODIFY, i);
                }
            } else if (parameterType == INOUT) {
                // In case there is a type in outField, outParameter is created.
                // During translate call, either outParameter or outField is used for
                // creating inOut parameter.
                setShouldBuildOutputRow(true);
                setIsCallableStatementRequired(true);
                DatabaseField outField = (DatabaseField)((Object[])parameter)[1];
                if (outField.getType() == null) {
                    DatabaseField typeOutField = getFieldWithTypeFromDescriptor(outField);
                    if (typeOutField != null) {
                        outField = (DatabaseField)typeOutField.clone();
                    }
                }
                if (outField.getType() != null) {
                    // outParameter contains all the info for registerOutputParameter call.
                    OutputParameterForCallableStatement outParameter = new OutputParameterForCallableStatement(outField, session.getPlatform());
                    ((Object[])parameter)[1] = outParameter;
                }
            } else if ((parameterType == OUT) || (parameterType == OUT_CURSOR)) {
                boolean isCursor = parameterType == OUT_CURSOR;
                if (!isCursor) {
                    setShouldBuildOutputRow(true);
                }
                setIsCallableStatementRequired(true);
                DatabaseField outField = (DatabaseField)parameter;
                if (outField.getType() == null) {
                    DatabaseField typeOutField = getFieldWithTypeFromDescriptor(outField);
                    if (typeOutField != null) {
                        outField = (DatabaseField)typeOutField.clone();
                    }
                }

                // outParameter contains all the info for registerOutputParameter call.
                OutputParameterForCallableStatement outParameter = new OutputParameterForCallableStatement(outField, session.getPlatform(), isCursor);
                getParameters().setElementAt(outParameter, i);
                // nothing to do during translate method
                getParameterTypes().setElementAt(LITERAL, i);
            }
        }
        if (this.returnsResultSet == FalseUndefinedTrue.Undefined) {
            setReturnsResultSet(!isCallableStatementRequired());
        }
    
public java.sql.StatementprepareStatement(DatabaseAccessor accessor, oracle.toplink.essentials.internal.sessions.AbstractRecord translationRow, oracle.toplink.essentials.internal.sessions.AbstractSession session)
INTERNAL: Prepare the JDBC statement, this may be parameterize or a call statement. If caching statements this must check for the pre-prepared statement and re-bind to it.

        Statement statement = accessor.prepareStatement(this, session);

        if (getMaxRows() > 0) { 
            statement.setMaxRows(getMaxRows()); 
        }

        if (!hasParameters()) {
            return statement;
        }

        for (int index = 0; index < getParameters().size(); index++) {
            session.getPlatform().setParameterValueInDatabaseCall(this.getParameters(), (PreparedStatement)statement, index, session);
        }

        return statement;
    
public voidsetContexts(oracle.toplink.essentials.internal.sessions.AbstractRecord contexts)
INTERNAL: Set the contexts (for LOB)

        this.contexts = contexts;
    
public voidsetFields(java.util.Vector fields)
The fields expected by the calls result set.

        this.fields = fields;
    
public voidsetFirstResult(int firstResult)
The firstResult set on the result set

        this.firstResult = firstResult;
    
public voidsetHasOptimisticLock(boolean hasOptimisticLock)
This check is needed only when doing batch writing and we hit on optimistic locking.

        this.hasOptimisticLock = hasOptimisticLock;
    
protected voidsetIsCallableStatementRequired(boolean isCallableStatementRequired)
Callable statement is required if there is an output parameter.

        this.isCallableStatementRequired = isCallableStatementRequired;
    
public voidsetIsCursorOutputProcedure(boolean isCursorOutputProcedure)
Used for Oracle result sets through procedures.

        this.isCursorOutputProcedure = isCursorOutputProcedure;
    
public voidsetIsFieldMatchingRequired(boolean isFieldMatchingRequired)
Field matching is required for custom SQL statements where the result set field order is not known.

        this.isFieldMatchingRequired = isFieldMatchingRequired;
    
public voidsetIsResultSetScrollable(boolean isResultSetScrollable)

        this.isResultSetScrollable = isResultSetScrollable;
    
public voidsetMaxRows(int maxRows)
set query max returned row size to the JDBC Statement

        this.maxRows = maxRows;
    
public voidsetQueryString(java.lang.String queryString)
INTERNAL: Set the query string (SQL) of the call.

        setSQLStringInternal(queryString);
    
public voidsetResult(java.sql.ResultSet result)
The result set is stored for the return value of cursor selects.

        this.result = result;
    
public voidsetResultSetConcurrency(int resultSetConcurrency)

        this.resultSetConcurrency = resultSetConcurrency;
    
public voidsetResultSetType(int resultSetType)

        this.resultSetType = resultSetType;
    
public voidsetReturnsResultSet(boolean returnsResultSet)
PUBLIC: Use this method to tell TopLink that the stored procedure will be returning a JDBC ResultSet

        if (returnsResultSet) {
            this.returnsResultSet = FalseUndefinedTrue.True;
        } else {
            this.returnsResultSet = FalseUndefinedTrue.False;
        }
    
protected voidsetSQLStringInternal(java.lang.String sqlString)
INTERNAL: Set the SQL string.

        this.sqlString = sqlString;
    
protected voidsetShouldBuildOutputRow(boolean shouldBuildOutputRow)
INTERNAL: Set whether the call has to build output row

        this.shouldBuildOutputRow = shouldBuildOutputRow;
    
public voidsetShouldCacheStatement(boolean shouldCacheStatement)
Bound calls can use prepared statement caching.

        if (shouldCacheStatement) {
            this.shouldCacheStatement = FalseUndefinedTrue.True;
        } else {
            this.shouldCacheStatement = FalseUndefinedTrue.False;
        }
    
public voidsetStatement(java.sql.Statement statement)
The statement is stored for the return value of cursor selects.

        this.statement = statement;
    
public voidsetUsesBinding(boolean usesBinding)
The call may specify that its parameters should be bound.

        if (usesBinding) {
            this.usesBinding = FalseUndefinedTrue.True;
        } else {
            this.usesBinding = FalseUndefinedTrue.False;
        }
    
public booleanshouldBuildOutputRow()
Set whether the call has to build output row

        return this.shouldBuildOutputRow;
    
public booleanshouldCacheStatement(oracle.toplink.essentials.internal.sessions.AbstractSession session)
Bound calls can use prepared statement caching.

        return shouldCacheStatement(session.getPlatform());
    
public booleanshouldCacheStatement(DatabasePlatform databasePlatform)
Bound calls can use prepared statement caching.

        //CR4272  If result set is scrollable, do not cache statement since scrollable cursor can not be used for cached statement
        if (isResultSetScrollable()) {
            return false;
        }
        if (shouldCacheStatement == FalseUndefinedTrue.Undefined) {
            return databasePlatform.shouldCacheAllStatements();
        } else {
            return shouldCacheStatement == FalseUndefinedTrue.True;
        }
    
public java.lang.StringtoString()
INTERNAL: Print the SQL string.

        String str = Helper.getShortClassName(getClass());
        if (getSQLString() == null) {
            return str;
        } else {
            return str + "(" + getSQLString() + ")";
        }
    
public voidtranslate(oracle.toplink.essentials.internal.sessions.AbstractRecord translationRow, oracle.toplink.essentials.internal.sessions.AbstractRecord modifyRow, oracle.toplink.essentials.internal.sessions.AbstractSession session)
INTERNAL: Allow the call to translate from the translation for predefined calls.

        if (!isPrepared()) {
            throw ValidationException.cannotTranslateUnpreparedCall(toString());
        }
        if (usesBinding(session)) {
            Vector parametersValues = new Vector();
            for (int index = 0; index < getParameters().size(); index++) {
                Object parameter = getParameters().elementAt(index);
                Object parameterType = getParameterTypes().elementAt(index);
                if (parameterType == MODIFY) {
                    DatabaseField field = (DatabaseField)parameter;
                    Object value = modifyRow.get(field);
                    if (value == null) {
                        value = modifyRow.getField(field);
                    }
                    parametersValues.addElement(value);
                } else if (parameterType == CUSTOM_MODIFY) {
                    DatabaseField field = (DatabaseField)parameter;
                    Object value = modifyRow.get(field);
                    value = session.getPlatform().getCustomModifyValueForCall(this, value, field, true);
                    if (value == null) {
                        value = modifyRow.getField(field);
                    }
                    parametersValues.addElement(value);
                } else if (parameterType == TRANSLATION) {
                    Object value = null;
                    DatabaseField field = null;
                    if (parameter instanceof ParameterExpression) {
                        value = ((ParameterExpression)parameter).getValue(translationRow, session);
                    } else {
                        field = (DatabaseField)parameter;
                        value = translationRow.get(field);
                        if (value == null) {// Backward compatibility double check.
                            value = modifyRow.get(field);
                        }
                    }
                    if (value instanceof Vector) {
                        throw QueryException.inCannotBeParameterized(getQuery());
                    }
                    if ((value == null) && (field != null)) {
                        value = translationRow.getField(field);
                    }
                    parametersValues.addElement(value);
                } else if (parameterType == LITERAL) {
                    parametersValues.addElement(parameter);
                } else if (parameterType == IN) {
                    Object value = getValueForInParameter(parameter, translationRow, modifyRow, session, true);
                    parametersValues.addElement(value);
                } else if (parameterType == INOUT) {
                    Object value = getValueForInOutParameter(parameter, translationRow, modifyRow, session);
                    parametersValues.addElement(value);
                }
            }
            setParameters(parametersValues);
            return;
        }

        translateQueryString(translationRow, modifyRow, session);
    
public voiduseUnnamedCursorOutputAsResultSet()
PUBLIC: Used for Oracle result sets through procedures. The first OUT parameter is set as a cursor output.

        setIsCursorOutputProcedure(true);
    
public booleanusesBinding(oracle.toplink.essentials.internal.sessions.AbstractSession session)
The call may specify that its parameters should be bound.

        return usesBinding(session.getPlatform());
    
public booleanusesBinding(DatabasePlatform databasePlatform)
The call may specify that its parameters should be bound.

        if (usesBinding == FalseUndefinedTrue.Undefined) {
            return databasePlatform.shouldBindAllParameters();
        } else {
            return usesBinding == FalseUndefinedTrue.True;
        }