#if NET40 // Copyright � 2004, 2013, Oracle and/or its affiliates. All rights reserved. // // MySQL Connector/NET is licensed under the terms of the GPLv2 // , like most // MySQL Connectors. There are special exceptions to the terms and // conditions of the GPLv2 as it is applied to this software, see the // FLOSS License Exception // . // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published // by the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA using System; using Externals.MySql.Data.Types; using System.ComponentModel; using System.Globalization; using System.Reflection; using System.Text; using System.Collections; using System.Data; using System.Data.Common; namespace Externals.MySql.Data.MySqlClient { /// /// Represents a parameter to a , and optionally, its mapping to columns. This class cannot be inherited. /// internal sealed partial class MySqlParameter : ICloneable { private const int UNSIGNED_MASK = 0x8000; private object paramValue; private string paramName; private MySqlDbType mySqlDbType; private bool inferType = true; private const int GEOMETRY_LENGTH = 25; #region Constructors public MySqlParameter() { Init(); } /// /// Initializes a new instance of the class with the parameter name and a value of the new MySqlParameter. /// /// The name of the parameter to map. /// An that is the value of the . public MySqlParameter(string parameterName, object value) : this() { ParameterName = parameterName; Value = value; } /// /// Initializes a new instance of the class with the parameter name and the data type. /// /// The name of the parameter to map. /// One of the values. public MySqlParameter(string parameterName, MySqlDbType dbType) : this(parameterName, null) { MySqlDbType = dbType; } /// /// Initializes a new instance of the class with the parameter name, the , and the size. /// /// The name of the parameter to map. /// One of the values. /// The length of the parameter. public MySqlParameter(string parameterName, MySqlDbType dbType, int size) : this(parameterName, dbType) { Size = size; } partial void Init(); #endregion #region Properties [Category("Misc")] public override String ParameterName { get { return paramName; } set { SetParameterName(value); } } internal MySqlParameterCollection Collection { get; set; } internal Encoding Encoding { get; set; } internal bool TypeHasBeenSet { get { return inferType == false; } } internal string BaseName { get { if (ParameterName.StartsWith("@", StringComparison.Ordinal) || ParameterName.StartsWith("?", StringComparison.Ordinal)) return ParameterName.Substring(1); return ParameterName; } } /// /// Gets or sets a value indicating whether the parameter is input-only, output-only, bidirectional, or a stored procedure return value parameter. /// As of MySql version 4.1 and earlier, input-only is the only valid choice. /// [Category("Data")] public override ParameterDirection Direction { get; set; } /// /// Gets or sets a value indicating whether the parameter accepts null values. /// [Browsable(false)] public override Boolean IsNullable { get; set; } /// /// Gets or sets the MySqlDbType of the parameter. /// [Category("Data")] [DbProviderSpecificTypeProperty(true)] public MySqlDbType MySqlDbType { get { return mySqlDbType; } set { SetMySqlDbType(value); inferType = false; } } /// /// Gets or sets the maximum number of digits used to represent the property. /// [Category("Data")] public byte Precision { get; set; } /// /// Gets or sets the number of decimal places to which is resolved. /// [Category("Data")] public byte Scale { get; set; } /// /// Gets or sets the maximum size, in bytes, of the data within the column. /// [Category("Data")] public override int Size { get; set; } /// /// Gets or sets the value of the parameter. /// [TypeConverter(typeof(StringConverter))] [Category("Data")] public override object Value { get { return paramValue; } set { paramValue = value; byte[] valueAsByte = value as byte[]; string valueAsString = value as string; if (valueAsByte != null) Size = valueAsByte.Length; else if (valueAsString != null) Size = valueAsString.Length; if (inferType) SetTypeFromValue(); } } private IMySqlValue _valueObject; internal IMySqlValue ValueObject { get { return _valueObject; } private set { _valueObject = value; } } /// /// Returns the possible values for this parameter if this parameter is of type /// SET or ENUM. Returns null otherwise. /// public IList PossibleValues { get; internal set; } #endregion private void SetParameterName(string name) { if (Collection != null) Collection.ParameterNameChanged(this, paramName, name); paramName = name; } /// /// Overridden. Gets a string containing the . /// /// public override string ToString() { return paramName; } internal int GetPSType() { switch (mySqlDbType) { case MySqlDbType.Bit: return (int)MySqlDbType.Int64 | UNSIGNED_MASK; case MySqlDbType.UByte: return (int)MySqlDbType.Byte | UNSIGNED_MASK; case MySqlDbType.UInt64: return (int)MySqlDbType.Int64 | UNSIGNED_MASK; case MySqlDbType.UInt32: return (int)MySqlDbType.Int32 | UNSIGNED_MASK; case MySqlDbType.UInt24: return (int)MySqlDbType.Int32 | UNSIGNED_MASK; case MySqlDbType.UInt16: return (int)MySqlDbType.Int16 | UNSIGNED_MASK; default: return (int)mySqlDbType; } } internal void Serialize(MySqlPacket packet, bool binary, MySqlConnectionStringBuilder settings) { if (!binary && (paramValue == null || paramValue == DBNull.Value)) packet.WriteStringNoNull("NULL"); else { if (ValueObject.MySqlDbType == MySqlDbType.Guid) { MySqlGuid g = (MySqlGuid)ValueObject; g.OldGuids = settings.OldGuids; ValueObject = g; } if (ValueObject.MySqlDbType == MySqlDbType.Geometry) { MySqlGeometry v = (MySqlGeometry)ValueObject; if (v.IsNull && Value != null) { MySqlGeometry.TryParse(Value.ToString(), out v); } ValueObject = v; } ValueObject.WriteValue(packet, binary, paramValue, Size); } } partial void SetDbTypeFromMySqlDbType(); private void SetMySqlDbType(MySqlDbType mysql_dbtype) { mySqlDbType = mysql_dbtype; ValueObject = MySqlField.GetIMySqlValue(mySqlDbType); SetDbTypeFromMySqlDbType(); } private void SetTypeFromValue() { if (paramValue == null || paramValue == DBNull.Value) return; if (paramValue is Guid) MySqlDbType = MySqlDbType.Guid; else if (paramValue is TimeSpan) MySqlDbType = MySqlDbType.Time; else if (paramValue is bool) MySqlDbType = MySqlDbType.Byte; else { Type t = paramValue.GetType(); switch (t.Name) { case "SByte": MySqlDbType = MySqlDbType.Byte; break; case "Byte": MySqlDbType = MySqlDbType.UByte; break; case "Int16": MySqlDbType = MySqlDbType.Int16; break; case "UInt16": MySqlDbType = MySqlDbType.UInt16; break; case "Int32": MySqlDbType = MySqlDbType.Int32; break; case "UInt32": MySqlDbType = MySqlDbType.UInt32; break; case "Int64": MySqlDbType = MySqlDbType.Int64; break; case "UInt64": MySqlDbType = MySqlDbType.UInt64; break; case "DateTime": MySqlDbType = MySqlDbType.DateTime; break; case "String": MySqlDbType = MySqlDbType.VarChar; break; case "Single": MySqlDbType = MySqlDbType.Float; break; case "Double": MySqlDbType = MySqlDbType.Double; break; case "Decimal": MySqlDbType = MySqlDbType.Decimal; break; case "Object": default: if (t.BaseType == typeof(Enum)) MySqlDbType = MySqlDbType.Int32; else MySqlDbType = MySqlDbType.Blob; break; } } } #region ICloneable public MySqlParameter Clone() { MySqlParameter clone = new MySqlParameter(paramName, mySqlDbType, Direction, SourceColumn, SourceVersion, paramValue); // if we have not had our type set yet then our clone should not either clone.inferType = inferType; return clone; } object ICloneable.Clone() { return this.Clone(); } #endregion // this method is pretty dumb but we want it to be fast. it doesn't return size based // on value and type but just on the value. internal long EstimatedSize() { if (Value == null || Value == DBNull.Value) return 4; // size of NULL if (Value is byte[]) return (Value as byte[]).Length; if (Value is string) return (Value as string).Length * 4; // account for UTF-8 (yeah I know) if (Value is decimal || Value is float) return 64; return 32; } } } #endif