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