Modified SQLDescribeCol to work around bug in pinvoke...when doing a ref on a typed...
[mono.git] / mcs / class / System.Data / System.Data.Odbc / OdbcCommand.cs
1 //
2 // System.Data.Odbc.OdbcCommand
3 //
4 // Authors:
5 //   Brian Ritchie (brianlritchie@hotmail.com)
6 //
7 // Copyright (C) Brian Ritchie, 2002
8 //
9
10 using System.ComponentModel;
11 using System.Data;
12 using System.Data.Common;
13 using System.Collections;
14 using System.Runtime.InteropServices;
15
16 namespace System.Data.Odbc
17 {
18         /// <summary>
19         /// Represents an SQL statement or stored procedure to execute against a data source.
20         /// </summary>
21         public sealed class OdbcCommand : Component, ICloneable, IDbCommand
22         {
23                 #region Fields
24
25                 string commandText;
26                 int timeout;
27                 CommandType commandType;
28                 OdbcConnection connection;
29                 OdbcParameterCollection parameters;
30                 OdbcTransaction transaction;
31                 bool designTimeVisible;
32                 bool prepared=false;
33                 OdbcDataReader dataReader;
34                 CommandBehavior behavior;
35                 internal IntPtr hstmt;
36                 
37                 #endregion // Fields
38
39                 #region Constructors
40
41                 public OdbcCommand ()
42                 {
43                         commandText = String.Empty;
44                         timeout = 30; // default timeout 
45                         commandType = CommandType.Text;
46                         connection = null;
47                         parameters = new OdbcParameterCollection ();
48                         transaction = null;
49                         designTimeVisible = false;
50                         dataReader = null;
51                         behavior = CommandBehavior.Default;
52                 }
53
54                 public OdbcCommand (string cmdText) : this ()
55                 {
56                         CommandText = cmdText;
57                 }
58
59                 public OdbcCommand (string cmdText, OdbcConnection connection)
60                         : this (cmdText)
61                 {
62                         Connection = connection;
63                 }
64
65                 public OdbcCommand (string cmdText,
66                                      OdbcConnection connection,
67                                      OdbcTransaction transaction) : this (cmdText, connection)
68                 {
69                         this.transaction = transaction;
70                 }
71
72                 #endregion // Constructors
73
74                 #region Properties
75
76                 internal IntPtr hStmt
77                 {
78                         get { return hstmt; }
79                 }
80
81                 public string CommandText 
82                 {
83                         get {
84                                 return commandText;
85                         }
86                         set { 
87                                 prepared=false;
88                                 commandText = value;
89                         }
90                 }
91
92                 public int CommandTimeout {
93                         get {
94                                 return timeout;
95                         }
96                         set {
97                                 timeout = value;
98                         }
99                 }
100
101                 public CommandType CommandType { 
102                         get {
103                                 return commandType;
104                         }
105                         set {
106                                 commandType = value;
107                         }
108                 }
109
110                 public OdbcConnection Connection { 
111                         get {
112                                 return connection;
113                         }
114                         set {
115                                 connection = value;
116                         }
117                 }
118
119                 public bool DesignTimeVisible { 
120                         get {
121                                 return designTimeVisible;
122                         }
123                         set {
124                                 designTimeVisible = value;
125                         }
126                 }
127
128                 public OdbcParameterCollection Parameters {
129                         get {
130                                 return parameters;
131                         }
132                         set {
133                                 parameters = value;
134                         }
135                 }
136
137                 public OdbcTransaction Transaction {
138                         get {
139                                 return transaction;
140                         }
141                         set {
142                                 transaction = value;
143                         }
144                 }
145
146                 public UpdateRowSource UpdatedRowSource { 
147                         [MonoTODO]
148                         get {
149                                 throw new NotImplementedException ();
150                         }
151                         [MonoTODO]
152                         set {
153                                 throw new NotImplementedException ();
154                         }
155                 }
156
157                 IDbConnection IDbCommand.Connection {
158                         get {
159                                 return Connection;
160                         }
161                         set {
162                                 Connection = (OdbcConnection) value;
163                         }
164                 }
165
166                 IDataParameterCollection IDbCommand.Parameters  {
167                         get {
168                                 return Parameters;
169                         }
170                 }
171
172                 IDbTransaction IDbCommand.Transaction  {
173                         get {
174                                 return (IDbTransaction) Transaction;
175                         }
176                         set {
177                                 throw new NotImplementedException ();
178                         }
179                 }
180
181                 #endregion // Properties
182
183                 #region Methods
184
185                 public void Cancel () 
186                 {
187                         if (hstmt!=IntPtr.Zero)
188                         {
189                                 OdbcReturn ret=libodbc.SQLCancel(hstmt);
190                                 libodbchelper.DisplayError("SQLCancel",ret);
191                         }
192                         else
193                                 throw new InvalidOperationException();
194                 }
195
196                 public OdbcParameter CreateParameter ()
197                 {
198                         return new OdbcParameter ();
199                 }
200
201                 IDbDataParameter IDbCommand.CreateParameter ()
202                 {
203                         return CreateParameter ();
204                 }
205                 
206                 [MonoTODO]
207                 protected override void Dispose (bool disposing)
208                 {
209                 }
210                 
211                 private void ExecSQL(string sql)
212                 {
213                         OdbcReturn ret;
214         
215                         if (!prepared)
216                         {
217                                 Prepare();
218                                 if (Parameters.Count>0)
219                                         Parameters.Bind(hstmt);
220                         }
221                         
222                         if (prepared)
223                         {
224                                 ret=libodbc.SQLExecute(hstmt);
225                                 libodbchelper.DisplayError("SQLExecute",ret);
226                         }
227                         else
228                         {
229                                 ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt, Connection.hDbc, ref hstmt);
230                                 libodbchelper.DisplayError("SQLAllocHandle(hstmt)",ret);
231                                 ret=libodbc.SQLExecDirect(hstmt, sql, sql.Length);
232                                 libodbchelper.DisplayError("SQLExecDirect",ret);
233                         }
234                 }
235
236                 public int ExecuteNonQuery ()
237                 {
238                         if (connection == null)
239                                 throw new InvalidOperationException ();
240                         if (connection.State == ConnectionState.Closed)
241                                 throw new InvalidOperationException ();
242                         // FIXME: a third check is mentioned in .NET docs
243                         if (connection.DataReader != null)
244                                 throw new InvalidOperationException ();
245
246                         ExecSQL(CommandText);
247
248                         if (!prepared)
249                                 libodbc.SQLFreeHandle( (ushort) OdbcHandleType.Stmt, hstmt);
250                         return 0;
251                 }
252
253                 public void Prepare()
254                 {
255                         OdbcReturn ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt, Connection.hDbc, ref hstmt);
256                         libodbchelper.DisplayError("SQLAlloc(Prepare)",ret);
257                         ret=libodbc.SQLPrepare(hstmt, CommandText, CommandText.Length);
258                         libodbchelper.DisplayError("SQLPrepare",ret);
259                         prepared=true;
260                 }
261
262                 public OdbcDataReader ExecuteReader ()
263                 {
264                         return ExecuteReader (CommandBehavior.Default);
265                 }
266
267                 IDataReader IDbCommand.ExecuteReader ()
268                 {
269                         return ExecuteReader ();
270                 }
271
272                 public OdbcDataReader ExecuteReader (CommandBehavior behavior)
273                 {
274                         ExecuteNonQuery();
275                         dataReader=new OdbcDataReader(this);
276                         return dataReader;
277                 }
278
279                 IDataReader IDbCommand.ExecuteReader (CommandBehavior behavior)
280                 {
281                         return ExecuteReader (behavior);
282                 }
283                 
284                 public object ExecuteScalar ()
285                 {
286                                         throw new NotImplementedException ();
287 //                      if (connection.DataReader != null)
288 //                              throw new InvalidOperationException ();
289 //                      
290                 }
291
292                 [MonoTODO]
293                 object ICloneable.Clone ()
294                 {
295                         throw new NotImplementedException ();   
296                 }
297
298                 public void ResetCommandTimeout ()
299                 {
300                         timeout = 30;
301                 }
302
303                 #endregion
304         }
305 }