Add a more functional (i.e. fewer-stubs) implementation of System.Data.Linq.
[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 // Copyright (C) 2002 Tim Coleman
8 // Copyright (C) 2008,2009 Novell Inc.
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using Mono.Data.Tds;
33 using System;
34
35 namespace Mono.Data.Tds.Protocol {
36         public class Tds80 : Tds70
37         {
38                 #region Fields
39
40                 public static readonly TdsVersion Version = TdsVersion.tds80;
41
42                 #endregion // Fields
43
44                 #region Constructors
45
46                 public Tds80 (string server, int port)
47                         : this (server, port, 512, 15)
48                 {
49                 }
50
51                 public Tds80 (string server, int port, int packetSize, int timeout)
52                         : base (server, port, packetSize, timeout, Version)
53                 {
54                 }
55
56                 #endregion // Constructors
57
58                 #region Properties
59                 
60                 protected override byte[] ClientVersion {
61                         get { return new byte[] {0x00, 0x0, 0x0, 0x71};}
62                 }
63                 #endregion // Properties
64                 
65                 #region Methods
66
67                 public override bool Connect (TdsConnectionParameters connectionParameters)
68                 {
69                         return base.Connect (connectionParameters);
70                 }
71
72                 protected override TdsDataColumnCollection ProcessColumnInfo ()
73                 {
74                         // VARADHAN: TDS 8 Debugging
75                         //Console.WriteLine ("Tds80.cs: In ProcessColumnInfo... entry");
76                         TdsDataColumnCollection result = new TdsDataColumnCollection ();
77                         int numColumns = Comm.GetTdsShort ();
78                         //Console.WriteLine ("Column count={0}", numColumns); TDS 8 Debugging
79                         for (int i = 0; i < numColumns; i += 1) {
80                                 byte[] flagData = new byte[4];
81                                 for (int j = 0; j < 4; j += 1) 
82                                         flagData[j] = Comm.GetByte ();
83
84                                 bool nullable = (flagData[2] & 0x01) > 0;
85                                 //bool caseSensitive = (flagData[2] & 0x02) > 0;
86                                 bool writable = (flagData[2] & 0x0c) > 0;
87                                 bool autoIncrement = (flagData[2] & 0x10) > 0;
88                                 bool isIdentity = (flagData[2] & 0x10) > 0;
89
90                                 TdsColumnType columnType = (TdsColumnType) (Comm.GetByte () & 0xff);
91                                 //Console.WriteLine ("Actual ColumnType: {0}", columnType);  TDS 8 Debugging
92
93                                 if ((byte) columnType == 0xef)
94                                         columnType = TdsColumnType.NChar;
95
96                                 TdsColumnType xColumnType = columnType;
97                                 if (IsLargeType (columnType)) {
98                                         if (columnType != TdsColumnType.NChar)
99                                                 columnType -= 128;
100                                 }
101
102                                 int columnSize;
103                                 string tableName = null;
104                                 byte[] collation = null;
105
106                                 if (IsBlobType (columnType)) {
107                                         columnSize = Comm.GetTdsInt ();
108                                 } else if (IsFixedSizeColumn (columnType)) {
109                                         columnSize = LookupBufferSize (columnType);
110                                 } else if (IsLargeType (xColumnType)) {
111                                         columnSize = Comm.GetTdsShort ();
112                                 } else  {
113                                         columnSize = Comm.GetByte () & 0xff;
114                                 }
115
116                                 if (xColumnType == TdsColumnType.BigChar || xColumnType == TdsColumnType.BigNVarChar ||
117                                     xColumnType == TdsColumnType.BigVarChar || xColumnType == TdsColumnType.NChar ||
118                                     xColumnType == TdsColumnType.NVarChar ||   xColumnType == TdsColumnType.Text ||
119                                     xColumnType == TdsColumnType.NText) {
120                                     // Read collation for SqlServer 2000 and beyond
121                                     collation = Comm.GetBytes (5, true);
122                                 }
123
124                                 if (IsBlobType (columnType)) {
125                                         tableName = Comm.GetString (Comm.GetTdsShort ());
126                                         //Console.WriteLine ("Tablename: "+tableName);  TDS 8 Debugging
127                                 }
128
129                                 byte precision = 0;
130                                 byte scale = 0;
131
132                                 switch (columnType) {
133                                 case TdsColumnType.NText:
134                                 case TdsColumnType.NChar:
135                                 case TdsColumnType.NVarChar:
136                                         columnSize /= 2;
137                                         break;
138                                 case TdsColumnType.Decimal:
139                                 case TdsColumnType.Numeric:
140                                         //Comm.Skip (1);
141                                         precision = Comm.GetByte ();
142                                         //Console.WriteLine ("Precision: {0}", precision);  TDS 8 Debugging
143                                         scale = Comm.GetByte ();
144                                         //Console.WriteLine ("Scale: {0}", scale);  TDS 8 Debugging
145                                         break;
146                                 }
147
148                                 string columnName = Comm.GetString (Comm.GetByte ());
149
150                                 TdsDataColumn col = new TdsDataColumn ();
151                                 result.Add (col);
152 #if NET_2_0
153                                 col.ColumnType = columnType;
154                                 col.ColumnName = columnName;
155                                 col.IsAutoIncrement = autoIncrement;
156                                 col.IsIdentity = isIdentity;
157                                 col.ColumnSize = columnSize;
158                                 col.NumericPrecision = precision;
159                                 col.NumericScale = scale;
160                                 col.IsReadOnly = !writable;
161                                 col.AllowDBNull = nullable;
162                                 col.BaseTableName = tableName;
163 #else
164                                 col ["ColumnType"] = columnType;
165                                 col ["ColumnName"] = columnName;
166                                 col ["IsAutoIncrement"] = autoIncrement;
167                                 col ["IsIdentity"] = isIdentity;
168                                 col ["ColumnSize"] = columnSize;
169                                 col ["NumericPrecision"] = precision;
170                                 col ["NumericScale"] = scale;
171                                 col ["IsReadOnly"] = !writable;
172                                 col ["AllowDBNull"] = nullable;
173                                 col ["BaseTableName"] = tableName;
174 #endif
175                         }
176                         //Console.WriteLine ("Tds80.cs: In ProcessColumnInfo... exit");  TDS 8 Debugging
177                         return result;
178                 }
179
180                 protected override void ProcessOutputParam ()
181                 {
182                         GetSubPacketLength ();
183                         
184                         Comm.Skip ((Comm.GetByte () & 0xff) <<1); // Parameter name
185                         Comm.Skip (1);  // Status: 0x01 - in case of OUTPUT parameter
186                                                         // Status: 0x02 - in case of return value of UDF
187                         Comm.Skip (4);  // Usertype - sizeof (ULong)
188
189                         TdsColumnType colType = (TdsColumnType) Comm.GetByte ();
190                         object value = GetColumnValue (colType, true);
191                         OutputParameters.Add (value);
192                 }
193                 
194                 #endregion // Methods
195         }
196 }