svn path=/trunk/mcs/; revision=104772
[mono.git] / mcs / class / Mono.Data.Tds / Mono.Data.Tds / TdsMetaParameter.cs
index 8a59211cff8e2c76207d98505d0288ad33b1fe88..77b2e5294f46ff94b3b18c6a5223222eaffd61e5 100644 (file)
@@ -46,6 +46,7 @@ namespace Mono.Data.Tds {
                bool isSizeSet = false;
                bool isNullable;
                object value;
+               bool isVariableSizeType;
 
                #endregion // Fields
 
@@ -96,7 +97,37 @@ namespace Mono.Data.Tds {
 
                public object Value {
                        get { return value; }
-                       set { this.value = value; }
+                       set { 
+                               if (value == DBNull.Value || value == null) {
+                                       this.value = value;
+                                       return;
+                               }
+
+                               // if size is set, truncate the value to specified size
+                               if (value.GetType () == typeof (string)) {
+                                       int len = ((string)value).Length;
+                                       
+                                       if ((TypeName == "nvarchar" || 
+                                            TypeName == "nchar") 
+                                           && isSizeSet && size > 0 && len > size) {
+                                               this.value = ((string)value).Substring (0, size);
+                                       } else {
+                                               this.value = value;
+                                       }
+                               } else if (value.GetType () == typeof (byte[])) {
+                                       int len = ((byte[])value).Length;
+                                       
+                                       if (isSizeSet && size > 0 && len > size ) {
+                                               byte [] tmpVal = new byte [size];
+                                               Array.Copy (((byte[]) value), ((byte[]) this.value), size);
+                                               this.value = tmpVal;
+                                       } else {
+                                               this.value = value;
+                                       }
+                               } else {
+                                       this.value = value;
+                               }
+                       }
                }
 
                public byte Precision {
@@ -126,6 +157,12 @@ namespace Mono.Data.Tds {
                        }
                }
 
+               public bool IsVariableSizeType
+               {
+                       get { return isVariableSizeType; }
+                       set { isVariableSizeType = value; }
+               }
+
                #endregion // Properties
 
                #region Methods
@@ -145,7 +182,10 @@ namespace Mono.Data.Tds {
                                }
                        }
                        
-                       StringBuilder result = new StringBuilder (String.Format ("{0} {1}", ParameterName, typeName));
+                       string includeAt = "@";
+                       if (ParameterName [0] == '@')
+                               includeAt = "";
+                       StringBuilder result = new StringBuilder (String.Format ("{0}{1} {2}", includeAt, ParameterName, typeName));
                        switch (typeName) {
                        case "decimal":
                        case "numeric":
@@ -162,10 +202,10 @@ namespace Mono.Data.Tds {
                                        if (size <= 0)
                                                size = 1;
                                }
-                               result.Append (String.Format ("({0})", size));
+                               result.Append (size > 8000 ? "(max)" : String.Format ("({0})", size));
                                break;
                        case "nvarchar":
-                               result.Append (String.Format ("({0})", Size > 0 ? Size : 4000));
+                               result.Append (Size > 0 ? (Size > 8000 ? "(max)" : String.Format ("({0})", Size)) : "(4000)");
                                break;
                        case "char":
                        case "nchar":
@@ -184,7 +224,10 @@ namespace Mono.Data.Tds {
 
                        switch (Value.GetType ().ToString ()) {
                        case "System.String":
-                               return ((string) value).Length;
+                               int len = ((string)value).Length;
+                               if (TypeName == "nvarchar" || TypeName == "nchar" || TypeName == "ntext")
+                                       len *= 2;
+                               return len ;    
                        case "System.Byte[]":
                                return ((byte[]) value).Length;
                        }
@@ -193,45 +236,91 @@ namespace Mono.Data.Tds {
 
                private int GetSize ()
                {
-                       if (IsNullable) {
-                               switch (TypeName) {
-                               case "bigint":
-                                       return 8;
-                               case "datetime":
-                                       return 8;
-                               case "float":
-                                       return 8;
-                               case "int":
-                                       return 4;
-                               case "real":
-                                       return 4;
-                               case "smalldatetime":
-                                       return 4;
-                               case "smallint":
-                                       return 2;
-                               case "tinyint":
-                                       return 1;
-                               }
+                       switch (TypeName) {
+                       case "decimal":
+                               return 17;
+                       case "uniqueidentifier":
+                               return 16;
+                       case "bigint":
+                       case "datetime":
+                       case "float":
+                       case "money":
+                               return 8;
+                       case "int":
+                       case "real":
+                       case "smalldatetime":
+                       case "smallmoney":
+                               return 4;
+                       case "smallint":
+                               return 2;
+                       case "tinyint":
+                       case "bit":
+                               return 1;
+                       /*
+                       case "nvarchar" :
+                       */
+                       case "nchar" :
+                       case "ntext" :
+                               return size*2 ;
                        }
                        return size;
                }
 
+               internal byte[] GetBytes ()
+               {
+                       byte[] result = {};
+                       if (Value == DBNull.Value || Value == null)
+                               return result;
+
+                       switch (TypeName)
+                       {
+                               case "nvarchar" :
+                               case "nchar" :
+                               case "ntext" :
+                                       return Encoding.Unicode.GetBytes ((string)Value);
+                               case "varchar" :
+                               case "char" :
+                               case "text" :
+                                       return Encoding.Default.GetBytes ((string)Value);
+                               default :
+                                       return ((byte[]) Value);
+                       }
+               }
+
                internal TdsColumnType GetMetaType ()
                {
                        switch (TypeName) {
                        case "binary":
-                               return TdsColumnType.Binary;
+                               return TdsColumnType.BigBinary;
                        case "bit":
+                               if (IsNullable)
+                                       return TdsColumnType.BitN;
                                return TdsColumnType.Bit;
+                       case "bigint":
+                               return TdsColumnType.IntN;
                        case "char":
                                return TdsColumnType.Char;
+                       case "money":
+                               if (IsNullable)
+                                       return TdsColumnType.MoneyN;
+                               return TdsColumnType.Money;
+                       case "smallmoney":
+                               if (IsNullable)
+                                       return TdsColumnType.MoneyN ;
+                               return TdsColumnType.Money4;
                        case "decimal":
                                return TdsColumnType.Decimal;
                        case "datetime":
                                if (IsNullable)
                                        return TdsColumnType.DateTimeN;
                                return TdsColumnType.DateTime;
+                       case "smalldatetime":
+                               if (IsNullable)
+                                       return TdsColumnType.DateTimeN;
+                               return TdsColumnType.DateTime4;
                        case "float":
+                               if (IsNullable)
+                                       return TdsColumnType.FloatN ;
                                return TdsColumnType.Float8;
                        case "image":
                                return TdsColumnType.Image;
@@ -246,8 +335,10 @@ namespace Mono.Data.Tds {
                        case "ntext":
                                return TdsColumnType.NText;
                        case "nvarchar":
-                               return TdsColumnType.NVarChar;
+                               return TdsColumnType.BigNVarChar;
                        case "real":
+                               if (IsNullable)
+                                       return TdsColumnType.FloatN ;
                                return TdsColumnType.Real;
                        case "smallint":
                                if (IsNullable)
@@ -262,11 +353,24 @@ namespace Mono.Data.Tds {
                        case "uniqueidentifier":
                                return TdsColumnType.UniqueIdentifier;
                        case "varbinary":
-                               return TdsColumnType.VarBinary;
+                               return TdsColumnType.BigVarBinary;
                        case "varchar":
-                               return TdsColumnType.VarChar;
+                               return TdsColumnType.BigVarChar;
                        default:
-                               throw new NotSupportedException ();
+                               throw new NotSupportedException ("Unknown Type : " + TypeName);
+                       }
+               }
+
+               public void Validate (int index)
+               {
+                       if ((this.direction == TdsParameterDirection.InputOutput || this.direction == TdsParameterDirection.Output) &&
+                                this.isVariableSizeType && (Value == DBNull.Value || Value == null) && Size == 0
+                               ) 
+                       {
+                               throw new InvalidOperationException (String.Format ("{0}[{1}]: the Size property should " +
+                                                                                               "not be of size 0",
+                                                                                               this.typeName,
+                                                                                               index));
                        }
                }