This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mcs / class / System.Data / System.Data.Odbc / OdbcCommand.cs
1 //\r
2 // System.Data.Odbc.OdbcCommand\r
3 //\r
4 // Authors:\r
5 //   Brian Ritchie (brianlritchie@hotmail.com)\r
6 //\r
7 // Copyright (C) Brian Ritchie, 2002\r
8 //\r
9
10 //
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
12 //
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:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
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.
31 //
32 \r
33 using System.ComponentModel;\r
34 using System.Data;\r
35 using System.Data.Common;\r
36 using System.Collections;\r
37 using System.Runtime.InteropServices;\r
38 \r
39 namespace System.Data.Odbc\r
40 {\r
41         /// <summary>\r
42         /// Represents an SQL statement or stored procedure to execute against a data source.\r
43         /// </summary>\r
44         [DesignerAttribute ("Microsoft.VSDesigner.Data.VS.OdbcCommandDesigner, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.IDesigner")]\r
45         [ToolboxItemAttribute ("System.Drawing.Design.ToolboxItem, "+ Consts.AssemblySystem_Drawing)]\r
46         public sealed class OdbcCommand : Component, ICloneable, IDbCommand\r
47         {\r
48                 #region Fields\r
49 \r
50                 string commandText;\r
51                 int timeout;\r
52                 CommandType commandType;\r
53                 OdbcConnection connection;\r
54                 OdbcParameterCollection parameters;\r
55                 OdbcTransaction transaction;\r
56                 bool designTimeVisible;\r
57                 bool prepared=false;\r
58                 OdbcDataReader dataReader;\r
59                 IntPtr hstmt;\r
60                 \r
61                 #endregion // Fields\r
62 \r
63                 #region Constructors\r
64 \r
65                 public OdbcCommand ()\r
66                 {\r
67                         commandText = String.Empty;\r
68                         timeout = 30; // default timeout \r
69                         commandType = CommandType.Text;\r
70                         connection = null;\r
71                         parameters = new OdbcParameterCollection ();\r
72                         transaction = null;\r
73                         designTimeVisible = false;\r
74                         dataReader = null;\r
75                 }\r
76 \r
77                 public OdbcCommand (string cmdText) : this ()\r
78                 {\r
79                         CommandText = cmdText;\r
80                 }\r
81 \r
82                 public OdbcCommand (string cmdText, OdbcConnection connection)\r
83                         : this (cmdText)\r
84                 {\r
85                         Connection = connection;\r
86                 }\r
87 \r
88                 public OdbcCommand (string cmdText,\r
89                                      OdbcConnection connection,\r
90                                      OdbcTransaction transaction) : this (cmdText, connection)\r
91                 {\r
92                         this.transaction = transaction;\r
93                 }\r
94 \r
95                 #endregion // Constructors\r
96 \r
97                 #region Properties\r
98 \r
99                 internal IntPtr hStmt\r
100                 {\r
101                         get { return hstmt; }\r
102                 }\r
103                 \r
104 \r
105                 [OdbcCategory ("Data")]\r
106                 [DefaultValue ("")]\r
107                 [OdbcDescriptionAttribute ("Command text to execute")]\r
108                 [EditorAttribute ("Microsoft.VSDesigner.Data.Odbc.Design.OdbcCommandTextEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]\r
109                 [RefreshPropertiesAttribute (RefreshProperties.All)]\r
110                 public string CommandText \r
111                 {\r
112                         get {\r
113                                 return commandText;\r
114                         }\r
115                         set { \r
116                                 prepared=false;\r
117                                 commandText = value;\r
118                         }\r
119                 }\r
120 \r
121 \r
122                 [OdbcDescriptionAttribute ("Time to wait for command to execute")]\r
123                 [DefaultValue (30)]\r
124                 public int CommandTimeout {\r
125                         get {\r
126                                 return timeout;\r
127                         }\r
128                         set {\r
129                                 timeout = value;\r
130                         }\r
131                 }\r
132 \r
133                 [OdbcCategory ("Data")]\r
134                 [DefaultValue ("Text")]\r
135                 [OdbcDescriptionAttribute ("How to interpret the CommandText")]\r
136                 [RefreshPropertiesAttribute (RefreshProperties.All)]\r
137                 public CommandType CommandType { \r
138                         get {\r
139                                 return commandType;\r
140                         }\r
141                         set {\r
142                                 commandType = value;\r
143                         }\r
144                 }\r
145 \r
146                 [OdbcCategory ("Behavior")]\r
147                 [OdbcDescriptionAttribute ("Connection used by the command")]\r
148                 [DefaultValue (null)]\r
149                 [EditorAttribute ("Microsoft.VSDesigner.Data.Design.DbConnectionEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]\r
150                 public OdbcConnection Connection { \r
151                         get {\r
152                                 return connection;\r
153                         }\r
154                         set {\r
155                                 connection = value;\r
156                         }\r
157                 }\r
158 \r
159                 [BrowsableAttribute (false)]\r
160                 [DesignOnlyAttribute (true)]\r
161                 [DefaultValue (true)]\r
162                 public bool DesignTimeVisible { \r
163                         get {\r
164                                 return designTimeVisible;\r
165                         }\r
166                         set {\r
167                                 designTimeVisible = value;\r
168                         }\r
169                 }\r
170 \r
171                 [OdbcCategory ("Data")]\r
172                 [OdbcDescriptionAttribute ("The parameters collection")]\r
173                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Content)]\r
174                 public OdbcParameterCollection Parameters {\r
175                         get {\r
176                                 return parameters;\r
177                         }\r
178                 }\r
179                 \r
180                 [BrowsableAttribute (false)]\r
181                 [OdbcDescriptionAttribute ("The transaction used by the command")]\r
182                 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]\r
183                 public OdbcTransaction Transaction {\r
184                         get {\r
185                                 return transaction;\r
186                         }\r
187                         set {\r
188                                 transaction = value;\r
189                         }\r
190                 }\r
191                 \r
192                 [OdbcCategory ("Behavior")]\r
193                 [DefaultValue (UpdateRowSource.Both)]\r
194                 [OdbcDescriptionAttribute ("When used by a DataAdapter.Update, how command results are applied to the current DataRow")]\r
195                 public UpdateRowSource UpdatedRowSource { \r
196                         [MonoTODO]\r
197                         get {\r
198                                 throw new NotImplementedException ();\r
199                         }\r
200                         [MonoTODO]\r
201                         set {\r
202                                 throw new NotImplementedException ();\r
203                         }\r
204                 }\r
205 \r
206                 IDbConnection IDbCommand.Connection {\r
207                         get {\r
208                                 return Connection;\r
209                         }\r
210                         set {\r
211                                 Connection = (OdbcConnection) value;\r
212                         }\r
213                 }\r
214 \r
215                 IDataParameterCollection IDbCommand.Parameters  {\r
216                         get {\r
217                                 return Parameters;\r
218                         }\r
219                 }\r
220 \r
221                 IDbTransaction IDbCommand.Transaction  {\r
222                         get {\r
223                                 return (IDbTransaction) Transaction;\r
224                         }\r
225                         set {\r
226                                 if (value is OdbcTransaction)
227                                 {
228                                         Transaction = (OdbcTransaction)value;
229                                 }
230                                 else
231                                 {
232                                         throw new ArgumentException ();
233                                 }
234                         }\r
235                 }\r
236 \r
237                 #endregion // Properties\r
238 \r
239                 #region Methods\r
240 \r
241                 public void Cancel () \r
242                 {\r
243                         if (hstmt!=IntPtr.Zero)\r
244                         {\r
245                                 OdbcReturn Ret=libodbc.SQLCancel(hstmt);\r
246                                 if ((Ret!=OdbcReturn.Success) && (Ret!=OdbcReturn.SuccessWithInfo)) \r
247                                         throw new OdbcException(new OdbcError("SQLCancel",OdbcHandleType.Stmt,hstmt));\r
248                         }\r
249                         else\r
250                                 throw new InvalidOperationException();\r
251                 }\r
252 \r
253                 public OdbcParameter CreateParameter ()\r
254                 {\r
255                         return new OdbcParameter ();\r
256                 }\r
257 \r
258                 IDbDataParameter IDbCommand.CreateParameter ()\r
259                 {\r
260                         return CreateParameter ();\r
261                 }\r
262                 \r
263                 [MonoTODO]\r
264                 protected override void Dispose (bool disposing)\r
265                 {\r
266                 }\r
267                 \r
268                 private void ExecSQL(string sql)\r
269                 {\r
270                         OdbcReturn ret;\r
271 \r
272                         if ((parameters.Count>0) && !prepared)\r
273                                 Prepare();\r
274         \r
275                         if (prepared)\r
276                         {\r
277                                 ret=libodbc.SQLExecute(hstmt);\r
278                                 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) \r
279                                         throw new OdbcException(new OdbcError("SQLExecute",OdbcHandleType.Stmt,hstmt));\r
280                         }\r
281                         else\r
282                         {\r
283                                 ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt, Connection.hDbc, ref hstmt);\r
284                                 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) \r
285                                         throw new OdbcException(new OdbcError("SQLAllocHandle",OdbcHandleType.Dbc,Connection.hDbc));\r
286 \r
287                                 ret=libodbc.SQLExecDirect(hstmt, sql, sql.Length);\r
288                                 if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) \r
289                                         throw new OdbcException(new OdbcError("SQLExecDirect",OdbcHandleType.Stmt,hstmt));\r
290                         }\r
291                 }\r
292 \r
293                 public int ExecuteNonQuery ()\r
294                 {\r
295                         if (connection == null)\r
296                                 throw new InvalidOperationException ();\r
297                         if (connection.State == ConnectionState.Closed)\r
298                                 throw new InvalidOperationException ();\r
299                         // FIXME: a third check is mentioned in .NET docs\r
300 \r
301                         ExecSQL(CommandText);\r
302 \r
303 //                      if (!prepared)\r
304 //                              libodbc.SQLFreeHandle( (ushort) OdbcHandleType.Stmt, hstmt);\r
305                         return 0;\r
306                 }\r
307 \r
308                 public void Prepare()\r
309                 {\r
310                         OdbcReturn ret=libodbc.SQLAllocHandle(OdbcHandleType.Stmt, Connection.hDbc, ref hstmt);\r
311                         if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) \r
312                                 throw new OdbcException(new OdbcError("SQLAllocHandle",OdbcHandleType.Dbc,Connection.hDbc));\r
313 \r
314                         ret=libodbc.SQLPrepare(hstmt, CommandText, CommandText.Length);\r
315                         if ((ret!=OdbcReturn.Success) && (ret!=OdbcReturn.SuccessWithInfo)) \r
316                                 throw new OdbcException(new OdbcError("SQLPrepare",OdbcHandleType.Stmt,hstmt));\r
317 \r
318                         int i=1;\r
319                         foreach (OdbcParameter p in parameters)\r
320                         {\r
321                                 p.Bind(hstmt, i);\r
322                                 i++;\r
323                         }\r
324 \r
325                         prepared=true;\r
326                 }\r
327 \r
328                 public OdbcDataReader ExecuteReader ()\r
329                 {\r
330                         return ExecuteReader (CommandBehavior.Default);\r
331                 }\r
332 \r
333                 IDataReader IDbCommand.ExecuteReader ()\r
334                 {\r
335                         return ExecuteReader ();\r
336                 }\r
337 \r
338                 public OdbcDataReader ExecuteReader (CommandBehavior behavior)\r
339                 {\r
340                         ExecuteNonQuery();\r
341                         dataReader=new OdbcDataReader(this,behavior);\r
342                         return dataReader;\r
343                 }\r
344 \r
345                 IDataReader IDbCommand.ExecuteReader (CommandBehavior behavior)\r
346                 {\r
347                         return ExecuteReader (behavior);\r
348                 }\r
349                 \r
350                 public object ExecuteScalar ()\r
351                 {\r
352                         object val = null;\r
353                         OdbcDataReader reader=ExecuteReader();\r
354                         try\r
355                         {\r
356                                 if (reader.Read ())\r
357                                         val=reader[0];\r
358                         }\r
359                         finally\r
360                         {\r
361                                 reader.Close();\r
362                         }\r
363                         return val;\r
364                 }\r
365 \r
366                 [MonoTODO]\r
367                 object ICloneable.Clone ()\r
368                 {\r
369                         throw new NotImplementedException ();   \r
370                 }\r
371 \r
372                 public void ResetCommandTimeout ()\r
373                 {\r
374                         timeout = 30;\r
375                 }\r
376 \r
377                 #endregion\r
378         }\r
379 }\r