dbc06efed5b9d907f051bd0421d27cbe1f1ae8fc
[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 //         
15 // Copyright (C) Tim Coleman, 2003
16 // 
17
18 using System;
19 using System.Collections;
20 using System.Runtime.InteropServices;
21
22 namespace System.Data.OracleClient.Oci {
23         internal sealed class OciStatementHandle : OciHandle, IOciHandle, IDisposable
24         {
25                 #region Fields
26
27                 OciStatementLanguage language;
28                 OciStatementMode mode;
29                 OciServiceHandle serviceHandle;
30                 OciErrorHandle errorHandle;
31                 ArrayList values;
32
33                 bool moreResults;
34                 int columnCount;
35         
36                 #endregion // Fields
37
38                 #region Constructors
39
40                 public OciStatementHandle (OciEnvironmentHandle environment, IntPtr handle)
41                         : base (OciHandleType.Statement, environment, handle)
42                 {
43                         language = OciStatementLanguage.NTV;
44                         mode = OciStatementMode.Default;
45                         moreResults = false;
46                 }
47
48                 #endregion // Constructors
49
50                 #region Properties
51
52                 public int ColumnCount {
53                         get { return columnCount; }
54                 }
55
56                 public OciErrorHandle ErrorHandle {
57                         get { return errorHandle; }
58                         set { errorHandle = value; }
59                 }
60
61                 public OciStatementLanguage Language {
62                         get { return language; }
63                         set { language = value; }
64                 }
65
66                 public OciServiceHandle Service {
67                         get { return serviceHandle; }
68                         set { serviceHandle = value; }
69                 }
70
71                 public ArrayList Values {
72                         get { return values; }
73                 }
74
75                 #endregion // Properties
76
77                 #region Methods
78
79                 [DllImport ("oci")]
80                 public static extern int OCIDescriptorFree (IntPtr descp,
81                                                         [MarshalAs (UnmanagedType.U4)] OciDescriptorType type);
82
83                 [DllImport ("oci")]
84                 public static extern int OCIParamGet (IntPtr hndlp,
85                                                         [MarshalAs (UnmanagedType.U4)] OciHandleType htype,
86                                                         IntPtr errhp,
87                                                         out IntPtr parmdpp,
88                                                         [MarshalAs (UnmanagedType.U4)] int pos);
89
90                 [DllImport ("oci")]
91                 public static extern int OCIStmtExecute (IntPtr svchp,
92                                                         IntPtr stmthp,
93                                                         IntPtr errhp,
94                                                         [MarshalAs (UnmanagedType.U4)] bool iters,
95                                                         uint rowoff,
96                                                         IntPtr snap_in,
97                                                         IntPtr snap_out,
98                                                         [MarshalAs (UnmanagedType.U4)] OciExecuteMode mode);
99
100                 [DllImport ("oci")]
101                 public static extern int OCIStmtFetch (IntPtr stmtp,
102                                                         IntPtr errhp,
103                                                         uint nrows,
104                                                         ushort orientation,
105                                                         uint mode);
106                                                         
107
108                 [DllImport ("oci")]
109                 public static extern int OCIStmtPrepare (IntPtr stmthp,
110                                                         IntPtr errhp,
111                                                         string stmt,
112                                                         [MarshalAs (UnmanagedType.U4)] int stmt_length,
113                                                         [MarshalAs (UnmanagedType.U4)] OciStatementLanguage language,
114                                                         [MarshalAs (UnmanagedType.U4)] OciStatementMode mode);
115
116                 public IntPtr CreateParameterHandle (int position)
117                 {
118                         IntPtr handle = IntPtr.Zero;
119                         int status = 0;
120
121                         status = OCIParamGet (Handle,
122                                                 OciHandleType.Statement,
123                                                 ErrorHandle.Handle,
124                                                 out handle,
125                                                 position);
126                         if (status != 0) {
127                                 OciErrorInfo info = ErrorHandle.HandleError ();
128                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
129                         }
130
131                         return handle;
132                 }
133
134                 public void FreeParameterHandle (IntPtr handle)
135                 {
136                         int status = 0;
137
138                         status = OCIDescriptorFree (handle, OciDescriptorType.Parameter);
139                         if (status != 0) {
140                                 OciErrorInfo info = ErrorHandle.HandleError ();
141                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
142                         }
143                 }
144
145                 void Define ()
146                 {
147                         values = new ArrayList ();
148                         for (int i = 0; i < columnCount; i += 1)  
149                                 values.Add (new OciDefineHandle (this, i + 1));
150                 }
151
152                 public void Dispose ()
153                 {
154                         Environment.FreeHandle (this);
155                 }
156
157                 public bool ExecuteQuery ()
158                 {
159                         return Execute (false);
160                 }
161
162                 public bool ExecuteNonQuery ()
163                 {
164                         return Execute (true);
165                 }
166
167                 public bool Execute (bool nonQuery)
168                 {
169                         int status = 0;
170                         columnCount = 0;
171                         moreResults = false;
172
173                         status = OCIStmtExecute (Service.Handle,
174                                                 Handle,
175                                                 ErrorHandle.Handle,
176                                                 nonQuery,
177                                                 0,
178                                                 IntPtr.Zero,
179                                                 IntPtr.Zero,
180                                                 OciExecuteMode.Default);
181
182                         switch (status) {
183                         case OciGlue.OCI_DEFAULT:
184                                 if (!nonQuery) {
185                                         GetColumnCount ();
186                                         Define ();
187                                         moreResults = true;
188                                 }
189                                 break;
190                         case OciGlue.OCI_NO_DATA:
191                                 break;
192                         default:
193                                 OciErrorInfo info = ErrorHandle.HandleError ();
194                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
195                         }
196
197                         return true;
198                 }
199
200                 void GetColumnCount ()
201                 {
202                         int status = 0;
203                         status = OciGlue.OCIAttrGetInt32 ( Handle,
204                                                 (uint) OciHandleType.Statement,
205                                                 out columnCount,
206                                                 IntPtr.Zero,
207                                                 OciAttributeType.ParameterCount,
208                                                 ErrorHandle.Handle);
209                         if (status != 0) {
210                                 OciErrorInfo info = ErrorHandle.HandleError ();
211                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
212                         }
213                 }
214
215                 public bool GetAttributeBool (IntPtr handle, OciAttributeType type)
216                 {
217                         bool output;
218                         int status = 0;
219
220                         status = OciGlue.OCIAttrGetBool (handle,
221                                                 (uint) OciDescriptorType.Parameter,
222                                                 out output,
223                                                 IntPtr.Zero,
224                                                 type,
225                                                 ErrorHandle.Handle);
226                         if (status != 0) {
227                                 OciErrorInfo info = ErrorHandle.HandleError ();
228                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
229                         }
230
231                         return output;
232                 }
233
234                 public byte GetAttributeByte (IntPtr handle, OciAttributeType type)
235                 {
236                         byte output;
237                         int status = 0;
238
239                         status = OciGlue.OCIAttrGetByte (handle,
240                                                 (uint) OciDescriptorType.Parameter,
241                                                 out output,
242                                                 IntPtr.Zero,
243                                                 type,
244                                                 ErrorHandle.Handle);
245                         if (status != 0) {
246                                 OciErrorInfo info = ErrorHandle.HandleError ();
247                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
248                         }
249
250                         return output;
251                 }
252
253                 public int GetAttributeInt32 (IntPtr handle, OciAttributeType type)
254                 {
255                         int status = 0;
256                         int output;
257
258                         status = OciGlue.OCIAttrGetInt32 (handle,
259                                                 (uint) OciDescriptorType.Parameter,     
260                                                 out output,
261                                                 IntPtr.Zero,
262                                                 type,
263                                                 ErrorHandle.Handle);
264
265                         if (status != 0) {
266                                 OciErrorInfo info = ErrorHandle.HandleError ();
267                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
268                         }
269
270                         return output;
271                 }
272
273                 [MonoTODO]
274                 public string GetAttributeString (IntPtr handle, OciAttributeType type)
275                 {
276                         string output = String.Empty;
277                         IntPtr outputPtr = IntPtr.Zero;
278                         int outSize;
279                         int status = 0;
280
281                         status = OciGlue.OCIAttrGet (handle,
282                                                 (uint) OciDescriptorType.Parameter,
283                                                 out outputPtr,
284                                                 out outSize,
285                                                 type,
286                                                 ErrorHandle.Handle);
287                         if (status != 0) {
288                                 OciErrorInfo info = ErrorHandle.HandleError ();
289                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
290                         }
291
292                         if (outputPtr != IntPtr.Zero && outSize > 0) {
293                                 object name = Marshal.PtrToStringAnsi (outputPtr, outSize);
294                                 if (name != null) {
295                                         output = String.Copy ((string) name);
296                                         /* TRWC 
297                                          * We shouldn't really free this, but how can we make Oracle
298                                          * do it?
299                                          */
300                                         // Marshal.FreeHGlobal (outputPtr); -- this *may* leak memory
301                                 }
302                         }
303
304                         return output;
305                 }
306
307                 [MonoTODO]
308                 public OciColumnInfo DescribeColumn (int ordinal)
309                 {
310                         int status = 0;
311                         OciColumnInfo columnInfo;
312
313                         string schemaName;      
314
315                         IntPtr parameterHandle = CreateParameterHandle (ordinal + 1);
316
317                         columnInfo.ColumnName = ""; // GetAttributeString (parameterHandle, OciAttributeType.DisplayName);
318                         columnInfo.ColumnOrdinal = ordinal + 1;
319                         columnInfo.ColumnSize = GetAttributeInt32 (parameterHandle, OciAttributeType.DataSize);
320                         columnInfo.Precision = GetAttributeByte (parameterHandle, OciAttributeType.Precision);
321                         columnInfo.Scale = GetAttributeByte (parameterHandle, OciAttributeType.Scale);
322                         columnInfo.DataType = (OciDataType) GetAttributeInt32 (parameterHandle, OciAttributeType.DataType);
323                         columnInfo.AllowDBNull = GetAttributeBool (parameterHandle, OciAttributeType.IsNull);
324                         columnInfo.BaseColumnName = GetAttributeString (parameterHandle, OciAttributeType.Name);
325
326                         // TRWC not sure what to do with this yet.
327                         schemaName = GetAttributeString (parameterHandle, OciAttributeType.SchemaName);
328
329                         FreeParameterHandle (parameterHandle);
330
331                         return columnInfo;
332                 }
333
334                 public OciStatementType GetStatementType ()
335                 {
336                         int status = 0;
337                         int statementType;
338
339                         status = OciGlue.OCIAttrGetInt32 (Handle,
340                                                         (uint) OciHandleType.Statement,
341                                                         out statementType,
342                                                         IntPtr.Zero,
343                                                         OciAttributeType.StatementType,
344                                                         errorHandle.Handle);
345                         if (status != 0) {
346                                 OciErrorInfo info = ErrorHandle.HandleError ();
347                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
348                         }
349
350                         return (OciStatementType) statementType;
351                 }
352
353                 public bool Fetch ()
354                 {
355                         int status = 0;
356                         status = OCIStmtFetch (Handle,
357                                                 ErrorHandle.Handle,
358                                                 1,
359                                                 2,
360                                                 0);
361
362                         switch (status) {
363                         case OciGlue.OCI_NO_DATA:
364                                 moreResults = false;
365                                 break;
366                         case OciGlue.OCI_DEFAULT:
367                                 moreResults = true;
368                                 break;
369                         default:
370                                 OciErrorInfo info = ErrorHandle.HandleError ();
371                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
372                         }
373
374                         return moreResults;
375                 }
376
377                 public void Prepare (string commandText)
378                 {
379                         int status = 0;
380                         status = OCIStmtPrepare (Handle,
381                                                 errorHandle.Handle,
382                                                 commandText,
383                                                 commandText.Length,
384                                                 language,
385                                                 mode);
386                         if (status != 0) {
387                                 OciErrorInfo info = ErrorHandle.HandleError ();
388                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
389                         }
390                 }
391
392                 #endregion // Methods
393         }
394 }