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;
20 using System.Data.SqlTypes;
22 namespace System.Data.SqlClient {
23 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; }
68 public bool IsClosed {
69 get { return isClosed; }
72 public object this [int i] {
73 get { return GetValue (i); }
76 public object this [string name] {
77 get { return GetValue (GetOrdinal (name)); }
80 public int RecordsAffected {
81 get { return recordsAffected; }
84 #endregion // Properties
91 command.CloseDataReader (moreResults);
94 private static DataTable ConstructSchemaTable ()
96 Type booleanType = Type.GetType ("System.Boolean");
97 Type stringType = Type.GetType ("System.String");
98 Type intType = Type.GetType ("System.Int32");
99 Type typeType = Type.GetType ("System.Type");
100 Type shortType = Type.GetType ("System.Int16");
102 DataTable schemaTable = new DataTable ("SchemaTable");
103 schemaTable.Columns.Add ("ColumnName", stringType);
104 schemaTable.Columns.Add ("ColumnOrdinal", intType);
105 schemaTable.Columns.Add ("ColumnSize", intType);
106 schemaTable.Columns.Add ("NumericPrecision", shortType);
107 schemaTable.Columns.Add ("NumericScale", shortType);
108 schemaTable.Columns.Add ("IsUnique", booleanType);
109 schemaTable.Columns.Add ("IsKey", booleanType);
110 schemaTable.Columns.Add ("BaseServerName", stringType);
111 schemaTable.Columns.Add ("BaseCatalogName", stringType);
112 schemaTable.Columns.Add ("BaseColumnName", stringType);
113 schemaTable.Columns.Add ("BaseSchemaName", stringType);
114 schemaTable.Columns.Add ("BaseTableName", stringType);
115 schemaTable.Columns.Add ("DataType", typeType);
116 schemaTable.Columns.Add ("AllowDBNull", booleanType);
117 schemaTable.Columns.Add ("ProviderType", intType);
118 schemaTable.Columns.Add ("IsAliased", booleanType);
119 schemaTable.Columns.Add ("IsExpression", booleanType);
120 schemaTable.Columns.Add ("IsIdentity", booleanType);
121 schemaTable.Columns.Add ("IsAutoIncrement", booleanType);
122 schemaTable.Columns.Add ("IsRowVersion", booleanType);
123 schemaTable.Columns.Add ("IsHidden", booleanType);
124 schemaTable.Columns.Add ("IsLong", booleanType);
125 schemaTable.Columns.Add ("IsReadOnly", booleanType);
130 public bool GetBoolean (int i)
132 object value = GetValue (i);
133 if (!(value is bool))
134 throw new InvalidCastException ();
138 public byte GetByte (int i)
140 object value = GetValue (i);
141 if (!(value is byte))
142 throw new InvalidCastException ();
146 public long GetBytes (int i, long dataIndex, byte[] buffer, int bufferIndex, int length)
148 object value = GetValue (i);
149 if (!(value is byte []))
150 throw new InvalidCastException ();
151 Array.Copy ((byte []) value, (int) dataIndex, buffer, bufferIndex, length);
152 return ((byte []) value).Length - dataIndex;
156 public char GetChar (int i)
158 throw new NotImplementedException ();
161 public long GetChars (int i, long dataIndex, char[] buffer, int bufferIndex, int length)
163 object value = GetValue (i);
164 if (!(value is char []))
165 throw new InvalidCastException ();
166 Array.Copy ((char []) value, (int) dataIndex, buffer, bufferIndex, length);
167 return ((char []) value).Length - dataIndex;
171 public IDataReader GetData (int i)
173 throw new NotImplementedException ();
176 public string GetDataTypeName (int i)
178 return (string) dataTypeNames [i];
181 public DateTime GetDateTime (int i)
183 object value = GetValue (i);
184 if (!(value is DateTime))
185 throw new InvalidCastException ();
186 return (DateTime) value;
189 public decimal GetDecimal (int i)
191 object value = GetValue (i);
192 if (!(value is TdsBigDecimal))
193 throw new InvalidCastException ();
194 int[] bits = ((TdsBigDecimal) value).Data;
196 throw new OverflowException ();
197 byte scale = ((TdsBigDecimal) value).Scale;
198 bool isNegative = ((TdsBigDecimal) value).IsNegative;
199 return new Decimal (bits[0], bits[1], bits[2], isNegative, scale);
202 private TdsBigDecimal GetDecimalImpl (int i)
204 object value = GetValue (i);
205 if (!(value is TdsBigDecimal))
206 throw new InvalidCastException ();
207 return (TdsBigDecimal) value;
210 public double GetDouble (int i)
212 object value = GetValue (i);
213 if (!(value is double))
214 throw new InvalidCastException ();
215 return (double) value;
218 public Type GetFieldType (int i)
220 return (Type) schemaTable.Rows[i]["DataType"];
223 public float GetFloat (int i)
225 object value = GetValue (i);
226 if (!(value is float))
227 throw new InvalidCastException ();
228 return (float) value;
232 public Guid GetGuid (int i)
234 throw new NotImplementedException ();
237 public short GetInt16 (int i)
239 object value = GetValue (i);
240 if (!(value is short))
241 throw new InvalidCastException ();
242 return (short) value;
245 public int GetInt32 (int i)
247 object value = GetValue (i);
249 throw new InvalidCastException ();
253 public long GetInt64 (int i)
255 object value = GetValue (i);
256 if (!(value is long))
257 throw new InvalidCastException ();
261 public string GetName (int i)
263 return (string) schemaTable.Rows[i]["ColumnName"];
267 public int GetOrdinal (string name)
269 foreach (DataRow schemaRow in schemaTable.Rows)
270 if (((string) schemaRow ["ColumnName"]).Equals (name))
271 return (int) schemaRow ["ColumnOrdinal"];
272 foreach (DataRow schemaRow in schemaTable.Rows)
273 if (String.Compare (((string) schemaRow ["ColumnName"]), name, true) == 0)
274 return (int) schemaRow ["ColumnOrdinal"];
275 throw new IndexOutOfRangeException ();
278 public DataTable GetSchemaTable ()
280 if (schemaTable.Rows != null && schemaTable.Rows.Count > 0)
288 dataTypeNames = new ArrayList ();
289 dataTypes = new ArrayList ();
291 foreach (TdsSchemaInfo schema in command.Tds.Schema) {
292 DataRow row = schemaTable.NewRow ();
295 switch (schema.ColumnType) {
296 case TdsColumnType.Image :
297 dataTypeNames.Add ("image");
298 row ["ProviderType"] = (int) SqlDbType.Image;
299 row ["DataType"] = typeof (byte[]);
301 case TdsColumnType.Text :
302 dataTypes.Add (typeof (string));
303 dataTypeNames.Add ("text");
304 row ["ProviderType"] = (int) SqlDbType.Text;
305 row ["DataType"] = typeof (string);
307 case TdsColumnType.UniqueIdentifier :
308 dataTypeNames.Add ("uniqueidentifier");
309 row ["ProviderType"] = (int) SqlDbType.UniqueIdentifier;
310 row ["DataType"] = typeof (Guid);
312 case TdsColumnType.VarBinary :
313 case TdsColumnType.BigVarBinary :
314 dataTypeNames.Add ("varbinary");
315 row ["ProviderType"] = (int) SqlDbType.VarBinary;
316 row ["DataType"] = typeof (byte[]);
318 case TdsColumnType.IntN :
319 case TdsColumnType.Int4 :
320 dataTypeNames.Add ("int");
321 row ["ProviderType"] = (int) SqlDbType.Int;
322 row ["DataType"] = typeof (int);
324 case TdsColumnType.VarChar :
325 case TdsColumnType.BigVarChar :
326 dataTypeNames.Add ("varchar");
327 row ["ProviderType"] = (int) SqlDbType.VarChar;
328 row ["DataType"] = typeof (string);
330 case TdsColumnType.Binary :
331 case TdsColumnType.BigBinary :
332 dataTypeNames.Add ("binary");
333 row ["ProviderType"] = (int) SqlDbType.Binary;
334 row ["DataType"] = typeof (byte[]);
336 case TdsColumnType.Char :
337 case TdsColumnType.BigChar :
338 dataTypeNames.Add ("char");
339 row ["ProviderType"] = (int) SqlDbType.Char;
340 row ["DataType"] = typeof (string);
342 case TdsColumnType.Int1 :
343 dataTypeNames.Add ("tinyint");
344 row ["ProviderType"] = (int) SqlDbType.TinyInt;
345 row ["DataType"] = typeof (byte);
347 case TdsColumnType.Bit :
348 case TdsColumnType.BitN :
349 dataTypeNames.Add ("bit");
350 row ["ProviderType"] = (int) SqlDbType.Bit;
351 row ["DataType"] = typeof (bool);
353 case TdsColumnType.Int2 :
354 dataTypeNames.Add ("smallint");
355 row ["ProviderType"] = (int) SqlDbType.SmallInt;
356 row ["DataType"] = typeof (short);
358 case TdsColumnType.DateTime4 :
359 case TdsColumnType.DateTime :
360 case TdsColumnType.DateTimeN :
361 dataTypeNames.Add ("datetime");
362 row ["ProviderType"] = (int) SqlDbType.DateTime;
363 row ["DataType"] = typeof (DateTime);
365 case TdsColumnType.Real :
366 dataTypeNames.Add ("real");
367 row ["ProviderType"] = (int) SqlDbType.Real;
368 row ["DataType"] = typeof (float);
370 case TdsColumnType.Money :
371 case TdsColumnType.MoneyN :
372 case TdsColumnType.Money4 :
373 dataTypeNames.Add ("money");
374 row ["ProviderType"] = (int) SqlDbType.Money;
375 row ["DataType"] = typeof (decimal);
377 case TdsColumnType.Float8 :
378 case TdsColumnType.FloatN :
379 dataTypeNames.Add ("float");
380 row ["ProviderType"] = (int) SqlDbType.Float;
381 row ["DataType"] = typeof (double);
383 case TdsColumnType.NText :
384 dataTypeNames.Add ("ntext");
385 row ["ProviderType"] = (int) SqlDbType.NText;
386 row ["DataType"] = typeof (string);
388 case TdsColumnType.NVarChar :
389 dataTypeNames.Add ("nvarchar");
390 row ["ProviderType"] = (int) SqlDbType.NVarChar;
391 row ["DataType"] = typeof (string);
393 case TdsColumnType.Decimal :
394 case TdsColumnType.Numeric :
395 dataTypeNames.Add ("decimal");
396 row ["ProviderType"] = (int) SqlDbType.Decimal;
397 row ["DataType"] = typeof (decimal);
399 case TdsColumnType.NChar :
400 dataTypeNames.Add ("nchar");
401 row ["ProviderType"] = (int) SqlDbType.Char;
402 row ["DataType"] = typeof (string);
404 case TdsColumnType.SmallMoney :
405 dataTypeNames.Add ("smallmoney");
406 row ["ProviderType"] = (int) SqlDbType.SmallMoney;
407 row ["DataType"] = typeof (decimal);
410 dataTypeNames.Add ("variant");
411 row ["ProviderType"] = (int) SqlDbType.Variant;
412 row ["DataType"] = typeof (object);
416 // set default values
417 row ["AllowDBNull"] = true;
418 row ["BaseCatalogName"] = DBNull.Value;
419 row ["BaseColumnName"] = DBNull.Value;
420 row ["BaseSchemaName"] = DBNull.Value;
421 row ["BaseTableName"] = DBNull.Value;
422 row ["ColumnName"] = DBNull.Value;
423 row ["IsUnique"] = false;
424 row ["NumericPrecision"] = DBNull.Value;
425 row ["NumericScale"] = DBNull.Value;
427 // load schema values
428 row ["ColumnOrdinal"] = schema.ColumnOrdinal;
429 row ["ColumnSize"] = schema.ColumnSize;
430 row ["AllowDBNull"] = schema.AllowDBNull;
431 row ["IsExpression"] = schema.IsExpression;
432 row ["IsIdentity"] = schema.IsIdentity;
433 row ["IsReadOnly"] = schema.IsReadOnly;
434 row ["IsKey"] = schema.IsKey;
436 if (schema.BaseColumnName != null)
437 row ["BaseColumnName"] = schema.BaseColumnName;
439 if (schema.ColumnName != null)
440 row ["ColumnName"] = schema.ColumnName;
442 if (schema.BaseTableName != null)
443 row ["BaseTableName"] = schema.BaseTableName;
445 if (schema.NumericScale != 0)
446 row ["NumericPrecision"] = schema.NumericPrecision;
448 if (schema.NumericScale == 0)
449 row ["NumericScale"] = schema.NumericScale;
451 schemaTable.Rows.Add (row);
458 public SqlBinary GetSqlBinary (int i)
460 throw new NotImplementedException ();
463 public SqlBoolean GetSqlBoolean (int i)
465 object value = GetValue (i);
467 return SqlBoolean.Null;
468 if (!(value is bool))
469 throw new InvalidCastException ();
473 public SqlByte GetSqlByte (int i)
475 object value = GetValue (i);
478 if (!(value is byte))
479 throw new InvalidCastException ();
483 public SqlDateTime GetSqlDateTime (int i)
485 object value = GetValue (i);
487 return SqlDateTime.Null;
488 if (!(value is DateTime))
489 throw new InvalidCastException ();
490 return (DateTime) value;
493 public SqlDecimal GetSqlDecimal (int i)
495 object value = GetValue (i);
497 return SqlDecimal.Null;
498 if (!(value is TdsBigDecimal))
499 throw new InvalidCastException ();
500 return SqlDecimal.FromTdsBigDecimal ((TdsBigDecimal) value);
503 public SqlDouble GetSqlDouble (int i)
505 object value = GetValue (i);
507 return SqlDouble.Null;
508 if (!(value is double))
509 throw new InvalidCastException ();
510 return (double) value;
513 public SqlGuid GetSqlGuid (int i)
515 object value = GetValue (i);
518 if (!(value is Guid))
519 throw new InvalidCastException ();
523 public SqlInt16 GetSqlInt16 (int i)
525 object value = GetValue (i);
527 return SqlInt16.Null;
528 if (!(value is short))
529 throw new InvalidCastException ();
530 return (short) value;
533 public SqlInt32 GetSqlInt32 (int i)
535 object value = GetValue (i);
537 return SqlInt32.Null;
539 throw new InvalidCastException ();
543 public SqlInt64 GetSqlInt64 (int i)
545 object value = GetValue (i);
547 return SqlInt64.Null;
548 if (!(value is long))
549 throw new InvalidCastException ();
553 public SqlMoney GetSqlMoney (int i)
555 object value = GetValue (i);
557 return SqlMoney.Null;
558 if (!(value is TdsBigDecimal))
559 throw new InvalidCastException ();
560 return (SqlMoney) (SqlDecimal) value;
563 public SqlSingle GetSqlSingle (int i)
565 object value = GetValue (i);
567 return SqlSingle.Null;
568 if (!(value is float))
569 throw new InvalidCastException ();
570 return (float) value;
573 public SqlString GetSqlString (int i)
575 object value = GetValue (i);
577 return SqlString.Null;
578 if (!(value is string))
579 throw new InvalidCastException ();
580 return (string) value;
584 public object GetSqlValue (int i)
586 object value = GetValue (i);
589 throw new NotImplementedException ();
593 public int GetSqlValues (object[] values)
595 throw new NotImplementedException ();
598 public string GetString (int i)
600 object value = GetValue (i);
601 if (!(value is string))
602 throw new InvalidCastException ();
603 return (string) value;
606 public object GetValue (int i)
608 return command.Tds.ColumnValues[i];
611 public int GetValues (object[] values)
613 int len = values.Length;
614 command.Tds.ColumnValues.CopyTo (0, values, 0, len);
615 return (len > FieldCount ? len : FieldCount);
619 void IDisposable.Dispose ()
621 throw new NotImplementedException ();
624 IEnumerator IEnumerable.GetEnumerator ()
626 return new DbEnumerator (this);
629 public bool IsDBNull (int i)
631 return GetValue (i) == null;
634 public bool NextResult ()
636 if ((command.CommandBehavior & CommandBehavior.SingleResult) != 0 && resultsRead > 0)
638 if (command.Tds.DoneProc)
641 schemaTable.Rows.Clear ();
643 moreResults = command.Tds.NextResult ();
651 if ((command.CommandBehavior & CommandBehavior.SingleRow) != 0 && rowsRead > 0)
653 if ((command.CommandBehavior & CommandBehavior.SchemaOnly) != 0)
658 bool result = command.Tds.NextRow ();
665 #endregion // Methods