* Mono.Data.SqlClient/SqliteCobmmand.cs, SqliteDataReader.cs,
[mono.git] / mcs / class / Mono.Data.SqliteClient / Mono.Data.SqliteClient / SqliteDataReader.cs
1 // -*- c-basic-offset: 8; inent-tabs-mode: nil -*-
2 //
3 //  SqliteDataReader.cs
4 //
5 //  Author(s): Vladimir Vukicevic  <vladimir@pobox.com>
6 //
7 //  Copyright (C) 2002  Vladimir Vukicevic
8 //
9
10 using System;
11 using System.Runtime.InteropServices;
12 using System.Collections;
13 using System.Data;
14
15 namespace Mono.Data.SqliteClient
16 {
17         public class SqliteDataReader : IDataReader
18         {
19                 SqliteCommand command;
20                 ArrayList rows;
21                 ArrayList columns;
22                 Hashtable column_names;
23                 int current_row;
24                 bool closed;
25                 bool reading;
26                 int records_affected;
27
28                 internal SqliteDataReader (SqliteCommand cmd)
29                 {
30                         command = cmd;
31                         rows = new ArrayList ();
32                         columns = new ArrayList ();
33                         column_names = new Hashtable ();
34                         closed = false;
35                         current_row = -1;
36                         reading = true;
37                 }
38
39                 internal void ReadingDone ()
40                 {
41                         records_affected = command.NumChanges ();
42                         reading = false;
43                 }
44
45                 public void Close ()
46                 {
47                         closed = true;
48                 }
49
50                 public void Dispose ()
51                 {
52                         // nothing to do
53                 }
54
55                 public DataTable GetSchemaTable ()
56                 {
57
58 #if NOTDEF
59                         // We sort of cheat here since sqlite treats all types as strings
60                         // we -could- parse the table definition (since that's the only info
61                         // that we can get out of sqlite about the table), but it's probably
62                         // not worth it.
63                         DataTable data_table = new DataTable ();
64
65                         DataColumn col;
66                         DataRow row;
67
68                         // first create the columns
69                         for (int i = 0; i < column_names.Count; i++) {
70                                 col = new DataColumn ();
71                                 col.DataType = System.Type.GetType("System.String");
72                                 col.ColumnName = columns[i];
73                                 data_table.Columns.Add (col);
74                         }
75
76                         // then loop through the rows
77                         for (int i = 0; i < rows.Length; i++) {
78                                 row = data_table.NewRow ();
79                                 for (int j = 0; j < column_names.Count; j++) {
80                                         row[columns[j]] = rows[i][j];
81                                 }
82                                 data_table.Rows.Add (row);
83                         }
84
85                         return data_table;
86 #else
87                         return null;
88 #endif
89                 }
90
91                 public bool NextResult ()
92                 {
93                         current_row++;
94                         if (current_row < rows.Count)
95                                 return true;
96                         return false;
97                 }
98
99                 public bool Read ()
100                 {
101                         return NextResult ();
102                 }
103
104                 public int Depth {
105                         get {
106                                 return 0;
107                         }
108                 }
109
110                 public bool IsClosed {
111                         get {
112                                 return closed;
113                         }
114                 }
115
116                 public int RecordsAffected {
117                         get {
118                                 return records_affected;
119                         }
120                 }
121
122                 // sqlite callback
123                 internal unsafe int SqliteCallback (ref object o, int argc, sbyte **argv, sbyte **colnames)
124                 {
125                         // cache names of columns if we need to
126                         if (column_names.Count == 0) {
127                                 for (int i = 0; i < argc; i++) {
128                                         string col = new String (colnames[i]);
129                                         columns.Add (col);
130                                         column_names[col.ToLower ()] = i++;
131                                 }
132                         }
133
134                         ArrayList data_row = new ArrayList (argc);
135                         for (int i = 0; i < argc; i++) {
136                                 if (argv[i] != ((sbyte *)0)) {
137                                         data_row.Add(new String (argv[i]));
138                                 } else {
139                                         data_row.Add(null);
140                                 }
141                         }
142                         rows.Add (data_row);
143                         return 0;
144                 }
145
146                 //
147                 // IDataRecord getters
148                 //
149
150                 public bool GetBoolean (int i)
151                 {
152                         return Convert.ToBoolean ((string) ((ArrayList) rows[current_row])[i]);
153                 }
154
155                 public byte GetByte (int i)
156                 {
157                         return Convert.ToByte ((string) ((ArrayList) rows[current_row])[i]);
158                 }
159
160                 public long GetBytes (int i, long fieldOffset, byte[] buffer, 
161                                int bufferOffset, int length)
162                 {
163                         throw new NotImplementedException ();
164                 }
165
166                 public char GetChar (int i)
167                 {
168                         return Convert.ToChar ((string) ((ArrayList) rows[current_row])[i]);
169                 }
170
171                 public long GetChars (int i, long fieldOffset, char[] buffer, 
172                                int bufferOffset, int length)
173                 {
174                         throw new NotImplementedException ();
175                 }
176
177                 public IDataReader GetData (int i)
178                 {
179                         // sigh.. in the MSDN docs, it says that "This member supports the
180                         // .NET Framework infrastructure and is not nitended to be used
181                         // directly from your code." -- so why the hell is it in the public
182                         // interface?
183                         throw new NotImplementedException ();
184                 }
185
186                 public string GetDataTypeName (int i)
187                 {
188                         return "System.String";
189                 }
190
191                 public DateTime GetDateTime (int i)
192                 {
193                         return Convert.ToDateTime ((string) ((ArrayList) rows[current_row])[i]);
194                 }
195
196                 public decimal GetDecimal (int i)
197                 {
198                         return Convert.ToDecimal ((string) ((ArrayList) rows[current_row])[i]);
199                 }
200
201                 public double GetDouble (int i)
202                 {
203                         return Convert.ToDouble ((string) ((ArrayList) rows[current_row])[i]);
204                 }
205
206                 public Type GetFieldType (int i)
207                 {
208                         return System.Type.GetType ("System.String");
209                 }
210
211                 public float GetFloat (int i)
212                 {
213                         return Convert.ToSingle ((string) ((ArrayList) rows[current_row])[i]);
214                 }
215
216                 public Guid GetGuid (int i)
217                 {
218                         throw new NotImplementedException ();
219                 }
220
221                 public short GetInt16 (int i)
222                 {
223                         return Convert.ToInt16 ((string) ((ArrayList) rows[current_row])[i]);
224                 }
225
226                 public int GetInt32 (int i)
227                 {
228                         return Convert.ToInt32 ((string) ((ArrayList) rows[current_row])[i]);
229                 }
230
231                 public long GetInt64 (int i)
232                 {
233                         return Convert.ToInt64 ((string) ((ArrayList) rows[current_row])[i]);
234                 }
235
236                 public string GetName (int i)
237                 {
238                         return (string) columns[i];
239                 }
240
241                 public int GetOrdinal (string name)
242                 {
243                         return (int) column_names[name];
244                 }
245
246                 public string GetString (int i)
247                 {
248                         return ((string) ((ArrayList) rows[current_row])[i]);
249                 }
250
251                 public object GetValue (int i)
252                 {
253                         return ((ArrayList) rows[current_row])[i];
254                 }
255
256                 public int GetValues (object[] values)
257                 {
258                         int num_to_fill = Math.Min (values.Length, columns.Count);
259                         for (int i = 0; i < num_to_fill; i++) {
260                                 if (((ArrayList) rows[current_row])[i] != null) {
261                                         values[i] = ((ArrayList) rows[current_row])[i];
262                                 } else {
263                                         values[i] = DBNull.Value;
264                                 }
265                         }
266                         return num_to_fill;
267                 }
268
269                 public bool IsDBNull (int i)
270                 {
271                         if (((ArrayList) rows[current_row])[i] == null)
272                                 return true;
273                         return false;
274                 }
275
276                 public int FieldCount {
277                         get {
278                                 if (current_row == -1 || current_row == rows.Count)
279                                         return 0;
280                                 return columns.Count;
281                         }
282                 }
283
284                 public object this[string name] {
285                         get {
286                                 return ((ArrayList) rows[current_row])[(int) column_names[name]];
287                         }
288                 }
289                 
290                 public object this[int i] {
291                         get {
292                                 return ((ArrayList) rows[current_row])[i];
293                         }
294                 }
295         }
296 }