Logo Search packages:      
Sourcecode: mysql-connector-java version File versions  Download package

CallableStatement.java

/*
  Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.

  The MySQL Connector/J is licensed under the terms of the GPLv2
  <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
  There are special exceptions to the terms and conditions of the GPLv2 as it is applied to
  this software, see the FLOSS License Exception
  <http://www.mysql.com/about/legal/licensing/foss-exception.html>.

  This program is free software; you can redistribute it and/or modify it under the terms
  of the GNU General Public License as published by the Free Software Foundation; version 2
  of the License.

  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the GNU General Public License for more details.

  You should have received a copy of the GNU General Public License along with this
  program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth
  Floor, Boston, MA 02110-1301  USA
 
 */
package com.mysql.jdbc;

import java.io.InputStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.Array;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Date;
import java.sql.ParameterMetaData;
import java.sql.Ref;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Representation of stored procedures for JDBC
 * 
 * @author Mark Matthews
 * @version $Id: CallableStatement.java,v 1.1.2.1 2005/05/13 18:58:38 mmatthews
 *          Exp $
 */
00057 public class CallableStatement extends PreparedStatement implements
            java.sql.CallableStatement {
      protected final static Constructor JDBC_4_CSTMT_2_ARGS_CTOR;
      
      protected final static Constructor JDBC_4_CSTMT_4_ARGS_CTOR;
      
      static {
            if (Util.isJdbc4()) {
                  try {
                        JDBC_4_CSTMT_2_ARGS_CTOR = Class.forName(
                                    "com.mysql.jdbc.JDBC4CallableStatement")
                                    .getConstructor(
                                                new Class[] { MySQLConnection.class,
                                                            CallableStatementParamInfo.class });
                        JDBC_4_CSTMT_4_ARGS_CTOR = Class.forName(
                                    "com.mysql.jdbc.JDBC4CallableStatement")
                                    .getConstructor(
                                                new Class[] { MySQLConnection.class,
                                                            String.class, String.class,
                                                            Boolean.TYPE });
                  } catch (SecurityException e) {
                        throw new RuntimeException(e);
                  } catch (NoSuchMethodException e) {
                        throw new RuntimeException(e);
                  } catch (ClassNotFoundException e) {
                        throw new RuntimeException(e);
                  }
            } else {
                  JDBC_4_CSTMT_4_ARGS_CTOR = null;
                  JDBC_4_CSTMT_2_ARGS_CTOR = null;
            }
      }
      
00090       protected static class CallableStatementParam {
            int desiredJdbcType;

            int index;

            int inOutModifier;

            boolean isIn;

            boolean isOut;

            int jdbcType;

            short nullability;

            String paramName;

            int precision;

            int scale;

            String typeName;

            CallableStatementParam(String name, int idx, boolean in, boolean out,
                        int jdbcType, String typeName, int precision, int scale,
                        short nullability, int inOutModifier) {
                  this.paramName = name;
                  this.isIn = in;
                  this.isOut = out;
                  this.index = idx;

                  this.jdbcType = jdbcType;
                  this.typeName = typeName;
                  this.precision = precision;
                  this.scale = scale;
                  this.nullability = nullability;
                  this.inOutModifier = inOutModifier;
            }

            /*
             * (non-Javadoc)
             * 
             * @see java.lang.Object#clone()
             */
            protected Object clone() throws CloneNotSupportedException {
                  return super.clone();
            }
      }

00139       protected class CallableStatementParamInfo {
            String catalogInUse;

            boolean isFunctionCall;

            String nativeSql;

            int numParameters;

            List parameterList;

            Map parameterMap;

            
            /**
             * synchronized externally in checkReadOnlyProcedure()
             */
00156             boolean isReadOnlySafeProcedure = false;
            
            /**
             * synchronized externally in checkReadOnlyProcedure()
             */
00161             boolean isReadOnlySafeChecked = false;

            /**
             * Constructor that converts a full list of parameter metadata into one
             * that only represents the placeholders present in the {CALL ()}.
             * 
             * @param fullParamInfo the metadata for all parameters for this stored 
             * procedure or function.
             */
00170             CallableStatementParamInfo(CallableStatementParamInfo fullParamInfo) {
                  this.nativeSql = originalSql;
                  this.catalogInUse = currentCatalog;
                  isFunctionCall = fullParamInfo.isFunctionCall;
                  int[] localParameterMap = placeholderToParameterIndexMap;
                  int parameterMapLength = localParameterMap.length;
                  
                  this.isReadOnlySafeProcedure = fullParamInfo.isReadOnlySafeProcedure;
                  this.isReadOnlySafeChecked = fullParamInfo.isReadOnlySafeChecked;
                  parameterList = new ArrayList(fullParamInfo.numParameters);
                  parameterMap = new HashMap(fullParamInfo.numParameters);
                  
                  if (isFunctionCall) {
                        // Take the return value
                        parameterList.add(fullParamInfo.parameterList.get(0));
                  }
                  
                  int offset = isFunctionCall ? 1 : 0;
                  
                  for (int i = 0; i < parameterMapLength; i++) {
                        if (localParameterMap[i] != 0) {
                              CallableStatementParam param = (CallableStatementParam)fullParamInfo.parameterList.get(localParameterMap[i] + offset);
                              
                              parameterList.add(param);
                              parameterMap.put(param.paramName, param);
                        }
                  }
                  
                  this.numParameters = parameterList.size();
            }
            
            CallableStatementParamInfo(java.sql.ResultSet paramTypesRs)
                        throws SQLException {
                  boolean hadRows = paramTypesRs.last();

                  this.nativeSql = originalSql;
                  this.catalogInUse = currentCatalog;
                  isFunctionCall = callingStoredFunction;

                  if (hadRows) {
                        this.numParameters = paramTypesRs.getRow();

                        this.parameterList = new ArrayList(this.numParameters);
                        this.parameterMap = new HashMap(this.numParameters);

                        paramTypesRs.beforeFirst();

                        addParametersFromDBMD(paramTypesRs);
                  } else {
                        this.numParameters = 0;
                  }
                  
                  if (isFunctionCall) {
                        this.numParameters += 1;
            }
            }

            private void addParametersFromDBMD(java.sql.ResultSet paramTypesRs)
                        throws SQLException {
                  int i = 0;

                  while (paramTypesRs.next()) {
                        String paramName = paramTypesRs.getString(4);
                        int inOutModifier = paramTypesRs.getInt(5);

                        boolean isOutParameter = false;
                        boolean isInParameter = false;

                        if (i == 0 && isFunctionCall) {
                              isOutParameter = true;
                              isInParameter = false;
                        } else if (inOutModifier == DatabaseMetaData.procedureColumnInOut) {
                              isOutParameter = true;
                              isInParameter = true;
                        } else if (inOutModifier == DatabaseMetaData.procedureColumnIn) {
                              isOutParameter = false;
                              isInParameter = true;
                        } else if (inOutModifier == DatabaseMetaData.procedureColumnOut) {
                              isOutParameter = true;
                              isInParameter = false;
                        }

                        int jdbcType = paramTypesRs.getInt(6);
                        String typeName = paramTypesRs.getString(7);
                        int precision = paramTypesRs.getInt(8);
                        int scale = paramTypesRs.getInt(10);
                        short nullability = paramTypesRs.getShort(12);

                        CallableStatementParam paramInfoToAdd = new CallableStatementParam(
                                    paramName, i++, isInParameter, isOutParameter,
                                    jdbcType, typeName, precision, scale, nullability,
                                    inOutModifier);

                        this.parameterList.add(paramInfoToAdd);
                        this.parameterMap.put(paramName, paramInfoToAdd);
                  }
            }

            protected void checkBounds(int paramIndex) throws SQLException {
                  int localParamIndex = paramIndex - 1;

                  if ((paramIndex < 0) || (localParamIndex >= this.numParameters)) {
                        throw SQLError.createSQLException(
                                    Messages.getString("CallableStatement.11") + paramIndex //$NON-NLS-1$
                                                + Messages.getString("CallableStatement.12") + numParameters //$NON-NLS-1$
                                                + Messages.getString("CallableStatement.13"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
                  }
            }

            /*
             * (non-Javadoc)
             * 
             * @see java.lang.Object#clone()
             */
            protected Object clone() throws CloneNotSupportedException {
                  return super.clone();
            }

            CallableStatementParam getParameter(int index) {
                  return (CallableStatementParam) this.parameterList.get(index);
            }

            CallableStatementParam getParameter(String name) {
                  return (CallableStatementParam) this.parameterMap.get(name);
            }

            public String getParameterClassName(int arg0) throws SQLException {
                  String mysqlTypeName = getParameterTypeName(arg0);
                  
                  boolean isBinaryOrBlob = StringUtils.indexOfIgnoreCase(mysqlTypeName, "BLOB") != -1 || 
                        StringUtils.indexOfIgnoreCase(mysqlTypeName, "BINARY") != -1;
                  
                  boolean isUnsigned = StringUtils.indexOfIgnoreCase(mysqlTypeName, "UNSIGNED") != -1;
                  
                  int mysqlTypeIfKnown = 0;
                  
                  if (StringUtils.startsWithIgnoreCase(mysqlTypeName, "MEDIUMINT")) {
                        mysqlTypeIfKnown = MysqlDefs.FIELD_TYPE_INT24;
                  }
                  
                  return ResultSetMetaData.getClassNameForJavaType(getParameterType(arg0), 
                              isUnsigned, mysqlTypeIfKnown, isBinaryOrBlob, false);
            }

            public int getParameterCount() throws SQLException {
                  if (this.parameterList == null) {
                        return 0;
                  }
                  
                  return this.parameterList.size();
            }

            public int getParameterMode(int arg0) throws SQLException {
                  checkBounds(arg0);

                  return getParameter(arg0 - 1).inOutModifier;
            }

            public int getParameterType(int arg0) throws SQLException {
                  checkBounds(arg0);

                  return getParameter(arg0 - 1).jdbcType;
            }

            public String getParameterTypeName(int arg0) throws SQLException {
                  checkBounds(arg0);

                  return getParameter(arg0 - 1).typeName;
            }

            public int getPrecision(int arg0) throws SQLException {
                  checkBounds(arg0);

                  return getParameter(arg0 - 1).precision;
            }

            public int getScale(int arg0) throws SQLException {
                  checkBounds(arg0);

                  return getParameter(arg0 - 1).scale;
            }

            public int isNullable(int arg0) throws SQLException {
                  checkBounds(arg0);

                  return getParameter(arg0 - 1).nullability;
            }

            public boolean isSigned(int arg0) throws SQLException {
                  checkBounds(arg0);

                  return false;
            }

            Iterator iterator() {
                  return this.parameterList.iterator();
            }

            int numberOfParameters() {
                  return this.numParameters;
            }
      }

      /**
       * Can't implement this directly, as then you can't use callable statements
       * on JDK-1.3.1, which unfortunately isn't EOL'd yet, and still present
       * quite a bit out there in the wild (Websphere, FreeBSD, anyone?)
       */

00379       protected class CallableStatementParamInfoJDBC3 extends CallableStatementParamInfo
                  implements ParameterMetaData {

            CallableStatementParamInfoJDBC3(java.sql.ResultSet paramTypesRs)
                        throws SQLException {
                  super(paramTypesRs);
            }

            public CallableStatementParamInfoJDBC3(CallableStatementParamInfo paramInfo) {
                  super(paramInfo);
            }
            
            /**
           * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
           * for an object that does. Returns false otherwise. If this implements the interface then return true,
           * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped
           * object. If this does not implement the interface and is not a wrapper, return false.
           * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that
           * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method
           * returns true then calling <code>unwrap</code> with the same argument should succeed.
           *
           * @param interfaces a Class defining an interface.
           * @return true if this implements the interface or directly or indirectly wraps an object that does.
           * @throws java.sql.SQLException  if an error occurs while determining whether this is a wrapper
           * for an object with the given interface.
           * @since 1.6
           */
00406             public boolean isWrapperFor(Class iface) throws SQLException {
                  checkClosed();
                  
                  // This works for classes that aren't actually wrapping
                  // anything
                  return iface.isInstance(this);
            }

          /**
           * Returns an object that implements the given interface to allow access to non-standard methods,
           * or standard methods not exposed by the proxy.
           * The result may be either the object found to implement the interface or a proxy for that object.
           * If the receiver implements the interface then that is the object. If the receiver is a wrapper
           * and the wrapped object implements the interface then that is the object. Otherwise the object is
           *  the result of calling <code>unwrap</code> recursively on the wrapped object. If the receiver is not a
           * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown.
           *
           * @param iface A Class defining an interface that the result must implement.
           * @return an object that implements the interface. May be a proxy for the actual implementing object.
           * @throws java.sql.SQLException If no object found that implements the interface 
           * @since 1.6
           */
00428             public Object unwrap(Class iface) throws java.sql.SQLException {
            try {
                  // This works for classes that aren't actually wrapping
                  // anything
                  return Util.cast(iface, this);
              } catch (ClassCastException cce) {
                  throw SQLError.createSQLException("Unable to unwrap to " + iface.toString(), 
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
              }
          }
      }

      private final static int NOT_OUTPUT_PARAMETER_INDICATOR = Integer.MIN_VALUE;

      private final static String PARAMETER_NAMESPACE_PREFIX = "@com_mysql_jdbc_outparam_"; //$NON-NLS-1$

      private static String mangleParameterName(String origParameterName) {
            //Fixed for 5.5+ in callers
            if (origParameterName == null) {
                  return null;
            }

            int offset = 0;

            if (origParameterName.length() > 0
                        && origParameterName.charAt(0) == '@') {
                  offset = 1;
            }

            StringBuffer paramNameBuf = new StringBuffer(PARAMETER_NAMESPACE_PREFIX
                        .length()
                        + origParameterName.length());
            paramNameBuf.append(PARAMETER_NAMESPACE_PREFIX);
            paramNameBuf.append(origParameterName.substring(offset));

            return paramNameBuf.toString();
      }

      private boolean callingStoredFunction = false;

      private ResultSetInternalMethods functionReturnValueResults;

      private boolean hasOutputParams = false;

      // private List parameterList;
      // private Map parameterMap;
      private ResultSetInternalMethods outputParameterResults;

      protected boolean outputParamWasNull = false;

      private int[] parameterIndexToRsIndex;

      protected CallableStatementParamInfo paramInfo;

      private CallableStatementParam returnValueParam;
      
      /**
       * Creates a new CallableStatement
       * 
       * @param conn
       *            the connection creating this statement
       * @param paramInfo
       *            the SQL to prepare
       * 
       * @throws SQLException
       *             if an error occurs
       */
00495       public CallableStatement(MySQLConnection conn,
                  CallableStatementParamInfo paramInfo) throws SQLException {
            super(conn, paramInfo.nativeSql, paramInfo.catalogInUse);

            this.paramInfo = paramInfo;
            this.callingStoredFunction = this.paramInfo.isFunctionCall;
            
            if (this.callingStoredFunction) {
                  this.parameterCount += 1;
            }
            
            this.retrieveGeneratedKeys = true; // not provided for in the JDBC spec
      }

      /**
       * Creates a callable statement instance -- We need to provide factory-style methods
       * so we can support both JDBC3 (and older) and JDBC4 runtimes, otherwise
       * the class verifier complains when it tries to load JDBC4-only interface
       * classes that are present in JDBC4 method signatures.
       */

00516       protected static CallableStatement getInstance(MySQLConnection conn, String sql,
                  String catalog, boolean isFunctionCall) throws SQLException {
            if (!Util.isJdbc4()) {
                  return new CallableStatement(conn, sql, catalog, isFunctionCall);
            }

            return (CallableStatement) Util.handleNewInstance(
                        JDBC_4_CSTMT_4_ARGS_CTOR, new Object[] { conn, sql, catalog,
                                    Boolean.valueOf(isFunctionCall) }, conn.getExceptionInterceptor());
      }
      
      /**
       * Creates a callable statement instance -- We need to provide factory-style methods
       * so we can support both JDBC3 (and older) and JDBC4 runtimes, otherwise
       * the class verifier complains when it tries to load JDBC4-only interface
       * classes that are present in JDBC4 method signatures.
       */

00534       protected static CallableStatement getInstance(MySQLConnection conn,
                  CallableStatementParamInfo paramInfo) throws SQLException {
            if (!Util.isJdbc4()) {
                  return new CallableStatement(conn, paramInfo);
            }

            return (CallableStatement) Util.handleNewInstance(
                        JDBC_4_CSTMT_2_ARGS_CTOR, new Object[] { conn, paramInfo }, conn.getExceptionInterceptor());

      }
      
      private int[] placeholderToParameterIndexMap;
      
      private synchronized void generateParameterMap() throws SQLException {
            if (this.paramInfo == null) {
                  return;
            }
            
            // if the user specified some parameters as literals, we need to
            // provide a map from the specified placeholders to the actual
            // parameter numbers
            
            int parameterCountFromMetaData = this.paramInfo.getParameterCount();
            
            // Ignore the first ? if this is a stored function, it doesn't count
            
            if (this.callingStoredFunction) {
                  parameterCountFromMetaData--;
            }
            
            if (this.paramInfo != null &&
                        this.parameterCount != parameterCountFromMetaData) {
                  this.placeholderToParameterIndexMap = new int[this.parameterCount];
                  
                  int startPos = this.callingStoredFunction ? StringUtils.indexOfIgnoreCase(this.originalSql, 
                  "SELECT") : StringUtils.indexOfIgnoreCase(this.originalSql, "CALL");
                  
                  if (startPos != -1) {
                        int parenOpenPos = this.originalSql.indexOf('(', startPos + 4);
                        
                        if (parenOpenPos != -1) {
                              int parenClosePos = StringUtils.indexOfIgnoreCaseRespectQuotes(parenOpenPos, 
                                          this.originalSql, ")", '\'', true);
                              
                              if (parenClosePos != -1) {
                                    List parsedParameters = StringUtils.split(this.originalSql.substring(parenOpenPos + 1, parenClosePos), ",", "'\"", "'\"", true);
                                    
                                    int numParsedParameters = parsedParameters.size();
                                    
                                    // sanity check
                                    
                                    if (numParsedParameters != this.parameterCount) {
                                          // bail?
                                    }
                                    
                                    int placeholderCount = 0;
                                    
                                    for (int i = 0; i < numParsedParameters; i++) {
                                          if (((String)parsedParameters.get(i)).equals("?")) {
                                                this.placeholderToParameterIndexMap[placeholderCount++] = i;
                                          }
                                    }
                              }
                        }
                  }
            }
      }
      
      /**
       * Creates a new CallableStatement
       * 
       * @param conn
       *            the connection creating this statement
       * @param sql
       *            the SQL to prepare
       * @param catalog
       *            the current catalog
       * 
       * @throws SQLException
       *             if an error occurs
       */
00615       public CallableStatement(MySQLConnection conn, String sql, String catalog,
                  boolean isFunctionCall) throws SQLException {
            super(conn, sql, catalog);

            this.callingStoredFunction = isFunctionCall;

            if (!this.callingStoredFunction) {
                  if (!StringUtils.startsWithIgnoreCaseAndWs(sql, "CALL")) {
                        // not really a stored procedure call
                        fakeParameterTypes(false);
                  } else {
                        determineParameterTypes();
                  }
                  
                  generateParameterMap();
            } else {
                  determineParameterTypes();
                  generateParameterMap();
                  
                  this.parameterCount += 1;
            }
            
            this.retrieveGeneratedKeys = true; // not provided for in the JDBC spec
      }

      /*
       * (non-Javadoc)
       * 
       * @see java.sql.PreparedStatement#addBatch()
       */
00645       public void addBatch() throws SQLException {
            setOutParams();

            super.addBatch();
      }

      private synchronized CallableStatementParam checkIsOutputParam(int paramIndex)
                  throws SQLException {

            if (this.callingStoredFunction) {
                  if (paramIndex == 1) {

                        if (this.returnValueParam == null) {
                              this.returnValueParam = new CallableStatementParam("", 0,
                                          false, true, Types.VARCHAR, "VARCHAR", 0, 0,
                                          DatabaseMetaData.attributeNullableUnknown,
                                          DatabaseMetaData.procedureColumnReturn);
                        }

                        return this.returnValueParam;
                  }

                  // Move to position in output result set
                  paramIndex--;
            }

            checkParameterIndexBounds(paramIndex);

            int localParamIndex = paramIndex - 1;

            if (this.placeholderToParameterIndexMap != null) {
                  localParamIndex = this.placeholderToParameterIndexMap[localParamIndex];
            }
            
            CallableStatementParam paramDescriptor = this.paramInfo
                        .getParameter(localParamIndex);

            // We don't have reliable metadata in this case, trust
            // the caller
            
            if (this.connection.getNoAccessToProcedureBodies()) {
                  paramDescriptor.isOut = true;
                  paramDescriptor.isIn = true;
                  paramDescriptor.inOutModifier = DatabaseMetaData.procedureColumnInOut;
            } else if (!paramDescriptor.isOut) {
                  throw SQLError.createSQLException(
                              Messages.getString("CallableStatement.9") + paramIndex //$NON-NLS-1$
                                          + Messages.getString("CallableStatement.10"), //$NON-NLS-1$
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
            }

            this.hasOutputParams = true;

            return paramDescriptor;
      }

      /**
       * DOCUMENT ME!
       * 
       * @param paramIndex
       * 
       * @throws SQLException
       */
00708       private synchronized void checkParameterIndexBounds(int paramIndex) throws SQLException {
            this.paramInfo.checkBounds(paramIndex);
      }

      /**
       * Checks whether or not this statement is supposed to be providing
       * streamable result sets...If output parameters are registered, the driver
       * can not stream the results.
       * 
       * @throws SQLException
       *             DOCUMENT ME!
       */
00720       private void checkStreamability() throws SQLException {
            if (this.hasOutputParams && createStreamingResultSet()) {
                  throw SQLError.createSQLException(Messages.getString("CallableStatement.14"), //$NON-NLS-1$
                              SQLError.SQL_STATE_DRIVER_NOT_CAPABLE, getExceptionInterceptor());
            }
      }

00727       public synchronized void clearParameters() throws SQLException {
            super.clearParameters();

            try {
                  if (this.outputParameterResults != null) {
                        this.outputParameterResults.close();
                  }
            } finally {
                  this.outputParameterResults = null;
            }
      }

      /**
       * Used to fake up some metadata when we don't have access to 
       * SHOW CREATE PROCEDURE or mysql.proc.
       * 
       * @throws SQLException if we can't build the metadata.
       */
00745       private synchronized void fakeParameterTypes(boolean isReallyProcedure) throws SQLException {
            Field[] fields = new Field[13];

            fields[0] = new Field("", "PROCEDURE_CAT", Types.CHAR, 0);
            fields[1] = new Field("", "PROCEDURE_SCHEM", Types.CHAR, 0);
            fields[2] = new Field("", "PROCEDURE_NAME", Types.CHAR, 0);
            fields[3] = new Field("", "COLUMN_NAME", Types.CHAR, 0);
            fields[4] = new Field("", "COLUMN_TYPE", Types.CHAR, 0);
            fields[5] = new Field("", "DATA_TYPE", Types.SMALLINT, 0);
            fields[6] = new Field("", "TYPE_NAME", Types.CHAR, 0);
            fields[7] = new Field("", "PRECISION", Types.INTEGER, 0);
            fields[8] = new Field("", "LENGTH", Types.INTEGER, 0);
            fields[9] = new Field("", "SCALE", Types.SMALLINT, 0);
            fields[10] = new Field("", "RADIX", Types.SMALLINT, 0);
            fields[11] = new Field("", "NULLABLE", Types.SMALLINT, 0);
            fields[12] = new Field("", "REMARKS", Types.CHAR, 0);

            String procName = isReallyProcedure ? extractProcedureName() : null;

            byte[] procNameAsBytes = null;

            try {
                  procNameAsBytes = procName == null ? null : procName.getBytes("UTF-8");
            } catch (UnsupportedEncodingException ueEx) {
                  procNameAsBytes = StringUtils.s2b(procName, this.connection);
            }

            ArrayList resultRows = new ArrayList();

            for (int i = 0; i < this.parameterCount; i++) {
                  byte[][] row = new byte[13][];
                  row[0] = null; // PROCEDURE_CAT
                  row[1] = null; // PROCEDURE_SCHEM
                  row[2] = procNameAsBytes; // PROCEDURE/NAME
                  row[3] = StringUtils.s2b(String.valueOf(i), this.connection); // COLUMN_NAME

                  row[4] = StringUtils.s2b(String
                              .valueOf(DatabaseMetaData.procedureColumnIn),
                              this.connection);

                  row[5] = StringUtils.s2b(String.valueOf(Types.VARCHAR),
                              this.connection); // DATA_TYPE
                  row[6] = StringUtils.s2b("VARCHAR", this.connection); // TYPE_NAME
                  row[7] = StringUtils.s2b(Integer.toString(65535), this.connection); // PRECISION
                  row[8] = StringUtils.s2b(Integer.toString(65535), this.connection); // LENGTH
                  row[9] = StringUtils.s2b(Integer.toString(0), this.connection); // SCALE
                  row[10] = StringUtils.s2b(Integer.toString(10), this.connection); // RADIX

                  row[11] = StringUtils.s2b(Integer
                              .toString(DatabaseMetaData.procedureNullableUnknown),
                              this.connection); // nullable

                  row[12] = null;

                  resultRows.add(new ByteArrayRow(row, getExceptionInterceptor()));
            }

            java.sql.ResultSet paramTypesRs = DatabaseMetaData.buildResultSet(
                        fields, resultRows, this.connection);

            convertGetProcedureColumnsToInternalDescriptors(paramTypesRs);
      }
      
      private synchronized void determineParameterTypes() throws SQLException {
            
            java.sql.ResultSet paramTypesRs = null;

            try {
                  //Bug#57022, we need to check for db.SPname notation first
                  //  and pass on only SPname
                  String procName = extractProcedureName();
                  String quotedId = "";
                  try {
                        quotedId = this.connection.supportsQuotedIdentifiers() ? 
                                    this.connection.getMetaData().getIdentifierQuoteString()    : "";
                  } catch (SQLException sqlEx) {
                        // Forced by API, never thrown from getIdentifierQuoteString() in
                        // this implementation.
                        AssertionFailedException.shouldNotHappen(sqlEx);
                  }
                  
                  List parseList = StringUtils.splitDBdotName(procName, "", 
                              quotedId , this.connection.isNoBackslashEscapesSet());
                  String tmpCatalog = "";
                  //There *should* be 2 rows, if any.
                  if (parseList.size() == 2) {
                        tmpCatalog = (String) parseList.get(0);
                        procName = (String) parseList.get(1);                 
                  } else {
                        //keep values as they are
                  }
                  
                  java.sql.DatabaseMetaData dbmd = this.connection.getMetaData();

                  boolean useCatalog = false;

                  if (tmpCatalog.length() <= 0) {
                        useCatalog = true;
                  }
                  
                  paramTypesRs = dbmd.getProcedureColumns(this.connection
                              .versionMeetsMinimum(5, 0, 2)
                              && useCatalog ? this.currentCatalog : tmpCatalog/*null*/, null, procName,
                              "%"); //$NON-NLS-1$
                  
                  boolean hasResults = false;
                  try {
                        if (paramTypesRs.next()) {
                              paramTypesRs.previous();
                              hasResults = true;
                        }
                  } catch (Exception e) {
                        // paramTypesRs is empty, proceed with fake params. swallow, was expected 
                  }
                  if (hasResults){
                        convertGetProcedureColumnsToInternalDescriptors(paramTypesRs);
                  } else {
                        fakeParameterTypes(true);
                  }
            } finally {
                  SQLException sqlExRethrow = null;

                  if (paramTypesRs != null) {
                        try {
                              paramTypesRs.close();
                        } catch (SQLException sqlEx) {
                              sqlExRethrow = sqlEx;
                        }

                        paramTypesRs = null;
                  }

                  if (sqlExRethrow != null) {
                        throw sqlExRethrow;
                  }
            }
      }

      private synchronized void convertGetProcedureColumnsToInternalDescriptors(java.sql.ResultSet paramTypesRs) throws SQLException {
            if (!this.connection.isRunningOnJDK13()) {
                  this.paramInfo = new CallableStatementParamInfoJDBC3(
                              paramTypesRs);
            } else {
                  this.paramInfo = new CallableStatementParamInfo(paramTypesRs);
            }
      }

      /*
       * (non-Javadoc)
       * 
       * @see java.sql.PreparedStatement#execute()
       */
00897       public synchronized boolean execute() throws SQLException {
            boolean returnVal = false;

            checkClosed();

            checkStreamability();

            synchronized (this.connection) {
                  setInOutParamsOnServer();
                  setOutParams();

                  returnVal = super.execute();

                  if (this.callingStoredFunction) {
                        this.functionReturnValueResults = this.results;
                        this.functionReturnValueResults.next();
                        this.results = null;
                  }

                  retrieveOutParams();
            }

            if (!this.callingStoredFunction) {
                  return returnVal;
            }

            // Functions can't return results
            return false;
      }

      /*
       * (non-Javadoc)
       * 
       * @see java.sql.PreparedStatement#executeQuery()
       */
00932       public synchronized java.sql.ResultSet executeQuery() throws SQLException {
            checkClosed();

            checkStreamability();

            java.sql.ResultSet execResults = null;

            synchronized (this.connection) {
                  setInOutParamsOnServer();
                  setOutParams();

                  execResults = super.executeQuery();

                  retrieveOutParams();
            }

            return execResults;
      }

      /*
       * (non-Javadoc)
       * 
       * @see java.sql.PreparedStatement#executeUpdate()
       */
00956       public synchronized int executeUpdate() throws SQLException {
            int returnVal = -1;

            checkClosed();

            checkStreamability();

            if (this.callingStoredFunction) {
                  execute();

                  return -1;
            }

            synchronized (this.connection) {
                  setInOutParamsOnServer();
                  setOutParams();

                  returnVal = super.executeUpdate();

                  retrieveOutParams();
            }

            return returnVal;
      }

      private String extractProcedureName() throws SQLException {
            String sanitizedSql = StringUtils.stripComments(this.originalSql, 
                        "`\"'", "`\"'", true, false, true, true);
            
            // TODO: Do this with less memory allocation
            int endCallIndex = StringUtils.indexOfIgnoreCase(sanitizedSql,
                        "CALL "); //$NON-NLS-1$
            int offset = 5;

            if (endCallIndex == -1) {
                  endCallIndex = StringUtils.indexOfIgnoreCase(sanitizedSql,
                              "SELECT ");
                  offset = 7;
            }

            if (endCallIndex != -1) {
                  StringBuffer nameBuf = new StringBuffer();

                  String trimmedStatement = sanitizedSql.substring(
                              endCallIndex + offset).trim();

                  int statementLength = trimmedStatement.length();

                  for (int i = 0; i < statementLength; i++) {
                        char c = trimmedStatement.charAt(i);

                        if (Character.isWhitespace(c) || (c == '(') || (c == '?')) {
                              break;
                        }
                        nameBuf.append(c);

                  }

                  return nameBuf.toString();
            }
            
            throw SQLError.createSQLException(Messages.getString("CallableStatement.1"), //$NON-NLS-1$
                        SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
      }

      /**
       * Adds 'at' symbol to beginning of parameter names if needed.
       * 
       * @param paramNameIn
       *            the parameter name to 'fix'
       * 
       * @return the parameter name with an 'a' prepended, if needed
       * 
       * @throws SQLException
       *             if the parameter name is null or empty.
       */
01032       protected synchronized String fixParameterName(String paramNameIn) throws SQLException {
            //Fixed for 5.5+
            if (((paramNameIn == null) || (paramNameIn.length() == 0)) && (!hasParametersView())) {
                  throw SQLError.createSQLException(
                              ((Messages.getString("CallableStatement.0") + paramNameIn) == null) //$NON-NLS-1$
                                          ? Messages.getString("CallableStatement.15") : Messages.getString("CallableStatement.16"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, 
                                                      getExceptionInterceptor()); //$NON-NLS-1$ //$NON-NLS-2$
            }

            if ((paramNameIn == null) && (hasParametersView())) {
                  paramNameIn = "nullpn";
            };

            if (this.connection.getNoAccessToProcedureBodies()) {
                  throw SQLError.createSQLException("No access to parameters by name when connection has been configured not to access procedure bodies",
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
            }
            
            return mangleParameterName(paramNameIn);

            /*
             * if (paramNameIn.startsWith("@")) { return paramNameIn; } else {
             * StringBuffer paramNameBuf = new StringBuffer("@");
             * paramNameBuf.append(paramNameIn);
             * 
             * return paramNameBuf.toString(); }
             */
      }

      /**
       * @see java.sql.CallableStatement#getArray(int)
       */
01064       public synchronized Array getArray(int i) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(i);

            Array retValue = rs.getArray(mapOutputParameterIndexToRsIndex(i));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getArray(java.lang.String)
       */
01077       public synchronized Array getArray(String parameterName)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            Array retValue = rs.getArray(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getBigDecimal(int)
       */
01092       public synchronized BigDecimal getBigDecimal(int parameterIndex)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            BigDecimal retValue = rs
                        .getBigDecimal(mapOutputParameterIndexToRsIndex(parameterIndex));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * DOCUMENT ME!
       * 
       * @param parameterIndex
       *            DOCUMENT ME!
       * @param scale
       *            DOCUMENT ME!
       * 
       * @return DOCUMENT ME!
       * 
       * @throws SQLException
       *             DOCUMENT ME!
       * 
       * @see java.sql.CallableStatement#getBigDecimal(int, int)
       * @deprecated
       */
01120       public synchronized BigDecimal getBigDecimal(int parameterIndex, int scale)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            BigDecimal retValue = rs.getBigDecimal(
                        mapOutputParameterIndexToRsIndex(parameterIndex), scale);

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getBigDecimal(java.lang.String)
       */
01135       public synchronized BigDecimal getBigDecimal(String parameterName)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            BigDecimal retValue = rs.getBigDecimal(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getBlob(int)
       */
01150       public synchronized Blob getBlob(int parameterIndex) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            Blob retValue = rs
                        .getBlob(mapOutputParameterIndexToRsIndex(parameterIndex));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getBlob(java.lang.String)
       */
01164       public synchronized Blob getBlob(String parameterName) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            Blob retValue = rs.getBlob(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getBoolean(int)
       */
01178       public synchronized boolean getBoolean(int parameterIndex)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            boolean retValue = rs
                        .getBoolean(mapOutputParameterIndexToRsIndex(parameterIndex));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getBoolean(java.lang.String)
       */
01193       public synchronized boolean getBoolean(String parameterName)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            boolean retValue = rs.getBoolean(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getByte(int)
       */
01208       public synchronized byte getByte(int parameterIndex) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            byte retValue = rs
                        .getByte(mapOutputParameterIndexToRsIndex(parameterIndex));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getByte(java.lang.String)
       */
01222       public synchronized byte getByte(String parameterName) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            byte retValue = rs.getByte(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getBytes(int)
       */
01236       public synchronized byte[] getBytes(int parameterIndex) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            byte[] retValue = rs
                        .getBytes(mapOutputParameterIndexToRsIndex(parameterIndex));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getBytes(java.lang.String)
       */
01250       public synchronized byte[] getBytes(String parameterName)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            byte[] retValue = rs.getBytes(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getClob(int)
       */
01265       public synchronized Clob getClob(int parameterIndex) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            Clob retValue = rs
                        .getClob(mapOutputParameterIndexToRsIndex(parameterIndex));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getClob(java.lang.String)
       */
01279       public synchronized Clob getClob(String parameterName) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            Clob retValue = rs.getClob(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getDate(int)
       */
01293       public synchronized Date getDate(int parameterIndex) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            Date retValue = rs
                        .getDate(mapOutputParameterIndexToRsIndex(parameterIndex));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getDate(int, java.util.Calendar)
       */
01307       public synchronized Date getDate(int parameterIndex, Calendar cal)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            Date retValue = rs.getDate(
                        mapOutputParameterIndexToRsIndex(parameterIndex), cal);

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getDate(java.lang.String)
       */
01322       public synchronized Date getDate(String parameterName) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            Date retValue = rs.getDate(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getDate(java.lang.String,
       *      java.util.Calendar)
       */
01337       public synchronized Date getDate(String parameterName, Calendar cal)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            Date retValue = rs.getDate(fixParameterName(parameterName), cal);

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getDouble(int)
       */
01352       public synchronized double getDouble(int parameterIndex)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            double retValue = rs
                        .getDouble(mapOutputParameterIndexToRsIndex(parameterIndex));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getDouble(java.lang.String)
       */
01367       public synchronized double getDouble(String parameterName)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            double retValue = rs.getDouble(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getFloat(int)
       */
01382       public synchronized float getFloat(int parameterIndex) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            float retValue = rs
                        .getFloat(mapOutputParameterIndexToRsIndex(parameterIndex));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getFloat(java.lang.String)
       */
01396       public synchronized float getFloat(String parameterName)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            float retValue = rs.getFloat(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getInt(int)
       */
01411       public synchronized int getInt(int parameterIndex) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            int retValue = rs
                        .getInt(mapOutputParameterIndexToRsIndex(parameterIndex));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getInt(java.lang.String)
       */
01425       public synchronized int getInt(String parameterName) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            int retValue = rs.getInt(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getLong(int)
       */
01439       public synchronized long getLong(int parameterIndex) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            long retValue = rs
                        .getLong(mapOutputParameterIndexToRsIndex(parameterIndex));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getLong(java.lang.String)
       */
01453       public synchronized long getLong(String parameterName) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            long retValue = rs.getLong(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      protected synchronized int getNamedParamIndex(String paramName, boolean forOut)
      throws SQLException {
            if (this.connection.getNoAccessToProcedureBodies()) {
                  throw SQLError.createSQLException("No access to parameters by name when connection has been configured not to access procedure bodies",
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
            }
            
            //Fixed for 5.5+ in callers
            if ((paramName == null) || (paramName.length() == 0)) {
                  throw SQLError.createSQLException(Messages.getString("CallableStatement.2"), //$NON-NLS-1$
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
            }

            if (this.paramInfo == null) {
                  throw SQLError.createSQLException(
                              Messages.getString("CallableStatement.3") + paramName + Messages.getString("CallableStatement.4"), //$NON-NLS-1$ //$NON-NLS-2$
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
            }

            CallableStatementParam namedParamInfo = this.paramInfo
                  .getParameter(paramName);

            if (forOut && !namedParamInfo.isOut) {
                  throw SQLError.createSQLException(
                              Messages.getString("CallableStatement.5") + paramName //$NON-NLS-1$
                              + Messages.getString("CallableStatement.6"), //$NON-NLS-1$
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
            }


            if (this.placeholderToParameterIndexMap == null) {
                  return namedParamInfo.index + 1; // JDBC indices are 1-based
            } 

            for (int i = 0; i < this.placeholderToParameterIndexMap.length; i++) {
                  if (this.placeholderToParameterIndexMap[i] == namedParamInfo.index) {
                        return i + 1;
                  }
            }

            throw SQLError.createSQLException("Can't find local placeholder mapping for parameter named \"" + 
                        paramName + "\".", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
      }

      /**
       * @see java.sql.CallableStatement#getObject(int)
       */
01511       public synchronized Object getObject(int parameterIndex)
                  throws SQLException {
            CallableStatementParam paramDescriptor = checkIsOutputParam(parameterIndex);

            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            Object retVal = rs.getObjectStoredProc(
                        mapOutputParameterIndexToRsIndex(parameterIndex),
                        paramDescriptor.desiredJdbcType);

            this.outputParamWasNull = rs.wasNull();

            return retVal;
      }

      /**
       * @see java.sql.CallableStatement#getObject(int, java.util.Map)
       */
01529       public synchronized Object getObject(int parameterIndex, Map map)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            Object retVal = rs.getObject(
                        mapOutputParameterIndexToRsIndex(parameterIndex), map);

            this.outputParamWasNull = rs.wasNull();

            return retVal;
      }

      /**
       * @see java.sql.CallableStatement#getObject(java.lang.String)
       */
01544       public synchronized Object getObject(String parameterName)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            Object retValue = rs.getObject(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getObject(java.lang.String,
       *      java.util.Map)
       */
01560       public synchronized Object getObject(String parameterName, Map map)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            Object retValue = rs.getObject(fixParameterName(parameterName), map);

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * Returns the ResultSet that holds the output parameters, or throws an
       * appropriate exception if none exist, or they weren't returned.
       * 
       * @return the ResultSet that holds the output parameters
       * 
       * @throws SQLException
       *             if no output parameters were defined, or if no output
       *             parameters were returned.
       */
01582       protected synchronized ResultSetInternalMethods getOutputParameters(int paramIndex) throws SQLException {
            this.outputParamWasNull = false;

            if (paramIndex == 1 && this.callingStoredFunction
                        && this.returnValueParam != null) {
                  return this.functionReturnValueResults;
            }

            if (this.outputParameterResults == null) {
                  if (this.paramInfo.numberOfParameters() == 0) {
                        throw SQLError.createSQLException(Messages
                                    .getString("CallableStatement.7"), //$NON-NLS-1$
                                    SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
                  }
                  throw SQLError.createSQLException(Messages.getString("CallableStatement.8"), //$NON-NLS-1$
                              SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
            }

            return this.outputParameterResults;

      }

01604       public synchronized ParameterMetaData getParameterMetaData()
                  throws SQLException {
            if (this.placeholderToParameterIndexMap == null) {
                  return (CallableStatementParamInfoJDBC3) this.paramInfo;
            } else {
                  return new CallableStatementParamInfoJDBC3(this.paramInfo);
            }
      }

      /**
       * @see java.sql.CallableStatement#getRef(int)
       */
01616       public synchronized Ref getRef(int parameterIndex) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            Ref retValue = rs
                        .getRef(mapOutputParameterIndexToRsIndex(parameterIndex));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getRef(java.lang.String)
       */
01630       public synchronized Ref getRef(String parameterName) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            Ref retValue = rs.getRef(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getShort(int)
       */
01644       public synchronized short getShort(int parameterIndex) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            short retValue = rs
                        .getShort(mapOutputParameterIndexToRsIndex(parameterIndex));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getShort(java.lang.String)
       */
01658       public synchronized short getShort(String parameterName)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            short retValue = rs.getShort(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getString(int)
       */
01673       public synchronized String getString(int parameterIndex)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            String retValue = rs
                        .getString(mapOutputParameterIndexToRsIndex(parameterIndex));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getString(java.lang.String)
       */
01688       public synchronized String getString(String parameterName)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            String retValue = rs.getString(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getTime(int)
       */
01703       public synchronized Time getTime(int parameterIndex) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            Time retValue = rs
                        .getTime(mapOutputParameterIndexToRsIndex(parameterIndex));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getTime(int, java.util.Calendar)
       */
01717       public synchronized Time getTime(int parameterIndex, Calendar cal)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            Time retValue = rs.getTime(
                        mapOutputParameterIndexToRsIndex(parameterIndex), cal);

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getTime(java.lang.String)
       */
01732       public synchronized Time getTime(String parameterName) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            Time retValue = rs.getTime(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getTime(java.lang.String,
       *      java.util.Calendar)
       */
01747       public synchronized Time getTime(String parameterName, Calendar cal)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            Time retValue = rs.getTime(fixParameterName(parameterName), cal);

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getTimestamp(int)
       */
01762       public synchronized Timestamp getTimestamp(int parameterIndex)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            Timestamp retValue = rs
                        .getTimestamp(mapOutputParameterIndexToRsIndex(parameterIndex));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getTimestamp(int, java.util.Calendar)
       */
01777       public synchronized Timestamp getTimestamp(int parameterIndex, Calendar cal)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            Timestamp retValue = rs.getTimestamp(
                        mapOutputParameterIndexToRsIndex(parameterIndex), cal);

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getTimestamp(java.lang.String)
       */
01792       public synchronized Timestamp getTimestamp(String parameterName)
                  throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            Timestamp retValue = rs.getTimestamp(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getTimestamp(java.lang.String,
       *      java.util.Calendar)
       */
01808       public synchronized Timestamp getTimestamp(String parameterName,
                  Calendar cal) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            Timestamp retValue = rs.getTimestamp(fixParameterName(parameterName),
                        cal);

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getURL(int)
       */
01824       public synchronized URL getURL(int parameterIndex) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(parameterIndex);

            URL retValue = rs
                        .getURL(mapOutputParameterIndexToRsIndex(parameterIndex));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      /**
       * @see java.sql.CallableStatement#getURL(java.lang.String)
       */
01838       public synchronized URL getURL(String parameterName) throws SQLException {
            ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
            // from ?=

            URL retValue = rs.getURL(fixParameterName(parameterName));

            this.outputParamWasNull = rs.wasNull();

            return retValue;
      }

      protected synchronized int mapOutputParameterIndexToRsIndex(int paramIndex)
                  throws SQLException {

            if (this.returnValueParam != null && paramIndex == 1) {
                  return 1;
            }

            checkParameterIndexBounds(paramIndex);

            int localParamIndex = paramIndex - 1;

            if (this.placeholderToParameterIndexMap != null) {
                  localParamIndex = this.placeholderToParameterIndexMap[localParamIndex];
            }

            int rsIndex = this.parameterIndexToRsIndex[localParamIndex];

            if (rsIndex == NOT_OUTPUT_PARAMETER_INDICATOR) {
                  throw SQLError.createSQLException(
                              Messages.getString("CallableStatement.21") + paramIndex //$NON-NLS-1$
                                          + Messages.getString("CallableStatement.22"), //$NON-NLS-1$
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
            }

            return rsIndex + 1;
      }

      /**
       * @see java.sql.CallableStatement#registerOutParameter(int, int)
       */
01879       public void registerOutParameter(int parameterIndex, int sqlType)
                  throws SQLException {
            CallableStatementParam paramDescriptor = checkIsOutputParam(parameterIndex);
            paramDescriptor.desiredJdbcType = sqlType;
      }

      /**
       * @see java.sql.CallableStatement#registerOutParameter(int, int, int)
       */
01888       public void registerOutParameter(int parameterIndex, int sqlType, int scale)
                  throws SQLException {
            registerOutParameter(parameterIndex, sqlType);
      }

      /**
       * @see java.sql.CallableStatement#registerOutParameter(int, int,
       *      java.lang.String)
       */
01897       public void registerOutParameter(int parameterIndex, int sqlType,
                  String typeName) throws SQLException {
            checkIsOutputParam(parameterIndex);
      }

      /**
       * @see java.sql.CallableStatement#registerOutParameter(java.lang.String,
       *      int)
       */
01906       public synchronized void registerOutParameter(String parameterName,
                  int sqlType) throws SQLException {
            registerOutParameter(getNamedParamIndex(parameterName, true), sqlType);
      }

      /**
       * @see java.sql.CallableStatement#registerOutParameter(java.lang.String,
       *      int, int)
       */
01915       public void registerOutParameter(String parameterName, int sqlType,
                  int scale) throws SQLException {
            registerOutParameter(getNamedParamIndex(parameterName, true), sqlType);
      }

      /**
       * @see java.sql.CallableStatement#registerOutParameter(java.lang.String,
       *      int, java.lang.String)
       */
01924       public void registerOutParameter(String parameterName, int sqlType,
                  String typeName) throws SQLException {
            registerOutParameter(getNamedParamIndex(parameterName, true), sqlType,
                        typeName);
      }

      /**
       * Issues a second query to retrieve all output parameters.
       * 
       * @throws SQLException
       *             if an error occurs.
       */
01936       private synchronized void retrieveOutParams() throws SQLException {
            int numParameters = this.paramInfo.numberOfParameters();

            this.parameterIndexToRsIndex = new int[numParameters];

            for (int i = 0; i < numParameters; i++) {
                  this.parameterIndexToRsIndex[i] = NOT_OUTPUT_PARAMETER_INDICATOR;
            }

            int localParamIndex = 0;

            if (numParameters > 0) {
                  StringBuffer outParameterQuery = new StringBuffer("SELECT "); //$NON-NLS-1$

                  boolean firstParam = true;
                  boolean hadOutputParams = false;

                  for (Iterator paramIter = this.paramInfo.iterator(); paramIter
                              .hasNext();) {
                        CallableStatementParam retrParamInfo = (CallableStatementParam) paramIter
                                    .next();

                        if (retrParamInfo.isOut) {
                              hadOutputParams = true;

                              this.parameterIndexToRsIndex[retrParamInfo.index] = localParamIndex++;

                              if ((retrParamInfo.paramName == null) && (hasParametersView())) {
                                    retrParamInfo.paramName = "nullnp" + retrParamInfo.index;
                              }
                              
                              String outParameterName = mangleParameterName(retrParamInfo.paramName);

                              if (!firstParam) {
                                    outParameterQuery.append(","); //$NON-NLS-1$
                              } else {
                                    firstParam = false;
                              }

                              if (!outParameterName.startsWith("@")) { //$NON-NLS-1$
                                    outParameterQuery.append('@');
                              }

                              outParameterQuery.append(outParameterName);
                        }
                  }

                  if (hadOutputParams) {
                        // We can't use 'ourself' to execute this query, or any
                        // pending result sets would be overwritten
                        java.sql.Statement outParameterStmt = null;
                        java.sql.ResultSet outParamRs = null;

                        try {
                              outParameterStmt = this.connection.createStatement();
                              outParamRs = outParameterStmt
                                          .executeQuery(outParameterQuery.toString());
                              this.outputParameterResults = ((com.mysql.jdbc.ResultSetInternalMethods) outParamRs)
                                          .copy();

                              if (!this.outputParameterResults.next()) {
                                    this.outputParameterResults.close();
                                    this.outputParameterResults = null;
                              }
                        } finally {
                              if (outParameterStmt != null) {
                                    outParameterStmt.close();
                              }
                        }
                  } else {
                        this.outputParameterResults = null;
                  }
            } else {
                  this.outputParameterResults = null;
            }
      }

      /**
       * @see java.sql.CallableStatement#setAsciiStream(java.lang.String,
       *      java.io.InputStream, int)
       */
02017       public void setAsciiStream(String parameterName, InputStream x, int length)
                  throws SQLException {
            setAsciiStream(getNamedParamIndex(parameterName, false), x, length);
      }

      /**
       * @see java.sql.CallableStatement#setBigDecimal(java.lang.String,
       *      java.math.BigDecimal)
       */
02026       public void setBigDecimal(String parameterName, BigDecimal x)
                  throws SQLException {
            setBigDecimal(getNamedParamIndex(parameterName, false), x);
      }

      /**
       * @see java.sql.CallableStatement#setBinaryStream(java.lang.String,
       *      java.io.InputStream, int)
       */
02035       public void setBinaryStream(String parameterName, InputStream x, int length)
                  throws SQLException {
            setBinaryStream(getNamedParamIndex(parameterName, false), x, length);
      }

      /**
       * @see java.sql.CallableStatement#setBoolean(java.lang.String, boolean)
       */
02043       public void setBoolean(String parameterName, boolean x) throws SQLException {
            setBoolean(getNamedParamIndex(parameterName, false), x);
      }

      /**
       * @see java.sql.CallableStatement#setByte(java.lang.String, byte)
       */
02050       public void setByte(String parameterName, byte x) throws SQLException {
            setByte(getNamedParamIndex(parameterName, false), x);
      }

      /**
       * @see java.sql.CallableStatement#setBytes(java.lang.String, byte[])
       */
02057       public void setBytes(String parameterName, byte[] x) throws SQLException {
            setBytes(getNamedParamIndex(parameterName, false), x);
      }

      /**
       * @see java.sql.CallableStatement#setCharacterStream(java.lang.String,
       *      java.io.Reader, int)
       */
02065       public void setCharacterStream(String parameterName, Reader reader,
                  int length) throws SQLException {
            setCharacterStream(getNamedParamIndex(parameterName, false), reader,
                        length);
      }

      /**
       * @see java.sql.CallableStatement#setDate(java.lang.String, java.sql.Date)
       */
02074       public void setDate(String parameterName, Date x) throws SQLException {
            setDate(getNamedParamIndex(parameterName, false), x);
      }

      /**
       * @see java.sql.CallableStatement#setDate(java.lang.String, java.sql.Date,
       *      java.util.Calendar)
       */
02082       public void setDate(String parameterName, Date x, Calendar cal)
                  throws SQLException {
            setDate(getNamedParamIndex(parameterName, false), x, cal);
      }

      /**
       * @see java.sql.CallableStatement#setDouble(java.lang.String, double)
       */
02090       public void setDouble(String parameterName, double x) throws SQLException {
            setDouble(getNamedParamIndex(parameterName, false), x);
      }

      /**
       * @see java.sql.CallableStatement#setFloat(java.lang.String, float)
       */
02097       public void setFloat(String parameterName, float x) throws SQLException {
            setFloat(getNamedParamIndex(parameterName, false), x);
      }

      /**
       * 
       */
      private synchronized void setInOutParamsOnServer() throws SQLException {
            if (this.paramInfo.numParameters > 0) {
                  int parameterIndex = 0;

                  for (Iterator paramIter = this.paramInfo.iterator(); paramIter
                              .hasNext();) {

                        CallableStatementParam inParamInfo = (CallableStatementParam) paramIter
                                    .next();

                        //Fix for 5.5+
                        if (inParamInfo.isOut && inParamInfo.isIn) {
                              if ((inParamInfo.paramName == null) && (hasParametersView())) {
                                    inParamInfo.paramName = "nullnp" + inParamInfo.index;
                              };
                              
                              String inOutParameterName = mangleParameterName(inParamInfo.paramName);
                              StringBuffer queryBuf = new StringBuffer(
                                          4 + inOutParameterName.length() + 1 + 1);
                              queryBuf.append("SET "); //$NON-NLS-1$
                              queryBuf.append(inOutParameterName);
                              queryBuf.append("=?"); //$NON-NLS-1$

                              PreparedStatement setPstmt = null;

                              try {
                                    setPstmt = (PreparedStatement) this.connection
                                                .clientPrepareStatement(queryBuf.toString());

                                    byte[] parameterAsBytes = getBytesRepresentation(
                                                inParamInfo.index);

                                    if (parameterAsBytes != null) {
                                          if (parameterAsBytes.length > 8
                                                      && parameterAsBytes[0] == '_'
                                                      && parameterAsBytes[1] == 'b'
                                                      && parameterAsBytes[2] == 'i'
                                                      && parameterAsBytes[3] == 'n'
                                                      && parameterAsBytes[4] == 'a'
                                                      && parameterAsBytes[5] == 'r'
                                                      && parameterAsBytes[6] == 'y'
                                                      && parameterAsBytes[7] == '\'') {
                                                setPstmt.setBytesNoEscapeNoQuotes(1,
                                                            parameterAsBytes);
                                          } else {
                                                int sqlType = inParamInfo.desiredJdbcType;
                                                
                                                switch (sqlType) {
                                                case Types.BIT:
                                                case Types.BINARY: 
                                                case Types.BLOB: 
                                                case Types.JAVA_OBJECT:
                                                case Types.LONGVARBINARY: 
                                                case Types.VARBINARY:
                                                      setPstmt.setBytes(1, parameterAsBytes);
                                                      break;
                                                default:
                                                      // the inherited PreparedStatement methods
                                                      // have already escaped and quoted these parameters
                                                      setPstmt.setBytesNoEscape(1, parameterAsBytes);
                                                }
                                          }
                                    } else {
                                          setPstmt.setNull(1, Types.NULL);
                                    }

                                    setPstmt.executeUpdate();
                              } finally {
                                    if (setPstmt != null) {
                                          setPstmt.close();
                                    }
                              }
                        }

                        parameterIndex++;
                  }
            }
      }

      /**
       * @see java.sql.CallableStatement#setInt(java.lang.String, int)
       */
02186       public void setInt(String parameterName, int x) throws SQLException {
            setInt(getNamedParamIndex(parameterName, false), x);
      }

      /**
       * @see java.sql.CallableStatement#setLong(java.lang.String, long)
       */
02193       public void setLong(String parameterName, long x) throws SQLException {
            setLong(getNamedParamIndex(parameterName, false), x);
      }

      /**
       * @see java.sql.CallableStatement#setNull(java.lang.String, int)
       */
02200       public void setNull(String parameterName, int sqlType) throws SQLException {
            setNull(getNamedParamIndex(parameterName, false), sqlType);
      }

      /**
       * @see java.sql.CallableStatement#setNull(java.lang.String, int,
       *      java.lang.String)
       */
02208       public void setNull(String parameterName, int sqlType, String typeName)
                  throws SQLException {
            setNull(getNamedParamIndex(parameterName, false), sqlType, typeName);
      }

      /**
       * @see java.sql.CallableStatement#setObject(java.lang.String,
       *      java.lang.Object)
       */
02217       public void setObject(String parameterName, Object x) throws SQLException {
            setObject(getNamedParamIndex(parameterName, false), x);
      }

      /**
       * @see java.sql.CallableStatement#setObject(java.lang.String,
       *      java.lang.Object, int)
       */
02225       public void setObject(String parameterName, Object x, int targetSqlType)
                  throws SQLException {
            setObject(getNamedParamIndex(parameterName, false), x, targetSqlType);
      }

      /**
       * @see java.sql.CallableStatement#setObject(java.lang.String,
       *      java.lang.Object, int, int)
       */
02234       public void setObject(String parameterName, Object x, int targetSqlType,
                  int scale) throws SQLException {
      }

      private synchronized void setOutParams() throws SQLException {
            if (this.paramInfo.numParameters > 0) {
                  for (Iterator paramIter = this.paramInfo.iterator(); paramIter
                              .hasNext();) {
                        CallableStatementParam outParamInfo = (CallableStatementParam) paramIter
                                    .next();

                        if (!this.callingStoredFunction && outParamInfo.isOut) {

                              if ((outParamInfo.paramName == null) && (hasParametersView())) {
                                    outParamInfo.paramName = "nullnp" + outParamInfo.index;
                              };

                              String outParameterName = mangleParameterName(outParamInfo.paramName);

                              int outParamIndex = 0;
                              
                              if (this.placeholderToParameterIndexMap == null) { 
                                          outParamIndex = outParamInfo.index + 1;
                              } else {
                                          // Find it, todo: remove this linear search
                                          boolean found = false;
                                          
                                          for (int i = 0; i < this.placeholderToParameterIndexMap.length; i++) {
                                                if (this.placeholderToParameterIndexMap[i] == outParamInfo.index) {
                                                      outParamIndex = i + 1; /* JDBC is 1-based */
                                                      found = true;
                                                      break;
                                                }
                                          }
                                          
                                          if (!found) {
                                                throw SQLError.createSQLException("boo!", "S1000", this.connection.getExceptionInterceptor());
                                          }
                              }
                              
                              this.setBytesNoEscapeNoQuotes(outParamIndex,
                                          StringUtils.getBytes(outParameterName,
                                                      this.charConverter, this.charEncoding,
                                                      this.connection
                                                                  .getServerCharacterEncoding(),
                                                      this.connection.parserKnowsUnicode(), getExceptionInterceptor()));
                        }
                  }
            }
      }

      /**
       * @see java.sql.CallableStatement#setShort(java.lang.String, short)
       */
02288       public void setShort(String parameterName, short x) throws SQLException {
            setShort(getNamedParamIndex(parameterName, false), x);
      }

      /**
       * @see java.sql.CallableStatement#setString(java.lang.String,
       *      java.lang.String)
       */
02296       public void setString(String parameterName, String x) throws SQLException {
            setString(getNamedParamIndex(parameterName, false), x);
      }

      /**
       * @see java.sql.CallableStatement#setTime(java.lang.String, java.sql.Time)
       */
02303       public void setTime(String parameterName, Time x) throws SQLException {
            setTime(getNamedParamIndex(parameterName, false), x);
      }

      /**
       * @see java.sql.CallableStatement#setTime(java.lang.String, java.sql.Time,
       *      java.util.Calendar)
       */
02311       public void setTime(String parameterName, Time x, Calendar cal)
                  throws SQLException {
            setTime(getNamedParamIndex(parameterName, false), x, cal);
      }

      /**
       * @see java.sql.CallableStatement#setTimestamp(java.lang.String,
       *      java.sql.Timestamp)
       */
02320       public void setTimestamp(String parameterName, Timestamp x)
                  throws SQLException {
            setTimestamp(getNamedParamIndex(parameterName, false), x);
      }

      /**
       * @see java.sql.CallableStatement#setTimestamp(java.lang.String,
       *      java.sql.Timestamp, java.util.Calendar)
       */
02329       public void setTimestamp(String parameterName, Timestamp x, Calendar cal)
                  throws SQLException {
            setTimestamp(getNamedParamIndex(parameterName, false), x, cal);
      }

      /**
       * @see java.sql.CallableStatement#setURL(java.lang.String, java.net.URL)
       */
02337       public void setURL(String parameterName, URL val) throws SQLException {
            setURL(getNamedParamIndex(parameterName, false), val);
      }

      /**
       * @see java.sql.CallableStatement#wasNull()
       */
02344       public synchronized boolean wasNull() throws SQLException {
            return this.outputParamWasNull;
      }

02348       public int[] executeBatch() throws SQLException {
            if (this.hasOutputParams) {
                  throw SQLError.createSQLException("Can't call executeBatch() on CallableStatement with OUTPUT parameters",
                              SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
            }
            
            return super.executeBatch();
      }

02357       protected int getParameterIndexOffset() {
            if (this.callingStoredFunction) {
                  return -1;
            }
            
            return super.getParameterIndexOffset();
      }
      
      public void setAsciiStream(String parameterName, InputStream x) throws SQLException {
            setAsciiStream(getNamedParamIndex(parameterName, false), x);
            
      }

      public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException {
            setAsciiStream(getNamedParamIndex(parameterName, false), x, length);
            
      }

      public void setBinaryStream(String parameterName, InputStream x) throws SQLException {
            setBinaryStream(getNamedParamIndex(parameterName, false), x);
            
      }

      public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException {
            setBinaryStream(getNamedParamIndex(parameterName, false), x, length);
            
      }

      public void setBlob(String parameterName, Blob x) throws SQLException {
            setBlob(getNamedParamIndex(parameterName, false), x);
            
      }

      public void setBlob(String parameterName, InputStream inputStream) throws SQLException {
            setBlob(getNamedParamIndex(parameterName, false), inputStream);
            
      }

      public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException {
            setBlob(getNamedParamIndex(parameterName, false), inputStream, length);
            
      }

      public void setCharacterStream(String parameterName, Reader reader) throws SQLException {
            setCharacterStream(getNamedParamIndex(parameterName, false), reader);
            
      }

      public void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException {
            setCharacterStream(getNamedParamIndex(parameterName, false), reader, length);
            
      }

      public void setClob(String parameterName, Clob x) throws SQLException {
            setClob(getNamedParamIndex(parameterName, false), x);
            
      }

      public void setClob(String parameterName, Reader reader) throws SQLException {
            setClob(getNamedParamIndex(parameterName, false), reader);
            
      }

      public void setClob(String parameterName, Reader reader, long length) throws SQLException {
            setClob(getNamedParamIndex(parameterName, false), reader, length);
            
      }

      public void setNCharacterStream(String parameterName, Reader value) throws SQLException {
            setNCharacterStream(getNamedParamIndex(parameterName, false), value);
            
      }

      public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException {
            setNCharacterStream(getNamedParamIndex(parameterName, false), value, length);
            
      }
      
      /**
       * Check whether the stored procedure alters any data or is safe for read-only usage.
       * 
       * @return true if procedure does not alter data
       * @throws SQLException
       */
02441       private synchronized boolean checkReadOnlyProcedure() throws SQLException {
            if (this.connection.getNoAccessToProcedureBodies()) {
                  return false;
            }

            synchronized (this.paramInfo) {
                  if (this.paramInfo.isReadOnlySafeChecked) {
                        return this.paramInfo.isReadOnlySafeProcedure;
                  }

                  ResultSet rs = null;
                  java.sql.PreparedStatement ps = null;
                  
                  try {
                        String procName = extractProcedureName();

                        String catalog = this.currentCatalog;

                        if (procName.indexOf(".") != -1) {
                              catalog = procName.substring(0, procName.indexOf("."));
                              
                              if (StringUtils.startsWithIgnoreCaseAndWs(catalog, "`") && catalog.trim().endsWith("`")) {
                                    catalog = catalog.substring(1, catalog.length() - 1);
                              }
                              
                              procName = procName.substring(procName.indexOf(".") + 1);
                              procName = new String(StringUtils.stripEnclosure(procName
                                          .getBytes(), "`", "`"));
                        }
                        ps = this.connection
                                    .prepareStatement("SELECT SQL_DATA_ACCESS FROM "
                                                + " information_schema.routines "
                                                + " WHERE routine_schema = ? "
                                                + " AND routine_name = ?");
                        ps.setMaxRows(0);
                        ps.setFetchSize(0);

                        ps.setString(1, catalog);
                        ps.setString(2, procName);
                        rs = ps.executeQuery();
                        if (rs.next()) {
                              String sqlDataAccess = rs.getString(1);
                              if ("READS SQL DATA".equalsIgnoreCase(sqlDataAccess)
                                          || "NO SQL".equalsIgnoreCase(sqlDataAccess)) {
                                    synchronized (this.paramInfo) {
                                          this.paramInfo.isReadOnlySafeChecked = true;
                                          this.paramInfo.isReadOnlySafeProcedure = true;
                                    }
                                    return true;
                              }
                        }
                  } catch (SQLException e) {
                        // swallow the Exception
                  } finally {
                        if(rs != null){
                              rs.close();
                        }
                        if(ps != null){
                              ps.close();
                        }
                        
                  }
                  this.paramInfo.isReadOnlySafeChecked = false;
                  this.paramInfo.isReadOnlySafeProcedure = false;
            }
            return false;
                              
      }

02510       protected boolean checkReadOnlySafeStatement() throws SQLException {
            return (super.checkReadOnlySafeStatement() || this.checkReadOnlyProcedure());
      }
      
      private synchronized boolean hasParametersView() throws SQLException {
            try {
                  if (this.connection.versionMeetsMinimum(5, 5, 0)) {
                        java.sql.DatabaseMetaData dbmd1 = new DatabaseMetaDataUsingInfoSchema(this.connection, this.connection.getCatalog());
                        return ((DatabaseMetaDataUsingInfoSchema)dbmd1).gethasParametersView();
                  } else {
                        return false;
                  }
            } catch (SQLException e) {
                  return false;
            }
      }


   
}

Generated by  Doxygen 1.6.0   Back to index