Merge pull request #1 from knocte/master
[mono.git] / mcs / class / Mono.Data.Tds / Mono.Data.Tds.Protocol / Tds80.cs
1 //
2 // Mono.Data.Tds.Protocol.Tds80.cs
3 //
4 // Author:
5 //   Tim Coleman (tim@timcoleman.com)
6 //       Veerapuram Varadhan  (vvaradhan@novell.com)
7 //
8 // Copyright (C) 2002 Tim Coleman
9 // Copyright (C) 2008,2009 Novell Inc.
10 //
11
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using Mono.Data.Tds;
34 using System;
35
36 namespace Mono.Data.Tds.Protocol {
37         public class Tds80 : Tds70
38         {
39                 #region Fields
40
41                 public static readonly TdsVersion Version = TdsVersion.tds80;
42
43                 #endregion // Fields
44
45                 #region Constructors
46
47                 [Obsolete ("Use the constructor that receives a lifetime parameter")]
48                 public Tds80 (string server, int port)
49                         : this (server, port, 512, 15, 0)
50                 {
51                 }
52
53                 [Obsolete ("Use the constructor that receives a lifetime parameter")]
54                 public Tds80 (string server, int port, int packetSize, int timeout)
55                         : base (server, port, packetSize, timeout, 0, Version)
56                 {
57                 }
58
59                 public Tds80 (string server, int port, int lifetime)
60                         : this (server, port, 512, 15, lifetime)
61                 {
62                 }
63
64                 public Tds80 (string server, int port, int packetSize, int timeout, int lifeTime)
65                         : base (server, port, packetSize, timeout, lifeTime, Version)
66                 {
67                 }
68
69                 #endregion // Constructors
70
71                 #region Properties
72                 
73                 protected override byte[] ClientVersion {
74                         get { return new byte[] {0x00, 0x0, 0x0, 0x71};}
75                 }
76                 protected override byte Precision {
77                         get { return 38; }
78                 }
79                 
80                 #endregion // Properties
81                 
82                 #region Methods
83
84                 public override bool Connect (TdsConnectionParameters connectionParameters)
85                 {
86                         //Console.WriteLine ("Tds80::Connect");
87                         return base.Connect (connectionParameters);
88                 }
89
90                 protected override void ProcessColumnInfo ()
91                 {
92                         // We are connected to a Sql 7.0 server
93                         if (TdsVersion < TdsVersion.tds80) {
94                                 base.ProcessColumnInfo ();
95                                 return;
96                         }
97                         
98                         // VARADHAN: TDS 8 Debugging
99                         //Console.WriteLine ("Tds80.cs: In ProcessColumnInfo... entry");
100                         int numColumns = Comm.GetTdsShort ();
101                         //Console.WriteLine ("Column count={0}", numColumns); TDS 8 Debugging
102                         for (int i = 0; i < numColumns; i += 1) {
103                                 byte[] flagData = new byte[4];
104                                 for (int j = 0; j < 4; j += 1) 
105                                         flagData[j] = Comm.GetByte ();
106
107                                 bool nullable = (flagData[2] & 0x01) > 0;
108                                 //bool caseSensitive = (flagData[2] & 0x02) > 0;
109                                 bool writable = (flagData[2] & 0x0c) > 0;
110                                 bool autoIncrement = (flagData[2] & 0x10) > 0;
111                                 bool isIdentity = (flagData[2] & 0x10) > 0;
112
113                                 TdsColumnType columnType = (TdsColumnType) (Comm.GetByte () & 0xff);
114                                 //Console.WriteLine ("Actual ColumnType: {0}", columnType);  TDS 8 Debugging
115
116                                 if ((byte) columnType == 0xef)
117                                         columnType = TdsColumnType.NChar;
118
119                                 TdsColumnType xColumnType = columnType;
120                                 if (IsLargeType (columnType)) {
121                                         if (columnType != TdsColumnType.NChar)
122                                                 columnType -= 128;
123                                 }
124
125                                 int columnSize;
126                                 string tableName = null;
127                                 byte[] collation = null;
128                                 int lcid = 0, sortId = 0;
129
130                                 if (IsBlobType (columnType)) {
131                                         columnSize = Comm.GetTdsInt ();
132                                 } else if (IsFixedSizeColumn (columnType)) {
133                                         columnSize = LookupBufferSize (columnType);
134                                 } else if (IsLargeType (xColumnType)) {
135                                         columnSize = Comm.GetTdsShort ();
136                                 } else  {
137                                         columnSize = Comm.GetByte () & 0xff;
138                                 }
139
140                                 if (xColumnType == TdsColumnType.BigChar || xColumnType == TdsColumnType.BigNVarChar ||
141                                     xColumnType == TdsColumnType.BigVarChar || xColumnType == TdsColumnType.NChar ||
142                                     xColumnType == TdsColumnType.NVarChar ||   xColumnType == TdsColumnType.Text ||
143                                     xColumnType == TdsColumnType.NText) {
144                                     // Read collation for SqlServer 2000 and beyond
145                                     collation = Comm.GetBytes (5, true);
146                                         lcid = TdsCollation.LCID (collation);
147                                         sortId = TdsCollation.SortId (collation);
148                                 }
149
150                                 if (IsBlobType (columnType)) {
151                                         tableName = Comm.GetString (Comm.GetTdsShort ());
152                                         //Console.WriteLine ("Tablename: "+tableName);  TDS 8 Debugging
153                                 }
154
155                                 byte precision = 0;
156                                 byte scale = 0;
157
158                                 switch (columnType) {
159                                 case TdsColumnType.NText:
160                                 case TdsColumnType.NChar:
161                                 case TdsColumnType.NVarChar:
162                                         columnSize /= 2;
163                                         break;
164                                 case TdsColumnType.Decimal:
165                                 case TdsColumnType.Numeric:
166                                         //Comm.Skip (1);
167                                         precision = Comm.GetByte ();
168                                         //Console.WriteLine ("Precision: {0}", precision);  TDS 8 Debugging
169                                         scale = Comm.GetByte ();
170                                         //Console.WriteLine ("Scale: {0}", scale);  TDS 8 Debugging
171                                         break;
172                                 }
173
174                                 string columnName = Comm.GetString (Comm.GetByte ());
175
176                                 TdsDataColumn col = new TdsDataColumn ();
177                                 Columns.Add (col);
178 #if NET_2_0
179                                 col.ColumnType = columnType;
180                                 col.ColumnName = columnName;
181                                 col.IsAutoIncrement = autoIncrement;
182                                 col.IsIdentity = isIdentity;
183                                 col.ColumnSize = columnSize;
184                                 col.NumericPrecision = precision;
185                                 col.NumericScale = scale;
186                                 col.IsReadOnly = !writable;
187                                 col.AllowDBNull = nullable;
188                                 col.BaseTableName = tableName;
189                                 col.LCID = lcid;
190                                 col.SortOrder = sortId;
191 #else
192                                 col ["ColumnType"] = columnType;
193                                 col ["ColumnName"] = columnName;
194                                 col ["IsAutoIncrement"] = autoIncrement;
195                                 col ["IsIdentity"] = isIdentity;
196                                 col ["ColumnSize"] = columnSize;
197                                 col ["NumericPrecision"] = precision;
198                                 col ["NumericScale"] = scale;
199                                 col ["IsReadOnly"] = !writable;
200                                 col ["AllowDBNull"] = nullable;
201                                 col ["BaseTableName"] = tableName;
202                                 col ["LCID"] = lcid;
203                                 col ["SortOrder"] = sortId;
204 #endif
205                         }
206                         //Console.WriteLine ("Tds80.cs: In ProcessColumnInfo... exit");  TDS 8 Debugging
207                 }
208
209                 protected override void ProcessOutputParam ()
210                 {
211                         // We are connected to a Sql 7.0 server
212                         if (TdsVersion < TdsVersion.tds80) {
213                                 base.ProcessOutputParam ();
214                                 return;
215                         }
216
217                         GetSubPacketLength ();
218                         
219                         Comm.Skip ((Comm.GetByte () & 0xff) <<1); // Parameter name
220                         Comm.Skip (1);  // Status: 0x01 - in case of OUTPUT parameter
221                                                         // Status: 0x02 - in case of return value of UDF
222                         Comm.Skip (4);  // Usertype - sizeof (ULong)
223
224                         TdsColumnType colType = (TdsColumnType) Comm.GetByte ();
225                         object value = GetColumnValue (colType, true);
226                         OutputParameters.Add (value);
227                 }
228                 
229                 public override void Execute (string commandText, TdsMetaParameterCollection parameters, int timeout, bool wantResults)
230                 {
231                         // We are connected to a Sql 7.0 server
232                         if (TdsVersion < TdsVersion.tds80) {
233                                 base.Execute (commandText, parameters, timeout, wantResults);
234                                 return;
235                         }
236
237                         Parameters = parameters;
238                         string sql = commandText;
239
240                         if (Parameters != null && Parameters.Count > 0) {
241                                 ExecRPC (TdsRpcProcId.ExecuteSql, commandText, parameters, timeout, wantResults);
242                         } else {
243                                 if (wantResults)
244                                         sql = BuildExec (commandText);
245                                 ExecuteQuery (sql, timeout, wantResults);
246                         }
247                 }
248                 
249                 public override void ExecPrepared (string commandText, TdsMetaParameterCollection parameters, int timeout, bool wantResults)
250                 {
251                         Parameters = parameters;
252                         // We are connected to a Sql 7.0 server
253                         if (TdsVersion < TdsVersion.tds80 || 
254                             Parameters == null || Parameters.Count < 1) {
255                                 base.ExecPrepared (commandText, parameters, timeout, wantResults);
256                                 return;
257                         }
258                         TdsMetaParameterCollection parms = new TdsMetaParameterCollection ();
259                         parms.Add (new TdsMetaParameter ("@Handle", "int", Int32.Parse (commandText)));
260                         foreach (TdsMetaParameter parm in Parameters)
261                                 parms.Add (parm);
262                         
263                         ExecRPC ("sp_execute", parms, timeout, wantResults);                    
264                 }
265
266                 #endregion // Methods
267         }
268 }