1 // -*- c-basic-offset: 8; inent-tabs-mode: nil -*-
5 // Author(s): Vladimir Vukicevic <vladimir@pobox.com>
7 // Copyright (C) 2002 Vladimir Vukicevic
11 using System.Runtime.InteropServices;
12 using System.Collections;
14 using System.Data.Common;
16 namespace Mono.Data.SqliteClient
18 public class SqliteDataReader : MarshalByRefObject,
19 IEnumerable, IDataReader, IDisposable, IDataRecord
21 SqliteCommand command;
24 Hashtable column_names;
30 internal SqliteDataReader (SqliteCommand cmd)
33 rows = new ArrayList ();
34 columns = new ArrayList ();
35 column_names = new Hashtable ();
41 internal void ReadingDone ()
43 records_affected = command.NumChanges ();
52 public void Dispose ()
57 IEnumerator IEnumerable.GetEnumerator () {
58 return new DbEnumerator (this);
61 public DataTable GetSchemaTable () {
63 // We sort of cheat here since sqlite treats all types as strings
64 // we -could- parse the table definition (since that's the only info
65 // that we can get out of sqlite about the table), but it's probably
68 DataTable dataTableSchema = null;
73 // only create the schema DataTable if
74 // there is fields in a result set due
75 // to the result of a query; otherwise,
76 // a null needs to be returned
77 if(this.FieldCount > 0) {
79 dataTableSchema = new DataTable ();
81 dataTableSchema.Columns.Add ("ColumnName", typeof (string));
82 dataTableSchema.Columns.Add ("ColumnOrdinal", typeof (int));
83 dataTableSchema.Columns.Add ("ColumnSize", typeof (int));
84 dataTableSchema.Columns.Add ("NumericPrecision", typeof (int));
85 dataTableSchema.Columns.Add ("NumericScale", typeof (int));
86 dataTableSchema.Columns.Add ("IsUnique", typeof (bool));
87 dataTableSchema.Columns.Add ("IsKey", typeof (bool));
88 dc = dataTableSchema.Columns["IsKey"];
89 dc.AllowDBNull = true; // IsKey can have a DBNull
90 dataTableSchema.Columns.Add ("BaseCatalogName", typeof (string));
91 dataTableSchema.Columns.Add ("BaseColumnName", typeof (string));
92 dataTableSchema.Columns.Add ("BaseSchemaName", typeof (string));
93 dataTableSchema.Columns.Add ("BaseTableName", typeof (string));
94 dataTableSchema.Columns.Add ("DataType", typeof(Type));
95 dataTableSchema.Columns.Add ("AllowDBNull", typeof (bool));
96 dataTableSchema.Columns.Add ("ProviderType", typeof (int));
97 dataTableSchema.Columns.Add ("IsAliased", typeof (bool));
98 dataTableSchema.Columns.Add ("IsExpression", typeof (bool));
99 dataTableSchema.Columns.Add ("IsIdentity", typeof (bool));
100 dataTableSchema.Columns.Add ("IsAutoIncrement", typeof (bool));
101 dataTableSchema.Columns.Add ("IsRowVersion", typeof (bool));
102 dataTableSchema.Columns.Add ("IsHidden", typeof (bool));
103 dataTableSchema.Columns.Add ("IsLong", typeof (bool));
104 dataTableSchema.Columns.Add ("IsReadOnly", typeof (bool));
106 for (int i = 0; i < this.FieldCount; i += 1 ) {
108 schemaRow = dataTableSchema.NewRow ();
110 schemaRow["ColumnName"] = columns[i];
111 schemaRow["ColumnOrdinal"] = i + 1;
113 // FIXME: how do you determine the column size
115 int columnSize = 8192; // pulled out of the air
116 schemaRow["ColumnSize"] = columnSize;
117 schemaRow["NumericPrecision"] = 0;
118 schemaRow["NumericScale"] = 0;
120 schemaRow["IsUnique"] = false;
121 schemaRow["IsKey"] = DBNull.Value;
123 schemaRow["BaseCatalogName"] = "";
125 schemaRow["BaseColumnName"] = columns[i];
126 schemaRow["BaseSchemaName"] = "";
127 schemaRow["BaseTableName"] = "";
129 // FIXME: don't know how to determine
\r
130 // the .NET type based on the
\r
131 // SQL Lite data type
\r
133 schemaRow["DataType"] = typeof(string);
\r
135 schemaRow["AllowDBNull"] = true;
137 // FIXME: don't know how to get the
138 // SQL Lite data type
139 int providerType = 0; // out of the air
140 schemaRow["ProviderType"] = providerType;
142 schemaRow["IsAliased"] = false;
143 schemaRow["IsExpression"] = false;
144 schemaRow["IsIdentity"] = false;
145 schemaRow["IsAutoIncrement"] = false;
146 schemaRow["IsRowVersion"] = false;
147 schemaRow["IsHidden"] = false;
148 schemaRow["IsLong"] = false;
149 schemaRow["IsReadOnly"] = false;
151 schemaRow.AcceptChanges();
153 dataTableSchema.Rows.Add (schemaRow);
156 return dataTableSchema;
159 public bool NextResult ()
162 if (current_row < rows.Count)
169 return NextResult ();
178 public bool IsClosed {
184 public int RecordsAffected {
186 return records_affected;
191 internal unsafe int SqliteCallback (ref object o, int argc, sbyte **argv, sbyte **colnames)
193 // cache names of columns if we need to
194 if (column_names.Count == 0) {
195 for (int i = 0; i < argc; i++) {
196 string col = new String (colnames[i]);
198 column_names[col.ToLower ()] = i++;
202 ArrayList data_row = new ArrayList (argc);
203 for (int i = 0; i < argc; i++) {
204 if (argv[i] != ((sbyte *)0)) {
205 data_row.Add(new String (argv[i]));
215 // IDataRecord getters
218 public bool GetBoolean (int i)
220 return Convert.ToBoolean ((string) ((ArrayList) rows[current_row])[i]);
223 public byte GetByte (int i)
225 return Convert.ToByte ((string) ((ArrayList) rows[current_row])[i]);
228 public long GetBytes (int i, long fieldOffset, byte[] buffer,
229 int bufferOffset, int length)
231 throw new NotImplementedException ();
234 public char GetChar (int i)
236 return Convert.ToChar ((string) ((ArrayList) rows[current_row])[i]);
239 public long GetChars (int i, long fieldOffset, char[] buffer,
240 int bufferOffset, int length)
242 throw new NotImplementedException ();
245 public IDataReader GetData (int i)
247 // sigh.. in the MSDN docs, it says that "This member supports the
248 // .NET Framework infrastructure and is not nitended to be used
249 // directly from your code." -- so why the hell is it in the public
251 throw new NotImplementedException ();
254 public string GetDataTypeName (int i)
256 return "text"; // SQL Lite data type
259 public DateTime GetDateTime (int i)
261 return Convert.ToDateTime ((string) ((ArrayList) rows[current_row])[i]);
264 public decimal GetDecimal (int i)
266 return Convert.ToDecimal ((string) ((ArrayList) rows[current_row])[i]);
269 public double GetDouble (int i)
271 return Convert.ToDouble ((string) ((ArrayList) rows[current_row])[i]);
274 public Type GetFieldType (int i)
276 return System.Type.GetType ("System.String"); // .NET data type
279 public float GetFloat (int i)
281 return Convert.ToSingle ((string) ((ArrayList) rows[current_row])[i]);
284 public Guid GetGuid (int i)
286 throw new NotImplementedException ();
289 public short GetInt16 (int i)
291 return Convert.ToInt16 ((string) ((ArrayList) rows[current_row])[i]);
294 public int GetInt32 (int i)
296 return Convert.ToInt32 ((string) ((ArrayList) rows[current_row])[i]);
299 public long GetInt64 (int i)
301 return Convert.ToInt64 ((string) ((ArrayList) rows[current_row])[i]);
304 public string GetName (int i)
306 return (string) columns[i];
309 public int GetOrdinal (string name)
311 return (int) column_names[name];
314 public string GetString (int i)
316 return ((string) ((ArrayList) rows[current_row])[i]);
319 public object GetValue (int i)
321 return ((ArrayList) rows[current_row])[i];
324 public int GetValues (object[] values)
326 int num_to_fill = System.Math.Min (values.Length, columns.Count);
327 for (int i = 0; i < num_to_fill; i++) {
328 if (((ArrayList) rows[current_row])[i] != null) {
329 values[i] = ((ArrayList) rows[current_row])[i];
331 values[i] = DBNull.Value;
337 public bool IsDBNull (int i)
339 if (((ArrayList) rows[current_row])[i] == null)
344 public int FieldCount {
346 if (current_row == -1 || current_row == rows.Count)
348 return columns.Count;
352 public object this[string name] {
354 return ((ArrayList) rows[current_row])[(int) column_names[name]];
358 public object this[int i] {
360 return ((ArrayList) rows[current_row])[i];