(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / Mono.Data.TdsClient / Mono.Data.TdsClient / TdsCommand.cs
blob4a25e4c58bdb1c84c471c9c295d28c04b43c060f
1 //
2 // Mono.Data.TdsClient.TdsCommand.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 http://www.ximian.com/
10 // (C) Daniel Morgan, 2002
11 // Copyright (C) Tim Coleman, 2002
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.
35 using Mono.Data.Tds;
36 using Mono.Data.Tds.Protocol;
37 using System;
38 using System.Collections;
39 using System.Collections.Specialized;
40 using System.ComponentModel;
41 using System.Data;
42 using System.Data.Common;
43 using System.Runtime.InteropServices;
44 using System.Text;
46 namespace Mono.Data.TdsClient {
47 public sealed class TdsCommand : Component, IDbCommand, ICloneable
49 #region Fields
51 bool disposed = false;
52 int commandTimeout;
53 bool designTimeVisible;
54 string commandText;
55 CommandType commandType;
56 TdsConnection connection;
57 TdsTransaction transaction;
58 UpdateRowSource updatedRowSource;
59 CommandBehavior behavior = CommandBehavior.Default;
60 TdsParameterCollection parameters;
62 #endregion // Fields
64 #region Constructors
66 public TdsCommand()
67 : this (String.Empty, null, null)
71 public TdsCommand (string commandText)
72 : this (commandText, null, null)
74 commandText = commandText;
77 public TdsCommand (string commandText, TdsConnection connection)
78 : this (commandText, connection, null)
80 Connection = connection;
83 public TdsCommand (string commandText, TdsConnection connection, TdsTransaction transaction)
85 this.commandText = commandText;
86 this.connection = connection;
87 this.transaction = transaction;
88 this.commandType = CommandType.Text;
89 this.updatedRowSource = UpdateRowSource.Both;
91 this.designTimeVisible = false;
92 this.commandTimeout = 30;
93 parameters = new TdsParameterCollection (this);
96 #endregion // Constructors
98 #region Properties
100 internal CommandBehavior CommandBehavior {
101 get { return behavior; }
104 public string CommandText {
105 get { return commandText; }
106 set { commandText = value; }
109 public int CommandTimeout {
110 get { return commandTimeout; }
111 set {
112 if (commandTimeout < 0)
113 throw new ArgumentException ("The property value assigned is less than 0.");
114 commandTimeout = value;
118 public CommandType CommandType {
119 get { return commandType; }
120 set {
121 if (value == CommandType.TableDirect)
122 throw new ArgumentException ("CommandType.TableDirect is not supported by the Mono TdsClient Data Provider.");
123 commandType = value;
127 public TdsConnection Connection {
128 get { return connection; }
129 set {
130 if (transaction != null && connection.Transaction != null && connection.Transaction.IsOpen)
131 throw new InvalidOperationException ("The Connection property was changed while a transaction was in progress.");
132 transaction = null;
133 connection = value;
137 public bool DesignTimeVisible {
138 get { return designTimeVisible; }
139 set { designTimeVisible = value; }
142 public TdsParameterCollection Parameters {
143 get { return parameters; }
146 internal ITds Tds {
147 get { return Connection.Tds; }
150 IDbConnection IDbCommand.Connection {
151 get { return Connection; }
152 set {
153 if (!(value is TdsConnection))
154 throw new InvalidCastException ("The value was not a valid TdsConnection.");
155 Connection = (TdsConnection) value;
159 IDataParameterCollection IDbCommand.Parameters {
160 get { return Parameters; }
163 IDbTransaction IDbCommand.Transaction {
164 get { return Transaction; }
165 set {
166 if (!(value is TdsTransaction))
167 throw new ArgumentException ();
168 Transaction = (TdsTransaction) value;
172 public TdsTransaction Transaction {
173 get { return transaction; }
174 set { transaction = value; }
177 public UpdateRowSource UpdatedRowSource {
178 get { return updatedRowSource; }
179 set { updatedRowSource = value; }
182 #endregion // Fields
184 #region Methods
186 public void Cancel ()
188 if (Connection == null || Connection.Tds == null)
189 return;
190 Connection.Tds.Cancel ();
193 internal void CloseDataReader (bool moreResults)
195 GetOutputParameters ();
196 Connection.DataReader = null;
198 if ((behavior & CommandBehavior.CloseConnection) != 0)
199 Connection.Close ();
202 public TdsParameter CreateParameter ()
204 return new TdsParameter ();
207 internal void DeriveParameters ()
209 if (commandType != CommandType.StoredProcedure)
210 throw new InvalidOperationException (String.Format ("TdsCommand DeriveParameters only supports CommandType.StoredProcedure, not CommandType.{0}", commandType));
211 ValidateCommand ("DeriveParameters");
213 TdsParameterCollection localParameters = new TdsParameterCollection (this);
214 localParameters.Add ("@P1", TdsType.NVarChar, commandText.Length).Value = commandText;
216 string sql = "sp_procedure_params_rowset";
218 Connection.Tds.ExecProc (sql, localParameters.MetaParameters, 0, true);
220 TdsDataReader reader = new TdsDataReader (this);
221 parameters.Clear ();
222 object[] dbValues = new object[reader.FieldCount];
224 while (reader.Read ()) {
225 reader.GetValues (dbValues);
226 parameters.Add (new TdsParameter (dbValues));
228 reader.Close ();
231 private void Execute (CommandBehavior behavior, bool wantResults)
233 TdsMetaParameterCollection parms = Parameters.MetaParameters;
234 bool schemaOnly = ((CommandBehavior & CommandBehavior.SchemaOnly) > 0);
235 bool keyInfo = ((CommandBehavior & CommandBehavior.SchemaOnly) > 0);
237 StringBuilder sql1 = new StringBuilder ();
238 StringBuilder sql2 = new StringBuilder ();
240 if (schemaOnly || keyInfo)
241 sql1.Append ("SET FMTONLY OFF;");
242 if (keyInfo) {
243 sql1.Append ("SET NO_BROWSETABLE ON;");
244 sql2.Append ("SET NO_BROWSETABLE OFF;");
246 if (schemaOnly) {
247 sql1.Append ("SET FMTONLY ON;");
248 sql2.Append ("SET FMTONLY OFF;");
251 switch (CommandType) {
252 case CommandType.StoredProcedure:
253 if (keyInfo || schemaOnly)
254 Connection.Tds.Execute (sql1.ToString ());
255 Connection.Tds.ExecProc (CommandText, parms, CommandTimeout, wantResults);
256 if (keyInfo || schemaOnly)
257 Connection.Tds.Execute (sql2.ToString ());
258 break;
259 case CommandType.Text:
260 string sql = String.Format ("{0}{1}{2}", sql1.ToString (), CommandText, sql2.ToString ());
261 Connection.Tds.Execute (sql, parms, CommandTimeout, wantResults);
262 break;
266 public int ExecuteNonQuery ()
268 ValidateCommand ("ExecuteNonQuery");
269 int result = 0;
271 try {
272 Execute (CommandBehavior.Default, false);
274 catch (TdsTimeoutException e) {
275 throw TdsException.FromTdsInternalException ((TdsInternalException) e);
278 GetOutputParameters ();
279 return result;
282 public TdsDataReader ExecuteReader ()
284 return ExecuteReader (CommandBehavior.Default);
287 public TdsDataReader ExecuteReader (CommandBehavior behavior)
289 ValidateCommand ("ExecuteReader");
290 try {
291 Execute (behavior, true);
293 catch (TdsTimeoutException e) {
294 throw TdsException.FromTdsInternalException ((TdsInternalException) e);
296 Connection.DataReader = new TdsDataReader (this);
297 return Connection.DataReader;
300 public object ExecuteScalar ()
302 ValidateCommand ("ExecuteScalar");
303 try {
304 Execute (CommandBehavior.Default, true);
306 catch (TdsTimeoutException e) {
307 throw TdsException.FromTdsInternalException ((TdsInternalException) e);
310 if (!Connection.Tds.NextResult () || !Connection.Tds.NextRow ())
311 return null;
313 object result = Connection.Tds.ColumnValues [0];
314 CloseDataReader (true);
315 return result;
318 private void GetOutputParameters ()
320 Connection.Tds.SkipToEnd ();
322 IList list = Connection.Tds.ColumnValues;
324 if (list != null && list.Count > 0) {
325 int index = 0;
326 foreach (TdsParameter parameter in parameters) {
327 if (parameter.Direction != ParameterDirection.Input) {
328 parameter.Value = list [index];
329 index += 1;
331 if (index >= list.Count)
332 break;
337 object ICloneable.Clone ()
339 return new TdsCommand (commandText, Connection);
342 IDbDataParameter IDbCommand.CreateParameter ()
344 return CreateParameter ();
347 IDataReader IDbCommand.ExecuteReader ()
349 return ExecuteReader ();
352 IDataReader IDbCommand.ExecuteReader (CommandBehavior behavior)
354 return ExecuteReader (behavior);
357 public void Prepare ()
359 throw new NotSupportedException ("TdsClient does not support PREPARE.");
362 public void ResetCommandTimeout ()
364 commandTimeout = 30;
367 private void ValidateCommand (string method)
369 if (Connection == null)
370 throw new InvalidOperationException (String.Format ("{0} requires a Connection object to continue.", method));
371 if (Connection.Transaction != null && transaction != Connection.Transaction)
372 throw new InvalidOperationException ("The Connection object does not have the same transaction as the command object.");
373 if (Connection.State != ConnectionState.Open)
374 throw new InvalidOperationException (String.Format ("ExecuteNonQuery requires an open Connection object to continue. This connection is closed.", method));
375 if (commandText == String.Empty || commandText == null)
376 throw new InvalidOperationException ("The command text for this Command has not been set.");
377 if (Connection.DataReader != null)
378 throw new InvalidOperationException ("There is already an open DataReader associated with this Connection which must be closed first.");
381 #endregion // Methods