// Copyright (c) 2021, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, as // published by the Free Software Foundation. // // This program is also distributed with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, // as designated in a particular file or component or in included license // documentation. The authors of MySQL hereby grant you an // additional permission to link the program and your derivative works // with the separately licensed software that they have included with // MySQL. // // Without limiting anything contained in the foregoing, this file, // which is part of MySQL Connector/NET, is also subject to the // Universal FOSS Exception, version 1.0, a copy of which can be found at // http://oss.oracle.com/licenses/universal-foss-exception. // // 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, version 2.0, 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 MySql.Data.Types; using System; using System.Reflection; namespace MySql.Data.MySqlClient { /// /// Represents a query attribute to a . /// public class MySqlAttribute { private const int UNSIGNED_MASK = 0x8000; private string _attributeName; private object _attributeValue; private MySqlDbType _mySqlDbType; private int _size; #region Constructors /// /// Initializes a new instance of the class. /// public MySqlAttribute() { } /// /// Initializes a new instance of the class with the attribute name and its value. /// /// Name of the attribute. /// Value of the attribute. public MySqlAttribute(string attributeName, object attributeValue) { this.AttributeName = attributeName; this.Value = attributeValue; } #endregion #region Properties internal MySqlAttributeCollection Collection { get; set; } /// /// Name of the query attribute. /// public String AttributeName { get { return this._attributeName; } set { if (String.IsNullOrWhiteSpace(value)) { throw new ArgumentException("'AttributeName' property can not be null or empty string.", "AttributeName"); } this._attributeName = value; } } /// /// Value of the query attribute. /// public object Value { get { return this._attributeValue; } set { this._attributeValue = value; if (value is byte[] valueAsByte) { this._size = valueAsByte.Length; } else if (value is string valueAsString) { this._size = valueAsString.Length; } this.SetTypeFromValue(); } } /// /// Gets or sets the of the attribute. /// public MySqlDbType MySqlDbType { get { return this._mySqlDbType; } set { this.SetMySqlDbType(value); } } internal IMySqlValue ValueObject { get; private set; } #endregion /// /// Sets the MySqlDbType from the Value /// private void SetTypeFromValue() { if (this._attributeValue == null || this._attributeValue == DBNull.Value) { return; } if (this._attributeValue is Guid) { this.MySqlDbType = MySqlDbType.Guid; } else if (this._attributeValue is TimeSpan) { this.MySqlDbType = MySqlDbType.Time; } else if (this._attributeValue is bool) { this.MySqlDbType = MySqlDbType.Byte; } else { Type t = this._attributeValue.GetType(); if (t.GetTypeInfo().BaseType == typeof(Enum)) { t = t.GetTypeInfo().GetEnumUnderlyingType(); } switch (t.Name) { case "SByte": this.MySqlDbType = MySqlDbType.Byte; break; case "Byte": this.MySqlDbType = MySqlDbType.UByte; break; case "Int16": this.MySqlDbType = MySqlDbType.Int16; break; case "UInt16": this.MySqlDbType = MySqlDbType.UInt16; break; case "Int32": this.MySqlDbType = MySqlDbType.Int32; break; case "UInt32": this.MySqlDbType = MySqlDbType.UInt32; break; case "Int64": this.MySqlDbType = MySqlDbType.Int64; break; case "UInt64": this.MySqlDbType = MySqlDbType.UInt64; break; case "DateTime": this.MySqlDbType = MySqlDbType.DateTime; break; case "String": this.MySqlDbType = MySqlDbType.VarChar; break; case "Single": this.MySqlDbType = MySqlDbType.Float; break; case "Double": this.MySqlDbType = MySqlDbType.Double; break; case "MySqlGeometry": this.MySqlDbType = MySqlDbType.Geometry; break; case "Decimal": this.MySqlDbType = MySqlDbType.Decimal; break; case "Object": default: this.MySqlDbType = MySqlDbType.Blob; break; } } } private void SetMySqlDbType(MySqlDbType mysqlDbtype) { this._mySqlDbType = mysqlDbtype == MySqlDbType.JSON ? MySqlDbType.VarChar : mysqlDbtype; this.ValueObject = MySqlField.GetIMySqlValue(this._mySqlDbType); } /// /// Gets the value for the attribute type. /// internal int GetPSType() { switch (this._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; case MySqlDbType.Guid: return (int)MySqlDbType.Guid - 600; default: int value = (int)this._mySqlDbType; value = value > 255 ? value - 500 : value; return value; } } /// /// Serialize the value of the query attribute. /// internal void Serialize(MySqlPacket packet, bool binary, MySqlConnectionStringBuilder settings) { if (!binary && (this._attributeValue == null || this._attributeValue == DBNull.Value)) { packet.WriteStringNoNull("NULL"); } else { if (this.ValueObject.MySqlDbType == MySqlDbType.Guid) { MySqlGuid g = (MySqlGuid)this.ValueObject; g.OldGuids = settings.OldGuids; this.ValueObject = g; } if (this.ValueObject.MySqlDbType == MySqlDbType.Geometry) { MySqlGeometry v = (MySqlGeometry)this.ValueObject; if (v.IsNull && this.Value != null) { MySqlGeometry.TryParse(this.Value.ToString(), out v); } this.ValueObject = v; } this.ValueObject.WriteValue(packet, binary, this._attributeValue, this._size); } } } }