2 // Mono.Data.Tds.Protocol.Tds.cs
5 // Tim Coleman (tim@timcoleman.com)
6 // Sebastien Pouliot (spouliot@motus.com)
7 // Daniel Morgan (danielmorgan@verizon.net)
8 // Veerapuram Varadhan (vvaradhan@novell.com)
10 // Copyright (C) 2002 Tim Coleman
11 // Portions (C) 2003 Motus Technologies Inc. (http://www.motus.com)
12 // Portions (C) 2003,2005 Daniel Morgan
13 // Portions (C) 2008,2009 Novell Inc.
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using Mono
.Security
.Protocol
.Ntlm
;
39 using System
.Collections
;
40 using System
.ComponentModel
;
41 using System
.Diagnostics
;
42 using System
.Net
.Sockets
;
43 using System
.Globalization
;
46 namespace Mono
.Data
.Tds
.Protocol
48 public abstract class Tds
53 TdsVersion tdsVersion
;
55 protected internal TdsConnectionParameters connectionParms
;
56 protected readonly byte[] NTLMSSP_ID
= new byte[] {0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00}
;
61 string originalDatabase
= string.Empty
;
62 string databaseProductName
;
63 string databaseProductVersion
;
64 int databaseMajorVersion
;
65 CultureInfo locale
= CultureInfo
.InvariantCulture
;
78 TdsDataRow currentRow
;
79 TdsDataColumnCollection columns
;
82 ArrayList columnNames
;
84 TdsMetaParameterCollection parameters
= new TdsMetaParameterCollection ();
93 ArrayList outputParameters
= new ArrayList ();
94 protected TdsInternalErrorCollection messages
= new TdsInternalErrorCollection ();
96 int recordsAffected
= -1;
100 int StreamColumnIndex
;
102 bool sequentialAccess
;
108 internal int poolStatus
= 0;
114 protected string Charset
{
115 get { return charset; }
118 protected CultureInfo Locale
{
119 get { return locale; }
122 public bool DoneProc
{
123 get { return doneProc; }
126 protected string Language
{
127 get { return language; }
130 protected ArrayList ColumnNames
{
131 get { return columnNames; }
134 public TdsDataRow ColumnValues
{
135 get { return currentRow; }
138 internal TdsComm Comm
{
142 public string Database
{
143 get { return database; }
146 public string DataSource
{
147 get { return dataSource; }
150 public bool IsConnected
{
151 get { return connected && comm != null && comm.IsConnected (); }
152 set { connected = value; }
155 public bool Pooling
{
156 get { return pooling; }
157 set { pooling = value; }
160 public bool MoreResults
{
161 get { return moreResults; }
162 set { moreResults = value; }
165 public int PacketSize
{
166 get { return packetSize; }
169 public int RecordsAffected
{
170 get { return recordsAffected; }
171 set { recordsAffected = value; }
174 public string ServerVersion
{
175 get { return databaseProductVersion; }
178 public TdsDataColumnCollection Columns
{
179 get { return columns; }
182 public TdsVersion TdsVersion
{
183 get { return tdsVersion; }
186 public ArrayList OutputParameters
{
187 get { return outputParameters; }
188 set { outputParameters = value; }
191 protected TdsMetaParameterCollection Parameters
{
192 get { return parameters; }
193 set { parameters = value; }
196 public bool SequentialAccess
{
197 get { return sequentialAccess; }
198 set { sequentialAccess = value; }
201 public byte[] Collation
{
202 get {return collation; }
205 public TdsVersion ServerTdsVersion
{
207 switch (databaseMajorVersion
) {
208 case 4: return TdsVersion
.tds42
;
209 case 5: return TdsVersion
.tds50
;
210 case 7: return TdsVersion
.tds70
;
211 case 8: return TdsVersion
.tds80
;
212 case 9: return TdsVersion
.tds90
;
213 case 10: return TdsVersion
.tds100
;
214 default: return tdsVersion
; // return client's version
219 private void SkipRow ()
221 SkipToColumnIndex (Columns
.Count
);
224 StreamColumnIndex
= 0;
226 LoadInProgress
= false;
229 private void SkipToColumnIndex (int colIndex
)
234 if (colIndex
< StreamColumnIndex
)
235 throw new Exception ("Cannot Skip to a colindex less than the curr index");
237 while (colIndex
!= StreamColumnIndex
) {
239 TdsColumnType
? colType
= Columns
[StreamColumnIndex
].ColumnType
;
241 throw new Exception ("Column type unset.");
243 TdsColumnType colType
= (TdsColumnType
) Columns
[StreamColumnIndex
]["ColumnType"];
245 if (!(colType
== TdsColumnType
.Image
||
246 colType
== TdsColumnType
.Text
||
247 colType
== TdsColumnType
.NText
)) {
248 GetColumnValue (colType
, false, StreamColumnIndex
);
249 StreamColumnIndex
++;
253 Comm
.Skip (StreamLength
);
260 public object GetSequentialColumnValue (int colIndex
)
262 if (colIndex
< StreamColumnIndex
)
263 throw new InvalidOperationException ("Invalid attempt tp read from column ordinal" + colIndex
);
268 if (colIndex
!= StreamColumnIndex
)
269 SkipToColumnIndex (colIndex
);
272 object o
= GetColumnValue (Columns
[colIndex
].ColumnType
, false, colIndex
);
274 object o
= GetColumnValue ((TdsColumnType
)Columns
[colIndex
]["ColumnType"], false, colIndex
);
280 public long GetSequentialColumnValue (int colIndex
, long fieldIndex
, byte[] buffer
, int bufferIndex
, int size
)
282 if (colIndex
< StreamColumnIndex
)
283 throw new InvalidOperationException ("Invalid attempt to read from column ordinal" + colIndex
);
285 if (colIndex
!= StreamColumnIndex
)
286 SkipToColumnIndex (colIndex
);
288 if (!LoadInProgress
) {
290 BeginLoad (Columns
[colIndex
].ColumnType
);
292 BeginLoad ((TdsColumnType
)Columns
[colIndex
]["ColumnType"]);
298 return LoadData (fieldIndex
, buffer
, bufferIndex
, size
);
299 } catch (IOException ex
) {
301 throw new TdsInternalException ("Server closed the connection.", ex
);
305 private void BeginLoad (
307 TdsColumnType
? colType
309 TdsColumnType colType
320 throw new ArgumentNullException ("colType");
324 case TdsColumnType
.Text
:
325 case TdsColumnType
.NText
:
326 case TdsColumnType
.Image
:
327 if (Comm
.GetByte () != 0) {
329 StreamLength
= Comm
.GetTdsInt ();
331 // use -2 to indicate that we're dealing
336 case TdsColumnType
.BigVarChar
:
337 case TdsColumnType
.BigChar
:
338 case TdsColumnType
.BigBinary
:
339 case TdsColumnType
.BigVarBinary
:
341 StreamLength
= Comm
.GetTdsShort ();
343 case TdsColumnType
.VarChar
:
344 case TdsColumnType
.NVarChar
:
345 case TdsColumnType
.Char
:
346 case TdsColumnType
.NChar
:
347 case TdsColumnType
.Binary
:
348 case TdsColumnType
.VarBinary
:
349 StreamLength
= Comm
.GetTdsShort ();
357 LoadInProgress
= true;
360 private void EndLoad()
362 if (StreamLength
> 0)
363 Comm
.Skip (StreamLength
);
367 LoadInProgress
= false;
370 private long LoadData (long fieldIndex
, byte[] buffer
, int bufferIndex
, int size
)
372 if (StreamLength
<= 0)
375 if (fieldIndex
< StreamIndex
)
376 throw new InvalidOperationException (string.Format (
377 "Attempting to read at dataIndex '{0}' is " +
378 "not allowed as this is less than the " +
379 "current position. You must read from " +
380 "dataIndex '{1}' or greater.",
381 fieldIndex
, StreamIndex
));
383 if (fieldIndex
>= (StreamLength
+ StreamIndex
))
386 // determine number of bytes to skip
387 int skip
= (int) (fieldIndex
- StreamIndex
);
390 // update the current position
391 StreamIndex
+= (fieldIndex
- StreamIndex
);
392 // update the remaining length
393 StreamLength
-= skip
;
395 // Load the reqd amt of bytes
396 int loadlen
= (int) ((size
> StreamLength
) ? StreamLength
: size
);
397 byte[] arr
= Comm
.GetBytes (loadlen
, true);
399 // update the index and stream length
400 StreamIndex
+= loadlen
+ (fieldIndex
- StreamIndex
);
401 StreamLength
-= loadlen
;
402 arr
.CopyTo (buffer
, bufferIndex
);
407 #endregion // Properties
411 public event TdsInternalErrorMessageEventHandler TdsErrorMessage
;
412 public event TdsInternalInfoMessageEventHandler TdsInfoMessage
;
418 public Tds (string dataSource
, int port
, int packetSize
, int timeout
, TdsVersion tdsVersion
)
420 this.tdsVersion
= tdsVersion
;
421 this.packetSize
= packetSize
;
422 this.dataSource
= dataSource
;
423 this.columns
= new TdsDataColumnCollection ();
425 comm
= new TdsComm (dataSource
, port
, packetSize
, timeout
, tdsVersion
);
428 #endregion // Constructors
430 #region Public Methods
432 internal protected void InitExec ()
438 // Reset "read" status variables - used in case of SequentialAccess
439 isResultRead
= false;
443 StreamColumnIndex
= 0;
444 LoadInProgress
= false;
446 // Reset more variables
447 queryInProgress
= false;
448 cancelsRequested
= 0;
449 cancelsProcessed
= 0;
450 recordsAffected
= -1;
453 outputParameters
.Clear ();
456 public void Cancel ()
458 if (queryInProgress
) {
459 if (cancelsRequested
== cancelsProcessed
) {
460 comm
.StartPacket (TdsPacketType
.Cancel
);
463 } catch (IOException ex
) {
465 throw new TdsInternalException ("Server closed the connection.", ex
);
467 cancelsRequested
+= 1;
472 public abstract bool Connect (TdsConnectionParameters connectionParameters
);
474 public static TdsTimeoutException
CreateTimeoutException (string dataSource
, string method
)
476 string message
= "Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.";
477 return new TdsTimeoutException (0, 0, message
, -2, method
, dataSource
, "Mono TdsClient Data Provider", 0);
480 public void Disconnect ()
483 comm
.StartPacket (TdsPacketType
.Logoff
);
484 comm
.Append ((byte) 0);
487 // We're closing the socket anyway
493 public virtual bool Reset ()
495 database
= originalDatabase
;
499 protected virtual bool IsValidRowCount (byte status
, byte op
)
501 return ((status
& (0x10)) != 0) ;
504 public void Execute (string sql
)
506 Execute (sql
, null, 0, false);
509 public void ExecProc (string sql
)
511 ExecProc (sql
, null, 0, false);
514 public virtual void Execute (string sql
, TdsMetaParameterCollection parameters
, int timeout
, bool wantResults
)
516 ExecuteQuery (sql
, timeout
, wantResults
);
519 public virtual void ExecProc (string sql
, TdsMetaParameterCollection parameters
, int timeout
, bool wantResults
)
521 ExecuteQuery (String
.Format ("exec {0}", sql
), timeout
, wantResults
);
524 public virtual void ExecPrepared (string sql
, TdsMetaParameterCollection parameters
, int timeout
, bool wantResults
)
526 throw new NotSupportedException ();
529 internal void ExecBulkCopyMetaData (int timeout
, bool wantResults
)
534 CheckForData (timeout
);
537 } catch (IOException ex
) {
539 throw new TdsInternalException ("Server closed the connection.", ex
);
543 internal void ExecBulkCopy (int timeout
, bool wantResults
)
548 CheckForData (timeout
);
551 } catch (IOException ex
) {
553 throw new TdsInternalException ("Server closed the connection.", ex
);
557 protected void ExecuteQuery (string sql
, int timeout
, bool wantResults
)
561 Comm
.StartPacket (TdsPacketType
.Query
);
565 CheckForData (timeout
);
568 } catch (IOException ex
) {
570 throw new TdsInternalException ("Server closed the connection.", ex
);
574 protected virtual void ExecRPC (string rpcName
, TdsMetaParameterCollection parameters
,
575 int timeout
, bool wantResults
)
577 Comm
.StartPacket (TdsPacketType
.DBRPC
);
579 byte [] rpcNameBytes
= Comm
.Encoder
.GetBytes (rpcName
);
580 byte rpcNameLength
= (byte) rpcNameBytes
.Length
;
581 ushort mask
= 0x0000;
582 ushort packetLength
= (ushort) (sizeof (byte) + rpcNameLength
+
585 Comm
.Append (packetLength
);
586 Comm
.Append (rpcNameLength
);
587 Comm
.Append (rpcNameBytes
);
592 CheckForData (timeout
);
595 } catch (IOException ex
) {
597 throw new TdsInternalException ("Server closed the connection.", ex
);
601 public bool NextResult ()
603 if (SequentialAccess
) {
605 while (NextRow ()) {}
607 isResultRead
= false;
613 TdsPacketSubType subType
;
616 bool outputParams
= false;
619 subType
= ProcessSubPacket ();
625 case TdsPacketSubType
.ColumnInfo
:
626 case TdsPacketSubType
.ColumnMetadata
:
627 case TdsPacketSubType
.RowFormat
:
628 byte peek
= Comm
.Peek ();
629 done
= (peek
!= (byte) TdsPacketSubType
.TableName
);
630 if (done
&& doneProc
&& peek
== (byte) TdsPacketSubType
.Row
) {
635 case TdsPacketSubType
.TableName
:
638 done
= (peek
!= (byte) TdsPacketSubType
.ColumnDetail
);
640 case TdsPacketSubType
.ColumnDetail
:
652 public bool NextRow ()
654 if (SequentialAccess
) {
661 TdsPacketSubType subType
;
666 subType
= ProcessSubPacket ();
668 case TdsPacketSubType
.Row
:
672 case TdsPacketSubType
.Done
:
673 case TdsPacketSubType
.DoneProc
:
674 case TdsPacketSubType
.DoneInProc
:
684 public virtual string Prepare (string sql
, TdsMetaParameterCollection parameters
)
686 throw new NotSupportedException ();
689 public void SkipToEnd ()
692 while (NextResult ()) { /* DO NOTHING */ }
693 } catch (IOException ex
) {
695 throw new TdsInternalException ("Server closed the connection.", ex
);
699 public virtual void Unprepare (string statementId
)
701 throw new NotSupportedException ();
704 #endregion // Public Methods
706 #region // Private Methods
708 [MonoTODO ("Is cancel enough, or do we need to drop the connection?")]
709 protected void CheckForData (int timeout
)
711 if (timeout
> 0 && !comm
.Poll (timeout
, SelectMode
.SelectRead
)) {
713 throw CreateTimeoutException (dataSource
, "CheckForData()");
717 protected TdsInternalInfoMessageEventArgs
CreateTdsInfoMessageEvent (TdsInternalErrorCollection errors
)
719 return new TdsInternalInfoMessageEventArgs (errors
);
722 protected TdsInternalErrorMessageEventArgs
CreateTdsErrorMessageEvent (byte theClass
, int lineNumber
, string message
, int number
, string procedure
, string server
, string source
, byte state
)
724 return new TdsInternalErrorMessageEventArgs (new TdsInternalError (theClass
, lineNumber
, message
, number
, procedure
, server
, source
, state
));
727 private Encoding
GetEncodingFromColumnCollation (int lcid
, int sortId
)
730 return TdsCharset
.GetEncodingFromSortOrder (sortId
);
732 return TdsCharset
.GetEncodingFromLCID (lcid
);
735 protected object GetColumnValue (
737 TdsColumnType
? colType
,
739 TdsColumnType colType
,
743 return GetColumnValue (colType
, outParam
, -1);
746 private object GetColumnValue (
748 TdsColumnType
? colType
,
750 TdsColumnType colType
,
752 bool outParam
, int ordinal
)
755 object element
= null;
757 int lcid
= 0, sortId
= 0;
761 throw new ArgumentNullException ("colType");
763 if (ordinal
> -1 && tdsVersion
> TdsVersion
.tds70
) {
765 lcid
= (int) columns
[ordinal
].LCID
;
766 sortId
= (int) columns
[ordinal
].SortOrder
;
768 lcid
= (int) columns
[ordinal
]["LCID"];
769 sortId
= (int) columns
[ordinal
]["SortOrder"];
774 case TdsColumnType
.IntN
:
777 element
= GetIntValue (colType
);
779 case TdsColumnType
.Int1
:
780 case TdsColumnType
.Int2
:
781 case TdsColumnType
.Int4
:
782 case TdsColumnType
.BigInt
:
783 element
= GetIntValue (colType
);
785 case TdsColumnType
.Image
:
788 element
= GetImageValue ();
790 case TdsColumnType
.Text
:
791 enc
= GetEncodingFromColumnCollation (lcid
, sortId
);
794 element
= GetTextValue (false, enc
);
796 case TdsColumnType
.NText
:
797 enc
= GetEncodingFromColumnCollation (lcid
, sortId
);
800 element
= GetTextValue (true, enc
);
802 case TdsColumnType
.Char
:
803 case TdsColumnType
.VarChar
:
804 enc
= GetEncodingFromColumnCollation (lcid
, sortId
);
807 element
= GetStringValue (colType
, false, outParam
, enc
);
809 case TdsColumnType
.BigVarBinary
:
812 len
= comm
.GetTdsShort ();
813 element
= comm
.GetBytes (len
, true);
816 case TdsColumnType.BigBinary :
819 len = comm.GetTdsShort ();
820 element = comm.GetBytes (len, true);
823 case TdsColumnType
.BigBinary
:
826 element
= GetBinaryValue ();
828 case TdsColumnType
.BigChar
:
829 case TdsColumnType
.BigVarChar
:
830 enc
= GetEncodingFromColumnCollation (lcid
, sortId
);
833 element
= GetStringValue (colType
, false, outParam
, enc
);
835 case TdsColumnType
.NChar
:
836 case TdsColumnType
.BigNVarChar
:
837 enc
= GetEncodingFromColumnCollation (lcid
, sortId
);
840 element
= GetStringValue (colType
, true, outParam
, enc
);
842 case TdsColumnType
.NVarChar
:
843 enc
= GetEncodingFromColumnCollation (lcid
, sortId
);
846 element
= GetStringValue (colType
, true, outParam
, enc
);
848 case TdsColumnType
.Real
:
849 case TdsColumnType
.Float8
:
850 element
= GetFloatValue (colType
);
852 case TdsColumnType
.FloatN
:
855 element
= GetFloatValue (colType
);
857 case TdsColumnType
.SmallMoney
:
858 case TdsColumnType
.Money
:
859 element
= GetMoneyValue (colType
);
861 case TdsColumnType
.MoneyN
:
864 element
= GetMoneyValue (colType
);
866 case TdsColumnType
.Numeric
:
867 case TdsColumnType
.Decimal
:
872 precision
= comm
.GetByte ();
873 scale
= comm
.GetByte ();
877 precision
= (byte) columns
[ordinal
].NumericPrecision
;
878 scale
= (byte) columns
[ordinal
].NumericScale
;
880 precision
= (byte) columns
[ordinal
]["NumericPrecision"];
881 scale
= (byte) columns
[ordinal
]["NumericScale"];
885 element
= GetDecimalValue (precision
, scale
);
887 // workaround for fact that TDS 7.0 returns
888 // bigint as decimal (19,0), and client code
889 // expects it to be returned as a long
890 if (scale
== 0 && precision
<= 19 && tdsVersion
== TdsVersion
.tds70
) {
891 if (!(element
is System
.DBNull
))
892 element
= Convert
.ToInt64 (element
);
895 case TdsColumnType
.DateTimeN
:
898 element
= GetDateTimeValue (colType
);
900 case TdsColumnType
.DateTime4
:
901 case TdsColumnType
.DateTime
:
902 element
= GetDateTimeValue (colType
);
904 case TdsColumnType
.VarBinary
:
905 case TdsColumnType
.Binary
:
908 element
= GetBinaryValue ();
910 case TdsColumnType
.BitN
:
913 if (comm
.GetByte () == 0)
914 element
= DBNull
.Value
;
916 element
= (comm
.GetByte() != 0);
918 case TdsColumnType
.Bit
:
919 int columnSize
= comm
.GetByte ();
920 element
= (columnSize
!= 0);
922 case TdsColumnType
.UniqueIdentifier
:
923 if (comm
.Peek () != 16) { // If it's null, then what to do?
924 /*byte swallowed =*/ comm
.GetByte();
925 element
= DBNull
.Value
;
931 len
= comm
.GetByte () & 0xff;
933 byte[] guidBytes
= comm
.GetBytes (len
, true);
934 if (!BitConverter
.IsLittleEndian
) {
935 byte[] swappedguidBytes
= new byte[len
];
936 for (int i
= 0; i
< 4; i
++)
937 swappedguidBytes
[i
] = guidBytes
[4-i
-1];
938 for (int i
= 4; i
< 6; i
++)
939 swappedguidBytes
[i
] = guidBytes
[6-(i
-4)-1];
940 for (int i
= 6; i
< 8; i
++)
941 swappedguidBytes
[i
] = guidBytes
[8-(i
-6)-1];
942 for (int i
= 8; i
< 16; i
++)
943 swappedguidBytes
[i
] = guidBytes
[i
];
944 Array
.Copy(swappedguidBytes
, 0, guidBytes
, 0, len
);
946 element
= new Guid (guidBytes
);
955 private object GetBinaryValue ()
958 object result
= DBNull
.Value
;
960 if (tdsVersion
>= TdsVersion
.tds70
) {
961 len
= comm
.GetTdsShort ();
962 if (len
!= 0xffff && len
>= 0)
963 result
= comm
.GetBytes (len
, true);
965 len
= (comm
.GetByte () & 0xff);
967 result
= comm
.GetBytes (len
, true);
973 private object GetDateTimeValue (
986 throw new ArgumentNullException ("type");
989 case TdsColumnType
.DateTime4
:
992 case TdsColumnType
.DateTime
:
995 case TdsColumnType
.DateTimeN
:
996 byte tmp
= comm
.Peek ();
997 if (tmp
!= 0 && tmp
!= 4 && tmp
!= 8)
999 len
= comm
.GetByte ();
1003 DateTime epoch
= new DateTime (1900, 1, 1);
1007 result
= epoch
.AddDays (comm
.GetTdsInt ());
1008 int seconds
= comm
.GetTdsInt ();
1009 long millis
= (long) System
.Math
.Round (((((long) seconds
) % 300L) * 1000L) / 300f
);
1010 if (seconds
!= 0 || millis
!= 0) {
1011 result
= ((DateTime
) result
).AddSeconds (seconds
/ 300);
1012 result
= ((DateTime
) result
).AddMilliseconds (millis
);
1016 // MSDN says small datetime is stored in 2 bytes as no of days
1017 // *after* 1/1/1900. so, cast to unsigned short
1018 result
= epoch
.AddDays ((ushort) comm
.GetTdsShort ());
1019 short minutes
= comm
.GetTdsShort ();
1021 result
= ((DateTime
) result
).AddMinutes ((int) minutes
);
1024 result
= DBNull
.Value
;
1031 private object GetDecimalValue (byte precision
, byte scale
)
1033 if (tdsVersion
< TdsVersion
.tds70
)
1034 return GetDecimalValueTds50 (precision
, scale
);
1036 return GetDecimalValueTds70 (precision
, scale
);
1039 private object GetDecimalValueTds70 (byte precision
, byte scale
)
1041 int[] bits
= new int[4] {0,0,0,0}
;
1043 int len
= (comm
.GetByte() & 0xff) - 1;
1045 return DBNull
.Value
;
1047 bool positive
= (comm
.GetByte () == 1);
1049 throw new OverflowException ();
1051 for (int i
= 0, index
= 0; i
< len
&& i
< 16; i
+= 4, index
+= 1)
1052 bits
[index
] = comm
.GetTdsInt ();
1055 return new TdsBigDecimal (precision
, scale
, !positive
, bits
);
1057 return new Decimal (bits
[0], bits
[1], bits
[2], !positive
, scale
);
1060 private object GetDecimalValueTds50 (byte precision
, byte scale
)
1062 int[] bits
= new int[4] {0,0,0,0}
;
1064 int len
= (comm
.GetByte() & 0xff);
1066 return DBNull
.Value
;
1068 byte[] dec_bytes
=comm
.GetBytes(len
,false);
1070 byte[] easy
=new byte[4];
1072 bool positive
= dec_bytes
[0]==1;
1075 throw new OverflowException ();
1077 for (int i
= 1, index
= 0; i
< len
&& i
< 16; i
+=
1079 for(int j
=0; j
<4; j
++)
1081 easy
[j
]=dec_bytes
[len
-
1085 if(!BitConverter
.IsLittleEndian
)
1086 easy
=comm
.Swap(easy
);
1087 bits
[index
] = BitConverter
.ToInt32(easy
,0);
1090 return new TdsBigDecimal (precision
,
1091 scale
, positive
, bits
);
1093 return new Decimal(bits
[0], bits
[1], bits
1094 [2], positive
, scale
);
1098 private object GetFloatValue (
1100 TdsColumnType
? columnType
1102 TdsColumnType columnType
1107 if (columnType
== null)
1108 throw new ArgumentNullException ("columnType");
1112 switch (columnType
) {
1113 case TdsColumnType
.Real
:
1116 case TdsColumnType
.Float8
:
1119 case TdsColumnType
.FloatN
:
1120 columnSize
= comm
.GetByte ();
1124 switch (columnSize
) {
1126 return BitConverter
.Int64BitsToDouble (comm
.GetTdsInt64 ());
1128 return BitConverter
.ToSingle (BitConverter
.GetBytes (comm
.GetTdsInt ()), 0);
1130 return DBNull
.Value
;
1134 private object GetImageValue ()
1136 byte hasValue
= comm
.GetByte ();
1139 return DBNull
.Value
;
1142 int len
= comm
.GetTdsInt ();
1145 return DBNull
.Value
;
1147 return (comm
.GetBytes (len
, true));
1150 private object GetIntValue (
1162 throw new ArgumentNullException ("type");
1165 case TdsColumnType
.BigInt
:
1168 case TdsColumnType
.IntN
:
1169 len
= comm
.GetByte ();
1171 case TdsColumnType
.Int4
:
1174 case TdsColumnType
.Int2
:
1177 case TdsColumnType
.Int1
:
1181 return DBNull
.Value
;
1186 return (comm
.GetTdsInt64 ());
1188 return (comm
.GetTdsInt ());
1190 return (comm
.GetTdsShort ());
1192 return (comm
.GetByte ());
1194 return DBNull
.Value
;
1198 private object GetMoneyValue (
1210 throw new ArgumentNullException ("type");
1213 case TdsColumnType
.SmallMoney
:
1214 case TdsColumnType
.Money4
:
1217 case TdsColumnType
.Money
:
1220 case TdsColumnType
.MoneyN
:
1221 len
= comm
.GetByte ();
1224 return DBNull
.Value
;
1229 int val
= Comm
.GetTdsInt ();
1230 bool negative
= val
< 0;
1233 return new Decimal (val
, 0, 0, negative
, 4);
1236 int hi
= Comm
.GetTdsInt ();
1237 int lo
= Comm
.GetTdsInt ();
1238 bool negative
= hi
< 0;
1244 return new Decimal (lo
, hi
, 0, negative
, 4);
1247 return DBNull
.Value
;
1251 protected object GetStringValue (
1253 TdsColumnType
? colType
,
1255 TdsColumnType colType
,
1257 bool wideChars
, bool outputParam
, Encoding encoder
)
1259 bool shortLen
= false;
1260 Encoding enc
= encoder
;
1262 if (tdsVersion
> TdsVersion
.tds70
&& outputParam
&&
1263 (colType
== TdsColumnType
.BigChar
|| colType
== TdsColumnType
.BigNVarChar
||
1264 colType
== TdsColumnType
.BigVarChar
|| colType
== TdsColumnType
.NChar
||
1265 colType
== TdsColumnType
.NVarChar
)) {
1266 // Read collation for SqlServer 2000 and beyond
1268 collation
= Comm
.GetBytes (5, true);
1269 enc
= TdsCharset
.GetEncoding (collation
);
1272 shortLen
= (tdsVersion
>= TdsVersion
.tds70
) && (wideChars
|| !outputParam
);
1275 int len
= shortLen
? comm
.GetTdsShort () : (comm
.GetByte () & 0xff);
1276 return GetStringValue (wideChars
, len
, enc
);
1279 protected object GetStringValue (bool wideChars
, int len
, Encoding enc
)
1281 if (tdsVersion
< TdsVersion
.tds70
&& len
== 0)
1282 return DBNull
.Value
;
1284 else if (len
>= 0) {
1287 result
= comm
.GetString (len
/ 2, enc
);
1289 result
= comm
.GetString (len
, false, enc
);
1290 if (tdsVersion
< TdsVersion
.tds70
&& ((string) result
).Equals (" "))
1291 result
= string.Empty
;
1295 return DBNull
.Value
;
1298 protected int GetSubPacketLength ()
1300 return comm
.GetTdsShort ();
1303 private object GetTextValue (bool wideChars
, Encoding encoder
)
1305 string result
= null;
1306 byte hasValue
= comm
.GetByte ();
1309 return DBNull
.Value
;
1311 // 16 Byte TEXTPTR, 8 Byte TIMESTAMP
1314 int len
= comm
.GetTdsInt ();
1316 //if the len is 0 , then the string can be a '' string
1317 // this method is called only for Text and NText. Hence will
1318 // return a empty string
1320 return string.Empty
;
1323 result
= comm
.GetString (len
/ 2, encoder
);
1325 result
= comm
.GetString (len
, false, encoder
);
1328 if ((byte) tdsVersion
< (byte) TdsVersion
.tds70
&& result
== " ")
1329 result
= string.Empty
;
1334 internal bool IsBlobType (TdsColumnType columnType
)
1336 return (columnType
== TdsColumnType
.Text
|| columnType
== TdsColumnType
.Image
|| columnType
== TdsColumnType
.NText
);
1339 internal bool IsLargeType (TdsColumnType columnType
)
1341 return ((byte) columnType
> 128);
1344 protected bool IsWideType (TdsColumnType columnType
)
1346 switch (columnType
) {
1347 case TdsColumnType
.NChar
:
1348 case TdsColumnType
.NText
:
1349 case TdsColumnType
.NVarChar
:
1356 internal static bool IsFixedSizeColumn (TdsColumnType columnType
)
1358 switch (columnType
) {
1359 case TdsColumnType
.Int1
:
1360 case TdsColumnType
.Int2
:
1361 case TdsColumnType
.Int4
:
1362 case TdsColumnType
.BigInt
:
1363 case TdsColumnType
.Float8
:
1364 case TdsColumnType
.DateTime
:
1365 case TdsColumnType
.Bit
:
1366 case TdsColumnType
.Money
:
1367 case TdsColumnType
.Money4
:
1368 case TdsColumnType
.SmallMoney
:
1369 case TdsColumnType
.Real
:
1370 case TdsColumnType
.DateTime4
:
1372 case TdsColumnType.Decimal:
1373 case TdsColumnType.Numeric:
1381 protected void LoadRow ()
1383 if (SequentialAccess
) {
1387 isResultRead
= true;
1391 currentRow
= new TdsDataRow ();
1394 foreach (TdsDataColumn column
in columns
) {
1396 object o
= GetColumnValue (column
.ColumnType
, false, i
);
1398 object o
= GetColumnValue ((TdsColumnType
)column
["ColumnType"], false, i
);
1402 outputParameters
.Add (o
);
1404 if (o
is TdsBigDecimal
&& currentRow
.BigDecimalIndex
< 0)
1405 currentRow
.BigDecimalIndex
= i
;
1410 internal static int LookupBufferSize (TdsColumnType columnType
)
1412 switch (columnType
) {
1413 case TdsColumnType
.Int1
:
1414 case TdsColumnType
.Bit
:
1416 case TdsColumnType
.Int2
:
1418 case TdsColumnType
.Int4
:
1419 case TdsColumnType
.Real
:
1420 case TdsColumnType
.DateTime4
:
1421 case TdsColumnType
.Money4
:
1422 case TdsColumnType
.SmallMoney
:
1424 case TdsColumnType
.Float8
:
1425 case TdsColumnType
.DateTime
:
1426 case TdsColumnType
.Money
:
1427 case TdsColumnType
.BigInt
:
1434 protected internal int ProcessAuthentication ()
1436 int pdu_size
= Comm
.GetTdsShort ();
1437 byte[] msg2
= Comm
.GetBytes (pdu_size
, true);
1439 Type2Message t2
= new Type2Message (msg2
);
1440 // 0x0001 Negotiate Unicode
1441 // 0x0200 Negotiate NTLM
1442 // 0x8000 Negotiate Always Sign
1444 Type3Message t3
= new Type3Message ();
1445 t3
.Challenge
= t2
.Nonce
;
1447 t3
.Domain
= this.connectionParms
.DefaultDomain
;
1448 t3
.Host
= this.connectionParms
.Hostname
;
1449 t3
.Username
= this.connectionParms
.User
;
1450 t3
.Password
= this.connectionParms
.Password
;
1452 Comm
.StartPacket (TdsPacketType
.SspAuth
); // 0x11
1453 Comm
.Append (t3
.GetBytes ());
1456 } catch (IOException ex
) {
1458 throw new TdsInternalException ("Server closed the connection.", ex
);
1460 return 1; // TDS_SUCCEED
1463 protected void ProcessColumnDetail ()
1465 int len
= GetSubPacketLength ();
1466 byte[] values
= new byte[3];
1467 int columnNameLength
;
1468 string baseColumnName
= String
.Empty
;
1471 while (position
< len
) {
1472 for (int j
= 0; j
< 3; j
+= 1)
1473 values
[j
] = comm
.GetByte ();
1476 bool isAlias
= ((values
[2] & (byte) TdsColumnStatus
.Rename
) != 0);
1478 if (tdsVersion
>= TdsVersion
.tds70
) {
1479 columnNameLength
= comm
.GetByte ();
1480 position
+= 2 * columnNameLength
+ 1;
1483 columnNameLength
= comm
.GetByte ();
1484 position
+= columnNameLength
+ 1;
1486 baseColumnName
= comm
.GetString (columnNameLength
);
1489 byte index
= (byte) (values
[0] - (byte) 1);
1490 byte tableIndex
= (byte) (values
[1] - (byte) 1);
1491 bool isExpression
= ((values
[2] & (byte) TdsColumnStatus
.IsExpression
) != 0);
1493 TdsDataColumn column
= columns
[index
];
1495 column
.IsHidden
= ((values
[2] & (byte) TdsColumnStatus
.Hidden
) != 0);
1496 column
.IsExpression
= isExpression
;
1497 column
.IsKey
= ((values
[2] & (byte) TdsColumnStatus
.IsKey
) != 0);
1498 column
.IsAliased
= isAlias
;
1499 column
.BaseColumnName
= ((isAlias
) ? baseColumnName
: null);
1500 column
.BaseTableName
= ((!isExpression
) ? (string) tableNames
[tableIndex
] : null);
1502 column
["IsHidden"] = ((values
[2] & (byte) TdsColumnStatus
.Hidden
) != 0);
1503 column
["IsExpression"] = isExpression
;
1504 column
["IsKey"] = ((values
[2] & (byte) TdsColumnStatus
.IsKey
) != 0);
1505 column
["IsAliased"] = isAlias
;
1506 column
["BaseColumnName"] = ((isAlias
) ? baseColumnName
: null);
1507 column
["BaseTableName"] = ((!isExpression
) ? tableNames
[tableIndex
] : null);
1512 protected abstract void ProcessColumnInfo ();
1514 protected void ProcessColumnNames ()
1516 columnNames
= new ArrayList ();
1518 int totalLength
= comm
.GetTdsShort ();
1522 while (bytesRead
< totalLength
) {
1523 int columnNameLength
= comm
.GetByte ();
1524 string columnName
= comm
.GetString (columnNameLength
);
1525 bytesRead
= bytesRead
+ 1 + columnNameLength
;
1526 columnNames
.Add (columnName
);
1531 [MonoTODO ("Make sure counting works right, especially with multiple resultsets.")]
1532 protected void ProcessEndToken (TdsPacketSubType type
)
1534 byte status
= Comm
.GetByte ();
1536 byte op
= comm
.GetByte ();
1539 int rowCount
= comm
.GetTdsInt ();
1540 bool validRowCount
= IsValidRowCount (status
,op
);
1541 moreResults
= ((status
& 0x01) != 0);
1542 bool cancelled
= ((status
& 0x20) != 0);
1545 case TdsPacketSubType
.DoneProc
:
1547 goto case TdsPacketSubType
.Done
;
1548 case TdsPacketSubType
.Done
:
1549 case TdsPacketSubType
.DoneInProc
:
1550 if (validRowCount
) {
1551 if (recordsAffected
== -1)
1552 recordsAffected
= rowCount
;
1554 recordsAffected
+= rowCount
;
1560 queryInProgress
= false;
1562 cancelsProcessed
+= 1;
1563 if (messages
.Count
> 0 && !moreResults
)
1564 OnTdsInfoMessage (CreateTdsInfoMessageEvent (messages
));
1567 protected void ProcessEnvironmentChange ()
1569 // VARADHAN: TDS 8 Debugging
1570 //Console.WriteLine ("In ProcessEnvironmentChange... entry");
1571 int len
= GetSubPacketLength ();
1572 TdsEnvPacketSubType type
= (TdsEnvPacketSubType
) comm
.GetByte ();
1576 case TdsEnvPacketSubType
.BlockSize
:
1578 cLen
= comm
.GetByte ();
1579 blockSize
= comm
.GetString (cLen
);
1581 if (tdsVersion
>= TdsVersion
.tds70
)
1582 comm
.Skip (len
- 2 - cLen
* 2);
1584 comm
.Skip (len
- 2 - cLen
);
1586 packetSize
= Int32
.Parse (blockSize
);
1587 comm
.ResizeOutBuf (packetSize
);
1589 case TdsEnvPacketSubType
.CharSet
:
1590 cLen
= comm
.GetByte ();
1591 if (tdsVersion
== TdsVersion
.tds70
) {
1592 SetCharset (comm
.GetString (cLen
));
1593 comm
.Skip (len
- 2 - cLen
* 2);
1596 SetCharset (comm
.GetString (cLen
));
1597 comm
.Skip (len
- 2 - cLen
);
1601 case TdsEnvPacketSubType
.Locale
:
1602 cLen
= comm
.GetByte ();
1604 if (tdsVersion
>= TdsVersion
.tds70
) {
1605 lcid
= (int) Convert
.ChangeType (comm
.GetString (cLen
), typeof (int));
1606 comm
.Skip (len
- 2 - cLen
* 2);
1609 lcid
= (int) Convert
.ChangeType (comm
.GetString (cLen
), typeof (int));
1610 comm
.Skip (len
- 2 - cLen
);
1612 locale
= new CultureInfo (lcid
);
1614 case TdsEnvPacketSubType
.Database
:
1615 cLen
= comm
.GetByte ();
1616 string newDB
= comm
.GetString (cLen
);
1617 cLen
= comm
.GetByte () & 0xff;
1618 comm
.GetString (cLen
);
1619 if (originalDatabase
== string.Empty
)
1620 originalDatabase
= newDB
;
1623 case TdsEnvPacketSubType
.CollationInfo
:
1624 //Console.WriteLine ("ProcessEnvironmentChange::Got collation info");
1625 cLen
= comm
.GetByte ();
1626 collation
= comm
.GetBytes (cLen
, true);
1627 lcid
= TdsCollation
.LCID (collation
);
1628 locale
= new CultureInfo (lcid
);
1629 SetCharset (TdsCharset
.GetEncoding (collation
));
1633 comm
.Skip (len
- 1);
1636 // VARADHAN: TDS 8 Debugging
1637 //Console.WriteLine ("In ProcessEnvironmentChange... exit");
1640 protected void ProcessLoginAck ()
1642 uint srvVersion
= 0;
1643 GetSubPacketLength ();
1645 //Console.WriteLine ("ProcessLoginAck: B4 tdsVersion:{0}", tdsVersion);
1646 // Valid only for a Login7 request
1647 if (tdsVersion
>= TdsVersion
.tds70
) {
1649 srvVersion
= (uint)comm
.GetTdsInt ();
1651 //Console.WriteLine ("srvVersion: {0}", srvVersion);
1652 switch (srvVersion
) {
1654 tdsVersion
= TdsVersion
.tds70
;
1657 tdsVersion
= TdsVersion
.tds80
;
1660 tdsVersion
= TdsVersion
.tds81
;
1663 tdsVersion
= TdsVersion
.tds90
;
1666 //Console.WriteLine ("ProcessLoginAck: after tdsVersion:{0}", tdsVersion);
1669 if (tdsVersion
>= TdsVersion
.tds70
) {
1670 int nameLength
= comm
.GetByte ();
1671 databaseProductName
= comm
.GetString (nameLength
);
1672 databaseMajorVersion
= comm
.GetByte ();
1673 databaseProductVersion
= String
.Format ("{0}.{1}.{2}", databaseMajorVersion
.ToString("00"),
1674 comm
.GetByte ().ToString("00"),
1675 (256 * comm
.GetByte () + comm
.GetByte ()).ToString("0000"));
1678 short nameLength
= comm
.GetByte ();
1679 databaseProductName
= comm
.GetString (nameLength
);
1681 databaseMajorVersion
= comm
.GetByte ();
1682 databaseProductVersion
= String
.Format ("{0}.{1}", databaseMajorVersion
, comm
.GetByte ());
1686 if (databaseProductName
.Length
> 1 && -1 != databaseProductName
.IndexOf ('\0')) {
1687 int last
= databaseProductName
.IndexOf ('\0');
1688 databaseProductName
= databaseProductName
.Substring (0, last
);
1692 //Console.WriteLine ("databaseProductVersion:{0}", databaseProductVersion);
1695 protected void OnTdsErrorMessage (TdsInternalErrorMessageEventArgs e
)
1697 if (TdsErrorMessage
!= null)
1698 TdsErrorMessage (this, e
);
1701 protected void OnTdsInfoMessage (TdsInternalInfoMessageEventArgs e
)
1703 if (TdsInfoMessage
!= null)
1704 TdsInfoMessage (this, e
);
1708 protected void ProcessMessage (TdsPacketSubType subType
)
1710 GetSubPacketLength ();
1712 int number
= comm
.GetTdsInt ();
1713 byte state
= comm
.GetByte ();
1714 byte theClass
= comm
.GetByte ();
1720 bool isError
= false;
1722 if (subType
== TdsPacketSubType
.EED
) {
1723 isError
= (theClass
> 10);
1724 comm
.Skip (comm
.GetByte ()); // SQL State
1725 comm
.Skip (1); // Status
1726 comm
.Skip (2); // TranState
1728 isError
= (subType
== TdsPacketSubType
.Error
);
1730 message
= comm
.GetString (comm
.GetTdsShort ());
1731 server
= comm
.GetString (comm
.GetByte ());
1732 procedure
= comm
.GetString (comm
.GetByte ());
1733 lineNumber
= comm
.GetByte ();
1735 source
= String
.Empty
; // FIXME
1738 OnTdsErrorMessage (CreateTdsErrorMessageEvent (theClass
, lineNumber
, message
, number
, procedure
, server
, source
, state
));
1740 messages
.Add (new TdsInternalError (theClass
, lineNumber
, message
, number
, procedure
, server
, source
, state
));
1743 protected virtual void ProcessOutputParam ()
1745 GetSubPacketLength ();
1746 /*string paramName = */comm
.GetString (comm
.GetByte () & 0xff);
1749 TdsColumnType colType
= (TdsColumnType
) comm
.GetByte ();
1750 object value = GetColumnValue (colType
, true);
1751 outputParameters
.Add (value);
1754 protected void ProcessDynamic ()
1757 /*byte type =*/ Comm
.GetByte ();
1758 /*byte status =*/ Comm
.GetByte ();
1759 /*string id =*/ Comm
.GetString (Comm
.GetByte ());
1762 protected virtual TdsPacketSubType
ProcessSubPacket ()
1764 // VARADHAN: TDS 8 Debugging
1765 // Console.WriteLine ("In ProcessSubPacket... entry");
1767 TdsPacketSubType subType
= (TdsPacketSubType
) comm
.GetByte ();
1769 // VARADHAN: TDS 8 Debugging
1770 //Console.WriteLine ("Subpacket type: {0}", subType);
1772 case TdsPacketSubType
.Dynamic2
:
1773 comm
.Skip (comm
.GetTdsInt ());
1775 case TdsPacketSubType
.AltName
:
1776 case TdsPacketSubType
.AltFormat
:
1777 case TdsPacketSubType
.Capability
:
1778 case TdsPacketSubType
.ParamFormat
:
1779 comm
.Skip (comm
.GetTdsShort ());
1781 case TdsPacketSubType
.Dynamic
:
1784 case TdsPacketSubType
.EnvironmentChange
:
1785 ProcessEnvironmentChange ();
1787 case TdsPacketSubType
.Info
: // TDS 4.2/7.0
1788 case TdsPacketSubType
.EED
: // TDS 5.0
1789 case TdsPacketSubType
.Error
: // TDS 4.2/7.0
1790 ProcessMessage (subType
);
1792 case TdsPacketSubType
.Param
:
1793 ProcessOutputParam ();
1795 case TdsPacketSubType
.LoginAck
:
1798 case TdsPacketSubType
.Authentication
: // TDS 7.0
1799 ProcessAuthentication ();
1801 case TdsPacketSubType
.ReturnStatus
:
1802 ProcessReturnStatus ();
1804 case TdsPacketSubType
.ProcId
:
1807 case TdsPacketSubType
.Done
:
1808 case TdsPacketSubType
.DoneProc
:
1809 case TdsPacketSubType
.DoneInProc
:
1810 ProcessEndToken (subType
);
1812 case TdsPacketSubType
.ColumnName
:
1814 ProcessColumnNames ();
1816 case TdsPacketSubType
.ColumnInfo
: // TDS 4.2
1817 case TdsPacketSubType
.ColumnMetadata
: // TDS 7.0
1818 case TdsPacketSubType
.RowFormat
: // TDS 5.0
1820 ProcessColumnInfo ();
1822 case TdsPacketSubType
.ColumnDetail
:
1823 ProcessColumnDetail ();
1825 case TdsPacketSubType
.TableName
:
1826 ProcessTableName ();
1828 case TdsPacketSubType
.ColumnOrder
:
1829 comm
.Skip (comm
.GetTdsShort ());
1831 case TdsPacketSubType
.Control
:
1832 comm
.Skip (comm
.GetTdsShort ());
1834 case TdsPacketSubType
.Row
:
1839 // VARADHAN: TDS 8 Debugging
1840 //Console.WriteLine ("In ProcessSubPacket... exit");
1844 protected void ProcessTableName ()
1846 tableNames
= new ArrayList ();
1847 int totalLength
= comm
.GetTdsShort ();
1851 while (position
< totalLength
) {
1852 if (tdsVersion
>= TdsVersion
.tds70
) {
1853 len
= comm
.GetTdsShort ();
1854 position
+= 2 * (len
+ 1);
1857 len
= comm
.GetByte ();
1858 position
+= len
+ 1;
1860 tableNames
.Add (comm
.GetString (len
));
1864 protected void SetCharset (Encoding encoder
)
1866 comm
.Encoder
= encoder
;
1869 protected void SetCharset (string charset
)
1871 if (charset
== null || charset
.Length
> 30)
1874 if (this.charset
!= null && this.charset
== charset
)
1877 if (charset
.StartsWith ("cp")) {
1878 encoder
= Encoding
.GetEncoding (Int32
.Parse (charset
.Substring (2)));
1879 this.charset
= charset
;
1882 encoder
= Encoding
.GetEncoding ("iso-8859-1");
1883 this.charset
= "iso_1";
1885 SetCharset (encoder
);
1888 protected void SetLanguage (string language
)
1890 if (language
== null || language
.Length
> 30)
1891 language
= "us_english";
1893 this.language
= language
;
1896 protected virtual void ProcessReturnStatus ()
1901 #endregion // Private Methods
1904 #region asynchronous methods
1905 protected IAsyncResult
BeginExecuteQueryInternal (string sql
, bool wantResults
,
1906 AsyncCallback callback
, object state
)
1910 TdsAsyncResult ar
= new TdsAsyncResult (callback
, state
);
1911 ar
.TdsAsyncState
.WantResults
= wantResults
;
1913 Comm
.StartPacket (TdsPacketType
.Query
);
1917 Comm
.BeginReadPacket (new AsyncCallback(OnBeginExecuteQueryCallback
),
1919 } catch (IOException ex
) {
1921 throw new TdsInternalException ("Server closed the connection.", ex
);
1927 protected void EndExecuteQueryInternal (IAsyncResult ar
)
1929 if (!ar
.IsCompleted
)
1930 ar
.AsyncWaitHandle
.WaitOne ();
1931 TdsAsyncResult result
= (TdsAsyncResult
) ar
;
1932 if (result
.IsCompletedWithException
)
1933 throw result
.Exception
;
1936 protected void OnBeginExecuteQueryCallback (IAsyncResult ar
)
1938 TdsAsyncResult result
= (TdsAsyncResult
) ar
.AsyncState
;
1939 TdsAsyncState tdsState
= (TdsAsyncState
) result
.TdsAsyncState
;
1942 Comm
.EndReadPacket (ar
);
1943 if (!tdsState
.WantResults
)
1945 } catch (Exception e
) {
1946 result
.MarkComplete (e
);
1949 result
.MarkComplete ();
1953 public virtual IAsyncResult
BeginExecuteNonQuery (string sql
,
1954 TdsMetaParameterCollection parameters
,
1955 AsyncCallback callback
,
1958 // abstract, kept to be backward compatiable.
1959 throw new NotImplementedException ("should not be called!");
1962 public virtual void EndExecuteNonQuery (IAsyncResult ar
)
1965 throw new NotImplementedException ("should not be called!");
1968 public virtual IAsyncResult
BeginExecuteQuery (string sql
,
1969 TdsMetaParameterCollection parameters
,
1970 AsyncCallback callback
,
1973 // abstract, kept to be backward compatiable.
1974 throw new NotImplementedException ("should not be called!");
1977 public virtual void EndExecuteQuery (IAsyncResult ar
)
1980 throw new NotImplementedException ("should not be called!");
1983 public virtual IAsyncResult
BeginExecuteProcedure (string prolog
,
1987 TdsMetaParameterCollection parameters
,
1988 AsyncCallback callback
,
1991 throw new NotImplementedException ("should not be called!");
1994 public virtual void EndExecuteProcedure (IAsyncResult ar
)
1997 throw new NotImplementedException ("should not be called!");
2000 public void WaitFor (IAsyncResult ar
)
2002 if (! ar
.IsCompleted
)
2003 ar
.AsyncWaitHandle
.WaitOne ();
2006 public void CheckAndThrowException (IAsyncResult ar
)
2008 TdsAsyncResult result
= (TdsAsyncResult
) ar
;
2009 if (result
.IsCompleted
&& result
.IsCompletedWithException
)
2010 throw result
.Exception
;
2013 #endregion // asynchronous methods