Clover.NET coverage report - Coverage

Coverage timestamp: Friday, May 20, 2005 9:17:00 PM

File Stats: LOC: 439   Methods: 6
NCLOC: 282 Classes: 1
 
Source File Conditionals Statements Methods TOTAL
Configuration\Statements\PreparedStatementFactory.cs 39.4 % 59.3 % 83.3 % 53.3 %
coverage coverage
1  
2   #region Apache Notice
3   /*****************************************************************************
4   * $Header: $
5   * $Revision: $
6   * $Date: $
7   *
8   * iBATIS.NET Data Mapper
9   * Copyright (C) 2004 - Gilles Bayon
10   *
11   *
12   * Licensed under the Apache License, Version 2.0 (the "License");
13   * you may not use this file except in compliance with the License.
14   * You may obtain a copy of the License at
15   *
16   * http://www.apache.org/licenses/LICENSE-2.0
17   *
18   * Unless required by applicable law or agreed to in writing, software
19   * distributed under the License is distributed on an "AS IS" BASIS,
20   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21   * See the License for the specific language governing permissions and
22   * limitations under the License.
23   *
24   ********************************************************************************/
25   #endregion
26  
27   #region Using
28  
29   using System;
30   using System.Collections;
31   using System.Collections.Specialized;
32   using System.Data;
33   using System.Reflection;
34   using System.Text;
35   using IBatisNet.Common;
36   using IBatisNet.Common.Utilities;
37   using IBatisNet.Common.Utilities.Objects;
38   using IBatisNet.DataMapper.Configuration.ParameterMapping;
39   using IBatisNet.DataMapper.Exceptions;
40   using IBatisNet.DataMapper.Scope;
41   using log4net;
42  
43   #endregion
44  
45   namespace IBatisNet.DataMapper.Configuration.Statements
46   {
47   /// <summary>
48   /// Summary description for PreparedStatementFactory.
49   /// </summary>
50   public class PreparedStatementFactory
51   {
52  
53   #region Fields
54  
55   private PreparedStatement _preparedStatement = null;
56  
57   private string _parameterPrefix = string.Empty;
58   private IStatement _statement = null;
59   private IDalSession _session = null;
60   private string _commandText = string.Empty;
61   private RequestScope _request = null;
62   // (property, DbParameter)
63   private HybridDictionary _propertyDbParameterMap = new HybridDictionary();
64  
65   private static readonly ILog _logger = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType );
66  
67   #endregion
68  
69   /// <summary>
70   /// Constructor
71   /// </summary>
72   /// <param name="session"></param>
73   /// <param name="statement"></param>
74   /// <param name="commandText"></param>
75   /// <param name="request"></param>
76 20460 public PreparedStatementFactory(IDalSession session, RequestScope request, IStatement statement, string commandText)
77   {
78 20460 _session = session;
79 20460 _request = request;
80 20460 _statement = statement;
81 20460 _commandText = commandText;
82   }
83  
84  
85   /// <summary>
86   /// Create a list of IDataParameter for the statement and build the sql string.
87   /// </summary>
88 20460 public PreparedStatement Prepare()
89   {
90 20460 _preparedStatement = new PreparedStatement();
91 20460 _parameterPrefix = _session.DataSource.Provider.ParameterPrefix;
92  
93 20460 _preparedStatement.PreparedSql = _commandText;
94  
95 20460 if (_statement.CommandType == CommandType.Text)
96   {
97 20454 if (_request.ParameterMap != null)
98   {
99 16199 CreateParametersForTextCommand();
100 16199 EvaluateParameterMap();
101   }
102   }
103 6 else if (_statement.CommandType == CommandType.StoredProcedure) // StoredProcedure
104   {
105 6 if (_request.ParameterMap == null) // No parameterMap --> error
106   {
107 0 throw new DataMapperException("A procedure statement tag must have a parameterMap attribute, which is not the case for the procedure '"+_statement.Id+".");
108   }
109   else // use the parameterMap
110   {
111 6 if (_session.DataSource.Provider.UseDeriveParameters)
112   {
113 6 DiscoverParameter(_session);
114   }
115   else
116   {
117 0 CreateParametersForProcedureCommand();
118   // EvaluateParameterMap(); // Did we need that ? I don't think for the procedure
119   }
120   }
121  
122   #region Fix for Odbc
123   // Although executing a parameterized stored procedure using the ODBC .NET Provider
124   // is slightly different from executing the same procedure using the SQL or
125   // the OLE DB Provider, there is one important difference
126   // -- the stored procedure must be called using the ODBC CALL syntax rather than
127   // the name of the stored procedure.
128   // For additional information on this CALL syntax,
129   // see the page entitled "Procedure Calls" in the ODBC Programmer's Reference
130   // in the MSDN Library.
131   //http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q309486
132  
133 6 if ( _session.DataSource.Provider.IsObdc == true )
134   {
135 0 StringBuilder commandTextBuilder = new StringBuilder("{ call ");
136 0 commandTextBuilder.Append( _commandText );
137  
138 0 if (_preparedStatement.DbParameters.Count >0)
139   {
140   commandTextBuilder.Append(" (");
141   int supIndex = _preparedStatement.DbParameters.Count-1;
142   for(int i=0;i<supIndex;i++)
143   {
144   commandTextBuilder.Append("?,");
145   }
146   commandTextBuilder.Append("?) }");
147   }
148 0 _preparedStatement.PreparedSql = commandTextBuilder.ToString();
149   }
150  
151   #endregion
152   }
153  
154 20460 if (_logger.IsDebugEnabled)
155   {
156 0 _logger.Debug("SQL for statement '"+ _statement.Id +"' :" + _preparedStatement.PreparedSql);
157   }
158  
159 20460 return _preparedStatement;
160   }
161  
162  
163   #region Private methods
164  
165   /// <summary>
166   /// For store procedure, auto discover IDataParameters for stored procedures at run-time.
167   /// </summary>
168   /// <param name="session">The current session.</param>
169 6 private void DiscoverParameter(IDalSession session)
170   {
171   // pull the parameters for this stored procedure from the parameter cache
172   // (or discover them & populate the cache)
173 6 IDataParameter[] commandParameters = DBHelperParameterCache.GetSpParameterSet(session, _commandText);
174  
175 6 int start = session.DataSource.Provider.ParameterPrefix.Length;
176 6 foreach(IDataParameter dataParameter in commandParameters)
177   {
178 21 if (session.DataSource.Provider.UseParameterPrefixInParameter == false)
179   {
180 0 if (dataParameter.ParameterName.StartsWith(session.DataSource.Provider.ParameterPrefix)) {
181   dataParameter.ParameterName = dataParameter.ParameterName.Substring(start);
182   }
183   }
184 21 _preparedStatement.DbParametersName.Add( dataParameter.ParameterName );
185 21 _preparedStatement.DbParameters.Add( dataParameter );
186   }
187   }
188  
189  
190   /// <summary>
191   /// Create IDataParameters for command text statement.
192   /// </summary>
193 16199 private void CreateParametersForTextCommand()
194   {
195 16199 string sqlParamName = string.Empty;
196 16199 string dbTypePropertyName = _session.DataSource.Provider.ParameterDbTypeProperty;
197 16199 Type enumDbType = _session.DataSource.Provider.ParameterDbType;
198 16199 IList list = null;
199 16199 int i = 0;
200  
201 16199 if (_session.DataSource.Provider.UsePositionalParameters) //obdc/oledb
202   {
203 0 list = _request.ParameterMap.Properties;
204   }
205   else
206   {
207 16199 list = _request.ParameterMap.PropertiesList;
208   }
209  
210 16199 foreach(ParameterProperty property in list)
211   {
212 32184 if (_session.DataSource.Provider.UseParameterPrefixInParameter)
213   {
214   // From Ryan Yao: JIRA-27, used "param" + i++ for sqlParamName
215 32184 sqlParamName = _parameterPrefix + "param" + i++;
216   }
217   else
218   {
219 0 sqlParamName = "param" + i++;
220   }
221  
222 32184 IDataParameter dataParameter = _session.CreateCommand(_statement.CommandType).CreateParameter();
223  
224   // Manage dbType attribute if any
225 32184 if (property.DbType != null && property.DbType.Length >0)
226   {
227   // Exemple : Enum.parse(System.Data.SqlDbType, 'VarChar')
228 3911 object dbType = Enum.Parse( enumDbType, property.DbType, true );
229  
230   // Exemple : ObjectHelper.SetProperty(sqlparameter, 'SqlDbType', SqlDbType.Int);
231 3911 ObjectProbe.SetPropertyValue(dataParameter, dbTypePropertyName, dbType);
232   }
233  
234   // Set IDbDataParameter
235   // JIRA-49 Fixes (size, precision, and scale)
236 32184 if (_session.DataSource.Provider.SetDbParameterSize)
237   {
238 32184 if (property.Size != -1)
239   {
240 0 ((IDbDataParameter)dataParameter).Size = property.Size;
241   }
242   }
243  
244 32184 if (_session.DataSource.Provider.SetDbParameterPrecision)
245   {
246 32184 ((IDbDataParameter)dataParameter).Precision = property.Precision;
247   }
248  
249 32184 if (_session.DataSource.Provider.SetDbParameterScale)
250   {
251 32184 ((IDbDataParameter)dataParameter).Scale = property.Scale;
252   }
253  
254   // Set as direction parameter
255 32184 dataParameter.Direction = property.Direction;
256  
257 32184 dataParameter.ParameterName = sqlParamName;
258  
259 32184 _preparedStatement.DbParametersName.Add( property.PropertyName );
260 32184 _preparedStatement.DbParameters.Add( dataParameter );
261  
262 32184 if ( _session.DataSource.Provider.UsePositionalParameters == false)
263   {
264 32184 _propertyDbParameterMap.Add(property, dataParameter);
265   }
266   }
267   }
268  
269  
270   /// <summary>
271   /// Create IDataParameters for procedure statement.
272   /// </summary>
273 0 private void CreateParametersForProcedureCommand()
274   {
275   string sqlParamName = string.Empty;
276   string dbTypePropertyName = _session.DataSource.Provider.ParameterDbTypeProperty;
277   Type enumDbType = _session.DataSource.Provider.ParameterDbType;
278   IList list = null;
279  
280   if (_session.DataSource.Provider.UsePositionalParameters) //obdc/oledb
281   {
282   list = _request.ParameterMap.Properties;
283   }
284   else
285   {
286   list = _request.ParameterMap.PropertiesList;
287   }
288  
289   // ParemeterMap are required for procedure and we tested existance in Prepare() method
290   // so we don't have to test existence here.
291   // A ParameterMap used in CreateParametersForProcedureText must
292   // have property and column attributes set.
293   // The column attribute is the name of a procedure parameter.
294   foreach(ParameterProperty property in list)
295   {
296   if (_session.DataSource.Provider.UseParameterPrefixInParameter)
297   {
298   sqlParamName = _parameterPrefix + property.ColumnName;
299   }
300   else //obdc/oledb
301   {
302   sqlParamName = property.ColumnName;
303   }
304  
305   IDataParameter dataParameter = _session.CreateCommand(_statement.CommandType).CreateParameter();
306  
307   // Manage dbType attribute if any
308   if (property.DbType!=null && property.DbType.Length >0)
309   {
310   // Exemple : Enum.parse(System.Data.SqlDbType, 'VarChar')
311   object dbType = Enum.Parse( enumDbType, property.DbType, true );
312  
313   // Exemple : ObjectHelper.SetProperty(sqlparameter, 'SqlDbType', SqlDbType.Int);
314   ObjectProbe.SetPropertyValue(dataParameter, dbTypePropertyName, dbType);
315   }
316  
317   // Set IDbDataParameter
318   // JIRA-49 Fixes (size, precision, and scale)
319   if (_session.DataSource.Provider.SetDbParameterSize)
320   {
321   if (property.Size != -1)
322   {
323   ((IDbDataParameter)dataParameter).Size = property.Size;
324   }
325   }
326  
327   if (_session.DataSource.Provider.SetDbParameterPrecision)
328   {
329   ((IDbDataParameter)dataParameter).Precision = property.Precision;
330   }
331  
332   if (_session.DataSource.Provider.SetDbParameterScale)
333   {
334   ((IDbDataParameter)dataParameter).Scale = property.Scale;
335   }
336  
337   // Set as direction parameter
338   dataParameter.Direction = property.Direction;
339  
340   dataParameter.ParameterName = sqlParamName;
341  
342   _preparedStatement.DbParametersName.Add( property.PropertyName );
343   _preparedStatement.DbParameters.Add( dataParameter );
344  
345   if ( _session.DataSource.Provider.UsePositionalParameters == false)
346   {
347   _propertyDbParameterMap.Add(property, dataParameter);
348   }
349   }
350   }
351  
352  
353   /// <summary>
354   /// Parse sql command text.
355   /// </summary>
356 16199 private void EvaluateParameterMap()
357   {
358 16199 string delimiter = "?";
359 16199 string token = null;
360 16199 int index = 0;
361 16199 string sqlParamName = string.Empty;
362 16199 StringTokenizer parser = new StringTokenizer(_commandText, delimiter, true);
363 16199 StringBuilder newCommandTextBuffer = new StringBuilder();
364  
365 16199 IEnumerator enumerator = parser.GetEnumerator();
366  
367 96759 while (enumerator.MoveNext())
368   {
369 80560 token = (string)enumerator.Current;
370  
371 80560 if (delimiter.Equals(token)) // ?
372   {
373 32699 ParameterProperty property = (ParameterProperty)_request.ParameterMap.Properties[index];
374 32699 IDataParameter dataParameter = null;
375  
376 32699 if (_session.DataSource.Provider.UsePositionalParameters)
377   {
378   // TODO Refactor?
379 0 if (_parameterPrefix.Equals(":"))
380   {
381   // ODP.NET uses positional parameters by default
382   // but uses ":0" or ":1" instead of "?"
383   sqlParamName = ":" + index;
384   }
385   else
386   {
387   // OLEDB/OBDC doesn't support named parameters !!!
388   sqlParamName = "?";
389   }
390  
391   }
392   else
393   {
394 32699 dataParameter = (IDataParameter) _propertyDbParameterMap[property];
395  
396   // 5 May 2004
397   // Need to check UseParameterPrefixInParameter here
398   // since CreateParametersForStatementText now does
399   // a check for UseParameterPrefixInParameter before
400   // creating the parameter name!
401 32699 if (_session.DataSource.Provider.UseParameterPrefixInParameter)
402   {
403   // Fix ByteFX.Data.MySqlClient.MySqlParameter
404   // who strip prefix in Parameter Name ?!
405 32699 if (_session.DataSource.Provider.Name.IndexOf("ByteFx")>=0)
406   {
407 0 sqlParamName = _parameterPrefix+dataParameter.ParameterName;
408   }
409   else
410   {
411 32699 sqlParamName = dataParameter.ParameterName;
412   }
413   }
414   else
415   {
416 0 sqlParamName = _parameterPrefix+dataParameter.ParameterName;
417   }
418   }
419  
420 32699 newCommandTextBuffer.Append(" ");
421 32699 newCommandTextBuffer.Append(sqlParamName);
422  
423 32699 sqlParamName = string.Empty;
424 32699 index ++;
425   }
426   else
427   {
428 47861 newCommandTextBuffer.Append(token);
429   }
430   }
431  
432 16199 _preparedStatement.PreparedSql = newCommandTextBuffer.ToString();
433   }
434  
435  
436   #endregion
437   }
438   }
439