diff --git a/src/Migrator.Tests/ColumnPropertyMapperTest.cs b/src/Migrator.Tests/ColumnPropertyMapperTest.cs index 3add18d0..36a4659a 100644 --- a/src/Migrator.Tests/ColumnPropertyMapperTest.cs +++ b/src/Migrator.Tests/ColumnPropertyMapperTest.cs @@ -1,8 +1,10 @@ +using System; using System.Data; using DotNetProjects.Migrator.Framework; using DotNetProjects.Migrator.Providers; using DotNetProjects.Migrator.Providers.Impl.Oracle; using DotNetProjects.Migrator.Providers.Impl.PostgreSQL; +using DotNetProjects.Migrator.Providers.Impl.Mysql; using DotNetProjects.Migrator.Providers.Impl.SQLite; using DotNetProjects.Migrator.Providers.Impl.SqlServer; using NUnit.Framework; @@ -95,6 +97,38 @@ public void SqlServerCreatesSqWithNullDefault() Assert.That("[foo] varchar(30) DEFAULT 'NULL'", Is.EqualTo(mapper.ColumnSql)); } + [Test] + public void SqlServerCreatesSqlWithTimeSpanDefault() + { + var mapper = new ColumnPropertiesMapper(new SqlServerDialect(), "TIME"); + mapper.MapColumnProperties(new Column("foo", DbType.Time, new TimeSpan(1, 2, 3))); + Assert.That("[foo] TIME DEFAULT '01:02:03'", Is.EqualTo(mapper.ColumnSql)); + } + + [Test] + public void PostgreSqlCreatesSqlWithTimeSpanDefault() + { + var mapper = new ColumnPropertiesMapper(new PostgreSQLDialect(), "time"); + mapper.MapColumnProperties(new Column("foo", DbType.Time, new TimeSpan(1, 2, 3))); + Assert.That("foo time DEFAULT '01:02:03.000'", Is.EqualTo(mapper.ColumnSql)); + } + + [Test] + public void SQLiteCreatesSqlWithTimeSpanDefault() + { + var mapper = new ColumnPropertiesMapper(new SQLiteDialect(), "TIME"); + mapper.MapColumnProperties(new Column("foo", DbType.Time, new TimeSpan(1, 2, 3))); + Assert.That("foo TIME DEFAULT '01:02:03'", Is.EqualTo(mapper.ColumnSql)); + } + + [Test] + public void MySqlCreatesSqlWithTimeSpanDefault() + { + var mapper = new ColumnPropertiesMapper(new MysqlDialect(), "TIME"); + mapper.MapColumnProperties(new Column("foo", DbType.Time, new TimeSpan(1, 2, 3))); + Assert.That("foo TIME DEFAULT '01:02:03'", Is.EqualTo(mapper.ColumnSql)); + } + [Test] public void SqlServerCreatesSql() { @@ -103,6 +137,42 @@ public void SqlServerCreatesSql() Assert.That("[foo] varchar(30)", Is.EqualTo(mapper.ColumnSql)); } + [Test] + public void SqlServerMapsTimeType() + { + var dialect = new SqlServerDialect(); + + Assert.That(dialect.GetTypeName(DbType.Time), Is.EqualTo("TIME")); + Assert.That(dialect.GetDbType("time"), Is.EqualTo(DbType.Time)); + } + + [Test] + public void PostgreSqlMapsTimeType() + { + var dialect = new PostgreSQLDialect(); + + Assert.That(dialect.GetTypeName(DbType.Time), Is.EqualTo("time")); + Assert.That(dialect.GetDbType("time"), Is.EqualTo(DbType.Time)); + } + + [Test] + public void SQLiteMapsTimeType() + { + var dialect = new SQLiteDialect(); + + Assert.That(dialect.GetTypeName(DbType.Time), Is.EqualTo("TIME")); + Assert.That(dialect.GetDbType("time"), Is.EqualTo(DbType.Time)); + } + + [Test] + public void MySqlMapsTimeType() + { + var dialect = new MysqlDialect(); + + Assert.That(dialect.GetTypeName(DbType.Time), Is.EqualTo("TIME")); + Assert.That(dialect.GetDbType("time"), Is.EqualTo(DbType.Time)); + } + [Test] public void SqlServerIndexSqlIsNoNullWhenIndexed() { @@ -118,4 +188,4 @@ public void SQLiteIndexSqlWithEmptyStringDefault() mapper.MapColumnProperties(new Column("foo", DbType.String, 1, ColumnProperty.NotNull, string.Empty)); Assert.That("foo varchar(30) NOT NULL DEFAULT ''", Is.EqualTo(mapper.ColumnSql)); } -} \ No newline at end of file +} diff --git a/src/Migrator.Tests/Providers/PostgreSQL/PostgreSQLTransformationProvider_AddTableTests.cs b/src/Migrator.Tests/Providers/PostgreSQL/PostgreSQLTransformationProvider_AddTableTests.cs index d09187b1..ec9501e0 100644 --- a/src/Migrator.Tests/Providers/PostgreSQL/PostgreSQLTransformationProvider_AddTableTests.cs +++ b/src/Migrator.Tests/Providers/PostgreSQL/PostgreSQLTransformationProvider_AddTableTests.cs @@ -1,6 +1,8 @@ -using System.Threading.Tasks; -using Migrator.Tests.Providers.Generic; -using NUnit.Framework; +using System.Data; +using System.Threading.Tasks; +using DotNetProjects.Migrator.Framework; +using Migrator.Tests.Providers.Generic; +using NUnit.Framework; namespace Migrator.Tests.Providers.PostgreSQL; @@ -9,8 +11,20 @@ namespace Migrator.Tests.Providers.PostgreSQL; public class PostgreSQLTransformationProvider_AddTableTests : Generic_AddTableTestsBase { [SetUp] - public async Task SetUpAsync() - { - await BeginPostgreSQLTransactionAsync(); - } -} + public async Task SetUpAsync() + { + await BeginPostgreSQLTransactionAsync(); + } + + [Test] + public void AddTableTime() + { + var tableName = "Table1"; + var columnName = "Column1"; + + Provider.AddTable(tableName, new Column(columnName, DbType.Time, ColumnProperty.NotNull)); + var column = Provider.GetColumnByName(tableName, columnName); + + Assert.That(column.Type, Is.EqualTo(DbType.Time)); + } +} diff --git a/src/Migrator.Tests/Providers/SQLServer/SQLServerTransformationProvider_AddTableTests.cs b/src/Migrator.Tests/Providers/SQLServer/SQLServerTransformationProvider_AddTableTests.cs index 1632e892..f17fa9c4 100644 --- a/src/Migrator.Tests/Providers/SQLServer/SQLServerTransformationProvider_AddTableTests.cs +++ b/src/Migrator.Tests/Providers/SQLServer/SQLServerTransformationProvider_AddTableTests.cs @@ -41,14 +41,26 @@ public void AddTableDateTime() } [Test] - public void AddTableDateTime2() - { - var tableName = "Table1"; - var columnName = "Column1"; - - Provider.AddTable(tableName, new Column(columnName, DbType.DateTime2, ColumnProperty.NotNull)); - var column = Provider.GetColumnByName(tableName, columnName); - - Assert.That(column.Type, Is.EqualTo(DbType.DateTime2)); - } -} + public void AddTableDateTime2() + { + var tableName = "Table1"; + var columnName = "Column1"; + + Provider.AddTable(tableName, new Column(columnName, DbType.DateTime2, ColumnProperty.NotNull)); + var column = Provider.GetColumnByName(tableName, columnName); + + Assert.That(column.Type, Is.EqualTo(DbType.DateTime2)); + } + + [Test] + public void AddTableTime() + { + var tableName = "Table1"; + var columnName = "Column1"; + + Provider.AddTable(tableName, new Column(columnName, DbType.Time, ColumnProperty.NotNull)); + var column = Provider.GetColumnByName(tableName, columnName); + + Assert.That(column.Type, Is.EqualTo(DbType.Time)); + } +} diff --git a/src/Migrator.Tests/Providers/SQLite/SQLiteTransformationProvider_AddTableTests.cs b/src/Migrator.Tests/Providers/SQLite/SQLiteTransformationProvider_AddTableTests.cs index 1cc48749..f295a950 100644 --- a/src/Migrator.Tests/Providers/SQLite/SQLiteTransformationProvider_AddTableTests.cs +++ b/src/Migrator.Tests/Providers/SQLite/SQLiteTransformationProvider_AddTableTests.cs @@ -1,6 +1,7 @@ -using System; -using System.Data.SQLite; -using System.Linq; +using System; +using System.Data; +using System.Data.SQLite; +using System.Linq; using System.Threading.Tasks; using DotNetProjects.Migrator.Framework; using DotNetProjects.Migrator.Providers.Impl.SQLite; @@ -19,11 +20,11 @@ public async Task SetUpAsync() await BeginSQLiteTransactionAsync(); } - [Test] - public void AddTable_UniqueOnlyOnColumnLevel_Obsolete_UniquesListIsEmpty() - { - const string tableName = "MyTableName"; - const string columnName = "MyColumnName"; + [Test] + public void AddTable_UniqueOnlyOnColumnLevel_Obsolete_UniquesListIsEmpty() + { + const string tableName = "MyTableName"; + const string columnName = "MyColumnName"; // Arrange/Act Provider.AddTable(tableName, new Column(columnName, System.Data.DbType.Int32, ColumnProperty.Unique)); @@ -66,14 +67,26 @@ public void AddTable_CompositePrimaryKey_ContainsNull() Assert.That(sqliteInfo.Columns.First().Name, Is.EqualTo(columnName1)); Assert.That(sqliteInfo.Columns[1].Name, Is.EqualTo(columnName2)); - // 19 = UNIQUE constraint failed - Assert.That(ex.ErrorCode, Is.EqualTo(19)); - } - - [Test] - public void AddTable_SinglePrimaryKey_ContainsNull() - { - const string tableName = "MyTableName"; + // 19 = UNIQUE constraint failed + Assert.That(ex.ErrorCode, Is.EqualTo(19)); + } + + [Test] + public void AddTableTime() + { + const string tableName = "MyTableName"; + const string columnName = "MyColumnName"; + + Provider.AddTable(tableName, new Column(columnName, DbType.Time, ColumnProperty.NotNull)); + var column = Provider.GetColumnByName(tableName, columnName); + + Assert.That(column.Type, Is.EqualTo(DbType.Time)); + } + + [Test] + public void AddTable_SinglePrimaryKey_ContainsNull() + { + const string tableName = "MyTableName"; const string columnName1 = "Column1"; const string columnName2 = "Column2"; @@ -179,4 +192,4 @@ public void AddTable_GuidPrimaryKeyCompositeWithGuid_DoesNotThrowOnDuplicateNULL Provider.Insert(tableName, [columnName1, columnName2], [guid2, guid2]); Assert.Throws(() => Provider.Insert(tableName, [columnName1, columnName2], [guid2, guid2])); } -} \ No newline at end of file +} diff --git a/src/Migrator/Providers/Impl/Mysql/MysqlDialect.cs b/src/Migrator/Providers/Impl/Mysql/MysqlDialect.cs index fa51e466..5e591c4b 100644 --- a/src/Migrator/Providers/Impl/Mysql/MysqlDialect.cs +++ b/src/Migrator/Providers/Impl/Mysql/MysqlDialect.cs @@ -1,4 +1,5 @@ -using System.Data; +using System; +using System.Data; using DotNetProjects.Migrator.Framework; namespace DotNetProjects.Migrator.Providers.Impl.Mysql; @@ -278,13 +279,17 @@ public override ITransformationProvider GetTransformationProvider(Dialect dialec return new MySqlTransformationProvider(dialect, connection, scope, providerName); } - public override string Default(object defaultValue) - { - if (defaultValue.GetType().Equals(typeof(bool))) - { - defaultValue = ((bool)defaultValue) ? 1 : 0; - } - - return base.Default(defaultValue); - } -} + public override string Default(object defaultValue) + { + if (defaultValue is bool booleanValue) + { + defaultValue = booleanValue ? 1 : 0; + } + else if (defaultValue is TimeSpan) + { + return $"DEFAULT '{defaultValue}'"; + } + + return base.Default(defaultValue); + } +} diff --git a/src/Migrator/Providers/Impl/PostgreSQL/PostgreSQLTransformationProvider.cs b/src/Migrator/Providers/Impl/PostgreSQL/PostgreSQLTransformationProvider.cs index e0ff80b0..e570dbd5 100644 --- a/src/Migrator/Providers/Impl/PostgreSQL/PostgreSQLTransformationProvider.cs +++ b/src/Migrator/Providers/Impl/PostgreSQL/PostgreSQLTransformationProvider.cs @@ -557,10 +557,10 @@ public override Column[] GetColumns(string table) { dbType = MigratorDbType.Xml; } - else if (columnInfo.DataType == "time") - { - dbType = MigratorDbType.Time; - } + else if (columnInfo.DataType == "time" || columnInfo.DataType == "time without time zone") + { + dbType = MigratorDbType.Time; + } else if (columnInfo.DataType == "boolean") { dbType = MigratorDbType.Boolean; diff --git a/src/Migrator/Providers/Impl/SQLite/SQLiteDialect.cs b/src/Migrator/Providers/Impl/SQLite/SQLiteDialect.cs index d4036da3..054c370e 100644 --- a/src/Migrator/Providers/Impl/SQLite/SQLiteDialect.cs +++ b/src/Migrator/Providers/Impl/SQLite/SQLiteDialect.cs @@ -1,4 +1,5 @@ -using System.Data; +using System; +using System.Data; using DotNetProjects.Migrator.Framework; namespace DotNetProjects.Migrator.Providers.Impl.SQLite; @@ -56,15 +57,19 @@ public SQLiteDialect() public override string QuoteTemplate => "\"{0}\""; - public override string Default(object defaultValue) - { - if (defaultValue is bool) - { - return string.Format("DEFAULT {0}", (bool)defaultValue ? "1" : "0"); - } - - return base.Default(defaultValue); - } + public override string Default(object defaultValue) + { + if (defaultValue is bool) + { + return string.Format("DEFAULT {0}", (bool)defaultValue ? "1" : "0"); + } + else if (defaultValue is TimeSpan) + { + return $"DEFAULT '{defaultValue}'"; + } + + return base.Default(defaultValue); + } public override bool NeedsNotNullForIdentity { diff --git a/src/Migrator/Providers/Impl/SqlServer/SqlServerDialect.cs b/src/Migrator/Providers/Impl/SqlServer/SqlServerDialect.cs index 2f2885a9..0bf94e06 100644 --- a/src/Migrator/Providers/Impl/SqlServer/SqlServerDialect.cs +++ b/src/Migrator/Providers/Impl/SqlServer/SqlServerDialect.cs @@ -48,7 +48,7 @@ public SqlServerDialect() RegisterColumnType(DbType.String, 4000, "NVARCHAR($l)"); RegisterColumnType(DbType.String, int.MaxValue, "NVARCHAR(max)"); //RegisterColumnType(DbType.String, 1073741823, "NTEXT"); - RegisterColumnType(DbType.Time, "DATETIME"); + RegisterColumnType(DbType.Time, "TIME"); RegisterColumnType(DbType.VarNumeric, "NUMERIC(18,0)"); RegisterColumnType(DbType.VarNumeric, 38, "NUMERIC($l,0)"); RegisterColumnType(MigratorDbType.Interval, "BIGINT"); @@ -132,19 +132,23 @@ public override string Default(object defaultValue) + ((DateTime)defaultValue).Millisecond.ToString("D3") + "',121)"; } - else if (defaultValue.GetType().Equals(typeof(DateTimeOffset))) - { - return "DEFAULT CONVERT(DateTime,'" - + ((DateTimeOffset)defaultValue).Year.ToString("D4") + '-' - + ((DateTimeOffset)defaultValue).Month.ToString("D2") + '-' + else if (defaultValue.GetType().Equals(typeof(DateTimeOffset))) + { + return "DEFAULT CONVERT(DateTime,'" + + ((DateTimeOffset)defaultValue).Year.ToString("D4") + '-' + + ((DateTimeOffset)defaultValue).Month.ToString("D2") + '-' + ((DateTimeOffset)defaultValue).Day.ToString("D2") + ' ' + ((DateTimeOffset)defaultValue).Hour.ToString("D2") + ':' + ((DateTimeOffset)defaultValue).Minute.ToString("D2") + ':' + ((DateTimeOffset)defaultValue).Second.ToString("D2") + '.' - + ((DateTimeOffset)defaultValue).Millisecond.ToString("D3") - + "',121)"; - } - - return base.Default(defaultValue); - } -} + + ((DateTimeOffset)defaultValue).Millisecond.ToString("D3") + + "',121)"; + } + else if (defaultValue.GetType().Equals(typeof(TimeSpan))) + { + return "DEFAULT '" + defaultValue + "'"; + } + + return base.Default(defaultValue); + } +} diff --git a/src/Migrator/Providers/Impl/SqlServer/SqlServerTransformationProvider.cs b/src/Migrator/Providers/Impl/SqlServer/SqlServerTransformationProvider.cs index 871c2cb8..f4b80c5b 100644 --- a/src/Migrator/Providers/Impl/SqlServer/SqlServerTransformationProvider.cs +++ b/src/Migrator/Providers/Impl/SqlServer/SqlServerTransformationProvider.cs @@ -645,14 +645,18 @@ public override Column[] GetColumns(string table) { column.MigratorDbType = MigratorDbType.DateTime2; } - else if (dataTypeString == "datetimeoffset") - { - column.MigratorDbType = MigratorDbType.DateTimeOffset; - } - else if (dataTypeString == "binary" || dataTypeString == "varbinary") - { - column.MigratorDbType = MigratorDbType.Binary; - } + else if (dataTypeString == "datetimeoffset") + { + column.MigratorDbType = MigratorDbType.DateTimeOffset; + } + else if (dataTypeString == "time") + { + column.MigratorDbType = MigratorDbType.Time; + } + else if (dataTypeString == "binary" || dataTypeString == "varbinary") + { + column.MigratorDbType = MigratorDbType.Binary; + } else if (dataTypeString == "uniqueidentifier") { column.MigratorDbType = MigratorDbType.Guid; diff --git a/src/Migrator/Providers/TypeNames.cs b/src/Migrator/Providers/TypeNames.cs index 8f0944d0..56834ace 100644 --- a/src/Migrator/Providers/TypeNames.cs +++ b/src/Migrator/Providers/TypeNames.cs @@ -54,22 +54,40 @@ public class TypeNames private readonly Dictionary> weighted = new Dictionary>(); - public DbType GetDbType(string type) - { - type = type.Trim().ToLower(); - var retval = defaults.Where(x => x.Value.Trim().ToLower().StartsWith(type)).Select(x => x.Key); - if (retval.Any()) - { - return (DbType)retval.First(); - } - - retval = weighted.Where(x => x.Value.Where(y => y.Value.Trim().ToLower().StartsWith(type)).Any()).Select(x => x.Key); - if (retval.Any()) - { - return (DbType)retval.First(); - } - - var alias = aliases.Where(x => x.Key.Trim().ToLower().StartsWith(type)); + public DbType GetDbType(string type) + { + type = type.Trim().ToLower(); + var retval = defaults.Where(x => x.Value.Trim().ToLower() == type).Select(x => x.Key); + if (retval.Any()) + { + return (DbType)retval.First(); + } + + retval = weighted.Where(x => x.Value.Where(y => y.Value.Trim().ToLower() == type).Any()).Select(x => x.Key); + if (retval.Any()) + { + return (DbType)retval.First(); + } + + var alias = aliases.Where(x => x.Key.Trim().ToLower() == type); + if (alias.Any()) + { + return (DbType)alias.First().Value; + } + + retval = defaults.Where(x => x.Value.Trim().ToLower().StartsWith(type)).Select(x => x.Key); + if (retval.Any()) + { + return (DbType)retval.First(); + } + + retval = weighted.Where(x => x.Value.Where(y => y.Value.Trim().ToLower().StartsWith(type)).Any()).Select(x => x.Key); + if (retval.Any()) + { + return (DbType)retval.First(); + } + + alias = aliases.Where(x => x.Key.Trim().ToLower().StartsWith(type)); if (alias.Any()) {