From: <fab...@us...> - 2010-08-05 12:30:44
|
Revision: 5114 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5114&view=rev Author: fabiomaulo Date: 2010-08-05 12:30:38 +0000 (Thu, 05 Aug 2010) Log Message: ----------- Fix NH-2149 (by Paul Wideman) Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Dialect/MySQL5Dialect.cs trunk/nhibernate/src/NHibernate/Dialect/MySQLDialect.cs Modified: trunk/nhibernate/src/NHibernate/Dialect/MySQL5Dialect.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Dialect/MySQL5Dialect.cs 2010-08-05 12:20:09 UTC (rev 5113) +++ trunk/nhibernate/src/NHibernate/Dialect/MySQL5Dialect.cs 2010-08-05 12:30:38 UTC (rev 5114) @@ -12,6 +12,15 @@ RegisterColumnType(DbType.Guid, "BINARY(16)"); } + protected override void RegisterCastTypes() { + base.RegisterCastTypes(); + // MySql 5 also supports DECIMAL as a cast type target + // http://dev.mysql.com/doc/refman/5.5/en/cast-functions.html + RegisterCastType(DbType.Decimal, "DECIMAL"); + RegisterCastType(DbType.Double, "DECIMAL"); + RegisterCastType(DbType.Single, "DECIMAL"); + } + //Reference 5.x //Numeric: //http://dev.mysql.com/doc/refman/5.0/en/numeric-type-overview.html Modified: trunk/nhibernate/src/NHibernate/Dialect/MySQLDialect.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Dialect/MySQLDialect.cs 2010-08-05 12:20:09 UTC (rev 5113) +++ trunk/nhibernate/src/NHibernate/Dialect/MySQLDialect.cs 2010-08-05 12:30:38 UTC (rev 5114) @@ -5,6 +5,7 @@ using NHibernate.Dialect.Function; using NHibernate.Dialect.Schema; using NHibernate.SqlCommand; +using NHibernate.SqlTypes; using NHibernate.Util; using Environment=NHibernate.Cfg.Environment; @@ -32,85 +33,90 @@ /// </remarks> public class MySQLDialect : Dialect { - public MySQLDialect() - { - //Reference 3-4.x - //Numeric: - //http://dev.mysql.com/doc/refman/4.1/en/numeric-type-overview.html - //Date and time: - //http://dev.mysql.com/doc/refman/4.1/en/date-and-time-type-overview.html - //String: - //http://dev.mysql.com/doc/refman/5.0/en/string-type-overview.html - //default: - //http://dev.mysql.com/doc/refman/5.0/en/data-type-defaults.html + private readonly TypeNames castTypeNames = new TypeNames(); - //string type - RegisterColumnType(DbType.AnsiStringFixedLength, "CHAR(255)"); - RegisterColumnType(DbType.AnsiStringFixedLength, 255, "CHAR($l)"); - RegisterColumnType(DbType.AnsiStringFixedLength, 65535, "TEXT"); - RegisterColumnType(DbType.AnsiStringFixedLength, 16777215, "MEDIUMTEXT"); - RegisterColumnType(DbType.AnsiString, "VARCHAR(255)"); - RegisterColumnType(DbType.AnsiString, 255, "VARCHAR($l)"); - RegisterColumnType(DbType.AnsiString, 65535, "TEXT"); - RegisterColumnType(DbType.AnsiString, 16777215, "MEDIUMTEXT"); - RegisterColumnType(DbType.StringFixedLength, "CHAR(255)"); - RegisterColumnType(DbType.StringFixedLength, 255, "CHAR($l)"); - RegisterColumnType(DbType.StringFixedLength, 65535, "TEXT"); - RegisterColumnType(DbType.StringFixedLength, 16777215, "MEDIUMTEXT"); - RegisterColumnType(DbType.String, "VARCHAR(255)"); - RegisterColumnType(DbType.String, 255, "VARCHAR($l)"); - RegisterColumnType(DbType.String, 65535, "TEXT"); - RegisterColumnType(DbType.String, 16777215, "MEDIUMTEXT"); - //todo: future: add compatibility with decimal??? - //An unpacked fixed-point number. Behaves like a CHAR column; - //\x93unpacked\x94 means the number is stored as a string, using one character for each digit of the value. - //M is the total number of digits and D is the number of digits after the decimal point - //DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL] + public MySQLDialect() + { + //Reference 3-4.x + //Numeric: + //http://dev.mysql.com/doc/refman/4.1/en/numeric-type-overview.html + //Date and time: + //http://dev.mysql.com/doc/refman/4.1/en/date-and-time-type-overview.html + //String: + //http://dev.mysql.com/doc/refman/5.0/en/string-type-overview.html + //default: + //http://dev.mysql.com/doc/refman/5.0/en/data-type-defaults.html - //binary type: - RegisterColumnType(DbType.Binary, "LONGBLOB"); - RegisterColumnType(DbType.Binary, 127, "TINYBLOB"); - RegisterColumnType(DbType.Binary, 65535, "BLOB"); - RegisterColumnType(DbType.Binary, 16777215, "MEDIUMBLOB"); - //Numeric type: - RegisterColumnType(DbType.Boolean, "TINYINT(1)"); // SELECT IF(0, 'true', 'false'); - RegisterColumnType(DbType.Byte, "TINYINT UNSIGNED"); - RegisterColumnType(DbType.Currency, "MONEY"); - RegisterColumnType(DbType.Decimal, "NUMERIC(19,5)"); - RegisterColumnType(DbType.Decimal, 19, "NUMERIC($p, $s)"); - RegisterColumnType(DbType.Double, "DOUBLE"); - //The signed range is -32768 to 32767. The unsigned range is 0 to 65535. - RegisterColumnType(DbType.Int16, "SMALLINT"); - RegisterColumnType(DbType.Int32, "INTEGER"); //alias INT - //As of MySQL 4.1, SERIAL is an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE. - RegisterColumnType(DbType.Int64, "BIGINT"); - //!!! - //Using FLOAT might give you some unexpected problems because all calculations in MySQL are done with double precision - RegisterColumnType(DbType.Single, "FLOAT"); - RegisterColumnType(DbType.Byte, 1, "BIT"); //Like TinyInt(i) - RegisterColumnType(DbType.SByte, "TINYINT"); + //string type + RegisterColumnType(DbType.AnsiStringFixedLength, "CHAR(255)"); + RegisterColumnType(DbType.AnsiStringFixedLength, 255, "CHAR($l)"); + RegisterColumnType(DbType.AnsiStringFixedLength, 65535, "TEXT"); + RegisterColumnType(DbType.AnsiStringFixedLength, 16777215, "MEDIUMTEXT"); + RegisterColumnType(DbType.AnsiString, "VARCHAR(255)"); + RegisterColumnType(DbType.AnsiString, 255, "VARCHAR($l)"); + RegisterColumnType(DbType.AnsiString, 65535, "TEXT"); + RegisterColumnType(DbType.AnsiString, 16777215, "MEDIUMTEXT"); + RegisterColumnType(DbType.StringFixedLength, "CHAR(255)"); + RegisterColumnType(DbType.StringFixedLength, 255, "CHAR($l)"); + RegisterColumnType(DbType.StringFixedLength, 65535, "TEXT"); + RegisterColumnType(DbType.StringFixedLength, 16777215, "MEDIUMTEXT"); + RegisterColumnType(DbType.String, "VARCHAR(255)"); + RegisterColumnType(DbType.String, 255, "VARCHAR($l)"); + RegisterColumnType(DbType.String, 65535, "TEXT"); + RegisterColumnType(DbType.String, 16777215, "MEDIUMTEXT"); + //todo: future: add compatibility with decimal??? + //An unpacked fixed-point number. Behaves like a CHAR column; + //\x93unpacked\x94 means the number is stored as a string, using one character for each digit of the value. + //M is the total number of digits and D is the number of digits after the decimal point + //DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL] - //UNSINGED Numeric type: - RegisterColumnType(DbType.UInt16, "SMALLINT UNSIGNED"); - RegisterColumnType(DbType.UInt32, "INTEGER UNSIGNED"); - RegisterColumnType(DbType.UInt64, "BIGINT UNSIGNED"); - //there are no other DbType unsigned...but mysql support Float unsigned, double unsigned, etc.. + //binary type: + RegisterColumnType(DbType.Binary, "LONGBLOB"); + RegisterColumnType(DbType.Binary, 127, "TINYBLOB"); + RegisterColumnType(DbType.Binary, 65535, "BLOB"); + RegisterColumnType(DbType.Binary, 16777215, "MEDIUMBLOB"); - //Date and time type: - RegisterColumnType(DbType.Date, "DATE"); - RegisterColumnType(DbType.DateTime, "DATETIME"); - RegisterColumnType(DbType.Time, "TIME"); + //Numeric type: + RegisterColumnType(DbType.Boolean, "TINYINT(1)"); // SELECT IF(0, 'true', 'false'); + RegisterColumnType(DbType.Byte, "TINYINT UNSIGNED"); + RegisterColumnType(DbType.Currency, "MONEY"); + RegisterColumnType(DbType.Decimal, "NUMERIC(19,5)"); + RegisterColumnType(DbType.Decimal, 19, "NUMERIC($p, $s)"); + RegisterColumnType(DbType.Double, "DOUBLE"); + //The signed range is -32768 to 32767. The unsigned range is 0 to 65535. + RegisterColumnType(DbType.Int16, "SMALLINT"); + RegisterColumnType(DbType.Int32, "INTEGER"); //alias INT + //As of MySQL 4.1, SERIAL is an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE. + RegisterColumnType(DbType.Int64, "BIGINT"); + //!!! + //Using FLOAT might give you some unexpected problems because all calculations in MySQL are done with double precision + RegisterColumnType(DbType.Single, "FLOAT"); + RegisterColumnType(DbType.Byte, 1, "BIT"); //Like TinyInt(i) + RegisterColumnType(DbType.SByte, "TINYINT"); - //special: - RegisterColumnType(DbType.Guid, "VARCHAR(40)"); + //UNSINGED Numeric type: + RegisterColumnType(DbType.UInt16, "SMALLINT UNSIGNED"); + RegisterColumnType(DbType.UInt32, "INTEGER UNSIGNED"); + RegisterColumnType(DbType.UInt64, "BIGINT UNSIGNED"); + //there are no other DbType unsigned...but mysql support Float unsigned, double unsigned, etc.. - //functions: - RegisterFunction("concat", new VarArgsSQLFunction(NHibernateUtil.String, "concat(", ",", ")")); + //Date and time type: + RegisterColumnType(DbType.Date, "DATE"); + RegisterColumnType(DbType.DateTime, "DATETIME"); + RegisterColumnType(DbType.Time, "TIME"); - DefaultProperties[Environment.ConnectionDriver] = "NHibernate.Driver.MySqlDataDriver"; - } + //special: + RegisterColumnType(DbType.Guid, "VARCHAR(40)"); + RegisterCastTypes(); + + //functions: + RegisterFunction("concat", new VarArgsSQLFunction(NHibernateUtil.String, "concat(", ",", ")")); + + DefaultProperties[Environment.ConnectionDriver] = "NHibernate.Driver.MySqlDataDriver"; + } + /// <summary></summary> public override string AddColumnString { @@ -245,5 +251,57 @@ { get { return "create temporary table if not exists"; } } + + protected virtual void RegisterCastTypes() + { + // According to the MySql documentation (http://dev.mysql.com/doc/refman/4.1/en/cast-functions.html) + // only a few values are supported for the cast target type: BINARY, CHAR, DATE, DATETIME, + // SIGNED, TIME, and UNSIGNED. So we must limit our possible cast types to these + + // The Dialect.GetCastTypeName() method uses the default length, precision, and + // scale values, so there's no need to consider those values here either, just use the defaults + RegisterCastType(DbType.AnsiString, "CHAR"); + RegisterCastType(DbType.AnsiStringFixedLength, "CHAR"); + RegisterCastType(DbType.String, "CHAR"); + RegisterCastType(DbType.StringFixedLength, "CHAR"); + RegisterCastType(DbType.Binary, "BINARY"); + RegisterCastType(DbType.Int16, "SIGNED"); + RegisterCastType(DbType.Int32, "SIGNED"); + RegisterCastType(DbType.Int64, "SIGNED"); + RegisterCastType(DbType.UInt16, "UNSIGNED"); + RegisterCastType(DbType.UInt32, "UNSIGNED"); + RegisterCastType(DbType.UInt64, "UNSIGNED"); + RegisterCastType(DbType.Guid, "CHAR(40)"); + RegisterCastType(DbType.Time, "TIME"); + RegisterCastType(DbType.Date, "DATE"); + RegisterCastType(DbType.DateTime, "DATETIME"); + } + + /// <summary> + /// Suclasses register a typename for the given type code, to be used in CAST() + /// statements. + /// </summary> + /// <param name="code">The typecode</param> + /// <param name="name">The database type name</param> + protected void RegisterCastType(DbType code, string name) + { + castTypeNames.Put(code, name); + } + + /// <summary> + /// Get the name of the database type appropriate for casting operations + /// (via the CAST() SQL function) for the given <see cref="SqlType"/> typecode. + /// </summary> + /// <param name="sqlType">The <see cref="SqlType"/> typecode </param> + /// <returns> The database type name </returns> + public override string GetCastTypeName(SqlType sqlType) + { + string result = castTypeNames.Get(sqlType.DbType); + if (result == null) + { + throw new HibernateException(string.Format("No CAST() type mapping for SqlType {0}", sqlType)); + } + return result; + } } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |