2 // System.Data.Odbc.OdbcCommand
5 // Brian Ritchie (brianlritchie@hotmail.com)
7 // Copyright (C) Brian Ritchie, 2002
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
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:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
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.
34 using System.ComponentModel;
36 using System.Data.Common;
37 using System.Collections;
38 using System.Runtime.InteropServices;
40 namespace System.Data.Odbc
43 /// Represents an SQL statement or stored procedure to execute against a data source.
45 [DesignerAttribute ("Microsoft.VSDesigner.Data.VS.OdbcCommandDesigner, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.IDesigner")]
46 [ToolboxItemAttribute ("System.Drawing.Design.ToolboxItem, "+ Consts.AssemblySystem_Drawing)]
48 public sealed class OdbcCommand : DbCommand, ICloneable
50 public sealed class OdbcCommand : Component, ICloneable, IDbCommand
57 CommandType commandType;
58 UpdateRowSource updateRowSource = UpdateRowSource.Both;
60 OdbcConnection connection;
61 OdbcTransaction transaction;
62 OdbcParameterCollection _parameters;
64 bool designTimeVisible;
66 IntPtr hstmt = IntPtr.Zero;
68 bool disposed = false;
76 this.CommandText = String.Empty;
77 this.CommandTimeout = 30; // default timeout
78 this.CommandType = CommandType.Text;
80 _parameters = new OdbcParameterCollection ();
82 designTimeVisible = false;
84 updateRowSource = UpdateRowSource.Both;
88 public OdbcCommand (string cmdText) : this ()
90 CommandText = cmdText;
93 public OdbcCommand (string cmdText, OdbcConnection connection)
96 Connection = connection;
99 public OdbcCommand (string cmdText,
100 OdbcConnection connection,
101 OdbcTransaction transaction) : this (cmdText, connection)
103 this.Transaction = transaction;
106 #endregion // Constructors
110 internal IntPtr hStmt
112 get { return hstmt; }
116 [OdbcCategory ("Data")]
118 [OdbcDescriptionAttribute ("Command text to execute")]
119 [EditorAttribute ("Microsoft.VSDesigner.Data.Odbc.Design.OdbcCommandTextEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]
120 [RefreshPropertiesAttribute (RefreshProperties.All)]
127 get { return commandText; }
134 [OdbcDescriptionAttribute ("Time to wait for command to execute")]
135 #if NET_1_0 || ONLY_1_1
143 get { return timeout; }
144 set { timeout = value; }
147 [OdbcCategory ("Data")]
148 [DefaultValue ("Text")]
149 [OdbcDescriptionAttribute ("How to interpret the CommandText")]
150 [RefreshPropertiesAttribute (RefreshProperties.All)]
155 CommandType CommandType {
156 get { return commandType; }
157 set { commandType = value; }
161 [OdbcCategory ("Behavior")]
162 [OdbcDescriptionAttribute ("Connection used by the command")]
163 [DefaultValue (null)]
164 [EditorAttribute ("Microsoft.VSDesigner.Data.Design.DbConnectionEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]
165 public OdbcConnection Connection {
176 [DefaultValue (null)]
177 [EditorAttribute ("Microsoft.VSDesigner.Data.Design.DbConnectionEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]
178 public new OdbcConnection Connection
180 get { return DbConnection as OdbcConnection; }
181 set { DbConnection = value; }
186 [BrowsableAttribute (false)]
187 [DesignOnlyAttribute (true)]
188 [DefaultValue (true)]
190 [EditorBrowsable (EditorBrowsableState.Never)]
192 [Editor ("Microsoft.VSDesigner.Data.Design.DbConnectionEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]
198 bool DesignTimeVisible {
200 return designTimeVisible;
203 designTimeVisible = value;
208 [OdbcCategory ("Data")]
209 [OdbcDescriptionAttribute ("The parameters collection")]
210 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Content)]
215 OdbcParameterCollection Parameters {
220 return base.Parameters as OdbcParameterCollection;
226 [BrowsableAttribute (false)]
227 [OdbcDescriptionAttribute ("The transaction used by the command")]
228 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
233 OdbcTransaction Transaction {
242 [OdbcCategory ("Behavior")]
243 [DefaultValue (UpdateRowSource.Both)]
244 [OdbcDescriptionAttribute ("When used by a DataAdapter.Update, how command results are applied to the current DataRow")]
249 UpdateRowSource UpdatedRowSource {
251 return updateRowSource;
254 updateRowSource = value;
259 protected override DbConnection DbConnection
261 get { return connection; }
263 connection = (OdbcConnection) value;
271 IDbConnection IDbCommand.Connection {
276 Connection = (OdbcConnection) value;
280 IDataParameterCollection IDbCommand.Parameters {
286 protected override DbParameterCollection DbParameterCollection
288 get { return _parameters as DbParameterCollection;}
294 IDbTransaction IDbCommand.Transaction {
296 return (IDbTransaction) Transaction;
299 if (value is OdbcTransaction)
301 Transaction = (OdbcTransaction)value;
305 throw new ArgumentException ();
310 protected override DbTransaction DbTransaction
312 get { return transaction; }
314 transaction = (OdbcTransaction)value;
321 #endregion // Properties
331 if (hstmt!=IntPtr.Zero)
333 OdbcReturn Ret=libodbc.SQLCancel(hstmt);
334 if ((Ret!=OdbcReturn.Success) && (Ret!=OdbcReturn.SuccessWithInfo))
335 throw new OdbcException(new OdbcError("SQLCancel",OdbcHandleType.Stmt,hstmt));
338 throw new InvalidOperationException();
342 IDbDataParameter IDbCommand.CreateParameter ()
344 return CreateParameter ();
348 protected override DbParameter CreateDbParameter ()
350 return CreateParameter ();
355 public new OdbcParameter CreateParameter ()
357 return new OdbcParameter ();
360 protected override void Dispose (bool disposing)
365 FreeStatement (); // free handles
371 private IntPtr ReAllocStatment ()
375 if (hstmt != IntPtr.Zero)
378 ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt, Connection.hDbc, ref hstmt);
379 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
380 throw new OdbcException(new OdbcError("SQLAllocHandle",OdbcHandleType.Dbc,Connection.hDbc));
385 private void FreeStatement ()
387 if (hstmt == IntPtr.Zero)
390 // free previously allocated handle.
391 OdbcReturn ret = libodbc.SQLFreeStmt (hstmt, libodbc.SQLFreeStmtOptions.Close);
392 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
393 throw new OdbcException(new OdbcError("SQLCloseCursor",OdbcHandleType.Stmt,hstmt));
395 ret = libodbc.SQLFreeHandle( (ushort) OdbcHandleType.Stmt, hstmt);
396 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
397 throw new OdbcException(new OdbcError("SQLFreeHandle",OdbcHandleType.Stmt,hstmt));
401 private void ExecSQL(string sql)
404 if (! prepared && Parameters.Count <= 0) {
408 ret = libodbc.SQLExecDirect (hstmt, sql, libodbc.SQL_NTS);
409 if ((ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo) &&
410 (ret != OdbcReturn.NoData))
411 throw new OdbcException(new OdbcError("SQLExecDirect",OdbcHandleType.Stmt,hstmt));
419 ret=libodbc.SQLExecute(hstmt);
420 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
421 throw new OdbcException(new OdbcError("SQLExecute",OdbcHandleType.Stmt,hstmt));
424 internal void FreeIfNotPrepared ()
434 int ExecuteNonQuery ()
436 return ExecuteNonQuery (true);
439 private int ExecuteNonQuery (bool freeHandle)
442 if (Connection == null)
443 throw new InvalidOperationException ("No open connection");
444 if (Connection.State == ConnectionState.Closed)
445 throw new InvalidOperationException ("Connection state is closed");
446 // FIXME: a third check is mentioned in .NET docs
448 ExecSQL(CommandText);
450 // .NET documentation says that except for INSERT, UPDATE and
451 // DELETE where the return value is the number of rows affected
452 // for the rest of the commands the return value is -1.
453 if ((CommandText.ToUpper().IndexOf("UPDATE")!=-1) ||
454 (CommandText.ToUpper().IndexOf("INSERT")!=-1) ||
455 (CommandText.ToUpper().IndexOf("DELETE")!=-1)) {
458 OdbcReturn ret = libodbc.SQLRowCount(hstmt,ref numrows);
464 if (freeHandle && !prepared)
479 ret=libodbc.SQLPrepare(hstmt, CommandText, CommandText.Length);
480 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo))
481 throw new OdbcException(new OdbcError("SQLPrepare",OdbcHandleType.Stmt,hstmt));
485 private void BindParameters ()
488 foreach (OdbcParameter p in Parameters)
501 OdbcDataReader ExecuteReader ()
503 return ExecuteReader (CommandBehavior.Default);
507 IDataReader IDbCommand.ExecuteReader ()
509 return ExecuteReader ();
512 protected override DbDataReader ExecuteDbDataReader (CommandBehavior behavior)
514 return ExecuteReader (behavior);
523 OdbcDataReader ExecuteReader (CommandBehavior behavior)
525 int recordsAffected = ExecuteNonQuery(false);
526 OdbcDataReader dataReader=new OdbcDataReader(this, behavior, recordsAffected);
531 IDataReader IDbCommand.ExecuteReader (CommandBehavior behavior)
533 return ExecuteReader (behavior);
541 object ExecuteScalar ()
544 OdbcDataReader reader=ExecuteReader();
558 object ICloneable.Clone ()
560 throw new NotImplementedException ();
563 public void ResetCommandTimeout ()