2002-11-26 Tim Coleman <tim@timcoleman.com>
[mono.git] / mcs / class / Mono.Data.SybaseClient / Mono.Data.SybaseClient / SybaseParameter.cs
1 //
2 // Mono.Data.SybaseClient.SybaseParameter.cs
3 //
4 // Author:
5 //   Rodrigo Moya (rodrigo@ximian.com)
6 //   Daniel Morgan (danmorg@sc.rr.com)
7 //   Tim Coleman (tim@timcoleman.com)
8 //
9 // (C) Ximian, Inc. 2002
10 // Copyright (C) Tim Coleman, 2002
11 //
12
13 using Mono.Data.Tds;
14 using Mono.Data.Tds.Protocol;
15 using System;
16 using System.ComponentModel;
17 using System.Data;
18 using System.Data.Common;
19 using System.Runtime.InteropServices;
20 using System.Text;
21
22 namespace Mono.Data.SybaseClient {
23         public sealed class SybaseParameter : MarshalByRefObject, IDbDataParameter, IDataParameter, ICloneable
24         {
25                 #region Fields
26
27                 TdsMetaParameter metaParameter;
28
29                 SybaseParameterCollection container = null;
30                 DbType dbType;
31                 ParameterDirection direction = ParameterDirection.Input;
32                 bool isNullable;
33                 bool isSizeSet = false;
34                 bool isTypeSet = false;
35                 int offset;
36                 SybaseType sybaseType;
37                 string sourceColumn;
38                 DataRowVersion sourceVersion;
39
40                 #endregion // Fields
41
42                 #region Constructors
43
44                 public SybaseParameter () 
45                         : this (String.Empty, SybaseType.NVarChar, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
46                 {
47                 }
48
49                 public SybaseParameter (string parameterName, object value) 
50                 {
51                         metaParameter = new TdsMetaParameter (parameterName, value);
52                         this.sourceVersion = DataRowVersion.Current;
53                         InferSybaseType (value);
54                 }
55                 
56                 public SybaseParameter (string parameterName, SybaseType dbType) 
57                         : this (parameterName, dbType, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
58                 {
59                 }
60
61                 public SybaseParameter (string parameterName, SybaseType dbType, int size) 
62                         : this (parameterName, dbType, size, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
63                 {
64                 }
65                 
66                 public SybaseParameter (string parameterName, SybaseType dbType, int size, string sourceColumn) 
67                         : this (parameterName, dbType, size, ParameterDirection.Input, false, 0, 0, sourceColumn, DataRowVersion.Current, null)
68                 {
69                 }
70                 
71                 [EditorBrowsable (EditorBrowsableState.Advanced)]        
72                 public SybaseParameter (string parameterName, SybaseType dbType, int size, ParameterDirection direction, bool isNullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value) 
73                 {
74                         metaParameter = new TdsMetaParameter (parameterName, size, isNullable, precision, scale, value);
75
76                         SybaseType = dbType;
77                         Direction = direction;
78                         SourceColumn = sourceColumn;
79                         SourceVersion = sourceVersion;
80                 }
81
82                 // This constructor is used internally to construct a
83                 // SybaseParameter.  The value array comes from sp_procedure_params_rowset.
84                 // This is in SybaseCommand.DeriveParameters.
85                 internal SybaseParameter (object[] dbValues)
86                 {
87                         Precision = 0;
88                         Scale = 0;
89                         Direction = ParameterDirection.Input;
90
91                         ParameterName = (string) dbValues[3];
92
93                         switch ((short) dbValues[5]) {
94                         case 1:
95                                 Direction = ParameterDirection.Input;
96                                 break;
97                         case 2:
98                                 Direction = ParameterDirection.Output;
99                                 break;
100                         case 3:
101                                 Direction = ParameterDirection.InputOutput;
102                                 break;
103                         case 4:
104                                 Direction = ParameterDirection.ReturnValue;
105                                 break;
106                         }
107
108                         IsNullable = (bool) dbValues[8];
109
110                         if (dbValues[12] != null)
111                                 Precision = (byte) ((short) dbValues[12]);
112                         if (dbValues[13] != null)
113                                 Scale = (byte) ((short) dbValues[13]);
114
115                         SetDbTypeName ((string) dbValues[16]);
116                 }
117
118                 #endregion // Constructors
119
120                 #region Properties
121
122                 // Used to ensure that only one collection can contain this
123                 // parameter
124                 internal SybaseParameterCollection Container {
125                         get { return container; }
126                         set { container = value; }
127                 }
128
129                 public DbType DbType {
130                         get { return dbType; }
131                         set { 
132                                 SetDbType (value); 
133                                 isTypeSet = true;
134                         }
135                 }
136
137                 public ParameterDirection Direction {
138                         get { return direction; }
139                         set { 
140                                 direction = value; 
141                                 if (direction == ParameterDirection.Output)
142                                         MetaParameter.Direction = TdsParameterDirection.Output;
143                         }
144                 }
145
146                 internal TdsMetaParameter MetaParameter {
147                         get { return metaParameter; }
148                 }
149
150                 string IDataParameter.ParameterName {
151                         get { return metaParameter.ParameterName; }
152                         set { metaParameter.ParameterName = value; }
153                 }
154
155                 public bool IsNullable  {
156                         get { return metaParameter.IsNullable; }
157                         set { metaParameter.IsNullable = value; }
158                 }
159
160                 public int Offset {
161                         get { return offset; }
162                         set { offset = value; }
163                 }
164                 
165                 public string ParameterName {
166                         get { return metaParameter.ParameterName; }
167                         set { metaParameter.ParameterName = value; }
168                 }
169
170                 public byte Precision {
171                         get { return metaParameter.Precision; }
172                         set { metaParameter.Precision = value; }
173                 }
174
175                 public byte Scale {
176                         get { return metaParameter.Scale; }
177                         set { metaParameter.Scale = value; }
178                 }
179
180                 public int Size {
181                         get { return metaParameter.Size; }
182                         set { metaParameter.Size = value; }
183                 }
184
185                 public string SourceColumn {
186                         get { return sourceColumn; }
187                         set { sourceColumn = value; }
188                 }
189
190                 public DataRowVersion SourceVersion {
191                         get { return sourceVersion; }
192                         set { sourceVersion = value; }
193                 }
194                 
195                 public SybaseType SybaseType {
196                         get { return sybaseType; }
197                         set { 
198                                 SetSybaseType (value); 
199                                 isTypeSet = true;
200                         }
201                 }
202
203                 public object Value {
204                         get { return metaParameter.Value; }
205                         set { 
206                                 if (!isTypeSet)
207                                         InferSybaseType (value);
208                                 metaParameter.Value = value; 
209                         }
210                 }
211
212                 #endregion // Properties
213
214                 #region Methods
215
216                 object ICloneable.Clone ()
217                 {
218                         return new SybaseParameter (ParameterName, SybaseType, Size, Direction, IsNullable, Precision, Scale, SourceColumn, SourceVersion, Value);
219                 }
220
221                 // If the value is set without the DbType/SybaseType being set, then we
222                 // infer type information.
223                 private void InferSybaseType (object value)
224                 {
225                         Type type = value.GetType ();
226
227                         string exception = String.Format ("The parameter data type of {0} is invalid.", type.Name);
228
229                         switch (type.FullName) {
230                         case "System.Int64":
231                                 SetSybaseType (SybaseType.BigInt);
232                                 break;
233                         case "System.Boolean":
234                                 SetSybaseType (SybaseType.Bit);
235                                 break;
236                         case "System.String":
237                                 SetSybaseType (SybaseType.NVarChar);
238                                 break;
239                         case "System.DateTime":
240                                 SetSybaseType (SybaseType.DateTime);
241                                 break;
242                         case "System.Decimal":
243                                 SetSybaseType (SybaseType.Decimal);
244                                 break;
245                         case "System.Double":
246                                 SetSybaseType (SybaseType.Float);
247                                 break;
248                         case "System.Byte[]":
249                                 SetSybaseType (SybaseType.VarBinary);
250                                 break;
251                         case "System.Byte":
252                                 SetSybaseType (SybaseType.TinyInt);
253                                 break;
254                         case "System.Int32":
255                                 SetSybaseType (SybaseType.Int);
256                                 break;
257                         case "System.Single":
258                                 SetSybaseType (SybaseType.Real);
259                                 break;
260                         case "System.Int16":
261                                 SetSybaseType (SybaseType.SmallInt);
262                                 break;
263                         case "System.Guid":
264                                 SetSybaseType (SybaseType.UniqueIdentifier);
265                                 break;
266                         case "System.Object":
267                                 SetSybaseType (SybaseType.Variant);
268                                 break;
269                         default:
270                                 throw new ArgumentException (exception);                                
271                         }
272                 }
273
274                 // When the DbType is set, we also set the SybaseType, as well as the SQL Server
275                 // string representation of the type name.  If the DbType is not convertible
276                 // to an SybaseType, throw an exception.
277                 private void SetDbType (DbType type)
278                 {
279                         string exception = String.Format ("No mapping exists from DbType {0} to a known SybaseType.", type);
280
281                         switch (type) {
282                         case DbType.AnsiString:
283                                 MetaParameter.TypeName = "varchar";
284                                 sybaseType = SybaseType.VarChar;
285                                 break;
286                         case DbType.AnsiStringFixedLength:
287                                 MetaParameter.TypeName = "char";
288                                 sybaseType = SybaseType.Char;
289                                 break;
290                         case DbType.Binary:
291                                 MetaParameter.TypeName = "varbinary";
292                                 sybaseType = SybaseType.VarBinary;
293                                 break;
294                         case DbType.Boolean:
295                                 MetaParameter.TypeName = "bit";
296                                 sybaseType = SybaseType.Bit;
297                                 break;
298                         case DbType.Byte:
299                                 MetaParameter.TypeName = "tinyint";
300                                 sybaseType = SybaseType.TinyInt;
301                                 break;
302                         case DbType.Currency:
303                                 sybaseType = SybaseType.Money;
304                                 MetaParameter.TypeName = "money";
305                                 break;
306                         case DbType.Date:
307                         case DbType.DateTime:
308                                 MetaParameter.TypeName = "datetime";
309                                 sybaseType = SybaseType.DateTime;
310                                 break;
311                         case DbType.Decimal:
312                                 MetaParameter.TypeName = "decimal";
313                                 sybaseType = SybaseType.Decimal;
314                                 break;
315                         case DbType.Double:
316                                 MetaParameter.TypeName = "float";
317                                 sybaseType = SybaseType.Float;
318                                 break;
319                         case DbType.Guid:
320                                 MetaParameter.TypeName = "uniqueidentifier";
321                                 sybaseType = SybaseType.UniqueIdentifier;
322                                 break;
323                         case DbType.Int16:
324                                 MetaParameter.TypeName = "smallint";
325                                 sybaseType = SybaseType.SmallInt;
326                                 break;
327                         case DbType.Int32:
328                                 MetaParameter.TypeName = "int";
329                                 sybaseType = SybaseType.Int;
330                                 break;
331                         case DbType.Int64:
332                                 MetaParameter.TypeName = "bigint";
333                                 sybaseType = SybaseType.BigInt;
334                                 break;
335                         case DbType.Object:
336                                 MetaParameter.TypeName = "sql_variant";
337                                 sybaseType = SybaseType.Variant;
338                                 break;
339                         case DbType.Single:
340                                 MetaParameter.TypeName = "real";
341                                 sybaseType = SybaseType.Real;
342                                 break;
343                         case DbType.String:
344                                 MetaParameter.TypeName = "nvarchar";
345                                 sybaseType = SybaseType.NVarChar;
346                                 break;
347                         case DbType.StringFixedLength:
348                                 MetaParameter.TypeName = "nchar";
349                                 sybaseType = SybaseType.NChar;
350                                 break;
351                         case DbType.Time:
352                                 MetaParameter.TypeName = "datetime";
353                                 sybaseType = SybaseType.DateTime;
354                                 break;
355                         default:
356                                 throw new ArgumentException (exception);
357                         }
358                         dbType = type;
359                 }
360
361                 // Used by internal constructor which has a SQL Server typename
362                 private void SetDbTypeName (string dbTypeName)
363                 {
364                         switch (dbTypeName.ToLower ()) {        
365                         case "bigint":
366                                 SybaseType = SybaseType.BigInt;
367                                 break;
368                         case "binary":
369                                 SybaseType = SybaseType.Binary;
370                                 break;
371                         case "bit":
372                                 SybaseType = SybaseType.Bit;
373                                 break;
374                         case "char":
375                                 SybaseType = SybaseType.Char;
376                                 break;
377                         case "datetime":
378                                 SybaseType = SybaseType.DateTime;
379                                 break;
380                         case "decimal":
381                                 SybaseType = SybaseType.Decimal;
382                                 break;
383                         case "float":
384                                 SybaseType = SybaseType.Float;
385                                 break;
386                         case "image":
387                                 SybaseType = SybaseType.Image;
388                                 break;
389                         case "int":
390                                 SybaseType = SybaseType.Int;
391                                 break;
392                         case "money":
393                                 SybaseType = SybaseType.Money;
394                                 break;
395                         case "nchar":
396                                 SybaseType = SybaseType.NChar;
397                                 break;
398                         case "ntext":
399                                 SybaseType = SybaseType.NText;
400                                 break;
401                         case "nvarchar":
402                                 SybaseType = SybaseType.NVarChar;
403                                 break;
404                         case "real":
405                                 SybaseType = SybaseType.Real;
406                                 break;
407                         case "smalldatetime":
408                                 SybaseType = SybaseType.SmallDateTime;
409                                 break;
410                         case "smallint":
411                                 SybaseType = SybaseType.SmallInt;
412                                 break;
413                         case "smallmoney":
414                                 SybaseType = SybaseType.SmallMoney;
415                                 break;
416                         case "text":
417                                 SybaseType = SybaseType.Text;
418                                 break;
419                         case "timestamp":
420                                 SybaseType = SybaseType.Timestamp;
421                                 break;
422                         case "tinyint":
423                                 SybaseType = SybaseType.TinyInt;
424                                 break;
425                         case "uniqueidentifier":
426                                 SybaseType = SybaseType.UniqueIdentifier;
427                                 break;
428                         case "varbinary":
429                                 SybaseType = SybaseType.VarBinary;
430                                 break;
431                         case "varchar":
432                                 SybaseType = SybaseType.VarChar;
433                                 break;
434                         default:
435                                 SybaseType = SybaseType.Variant;
436                                 break;
437                         }
438                 }
439
440                 // When the SybaseType is set, we also set the DbType, as well as the SQL Server
441                 // string representation of the type name.  If the SybaseType is not convertible
442                 // to a DbType, throw an exception.
443                 private void SetSybaseType (SybaseType type)
444                 {
445                         string exception = String.Format ("No mapping exists from SybaseType {0} to a known DbType.", type);
446
447                         switch (type) {
448                         case SybaseType.BigInt:
449                                 MetaParameter.TypeName = "bigint";
450                                 dbType = DbType.Int64;
451                                 break;
452                         case SybaseType.Binary:
453                                 MetaParameter.TypeName = "binary";
454                                 dbType = DbType.Binary;
455                                 break;
456                         case SybaseType.Timestamp:
457                                 MetaParameter.TypeName = "timestamp";
458                                 dbType = DbType.Binary;
459                                 break;
460                         case SybaseType.VarBinary:
461                                 MetaParameter.TypeName = "varbinary";
462                                 dbType = DbType.Binary;
463                                 break;
464                         case SybaseType.Bit:
465                                 MetaParameter.TypeName = "bit";
466                                 dbType = DbType.Boolean;
467                                 break;
468                         case SybaseType.Char:
469                                 MetaParameter.TypeName = "char";
470                                 dbType = DbType.AnsiStringFixedLength;
471                                 break;
472                         case SybaseType.DateTime:
473                                 MetaParameter.TypeName = "datetime";
474                                 dbType = DbType.DateTime;
475                                 break;
476                         case SybaseType.SmallDateTime:
477                                 MetaParameter.TypeName = "smalldatetime";
478                                 dbType = DbType.DateTime;
479                                 break;
480                         case SybaseType.Decimal:
481                                 MetaParameter.TypeName = "decimal";
482                                 dbType = DbType.Decimal;
483                                 break;
484                         case SybaseType.Float:
485                                 MetaParameter.TypeName = "float";
486                                 dbType = DbType.Double;
487                                 break;
488                         case SybaseType.Image:
489                                 MetaParameter.TypeName = "image";
490                                 dbType = DbType.Binary;
491                                 break;
492                         case SybaseType.Int:
493                                 MetaParameter.TypeName = "int";
494                                 dbType = DbType.Int32;
495                                 break;
496                         case SybaseType.Money:
497                                 MetaParameter.TypeName = "money";
498                                 dbType = DbType.Currency;
499                                 break;
500                         case SybaseType.SmallMoney:
501                                 MetaParameter.TypeName = "smallmoney";
502                                 dbType = DbType.Currency;
503                                 break;
504                         case SybaseType.NChar:
505                                 MetaParameter.TypeName = "nchar";
506                                 dbType = DbType.StringFixedLength;
507                                 break;
508                         case SybaseType.NText:
509                                 MetaParameter.TypeName = "ntext";
510                                 dbType = DbType.String;
511                                 break;
512                         case SybaseType.NVarChar:
513                                 MetaParameter.TypeName = "nvarchar";
514                                 dbType = DbType.String;
515                                 break;
516                         case SybaseType.Real:
517                                 MetaParameter.TypeName = "real";
518                                 dbType = DbType.Single;
519                                 break;
520                         case SybaseType.SmallInt:
521                                 MetaParameter.TypeName = "smallint";
522                                 dbType = DbType.Int16;
523                                 break;
524                         case SybaseType.Text:
525                                 MetaParameter.TypeName = "text";
526                                 dbType = DbType.AnsiString;
527                                 break;
528                         case SybaseType.VarChar:
529                                 MetaParameter.TypeName = "varchar";
530                                 dbType = DbType.AnsiString;
531                                 break;
532                         case SybaseType.TinyInt:
533                                 MetaParameter.TypeName = "tinyint";
534                                 dbType = DbType.Byte;
535                                 break;
536                         case SybaseType.UniqueIdentifier:
537                                 MetaParameter.TypeName = "uniqueidentifier";
538                                 dbType = DbType.Guid;
539                                 break;
540                         case SybaseType.Variant:
541                                 MetaParameter.TypeName = "sql_variant";
542                                 dbType = DbType.Object;
543                                 break;
544                         default:
545                                 throw new ArgumentException (exception);
546                         }
547                         sybaseType = type;
548                 }
549
550                 public override string ToString() 
551                 {
552                         return ParameterName;
553                 }
554
555                 #endregion // Methods
556         }
557 }