You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
363 lines
13 KiB
363 lines
13 KiB
#if MYSQL_6_9
|
|
|
|
// Copyright 2004, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
//
|
|
// MySQL Connector/NET is licensed under the terms of the GPLv2
|
|
// <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, 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
|
|
// <http://www.mysql.com/about/legal/licensing/foss-exception.html>.
|
|
//
|
|
// 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
|
|
{
|
|
/// <summary>
|
|
/// Represents a parameter to a <see cref="MySqlCommand"/>, and optionally, its mapping to <see cref="DataSet"/> columns. This class cannot be inherited.
|
|
/// </summary>
|
|
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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="MySqlParameter"/> class with the parameter name and a value of the new MySqlParameter.
|
|
/// </summary>
|
|
/// <param name="parameterName">The name of the parameter to map. </param>
|
|
/// <param name="value">An <see cref="Object"/> that is the value of the <see cref="MySqlParameter"/>. </param>
|
|
public MySqlParameter(string parameterName, object value) : this()
|
|
{
|
|
ParameterName = parameterName;
|
|
Value = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="MySqlParameter"/> class with the parameter name and the data type.
|
|
/// </summary>
|
|
/// <param name="parameterName">The name of the parameter to map. </param>
|
|
/// <param name="dbType">One of the <see cref="MySqlDbType"/> values. </param>
|
|
public MySqlParameter(string parameterName, MySqlDbType dbType) : this(parameterName, null)
|
|
{
|
|
MySqlDbType = dbType;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="MySqlParameter"/> class with the parameter name, the <see cref="MySqlDbType"/>, and the size.
|
|
/// </summary>
|
|
/// <param name="parameterName">The name of the parameter to map. </param>
|
|
/// <param name="dbType">One of the <see cref="MySqlDbType"/> values. </param>
|
|
/// <param name="size">The length of the parameter. </param>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
[Category("Data")]
|
|
public override ParameterDirection Direction { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether the parameter accepts null values.
|
|
/// </summary>
|
|
[Browsable(false)]
|
|
public override Boolean IsNullable { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the MySqlDbType of the parameter.
|
|
/// </summary>
|
|
[Category("Data")]
|
|
[DbProviderSpecificTypeProperty(true)]
|
|
public MySqlDbType MySqlDbType
|
|
{
|
|
get { return mySqlDbType; }
|
|
set
|
|
{
|
|
SetMySqlDbType(value);
|
|
inferType = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the maximum number of digits used to represent the <see cref="Value"/> property.
|
|
/// </summary>
|
|
[Category("Data")]
|
|
#if NET40
|
|
public byte Precision { get; set; }
|
|
#else
|
|
public override byte Precision { get; set; }
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// Gets or sets the number of decimal places to which <see cref="Value"/> is resolved.
|
|
/// </summary>
|
|
[Category("Data")]
|
|
#if NET40
|
|
public byte Scale { get; set; }
|
|
#else
|
|
public override byte Scale { get; set; }
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// Gets or sets the maximum size, in bytes, of the data within the column.
|
|
/// </summary>
|
|
[Category("Data")]
|
|
public override int Size { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the value of the parameter.
|
|
/// </summary>
|
|
[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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the possible values for this parameter if this parameter is of type
|
|
/// SET or ENUM. Returns null otherwise.
|
|
/// </summary>
|
|
public IList PossibleValues { get; internal set; }
|
|
|
|
#endregion
|
|
|
|
private void SetParameterName(string name)
|
|
{
|
|
if (Collection != null)
|
|
Collection.ParameterNameChanged(this, paramName, name);
|
|
paramName = name;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Overridden. Gets a string containing the <see cref="ParameterName"/>.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
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
|
|
|