Added tests for Task.WhenAll w/ empty list
[mono.git] / mcs / class / System.Data.OracleClient / System.Data.OracleClient.Oci / OciStatementHandle.cs
1 // 
2 // OciStatementHandle.cs 
3 //  
4 // Part of managed C#/.NET library System.Data.OracleClient.dll
5 //
6 // Part of the Mono class libraries at
7 // mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci
8 //
9 // Assembly: System.Data.OracleClient.dll
10 // Namespace: System.Data.OracleClient.Oci
11 // 
12 // Author: 
13 //     Tim Coleman <tim@timcoleman.com>
14 //     Daniel Morgan <danielmorgan@verizon.net>
15 //         
16 // Copyright (C) Tim Coleman, 2003
17 // Copyright (C) Daniel Morgan, 2005
18 // 
19
20 using System;
21 using System.Collections;
22 using System.Runtime.InteropServices;
23
24 namespace System.Data.OracleClient.Oci {
25         internal sealed class OciStatementHandle : OciHandle, IDisposable
26         {
27                 #region Fields
28
29                 int columnCount;
30                 bool disposed = false;
31                 OciErrorHandle errorHandle;
32                 bool moreResults;
33                 OciServiceHandle serviceHandle;
34                 ArrayList values;
35                 OracleCommand command;
36         
37                 #endregion // Fields
38
39                 #region Constructors
40
41                 public OciStatementHandle (OciHandle parent, IntPtr handle)
42                         : base (OciHandleType.Statement, parent, handle)
43                 {
44                         moreResults = false;
45                 }
46
47                 #endregion // Constructors
48
49                 #region Properties
50
51                 public int ColumnCount {
52                         get { return columnCount; }
53                 }
54
55                 public OciErrorHandle ErrorHandle {
56                         get { return errorHandle; }
57                         set { errorHandle = value; }
58                 }
59
60                 public OciServiceHandle Service {
61                         get { return serviceHandle; }
62                         set { serviceHandle = value; }
63                 }
64                 
65                 public ArrayList Values {
66                         get { return values; }
67                 }
68
69                 public OracleCommand Command {
70                         get { return command; }
71                         set { command = value; }
72                 }
73
74                 #endregion // Properties
75
76                 #region Methods
77                 
78                 protected override void Dispose (bool disposing)
79                 {
80                         if (!disposed) {
81                                 disposed = true;
82                                 
83                                 if (disposing) {
84                                         if (values != null) {
85                                                 foreach (OciDefineHandle h in values)
86                                                         h.Dispose ();
87                                                 values = null;
88                                         }
89                                 }
90                                 
91                                 base.Dispose (disposing);
92                         }
93                 }
94
95                 public OciParameterDescriptor GetParameter (int position)
96                 {
97                         IntPtr handle = IntPtr.Zero;
98                         int status = 0;
99
100                         status = OciCalls.OCIParamGet (this,
101                                                 OciHandleType.Statement,
102                                                 ErrorHandle,
103                                                 out handle,
104                                                 position + 1);
105
106                         if (status != 0) {
107                                 OciErrorInfo info = ErrorHandle.HandleError ();
108                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
109                         }
110
111                         OciParameterDescriptor output = new OciParameterDescriptor (this, handle);
112                         output.ErrorHandle = ErrorHandle;
113                         return output;
114                 }
115
116                 public OciDefineHandle GetDefineHandle (int position, OracleConnection connection)
117                 {
118                         OciDefineHandle defineHandle = new OciDefineHandle (this, IntPtr.Zero);
119                         defineHandle.ErrorHandle = ErrorHandle;
120                         defineHandle.DefineByPosition (position, connection);
121
122                         return defineHandle;
123                 }
124
125                 void Define ()
126                 {
127                         Define (command.Connection);
128                 }
129
130                 void Define (OracleConnection connection) 
131                 {
132                         values = new ArrayList ();
133                         for (int i = 0; i < columnCount; i += 1)  
134                                 values.Add (GetDefineHandle (i, connection));
135                 }
136
137                 public bool ExecuteQuery (bool schemaOnly)
138                 {
139                         return Execute (false, false, schemaOnly);
140                 }
141
142                 public bool ExecuteNonQuery (bool useAutoCommit)
143                 {
144                         return Execute (true, useAutoCommit, false);
145                 }
146
147                 public bool Execute (bool nonQuery, bool useAutoCommit, bool schemaOnly)
148                 {
149                         int status = 0;
150                         columnCount = 0;
151                         moreResults = false;
152                         int executeMode;
153
154                         if( useAutoCommit)
155                                 executeMode = (int)OciExecuteMode.CommitOnSuccess;
156                         else {
157                                 if (schemaOnly)
158                                         executeMode = (int)OciExecuteMode.DescribeOnly;
159                                 else
160                                         executeMode = (int)OciExecuteMode.Default;
161                         }
162
163                         if (this.disposed) 
164                         {
165                                 throw new InvalidOperationException ("StatementHandle is already disposed.");
166                         }
167
168                         status = OciCalls.OCIStmtExecute (Service,
169                                 Handle,
170                                 ErrorHandle,
171                                 nonQuery,
172                                 0,
173                                 IntPtr.Zero,
174                                 IntPtr.Zero,
175                                 (OciExecuteMode)executeMode);
176
177                         switch (status) {
178                         case OciGlue.OCI_DEFAULT:
179                                 if (!nonQuery) {
180                                         GetColumnCount ();
181                                         Define ();
182                                         moreResults = true;
183                                 }
184                                 break;
185                         case OciGlue.OCI_NO_DATA:
186                                 break;
187                         case OciGlue.OCI_INVALID_HANDLE:
188                                 throw new OracleException (0, "Invalid handle.");
189                         default:
190                                 OciErrorInfo info = ErrorHandle.HandleError ();
191                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
192                         }
193                         return true;
194                 }
195                 
196                 internal void SetupRefCursorResult (OracleConnection connection) 
197                 {
198                         GetColumnCount ();
199                         Define (connection);
200                         moreResults = true;
201                 }
202
203                 void GetColumnCount ()
204                 {
205                         columnCount = GetAttributeInt32 (OciAttributeType.ParameterCount, ErrorHandle);
206                 }
207
208                 public OciStatementType GetStatementType ()
209                 {
210                         return (OciStatementType) GetAttributeUInt16 (OciAttributeType.StatementType, ErrorHandle);
211                 }
212
213                 public bool Fetch ()
214                 {
215                         int status = 0;
216
217                         if (this.disposed) 
218                         {
219                                 throw new InvalidOperationException ("StatementHandle is already disposed.");
220                         }
221
222                         status = OciCalls.OCIStmtFetch (Handle,
223                                 ErrorHandle.Handle,
224                                 1,
225                                 2,
226                                 0);
227                 
228                         switch (status) {
229                         case OciGlue.OCI_NO_DATA:
230                                 moreResults = false;
231                                 break;
232                         case OciGlue.OCI_DEFAULT:
233                                 moreResults = true;
234                                 break;
235                         case OciGlue.OCI_SUCCESS_WITH_INFO:
236                                 //OciErrorInfo ei = ErrorHandle.HandleError ();
237                                 //command.Connection.CreateInfoMessage (ei);
238                                 moreResults = true;
239                                 break;
240                         default:
241                                 OciErrorInfo info = ErrorHandle.HandleError ();
242                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
243                         }
244
245                         return moreResults;
246                 }
247
248                 public void Prepare (string commandText)
249                 {
250                         int status = 0;
251
252                         if (this.disposed) {
253                                 throw new InvalidOperationException ("StatementHandle is already disposed.");
254                         }
255
256                         int rsize = 0;
257                         byte [] buffer;
258                         
259                         // Get size of buffer
260                         OciCalls.OCIUnicodeToCharSet (Parent, null, commandText, out rsize);
261                         
262                         // Fill buffer
263                         buffer = new byte[rsize];
264                         OciCalls.OCIUnicodeToCharSet (Parent, buffer, commandText, out rsize);
265
266                         // Execute statement
267                         status = OciCalls.OCIStmtPrepare (this,
268                                 ErrorHandle,
269                                 buffer,
270                                 buffer.Length,
271                                 OciStatementLanguage.NTV,
272                                 OciStatementMode.Default);
273
274                         if (status != 0) {
275                                 OciErrorInfo info = ErrorHandle.HandleError ();
276                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
277                         }
278                 }
279
280                 #endregion // Methods
281         }
282 }