6f03f656d9424e5ff7afc0f9027f26f9a692b202
[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 sbyte GetAttributeSByte (IntPtr handle, OciAttributeType type) {
235                         sbyte output;
236                         int status = 0;
237
238                         status = OciGlue.OCIAttrGetSByte (handle,
239                                 (uint) OciDescriptorType.Parameter,
240                                 out output,
241                                 IntPtr.Zero,
242                                 type,
243                                 ErrorHandle.Handle);
244                         if (status != 0) {
245                                 OciErrorInfo info = ErrorHandle.HandleError ();
246                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
247                         }
248
249                         return output;
250                 }
251
252                 public byte GetAttributeByte (IntPtr handle, OciAttributeType type)
253                 {
254                         byte output;
255                         int status = 0;
256
257                         status = OciGlue.OCIAttrGetByte (handle,
258                                                 (uint) OciDescriptorType.Parameter,
259                                                 out output,
260                                                 IntPtr.Zero,
261                                                 type,
262                                                 ErrorHandle.Handle);
263                         if (status != 0) {
264                                 OciErrorInfo info = ErrorHandle.HandleError ();
265                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
266                         }
267
268                         return output;
269                 }
270
271                 public ushort GetAttributeUInt16 (IntPtr handle, OciAttributeType type) {
272                         int status = 0;
273                         ushort output;
274
275                         status = OciGlue.OCIAttrGetUInt16 (handle,
276                                 (uint) OciDescriptorType.Parameter,     
277                                 out output,
278                                 IntPtr.Zero,
279                                 type,
280                                 ErrorHandle.Handle);
281
282                         if (status != 0) {
283                                 OciErrorInfo info = ErrorHandle.HandleError ();
284                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
285                         }
286
287                         return output;
288                 }
289
290                 public int GetAttributeInt32 (IntPtr handle, OciAttributeType type)
291                 {
292                         int status = 0;
293                         int output;
294
295                         status = OciGlue.OCIAttrGetInt32 (handle,
296                                                 (uint) OciDescriptorType.Parameter,     
297                                                 out output,
298                                                 IntPtr.Zero,
299                                                 type,
300                                                 ErrorHandle.Handle);
301
302                         if (status != 0) {
303                                 OciErrorInfo info = ErrorHandle.HandleError ();
304                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
305                         }
306
307                         return output;
308                 }
309
310                 [MonoTODO]
311                 public string GetAttributeString (IntPtr handle, OciAttributeType type)
312                 {
313                         string output = String.Empty;
314                         IntPtr outputPtr = IntPtr.Zero;
315                         int outSize;
316                         int status = 0;
317
318                         status = OciGlue.OCIAttrGet (handle,
319                                                 (uint) OciDescriptorType.Parameter,
320                                                 out outputPtr,
321                                                 out outSize,
322                                                 type,
323                                                 ErrorHandle.Handle);
324                         if (status != 0) {
325                                 OciErrorInfo info = ErrorHandle.HandleError ();
326                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
327                         }
328
329                         if (outputPtr != IntPtr.Zero && outSize > 0) {
330                                 object name = Marshal.PtrToStringAnsi (outputPtr, outSize);
331                                 if (name != null) {
332                                         output = String.Copy ((string) name);
333                                         /* TRWC 
334                                          * We shouldn't really free this, but how can we make Oracle
335                                          * do it?
336                                          */
337                                         // Marshal.FreeHGlobal (outputPtr); -- this *may* leak memory
338                                 }
339                         }
340
341                         return output;
342                 }
343
344                 [MonoTODO]
345                 public OciColumnInfo DescribeColumn (int ordinal)
346                 {
347                         int status = 0;
348                         OciColumnInfo columnInfo;
349
350                         string schemaName;      
351
352                         IntPtr parameterHandle = CreateParameterHandle (ordinal + 1);
353
354                         columnInfo.ColumnName = GetAttributeString (parameterHandle, OciAttributeType.Name);
355                         columnInfo.ColumnOrdinal = ordinal + 1;
356                         columnInfo.ColumnSize = GetAttributeUInt16 (parameterHandle, OciAttributeType.DataSize);
357                         columnInfo.Precision = GetAttributeByte (parameterHandle, OciAttributeType.Precision);
358                         columnInfo.Scale = GetAttributeSByte (parameterHandle, OciAttributeType.Scale);
359                         columnInfo.DataType = (OciDataType) GetAttributeInt32 (parameterHandle, OciAttributeType.DataType);
360                         columnInfo.AllowDBNull = GetAttributeBool (parameterHandle, OciAttributeType.IsNull);
361                         columnInfo.BaseColumnName = GetAttributeString (parameterHandle, OciAttributeType.Name);
362
363                         // TRWC not sure what to do with this yet.
364                         schemaName = GetAttributeString (parameterHandle, OciAttributeType.SchemaName);
365
366                         FreeParameterHandle (parameterHandle);
367
368                         return columnInfo;
369                 }
370
371                 public OciStatementType GetStatementType ()
372                 {
373                         int status = 0;
374                         int statementType;
375
376                         status = OciGlue.OCIAttrGetInt32 (Handle,
377                                                         (uint) OciHandleType.Statement,
378                                                         out statementType,
379                                                         IntPtr.Zero,
380                                                         OciAttributeType.StatementType,
381                                                         errorHandle.Handle);
382                         if (status != 0) {
383                                 OciErrorInfo info = ErrorHandle.HandleError ();
384                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
385                         }
386
387                         return (OciStatementType) statementType;
388                 }
389
390                 public bool Fetch ()
391                 {
392                         int status = 0;
393                         status = OCIStmtFetch (Handle,
394                                                 ErrorHandle.Handle,
395                                                 1,
396                                                 2,
397                                                 0);
398
399                         switch (status) {
400                         case OciGlue.OCI_NO_DATA:
401                                 moreResults = false;
402                                 break;
403                         case OciGlue.OCI_DEFAULT:
404                                 moreResults = true;
405                                 break;
406                         default:
407                                 OciErrorInfo info = ErrorHandle.HandleError ();
408                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
409                         }
410
411                         return moreResults;
412                 }
413
414                 public void Prepare (string commandText)
415                 {
416                         int status = 0;
417                         status = OCIStmtPrepare (Handle,
418                                                 errorHandle.Handle,
419                                                 commandText,
420                                                 commandText.Length,
421                                                 language,
422                                                 mode);
423                         if (status != 0) {
424                                 OciErrorInfo info = ErrorHandle.HandleError ();
425                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
426                         }
427                 }
428
429                 #endregion // Methods
430         }
431 }