PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/mcs/class/System.Data.Linq/src/DbLinq.MySql/MySqlVendor.cs

https://bitbucket.org/puffnfresh/mono-dependency-analysis
C# | 291 lines | 258 code | 4 blank | 29 comment | 0 complexity | 0c729405bbe5a8d70ac74991fab159be MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0, Unlicense, Apache-2.0, LGPL-2.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. using DbLinq.Data.Linq;
  35. using DbLinq.Data.Linq.SqlClient;
  36. using DbLinq.Util;
  37. using DbLinq.Vendor;
  38. #if MONO_STRICT
  39. using System.Data.Linq;
  40. #else
  41. using DbLinq.Data.Linq;
  42. #endif
  43. namespace DbLinq.MySql
  44. {
  45. [Vendor(typeof(MySqlProvider))]
  46. #if !MONO_STRICT
  47. public
  48. #endif
  49. class MySqlVendor : Vendor.Implementation.Vendor
  50. {
  51. public override string VendorName { get { return "MySQL"; } }
  52. protected readonly MySqlSqlProvider sqlProvider = new MySqlSqlProvider();
  53. public override ISqlProvider SqlProvider { get { return sqlProvider; } }
  54. /// <summary>
  55. /// for large number of rows, we want to use BULK INSERT,
  56. /// because it does not fill up the translation log.
  57. /// This is enabled for tables where Vendor.UserBulkInsert[db.Table] is true.
  58. /// </summary>
  59. public override void BulkInsert<T>(Table<T> table, List<T> rows, int pageSize, IDbTransaction transaction)
  60. {
  61. // name parameters we're going to insert
  62. var members = new Dictionary<string, MemberInfo>();
  63. var tableName = table.Context.Mapping.GetTable(typeof(T)).TableName;
  64. foreach (var dataMember in table.Context.Mapping.GetTable(typeof(T)).RowType.PersistentDataMembers)
  65. {
  66. members[dataMember.MappedName.Trim('"')] = dataMember.Member;
  67. }
  68. var columns = new List<string>(members.Keys);
  69. //PC: this is a test: when no page size specified, we manage to use less than 100 parameters
  70. if (pageSize == 0)
  71. pageSize = 99 / columns.Count;
  72. // performes INSERTs
  73. int lineIndex = 1;
  74. foreach (var page in Page.Paginate(rows, pageSize))
  75. {
  76. var valuesLists = new List<IList<string>>();
  77. using (var command = transaction.Connection.CreateCommand())
  78. {
  79. foreach (T row in page)
  80. {
  81. var values = new List<string>();
  82. foreach (var keyValue in members)
  83. {
  84. var parameter = command.CreateParameter();
  85. parameter.ParameterName = SqlProvider.GetParameterName(string.Format("{0}_{1}", keyValue.Key, lineIndex));
  86. parameter.SetValue(keyValue.Value.GetMemberValue(row));
  87. values.Add(parameter.ParameterName);
  88. command.Parameters.Add(parameter);
  89. }
  90. lineIndex++;
  91. valuesLists.Add(values);
  92. }
  93. command.CommandText = sqlProvider.GetBulkInsert(SqlProvider.GetTable(tableName), columns,
  94. valuesLists);
  95. var result = command.ExecuteNonQuery();
  96. }
  97. }
  98. }
  99. #if OBSOLETE
  100. public override void DoBulkInsert<T>(Table<T> table, List<T> rows, IDbConnection connection)
  101. {
  102. int pageSize = UseBulkInsert[table];
  103. //ProjectionData projData = ProjectionData.FromReflectedType(typeof(T));
  104. ProjectionData projData = AttribHelper.GetProjectionData(typeof(T));
  105. TableAttribute tableAttrib = typeof(T).GetCustomAttributes(false).OfType<TableAttribute>().Single();
  106. //build "INSERT INTO products (ProductName, SupplierID, CategoryID, QuantityPerUnit)"
  107. string header = "INSERT INTO " + tableAttrib.Name + " " + InsertClauseBuilder.InsertRowHeader(projData);
  108. foreach (List<T> page in Page.Paginate(rows, pageSize))
  109. {
  110. int numFieldsAdded = 0;
  111. StringBuilder sbValues = new StringBuilder(" VALUES ");
  112. List<IDbDataParameter> paramList = new List<IDbDataParameter>();
  113. IDbCommand cmd = connection.CreateCommand();
  114. //package up all fields in N rows:
  115. string separator = "";
  116. foreach (T row in page)
  117. {
  118. //prepare values = "(?P1, ?P2, ?P3, ?P4)"
  119. string values =
  120. InsertClauseBuilder.InsertRowFields(this, cmd, row, projData, paramList, ref numFieldsAdded);
  121. sbValues.Append(separator).Append(values);
  122. separator = ", ";
  123. }
  124. string sql = header + sbValues; //'INSET t1 (field1) VALUES (11),(12)'
  125. cmd.CommandText = sql;
  126. paramList.ForEach(param => cmd.Parameters.Add(param));
  127. int result = cmd.ExecuteNonQuery();
  128. }
  129. }
  130. #endif
  131. /// <summary>
  132. /// call mysql stored proc or stored function,
  133. /// optionally return DataSet, and collect return params.
  134. /// </summary>
  135. public override System.Data.Linq.IExecuteResult ExecuteMethodCall(DataContext context, MethodInfo method
  136. , params object[] inputValues)
  137. {
  138. if (method == null)
  139. throw new ArgumentNullException("L56 Null 'method' parameter");
  140. //check to make sure there is exactly one [FunctionEx]? that's below.
  141. //FunctionAttribute functionAttrib = GetFunctionAttribute(method);
  142. var functionAttrib = context.Mapping.GetFunction(method);
  143. ParameterInfo[] paramInfos = method.GetParameters();
  144. //int numRequiredParams = paramInfos.Count(p => p.IsIn || p.IsRetval);
  145. //if (numRequiredParams != inputValues.Length)
  146. // throw new ArgumentException("L161 Argument count mismatch");
  147. string sp_name = functionAttrib.MappedName;
  148. // picrap: is there any way to abstract some part of this?
  149. using (IDbCommand command = context.Connection.CreateCommand())
  150. {
  151. command.CommandText = sp_name;
  152. //MySqlCommand command = new MySqlCommand("select hello0()");
  153. int currInputIndex = 0;
  154. List<string> paramNames = new List<string>();
  155. for (int i = 0; i < paramInfos.Length; i++)
  156. {
  157. ParameterInfo paramInfo = paramInfos[i];
  158. //TODO: check to make sure there is exactly one [Parameter]?
  159. ParameterAttribute paramAttrib = paramInfo.GetCustomAttributes(false).OfType<ParameterAttribute>().Single();
  160. string paramName = "?" + paramAttrib.Name; //eg. '?param1'
  161. paramNames.Add(paramName);
  162. System.Data.ParameterDirection direction = GetDirection(paramInfo, paramAttrib);
  163. //MySqlDbType dbType = MySqlTypeConversions.ParseType(paramAttrib.DbType);
  164. IDbDataParameter cmdParam = command.CreateParameter();
  165. cmdParam.ParameterName = paramName;
  166. //cmdParam.Direction = System.Data.ParameterDirection.Input;
  167. if (direction == System.Data.ParameterDirection.Input || direction == System.Data.ParameterDirection.InputOutput)
  168. {
  169. object inputValue = inputValues[currInputIndex++];
  170. cmdParam.Value = inputValue;
  171. }
  172. else
  173. {
  174. cmdParam.Value = null;
  175. }
  176. cmdParam.Direction = direction;
  177. command.Parameters.Add(cmdParam);
  178. }
  179. if (!functionAttrib.IsComposable) // IsCompsable is false when we have a procedure
  180. {
  181. //procedures: under the hood, this seems to prepend 'CALL '
  182. command.CommandType = System.Data.CommandType.StoredProcedure;
  183. }
  184. else
  185. {
  186. //functions: 'SELECT myFunction()' or 'SELECT hello(?s)'
  187. string cmdText = "SELECT " + command.CommandText + "($args)";
  188. cmdText = cmdText.Replace("$args", string.Join(",", paramNames.ToArray()));
  189. command.CommandText = cmdText;
  190. }
  191. if (method.ReturnType == typeof(DataSet))
  192. {
  193. //unknown shape of resultset:
  194. System.Data.DataSet dataSet = new DataSet();
  195. //IDataAdapter adapter = new MySqlDataAdapter((MySqlCommand)command);
  196. IDbDataAdapter adapter = CreateDataAdapter(context);
  197. adapter.SelectCommand = command;
  198. adapter.Fill(dataSet);
  199. List<object> outParamValues = CopyOutParams(paramInfos, command.Parameters);
  200. return new ProcedureResult(dataSet, outParamValues.ToArray());
  201. }
  202. else
  203. {
  204. object obj = command.ExecuteScalar();
  205. List<object> outParamValues = CopyOutParams(paramInfos, command.Parameters);
  206. return new ProcedureResult(obj, outParamValues.ToArray());
  207. }
  208. }
  209. }
  210. static System.Data.ParameterDirection GetDirection(ParameterInfo paramInfo, ParameterAttribute paramAttrib)
  211. {
  212. //strange hack to determine what's a ref, out parameter:
  213. //http://lists.ximian.com/pipermain/mono-list/2003-March/012751.html
  214. bool hasAmpersand = paramInfo.ParameterType.FullName.Contains('&');
  215. if (paramInfo.IsOut)
  216. return System.Data.ParameterDirection.Output;
  217. if (hasAmpersand)
  218. return System.Data.ParameterDirection.InputOutput;
  219. return System.Data.ParameterDirection.Input;
  220. }
  221. /// <summary>
  222. /// Collect all Out or InOut param values, casting them to the correct .net type.
  223. /// </summary>
  224. private List<object> CopyOutParams(ParameterInfo[] paramInfos, IDataParameterCollection paramSet)
  225. {
  226. List<object> outParamValues = new List<object>();
  227. //Type type_t = typeof(T);
  228. int i = -1;
  229. foreach (IDbDataParameter param in paramSet)
  230. {
  231. i++;
  232. if (param.Direction == System.Data.ParameterDirection.Input)
  233. {
  234. outParamValues.Add("unused");
  235. continue;
  236. }
  237. object val = param.Value;
  238. Type desired_type = paramInfos[i].ParameterType;
  239. if (desired_type.Name.EndsWith("&"))
  240. {
  241. //for ref and out parameters, we need to tweak ref types, e.g.
  242. // "System.Int32&, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  243. string fullName1 = desired_type.AssemblyQualifiedName;
  244. string fullName2 = fullName1.Replace("&", "");
  245. desired_type = Type.GetType(fullName2);
  246. }
  247. try
  248. {
  249. //fi.SetValue(t, val); //fails with 'System.Decimal cannot be converted to Int32'
  250. //DbLinq.util.FieldUtils.SetObjectIdField(t, fi, val);
  251. //object val2 = FieldUtils.CastValue(val, desired_type);
  252. object val2 = TypeConvert.To(val, desired_type);
  253. outParamValues.Add(val2);
  254. }
  255. catch (Exception)
  256. {
  257. //fails with 'System.Decimal cannot be converted to Int32'
  258. //Logger.Write(Level.Error, "CopyOutParams ERROR L245: failed on CastValue(): " + ex.Message);
  259. }
  260. }
  261. return outParamValues;
  262. }
  263. }
  264. }