flush
[mcs.git] / class / Mono.Data.Tds / Mono.Data.Tds.Protocol / Tds42.cs
blobfdca83087b1cc65b930f7218a481968462430fa5
1 //
2 // Mono.Data.Tds.Protocol.Tds42.cs
3 //
4 // Author:
5 // Tim Coleman (tim@timcoleman.com)
6 //
7 // Copyright (C) 2002 Tim Coleman
8 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 //
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 //
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System;
33 namespace Mono.Data.Tds.Protocol {
34 public sealed class Tds42 : Tds
36 #region Fields
38 public static readonly TdsVersion Version = TdsVersion.tds42;
40 #endregion // Fields
42 #region Constructors
44 public Tds42 (string server, int port)
45 : this (server, port, 512, 15)
49 public Tds42 (string server, int port, int packetSize, int timeout)
50 : base (server, port, packetSize, timeout, Version)
54 #endregion // Constructors
56 #region Methods
58 public override bool Connect (TdsConnectionParameters connectionParameters)
60 if (IsConnected)
61 throw new InvalidOperationException ("The connection is already open.");
63 SetCharset (connectionParameters.Charset);
64 SetLanguage (connectionParameters.Language);
66 byte pad = (byte) 0;
67 byte[] empty = new byte[0];
69 Comm.StartPacket (TdsPacketType.Logon);
71 // hostname (offset 0)
72 byte[] tmp = Comm.Append (connectionParameters.Hostname, 30, pad);
73 Comm.Append ((byte) (tmp.Length < 30 ? tmp.Length : 30));
75 // username (offset 31 0x1f)
76 tmp = Comm.Append (connectionParameters.User, 30, pad);
77 Comm.Append ((byte) (tmp.Length < 30 ? tmp.Length : 30));
79 // password (offset 62 0x3e)
80 tmp = Comm.Append (connectionParameters.Password, 30, pad);
81 Comm.Append ((byte) (tmp.Length < 30 ? tmp.Length : 30));
83 // hostproc (offset 93 0x5d)
84 Comm.Append ("00000116", 8, pad);
86 // unused (offset 109 0x6d)
87 Comm.Append (empty, (30-14), pad);
89 // apptype
90 Comm.Append ((byte) 0x0);
91 Comm.Append ((byte) 0xa0);
92 Comm.Append ((byte) 0x24);
93 Comm.Append ((byte) 0xcc);
94 Comm.Append ((byte) 0x50);
95 Comm.Append ((byte) 0x12);
97 // hostproc length
98 Comm.Append ((byte) 8);
100 // Byte order of 2 byte ints
101 // 2 = <MSB, LSB>, 3 = <LSB, MSB>
102 Comm.Append ((byte) 3);
104 // Byte order of 4 byte ints
105 // 0 = <MSB, LSB>, 1 = <LSB, MSB>
106 Comm.Append ((byte) 1);
108 // Character representation
109 // (6 = ASCII, 7 = EBCDIC)
110 Comm.Append ((byte) 6);
112 // Eight byte floating point representation
113 // 4 = IEEE <MSB, ..., LSB>
114 // 5 = VAX 'D'
115 // 10 = IEEE <LSB, ..., MSB>
116 // 11 = ND5000
117 Comm.Append ((byte) 10);
119 // Eight byte date format
120 // 8 = <MSB, ..., LSB>
121 Comm.Append ((byte) 9);
123 // notify of use db
124 Comm.Append ((byte) 1);
126 // disallow dump/load and bulk insert
127 Comm.Append ((byte) 1);
129 // sql interface type
130 Comm.Append ((byte) 0);
132 // type of network connection
133 Comm.Append ((byte) 0);
136 // spare [7]
137 Comm.Append (empty, 7, pad);
138 // appname
139 tmp = Comm.Append (connectionParameters.ApplicationName, 30, pad);
140 Comm.Append ((byte) (tmp.Length < 30 ? tmp.Length : 30));
142 // server name
143 tmp = Comm.Append (DataSource, 30, pad);
144 Comm.Append ((byte) (tmp.Length < 30 ? tmp.Length : 30));
146 // remote passwords
147 Comm.Append (empty, 2, pad);
148 tmp = Comm.Append (connectionParameters.Password, 253, pad);
149 Comm.Append ((byte) (tmp.Length < 253 ? tmp.Length + 2 : 253 + 2));
151 // tds version
152 Comm.Append ((byte) (((byte) Version) / 10));
153 Comm.Append ((byte) (((byte) Version) % 10));
154 Comm.Append ((byte) 0);
155 Comm.Append ((byte) 0);
157 // prog name
158 tmp = Comm.Append (connectionParameters.ProgName, 10, pad);
159 Comm.Append ((byte) (tmp.Length < 10 ? tmp.Length : 10));
161 // prog version
162 Comm.Append ((byte) 6);
164 // Tell the server we can handle SQLServer version 6
165 Comm.Append ((byte) 0);
167 // Send zero to tell the server we can't handle any other version
168 Comm.Append ((byte) 0);
169 Comm.Append ((byte) 0);
171 // auto convert short
172 Comm.Append ((byte) 0);
174 // type of flt4
175 Comm.Append ((byte) 0x0d);
177 // type of date4
178 Comm.Append ((byte) 0x11);
180 // language
181 tmp = Comm.Append (Language, 30, pad);
182 Comm.Append ((byte) (tmp.Length < 30 ? tmp.Length : 30));
184 // notify on lang change
185 Comm.Append ((byte) 1);
187 // security label hierarchy
188 Comm.Append ((short) 0);
190 // security components
191 Comm.Append (empty, 8, pad);
193 // security spare
194 Comm.Append ((short) 0);
196 // security login role
197 Comm.Append ((byte) 0);
199 // charset
200 tmp = Comm.Append (Charset, 30, pad);
201 Comm.Append ((byte) (tmp.Length < 30 ? tmp.Length : 30));
203 // notify on charset change
204 Comm.Append ((byte) 1);
206 // length of tds packets
207 tmp = Comm.Append (PacketSize.ToString (), 6, pad);
208 Comm.Append ((byte) 3);
210 // pad out to a longword
211 Comm.Append (empty, 8, pad);
213 Comm.SendPacket ();
215 MoreResults = true;
216 SkipToEnd ();
218 return IsConnected;
221 protected override void ProcessColumnInfo ()
223 byte precision;
224 byte scale;
225 int totalLength = Comm.GetTdsShort ();
226 int bytesRead = 0;
228 while (bytesRead < totalLength) {
229 scale = 0;
230 precision = 0;
232 int bufLength = -1;
233 byte[] flagData = new byte[4];
234 for (int i = 0; i < 4; i += 1) {
235 flagData[i] = Comm.GetByte ();
236 bytesRead += 1;
238 bool nullable = (flagData[2] & 0x01) > 0;
239 //bool caseSensitive = (flagData[2] & 0x02) > 0;
240 bool writable = (flagData[2] & 0x0c) > 0;
241 //bool autoIncrement = (flagData[2] & 0x10) > 0;
243 string tableName = String.Empty;
244 TdsColumnType columnType = (TdsColumnType) Comm.GetByte ();
246 bytesRead += 1;
248 if (columnType == TdsColumnType.Text || columnType == TdsColumnType.Image) {
249 Comm.Skip (4);
250 bytesRead += 4;
252 int tableNameLength = Comm.GetTdsShort ();
253 bytesRead += 2;
254 tableName = Comm.GetString (tableNameLength);
255 bytesRead += tableNameLength;
256 bufLength = 2 << 31 - 1;
258 else if (columnType == TdsColumnType.Decimal || columnType == TdsColumnType.Numeric) {
259 bufLength = Comm.GetByte ();
260 bytesRead += 1;
261 precision = Comm.GetByte ();
262 bytesRead += 1;
263 scale = Comm.GetByte ();
264 bytesRead += 1;
266 else if (IsFixedSizeColumn (columnType))
267 bufLength = LookupBufferSize (columnType);
268 else {
269 bufLength = (int) Comm.GetByte () & 0xff;
270 bytesRead += 1;
273 TdsDataColumn col = new TdsDataColumn ();
274 int index = Columns.Add (col);
275 #if NET_2_0
276 col.ColumnType = columnType;
277 col.ColumnSize = bufLength;
278 col.ColumnName = ColumnNames[index] as string;
279 col.NumericPrecision = precision;
280 col.NumericScale = scale;
281 col.IsReadOnly = !writable;
282 col.BaseTableName = tableName;
283 col.AllowDBNull = nullable;
284 #else
285 col["ColumnType"] = columnType;
286 col["ColumnSize"] = bufLength;
287 col["ColumnName"] = ColumnNames[index];
288 col["NumericPrecision"] = precision;
289 col["NumericScale"] = scale;
290 col["IsReadOnly"] = !writable;
291 col["BaseTableName"] = tableName;
292 col["AllowDBNull"] = nullable;
293 #endif
297 #endregion // Methods