2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / System.Data.OracleClient / System.Data.OracleClient / OracleParameter.cs
1 // 
2 // OracleParameter.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 //    Tim Coleman <tim@timcoleman.com>
12 //
13 // Copyright (C) Tim Coleman , 2003
14 //
15 // Licensed under the MIT/X11 License.
16 //
17
18 using System;
19 using System.Collections;
20 using System.ComponentModel;
21 using System.Data;
22 using System.Data.OracleClient.Oci;
23 using System.Globalization;
24 using System.Runtime.InteropServices;
25
26 namespace System.Data.OracleClient {
27         [TypeConverter (typeof(OracleParameter.OracleParameterConverter))]
28         public sealed class OracleParameter : MarshalByRefObject, IDbDataParameter, IDataParameter, ICloneable
29         {
30                 #region Fields
31
32                 string name;
33                 OracleType oracleType = OracleType.VarChar;
34                 OciDataType ociType;
35                 int size;
36                 ParameterDirection direction = ParameterDirection.Input;
37                 bool isNullable;
38                 byte precision;
39                 byte scale;
40                 string srcColumn;
41                 DataRowVersion srcVersion;
42                 DbType dbType = DbType.AnsiString;
43                 int offset = 0;
44                 bool sizeSet = false;
45                 object value = null;
46
47                 OracleParameterCollection container = null;
48                 OciBindHandle bindHandle;
49
50                 #endregion // Fields
51
52                 #region Constructors
53
54                 public OracleParameter ()
55                         : this (String.Empty, OracleType.VarChar, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
56                 {
57                 }
58
59                 public OracleParameter (string name, object value)
60                 {
61                         this.name = name;
62                         this.value = value;
63                         SourceVersion = DataRowVersion.Current;
64                         InferOracleType (value);
65                 }
66
67                 public OracleParameter (string name, OracleType dataType)
68                         : this (name, dataType, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
69                 {
70                 }
71
72                 public OracleParameter (string name, OracleType dataType, int size)
73                         : this (name, dataType, size, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
74                 {
75                 }
76
77                 public OracleParameter (string name, OracleType dataType, int size, string srcColumn)
78                         : this (name, dataType, size, ParameterDirection.Input, false, 0, 0, srcColumn, DataRowVersion.Current, null)
79                 {
80                 }
81
82                 public OracleParameter (string name, OracleType dataType, int size, ParameterDirection direction, bool isNullable, byte precision, byte scale, string srcColumn, DataRowVersion srcVersion, object value)
83                 {
84                         this.name = name;
85                         this.size = size;
86                         this.value = value;
87
88                         OracleType = dataType;
89                         Direction = direction;
90                         SourceColumn = srcColumn;
91                         SourceVersion = srcVersion;
92                 }
93
94                 #endregion // Constructors
95
96                 #region Properties
97
98                 internal OracleParameterCollection Container {
99                         get { return container; }
100                         set { container = value; }
101                 }
102
103                 [Browsable (false)]
104                 [RefreshProperties (RefreshProperties.All)]
105                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
106                 public DbType DbType {
107                         get { return dbType; }
108                         set { SetDbType (value); }
109                 }
110
111                 [DefaultValue (ParameterDirection.Input)]
112                 [RefreshProperties (RefreshProperties.All)]
113                 public ParameterDirection Direction {
114                         get { return direction; }
115                         set { direction = value; }
116                 }
117
118                 [Browsable (false)]
119                 [DesignOnly (true)]
120                 [DefaultValue (false)]
121                 [EditorBrowsable (EditorBrowsableState.Never)]
122                 public bool IsNullable {
123                         get { return isNullable; }
124                         set { isNullable = value; }
125                 }
126
127                 [DefaultValue (0)]
128                 [Browsable (false)]
129                 public int Offset {
130                         get { return offset; }
131                         set { offset = value; }
132                 }
133
134                 [DefaultValue (OracleType.VarChar)]
135                 [RefreshProperties (RefreshProperties.All)]
136                 public OracleType OracleType {
137                         get { return oracleType; }
138                         set { SetOracleType (value); }
139                 }
140                 
141                 [DefaultValue ("")]
142                 public string ParameterName {
143                         get { return name; }
144                         set { name = value; }
145                 }
146
147                 [DefaultValue (0)]
148                 public byte Precision {
149                         get { return precision; }
150                         set { /* NO EFFECT*/ }
151                 }
152
153                 [DefaultValue (0)]
154                 public byte Scale {
155                         get { return scale; }
156                         set { /* NO EFFECT*/ }
157                 }
158
159                 [DefaultValue (0)]
160                 public int Size {
161                         get { return size; }
162                         set { 
163                                 sizeSet = true;
164                                 size = value; 
165                         }
166                 }
167
168                 [DefaultValue ("")]
169                 public string SourceColumn {
170                         get { return srcColumn; }
171                         set { srcColumn = value; }
172                 }
173
174                 [DefaultValue (DataRowVersion.Current)]
175                 public DataRowVersion SourceVersion {
176                         get { return srcVersion; }
177                         set { srcVersion = value; }
178                 }
179
180                 [DefaultValue (null)]
181                 [RefreshProperties (RefreshProperties.All)]
182                 [TypeConverter (typeof(StringConverter))]
183                 public object Value {
184                         get { return this.value; }
185                         set { this.value = value; }
186                 }
187
188                 #endregion // Properties
189
190                 #region Methods
191
192                 private void AssertSizeIsSet ()
193                 {
194                         if (!sizeSet)
195                                 throw new Exception ("Size must be set.");
196                 }
197
198                 internal void Bind (OciStatementHandle statement, OracleConnection connection)
199                 {
200                         if (bindHandle == null)
201                                 bindHandle = new OciBindHandle ((OciHandle) statement);
202
203                         IntPtr tmpHandle = bindHandle.Handle;
204
205                         if (Direction != ParameterDirection.Input)
206                                 AssertSizeIsSet ();
207                         if (!sizeSet)
208                                 size = InferSize ();
209
210                         int status = 0;
211                         int indicator = 0;
212                         OciDataType bindType = ociType;
213                         IntPtr bindValue = IntPtr.Zero;
214                         int bindSize = size;
215
216                         if (value == DBNull.Value)
217                                 indicator = -1;
218                         else {
219                                 bindType = OciDataType.VarChar2; // FIXME
220                                 bindValue = Marshal.StringToHGlobalAnsi (value.ToString ());
221                                 bindSize = value.ToString ().Length;
222                         }
223
224                         status = OciCalls.OCIBindByName (statement,
225                                                 out tmpHandle,
226                                                 connection.ErrorHandle,
227                                                 ParameterName,
228                                                 ParameterName.Length,
229                                                 bindValue,
230                                                 bindSize,
231                                                 bindType,
232                                                 indicator,
233                                                 IntPtr.Zero,
234                                                 IntPtr.Zero,
235                                                 0,
236                                                 IntPtr.Zero,
237                                                 0);
238
239                         if (status != 0) {
240                                 OciErrorInfo info = connection.ErrorHandle.HandleError ();
241                                 throw new OracleException (info.ErrorCode, info.ErrorMessage);
242                         }
243
244                         bindHandle.SetHandle (tmpHandle);
245                 }
246
247                 [MonoTODO]
248                 object ICloneable.Clone ()
249                 {
250                         throw new NotImplementedException ();
251                 }
252
253                 private void InferOracleType (object value)
254                 {
255                         Type type = value.GetType ();
256                         string exception = String.Format ("The parameter data type of {0} is invalid.", type.Name);
257                         switch (type.FullName) {
258                         case "System.Int64":
259                                 SetOracleType (OracleType.Number);
260                                 break;
261                         case "System.Boolean":
262                         case "System.Byte":
263                                 SetOracleType (OracleType.Byte);
264                                 break;
265                         case "System.String":
266                                 SetOracleType (OracleType.VarChar);
267                                 break;
268                         case "System.DataType":
269                                 SetOracleType (OracleType.DateTime);
270                                 break;
271                         case "System.Decimal":
272                                 SetOracleType (OracleType.Number);
273                                 //scale = ((decimal) value).Scale;
274                                 break;
275                         case "System.Double":
276                                 SetOracleType (OracleType.Double);
277                                 break;
278                         case "System.Byte[]":
279                         case "System.Guid":
280                                 SetOracleType (OracleType.Raw);
281                                 break;
282                         case "System.Int32":
283                                 SetOracleType (OracleType.Int32);
284                                 break;
285                         case "System.Single":
286                                 SetOracleType (OracleType.Float);
287                                 break;
288                         case "System.Int16":
289                                 SetOracleType (OracleType.Int16);
290                                 break;
291                         default:
292                                 throw new ArgumentException (exception);
293                         }
294                 }
295
296                 [MonoTODO ("different size depending on type.")]
297                 private int InferSize ()
298                 {
299                         return value.ToString ().Length;
300                 }
301
302                 private void SetDbType (DbType type)
303                 {
304                         string exception = String.Format ("No mapping exists from DbType {0} to a known OracleType.", type);
305                         switch (type) {
306                         case DbType.AnsiString:
307                                 oracleType = OracleType.VarChar;
308                                 ociType = OciDataType.VarChar;
309                                 break;
310                         case DbType.AnsiStringFixedLength:
311                                 oracleType = OracleType.Char;
312                                 ociType = OciDataType.Char;
313                                 break;
314                         case DbType.Binary:
315                         case DbType.Guid:
316                                 oracleType = OracleType.Raw;
317                                 ociType = OciDataType.Raw;
318                                 break;
319                         case DbType.Boolean:
320                         case DbType.Byte:
321                                 oracleType = OracleType.Byte;
322                                 ociType = OciDataType.Integer;
323                                 break;
324                         case DbType.Currency:
325                         case DbType.Decimal:
326                         case DbType.Int64:
327                                 oracleType = OracleType.Number;
328                                 ociType = OciDataType.Number;
329                                 break;
330                         case DbType.Date:
331                         case DbType.DateTime:
332                         case DbType.Time:
333                                 oracleType = OracleType.DateTime;
334                                 ociType = OciDataType.Char;
335                                 break;
336                         case DbType.Double:
337                                 oracleType = OracleType.Double;
338                                 ociType = OciDataType.Float;
339                                 break;
340                         case DbType.Int16:
341                                 oracleType = OracleType.Int16;
342                                 ociType = OciDataType.Integer;
343                                 break;
344                         case DbType.Int32:
345                                 oracleType = OracleType.Int32;
346                                 ociType = OciDataType.Integer;
347                                 break;
348                         case DbType.Object:
349                                 oracleType = OracleType.Blob;
350                                 ociType = OciDataType.Blob;
351                                 break;
352                         case DbType.Single:
353                                 oracleType = OracleType.Float;
354                                 ociType = OciDataType.Float;
355                                 break;
356                         case DbType.String:
357                                 oracleType = OracleType.NVarChar;
358                                 ociType = OciDataType.VarChar;
359                                 break;
360                         case DbType.StringFixedLength:
361                                 oracleType = OracleType.NChar;
362                                 ociType = OciDataType.Char;
363                                 break;
364                         default:
365                                 throw new ArgumentException (exception);
366                         }
367                         dbType = type;
368
369                 }
370
371                 private void SetOracleType (OracleType type)
372                 {
373                         string exception = String.Format ("No mapping exists from OracleType {0} to a known DbType.", type);
374                         switch (type) {
375                         case OracleType.BFile:
376                         case OracleType.Blob:
377                         case OracleType.LongRaw:
378                         case OracleType.Raw:
379                                 dbType = DbType.Binary;
380                                 ociType = OciDataType.Raw;
381                                 break;
382                         case OracleType.Byte:
383                                 dbType = DbType.Byte;
384                                 ociType = OciDataType.Integer;
385                                 break;
386                         case OracleType.Char:
387                                 dbType = DbType.AnsiStringFixedLength;
388                                 ociType = OciDataType.Char;
389                                 break;
390                         case OracleType.Clob:
391                         case OracleType.LongVarChar:
392                         case OracleType.RowId:
393                         case OracleType.VarChar:
394                                 dbType = DbType.AnsiString;
395                                 ociType = OciDataType.VarChar;
396                                 break;
397                         case OracleType.Cursor:
398                         case OracleType.IntervalDayToSecond:
399                                 dbType = DbType.Object;
400                                 ociType = OciDataType.Blob;
401                                 break;
402                         case OracleType.DateTime:
403                         case OracleType.Timestamp:
404                         case OracleType.TimestampLocal:
405                         case OracleType.TimestampWithTZ:
406                                 dbType = DbType.DateTime;
407                                 ociType = OciDataType.Char;
408                                 break;
409                         case OracleType.Double:
410                                 dbType = DbType.Double;
411                                 ociType = OciDataType.Float;
412                                 break;
413                         case OracleType.Float:
414                                 dbType = DbType.Single;
415                                 ociType = OciDataType.Float;
416                                 break;
417                         case OracleType.Int16:
418                                 dbType = DbType.Int16;
419                                 ociType = OciDataType.Integer;
420                                 break;
421                         case OracleType.Int32:
422                         case OracleType.IntervalYearToMonth:
423                                 dbType = DbType.Int32;
424                                 ociType = OciDataType.Integer;
425                                 break;
426                         case OracleType.NChar:
427                                 dbType = DbType.StringFixedLength;
428                                 ociType = OciDataType.Char;
429                                 break;
430                         case OracleType.NClob:
431                         case OracleType.NVarChar:
432                                 dbType = DbType.String;
433                                 ociType = OciDataType.VarChar;
434                                 break;
435                         case OracleType.Number:
436                                 dbType = DbType.VarNumeric;
437                                 ociType = OciDataType.Number;
438                                 break;
439                         case OracleType.SByte:
440                                 dbType = DbType.SByte;
441                                 ociType = OciDataType.Integer;
442                                 break;
443                         case OracleType.UInt16:
444                                 dbType = DbType.UInt16;
445                                 ociType = OciDataType.Integer;
446                                 break;
447                         case OracleType.UInt32:
448                                 dbType = DbType.UInt32;
449                                 ociType = OciDataType.Integer;
450                                 break;
451                         default:
452                                 throw new ArgumentException (exception);
453                         }
454
455                         oracleType = type;
456                 }
457
458                 public override string ToString ()
459                 {
460                         return ParameterName;
461                 }
462
463                 #endregion // Methods
464
465                 internal sealed class OracleParameterConverter : ExpandableObjectConverter
466                 {
467                         public OracleParameterConverter ()
468                         {
469                         }
470
471                         [MonoTODO]
472                         public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)
473                         {
474                                 throw new NotImplementedException ();
475                         }
476
477                         [MonoTODO]
478                         public override object ConvertTo (ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
479                         {
480                                 throw new NotImplementedException ();
481                         }
482                 }
483         }
484 }