--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.GenericParameterValueSet\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to you under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.sql;\r
+\r
+import org.apache.derby.iapi.services.loader.ClassFactory;\r
+import org.apache.derby.iapi.services.loader.ClassInspector;\r
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;\r
+\r
+import org.apache.derby.iapi.sql.ParameterValueSet;\r
+\r
+import org.apache.derby.iapi.types.DataTypeDescriptor;\r
+import org.apache.derby.iapi.types.DataValueFactory;\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+import org.apache.derby.iapi.types.UserDataValue;\r
+\r
+import org.apache.derby.iapi.reference.SQLState;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import java.io.InputStream;\r
+import java.sql.Date;\r
+import java.sql.Time;\r
+import java.sql.Timestamp;\r
+import java.sql.Types;\r
+import org.apache.derby.iapi.reference.JDBC30Translation;\r
+\r
+/**\r
+ * Implementation of ParameterValueSet\r
+ *\r
+ * @see ParameterValueSet\r
+ *\r
+ */\r
+\r
+final class GenericParameterValueSet implements ParameterValueSet \r
+{\r
+ //all this has to be copied in the clone constructor\r
+ private final GenericParameter[] parms;\r
+ final ClassInspector ci;\r
+ private final boolean hasReturnOutputParam;\r
+\r
+\r
+ /**\r
+ * Constructor for a GenericParameterValueSet\r
+ *\r
+ * @param numParms The number of parameters in the new ParameterValueSet\r
+ * @param hasReturnOutputParam if we have a ? = call syntax. Note that\r
+ * this is NOT the same thing as an output parameter -- return\r
+ * output parameters are special cases of output parameters.\r
+ */\r
+ GenericParameterValueSet(ClassInspector ci, int numParms, boolean hasReturnOutputParam)\r
+ {\r
+ this.ci = ci;\r
+ this.hasReturnOutputParam = hasReturnOutputParam;\r
+ parms = new GenericParameter[numParms];\r
+ for (int i = 0; i < numParms; i++)\r
+ {\r
+ /*\r
+ ** Last param is if this is a return output param. True if \r
+ ** we have an output param and we are on the 1st parameter.\r
+ */ \r
+ parms[i] = new GenericParameter(this, (hasReturnOutputParam && i == 0));\r
+ }\r
+ }\r
+\r
+ /*\r
+ ** Construct a pvs by cloning a pvs.\r
+ */\r
+ private GenericParameterValueSet(int numParms, GenericParameterValueSet pvs)\r
+ {\r
+ this.hasReturnOutputParam = pvs.hasReturnOutputParam;\r
+ this.ci = pvs.ci;\r
+ parms = new GenericParameter[numParms];\r
+ for (int i = 0; i < numParms; i++)\r
+ {\r
+ parms[i] = pvs.getGenericParameter(i).getClone(this);\r
+ }\r
+ }\r
+\r
+ /*\r
+ ** ParameterValueSet interface methods\r
+ */\r
+ \r
+ /**\r
+ * Initialize the set by allocating a holder DataValueDescriptor object\r
+ * for each parameter.\r
+ */\r
+ public void initialize(DataTypeDescriptor[] types) throws StandardException\r
+ {\r
+ for (int i = 0; i < parms.length; i++)\r
+ {\r
+ DataTypeDescriptor dtd = types[i];\r
+ \r
+ parms[i].initialize(dtd.getNull(),\r
+ dtd.getJDBCTypeId(), dtd.getTypeId().getCorrespondingJavaTypeName());\r
+ }\r
+ }\r
+\r
+ public void setParameterMode(int position, int mode) {\r
+ parms[position].parameterMode = (short) mode;\r
+ }\r
+\r
+ /**\r
+ * @see ParameterValueSet#clearParameters\r
+ */\r
+ public void clearParameters()\r
+ {\r
+ for (int i = 0; i < parms.length; i++)\r
+ {\r
+ parms[i].clear();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Returns the number of parameters in this set.\r
+ *\r
+ * @return The number of parameters in this set.\r
+ */\r
+ public int getParameterCount()\r
+ {\r
+ return parms.length;\r
+ }\r
+\r
+ /**\r
+ * Returns the parameter value at the given position.\r
+ *\r
+ * @return The parameter at the given position.\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ public DataValueDescriptor getParameter( int position ) throws StandardException\r
+ {\r
+ try {\r
+ return parms[position].getValue();\r
+ } catch (ArrayIndexOutOfBoundsException e) {\r
+ checkPosition(position);\r
+ return null;\r
+ }\r
+ }\r
+\r
+\r
+\r
+ public DataValueDescriptor getParameterForSet(int position) throws StandardException {\r
+\r
+ try {\r
+\r
+ GenericParameter gp = parms[position];\r
+ if (gp.parameterMode == JDBC30Translation.PARAMETER_MODE_OUT)\r
+ throw StandardException.newException(SQLState.LANG_RETURN_OUTPUT_PARAM_CANNOT_BE_SET);\r
+\r
+ gp.isSet = true;\r
+\r
+ return gp.getValue();\r
+ } catch (ArrayIndexOutOfBoundsException e) {\r
+ checkPosition(position);\r
+ return null;\r
+ }\r
+\r
+ }\r
+ \r
+ public DataValueDescriptor getParameterForGet(int position) throws StandardException {\r
+\r
+ try {\r
+\r
+ GenericParameter gp = parms[position];\r
+\r
+ switch (gp.parameterMode) {\r
+ case JDBC30Translation.PARAMETER_MODE_IN:\r
+ case JDBC30Translation.PARAMETER_MODE_UNKNOWN:\r
+ throw StandardException.newException(SQLState.LANG_NOT_OUTPUT_PARAMETER, Integer.toString(position + 1));\r
+ }\r
+\r
+ return gp.getValue();\r
+ } catch (ArrayIndexOutOfBoundsException e) {\r
+ checkPosition(position);\r
+ return null;\r
+ }\r
+ }\r
+\r
+ public void setParameterAsObject(int position, Object value) throws StandardException {\r
+\r
+ UserDataValue dvd = (UserDataValue) getParameterForSet(position);\r
+\r
+ GenericParameter gp = parms[position];\r
+ if (value != null) {\r
+\r
+ {\r
+\r
+ boolean throwError;\r
+ ClassNotFoundException t = null;\r
+ try {\r
+ throwError = !ci.instanceOf(gp.declaredClassName, value);\r
+ } catch (ClassNotFoundException cnfe) {\r
+ t = cnfe;\r
+ throwError = true;\r
+ }\r
+\r
+ if (throwError) {\r
+ throw StandardException.newException(SQLState.LANG_DATA_TYPE_SET_MISMATCH, t,\r
+ ClassInspector.readableClassName(value.getClass()), gp.declaredClassName);\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ dvd.setValue(value);\r
+ }\r
+\r
+ /**\r
+ * @see ParameterValueSet#allAreSet\r
+ */\r
+ public boolean allAreSet()\r
+ {\r
+ for (int i = 0; i < parms.length; i++)\r
+ {\r
+ GenericParameter gp = parms[i];\r
+ if (!gp.isSet)\r
+ {\r
+ switch (gp.parameterMode) {\r
+ case JDBC30Translation.PARAMETER_MODE_OUT:\r
+ break;\r
+ case JDBC30Translation.PARAMETER_MODE_IN_OUT:\r
+ case JDBC30Translation.PARAMETER_MODE_UNKNOWN:\r
+ case JDBC30Translation.PARAMETER_MODE_IN:\r
+ return false;\r
+ }\r
+ }\r
+ }\r
+\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * @see ParameterValueSet#transferDataValues\r
+ */\r
+ public void transferDataValues(ParameterValueSet pvstarget) throws StandardException\r
+ {\r
+ // don't take application's values for return output parameters\r
+ int firstParam = pvstarget.hasReturnOutputParameter() ? 1 : 0;\r
+ for (int i = firstParam; i < parms.length;i++)\r
+ {\r
+\r
+ GenericParameter oldp = parms[i];\r
+\r
+ if (oldp.registerOutType != Types.NULL) {\r
+\r
+ pvstarget.registerOutParameter(i, oldp.registerOutType, oldp.registerOutScale);\r
+\r
+ }\r
+\r
+ if (oldp.isSet)\r
+ {\r
+ pvstarget.getParameterForSet(i).setValue(oldp.getValue());\r
+ }\r
+ }\r
+ }\r
+\r
+ GenericParameter getGenericParameter(int position)\r
+ {\r
+ return(parms[position]);\r
+ }\r
+\r
+ /* Class implementation */\r
+ public String toString()\r
+ {\r
+ /* This method needed for derby.language.logStatementText=true.\r
+ * Do not put under SanityManager.DEBUG.\r
+ */\r
+ StringBuffer strbuf = new StringBuffer();\r
+\r
+ for (int ctr = 0; ctr < parms.length; ctr++)\r
+ {\r
+ strbuf.append("begin parameter #" + (ctr + 1) + ": ");\r
+ strbuf.append(parms[ctr].toString());\r
+ strbuf.append(" :end parameter ");\r
+ }\r
+\r
+ return strbuf.toString();\r
+ }\r
+\r
+ /**\r
+ * Check the position number for a parameter and throw an exception if\r
+ * it is out of range.\r
+ *\r
+ * @param position The position number to check\r
+ *\r
+ * @exception StandardException Thrown if position number is\r
+ * out of range.\r
+ */\r
+ private void checkPosition(int position) throws StandardException\r
+ {\r
+ if (position < 0 || position >= parms.length)\r
+ {\r
+\r
+ if (parms.length == 0)\r
+ throw StandardException.newException(SQLState.NO_INPUT_PARAMETERS);\r
+\r
+ throw StandardException.newException(SQLState.LANG_INVALID_PARAM_POSITION, \r
+ String.valueOf(position+1),\r
+ String.valueOf(parms.length));\r
+ }\r
+ }\r
+\r
+\r
+ public ParameterValueSet getClone()\r
+ {\r
+ return(new GenericParameterValueSet(parms.length, this));\r
+ }\r
+\r
+ //////////////////////////////////////////////////////////////////\r
+ //\r
+ // CALLABLE STATEMENT\r
+ //\r
+ //////////////////////////////////////////////////////////////////\r
+\r
+ /**\r
+ * Mark the parameter as an output parameter.\r
+ *\r
+ * @param parameterIndex The ordinal parameterIndex of a parameter to set\r
+ * to the given value.\r
+ * @param sqlType A type from java.sql.Types\r
+ * @param scale the scale to use. -1 means ignore scale\r
+ *\r
+ * @exception StandardException on error\r
+ */\r
+ public void registerOutParameter(int parameterIndex, int sqlType, int scale)\r
+ throws StandardException\r
+ {\r
+ checkPosition(parameterIndex);\r
+ parms[parameterIndex].setOutParameter(sqlType, scale);\r
+ }\r
+\r
+ /**\r
+ * Validate the parameters. This is done for situations where\r
+ * we cannot validate everything in the setXXX() calls. In\r
+ * particular, before we do an execute() on a CallableStatement,\r
+ * we need to go through the parameters and make sure that\r
+ * all parameters are set up properly. The motivator for this\r
+ * is that setXXX() can be called either before or after \r
+ * registerOutputParamter(), we cannot be sure we have the types\r
+ * correct until we get to execute().\r
+ *\r
+ * @exception StandardException if the parameters aren't valid\r
+ */\r
+ public void validate() throws StandardException\r
+ {\r
+ for (int i = 0; i < parms.length; i++)\r
+ {\r
+ parms[i].validate();\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ * Return the parameter number (in jdbc lingo, i.e. 1 based)\r
+ * for the given parameter. Linear search. \r
+ *\r
+ * @return the parameter number, or 0 if not found\r
+ */\r
+ public int getParameterNumber(GenericParameter theParam)\r
+ {\r
+ for (int i = 0; i < parms.length; i++)\r
+ {\r
+ if (parms[i] == theParam)\r
+ {\r
+ return i+1;\r
+ }\r
+ }\r
+ return 0;\r
+ }\r
+\r
+ /**\r
+ Check that there are not output parameters defined\r
+ by the parameter set. If there are unknown parameter\r
+ types they are forced to input types. i.e. Derby static method\r
+ calls with parameters that are array.\r
+\r
+ @return true if a declared Java Procedure INOUT or OUT parameter is in the set, false otherwise.\r
+ */\r
+ public boolean checkNoDeclaredOutputParameters() {\r
+\r
+ boolean hasDeclaredOutputParameter = false;\r
+ for (int i=0; i<parms.length; i++) {\r
+\r
+ GenericParameter gp = parms[i];\r
+\r
+ switch (gp.parameterMode) {\r
+ case JDBC30Translation.PARAMETER_MODE_IN:\r
+ break;\r
+ case JDBC30Translation.PARAMETER_MODE_IN_OUT:\r
+ case JDBC30Translation.PARAMETER_MODE_OUT:\r
+ hasDeclaredOutputParameter = true;\r
+ break;\r
+ case JDBC30Translation.PARAMETER_MODE_UNKNOWN:\r
+ gp.parameterMode = JDBC30Translation.PARAMETER_MODE_IN;\r
+ break;\r
+ }\r
+ }\r
+ return hasDeclaredOutputParameter;\r
+ }\r
+\r
+ /**\r
+ Return the mode of the parameter according to JDBC 3.0 ParameterMetaData\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ *\r
+ */\r
+ public short getParameterMode(int parameterIndex)\r
+ {\r
+ short mode = parms[parameterIndex - 1].parameterMode;\r
+ //if (mode == (short) JDBC30Translation.PARAMETER_MODE_UNKNOWN)\r
+ // mode = (short) JDBC30Translation.PARAMETER_MODE_IN;\r
+ return mode;\r
+ }\r
+\r
+ /**\r
+ * Is there a return output parameter in this pvs. A return\r
+ * parameter is from a CALL statement of the following\r
+ * syntax: ? = CALL myMethod()\r
+ *\r
+ * @return true if it has a return parameter\r
+ *\r
+ */\r
+ public boolean hasReturnOutputParameter()\r
+ {\r
+ return hasReturnOutputParam;\r
+ }\r
+\r
+ /**\r
+ * Get the value of the return parameter in order to set it.\r
+ *\r
+ *\r
+ * @exception StandardException if a database-access error occurs.\r
+ */\r
+ public DataValueDescriptor getReturnValueForSet() throws StandardException\r
+ {\r
+ checkPosition(0);\r
+ \r
+ if (SanityManager.DEBUG)\r
+ {\r
+ if (!hasReturnOutputParam)\r
+ SanityManager.THROWASSERT("getReturnValueForSet called on non-return parameter");\r
+ }\r
+ \r
+ return parms[0].getValue();\r
+ }\r
+\r
+ /**\r
+ * Return the scale of the given parameter index in this pvs.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ *\r
+ * @return scale\r
+ */\r
+ public int getScale(int parameterIndex)\r
+ {\r
+ return parms[parameterIndex-1].getScale();\r
+ }\r
+\r
+ /**\r
+ * Return the precision of the given parameter index in this pvs.\r
+ *\r
+ * @param parameterIndex the first parameter is 1, the second is 2, ...\r
+ *\r
+ * @return precision\r
+ */\r
+ public int getPrecision(int parameterIndex)\r
+ {\r
+ return parms[parameterIndex-1].getPrecision();\r
+ }\r
+\r
+}\r