2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / System.Data / System.Data.Odbc / OdbcParameter.cs
index fbf5c04c12565a519dd7d290b5f11ea853319c62..77c2d7e083c755df0d3a086518be63844f22239b 100644 (file)
@@ -7,19 +7,43 @@
 // Copyright (C) Brian Ritchie, 2002
 //
 
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
 using System;
 using System.Data;
 using System.Data.Common;
+using System.ComponentModel;
 
 namespace System.Data.Odbc
 {
-       public sealed class OdbcParameter : MarshalByRefObject, IDbDataParameter, 
-IDataParameter, ICloneable
+       [TypeConverterAttribute (typeof (OdbcParameterConverter))]      
+       public sealed class OdbcParameter : MarshalByRefObject, IDbDataParameter, IDataParameter, ICloneable
        {
                #region Fields
 
                string name;
-               object value;
+               object ParamValue;
                int size;
                bool isNullable;
                byte precision;
@@ -29,17 +53,22 @@ IDataParameter, ICloneable
                ParameterDirection direction;
                OdbcType odbcType;
                DbType dbType;
-
-               int IntValue;
+               OdbcParameterCollection container = null;       
+               
+               // Buffers for parameter value based on type. Currently I've only optimized 
+               // for int parameters and everything else is just converted to a string.
+               private bool bufferIsSet;
+               int intbuf;
+               byte[] buffer;
 
                #endregion
 
                #region Constructors
-
+               
                public OdbcParameter ()
                {
                        name = String.Empty;
-                       value = null;
+                       ParamValue = null;
                        size = 0;
                        isNullable = true;
                        precision = 0;
@@ -47,14 +76,25 @@ IDataParameter, ICloneable
                        sourceColumn = String.Empty;
                }
 
-               public OdbcParameter (string name, object value)
+               public OdbcParameter (string name, object value) 
                        : this ()
                {
                        this.name = name;
-                       this.value = value;
+                       this.ParamValue = value;
+                        
+                        if (value != null && !value.GetType ().IsValueType) {
+                                Type type = value.GetType ();
+                                if (type.IsArray)
+                                        size = type.GetElementType () == typeof (byte) ? 
+                                                ((Array) value).Length : 0;
+                                else
+                                        size = value.ToString ().Length;
+                        }
+
+
                }
 
-               public OdbcParameter (string name, OdbcType dataType)
+               public OdbcParameter (string name, OdbcType dataType) 
                        : this ()
                {
                        this.name = name;
@@ -67,16 +107,14 @@ IDataParameter, ICloneable
                        this.size = size;
                }
 
-               public OdbcParameter (string name, OdbcType dataType, int size, string 
-srcColumn)
+               public OdbcParameter (string name, OdbcType dataType, int size, string srcColumn)
                        : this (name, dataType, size)
                {
                        this.sourceColumn = srcColumn;
                }
 
-               public OdbcParameter(string name, OdbcType dataType, int size, 
-ParameterDirection direction, bool isNullable, byte precision, byte scale, 
-string srcColumn, DataRowVersion srcVersion, object value)
+               [EditorBrowsable (EditorBrowsableState.Advanced)]
+               public OdbcParameter(string name, OdbcType dataType, int size, ParameterDirection direction, bool isNullable, byte precision, byte scale, string srcColumn, DataRowVersion srcVersion, object value)
                        : this (name, dataType, size, srcColumn)
                {
                        this.direction = direction;
@@ -84,94 +122,173 @@ string srcColumn, DataRowVersion srcVersion, object value)
                        this.precision = precision;
                        this.scale = scale;
                        this.sourceVersion = srcVersion;
-                       this.value = value;
+                       this.ParamValue = value;
                }
 
                #endregion
 
                #region Properties
 
+               // Used to ensure that only one collection can contain this
+                // parameter
+                internal OdbcParameterCollection Container {
+                        get { return container; }
+                        set { container = value; }
+                }
+               
+               [BrowsableAttribute (false)]
+                [OdbcDescriptionAttribute ("The parameter generic type")]
+                [RefreshPropertiesAttribute (RefreshProperties.All)]
+                [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
+               [OdbcCategory ("Data")]
                public DbType DbType {
                        get { return dbType; }
-                       set {
+                       set { 
                                dbType = value;
                        }
                }
-
+               
+               [OdbcCategory ("Data")]
+               [OdbcDescriptionAttribute ("Input, output, or bidirectional parameter")]  
+               [DefaultValue (ParameterDirection.Input)]
                public ParameterDirection Direction {
                        get { return direction; }
                        set { direction = value; }
                }
-
+               
+               [BrowsableAttribute (false)]
+                [OdbcDescriptionAttribute ("A design-time property used for strongly typed code generation")]
+                [DesignOnlyAttribute (true)]
+                [EditorBrowsableAttribute (EditorBrowsableState.Advanced)]
+                [DefaultValue (false)]
                public bool IsNullable {
-                       get { return isNullable; }
+                       get { return isNullable; }\r
+                       set { isNullable = value; }\r
                }
 
+               [DefaultValue (OdbcType.NChar)]
+                [OdbcDescriptionAttribute ("The parameter native type")]
+                [RefreshPropertiesAttribute (RefreshProperties.All)]
+               [OdbcCategory ("Data")]
                public OdbcType OdbcType {
                        get { return odbcType; }
                        set {
                                odbcType = value;
                        }
                }
-
+               
+               [OdbcDescription ("DataParameter_ParameterName")]
+                [DefaultValue ("")]    
                public string ParameterName {
                        get { return name; }
                        set { name = value; }
                }
 
+               [OdbcDescription ("DbDataParameter_Precision")]
+                [OdbcCategory ("DataCategory_Data")]
+                [DefaultValue (0)]
                public byte Precision {
                        get { return precision; }
                        set { precision = value; }
                }
-
+               
+                [OdbcDescription ("DbDataParameter_Scale")]
+                [OdbcCategory ("DataCategory_Data")]
+                [DefaultValue (0)]
                public byte Scale {
                        get { return scale; }
                        set { scale = value; }
                }
-
+               
+               [OdbcDescription ("DbDataParameter_Size")]
+                [OdbcCategory ("DataCategory_Data")]
+                [DefaultValue (0)]
                public int Size {
                        get { return size; }
                        set { size = value; }
                }
 
+               [OdbcDescription ("DataParameter_SourceColumn")]
+                [OdbcCategory ("DataCategory_Data")]
+                [DefaultValue ("")]
                public string SourceColumn {
                        get { return sourceColumn; }
                        set { sourceColumn = value; }
                }
-
+               
+                [OdbcDescription ("DataParameter_SourceVersion")]
+                [OdbcCategory ("DataCategory_Data")]
+                [DefaultValue (512)]                   
                public DataRowVersion SourceVersion {
                        get { return sourceVersion; }
                        set { sourceVersion = value; }
                }
 
+               [TypeConverter (typeof(StringConverter))]
+                [OdbcDescription ("DataParameter_Value")]
+                [OdbcCategory ("DataCategory_Data")]
+                [DefaultValue (null)]          
                public object Value {
-                       get {
-                               return IntValue;
+                       get { 
+                               return ParamValue;
                        }
-                       set { this.IntValue =(int) value; }
-               }
-
-               #endregion // Properties
-
-               #region Internal Properties
-
-               internal void Bind(int hstmt,int ParamNum)
-               {
-                       if (OdbcType==OdbcType.Integer)
-                       {
-                               OdbcReturn ret=libodbc.SQLBindParam(hstmt, Convert.ToInt16(ParamNum), 4, 
-4, 0,0,ref IntValue, 0);
-                               libodbc.DisplayError("SQLBindParam",ret);
-
+                       set { 
+                               this.ParamValue = value;
+                               bufferIsSet = false;
                        }
-                       else Console.WriteLine("Unknown Paramter Type");
-
                }
 
-               #endregion // Internal Properties
-
-               #region Methods
+               #endregion // Properties
 
+               #region Methods\r
+\r
+               internal void Bind(IntPtr hstmt, int ParamNum) {\r
+                       OdbcReturn ret;\r
+                       // Set up the buffer if we haven't done so yet\r
+                       if (!bufferIsSet)\r
+                               setBuffer();\r
+\r
+                       // Convert System.Data.ParameterDirection into odbc enum\r
+                       OdbcInputOutputDirection paramdir = libodbc.ConvertParameterDirection(this.direction);\r
+                       // Bind parameter based on type\r
+                       if (odbcType == OdbcType.Int)\r
+                               ret = libodbc.SQLBindParameter(hstmt, (ushort)ParamNum, (short)paramdir,\r
+                                       (short)odbcType, (short)odbcType, Convert.ToUInt32(size),\r
+                                       0, ref intbuf, 0, 0);\r
+                       else\r
+                               ret = libodbc.SQLBindParameter(hstmt, (ushort)ParamNum, (short)paramdir,\r
+                                       (short)OdbcType.Char, (short)odbcType, Convert.ToUInt32(size),\r
+                                       0, buffer, 0, 0);\r
+                       // Check for error condition\r
+                       if ((ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo))\r
+                               throw new OdbcException(new OdbcError("SQLBindParam", OdbcHandleType.Stmt, hstmt));\r
+               }\r
+\r
+               private void setBuffer() {\r
+                       // Load buffer with new value
+                       if (odbcType == OdbcType.Int)
+                                intbuf = ParamValue == null ? new int () : (int) ParamValue;
+                        else {\r
+                               string paramValueString = ParamValue.ToString();\r
+                               // Treat everything else as a string\r
+                               // Init string buffer\r
+                                if (ParamValue is String)
+                                        paramValueString = "\'"+paramValueString+"\'";
+
+                                 int minSize = size;
+                                 minSize = size > 20 ? size : 20;
+                                if (buffer == null || buffer.Length < minSize)
+                                         buffer = new byte[minSize];
+                                 else
+                                         buffer.Initialize();
+                                 
+                                 // Convert value into string and store into buffer
+                                 minSize = paramValueString.Length < minSize ? paramValueString.Length : minSize;
+                                 System.Text.Encoding.ASCII.GetBytes(paramValueString, 0, minSize, buffer, 0);\r
+                       }\r
+                       bufferIsSet = true;\r
+               }\r
+\r
                [MonoTODO]
                object ICloneable.Clone ()
                {
@@ -185,4 +302,3 @@ string srcColumn, DataRowVersion srcVersion, object value)
                #endregion
        }
 }
-