diff --git a/CodeGenerator/Generators/UtilsGen.cs b/CodeGenerator/Generators/UtilsGen.cs index c0e5196c..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*\((?[^)]*)\)", RegexOptions.IgnoreCase); @@ -80,7 +81,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 +90,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 +104,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 Tables { get; } - private HashSet NullableTypesInDotnetCore { get; } = ["string", "object"]; + private HashSet NullableTypesInDotnetCore { get; } = ["string", "object", "byte[]"]; // TODO add arrays in here in a non hard-coded manner private HashSet NullableTypes { get; } = ["bool", "byte", "short", "int", "long", "float", "double", "decimal", "DateTime"]; diff --git a/Drivers/MySqlConnectorDriver.cs b/Drivers/MySqlConnectorDriver.cs index 86e67673..ad2eb2be 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({{Variable.Options}}); - {{csvWriterVar}}.Context.TypeConverterOptionsCache.AddOptions({{Variable.Options}}); + var {{optionsVar}} = new TypeConverterOptions { Formats = new[] { supportedDateTimeFormat } }; + {{csvWriterVar}}.Context.TypeConverterOptionsCache.AddOptions({{optionsVar}}); + {{csvWriterVar}}.Context.TypeConverterOptionsCache.AddOptions({{optionsVar}}); {{csvWriterVar}}.Context.TypeConverterCache.AddConverter(new Utils.BoolToBitConverter()); + {{csvWriterVar}}.Context.TypeConverterCache.AddConverter<{{AddNullableSuffixIfNeeded("byte[]", false)}}>(new Utils.ByteArrayConverter()); {{csvWriterVar}}.Context.TypeConverterCache.AddConverter({{nullConverterFn}}); {{csvWriterVar}}.Context.TypeConverterCache.AddConverter({{nullConverterFn}}); {{csvWriterVar}}.Context.TypeConverterCache.AddConverter({{nullConverterFn}}); @@ -212,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 { {{loaderColumns}} }); await {{loaderVar}}.LoadAsync(); 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`. -
+
Supported Data Types 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 25d801a1..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
-
+
Supported Data Types Since in batch insert the data is not validated by the SQL itself but written and read from a CSV, @@ -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/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
-
+
Supported Data Types | DB Type | Supported? | 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..c1c7fa0d 100644 --- a/examples/MySqlConnectorDapperExample/QuerySql.cs +++ b/examples/MySqlConnectorDapperExample/QuerySql.cs @@ -343,14 +343,13 @@ public async Task> 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(); 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 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(Options); - csvWriter.Context.TypeConverterOptionsCache.AddOptions(Options); + csvWriter.Context.TypeConverterOptionsCache.AddOptions(options); + csvWriter.Context.TypeConverterOptionsCache.AddOptions(options); csvWriter.Context.TypeConverterCache.AddConverter(new Utils.BoolToBitConverter()); + csvWriter.Context.TypeConverterCache.AddConverter(new Utils.ByteArrayConverter()); csvWriter.Context.TypeConverterCache.AddConverter(nullConverterFn); csvWriter.Context.TypeConverterCache.AddConverter(nullConverterFn); csvWriter.Context.TypeConverterCache.AddConverter(nullConverterFn); @@ -498,9 +508,10 @@ public async Task InsertMysqlTypesBatch(List args) FieldTerminator = ",", FieldQuotationCharacter = '"', FieldQuotationOptional = true, - NumberOfLinesToSkip = 1 + NumberOfLinesToSkip = 1, + LineTerminator = "\n" }; - loader.Columns.AddRange(new List { "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 { "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 +565,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 +597,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 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..432816f7 100644 --- a/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs +++ b/examples/MySqlConnectorDapperLegacyExample/QuerySql.cs @@ -344,14 +344,13 @@ public async Task> 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(); 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 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(Options); - csvWriter.Context.TypeConverterOptionsCache.AddOptions(Options); + csvWriter.Context.TypeConverterOptionsCache.AddOptions(options); + csvWriter.Context.TypeConverterOptionsCache.AddOptions(options); csvWriter.Context.TypeConverterCache.AddConverter(new Utils.BoolToBitConverter()); + csvWriter.Context.TypeConverterCache.AddConverter(new Utils.ByteArrayConverter()); csvWriter.Context.TypeConverterCache.AddConverter(nullConverterFn); csvWriter.Context.TypeConverterCache.AddConverter(nullConverterFn); csvWriter.Context.TypeConverterCache.AddConverter(nullConverterFn); @@ -499,9 +509,10 @@ public async Task InsertMysqlTypesBatch(List args) FieldTerminator = ",", FieldQuotationCharacter = '"', FieldQuotationOptional = true, - NumberOfLinesToSkip = 1 + NumberOfLinesToSkip = 1, + LineTerminator = "\n" }; - loader.Columns.AddRange(new List { "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 { "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 +566,7 @@ public async Task 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 +598,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 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..f0956e00 100644 --- a/examples/MySqlConnectorExample/QuerySql.cs +++ b/examples/MySqlConnectorExample/QuerySql.cs @@ -355,8 +355,8 @@ public async Task> 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 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(Options); - csvWriter.Context.TypeConverterOptionsCache.AddOptions(Options); + csvWriter.Context.TypeConverterOptionsCache.AddOptions(options); + csvWriter.Context.TypeConverterOptionsCache.AddOptions(options); csvWriter.Context.TypeConverterCache.AddConverter(new Utils.BoolToBitConverter()); + csvWriter.Context.TypeConverterCache.AddConverter(new Utils.ByteArrayConverter()); csvWriter.Context.TypeConverterCache.AddConverter(nullConverterFn); csvWriter.Context.TypeConverterCache.AddConverter(nullConverterFn); csvWriter.Context.TypeConverterCache.AddConverter(nullConverterFn); @@ -448,9 +451,10 @@ public async Task InsertMysqlTypesBatch(List args) FieldTerminator = ",", FieldQuotationCharacter = '"', FieldQuotationOptional = true, - NumberOfLinesToSkip = 1 + NumberOfLinesToSkip = 1, + LineTerminator = "\n" }; - loader.Columns.AddRange(new List { "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 { "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 +504,12 @@ public async Task InsertMysqlTypesBatch(List 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(28), - CBinary = reader.IsDBNull(29) ? null : reader.GetFieldValue(29), - CVarbinary = reader.IsDBNull(30) ? null : reader.GetFieldValue(30), - CTinyblob = reader.IsDBNull(31) ? null : reader.GetFieldValue(31), - CBlob = reader.IsDBNull(32) ? null : reader.GetFieldValue(32), - CMediumblob = reader.IsDBNull(33) ? null : reader.GetFieldValue(33), - CLongblob = reader.IsDBNull(34) ? null : reader.GetFieldValue(34) + CBinary = reader.IsDBNull(29) ? (byte[]? )null : reader.GetFieldValue(29), + CVarbinary = reader.IsDBNull(30) ? (byte[]? )null : reader.GetFieldValue(30), + CTinyblob = reader.IsDBNull(31) ? (byte[]? )null : reader.GetFieldValue(31), + CBlob = reader.IsDBNull(32) ? (byte[]? )null : reader.GetFieldValue(32), + CMediumblob = reader.IsDBNull(33) ? (byte[]? )null : reader.GetFieldValue(33), + CLongblob = reader.IsDBNull(34) ? (byte[]? )null : reader.GetFieldValue(34) }; } } @@ -515,8 +519,8 @@ public async Task InsertMysqlTypesBatch(List 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 GetMysqlTypesAgg() { using (var connection = new MySqlConnection(ConnectionString)) @@ -558,7 +562,13 @@ public async Task InsertMysqlTypesBatch(List 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(29), + CVarbinary = reader.IsDBNull(30) ? (byte[]? )null : reader.GetFieldValue(30), + CTinyblob = reader.IsDBNull(31) ? (byte[]? )null : reader.GetFieldValue(31), + CBlob = reader.IsDBNull(32) ? (byte[]? )null : reader.GetFieldValue(32), + CMediumblob = reader.IsDBNull(33) ? (byte[]? )null : reader.GetFieldValue(33), + CLongblob = reader.IsDBNull(34) ? (byte[]? )null : reader.GetFieldValue(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..3cafb3e6 100644 --- a/examples/MySqlConnectorLegacyExample/QuerySql.cs +++ b/examples/MySqlConnectorLegacyExample/QuerySql.cs @@ -438,14 +438,13 @@ public async Task> 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 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(Options); - csvWriter.Context.TypeConverterOptionsCache.AddOptions(Options); + csvWriter.Context.TypeConverterOptionsCache.AddOptions(options); + csvWriter.Context.TypeConverterOptionsCache.AddOptions(options); csvWriter.Context.TypeConverterCache.AddConverter(new Utils.BoolToBitConverter()); + csvWriter.Context.TypeConverterCache.AddConverter(new Utils.ByteArrayConverter()); csvWriter.Context.TypeConverterCache.AddConverter(nullConverterFn); csvWriter.Context.TypeConverterCache.AddConverter(nullConverterFn); csvWriter.Context.TypeConverterCache.AddConverter(nullConverterFn); @@ -596,9 +606,10 @@ public async Task InsertMysqlTypesBatch(List args) FieldTerminator = ",", FieldQuotationCharacter = '"', FieldQuotationOptional = true, - NumberOfLinesToSkip = 1 + NumberOfLinesToSkip = 1, + LineTerminator = "\n" }; - loader.Columns.AddRange(new List { "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 { "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 +711,7 @@ public async Task 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 +743,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 GetMysqlTypesAgg() { @@ -774,7 +791,13 @@ public async Task 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(29), + CVarbinary = reader.IsDBNull(30) ? null : reader.GetFieldValue(30), + CTinyblob = reader.IsDBNull(31) ? null : reader.GetFieldValue(31), + CBlob = reader.IsDBNull(32) ? null : reader.GetFieldValue(32), + CMediumblob = reader.IsDBNull(33) ? null : reader.GetFieldValue(33), + CLongblob = reader.IsDBNull(34) ? null : reader.GetFieldValue(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 ar return new GetPostgresTypesRow { CBoolean = reader.IsDBNull(0) ? (bool? )null : reader.GetBoolean(0), - CBit = reader.IsDBNull(1) ? null : reader.GetFieldValue(1), + CBit = reader.IsDBNull(1) ? (byte[]? )null : reader.GetFieldValue(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 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(15), + CBytea = reader.IsDBNull(15) ? (byte[]? )null : reader.GetFieldValue(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(18), @@ -483,7 +483,7 @@ public async Task InsertPostgresTypesBatch(List 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(15) + CBytea = reader.IsDBNull(15) ? (byte[]? )null : reader.GetFieldValue(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 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(3) + CBlob = reader.IsDBNull(3) ? (byte[]? )null : reader.GetFieldValue(3) }; } } @@ -438,7 +438,7 @@ public async Task InsertSqliteTypesBatch(List 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(4) + CBlob = reader.IsDBNull(4) ? (byte[]? )null : reader.GetFieldValue(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