PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System.Data.Linq/src/DbLinq.Firebird/FirebirdVendor.cs

https://github.com/ztfuqingvip/mono
C# | 204 lines | 131 code | 19 blank | 54 comment | 15 complexity | 8248d840549f93d646e997100a59db5a MD5 | raw file
Possible License(s): GPL-2.0, Unlicense, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0
  1. #region MIT license
  2. //
  3. // MIT license
  4. //
  5. // Copyright (c) 2007-2008 Jiri Moudry, Pascal Craponne
  6. //
  7. // Permission is hereby granted, free of charge, to any person obtaining a copy
  8. // of this software and associated documentation files (the "Software"), to deal
  9. // in the Software without restriction, including without limitation the rights
  10. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. // copies of the Software, and to permit persons to whom the Software is
  12. // furnished to do so, subject to the following conditions:
  13. //
  14. // The above copyright notice and this permission notice shall be included in
  15. // all copies or substantial portions of the Software.
  16. //
  17. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. // THE SOFTWARE.
  24. //
  25. #endregion
  26. using System;
  27. using System.Data.Common;
  28. using System.Linq;
  29. using System.Collections.Generic;
  30. using System.Text;
  31. using System.Data.Linq.Mapping;
  32. using System.Reflection;
  33. using System.Data;
  34. #if MONO_STRICT
  35. using System.Data.Linq;
  36. #else
  37. using DbLinq.Data.Linq;
  38. #endif
  39. using DbLinq.Data.Linq.SqlClient;
  40. using DbLinq.Util;
  41. using DbLinq.Vendor;
  42. namespace DbLinq.Firebird
  43. {
  44. [Vendor(typeof(FirebirdProvider))]
  45. #if !MONO_STRICT
  46. public
  47. #endif
  48. class FirebirdVendor : Vendor.Implementation.Vendor
  49. {
  50. public override string VendorName { get { return "FirebirdSql"; } }
  51. protected readonly FirebirdSqlProvider sqlProvider = new FirebirdSqlProvider();
  52. public override ISqlProvider SqlProvider { get { return sqlProvider; } }
  53. /// <summary>
  54. /// call mysql stored proc or stored function,
  55. /// optionally return DataSet, and collect return params.
  56. /// </summary>
  57. public override System.Data.Linq.IExecuteResult ExecuteMethodCall(DataContext context, MethodInfo method
  58. , params object[] inputValues)
  59. {
  60. if (method == null)
  61. throw new ArgumentNullException("L56 Null 'method' parameter");
  62. //check to make sure there is exactly one [FunctionEx]? that's below.
  63. //FunctionAttribute functionAttrib = GetFunctionAttribute(method);
  64. var functionAttrib = context.Mapping.GetFunction(method);
  65. ParameterInfo[] paramInfos = method.GetParameters();
  66. //int numRequiredParams = paramInfos.Count(p => p.IsIn || p.IsRetval);
  67. //if (numRequiredParams != inputValues.Length)
  68. // throw new ArgumentException("L161 Argument count mismatch");
  69. string sp_name = functionAttrib.MappedName;
  70. // picrap: is there any way to abstract some part of this?
  71. using (IDbCommand command = context.Connection.CreateCommand())
  72. {
  73. command.CommandText = sp_name;
  74. //FbSqlCommand command = new FbSqlCommand("select * from hello0()");
  75. int currInputIndex = 0;
  76. List<string> paramNames = new List<string>();
  77. for (int i = 0; i < paramInfos.Length; i++)
  78. {
  79. ParameterInfo paramInfo = paramInfos[i];
  80. //TODO: check to make sure there is exactly one [Parameter]?
  81. ParameterAttribute paramAttrib = paramInfo.GetCustomAttributes(false).OfType<ParameterAttribute>().Single();
  82. string paramName = "@" + paramAttrib.Name; //eg. '@param1'
  83. paramNames.Add(paramName);
  84. System.Data.ParameterDirection direction = GetDirection(paramInfo, paramAttrib);
  85. //FbDbType dbType = FbSqlTypeConversions.ParseType(paramAttrib.DbType);
  86. IDbDataParameter cmdParam = command.CreateParameter();
  87. cmdParam.ParameterName = paramName;
  88. //cmdParam.Direction = System.Data.ParameterDirection.Input;
  89. if (direction == System.Data.ParameterDirection.Input || direction == System.Data.ParameterDirection.InputOutput)
  90. {
  91. object inputValue = inputValues[currInputIndex++];
  92. cmdParam.Value = inputValue;
  93. }
  94. else
  95. {
  96. cmdParam.Value = null;
  97. }
  98. cmdParam.Direction = direction;
  99. command.Parameters.Add(cmdParam);
  100. }
  101. if (!functionAttrib.IsComposable) // IsCompsable is false when we have a procedure
  102. {
  103. //procedures: under the hood, this seems to prepend 'CALL '
  104. command.CommandType = System.Data.CommandType.StoredProcedure;
  105. }
  106. else
  107. {
  108. //functions: 'SELECT * FROM myFunction()' or 'SELECT * FROM hello(?s)'
  109. command.CommandText = "SELECT * FROM " + command.CommandText + "("
  110. + string.Join(",", paramNames.ToArray()) + ")";
  111. }
  112. if (method.ReturnType == typeof(DataSet))
  113. {
  114. //unknown shape of resultset:
  115. System.Data.DataSet dataSet = new DataSet();
  116. //IDataAdapter adapter = new FbDataAdapter((FbCommand)command);
  117. IDbDataAdapter adapter = CreateDataAdapter(context);
  118. adapter.SelectCommand = command;
  119. adapter.Fill(dataSet);
  120. List<object> outParamValues = CopyOutParams(paramInfos, command.Parameters);
  121. return new ProcedureResult(dataSet, outParamValues.ToArray());
  122. }
  123. else
  124. {
  125. object obj = command.ExecuteScalar();
  126. List<object> outParamValues = CopyOutParams(paramInfos, command.Parameters);
  127. return new ProcedureResult(obj, outParamValues.ToArray());
  128. }
  129. }
  130. }
  131. static System.Data.ParameterDirection GetDirection(ParameterInfo paramInfo, ParameterAttribute paramAttrib)
  132. {
  133. //strange hack to determine what's a ref, out parameter:
  134. //http://lists.ximian.com/pipermain/mono-list/2003-March/012751.html
  135. bool hasAmpersand = paramInfo.ParameterType.FullName.Contains('&');
  136. if (paramInfo.IsOut)
  137. return System.Data.ParameterDirection.Output;
  138. if (hasAmpersand)
  139. return System.Data.ParameterDirection.InputOutput;
  140. return System.Data.ParameterDirection.Input;
  141. }
  142. /// <summary>
  143. /// Collect all Out or InOut param values, casting them to the correct .net type.
  144. /// </summary>
  145. private List<object> CopyOutParams(ParameterInfo[] paramInfos, IDataParameterCollection paramSet)
  146. {
  147. List<object> outParamValues = new List<object>();
  148. //Type type_t = typeof(T);
  149. int i = -1;
  150. foreach (IDbDataParameter param in paramSet)
  151. {
  152. i++;
  153. if (param.Direction == System.Data.ParameterDirection.Input)
  154. {
  155. outParamValues.Add("unused");
  156. continue;
  157. }
  158. object val = param.Value;
  159. Type desired_type = paramInfos[i].ParameterType;
  160. if (desired_type.Name.EndsWith("&"))
  161. {
  162. //for ref and out parameters, we need to tweak ref types, e.g.
  163. // "System.Int32&, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  164. string fullName1 = desired_type.AssemblyQualifiedName;
  165. string fullName2 = fullName1.Replace("&", "");
  166. desired_type = Type.GetType(fullName2);
  167. }
  168. try
  169. {
  170. //fi.SetValue(t, val); //fails with 'System.Decimal cannot be converted to Int32'
  171. //DbLinq.util.FieldUtils.SetObjectIdField(t, fi, val);
  172. //object val2 = FieldUtils.CastValue(val, desired_type);
  173. object val2 = TypeConvert.To(val, desired_type);
  174. outParamValues.Add(val2);
  175. }
  176. catch (Exception)
  177. {
  178. //fails with 'System.Decimal cannot be converted to Int32'
  179. //Logger.Write(Level.Error, "CopyOutParams ERROR L245: failed on CastValue(): " + ex.Message);
  180. }
  181. }
  182. return outParamValues;
  183. }
  184. }
  185. }