Use System.Math instead of just `Math'.
[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 using System.Data.Common;
15
16 namespace Mono.Data.SqliteClient
17 {
18         public class SqliteDataReader : MarshalByRefObject,
19                 IEnumerable, IDataReader, IDisposable, IDataRecord
20         {
21                 SqliteCommand command;
22                 ArrayList rows;
23                 ArrayList columns;
24                 Hashtable column_names;
25                 int current_row;
26                 bool closed;
27                 bool reading;
28                 int records_affected;
29
30                 internal SqliteDataReader (SqliteCommand cmd)
31                 {
32                         command = cmd;
33                         rows = new ArrayList ();
34                         columns = new ArrayList ();
35                         column_names = new Hashtable ();
36                         closed = false;
37                         current_row = -1;
38                         reading = true;
39                 }
40
41                 internal void ReadingDone ()
42                 {
43                         records_affected = command.NumChanges ();
44                         reading = false;
45                 }
46
47                 public void Close ()
48                 {
49                         closed = true;
50                 }
51
52                 public void Dispose ()
53                 {
54                         // nothing to do
55                 }
56
57                 IEnumerator IEnumerable.GetEnumerator () {
58                         return new DbEnumerator (this);
59                 }
60
61                 public DataTable GetSchemaTable () {
62                         
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
66                         // not worth it.
67
68                         DataTable dataTableSchema  = null;
69
70                         DataColumn dc;
71                         DataRow schemaRow;
72
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) {
78                                 
79                                 dataTableSchema = new DataTable ();
80                                 
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));
105
106                                 for (int i = 0; i < this.FieldCount; i += 1 ) {
107                                         
108                                         schemaRow = dataTableSchema.NewRow ();
109                                                                                 
110                                         schemaRow["ColumnName"] = columns[i];
111                                         schemaRow["ColumnOrdinal"] = i + 1;
112                                         
113                                         // FIXME: how do you determine the column size
114                                         //        using SQL Lite?
115                                         int columnSize = 8192; // pulled out of the air
116                                         schemaRow["ColumnSize"] = columnSize;
117                                         schemaRow["NumericPrecision"] = 0;
118                                         schemaRow["NumericScale"] = 0;
119
120                                         schemaRow["IsUnique"] = false;
121                                         schemaRow["IsKey"] = DBNull.Value;
122                                         
123                                         schemaRow["BaseCatalogName"] = "";
124                                         
125                                         schemaRow["BaseColumnName"] = columns[i];
126                                         schemaRow["BaseSchemaName"] = "";
127                                         schemaRow["BaseTableName"] = "";
128 \r
129                                         // FIXME: don't know how to determine\r
130                                         // the .NET type based on the\r
131                                         // SQL Lite data type\r
132                                         // Use string\r
133                                         schemaRow["DataType"] = typeof(string);\r
134
135                                         schemaRow["AllowDBNull"] = true;
136                                         
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;
141                                         
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;
150                                         
151                                         schemaRow.AcceptChanges();
152                                         
153                                         dataTableSchema.Rows.Add (schemaRow);
154                                 }
155                         }
156                         return dataTableSchema;
157                 }
158
159                 public bool NextResult ()
160                 {
161                         current_row++;
162                         if (current_row < rows.Count)
163                                 return true;
164                         return false;
165                 }
166
167                 public bool Read ()
168                 {
169                         return NextResult ();
170                 }
171
172                 public int Depth {
173                         get {
174                                 return 0;
175                         }
176                 }
177
178                 public bool IsClosed {
179                         get {
180                                 return closed;
181                         }
182                 }
183
184                 public int RecordsAffected {
185                         get {
186                                 return records_affected;
187                         }
188                 }
189
190                 // sqlite callback
191                 internal unsafe int SqliteCallback (ref object o, int argc, sbyte **argv, sbyte **colnames)
192                 {
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]);
197                                         columns.Add (col);
198                                         column_names[col.ToLower ()] = i++;
199                                 }
200                         }
201
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]));
206                                 } else {
207                                         data_row.Add(null);
208                                 }
209                         }
210                         rows.Add (data_row);
211                         return 0;
212                 }
213
214                 //
215                 // IDataRecord getters
216                 //
217
218                 public bool GetBoolean (int i)
219                 {
220                         return Convert.ToBoolean ((string) ((ArrayList) rows[current_row])[i]);
221                 }
222
223                 public byte GetByte (int i)
224                 {
225                         return Convert.ToByte ((string) ((ArrayList) rows[current_row])[i]);
226                 }
227
228                 public long GetBytes (int i, long fieldOffset, byte[] buffer, 
229                                int bufferOffset, int length)
230                 {
231                         throw new NotImplementedException ();
232                 }
233
234                 public char GetChar (int i)
235                 {
236                         return Convert.ToChar ((string) ((ArrayList) rows[current_row])[i]);
237                 }
238
239                 public long GetChars (int i, long fieldOffset, char[] buffer, 
240                                int bufferOffset, int length)
241                 {
242                         throw new NotImplementedException ();
243                 }
244
245                 public IDataReader GetData (int i)
246                 {
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
250                         // interface?
251                         throw new NotImplementedException ();
252                 }
253
254                 public string GetDataTypeName (int i)
255                 {
256                         return "text"; // SQL Lite data type
257                 }
258
259                 public DateTime GetDateTime (int i)
260                 {
261                         return Convert.ToDateTime ((string) ((ArrayList) rows[current_row])[i]);
262                 }
263
264                 public decimal GetDecimal (int i)
265                 {
266                         return Convert.ToDecimal ((string) ((ArrayList) rows[current_row])[i]);
267                 }
268
269                 public double GetDouble (int i)
270                 {
271                         return Convert.ToDouble ((string) ((ArrayList) rows[current_row])[i]);
272                 }
273
274                 public Type GetFieldType (int i)
275                 {
276                         return System.Type.GetType ("System.String"); // .NET data type
277                 }
278
279                 public float GetFloat (int i)
280                 {
281                         return Convert.ToSingle ((string) ((ArrayList) rows[current_row])[i]);
282                 }
283
284                 public Guid GetGuid (int i)
285                 {
286                         throw new NotImplementedException ();
287                 }
288
289                 public short GetInt16 (int i)
290                 {
291                         return Convert.ToInt16 ((string) ((ArrayList) rows[current_row])[i]);
292                 }
293
294                 public int GetInt32 (int i)
295                 {
296                         return Convert.ToInt32 ((string) ((ArrayList) rows[current_row])[i]);
297                 }
298
299                 public long GetInt64 (int i)
300                 {
301                         return Convert.ToInt64 ((string) ((ArrayList) rows[current_row])[i]);
302                 }
303
304                 public string GetName (int i)
305                 {
306                         return (string) columns[i];
307                 }
308
309                 public int GetOrdinal (string name)
310                 {
311                         return (int) column_names[name];
312                 }
313
314                 public string GetString (int i)
315                 {
316                         return ((string) ((ArrayList) rows[current_row])[i]);
317                 }
318
319                 public object GetValue (int i)
320                 {
321                         return ((ArrayList) rows[current_row])[i];
322                 }
323
324                 public int GetValues (object[] values)
325                 {
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];
330                                 } else {
331                                         values[i] = DBNull.Value;
332                                 }
333                         }
334                         return num_to_fill;
335                 }
336
337                 public bool IsDBNull (int i)
338                 {
339                         if (((ArrayList) rows[current_row])[i] == null)
340                                 return true;
341                         return false;
342                 }
343
344                 public int FieldCount {
345                         get {
346                                 if (current_row == -1 || current_row == rows.Count)
347                                         return 0;
348                                 return columns.Count;
349                         }
350                 }
351
352                 public object this[string name] {
353                         get {
354                                 return ((ArrayList) rows[current_row])[(int) column_names[name]];
355                         }
356                 }
357                 
358                 public object this[int i] {
359                         get {
360                                 return ((ArrayList) rows[current_row])[i];
361                         }
362                 }
363         }
364 }