2 // System.Data.SqlClient.SqlDataReader.cs
5 // Rodrigo Moya (rodrigo@ximian.com)
6 // Daniel Morgan (danmorg@sc.rr.com)
7 // Tim Coleman (tim@timcoleman.com)
9 // (C) Ximian, Inc 2002
10 // (C) Daniel Morgan 2002
11 // Copyright (C) Tim Coleman, 2002
14 using Mono.Data.TdsClient.Internal;
16 using System.Collections;
17 using System.ComponentModel;
19 using System.Data.Common;
21 namespace System.Data.SqlClient {
22 public sealed class SqlDataReader : MarshalByRefObject, IEnumerable, IDataReader, IDisposable, IDataRecord
36 DataTable schemaTable;
38 ArrayList dataTypeNames;
45 internal SqlDataReader (SqlCommand command)
47 schemaTable = ConstructSchemaTable ();
49 this.command = command;
51 this.isClosed = false;
64 public int FieldCount {
65 get { return fieldCount; }
69 get { return hasRows; }
72 public bool IsClosed {
73 get { return isClosed; }
76 public object this [int i] {
77 get { return GetValue (i); }
80 public object this [string name] {
81 get { return GetValue (GetOrdinal (name)); }
84 public int RecordsAffected {
85 get { return recordsAffected; }
88 #endregion // Properties
95 command.CloseDataReader (moreResults);
98 private static DataTable ConstructSchemaTable ()
100 Type booleanType = Type.GetType ("System.Boolean");
101 Type stringType = Type.GetType ("System.String");
102 Type intType = Type.GetType ("System.Int32");
103 Type typeType = Type.GetType ("System.Type");
104 Type shortType = Type.GetType ("System.Int16");
106 DataTable schemaTable = new DataTable ("SchemaTable");
107 schemaTable.Columns.Add ("ColumnName", stringType);
108 schemaTable.Columns.Add ("ColumnOrdinal", intType);
109 schemaTable.Columns.Add ("ColumnSize", intType);
110 schemaTable.Columns.Add ("NumericPrecision", shortType);
111 schemaTable.Columns.Add ("NumericScale", shortType);
112 schemaTable.Columns.Add ("IsUnique", booleanType);
113 schemaTable.Columns.Add ("IsKey", booleanType);
114 schemaTable.Columns.Add ("BaseServerName", stringType);
115 schemaTable.Columns.Add ("BaseCatalogName", stringType);
116 schemaTable.Columns.Add ("BaseColumnName", stringType);
117 schemaTable.Columns.Add ("BaseSchemaName", stringType);
118 schemaTable.Columns.Add ("BaseTableName", stringType);
119 schemaTable.Columns.Add ("DataType", typeType);
120 schemaTable.Columns.Add ("AllowDBNull", booleanType);
121 schemaTable.Columns.Add ("ProviderType", intType);
122 schemaTable.Columns.Add ("IsAliased", booleanType);
123 schemaTable.Columns.Add ("IsExpression", booleanType);
124 schemaTable.Columns.Add ("IsIdentity", booleanType);
125 schemaTable.Columns.Add ("IsAutoIncrement", booleanType);
126 schemaTable.Columns.Add ("IsRowVersion", booleanType);
127 schemaTable.Columns.Add ("IsHidden", booleanType);
128 schemaTable.Columns.Add ("IsLong", booleanType);
129 schemaTable.Columns.Add ("IsReadOnly", booleanType);
134 public bool GetBoolean (int i)
136 object value = GetValue (i);
137 if (!(value is bool))
138 throw new InvalidCastException ();
142 public byte GetByte (int i)
144 object value = GetValue (i);
145 if (!(value is byte))
146 throw new InvalidCastException ();
151 public long GetBytes (int i, long dataIndex, byte[] buffer, int bufferIndex, int length)
153 object value = GetValue (i);
154 if (!(value is byte []))
155 throw new InvalidCastException ();
156 Array.Copy ((byte []) value, (int) dataIndex, buffer, bufferIndex, length);
157 return ((byte []) value).Length - dataIndex;
161 public char GetChar (int i)
163 throw new NotImplementedException ();
167 public long GetChars (int i, long dataIndex, char[] buffer, int bufferIndex, int length)
169 object value = GetValue (i);
170 if (!(value is char []))
171 throw new InvalidCastException ();
172 Array.Copy ((char []) value, (int) dataIndex, buffer, bufferIndex, length);
173 return ((char []) value).Length - dataIndex;
177 public IDataReader GetData (int i)
179 throw new NotImplementedException ();
182 public string GetDataTypeName (int i)
184 return (string) dataTypeNames [i];
187 public DateTime GetDateTime (int i)
189 object value = GetValue (i);
190 if (!(value is DateTime))
191 throw new InvalidCastException ();
192 return (DateTime) value;
195 public decimal GetDecimal (int i)
197 object value = GetValue (i);
198 if (!(value is decimal))
199 throw new InvalidCastException ();
200 return (decimal) value;
202 public double GetDouble (int i)
204 object value = GetValue (i);
205 if (!(value is double))
206 throw new InvalidCastException ();
207 return (double) value;
210 public Type GetFieldType (int i)
212 return (Type) schemaTable.Rows[i]["DataType"];
215 public float GetFloat (int i)
217 object value = GetValue (i);
218 if (!(value is float))
219 throw new InvalidCastException ();
220 return (float) value;
224 public Guid GetGuid (int i)
226 throw new NotImplementedException ();
229 public short GetInt16 (int i)
231 object value = GetValue (i);
232 if (!(value is short))
233 throw new InvalidCastException ();
234 return (short) value;
237 public int GetInt32 (int i)
239 object value = GetValue (i);
241 throw new InvalidCastException ();
245 public long GetInt64 (int i)
247 object value = GetValue (i);
248 if (!(value is long))
249 throw new InvalidCastException ();
253 public string GetName (int i)
255 return (string) schemaTable.Rows[i]["ColumnName"];
259 public int GetOrdinal (string name)
261 foreach (DataRow schemaRow in schemaTable.Rows)
262 if (((string) schemaRow ["ColumnName"]).Equals (name))
263 return (int) schemaRow ["ColumnOrdinal"];
264 foreach (DataRow schemaRow in schemaTable.Rows)
265 if (String.Compare (((string) schemaRow ["ColumnName"]), name, true) == 0)
266 return (int) schemaRow ["ColumnOrdinal"];
267 throw new IndexOutOfRangeException ();
270 public DataTable GetSchemaTable ()
272 if (schemaTable.Rows != null && schemaTable.Rows.Count > 0)
280 dataTypeNames = new ArrayList ();
281 dataTypes = new ArrayList ();
283 foreach (TdsSchemaInfo schema in command.Tds.Schema) {
284 DataRow row = schemaTable.NewRow ();
287 switch (schema.ColumnType) {
288 case TdsColumnType.Image :
289 dataTypeNames.Add ("image");
290 row ["ProviderType"] = (int) SqlDbType.Image;
291 row ["DataType"] = typeof (byte[]);
293 case TdsColumnType.Text :
294 dataTypes.Add (typeof (string));
295 dataTypeNames.Add ("text");
296 row ["ProviderType"] = (int) SqlDbType.Text;
297 row ["DataType"] = typeof (string);
299 case TdsColumnType.UniqueIdentifier :
300 dataTypeNames.Add ("uniqueidentifier");
301 row ["ProviderType"] = (int) SqlDbType.UniqueIdentifier;
302 row ["DataType"] = typeof (Guid);
304 case TdsColumnType.VarBinary :
305 case TdsColumnType.BigVarBinary :
306 dataTypeNames.Add ("varbinary");
307 row ["ProviderType"] = (int) SqlDbType.VarBinary;
308 row ["DataType"] = typeof (byte[]);
310 case TdsColumnType.IntN :
311 case TdsColumnType.Int4 :
312 dataTypeNames.Add ("int");
313 row ["ProviderType"] = (int) SqlDbType.Int;
314 row ["DataType"] = typeof (int);
316 case TdsColumnType.VarChar :
317 case TdsColumnType.BigVarChar :
318 dataTypeNames.Add ("varchar");
319 row ["ProviderType"] = (int) SqlDbType.VarChar;
320 row ["DataType"] = typeof (string);
322 case TdsColumnType.Binary :
323 case TdsColumnType.BigBinary :
324 dataTypeNames.Add ("binary");
325 row ["ProviderType"] = (int) SqlDbType.Binary;
326 row ["DataType"] = typeof (byte[]);
328 case TdsColumnType.Char :
329 case TdsColumnType.BigChar :
330 dataTypeNames.Add ("char");
331 row ["ProviderType"] = (int) SqlDbType.Char;
332 row ["DataType"] = typeof (string);
334 case TdsColumnType.Int1 :
335 dataTypeNames.Add ("tinyint");
336 row ["ProviderType"] = (int) SqlDbType.TinyInt;
337 row ["DataType"] = typeof (byte);
339 case TdsColumnType.Bit :
340 case TdsColumnType.BitN :
341 dataTypeNames.Add ("bit");
342 row ["ProviderType"] = (int) SqlDbType.Bit;
343 row ["DataType"] = typeof (bool);
345 case TdsColumnType.Int2 :
346 dataTypeNames.Add ("smallint");
347 row ["ProviderType"] = (int) SqlDbType.SmallInt;
348 row ["DataType"] = typeof (short);
350 case TdsColumnType.DateTime4 :
351 case TdsColumnType.DateTime :
352 case TdsColumnType.DateTimeN :
353 dataTypeNames.Add ("datetime");
354 row ["ProviderType"] = (int) SqlDbType.DateTime;
355 row ["DataType"] = typeof (DateTime);
357 case TdsColumnType.Real :
358 dataTypeNames.Add ("real");
359 row ["ProviderType"] = (int) SqlDbType.Real;
360 row ["DataType"] = typeof (float);
362 case TdsColumnType.Money :
363 case TdsColumnType.MoneyN :
364 case TdsColumnType.Money4 :
365 dataTypeNames.Add ("money");
366 row ["ProviderType"] = (int) SqlDbType.Money;
367 row ["DataType"] = typeof (decimal);
369 case TdsColumnType.Float8 :
370 case TdsColumnType.FloatN :
371 dataTypeNames.Add ("float");
372 row ["ProviderType"] = (int) SqlDbType.Float;
373 row ["DataType"] = typeof (double);
375 case TdsColumnType.NText :
376 dataTypeNames.Add ("ntext");
377 row ["ProviderType"] = (int) SqlDbType.NText;
378 row ["DataType"] = typeof (string);
380 case TdsColumnType.NVarChar :
381 dataTypeNames.Add ("nvarchar");
382 row ["ProviderType"] = (int) SqlDbType.NVarChar;
383 row ["DataType"] = typeof (string);
385 case TdsColumnType.Decimal :
386 case TdsColumnType.Numeric :
387 dataTypeNames.Add ("decimal");
388 row ["ProviderType"] = (int) SqlDbType.Decimal;
389 row ["DataType"] = typeof (decimal);
391 case TdsColumnType.NChar :
392 dataTypeNames.Add ("nchar");
393 row ["ProviderType"] = (int) SqlDbType.Char;
394 row ["DataType"] = typeof (string);
396 case TdsColumnType.SmallMoney :
397 dataTypeNames.Add ("smallmoney");
398 row ["ProviderType"] = (int) SqlDbType.SmallMoney;
399 row ["DataType"] = typeof (decimal);
402 dataTypeNames.Add ("variant");
403 row ["ProviderType"] = (int) SqlDbType.Variant;
404 row ["DataType"] = typeof (object);
408 row ["ColumnOrdinal"] = schema.ColumnOrdinal;
409 row ["ColumnSize"] = schema.ColumnSize;
410 row ["AllowDBNull"] = schema.AllowDBNull;
411 row ["IsReadOnly"] = schema.IsReadOnly;
412 row ["IsIdentity"] = schema.IsIdentity;
413 row ["IsKey"] = schema.IsKey;
415 // FIXME: Base Column Name and Column Name are not necessarily the same
416 if (schema.ColumnName == null)
417 row ["BaseColumnName"] = DBNull.Value;
419 row ["BaseColumnName"] = schema.ColumnName;
421 if (schema.ColumnName == null)
422 row ["ColumnName"] = DBNull.Value;
424 row ["ColumnName"] = schema.ColumnName;
426 if (schema.TableName == null)
427 row ["BaseTableName"] = DBNull.Value;
429 row ["BaseTableName"] = schema.TableName;
431 if (schema.NumericScale == 0)
432 row ["NumericPrecision"] = DBNull.Value;
434 row ["NumericPrecision"] = schema.NumericPrecision;
436 if (schema.NumericScale == 0)
437 row ["NumericScale"] = DBNull.Value;
439 row ["NumericScale"] = schema.NumericScale;
441 schemaTable.Rows.Add (row);
448 public string GetString (int i)
450 object value = GetValue (i);
451 if (!(value is string))
452 throw new InvalidCastException ();
453 return (string) value;
456 public object GetValue (int i)
458 return command.Tds.ColumnValues[i];
461 public int GetValues (object[] values)
463 int len = values.Length;
464 command.Tds.ColumnValues.CopyTo (0, values, 0, len);
465 return (len > FieldCount ? len : FieldCount);
469 void IDisposable.Dispose ()
471 throw new NotImplementedException ();
474 IEnumerator IEnumerable.GetEnumerator ()
476 return new DbEnumerator (this);
479 public bool IsDBNull (int i)
481 return GetValue (i) == null;
484 public bool NextResult ()
486 if ((command.CommandBehavior & CommandBehavior.SingleResult) != 0 && resultsRead > 0)
488 if (command.CommandType == CommandType.StoredProcedure && command.Tds.DoneProc)
491 schemaTable.Rows.Clear ();
493 moreResults = command.Tds.NextResult ();
494 command.Connection.CheckForErrors ();
502 if ((command.CommandBehavior & CommandBehavior.SingleRow) != 0 && rowsRead > 0)
504 if ((command.CommandBehavior & CommandBehavior.SchemaOnly) != 0)
509 bool result = command.Tds.NextRow ();
510 command.Connection.CheckForErrors ();
517 #endregion // Methods