PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/FirebirdSql.Data.Firebird/FirebirdSql.Data.Common/ArrayBase.cs

https://github.com/cschlote/mono
C# | 350 lines | 245 code | 76 blank | 29 comment | 24 complexity | 862810f6d6144a05671ae00a1e7fdbdf MD5 | raw file
  1. /*
  2. * Firebird ADO.NET Data provider for .NET and Mono
  3. *
  4. * The contents of this file are subject to the Initial
  5. * Developer's Public License Version 1.0 (the "License");
  6. * you may not use this file except in compliance with the
  7. * License. You may obtain a copy of the License at
  8. * http://www.firebirdsql.org/index.php?op=doc&id=idpl
  9. *
  10. * Software distributed under the License is distributed on
  11. * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
  12. * express or implied. See the License for the specific
  13. * language governing rights and limitations under the License.
  14. *
  15. * Copyright (c) 2002, 2005 Carlos Guzman Alvarez
  16. * All Rights Reserved.
  17. */
  18. using System;
  19. using System.Text;
  20. using System.Globalization;
  21. namespace FirebirdSql.Data.Common
  22. {
  23. internal abstract class ArrayBase
  24. {
  25. #region Fields
  26. private ArrayDesc descriptor;
  27. private string tableName;
  28. private string fieldName;
  29. private string rdbFieldName;
  30. #endregion
  31. #region Properties
  32. public ArrayDesc Descriptor
  33. {
  34. get { return this.descriptor; }
  35. }
  36. #endregion
  37. #region Abstract Properties
  38. public abstract long Handle
  39. {
  40. get;
  41. set;
  42. }
  43. public abstract IDatabase DB
  44. {
  45. get;
  46. set;
  47. }
  48. public abstract ITransaction Transaction
  49. {
  50. get;
  51. set;
  52. }
  53. #endregion
  54. #region Constructors
  55. protected ArrayBase(ArrayDesc descriptor)
  56. {
  57. this.tableName = descriptor.RelationName;
  58. this.fieldName = descriptor.FieldName;
  59. this.descriptor = descriptor;
  60. }
  61. protected ArrayBase(string tableName, string fieldName)
  62. {
  63. this.tableName = tableName;
  64. this.fieldName = fieldName;
  65. this.rdbFieldName = String.Empty;
  66. }
  67. #endregion
  68. #region Abstract Methods
  69. public abstract byte[] GetSlice(int slice_length);
  70. public abstract void PutSlice(System.Array source_array, int slice_length);
  71. #endregion
  72. #region Protected Abstract Methods
  73. protected abstract System.Array DecodeSlice(byte[] slice);
  74. #endregion
  75. #region Methods
  76. public Array Read()
  77. {
  78. byte[] slice = this.GetSlice(this.GetSliceLength(true));
  79. return this.DecodeSlice(slice);
  80. }
  81. public void Write(System.Array sourceArray)
  82. {
  83. this.SetDesc(sourceArray);
  84. this.PutSlice(sourceArray, this.GetSliceLength(false));
  85. }
  86. public void SetDesc(System.Array sourceArray)
  87. {
  88. this.descriptor.Dimensions = (short)sourceArray.Rank;
  89. for (int i = 0; i < sourceArray.Rank; i++)
  90. {
  91. int lb = this.descriptor.Bounds[i].LowerBound;
  92. int ub = sourceArray.GetLength(i) - 1 + lb;
  93. this.descriptor.Bounds[i].UpperBound = ub;
  94. }
  95. }
  96. public void LookupBounds()
  97. {
  98. this.LookupDesc();
  99. StatementBase lookup = this.DB.CreateStatement(this.Transaction);
  100. lookup.Prepare(this.GetArrayBounds());
  101. lookup.Execute();
  102. int i = 0;
  103. this.descriptor.Bounds = new ArrayBound[16];
  104. DbValue[] values;
  105. while ((values = lookup.Fetch()) != null)
  106. {
  107. this.descriptor.Bounds[i].LowerBound = values[0].GetInt32();
  108. this.descriptor.Bounds[i].UpperBound = values[1].GetInt32();
  109. i++;
  110. }
  111. lookup.Release();
  112. lookup = null;
  113. }
  114. public void LookupDesc()
  115. {
  116. // Initializa array descriptor information
  117. this.descriptor = new ArrayDesc();
  118. // Create statement for retrieve information
  119. StatementBase lookup = this.DB.CreateStatement(this.Transaction);
  120. lookup.Prepare(this.GetArrayDesc());
  121. lookup.Execute();
  122. DbValue[] values = lookup.Fetch();
  123. if (values != null && values.Length > 0)
  124. {
  125. this.descriptor.RelationName = tableName;
  126. this.descriptor.FieldName = fieldName;
  127. this.descriptor.DataType = values[0].GetByte();
  128. this.descriptor.Scale = values[1].GetInt16();
  129. this.descriptor.Length = values[2].GetInt16();
  130. this.descriptor.Dimensions = values[3].GetInt16();
  131. this.descriptor.Flags = 0;
  132. this.rdbFieldName = values[4].GetString().Trim();
  133. }
  134. else
  135. {
  136. throw new InvalidOperationException();
  137. }
  138. lookup.Release();
  139. lookup = null;
  140. }
  141. #endregion
  142. #region Protected Methods
  143. protected int GetSliceLength(bool read)
  144. {
  145. int length = 0;
  146. int elements = 0;
  147. for (int i = 0; i < this.descriptor.Dimensions; i++)
  148. {
  149. ArrayBound bound = this.descriptor.Bounds[i];
  150. elements += (bound.UpperBound - bound.LowerBound) + 1;
  151. }
  152. length = elements * this.descriptor.Length;
  153. switch (this.descriptor.DataType)
  154. {
  155. case IscCodes.blr_varying:
  156. case IscCodes.blr_varying2:
  157. length += elements * 2;
  158. break;
  159. }
  160. return length;
  161. }
  162. protected Type GetSystemType()
  163. {
  164. Type systemType;
  165. switch (this.descriptor.DataType)
  166. {
  167. case IscCodes.blr_text:
  168. case IscCodes.blr_text2:
  169. case IscCodes.blr_cstring:
  170. case IscCodes.blr_cstring2:
  171. // Char
  172. systemType = typeof(System.String);
  173. break;
  174. case IscCodes.blr_varying:
  175. case IscCodes.blr_varying2:
  176. // VarChar
  177. systemType = typeof(System.String);
  178. break;
  179. case IscCodes.blr_short:
  180. // Short/Smallint
  181. if (this.descriptor.Scale < 0)
  182. {
  183. systemType = typeof(System.Decimal);
  184. }
  185. else
  186. {
  187. systemType = typeof(System.Int16);
  188. }
  189. break;
  190. case IscCodes.blr_long:
  191. // Integer
  192. if (this.descriptor.Scale < 0)
  193. {
  194. systemType = typeof(System.Decimal);
  195. }
  196. else
  197. {
  198. systemType = typeof(System.Int32);
  199. }
  200. break;
  201. case IscCodes.blr_float:
  202. // Float
  203. systemType = typeof(System.Single);
  204. break;
  205. case IscCodes.blr_double:
  206. case IscCodes.blr_d_float:
  207. // Double
  208. systemType = typeof(System.Double);
  209. break;
  210. case IscCodes.blr_quad:
  211. case IscCodes.blr_int64:
  212. // Long/Quad
  213. if (this.descriptor.Scale < 0)
  214. {
  215. systemType = typeof(System.Decimal);
  216. }
  217. else
  218. {
  219. systemType = typeof(System.Int64);
  220. }
  221. break;
  222. case IscCodes.blr_timestamp:
  223. // Timestamp
  224. systemType = typeof(System.DateTime);
  225. break;
  226. case IscCodes.blr_sql_time:
  227. // Time
  228. systemType = typeof(System.DateTime);
  229. break;
  230. case IscCodes.blr_sql_date:
  231. // Date
  232. systemType = typeof(System.DateTime);
  233. break;
  234. default:
  235. throw new NotSupportedException("Unknown data type");
  236. }
  237. return systemType;
  238. }
  239. #endregion
  240. #region Private Methods
  241. private string GetArrayDesc()
  242. {
  243. StringBuilder sql = new StringBuilder();
  244. sql.Append(
  245. "SELECT Y.RDB$FIELD_TYPE, Y.RDB$FIELD_SCALE, Y.RDB$FIELD_LENGTH, Y.RDB$DIMENSIONS, X.RDB$FIELD_SOURCE " +
  246. "FROM RDB$RELATION_FIELDS X, RDB$FIELDS Y " +
  247. "WHERE X.RDB$FIELD_SOURCE = Y.RDB$FIELD_NAME ");
  248. if (this.tableName != null && this.tableName.Length != 0)
  249. {
  250. sql.AppendFormat(
  251. CultureInfo.CurrentCulture, " AND X.RDB$RELATION_NAME = '{0}'", tableName);
  252. }
  253. if (this.fieldName != null && this.fieldName.Length != 0)
  254. {
  255. sql.AppendFormat(
  256. CultureInfo.CurrentCulture, " AND X.RDB$FIELD_NAME = '{0}'", fieldName);
  257. }
  258. return sql.ToString();
  259. }
  260. private string GetArrayBounds()
  261. {
  262. StringBuilder sql = new StringBuilder();
  263. sql.Append("SELECT X.RDB$LOWER_BOUND, X.RDB$UPPER_BOUND FROM RDB$FIELD_DIMENSIONS X ");
  264. if (this.fieldName != null && this.fieldName.Length != 0)
  265. {
  266. sql.AppendFormat(
  267. CultureInfo.CurrentCulture, "WHERE X.RDB$FIELD_NAME = '{0}'", rdbFieldName);
  268. }
  269. sql.Append(" ORDER BY X.RDB$DIMENSION");
  270. return sql.ToString();
  271. }
  272. #endregion
  273. }
  274. }