2003-12-16 Joerg Rosenkranz <joergr@voelcker.com>
[mono.git] / mcs / class / System.Data.OracleClient / System.Data.OracleClient / OracleCommand.cs
1 // 
2 // OracleCommand.cs
3 //
4 // Part of the Mono class libraries at
5 // mcs/class/System.Data.OracleClient/System.Data.OracleClient
6 //
7 // Assembly: System.Data.OracleClient.dll
8 // Namespace: System.Data.OracleClient
9 //
10 // Authors: 
11 //    Daniel Morgan <danmorg@sc.rr.com>
12 //    Tim Coleman <tim@timcoleman.com>
13 //
14 // Copyright (C) Daniel Morgan, 2002
15 // Copyright (C) Tim Coleman , 2003
16 //
17 // Licensed under the MIT/X11 License.
18 //
19
20 using System;
21 using System.ComponentModel;
22 using System.Data;
23 using System.Data.OracleClient.Oci;
24
25 namespace System.Data.OracleClient {
26         public class OracleCommand : Component, ICloneable, IDbCommand
27         {
28                 #region Fields
29
30                 bool disposed = false;
31                 CommandBehavior behavior;
32                 string commandText;
33                 CommandType commandType;
34                 OracleConnection connection;
35                 bool designTimeVisible;
36                 OracleParameterCollection parameters;
37                 OracleTransaction transaction;
38                 UpdateRowSource updatedRowSource;
39
40                 OciStatementHandle preparedStatement;
41                 OciStatementType statementType;
42
43                 #endregion // Fields
44
45                 #region Constructors
46
47                 public OracleCommand ()
48                         : this (String.Empty, null, null)
49                 {
50                 }
51
52                 public OracleCommand (string commandText)
53                         : this (commandText, null, null)
54                 {
55                 }
56
57                 public OracleCommand (string commandText, OracleConnection connection)
58                         : this (commandText, connection, null)
59                 {
60                 }
61
62                 public OracleCommand (string commandText, OracleConnection connection, OracleTransaction tx)
63                 {
64                         preparedStatement = null;
65                         CommandText = commandText;
66                         Connection = connection;
67                         Transaction = tx;
68                         CommandType = CommandType.Text;
69                         UpdatedRowSource = UpdateRowSource.Both;
70                         DesignTimeVisible = false;
71
72                         parameters = new OracleParameterCollection (this);
73                 }
74
75                 #endregion // Constructors
76
77                 #region Properties
78
79                 public string CommandText {
80                         get { return commandText; }
81                         set { commandText = value; }
82                 }
83
84                 public CommandType CommandType {
85                         get { return commandType; }
86                         set { commandType = value; }
87                 }
88
89                 public OracleConnection Connection {
90                         get { return connection; }
91                         set { connection = value; }
92                 }
93
94                 public bool DesignTimeVisible {
95                         get { return designTimeVisible; }
96                         set { designTimeVisible = value; }
97                 }
98
99                 internal OciEnvironmentHandle Environment {
100                         get { return Connection.Environment; }
101                 }
102
103                 internal OciErrorHandle ErrorHandle {
104                         get { return Connection.ErrorHandle; }
105                 }
106
107                 int IDbCommand.CommandTimeout {
108                         get { return 0; }
109                         set { }
110                 }
111
112                 IDbConnection IDbCommand.Connection {
113                         get { return Connection; }
114                         set { 
115                                 if (!(value is OracleConnection))
116                                         throw new InvalidCastException ("The value was not a valid OracleConnection.");
117                                 Connection = (OracleConnection) value;
118                         }
119                 }
120
121                 IDataParameterCollection IDbCommand.Parameters {
122                         get { return Parameters; }
123                 }
124
125                 IDbTransaction IDbCommand.Transaction {
126                         get { return Transaction; }
127                         set { 
128                                 if (!(value is OracleTransaction))
129                                         throw new ArgumentException ();
130                                 Transaction = (OracleTransaction) value; 
131                         }
132                 }
133
134                 public OracleParameterCollection Parameters {
135                         get { return parameters; }
136                 }
137
138                 public OracleTransaction Transaction {
139                         get { return transaction; }
140                         set { transaction = value; }
141                 }
142
143                 public UpdateRowSource UpdatedRowSource {
144                         get { return updatedRowSource; }
145                         set { updatedRowSource = value; }
146                 }
147
148                 #endregion
149
150                 #region Methods
151
152                 private void AssertCommandTextIsSet ()
153                 {
154                         if (CommandText == String.Empty || CommandText == null)
155                                 throw new InvalidOperationException ("The command text for this Command has not been set.");
156                 }
157
158                 private void AssertConnectionIsOpen ()
159                 {
160                         if (Connection == null || Connection.State == ConnectionState.Closed)
161                                 throw new InvalidOperationException ("An open Connection object is required to continue.");
162                 }
163
164                 private void AssertNoDataReader ()
165                 {
166                         if (Connection.DataReader != null)
167                                 throw new InvalidOperationException ("There is already an open DataReader associated with this Connection which must be closed first.");
168                 }
169
170                 private void AssertTransactionMatch ()
171                 {
172                         if (Connection.Transaction != null && Transaction != Connection.Transaction)
173                                 throw new InvalidOperationException ("Execute requires the Command object to have a Transaction object when the Connection object assigned to the command is in a pending local transaction.  The Transaction property of the Command has not been initialized.");
174                 }
175
176                 private void BindParameters (OciStatementHandle statement)
177                 {
178                         foreach (OracleParameter p in Parameters) 
179                                 p.Bind (statement, Connection);
180                 }
181
182                 [MonoTODO]
183                 public void Cancel ()
184                 {
185                         throw new NotImplementedException ();
186                 }
187
188                 [MonoTODO]
189                 public object Clone ()
190                 {
191                         throw new NotImplementedException ();
192                 }
193
194                 internal void CloseDataReader ()
195                 {
196                         Connection.DataReader = null;
197                         if ((behavior & CommandBehavior.CloseConnection) != 0)
198                                 Connection.Close ();
199                 }
200
201                 public OracleParameter CreateParameter ()
202                 {
203                         return new OracleParameter ();
204                 }
205
206                 private int ExecuteNonQueryInternal (OciStatementHandle statement)
207                 {
208                         if (preparedStatement == null)
209                                 statement.Prepare (CommandText);
210
211                         BindParameters (statement);
212                         statement.ExecuteNonQuery ();
213
214                         int rowsAffected = statement.GetAttributeInt32 (OciAttributeType.RowCount, ErrorHandle);
215                         
216                         statement.Dispose ();
217                         return rowsAffected;
218                 }
219
220                 public int ExecuteNonQuery () 
221                 {
222                         AssertConnectionIsOpen ();
223                         AssertTransactionMatch ();
224                         AssertCommandTextIsSet ();
225
226                         if (Transaction != null)
227                                 Transaction.AttachToServiceContext ();
228
229                         return ExecuteNonQueryInternal (GetStatementHandle ());
230                 }
231
232                 public int ExecuteOracleNonQuery (out OracleString rowid)
233                 {
234                         AssertConnectionIsOpen ();
235                         AssertTransactionMatch ();
236                         AssertCommandTextIsSet ();
237
238                         if (Transaction != null)
239                                 Transaction.AttachToServiceContext ();
240
241                         OciStatementHandle statement = GetStatementHandle ();
242
243                         int retval = ExecuteNonQueryInternal (statement);
244
245                         OciRowIdDescriptor descriptor = (OciRowIdDescriptor) Environment.Allocate (OciHandleType.RowId);
246                         descriptor.SetHandle (statement.GetAttributeIntPtr (OciAttributeType.RowId, ErrorHandle));
247
248                         rowid = new OracleString (descriptor.GetRowId (ErrorHandle));
249
250                         return retval;
251                 }
252
253                 [MonoTODO]
254                 public object ExecuteOracleScalar (out OracleString rowid)
255                 {
256                         throw new NotImplementedException ();
257                 }
258
259                 public OracleDataReader ExecuteReader ()
260                 {
261                         return ExecuteReader (CommandBehavior.Default);
262                 }
263
264                 public OracleDataReader ExecuteReader (CommandBehavior behavior)
265                 {
266                         AssertConnectionIsOpen ();
267                         AssertTransactionMatch ();
268                         AssertCommandTextIsSet ();
269                         AssertNoDataReader ();
270
271                         if (Transaction != null)
272                                 Transaction.AttachToServiceContext ();
273
274                         OciStatementHandle statement = GetStatementHandle ();
275
276                         if (preparedStatement == null)
277                                 statement.Prepare (CommandText);
278                         BindParameters (statement);
279                         statement.ExecuteQuery ();
280
281                         return new OracleDataReader (this, statement);
282                 }
283
284                 public object ExecuteScalar ()
285                 {
286                         object output;
287
288                         AssertConnectionIsOpen ();
289                         AssertTransactionMatch ();
290                         AssertCommandTextIsSet ();
291
292                         if (Transaction != null)
293                                 Transaction.AttachToServiceContext ();
294
295                         OciStatementHandle statement = GetStatementHandle ();
296                         if (preparedStatement == null)
297                                 statement.Prepare (CommandText);
298                         BindParameters (statement);
299
300                         statement.ExecuteQuery ();
301
302                         if (statement.Fetch ()) 
303                                 output = ((OciDefineHandle) statement.Values [0]).GetValue ();
304                         else
305                                 output = DBNull.Value;
306
307                         return output;
308                 }
309
310                 private OciStatementHandle GetStatementHandle ()
311                 {
312                         AssertConnectionIsOpen ();
313                         if (preparedStatement != null) 
314                                 return preparedStatement;
315                         
316                         OciStatementHandle h = (OciStatementHandle) Connection.Environment.Allocate (OciHandleType.Statement);
317                         h.ErrorHandle = Connection.ErrorHandle;
318                         h.Service = Connection.ServiceContext;
319                         return h;
320                 }
321
322                 IDbDataParameter IDbCommand.CreateParameter ()
323                 {
324                         return CreateParameter ();
325                 }
326
327                 IDataReader IDbCommand.ExecuteReader ()
328                 {
329                         return ExecuteReader ();
330                 }
331
332                 IDataReader IDbCommand.ExecuteReader (CommandBehavior behavior)
333                 {
334                         return ExecuteReader (behavior);
335                 }
336
337                 public void Prepare ()
338                 {
339                         AssertConnectionIsOpen ();
340                         OciStatementHandle statement = GetStatementHandle ();
341                         statement.Prepare (CommandText);
342                         preparedStatement = statement;
343                 }
344
345                 #endregion // Methods
346         }
347 }