0001: /*
0002: Copyright (C) 2002-2007 MySQL AB
0003:
0004: This program is free software; you can redistribute it and/or modify
0005: it under the terms of version 2 of the GNU General Public License as
0006: published by the Free Software Foundation.
0007:
0008: There are special exceptions to the terms and conditions of the GPL
0009: as it is applied to this software. View the full text of the
0010: exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
0011: software distribution.
0012:
0013: This program is distributed in the hope that it will be useful,
0014: but WITHOUT ANY WARRANTY; without even the implied warranty of
0015: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0016: GNU General Public License for more details.
0017:
0018: You should have received a copy of the GNU General Public License
0019: along with this program; if not, write to the Free Software
0020: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0021:
0022: */
0023: package com.mysql.jdbc;
0024:
0025: import java.io.InputStream;
0026: import java.io.Reader;
0027: import java.io.UnsupportedEncodingException;
0028:
0029: import java.lang.reflect.Constructor;
0030: import java.lang.reflect.InvocationTargetException;
0031: import java.math.BigDecimal;
0032:
0033: import java.net.URL;
0034:
0035: import java.sql.Array;
0036: import java.sql.Blob;
0037: import java.sql.Clob;
0038: import java.sql.Date;
0039: import java.sql.ParameterMetaData;
0040: import java.sql.Ref;
0041: import java.sql.SQLException;
0042: import java.sql.Time;
0043: import java.sql.Timestamp;
0044: import java.sql.Types;
0045:
0046: import java.util.ArrayList;
0047: import java.util.Calendar;
0048: import java.util.HashMap;
0049: import java.util.Iterator;
0050: import java.util.List;
0051: import java.util.Map;
0052: import java.util.Properties;
0053:
0054: import com.mysql.jdbc.exceptions.NotYetImplementedException;
0055:
0056: /**
0057: * Representation of stored procedures for JDBC
0058: *
0059: * @author Mark Matthews
0060: * @version $Id: CallableStatement.java,v 1.1.2.1 2005/05/13 18:58:38 mmatthews
0061: * Exp $
0062: */
0063: public class CallableStatement extends PreparedStatement implements
0064: java.sql.CallableStatement {
0065: protected final static Constructor JDBC_4_CSTMT_2_ARGS_CTOR;
0066:
0067: protected final static Constructor JDBC_4_CSTMT_4_ARGS_CTOR;
0068:
0069: static {
0070: if (Util.isJdbc4()) {
0071: try {
0072: JDBC_4_CSTMT_2_ARGS_CTOR = Class
0073: .forName(
0074: "com.mysql.jdbc.JDBC4CallableStatement")
0075: .getConstructor(
0076: new Class[] {
0077: ConnectionImpl.class,
0078: CallableStatementParamInfo.class });
0079: JDBC_4_CSTMT_4_ARGS_CTOR = Class.forName(
0080: "com.mysql.jdbc.JDBC4CallableStatement")
0081: .getConstructor(
0082: new Class[] { ConnectionImpl.class,
0083: String.class, String.class,
0084: Boolean.TYPE });
0085: } catch (SecurityException e) {
0086: throw new RuntimeException(e);
0087: } catch (NoSuchMethodException e) {
0088: throw new RuntimeException(e);
0089: } catch (ClassNotFoundException e) {
0090: throw new RuntimeException(e);
0091: }
0092: } else {
0093: JDBC_4_CSTMT_4_ARGS_CTOR = null;
0094: JDBC_4_CSTMT_2_ARGS_CTOR = null;
0095: }
0096: }
0097:
0098: protected class CallableStatementParam {
0099: int desiredJdbcType;
0100:
0101: int index;
0102:
0103: int inOutModifier;
0104:
0105: boolean isIn;
0106:
0107: boolean isOut;
0108:
0109: int jdbcType;
0110:
0111: short nullability;
0112:
0113: String paramName;
0114:
0115: int precision;
0116:
0117: int scale;
0118:
0119: String typeName;
0120:
0121: CallableStatementParam(String name, int idx, boolean in,
0122: boolean out, int jdbcType, String typeName,
0123: int precision, int scale, short nullability,
0124: int inOutModifier) {
0125: this .paramName = name;
0126: this .isIn = in;
0127: this .isOut = out;
0128: this .index = idx;
0129:
0130: this .jdbcType = jdbcType;
0131: this .typeName = typeName;
0132: this .precision = precision;
0133: this .scale = scale;
0134: this .nullability = nullability;
0135: this .inOutModifier = inOutModifier;
0136: }
0137:
0138: /*
0139: * (non-Javadoc)
0140: *
0141: * @see java.lang.Object#clone()
0142: */
0143: protected Object clone() throws CloneNotSupportedException {
0144: return super .clone();
0145: }
0146: }
0147:
0148: protected class CallableStatementParamInfo {
0149: String catalogInUse;
0150:
0151: boolean isFunctionCall;
0152:
0153: String nativeSql;
0154:
0155: int numParameters;
0156:
0157: List parameterList;
0158:
0159: Map parameterMap;
0160:
0161: /**
0162: * Constructor that converts a full list of parameter metadata into one
0163: * that only represents the placeholders present in the {CALL ()}.
0164: *
0165: * @param fullParamInfo the metadata for all parameters for this stored
0166: * procedure or function.
0167: */
0168: CallableStatementParamInfo(
0169: CallableStatementParamInfo fullParamInfo) {
0170: this .nativeSql = originalSql;
0171: this .catalogInUse = currentCatalog;
0172: isFunctionCall = fullParamInfo.isFunctionCall;
0173: int[] localParameterMap = placeholderToParameterIndexMap;
0174: int parameterMapLength = localParameterMap.length;
0175:
0176: parameterList = new ArrayList(fullParamInfo.numParameters);
0177: parameterMap = new HashMap(fullParamInfo.numParameters);
0178:
0179: if (isFunctionCall) {
0180: // Take the return value
0181: parameterList.add(fullParamInfo.parameterList.get(0));
0182: }
0183:
0184: int offset = isFunctionCall ? 1 : 0;
0185:
0186: for (int i = 0; i < parameterMapLength; i++) {
0187: if (localParameterMap[i] != 0) {
0188: CallableStatementParam param = (CallableStatementParam) fullParamInfo.parameterList
0189: .get(localParameterMap[i] + offset);
0190:
0191: parameterList.add(param);
0192: parameterMap.put(param.paramName, param);
0193: }
0194: }
0195:
0196: this .numParameters = parameterList.size();
0197: }
0198:
0199: CallableStatementParamInfo(java.sql.ResultSet paramTypesRs)
0200: throws SQLException {
0201: boolean hadRows = paramTypesRs.last();
0202:
0203: this .nativeSql = originalSql;
0204: this .catalogInUse = currentCatalog;
0205: isFunctionCall = callingStoredFunction;
0206:
0207: if (hadRows) {
0208: this .numParameters = paramTypesRs.getRow();
0209:
0210: this .parameterList = new ArrayList(this .numParameters);
0211: this .parameterMap = new HashMap(this .numParameters);
0212:
0213: paramTypesRs.beforeFirst();
0214:
0215: addParametersFromDBMD(paramTypesRs);
0216: } else {
0217: this .numParameters = 0;
0218: }
0219:
0220: if (isFunctionCall) {
0221: this .numParameters += 1;
0222: }
0223: }
0224:
0225: private void addParametersFromDBMD(
0226: java.sql.ResultSet paramTypesRs) throws SQLException {
0227: int i = 0;
0228:
0229: while (paramTypesRs.next()) {
0230: String paramName = paramTypesRs.getString(4);
0231: int inOutModifier = paramTypesRs.getInt(5);
0232:
0233: boolean isOutParameter = false;
0234: boolean isInParameter = false;
0235:
0236: if (i == 0 && isFunctionCall) {
0237: isOutParameter = true;
0238: isInParameter = false;
0239: } else if (inOutModifier == DatabaseMetaData.procedureColumnInOut) {
0240: isOutParameter = true;
0241: isInParameter = true;
0242: } else if (inOutModifier == DatabaseMetaData.procedureColumnIn) {
0243: isOutParameter = false;
0244: isInParameter = true;
0245: } else if (inOutModifier == DatabaseMetaData.procedureColumnOut) {
0246: isOutParameter = true;
0247: isInParameter = false;
0248: }
0249:
0250: int jdbcType = paramTypesRs.getInt(6);
0251: String typeName = paramTypesRs.getString(7);
0252: int precision = paramTypesRs.getInt(8);
0253: int scale = paramTypesRs.getInt(10);
0254: short nullability = paramTypesRs.getShort(12);
0255:
0256: CallableStatementParam paramInfoToAdd = new CallableStatementParam(
0257: paramName, i++, isInParameter, isOutParameter,
0258: jdbcType, typeName, precision, scale,
0259: nullability, inOutModifier);
0260:
0261: this .parameterList.add(paramInfoToAdd);
0262: this .parameterMap.put(paramName, paramInfoToAdd);
0263: }
0264: }
0265:
0266: protected void checkBounds(int paramIndex) throws SQLException {
0267: int localParamIndex = paramIndex - 1;
0268:
0269: if ((paramIndex < 0)
0270: || (localParamIndex >= this .numParameters)) {
0271: throw SQLError
0272: .createSQLException(
0273: Messages
0274: .getString("CallableStatement.11") + paramIndex //$NON-NLS-1$
0275: + Messages
0276: .getString("CallableStatement.12") + numParameters //$NON-NLS-1$
0277: + Messages
0278: .getString("CallableStatement.13"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
0279: }
0280: }
0281:
0282: /*
0283: * (non-Javadoc)
0284: *
0285: * @see java.lang.Object#clone()
0286: */
0287: protected Object clone() throws CloneNotSupportedException {
0288: // TODO Auto-generated method stub
0289: return super .clone();
0290: }
0291:
0292: CallableStatementParam getParameter(int index) {
0293: return (CallableStatementParam) this .parameterList
0294: .get(index);
0295: }
0296:
0297: CallableStatementParam getParameter(String name) {
0298: return (CallableStatementParam) this .parameterMap.get(name);
0299: }
0300:
0301: public String getParameterClassName(int arg0)
0302: throws SQLException {
0303: String mysqlTypeName = getParameterTypeName(arg0);
0304:
0305: boolean isBinaryOrBlob = StringUtils.indexOfIgnoreCase(
0306: mysqlTypeName, "BLOB") != -1
0307: || StringUtils.indexOfIgnoreCase(mysqlTypeName,
0308: "BINARY") != -1;
0309:
0310: boolean isUnsigned = StringUtils.indexOfIgnoreCase(
0311: mysqlTypeName, "UNSIGNED") != -1;
0312:
0313: int mysqlTypeIfKnown = 0;
0314:
0315: if (StringUtils.startsWithIgnoreCase(mysqlTypeName,
0316: "MEDIUMINT")) {
0317: mysqlTypeIfKnown = MysqlDefs.FIELD_TYPE_INT24;
0318: }
0319:
0320: return ResultSetMetaData.getClassNameForJavaType(
0321: getParameterType(arg0), isUnsigned,
0322: mysqlTypeIfKnown, isBinaryOrBlob, false);
0323: }
0324:
0325: public int getParameterCount() throws SQLException {
0326: if (this .parameterList == null) {
0327: return 0;
0328: }
0329:
0330: return this .parameterList.size();
0331: }
0332:
0333: public int getParameterMode(int arg0) throws SQLException {
0334: checkBounds(arg0);
0335:
0336: return getParameter(arg0 - 1).inOutModifier;
0337: }
0338:
0339: public int getParameterType(int arg0) throws SQLException {
0340: checkBounds(arg0);
0341:
0342: return getParameter(arg0 - 1).jdbcType;
0343: }
0344:
0345: public String getParameterTypeName(int arg0)
0346: throws SQLException {
0347: checkBounds(arg0);
0348:
0349: return getParameter(arg0 - 1).typeName;
0350: }
0351:
0352: public int getPrecision(int arg0) throws SQLException {
0353: checkBounds(arg0);
0354:
0355: return getParameter(arg0 - 1).precision;
0356: }
0357:
0358: public int getScale(int arg0) throws SQLException {
0359: checkBounds(arg0);
0360:
0361: return getParameter(arg0 - 1).scale;
0362: }
0363:
0364: public int isNullable(int arg0) throws SQLException {
0365: checkBounds(arg0);
0366:
0367: return getParameter(arg0 - 1).nullability;
0368: }
0369:
0370: public boolean isSigned(int arg0) throws SQLException {
0371: checkBounds(arg0);
0372:
0373: return false;
0374: }
0375:
0376: Iterator iterator() {
0377: return this .parameterList.iterator();
0378: }
0379:
0380: int numberOfParameters() {
0381: return this .numParameters;
0382: }
0383: }
0384:
0385: /**
0386: * Can't implement this directly, as then you can't use callable statements
0387: * on JDK-1.3.1, which unfortunately isn't EOL'd yet, and still present
0388: * quite a bit out there in the wild (Websphere, FreeBSD, anyone?)
0389: */
0390:
0391: protected class CallableStatementParamInfoJDBC3 extends
0392: CallableStatementParamInfo implements ParameterMetaData {
0393:
0394: CallableStatementParamInfoJDBC3(java.sql.ResultSet paramTypesRs)
0395: throws SQLException {
0396: super (paramTypesRs);
0397: }
0398:
0399: public CallableStatementParamInfoJDBC3(
0400: CallableStatementParamInfo paramInfo) {
0401: super (paramInfo);
0402: }
0403:
0404: /**
0405: * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
0406: * for an object that does. Returns false otherwise. If this implements the interface then return true,
0407: * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped
0408: * object. If this does not implement the interface and is not a wrapper, return false.
0409: * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that
0410: * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method
0411: * returns true then calling <code>unwrap</code> with the same argument should succeed.
0412: *
0413: * @param interfaces a Class defining an interface.
0414: * @return true if this implements the interface or directly or indirectly wraps an object that does.
0415: * @throws java.sql.SQLException if an error occurs while determining whether this is a wrapper
0416: * for an object with the given interface.
0417: * @since 1.6
0418: */
0419: public boolean isWrapperFor(Class iface) throws SQLException {
0420: checkClosed();
0421:
0422: // This works for classes that aren't actually wrapping
0423: // anything
0424: return iface.isInstance(this );
0425: }
0426:
0427: /**
0428: * Returns an object that implements the given interface to allow access to non-standard methods,
0429: * or standard methods not exposed by the proxy.
0430: * The result may be either the object found to implement the interface or a proxy for that object.
0431: * If the receiver implements the interface then that is the object. If the receiver is a wrapper
0432: * and the wrapped object implements the interface then that is the object. Otherwise the object is
0433: * the result of calling <code>unwrap</code> recursively on the wrapped object. If the receiver is not a
0434: * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown.
0435: *
0436: * @param iface A Class defining an interface that the result must implement.
0437: * @return an object that implements the interface. May be a proxy for the actual implementing object.
0438: * @throws java.sql.SQLException If no object found that implements the interface
0439: * @since 1.6
0440: */
0441: public Object unwrap(Class iface) throws java.sql.SQLException {
0442: try {
0443: // This works for classes that aren't actually wrapping
0444: // anything
0445: return Util.cast(iface, this );
0446: } catch (ClassCastException cce) {
0447: throw SQLError.createSQLException(
0448: "Unable to unwrap to " + iface.toString(),
0449: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
0450: }
0451: }
0452: }
0453:
0454: private final static int NOT_OUTPUT_PARAMETER_INDICATOR = Integer.MIN_VALUE;
0455:
0456: private final static String PARAMETER_NAMESPACE_PREFIX = "@com_mysql_jdbc_outparam_"; //$NON-NLS-1$
0457:
0458: private static String mangleParameterName(String origParameterName) {
0459: if (origParameterName == null) {
0460: return null;
0461: }
0462:
0463: int offset = 0;
0464:
0465: if (origParameterName.length() > 0
0466: && origParameterName.charAt(0) == '@') {
0467: offset = 1;
0468: }
0469:
0470: StringBuffer paramNameBuf = new StringBuffer(
0471: PARAMETER_NAMESPACE_PREFIX.length()
0472: + origParameterName.length());
0473: paramNameBuf.append(PARAMETER_NAMESPACE_PREFIX);
0474: paramNameBuf.append(origParameterName.substring(offset));
0475:
0476: return paramNameBuf.toString();
0477: }
0478:
0479: private boolean callingStoredFunction = false;
0480:
0481: private ResultSetInternalMethods functionReturnValueResults;
0482:
0483: private boolean hasOutputParams = false;
0484:
0485: // private List parameterList;
0486: // private Map parameterMap;
0487: private ResultSetInternalMethods outputParameterResults;
0488:
0489: protected boolean outputParamWasNull = false;
0490:
0491: private int[] parameterIndexToRsIndex;
0492:
0493: protected CallableStatementParamInfo paramInfo;
0494:
0495: private CallableStatementParam returnValueParam;
0496:
0497: /**
0498: * Creates a new CallableStatement
0499: *
0500: * @param conn
0501: * the connection creating this statement
0502: * @param paramInfo
0503: * the SQL to prepare
0504: *
0505: * @throws SQLException
0506: * if an error occurs
0507: */
0508: public CallableStatement(ConnectionImpl conn,
0509: CallableStatementParamInfo paramInfo) throws SQLException {
0510: super (conn, paramInfo.nativeSql, paramInfo.catalogInUse);
0511:
0512: this .paramInfo = paramInfo;
0513: this .callingStoredFunction = this .paramInfo.isFunctionCall;
0514:
0515: if (this .callingStoredFunction) {
0516: this .parameterCount += 1;
0517: }
0518: }
0519:
0520: /**
0521: * Creates a callable statement instance -- We need to provide factory-style methods
0522: * so we can support both JDBC3 (and older) and JDBC4 runtimes, otherwise
0523: * the class verifier complains when it tries to load JDBC4-only interface
0524: * classes that are present in JDBC4 method signatures.
0525: */
0526:
0527: protected static CallableStatement getInstance(ConnectionImpl conn,
0528: String sql, String catalog, boolean isFunctionCall)
0529: throws SQLException {
0530: if (!Util.isJdbc4()) {
0531: return new CallableStatement(conn, sql, catalog,
0532: isFunctionCall);
0533: }
0534:
0535: return (CallableStatement) Util.handleNewInstance(
0536: JDBC_4_CSTMT_4_ARGS_CTOR, new Object[] { conn, sql,
0537: catalog, Boolean.valueOf(isFunctionCall) });
0538: }
0539:
0540: /**
0541: * Creates a callable statement instance -- We need to provide factory-style methods
0542: * so we can support both JDBC3 (and older) and JDBC4 runtimes, otherwise
0543: * the class verifier complains when it tries to load JDBC4-only interface
0544: * classes that are present in JDBC4 method signatures.
0545: */
0546:
0547: protected static CallableStatement getInstance(ConnectionImpl conn,
0548: CallableStatementParamInfo paramInfo) throws SQLException {
0549: if (!Util.isJdbc4()) {
0550: return new CallableStatement(conn, paramInfo);
0551: }
0552:
0553: return (CallableStatement) Util.handleNewInstance(
0554: JDBC_4_CSTMT_2_ARGS_CTOR, new Object[] { conn,
0555: paramInfo });
0556:
0557: }
0558:
0559: private int[] placeholderToParameterIndexMap;
0560:
0561: private void generateParameterMap() throws SQLException {
0562: if (this .paramInfo == null) {
0563: return;
0564: }
0565:
0566: // if the user specified some parameters as literals, we need to
0567: // provide a map from the specified placeholders to the actual
0568: // parameter numbers
0569:
0570: int parameterCountFromMetaData = this .paramInfo
0571: .getParameterCount();
0572:
0573: // Ignore the first ? if this is a stored function, it doesn't count
0574:
0575: if (this .callingStoredFunction) {
0576: parameterCountFromMetaData--;
0577: }
0578:
0579: if (this .paramInfo != null
0580: && this .parameterCount != parameterCountFromMetaData) {
0581: this .placeholderToParameterIndexMap = new int[this .parameterCount];
0582:
0583: int startPos = this .callingStoredFunction ? StringUtils
0584: .indexOfIgnoreCase(this .originalSql, "SELECT")
0585: : StringUtils.indexOfIgnoreCase(this .originalSql,
0586: "CALL");
0587:
0588: if (startPos != -1) {
0589: int parenOpenPos = this .originalSql.indexOf('(',
0590: startPos + 4);
0591:
0592: if (parenOpenPos != -1) {
0593: int parenClosePos = StringUtils
0594: .indexOfIgnoreCaseRespectQuotes(
0595: parenOpenPos, this .originalSql,
0596: ")", '\'', true);
0597:
0598: if (parenClosePos != -1) {
0599: List parsedParameters = StringUtils.split(
0600: this .originalSql
0601: .substring(parenOpenPos + 1,
0602: parenClosePos), ",",
0603: "'\"", "'\"", true);
0604:
0605: int numParsedParameters = parsedParameters
0606: .size();
0607:
0608: // sanity check
0609:
0610: if (numParsedParameters != this .parameterCount) {
0611: // bail?
0612: }
0613:
0614: int placeholderCount = 0;
0615:
0616: for (int i = 0; i < numParsedParameters; i++) {
0617: if (((String) parsedParameters.get(i))
0618: .equals("?")) {
0619: this .placeholderToParameterIndexMap[placeholderCount++] = i;
0620: }
0621: }
0622: }
0623: }
0624: }
0625: }
0626: }
0627:
0628: /**
0629: * Creates a new CallableStatement
0630: *
0631: * @param conn
0632: * the connection creating this statement
0633: * @param sql
0634: * the SQL to prepare
0635: * @param catalog
0636: * the current catalog
0637: *
0638: * @throws SQLException
0639: * if an error occurs
0640: */
0641: public CallableStatement(ConnectionImpl conn, String sql,
0642: String catalog, boolean isFunctionCall) throws SQLException {
0643: super (conn, sql, catalog);
0644:
0645: this .callingStoredFunction = isFunctionCall;
0646:
0647: determineParameterTypes();
0648: generateParameterMap();
0649:
0650: if (this .callingStoredFunction) {
0651: this .parameterCount += 1;
0652: }
0653: }
0654:
0655: /*
0656: * (non-Javadoc)
0657: *
0658: * @see java.sql.PreparedStatement#addBatch()
0659: */
0660: public void addBatch() throws SQLException {
0661: setOutParams();
0662:
0663: super .addBatch();
0664: }
0665:
0666: private CallableStatementParam checkIsOutputParam(int paramIndex)
0667: throws SQLException {
0668:
0669: if (this .callingStoredFunction) {
0670: if (paramIndex == 1) {
0671:
0672: if (this .returnValueParam == null) {
0673: this .returnValueParam = new CallableStatementParam(
0674: "", 0, false, true, Types.VARCHAR,
0675: "VARCHAR", 0, 0,
0676: DatabaseMetaData.attributeNullableUnknown,
0677: DatabaseMetaData.procedureColumnReturn);
0678: }
0679:
0680: return this .returnValueParam;
0681: }
0682:
0683: // Move to position in output result set
0684: paramIndex--;
0685: }
0686:
0687: checkParameterIndexBounds(paramIndex);
0688:
0689: int localParamIndex = paramIndex - 1;
0690:
0691: if (this .placeholderToParameterIndexMap != null) {
0692: localParamIndex = this .placeholderToParameterIndexMap[localParamIndex];
0693: }
0694:
0695: CallableStatementParam paramDescriptor = this .paramInfo
0696: .getParameter(localParamIndex);
0697:
0698: // We don't have reliable metadata in this case, trust
0699: // the caller
0700:
0701: if (this .connection.getNoAccessToProcedureBodies()) {
0702: paramDescriptor.isOut = true;
0703: paramDescriptor.isIn = true;
0704: paramDescriptor.inOutModifier = DatabaseMetaData.procedureColumnInOut;
0705: } else if (!paramDescriptor.isOut) {
0706: throw SQLError.createSQLException(Messages
0707: .getString("CallableStatement.9") + paramIndex //$NON-NLS-1$
0708: + Messages.getString("CallableStatement.10"), //$NON-NLS-1$
0709: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
0710: }
0711:
0712: this .hasOutputParams = true;
0713:
0714: return paramDescriptor;
0715: }
0716:
0717: /**
0718: * DOCUMENT ME!
0719: *
0720: * @param paramIndex
0721: *
0722: * @throws SQLException
0723: */
0724: private void checkParameterIndexBounds(int paramIndex)
0725: throws SQLException {
0726: this .paramInfo.checkBounds(paramIndex);
0727: }
0728:
0729: /**
0730: * Checks whether or not this statement is supposed to be providing
0731: * streamable result sets...If output parameters are registered, the driver
0732: * can not stream the results.
0733: *
0734: * @throws SQLException
0735: * DOCUMENT ME!
0736: */
0737: private void checkStreamability() throws SQLException {
0738: if (this .hasOutputParams && createStreamingResultSet()) {
0739: throw SQLError.createSQLException(Messages
0740: .getString("CallableStatement.14"), //$NON-NLS-1$
0741: SQLError.SQL_STATE_DRIVER_NOT_CAPABLE);
0742: }
0743: }
0744:
0745: public synchronized void clearParameters() throws SQLException {
0746: super .clearParameters();
0747:
0748: try {
0749: if (this .outputParameterResults != null) {
0750: this .outputParameterResults.close();
0751: }
0752: } finally {
0753: this .outputParameterResults = null;
0754: }
0755: }
0756:
0757: /**
0758: * Used to fake up some metadata when we don't have access to
0759: * SHOW CREATE PROCEDURE or mysql.proc.
0760: *
0761: * @throws SQLException if we can't build the metadata.
0762: */
0763: private void fakeParameterTypes() throws SQLException {
0764: Field[] fields = new Field[13];
0765:
0766: fields[0] = new Field("", "PROCEDURE_CAT", Types.CHAR, 0);
0767: fields[1] = new Field("", "PROCEDURE_SCHEM", Types.CHAR, 0);
0768: fields[2] = new Field("", "PROCEDURE_NAME", Types.CHAR, 0);
0769: fields[3] = new Field("", "COLUMN_NAME", Types.CHAR, 0);
0770: fields[4] = new Field("", "COLUMN_TYPE", Types.CHAR, 0);
0771: fields[5] = new Field("", "DATA_TYPE", Types.SMALLINT, 0);
0772: fields[6] = new Field("", "TYPE_NAME", Types.CHAR, 0);
0773: fields[7] = new Field("", "PRECISION", Types.INTEGER, 0);
0774: fields[8] = new Field("", "LENGTH", Types.INTEGER, 0);
0775: fields[9] = new Field("", "SCALE", Types.SMALLINT, 0);
0776: fields[10] = new Field("", "RADIX", Types.SMALLINT, 0);
0777: fields[11] = new Field("", "NULLABLE", Types.SMALLINT, 0);
0778: fields[12] = new Field("", "REMARKS", Types.CHAR, 0);
0779:
0780: String procName = extractProcedureName();
0781:
0782: byte[] procNameAsBytes = null;
0783:
0784: try {
0785: procNameAsBytes = procName.getBytes("UTF-8");
0786: } catch (UnsupportedEncodingException ueEx) {
0787: procNameAsBytes = StringUtils
0788: .s2b(procName, this .connection);
0789: }
0790:
0791: ArrayList resultRows = new ArrayList();
0792:
0793: for (int i = 0; i < this .parameterCount; i++) {
0794: byte[][] row = new byte[13][];
0795: row[0] = null; // PROCEDURE_CAT
0796: row[1] = null; // PROCEDURE_SCHEM
0797: row[2] = procNameAsBytes; // PROCEDURE/NAME
0798: row[3] = StringUtils
0799: .s2b(String.valueOf(i), this .connection); // COLUMN_NAME
0800:
0801: row[4] = StringUtils.s2b(String
0802: .valueOf(DatabaseMetaData.procedureColumnIn),
0803: this .connection);
0804:
0805: row[5] = StringUtils.s2b(String.valueOf(Types.VARCHAR),
0806: this .connection); // DATA_TYPE
0807: row[6] = StringUtils.s2b("VARCHAR", this .connection); // TYPE_NAME
0808: row[7] = StringUtils.s2b(Integer.toString(65535),
0809: this .connection); // PRECISION
0810: row[8] = StringUtils.s2b(Integer.toString(65535),
0811: this .connection); // LENGTH
0812: row[9] = StringUtils.s2b(Integer.toString(0),
0813: this .connection); // SCALE
0814: row[10] = StringUtils.s2b(Integer.toString(10),
0815: this .connection); // RADIX
0816:
0817: row[11] = StringUtils
0818: .s2b(
0819: Integer
0820: .toString(DatabaseMetaData.procedureNullableUnknown),
0821: this .connection); // nullable
0822:
0823: row[12] = null;
0824:
0825: resultRows.add(new ByteArrayRow(row));
0826: }
0827:
0828: java.sql.ResultSet paramTypesRs = DatabaseMetaData
0829: .buildResultSet(fields, resultRows, this .connection);
0830:
0831: convertGetProcedureColumnsToInternalDescriptors(paramTypesRs);
0832: }
0833:
0834: private void determineParameterTypes() throws SQLException {
0835: if (this .connection.getNoAccessToProcedureBodies()) {
0836: fakeParameterTypes();
0837:
0838: return;
0839: }
0840:
0841: java.sql.ResultSet paramTypesRs = null;
0842:
0843: try {
0844: String procName = extractProcedureName();
0845:
0846: java.sql.DatabaseMetaData dbmd = this .connection
0847: .getMetaData();
0848:
0849: boolean useCatalog = false;
0850:
0851: if (procName.indexOf(".") == -1) {
0852: useCatalog = true;
0853: }
0854:
0855: paramTypesRs = dbmd.getProcedureColumns(this .connection
0856: .versionMeetsMinimum(5, 0, 2)
0857: && useCatalog ? this .currentCatalog : null, null,
0858: procName, "%"); //$NON-NLS-1$
0859:
0860: convertGetProcedureColumnsToInternalDescriptors(paramTypesRs);
0861: } finally {
0862: SQLException sqlExRethrow = null;
0863:
0864: if (paramTypesRs != null) {
0865: try {
0866: paramTypesRs.close();
0867: } catch (SQLException sqlEx) {
0868: sqlExRethrow = sqlEx;
0869: }
0870:
0871: paramTypesRs = null;
0872: }
0873:
0874: if (sqlExRethrow != null) {
0875: throw sqlExRethrow;
0876: }
0877: }
0878: }
0879:
0880: private void convertGetProcedureColumnsToInternalDescriptors(
0881: java.sql.ResultSet paramTypesRs) throws SQLException {
0882: if (!this .connection.isRunningOnJDK13()) {
0883: this .paramInfo = new CallableStatementParamInfoJDBC3(
0884: paramTypesRs);
0885: } else {
0886: this .paramInfo = new CallableStatementParamInfo(
0887: paramTypesRs);
0888: }
0889: }
0890:
0891: /*
0892: * (non-Javadoc)
0893: *
0894: * @see java.sql.PreparedStatement#execute()
0895: */
0896: public boolean execute() throws SQLException {
0897: boolean returnVal = false;
0898:
0899: checkClosed();
0900:
0901: checkStreamability();
0902:
0903: synchronized (this .connection.getMutex()) {
0904: setInOutParamsOnServer();
0905: setOutParams();
0906:
0907: returnVal = super .execute();
0908:
0909: if (this .callingStoredFunction) {
0910: this .functionReturnValueResults = this .results;
0911: this .functionReturnValueResults.next();
0912: this .results = null;
0913: }
0914:
0915: retrieveOutParams();
0916: }
0917:
0918: if (!this .callingStoredFunction) {
0919: return returnVal;
0920: }
0921:
0922: // Functions can't return results
0923: return false;
0924: }
0925:
0926: /*
0927: * (non-Javadoc)
0928: *
0929: * @see java.sql.PreparedStatement#executeQuery()
0930: */
0931: public java.sql.ResultSet executeQuery() throws SQLException {
0932: checkClosed();
0933:
0934: checkStreamability();
0935:
0936: java.sql.ResultSet execResults = null;
0937:
0938: synchronized (this .connection.getMutex()) {
0939: setInOutParamsOnServer();
0940: setOutParams();
0941:
0942: execResults = super .executeQuery();
0943:
0944: retrieveOutParams();
0945: }
0946:
0947: return execResults;
0948: }
0949:
0950: /*
0951: * (non-Javadoc)
0952: *
0953: * @see java.sql.PreparedStatement#executeUpdate()
0954: */
0955: public int executeUpdate() throws SQLException {
0956: int returnVal = -1;
0957:
0958: checkClosed();
0959:
0960: checkStreamability();
0961:
0962: if (this .callingStoredFunction) {
0963: execute();
0964:
0965: return -1;
0966: }
0967:
0968: synchronized (this .connection.getMutex()) {
0969: setInOutParamsOnServer();
0970: setOutParams();
0971:
0972: returnVal = super .executeUpdate();
0973:
0974: retrieveOutParams();
0975: }
0976:
0977: return returnVal;
0978: }
0979:
0980: private String extractProcedureName() throws SQLException {
0981: String sanitizedSql = StringUtils.stripComments(
0982: this .originalSql, "`\"'", "`\"'", true, false, true,
0983: true);
0984:
0985: // TODO: Do this with less memory allocation
0986: int endCallIndex = StringUtils.indexOfIgnoreCase(sanitizedSql,
0987: "CALL "); //$NON-NLS-1$
0988: int offset = 5;
0989:
0990: if (endCallIndex == -1) {
0991: endCallIndex = StringUtils.indexOfIgnoreCase(sanitizedSql,
0992: "SELECT ");
0993: offset = 7;
0994: }
0995:
0996: if (endCallIndex != -1) {
0997: StringBuffer nameBuf = new StringBuffer();
0998:
0999: String trimmedStatement = sanitizedSql.substring(
1000: endCallIndex + offset).trim();
1001:
1002: int statementLength = trimmedStatement.length();
1003:
1004: for (int i = 0; i < statementLength; i++) {
1005: char c = trimmedStatement.charAt(i);
1006:
1007: if (Character.isWhitespace(c) || (c == '(')
1008: || (c == '?')) {
1009: break;
1010: }
1011: nameBuf.append(c);
1012:
1013: }
1014:
1015: return nameBuf.toString();
1016: }
1017:
1018: throw SQLError.createSQLException(Messages
1019: .getString("CallableStatement.1"), //$NON-NLS-1$
1020: SQLError.SQL_STATE_GENERAL_ERROR);
1021: }
1022:
1023: /**
1024: * Adds 'at' symbol to beginning of parameter names if needed.
1025: *
1026: * @param paramNameIn
1027: * the parameter name to 'fix'
1028: *
1029: * @return the parameter name with an 'a' prepended, if needed
1030: *
1031: * @throws SQLException
1032: * if the parameter name is null or empty.
1033: */
1034: protected String fixParameterName(String paramNameIn)
1035: throws SQLException {
1036: if ((paramNameIn == null) || (paramNameIn.length() == 0)) {
1037: throw SQLError
1038: .createSQLException(
1039: ((Messages.getString("CallableStatement.0") + paramNameIn) == null) //$NON-NLS-1$
1040: ? Messages
1041: .getString("CallableStatement.15") : Messages.getString("CallableStatement.16"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ //$NON-NLS-2$
1042: }
1043:
1044: if (this .connection.getNoAccessToProcedureBodies()) {
1045: throw SQLError
1046: .createSQLException(
1047: "No access to parameters by name when connection has been configured not to access procedure bodies",
1048: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1049: }
1050:
1051: return mangleParameterName(paramNameIn);
1052:
1053: /*
1054: * if (paramNameIn.startsWith("@")) { return paramNameIn; } else {
1055: * StringBuffer paramNameBuf = new StringBuffer("@");
1056: * paramNameBuf.append(paramNameIn);
1057: *
1058: * return paramNameBuf.toString(); }
1059: */
1060: }
1061:
1062: /**
1063: * @see java.sql.CallableStatement#getArray(int)
1064: */
1065: public synchronized Array getArray(int i) throws SQLException {
1066: ResultSetInternalMethods rs = getOutputParameters(i);
1067:
1068: Array retValue = rs
1069: .getArray(mapOutputParameterIndexToRsIndex(i));
1070:
1071: this .outputParamWasNull = rs.wasNull();
1072:
1073: return retValue;
1074: }
1075:
1076: /**
1077: * @see java.sql.CallableStatement#getArray(java.lang.String)
1078: */
1079: public synchronized Array getArray(String parameterName)
1080: throws SQLException {
1081: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1082: // from ?=
1083:
1084: Array retValue = rs.getArray(fixParameterName(parameterName));
1085:
1086: this .outputParamWasNull = rs.wasNull();
1087:
1088: return retValue;
1089: }
1090:
1091: /**
1092: * @see java.sql.CallableStatement#getBigDecimal(int)
1093: */
1094: public synchronized BigDecimal getBigDecimal(int parameterIndex)
1095: throws SQLException {
1096: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1097:
1098: BigDecimal retValue = rs
1099: .getBigDecimal(mapOutputParameterIndexToRsIndex(parameterIndex));
1100:
1101: this .outputParamWasNull = rs.wasNull();
1102:
1103: return retValue;
1104: }
1105:
1106: /**
1107: * DOCUMENT ME!
1108: *
1109: * @param parameterIndex
1110: * DOCUMENT ME!
1111: * @param scale
1112: * DOCUMENT ME!
1113: *
1114: * @return DOCUMENT ME!
1115: *
1116: * @throws SQLException
1117: * DOCUMENT ME!
1118: *
1119: * @see java.sql.CallableStatement#getBigDecimal(int, int)
1120: * @deprecated
1121: */
1122: public synchronized BigDecimal getBigDecimal(int parameterIndex,
1123: int scale) throws SQLException {
1124: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1125:
1126: BigDecimal retValue = rs
1127: .getBigDecimal(
1128: mapOutputParameterIndexToRsIndex(parameterIndex),
1129: scale);
1130:
1131: this .outputParamWasNull = rs.wasNull();
1132:
1133: return retValue;
1134: }
1135:
1136: /**
1137: * @see java.sql.CallableStatement#getBigDecimal(java.lang.String)
1138: */
1139: public synchronized BigDecimal getBigDecimal(String parameterName)
1140: throws SQLException {
1141: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1142: // from ?=
1143:
1144: BigDecimal retValue = rs
1145: .getBigDecimal(fixParameterName(parameterName));
1146:
1147: this .outputParamWasNull = rs.wasNull();
1148:
1149: return retValue;
1150: }
1151:
1152: /**
1153: * @see java.sql.CallableStatement#getBlob(int)
1154: */
1155: public synchronized Blob getBlob(int parameterIndex)
1156: throws SQLException {
1157: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1158:
1159: Blob retValue = rs
1160: .getBlob(mapOutputParameterIndexToRsIndex(parameterIndex));
1161:
1162: this .outputParamWasNull = rs.wasNull();
1163:
1164: return retValue;
1165: }
1166:
1167: /**
1168: * @see java.sql.CallableStatement#getBlob(java.lang.String)
1169: */
1170: public synchronized Blob getBlob(String parameterName)
1171: throws SQLException {
1172: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1173: // from ?=
1174:
1175: Blob retValue = rs.getBlob(fixParameterName(parameterName));
1176:
1177: this .outputParamWasNull = rs.wasNull();
1178:
1179: return retValue;
1180: }
1181:
1182: /**
1183: * @see java.sql.CallableStatement#getBoolean(int)
1184: */
1185: public synchronized boolean getBoolean(int parameterIndex)
1186: throws SQLException {
1187: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1188:
1189: boolean retValue = rs
1190: .getBoolean(mapOutputParameterIndexToRsIndex(parameterIndex));
1191:
1192: this .outputParamWasNull = rs.wasNull();
1193:
1194: return retValue;
1195: }
1196:
1197: /**
1198: * @see java.sql.CallableStatement#getBoolean(java.lang.String)
1199: */
1200: public synchronized boolean getBoolean(String parameterName)
1201: throws SQLException {
1202: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1203: // from ?=
1204:
1205: boolean retValue = rs
1206: .getBoolean(fixParameterName(parameterName));
1207:
1208: this .outputParamWasNull = rs.wasNull();
1209:
1210: return retValue;
1211: }
1212:
1213: /**
1214: * @see java.sql.CallableStatement#getByte(int)
1215: */
1216: public synchronized byte getByte(int parameterIndex)
1217: throws SQLException {
1218: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1219:
1220: byte retValue = rs
1221: .getByte(mapOutputParameterIndexToRsIndex(parameterIndex));
1222:
1223: this .outputParamWasNull = rs.wasNull();
1224:
1225: return retValue;
1226: }
1227:
1228: /**
1229: * @see java.sql.CallableStatement#getByte(java.lang.String)
1230: */
1231: public synchronized byte getByte(String parameterName)
1232: throws SQLException {
1233: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1234: // from ?=
1235:
1236: byte retValue = rs.getByte(fixParameterName(parameterName));
1237:
1238: this .outputParamWasNull = rs.wasNull();
1239:
1240: return retValue;
1241: }
1242:
1243: /**
1244: * @see java.sql.CallableStatement#getBytes(int)
1245: */
1246: public synchronized byte[] getBytes(int parameterIndex)
1247: throws SQLException {
1248: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1249:
1250: byte[] retValue = rs
1251: .getBytes(mapOutputParameterIndexToRsIndex(parameterIndex));
1252:
1253: this .outputParamWasNull = rs.wasNull();
1254:
1255: return retValue;
1256: }
1257:
1258: /**
1259: * @see java.sql.CallableStatement#getBytes(java.lang.String)
1260: */
1261: public synchronized byte[] getBytes(String parameterName)
1262: throws SQLException {
1263: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1264: // from ?=
1265:
1266: byte[] retValue = rs.getBytes(fixParameterName(parameterName));
1267:
1268: this .outputParamWasNull = rs.wasNull();
1269:
1270: return retValue;
1271: }
1272:
1273: /**
1274: * @see java.sql.CallableStatement#getClob(int)
1275: */
1276: public synchronized Clob getClob(int parameterIndex)
1277: throws SQLException {
1278: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1279:
1280: Clob retValue = rs
1281: .getClob(mapOutputParameterIndexToRsIndex(parameterIndex));
1282:
1283: this .outputParamWasNull = rs.wasNull();
1284:
1285: return retValue;
1286: }
1287:
1288: /**
1289: * @see java.sql.CallableStatement#getClob(java.lang.String)
1290: */
1291: public synchronized Clob getClob(String parameterName)
1292: throws SQLException {
1293: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1294: // from ?=
1295:
1296: Clob retValue = rs.getClob(fixParameterName(parameterName));
1297:
1298: this .outputParamWasNull = rs.wasNull();
1299:
1300: return retValue;
1301: }
1302:
1303: /**
1304: * @see java.sql.CallableStatement#getDate(int)
1305: */
1306: public synchronized Date getDate(int parameterIndex)
1307: throws SQLException {
1308: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1309:
1310: Date retValue = rs
1311: .getDate(mapOutputParameterIndexToRsIndex(parameterIndex));
1312:
1313: this .outputParamWasNull = rs.wasNull();
1314:
1315: return retValue;
1316: }
1317:
1318: /**
1319: * @see java.sql.CallableStatement#getDate(int, java.util.Calendar)
1320: */
1321: public synchronized Date getDate(int parameterIndex, Calendar cal)
1322: throws SQLException {
1323: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1324:
1325: Date retValue = rs.getDate(
1326: mapOutputParameterIndexToRsIndex(parameterIndex), cal);
1327:
1328: this .outputParamWasNull = rs.wasNull();
1329:
1330: return retValue;
1331: }
1332:
1333: /**
1334: * @see java.sql.CallableStatement#getDate(java.lang.String)
1335: */
1336: public synchronized Date getDate(String parameterName)
1337: throws SQLException {
1338: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1339: // from ?=
1340:
1341: Date retValue = rs.getDate(fixParameterName(parameterName));
1342:
1343: this .outputParamWasNull = rs.wasNull();
1344:
1345: return retValue;
1346: }
1347:
1348: /**
1349: * @see java.sql.CallableStatement#getDate(java.lang.String,
1350: * java.util.Calendar)
1351: */
1352: public synchronized Date getDate(String parameterName, Calendar cal)
1353: throws SQLException {
1354: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1355: // from ?=
1356:
1357: Date retValue = rs
1358: .getDate(fixParameterName(parameterName), cal);
1359:
1360: this .outputParamWasNull = rs.wasNull();
1361:
1362: return retValue;
1363: }
1364:
1365: /**
1366: * @see java.sql.CallableStatement#getDouble(int)
1367: */
1368: public synchronized double getDouble(int parameterIndex)
1369: throws SQLException {
1370: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1371:
1372: double retValue = rs
1373: .getDouble(mapOutputParameterIndexToRsIndex(parameterIndex));
1374:
1375: this .outputParamWasNull = rs.wasNull();
1376:
1377: return retValue;
1378: }
1379:
1380: /**
1381: * @see java.sql.CallableStatement#getDouble(java.lang.String)
1382: */
1383: public synchronized double getDouble(String parameterName)
1384: throws SQLException {
1385: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1386: // from ?=
1387:
1388: double retValue = rs.getDouble(fixParameterName(parameterName));
1389:
1390: this .outputParamWasNull = rs.wasNull();
1391:
1392: return retValue;
1393: }
1394:
1395: /**
1396: * @see java.sql.CallableStatement#getFloat(int)
1397: */
1398: public synchronized float getFloat(int parameterIndex)
1399: throws SQLException {
1400: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1401:
1402: float retValue = rs
1403: .getFloat(mapOutputParameterIndexToRsIndex(parameterIndex));
1404:
1405: this .outputParamWasNull = rs.wasNull();
1406:
1407: return retValue;
1408: }
1409:
1410: /**
1411: * @see java.sql.CallableStatement#getFloat(java.lang.String)
1412: */
1413: public synchronized float getFloat(String parameterName)
1414: throws SQLException {
1415: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1416: // from ?=
1417:
1418: float retValue = rs.getFloat(fixParameterName(parameterName));
1419:
1420: this .outputParamWasNull = rs.wasNull();
1421:
1422: return retValue;
1423: }
1424:
1425: /**
1426: * @see java.sql.CallableStatement#getInt(int)
1427: */
1428: public synchronized int getInt(int parameterIndex)
1429: throws SQLException {
1430: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1431:
1432: int retValue = rs
1433: .getInt(mapOutputParameterIndexToRsIndex(parameterIndex));
1434:
1435: this .outputParamWasNull = rs.wasNull();
1436:
1437: return retValue;
1438: }
1439:
1440: /**
1441: * @see java.sql.CallableStatement#getInt(java.lang.String)
1442: */
1443: public synchronized int getInt(String parameterName)
1444: throws SQLException {
1445: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1446: // from ?=
1447:
1448: int retValue = rs.getInt(fixParameterName(parameterName));
1449:
1450: this .outputParamWasNull = rs.wasNull();
1451:
1452: return retValue;
1453: }
1454:
1455: /**
1456: * @see java.sql.CallableStatement#getLong(int)
1457: */
1458: public synchronized long getLong(int parameterIndex)
1459: throws SQLException {
1460: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1461:
1462: long retValue = rs
1463: .getLong(mapOutputParameterIndexToRsIndex(parameterIndex));
1464:
1465: this .outputParamWasNull = rs.wasNull();
1466:
1467: return retValue;
1468: }
1469:
1470: /**
1471: * @see java.sql.CallableStatement#getLong(java.lang.String)
1472: */
1473: public synchronized long getLong(String parameterName)
1474: throws SQLException {
1475: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1476: // from ?=
1477:
1478: long retValue = rs.getLong(fixParameterName(parameterName));
1479:
1480: this .outputParamWasNull = rs.wasNull();
1481:
1482: return retValue;
1483: }
1484:
1485: protected int getNamedParamIndex(String paramName, boolean forOut)
1486: throws SQLException {
1487: if (this .connection.getNoAccessToProcedureBodies()) {
1488: throw SQLError
1489: .createSQLException(
1490: "No access to parameters by name when connection has been configured not to access procedure bodies",
1491: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1492: }
1493:
1494: if ((paramName == null) || (paramName.length() == 0)) {
1495: throw SQLError.createSQLException(Messages
1496: .getString("CallableStatement.2"), //$NON-NLS-1$
1497: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1498: }
1499:
1500: if (this .paramInfo == null) {
1501: throw SQLError
1502: .createSQLException(
1503: Messages.getString("CallableStatement.3") + paramName + Messages.getString("CallableStatement.4"), //$NON-NLS-1$ //$NON-NLS-2$
1504: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1505: }
1506:
1507: CallableStatementParam namedParamInfo = this .paramInfo
1508: .getParameter(paramName);
1509:
1510: if (forOut && !namedParamInfo.isOut) {
1511: throw SQLError.createSQLException(Messages
1512: .getString("CallableStatement.5") + paramName //$NON-NLS-1$
1513: + Messages.getString("CallableStatement.6"), //$NON-NLS-1$
1514: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1515: }
1516:
1517: if (this .placeholderToParameterIndexMap == null) {
1518: return namedParamInfo.index + 1; // JDBC indices are 1-based
1519: }
1520:
1521: for (int i = 0; i < this .placeholderToParameterIndexMap.length; i++) {
1522: if (this .placeholderToParameterIndexMap[i] == namedParamInfo.index) {
1523: return i + 1;
1524: }
1525: }
1526:
1527: throw SQLError.createSQLException(
1528: "Can't find local placeholder mapping for parameter named \""
1529: + paramName + "\".",
1530: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1531: }
1532:
1533: /**
1534: * @see java.sql.CallableStatement#getObject(int)
1535: */
1536: public synchronized Object getObject(int parameterIndex)
1537: throws SQLException {
1538: CallableStatementParam paramDescriptor = checkIsOutputParam(parameterIndex);
1539:
1540: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1541:
1542: Object retVal = rs.getObjectStoredProc(
1543: mapOutputParameterIndexToRsIndex(parameterIndex),
1544: paramDescriptor.desiredJdbcType);
1545:
1546: this .outputParamWasNull = rs.wasNull();
1547:
1548: return retVal;
1549: }
1550:
1551: /**
1552: * @see java.sql.CallableStatement#getObject(int, java.util.Map)
1553: */
1554: public synchronized Object getObject(int parameterIndex, Map map)
1555: throws SQLException {
1556: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1557:
1558: Object retVal = rs.getObject(
1559: mapOutputParameterIndexToRsIndex(parameterIndex), map);
1560:
1561: this .outputParamWasNull = rs.wasNull();
1562:
1563: return retVal;
1564: }
1565:
1566: /**
1567: * @see java.sql.CallableStatement#getObject(java.lang.String)
1568: */
1569: public synchronized Object getObject(String parameterName)
1570: throws SQLException {
1571: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1572: // from ?=
1573:
1574: Object retValue = rs.getObject(fixParameterName(parameterName));
1575:
1576: this .outputParamWasNull = rs.wasNull();
1577:
1578: return retValue;
1579: }
1580:
1581: /**
1582: * @see java.sql.CallableStatement#getObject(java.lang.String,
1583: * java.util.Map)
1584: */
1585: public synchronized Object getObject(String parameterName, Map map)
1586: throws SQLException {
1587: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1588: // from ?=
1589:
1590: Object retValue = rs.getObject(fixParameterName(parameterName),
1591: map);
1592:
1593: this .outputParamWasNull = rs.wasNull();
1594:
1595: return retValue;
1596: }
1597:
1598: /**
1599: * Returns the ResultSet that holds the output parameters, or throws an
1600: * appropriate exception if none exist, or they weren't returned.
1601: *
1602: * @return the ResultSet that holds the output parameters
1603: *
1604: * @throws SQLException
1605: * if no output parameters were defined, or if no output
1606: * parameters were returned.
1607: */
1608: protected ResultSetInternalMethods getOutputParameters(
1609: int paramIndex) throws SQLException {
1610: this .outputParamWasNull = false;
1611:
1612: if (paramIndex == 1 && this .callingStoredFunction
1613: && this .returnValueParam != null) {
1614: return this .functionReturnValueResults;
1615: }
1616:
1617: if (this .outputParameterResults == null) {
1618: if (this .paramInfo.numberOfParameters() == 0) {
1619: throw SQLError.createSQLException(Messages
1620: .getString("CallableStatement.7"), //$NON-NLS-1$
1621: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1622: }
1623: throw SQLError.createSQLException(Messages
1624: .getString("CallableStatement.8"), //$NON-NLS-1$
1625: SQLError.SQL_STATE_GENERAL_ERROR);
1626: }
1627:
1628: return this .outputParameterResults;
1629:
1630: }
1631:
1632: public synchronized ParameterMetaData getParameterMetaData()
1633: throws SQLException {
1634: if (this .placeholderToParameterIndexMap == null) {
1635: return (CallableStatementParamInfoJDBC3) this .paramInfo;
1636: } else {
1637: return new CallableStatementParamInfoJDBC3(this .paramInfo);
1638: }
1639: }
1640:
1641: /**
1642: * @see java.sql.CallableStatement#getRef(int)
1643: */
1644: public synchronized Ref getRef(int parameterIndex)
1645: throws SQLException {
1646: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1647:
1648: Ref retValue = rs
1649: .getRef(mapOutputParameterIndexToRsIndex(parameterIndex));
1650:
1651: this .outputParamWasNull = rs.wasNull();
1652:
1653: return retValue;
1654: }
1655:
1656: /**
1657: * @see java.sql.CallableStatement#getRef(java.lang.String)
1658: */
1659: public synchronized Ref getRef(String parameterName)
1660: throws SQLException {
1661: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1662: // from ?=
1663:
1664: Ref retValue = rs.getRef(fixParameterName(parameterName));
1665:
1666: this .outputParamWasNull = rs.wasNull();
1667:
1668: return retValue;
1669: }
1670:
1671: /**
1672: * @see java.sql.CallableStatement#getShort(int)
1673: */
1674: public synchronized short getShort(int parameterIndex)
1675: throws SQLException {
1676: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1677:
1678: short retValue = rs
1679: .getShort(mapOutputParameterIndexToRsIndex(parameterIndex));
1680:
1681: this .outputParamWasNull = rs.wasNull();
1682:
1683: return retValue;
1684: }
1685:
1686: /**
1687: * @see java.sql.CallableStatement#getShort(java.lang.String)
1688: */
1689: public synchronized short getShort(String parameterName)
1690: throws SQLException {
1691: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1692: // from ?=
1693:
1694: short retValue = rs.getShort(fixParameterName(parameterName));
1695:
1696: this .outputParamWasNull = rs.wasNull();
1697:
1698: return retValue;
1699: }
1700:
1701: /**
1702: * @see java.sql.CallableStatement#getString(int)
1703: */
1704: public synchronized String getString(int parameterIndex)
1705: throws SQLException {
1706: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1707:
1708: String retValue = rs
1709: .getString(mapOutputParameterIndexToRsIndex(parameterIndex));
1710:
1711: this .outputParamWasNull = rs.wasNull();
1712:
1713: return retValue;
1714: }
1715:
1716: /**
1717: * @see java.sql.CallableStatement#getString(java.lang.String)
1718: */
1719: public synchronized String getString(String parameterName)
1720: throws SQLException {
1721: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1722: // from ?=
1723:
1724: String retValue = rs.getString(fixParameterName(parameterName));
1725:
1726: this .outputParamWasNull = rs.wasNull();
1727:
1728: return retValue;
1729: }
1730:
1731: /**
1732: * @see java.sql.CallableStatement#getTime(int)
1733: */
1734: public synchronized Time getTime(int parameterIndex)
1735: throws SQLException {
1736: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1737:
1738: Time retValue = rs
1739: .getTime(mapOutputParameterIndexToRsIndex(parameterIndex));
1740:
1741: this .outputParamWasNull = rs.wasNull();
1742:
1743: return retValue;
1744: }
1745:
1746: /**
1747: * @see java.sql.CallableStatement#getTime(int, java.util.Calendar)
1748: */
1749: public synchronized Time getTime(int parameterIndex, Calendar cal)
1750: throws SQLException {
1751: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1752:
1753: Time retValue = rs.getTime(
1754: mapOutputParameterIndexToRsIndex(parameterIndex), cal);
1755:
1756: this .outputParamWasNull = rs.wasNull();
1757:
1758: return retValue;
1759: }
1760:
1761: /**
1762: * @see java.sql.CallableStatement#getTime(java.lang.String)
1763: */
1764: public synchronized Time getTime(String parameterName)
1765: throws SQLException {
1766: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1767: // from ?=
1768:
1769: Time retValue = rs.getTime(fixParameterName(parameterName));
1770:
1771: this .outputParamWasNull = rs.wasNull();
1772:
1773: return retValue;
1774: }
1775:
1776: /**
1777: * @see java.sql.CallableStatement#getTime(java.lang.String,
1778: * java.util.Calendar)
1779: */
1780: public synchronized Time getTime(String parameterName, Calendar cal)
1781: throws SQLException {
1782: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1783: // from ?=
1784:
1785: Time retValue = rs
1786: .getTime(fixParameterName(parameterName), cal);
1787:
1788: this .outputParamWasNull = rs.wasNull();
1789:
1790: return retValue;
1791: }
1792:
1793: /**
1794: * @see java.sql.CallableStatement#getTimestamp(int)
1795: */
1796: public synchronized Timestamp getTimestamp(int parameterIndex)
1797: throws SQLException {
1798: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1799:
1800: Timestamp retValue = rs
1801: .getTimestamp(mapOutputParameterIndexToRsIndex(parameterIndex));
1802:
1803: this .outputParamWasNull = rs.wasNull();
1804:
1805: return retValue;
1806: }
1807:
1808: /**
1809: * @see java.sql.CallableStatement#getTimestamp(int, java.util.Calendar)
1810: */
1811: public synchronized Timestamp getTimestamp(int parameterIndex,
1812: Calendar cal) throws SQLException {
1813: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1814:
1815: Timestamp retValue = rs.getTimestamp(
1816: mapOutputParameterIndexToRsIndex(parameterIndex), cal);
1817:
1818: this .outputParamWasNull = rs.wasNull();
1819:
1820: return retValue;
1821: }
1822:
1823: /**
1824: * @see java.sql.CallableStatement#getTimestamp(java.lang.String)
1825: */
1826: public synchronized Timestamp getTimestamp(String parameterName)
1827: throws SQLException {
1828: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1829: // from ?=
1830:
1831: Timestamp retValue = rs
1832: .getTimestamp(fixParameterName(parameterName));
1833:
1834: this .outputParamWasNull = rs.wasNull();
1835:
1836: return retValue;
1837: }
1838:
1839: /**
1840: * @see java.sql.CallableStatement#getTimestamp(java.lang.String,
1841: * java.util.Calendar)
1842: */
1843: public synchronized Timestamp getTimestamp(String parameterName,
1844: Calendar cal) throws SQLException {
1845: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1846: // from ?=
1847:
1848: Timestamp retValue = rs.getTimestamp(
1849: fixParameterName(parameterName), cal);
1850:
1851: this .outputParamWasNull = rs.wasNull();
1852:
1853: return retValue;
1854: }
1855:
1856: /**
1857: * @see java.sql.CallableStatement#getURL(int)
1858: */
1859: public synchronized URL getURL(int parameterIndex)
1860: throws SQLException {
1861: ResultSetInternalMethods rs = getOutputParameters(parameterIndex);
1862:
1863: URL retValue = rs
1864: .getURL(mapOutputParameterIndexToRsIndex(parameterIndex));
1865:
1866: this .outputParamWasNull = rs.wasNull();
1867:
1868: return retValue;
1869: }
1870:
1871: /**
1872: * @see java.sql.CallableStatement#getURL(java.lang.String)
1873: */
1874: public synchronized URL getURL(String parameterName)
1875: throws SQLException {
1876: ResultSetInternalMethods rs = getOutputParameters(0); // definitely not going to be
1877: // from ?=
1878:
1879: URL retValue = rs.getURL(fixParameterName(parameterName));
1880:
1881: this .outputParamWasNull = rs.wasNull();
1882:
1883: return retValue;
1884: }
1885:
1886: protected int mapOutputParameterIndexToRsIndex(int paramIndex)
1887: throws SQLException {
1888:
1889: if (this .returnValueParam != null && paramIndex == 1) {
1890: return 1;
1891: }
1892:
1893: checkParameterIndexBounds(paramIndex);
1894:
1895: int localParamIndex = paramIndex - 1;
1896:
1897: if (this .placeholderToParameterIndexMap != null) {
1898: localParamIndex = this .placeholderToParameterIndexMap[localParamIndex];
1899: }
1900:
1901: int rsIndex = this .parameterIndexToRsIndex[localParamIndex];
1902:
1903: if (rsIndex == NOT_OUTPUT_PARAMETER_INDICATOR) {
1904: throw SQLError.createSQLException(Messages
1905: .getString("CallableStatement.21") + paramIndex //$NON-NLS-1$
1906: + Messages.getString("CallableStatement.22"), //$NON-NLS-1$
1907: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1908: }
1909:
1910: return rsIndex + 1;
1911: }
1912:
1913: /**
1914: * @see java.sql.CallableStatement#registerOutParameter(int, int)
1915: */
1916: public void registerOutParameter(int parameterIndex, int sqlType)
1917: throws SQLException {
1918: CallableStatementParam paramDescriptor = checkIsOutputParam(parameterIndex);
1919: paramDescriptor.desiredJdbcType = sqlType;
1920: }
1921:
1922: /**
1923: * @see java.sql.CallableStatement#registerOutParameter(int, int, int)
1924: */
1925: public void registerOutParameter(int parameterIndex, int sqlType,
1926: int scale) throws SQLException {
1927: registerOutParameter(parameterIndex, sqlType);
1928: }
1929:
1930: /**
1931: * @see java.sql.CallableStatement#registerOutParameter(int, int,
1932: * java.lang.String)
1933: */
1934: public void registerOutParameter(int parameterIndex, int sqlType,
1935: String typeName) throws SQLException {
1936: checkIsOutputParam(parameterIndex);
1937: }
1938:
1939: /**
1940: * @see java.sql.CallableStatement#registerOutParameter(java.lang.String,
1941: * int)
1942: */
1943: public synchronized void registerOutParameter(String parameterName,
1944: int sqlType) throws SQLException {
1945: registerOutParameter(getNamedParamIndex(parameterName, true),
1946: sqlType);
1947: }
1948:
1949: /**
1950: * @see java.sql.CallableStatement#registerOutParameter(java.lang.String,
1951: * int, int)
1952: */
1953: public void registerOutParameter(String parameterName, int sqlType,
1954: int scale) throws SQLException {
1955: registerOutParameter(getNamedParamIndex(parameterName, true),
1956: sqlType);
1957: }
1958:
1959: /**
1960: * @see java.sql.CallableStatement#registerOutParameter(java.lang.String,
1961: * int, java.lang.String)
1962: */
1963: public void registerOutParameter(String parameterName, int sqlType,
1964: String typeName) throws SQLException {
1965: registerOutParameter(getNamedParamIndex(parameterName, true),
1966: sqlType, typeName);
1967: }
1968:
1969: /**
1970: * Issues a second query to retrieve all output parameters.
1971: *
1972: * @throws SQLException
1973: * if an error occurs.
1974: */
1975: private void retrieveOutParams() throws SQLException {
1976: int numParameters = this .paramInfo.numberOfParameters();
1977:
1978: this .parameterIndexToRsIndex = new int[numParameters];
1979:
1980: for (int i = 0; i < numParameters; i++) {
1981: this .parameterIndexToRsIndex[i] = NOT_OUTPUT_PARAMETER_INDICATOR;
1982: }
1983:
1984: int localParamIndex = 0;
1985:
1986: if (numParameters > 0) {
1987: StringBuffer outParameterQuery = new StringBuffer("SELECT "); //$NON-NLS-1$
1988:
1989: boolean firstParam = true;
1990: boolean hadOutputParams = false;
1991:
1992: for (Iterator paramIter = this .paramInfo.iterator(); paramIter
1993: .hasNext();) {
1994: CallableStatementParam retrParamInfo = (CallableStatementParam) paramIter
1995: .next();
1996:
1997: if (retrParamInfo.isOut) {
1998: hadOutputParams = true;
1999:
2000: this .parameterIndexToRsIndex[retrParamInfo.index] = localParamIndex++;
2001:
2002: String outParameterName = mangleParameterName(retrParamInfo.paramName);
2003:
2004: if (!firstParam) {
2005: outParameterQuery.append(","); //$NON-NLS-1$
2006: } else {
2007: firstParam = false;
2008: }
2009:
2010: if (!outParameterName.startsWith("@")) { //$NON-NLS-1$
2011: outParameterQuery.append('@');
2012: }
2013:
2014: outParameterQuery.append(outParameterName);
2015: }
2016: }
2017:
2018: if (hadOutputParams) {
2019: // We can't use 'ourself' to execute this query, or any
2020: // pending result sets would be overwritten
2021: java.sql.Statement outParameterStmt = null;
2022: java.sql.ResultSet outParamRs = null;
2023:
2024: try {
2025: outParameterStmt = this .connection
2026: .createStatement();
2027: outParamRs = outParameterStmt
2028: .executeQuery(outParameterQuery.toString());
2029: this .outputParameterResults = ((com.mysql.jdbc.ResultSetInternalMethods) outParamRs)
2030: .copy();
2031:
2032: if (!this .outputParameterResults.next()) {
2033: this .outputParameterResults.close();
2034: this .outputParameterResults = null;
2035: }
2036: } finally {
2037: if (outParameterStmt != null) {
2038: outParameterStmt.close();
2039: }
2040: }
2041: } else {
2042: this .outputParameterResults = null;
2043: }
2044: } else {
2045: this .outputParameterResults = null;
2046: }
2047: }
2048:
2049: /**
2050: * @see java.sql.CallableStatement#setAsciiStream(java.lang.String,
2051: * java.io.InputStream, int)
2052: */
2053: public void setAsciiStream(String parameterName, InputStream x,
2054: int length) throws SQLException {
2055: setAsciiStream(getNamedParamIndex(parameterName, false), x,
2056: length);
2057: }
2058:
2059: /**
2060: * @see java.sql.CallableStatement#setBigDecimal(java.lang.String,
2061: * java.math.BigDecimal)
2062: */
2063: public void setBigDecimal(String parameterName, BigDecimal x)
2064: throws SQLException {
2065: setBigDecimal(getNamedParamIndex(parameterName, false), x);
2066: }
2067:
2068: /**
2069: * @see java.sql.CallableStatement#setBinaryStream(java.lang.String,
2070: * java.io.InputStream, int)
2071: */
2072: public void setBinaryStream(String parameterName, InputStream x,
2073: int length) throws SQLException {
2074: setBinaryStream(getNamedParamIndex(parameterName, false), x,
2075: length);
2076: }
2077:
2078: /**
2079: * @see java.sql.CallableStatement#setBoolean(java.lang.String, boolean)
2080: */
2081: public void setBoolean(String parameterName, boolean x)
2082: throws SQLException {
2083: setBoolean(getNamedParamIndex(parameterName, false), x);
2084: }
2085:
2086: /**
2087: * @see java.sql.CallableStatement#setByte(java.lang.String, byte)
2088: */
2089: public void setByte(String parameterName, byte x)
2090: throws SQLException {
2091: setByte(getNamedParamIndex(parameterName, false), x);
2092: }
2093:
2094: /**
2095: * @see java.sql.CallableStatement#setBytes(java.lang.String, byte[])
2096: */
2097: public void setBytes(String parameterName, byte[] x)
2098: throws SQLException {
2099: setBytes(getNamedParamIndex(parameterName, false), x);
2100: }
2101:
2102: /**
2103: * @see java.sql.CallableStatement#setCharacterStream(java.lang.String,
2104: * java.io.Reader, int)
2105: */
2106: public void setCharacterStream(String parameterName, Reader reader,
2107: int length) throws SQLException {
2108: setCharacterStream(getNamedParamIndex(parameterName, false),
2109: reader, length);
2110: }
2111:
2112: /**
2113: * @see java.sql.CallableStatement#setDate(java.lang.String, java.sql.Date)
2114: */
2115: public void setDate(String parameterName, Date x)
2116: throws SQLException {
2117: setDate(getNamedParamIndex(parameterName, false), x);
2118: }
2119:
2120: /**
2121: * @see java.sql.CallableStatement#setDate(java.lang.String, java.sql.Date,
2122: * java.util.Calendar)
2123: */
2124: public void setDate(String parameterName, Date x, Calendar cal)
2125: throws SQLException {
2126: setDate(getNamedParamIndex(parameterName, false), x, cal);
2127: }
2128:
2129: /**
2130: * @see java.sql.CallableStatement#setDouble(java.lang.String, double)
2131: */
2132: public void setDouble(String parameterName, double x)
2133: throws SQLException {
2134: setDouble(getNamedParamIndex(parameterName, false), x);
2135: }
2136:
2137: /**
2138: * @see java.sql.CallableStatement#setFloat(java.lang.String, float)
2139: */
2140: public void setFloat(String parameterName, float x)
2141: throws SQLException {
2142: setFloat(getNamedParamIndex(parameterName, false), x);
2143: }
2144:
2145: /**
2146: *
2147: */
2148: private void setInOutParamsOnServer() throws SQLException {
2149: if (this .paramInfo.numParameters > 0) {
2150: int parameterIndex = 0;
2151:
2152: for (Iterator paramIter = this .paramInfo.iterator(); paramIter
2153: .hasNext();) {
2154:
2155: CallableStatementParam inParamInfo = (CallableStatementParam) paramIter
2156: .next();
2157:
2158: if (inParamInfo.isOut && inParamInfo.isIn) {
2159: String inOutParameterName = mangleParameterName(inParamInfo.paramName);
2160: StringBuffer queryBuf = new StringBuffer(
2161: 4 + inOutParameterName.length() + 1 + 1);
2162: queryBuf.append("SET "); //$NON-NLS-1$
2163: queryBuf.append(inOutParameterName);
2164: queryBuf.append("=?"); //$NON-NLS-1$
2165:
2166: PreparedStatement setPstmt = null;
2167:
2168: try {
2169: setPstmt = this .connection
2170: .clientPrepareStatement(queryBuf
2171: .toString());
2172:
2173: byte[] parameterAsBytes = getBytesRepresentation(inParamInfo.index);
2174:
2175: if (parameterAsBytes != null) {
2176: if (parameterAsBytes.length > 8
2177: && parameterAsBytes[0] == '_'
2178: && parameterAsBytes[1] == 'b'
2179: && parameterAsBytes[2] == 'i'
2180: && parameterAsBytes[3] == 'n'
2181: && parameterAsBytes[4] == 'a'
2182: && parameterAsBytes[5] == 'r'
2183: && parameterAsBytes[6] == 'y'
2184: && parameterAsBytes[7] == '\'') {
2185: setPstmt.setBytesNoEscapeNoQuotes(1,
2186: parameterAsBytes);
2187: } else {
2188: int sqlType = inParamInfo.desiredJdbcType;
2189:
2190: switch (sqlType) {
2191: case Types.BIT:
2192: case Types.BINARY:
2193: case Types.BLOB:
2194: case Types.JAVA_OBJECT:
2195: case Types.LONGVARBINARY:
2196: case Types.VARBINARY:
2197: setPstmt.setBytes(1,
2198: parameterAsBytes);
2199: break;
2200: default:
2201: // the inherited PreparedStatement methods
2202: // have already escaped and quoted these parameters
2203: setPstmt.setBytesNoEscape(1,
2204: parameterAsBytes);
2205: }
2206: }
2207: } else {
2208: setPstmt.setNull(1, Types.NULL);
2209: }
2210:
2211: setPstmt.executeUpdate();
2212: } finally {
2213: if (setPstmt != null) {
2214: setPstmt.close();
2215: }
2216: }
2217: }
2218:
2219: parameterIndex++;
2220: }
2221: }
2222: }
2223:
2224: /**
2225: * @see java.sql.CallableStatement#setInt(java.lang.String, int)
2226: */
2227: public void setInt(String parameterName, int x) throws SQLException {
2228: setInt(getNamedParamIndex(parameterName, false), x);
2229: }
2230:
2231: /**
2232: * @see java.sql.CallableStatement#setLong(java.lang.String, long)
2233: */
2234: public void setLong(String parameterName, long x)
2235: throws SQLException {
2236: setLong(getNamedParamIndex(parameterName, false), x);
2237: }
2238:
2239: /**
2240: * @see java.sql.CallableStatement#setNull(java.lang.String, int)
2241: */
2242: public void setNull(String parameterName, int sqlType)
2243: throws SQLException {
2244: setNull(getNamedParamIndex(parameterName, false), sqlType);
2245: }
2246:
2247: /**
2248: * @see java.sql.CallableStatement#setNull(java.lang.String, int,
2249: * java.lang.String)
2250: */
2251: public void setNull(String parameterName, int sqlType,
2252: String typeName) throws SQLException {
2253: setNull(getNamedParamIndex(parameterName, false), sqlType,
2254: typeName);
2255: }
2256:
2257: /**
2258: * @see java.sql.CallableStatement#setObject(java.lang.String,
2259: * java.lang.Object)
2260: */
2261: public void setObject(String parameterName, Object x)
2262: throws SQLException {
2263: setObject(getNamedParamIndex(parameterName, false), x);
2264: }
2265:
2266: /**
2267: * @see java.sql.CallableStatement#setObject(java.lang.String,
2268: * java.lang.Object, int)
2269: */
2270: public void setObject(String parameterName, Object x,
2271: int targetSqlType) throws SQLException {
2272: setObject(getNamedParamIndex(parameterName, false), x,
2273: targetSqlType);
2274: }
2275:
2276: /**
2277: * @see java.sql.CallableStatement#setObject(java.lang.String,
2278: * java.lang.Object, int, int)
2279: */
2280: public void setObject(String parameterName, Object x,
2281: int targetSqlType, int scale) throws SQLException {
2282: }
2283:
2284: private void setOutParams() throws SQLException {
2285: if (this .paramInfo.numParameters > 0) {
2286: for (Iterator paramIter = this .paramInfo.iterator(); paramIter
2287: .hasNext();) {
2288: CallableStatementParam outParamInfo = (CallableStatementParam) paramIter
2289: .next();
2290:
2291: if (!this .callingStoredFunction && outParamInfo.isOut) {
2292: String outParameterName = mangleParameterName(outParamInfo.paramName);
2293:
2294: int outParamIndex;
2295:
2296: if (this .placeholderToParameterIndexMap == null) {
2297: outParamIndex = outParamInfo.index + 1;
2298: } else {
2299: outParamIndex = this .placeholderToParameterIndexMap[outParamInfo.index - 1 /* JDBC is 1-based */];
2300: }
2301:
2302: this
2303: .setBytesNoEscapeNoQuotes(
2304: outParamIndex,
2305: StringUtils
2306: .getBytes(
2307: outParameterName,
2308: this .charConverter,
2309: this .charEncoding,
2310: this .connection
2311: .getServerCharacterEncoding(),
2312: this .connection
2313: .parserKnowsUnicode()));
2314: }
2315: }
2316: }
2317: }
2318:
2319: /**
2320: * @see java.sql.CallableStatement#setShort(java.lang.String, short)
2321: */
2322: public void setShort(String parameterName, short x)
2323: throws SQLException {
2324: setShort(getNamedParamIndex(parameterName, false), x);
2325: }
2326:
2327: /**
2328: * @see java.sql.CallableStatement#setString(java.lang.String,
2329: * java.lang.String)
2330: */
2331: public void setString(String parameterName, String x)
2332: throws SQLException {
2333: setString(getNamedParamIndex(parameterName, false), x);
2334: }
2335:
2336: /**
2337: * @see java.sql.CallableStatement#setTime(java.lang.String, java.sql.Time)
2338: */
2339: public void setTime(String parameterName, Time x)
2340: throws SQLException {
2341: setTime(getNamedParamIndex(parameterName, false), x);
2342: }
2343:
2344: /**
2345: * @see java.sql.CallableStatement#setTime(java.lang.String, java.sql.Time,
2346: * java.util.Calendar)
2347: */
2348: public void setTime(String parameterName, Time x, Calendar cal)
2349: throws SQLException {
2350: setTime(getNamedParamIndex(parameterName, false), x, cal);
2351: }
2352:
2353: /**
2354: * @see java.sql.CallableStatement#setTimestamp(java.lang.String,
2355: * java.sql.Timestamp)
2356: */
2357: public void setTimestamp(String parameterName, Timestamp x)
2358: throws SQLException {
2359: setTimestamp(getNamedParamIndex(parameterName, false), x);
2360: }
2361:
2362: /**
2363: * @see java.sql.CallableStatement#setTimestamp(java.lang.String,
2364: * java.sql.Timestamp, java.util.Calendar)
2365: */
2366: public void setTimestamp(String parameterName, Timestamp x,
2367: Calendar cal) throws SQLException {
2368: setTimestamp(getNamedParamIndex(parameterName, false), x, cal);
2369: }
2370:
2371: /**
2372: * @see java.sql.CallableStatement#setURL(java.lang.String, java.net.URL)
2373: */
2374: public void setURL(String parameterName, URL val)
2375: throws SQLException {
2376: setURL(getNamedParamIndex(parameterName, false), val);
2377: }
2378:
2379: /**
2380: * @see java.sql.CallableStatement#wasNull()
2381: */
2382: public synchronized boolean wasNull() throws SQLException {
2383: return this .outputParamWasNull;
2384: }
2385:
2386: public int[] executeBatch() throws SQLException {
2387: if (this .hasOutputParams) {
2388: throw SQLError
2389: .createSQLException(
2390: "Can't call executeBatch() on CallableStatement with OUTPUT parameters",
2391: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2392: }
2393:
2394: return super .executeBatch();
2395: }
2396:
2397: protected int getParameterIndexOffset() {
2398: if (this .callingStoredFunction) {
2399: return -1;
2400: }
2401:
2402: return super .getParameterIndexOffset();
2403: }
2404:
2405: public void setAsciiStream(String parameterName, InputStream x)
2406: throws SQLException {
2407: setAsciiStream(getNamedParamIndex(parameterName, false), x);
2408:
2409: }
2410:
2411: public void setAsciiStream(String parameterName, InputStream x,
2412: long length) throws SQLException {
2413: setAsciiStream(getNamedParamIndex(parameterName, false), x,
2414: length);
2415:
2416: }
2417:
2418: public void setBinaryStream(String parameterName, InputStream x)
2419: throws SQLException {
2420: setBinaryStream(getNamedParamIndex(parameterName, false), x);
2421:
2422: }
2423:
2424: public void setBinaryStream(String parameterName, InputStream x,
2425: long length) throws SQLException {
2426: setBinaryStream(getNamedParamIndex(parameterName, false), x,
2427: length);
2428:
2429: }
2430:
2431: public void setBlob(String parameterName, Blob x)
2432: throws SQLException {
2433: setBlob(getNamedParamIndex(parameterName, false), x);
2434:
2435: }
2436:
2437: public void setBlob(String parameterName, InputStream inputStream)
2438: throws SQLException {
2439: setBlob(getNamedParamIndex(parameterName, false), inputStream);
2440:
2441: }
2442:
2443: public void setBlob(String parameterName, InputStream inputStream,
2444: long length) throws SQLException {
2445: setBlob(getNamedParamIndex(parameterName, false), inputStream,
2446: length);
2447:
2448: }
2449:
2450: public void setCharacterStream(String parameterName, Reader reader)
2451: throws SQLException {
2452: setCharacterStream(getNamedParamIndex(parameterName, false),
2453: reader);
2454:
2455: }
2456:
2457: public void setCharacterStream(String parameterName, Reader reader,
2458: long length) throws SQLException {
2459: setCharacterStream(getNamedParamIndex(parameterName, false),
2460: reader, length);
2461:
2462: }
2463:
2464: public void setClob(String parameterName, Clob x)
2465: throws SQLException {
2466: setClob(getNamedParamIndex(parameterName, false), x);
2467:
2468: }
2469:
2470: public void setClob(String parameterName, Reader reader)
2471: throws SQLException {
2472: setClob(getNamedParamIndex(parameterName, false), reader);
2473:
2474: }
2475:
2476: public void setClob(String parameterName, Reader reader, long length)
2477: throws SQLException {
2478: setClob(getNamedParamIndex(parameterName, false), reader,
2479: length);
2480:
2481: }
2482:
2483: public void setNCharacterStream(String parameterName, Reader value)
2484: throws SQLException {
2485: setNCharacterStream(getNamedParamIndex(parameterName, false),
2486: value);
2487:
2488: }
2489:
2490: public void setNCharacterStream(String parameterName, Reader value,
2491: long length) throws SQLException {
2492: setNCharacterStream(getNamedParamIndex(parameterName, false),
2493: value, length);
2494:
2495: }
2496:
2497: }
|