From 30d876e85ac6318bb717295b8bdd87a10ce044f9 Mon Sep 17 00:00:00 2001
From: Ilan Uzan <ilan9uzan@gmail.com>
Date: Fri, 7 Mar 2025 18:35:38 +0100
Subject: [PATCH 1/4] support batch insert of binary data in mysql

---
 CodeGenerator/Generators/UtilsGen.cs          | 17 ++++++-
 Drivers/DbDriver.cs                           |  2 +-
 Drivers/MySqlConnectorDriver.cs               | 15 ++++--
 docs/05_MySql.md                              | 12 ++---
 end2end/EndToEndScaffold/Templates.cs         | 40 ++++++++++++----
 .../MySqlConnectorDapperTester.generated.cs   | 26 +++++++---
 .../MySqlConnectorTester.generated.cs         | 26 +++++++---
 .../SqliteDapperTester.generated.cs           |  2 +-
 .../EndToEndTests/SqliteTester.generated.cs   |  2 +-
 .../MySqlConnectorDapperTester.generated.cs   | 26 +++++++---
 .../MySqlConnectorTester.generated.cs         | 26 +++++++---
 .../SqliteDapperTester.generated.cs           |  2 +-
 .../SqliteTester.generated.cs                 |  2 +-
 .../MySqlConnectorDapperExample/QuerySql.cs   | 40 +++++++++++-----
 examples/MySqlConnectorDapperExample/Utils.cs | 16 ++++++-
 .../QuerySql.cs                               | 40 +++++++++++-----
 .../Utils.cs                                  | 12 +++++
 examples/MySqlConnectorExample/QuerySql.cs    | 47 ++++++++++--------
 examples/MySqlConnectorExample/Utils.cs       | 16 ++++++-
 .../MySqlConnectorLegacyExample/QuerySql.cs   | 48 ++++++++++++++-----
 examples/MySqlConnectorLegacyExample/Utils.cs | 12 +++++
 examples/NpgsqlExample/QuerySql.cs            |  6 +--
 examples/SqliteExample/QuerySql.cs            |  4 +-
 examples/config/mysql/query.sql               | 26 ++++++----
 24 files changed, 339 insertions(+), 126 deletions(-)

diff --git a/CodeGenerator/Generators/UtilsGen.cs b/CodeGenerator/Generators/UtilsGen.cs
index c0e5196c..e6ab65e0 100644
--- a/CodeGenerator/Generators/UtilsGen.cs
+++ b/CodeGenerator/Generators/UtilsGen.cs
@@ -80,7 +80,7 @@ public static string TransformQueryForSqliteBatch(string originalSql, int cntRec
             ? $$"""
                 public class NullToStringConverter : DefaultTypeConverter
                 {
-                    public override {{dbDriver.AddNullableSuffixIfNeeded("string", true)}} ConvertToString(
+                    public override {{dbDriver.AddNullableSuffixIfNeeded("string", false)}} ConvertToString(
                         {{dbDriver.AddNullableSuffixIfNeeded("object", false)}} value, IWriterRow row, MemberMapData memberMapData)
                     {
                         return value == null ? @"\N" : base.ConvertToString(value, row, memberMapData);
@@ -89,7 +89,7 @@ public class NullToStringConverter : DefaultTypeConverter
                 
                 public class BoolToBitConverter : DefaultTypeConverter
                 {
-                    public override {{dbDriver.AddNullableSuffixIfNeeded("string", true)}} ConvertToString(
+                    public override {{dbDriver.AddNullableSuffixIfNeeded("string", false)}} ConvertToString(
                     {{dbDriver.AddNullableSuffixIfNeeded("object", false)}} value, IWriterRow row, MemberMapData memberMapData)
                     {
                         switch (value)
@@ -103,6 +103,19 @@ public class BoolToBitConverter : DefaultTypeConverter
                         }
                     }
                 }
+                
+                public class ByteArrayConverter : DefaultTypeConverter
+                {
+                    public override {{dbDriver.AddNullableSuffixIfNeeded("string", false)}} ConvertToString(
+                    {{dbDriver.AddNullableSuffixIfNeeded("object", false)}} value, IWriterRow row, MemberMapData memberMapData)
+                    {
+                        if (value == null)
+                            return @"\N";
+                        if (value is byte[] byteArray)
+                            return System.Text.Encoding.UTF8.GetString(byteArray);
+                        return base.ConvertToString(value, row, memberMapData);
+                    }
+                }
                 """
             : string.Empty;
 
diff --git a/Drivers/DbDriver.cs b/Drivers/DbDriver.cs
index 6deeae33..256a6dae 100644
--- a/Drivers/DbDriver.cs
+++ b/Drivers/DbDriver.cs
@@ -15,7 +15,7 @@ public abstract class DbDriver
 
     public Dictionary<string, Table> Tables { get; }
 
-    private HashSet<string> NullableTypesInDotnetCore { get; } = ["string", "object"];
+    private HashSet<string> NullableTypesInDotnetCore { get; } = ["string", "object", "byte[]"]; // TODO add arrays in here in a non hard-coded manner
 
     private HashSet<string> NullableTypes { get; } = ["bool", "byte", "short", "int", "long", "float", "double", "decimal", "DateTime"];
 
diff --git a/Drivers/MySqlConnectorDriver.cs b/Drivers/MySqlConnectorDriver.cs
index 86e67673..056d71e1 100644
--- a/Drivers/MySqlConnectorDriver.cs
+++ b/Drivers/MySqlConnectorDriver.cs
@@ -172,22 +172,29 @@ public string GetCopyFromImpl(Query query, string queryTextConstant)
 
         var csvWriterVar = Variable.CsvWriter.AsVarName();
         var loaderVar = Variable.Loader.AsVarName();
+        var optionsVar = Variable.Options.AsVarName();
         var connectionVar = Variable.Connection.AsVarName();
         var nullConverterFn = Variable.NullConverterFn.AsVarName();
 
         var loaderColumns = query.Params.Select(p => $"\"{p.Column.Name}\"").JoinByComma();
         var (establishConnection, connectionOpen) = EstablishConnection(query);
+
         return $$"""
                  const string supportedDateTimeFormat = "yyyy-MM-dd H:mm:ss";
-                 var {{Variable.Config.AsVarName()}} = new CsvConfiguration(CultureInfo.CurrentCulture) { Delimiter = "{{csvDelimiter}}" };
+                 var {{Variable.Config.AsVarName()}} = new CsvConfiguration(CultureInfo.CurrentCulture) 
+                 { 
+                    Delimiter = "{{csvDelimiter}}",
+                    NewLine = "\n"
+                 };
                  var {{nullConverterFn}} = new Utils.NullToStringConverter();
                  using (var {{Variable.Writer.AsVarName()}} = new StreamWriter("{{tempCsvFilename}}", false, new UTF8Encoding(false)))
                  using (var {{csvWriterVar}} = new CsvWriter({{Variable.Writer.AsVarName()}}, {{Variable.Config.AsVarName()}}))
                  {
-                    var {{Variable.Options}} = new TypeConverterOptions { Formats = new[] { supportedDateTimeFormat } };
-                    {{csvWriterVar}}.Context.TypeConverterOptionsCache.AddOptions<DateTime>({{Variable.Options}});
-                    {{csvWriterVar}}.Context.TypeConverterOptionsCache.AddOptions<DateTime?>({{Variable.Options}});
+                    var {{optionsVar}} = new TypeConverterOptions { Formats = new[] { supportedDateTimeFormat } };
+                    {{csvWriterVar}}.Context.TypeConverterOptionsCache.AddOptions<DateTime>({{optionsVar}});
+                    {{csvWriterVar}}.Context.TypeConverterOptionsCache.AddOptions<DateTime?>({{optionsVar}});
                     {{csvWriterVar}}.Context.TypeConverterCache.AddConverter<bool?>(new Utils.BoolToBitConverter());
+                    {{csvWriterVar}}.Context.TypeConverterCache.AddConverter<{{AddNullableSuffixIfNeeded("byte[]", false)}}>(new Utils.ByteArrayConverter());
                     {{csvWriterVar}}.Context.TypeConverterCache.AddConverter<byte?>({{nullConverterFn}});
                     {{csvWriterVar}}.Context.TypeConverterCache.AddConverter<short?>({{nullConverterFn}});
                     {{csvWriterVar}}.Context.TypeConverterCache.AddConverter<int?>({{nullConverterFn}});
diff --git a/docs/05_MySql.md b/docs/05_MySql.md
index 25d801a1..2bdc863a 100644
--- a/docs/05_MySql.md
+++ b/docs/05_MySql.md
@@ -63,12 +63,12 @@ we consider support for the different data types separately for batch inserts an
 | mediumtext                | ✅         | ✅                  |
 | text                      | ✅         | ✅                  |
 | longtext                  | ✅         | ✅                  |
-| binary                    | ✅         | ❌                  |
-| varbinary                 | ✅         | ❌                  |
-| tinyblob                  | ✅         | ❌                  |
-| blob                      | ✅         | ❌                  |
-| mediumblob                | ✅         | ❌                  |
-| longblob                  | ✅         | ❌                  |
+| binary                    | ✅         | ✅                  |
+| varbinary                 | ✅         | ✅                  |
+| tinyblob                  | ✅         | ✅                  |
+| blob                      | ✅         | ✅                  |
+| mediumblob                | ✅         | ✅                  |
+| longblob                  | ✅         | ✅                  |
 | enum                      | ❌         | ❌                  |
 | set                       | ❌         | ❌                  |
 | json                      | ❌         | ❌                  |
diff --git a/end2end/EndToEndScaffold/Templates.cs b/end2end/EndToEndScaffold/Templates.cs
index b57ae303..a9307fbd 100644
--- a/end2end/EndToEndScaffold/Templates.cs
+++ b/end2end/EndToEndScaffold/Templates.cs
@@ -668,7 +668,7 @@ private static void AssertSingularEquals(QuerySql.GetPostgresTypesAggRow expecte
         {
             Impl = $$"""
                    [Test]
-                   [TestCase(false, true, 0x32, 13, 2084, 3124, -54355, 324245, -67865, 9787668656, "&", "\u1857", "\u2649", "Sheena is a Punk Rocker", "Holiday in Cambodia", "London's Calling", "London's Burning", "Police & Thieves", "2000-1-30", "1983-11-3 02:01:22", new byte[] { 0x15, 0x16, 0x17 }, new byte[] { 0x15, 0x22 }, new byte[] { 0x23 }, new byte[] { 0x33, 0x13 }, new byte[] { 0x11, 0x62, 0x10 }, new byte[] { 0x38, 0x45, 0x06 })]
+                   [TestCase(false, true, 0x32, 13, 2084, 3124, -54355, 324245, -67865, 9787668656, "&", "\u1857", "\u2649", "Sheena is a Punk Rocker", "Holiday in Cambodia", "London's Calling", "London's Burning", "Police & Thieves", "2000-1-30", "1983-11-3 02:01:22", new byte[] { 0x15, 0x16, 0x17 }, new byte[] { 0x15, 0x24 }, new byte[] { 0x23 }, new byte[] { 0x33, 0x13 }, new byte[] { 0x11, 0x62, 0x10 }, new byte[] { 0x38, 0x45, 0x06 })]
                    [TestCase(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01", new byte[] { 0x0, 0x0, 0x0 }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { })]
                    [TestCase(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01", null, null, null, null, null, null)]
                    public async Task TestMySqlTypes(
@@ -797,9 +797,9 @@ private static void AssertSingularEquals(QuerySql.GetMysqlTypesRow expected, Que
         {
             Impl = $$"""
                      [Test]
-                     [TestCase(100, true, false, 0x05, -13, 324, -98760, 987965, 3132423, -7785442, 3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534, "D", "\u4321", "\u2345", "Parasite", "Clockwork Orange", "Dr. Strangelove", "Interview with a Vampire", "Memento", 1993, "2000-1-30", "1983-11-3 02:01:22", "2010-1-30 08:11:00")]
-                     [TestCase(500, false, true, 0x12, 8, -555, 66979, -423425, -9798642, 3297398, 1.23f, 99.35542, 32.33345, -12.3456, -55.55556, -11.1123334, 33.423542356346, "3", "\u1234", "\u6543", "Splendor in the Grass", "Pulp Fiction", "Chinatown", "Repulsion", "Million Dollar Baby", 2025, "2012-9-20", "2012-1-20 22:12:34", "1984-6-5 20:12:12")]
-                     [TestCase(10, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01")]
+                     [TestCase(100, true, false, 0x05, -13, 324, -98760, 987965, 3132423, -7785442, 3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534, "D", "\u4321", "\u2345", "Parasite", "Clockwork Orange", "Dr. Strangelove", "Interview with a Vampire", "Memento", 1993, "2000-1-30", "1983-11-3 02:01:22", "2010-1-30 08:11:00", new byte[] { 0x15, 0x16, 0x17 }, new byte[] { 0x15, 0x20 }, new byte[] { 0x23 }, new byte[] { 0x33, 0x13 }, new byte[] { 0x11, 0x62, 0x10 }, new byte[] { 0x38, 0x45, 0x06, 0x04 })]
+                     [TestCase(500, false, true, 0x12, 8, -555, 66979, -423425, -9798642, 3297398, 1.23f, 99.35542, 32.33345, -12.3456, -55.55556, -11.1123334, 33.423542356346, "3", "\u1234", "\u6543", "Splendor in the Grass", "Pulp Fiction", "Chinatown", "Repulsion", "Million Dollar Baby", 2025, "2012-9-20", "2012-1-20 22:12:34", "1984-6-5 20:12:12", new byte[] { 0x0, 0x0, 0x0 }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { })]
+                     [TestCase(10, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01", null, null, null, null, null, null)]
                      public async Task TestCopyFrom(
                         int batchSize, 
                         bool? cBool,
@@ -829,7 +829,13 @@ public async Task TestCopyFrom(
                         short? cYear,
                         DateTime? cDate, 
                         DateTime? cDatetime,
-                        DateTime? cTimestamp)
+                        DateTime? cTimestamp,
+                        byte[] cBinary,
+                        byte[] cVarbinary, 
+                        byte[] cTinyblob, 
+                        byte[] cBlob, 
+                        byte[] cMediumblob, 
+                        byte[] cLongblob)
                      {
                          var batchArgs = Enumerable.Range(0, batchSize)
                              .Select(_ => new QuerySql.InsertMysqlTypesBatchArgs
@@ -853,7 +859,13 @@ public async Task TestCopyFrom(
                                  CYear = cYear,
                                  CDate = cDate,
                                  CDatetime = cDatetime,
-                                 CTimestamp = cTimestamp
+                                 CTimestamp = cTimestamp,
+                                 CBinary = cBinary,
+                                 CVarbinary = cVarbinary, 
+                                 CTinyblob = cTinyblob,
+                                 CBlob = cBlob,
+                                 CMediumblob = cMediumblob,
+                                 CLongblob = cLongblob
                              })
                              .ToList();
                          await QuerySql.InsertMysqlTypesBatch(batchArgs);
@@ -879,7 +891,13 @@ public async Task TestCopyFrom(
                              CYear = cYear,
                              CDate = cDate,
                              CDatetime = cDatetime,
-                             CTimestamp = cTimestamp
+                             CTimestamp = cTimestamp,
+                             CBinary = cBinary,
+                             CVarbinary = cVarbinary, 
+                             CTinyblob = cTinyblob,
+                             CBlob = cBlob,
+                             CMediumblob = cMediumblob,
+                             CLongblob = cLongblob
                          };
                          var actual = await QuerySql.GetMysqlTypesAgg();
                          AssertSingularEquals(expected, actual{{UnknownRecordValuePlaceholder}});
@@ -908,6 +926,12 @@ private static void AssertSingularEquals(QuerySql.GetMysqlTypesAggRow expected,
                          Assert.That(actual.CDate, Is.EqualTo(expected.CDate));
                          Assert.That(actual.CDatetime, Is.EqualTo(expected.CDatetime));
                          Assert.That(actual.CTimestamp, Is.EqualTo(expected.CTimestamp));
+                         Assert.That(actual.CBinary, Is.EqualTo(expected.CBinary));
+                         Assert.That(actual.CVarbinary, Is.EqualTo(expected.CVarbinary));
+                         Assert.That(actual.CTinyblob, Is.EqualTo(expected.CTinyblob));
+                         Assert.That(actual.CBlob, Is.EqualTo(expected.CBlob));
+                         Assert.That(actual.CMediumblob, Is.EqualTo(expected.CMediumblob));
+                         Assert.That(actual.CLongblob, Is.EqualTo(expected.CLongblob));
                      }
                      """
         },
@@ -915,7 +939,7 @@ private static void AssertSingularEquals(QuerySql.GetMysqlTypesAggRow expected,
         {
             Impl = $$"""
                    [Test]
-                   [TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x22 })]
+                   [TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x33 })]
                    [TestCase(null, null, null, new byte[] { })]
                    [TestCase(null, null, null, null)]
                    public async Task TestSqliteTypes(
diff --git a/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs b/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs
index 0ed57f71..14967e30 100644
--- a/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs
+++ b/end2end/EndToEndTests/MySqlConnectorDapperTester.generated.cs
@@ -125,12 +125,12 @@ private static bool SingularEquals(QuerySql.GetAuthorByIdRow x, QuerySql.GetAuth
         }
 
         [Test]
-        [TestCase(100, true, false, 0x05, -13, 324, -98760, 987965, 3132423, -7785442, 3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534, "D", "\u4321", "\u2345", "Parasite", "Clockwork Orange", "Dr. Strangelove", "Interview with a Vampire", "Memento", 1993, "2000-1-30", "1983-11-3 02:01:22", "2010-1-30 08:11:00")]
-        [TestCase(500, false, true, 0x12, 8, -555, 66979, -423425, -9798642, 3297398, 1.23f, 99.35542, 32.33345, -12.3456, -55.55556, -11.1123334, 33.423542356346, "3", "\u1234", "\u6543", "Splendor in the Grass", "Pulp Fiction", "Chinatown", "Repulsion", "Million Dollar Baby", 2025, "2012-9-20", "2012-1-20 22:12:34", "1984-6-5 20:12:12")]
-        [TestCase(10, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01")]
-        public async Task TestCopyFrom(int batchSize, bool? cBool, bool? cBoolean, byte? cBit, short? cTinyint, short? cSmallint, int? cMediumint, int? cInt, int? cInteger, long? cBigint, float? cFloat, decimal? cNumeric, decimal? cDecimal, decimal? cDec, decimal? cFixed, double? cDouble, double? cDoublePrecision, string? cChar, string? cNchar, string? cNationalChar, string? cVarchar, string? cTinytext, string? cMediumtext, string? cText, string? cLongtext, short? cYear, DateTime? cDate, DateTime? cDatetime, DateTime? cTimestamp)
+        [TestCase(100, true, false, 0x05, -13, 324, -98760, 987965, 3132423, -7785442, 3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534, "D", "\u4321", "\u2345", "Parasite", "Clockwork Orange", "Dr. Strangelove", "Interview with a Vampire", "Memento", 1993, "2000-1-30", "1983-11-3 02:01:22", "2010-1-30 08:11:00", new byte[] { 0x15, 0x16, 0x17 }, new byte[] { 0x15, 0x20 }, new byte[] { 0x23 }, new byte[] { 0x33, 0x13 }, new byte[] { 0x11, 0x62, 0x10 }, new byte[] { 0x38, 0x45, 0x06, 0x04 })]
+        [TestCase(500, false, true, 0x12, 8, -555, 66979, -423425, -9798642, 3297398, 1.23f, 99.35542, 32.33345, -12.3456, -55.55556, -11.1123334, 33.423542356346, "3", "\u1234", "\u6543", "Splendor in the Grass", "Pulp Fiction", "Chinatown", "Repulsion", "Million Dollar Baby", 2025, "2012-9-20", "2012-1-20 22:12:34", "1984-6-5 20:12:12", new byte[] { 0x0, 0x0, 0x0 }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { })]
+        [TestCase(10, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01", null, null, null, null, null, null)]
+        public async Task TestCopyFrom(int batchSize, bool? cBool, bool? cBoolean, byte? cBit, short? cTinyint, short? cSmallint, int? cMediumint, int? cInt, int? cInteger, long? cBigint, float? cFloat, decimal? cNumeric, decimal? cDecimal, decimal? cDec, decimal? cFixed, double? cDouble, double? cDoublePrecision, string? cChar, string? cNchar, string? cNationalChar, string? cVarchar, string? cTinytext, string? cMediumtext, string? cText, string? cLongtext, short? cYear, DateTime? cDate, DateTime? cDatetime, DateTime? cTimestamp, byte[] cBinary, byte[] cVarbinary, byte[] cTinyblob, byte[] cBlob, byte[] cMediumblob, byte[] cLongblob)
         {
-            var batchArgs = Enumerable.Range(0, batchSize).Select(_ => new QuerySql.InsertMysqlTypesBatchArgs { CBool = cBool, CBoolean = cBoolean, CTinyint = cTinyint, CSmallint = cSmallint, CMediumint = cMediumint, CInt = cInt, CInteger = cInteger, CBigint = cBigint, CChar = cChar, CNchar = cNchar, CNationalChar = cNationalChar, CVarchar = cVarchar, CTinytext = cTinytext, CMediumtext = cMediumtext, CText = cText, CLongtext = cLongtext, CYear = cYear, CDate = cDate, CDatetime = cDatetime, CTimestamp = cTimestamp }).ToList();
+            var batchArgs = Enumerable.Range(0, batchSize).Select(_ => new QuerySql.InsertMysqlTypesBatchArgs { CBool = cBool, CBoolean = cBoolean, CTinyint = cTinyint, CSmallint = cSmallint, CMediumint = cMediumint, CInt = cInt, CInteger = cInteger, CBigint = cBigint, CChar = cChar, CNchar = cNchar, CNationalChar = cNationalChar, CVarchar = cVarchar, CTinytext = cTinytext, CMediumtext = cMediumtext, CText = cText, CLongtext = cLongtext, CYear = cYear, CDate = cDate, CDatetime = cDatetime, CTimestamp = cTimestamp, CBinary = cBinary, CVarbinary = cVarbinary, CTinyblob = cTinyblob, CBlob = cBlob, CMediumblob = cMediumblob, CLongblob = cLongblob }).ToList();
             await QuerySql.InsertMysqlTypesBatch(batchArgs);
             var expected = new QuerySql.GetMysqlTypesAggRow
             {
@@ -154,7 +154,13 @@ public async Task TestCopyFrom(int batchSize, bool? cBool, bool? cBoolean, byte?
                 CYear = cYear,
                 CDate = cDate,
                 CDatetime = cDatetime,
-                CTimestamp = cTimestamp
+                CTimestamp = cTimestamp,
+                CBinary = cBinary,
+                CVarbinary = cVarbinary,
+                CTinyblob = cTinyblob,
+                CBlob = cBlob,
+                CMediumblob = cMediumblob,
+                CLongblob = cLongblob
             };
             var actual = await QuerySql.GetMysqlTypesAgg();
             AssertSingularEquals(expected, actual);
@@ -183,6 +189,12 @@ private static void AssertSingularEquals(QuerySql.GetMysqlTypesAggRow expected,
             Assert.That(actual.CDate, Is.EqualTo(expected.CDate));
             Assert.That(actual.CDatetime, Is.EqualTo(expected.CDatetime));
             Assert.That(actual.CTimestamp, Is.EqualTo(expected.CTimestamp));
+            Assert.That(actual.CBinary, Is.EqualTo(expected.CBinary));
+            Assert.That(actual.CVarbinary, Is.EqualTo(expected.CVarbinary));
+            Assert.That(actual.CTinyblob, Is.EqualTo(expected.CTinyblob));
+            Assert.That(actual.CBlob, Is.EqualTo(expected.CBlob));
+            Assert.That(actual.CMediumblob, Is.EqualTo(expected.CMediumblob));
+            Assert.That(actual.CLongblob, Is.EqualTo(expected.CLongblob));
         }
 
         [Test]
@@ -367,7 +379,7 @@ public async Task TestNargNotNull()
         }
 
         [Test]
-        [TestCase(false, true, 0x32, 13, 2084, 3124, -54355, 324245, -67865, 9787668656, "&", "\u1857", "\u2649", "Sheena is a Punk Rocker", "Holiday in Cambodia", "London's Calling", "London's Burning", "Police & Thieves", "2000-1-30", "1983-11-3 02:01:22", new byte[] { 0x15, 0x16, 0x17 }, new byte[] { 0x15, 0x22 }, new byte[] { 0x23 }, new byte[] { 0x33, 0x13 }, new byte[] { 0x11, 0x62, 0x10 }, new byte[] { 0x38, 0x45, 0x06 })]
+        [TestCase(false, true, 0x32, 13, 2084, 3124, -54355, 324245, -67865, 9787668656, "&", "\u1857", "\u2649", "Sheena is a Punk Rocker", "Holiday in Cambodia", "London's Calling", "London's Burning", "Police & Thieves", "2000-1-30", "1983-11-3 02:01:22", new byte[] { 0x15, 0x16, 0x17 }, new byte[] { 0x15, 0x24 }, new byte[] { 0x23 }, new byte[] { 0x33, 0x13 }, new byte[] { 0x11, 0x62, 0x10 }, new byte[] { 0x38, 0x45, 0x06 })]
         [TestCase(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01", new byte[] { 0x0, 0x0, 0x0 }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { })]
         [TestCase(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01", null, null, null, null, null, null)]
         public async Task TestMySqlTypes(bool cBool, bool cBoolean, byte cBit, short cTinyint, short cYear, short cSmallint, int cMediumint, int cInt, int cInteger, long cBigint, string cChar, string cNchar, string cNationalChar, string cVarchar, string cTinytext, string cMediumtext, string cText, string cLongtext, DateTime cDate, DateTime cTimestamp, byte[] cBinary, byte[] cVarbinary, byte[] cTinyblob, byte[] cBlob, byte[] cMediumblob, byte[] cLongblob)
diff --git a/end2end/EndToEndTests/MySqlConnectorTester.generated.cs b/end2end/EndToEndTests/MySqlConnectorTester.generated.cs
index bf9e299b..90d14a59 100644
--- a/end2end/EndToEndTests/MySqlConnectorTester.generated.cs
+++ b/end2end/EndToEndTests/MySqlConnectorTester.generated.cs
@@ -125,12 +125,12 @@ private static bool SingularEquals(QuerySql.GetAuthorByIdRow x, QuerySql.GetAuth
         }
 
         [Test]
-        [TestCase(100, true, false, 0x05, -13, 324, -98760, 987965, 3132423, -7785442, 3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534, "D", "\u4321", "\u2345", "Parasite", "Clockwork Orange", "Dr. Strangelove", "Interview with a Vampire", "Memento", 1993, "2000-1-30", "1983-11-3 02:01:22", "2010-1-30 08:11:00")]
-        [TestCase(500, false, true, 0x12, 8, -555, 66979, -423425, -9798642, 3297398, 1.23f, 99.35542, 32.33345, -12.3456, -55.55556, -11.1123334, 33.423542356346, "3", "\u1234", "\u6543", "Splendor in the Grass", "Pulp Fiction", "Chinatown", "Repulsion", "Million Dollar Baby", 2025, "2012-9-20", "2012-1-20 22:12:34", "1984-6-5 20:12:12")]
-        [TestCase(10, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01")]
-        public async Task TestCopyFrom(int batchSize, bool? cBool, bool? cBoolean, byte? cBit, short? cTinyint, short? cSmallint, int? cMediumint, int? cInt, int? cInteger, long? cBigint, float? cFloat, decimal? cNumeric, decimal? cDecimal, decimal? cDec, decimal? cFixed, double? cDouble, double? cDoublePrecision, string? cChar, string? cNchar, string? cNationalChar, string? cVarchar, string? cTinytext, string? cMediumtext, string? cText, string? cLongtext, short? cYear, DateTime? cDate, DateTime? cDatetime, DateTime? cTimestamp)
+        [TestCase(100, true, false, 0x05, -13, 324, -98760, 987965, 3132423, -7785442, 3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534, "D", "\u4321", "\u2345", "Parasite", "Clockwork Orange", "Dr. Strangelove", "Interview with a Vampire", "Memento", 1993, "2000-1-30", "1983-11-3 02:01:22", "2010-1-30 08:11:00", new byte[] { 0x15, 0x16, 0x17 }, new byte[] { 0x15, 0x20 }, new byte[] { 0x23 }, new byte[] { 0x33, 0x13 }, new byte[] { 0x11, 0x62, 0x10 }, new byte[] { 0x38, 0x45, 0x06, 0x04 })]
+        [TestCase(500, false, true, 0x12, 8, -555, 66979, -423425, -9798642, 3297398, 1.23f, 99.35542, 32.33345, -12.3456, -55.55556, -11.1123334, 33.423542356346, "3", "\u1234", "\u6543", "Splendor in the Grass", "Pulp Fiction", "Chinatown", "Repulsion", "Million Dollar Baby", 2025, "2012-9-20", "2012-1-20 22:12:34", "1984-6-5 20:12:12", new byte[] { 0x0, 0x0, 0x0 }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { })]
+        [TestCase(10, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01", null, null, null, null, null, null)]
+        public async Task TestCopyFrom(int batchSize, bool? cBool, bool? cBoolean, byte? cBit, short? cTinyint, short? cSmallint, int? cMediumint, int? cInt, int? cInteger, long? cBigint, float? cFloat, decimal? cNumeric, decimal? cDecimal, decimal? cDec, decimal? cFixed, double? cDouble, double? cDoublePrecision, string? cChar, string? cNchar, string? cNationalChar, string? cVarchar, string? cTinytext, string? cMediumtext, string? cText, string? cLongtext, short? cYear, DateTime? cDate, DateTime? cDatetime, DateTime? cTimestamp, byte[] cBinary, byte[] cVarbinary, byte[] cTinyblob, byte[] cBlob, byte[] cMediumblob, byte[] cLongblob)
         {
-            var batchArgs = Enumerable.Range(0, batchSize).Select(_ => new QuerySql.InsertMysqlTypesBatchArgs { CBool = cBool, CBoolean = cBoolean, CTinyint = cTinyint, CSmallint = cSmallint, CMediumint = cMediumint, CInt = cInt, CInteger = cInteger, CBigint = cBigint, CChar = cChar, CNchar = cNchar, CNationalChar = cNationalChar, CVarchar = cVarchar, CTinytext = cTinytext, CMediumtext = cMediumtext, CText = cText, CLongtext = cLongtext, CYear = cYear, CDate = cDate, CDatetime = cDatetime, CTimestamp = cTimestamp }).ToList();
+            var batchArgs = Enumerable.Range(0, batchSize).Select(_ => new QuerySql.InsertMysqlTypesBatchArgs { CBool = cBool, CBoolean = cBoolean, CTinyint = cTinyint, CSmallint = cSmallint, CMediumint = cMediumint, CInt = cInt, CInteger = cInteger, CBigint = cBigint, CChar = cChar, CNchar = cNchar, CNationalChar = cNationalChar, CVarchar = cVarchar, CTinytext = cTinytext, CMediumtext = cMediumtext, CText = cText, CLongtext = cLongtext, CYear = cYear, CDate = cDate, CDatetime = cDatetime, CTimestamp = cTimestamp, CBinary = cBinary, CVarbinary = cVarbinary, CTinyblob = cTinyblob, CBlob = cBlob, CMediumblob = cMediumblob, CLongblob = cLongblob }).ToList();
             await QuerySql.InsertMysqlTypesBatch(batchArgs);
             var expected = new QuerySql.GetMysqlTypesAggRow
             {
@@ -154,7 +154,13 @@ public async Task TestCopyFrom(int batchSize, bool? cBool, bool? cBoolean, byte?
                 CYear = cYear,
                 CDate = cDate,
                 CDatetime = cDatetime,
-                CTimestamp = cTimestamp
+                CTimestamp = cTimestamp,
+                CBinary = cBinary,
+                CVarbinary = cVarbinary,
+                CTinyblob = cTinyblob,
+                CBlob = cBlob,
+                CMediumblob = cMediumblob,
+                CLongblob = cLongblob
             };
             var actual = await QuerySql.GetMysqlTypesAgg();
             AssertSingularEquals(expected, actual.Value);
@@ -183,6 +189,12 @@ private static void AssertSingularEquals(QuerySql.GetMysqlTypesAggRow expected,
             Assert.That(actual.CDate, Is.EqualTo(expected.CDate));
             Assert.That(actual.CDatetime, Is.EqualTo(expected.CDatetime));
             Assert.That(actual.CTimestamp, Is.EqualTo(expected.CTimestamp));
+            Assert.That(actual.CBinary, Is.EqualTo(expected.CBinary));
+            Assert.That(actual.CVarbinary, Is.EqualTo(expected.CVarbinary));
+            Assert.That(actual.CTinyblob, Is.EqualTo(expected.CTinyblob));
+            Assert.That(actual.CBlob, Is.EqualTo(expected.CBlob));
+            Assert.That(actual.CMediumblob, Is.EqualTo(expected.CMediumblob));
+            Assert.That(actual.CLongblob, Is.EqualTo(expected.CLongblob));
         }
 
         [Test]
@@ -367,7 +379,7 @@ public async Task TestNargNotNull()
         }
 
         [Test]
-        [TestCase(false, true, 0x32, 13, 2084, 3124, -54355, 324245, -67865, 9787668656, "&", "\u1857", "\u2649", "Sheena is a Punk Rocker", "Holiday in Cambodia", "London's Calling", "London's Burning", "Police & Thieves", "2000-1-30", "1983-11-3 02:01:22", new byte[] { 0x15, 0x16, 0x17 }, new byte[] { 0x15, 0x22 }, new byte[] { 0x23 }, new byte[] { 0x33, 0x13 }, new byte[] { 0x11, 0x62, 0x10 }, new byte[] { 0x38, 0x45, 0x06 })]
+        [TestCase(false, true, 0x32, 13, 2084, 3124, -54355, 324245, -67865, 9787668656, "&", "\u1857", "\u2649", "Sheena is a Punk Rocker", "Holiday in Cambodia", "London's Calling", "London's Burning", "Police & Thieves", "2000-1-30", "1983-11-3 02:01:22", new byte[] { 0x15, 0x16, 0x17 }, new byte[] { 0x15, 0x24 }, new byte[] { 0x23 }, new byte[] { 0x33, 0x13 }, new byte[] { 0x11, 0x62, 0x10 }, new byte[] { 0x38, 0x45, 0x06 })]
         [TestCase(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01", new byte[] { 0x0, 0x0, 0x0 }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { })]
         [TestCase(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01", null, null, null, null, null, null)]
         public async Task TestMySqlTypes(bool cBool, bool cBoolean, byte cBit, short cTinyint, short cYear, short cSmallint, int cMediumint, int cInt, int cInteger, long cBigint, string cChar, string cNchar, string cNationalChar, string cVarchar, string cTinytext, string cMediumtext, string cText, string cLongtext, DateTime cDate, DateTime cTimestamp, byte[] cBinary, byte[] cVarbinary, byte[] cTinyblob, byte[] cBlob, byte[] cMediumblob, byte[] cLongblob)
diff --git a/end2end/EndToEndTests/SqliteDapperTester.generated.cs b/end2end/EndToEndTests/SqliteDapperTester.generated.cs
index dd4742d3..c73659b9 100644
--- a/end2end/EndToEndTests/SqliteDapperTester.generated.cs
+++ b/end2end/EndToEndTests/SqliteDapperTester.generated.cs
@@ -306,7 +306,7 @@ public async Task TestNargNotNull()
         }
 
         [Test]
-        [TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x22 })]
+        [TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x33 })]
         [TestCase(null, null, null, new byte[] { })]
         [TestCase(null, null, null, null)]
         public async Task TestSqliteTypes(int cInteger, decimal cReal, string cText, byte[] cBlob)
diff --git a/end2end/EndToEndTests/SqliteTester.generated.cs b/end2end/EndToEndTests/SqliteTester.generated.cs
index ad66f8d5..a51c2921 100644
--- a/end2end/EndToEndTests/SqliteTester.generated.cs
+++ b/end2end/EndToEndTests/SqliteTester.generated.cs
@@ -306,7 +306,7 @@ public async Task TestNargNotNull()
         }
 
         [Test]
-        [TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x22 })]
+        [TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x33 })]
         [TestCase(null, null, null, new byte[] { })]
         [TestCase(null, null, null, null)]
         public async Task TestSqliteTypes(int cInteger, decimal cReal, string cText, byte[] cBlob)
diff --git a/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs b/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs
index 28d2f7c6..77d7d16b 100644
--- a/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs
+++ b/end2end/EndToEndTestsLegacy/MySqlConnectorDapperTester.generated.cs
@@ -125,12 +125,12 @@ private static bool SingularEquals(QuerySql.GetAuthorByIdRow x, QuerySql.GetAuth
         }
 
         [Test]
-        [TestCase(100, true, false, 0x05, -13, 324, -98760, 987965, 3132423, -7785442, 3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534, "D", "\u4321", "\u2345", "Parasite", "Clockwork Orange", "Dr. Strangelove", "Interview with a Vampire", "Memento", 1993, "2000-1-30", "1983-11-3 02:01:22", "2010-1-30 08:11:00")]
-        [TestCase(500, false, true, 0x12, 8, -555, 66979, -423425, -9798642, 3297398, 1.23f, 99.35542, 32.33345, -12.3456, -55.55556, -11.1123334, 33.423542356346, "3", "\u1234", "\u6543", "Splendor in the Grass", "Pulp Fiction", "Chinatown", "Repulsion", "Million Dollar Baby", 2025, "2012-9-20", "2012-1-20 22:12:34", "1984-6-5 20:12:12")]
-        [TestCase(10, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01")]
-        public async Task TestCopyFrom(int batchSize, bool? cBool, bool? cBoolean, byte? cBit, short? cTinyint, short? cSmallint, int? cMediumint, int? cInt, int? cInteger, long? cBigint, float? cFloat, decimal? cNumeric, decimal? cDecimal, decimal? cDec, decimal? cFixed, double? cDouble, double? cDoublePrecision, string cChar, string cNchar, string cNationalChar, string cVarchar, string cTinytext, string cMediumtext, string cText, string cLongtext, short? cYear, DateTime? cDate, DateTime? cDatetime, DateTime? cTimestamp)
+        [TestCase(100, true, false, 0x05, -13, 324, -98760, 987965, 3132423, -7785442, 3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534, "D", "\u4321", "\u2345", "Parasite", "Clockwork Orange", "Dr. Strangelove", "Interview with a Vampire", "Memento", 1993, "2000-1-30", "1983-11-3 02:01:22", "2010-1-30 08:11:00", new byte[] { 0x15, 0x16, 0x17 }, new byte[] { 0x15, 0x20 }, new byte[] { 0x23 }, new byte[] { 0x33, 0x13 }, new byte[] { 0x11, 0x62, 0x10 }, new byte[] { 0x38, 0x45, 0x06, 0x04 })]
+        [TestCase(500, false, true, 0x12, 8, -555, 66979, -423425, -9798642, 3297398, 1.23f, 99.35542, 32.33345, -12.3456, -55.55556, -11.1123334, 33.423542356346, "3", "\u1234", "\u6543", "Splendor in the Grass", "Pulp Fiction", "Chinatown", "Repulsion", "Million Dollar Baby", 2025, "2012-9-20", "2012-1-20 22:12:34", "1984-6-5 20:12:12", new byte[] { 0x0, 0x0, 0x0 }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { })]
+        [TestCase(10, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01", null, null, null, null, null, null)]
+        public async Task TestCopyFrom(int batchSize, bool? cBool, bool? cBoolean, byte? cBit, short? cTinyint, short? cSmallint, int? cMediumint, int? cInt, int? cInteger, long? cBigint, float? cFloat, decimal? cNumeric, decimal? cDecimal, decimal? cDec, decimal? cFixed, double? cDouble, double? cDoublePrecision, string cChar, string cNchar, string cNationalChar, string cVarchar, string cTinytext, string cMediumtext, string cText, string cLongtext, short? cYear, DateTime? cDate, DateTime? cDatetime, DateTime? cTimestamp, byte[] cBinary, byte[] cVarbinary, byte[] cTinyblob, byte[] cBlob, byte[] cMediumblob, byte[] cLongblob)
         {
-            var batchArgs = Enumerable.Range(0, batchSize).Select(_ => new QuerySql.InsertMysqlTypesBatchArgs { CBool = cBool, CBoolean = cBoolean, CTinyint = cTinyint, CSmallint = cSmallint, CMediumint = cMediumint, CInt = cInt, CInteger = cInteger, CBigint = cBigint, CChar = cChar, CNchar = cNchar, CNationalChar = cNationalChar, CVarchar = cVarchar, CTinytext = cTinytext, CMediumtext = cMediumtext, CText = cText, CLongtext = cLongtext, CYear = cYear, CDate = cDate, CDatetime = cDatetime, CTimestamp = cTimestamp }).ToList();
+            var batchArgs = Enumerable.Range(0, batchSize).Select(_ => new QuerySql.InsertMysqlTypesBatchArgs { CBool = cBool, CBoolean = cBoolean, CTinyint = cTinyint, CSmallint = cSmallint, CMediumint = cMediumint, CInt = cInt, CInteger = cInteger, CBigint = cBigint, CChar = cChar, CNchar = cNchar, CNationalChar = cNationalChar, CVarchar = cVarchar, CTinytext = cTinytext, CMediumtext = cMediumtext, CText = cText, CLongtext = cLongtext, CYear = cYear, CDate = cDate, CDatetime = cDatetime, CTimestamp = cTimestamp, CBinary = cBinary, CVarbinary = cVarbinary, CTinyblob = cTinyblob, CBlob = cBlob, CMediumblob = cMediumblob, CLongblob = cLongblob }).ToList();
             await QuerySql.InsertMysqlTypesBatch(batchArgs);
             var expected = new QuerySql.GetMysqlTypesAggRow
             {
@@ -154,7 +154,13 @@ public async Task TestCopyFrom(int batchSize, bool? cBool, bool? cBoolean, byte?
                 CYear = cYear,
                 CDate = cDate,
                 CDatetime = cDatetime,
-                CTimestamp = cTimestamp
+                CTimestamp = cTimestamp,
+                CBinary = cBinary,
+                CVarbinary = cVarbinary,
+                CTinyblob = cTinyblob,
+                CBlob = cBlob,
+                CMediumblob = cMediumblob,
+                CLongblob = cLongblob
             };
             var actual = await QuerySql.GetMysqlTypesAgg();
             AssertSingularEquals(expected, actual);
@@ -183,6 +189,12 @@ private static void AssertSingularEquals(QuerySql.GetMysqlTypesAggRow expected,
             Assert.That(actual.CDate, Is.EqualTo(expected.CDate));
             Assert.That(actual.CDatetime, Is.EqualTo(expected.CDatetime));
             Assert.That(actual.CTimestamp, Is.EqualTo(expected.CTimestamp));
+            Assert.That(actual.CBinary, Is.EqualTo(expected.CBinary));
+            Assert.That(actual.CVarbinary, Is.EqualTo(expected.CVarbinary));
+            Assert.That(actual.CTinyblob, Is.EqualTo(expected.CTinyblob));
+            Assert.That(actual.CBlob, Is.EqualTo(expected.CBlob));
+            Assert.That(actual.CMediumblob, Is.EqualTo(expected.CMediumblob));
+            Assert.That(actual.CLongblob, Is.EqualTo(expected.CLongblob));
         }
 
         [Test]
@@ -367,7 +379,7 @@ public async Task TestNargNotNull()
         }
 
         [Test]
-        [TestCase(false, true, 0x32, 13, 2084, 3124, -54355, 324245, -67865, 9787668656, "&", "\u1857", "\u2649", "Sheena is a Punk Rocker", "Holiday in Cambodia", "London's Calling", "London's Burning", "Police & Thieves", "2000-1-30", "1983-11-3 02:01:22", new byte[] { 0x15, 0x16, 0x17 }, new byte[] { 0x15, 0x22 }, new byte[] { 0x23 }, new byte[] { 0x33, 0x13 }, new byte[] { 0x11, 0x62, 0x10 }, new byte[] { 0x38, 0x45, 0x06 })]
+        [TestCase(false, true, 0x32, 13, 2084, 3124, -54355, 324245, -67865, 9787668656, "&", "\u1857", "\u2649", "Sheena is a Punk Rocker", "Holiday in Cambodia", "London's Calling", "London's Burning", "Police & Thieves", "2000-1-30", "1983-11-3 02:01:22", new byte[] { 0x15, 0x16, 0x17 }, new byte[] { 0x15, 0x24 }, new byte[] { 0x23 }, new byte[] { 0x33, 0x13 }, new byte[] { 0x11, 0x62, 0x10 }, new byte[] { 0x38, 0x45, 0x06 })]
         [TestCase(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01", new byte[] { 0x0, 0x0, 0x0 }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { })]
         [TestCase(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01", null, null, null, null, null, null)]
         public async Task TestMySqlTypes(bool cBool, bool cBoolean, byte cBit, short cTinyint, short cYear, short cSmallint, int cMediumint, int cInt, int cInteger, long cBigint, string cChar, string cNchar, string cNationalChar, string cVarchar, string cTinytext, string cMediumtext, string cText, string cLongtext, DateTime cDate, DateTime cTimestamp, byte[] cBinary, byte[] cVarbinary, byte[] cTinyblob, byte[] cBlob, byte[] cMediumblob, byte[] cLongblob)
diff --git a/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs b/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs
index b464fb3f..f601c7fd 100644
--- a/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs
+++ b/end2end/EndToEndTestsLegacy/MySqlConnectorTester.generated.cs
@@ -125,12 +125,12 @@ private static bool SingularEquals(QuerySql.GetAuthorByIdRow x, QuerySql.GetAuth
         }
 
         [Test]
-        [TestCase(100, true, false, 0x05, -13, 324, -98760, 987965, 3132423, -7785442, 3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534, "D", "\u4321", "\u2345", "Parasite", "Clockwork Orange", "Dr. Strangelove", "Interview with a Vampire", "Memento", 1993, "2000-1-30", "1983-11-3 02:01:22", "2010-1-30 08:11:00")]
-        [TestCase(500, false, true, 0x12, 8, -555, 66979, -423425, -9798642, 3297398, 1.23f, 99.35542, 32.33345, -12.3456, -55.55556, -11.1123334, 33.423542356346, "3", "\u1234", "\u6543", "Splendor in the Grass", "Pulp Fiction", "Chinatown", "Repulsion", "Million Dollar Baby", 2025, "2012-9-20", "2012-1-20 22:12:34", "1984-6-5 20:12:12")]
-        [TestCase(10, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01")]
-        public async Task TestCopyFrom(int batchSize, bool? cBool, bool? cBoolean, byte? cBit, short? cTinyint, short? cSmallint, int? cMediumint, int? cInt, int? cInteger, long? cBigint, float? cFloat, decimal? cNumeric, decimal? cDecimal, decimal? cDec, decimal? cFixed, double? cDouble, double? cDoublePrecision, string cChar, string cNchar, string cNationalChar, string cVarchar, string cTinytext, string cMediumtext, string cText, string cLongtext, short? cYear, DateTime? cDate, DateTime? cDatetime, DateTime? cTimestamp)
+        [TestCase(100, true, false, 0x05, -13, 324, -98760, 987965, 3132423, -7785442, 3.4f, -31.555666, 11.098643, 34.4424, 423.2445, 998.9994542, 21.214312452534, "D", "\u4321", "\u2345", "Parasite", "Clockwork Orange", "Dr. Strangelove", "Interview with a Vampire", "Memento", 1993, "2000-1-30", "1983-11-3 02:01:22", "2010-1-30 08:11:00", new byte[] { 0x15, 0x16, 0x17 }, new byte[] { 0x15, 0x20 }, new byte[] { 0x23 }, new byte[] { 0x33, 0x13 }, new byte[] { 0x11, 0x62, 0x10 }, new byte[] { 0x38, 0x45, 0x06, 0x04 })]
+        [TestCase(500, false, true, 0x12, 8, -555, 66979, -423425, -9798642, 3297398, 1.23f, 99.35542, 32.33345, -12.3456, -55.55556, -11.1123334, 33.423542356346, "3", "\u1234", "\u6543", "Splendor in the Grass", "Pulp Fiction", "Chinatown", "Repulsion", "Million Dollar Baby", 2025, "2012-9-20", "2012-1-20 22:12:34", "1984-6-5 20:12:12", new byte[] { 0x0, 0x0, 0x0 }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { })]
+        [TestCase(10, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01", null, null, null, null, null, null)]
+        public async Task TestCopyFrom(int batchSize, bool? cBool, bool? cBoolean, byte? cBit, short? cTinyint, short? cSmallint, int? cMediumint, int? cInt, int? cInteger, long? cBigint, float? cFloat, decimal? cNumeric, decimal? cDecimal, decimal? cDec, decimal? cFixed, double? cDouble, double? cDoublePrecision, string cChar, string cNchar, string cNationalChar, string cVarchar, string cTinytext, string cMediumtext, string cText, string cLongtext, short? cYear, DateTime? cDate, DateTime? cDatetime, DateTime? cTimestamp, byte[] cBinary, byte[] cVarbinary, byte[] cTinyblob, byte[] cBlob, byte[] cMediumblob, byte[] cLongblob)
         {
-            var batchArgs = Enumerable.Range(0, batchSize).Select(_ => new QuerySql.InsertMysqlTypesBatchArgs { CBool = cBool, CBoolean = cBoolean, CTinyint = cTinyint, CSmallint = cSmallint, CMediumint = cMediumint, CInt = cInt, CInteger = cInteger, CBigint = cBigint, CChar = cChar, CNchar = cNchar, CNationalChar = cNationalChar, CVarchar = cVarchar, CTinytext = cTinytext, CMediumtext = cMediumtext, CText = cText, CLongtext = cLongtext, CYear = cYear, CDate = cDate, CDatetime = cDatetime, CTimestamp = cTimestamp }).ToList();
+            var batchArgs = Enumerable.Range(0, batchSize).Select(_ => new QuerySql.InsertMysqlTypesBatchArgs { CBool = cBool, CBoolean = cBoolean, CTinyint = cTinyint, CSmallint = cSmallint, CMediumint = cMediumint, CInt = cInt, CInteger = cInteger, CBigint = cBigint, CChar = cChar, CNchar = cNchar, CNationalChar = cNationalChar, CVarchar = cVarchar, CTinytext = cTinytext, CMediumtext = cMediumtext, CText = cText, CLongtext = cLongtext, CYear = cYear, CDate = cDate, CDatetime = cDatetime, CTimestamp = cTimestamp, CBinary = cBinary, CVarbinary = cVarbinary, CTinyblob = cTinyblob, CBlob = cBlob, CMediumblob = cMediumblob, CLongblob = cLongblob }).ToList();
             await QuerySql.InsertMysqlTypesBatch(batchArgs);
             var expected = new QuerySql.GetMysqlTypesAggRow
             {
@@ -154,7 +154,13 @@ public async Task TestCopyFrom(int batchSize, bool? cBool, bool? cBoolean, byte?
                 CYear = cYear,
                 CDate = cDate,
                 CDatetime = cDatetime,
-                CTimestamp = cTimestamp
+                CTimestamp = cTimestamp,
+                CBinary = cBinary,
+                CVarbinary = cVarbinary,
+                CTinyblob = cTinyblob,
+                CBlob = cBlob,
+                CMediumblob = cMediumblob,
+                CLongblob = cLongblob
             };
             var actual = await QuerySql.GetMysqlTypesAgg();
             AssertSingularEquals(expected, actual);
@@ -183,6 +189,12 @@ private static void AssertSingularEquals(QuerySql.GetMysqlTypesAggRow expected,
             Assert.That(actual.CDate, Is.EqualTo(expected.CDate));
             Assert.That(actual.CDatetime, Is.EqualTo(expected.CDatetime));
             Assert.That(actual.CTimestamp, Is.EqualTo(expected.CTimestamp));
+            Assert.That(actual.CBinary, Is.EqualTo(expected.CBinary));
+            Assert.That(actual.CVarbinary, Is.EqualTo(expected.CVarbinary));
+            Assert.That(actual.CTinyblob, Is.EqualTo(expected.CTinyblob));
+            Assert.That(actual.CBlob, Is.EqualTo(expected.CBlob));
+            Assert.That(actual.CMediumblob, Is.EqualTo(expected.CMediumblob));
+            Assert.That(actual.CLongblob, Is.EqualTo(expected.CLongblob));
         }
 
         [Test]
@@ -367,7 +379,7 @@ public async Task TestNargNotNull()
         }
 
         [Test]
-        [TestCase(false, true, 0x32, 13, 2084, 3124, -54355, 324245, -67865, 9787668656, "&", "\u1857", "\u2649", "Sheena is a Punk Rocker", "Holiday in Cambodia", "London's Calling", "London's Burning", "Police & Thieves", "2000-1-30", "1983-11-3 02:01:22", new byte[] { 0x15, 0x16, 0x17 }, new byte[] { 0x15, 0x22 }, new byte[] { 0x23 }, new byte[] { 0x33, 0x13 }, new byte[] { 0x11, 0x62, 0x10 }, new byte[] { 0x38, 0x45, 0x06 })]
+        [TestCase(false, true, 0x32, 13, 2084, 3124, -54355, 324245, -67865, 9787668656, "&", "\u1857", "\u2649", "Sheena is a Punk Rocker", "Holiday in Cambodia", "London's Calling", "London's Burning", "Police & Thieves", "2000-1-30", "1983-11-3 02:01:22", new byte[] { 0x15, 0x16, 0x17 }, new byte[] { 0x15, 0x24 }, new byte[] { 0x23 }, new byte[] { 0x33, 0x13 }, new byte[] { 0x11, 0x62, 0x10 }, new byte[] { 0x38, 0x45, 0x06 })]
         [TestCase(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01", new byte[] { 0x0, 0x0, 0x0 }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { })]
         [TestCase(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "1970-1-1 00:00:01", null, null, null, null, null, null)]
         public async Task TestMySqlTypes(bool cBool, bool cBoolean, byte cBit, short cTinyint, short cYear, short cSmallint, int cMediumint, int cInt, int cInteger, long cBigint, string cChar, string cNchar, string cNationalChar, string cVarchar, string cTinytext, string cMediumtext, string cText, string cLongtext, DateTime cDate, DateTime cTimestamp, byte[] cBinary, byte[] cVarbinary, byte[] cTinyblob, byte[] cBlob, byte[] cMediumblob, byte[] cLongblob)
diff --git a/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs b/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs
index 0bf0f77f..6fa13876 100644
--- a/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs
+++ b/end2end/EndToEndTestsLegacy/SqliteDapperTester.generated.cs
@@ -306,7 +306,7 @@ public async Task TestNargNotNull()
         }
 
         [Test]
-        [TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x22 })]
+        [TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x33 })]
         [TestCase(null, null, null, new byte[] { })]
         [TestCase(null, null, null, null)]
         public async Task TestSqliteTypes(int cInteger, decimal cReal, string cText, byte[] cBlob)
diff --git a/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs b/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs
index 4b662e0a..8e3e38c1 100644
--- a/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs
+++ b/end2end/EndToEndTestsLegacy/SqliteTester.generated.cs
@@ -306,7 +306,7 @@ public async Task TestNargNotNull()
         }
 
         [Test]
-        [TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x22 })]
+        [TestCase(-54355, 9787.66, "Songs of Love and Hate", new byte[] { 0x15, 0x20, 0x33 })]
         [TestCase(null, null, null, new byte[] { })]
         [TestCase(null, null, null, null)]
         public async Task TestSqliteTypes(int cInteger, decimal cReal, string cText, byte[] cBlob)
diff --git a/examples/MySqlConnectorDapperExample/QuerySql.cs b/examples/MySqlConnectorDapperExample/QuerySql.cs
index 90d56f63..39dccce0 100644
--- a/examples/MySqlConnectorDapperExample/QuerySql.cs
+++ b/examples/MySqlConnectorDapperExample/QuerySql.cs
@@ -343,14 +343,13 @@ public async Task<List<GetAuthorsByBookNameRow>> GetAuthorsByBookName(GetAuthors
         }
     }
 
-    private const string InsertMysqlTypesSql = "INSERT INTO mysql_types (c_bit, c_tinyint, c_bool, c_boolean, c_year, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_decimal, c_dec, c_numeric, c_fixed, c_float, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_date, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob) VALUES ( @c_bit, @c_tinyint, @c_bool, @c_boolean, @c_year, @c_smallint, @c_mediumint, @c_int, @c_integer, @c_bigint, @c_decimal, @c_dec, @c_numeric, @c_fixed, @c_float, @c_double, @c_double_precision, @c_char, @c_nchar, @c_national_char, @c_varchar, @c_tinytext, @c_mediumtext, @c_text, @c_longtext, @c_date, @c_timestamp, @c_binary, @c_varbinary, @c_tinyblob, @c_blob, @c_mediumblob, @c_longblob ); SELECT  LAST_INSERT_ID ( ) "; 
+    private const string InsertMysqlTypesSql = "INSERT INTO mysql_types (c_bit, c_bool, c_boolean, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_decimal, c_dec, c_numeric, c_fixed, c_float, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob) VALUES ( @c_bit, @c_bool, @c_boolean, @c_tinyint, @c_smallint, @c_mediumint, @c_int, @c_integer, @c_bigint, @c_decimal, @c_dec, @c_numeric, @c_fixed, @c_float, @c_double, @c_double_precision, @c_char, @c_nchar, @c_national_char, @c_varchar, @c_tinytext, @c_mediumtext, @c_text, @c_longtext, @c_year, @c_date, @c_datetime, @c_timestamp, @c_binary, @c_varbinary, @c_tinyblob, @c_blob, @c_mediumblob, @c_longblob ); SELECT  LAST_INSERT_ID ( ) "; 
     public class InsertMysqlTypesArgs
     {
         public byte? CBit { get; init; }
-        public short? CTinyint { get; init; }
         public bool? CBool { get; init; }
         public bool? CBoolean { get; init; }
-        public short? CYear { get; init; }
+        public short? CTinyint { get; init; }
         public short? CSmallint { get; init; }
         public int? CMediumint { get; init; }
         public int? CInt { get; init; }
@@ -371,7 +370,9 @@ public class InsertMysqlTypesArgs
         public string? CMediumtext { get; init; }
         public string? CText { get; init; }
         public string? CLongtext { get; init; }
+        public short? CYear { get; init; }
         public DateTime? CDate { get; init; }
+        public DateTime? CDatetime { get; init; }
         public DateTime? CTimestamp { get; init; }
         public byte[]? CBinary { get; init; }
         public byte[]? CVarbinary { get; init; }
@@ -386,10 +387,9 @@ public async Task InsertMysqlTypes(InsertMysqlTypesArgs args)
         {
             var queryParams = new Dictionary<string, object?>();
             queryParams.Add("c_bit", args.CBit);
-            queryParams.Add("c_tinyint", args.CTinyint);
             queryParams.Add("c_bool", args.CBool);
             queryParams.Add("c_boolean", args.CBoolean);
-            queryParams.Add("c_year", args.CYear);
+            queryParams.Add("c_tinyint", args.CTinyint);
             queryParams.Add("c_smallint", args.CSmallint);
             queryParams.Add("c_mediumint", args.CMediumint);
             queryParams.Add("c_int", args.CInt);
@@ -410,7 +410,9 @@ public async Task InsertMysqlTypes(InsertMysqlTypesArgs args)
             queryParams.Add("c_mediumtext", args.CMediumtext);
             queryParams.Add("c_text", args.CText);
             queryParams.Add("c_longtext", args.CLongtext);
+            queryParams.Add("c_year", args.CYear);
             queryParams.Add("c_date", args.CDate);
+            queryParams.Add("c_datetime", args.CDatetime);
             queryParams.Add("c_timestamp", args.CTimestamp);
             queryParams.Add("c_binary", args.CBinary);
             queryParams.Add("c_varbinary", args.CVarbinary);
@@ -424,9 +426,9 @@ public async Task InsertMysqlTypes(InsertMysqlTypesArgs args)
 
     public class InsertMysqlTypesBatchArgs
     {
+        public byte? CBit { get; init; }
         public bool? CBool { get; init; }
         public bool? CBoolean { get; init; }
-        public byte? CBit { get; init; }
         public short? CTinyint { get; init; }
         public short? CSmallint { get; init; }
         public int? CMediumint { get; init; }
@@ -452,28 +454,36 @@ public class InsertMysqlTypesBatchArgs
         public DateTime? CDate { get; init; }
         public DateTime? CDatetime { get; init; }
         public DateTime? CTimestamp { get; init; }
+        public byte[]? CBinary { get; init; }
+        public byte[]? CVarbinary { get; init; }
+        public byte[]? CTinyblob { get; init; }
+        public byte[]? CBlob { get; init; }
+        public byte[]? CMediumblob { get; init; }
+        public byte[]? CLongblob { get; init; }
     };
     public async Task InsertMysqlTypesBatch(List<InsertMysqlTypesBatchArgs> args)
     {
         const string supportedDateTimeFormat = "yyyy-MM-dd H:mm:ss";
         var config = new CsvConfiguration(CultureInfo.CurrentCulture)
         {
-            Delimiter = ","
+            Delimiter = ",",
+            NewLine = "\n"
         };
         var nullConverterFn = new Utils.NullToStringConverter();
         using (var writer = new StreamWriter("input.csv", false, new UTF8Encoding(false)))
         using (var csvWriter = new CsvWriter(writer, config))
         {
-            var Options = new TypeConverterOptions
+            var options = new TypeConverterOptions
             {
                 Formats = new[]
                 {
                     supportedDateTimeFormat
                 }
             };
-            csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime>(Options);
-            csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime?>(Options);
+            csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime>(options);
+            csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime?>(options);
             csvWriter.Context.TypeConverterCache.AddConverter<bool?>(new Utils.BoolToBitConverter());
+            csvWriter.Context.TypeConverterCache.AddConverter<byte[]?>(new Utils.ByteArrayConverter());
             csvWriter.Context.TypeConverterCache.AddConverter<byte?>(nullConverterFn);
             csvWriter.Context.TypeConverterCache.AddConverter<short?>(nullConverterFn);
             csvWriter.Context.TypeConverterCache.AddConverter<int?>(nullConverterFn);
@@ -500,7 +510,7 @@ public async Task InsertMysqlTypesBatch(List<InsertMysqlTypesBatchArgs> args)
                 FieldQuotationOptional = true,
                 NumberOfLinesToSkip = 1
             };
-            loader.Columns.AddRange(new List<string> { "c_bool", "c_boolean", "c_bit", "c_tinyint", "c_smallint", "c_mediumint", "c_int", "c_integer", "c_bigint", "c_float", "c_numeric", "c_decimal", "c_dec", "c_fixed", "c_double", "c_double_precision", "c_char", "c_nchar", "c_national_char", "c_varchar", "c_tinytext", "c_mediumtext", "c_text", "c_longtext", "c_year", "c_date", "c_datetime", "c_timestamp" });
+            loader.Columns.AddRange(new List<string> { "c_bit", "c_bool", "c_boolean", "c_tinyint", "c_smallint", "c_mediumint", "c_int", "c_integer", "c_bigint", "c_float", "c_numeric", "c_decimal", "c_dec", "c_fixed", "c_double", "c_double_precision", "c_char", "c_nchar", "c_national_char", "c_varchar", "c_tinytext", "c_mediumtext", "c_text", "c_longtext", "c_year", "c_date", "c_datetime", "c_timestamp", "c_binary", "c_varbinary", "c_tinyblob", "c_blob", "c_mediumblob", "c_longblob" });
             await loader.LoadAsync();
             await connection.CloseAsync();
         }
@@ -554,7 +564,7 @@ public class GetMysqlTypesRow
         }
     }
 
-    private const string GetMysqlTypesAggSql = "SELECT COUNT(1) AS cnt, c_bool, c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp FROM  mysql_types  GROUP  BY  c_bool , c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp LIMIT  1 ; SELECT  LAST_INSERT_ID ( ) "; 
+    private const string GetMysqlTypesAggSql = "SELECT COUNT(1) AS cnt, c_bool, c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint,  c_float , c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob FROM  mysql_types  GROUP  BY  c_bool , c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob LIMIT  1 ; SELECT  LAST_INSERT_ID ( ) "; 
     public class GetMysqlTypesAggRow
     {
         public required long Cnt { get; init; }
@@ -586,6 +596,12 @@ public class GetMysqlTypesAggRow
         public DateTime? CDate { get; init; }
         public DateTime? CDatetime { get; init; }
         public DateTime? CTimestamp { get; init; }
+        public byte[]? CBinary { get; init; }
+        public byte[]? CVarbinary { get; init; }
+        public byte[]? CTinyblob { get; init; }
+        public byte[]? CBlob { get; init; }
+        public byte[]? CMediumblob { get; init; }
+        public byte[]? CLongblob { get; init; }
     };
     public async Task<GetMysqlTypesAggRow?> GetMysqlTypesAgg()
     {
diff --git a/examples/MySqlConnectorDapperExample/Utils.cs b/examples/MySqlConnectorDapperExample/Utils.cs
index c22312b1..eb33f3fb 100644
--- a/examples/MySqlConnectorDapperExample/Utils.cs
+++ b/examples/MySqlConnectorDapperExample/Utils.cs
@@ -12,7 +12,7 @@ public static class Utils
 {
     public class NullToStringConverter : DefaultTypeConverter
     {
-        public override string ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+        public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
         {
             return value == null ? @"\N" : base.ConvertToString(value, row, memberMapData);
         }
@@ -20,7 +20,7 @@ public override string ConvertToString(object? value, IWriterRow row, MemberMapD
 
     public class BoolToBitConverter : DefaultTypeConverter
     {
-        public override string ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+        public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
         {
             switch (value)
             {
@@ -34,6 +34,18 @@ public override string ConvertToString(object? value, IWriterRow row, MemberMapD
         }
     }
 
+    public class ByteArrayConverter : DefaultTypeConverter
+    {
+        public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+        {
+            if (value == null)
+                return @"\N";
+            if (value is byte[] byteArray)
+                return System.Text.Encoding.UTF8.GetString(byteArray);
+            return base.ConvertToString(value, row, memberMapData);
+        }
+    }
+
     public static string TransformQueryForSliceArgs(string originalSql, int sliceSize, string paramName)
     {
         var paramArgs = Enumerable.Range(0, sliceSize).Select(i => $"@{paramName}Arg{i}").ToList();
diff --git a/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs b/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs
index bb36369d..2b6565b8 100644
--- a/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs
+++ b/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs
@@ -344,14 +344,13 @@ public async Task<List<GetAuthorsByBookNameRow>> GetAuthorsByBookName(GetAuthors
             }
         }
 
-        private const string InsertMysqlTypesSql = "INSERT INTO mysql_types (c_bit, c_tinyint, c_bool, c_boolean, c_year, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_decimal, c_dec, c_numeric, c_fixed, c_float, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_date, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob) VALUES ( @c_bit, @c_tinyint, @c_bool, @c_boolean, @c_year, @c_smallint, @c_mediumint, @c_int, @c_integer, @c_bigint, @c_decimal, @c_dec, @c_numeric, @c_fixed, @c_float, @c_double, @c_double_precision, @c_char, @c_nchar, @c_national_char, @c_varchar, @c_tinytext, @c_mediumtext, @c_text, @c_longtext, @c_date, @c_timestamp, @c_binary, @c_varbinary, @c_tinyblob, @c_blob, @c_mediumblob, @c_longblob ); SELECT  LAST_INSERT_ID ( ) "; 
+        private const string InsertMysqlTypesSql = "INSERT INTO mysql_types (c_bit, c_bool, c_boolean, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_decimal, c_dec, c_numeric, c_fixed, c_float, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob) VALUES ( @c_bit, @c_bool, @c_boolean, @c_tinyint, @c_smallint, @c_mediumint, @c_int, @c_integer, @c_bigint, @c_decimal, @c_dec, @c_numeric, @c_fixed, @c_float, @c_double, @c_double_precision, @c_char, @c_nchar, @c_national_char, @c_varchar, @c_tinytext, @c_mediumtext, @c_text, @c_longtext, @c_year, @c_date, @c_datetime, @c_timestamp, @c_binary, @c_varbinary, @c_tinyblob, @c_blob, @c_mediumblob, @c_longblob ); SELECT  LAST_INSERT_ID ( ) "; 
         public class InsertMysqlTypesArgs
         {
             public byte? CBit { get; set; }
-            public short? CTinyint { get; set; }
             public bool? CBool { get; set; }
             public bool? CBoolean { get; set; }
-            public short? CYear { get; set; }
+            public short? CTinyint { get; set; }
             public short? CSmallint { get; set; }
             public int? CMediumint { get; set; }
             public int? CInt { get; set; }
@@ -372,7 +371,9 @@ public class InsertMysqlTypesArgs
             public string CMediumtext { get; set; }
             public string CText { get; set; }
             public string CLongtext { get; set; }
+            public short? CYear { get; set; }
             public DateTime? CDate { get; set; }
+            public DateTime? CDatetime { get; set; }
             public DateTime? CTimestamp { get; set; }
             public byte[] CBinary { get; set; }
             public byte[] CVarbinary { get; set; }
@@ -387,10 +388,9 @@ public async Task InsertMysqlTypes(InsertMysqlTypesArgs args)
             {
                 var queryParams = new Dictionary<string, object>();
                 queryParams.Add("c_bit", args.CBit);
-                queryParams.Add("c_tinyint", args.CTinyint);
                 queryParams.Add("c_bool", args.CBool);
                 queryParams.Add("c_boolean", args.CBoolean);
-                queryParams.Add("c_year", args.CYear);
+                queryParams.Add("c_tinyint", args.CTinyint);
                 queryParams.Add("c_smallint", args.CSmallint);
                 queryParams.Add("c_mediumint", args.CMediumint);
                 queryParams.Add("c_int", args.CInt);
@@ -411,7 +411,9 @@ public async Task InsertMysqlTypes(InsertMysqlTypesArgs args)
                 queryParams.Add("c_mediumtext", args.CMediumtext);
                 queryParams.Add("c_text", args.CText);
                 queryParams.Add("c_longtext", args.CLongtext);
+                queryParams.Add("c_year", args.CYear);
                 queryParams.Add("c_date", args.CDate);
+                queryParams.Add("c_datetime", args.CDatetime);
                 queryParams.Add("c_timestamp", args.CTimestamp);
                 queryParams.Add("c_binary", args.CBinary);
                 queryParams.Add("c_varbinary", args.CVarbinary);
@@ -425,9 +427,9 @@ public async Task InsertMysqlTypes(InsertMysqlTypesArgs args)
 
         public class InsertMysqlTypesBatchArgs
         {
+            public byte? CBit { get; set; }
             public bool? CBool { get; set; }
             public bool? CBoolean { get; set; }
-            public byte? CBit { get; set; }
             public short? CTinyint { get; set; }
             public short? CSmallint { get; set; }
             public int? CMediumint { get; set; }
@@ -453,28 +455,36 @@ public class InsertMysqlTypesBatchArgs
             public DateTime? CDate { get; set; }
             public DateTime? CDatetime { get; set; }
             public DateTime? CTimestamp { get; set; }
+            public byte[] CBinary { get; set; }
+            public byte[] CVarbinary { get; set; }
+            public byte[] CTinyblob { get; set; }
+            public byte[] CBlob { get; set; }
+            public byte[] CMediumblob { get; set; }
+            public byte[] CLongblob { get; set; }
         };
         public async Task InsertMysqlTypesBatch(List<InsertMysqlTypesBatchArgs> args)
         {
             const string supportedDateTimeFormat = "yyyy-MM-dd H:mm:ss";
             var config = new CsvConfiguration(CultureInfo.CurrentCulture)
             {
-                Delimiter = ","
+                Delimiter = ",",
+                NewLine = "\n"
             };
             var nullConverterFn = new Utils.NullToStringConverter();
             using (var writer = new StreamWriter("input.csv", false, new UTF8Encoding(false)))
             using (var csvWriter = new CsvWriter(writer, config))
             {
-                var Options = new TypeConverterOptions
+                var options = new TypeConverterOptions
                 {
                     Formats = new[]
                     {
                         supportedDateTimeFormat
                     }
                 };
-                csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime>(Options);
-                csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime?>(Options);
+                csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime>(options);
+                csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime?>(options);
                 csvWriter.Context.TypeConverterCache.AddConverter<bool?>(new Utils.BoolToBitConverter());
+                csvWriter.Context.TypeConverterCache.AddConverter<byte[]>(new Utils.ByteArrayConverter());
                 csvWriter.Context.TypeConverterCache.AddConverter<byte?>(nullConverterFn);
                 csvWriter.Context.TypeConverterCache.AddConverter<short?>(nullConverterFn);
                 csvWriter.Context.TypeConverterCache.AddConverter<int?>(nullConverterFn);
@@ -501,7 +511,7 @@ public async Task InsertMysqlTypesBatch(List<InsertMysqlTypesBatchArgs> args)
                     FieldQuotationOptional = true,
                     NumberOfLinesToSkip = 1
                 };
-                loader.Columns.AddRange(new List<string> { "c_bool", "c_boolean", "c_bit", "c_tinyint", "c_smallint", "c_mediumint", "c_int", "c_integer", "c_bigint", "c_float", "c_numeric", "c_decimal", "c_dec", "c_fixed", "c_double", "c_double_precision", "c_char", "c_nchar", "c_national_char", "c_varchar", "c_tinytext", "c_mediumtext", "c_text", "c_longtext", "c_year", "c_date", "c_datetime", "c_timestamp" });
+                loader.Columns.AddRange(new List<string> { "c_bit", "c_bool", "c_boolean", "c_tinyint", "c_smallint", "c_mediumint", "c_int", "c_integer", "c_bigint", "c_float", "c_numeric", "c_decimal", "c_dec", "c_fixed", "c_double", "c_double_precision", "c_char", "c_nchar", "c_national_char", "c_varchar", "c_tinytext", "c_mediumtext", "c_text", "c_longtext", "c_year", "c_date", "c_datetime", "c_timestamp", "c_binary", "c_varbinary", "c_tinyblob", "c_blob", "c_mediumblob", "c_longblob" });
                 await loader.LoadAsync();
                 await connection.CloseAsync();
             }
@@ -555,7 +565,7 @@ public async Task<GetMysqlTypesRow> GetMysqlTypes()
             }
         }
 
-        private const string GetMysqlTypesAggSql = "SELECT COUNT(1) AS cnt, c_bool, c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp FROM  mysql_types  GROUP  BY  c_bool , c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp LIMIT  1 ; SELECT  LAST_INSERT_ID ( ) "; 
+        private const string GetMysqlTypesAggSql = "SELECT COUNT(1) AS cnt, c_bool, c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint,  c_float , c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob FROM  mysql_types  GROUP  BY  c_bool , c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob LIMIT  1 ; SELECT  LAST_INSERT_ID ( ) "; 
         public class GetMysqlTypesAggRow
         {
             public long Cnt { get; set; }
@@ -587,6 +597,12 @@ public class GetMysqlTypesAggRow
             public DateTime? CDate { get; set; }
             public DateTime? CDatetime { get; set; }
             public DateTime? CTimestamp { get; set; }
+            public byte[] CBinary { get; set; }
+            public byte[] CVarbinary { get; set; }
+            public byte[] CTinyblob { get; set; }
+            public byte[] CBlob { get; set; }
+            public byte[] CMediumblob { get; set; }
+            public byte[] CLongblob { get; set; }
         };
         public async Task<GetMysqlTypesAggRow> GetMysqlTypesAgg()
         {
diff --git a/examples/MySqlConnectorDapperLegacyExample/Utils.cs b/examples/MySqlConnectorDapperLegacyExample/Utils.cs
index 7ccaf222..d45740a7 100644
--- a/examples/MySqlConnectorDapperLegacyExample/Utils.cs
+++ b/examples/MySqlConnectorDapperLegacyExample/Utils.cs
@@ -35,6 +35,18 @@ public override string ConvertToString(object value, IWriterRow row, MemberMapDa
             }
         }
 
+        public class ByteArrayConverter : DefaultTypeConverter
+        {
+            public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
+            {
+                if (value == null)
+                    return @"\N";
+                if (value is byte[] byteArray)
+                    return System.Text.Encoding.UTF8.GetString(byteArray);
+                return base.ConvertToString(value, row, memberMapData);
+            }
+        }
+
         public static string TransformQueryForSliceArgs(string originalSql, int sliceSize, string paramName)
         {
             var paramArgs = Enumerable.Range(0, sliceSize).Select(i => $"@{paramName}Arg{i}").ToList();
diff --git a/examples/MySqlConnectorExample/QuerySql.cs b/examples/MySqlConnectorExample/QuerySql.cs
index 9476f798..849c359e 100644
--- a/examples/MySqlConnectorExample/QuerySql.cs
+++ b/examples/MySqlConnectorExample/QuerySql.cs
@@ -355,8 +355,8 @@ public async Task<List<GetAuthorsByBookNameRow>> GetAuthorsByBookName(GetAuthors
         }
     }
 
-    private const string InsertMysqlTypesSql = "INSERT INTO mysql_types (c_bit, c_tinyint, c_bool, c_boolean, c_year, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_decimal, c_dec, c_numeric, c_fixed, c_float, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_date, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob) VALUES ( @c_bit, @c_tinyint, @c_bool, @c_boolean, @c_year, @c_smallint, @c_mediumint, @c_int, @c_integer, @c_bigint, @c_decimal, @c_dec, @c_numeric, @c_fixed, @c_float, @c_double, @c_double_precision, @c_char, @c_nchar, @c_national_char, @c_varchar, @c_tinytext, @c_mediumtext, @c_text, @c_longtext, @c_date, @c_timestamp, @c_binary, @c_varbinary, @c_tinyblob, @c_blob, @c_mediumblob, @c_longblob ) "; 
-    public readonly record struct InsertMysqlTypesArgs(byte? CBit, short? CTinyint, bool? CBool, bool? CBoolean, short? CYear, short? CSmallint, int? CMediumint, int? CInt, int? CInteger, long? CBigint, string? CDecimal, string? CDec, string? CNumeric, string? CFixed, double? CFloat, double? CDouble, double? CDoublePrecision, string? CChar, string? CNchar, string? CNationalChar, string? CVarchar, string? CTinytext, string? CMediumtext, string? CText, string? CLongtext, DateTime? CDate, DateTime? CTimestamp, byte[]? CBinary, byte[]? CVarbinary, byte[]? CTinyblob, byte[]? CBlob, byte[]? CMediumblob, byte[]? CLongblob);
+    private const string InsertMysqlTypesSql = "INSERT INTO mysql_types (c_bit, c_bool, c_boolean, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_decimal, c_dec, c_numeric, c_fixed, c_float, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob) VALUES ( @c_bit, @c_bool, @c_boolean, @c_tinyint, @c_smallint, @c_mediumint, @c_int, @c_integer, @c_bigint, @c_decimal, @c_dec, @c_numeric, @c_fixed, @c_float, @c_double, @c_double_precision, @c_char, @c_nchar, @c_national_char, @c_varchar, @c_tinytext, @c_mediumtext, @c_text, @c_longtext, @c_year, @c_date, @c_datetime, @c_timestamp, @c_binary, @c_varbinary, @c_tinyblob, @c_blob, @c_mediumblob, @c_longblob ) "; 
+    public readonly record struct InsertMysqlTypesArgs(byte? CBit, bool? CBool, bool? CBoolean, short? CTinyint, short? CSmallint, int? CMediumint, int? CInt, int? CInteger, long? CBigint, string? CDecimal, string? CDec, string? CNumeric, string? CFixed, double? CFloat, double? CDouble, double? CDoublePrecision, string? CChar, string? CNchar, string? CNationalChar, string? CVarchar, string? CTinytext, string? CMediumtext, string? CText, string? CLongtext, short? CYear, DateTime? CDate, DateTime? CDatetime, DateTime? CTimestamp, byte[]? CBinary, byte[]? CVarbinary, byte[]? CTinyblob, byte[]? CBlob, byte[]? CMediumblob, byte[]? CLongblob);
     public async Task InsertMysqlTypes(InsertMysqlTypesArgs args)
     {
         using (var connection = new MySqlConnection(ConnectionString))
@@ -365,10 +365,9 @@ public async Task InsertMysqlTypes(InsertMysqlTypesArgs args)
             using (var command = new MySqlCommand(InsertMysqlTypesSql, connection))
             {
                 command.Parameters.AddWithValue("@c_bit", args.CBit ?? (object)DBNull.Value);
-                command.Parameters.AddWithValue("@c_tinyint", args.CTinyint ?? (object)DBNull.Value);
                 command.Parameters.AddWithValue("@c_bool", args.CBool ?? (object)DBNull.Value);
                 command.Parameters.AddWithValue("@c_boolean", args.CBoolean ?? (object)DBNull.Value);
-                command.Parameters.AddWithValue("@c_year", args.CYear ?? (object)DBNull.Value);
+                command.Parameters.AddWithValue("@c_tinyint", args.CTinyint ?? (object)DBNull.Value);
                 command.Parameters.AddWithValue("@c_smallint", args.CSmallint ?? (object)DBNull.Value);
                 command.Parameters.AddWithValue("@c_mediumint", args.CMediumint ?? (object)DBNull.Value);
                 command.Parameters.AddWithValue("@c_int", args.CInt ?? (object)DBNull.Value);
@@ -389,7 +388,9 @@ public async Task InsertMysqlTypes(InsertMysqlTypesArgs args)
                 command.Parameters.AddWithValue("@c_mediumtext", args.CMediumtext ?? (object)DBNull.Value);
                 command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value);
                 command.Parameters.AddWithValue("@c_longtext", args.CLongtext ?? (object)DBNull.Value);
+                command.Parameters.AddWithValue("@c_year", args.CYear ?? (object)DBNull.Value);
                 command.Parameters.AddWithValue("@c_date", args.CDate ?? (object)DBNull.Value);
+                command.Parameters.AddWithValue("@c_datetime", args.CDatetime ?? (object)DBNull.Value);
                 command.Parameters.AddWithValue("@c_timestamp", args.CTimestamp ?? (object)DBNull.Value);
                 command.Parameters.AddWithValue("@c_binary", args.CBinary ?? (object)DBNull.Value);
                 command.Parameters.AddWithValue("@c_varbinary", args.CVarbinary ?? (object)DBNull.Value);
@@ -402,28 +403,30 @@ public async Task InsertMysqlTypes(InsertMysqlTypesArgs args)
         }
     }
 
-    public readonly record struct InsertMysqlTypesBatchArgs(bool? CBool, bool? CBoolean, byte? CBit, short? CTinyint, short? CSmallint, int? CMediumint, int? CInt, int? CInteger, long? CBigint, double? CFloat, string? CNumeric, string? CDecimal, string? CDec, string? CFixed, double? CDouble, double? CDoublePrecision, string? CChar, string? CNchar, string? CNationalChar, string? CVarchar, string? CTinytext, string? CMediumtext, string? CText, string? CLongtext, short? CYear, DateTime? CDate, DateTime? CDatetime, DateTime? CTimestamp);
+    public readonly record struct InsertMysqlTypesBatchArgs(byte? CBit, bool? CBool, bool? CBoolean, short? CTinyint, short? CSmallint, int? CMediumint, int? CInt, int? CInteger, long? CBigint, double? CFloat, string? CNumeric, string? CDecimal, string? CDec, string? CFixed, double? CDouble, double? CDoublePrecision, string? CChar, string? CNchar, string? CNationalChar, string? CVarchar, string? CTinytext, string? CMediumtext, string? CText, string? CLongtext, short? CYear, DateTime? CDate, DateTime? CDatetime, DateTime? CTimestamp, byte[]? CBinary, byte[]? CVarbinary, byte[]? CTinyblob, byte[]? CBlob, byte[]? CMediumblob, byte[]? CLongblob);
     public async Task InsertMysqlTypesBatch(List<InsertMysqlTypesBatchArgs> args)
     {
         const string supportedDateTimeFormat = "yyyy-MM-dd H:mm:ss";
         var config = new CsvConfiguration(CultureInfo.CurrentCulture)
         {
-            Delimiter = ","
+            Delimiter = ",",
+            NewLine = "\n"
         };
         var nullConverterFn = new Utils.NullToStringConverter();
         using (var writer = new StreamWriter("input.csv", false, new UTF8Encoding(false)))
         using (var csvWriter = new CsvWriter(writer, config))
         {
-            var Options = new TypeConverterOptions
+            var options = new TypeConverterOptions
             {
                 Formats = new[]
                 {
                     supportedDateTimeFormat
                 }
             };
-            csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime>(Options);
-            csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime?>(Options);
+            csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime>(options);
+            csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime?>(options);
             csvWriter.Context.TypeConverterCache.AddConverter<bool?>(new Utils.BoolToBitConverter());
+            csvWriter.Context.TypeConverterCache.AddConverter<byte[]?>(new Utils.ByteArrayConverter());
             csvWriter.Context.TypeConverterCache.AddConverter<byte?>(nullConverterFn);
             csvWriter.Context.TypeConverterCache.AddConverter<short?>(nullConverterFn);
             csvWriter.Context.TypeConverterCache.AddConverter<int?>(nullConverterFn);
@@ -450,7 +453,7 @@ public async Task InsertMysqlTypesBatch(List<InsertMysqlTypesBatchArgs> args)
                 FieldQuotationOptional = true,
                 NumberOfLinesToSkip = 1
             };
-            loader.Columns.AddRange(new List<string> { "c_bool", "c_boolean", "c_bit", "c_tinyint", "c_smallint", "c_mediumint", "c_int", "c_integer", "c_bigint", "c_float", "c_numeric", "c_decimal", "c_dec", "c_fixed", "c_double", "c_double_precision", "c_char", "c_nchar", "c_national_char", "c_varchar", "c_tinytext", "c_mediumtext", "c_text", "c_longtext", "c_year", "c_date", "c_datetime", "c_timestamp" });
+            loader.Columns.AddRange(new List<string> { "c_bit", "c_bool", "c_boolean", "c_tinyint", "c_smallint", "c_mediumint", "c_int", "c_integer", "c_bigint", "c_float", "c_numeric", "c_decimal", "c_dec", "c_fixed", "c_double", "c_double_precision", "c_char", "c_nchar", "c_national_char", "c_varchar", "c_tinytext", "c_mediumtext", "c_text", "c_longtext", "c_year", "c_date", "c_datetime", "c_timestamp", "c_binary", "c_varbinary", "c_tinyblob", "c_blob", "c_mediumblob", "c_longblob" });
             await loader.LoadAsync();
             await connection.CloseAsync();
         }
@@ -500,12 +503,12 @@ public async Task InsertMysqlTypesBatch(List<InsertMysqlTypesBatchArgs> args)
                             CText = reader.IsDBNull(26) ? (string? )null : reader.GetString(26),
                             CLongtext = reader.IsDBNull(27) ? (string? )null : reader.GetString(27),
                             CBit = reader.IsDBNull(28) ? (byte? )null : reader.GetFieldValue<byte>(28),
-                            CBinary = reader.IsDBNull(29) ? null : reader.GetFieldValue<byte[]>(29),
-                            CVarbinary = reader.IsDBNull(30) ? null : reader.GetFieldValue<byte[]>(30),
-                            CTinyblob = reader.IsDBNull(31) ? null : reader.GetFieldValue<byte[]>(31),
-                            CBlob = reader.IsDBNull(32) ? null : reader.GetFieldValue<byte[]>(32),
-                            CMediumblob = reader.IsDBNull(33) ? null : reader.GetFieldValue<byte[]>(33),
-                            CLongblob = reader.IsDBNull(34) ? null : reader.GetFieldValue<byte[]>(34)
+                            CBinary = reader.IsDBNull(29) ? (byte[]? )null : reader.GetFieldValue<byte[]>(29),
+                            CVarbinary = reader.IsDBNull(30) ? (byte[]? )null : reader.GetFieldValue<byte[]>(30),
+                            CTinyblob = reader.IsDBNull(31) ? (byte[]? )null : reader.GetFieldValue<byte[]>(31),
+                            CBlob = reader.IsDBNull(32) ? (byte[]? )null : reader.GetFieldValue<byte[]>(32),
+                            CMediumblob = reader.IsDBNull(33) ? (byte[]? )null : reader.GetFieldValue<byte[]>(33),
+                            CLongblob = reader.IsDBNull(34) ? (byte[]? )null : reader.GetFieldValue<byte[]>(34)
                         };
                     }
                 }
@@ -515,8 +518,8 @@ public async Task InsertMysqlTypesBatch(List<InsertMysqlTypesBatchArgs> args)
         return null;
     }
 
-    private const string GetMysqlTypesAggSql = "SELECT COUNT(1) AS cnt, c_bool, c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp FROM  mysql_types  GROUP  BY  c_bool , c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp LIMIT  1  ";  
-    public readonly record struct GetMysqlTypesAggRow(long Cnt, bool? CBool, bool? CBoolean, byte? CBit, short? CTinyint, short? CSmallint, int? CMediumint, int? CInt, int? CInteger, long? CBigint, double? CFloat, string? CNumeric, string? CDecimal, string? CDec, string? CFixed, double? CDouble, double? CDoublePrecision, string? CChar, string? CNchar, string? CNationalChar, string? CVarchar, string? CTinytext, string? CMediumtext, string? CText, string? CLongtext, short? CYear, DateTime? CDate, DateTime? CDatetime, DateTime? CTimestamp);
+    private const string GetMysqlTypesAggSql = "SELECT COUNT(1) AS cnt, c_bool, c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint,  c_float , c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob FROM  mysql_types  GROUP  BY  c_bool , c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob LIMIT  1  ";  
+    public readonly record struct GetMysqlTypesAggRow(long Cnt, bool? CBool, bool? CBoolean, byte? CBit, short? CTinyint, short? CSmallint, int? CMediumint, int? CInt, int? CInteger, long? CBigint, double? CFloat, string? CNumeric, string? CDecimal, string? CDec, string? CFixed, double? CDouble, double? CDoublePrecision, string? CChar, string? CNchar, string? CNationalChar, string? CVarchar, string? CTinytext, string? CMediumtext, string? CText, string? CLongtext, short? CYear, DateTime? CDate, DateTime? CDatetime, DateTime? CTimestamp, byte[]? CBinary, byte[]? CVarbinary, byte[]? CTinyblob, byte[]? CBlob, byte[]? CMediumblob, byte[]? CLongblob);
     public async Task<GetMysqlTypesAggRow?> GetMysqlTypesAgg()
     {
         using (var connection = new MySqlConnection(ConnectionString))
@@ -558,7 +561,13 @@ public async Task InsertMysqlTypesBatch(List<InsertMysqlTypesBatchArgs> args)
                             CYear = reader.IsDBNull(25) ? (short? )null : reader.GetInt16(25),
                             CDate = reader.IsDBNull(26) ? (DateTime? )null : reader.GetDateTime(26),
                             CDatetime = reader.IsDBNull(27) ? (DateTime? )null : reader.GetDateTime(27),
-                            CTimestamp = reader.IsDBNull(28) ? (DateTime? )null : reader.GetDateTime(28)
+                            CTimestamp = reader.IsDBNull(28) ? (DateTime? )null : reader.GetDateTime(28),
+                            CBinary = reader.IsDBNull(29) ? (byte[]? )null : reader.GetFieldValue<byte[]>(29),
+                            CVarbinary = reader.IsDBNull(30) ? (byte[]? )null : reader.GetFieldValue<byte[]>(30),
+                            CTinyblob = reader.IsDBNull(31) ? (byte[]? )null : reader.GetFieldValue<byte[]>(31),
+                            CBlob = reader.IsDBNull(32) ? (byte[]? )null : reader.GetFieldValue<byte[]>(32),
+                            CMediumblob = reader.IsDBNull(33) ? (byte[]? )null : reader.GetFieldValue<byte[]>(33),
+                            CLongblob = reader.IsDBNull(34) ? (byte[]? )null : reader.GetFieldValue<byte[]>(34)
                         };
                     }
                 }
diff --git a/examples/MySqlConnectorExample/Utils.cs b/examples/MySqlConnectorExample/Utils.cs
index 58b738fd..4ade0262 100644
--- a/examples/MySqlConnectorExample/Utils.cs
+++ b/examples/MySqlConnectorExample/Utils.cs
@@ -12,7 +12,7 @@ public static class Utils
 {
     public class NullToStringConverter : DefaultTypeConverter
     {
-        public override string ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+        public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
         {
             return value == null ? @"\N" : base.ConvertToString(value, row, memberMapData);
         }
@@ -20,7 +20,7 @@ public override string ConvertToString(object? value, IWriterRow row, MemberMapD
 
     public class BoolToBitConverter : DefaultTypeConverter
     {
-        public override string ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+        public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
         {
             switch (value)
             {
@@ -34,6 +34,18 @@ public override string ConvertToString(object? value, IWriterRow row, MemberMapD
         }
     }
 
+    public class ByteArrayConverter : DefaultTypeConverter
+    {
+        public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
+        {
+            if (value == null)
+                return @"\N";
+            if (value is byte[] byteArray)
+                return System.Text.Encoding.UTF8.GetString(byteArray);
+            return base.ConvertToString(value, row, memberMapData);
+        }
+    }
+
     public static string TransformQueryForSliceArgs(string originalSql, int sliceSize, string paramName)
     {
         var paramArgs = Enumerable.Range(0, sliceSize).Select(i => $"@{paramName}Arg{i}").ToList();
diff --git a/examples/MySqlConnectorLegacyExample/QuerySql.cs b/examples/MySqlConnectorLegacyExample/QuerySql.cs
index eca598bf..e6599702 100644
--- a/examples/MySqlConnectorLegacyExample/QuerySql.cs
+++ b/examples/MySqlConnectorLegacyExample/QuerySql.cs
@@ -438,14 +438,13 @@ public async Task<List<GetAuthorsByBookNameRow>> GetAuthorsByBookName(GetAuthors
             }
         }
 
-        private const string InsertMysqlTypesSql = "INSERT INTO mysql_types (c_bit, c_tinyint, c_bool, c_boolean, c_year, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_decimal, c_dec, c_numeric, c_fixed, c_float, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_date, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob) VALUES ( @c_bit, @c_tinyint, @c_bool, @c_boolean, @c_year, @c_smallint, @c_mediumint, @c_int, @c_integer, @c_bigint, @c_decimal, @c_dec, @c_numeric, @c_fixed, @c_float, @c_double, @c_double_precision, @c_char, @c_nchar, @c_national_char, @c_varchar, @c_tinytext, @c_mediumtext, @c_text, @c_longtext, @c_date, @c_timestamp, @c_binary, @c_varbinary, @c_tinyblob, @c_blob, @c_mediumblob, @c_longblob ) "; 
+        private const string InsertMysqlTypesSql = "INSERT INTO mysql_types (c_bit, c_bool, c_boolean, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_decimal, c_dec, c_numeric, c_fixed, c_float, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob) VALUES ( @c_bit, @c_bool, @c_boolean, @c_tinyint, @c_smallint, @c_mediumint, @c_int, @c_integer, @c_bigint, @c_decimal, @c_dec, @c_numeric, @c_fixed, @c_float, @c_double, @c_double_precision, @c_char, @c_nchar, @c_national_char, @c_varchar, @c_tinytext, @c_mediumtext, @c_text, @c_longtext, @c_year, @c_date, @c_datetime, @c_timestamp, @c_binary, @c_varbinary, @c_tinyblob, @c_blob, @c_mediumblob, @c_longblob ) "; 
         public class InsertMysqlTypesArgs
         {
             public byte? CBit { get; set; }
-            public short? CTinyint { get; set; }
             public bool? CBool { get; set; }
             public bool? CBoolean { get; set; }
-            public short? CYear { get; set; }
+            public short? CTinyint { get; set; }
             public short? CSmallint { get; set; }
             public int? CMediumint { get; set; }
             public int? CInt { get; set; }
@@ -466,7 +465,9 @@ public class InsertMysqlTypesArgs
             public string CMediumtext { get; set; }
             public string CText { get; set; }
             public string CLongtext { get; set; }
+            public short? CYear { get; set; }
             public DateTime? CDate { get; set; }
+            public DateTime? CDatetime { get; set; }
             public DateTime? CTimestamp { get; set; }
             public byte[] CBinary { get; set; }
             public byte[] CVarbinary { get; set; }
@@ -483,10 +484,9 @@ public async Task InsertMysqlTypes(InsertMysqlTypesArgs args)
                 using (var command = new MySqlCommand(InsertMysqlTypesSql, connection))
                 {
                     command.Parameters.AddWithValue("@c_bit", args.CBit ?? (object)DBNull.Value);
-                    command.Parameters.AddWithValue("@c_tinyint", args.CTinyint ?? (object)DBNull.Value);
                     command.Parameters.AddWithValue("@c_bool", args.CBool ?? (object)DBNull.Value);
                     command.Parameters.AddWithValue("@c_boolean", args.CBoolean ?? (object)DBNull.Value);
-                    command.Parameters.AddWithValue("@c_year", args.CYear ?? (object)DBNull.Value);
+                    command.Parameters.AddWithValue("@c_tinyint", args.CTinyint ?? (object)DBNull.Value);
                     command.Parameters.AddWithValue("@c_smallint", args.CSmallint ?? (object)DBNull.Value);
                     command.Parameters.AddWithValue("@c_mediumint", args.CMediumint ?? (object)DBNull.Value);
                     command.Parameters.AddWithValue("@c_int", args.CInt ?? (object)DBNull.Value);
@@ -507,7 +507,9 @@ public async Task InsertMysqlTypes(InsertMysqlTypesArgs args)
                     command.Parameters.AddWithValue("@c_mediumtext", args.CMediumtext ?? (object)DBNull.Value);
                     command.Parameters.AddWithValue("@c_text", args.CText ?? (object)DBNull.Value);
                     command.Parameters.AddWithValue("@c_longtext", args.CLongtext ?? (object)DBNull.Value);
+                    command.Parameters.AddWithValue("@c_year", args.CYear ?? (object)DBNull.Value);
                     command.Parameters.AddWithValue("@c_date", args.CDate ?? (object)DBNull.Value);
+                    command.Parameters.AddWithValue("@c_datetime", args.CDatetime ?? (object)DBNull.Value);
                     command.Parameters.AddWithValue("@c_timestamp", args.CTimestamp ?? (object)DBNull.Value);
                     command.Parameters.AddWithValue("@c_binary", args.CBinary ?? (object)DBNull.Value);
                     command.Parameters.AddWithValue("@c_varbinary", args.CVarbinary ?? (object)DBNull.Value);
@@ -522,9 +524,9 @@ public async Task InsertMysqlTypes(InsertMysqlTypesArgs args)
 
         public class InsertMysqlTypesBatchArgs
         {
+            public byte? CBit { get; set; }
             public bool? CBool { get; set; }
             public bool? CBoolean { get; set; }
-            public byte? CBit { get; set; }
             public short? CTinyint { get; set; }
             public short? CSmallint { get; set; }
             public int? CMediumint { get; set; }
@@ -550,28 +552,36 @@ public class InsertMysqlTypesBatchArgs
             public DateTime? CDate { get; set; }
             public DateTime? CDatetime { get; set; }
             public DateTime? CTimestamp { get; set; }
+            public byte[] CBinary { get; set; }
+            public byte[] CVarbinary { get; set; }
+            public byte[] CTinyblob { get; set; }
+            public byte[] CBlob { get; set; }
+            public byte[] CMediumblob { get; set; }
+            public byte[] CLongblob { get; set; }
         };
         public async Task InsertMysqlTypesBatch(List<InsertMysqlTypesBatchArgs> args)
         {
             const string supportedDateTimeFormat = "yyyy-MM-dd H:mm:ss";
             var config = new CsvConfiguration(CultureInfo.CurrentCulture)
             {
-                Delimiter = ","
+                Delimiter = ",",
+                NewLine = "\n"
             };
             var nullConverterFn = new Utils.NullToStringConverter();
             using (var writer = new StreamWriter("input.csv", false, new UTF8Encoding(false)))
             using (var csvWriter = new CsvWriter(writer, config))
             {
-                var Options = new TypeConverterOptions
+                var options = new TypeConverterOptions
                 {
                     Formats = new[]
                     {
                         supportedDateTimeFormat
                     }
                 };
-                csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime>(Options);
-                csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime?>(Options);
+                csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime>(options);
+                csvWriter.Context.TypeConverterOptionsCache.AddOptions<DateTime?>(options);
                 csvWriter.Context.TypeConverterCache.AddConverter<bool?>(new Utils.BoolToBitConverter());
+                csvWriter.Context.TypeConverterCache.AddConverter<byte[]>(new Utils.ByteArrayConverter());
                 csvWriter.Context.TypeConverterCache.AddConverter<byte?>(nullConverterFn);
                 csvWriter.Context.TypeConverterCache.AddConverter<short?>(nullConverterFn);
                 csvWriter.Context.TypeConverterCache.AddConverter<int?>(nullConverterFn);
@@ -598,7 +608,7 @@ public async Task InsertMysqlTypesBatch(List<InsertMysqlTypesBatchArgs> args)
                     FieldQuotationOptional = true,
                     NumberOfLinesToSkip = 1
                 };
-                loader.Columns.AddRange(new List<string> { "c_bool", "c_boolean", "c_bit", "c_tinyint", "c_smallint", "c_mediumint", "c_int", "c_integer", "c_bigint", "c_float", "c_numeric", "c_decimal", "c_dec", "c_fixed", "c_double", "c_double_precision", "c_char", "c_nchar", "c_national_char", "c_varchar", "c_tinytext", "c_mediumtext", "c_text", "c_longtext", "c_year", "c_date", "c_datetime", "c_timestamp" });
+                loader.Columns.AddRange(new List<string> { "c_bit", "c_bool", "c_boolean", "c_tinyint", "c_smallint", "c_mediumint", "c_int", "c_integer", "c_bigint", "c_float", "c_numeric", "c_decimal", "c_dec", "c_fixed", "c_double", "c_double_precision", "c_char", "c_nchar", "c_national_char", "c_varchar", "c_tinytext", "c_mediumtext", "c_text", "c_longtext", "c_year", "c_date", "c_datetime", "c_timestamp", "c_binary", "c_varbinary", "c_tinyblob", "c_blob", "c_mediumblob", "c_longblob" });
                 await loader.LoadAsync();
                 await connection.CloseAsync();
             }
@@ -700,7 +710,7 @@ public async Task<GetMysqlTypesRow> GetMysqlTypes()
             return null;
         }
 
-        private const string GetMysqlTypesAggSql = "SELECT COUNT(1) AS cnt, c_bool, c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp FROM  mysql_types  GROUP  BY  c_bool , c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp LIMIT  1  ";  
+        private const string GetMysqlTypesAggSql = "SELECT COUNT(1) AS cnt, c_bool, c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint,  c_float , c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob FROM  mysql_types  GROUP  BY  c_bool , c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp, c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob LIMIT  1  ";  
         public class GetMysqlTypesAggRow
         {
             public long Cnt { get; set; }
@@ -732,6 +742,12 @@ public class GetMysqlTypesAggRow
             public DateTime? CDate { get; set; }
             public DateTime? CDatetime { get; set; }
             public DateTime? CTimestamp { get; set; }
+            public byte[] CBinary { get; set; }
+            public byte[] CVarbinary { get; set; }
+            public byte[] CTinyblob { get; set; }
+            public byte[] CBlob { get; set; }
+            public byte[] CMediumblob { get; set; }
+            public byte[] CLongblob { get; set; }
         };
         public async Task<GetMysqlTypesAggRow> GetMysqlTypesAgg()
         {
@@ -774,7 +790,13 @@ public async Task<GetMysqlTypesAggRow> GetMysqlTypesAgg()
                                 CYear = reader.IsDBNull(25) ? (short? )null : reader.GetInt16(25),
                                 CDate = reader.IsDBNull(26) ? (DateTime? )null : reader.GetDateTime(26),
                                 CDatetime = reader.IsDBNull(27) ? (DateTime? )null : reader.GetDateTime(27),
-                                CTimestamp = reader.IsDBNull(28) ? (DateTime? )null : reader.GetDateTime(28)
+                                CTimestamp = reader.IsDBNull(28) ? (DateTime? )null : reader.GetDateTime(28),
+                                CBinary = reader.IsDBNull(29) ? null : reader.GetFieldValue<byte[]>(29),
+                                CVarbinary = reader.IsDBNull(30) ? null : reader.GetFieldValue<byte[]>(30),
+                                CTinyblob = reader.IsDBNull(31) ? null : reader.GetFieldValue<byte[]>(31),
+                                CBlob = reader.IsDBNull(32) ? null : reader.GetFieldValue<byte[]>(32),
+                                CMediumblob = reader.IsDBNull(33) ? null : reader.GetFieldValue<byte[]>(33),
+                                CLongblob = reader.IsDBNull(34) ? null : reader.GetFieldValue<byte[]>(34)
                             };
                         }
                     }
diff --git a/examples/MySqlConnectorLegacyExample/Utils.cs b/examples/MySqlConnectorLegacyExample/Utils.cs
index 44aab210..b32581a7 100644
--- a/examples/MySqlConnectorLegacyExample/Utils.cs
+++ b/examples/MySqlConnectorLegacyExample/Utils.cs
@@ -35,6 +35,18 @@ public override string ConvertToString(object value, IWriterRow row, MemberMapDa
             }
         }
 
+        public class ByteArrayConverter : DefaultTypeConverter
+        {
+            public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
+            {
+                if (value == null)
+                    return @"\N";
+                if (value is byte[] byteArray)
+                    return System.Text.Encoding.UTF8.GetString(byteArray);
+                return base.ConvertToString(value, row, memberMapData);
+            }
+        }
+
         public static string TransformQueryForSliceArgs(string originalSql, int sliceSize, string paramName)
         {
             var paramArgs = Enumerable.Range(0, sliceSize).Select(i => $"@{paramName}Arg{i}").ToList();
diff --git a/examples/NpgsqlExample/QuerySql.cs b/examples/NpgsqlExample/QuerySql.cs
index 670ece46..e07abbd3 100644
--- a/examples/NpgsqlExample/QuerySql.cs
+++ b/examples/NpgsqlExample/QuerySql.cs
@@ -426,7 +426,7 @@ public async Task InsertPostgresTypesBatch(List<InsertPostgresTypesBatchArgs> ar
                         return new GetPostgresTypesRow
                         {
                             CBoolean = reader.IsDBNull(0) ? (bool? )null : reader.GetBoolean(0),
-                            CBit = reader.IsDBNull(1) ? null : reader.GetFieldValue<byte[]>(1),
+                            CBit = reader.IsDBNull(1) ? (byte[]? )null : reader.GetFieldValue<byte[]>(1),
                             CSmallint = reader.IsDBNull(2) ? (short? )null : reader.GetInt16(2),
                             CInteger = reader.IsDBNull(3) ? (int? )null : reader.GetInt32(3),
                             CBigint = reader.IsDBNull(4) ? (long? )null : reader.GetInt64(4),
@@ -440,7 +440,7 @@ public async Task InsertPostgresTypesBatch(List<InsertPostgresTypesBatchArgs> ar
                             CChar = reader.IsDBNull(12) ? (string? )null : reader.GetString(12),
                             CVarchar = reader.IsDBNull(13) ? (string? )null : reader.GetString(13),
                             CCharacterVarying = reader.IsDBNull(14) ? (string? )null : reader.GetString(14),
-                            CBytea = reader.IsDBNull(15) ? null : reader.GetFieldValue<byte[]>(15),
+                            CBytea = reader.IsDBNull(15) ? (byte[]? )null : reader.GetFieldValue<byte[]>(15),
                             CText = reader.IsDBNull(16) ? (string? )null : reader.GetString(16),
                             CJson = reader.IsDBNull(17) ? (object? )null : reader.GetString(17),
                             CTextArray = reader.IsDBNull(18) ? null : reader.GetFieldValue<string[]>(18),
@@ -483,7 +483,7 @@ public async Task InsertPostgresTypesBatch(List<InsertPostgresTypesBatchArgs> ar
                             CVarchar = reader.IsDBNull(12) ? (string? )null : reader.GetString(12),
                             CCharacterVarying = reader.IsDBNull(13) ? (string? )null : reader.GetString(13),
                             CText = reader.IsDBNull(14) ? (string? )null : reader.GetString(14),
-                            CBytea = reader.IsDBNull(15) ? null : reader.GetFieldValue<byte[]>(15)
+                            CBytea = reader.IsDBNull(15) ? (byte[]? )null : reader.GetFieldValue<byte[]>(15)
                         };
                     }
                 }
diff --git a/examples/SqliteExample/QuerySql.cs b/examples/SqliteExample/QuerySql.cs
index e9ed70f0..16ad9dbf 100644
--- a/examples/SqliteExample/QuerySql.cs
+++ b/examples/SqliteExample/QuerySql.cs
@@ -409,7 +409,7 @@ public async Task InsertSqliteTypesBatch(List<InsertSqliteTypesBatchArgs> args)
                             CInteger = reader.IsDBNull(0) ? (int? )null : reader.GetInt32(0),
                             CReal = reader.IsDBNull(1) ? (decimal? )null : reader.GetDecimal(1),
                             CText = reader.IsDBNull(2) ? (string? )null : reader.GetString(2),
-                            CBlob = reader.IsDBNull(3) ? null : reader.GetFieldValue<byte[]>(3)
+                            CBlob = reader.IsDBNull(3) ? (byte[]? )null : reader.GetFieldValue<byte[]>(3)
                         };
                     }
                 }
@@ -438,7 +438,7 @@ public async Task InsertSqliteTypesBatch(List<InsertSqliteTypesBatchArgs> args)
                             CInteger = reader.IsDBNull(1) ? (int? )null : reader.GetInt32(1),
                             CReal = reader.IsDBNull(2) ? (decimal? )null : reader.GetDecimal(2),
                             CText = reader.IsDBNull(3) ? (string? )null : reader.GetString(3),
-                            CBlob = reader.IsDBNull(4) ? null : reader.GetFieldValue<byte[]>(4)
+                            CBlob = reader.IsDBNull(4) ? (byte[]? )null : reader.GetFieldValue<byte[]>(4)
                         };
                     }
                 }
diff --git a/examples/config/mysql/query.sql b/examples/config/mysql/query.sql
index 81d2b324..99104fec 100644
--- a/examples/config/mysql/query.sql
+++ b/examples/config/mysql/query.sql
@@ -53,27 +53,37 @@ WHERE books.name = ?;
 
 -- name: InsertMysqlTypes :exec
 INSERT INTO mysql_types 
-(c_bit, c_tinyint, c_bool, c_boolean, c_year, c_smallint, c_mediumint, c_int, c_integer, c_bigint, 
+(c_bit, c_bool, c_boolean, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, 
  c_decimal, c_dec, c_numeric, c_fixed, c_float, c_double, c_double_precision, 
- c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_date, c_timestamp, 
+ c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext,
+ c_year, c_date, c_datetime, c_timestamp, 
  c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob) 
-VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
+VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
 
 -- name: InsertMysqlTypesBatch :copyfrom
 INSERT INTO mysql_types 
-(c_bool, c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, 
+(c_bit, c_bool, c_boolean, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, 
  c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, 
  c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, 
- c_year, c_date, c_datetime, c_timestamp) 
-VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
+ c_year, c_date, c_datetime, c_timestamp,
+ c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob) 
+VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
 
 -- name: GetMysqlTypes :one
 SELECT * FROM mysql_types LIMIT 1;
 
 -- name: GetMysqlTypesAgg :one
-SELECT COUNT(1) AS cnt, c_bool, c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp
+SELECT COUNT(1) AS cnt, c_bool, c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, 
+       c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, 
+       c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, 
+       c_year, c_date, c_datetime, c_timestamp, 
+       c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob
 FROM mysql_types
-GROUP BY c_bool, c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, c_year, c_date, c_datetime, c_timestamp
+GROUP BY c_bool, c_boolean, c_bit, c_tinyint, c_smallint, c_mediumint, c_int, c_integer, c_bigint, 
+         c_float, c_numeric, c_decimal, c_dec, c_fixed, c_double, c_double_precision, 
+         c_char, c_nchar, c_national_char, c_varchar, c_tinytext, c_mediumtext, c_text, c_longtext, 
+         c_year, c_date, c_datetime, c_timestamp, 
+         c_binary, c_varbinary, c_tinyblob, c_blob, c_mediumblob, c_longblob
 LIMIT 1;
 
 -- name: TruncateMysqlTypes :exec

From 044ed3b9eb01dab37513ca1a5d79d7c4a185685f Mon Sep 17 00:00:00 2001
From: Ilan Uzan <ilan9uzan@gmail.com>
Date: Sat, 15 Mar 2025 18:20:10 +0100
Subject: [PATCH 2/4] uncollapse data types support doc by default

---
 docs/04_Postgres.md | 2 +-
 docs/05_MySql.md    | 2 +-
 docs/06_Sqlite.md   | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/docs/04_Postgres.md b/docs/04_Postgres.md
index d71f6d89..3f720a83 100644
--- a/docs/04_Postgres.md
+++ b/docs/04_Postgres.md
@@ -12,7 +12,7 @@ data type that can have a unique constraint.
 Implemented via the `COPY FROM` command which can load binary data directly from `stdin`.
 </details>
 
-<details>
+<details open>
 <summary>Supported Data Types</summary>
 
 Since in batch insert the data is not validated by the SQL itself but written in a binary format, 
diff --git a/docs/05_MySql.md b/docs/05_MySql.md
index 2bdc863a..9167ceaf 100644
--- a/docs/05_MySql.md
+++ b/docs/05_MySql.md
@@ -34,7 +34,7 @@ Requires us to first save the input batch as a CSV, and then load it via the dri
 
 </details>
 
-<details>
+<details open>
 <summary>Supported Data Types</summary>
 
 Since in batch insert the data is not validated by the SQL itself but written and read from a CSV,
diff --git a/docs/06_Sqlite.md b/docs/06_Sqlite.md
index c6e5c181..1a63c783 100644
--- a/docs/06_Sqlite.md
+++ b/docs/06_Sqlite.md
@@ -25,7 +25,7 @@ INSERT INTO tab1 (field1, field2) VALUES
 
 </details>
 
-<details>
+<details open>
 <summary>Supported Data Types</summary>
 
 | DB Type | Supported? |

From 45c3c95db7edc668ea27e39f90fbb938e248a871 Mon Sep 17 00:00:00 2001
From: Ilan Uzan <ilan9uzan@gmail.com>
Date: Sat, 15 Mar 2025 20:34:21 +0100
Subject: [PATCH 3/4] specify line terminator as unix line endings when loading
 CSV to mysql

---
 Drivers/MySqlConnectorDriver.cs                        | 3 ++-
 examples/MySqlConnectorDapperExample/QuerySql.cs       | 3 ++-
 examples/MySqlConnectorDapperLegacyExample/QuerySql.cs | 3 ++-
 examples/MySqlConnectorExample/QuerySql.cs             | 3 ++-
 examples/MySqlConnectorLegacyExample/QuerySql.cs       | 3 ++-
 5 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/Drivers/MySqlConnectorDriver.cs b/Drivers/MySqlConnectorDriver.cs
index 056d71e1..ad2eb2be 100644
--- a/Drivers/MySqlConnectorDriver.cs
+++ b/Drivers/MySqlConnectorDriver.cs
@@ -219,7 +219,8 @@ public string GetCopyFromImpl(Query query, string queryTextConstant)
                          FieldTerminator = "{{csvDelimiter}}",
                          FieldQuotationCharacter = '"',
                          FieldQuotationOptional = true,
-                         NumberOfLinesToSkip = 1
+                         NumberOfLinesToSkip = 1,
+                         LineTerminator = "\n"
                      };
                      {{loaderVar}}.Columns.AddRange(new List<string> { {{loaderColumns}} });
                      await {{loaderVar}}.LoadAsync();
diff --git a/examples/MySqlConnectorDapperExample/QuerySql.cs b/examples/MySqlConnectorDapperExample/QuerySql.cs
index 39dccce0..c1c7fa0d 100644
--- a/examples/MySqlConnectorDapperExample/QuerySql.cs
+++ b/examples/MySqlConnectorDapperExample/QuerySql.cs
@@ -508,7 +508,8 @@ public async Task InsertMysqlTypesBatch(List<InsertMysqlTypesBatchArgs> args)
                 FieldTerminator = ",",
                 FieldQuotationCharacter = '"',
                 FieldQuotationOptional = true,
-                NumberOfLinesToSkip = 1
+                NumberOfLinesToSkip = 1,
+                LineTerminator = "\n"
             };
             loader.Columns.AddRange(new List<string> { "c_bit", "c_bool", "c_boolean", "c_tinyint", "c_smallint", "c_mediumint", "c_int", "c_integer", "c_bigint", "c_float", "c_numeric", "c_decimal", "c_dec", "c_fixed", "c_double", "c_double_precision", "c_char", "c_nchar", "c_national_char", "c_varchar", "c_tinytext", "c_mediumtext", "c_text", "c_longtext", "c_year", "c_date", "c_datetime", "c_timestamp", "c_binary", "c_varbinary", "c_tinyblob", "c_blob", "c_mediumblob", "c_longblob" });
             await loader.LoadAsync();
diff --git a/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs b/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs
index 2b6565b8..432816f7 100644
--- a/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs
+++ b/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs
@@ -509,7 +509,8 @@ public async Task InsertMysqlTypesBatch(List<InsertMysqlTypesBatchArgs> args)
                     FieldTerminator = ",",
                     FieldQuotationCharacter = '"',
                     FieldQuotationOptional = true,
-                    NumberOfLinesToSkip = 1
+                    NumberOfLinesToSkip = 1,
+                    LineTerminator = "\n"
                 };
                 loader.Columns.AddRange(new List<string> { "c_bit", "c_bool", "c_boolean", "c_tinyint", "c_smallint", "c_mediumint", "c_int", "c_integer", "c_bigint", "c_float", "c_numeric", "c_decimal", "c_dec", "c_fixed", "c_double", "c_double_precision", "c_char", "c_nchar", "c_national_char", "c_varchar", "c_tinytext", "c_mediumtext", "c_text", "c_longtext", "c_year", "c_date", "c_datetime", "c_timestamp", "c_binary", "c_varbinary", "c_tinyblob", "c_blob", "c_mediumblob", "c_longblob" });
                 await loader.LoadAsync();
diff --git a/examples/MySqlConnectorExample/QuerySql.cs b/examples/MySqlConnectorExample/QuerySql.cs
index 849c359e..f0956e00 100644
--- a/examples/MySqlConnectorExample/QuerySql.cs
+++ b/examples/MySqlConnectorExample/QuerySql.cs
@@ -451,7 +451,8 @@ public async Task InsertMysqlTypesBatch(List<InsertMysqlTypesBatchArgs> args)
                 FieldTerminator = ",",
                 FieldQuotationCharacter = '"',
                 FieldQuotationOptional = true,
-                NumberOfLinesToSkip = 1
+                NumberOfLinesToSkip = 1,
+                LineTerminator = "\n"
             };
             loader.Columns.AddRange(new List<string> { "c_bit", "c_bool", "c_boolean", "c_tinyint", "c_smallint", "c_mediumint", "c_int", "c_integer", "c_bigint", "c_float", "c_numeric", "c_decimal", "c_dec", "c_fixed", "c_double", "c_double_precision", "c_char", "c_nchar", "c_national_char", "c_varchar", "c_tinytext", "c_mediumtext", "c_text", "c_longtext", "c_year", "c_date", "c_datetime", "c_timestamp", "c_binary", "c_varbinary", "c_tinyblob", "c_blob", "c_mediumblob", "c_longblob" });
             await loader.LoadAsync();
diff --git a/examples/MySqlConnectorLegacyExample/QuerySql.cs b/examples/MySqlConnectorLegacyExample/QuerySql.cs
index e6599702..3cafb3e6 100644
--- a/examples/MySqlConnectorLegacyExample/QuerySql.cs
+++ b/examples/MySqlConnectorLegacyExample/QuerySql.cs
@@ -606,7 +606,8 @@ public async Task InsertMysqlTypesBatch(List<InsertMysqlTypesBatchArgs> args)
                     FieldTerminator = ",",
                     FieldQuotationCharacter = '"',
                     FieldQuotationOptional = true,
-                    NumberOfLinesToSkip = 1
+                    NumberOfLinesToSkip = 1,
+                    LineTerminator = "\n"
                 };
                 loader.Columns.AddRange(new List<string> { "c_bit", "c_bool", "c_boolean", "c_tinyint", "c_smallint", "c_mediumint", "c_int", "c_integer", "c_bigint", "c_float", "c_numeric", "c_decimal", "c_dec", "c_fixed", "c_double", "c_double_precision", "c_char", "c_nchar", "c_national_char", "c_varchar", "c_tinytext", "c_mediumtext", "c_text", "c_longtext", "c_year", "c_date", "c_datetime", "c_timestamp", "c_binary", "c_varbinary", "c_tinyblob", "c_blob", "c_mediumblob", "c_longblob" });
                 await loader.LoadAsync();

From 968d41567f9f57e1de8edc4f579e86576dffc32a Mon Sep 17 00:00:00 2001
From: Ilan Uzan <ilan9uzan@gmail.com>
Date: Sat, 15 Mar 2025 20:37:55 +0100
Subject: [PATCH 4/4] add TODO

---
 CodeGenerator/Generators/UtilsGen.cs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CodeGenerator/Generators/UtilsGen.cs b/CodeGenerator/Generators/UtilsGen.cs
index e6ab65e0..0ad3451e 100644
--- a/CodeGenerator/Generators/UtilsGen.cs
+++ b/CodeGenerator/Generators/UtilsGen.cs
@@ -53,6 +53,7 @@ private UsingDirectiveSyntax[] GetUsingDirectives()
 
     private MemberDeclarationSyntax GetUtilsClass()
     {
+        // TODO move driver specific logic to DB driver interface
         var optionalTransformQueryForSqliteBatch = dbDriver.Options.DriverName is DriverName.Sqlite
             ? """
               private static readonly Regex ValuesRegex = new Regex(@"VALUES\s*\((?<params>[^)]*)\)", RegexOptions.IgnoreCase);