Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/derby/impl/sql/GenericParameter.java


1   /*
2   
3      Derby - Class org.apache.derby.impl.sql.GenericParameter
4   
5      Copyright 1999, 2004 The Apache Software Foundation or its licensors, as applicable.
6   
7      Licensed under the Apache License, Version 2.0 (the "License");
8      you may not use this file except in compliance with the License.
9      You may obtain a copy of the License at
10  
11        http://www.apache.org/licenses/LICENSE-2.0
12  
13     Unless required by applicable law or agreed to in writing, software
14     distributed under the License is distributed on an "AS IS" BASIS,
15     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16     See the License for the specific language governing permissions and
17     limitations under the License.
18  
19   */
20  
21  package org.apache.derby.impl.sql;
22  
23  import org.apache.derby.iapi.services.loader.ClassInspector;
24  
25  import org.apache.derby.iapi.sql.ParameterValueSet;
26  
27  import org.apache.derby.iapi.types.DataValueDescriptor;
28  import org.apache.derby.iapi.types.BooleanDataValue;
29  import org.apache.derby.iapi.types.BitDataValue;
30  import org.apache.derby.iapi.types.DateTimeDataValue;
31  import org.apache.derby.iapi.types.NumberDataValue;
32  import org.apache.derby.iapi.types.StringDataValue;
33  import org.apache.derby.iapi.types.UserDataValue;
34  import org.apache.derby.iapi.types.TypeId;
35  import org.apache.derby.iapi.types.DataTypeDescriptor;
36  import org.apache.derby.iapi.types.*;
37  
38  import org.apache.derby.iapi.reference.SQLState;
39  
40  import org.apache.derby.iapi.reference.JDBC30Translation;
41  
42  import org.apache.derby.iapi.error.StandardException;
43  
44  import org.apache.derby.iapi.services.sanity.SanityManager;
45  
46  import org.apache.derby.iapi.types.*;
47  import org.apache.derby.iapi.types.*;
48  
49  import java.sql.Types;
50  
51  import java.lang.reflect.Array;
52  
53  /**
54   * A parameter.  Originally lifted from ParameterValueSet.
55   *
56   * @author jamie 
57   */
58  final class GenericParameter
59  {
60  
61    // These defaults match the Network Server/ JCC max precision and
62    // The JCC "guessed" scale. They are used as the defaults for 
63    // Decimal out params.
64    private static int DECIMAL_PARAMETER_DEFAULT_PRECISION = 31;
65    private static int DECIMAL_PARAMETER_DEFAULT_SCALE = 15;
66  
67  
68    /*
69    ** The parameter set we are part of
70    */
71    private final GenericParameterValueSet    pvs;
72  
73    /**
74    ** Our value
75    */
76    private DataValueDescriptor        value;
77  
78    /**
79      Compile time JDBC type identifier.
80    */
81    int                jdbcTypeId;
82  
83    /**
84      Compile time Java class name.
85    */
86    String              declaredClassName;
87  
88    /**
89      Mode of the parameter, from ParameterMetaData
90    */
91    short              parameterMode;
92  
93    /*
94    ** If we are set
95    */
96    boolean              isSet;
97  
98    /*
99    ** Output parameter values
100    */
101   private final boolean          isReturnOutputParameter;
102 
103   /**
104     Type that has been registered.
105   */
106   int  registerOutType = Types.NULL;
107   /**
108     Scale that has been registered.
109   */
110   int registerOutScale = -1;
111 
112   /**
113    * When a decimal output parameter is registered we give it a 
114    * precision
115    */
116 
117   int registerOutPrecision = -1;
118 
119   /**
120    * Constructor for a Parameter
121    *
122    * @param pvs the parameter set that this is part of
123    * @param isReturnOutputParameter true if this is a return output parameter
124    */
125   GenericParameter
126   (
127     GenericParameterValueSet  pvs,
128     boolean            isReturnOutputParameter
129   )
130   {
131     this.pvs = pvs;
132     parameterMode = (this.isReturnOutputParameter = isReturnOutputParameter)
133       ? (short) JDBC30Translation.PARAMETER_MODE_OUT : (short) JDBC30Translation.PARAMETER_MODE_IN;
134   }
135 
136   /**
137    * Clone myself.  It is a shallow copy for everything but
138    * the underlying data wrapper and its value -- e.g. for
139    * everything but the underlying SQLInt and its int.
140    *
141    * @param pvs the parameter value set
142    *
143    * @return a new generic parameter.
144    */
145   public GenericParameter getClone(GenericParameterValueSet pvs)
146   {
147     GenericParameter gpClone = new GenericParameter(pvs, isReturnOutputParameter);
148     gpClone.setStorableDataValue(this.getValue().getClone(), jdbcTypeId, declaredClassName);
149     gpClone.isSet = true;
150 
151     return gpClone;
152   }
153 
154   /**
155    * Set the DataValueDescriptor for this parameter.  If makrAsSet
156    * is set, then we consider this parameter both initialized and
157    * set.  Otherwise, it is just initialized but not yet set.
158    *
159    * @param std the storable data value
160    * @param markAsSet whether we should mark as being set or not.
161    *     The isSet() method will return this value.
162    */
163   void setStorableDataValue(DataValueDescriptor value, int jdbcTypeId, String className)
164   {
165     this.value = value;
166     this.jdbcTypeId = jdbcTypeId;
167     this.declaredClassName = className;
168   }
169 
170 
171   /**
172    * Clear the parameter, unless it is a return
173    * output parameter
174    */
175   void clear()
176   {
177     isSet = false;
178   }
179 
180 
181   /**
182    * Get the parameter value.  Doesn't check to
183    * see if it has been initialized or not.
184    *
185    * @return the parameter value, may return null
186    */
187   DataValueDescriptor getValue()
188   {
189     return value;
190   }
191 
192 
193   //////////////////////////////////////////////////////////////////
194   //
195   // CALLABLE STATEMENT
196   //
197   //////////////////////////////////////////////////////////////////
198 
199   /**
200    * Mark the parameter as an output parameter.
201    *
202    * @param sqlType  A type from java.sql.Types
203    * @param scale    scale, -1 if no scale arg
204    *
205    * @exception StandardException on error
206    */
207   void setOutParameter(int sqlType, int scale)
208     throws StandardException
209   {
210     // fast case duplicate registrations.
211     if (registerOutType == sqlType) {
212       if (scale == registerOutScale)
213         return;
214     }
215 
216     switch (parameterMode) {
217     case JDBC30Translation.PARAMETER_MODE_IN:
218     case JDBC30Translation.PARAMETER_MODE_UNKNOWN:
219     default:
220       throw StandardException.newException(SQLState.LANG_NOT_OUT_PARAM, getJDBCParameterNumberStr());
221 
222     case JDBC30Translation.PARAMETER_MODE_IN_OUT:
223     case JDBC30Translation.PARAMETER_MODE_OUT:
224       // Declared/Java procedure parameter.
225       if (!DataTypeDescriptor.isJDBCTypeEquivalent(jdbcTypeId, sqlType))
226         throw throwInvalidOutParamMap(sqlType);
227       break;
228 
229     }
230 
231     registerOutType = sqlType;
232     
233   }
234 
235   private StandardException throwInvalidOutParamMap(int sqlType) {
236 
237     //TypeId typeId = TypeId.getBuiltInTypeId(sqlType);
238     // String sqlTypeName = typeId == null ? "OTHER" : typeId.getSQLTypeName();
239 
240 
241     String jdbcTypesName = org.apache.derby.impl.jdbc.Util.typeName(sqlType);
242 
243     TypeId typeId = TypeId.getBuiltInTypeId(jdbcTypeId);
244     String thisTypeName = typeId == null ? declaredClassName : typeId.getSQLTypeName();
245         
246     StandardException e = StandardException.newException(SQLState.LANG_INVALID_OUT_PARAM_MAP,
247           getJDBCParameterNumberStr(),
248           jdbcTypesName, thisTypeName);
249 
250     return e;
251   }
252 
253 
254 
255   /**
256    * Validate the parameters.  This is done for situations where
257    * we cannot validate everything in the setXXX() calls.  In
258    * particular, before we do an execute() on a CallableStatement,
259    * we need to go through the parameters and make sure that
260    * all parameters are set up properly.  The motivator for this
261    * is that setXXX() can be called either before or after
262    * registerOutputParamter(), we cannot be sure we have the types
263    * correct until we get to execute().
264    *
265    * @exception StandardException if the parameters aren't valid
266    */
267   void validate() throws StandardException
268   {
269     switch (parameterMode) {
270     case JDBC30Translation.PARAMETER_MODE_UNKNOWN:
271       break;
272     case JDBC30Translation.PARAMETER_MODE_IN:
273       break;
274     case JDBC30Translation.PARAMETER_MODE_IN_OUT:
275     case JDBC30Translation.PARAMETER_MODE_OUT:
276       if (registerOutType == Types.NULL) {
277         throw StandardException.newException(SQLState.NEED_TO_REGISTER_PARAM,
278           getJDBCParameterNumberStr(),
279            org.apache.derby.catalog.types.RoutineAliasInfo.parameterMode(parameterMode));
280       }
281       break;
282     }
283   }
284 
285   /**
286    * Return the scale of the parameter.
287    *
288    * @return scale
289    */
290   int getScale()
291   {
292     //when the user doesn't pass any scale, the registerOutScale gets set to -1
293     return (registerOutScale == -1 ? 0 : registerOutScale);
294   }
295 
296 
297   int getPrecision()
298   {
299     return registerOutPrecision;
300     
301   }
302 
303   ////////////////////////////////////////////////////
304   //
305   // CLASS IMPLEMENTATION
306   //
307   ////////////////////////////////////////////////////
308 
309   /**
310    * do a setValue on the particular field.  Doesn't do
311    * checks on what it is being set to or on whether
312    * it is a return parameter or what.  This is only
313    * called internally; it is not expected to be called
314    * directly as a result of some jdbc call (e.g. setObject()).
315    *
316    * @param newValue the value to set
317    *
318    * @exception StandardException on error
319    */
320   void stuffObject(Object newValue) throws StandardException
321   {
322     value.setValue(newValue);
323     isSet = true;
324   }
325 
326   /**
327    * get string for param number
328    */
329   String getJDBCParameterNumberStr()
330   {
331     return Integer.toString(pvs.getParameterNumber(this));
332   }
333 
334   public String toString()
335   {
336     /* This method is used for debugging.
337      * It is called when derby.language.logStatementText=true,
338      * so there is no check of SanityManager.DEBUG.
339      * Anyway, we need to call value.getString() instead of
340      * value.toString() because the user may have done a
341      * a setStream() on the parameter.  (toString() could get
342      * an assertion failure in that case as it would be in an
343      * unexpected state since this is a very weird codepath.)
344      * getString() can throw an exception which we eat and
345      * and reflect in the returned string.
346      */
347     if (value == null)
348     {
349       return "null";
350     }
351     else
352     {
353       try
354       {
355         return value.getString();
356       }
357       catch (StandardException se)
358       {
359         return "unexpected exception from getString() - " + se;
360       }
361     }
362   }
363 }