Skip to content

Fix MySQL .AsTime() creating DATETIME column instead of TIME#2190

Merged
jzabroski merged 2 commits into
mainfrom
copilot/fix-time-column-type
Nov 22, 2025
Merged

Fix MySQL .AsTime() creating DATETIME column instead of TIME#2190
jzabroski merged 2 commits into
mainfrom
copilot/fix-time-column-type

Conversation

Copilot AI commented Nov 22, 2025

Copy link
Copy Markdown
Contributor

MySQL type map incorrectly mapped DbType.Time to DATETIME instead of TIME, affecting all MySQL versions (4, 5, 8) since they inherit from MySql4TypeMap.

Changes

  • Fixed type mapping: Changed MySql4TypeMap.cs line 115 from "DATETIME" to "TIME"
  • Added type map tests: Created MySql4TypeMapTests.cs, MySql5TypeMapTests.cs, and MySql8TypeMapTests.cs to validate Time/Date/DateTime mappings

Example

Create.Table("MyTable")
    .WithColumn("MyTimeColumn").AsTime()

Before: CREATE TABLE MyTable (MyTimeColumn DATETIME)
After: CREATE TABLE MyTable (MyTimeColumn TIME)

This aligns MySQL with PostgreSQL and other database generators that correctly map to native TIME types.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • 6wovsblobprodsu6weus74.blob.core.windows.net
    • Triggering command: /usr/bin/dotnet dotnet restore --no-dependencies /home/REDACTED/work/fluentmigrator/.codeql-scratch/dbs/csharp/working/11554EEF5C921FE9659F6431188DBD4A/missingpackages_workingdir --packages /home/REDACTED/work/fluentmigrator/.codeql-scratch/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /home/REDACTED/work/fluentmigrator/.codeql-scratch/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • aaevsblobprodsu6weus85.blob.core.windows.net
    • Triggering command: /usr/bin/dotnet dotnet restore --no-dependencies /home/REDACTED/work/fluentmigrator/.codeql-scratch/dbs/csharp/working/8AEA375C9885230658FAC60AC8549FD5/missingpackages_workingdir --packages /home/REDACTED/work/fluentmigrator/.codeql-scratch/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /home/REDACTED/work/fluentmigrator/.codeql-scratch/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
    • Triggering command: /usr/bin/dotnet dotnet restore --no-dependencies /home/REDACTED/work/fluentmigrator/.codeql-scratch/dbs/csharp/working/11554EEF5C921FE9659F6431188DBD4A/missingpackages_workingdir --packages /home/REDACTED/work/fluentmigrator/.codeql-scratch/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /home/REDACTED/work/fluentmigrator/.codeql-scratch/dbs/csharp/working/nugetconfig/nuget.config --force (dns block)
  • l78vsblobprodsu6weus64.blob.core.windows.net
    • Triggering command: /usr/bin/dotnet dotnet build FluentMigrator.sln -c Release (dns block)
    • Triggering command: /usr/bin/dotnet dotnet restore --no-dependencies /home/REDACTED/work/fluentmigrator/fluentmigrator/FluentMigrator.sln --packages /home/REDACTED/work/fluentmigrator/.codeql-scratch/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/home/REDACTED/work/fluentmigrator/.codeql-scratch/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/home/REDACTED/work/fluentmigrator/.codeql-scratch/dbs/csharp/working/emptyFakeDotnetRoot (dns block)
  • pyvvsblobprodsu6weus63.blob.core.windows.net
    • Triggering command: /usr/bin/dotnet dotnet restore --no-dependencies /home/REDACTED/work/fluentmigrator/fluentmigrator/FluentMigrator.sln --packages /home/REDACTED/work/fluentmigrator/.codeql-scratch/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/home/REDACTED/work/fluentmigrator/.codeql-scratch/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/home/REDACTED/work/fluentmigrator/.codeql-scratch/dbs/csharp/working/emptyFakeDotnetRoot (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Runner.MySql5 .AsTime() Creates DATETIME Column instead of TIME</issue_title>
<issue_description>With the following input:

 Create.Table("MyTable")
   .WithColumn("MyTimeColumn").AsTime()

I would expect MyTimeColumn to be of type TIME. However, it creates a DATETIME column. After looking at the MySql5TypeMap (linking the MySql4TypeMap since that is where the value originates) I assumed this was by design, but after checking out the PostgresTypeMap I now think it may be an oversight.

Thanks for any clarification!</issue_description>

Comments on the Issue (you are @copilot in this section)

@jzabroski Agree, this is a mess. Starting to build a Google Spreadsheet to help manage some of this.

https://docs.google.com/spreadsheets/d/1CWgsOhae-bGYt8fEKkDM7KsUkjN1BqHaRKN4am5HJsc/edit?usp=sharing</comment_new>
<comment_new>@jzabroski
I wrote a quick LinqPad code spike to prototype extracting all the type map metadata from FluentMigrator.

Requires FluentMigrator.Runner package to be installed via Nuget.

void Main()
{
	var result = System.Reflection.Assembly.Load(typeof(FluentMigrator.Runner.Generators.MySql.MySql4Generator).Assembly.GetName());
	Console.WriteLine(result.FullName);
	var typeMap = result.DefinedTypes.Where(dt => (typeof(FluentMigrator.Runner.Generators.Base.TypeMapBase).IsAssignableFrom(dt.AsType())));
	typeMap.Dump();
	
	result = System.Reflection.Assembly.Load(typeof(FluentMigrator.Runner.Generators.MySql.MySql5Generator).Assembly.GetName());
	Console.WriteLine(result.FullName);
	typeMap = result.DefinedTypes.Where(dt => (typeof(FluentMigrator.Runner.Generators.Base.TypeMapBase).IsAssignableFrom(dt.AsType())));
	typeMap.Dump();
	
	result = System.Reflection.Assembly.Load(typeof(FluentMigrator.Runner.Generators.Firebird.FirebirdGenerator).Assembly.GetName());
	Console.WriteLine(result.FullName);
	typeMap = result.DefinedTypes.Where(dt => (typeof(FluentMigrator.Runner.Generators.Base.TypeMapBase).IsAssignableFrom(dt.AsType())));
	typeMap.Dump();
	
	result = System.Reflection.Assembly.Load(typeof(FluentMigrator.Runner.Generators.DB2.Db2Generator).Assembly.GetName());
	Console.WriteLine(result.FullName);
	typeMap = result.DefinedTypes.Where(dt => (typeof(FluentMigrator.Runner.Generators.Base.TypeMapBase).IsAssignableFrom(dt.AsType())));
	typeMap.Dump();
	
	result = System.Reflection.Assembly.Load(typeof(FluentMigrator.Runner.Generators.Postgres.PostgresGenerator).Assembly.GetName());
	Console.WriteLine(result.FullName);
	typeMap = result.DefinedTypes.Where(dt => (typeof(FluentMigrator.Runner.Generators.Base.TypeMapBase).IsAssignableFrom(dt.AsType())));
	typeMap.Dump();
	
	result = System.Reflection.Assembly.Load(typeof(FluentMigrator.Runner.Generators.SqlAnywhere.SqlAnywhere16Generator).Assembly.GetName());
	Console.WriteLine(result.FullName);
	typeMap = result.DefinedTypes.Where(dt => (typeof(FluentMigrator.Runner.Generators.Base.TypeMapBase).IsAssignableFrom(dt.AsType())));
	typeMap.Dump();
	
	result = System.Reflection.Assembly.Load(typeof(FluentMigrator.Runner.Generators.SQLite.SQLiteGenerator).Assembly.GetName());
	Console.WriteLine(result.FullName);
	typeMap = result.DefinedTypes.Where(dt => (typeof(FluentMigrator.Runner.Generators.Base.TypeMapBase).IsAssignableFrom(dt.AsType())));
	typeMap.Dump();
	
	result = System.Reflection.Assembly.Load(typeof(FluentMigrator.Runner.Generators.Hana.HanaGenerator).Assembly.GetName());
	Console.WriteLine(result.FullName);
	typeMap = result.DefinedTypes.Where(dt => (typeof(FluentMigrator.Runner.Generators.Base.TypeMapBase).IsAssignableFrom(dt.AsType())));
	typeMap.Dump();

	result = System.Reflection.Assembly.Load(typeof(FluentMigrator.Runner.Generators.SqlServer.SqlServer2016Generator).Assembly.GetName());
	Console.WriteLine(result.FullName);
	typeMap = result.DefinedTypes.Where(dt => (typeof(FluentMigrator.Runner.Generators.Base.TypeMapBase).IsAssignableFrom(dt.AsType())));
	typeMap.Dump();	
}

I just need to then walk the ITypeMap data structure to extract all the types. I can then auto-populate the Google SPreadsheet with CsvHelper.</comment_new>


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Fix MySql5 AsTime() to create TIME column instead of DATETIME Fix MySQL .AsTime() creating DATETIME column instead of TIME Nov 22, 2025
Copilot AI requested a review from jzabroski November 22, 2025 03:43
@jzabroski
jzabroski marked this pull request as ready for review November 22, 2025 03:44
@jzabroski jzabroski added this to the 7.2.0 milestone Nov 22, 2025
@github-actions

Copy link
Copy Markdown

Test Results

    2 files  ±0      2 suites  ±0   36s ⏱️ -1s
5 346 tests ±0  5 014 ✅ ±0  332 💤 ±0  0 ❌ ±0 
5 827 runs  ±0  5 231 ✅ ±0  596 💤 ±0  0 ❌ ±0 

Results for commit a5ea680. ± Comparison against base commit f3e9bb3.

@jzabroski
jzabroski merged commit 9e43fd9 into main Nov 22, 2025
4 checks passed
@jzabroski
jzabroski deleted the copilot/fix-time-column-type branch November 22, 2025 03:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Runner.MySql5 .AsTime() Creates DATETIME Column instead of TIME

2 participants