context: // Copyright ?2004, 2010, 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.Text;
  using MySql.Data.Common;
  using MySql.Data.Types;
  using System.Globalization;
  using System.Text.RegularExpressions;
  using System;
  using System.Collections;
  using System.Collections.Generic;
  
  namespace MySql.Data.MySqlClient
  {
    internal enum ColumnFlags : int
    {
      NOT_NULL = 1,
      PRIMARY_KEY = 2,
      UNIQUE_KEY = 4,
      MULTIPLE_KEY = 8,
      BLOB = 16,
      UNSIGNED = 32,
      ZERO_FILL = 64,
      BINARY = 128,
      ENUM = 256,
      AUTO_INCREMENT = 512,
      TIMESTAMP = 1024,
      SET = 2048,
      NUMBER = 32768
    } ;
  
    /// <summary>
    /// Summary description for Field.
    /// </summary>
    internal class MySqlField
    {
      #region Fields
  
      // public fields
      public string CatalogName;
      public int ColumnLength;
      public string ColumnName;
      public string OriginalColumnName;
      public string TableName;
      public string RealTableName;
      public string DatabaseName;
      public Encoding Encoding;
      public int maxLength;
  
      // protected fields
      protected ColumnFlags colFlags;
      protected int charSetIndex;
      protected byte precision;
      protected byte scale;
      protected MySqlDbType mySqlDbType;
      protected DBVersion connVersion;
      protected Driver driver;
      protected bool binaryOk;
      protected List<Type> typeConversions = new List<Type>();
  
      #endregion
  
      public MySqlField(Driver driver)
      {
        this.driver = driver;
        connVersion = driver.Version;
        maxLength = 1;
        binaryOk = true;
      }
  
      #region Properties
  
      public int CharacterSetIndex
      {
        get { return charSetIndex; }
        set { charSetIndex = value; SetFieldEncoding(); }
      }
  
      public MySqlDbType Type
      {
        get { return mySqlDbType; }
      }
  
      public byte Precision
      {
        get { return precision; }
        set { precision = value; }
      }
  
      public byte Scale
      {
        get { return scale; }
        set { scale = value; }
      }
  
      public int MaxLength
      {
        get { return maxLength; }
        set { maxLength = value; }
      }
  
      public ColumnFlags Flags
      {
        get { return colFlags; }
      }
  
      public bool IsAutoIncrement
      {
        get { return (colFlags & ColumnFlags.AUTO_INCREMENT) > 0; }
      }
  
      public bool IsNumeric
      {
        get { return (colFlags & ColumnFlags.NUMBER) > 0; }
      }
  
      public bool AllowsNull
      {
        get { return (colFlags & ColumnFlags.NOT_NULL) == 0; }
      }
  
      public bool IsUnique
      {
        get { return (colFlags & ColumnFlags.UNIQUE_KEY) > 0; }
      }
  
      public bool IsPrimaryKey
      {
        get { return (colFlags & ColumnFlags.PRIMARY_KEY) > 0; }
      }
  
      public bool IsBlob
      {
        get
        {
          return (mySqlDbType >= MySqlDbType.TinyBlob &&
          mySqlDbType <= MySqlDbType.Blob) ||
          (mySqlDbType >= MySqlDbType.TinyText &&
          mySqlDbType <= MySqlDbType.Text) ||
          (colFlags & ColumnFlags.BLOB) > 0;
        }
      }
  
      public bool IsBinary
      {
        get
        {
          return binaryOk && (CharacterSetIndex == 63);
        }
      }
  
      public bool IsUnsigned
      {
        get { return (colFlags & ColumnFlags.UNSIGNED) > 0; }
      }
  
      public bool IsTextField
      {
        get
        {
          return Type == MySqlDbType.VarString || Type == MySqlDbType.VarChar ||
                      Type == MySqlDbType.String || (IsBlob && !IsBinary);
        }
      }
  
      public int CharacterLength
      {
        get { return ColumnLength / MaxLength; }
      }
  
      public List<Type> TypeConversions
      {
        get { return typeConversions; }
      }
  
      #endregion
  
      public void SetTypeAndFlags(MySqlDbType type, ColumnFlags flags)
      {
        colFlags = flags;
        mySqlDbType = type;
  
        if (String.IsNullOrEmpty(TableName) && String.IsNullOrEmpty(RealTableName) &&
          IsBinary && driver.Settings.FunctionsReturnString)
        {
          CharacterSetIndex = driver.ConnectionCharSetIndex;
        }
  
        // if our type is an unsigned number, then we need
        // to bump it up into our unsigned types
        // we're trusting that the server is not going to set the UNSIGNED
        // flag unless we are a number
        if (IsUnsigned)
        {
          switch (type)
          {
            case MySqlDbType.Byte:
              mySqlDbType = MySqlDbType.UByte;
              return;
            case MySqlDbType.Int16:
              mySqlDbType = MySqlDbType.UInt16;
              return;
            case MySqlDbType.Int24:
              mySqlDbType = MySqlDbType.UInt24;
              return;
            case MySqlDbType.Int32:
              mySqlDbType = MySqlDbType.UInt32;
              return;
            case MySqlDbType.Int64:
              mySqlDbType = MySqlDbType.UInt64;
              return;
          }
        }
  
        if (IsBlob)
        {
          // handle blob to UTF8 conversion if requested.  This is only activated
          // on binary blobs
          if (IsBinary && driver.Settings.TreatBlobsAsUTF8)
          {
            var convertBlob = false;
            var includeRegex = driver.Settings.GetBlobAsUTF8IncludeRegex();
            var excludeRegex = driver.Settings.GetBlobAsUTF8ExcludeRegex();
            if (includeRegex != null && includeRegex.IsMatch(ColumnName))
              convertBlob = true;
            else if (includeRegex == null && excludeRegex != null &&
              !excludeRegex.IsMatch(ColumnName))
              convertBlob = true;
  
            if (convertBlob)
            {
              binaryOk = false;
  
gt:             Encoding = Encoding.GetEncoding("UTF-8");