Thumbnail file hits. Based on a patch from D Bera
[beagle.git] / beagled / Mono.Data.SqliteClient / SqliteDataReader.cs
blob1c48f5e05e1c1bcf4deefbff113a983593255ce9
1 //
2 // Mono.Data.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 //
10 // Copyright (C) 2002 Vladimir Vukicevic
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System;
33 using System.Runtime.InteropServices;
34 using System.Collections;
35 using System.Data;
36 using System.Data.Common;
38 namespace Mono.Data.SqliteClient
40 public class SqliteDataReader : MarshalByRefObject, IEnumerable, IDataReader, IDisposable, IDataRecord
43 #region Fields
45 private SqliteCommand command;
46 private IntPtr pVm;
47 private int version;
49 private ArrayList current_row;
51 private ArrayList columns;
52 private Hashtable column_names;
53 private bool closed;
55 #endregion
57 #region Constructors and destructors
59 internal SqliteDataReader (SqliteCommand cmd, IntPtr _pVm, int _version)
61 command = cmd;
62 pVm = _pVm;
63 version = _version;
65 current_row = new ArrayList ();
67 columns = new ArrayList ();
68 column_names = new Hashtable ();
69 closed = false;
72 #endregion
74 #region Properties
76 public int Depth {
77 get { return 0; }
80 public int FieldCount {
81 get { return columns.Count; }
84 public object this[string name] {
85 get { return current_row [(int) column_names[name]]; }
88 public object this[int i] {
89 get { return current_row [i]; }
92 public bool IsClosed {
93 get { return closed; }
96 public int RecordsAffected {
97 get { return command.NumChanges (); }
100 #endregion
102 #region Internal Methods
104 internal bool ReadNextColumn ()
106 int pN = 0;
107 IntPtr pazValue = IntPtr.Zero;
108 IntPtr pazColName = IntPtr.Zero;
109 SqliteError res;
111 if (version == 3) {
112 res = Sqlite.sqlite3_step (pVm);
113 pN = Sqlite.sqlite3_column_count (pVm);
114 } else
115 res = Sqlite.sqlite_step (pVm, out pN, out pazValue, out pazColName);
117 if (res == SqliteError.DONE) {
118 return false;
121 if (res != SqliteError.ROW)
122 throw new SqliteException (res);
124 // We have some data; lets read it
126 // If we are reading the first column, populate the column names
127 if (column_names.Count == 0) {
128 for (int i = 0; i < pN; i++) {
129 string colName = "";
130 if (version == 2) {
131 IntPtr fieldPtr = (IntPtr)Marshal.ReadInt32 (pazColName, i*IntPtr.Size);
132 colName = Marshal.PtrToStringAnsi (fieldPtr);
133 } else {
134 colName = Marshal.PtrToStringAnsi (Sqlite.sqlite3_column_name (pVm, i));
136 columns.Add (colName);
137 column_names [colName] = i;
141 // Now read the actual data
142 current_row.Clear ();
143 for (int i = 0; i < pN; i++) {
144 string colData = "";
145 if (version == 2) {
146 IntPtr fieldPtr = (IntPtr)Marshal.ReadInt32 (pazValue, i*IntPtr.Size);
147 colData = Marshal.PtrToStringAnsi (fieldPtr);
148 current_row.Add (Marshal.PtrToStringAnsi (fieldPtr));
149 } else {
150 switch (Sqlite.sqlite3_column_type (pVm, i)) {
151 case 1:
152 Int64 sqliteint64 = Sqlite.sqlite3_column_int64 (pVm, i);
153 current_row.Add (sqliteint64.ToString ());
154 break;
155 case 2:
156 double sqlitedouble = Sqlite.sqlite3_column_double (pVm, i);
157 current_row.Add (sqlitedouble.ToString ());
158 break;
159 case 3:
160 colData = Marshal.PtrToStringAnsi (Sqlite.sqlite3_column_text (pVm, i));
161 current_row.Add (colData);
162 break;
163 case 4:
164 int blobbytes = Sqlite.sqlite3_column_bytes (pVm, i);
165 IntPtr blobptr = Sqlite.sqlite3_column_blob (pVm, i);
166 byte[] blob = new byte[blobbytes];
167 Marshal.Copy (blobptr, blob, 0, blobbytes);
168 current_row.Add (blob);
169 break;
170 case 5:
171 current_row.Add (null);
172 break;
173 default:
174 throw new ApplicationException ("FATAL: Unknown sqlite3_column_type");
179 return true;
182 #endregion
184 #region Public Methods
186 public void Close ()
188 closed = true;
190 if (pVm != IntPtr.Zero) {
191 IntPtr errMsg;
192 if (version == 3)
193 Sqlite.sqlite3_finalize (pVm, out errMsg);
194 else
195 Sqlite.sqlite_finalize (pVm, out errMsg);
196 pVm = IntPtr.Zero;
200 public void Dispose ()
202 Close ();
205 IEnumerator IEnumerable.GetEnumerator ()
207 return new DbEnumerator (this);
210 public DataTable GetSchemaTable ()
212 DataTable dataTableSchema = new DataTable ();
214 dataTableSchema.Columns.Add ("ColumnName", typeof (String));
215 dataTableSchema.Columns.Add ("ColumnOrdinal", typeof (Int32));
216 dataTableSchema.Columns.Add ("ColumnSize", typeof (Int32));
217 dataTableSchema.Columns.Add ("NumericPrecision", typeof (Int32));
218 dataTableSchema.Columns.Add ("NumericScale", typeof (Int32));
219 dataTableSchema.Columns.Add ("IsUnique", typeof (Boolean));
220 dataTableSchema.Columns.Add ("IsKey", typeof (Boolean));
221 dataTableSchema.Columns.Add ("BaseCatalogName", typeof (String));
222 dataTableSchema.Columns.Add ("BaseColumnName", typeof (String));
223 dataTableSchema.Columns.Add ("BaseSchemaName", typeof (String));
224 dataTableSchema.Columns.Add ("BaseTableName", typeof (String));
225 dataTableSchema.Columns.Add ("DataType", typeof(Type));
226 dataTableSchema.Columns.Add ("AllowDBNull", typeof (Boolean));
227 dataTableSchema.Columns.Add ("ProviderType", typeof (Int32));
228 dataTableSchema.Columns.Add ("IsAliased", typeof (Boolean));
229 dataTableSchema.Columns.Add ("IsExpression", typeof (Boolean));
230 dataTableSchema.Columns.Add ("IsIdentity", typeof (Boolean));
231 dataTableSchema.Columns.Add ("IsAutoIncrement", typeof (Boolean));
232 dataTableSchema.Columns.Add ("IsRowVersion", typeof (Boolean));
233 dataTableSchema.Columns.Add ("IsHidden", typeof (Boolean));
234 dataTableSchema.Columns.Add ("IsLong", typeof (Boolean));
235 dataTableSchema.Columns.Add ("IsReadOnly", typeof (Boolean));
237 dataTableSchema.BeginLoadData();
238 for (int i = 0; i < this.FieldCount; i += 1 ) {
240 DataRow schemaRow = dataTableSchema.NewRow ();
242 schemaRow["ColumnName"] = columns[i];
243 schemaRow["ColumnOrdinal"] = i;
244 schemaRow["ColumnSize"] = 0;
245 schemaRow["NumericPrecision"] = 0;
246 schemaRow["NumericScale"] = 0;
247 schemaRow["IsUnique"] = false;
248 schemaRow["IsKey"] = false;
249 schemaRow["BaseCatalogName"] = "";
250 schemaRow["BaseColumnName"] = columns[i];
251 schemaRow["BaseSchemaName"] = "";
252 schemaRow["BaseTableName"] = "";
253 schemaRow["DataType"] = typeof(string);
254 schemaRow["AllowDBNull"] = true;
255 schemaRow["ProviderType"] = 0;
256 schemaRow["IsAliased"] = false;
257 schemaRow["IsExpression"] = false;
258 schemaRow["IsIdentity"] = false;
259 schemaRow["IsAutoIncrement"] = false;
260 schemaRow["IsRowVersion"] = false;
261 schemaRow["IsHidden"] = false;
262 schemaRow["IsLong"] = false;
263 schemaRow["IsReadOnly"] = false;
265 dataTableSchema.Rows.Add (schemaRow);
266 schemaRow.AcceptChanges();
268 dataTableSchema.EndLoadData();
270 return dataTableSchema;
273 public bool NextResult ()
275 return ReadNextColumn ();
278 public bool Read ()
280 return ReadNextColumn ();
283 #endregion
285 #region IDataRecord getters
287 public bool GetBoolean (int i)
289 return Convert.ToBoolean ((string) current_row [i]);
292 public byte GetByte (int i)
294 return Convert.ToByte ((string) current_row [i]);
297 public long GetBytes (int i, long fieldOffset, byte[] buffer, int bufferOffset, int length)
299 throw new NotImplementedException ();
302 public char GetChar (int i)
304 return Convert.ToChar ((string) current_row [i]);
307 public long GetChars (int i, long fieldOffset, char[] buffer, int bufferOffset, int length)
309 throw new NotImplementedException ();
312 public IDataReader GetData (int i)
314 throw new NotImplementedException ();
317 public string GetDataTypeName (int i)
319 return "text"; // SQL Lite data type
322 public DateTime GetDateTime (int i)
324 return Convert.ToDateTime ((string) current_row [i]);
327 public decimal GetDecimal (int i)
329 return Convert.ToDecimal ((string) current_row [i]);
332 public double GetDouble (int i)
334 return Convert.ToDouble ((string) current_row [i]);
337 public Type GetFieldType (int i)
339 return System.Type.GetType ("System.String"); // .NET data type
342 public float GetFloat (int i)
344 return Convert.ToSingle ((string) current_row [i]);
347 public Guid GetGuid (int i)
349 throw new NotImplementedException ();
352 public short GetInt16 (int i)
354 return Convert.ToInt16 ((string) current_row [i]);
357 public int GetInt32 (int i)
359 return Convert.ToInt32 ((string) current_row [i]);
362 public long GetInt64 (int i)
364 return Convert.ToInt64 ((string) current_row [i]);
367 public string GetName (int i)
369 return (string) columns[i];
372 public int GetOrdinal (string name)
374 return (int) column_names[name];
377 public string GetString (int i)
379 return (string) current_row [i];
382 public object GetValue (int i)
384 return current_row [i];
387 public int GetValues (object[] values)
389 int num_to_fill = System.Math.Min (values.Length, columns.Count);
390 for (int i = 0; i < num_to_fill; i++) {
391 if (current_row [i] != null) {
392 values[i] = current_row [i];
393 } else {
394 values[i] = DBNull.Value;
397 return num_to_fill;
400 public bool IsDBNull (int i)
402 return current_row [i] == null;
405 #endregion