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

/drivers/sqlite-wp7/SQLClient/SqliteDataReader.cs

https://bitbucket.org/digitalizarte/coolstorage
C# | 373 lines | 267 code | 50 blank | 56 comment | 62 complexity | 97e0530e0f14a31df609e08ef185974b MD5 | raw file
  1. //
  2. // Community.CsharpSqlite.SQLiteClient.SqliteDataReader.cs
  3. //
  4. // Provides a means of reading a forward-only stream of rows from a Sqlite
  5. // database file.
  6. //
  7. // Author(s): Vladimir Vukicevic <vladimir@pobox.com>
  8. // Everaldo Canuto <everaldo_canuto@yahoo.com.br>
  9. // Joshua Tauberer <tauberer@for.net>
  10. //
  11. // Copyright (C) 2002 Vladimir Vukicevic
  12. //
  13. // Permission is hereby granted, free of charge, to any person obtaining
  14. // a copy of this software and associated documentation files (the
  15. // "Software"), to deal in the Software without restriction, including
  16. // without limitation the rights to use, copy, modify, merge, publish,
  17. // distribute, sublicense, and/or sell copies of the Software, and to
  18. // permit persons to whom the Software is furnished to do so, subject to
  19. // the following conditions:
  20. //
  21. // The above copyright notice and this permission notice shall be
  22. // included in all copies or substantial portions of the Software.
  23. //
  24. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  28. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  29. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  30. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  31. //
  32. using System;
  33. using System.Collections;
  34. using System.Collections.Generic;
  35. namespace Community.CsharpSqlite.SQLiteClient
  36. {
  37. public class SqliteDataReader : IDisposable
  38. {
  39. private SqliteCommand command;
  40. private List<object[]> rows;
  41. private string[] columns;
  42. private Hashtable column_names_sens, column_names_insens;
  43. private int current_row;
  44. private bool closed;
  45. private bool reading;
  46. private int records_affected;
  47. private string[] decltypes;
  48. internal SqliteDataReader (SqliteCommand cmd, Sqlite3.Vdbe pVm, int version)
  49. {
  50. command = cmd;
  51. rows = new List<object[]>();
  52. column_names_sens = new Hashtable ();
  53. column_names_insens = new Hashtable (StringComparer.InvariantCultureIgnoreCase);
  54. closed = false;
  55. current_row = -1;
  56. reading = true;
  57. ReadpVm (pVm, version, cmd);
  58. ReadingDone ();
  59. }
  60. public int Depth {
  61. get { return 0; }
  62. }
  63. public int FieldCount {
  64. get { return columns.Length; }
  65. }
  66. public object this[string name] {
  67. get {
  68. return GetValue (GetOrdinal (name));
  69. }
  70. }
  71. public object this[int i] {
  72. get { return GetValue (i); }
  73. }
  74. public bool IsClosed {
  75. get { return closed; }
  76. }
  77. public int RecordsAffected {
  78. get { return records_affected; }
  79. }
  80. internal void ReadpVm (Sqlite3.Vdbe pVm, int version, SqliteCommand cmd)
  81. {
  82. int pN;
  83. IntPtr pazValue;
  84. IntPtr pazColName;
  85. bool first = true;
  86. int[] declmode = null;
  87. while (true) {
  88. bool hasdata = cmd.ExecuteStatement(pVm, out pN, out pazValue, out pazColName);
  89. // For the first row, get the column information
  90. if (first) {
  91. first = false;
  92. if (version == 3) {
  93. // A decltype might be null if the type is unknown to sqlite.
  94. decltypes = new string[pN];
  95. declmode = new int[pN]; // 1 == integer, 2 == datetime
  96. for (int i = 0; i < pN; i++) {
  97. string decl = Sqlite3.sqlite3_column_decltype (pVm, i);
  98. if (decl != null) {
  99. decltypes[i] = decl.ToLower(System.Globalization.CultureInfo.InvariantCulture);
  100. if (decltypes[i] == "int" || decltypes[i] == "integer")
  101. declmode[i] = 1;
  102. else if (decltypes[i] == "date" || decltypes[i] == "datetime")
  103. declmode[i] = 2;
  104. }
  105. }
  106. }
  107. columns = new string[pN];
  108. for (int i = 0; i < pN; i++) {
  109. string colName;
  110. //if (version == 2) {
  111. // IntPtr fieldPtr = Marshal.ReadIntPtr (pazColName, i*IntPtr.Size);
  112. // colName = Sqlite.HeapToString (fieldPtr, ((SqliteConnection)cmd.Connection).Encoding);
  113. //} else {
  114. colName = Sqlite3.sqlite3_column_name (pVm, i);
  115. //}
  116. columns[i] = colName;
  117. column_names_sens [colName] = i;
  118. column_names_insens [colName] = i;
  119. }
  120. }
  121. if (!hasdata) break;
  122. object[] data_row = new object [pN];
  123. for (int i = 0; i < pN; i++) {
  124. /*
  125. if (version == 2) {
  126. IntPtr fieldPtr = Marshal.ReadIntPtr (pazValue, i*IntPtr.Size);
  127. data_row[i] = Sqlite.HeapToString (fieldPtr, ((SqliteConnection)cmd.Connection).Encoding);
  128. } else {
  129. */
  130. switch (Sqlite3.sqlite3_column_type (pVm, i)) {
  131. case 1:
  132. long val = Sqlite3.sqlite3_column_int64 (pVm, i);
  133. // If the column was declared as an 'int' or 'integer', let's play
  134. // nice and return an int (version 3 only).
  135. if (declmode[i] == 1 && val >= int.MinValue && val <= int.MaxValue)
  136. data_row[i] = (int)val;
  137. // Or if it was declared a date or datetime, do the reverse of what we
  138. // do for DateTime parameters.
  139. else if (declmode[i] == 2)
  140. data_row[i] = DateTime.FromFileTime(val);
  141. else
  142. data_row[i] = val;
  143. break;
  144. case 2:
  145. data_row[i] = Sqlite3.sqlite3_column_double (pVm, i);
  146. break;
  147. case 3:
  148. data_row[i] = Sqlite3.sqlite3_column_text (pVm, i);
  149. // If the column was declared as a 'date' or 'datetime', let's play
  150. // nice and return a DateTime (version 3 only).
  151. if (declmode[i] == 2)
  152. if (data_row[i] == null) data_row[i] = null;
  153. else data_row[i] = DateTime.Parse((string)data_row[i], System.Globalization.CultureInfo.InvariantCulture);
  154. break;
  155. case 4:
  156. int blobbytes = Sqlite3.sqlite3_column_bytes16 (pVm, i);
  157. byte[] blob = Sqlite3.sqlite3_column_blob(pVm, i);
  158. //byte[] blob = new byte[blobbytes];
  159. //Marshal.Copy (blobptr, blob, 0, blobbytes);
  160. data_row[i] = blob;
  161. break;
  162. case 5:
  163. data_row[i] = null;
  164. break;
  165. default:
  166. throw new ApplicationException ("FATAL: Unknown sqlite3_column_type");
  167. //}
  168. }
  169. }
  170. rows.Add (data_row);
  171. }
  172. }
  173. internal void ReadingDone ()
  174. {
  175. records_affected = command.NumChanges ();
  176. reading = false;
  177. }
  178. public void Close ()
  179. {
  180. closed = true;
  181. }
  182. public void Dispose ()
  183. {
  184. Close ();
  185. }
  186. public bool NextResult ()
  187. {
  188. current_row++;
  189. return (current_row < rows.Count);
  190. }
  191. public bool Read ()
  192. {
  193. return NextResult ();
  194. }
  195. public bool GetBoolean (int i)
  196. {
  197. return Convert.ToBoolean (((object[]) rows[current_row])[i]);
  198. }
  199. public byte GetByte (int i)
  200. {
  201. return Convert.ToByte (((object[]) rows[current_row])[i]);
  202. }
  203. public long GetBytes (int i, long fieldOffset, byte[] buffer, int bufferOffset, int length)
  204. {
  205. byte[] data = (byte[])(((object[]) rows[current_row])[i]);
  206. if (buffer != null)
  207. Array.Copy (data, (int)fieldOffset, buffer, bufferOffset, length);
  208. return data.Length - fieldOffset;
  209. }
  210. public char GetChar (int i)
  211. {
  212. return Convert.ToChar (((object[]) rows[current_row])[i]);
  213. }
  214. public long GetChars (int i, long fieldOffset, char[] buffer, int bufferOffset, int length)
  215. {
  216. char[] data = (char[])(((object[]) rows[current_row])[i]);
  217. if (buffer != null)
  218. Array.Copy (data, (int)fieldOffset, buffer, bufferOffset, length);
  219. return data.Length - fieldOffset;
  220. }
  221. public SqliteDataReader GetData (int i)
  222. {
  223. return ((SqliteDataReader) this [i]);
  224. }
  225. public string GetDataTypeName (int i)
  226. {
  227. if (decltypes != null && decltypes[i] != null)
  228. return decltypes[i];
  229. return "text"; // SQL Lite data type
  230. }
  231. public DateTime GetDateTime (int i)
  232. {
  233. return Convert.ToDateTime (((object[]) rows[current_row])[i]);
  234. }
  235. public decimal GetDecimal (int i)
  236. {
  237. return Convert.ToDecimal (((object[]) rows[current_row])[i]);
  238. }
  239. public double GetDouble (int i)
  240. {
  241. return Convert.ToDouble (((object[]) rows[current_row])[i]);
  242. }
  243. public Type GetFieldType (int i)
  244. {
  245. int row = current_row;
  246. if (row == -1 && rows.Count == 0) return typeof(string);
  247. if (row == -1) row = 0;
  248. object element = ((object[]) rows[row])[i];
  249. if (element != null)
  250. return element.GetType();
  251. else
  252. return typeof (string);
  253. // Note that the return value isn't guaranteed to
  254. // be the same as the rows are read if different
  255. // types of information are stored in the column.
  256. }
  257. public float GetFloat (int i)
  258. {
  259. return Convert.ToSingle (((object[]) rows[current_row])[i]);
  260. }
  261. public Guid GetGuid (int i)
  262. {
  263. object value = GetValue (i);
  264. if (!(value is Guid)) {
  265. if (value is DBNull)
  266. throw new SqliteExecutionException ("Column value must not be null");
  267. throw new InvalidCastException ("Type is " + value.GetType ().ToString ());
  268. }
  269. return ((Guid) value);
  270. }
  271. public short GetInt16 (int i)
  272. {
  273. return Convert.ToInt16 (((object[]) rows[current_row])[i]);
  274. }
  275. public int GetInt32 (int i)
  276. {
  277. return Convert.ToInt32 (((object[]) rows[current_row])[i]);
  278. }
  279. public long GetInt64 (int i)
  280. {
  281. return Convert.ToInt64 (((object[]) rows[current_row])[i]);
  282. }
  283. public string GetName (int i)
  284. {
  285. return columns[i];
  286. }
  287. public int GetOrdinal (string name)
  288. {
  289. object v = column_names_sens[name];
  290. if (v == null)
  291. v = column_names_insens[name];
  292. if (v == null)
  293. throw new ArgumentException("Column does not exist.");
  294. return (int) v;
  295. }
  296. public string GetString (int i)
  297. {
  298. if (((object[]) rows[current_row])[i] != null)
  299. return (((object[]) rows[current_row])[i]).ToString();
  300. else return null;
  301. }
  302. public object GetValue (int i)
  303. {
  304. return ((object[]) rows[current_row])[i];
  305. }
  306. public int GetValues (object[] values)
  307. {
  308. int num_to_fill = System.Math.Min (values.Length, columns.Length);
  309. for (int i = 0; i < num_to_fill; i++) {
  310. if (((object[]) rows[current_row])[i] != null) {
  311. values[i] = ((object[]) rows[current_row])[i];
  312. } else {
  313. values[i] = DBNull.Value;
  314. }
  315. }
  316. return num_to_fill;
  317. }
  318. public bool IsDBNull (int i)
  319. {
  320. return (((object[]) rows[current_row])[i] == null);
  321. }
  322. }
  323. }