New test.
[mono.git] / mcs / class / Mono.Data.SybaseClient / Mono.Data.SybaseClient / SybaseDataReader.cs
1 //
2 // Mono.Data.SybaseClient.SybaseDataReader.cs
3 //
4 // Author:
5 //   Rodrigo Moya (rodrigo@ximian.com)
6 //   Daniel Morgan (danmorg@sc.rr.com)
7 //   Tim Coleman (tim@timcoleman.com)
8 //
9 // (C) Ximian, Inc 2002
10 // (C) Daniel Morgan 2002
11 // Copyright (C) Tim Coleman, 2002
12 //
13
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //
34
35 using Mono.Data.SybaseTypes;
36 using Mono.Data.Tds.Protocol;
37 using System;
38 using System.Collections;
39 using System.ComponentModel;
40 using System.Data;
41 using System.Data.Common;
42
43 namespace Mono.Data.SybaseClient {
44         public sealed class SybaseDataReader : MarshalByRefObject, IEnumerable, IDataReader, IDisposable, IDataRecord
45         {
46                 #region Fields
47
48                 SybaseCommand command;
49                 ArrayList dataTypeNames;
50                 bool disposed = false;
51                 int fieldCount;
52                 bool isClosed;
53                 bool isSelect;
54                 bool moreResults;
55                 int resultsRead;
56                 int rowsRead;
57                 DataTable schemaTable;
58
59                 #endregion // Fields
60
61                 #region Constructors
62
63                 internal SybaseDataReader (SybaseCommand command)
64                 {
65                         this.command = command;
66                         schemaTable = ConstructSchemaTable ();
67                         resultsRead = 0;
68                         fieldCount = 0;
69                         isClosed = false;
70                         isSelect = (command.CommandText.Trim ().ToUpper ().StartsWith ("SELECT"));
71                         command.Tds.RecordsAffected = 0;
72                         NextResult ();
73                 }
74
75                 #endregion // Constructors
76
77                 #region Properties
78
79                 public int Depth {
80                         get { return 0; }
81                 }
82
83                 public int FieldCount {
84                         get { return fieldCount; }
85                 }
86
87                 public bool IsClosed {
88                         get { return isClosed; }
89                 }
90
91                 public object this [int i] {
92                         get { return GetValue (i); }
93                 }
94
95                 public object this [string name] {
96                         get { return GetValue (GetOrdinal (name)); }
97                 }
98         
99                 public int RecordsAffected {
100                         get { 
101                                 if (isSelect) 
102                                         return -1;
103                                 else
104                                         return command.Tds.RecordsAffected; 
105                         }
106                 }
107
108                 #endregion // Properties
109
110                 #region Methods
111
112                 public void Close ()
113                 {
114                         isClosed = true;
115                         command.CloseDataReader (moreResults);
116                 }
117
118                 private static DataTable ConstructSchemaTable ()
119                 {
120                         Type booleanType = Type.GetType ("System.Boolean");
121                         Type stringType = Type.GetType ("System.String");
122                         Type intType = Type.GetType ("System.Int32");
123                         Type typeType = Type.GetType ("System.Type");
124                         Type shortType = Type.GetType ("System.Int16");
125
126                         DataTable schemaTable = new DataTable ("SchemaTable");
127                         schemaTable.Columns.Add ("ColumnName", stringType);
128                         schemaTable.Columns.Add ("ColumnOrdinal", intType);
129                         schemaTable.Columns.Add ("ColumnSize", intType);
130                         schemaTable.Columns.Add ("NumericPrecision", shortType);
131                         schemaTable.Columns.Add ("NumericScale", shortType);
132                         schemaTable.Columns.Add ("IsUnique", booleanType);
133                         schemaTable.Columns.Add ("IsKey", booleanType);
134                         schemaTable.Columns.Add ("BaseServerName", stringType);
135                         schemaTable.Columns.Add ("BaseCatalogName", stringType);
136                         schemaTable.Columns.Add ("BaseColumnName", stringType);
137                         schemaTable.Columns.Add ("BaseSchemaName", stringType);
138                         schemaTable.Columns.Add ("BaseTableName", stringType);
139                         schemaTable.Columns.Add ("DataType", typeType);
140                         schemaTable.Columns.Add ("AllowDBNull", booleanType);
141                         schemaTable.Columns.Add ("ProviderType", intType);
142                         schemaTable.Columns.Add ("IsAliased", booleanType);
143                         schemaTable.Columns.Add ("IsExpression", booleanType);
144                         schemaTable.Columns.Add ("IsIdentity", booleanType);
145                         schemaTable.Columns.Add ("IsAutoIncrement", booleanType);
146                         schemaTable.Columns.Add ("IsRowVersion", booleanType);
147                         schemaTable.Columns.Add ("IsHidden", booleanType);
148                         schemaTable.Columns.Add ("IsLong", booleanType);
149                         schemaTable.Columns.Add ("IsReadOnly", booleanType);
150
151                         return schemaTable;
152                 }
153
154                 private void Dispose (bool disposing) 
155                 {
156                         if (!disposed) {
157                                 if (disposing) {
158                                         schemaTable.Dispose ();
159                                         Close ();
160                                 }
161                                 disposed = true;
162                         }
163                 }
164
165                 public bool GetBoolean (int i)
166                 {
167                         object value = GetValue (i);
168                         if (!(value is bool)) {
169                                 if (value is DBNull) throw new SybaseNullValueException ();
170                                 throw new InvalidCastException ();
171                         }
172                         return (bool) value;
173                 }
174
175                 public byte GetByte (int i)
176                 {
177                         object value = GetValue (i);
178                         if (!(value is byte)) {
179                                 if (value is DBNull) throw new SybaseNullValueException ();
180                                 throw new InvalidCastException ();
181                         }
182                         return (byte) value;
183                 }
184
185                 public long GetBytes (int i, long dataIndex, byte[] buffer, int bufferIndex, int length)
186                 {
187                         object value = GetValue (i);
188                         if (!(value is byte [])) {
189                                 if (value is DBNull) throw new SybaseNullValueException ();
190                                 throw new InvalidCastException ();
191                         }
192                         Array.Copy ((byte []) value, (int) dataIndex, buffer, bufferIndex, length);
193                         return ((byte []) value).Length - dataIndex;
194                 }
195
196                 public char GetChar (int i)
197                 {
198                         object value = GetValue (i);
199                         if (!(value is char)) {
200                                 if (value is DBNull) throw new SybaseNullValueException ();
201                                 throw new InvalidCastException ();
202                         }
203                         return (char) value;
204                 }
205
206                 public long GetChars (int i, long dataIndex, char[] buffer, int bufferIndex, int length)
207                 {
208                         object value = GetValue (i);
209                         if (!(value is char[])) {
210                                 if (value is DBNull) throw new SybaseNullValueException ();
211                                 throw new InvalidCastException ();
212                         }
213                         Array.Copy ((char []) value, (int) dataIndex, buffer, bufferIndex, length);
214                         return ((char []) value).Length - dataIndex;
215                 }
216
217                 [MonoTODO ("Implement GetData")]
218                 public IDataReader GetData (int i)
219                 {
220                         throw new NotImplementedException ();
221                 }
222
223                 public string GetDataTypeName (int i)
224                 {
225                         return (string) dataTypeNames [i];
226                 }
227
228                 public DateTime GetDateTime (int i)
229                 {
230                         object value = GetValue (i);
231                         if (!(value is DateTime)) {
232                                 if (value is DBNull) throw new SybaseNullValueException ();
233                                 throw new InvalidCastException ();
234                         }
235                         return (DateTime) value;
236                 }
237
238                 public decimal GetDecimal (int i)
239                 {
240                         object value = GetValue (i);
241                         if (!(value is decimal)) {
242                                 if (value is DBNull) throw new SybaseNullValueException ();
243                                 throw new InvalidCastException ();
244                         }
245                         return (decimal) value;
246                 }
247
248                 public double GetDouble (int i)
249                 {
250                         object value = GetValue (i);
251                         if (!(value is double)) {
252                                 if (value is DBNull) throw new SybaseNullValueException ();
253                                 throw new InvalidCastException ();
254                         }
255                         return (double) value;
256                 }
257
258                 public Type GetFieldType (int i)
259                 {
260                         return (Type) schemaTable.Rows[i]["DataType"];
261                 }
262
263                 public float GetFloat (int i)
264                 {
265                         object value = GetValue (i);
266                         if (!(value is float)) {
267                                 if (value is DBNull) throw new SybaseNullValueException ();
268                                 throw new InvalidCastException ();
269                         }
270                         return (float) value;
271                 }
272
273                 public Guid GetGuid (int i)
274                 {
275                         object value = GetValue (i);
276                         if (!(value is Guid)) {
277                                 if (value is DBNull) throw new SybaseNullValueException ();
278                                 throw new InvalidCastException ();
279                         }
280                         return (Guid) value;
281                 }
282
283                 public short GetInt16 (int i)
284                 {
285                         object value = GetValue (i);
286                         if (!(value is short)) {
287                                 if (value is DBNull) throw new SybaseNullValueException ();
288                                 throw new InvalidCastException ();
289                         }
290                         return (short) value;
291                 }
292
293                 public int GetInt32 (int i)
294                 {
295                         object value = GetValue (i);
296                         if (!(value is int)) {
297                                 if (value is DBNull) throw new SybaseNullValueException ();
298                                 throw new InvalidCastException ();
299                         }
300                         return (int) value;
301                 }
302
303                 public long GetInt64 (int i)
304                 {
305                         object value = GetValue (i);
306                         if (!(value is long)) {
307                                 if (value is DBNull) throw new SybaseNullValueException ();
308                                 throw new InvalidCastException ();
309                         }
310                         return (long) value;
311                 }
312
313                 public string GetName (int i)
314                 {
315                         return (string) schemaTable.Rows[i]["ColumnName"];
316                 }
317
318                 public int GetOrdinal (string name)
319                 {
320                         foreach (DataRow schemaRow in schemaTable.Rows)
321                                 if (((string) schemaRow ["ColumnName"]).Equals (name))
322                                         return (int) schemaRow ["ColumnOrdinal"];
323                         foreach (DataRow schemaRow in schemaTable.Rows)
324                                 if (String.Compare (((string) schemaRow ["ColumnName"]), name, true) == 0)
325                                         return (int) schemaRow ["ColumnOrdinal"];
326                         throw new IndexOutOfRangeException ();
327                 }
328
329                 public DataTable GetSchemaTable ()
330                 {
331                         if (schemaTable.Rows != null && schemaTable.Rows.Count > 0)
332                                 return schemaTable;
333
334                         if (!moreResults)
335                                 return null;
336
337                         fieldCount = 0;
338
339                         dataTypeNames = new ArrayList ();
340
341                         foreach (TdsDataColumn schema in command.Tds.Columns) {
342                                 DataRow row = schemaTable.NewRow ();
343
344                                 row ["ColumnName"]              = GetSchemaValue (schema, "ColumnName");
345                                 row ["ColumnSize"]              = GetSchemaValue (schema, "ColumnSize"); 
346                                 row ["ColumnOrdinal"]           = GetSchemaValue (schema, "ColumnOrdinal");
347                                 row ["NumericPrecision"]        = GetSchemaValue (schema, "NumericPrecision");
348                                 row ["NumericScale"]            = GetSchemaValue (schema, "NumericScale");
349                                 row ["IsUnique"]                = GetSchemaValue (schema, "IsUnique");
350                                 row ["IsKey"]                   = GetSchemaValue (schema, "IsKey");
351                                 row ["BaseServerName"]          = GetSchemaValue (schema, "BaseServerName");
352                                 row ["BaseCatalogName"]         = GetSchemaValue (schema, "BaseCatalogName");
353                                 row ["BaseColumnName"]          = GetSchemaValue (schema, "BaseColumnName");
354                                 row ["BaseSchemaName"]          = GetSchemaValue (schema, "BaseSchemaName");
355                                 row ["BaseTableName"]           = GetSchemaValue (schema, "BaseTableName");
356                                 row ["AllowDBNull"]             = GetSchemaValue (schema, "AllowDBNull");
357                                 row ["IsAliased"]               = GetSchemaValue (schema, "IsAliased");
358                                 row ["IsExpression"]            = GetSchemaValue (schema, "IsExpression");
359                                 row ["IsIdentity"]              = GetSchemaValue (schema, "IsIdentity");
360                                 row ["IsAutoIncrement"]         = GetSchemaValue (schema, "IsAutoIncrement");
361                                 row ["IsRowVersion"]            = GetSchemaValue (schema, "IsRowVersion");
362                                 row ["IsHidden"]                = GetSchemaValue (schema, "IsHidden");
363                                 row ["IsReadOnly"]              = GetSchemaValue (schema, "IsReadOnly");
364
365                                 // We don't always get the base column name.
366                                 if (row ["BaseColumnName"] == DBNull.Value)
367                                         row ["BaseColumnName"] = row ["ColumnName"];
368
369                                 switch ((TdsColumnType) schema ["ColumnType"]) {
370                                         case TdsColumnType.Image :
371                                                 dataTypeNames.Add ("image");
372                                                 row ["ProviderType"] = (int) SybaseType.Image;
373                                                 row ["DataType"] = typeof (byte[]);
374                                                 row ["IsLong"] = true;
375                                                 break;
376                                         case TdsColumnType.Text :
377                                                 dataTypeNames.Add ("text");
378                                                 row ["ProviderType"] = (int) SybaseType.Text;
379                                                 row ["DataType"] = typeof (string);
380                                                 row ["IsLong"] = true;
381                                                 break;
382                                         case TdsColumnType.UniqueIdentifier :
383                                                 dataTypeNames.Add ("uniqueidentifier");
384                                                 row ["ProviderType"] = (int) SybaseType.UniqueIdentifier;
385                                                 row ["DataType"] = typeof (Guid);
386                                                 row ["IsLong"] = false;
387                                                 break;
388                                         case TdsColumnType.VarBinary :
389                                         case TdsColumnType.BigVarBinary :
390                                                 dataTypeNames.Add ("varbinary");
391                                                 row ["ProviderType"] = (int) SybaseType.VarBinary;
392                                                 row ["DataType"] = typeof (byte[]);
393                                                 row ["IsLong"] = true;
394                                                 break;
395                                         case TdsColumnType.IntN :
396                                         case TdsColumnType.Int4 :
397                                                 dataTypeNames.Add ("int");
398                                                 row ["ProviderType"] = (int) SybaseType.Int;
399                                                 row ["DataType"] = typeof (int);
400                                                 row ["IsLong"] = false;
401                                                 break;
402                                         case TdsColumnType.VarChar :
403                                         case TdsColumnType.BigVarChar :
404                                                 dataTypeNames.Add ("varchar");
405                                                 row ["ProviderType"] = (int) SybaseType.VarChar;
406                                                 row ["DataType"] = typeof (string);
407                                                 row ["IsLong"] = false;
408                                                 break;
409                                         case TdsColumnType.Binary :
410                                         case TdsColumnType.BigBinary :
411                                                 dataTypeNames.Add ("binary");
412                                                 row ["ProviderType"] = (int) SybaseType.Binary;
413                                                 row ["DataType"] = typeof (byte[]);
414                                                 row ["IsLong"] = true;
415                                                 break;
416                                         case TdsColumnType.Char :
417                                         case TdsColumnType.BigChar :
418                                                 dataTypeNames.Add ("char");
419                                                 row ["ProviderType"] = (int) SybaseType.Char;
420                                                 row ["DataType"] = typeof (string);
421                                                 row ["IsLong"] = false;
422                                                 break;
423                                         case TdsColumnType.Int1 :
424                                                 dataTypeNames.Add ("tinyint");
425                                                 row ["ProviderType"] = (int) SybaseType.TinyInt;
426                                                 row ["DataType"] = typeof (byte);
427                                                 row ["IsLong"] = false;
428                                                 break;
429                                         case TdsColumnType.Bit :
430                                         case TdsColumnType.BitN :
431                                                 dataTypeNames.Add ("bit");
432                                                 row ["ProviderType"] = (int) SybaseType.Bit;
433                                                 row ["DataType"] = typeof (bool);
434                                                 row ["IsLong"] = false;
435                                                 break;
436                                         case TdsColumnType.Int2 :
437                                                 dataTypeNames.Add ("smallint");
438                                                 row ["ProviderType"] = (int) SybaseType.SmallInt;
439                                                 row ["DataType"] = typeof (short);
440                                                 row ["IsLong"] = false;
441                                                 break;
442                                         case TdsColumnType.DateTime4 :
443                                         case TdsColumnType.DateTime :
444                                         case TdsColumnType.DateTimeN :
445                                                 dataTypeNames.Add ("datetime");
446                                                 row ["ProviderType"] = (int) SybaseType.DateTime;
447                                                 row ["DataType"] = typeof (DateTime);
448                                                 row ["IsLong"] = false;
449                                                 break;
450                                         case TdsColumnType.Real :
451                                                 dataTypeNames.Add ("real");
452                                                 row ["ProviderType"] = (int) SybaseType.Real;
453                                                 row ["DataType"] = typeof (float);
454                                                 break;
455                                         case TdsColumnType.Money :
456                                         case TdsColumnType.MoneyN :
457                                         case TdsColumnType.Money4 :
458                                                 dataTypeNames.Add ("money");
459                                                 row ["ProviderType"] = (int) SybaseType.Money;
460                                                 row ["DataType"] = typeof (decimal);
461                                                 row ["IsLong"] = false;
462                                                 break;
463                                         case TdsColumnType.Float8 :
464                                         case TdsColumnType.FloatN :
465                                                 dataTypeNames.Add ("float");
466                                                 row ["ProviderType"] = (int) SybaseType.Float;
467                                                 row ["DataType"] = typeof (double);
468                                                 row ["IsLong"] = false;
469                                                 break;
470                                         case TdsColumnType.NText :
471                                                 dataTypeNames.Add ("ntext");
472                                                 row ["ProviderType"] = (int) SybaseType.NText;
473                                                 row ["DataType"] = typeof (string);
474                                                 row ["IsLong"] = true;
475                                                 break;
476                                         case TdsColumnType.NVarChar :
477                                                 dataTypeNames.Add ("nvarchar");
478                                                 row ["ProviderType"] = (int) SybaseType.NVarChar;
479                                                 row ["DataType"] = typeof (string);
480                                                 row ["IsLong"] = false;
481                                                 break;
482                                         case TdsColumnType.Decimal :
483                                         case TdsColumnType.Numeric :
484                                                 dataTypeNames.Add ("decimal");
485                                                 row ["ProviderType"] = (int) SybaseType.Decimal;
486                                                 row ["DataType"] = typeof (decimal);
487                                                 row ["IsLong"] = false;
488                                                 break;
489                                         case TdsColumnType.NChar :
490                                                 dataTypeNames.Add ("nchar");
491                                                 row ["ProviderType"] = (int) SybaseType.NChar;
492                                                 row ["DataType"] = typeof (string);
493                                                 row ["IsLong"] = false;
494                                                 break;
495                                         case TdsColumnType.SmallMoney :
496                                                 dataTypeNames.Add ("smallmoney");
497                                                 row ["ProviderType"] = (int) SybaseType.SmallMoney;
498                                                 row ["DataType"] = typeof (decimal);
499                                                 row ["IsLong"] = false;
500                                                 break;
501                                         default :
502                                                 dataTypeNames.Add ("variant");
503                                                 row ["ProviderType"] = (int) SybaseType.Variant;
504                                                 row ["DataType"] = typeof (object);
505                                                 row ["IsLong"] = false;
506                                                 break;
507                                 }
508
509                                 schemaTable.Rows.Add (row);
510
511                                 fieldCount += 1;
512                         }
513                         return schemaTable;
514                 }               
515
516                 private static object GetSchemaValue (TdsDataColumn schema, object key)
517                 {
518                         if (schema.ContainsKey (key) && schema [key] != null)
519                                 return schema [key];
520                         return DBNull.Value;
521                 }
522
523                 public SybaseBinary GetSybaseBinary (int i)
524                 {
525                         throw new NotImplementedException ();
526                 }
527
528                 public SybaseBoolean GetSybaseBoolean (int i) 
529                 {
530                         object value = GetSybaseValue (i);
531                         if (!(value is SybaseBoolean))
532                                 throw new InvalidCastException ();
533                         return (SybaseBoolean) value;
534                 }
535
536                 public SybaseByte GetSybaseByte (int i)
537                 {
538                         object value = GetSybaseValue (i);
539                         if (!(value is SybaseByte))
540                                 throw new InvalidCastException ();
541                         return (SybaseByte) value;
542                 }
543
544                 public SybaseDateTime GetSybaseDateTime (int i)
545                 {
546                         object value = GetSybaseValue (i);
547                         if (!(value is SybaseDateTime))
548                                 throw new InvalidCastException ();
549                         return (SybaseDateTime) value;
550                 }
551
552                 public SybaseDecimal GetSybaseDecimal (int i)
553                 {
554                         object value = GetSybaseValue (i);
555                         if (!(value is SybaseDecimal))
556                                 throw new InvalidCastException ();
557                         return (SybaseDecimal) value;
558                 }
559
560                 public SybaseDouble GetSybaseDouble (int i)
561                 {
562                         object value = GetSybaseValue (i);
563                         if (!(value is SybaseDouble))
564                                 throw new InvalidCastException ();
565                         return (SybaseDouble) value;
566                 }
567
568                 public SybaseGuid GetSybaseGuid (int i)
569                 {
570                         object value = GetSybaseValue (i);
571                         if (!(value is SybaseGuid))
572                                 throw new InvalidCastException ();
573                         return (SybaseGuid) value;
574                 }
575
576                 public SybaseInt16 GetSybaseInt16 (int i)
577                 {
578                         object value = GetSybaseValue (i);
579                         if (!(value is SybaseInt16))
580                                 throw new InvalidCastException ();
581                         return (SybaseInt16) value;
582                 }
583
584                 public SybaseInt32 GetSybaseInt32 (int i)
585                 {
586                         object value = GetSybaseValue (i);
587                         if (!(value is SybaseInt32))
588                                 throw new InvalidCastException ();
589                         return (SybaseInt32) value;
590                 }
591
592                 public SybaseInt64 GetSybaseInt64 (int i)
593                 {
594                         object value = GetSybaseValue (i);
595                         if (!(value is SybaseInt64))
596                                 throw new InvalidCastException ();
597                         return (SybaseInt64) value;
598                 }
599
600                 public SybaseMoney GetSybaseMoney (int i)
601                 {
602                         object value = GetSybaseValue (i);
603                         if (!(value is SybaseMoney))
604                                 throw new InvalidCastException ();
605                         return (SybaseMoney) value;
606                 }
607
608                 public SybaseSingle GetSybaseSingle (int i)
609                 {
610                         object value = GetSybaseValue (i);
611                         if (!(value is SybaseSingle))
612                                 throw new InvalidCastException ();
613                         return (SybaseSingle) value;
614                 }
615
616                 public SybaseString GetSybaseString (int i)
617                 {
618                         object value = GetSybaseValue (i);
619                         if (!(value is SybaseString))
620                                 throw new InvalidCastException ();
621                         return (SybaseString) value;
622                 }
623
624                 [MonoTODO ("Implement TdsBigDecimal conversion.  SybaseType.Real fails tests?")]
625                 public object GetSybaseValue (int i)
626                 {
627                         SybaseType type = (SybaseType) (schemaTable.Rows [i]["ProviderType"]);
628                         object value = GetValue (i);
629
630                         switch (type) {
631                         case SybaseType.BigInt:
632                                 if (value == DBNull.Value)
633                                         return SybaseInt64.Null;
634                                 return (SybaseInt64) ((long) value);
635                         case SybaseType.Binary:
636                         case SybaseType.Image:
637                         case SybaseType.VarBinary:
638                         case SybaseType.Timestamp:
639                                 if (value == DBNull.Value)
640                                         return SybaseBinary.Null;
641                                 return (SybaseBinary) ((byte[]) value);
642                         case SybaseType.Bit:
643                                 if (value == DBNull.Value)
644                                         return SybaseBoolean.Null;
645                                 return (SybaseBoolean) ((bool) value);
646                         case SybaseType.Char:
647                         case SybaseType.NChar:
648                         case SybaseType.NText:
649                         case SybaseType.NVarChar:
650                         case SybaseType.Text:
651                         case SybaseType.VarChar:
652                                 if (value == DBNull.Value)
653                                         return SybaseString.Null;
654                                 return (SybaseString) ((string) value);
655                         case SybaseType.DateTime:
656                         case SybaseType.SmallDateTime:
657                                 if (value == DBNull.Value)
658                                         return SybaseDateTime.Null;
659                                 return (SybaseDateTime) ((DateTime) value);
660                         case SybaseType.Decimal:
661                                 if (value == DBNull.Value)
662                                         return SybaseDecimal.Null;
663                                 if (value is TdsBigDecimal)
664                                         return SybaseDecimal.FromTdsBigDecimal ((TdsBigDecimal) value);
665                                 return (SybaseDecimal) ((decimal) value);
666                         case SybaseType.Float:
667                                 if (value == DBNull.Value)
668                                         return SybaseDouble.Null;
669                                 return (SybaseDouble) ((double) value);
670                         case SybaseType.Int:
671                                 if (value == DBNull.Value)
672                                         return SybaseInt32.Null;
673                                 return (SybaseInt32) ((int) value);
674                         case SybaseType.Money:
675                         case SybaseType.SmallMoney:
676                                 if (value == DBNull.Value)
677                                         return SybaseMoney.Null;
678                                 return (SybaseMoney) ((decimal) value);
679                         case SybaseType.Real:
680                                 if (value == DBNull.Value)
681                                         return SybaseSingle.Null;
682                                 return (SybaseSingle) ((float) value);
683                         case SybaseType.UniqueIdentifier:
684                                 if (value == DBNull.Value)
685                                         return SybaseGuid.Null;
686                                 return (SybaseGuid) ((Guid) value);
687                         case SybaseType.SmallInt:
688                                 if (value == DBNull.Value)
689                                         return SybaseInt16.Null;
690                                 return (SybaseInt16) ((short) value);
691                         case SybaseType.TinyInt:
692                                 if (value == DBNull.Value)
693                                         return SybaseByte.Null;
694                                 return (SybaseByte) ((byte) value);
695                         }
696
697                         throw new InvalidOperationException ("The type of this column is unknown.");
698                 }
699
700                 public int GetSybaseValues (object[] values)
701                 {
702                         int count = 0;
703                         int columnCount = schemaTable.Rows.Count;
704                         int arrayCount = values.Length;
705
706                         if (arrayCount > columnCount)
707                                 count = columnCount;
708                         else
709                                 count = arrayCount;
710
711                         for (int i = 0; i < count; i += 1) 
712                                 values [i] = GetSybaseValue (i);
713
714                         return count;
715                 }
716
717                 public string GetString (int i)
718                 {
719                         object value = GetValue (i);
720                         if (!(value is string)) {
721                                 if (value is DBNull) throw new SybaseNullValueException ();
722                                 throw new InvalidCastException ();
723                         }
724                         return (string) value;
725                 }
726
727                 public object GetValue (int i)
728                 {
729                         return command.Tds.ColumnValues [i];
730                 }
731
732                 public int GetValues (object[] values)
733                 {
734                         int len = values.Length;
735                         int bigDecimalIndex = command.Tds.ColumnValues.BigDecimalIndex;
736
737                         // If a four-byte decimal is stored, then we can't convert to
738                         // a native type.  Throw an OverflowException.
739                         if (bigDecimalIndex >= 0 && bigDecimalIndex < len)
740                                 throw new OverflowException ();
741
742                         command.Tds.ColumnValues.CopyTo (0, values, 0, len);
743                         return (len > FieldCount ? len : FieldCount);
744                 }
745
746                 void IDisposable.Dispose ()
747                 {
748                         Dispose (true);
749                         GC.SuppressFinalize (this);
750                 }
751
752                 IEnumerator IEnumerable.GetEnumerator ()
753                 {
754                         return new DbEnumerator (this);
755                 }
756
757                 public bool IsDBNull (int i)
758                 {
759                         return GetValue (i) == DBNull.Value;
760                 }
761
762                 public bool NextResult ()
763                 {
764                         if ((command.CommandBehavior & CommandBehavior.SingleResult) != 0 && resultsRead > 0)
765                                 return false;
766                         if (command.Tds.DoneProc)
767                                 return false;
768
769                         schemaTable.Rows.Clear ();
770
771                         moreResults = command.Tds.NextResult ();
772                         GetSchemaTable ();
773
774                         rowsRead = 0;
775                         resultsRead += 1;
776                         return moreResults;
777                 }
778
779                 public bool Read ()
780                 {
781                         if ((command.CommandBehavior & CommandBehavior.SingleRow) != 0 && rowsRead > 0)
782                                 return false;
783                         if ((command.CommandBehavior & CommandBehavior.SchemaOnly) != 0)
784                                 return false;
785                         if (!moreResults)
786                                 return false;
787
788                         bool result = command.Tds.NextRow ();
789
790                         rowsRead += 1;
791
792                         return result;
793                 }
794
795                 #endregion // Methods
796         }
797 }