- Transaction Isolation Level is supported
[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                 public IntPtr hstmt;
35                 
36                 #endregion // Fields
37
38                 #region Constructors
39
40                 public OdbcCommand ()
41                 {
42                         commandText = String.Empty;
43                         timeout = 30; // default timeout 
44                         commandType = CommandType.Text;
45                         connection = null;
46                         parameters = new OdbcParameterCollection ();
47                         transaction = null;
48                         designTimeVisible = false;
49                         dataReader = null;
50                 }
51
52                 public OdbcCommand (string cmdText) : this ()
53                 {
54                         CommandText = cmdText;
55                 }
56
57                 public OdbcCommand (string cmdText, OdbcConnection connection)
58                         : this (cmdText)
59                 {
60                         Connection = connection;
61                 }
62
63                 public OdbcCommand (string cmdText,
64                                      OdbcConnection connection,
65                                      OdbcTransaction transaction) : this (cmdText, connection)
66                 {
67                         this.transaction = transaction;
68                 }
69
70                 #endregion // Constructors
71
72                 #region Properties
73
74                 internal IntPtr hStmt
75                 {
76                         get { return hstmt; }
77                 }
78
79                 public string CommandText 
80                 {
81                         get {
82                                 return commandText;
83                         }
84                         set { 
85                                 prepared=false;
86                                 commandText = value;
87                         }
88                 }
89
90                 public int CommandTimeout {
91                         get {
92                                 return timeout;
93                         }
94                         set {
95                                 timeout = value;
96                         }
97                 }
98
99                 public CommandType CommandType { 
100                         get {
101                                 return commandType;
102                         }
103                         set {
104                                 commandType = value;
105                         }
106                 }
107
108                 public OdbcConnection Connection { 
109                         get {
110                                 return connection;
111                         }
112                         set {
113                                 connection = value;
114                         }
115                 }
116
117                 public bool DesignTimeVisible { 
118                         get {
119                                 return designTimeVisible;
120                         }
121                         set {
122                                 designTimeVisible = value;
123                         }
124                 }
125
126                 public OdbcParameterCollection Parameters {
127                         get {
128                                 return parameters;
129                         }
130                         set {
131                                 parameters = value;
132                         }
133                 }
134
135                 public OdbcTransaction Transaction {
136                         get {
137                                 return transaction;
138                         }
139                         set {
140                                 transaction = value;
141                         }
142                 }
143
144                 public UpdateRowSource UpdatedRowSource { 
145                         [MonoTODO]
146                         get {
147                                 throw new NotImplementedException ();
148                         }
149                         [MonoTODO]
150                         set {
151                                 throw new NotImplementedException ();
152                         }
153                 }
154
155                 IDbConnection IDbCommand.Connection {
156                         get {
157                                 return Connection;
158                         }
159                         set {
160                                 Connection = (OdbcConnection) value;
161                         }
162                 }
163
164                 IDataParameterCollection IDbCommand.Parameters  {
165                         get {
166                                 return Parameters;
167                         }
168                 }
169
170                 IDbTransaction IDbCommand.Transaction  {
171                         get {
172                                 return (IDbTransaction) Transaction;
173                         }
174                         set {
175                                 throw new NotImplementedException ();
176                         }
177                 }
178
179                 #endregion // Properties
180
181                 #region Methods
182
183                 public void Cancel () 
184                 {
185                         if (hstmt!=IntPtr.Zero)
186                         {
187                                 OdbcReturn Ret=libodbc.SQLCancel(hstmt);
188                                 if ((Ret!=OdbcReturn.Success) && (Ret!=OdbcReturn.SuccessWithInfo)) \r
189                                         throw new OdbcException(new OdbcError("SQLCancel",OdbcHandleType.Stmt,hstmt));
190                         }
191                         else
192                                 throw new InvalidOperationException();
193                 }
194
195                 public OdbcParameter CreateParameter ()
196                 {
197                         return new OdbcParameter ();
198                 }
199
200                 IDbDataParameter IDbCommand.CreateParameter ()
201                 {
202                         return CreateParameter ();
203                 }
204                 
205                 [MonoTODO]
206                 protected override void Dispose (bool disposing)
207                 {
208                 }
209                 
210                 private void ExecSQL(string sql)
211                 {
212                         OdbcReturn ret;
213
214                         if ((parameters.Count>0) && !prepared)
215                                 Prepare();
216         
217                         if (prepared)
218                         {
219                                 ret=libodbc.SQLExecute(hstmt);
220                                 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) \r
221                                         throw new OdbcException(new OdbcError("SQLExecute",OdbcHandleType.Stmt,hstmt));
222                         }
223                         else
224                         {
225                                 ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt, Connection.hDbc, ref hstmt);
226                                 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) \r
227                                         throw new OdbcException(new OdbcError("SQLAllocHandle",OdbcHandleType.Dbc,Connection.hDbc));
228
229                                 ret=libodbc.SQLExecDirect(hstmt, sql, sql.Length);
230                                 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) \r
231                                         throw new OdbcException(new OdbcError("SQLExecDirect",OdbcHandleType.Stmt,hstmt));
232                         }
233                 }
234
235                 public int ExecuteNonQuery ()
236                 {
237                         if (connection == null)
238                                 throw new InvalidOperationException ();
239                         if (connection.State == ConnectionState.Closed)
240                                 throw new InvalidOperationException ();
241                         // FIXME: a third check is mentioned in .NET docs
242                         if (connection.DataReader != null)
243                                 throw new InvalidOperationException ();
244
245                         ExecSQL(CommandText);
246
247 //                      if (!prepared)
248 //                              libodbc.SQLFreeHandle( (ushort) OdbcHandleType.Stmt, hstmt);
249                         return 0;
250                 }
251
252                 public void Prepare()
253                 {
254                         OdbcReturn ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt, Connection.hDbc, ref hstmt);
255                         if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) \r
256                                 throw new OdbcException(new OdbcError("SQLAllocHandle",OdbcHandleType.Dbc,Connection.hDbc));
257
258                         ret=libodbc.SQLPrepare(hstmt, CommandText, CommandText.Length);
259                         if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) \r
260                                 throw new OdbcException(new OdbcError("SQLPrepare",OdbcHandleType.Stmt,hstmt));
261
262                         int i=1;
263                         foreach (OdbcParameter p in parameters)
264                         {
265                                 p.Bind(hstmt, i);
266                                 i++;
267                         }
268
269                         prepared=true;
270                 }
271
272                 public OdbcDataReader ExecuteReader ()
273                 {
274                         return ExecuteReader (CommandBehavior.Default);
275                 }
276
277                 IDataReader IDbCommand.ExecuteReader ()
278                 {
279                         return ExecuteReader ();
280                 }
281
282                 public OdbcDataReader ExecuteReader (CommandBehavior behavior)
283                 {
284                         ExecuteNonQuery();
285                         dataReader=new OdbcDataReader(this,behavior);
286                         return dataReader;
287                 }
288
289                 IDataReader IDbCommand.ExecuteReader (CommandBehavior behavior)
290                 {
291                         return ExecuteReader (behavior);
292                 }
293                 
294                 public object ExecuteScalar ()
295                 {
296                         if (connection.DataReader != null)
297                                 throw new InvalidOperationException ();
298                         object val;
299                         OdbcDataReader reader=ExecuteReader();
300                         try
301                         {
302                                 val=reader[0];
303                         }
304                         finally
305                         {
306                                 reader.Close();
307                         }
308                         return val;
309                 }
310
311                 [MonoTODO]
312                 object ICloneable.Clone ()
313                 {
314                         throw new NotImplementedException ();   
315                 }
316
317                 public void ResetCommandTimeout ()
318                 {
319                         timeout = 30;
320                 }
321
322                 #endregion
323         }
324 }