PageRenderTime 54ms CodeModel.GetById 14ms RepoModel.GetById 2ms app.codeStats 0ms

/mcs/class/System.Data.Linq/src/DbLinq.PostgreSql/PgsqlVendor.cs

https://bitbucket.org/danipen/mono
C# | 236 lines | 147 code | 21 blank | 68 comment | 15 complexity | c5fc0de6868281c4d3233ce3919b9e6b MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-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;
  28. using System.Data.Common;
  29. using System.Linq;
  30. using System.Data.Linq.Mapping;
  31. using System.Reflection;
  32. using System.Collections.Generic;
  33. using DbLinq.Data.Linq.SqlClient;
  34. using DbLinq.PostgreSql;
  35. using DbLinq.Util;
  36. using DbLinq.Vendor;
  37. #if MONO_STRICT
  38. using DataContext=System.Data.Linq.DataContext;
  39. #else
  40. using DataContext=DbLinq.Data.Linq.DataContext;
  41. #endif
  42. namespace DbLinq.PostgreSql
  43. {
  44. #if !MONO_STRICT
  45. public
  46. #endif
  47. class PgsqlVendor : PostgreSqlVendor
  48. {
  49. // This is a compatibility class. It will go away after the
  50. // big PostgreSql rename.
  51. }
  52. /// <summary>
  53. /// PostgreSQL - specific code.
  54. /// </summary>
  55. [Vendor(typeof(PostgreSqlProvider))]
  56. #if !MONO_STRICT
  57. public
  58. #endif
  59. class PostgreSqlVendor : Vendor.Implementation.Vendor
  60. {
  61. public override string VendorName { get { return "PostgreSQL"; } }
  62. protected readonly PgsqlSqlProvider sqlProvider = new PgsqlSqlProvider();
  63. public override ISqlProvider SqlProvider { get { return sqlProvider; } }
  64. protected void SetParameterType(IDbDataParameter parameter, PropertyInfo property, string literal)
  65. {
  66. object dbType = Enum.Parse(property.PropertyType, literal);
  67. property.GetSetMethod().Invoke(parameter, new object[] { dbType });
  68. }
  69. protected void SetParameterType(IDbDataParameter parameter, string literal)
  70. {
  71. SetParameterType(parameter, parameter.GetType().GetProperty("NpgsqlDbType"), literal);
  72. }
  73. /*
  74. public override IDbDataParameter CreateSqlParameter(IDbCommand cmd, string dbTypeName, string paramName)
  75. {
  76. //System.Data.SqlDbType dbType = DbLinq.util.SqlTypeConversions.ParseType(dbTypeName);
  77. //SqlParameter param = new SqlParameter(paramName, dbType);
  78. NpgsqlTypes.NpgsqlDbType dbType = PgsqlTypeConversions.ParseType(dbTypeName);
  79. NpgsqlParameter param = new NpgsqlParameter(paramName, dbType);
  80. return param;
  81. }
  82. */
  83. /// <summary>
  84. /// call mysql stored proc or stored function,
  85. /// optionally return DataSet, and collect return params.
  86. /// </summary>
  87. public override System.Data.Linq.IExecuteResult ExecuteMethodCall(DataContext context, MethodInfo method
  88. , params object[] inputValues)
  89. {
  90. if (method == null)
  91. throw new ArgumentNullException("L56 Null 'method' parameter");
  92. //check to make sure there is exactly one [FunctionEx]? that's below.
  93. //FunctionAttribute functionAttrib = GetFunctionAttribute(method);
  94. var functionAttrib = context.Mapping.GetFunction(method);
  95. ParameterInfo[] paramInfos = method.GetParameters();
  96. //int numRequiredParams = paramInfos.Count(p => p.IsIn || p.IsRetval);
  97. //if (numRequiredParams != inputValues.Length)
  98. // throw new ArgumentException("L161 Argument count mismatch");
  99. string sp_name = functionAttrib.MappedName;
  100. using (IDbCommand command = context.Connection.CreateCommand())
  101. {
  102. command.CommandText = sp_name;
  103. //MySqlCommand command = new MySqlCommand("select hello0()");
  104. int currInputIndex = 0;
  105. List<string> paramNames = new List<string>();
  106. for (int i = 0; i < paramInfos.Length; i++)
  107. {
  108. ParameterInfo paramInfo = paramInfos[i];
  109. //TODO: check to make sure there is exactly one [Parameter]?
  110. ParameterAttribute paramAttrib = paramInfo.GetCustomAttributes(false).OfType<ParameterAttribute>().Single();
  111. //string paramName = "?" + paramAttrib.Name; //eg. '?param1' MYSQL
  112. string paramName = ":" + paramAttrib.Name; //eg. '?param1' PostgreSQL
  113. paramNames.Add(paramName);
  114. System.Data.ParameterDirection direction = GetDirection(paramInfo, paramAttrib);
  115. //MySqlDbType dbType = MySqlTypeConversions.ParseType(paramAttrib.DbType);
  116. IDbDataParameter cmdParam = command.CreateParameter();
  117. cmdParam.ParameterName = paramName;
  118. //cmdParam.Direction = System.Data.ParameterDirection.Input;
  119. if (direction == ParameterDirection.Input || direction == ParameterDirection.InputOutput)
  120. {
  121. object inputValue = inputValues[currInputIndex++];
  122. cmdParam.Value = inputValue;
  123. }
  124. else
  125. {
  126. cmdParam.Value = null;
  127. }
  128. cmdParam.Direction = direction;
  129. command.Parameters.Add(cmdParam);
  130. }
  131. if (!functionAttrib.IsComposable)
  132. {
  133. //procedures: under the hood, this seems to prepend 'CALL '
  134. command.CommandType = System.Data.CommandType.StoredProcedure;
  135. }
  136. else
  137. {
  138. //functions: 'SELECT myFunction()' or 'SELECT hello(?s)'
  139. string cmdText = "SELECT " + command.CommandText + "($args)";
  140. cmdText = cmdText.Replace("$args", string.Join(",", paramNames.ToArray()));
  141. command.CommandText = cmdText;
  142. }
  143. if (method.ReturnType == typeof(DataSet))
  144. {
  145. //unknown shape of resultset:
  146. System.Data.DataSet dataSet = new DataSet();
  147. IDbDataAdapter adapter = CreateDataAdapter(context);
  148. adapter.SelectCommand = command;
  149. adapter.Fill(dataSet);
  150. List<object> outParamValues = CopyOutParams(paramInfos, command.Parameters);
  151. return new ProcedureResult(dataSet, outParamValues.ToArray());
  152. }
  153. else
  154. {
  155. object obj = command.ExecuteScalar();
  156. List<object> outParamValues = CopyOutParams(paramInfos, command.Parameters);
  157. return new ProcedureResult(obj, outParamValues.ToArray());
  158. }
  159. }
  160. }
  161. static ParameterDirection GetDirection(ParameterInfo paramInfo, ParameterAttribute paramAttrib)
  162. {
  163. //strange hack to determine what's a ref, out parameter:
  164. //http://lists.ximian.com/pipermain/mono-list/2003-March/012751.html
  165. bool hasAmpersand = paramInfo.ParameterType.FullName.Contains('&');
  166. if (paramInfo.IsOut)
  167. return ParameterDirection.Output;
  168. if (hasAmpersand)
  169. return ParameterDirection.InputOutput;
  170. return ParameterDirection.Input;
  171. }
  172. /// <summary>
  173. /// Collect all Out or InOut param values, casting them to the correct .net type.
  174. /// </summary>
  175. private List<object> CopyOutParams(ParameterInfo[] paramInfos, IDataParameterCollection paramSet)
  176. {
  177. List<object> outParamValues = new List<object>();
  178. //Type type_t = typeof(T);
  179. int i = -1;
  180. foreach (IDbDataParameter param in paramSet)
  181. {
  182. i++;
  183. if (param.Direction == ParameterDirection.Input)
  184. {
  185. outParamValues.Add("unused");
  186. continue;
  187. }
  188. object val = param.Value;
  189. Type desired_type = paramInfos[i].ParameterType;
  190. if (desired_type.Name.EndsWith("&"))
  191. {
  192. //for ref and out parameters, we need to tweak ref types, e.g.
  193. // "System.Int32&, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  194. string fullName1 = desired_type.AssemblyQualifiedName;
  195. string fullName2 = fullName1.Replace("&", "");
  196. desired_type = Type.GetType(fullName2);
  197. }
  198. try
  199. {
  200. //fi.SetValue(t, val); //fails with 'System.Decimal cannot be converted to Int32'
  201. //DbLinq.util.FieldUtils.SetObjectIdField(t, fi, val);
  202. //object val2 = DbLinq.Util.FieldUtils.CastValue(val, desired_type);
  203. object val2 = TypeConvert.To(val, desired_type);
  204. outParamValues.Add(val2);
  205. }
  206. catch (Exception)
  207. {
  208. //fails with 'System.Decimal cannot be converted to Int32'
  209. //Logger.Write(Level.Error, "CopyOutParams ERROR L245: failed on CastValue(): " + ex.Message);
  210. }
  211. }
  212. return outParamValues;
  213. }
  214. }
  215. }