From 0ac564f801417689b1c0ed598e22d886b3d569a8 Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Tue, 14 Apr 2020 23:38:27 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E5=A2=9E=E5=8A=A0=20FreeSql.Provider.Damen?= =?UTF-8?q?g=20=E5=9F=BA=E4=BA=8E=20DmProvider=20Ado.net=20=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=E8=BE=BE=E6=A2=A6=E6=95=B0=E6=8D=AE=E5=BA=93=EF=BC=9B?= =?UTF-8?q?#155?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Examples/orm_vs/Program.cs | 15 + Examples/orm_vs/orm_vs.csproj | 1 + Examples/orm_vs_net40/Program.cs | 16 + Examples/orm_vs_net40/orm_vs_net40.csproj | 4 + FreeSql.DbContext/FreeSql.DbContext.xml | 16 - .../Dameng/Curd/DamengDeleteTest.cs | 106 + .../Dameng/Curd/DamengInsertTest.cs | 278 +++ .../Dameng/Curd/DamengSelectTest.cs | 1788 +++++++++++++++++ .../Dameng/Curd/DamengUpdateTest.cs | 173 ++ .../Dameng/DamengAdo/DamengAdoTest.cs | 66 + .../FreeSql.Tests/Dameng/DamengAopTest.cs | 40 + .../Dameng/DamengCodeFirstTest.cs | 352 ++++ .../FreeSql.Tests/Dameng/DamengDbFirstTest.cs | 25 + .../Dameng/DamengExpression/ConvertTest.cs | 169 ++ .../Dameng/DamengExpression/DateTimeTest.cs | 706 +++++++ .../Dameng/DamengExpression/MathTest.cs | 156 ++ .../Dameng/DamengExpression/OtherTest.cs | 165 ++ .../Dameng/DamengExpression/StringTest.cs | 726 +++++++ .../Dameng/DamengExpression/TimeSpanTest.cs | 293 +++ .../Dameng/MapType/BoolNullableTest.cs | 1571 +++++++++++++++ .../FreeSql.Tests/Dameng/MapType/BoolTest.cs | 1105 ++++++++++ .../Dameng/MapType/DateTimeOffSetTest.cs | 54 + .../FreeSql.Tests/Dameng/MapType/EnumTest.cs | 261 +++ .../Dameng/MapType/ToStringTest.cs | 570 ++++++ .../FreeSql.Tests/FreeSql.Tests.csproj | 7 + FreeSql.Tests/FreeSql.Tests/g.cs | 15 + FreeSql.sln | 15 + FreeSql/DataType.cs | 7 +- FreeSql/FreeSql.xml | 7 +- FreeSql/FreeSqlBuilder.cs | 5 + .../SelectProvider/Select0Provider.cs | 5 +- FreeSql/Internal/UtilsExpressionTree.cs | 35 +- .../Curd/DamengDelete.cs | 31 + .../Curd/DamengInsert.cs | 222 ++ .../Curd/DamengSelect.cs | 184 ++ .../Curd/DamengUpdate.cs | 77 + .../DamengAdo/DamengAdo.cs | 75 + .../DamengAdo/DamengConnectionPool.cs | 253 +++ .../DamengCodeFirst.cs | 469 +++++ .../FreeSql.Provider.Dameng/DamengDbFirst.cs | 559 ++++++ .../DamengExpression.cs | 469 +++++ .../DamengExtensions.cs | 12 + .../FreeSql.Provider.Dameng/DamengProvider.cs | 61 + .../FreeSql.Provider.Dameng/DamengUtils.cs | 102 + .../FreeSql.Provider.Dameng.csproj | 50 + .../lib/DmProvider/DmProvider.1.1.0.nuspec | 21 + .../lib/DmProvider/net20/DmProvider.dll | Bin 0 -> 379904 bytes .../net20/en/DmProvider.resources.dll | Bin 0 -> 20480 bytes .../net20/zh-CN/DmProvider.resources.dll | Bin 0 -> 21504 bytes .../DmProvider/netstandard2.0/DmProvider.dll | Bin 0 -> 384512 bytes .../en/DmProvider.resources.dll | Bin 0 -> 20480 bytes .../zh-CN/DmProvider.resources.dll | Bin 0 -> 21504 bytes .../Dameng/Curd/OdbcDamengSelect.cs | 54 +- .../OdbcDamengAdo/OdbcDamengConnectionPool.cs | 4 +- .../Dameng/OdbcDamengCodeFirst.cs | 6 +- .../Dameng/OdbcDamengDbFirst.cs | 4 +- .../Dameng/OdbcDamengProvider.cs | 6 - .../Dameng/OdbcDamengUtils.cs | 2 +- 58 files changed, 11337 insertions(+), 76 deletions(-) create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengDeleteTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengInsertTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengUpdateTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/DamengAdo/DamengAdoTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/DamengAopTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/DamengCodeFirstTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/DamengDbFirstTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/ConvertTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/DateTimeTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/MathTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/OtherTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/StringTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/TimeSpanTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/MapType/BoolNullableTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/MapType/BoolTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/MapType/DateTimeOffSetTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/MapType/EnumTest.cs create mode 100644 FreeSql.Tests/FreeSql.Tests/Dameng/MapType/ToStringTest.cs create mode 100644 Providers/FreeSql.Provider.Dameng/Curd/DamengDelete.cs create mode 100644 Providers/FreeSql.Provider.Dameng/Curd/DamengInsert.cs create mode 100644 Providers/FreeSql.Provider.Dameng/Curd/DamengSelect.cs create mode 100644 Providers/FreeSql.Provider.Dameng/Curd/DamengUpdate.cs create mode 100644 Providers/FreeSql.Provider.Dameng/DamengAdo/DamengAdo.cs create mode 100644 Providers/FreeSql.Provider.Dameng/DamengAdo/DamengConnectionPool.cs create mode 100644 Providers/FreeSql.Provider.Dameng/DamengCodeFirst.cs create mode 100644 Providers/FreeSql.Provider.Dameng/DamengDbFirst.cs create mode 100644 Providers/FreeSql.Provider.Dameng/DamengExpression.cs create mode 100644 Providers/FreeSql.Provider.Dameng/DamengExtensions.cs create mode 100644 Providers/FreeSql.Provider.Dameng/DamengProvider.cs create mode 100644 Providers/FreeSql.Provider.Dameng/DamengUtils.cs create mode 100644 Providers/FreeSql.Provider.Dameng/FreeSql.Provider.Dameng.csproj create mode 100644 Providers/FreeSql.Provider.Dameng/lib/DmProvider/DmProvider.1.1.0.nuspec create mode 100644 Providers/FreeSql.Provider.Dameng/lib/DmProvider/net20/DmProvider.dll create mode 100644 Providers/FreeSql.Provider.Dameng/lib/DmProvider/net20/en/DmProvider.resources.dll create mode 100644 Providers/FreeSql.Provider.Dameng/lib/DmProvider/net20/zh-CN/DmProvider.resources.dll create mode 100644 Providers/FreeSql.Provider.Dameng/lib/DmProvider/netstandard2.0/DmProvider.dll create mode 100644 Providers/FreeSql.Provider.Dameng/lib/DmProvider/netstandard2.0/en/DmProvider.resources.dll create mode 100644 Providers/FreeSql.Provider.Dameng/lib/DmProvider/netstandard2.0/zh-CN/DmProvider.resources.dll diff --git a/Examples/orm_vs/Program.cs b/Examples/orm_vs/Program.cs index ee8470db..3fdc979b 100644 --- a/Examples/orm_vs/Program.cs +++ b/Examples/orm_vs/Program.cs @@ -46,8 +46,23 @@ namespace orm_vs } } + static Lazy damengLazy = new Lazy(() => new FreeSql.FreeSqlBuilder() + .UseConnectionString(FreeSql.DataType.Dameng, "server=127.0.0.1;port=5236;user id=2user;password=123456789;database=2user") + //.UseConnectionFactory(FreeSql.DataType.Dameng, () => new Dm.DmConnection("data source=127.0.0.1:5236;user id=2user;password=123456789;Pooling=true;Max Pool Size=2")) + .UseAutoSyncStructure(true) + .UseNameConvert(FreeSql.Internal.NameConvertType.ToUpper) + //.UseNoneCommandParameter(true) + + .UseMonitorCommand( + cmd => Trace.WriteLine(cmd.CommandText), //监听SQL命令对象,在执行前 + (cmd, traceLog) => Console.WriteLine(traceLog)) + .Build()); + public static IFreeSql dameng => damengLazy.Value; + static void Main(string[] args) { + dameng.Select().ToList(); + var testlist1 = fsql.Select().OrderBy(a => a.Id).ToList(); var testlist2 = new List(); fsql.Select().OrderBy(a => a.Id).ToChunk(0, list => diff --git a/Examples/orm_vs/orm_vs.csproj b/Examples/orm_vs/orm_vs.csproj index 4ee359da..8a489e1f 100644 --- a/Examples/orm_vs/orm_vs.csproj +++ b/Examples/orm_vs/orm_vs.csproj @@ -13,6 +13,7 @@ + diff --git a/Examples/orm_vs_net40/Program.cs b/Examples/orm_vs_net40/Program.cs index 66cd43ef..9db52e73 100644 --- a/Examples/orm_vs_net40/Program.cs +++ b/Examples/orm_vs_net40/Program.cs @@ -33,8 +33,24 @@ namespace orm_vs // }); //} + static Lazy damengLazy = new Lazy(() => new FreeSql.FreeSqlBuilder() + .UseConnectionString(FreeSql.DataType.Dameng, "server=127.0.0.1;port=5236;user id=2user;password=123456789;database=2user") + //.UseConnectionFactory(FreeSql.DataType.Dameng, () => new Dm.DmConnection("data source=127.0.0.1:5236;user id=2user;password=123456789;Pooling=true;Max Pool Size=2")) + .UseAutoSyncStructure(true) + .UseNameConvert(FreeSql.Internal.NameConvertType.ToUpper) + //.UseNoneCommandParameter(true) + + .UseMonitorCommand( + cmd => Trace.WriteLine(cmd.CommandText), //监听SQL命令对象,在执行前 + (cmd, traceLog) => Console.WriteLine(traceLog)) + .Build()); + public static IFreeSql dameng => damengLazy.Value; + static void Main(string[] args) { + dameng.Select().ToList(); + + fsql.CodeFirst.SyncStructure(typeof(Song), typeof(Song_tag), typeof(Tag)); //sugar.CodeFirst.InitTables(typeof(Song), typeof(Song_tag), typeof(Tag)); //sugar创建表失败:SqlSugar.SqlSugarException: Sequence contains no elements diff --git a/Examples/orm_vs_net40/orm_vs_net40.csproj b/Examples/orm_vs_net40/orm_vs_net40.csproj index 15ca534f..223dc56b 100644 --- a/Examples/orm_vs_net40/orm_vs_net40.csproj +++ b/Examples/orm_vs_net40/orm_vs_net40.csproj @@ -49,6 +49,10 @@ {af9c50ec-6eb6-494b-9b3b-7edba6fd0ebb} FreeSql + + {e74d90e8-1cbc-4677-817b-1ca05ab97937} + FreeSql.Provider.Dameng + {28c6a39c-7ae7-4210-b7b0-0970216637a8} FreeSql.Provider.MySql diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index 19225654..8cf53748 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -120,13 +120,6 @@ 清空状态数据 - - - 根据 lambda 条件删除数据 - - - - 添加 @@ -221,15 +214,6 @@ - - - 批量注入 Repository,可以参考代码自行调整 - - - - - - 动态Type,在使用 Repository<object> 后使用本方法,指定实体类型 diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengDeleteTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengDeleteTest.cs new file mode 100644 index 00000000..17ba3c06 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengDeleteTest.cs @@ -0,0 +1,106 @@ +using FreeSql.DataAnnotations; +using System; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace FreeSql.Tests.Dameng +{ + public class DamengDeleteTest + { + + IDelete delete => g.dameng.Delete(); //�������� + + [Table(Name = "tb_topic22211")] + class Topic + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + public int? Clicks { get; set; } + public TestTypeInfo Type { get; set; } + public string Title { get; set; } + public DateTime CreateTime { get; set; } + } + + [Fact] + public void Dywhere() + { + Assert.Null(g.dameng.Delete().ToSql()); + var sql = g.dameng.Delete(new[] { 1, 2 }).ToSql(); + Assert.Equal("DELETE FROM \"TB_TOPIC22211\" WHERE (\"ID\" = 1 OR \"ID\" = 2)", sql); + + sql = g.dameng.Delete(new Topic { Id = 1, Title = "test" }).ToSql(); + Assert.Equal("DELETE FROM \"TB_TOPIC22211\" WHERE (\"ID\" = 1)", sql); + + sql = g.dameng.Delete(new[] { new Topic { Id = 1, Title = "test" }, new Topic { Id = 2, Title = "test" } }).ToSql(); + Assert.Equal("DELETE FROM \"TB_TOPIC22211\" WHERE (\"ID\" = 1 OR \"ID\" = 2)", sql); + + sql = g.dameng.Delete(new { id = 1 }).ToSql(); + Assert.Equal("DELETE FROM \"TB_TOPIC22211\" WHERE (\"ID\" = 1)", sql); + + sql = g.dameng.Delete(new[] { new { Id1 = 1, Id2 = 10 }, new { Id1 = 2, Id2 = 20 } }).ToSql(); + Assert.Equal("DELETE FROM \"MULTIPKTOPIC\" WHERE (\"ID1\" = 1 AND \"ID2\" = 10 OR \"ID1\" = 2 AND \"ID2\" = 20)", sql); + } + class MultiPkTopic + { + [Column(IsPrimary = true)] + public int Id1 { get; set; } + [Column(IsPrimary = true)] + public int Id2 { get; set; } + public int Clicks { get; set; } + public string Title { get; set; } + public DateTime CreateTime { get; set; } + } + + [Fact] + public void Where() + { + var sql = delete.Where(a => a.Id == 1).ToSql().Replace("\r\n", ""); + Assert.Equal("DELETE FROM \"TB_TOPIC22211\" WHERE (\"ID\" = 1)", sql); + + sql = delete.Where("id = :id", new { id = 1 }).ToSql().Replace("\r\n", ""); + Assert.Equal("DELETE FROM \"TB_TOPIC22211\" WHERE (id = :id)", sql); + + var item = new Topic { Id = 1, Title = "newtitle" }; + sql = delete.Where(item).ToSql().Replace("\r\n", ""); + Assert.Equal("DELETE FROM \"TB_TOPIC22211\" WHERE (\"ID\" = 1)", sql); + + var items = new List(); + for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100 }); + + sql = delete.Where(items).ToSql().Replace("\r\n", ""); + Assert.Equal("DELETE FROM \"TB_TOPIC22211\" WHERE (\"ID\" IN (1,2,3,4,5,6,7,8,9,10))", sql); + } + [Fact] + public void ExecuteAffrows() + { + + var id = g.dameng.Insert(new Topic { Title = "xxxx", CreateTime = DateTime.Now }).ExecuteIdentity(); + Assert.Equal(1, delete.Where(a => a.Id == id).ExecuteAffrows()); + } + [Fact] + public void ExecuteDeleted() + { + + //var item = g.dameng.Insert(new Topic { Title = "xxxx", CreateTime = DateTime.Now }).ExecuteInserted(); + //Assert.Equal(item[0].Id, delete.Where(a => a.Id == item[0].Id).ExecuteDeleted()[0].Id); + } + + [Fact] + public void AsTable() + { + Assert.Null(g.dameng.Delete().ToSql()); + var sql = g.dameng.Delete(new[] { 1, 2 }).AsTable(a => "TopicAsTable").ToSql(); + Assert.Equal("DELETE FROM \"TOPICASTABLE\" WHERE (\"ID\" = 1 OR \"ID\" = 2)", sql); + + sql = g.dameng.Delete(new Topic { Id = 1, Title = "test" }).AsTable(a => "TopicAsTable").ToSql(); + Assert.Equal("DELETE FROM \"TOPICASTABLE\" WHERE (\"ID\" = 1)", sql); + + sql = g.dameng.Delete(new[] { new Topic { Id = 1, Title = "test" }, new Topic { Id = 2, Title = "test" } }).AsTable(a => "TopicAsTable").ToSql(); + Assert.Equal("DELETE FROM \"TOPICASTABLE\" WHERE (\"ID\" = 1 OR \"ID\" = 2)", sql); + + sql = g.dameng.Delete(new { id = 1 }).AsTable(a => "TopicAsTable").ToSql(); + Assert.Equal("DELETE FROM \"TOPICASTABLE\" WHERE (\"ID\" = 1)", sql); + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengInsertTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengInsertTest.cs new file mode 100644 index 00000000..4bb00a07 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengInsertTest.cs @@ -0,0 +1,278 @@ +using FreeSql.DataAnnotations; +using System; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace FreeSql.Tests.Dameng +{ + public class DamengInsertTest + { + + IInsert insert => g.dameng.Insert(); //�������� + + [Table(Name = "tb_topic_insert")] + class Topic + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + public int? Clicks { get; set; } + public TestTypeInfo Type { get; set; } + public string Title { get; set; } + public DateTime CreateTime { get; set; } + } + + [Fact] + public void AppendData() + { + var items = new List(); + for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100, CreateTime = DateTime.Parse("2019-09-19 22:25:38.697071") }); + + var data = new List(); + var sql = insert.AppendData(items.First()).ToSql(); + Assert.Equal("INSERT INTO \"TB_TOPIC_INSERT\"(\"CLICKS\", \"TITLE\", \"CREATETIME\") VALUES(0, 'newtitle0', to_timestamp('2019-09-19 22:25:38.697071','YYYY-MM-DD HH24:MI:SS.FF6'))", sql); + data.Add(insert.AppendData(items.First()).ExecuteIdentity()); + + sql = insert.AppendData(items).ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(0, 'newtitle0', to_timestamp('2019-09-19 22:25:38.697071','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(100, 'newtitle1', to_timestamp('2019-09-19 22:25:38.697071','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(200, 'newtitle2', to_timestamp('2019-09-19 22:25:38.697071','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(300, 'newtitle3', to_timestamp('2019-09-19 22:25:38.697071','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(400, 'newtitle4', to_timestamp('2019-09-19 22:25:38.697071','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(500, 'newtitle5', to_timestamp('2019-09-19 22:25:38.697071','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(600, 'newtitle6', to_timestamp('2019-09-19 22:25:38.697071','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(700, 'newtitle7', to_timestamp('2019-09-19 22:25:38.697071','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(800, 'newtitle8', to_timestamp('2019-09-19 22:25:38.697071','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(900, 'newtitle9', to_timestamp('2019-09-19 22:25:38.697071','YYYY-MM-DD HH24:MI:SS.FF6')) + SELECT 1 FROM DUAL", sql); + data.Add(insert.AppendData(items.First()).ExecuteIdentity()); + + sql = insert.AppendData(items).InsertColumns(a => a.Title).ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle0') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle1') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle2') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle3') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle4') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle5') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle6') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle7') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle8') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle9') + SELECT 1 FROM DUAL", sql); + data.Add(insert.AppendData(items.First()).ExecuteIdentity()); + + sql = insert.AppendData(items).IgnoreColumns(a => a.CreateTime).ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(0, 'newtitle0') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(100, 'newtitle1') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(200, 'newtitle2') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(300, 'newtitle3') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(400, 'newtitle4') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(500, 'newtitle5') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(600, 'newtitle6') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(700, 'newtitle7') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(800, 'newtitle8') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(900, 'newtitle9') + SELECT 1 FROM DUAL", sql); + data.Add(insert.AppendData(items.First()).ExecuteIdentity()); + } + + [Fact] + public void InsertColumns() + { + var items = new List(); + for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100, CreateTime = DateTime.Now }); + + var data = new List(); + var sql = insert.AppendData(items).InsertColumns(a => a.Title).ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle0') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle1') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle2') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle3') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle4') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle5') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle6') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle7') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle8') +INTO ""TB_TOPIC_INSERT""(""TITLE"") VALUES('newtitle9') + SELECT 1 FROM DUAL", sql); + data.Add(insert.AppendData(items.First()).ExecuteIdentity()); + + sql = insert.AppendData(items).InsertColumns(a => new { a.Title, a.Clicks }).ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(0, 'newtitle0') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(100, 'newtitle1') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(200, 'newtitle2') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(300, 'newtitle3') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(400, 'newtitle4') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(500, 'newtitle5') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(600, 'newtitle6') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(700, 'newtitle7') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(800, 'newtitle8') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(900, 'newtitle9') + SELECT 1 FROM DUAL", sql); + data.Add(insert.AppendData(items.First()).ExecuteIdentity()); + } + [Fact] + public void IgnoreColumns() + { + var items = new List(); + for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100, CreateTime = DateTime.Now }); + + var data = new List(); + var sql = insert.AppendData(items).IgnoreColumns(a => a.CreateTime).ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(0, 'newtitle0') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(100, 'newtitle1') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(200, 'newtitle2') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(300, 'newtitle3') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(400, 'newtitle4') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(500, 'newtitle5') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(600, 'newtitle6') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(700, 'newtitle7') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(800, 'newtitle8') +INTO ""TB_TOPIC_INSERT""(""CLICKS"", ""TITLE"") VALUES(900, 'newtitle9') + SELECT 1 FROM DUAL", sql); + data.Add(insert.AppendData(items.First()).ExecuteIdentity()); + + sql = insert.AppendData(items).IgnoreColumns(a => new { a.Title, a.CreateTime }).ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TB_TOPIC_INSERT""(""CLICKS"") VALUES(0) +INTO ""TB_TOPIC_INSERT""(""CLICKS"") VALUES(100) +INTO ""TB_TOPIC_INSERT""(""CLICKS"") VALUES(200) +INTO ""TB_TOPIC_INSERT""(""CLICKS"") VALUES(300) +INTO ""TB_TOPIC_INSERT""(""CLICKS"") VALUES(400) +INTO ""TB_TOPIC_INSERT""(""CLICKS"") VALUES(500) +INTO ""TB_TOPIC_INSERT""(""CLICKS"") VALUES(600) +INTO ""TB_TOPIC_INSERT""(""CLICKS"") VALUES(700) +INTO ""TB_TOPIC_INSERT""(""CLICKS"") VALUES(800) +INTO ""TB_TOPIC_INSERT""(""CLICKS"") VALUES(900) + SELECT 1 FROM DUAL", sql); + data.Add(insert.AppendData(items.First()).ExecuteIdentity()); + + g.dameng.Delete().Where("1=1").ExecuteAffrows(); + var itemsIgnore = new List(); + for (var a = 0; a < 2072; a++) itemsIgnore.Add(new TopicIgnore { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100, CreateTime = DateTime.Now }); + g.dameng.Insert().AppendData(itemsIgnore).IgnoreColumns(a => new { a.Title }).ExecuteAffrows(); + Assert.Equal(2072, itemsIgnore.Count); + Assert.Equal(2072, g.dameng.Select().Where(a => a.Title == null).Count()); + } + [Table(Name = "tb_topicICs")] + class TopicIgnore + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + public int Clicks { get; set; } + public string Title { get; set; } + public DateTime CreateTime { get; set; } + } + [Fact] + public void ExecuteAffrows() + { + var items = new List(); + for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100, CreateTime = DateTime.Now }); + + Assert.Equal(1, insert.AppendData(items.First()).ExecuteAffrows()); + Assert.Equal(10, insert.AppendData(items).ExecuteAffrows()); + } + [Fact] + public void ExecuteIdentity() + { + var items = new List(); + for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100, CreateTime = DateTime.Now }); + + Assert.NotEqual(0, insert.AppendData(items.First()).ExecuteIdentity()); + } + [Fact] + public void ExecuteInserted() + { + //var items = new List(); + //for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100, CreateTime = DateTime.Now }); + + //var items2 = insert.AppendData(items).ExecuteInserted(); + } + + [Fact] + public void AsTable() + { + var items = new List(); + for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newTitle{a}", Clicks = a * 100 }); + + var sql = insert.AppendData(items.First()).AsTable(a => "Topic_InsertAsTable").ToSql(); + Assert.Equal("INSERT INTO \"TOPIC_INSERTASTABLE\"(\"CLICKS\", \"TITLE\", \"CREATETIME\") VALUES(0, 'newTitle0', to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6'))", sql); + + sql = insert.AppendData(items).AsTable(a => "Topic_InsertAsTable").ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(0, 'newTitle0', to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(100, 'newTitle1', to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(200, 'newTitle2', to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(300, 'newTitle3', to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(400, 'newTitle4', to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(500, 'newTitle5', to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(600, 'newTitle6', to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(700, 'newTitle7', to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(800, 'newTitle8', to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"", ""CREATETIME"") VALUES(900, 'newTitle9', to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) + SELECT 1 FROM DUAL", sql); + + sql = insert.AppendData(items).IgnoreColumns(a => a.Title).AsTable(a => "Topic_InsertAsTable").ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""CREATETIME"") VALUES(0, to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""CREATETIME"") VALUES(100, to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""CREATETIME"") VALUES(200, to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""CREATETIME"") VALUES(300, to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""CREATETIME"") VALUES(400, to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""CREATETIME"") VALUES(500, to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""CREATETIME"") VALUES(600, to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""CREATETIME"") VALUES(700, to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""CREATETIME"") VALUES(800, to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""CREATETIME"") VALUES(900, to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6')) + SELECT 1 FROM DUAL", sql); + + sql = insert.AppendData(items).IgnoreColumns(a => new { a.Clicks, a.CreateTime }).AsTable(a => "Topic_InsertAsTable").ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle0') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle1') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle2') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle3') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle4') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle5') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle6') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle7') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle8') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle9') + SELECT 1 FROM DUAL", sql); + + sql = insert.AppendData(items).InsertColumns(a => a.Title).AsTable(a => "Topic_InsertAsTable").ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle0') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle1') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle2') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle3') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle4') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle5') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle6') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle7') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle8') +INTO ""TOPIC_INSERTASTABLE""(""TITLE"") VALUES('newTitle9') + SELECT 1 FROM DUAL", sql); + + sql = insert.AppendData(items).InsertColumns(a => new { a.Title, a.Clicks }).AsTable(a => "Topic_InsertAsTable").ToSql(); + Assert.Equal(@"INSERT ALL +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"") VALUES(0, 'newTitle0') +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"") VALUES(100, 'newTitle1') +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"") VALUES(200, 'newTitle2') +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"") VALUES(300, 'newTitle3') +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"") VALUES(400, 'newTitle4') +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"") VALUES(500, 'newTitle5') +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"") VALUES(600, 'newTitle6') +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"") VALUES(700, 'newTitle7') +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"") VALUES(800, 'newTitle8') +INTO ""TOPIC_INSERTASTABLE""(""CLICKS"", ""TITLE"") VALUES(900, 'newTitle9') + SELECT 1 FROM DUAL", sql); + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs new file mode 100644 index 00000000..c19346f9 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs @@ -0,0 +1,1788 @@ +using FreeSql.DataAnnotations; +using System; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace FreeSql.Tests.Dameng +{ + public class DamengSelectTest + { + + ISelect select => g.dameng.Select(); + + [Table(Name = "tb_topic22")] + class Topic + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + public int Clicks { get; set; } + public int TypeGuid { get; set; } + public TestTypeInfo Type { get; set; } + public string Title { get; set; } + public DateTime CreateTime { get; set; } + } + class TestTypeInfo + { + [Column(IsIdentity = true)] + public int Guid { get; set; } + public int ParentId { get; set; } + public TestTypeParentInfo Parent { get; set; } + public string Name { get; set; } + } + class TestTypeParentInfo + { + public int Id { get; set; } + public string Name { get; set; } + + public List Types { get; set; } + } + + class TopicInserts + { + public Guid Id { get; set; } + public int Clicks { get; set; } + public int TypeGuid { get; set; } + public TestTypeInfo Type { get; set; } + public string Title { get; set; } + public DateTime CreateTime { get; set; } + } + public partial class Song + { + [Column(IsIdentity = true)] + public int Id { get; set; } + public DateTime? Create_time { get; set; } + public bool? Is_deleted { get; set; } + public string Title { get; set; } + public string Url { get; set; } + + public virtual ICollection Tags { get; set; } + } + public partial class Song_tag + { + public int Song_id { get; set; } + public virtual Song Song { get; set; } + + public int Tag_id { get; set; } + public virtual Tag Tag { get; set; } + } + public partial class Tag + { + [Column(IsIdentity = true)] + public int Id { get; set; } + public int? Parent_id { get; set; } + public virtual Tag Parent { get; set; } + + public decimal? Ddd { get; set; } + public string Name { get; set; } + + public virtual ICollection Songs { get; set; } + public virtual ICollection Tags { get; set; } + } + + [Fact] + public void AsSelect() + { + //OneToOne、ManyToOne + var t0 = g.dameng.Select().Where(a => a.Parent.Parent.Name == "粤语").ToSql(); + //SELECT a.`Id`, a.`Parent_id`, a__Parent.`Id` as3, a__Parent.`Parent_id` as4, a__Parent.`Ddd`, a__Parent.`Name`, a.`Ddd` as7, a.`Name` as8 + //FROM `Tag` a + //LEFT JOIN `Tag` a__Parent ON a__Parent.`Id` = a.`Parent_id` + //LEFT JOIN `Tag` a__Parent__Parent ON a__Parent__Parent.`Id` = a__Parent.`Parent_id` + //WHERE (a__Parent__Parent.`Name` = '粤语') + + //OneToMany + var t1 = g.dameng.Select().Where(a => a.Tags.AsSelect().Any(t => t.Parent.Id == 10)).ToSql(); + //SELECT a.`Id`, a.`Parent_id`, a.`Ddd`, a.`Name` + //FROM `Tag` a + //WHERE (exists(SELECT 1 + // FROM `Tag` t + // LEFT JOIN `Tag` t__Parent ON t__Parent.`Id` = t.`Parent_id` + // WHERE (t__Parent.`Id` = 10) AND (t.`Parent_id` = a.`Id`) + // limit 0,1)) + + //ManyToMany + var t2 = g.dameng.Select().Where(s => s.Tags.AsSelect().Any(t => t.Name == "国语")).ToSql(); + //SELECT a.`Id`, a.`Create_time`, a.`Is_deleted`, a.`Title`, a.`Url` + //FROM `Song` a + //WHERE(exists(SELECT 1 + // FROM `Song_tag` Mt_Ms + // WHERE(Mt_Ms.`Song_id` = a.`Id`) AND(exists(SELECT 1 + // FROM `Tag` t + // WHERE(t.`Name` = '国语') AND(t.`Id` = Mt_Ms.`Tag_id`) + // limit 0, 1)) + // limit 0, 1)) + } + + [Fact] + public void Lazy() + { + var tags = g.dameng.Select().Where(a => a.Parent.Name == "xxx") + .LeftJoin(a => a.Parent_id == a.Parent.Id) + .ToSql(); + + var songs = g.dameng.Select().Limit(10).ToList(); + } + + [Fact] + public void ToDataTable() + { + var items = new List(); + for (var a = 0; a < 11; a++) items.Add(new TopicInserts { Title = $"newtitle{a}", Clicks = a * 100, CreateTime = DateTime.Now }); + + //Assert.Equal(1, g.dameng.Insert().AppendData(items.First()).ExecuteAffrows()); + Assert.Equal(11, g.dameng.Insert().AppendData(items).ExecuteAffrows()); + + //items = Enumerable.Range(0, 9989).Select(a => new TopicInserts { Title = "newtitle" + a, CreateTime = DateTime.Now }).ToList(); + //Assert.Equal(9989, g.dameng.Insert(items).ExecuteAffrows()); + + //var dt1 = select.ToDataTable(); + //var dt2 = select.ToDataTable("id, 111222"); + //var dt3 = select.ToDataTable(a => new { a.Id, a.Type.Name, now = DateTime.Now }); + } + class TestDto + { + public int id { get; set; } + public string name { get; set; } //这是join表的属性 + public int ParentId { get; set; } //这是join表的属性 + } + class TestDto2 + { + public int id { get; set; } + public string name { get; set; } //这是join表的属性 + public int ParentId { get; set; } //这是join表的属性 + + public TestDto2() { } + public TestDto2(int id, string name) + { + this.id = id; + this.name = name; + } + } + [Fact] + public void ToList() + { + + var testDto1 = select.Limit(10).ToList(a => new TestDto { id = a.Id, name = a.Title }); + var testDto2 = select.Limit(10).ToList(a => new TestDto()); + var testDto3 = select.Limit(10).ToList(a => new TestDto { }); + var testDto4 = select.Limit(10).ToList(a => new TestDto() { }); + + var testDto11 = select.LeftJoin(a => a.Type.Guid == a.TypeGuid).Limit(10).ToList(a => new TestDto { id = a.Id, name = a.Title }); + var testDto22 = select.LeftJoin(a => a.Type.Guid == a.TypeGuid).Limit(10).ToList(a => new TestDto()); + var testDto33 = select.LeftJoin(a => a.Type.Guid == a.TypeGuid).Limit(10).ToList(a => new TestDto { }); + var testDto44 = select.LeftJoin(a => a.Type.Guid == a.TypeGuid).Limit(10).ToList(a => new TestDto() { }); + + var testDto211 = select.Limit(10).ToList(a => new TestDto2(a.Id, a.Title)); + var testDto212 = select.Limit(10).ToList(a => new TestDto2()); + var testDto213 = select.Limit(10).ToList(a => new TestDto2 { }); + var testDto214 = select.Limit(10).ToList(a => new TestDto2() { }); + var testDto215 = select.Limit(10).ToList(); + + var testDto2211 = select.LeftJoin(a => a.Type.Guid == a.TypeGuid).Limit(10).ToList(a => new TestDto2(a.Id, a.Title)); + var testDto2222 = select.LeftJoin(a => a.Type.Guid == a.TypeGuid).Limit(10).ToList(a => new TestDto2()); + var testDto2233 = select.LeftJoin(a => a.Type.Guid == a.TypeGuid).Limit(10).ToList(a => new TestDto2 { }); + var testDto2244 = select.LeftJoin(a => a.Type.Guid == a.TypeGuid).Limit(10).ToList(a => new TestDto2() { }); + var testDto2255 = select.LeftJoin(a => a.Type.Guid == a.TypeGuid).Limit(10).ToList(); + + g.dameng.Insert().AppendData(new TestGuidIdToList()).ExecuteAffrows(); + var testGuidId5 = g.dameng.Select().ToList(); + var testGuidId6 = g.dameng.Select().ToList(a => a.id); + + var t11 = select.Where(a => a.Type.Name.Length > 0).ToList(true); + var t21 = select.Where(a => a.Type.Parent.Name.Length > 0).ToList(true); + + g.dameng.Delete().Where("1=1").ExecuteAffrows(); + var repo = g.dameng.GetRepository(); + repo.DbContextOptions.EnableAddOrUpdateNavigateList = true; + repo.Insert(new District + { + Code = "001", + Name = "001_name", + Childs = new List(new[] { + new District{ + Code = "001_01", + Name = "001_01_name" + }, + new District{ + Code = "001_02", + Name = "001_02_name" + } + }) + }); + var ddd = g.dameng.Select().LeftJoin(d => d.ParentCode == d.Parent.Code).ToTreeList(); + Assert.Single(ddd); + Assert.Equal(2, ddd[0].Childs.Count); + } + public class District + { + [Column(IsPrimary = true, StringLength = 6)] + public string Code { get; set; } + + [Column(StringLength = 20, IsNullable = false)] + public string Name { get; set; } + + [Column(StringLength = 6)] + public string ParentCode { get; set; } + + [Navigate(nameof(ParentCode))] + public District Parent { get; set; } + + [Navigate(nameof(ParentCode))] + public List Childs { get; set; } + } + [Fact] + public void ToDictionary() + { + g.dameng.Insert(new Topic { Title = "xxx" }).ExecuteAffrows(); + var testDto1 = select.Limit(10).ToDictionary(a => a.Id); + var testDto2 = select.Limit(10).ToDictionary(a => a.Id, a => new { a.Id, a.Title }); + + var repo = g.dameng.GetRepository(); + var dic = repo.Select.Limit(10).ToDictionary(a => a.Id); + var first = dic.First().Value; + first.Clicks++; + repo.Update(first); + } + class TestGuidIdToList + { + public Guid id { get; set; } + public string title { get; set; } = Guid.NewGuid().ToString(); + } + [Fact] + public void ToOne() + { + var testnotfind = select.Where("1=2").First(a => a.CreateTime); + Assert.Equal(default(DateTime), testnotfind); + } + [Fact] + public void ToSql() + { + } + [Fact] + public void Any() + { + var count = select.Where(a => 1 == 1).Count(); + Assert.False(select.Where(a => 1 == 2).Any()); + Assert.Equal(count > 0, select.Where(a => 1 == 1).Any()); + + var sql2222 = select.Where(a => + select.Where(b => b.Id == a.Id && + select.Where(c => c.Id == b.Id).Where(d => d.Id == a.Id).Where(e => e.Id == b.Id) + //.Offset(a.Id) + .Any() + ).Any(c => c.Id == a.Id + 10) + ); + var sql2222Tolist = sql2222.ToList(); + + var collectionSelect = select.Where(a => + a.Type.Guid == a.TypeGuid && + a.Type.Parent.Id == a.Type.ParentId && + a.Type.Parent.Types.AsSelect().Where(b => b.Name == a.Title).Any(b => b.ParentId == a.Type.Parent.Id) + ); + collectionSelect.ToList(); + } + [Fact] + public void Count() + { + var count = select.Where(a => 1 == 1).Count(); + select.Where(a => 1 == 1).Count(out var count2); + Assert.Equal(count, count2); + Assert.Equal(0, select.Where(a => 1 == 2).Count()); + + var subquery = select.ToSql(a => new + { + all = a, + count = select.Where(b => b.Id > 0 && b.Id == a.Id).Count() + }); + var subqueryList = select.ToList(a => new + { + all = a, + count = select.Where(b => b.Id > 0 && b.Id == a.Id).Count() + }); + } + [Fact] + public void Master() + { + Assert.StartsWith(" SELECT", select.Master().Where(a => 1 == 1).ToSql()); + } + [Fact] + public void From() + { + var query2 = select.From((s, b) => s + .LeftJoin(a => a.TypeGuid == b.Guid) + ); + var sql2 = query2.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", b.\"GUID\", b.\"PARENTID\", b.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" b ON a.\"TYPEGUID\" = b.\"GUID\"", sql2); + query2.ToList(); + + var query3 = select.From((s, b, c) => s + .LeftJoin(a => a.TypeGuid == b.Guid) + .LeftJoin(a => b.ParentId == c.Id) + ); + var sql3 = query3.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", b.\"GUID\", b.\"PARENTID\", b.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" b ON a.\"TYPEGUID\" = b.\"GUID\" LEFT JOIN \"TESTTYPEPARENTINFO\" c ON b.\"PARENTID\" = c.\"ID\"", sql3); + query3.ToList(); + } + [Fact] + public void LeftJoin() + { + //����е�������a.Type��a.Type.Parent ���ǵ������� + var query = select.LeftJoin(a => a.Type.Guid == a.TypeGuid); + var sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\"", sql); + query.ToList(); + + query = select.LeftJoin(a => a.Type.Guid == a.TypeGuid && a.Type.Name == "xxx"); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" AND a__Type.\"NAME\" = 'xxx'", sql); + query.ToList(); + + query = select.LeftJoin(a => a.Type.Guid == a.TypeGuid && a.Type.Name == "xxx").Where(a => a.Type.Parent.Id == 10); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" AND a__Type.\"NAME\" = 'xxx' LEFT JOIN \"TESTTYPEPARENTINFO\" a__Type__Parent ON a__Type__Parent.\"ID\" = a__Type.\"PARENTID\" WHERE (a__Type__Parent.\"ID\" = 10)", sql); + query.ToList(); + + //���û�е������� + query = select.LeftJoin((a, b) => b.Guid == a.TypeGuid); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", b.\"GUID\", b.\"PARENTID\", b.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" b ON b.\"GUID\" = a.\"TYPEGUID\"", sql); + query.ToList(); + + query = select.LeftJoin((a, b) => b.Guid == a.TypeGuid && b.Name == "xxx"); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", b.\"GUID\", b.\"PARENTID\", b.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" b ON b.\"GUID\" = a.\"TYPEGUID\" AND b.\"NAME\" = 'xxx'", sql); + query.ToList(); + + query = select.LeftJoin((a, a__Type) => a__Type.Guid == a.TypeGuid && a__Type.Name == "xxx").Where(a => a.Type.Parent.Id == 10); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" AND a__Type.\"NAME\" = 'xxx' LEFT JOIN \"TESTTYPEPARENTINFO\" a__Type__Parent ON a__Type__Parent.\"ID\" = a__Type.\"PARENTID\" WHERE (a__Type__Parent.\"ID\" = 10)", sql); + query.ToList(); + + //������� + query = select + .LeftJoin(a => a.Type.Guid == a.TypeGuid) + .LeftJoin(a => a.Type.Parent.Id == a.Type.ParentId); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" LEFT JOIN \"TESTTYPEPARENTINFO\" a__Type__Parent ON a__Type__Parent.\"ID\" = a__Type.\"PARENTID\"", sql); + query.ToList(); + + query = select + .LeftJoin((a, a__Type) => a__Type.Guid == a.TypeGuid) + .LeftJoin((a, c) => c.Id == a.Type.ParentId); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" LEFT JOIN \"TESTTYPEPARENTINFO\" c ON c.\"ID\" = a__Type.\"PARENTID\"", sql); + query.ToList(); + + //���û�е�������b��c������ϵ + var query2 = select.From((s, b, c) => s + .LeftJoin(a => a.TypeGuid == b.Guid) + .LeftJoin(a => b.ParentId == c.Id)); + sql = query2.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", b.\"GUID\", b.\"PARENTID\", b.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" b ON a.\"TYPEGUID\" = b.\"GUID\" LEFT JOIN \"TESTTYPEPARENTINFO\" c ON b.\"PARENTID\" = c.\"ID\"", sql); + query2.ToList(); + + //������϶����㲻�� + query = select.LeftJoin("\"TESTTYPEINFO\" b on b.\"GUID\" = a.\"TYPEGUID\""); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" b on b.\"GUID\" = a.\"TYPEGUID\"", sql); + query.ToList(); + + query = select.LeftJoin("\"TESTTYPEINFO\" b on b.\"GUID\" = a.\"TYPEGUID\" and b.\"NAME\" = :bname", new { bname = "xxx" }); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" b on b.\"GUID\" = a.\"TYPEGUID\" and b.\"NAME\" = :bname", sql); + query.ToList(); + } + [Fact] + public void InnerJoin() + { + //����е�������a.Type��a.Type.Parent ���ǵ������� + var query = select.InnerJoin(a => a.Type.Guid == a.TypeGuid); + var sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a INNER JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\"", sql); + query.ToList(); + + query = select.InnerJoin(a => a.Type.Guid == a.TypeGuid && a.Type.Name == "xxx"); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a INNER JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" AND a__Type.\"NAME\" = 'xxx'", sql); + query.ToList(); + + query = select.InnerJoin(a => a.Type.Guid == a.TypeGuid && a.Type.Name == "xxx").Where(a => a.Type.Parent.Id == 10); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a INNER JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" AND a__Type.\"NAME\" = 'xxx' LEFT JOIN \"TESTTYPEPARENTINFO\" a__Type__Parent ON a__Type__Parent.\"ID\" = a__Type.\"PARENTID\" WHERE (a__Type__Parent.\"ID\" = 10)", sql); + query.ToList(); + + //���û�е������� + query = select.InnerJoin((a, b) => b.Guid == a.TypeGuid); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", b.\"GUID\", b.\"PARENTID\", b.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a INNER JOIN \"TESTTYPEINFO\" b ON b.\"GUID\" = a.\"TYPEGUID\"", sql); + query.ToList(); + + query = select.InnerJoin((a, b) => b.Guid == a.TypeGuid && b.Name == "xxx"); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", b.\"GUID\", b.\"PARENTID\", b.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a INNER JOIN \"TESTTYPEINFO\" b ON b.\"GUID\" = a.\"TYPEGUID\" AND b.\"NAME\" = 'xxx'", sql); + query.ToList(); + + query = select.InnerJoin((a, a__Type) => a__Type.Guid == a.TypeGuid && a__Type.Name == "xxx").Where(a => a.Type.Parent.Id == 10); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a INNER JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" AND a__Type.\"NAME\" = 'xxx' LEFT JOIN \"TESTTYPEPARENTINFO\" a__Type__Parent ON a__Type__Parent.\"ID\" = a__Type.\"PARENTID\" WHERE (a__Type__Parent.\"ID\" = 10)", sql); + query.ToList(); + + //������� + query = select + .InnerJoin(a => a.Type.Guid == a.TypeGuid) + .InnerJoin(a => a.Type.Parent.Id == a.Type.ParentId); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a INNER JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" INNER JOIN \"TESTTYPEPARENTINFO\" a__Type__Parent ON a__Type__Parent.\"ID\" = a__Type.\"PARENTID\"", sql); + query.ToList(); + + query = select + .InnerJoin((a, a__Type) => a__Type.Guid == a.TypeGuid) + .InnerJoin((a, c) => c.Id == a.Type.ParentId); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a INNER JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" INNER JOIN \"TESTTYPEPARENTINFO\" c ON c.\"ID\" = a__Type.\"PARENTID\"", sql); + query.ToList(); + + //���û�е�������b��c������ϵ + var query2 = select.From((s, b, c) => s + .InnerJoin(a => a.TypeGuid == b.Guid) + .InnerJoin(a => b.ParentId == c.Id)); + sql = query2.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", b.\"GUID\", b.\"PARENTID\", b.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a INNER JOIN \"TESTTYPEINFO\" b ON a.\"TYPEGUID\" = b.\"GUID\" INNER JOIN \"TESTTYPEPARENTINFO\" c ON b.\"PARENTID\" = c.\"ID\"", sql); + query2.ToList(); + + //������϶����㲻�� + query = select.InnerJoin("\"TESTTYPEINFO\" b on b.\"GUID\" = a.\"TYPEGUID\""); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a INNER JOIN \"TESTTYPEINFO\" b on b.\"GUID\" = a.\"TYPEGUID\"", sql); + query.ToList(); + + query = select.InnerJoin("\"TESTTYPEINFO\" b on b.\"GUID\" = a.\"TYPEGUID\" and b.\"NAME\" = :bname", new { bname = "xxx" }); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a INNER JOIN \"TESTTYPEINFO\" b on b.\"GUID\" = a.\"TYPEGUID\" and b.\"NAME\" = :bname", sql); + query.ToList(); + + } + [Fact] + public void RightJoin() + { + //����е�������a.Type��a.Type.Parent ���ǵ������� + var query = select.RightJoin(a => a.Type.Guid == a.TypeGuid); + var sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a RIGHT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\"", sql); + query.ToList(); + + query = select.RightJoin(a => a.Type.Guid == a.TypeGuid && a.Type.Name == "xxx"); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a RIGHT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" AND a__Type.\"NAME\" = 'xxx'", sql); + query.ToList(); + + query = select.RightJoin(a => a.Type.Guid == a.TypeGuid && a.Type.Name == "xxx").Where(a => a.Type.Parent.Id == 10); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a RIGHT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" AND a__Type.\"NAME\" = 'xxx' LEFT JOIN \"TESTTYPEPARENTINFO\" a__Type__Parent ON a__Type__Parent.\"ID\" = a__Type.\"PARENTID\" WHERE (a__Type__Parent.\"ID\" = 10)", sql); + query.ToList(); + + //���û�е������� + query = select.RightJoin((a, b) => b.Guid == a.TypeGuid); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", b.\"GUID\", b.\"PARENTID\", b.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a RIGHT JOIN \"TESTTYPEINFO\" b ON b.\"GUID\" = a.\"TYPEGUID\"", sql); + query.ToList(); + + query = select.RightJoin((a, b) => b.Guid == a.TypeGuid && b.Name == "xxx"); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", b.\"GUID\", b.\"PARENTID\", b.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a RIGHT JOIN \"TESTTYPEINFO\" b ON b.\"GUID\" = a.\"TYPEGUID\" AND b.\"NAME\" = 'xxx'", sql); + query.ToList(); + + query = select.RightJoin((a, a__Type) => a__Type.Guid == a.TypeGuid && a__Type.Name == "xxx").Where(a => a.Type.Parent.Id == 10); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a RIGHT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" AND a__Type.\"NAME\" = 'xxx' LEFT JOIN \"TESTTYPEPARENTINFO\" a__Type__Parent ON a__Type__Parent.\"ID\" = a__Type.\"PARENTID\" WHERE (a__Type__Parent.\"ID\" = 10)", sql); + query.ToList(); + + //������� + query = select + .RightJoin(a => a.Type.Guid == a.TypeGuid) + .RightJoin(a => a.Type.Parent.Id == a.Type.ParentId); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a RIGHT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" RIGHT JOIN \"TESTTYPEPARENTINFO\" a__Type__Parent ON a__Type__Parent.\"ID\" = a__Type.\"PARENTID\"", sql); + query.ToList(); + + query = select + .RightJoin((a, a__Type) => a__Type.Guid == a.TypeGuid) + .RightJoin((a, c) => c.Id == a.Type.ParentId); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a RIGHT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" RIGHT JOIN \"TESTTYPEPARENTINFO\" c ON c.\"ID\" = a__Type.\"PARENTID\"", sql); + query.ToList(); + + //���û�е�������b��c������ϵ + var query2 = select.From((s, b, c) => s + .RightJoin(a => a.TypeGuid == b.Guid) + .RightJoin(a => b.ParentId == c.Id)); + sql = query2.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", b.\"GUID\", b.\"PARENTID\", b.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a RIGHT JOIN \"TESTTYPEINFO\" b ON a.\"TYPEGUID\" = b.\"GUID\" RIGHT JOIN \"TESTTYPEPARENTINFO\" c ON b.\"PARENTID\" = c.\"ID\"", sql); + query2.ToList(); + + //������϶����㲻�� + query = select.RightJoin("\"TESTTYPEINFO\" b on b.\"GUID\" = a.\"TYPEGUID\""); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a RIGHT JOIN \"TESTTYPEINFO\" b on b.\"GUID\" = a.\"TYPEGUID\"", sql); + query.ToList(); + + query = select.RightJoin("\"TESTTYPEINFO\" b on b.\"GUID\" = a.\"TYPEGUID\" and b.\"NAME\" = :bname", new { bname = "xxx" }); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a RIGHT JOIN \"TESTTYPEINFO\" b on b.\"GUID\" = a.\"TYPEGUID\" and b.\"NAME\" = :bname", sql); + query.ToList(); + + } + [Fact] + public void Where() + { + var sqltmp1 = select.Where(a => a.Id == 0 && (a.Title == "x" || a.Title == "y") && a.Clicks == 1).ToSql(); + var sqltmp2 = select.Where(a => a.Id.Equals(true) && (a.Title.Equals("x") || a.Title.Equals("y")) && a.Clicks.Equals(1)).ToSql(); + var sqltmp3 = select.Where(a => a.Id == 0).Where(a => ((a.Title == "x" && a.Title == "z") || a.Title == "y")).ToSql(); + + var sqltmp4 = select.Where(a => (a.Id - 10) / 2 > 0).ToSql(); + + //����е�������a.Type��a.Type.Parent ���ǵ������� + var query = select.Where(a => a.Id == 10); + var sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a WHERE (a.\"ID\" = 10)", sql); + query.ToList(); + + query = select.Where(a => a.Id == 10 && a.Id > 10 || a.Clicks > 100); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a WHERE ((a.\"ID\" = 10 AND a.\"ID\" > 10 OR a.\"CLICKS\" > 100))", sql); + query.ToList(); + + query = select.Where(a => a.Id == 10).Where(a => a.Clicks > 100); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a WHERE (a.\"ID\" = 10) AND (a.\"CLICKS\" > 100)", sql); + query.ToList(); + + query = select.Where(a => a.Type.Name == "typeTitle"); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" WHERE (a__Type.\"NAME\" = 'typeTitle')", sql); + query.ToList(); + + query = select.Where(a => a.Type.Name == "typeTitle" && a.Type.Guid == a.TypeGuid); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" WHERE (a__Type.\"NAME\" = 'typeTitle' AND a__Type.\"GUID\" = a.\"TYPEGUID\")", sql); + query.ToList(); + + query = select.Where(a => a.Type.Parent.Name == "tparent"); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" LEFT JOIN \"TESTTYPEPARENTINFO\" a__Type__Parent ON a__Type__Parent.\"ID\" = a__Type.\"PARENTID\" WHERE (a__Type__Parent.\"NAME\" = 'tparent')", sql); + query.ToList(); + + //���û�е������ԣ��򵥶������ + query = select.Where((a, b) => b.Guid == a.TypeGuid && b.Name == "typeTitle"); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a, \"TESTTYPEINFO\" b WHERE (b.\"GUID\" = a.\"TYPEGUID\" AND b.\"NAME\" = 'typeTitle')", sql); + query.ToList(); + + query = select.Where((a, b) => b.Name == "typeTitle" && b.Guid == a.TypeGuid); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a, \"TESTTYPEINFO\" b WHERE (b.\"NAME\" = 'typeTitle' AND b.\"GUID\" = a.\"TYPEGUID\")", sql); + query.ToList(); + + query = select.Where((a, b, c) => c.Name == "tparent"); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a, \"TESTTYPEPARENTINFO\" c WHERE (c.\"NAME\" = 'tparent')", sql); + query.ToList(); + + //����һ�� From ��Ķ������ + var query2 = select.From((s, b, c) => s + .Where(a => a.Id == 10 && c.Name == "xxx") + .Where(a => b.ParentId == 20)); + sql = query2.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a, \"TESTTYPEINFO\" b, \"TESTTYPEPARENTINFO\" c WHERE (a.\"ID\" = 10 AND c.\"NAME\" = 'xxx') AND (b.\"PARENTID\" = 20)", sql); + query2.ToList(); + + //������϶����㲻�� + query = select.Where("a.\"CLICKS\" > 100 and a.\"ID\" = :id", new { id = 10 }); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a WHERE (a.\"CLICKS\" > 100 and a.\"ID\" = :id)", sql); + query.ToList(); + } + [Fact] + public void WhereIf() + { + //����е�������a.Type��a.Type.Parent ���ǵ������� + var query = select.WhereIf(true, a => a.Id == 10); + var sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a WHERE (a.\"ID\" = 10)", sql); + query.ToList(); + + query = select.WhereIf(true, a => a.Id == 10 && a.Id > 10 || a.Clicks > 100); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a WHERE ((a.\"ID\" = 10 AND a.\"ID\" > 10 OR a.\"CLICKS\" > 100))", sql); + query.ToList(); + + query = select.WhereIf(true, a => a.Id == 10).WhereIf(true, a => a.Clicks > 100); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a WHERE (a.\"ID\" = 10) AND (a.\"CLICKS\" > 100)", sql); + query.ToList(); + + query = select.WhereIf(true, a => a.Type.Name == "typeTitle"); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" WHERE (a__Type.\"NAME\" = 'typeTitle')", sql); + query.ToList(); + + query = select.WhereIf(true, a => a.Type.Name == "typeTitle" && a.Type.Guid == a.TypeGuid); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" WHERE (a__Type.\"NAME\" = 'typeTitle' AND a__Type.\"GUID\" = a.\"TYPEGUID\")", sql); + query.ToList(); + + query = select.WhereIf(true, a => a.Type.Parent.Name == "tparent"); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a LEFT JOIN \"TESTTYPEINFO\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" LEFT JOIN \"TESTTYPEPARENTINFO\" a__Type__Parent ON a__Type__Parent.\"ID\" = a__Type.\"PARENTID\" WHERE (a__Type__Parent.\"NAME\" = 'tparent')", sql); + query.ToList(); + + //����һ�� From ��Ķ������ + var query2 = select.From((s, b, c) => s + .WhereIf(true, a => a.Id == 10 && c.Name == "xxx") + .WhereIf(true, a => b.ParentId == 20)); + sql = query2.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a, \"TESTTYPEINFO\" b, \"TESTTYPEPARENTINFO\" c WHERE (a.\"ID\" = 10 AND c.\"NAME\" = 'xxx') AND (b.\"PARENTID\" = 20)", sql); + query2.ToList(); + + //������϶����㲻�� + query = select.WhereIf(true, "a.\"CLICKS\" > 100 and a.\"ID\" = :id", new { id = 10 }); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a WHERE (a.\"CLICKS\" > 100 and a.\"ID\" = :id)", sql); + query.ToList(); + + // ==========================================WhereIf(false) + + //����е�������a.Type��a.Type.Parent ���ǵ������� + query = select.WhereIf(false, a => a.Id == 10); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a", sql); + query.ToList(); + + query = select.WhereIf(false, a => a.Id == 10 && a.Id > 10 || a.Clicks > 100); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a", sql); + query.ToList(); + + query = select.WhereIf(false, a => a.Id == 10).WhereIf(false, a => a.Clicks > 100); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a", sql); + query.ToList(); + + query = select.WhereIf(false, a => a.Type.Name == "typeTitle"); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a", sql); + query.ToList(); + + query = select.WhereIf(false, a => a.Type.Name == "typeTitle" && a.Type.Guid == a.TypeGuid); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a", sql); + query.ToList(); + + query = select.WhereIf(false, a => a.Type.Parent.Name == "tparent"); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a", sql); + query.ToList(); + + //����һ�� From ��Ķ������ + query2 = select.From((s, b, c) => s + .WhereIf(false, a => a.Id == 10 && c.Name == "xxx") + .WhereIf(false, a => b.ParentId == 20)); + sql = query2.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a, \"TESTTYPEINFO\" b, \"TESTTYPEPARENTINFO\" c", sql); + query2.ToList(); + + //������϶����㲻�� + query = select.WhereIf(false, "a.\"CLICKS\" > 100 and a.\"ID\" = :id", new { id = 10 }); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a", sql); + query.ToList(); + } + [Fact] + public void WhereExists() + { + var sql2222 = select.Where(a => select.Where(b => b.Id == a.Id).Any()).ToList(); + + sql2222 = select.Where(a => + select.Where(b => b.Id == a.Id && select.Where(c => c.Id == b.Id).Where(d => d.Id == a.Id).Where(e => e.Id == b.Id) + + //.Offset(a.Id) + + .Any() + ).Any() + ).ToList(); + } + [Fact] + public void GroupBy() + { + var groupby = select.From((s, b, c) => s + .Where(a => a.Id == 1) + ) + .GroupBy((a, b, c) => new { tt2 = a.Title.Substring(0, 2), mod4 = a.Id % 4 }) + .Having(a => a.Count() > 0 && a.Avg(a.Key.mod4) > 0 && a.Max(a.Key.mod4) > 0) + .Having(a => a.Count() < 300 || a.Avg(a.Key.mod4) < 100) + .OrderBy(a => a.Key.tt2) + .OrderByDescending(a => a.Count()) + .Offset(10) + .Limit(2) + .Count(out var trycount) + .ToList(a => new + { + a.Key.tt2, + cou1 = a.Count(), + cou2 = a.Count(a.Value.Item3.Id), + arg1 = a.Avg(a.Key.mod4), + ccc2 = a.Key.tt2 ?? "now()", + //ccc = Convert.ToDateTime("now()"), partby = Convert.ToDecimal("sum(num) over(PARTITION BY server_id,os,rid,chn order by id desc)") + ccc3 = a.Max(a.Value.Item3.Id) + }); + + var testpid1 = g.dameng.Insert().AppendData(new TestTypeInfo { Name = "Name" + DateTime.Now.ToString("yyyyMMddHHmmss") }).ExecuteIdentity(); + g.dameng.Insert().AppendData(new TestInfo { Title = "Title" + DateTime.Now.ToString("yyyyMMddHHmmss"), CreateTime = DateTime.Now, TypeGuid = (int)testpid1 }).ExecuteAffrows(); + + var fkfjfj = select.GroupBy(a => a.Title) + .ToList(a => a.Sum(a.Value.TypeGuid)); + + var aggsql1 = select + .GroupBy(a => a.Title) + .ToSql(b => new + { + b.Key, + cou = b.Count(), + sum2 = b.Sum(b.Value.TypeGuid) + }); + var aggtolist1 = select + .GroupBy(a => a.Title) + .ToList(b => new + { + b.Key, + cou = b.Count(), + sum2 = b.Sum(b.Value.TypeGuid) + }); + var aggtolist11 = select + .GroupBy(a => a.Title) + .ToDictionary(b => new + { + b.Key, + cou = b.Count(), + sum2 = b.Sum(b.Value.TypeGuid) + }); + + var aggsql2 = select + .GroupBy(a => new { a.Title, yyyy = string.Concat(a.CreateTime.Year, '-', a.CreateTime.Month) }) + .ToSql(b => new + { + b.Key.Title, + b.Key.yyyy, + + cou = b.Count(), + sum2 = b.Sum(b.Value.TypeGuid) + }); + var aggtolist2 = select + .GroupBy(a => new { a.Title, yyyy = string.Concat(a.CreateTime.Year, '-', a.CreateTime.Month) }) + .ToList(b => new + { + b.Key.Title, + b.Key.yyyy, + cou = b.Count(), + sum2 = b.Sum(b.Value.TypeGuid) + }); + var aggtolist22 = select + .GroupBy(a => new { a.Title, yyyy = string.Concat(a.CreateTime.Year, '-', a.CreateTime.Month) }) + .ToDictionary(b => new + { + b.Key.Title, + b.Key.yyyy, + + cou = b.Count(), + sum2 = b.Sum(b.Value.TypeGuid) + }); + + var aggsql3 = select + .GroupBy(a => a.Title) + .ToSql(b => new + { + b.Key, + cou = b.Count(), + sum2 = b.Sum(b.Value.TypeGuid), + sum3 = b.Sum(b.Value.Type.Parent.Id) + }); + } + [Fact] + public void ToAggregate() + { + var sql = select.ToAggregate(a => new { sum = a.Sum(a.Key.Id + 11.11), avg = a.Avg(a.Key.Id), count = a.Count(), max = a.Max(a.Key.Id), min = a.Min(a.Key.Id) }); + } + [Fact] + public void OrderBy() + { + var sql = select.Offset(10).OrderBy(a => new Random().NextDouble()).ToList(); + } + [Fact] + public void Skip_Offset() + { + var sql = select.Offset(10).ToList(); + } + [Fact] + public void Take_Limit() + { + var sql = select.Limit(10).ToList(); + } + [Fact] + public void Page() + { + var sql1 = select.Page(1, 10).ToList(); + var sql2 = select.Page(2, 10).ToList(); + var sql3 = select.Page(3, 10).ToList(); + + var sql11 = select.OrderBy(a => new Random().NextDouble()).Page(1, 10).ToList(); + var sql22 = select.OrderBy(a => new Random().NextDouble()).Page(2, 10).ToList(); + var sql33 = select.OrderBy(a => new Random().NextDouble()).Page(3, 10).ToList(); + } + [Fact] + public void Distinct() + { + var t1 = select.Distinct().ToList(a => a.Title); + var t2 = select.Distinct().Limit(10).ToList(a => a.Title); + } + + [Fact] + public void Sum() + { + var subquery = select.ToSql(a => new + { + all = a, + count = (long)select.As("b").Sum(b => b.Id) + }); + Assert.Equal(@"SELECT a.""ID"" as1, a.""CLICKS"" as2, a.""TYPEGUID"" as3, a.""TITLE"" as4, a.""CREATETIME"" as5, (SELECT sum(b.""ID"") + FROM ""TB_TOPIC22"" b + WHERE ROWNUM < 2) as6 +FROM ""TB_TOPIC22"" a", subquery); + var subqueryList = select.ToList(a => new + { + all = a, + count = (long)select.As("b").Sum(b => b.Id) + }); + } + [Fact] + public void Min() + { + var subquery = select.ToSql(a => new + { + all = a, + count = select.As("b").Min(b => b.Id) + }); + Assert.Equal(@"SELECT a.""ID"" as1, a.""CLICKS"" as2, a.""TYPEGUID"" as3, a.""TITLE"" as4, a.""CREATETIME"" as5, (SELECT min(b.""ID"") + FROM ""TB_TOPIC22"" b + WHERE ROWNUM < 2) as6 +FROM ""TB_TOPIC22"" a", subquery); + var subqueryList = select.ToList(a => new + { + all = a, + count = select.As("b").Min(b => b.Id) + }); + } + [Fact] + public void Max() + { + var subquery = select.ToSql(a => new + { + all = a, + count = select.As("b").Max(b => b.Id) + }); + Assert.Equal(@"SELECT a.""ID"" as1, a.""CLICKS"" as2, a.""TYPEGUID"" as3, a.""TITLE"" as4, a.""CREATETIME"" as5, (SELECT max(b.""ID"") + FROM ""TB_TOPIC22"" b + WHERE ROWNUM < 2) as6 +FROM ""TB_TOPIC22"" a", subquery); + var subqueryList = select.ToList(a => new + { + all = a, + count = select.As("b").Max(b => b.Id) + }); + } + [Fact] + public void Avg() + { + var subquery = select.ToSql(a => new + { + all = a, + count = select.As("b").Avg(b => b.Id) + }); + Assert.Equal(@"SELECT a.""ID"" as1, a.""CLICKS"" as2, a.""TYPEGUID"" as3, a.""TITLE"" as4, a.""CREATETIME"" as5, (SELECT avg(b.""ID"") + FROM ""TB_TOPIC22"" b + WHERE ROWNUM < 2) as6 +FROM ""TB_TOPIC22"" a", subquery); + var subqueryList = select.ToList(a => new + { + all = a, + count = select.As("b").Avg(b => b.Id) + }); + } + [Fact] + public void WhereIn() + { + var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.""ID"", a.""CLICKS"", a.""TYPEGUID"", a.""TITLE"", a.""CREATETIME"" +FROM ""TB_TOPIC22"" a +WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE"" + FROM ""TB_TOPIC22"" b)))", subquery); + var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + } + [Fact] + public void As() + { + } + + [Fact] + public void AsTable() + { + g.dameng.CodeFirst.SyncStructure(typeof(Topic), "TB_TOPIC"); + + var listt = select.AsTable((a, b) => "(select * from tb_topic where clicks > 10)").Page(1, 10).ToList(); + + Func tableRule = (type, oldname) => + { + if (oldname.Length > 16) oldname = oldname.Remove(16); + if (type == typeof(Topic)) return oldname + "_T1"; + else if (type == typeof(TestTypeInfo)) return oldname + "_T2"; + return oldname + "_AT"; + }; + + //����е�������a.Type��a.Type.Parent ���ǵ������� + var query = select.LeftJoin(a => a.Type.Guid == a.TypeGuid).AsTable(tableRule); + var sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22_T1\" a LEFT JOIN \"TESTTYPEINFO_T2\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\"", sql); + + query = select.LeftJoin(a => a.Type.Guid == a.TypeGuid && a.Type.Name == "xxx").AsTable(tableRule); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22_T1\" a LEFT JOIN \"TESTTYPEINFO_T2\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" AND a__Type.\"NAME\" = 'xxx'", sql); + + query = select.LeftJoin(a => a.Type.Guid == a.TypeGuid && a.Type.Name == "xxx").Where(a => a.Type.Parent.Id == 10).AsTable(tableRule); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22_T1\" a LEFT JOIN \"TESTTYPEINFO_T2\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" AND a__Type.\"NAME\" = 'xxx' LEFT JOIN \"TESTTYPEPARENTIN_AT\" a__Type__Parent ON a__Type__Parent.\"ID\" = a__Type.\"PARENTID\" WHERE (a__Type__Parent.\"ID\" = 10)", sql); + + //���û�е������� + query = select.LeftJoin((a, b) => b.Guid == a.TypeGuid).AsTable(tableRule); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", b.\"GUID\", b.\"PARENTID\", b.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22_T1\" a LEFT JOIN \"TESTTYPEINFO_T2\" b ON b.\"GUID\" = a.\"TYPEGUID\"", sql); + + query = select.LeftJoin((a, b) => b.Guid == a.TypeGuid && b.Name == "xxx").AsTable(tableRule); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", b.\"GUID\", b.\"PARENTID\", b.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22_T1\" a LEFT JOIN \"TESTTYPEINFO_T2\" b ON b.\"GUID\" = a.\"TYPEGUID\" AND b.\"NAME\" = 'xxx'", sql); + + query = select.LeftJoin((a, a__Type) => a__Type.Guid == a.TypeGuid && a__Type.Name == "xxx").Where(a => a.Type.Parent.Id == 10).AsTable(tableRule); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22_T1\" a LEFT JOIN \"TESTTYPEINFO_T2\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" AND a__Type.\"NAME\" = 'xxx' LEFT JOIN \"TESTTYPEPARENTIN_AT\" a__Type__Parent ON a__Type__Parent.\"ID\" = a__Type.\"PARENTID\" WHERE (a__Type__Parent.\"ID\" = 10)", sql); + + //������� + query = select + .LeftJoin(a => a.Type.Guid == a.TypeGuid) + .LeftJoin(a => a.Type.Parent.Id == a.Type.ParentId).AsTable(tableRule); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22_T1\" a LEFT JOIN \"TESTTYPEINFO_T2\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" LEFT JOIN \"TESTTYPEPARENTIN_AT\" a__Type__Parent ON a__Type__Parent.\"ID\" = a__Type.\"PARENTID\"", sql); + + query = select + .LeftJoin((a, a__Type) => a__Type.Guid == a.TypeGuid) + .LeftJoin((a, c) => c.Id == a.Type.ParentId).AsTable(tableRule); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a__Type.\"GUID\", a__Type.\"PARENTID\", a__Type.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22_T1\" a LEFT JOIN \"TESTTYPEINFO_T2\" a__Type ON a__Type.\"GUID\" = a.\"TYPEGUID\" LEFT JOIN \"TESTTYPEPARENTIN_AT\" c ON c.\"ID\" = a__Type.\"PARENTID\"", sql); + + //���û�е�������b��c������ϵ + var query2 = select.From((s, b, c) => s + .LeftJoin(a => a.TypeGuid == b.Guid) + .LeftJoin(a => b.ParentId == c.Id)).AsTable(tableRule); + sql = query2.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", b.\"GUID\", b.\"PARENTID\", b.\"NAME\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22_T1\" a LEFT JOIN \"TESTTYPEINFO_T2\" b ON a.\"TYPEGUID\" = b.\"GUID\" LEFT JOIN \"TESTTYPEPARENTIN_AT\" c ON b.\"PARENTID\" = c.\"ID\"", sql); + + //������϶����㲻�� + query = select.LeftJoin("\"TESTTYPEINFO\" b on b.\"GUID\" = a.\"TYPEGUID\"").AsTable(tableRule); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22_T1\" a LEFT JOIN \"TESTTYPEINFO\" b on b.\"GUID\" = a.\"TYPEGUID\"", sql); + + query = select.LeftJoin("\"TESTTYPEINFO\" b on b.\"GUID\" = a.\"TYPEGUID\" and b.\"NAME\" = :bname", new { bname = "xxx" }).AsTable(tableRule); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22_T1\" a LEFT JOIN \"TESTTYPEINFO\" b on b.\"GUID\" = a.\"TYPEGUID\" and b.\"NAME\" = :bname", sql); + + query = select.AsTable((_, old) => old).AsTable((_, old) => old); + sql = query.ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT * from (SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a) ftb UNION ALLSELECT * from (SELECT a.\"ID\", a.\"CLICKS\", a.\"TYPEGUID\", a.\"TITLE\", a.\"CREATETIME\" FROM \"TB_TOPIC22\" a) ftb", sql); + query.ToList(); + + query = select.AsTable((_, old) => old).AsTable((_, old) => old); + sql = query.ToSql("count(1) as1").Replace("\r\n", ""); + Assert.Equal("SELECT * from (SELECT count(1) as1 FROM \"TB_TOPIC22\" a) ftb UNION ALLSELECT * from (SELECT count(1) as1 FROM \"TB_TOPIC22\" a) ftb", sql); + query.Count(); + + select.AsTable((_, old) => old).AsTable((_, old) => old).Max(a => a.Id); + select.AsTable((_, old) => old).AsTable((_, old) => old).Min(a => a.Id); + select.AsTable((_, old) => old).AsTable((_, old) => old).Sum(a => a.Id); + select.AsTable((_, old) => old).AsTable((_, old) => old).Avg(a => a.Id); + + var sqlsss = select + .AsTable((type, old) => type == typeof(Topic) ? $"{old}_1" : null) + .AsTable((type, old) => type == typeof(Topic) ? $"{old}_2" : null) + .ToSql(a => new + { + a.Id, + a.Clicks + }, FieldAliasOptions.AsProperty); + + var slsld3 = select + .AsTable((type, old) => type == typeof(Topic) ? $"({sqlsss})" : null) + .Page(1, 20) + .ToList(a => new + { + a.Id, + a.Clicks + }); + } + + public class TiOtmModel1 + { + [Column(IsIdentity = true)] + public int id { get; set; } + public virtual TiOtmModel2 model2 { get; set; } + + public string m1name { get; set; } + } + public class TiOtmModel2 + { + [Column(IsPrimary = true)] + public int model2id { get; set; } + public virtual TiOtmModel1 model1 { get; set; } + + public string m2setting { get; set; } + + public List childs { get; set; } + } + public class TiOtmModel3 + { + [Column(IsIdentity = true)] + public int id { get; set; } + + public int model2111Idaaa { get; set; } + public string title { get; set; } + + public List childs2 { get; set; } + } + public class TiOtmModel4 + { + [Column(IsIdentity = true)] + public int id { get; set; } + + public int model3333Id333 { get; set; } + public string title444 { get; set; } + } + + [Fact] + public void Include_OneToMany() + { + var model1 = new TiOtmModel1 { m1name = DateTime.Now.Second.ToString() }; + model1.id = (int)g.dameng.Insert(model1).ExecuteIdentity(); + var model2 = new TiOtmModel2 { model2id = model1.id, m2setting = DateTime.Now.Second.ToString() }; + g.dameng.Insert(model2).ExecuteAffrows(); + + var model3_1 = new TiOtmModel3 { model2111Idaaa = model1.id, title = "testmodel3__111" }; + model3_1.id = (int)g.dameng.Insert(model3_1).ExecuteIdentity(); + var model3_2 = new TiOtmModel3 { model2111Idaaa = model1.id, title = "testmodel3__222" }; + model3_2.id = (int)g.dameng.Insert(model3_2).ExecuteIdentity(); + var model3_3 = new TiOtmModel3 { model2111Idaaa = model1.id, title = "testmodel3__333" }; + model3_3.id = (int)g.dameng.Insert(model3_2).ExecuteIdentity(); + + var model4s = new[] { + new TiOtmModel4{ model3333Id333 = model3_1.id, title444 = "testmodel3_4__111" }, + new TiOtmModel4{ model3333Id333 = model3_1.id, title444 = "testmodel3_4__222" }, + new TiOtmModel4{ model3333Id333 = model3_2.id, title444 = "testmodel3_4__111" }, + new TiOtmModel4{ model3333Id333 = model3_2.id, title444 = "testmodel3_4__222" }, + new TiOtmModel4{ model3333Id333 = model3_2.id, title444 = "testmodel3_4__333" } + }; + Assert.Equal(5, g.dameng.Insert(model4s).ExecuteAffrows()); + + var t0 = g.dameng.Select() + .IncludeMany(a => a.childs.Where(m3 => m3.model2111Idaaa == a.model2id)) + .Where(a => a.model2id <= model1.id) + .ToList(); + + var t1 = g.dameng.Select() + .IncludeMany(a => a.model2.childs.Where(m3 => m3.model2111Idaaa == a.model2.model2id)) + .Where(a => a.id <= model1.id) + .ToList(); + + var t2 = g.dameng.Select() + .IncludeMany(a => a.model2.childs.Where(m3 => m3.model2111Idaaa == a.model2.model2id), + then => then.IncludeMany(m3 => m3.childs2.Where(m4 => m4.model3333Id333 == m3.id))) + .Where(a => a.id <= model1.id) + .ToList(); + + var t00 = g.dameng.Select() + .IncludeMany(a => a.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2id)) + .Where(a => a.model2id <= model1.id) + .ToList(); + + var t11 = g.dameng.Select() + .IncludeMany(a => a.model2.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2.model2id)) + .Where(a => a.id <= model1.id) + .ToList(); + + var t22 = g.dameng.Select() + .IncludeMany(a => a.model2.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2.model2id), + then => then.IncludeMany(m3 => m3.childs2.Take(2).Where(m4 => m4.model3333Id333 == m3.id))) + .Where(a => a.id <= model1.id) + .ToList(); + + //---- Select ---- + + var at0 = g.dameng.Select() + .IncludeMany(a => a.childs.Where(m3 => m3.model2111Idaaa == a.model2id).Select(m3 => new TiOtmModel3 { id = m3.id })) + .Where(a => a.model2id <= model1.id) + .ToList(); + + var at1 = g.dameng.Select() + .IncludeMany(a => a.model2.childs.Where(m3 => m3.model2111Idaaa == a.model2.model2id).Select(m3 => new TiOtmModel3 { id = m3.id })) + .Where(a => a.id <= model1.id) + .ToList(); + + var at2 = g.dameng.Select() + .IncludeMany(a => a.model2.childs.Where(m3 => m3.model2111Idaaa == a.model2.model2id).Select(m3 => new TiOtmModel3 { id = m3.id }), + then => then.IncludeMany(m3 => m3.childs2.Where(m4 => m4.model3333Id333 == m3.id).Select(m4 => new TiOtmModel4 { id = m4.id }))) + .Where(a => a.id <= model1.id) + .ToList(); + + var at00 = g.dameng.Select() + .IncludeMany(a => a.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2id).Select(m3 => new TiOtmModel3 { id = m3.id })) + .Where(a => a.model2id <= model1.id) + .ToList(); + + var at11 = g.dameng.Select() + .IncludeMany(a => a.model2.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2.model2id).Select(m3 => new TiOtmModel3 { id = m3.id })) + .Where(a => a.id <= model1.id) + .ToList(); + + var at22 = g.dameng.Select() + .IncludeMany(a => a.model2.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2.model2id).Select(m3 => new TiOtmModel3 { id = m3.id }), + then => then.IncludeMany(m3 => m3.childs2.Take(2).Where(m4 => m4.model3333Id333 == m3.id).Select(m4 => new TiOtmModel4 { id = m4.id }))) + .Where(a => a.id <= model1.id) + .ToList(); + } + + public class TiOtmModel11 + { + [Column(IsIdentity = true)] + public int id { get; set; } + public int model2id { get; set; } + public string m3setting { get; set; } + public TiOtmModel22 model2 { get; set; } + public string m1name { get; set; } + } + + public class TiOtmModel22 + { + [Column(IsIdentity = true)] + public int id { get; set; } + public string m2setting { get; set; } + public string aaa { get; set; } + public string bbb { get; set; } + public List childs { get; set; } + } + public class TiOtmModel33 + { + [Column(IsIdentity = true)] + public int id { get; set; } + public int model2Id { get; set; } + public string title { get; set; } + public string setting { get; set; } + } + [Fact] + public void Include_OneToMany2() + { + string setting = "x"; + var model2 = new TiOtmModel22 { m2setting = DateTime.Now.Second.ToString(), aaa = "aaa" + DateTime.Now.Second, bbb = "bbb" + DateTime.Now.Second }; + model2.id = (int)g.dameng.Insert(model2).ExecuteIdentity(); + + var model3s = new[] + { + new TiOtmModel33 {model2Id = model2.id, title = "testmodel3__111", setting = setting}, + new TiOtmModel33 {model2Id = model2.id, title = "testmodel3__222", setting = setting}, + new TiOtmModel33 {model2Id = model2.id, title = "testmodel3__333", setting = setting} + }; + Assert.Equal(3, g.dameng.Insert(model3s).ExecuteAffrows()); + + var model1 = new TiOtmModel11 { m1name = DateTime.Now.Second.ToString(), model2id = model2.id, m3setting = setting }; + model1.id = (int)g.dameng.Insert(model1).ExecuteIdentity(); + + var t1 = g.dameng.Select() + .LeftJoin(a => a.model2id == a.model2.id) + .IncludeMany(a => a.model2.childs.Where(m3 => m3.model2Id == a.model2.id && m3.setting == a.m3setting)) + .Where(a => a.id <= model1.id) + .ToList(true); + + var t11 = g.dameng.Select() + .LeftJoin(a => a.model2id == a.model2.id) + .IncludeMany(a => a.model2.childs.Take(1).Where(m3 => m3.model2Id == a.model2.id && m3.setting == a.m3setting)) + .Where(a => a.id <= model1.id) + .ToList(true); + + //---- Select ---- + + var at1 = g.dameng.Select() + .LeftJoin(a => a.model2id == a.model2.id) + .IncludeMany(a => a.model2.childs.Where(m3 => m3.model2Id == a.model2.id && m3.setting == a.m3setting).Select(m3 => new TiOtmModel33 { title = m3.title })) + .Where(a => a.id <= model1.id) + .ToList(true); + + var at11 = g.dameng.Select() + .LeftJoin(a => a.model2id == a.model2.id) + .IncludeMany(a => a.model2.childs.Take(1).Where(m3 => m3.model2Id == a.model2.id && m3.setting == a.m3setting).Select(m3 => new TiOtmModel33 { title = m3.title })) + .Where(a => a.id <= model1.id) + .ToList(true); + } + + [Fact] + public void Include_OneToChilds() + { + var tag1 = new Tag + { + Ddd = DateTime.Now.Second, + Name = "test_oneToChilds_01_中国" + }; + tag1.Id = (int)g.dameng.Insert(tag1).ExecuteIdentity(); + var tag1_1 = new Tag + { + Parent_id = tag1.Id, + Ddd = DateTime.Now.Second, + Name = "test_oneToChilds_01_北京" + }; + tag1_1.Id = (int)g.dameng.Insert(tag1_1).ExecuteIdentity(); + var tag1_2 = new Tag + { + Parent_id = tag1.Id, + Ddd = DateTime.Now.Second, + Name = "test_oneToChilds_01_上海" + }; + tag1_2.Id = (int)g.dameng.Insert(tag1_2).ExecuteIdentity(); + + var tag2 = new Tag + { + Ddd = DateTime.Now.Second, + Name = "test_oneToChilds_02_美国" + }; + tag2.Id = (int)g.dameng.Insert(tag2).ExecuteIdentity(); + var tag2_1 = new Tag + { + Parent_id = tag2.Id, + Ddd = DateTime.Now.Second, + Name = "test_oneToChilds_02_纽约" + }; + tag2_1.Id = (int)g.dameng.Insert(tag2_1).ExecuteIdentity(); + var tag2_2 = new Tag + { + Parent_id = tag2.Id, + Ddd = DateTime.Now.Second, + Name = "test_oneToChilds_02_华盛顿" + }; + tag2_2.Id = (int)g.dameng.Insert(tag2_2).ExecuteIdentity(); + + var tags0 = g.dameng.Select() + .Include(a => a.Parent) + .Where(a => a.Id == tag1.Id || a.Id == tag2.Id) + .ToList(); + + var tags1 = g.dameng.Select() + .IncludeMany(a => a.Tags) + .Include(a => a.Parent) + .IncludeMany(a => a.Songs) + .Where(a => a.Id == tag1.Id || a.Id == tag2.Id) + .ToList(); + + var tags2 = g.dameng.Select() + .IncludeMany(a => a.Tags, + then => then.Include(a => a.Parent).IncludeMany(a => a.Songs)) + .Include(a => a.Parent) + .IncludeMany(a => a.Songs) + .Where(a => a.Id == tag1.Id || a.Id == tag2.Id) + .ToList(); + + var tags3 = g.dameng.Select() + .IncludeMany(a => a.Tags, + then => then.Include(a => a.Parent).IncludeMany(a => a.Songs).IncludeMany(a => a.Tags)) + .Include(a => a.Parent) + .IncludeMany(a => a.Songs) + .Where(a => a.Id == tag1.Id || a.Id == tag2.Id) + .ToList(); + + var tags11 = g.dameng.Select() + .IncludeMany(a => a.Tags.Take(1)) + .Include(a => a.Parent) + .IncludeMany(a => a.Songs.Take(1)) + .Where(a => a.Id == tag1.Id || a.Id == tag2.Id) + .ToList(); + + var tags22 = g.dameng.Select() + .IncludeMany(a => a.Tags.Take(1), + then => then.Include(a => a.Parent).IncludeMany(a => a.Songs.Take(1))) + .Include(a => a.Parent) + .IncludeMany(a => a.Songs.Take(1)) + .Where(a => a.Id == tag1.Id || a.Id == tag2.Id) + .ToList(); + + var tags33 = g.dameng.Select() + .IncludeMany(a => a.Tags.Take(1), + then => then.Include(a => a.Parent).IncludeMany(a => a.Songs.Take(1)).IncludeMany(a => a.Tags.Take(1))) + .Include(a => a.Parent) + .IncludeMany(a => a.Songs.Take(1)) + .Where(a => a.Id == tag1.Id || a.Id == tag2.Id) + .ToList(); + + // --- Select --- + + var atags0 = g.dameng.Select() + .Include(a => a.Parent) + .Where(a => a.Id == tag1.Id || a.Id == tag2.Id) + .ToList(); + + var atags1 = g.dameng.Select() + .IncludeMany(a => a.Tags.Select(b => new Tag { Id = b.Id, Name = b.Name })) + .Include(a => a.Parent) + .IncludeMany(a => a.Songs.Select(b => new Song { Id = b.Id, Title = b.Title })) + .Where(a => a.Id == tag1.Id || a.Id == tag2.Id) + .ToList(); + + var atags2 = g.dameng.Select() + .IncludeMany(a => a.Tags.Select(b => new Tag { Id = b.Id, Name = b.Name }), + then => then.Include(a => a.Parent).IncludeMany(a => a.Songs)) + .Include(a => a.Parent) + .IncludeMany(a => a.Songs.Select(b => new Song { Id = b.Id, Title = b.Title })) + .Where(a => a.Id == tag1.Id || a.Id == tag2.Id) + .ToList(); + + var atags3 = g.dameng.Select() + .IncludeMany(a => a.Tags.Select(b => new Tag { Id = b.Id, Name = b.Name }), + then => then.Include(a => a.Parent).IncludeMany(a => a.Songs.Select(b => new Song { Id = b.Id, Title = b.Title })).IncludeMany(a => a.Tags.Select(b => new Tag { Id = b.Id, Name = b.Name }))) + .Include(a => a.Parent) + .IncludeMany(a => a.Songs.Select(b => new Song { Id = b.Id, Title = b.Title })) + .Where(a => a.Id == tag1.Id || a.Id == tag2.Id) + .ToList(); + + var atags11 = g.dameng.Select() + .IncludeMany(a => a.Tags.Take(1).Select(b => new Tag { Id = b.Id, Name = b.Name })) + .Include(a => a.Parent) + .IncludeMany(a => a.Songs.Take(1).Select(b => new Song { Id = b.Id, Title = b.Title })) + .Where(a => a.Id == tag1.Id || a.Id == tag2.Id) + .ToList(); + + var atags22 = g.dameng.Select() + .IncludeMany(a => a.Tags.Take(1).Select(b => new Tag { Id = b.Id, Name = b.Name }), + then => then.Include(a => a.Parent).IncludeMany(a => a.Songs.Take(1).Select(b => new Song { Id = b.Id, Title = b.Title }))) + .Include(a => a.Parent) + .IncludeMany(a => a.Songs.Take(1).Select(b => new Song { Id = b.Id, Title = b.Title })) + .Where(a => a.Id == tag1.Id || a.Id == tag2.Id) + .ToList(); + + var atags33 = g.dameng.Select() + .IncludeMany(a => a.Tags.Take(1).Select(b => new Tag { Id = b.Id, Name = b.Name }), + then => then.Include(a => a.Parent).IncludeMany(a => a.Songs.Take(1).Select(b => new Song { Id = b.Id, Title = b.Title })).IncludeMany(a => a.Tags.Take(1).Select(b => new Tag { Id = b.Id, Name = b.Name }))) + .Include(a => a.Parent) + .IncludeMany(a => a.Songs.Take(1).Select(b => new Song { Id = b.Id, Title = b.Title })) + .Where(a => a.Id == tag1.Id || a.Id == tag2.Id) + .ToList(); + } + + [Fact] + public void Include_ManyToMany() + { + + var tag1 = new Tag + { + Ddd = DateTime.Now.Second, + Name = "test_manytoMany_01_中国" + }; + tag1.Id = (int)g.dameng.Insert(tag1).ExecuteIdentity(); + var tag2 = new Tag + { + Ddd = DateTime.Now.Second, + Name = "test_manytoMany_02_美国" + }; + tag2.Id = (int)g.dameng.Insert(tag2).ExecuteIdentity(); + var tag3 = new Tag + { + Ddd = DateTime.Now.Second, + Name = "test_manytoMany_03_日本" + }; + tag3.Id = (int)g.dameng.Insert(tag3).ExecuteIdentity(); + + var song1 = new Song + { + Create_time = DateTime.Now, + Title = "test_manytoMany_01_我是中国人.mp3", + Url = "http://ww.baidu.com/" + }; + song1.Id = (int)g.dameng.Insert(song1).ExecuteIdentity(); + var song2 = new Song + { + Create_time = DateTime.Now, + Title = "test_manytoMany_02_爱你一万年.mp3", + Url = "http://ww.163.com/" + }; + song2.Id = (int)g.dameng.Insert(song2).ExecuteIdentity(); + var song3 = new Song + { + Create_time = DateTime.Now, + Title = "test_manytoMany_03_千年等一回.mp3", + Url = "http://ww.sina.com/" + }; + song3.Id = (int)g.dameng.Insert(song3).ExecuteIdentity(); + + g.dameng.Insert(new Song_tag { Song_id = song1.Id, Tag_id = tag1.Id }).ExecuteAffrows(); + g.dameng.Insert(new Song_tag { Song_id = song2.Id, Tag_id = tag1.Id }).ExecuteAffrows(); + g.dameng.Insert(new Song_tag { Song_id = song3.Id, Tag_id = tag1.Id }).ExecuteAffrows(); + g.dameng.Insert(new Song_tag { Song_id = song1.Id, Tag_id = tag2.Id }).ExecuteAffrows(); + g.dameng.Insert(new Song_tag { Song_id = song3.Id, Tag_id = tag2.Id }).ExecuteAffrows(); + g.dameng.Insert(new Song_tag { Song_id = song3.Id, Tag_id = tag3.Id }).ExecuteAffrows(); + + var songs1 = g.dameng.Select() + .IncludeMany(a => a.Tags) + .Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id) + .ToList(); + Assert.Equal(3, songs1.Count); + Assert.Equal(2, songs1[0].Tags.Count); + Assert.Equal(1, songs1[1].Tags.Count); + Assert.Equal(3, songs1[2].Tags.Count); + + var songs2 = g.dameng.Select() + .IncludeMany(a => a.Tags, + then => then.IncludeMany(t => t.Songs)) + .Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id) + .ToList(); + Assert.Equal(3, songs2.Count); + Assert.Equal(2, songs2[0].Tags.Count); + Assert.Equal(1, songs2[1].Tags.Count); + Assert.Equal(3, songs2[2].Tags.Count); + + var tags3 = g.dameng.Select() + .Include(a => a.Tag.Parent) + .IncludeMany(a => a.Tag.Songs) + .Where(a => a.Tag.Id == tag1.Id || a.Tag.Id == tag2.Id) + .ToList(true); + + + var songs11 = g.dameng.Select() + .IncludeMany(a => a.Tags.Take(1)) + .Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id) + .ToList(); + Assert.Equal(3, songs11.Count); + Assert.Equal(1, songs11[0].Tags.Count); + Assert.Equal(1, songs11[1].Tags.Count); + Assert.Equal(1, songs11[2].Tags.Count); + + var songs22 = g.dameng.Select() + .IncludeMany(a => a.Tags.Take(1), + then => then.IncludeMany(t => t.Songs.Take(1))) + .Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id) + .ToList(); + Assert.Equal(3, songs22.Count); + Assert.Equal(1, songs22[0].Tags.Count); + Assert.Equal(1, songs22[1].Tags.Count); + Assert.Equal(1, songs22[2].Tags.Count); + + var tags33 = g.dameng.Select() + .Include(a => a.Tag.Parent) + .IncludeMany(a => a.Tag.Songs.Take(1)) + .Where(a => a.Tag.Id == tag1.Id || a.Tag.Id == tag2.Id) + .ToList(true); + + // --- Select --- + + new List(new[] { song1, song2, song3 }).IncludeMany(g.dameng, a => a.Tags.Select(b => new Tag { Id = b.Id, Name = b.Name })); + + var asongs1 = g.dameng.Select() + .IncludeMany(a => a.Tags.Select(b => new Tag { Id = b.Id, Name = b.Name })) + .Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id) + .ToList(); + Assert.Equal(3, songs1.Count); + Assert.Equal(2, songs1[0].Tags.Count); + Assert.Equal(1, songs1[1].Tags.Count); + Assert.Equal(3, songs1[2].Tags.Count); + + var asongs2 = g.dameng.Select() + .IncludeMany(a => a.Tags.Select(b => new Tag { Id = b.Id, Name = b.Name }), + then => then.IncludeMany(t => t.Songs.Select(b => new Song { Id = b.Id, Title = b.Title }))) + .Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id) + .ToList(); + Assert.Equal(3, songs2.Count); + Assert.Equal(2, songs2[0].Tags.Count); + Assert.Equal(1, songs2[1].Tags.Count); + Assert.Equal(3, songs2[2].Tags.Count); + + var atags3 = g.dameng.Select() + .Include(a => a.Tag.Parent) + .IncludeMany(a => a.Tag.Songs.Select(b => new Song { Id = b.Id, Title = b.Title })) + .Where(a => a.Tag.Id == tag1.Id || a.Tag.Id == tag2.Id) + .ToList(true); + + + var asongs11 = g.dameng.Select() + .IncludeMany(a => a.Tags.Take(1).Select(b => new Tag { Id = b.Id, Name = b.Name })) + .Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id) + .ToList(); + Assert.Equal(3, songs11.Count); + Assert.Equal(1, songs11[0].Tags.Count); + Assert.Equal(1, songs11[1].Tags.Count); + Assert.Equal(1, songs11[2].Tags.Count); + + var asongs22 = g.dameng.Select() + .IncludeMany(a => a.Tags.Take(1).Select(b => new Tag { Id = b.Id, Name = b.Name }), + then => then.IncludeMany(t => t.Songs.Take(1).Select(b => new Song { Id = b.Id, Title = b.Title }))) + .Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id) + .ToList(); + Assert.Equal(3, songs22.Count); + Assert.Equal(1, songs22[0].Tags.Count); + Assert.Equal(1, songs22[1].Tags.Count); + Assert.Equal(1, songs22[2].Tags.Count); + + var atags33 = g.dameng.Select() + .Include(a => a.Tag.Parent) + .IncludeMany(a => a.Tag.Songs.Take(1).Select(b => new Song { Id = b.Id, Title = b.Title })) + .Where(a => a.Tag.Id == tag1.Id || a.Tag.Id == tag2.Id) + .ToList(true); + } + + public class ToDel1Pk + { + [Column(IsIdentity = true)] + public int id { get; set; } + public string name { get; set; } + } + public class ToDel2Pk + { + [Column(IsPrimary = true)] + public Guid pk1 { get; set; } + [Column(IsPrimary = true)] + public string pk2 { get; set; } + public string name { get; set; } + } + public class ToDel3Pk + { + [Column(IsPrimary = true)] + public Guid pk1 { get; set; } + [Column(IsPrimary = true)] + public int pk2 { get; set; } + [Column(IsPrimary = true)] + public string pk3 { get; set; } + public string name { get; set; } + } + [Fact] + public void ToDelete() + { + g.dameng.Select().ToDelete().ExecuteAffrows(); + Assert.Equal(0, g.dameng.Select().Count()); + g.dameng.Insert(new[] { + new ToDel1Pk{ name = "name1"}, + new ToDel1Pk{ name = "name2"}, + new ToDel1Pk{ name = "nick1"}, + new ToDel1Pk{ name = "nick2"}, + new ToDel1Pk{ name = "nick3"} + }).ExecuteAffrows(); + Assert.Equal(2, g.dameng.Select().Where(a => a.name.StartsWith("name")).ToDelete().ExecuteAffrows()); + Assert.Equal(3, g.dameng.Select().Count()); + Assert.Equal(3, g.dameng.Select().Where(a => a.name.StartsWith("nick")).Count()); + + g.dameng.Select().ToDelete().ExecuteAffrows(); + Assert.Equal(0, g.dameng.Select().Count()); + g.dameng.Insert(new[] { + new ToDel2Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = "pk2", name = "name1"}, + new ToDel2Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = "pk2", name = "name2"}, + new ToDel2Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = "pk2", name = "nick1"}, + new ToDel2Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = "pk2", name = "nick2"}, + new ToDel2Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = "pk2", name = "nick3"} + }).ExecuteAffrows(); + Assert.Equal(2, g.dameng.Select().Where(a => a.name.StartsWith("name")).ToDelete().ExecuteAffrows()); + Assert.Equal(3, g.dameng.Select().Count()); + Assert.Equal(3, g.dameng.Select().Where(a => a.name.StartsWith("nick")).Count()); + + g.dameng.Select().ToDelete().ExecuteAffrows(); + Assert.Equal(0, g.dameng.Select().Count()); + g.dameng.Insert(new[] { + new ToDel3Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = 1, pk3 = "pk3", name = "name1"}, + new ToDel3Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = 1, pk3 = "pk3", name = "name2"}, + new ToDel3Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = 1, pk3 = "pk3", name = "nick1"}, + new ToDel3Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = 1, pk3 = "pk3", name = "nick2"}, + new ToDel3Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = 1, pk3 = "pk3", name = "nick3"} + }).ExecuteAffrows(); + Assert.Equal(2, g.dameng.Select().Where(a => a.name.StartsWith("name")).ToDelete().ExecuteAffrows()); + Assert.Equal(3, g.dameng.Select().Count()); + Assert.Equal(3, g.dameng.Select().Where(a => a.name.StartsWith("nick")).Count()); + } + + public class ToUpd1Pk + { + [Column(IsIdentity = true)] + public int id { get; set; } + public string name { get; set; } + } + public class ToUpd2Pk + { + [Column(IsPrimary = true)] + public Guid pk1 { get; set; } + [Column(IsPrimary = true)] + public string pk2 { get; set; } + public string name { get; set; } + } + public class ToUpd3Pk + { + [Column(IsPrimary = true)] + public Guid pk1 { get; set; } + [Column(IsPrimary = true)] + public int pk2 { get; set; } + [Column(IsPrimary = true)] + public string pk3 { get; set; } + public string name { get; set; } + } + [Fact] + public void ToUpdate() + { + g.dameng.Select().ToDelete().ExecuteAffrows(); + Assert.Equal(0, g.dameng.Select().Count()); + g.dameng.Insert(new[] { + new ToUpd1Pk{ name = "name1"}, + new ToUpd1Pk{ name = "name2"}, + new ToUpd1Pk{ name = "nick1"}, + new ToUpd1Pk{ name = "nick2"}, + new ToUpd1Pk{ name = "nick3"} + }).ExecuteAffrows(); + Assert.Equal(2, g.dameng.Select().Where(a => a.name.StartsWith("name")).ToUpdate().Set(a => a.name, "nick?").ExecuteAffrows()); + Assert.Equal(5, g.dameng.Select().Count()); + Assert.Equal(5, g.dameng.Select().Where(a => a.name.StartsWith("nick")).Count()); + + g.dameng.Select().ToDelete().ExecuteAffrows(); + Assert.Equal(0, g.dameng.Select().Count()); + g.dameng.Insert(new[] { + new ToUpd2Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = "pk2", name = "name1"}, + new ToUpd2Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = "pk2", name = "name2"}, + new ToUpd2Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = "pk2", name = "nick1"}, + new ToUpd2Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = "pk2", name = "nick2"}, + new ToUpd2Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = "pk2", name = "nick3"} + }).ExecuteAffrows(); + Assert.Equal(2, g.dameng.Select().Where(a => a.name.StartsWith("name")).ToUpdate().Set(a => a.name, "nick?").ExecuteAffrows()); + Assert.Equal(5, g.dameng.Select().Count()); + Assert.Equal(5, g.dameng.Select().Where(a => a.name.StartsWith("nick")).Count()); + + g.dameng.Select().ToDelete().ExecuteAffrows(); + Assert.Equal(0, g.dameng.Select().Count()); + g.dameng.Insert(new[] { + new ToUpd3Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = 1, pk3 = "pk3", name = "name1"}, + new ToUpd3Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = 1, pk3 = "pk3", name = "name2"}, + new ToUpd3Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = 1, pk3 = "pk3", name = "nick1"}, + new ToUpd3Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = 1, pk3 = "pk3", name = "nick2"}, + new ToUpd3Pk{ pk1 = FreeUtil.NewMongodbId(), pk2 = 1, pk3 = "pk3", name = "nick3"} + }).ExecuteAffrows(); + Assert.Equal(2, g.dameng.Select().Where(a => a.name.StartsWith("name")).ToUpdate().Set(a => a.name, "nick?").ExecuteAffrows()); + Assert.Equal(5, g.dameng.Select().Count()); + Assert.Equal(5, g.dameng.Select().Where(a => a.name.StartsWith("nick")).Count()); + } + + [Fact] + public void ForUpdate() + { + var orm = g.dameng; + + Assert.Equal("安全起见,请务必在事务开启之后,再使用 ForUpdate", + Assert.Throws(() => orm.Select().ForUpdate().Limit(1).ToList())?.Message); + + orm.Transaction(() => + { + var sql = orm.Select().ForUpdate().Limit(1).ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"NAME\" FROM \"TOUPD1PK\" a WHERE ROWNUM < 2 for update", sql); + orm.Select().ForUpdate().Limit(1).ToList(); + + sql = orm.Select().ForUpdate(true).Limit(1).ToSql().Replace("\r\n", ""); + Assert.Equal("SELECT a.\"ID\", a.\"NAME\" FROM \"TOUPD1PK\" a WHERE ROWNUM < 2 for update nowait", sql); + orm.Select().ForUpdate(true).Limit(1).ToList(); + }); + } + + [Fact] + public void ToTreeList() + { + var fsql = g.dameng; + fsql.Delete().Where("1=1").ExecuteAffrows(); + var repo = fsql.GetRepository(); + repo.DbContextOptions.EnableAddOrUpdateNavigateList = true; + repo.DbContextOptions.NoneParameter = true; + repo.Insert(new VM_District_Child + { + Code = "100000", + Name = "中国", + Childs = new List(new[] { + new VM_District_Child + { + Code = "110000", + Name = "北京市", + Childs = new List(new[] { + new VM_District_Child{ Code="110100", Name = "北京市" }, + new VM_District_Child{ Code="110101", Name = "东城区" }, + }) + } + }) + }); + + var t1 = fsql.Select() + .InnerJoin(a => a.ParentCode == a.Parent.Code) + .Where(a => a.Code == "110101") + .ToList(true); + Assert.Single(t1); + Assert.Equal("110101", t1[0].Code); + Assert.NotNull(t1[0].Parent); + Assert.Equal("110000", t1[0].Parent.Code); + + var t2 = fsql.Select() + .InnerJoin(a => a.ParentCode == a.Parent.Code) + .InnerJoin(a => a.Parent.ParentCode == a.Parent.Parent.Code) + .Where(a => a.Code == "110101") + .ToList(true); + Assert.Single(t2); + Assert.Equal("110101", t2[0].Code); + Assert.NotNull(t2[0].Parent); + Assert.Equal("110000", t2[0].Parent.Code); + Assert.NotNull(t2[0].Parent.Parent); + Assert.Equal("100000", t2[0].Parent.Parent.Code); + + var t3 = fsql.Select().ToTreeList(); + Assert.Single(t3); + Assert.Equal("100000", t3[0].Code); + Assert.Single(t3[0].Childs); + Assert.Equal("110000", t3[0].Childs[0].Code); + Assert.Equal(2, t3[0].Childs[0].Childs.Count); + Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code); + Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code); + } + + [Table(Name = "D_District")] + public class BaseDistrict + { + [Column(IsPrimary = true, StringLength = 6)] + public string Code { get; set; } + + [Column(StringLength = 20, IsNullable = false)] + public string Name { get; set; } + + [Column(StringLength = 6)] + public virtual string ParentCode { get; set; } + } + [Table(Name = "D_District", DisableSyncStructure = true)] + public class VM_District_Child : BaseDistrict + { + public override string ParentCode { get => base.ParentCode; set => base.ParentCode = value; } + + [Navigate(nameof(ParentCode))] + public List Childs { get; set; } + } + [Table(Name = "D_District", DisableSyncStructure = true)] + public class VM_District_Parent : BaseDistrict + { + public override string ParentCode { get => base.ParentCode; set => base.ParentCode = value; } + + [Navigate(nameof(ParentCode))] + public VM_District_Parent Parent { get; set; } + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengUpdateTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengUpdateTest.cs new file mode 100644 index 00000000..d9160ab9 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengUpdateTest.cs @@ -0,0 +1,173 @@ +using FreeSql.DataAnnotations; +using System; +using System.Collections.Generic; +using Xunit; + +namespace FreeSql.Tests.Dameng +{ + public class DamengUpdateTest + { + IUpdate update => g.dameng.Update(); + + [Table(Name = "tb_topic")] + class Topic + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + public int? Clicks { get; set; } + public TestTypeInfo Type { get; set; } + public string Title { get; set; } + public DateTime CreateTime { get; set; } + } + + [Fact] + public void Dywhere() + { + Assert.Null(g.dameng.Update().ToSql()); + Assert.Equal("UPDATE \"TB_TOPIC\" SET title='test' \r\nWHERE (\"ID\" = 1 OR \"ID\" = 2)", g.dameng.Update(new[] { 1, 2 }).SetRaw("title='test'").ToSql()); + Assert.Equal("UPDATE \"TB_TOPIC\" SET title='test1' \r\nWHERE (\"ID\" = 1)", g.dameng.Update(new Topic { Id = 1, Title = "test" }).SetRaw("title='test1'").ToSql()); + Assert.Equal("UPDATE \"TB_TOPIC\" SET title='test1' \r\nWHERE (\"ID\" = 1 OR \"ID\" = 2)", g.dameng.Update(new[] { new Topic { Id = 1, Title = "test" }, new Topic { Id = 2, Title = "test" } }).SetRaw("title='test1'").ToSql()); + Assert.Equal("UPDATE \"TB_TOPIC\" SET title='test1' \r\nWHERE (\"ID\" = 1)", g.dameng.Update(new { id = 1 }).SetRaw("title='test1'").ToSql()); + } + + [Fact] + public void SetSource() + { + var sql = update.SetSource(new Topic { Id = 1, Title = "newtitle" }).ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET \"CLICKS\" = NULL, \"TITLE\" = 'newtitle', \"CREATETIME\" = to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6') WHERE (\"ID\" = 1)", sql); + + var items = new List(); + for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100 }); + items[0].Clicks = null; + + sql = update.SetSource(items).ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET \"CLICKS\" = CASE \"ID\" WHEN 1 THEN NULL WHEN 2 THEN 100 WHEN 3 THEN 200 WHEN 4 THEN 300 WHEN 5 THEN 400 WHEN 6 THEN 500 WHEN 7 THEN 600 WHEN 8 THEN 700 WHEN 9 THEN 800 WHEN 10 THEN 900 END, \"TITLE\" = CASE \"ID\" WHEN 1 THEN 'newtitle0' WHEN 2 THEN 'newtitle1' WHEN 3 THEN 'newtitle2' WHEN 4 THEN 'newtitle3' WHEN 5 THEN 'newtitle4' WHEN 6 THEN 'newtitle5' WHEN 7 THEN 'newtitle6' WHEN 8 THEN 'newtitle7' WHEN 9 THEN 'newtitle8' WHEN 10 THEN 'newtitle9' END, \"CREATETIME\" = CASE \"ID\" WHEN 1 THEN to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6') WHEN 2 THEN to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6') WHEN 3 THEN to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6') WHEN 4 THEN to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6') WHEN 5 THEN to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6') WHEN 6 THEN to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6') WHEN 7 THEN to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6') WHEN 8 THEN to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6') WHEN 9 THEN to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6') WHEN 10 THEN to_timestamp('0001-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6') END WHERE (\"ID\" IN (1,2,3,4,5,6,7,8,9,10))", sql); + + sql = update.SetSource(items).IgnoreColumns(a => new { a.Clicks, a.CreateTime }).ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET \"TITLE\" = CASE \"ID\" WHEN 1 THEN 'newtitle0' WHEN 2 THEN 'newtitle1' WHEN 3 THEN 'newtitle2' WHEN 4 THEN 'newtitle3' WHEN 5 THEN 'newtitle4' WHEN 6 THEN 'newtitle5' WHEN 7 THEN 'newtitle6' WHEN 8 THEN 'newtitle7' WHEN 9 THEN 'newtitle8' WHEN 10 THEN 'newtitle9' END WHERE (\"ID\" IN (1,2,3,4,5,6,7,8,9,10))", sql); + + sql = update.SetSource(items).Set(a => a.CreateTime, new DateTime(2020, 1, 1)).ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET \"CREATETIME\" = to_timestamp('2020-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6') WHERE (\"ID\" IN (1,2,3,4,5,6,7,8,9,10))", sql); + + if (g.dameng.Select().Where(a => a.id1 == 1 && a.id2 == 7).Any() == false) + g.dameng.Insert(new ts_source_mpk { id1 = 1, id2 = 7 }).ExecuteAffrows(); + if (g.dameng.Select().Where(a => a.id1 == 1 && a.id2 == 8).Any() == false) + g.dameng.Insert(new ts_source_mpk { id1 = 1, id2 = 8 }).ExecuteAffrows(); + + sql = g.dameng.Update().SetSource(new[] { + new ts_source_mpk { id1 = 1, id2 = 7, xx = "a1" }, + new ts_source_mpk { id1 = 1, id2 = 8, xx = "b122" } + }).NoneParameter().ToSql().Replace("\r\n", ""); + g.dameng.Update().SetSource(new[] { + new ts_source_mpk { id1 = 1, id2 = 7, xx = "a1" }, + new ts_source_mpk { id1 = 1, id2 = 8, xx = "b122" } + }).NoneParameter().ExecuteAffrows(); + var testlist = g.dameng.Select().ToList(); + } + public class ts_source_mpk + { + [Column(IsPrimary = true)] + public int id1 { get; set; } + [Column(IsPrimary = true)] + public int id2 { get; set; } + public string xx { get; set; } + } + [Fact] + public void IgnoreColumns() + { + var sql = update.SetSource(new Topic { Id = 1, Title = "newtitle" }).IgnoreColumns(a => new { a.Clicks, a.CreateTime }).ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET \"TITLE\" = 'newtitle' WHERE (\"ID\" = 1)", sql); + } + [Fact] + public void UpdateColumns() + { + var sql = update.SetSource(new Topic { Id = 1, Title = "newtitle" }).UpdateColumns(a => a.Title).ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET \"TITLE\" = 'newtitle' WHERE (\"ID\" = 1)", sql); + } + [Fact] + public void Set() + { + var sql = update.Where(a => a.Id == 1).Set(a => a.Title, "newtitle").ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET \"TITLE\" = 'newtitle' WHERE (\"ID\" = 1)", sql); + + sql = update.Where(a => a.Id == 1).Set(a => a.Title, "newtitle").Set(a => a.CreateTime, new DateTime(2020, 1, 1)).ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET \"TITLE\" = 'newtitle', \"CREATETIME\" = to_timestamp('2020-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6') WHERE (\"ID\" = 1)", sql); + + sql = update.Set(a => a.Clicks * 10 / 1).Where(a => a.Id == 1).ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET \"CLICKS\" = trunc(nvl(\"CLICKS\", 0) * 10 / 1) WHERE (\"ID\" = 1)", sql); + + sql = update.Set(a => a.Id - 10).Where(a => a.Id == 1).ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET \"ID\" = (\"ID\" - 10) WHERE (\"ID\" = 1)", sql); + + int incrv = 10; + sql = update.Set(a => a.Clicks * incrv / 1).Where(a => a.Id == 1).ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET \"CLICKS\" = trunc(nvl(\"CLICKS\", 0) * 10 / 1) WHERE (\"ID\" = 1)", sql); + + sql = update.Set(a => a.Id - incrv).Where(a => a.Id == 1).ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET \"ID\" = (\"ID\" - 10) WHERE (\"ID\" = 1)", sql); + + sql = update.Set(a => a.Clicks == a.Clicks * 10 / 1).Where(a => a.Id == 1).ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET \"CLICKS\" = trunc(\"CLICKS\" * 10 / 1) WHERE (\"ID\" = 1)", sql); + + var dt2000 = DateTime.Parse("2000-01-01"); + sql = update.Set(a => a.Clicks == (a.CreateTime > dt2000 ? 1 : 2)).Where(a => a.Id == 1).ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET \"CLICKS\" = case when \"CREATETIME\" > to_timestamp('2000-01-01 00:00:00.000000','YYYY-MM-DD HH24:MI:SS.FF6') then 1 else 2 end WHERE (\"ID\" = 1)", sql); + + sql = update.Set(a => a.Id == 10).Where(a => a.Id == 1).ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET \"ID\" = 10 WHERE (\"ID\" = 1)", sql); + } + [Fact] + public void SetRaw() + { + var sql = update.Where(a => a.Id == 1).SetRaw("clicks = clicks + ?", new { incrClick = 1 }).ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET clicks = clicks + ? WHERE (\"ID\" = 1)", sql); + } + [Fact] + public void SetDto() + { + var sql = update.SetDto(new { clicks = 1, title = "xxx" }).Where(a => a.Id == 1).ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET \"CLICKS\" = 1, \"TITLE\" = 'xxx' WHERE (\"ID\" = 1)", sql); + + sql = update.SetDto(new Dictionary { ["clicks"] = 1, ["title"] = "xxx" }).Where(a => a.Id == 1).ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET \"CLICKS\" = 1, \"TITLE\" = 'xxx' WHERE (\"ID\" = 1)", sql); + } + [Fact] + public void Where() + { + var sql = update.Where(a => a.Id == 1).SetRaw("title='newtitle'").ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET title='newtitle' WHERE (\"ID\" = 1)", sql); + + sql = update.Where("id = ?", new { id = 1 }).SetRaw("title='newtitle'").ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET title='newtitle' WHERE (id = ?)", sql); + + var item = new Topic { Id = 1, Title = "newtitle" }; + sql = update.Where(item).SetRaw("title='newtitle'").ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET title='newtitle' WHERE (\"ID\" = 1)", sql); + + var items = new List(); + for (var a = 0; a < 10; a++) items.Add(new Topic { Id = a + 1, Title = $"newtitle{a}", Clicks = a * 100 }); + sql = update.Where(items).SetRaw("title='newtitle'").ToSql().Replace("\r\n", ""); + Assert.Equal("UPDATE \"TB_TOPIC\" SET title='newtitle' WHERE (\"ID\" IN (1,2,3,4,5,6,7,8,9,10))", sql); + } + [Fact] + public void ExecuteAffrows() + { + + } + [Fact] + public void ExecuteUpdated() + { + + } + + [Fact] + public void AsTable() + { + Assert.Null(g.dameng.Update().ToSql()); + Assert.Equal("UPDATE \"TB_TOPICASTABLE\" SET title='test' \r\nWHERE (\"ID\" = 1 OR \"ID\" = 2)", g.dameng.Update(new[] { 1, 2 }).SetRaw("title='test'").AsTable(a => "tb_topicAsTable").ToSql()); + Assert.Equal("UPDATE \"TB_TOPICASTABLE\" SET title='test1' \r\nWHERE (\"ID\" = 1)", g.dameng.Update(new Topic { Id = 1, Title = "test" }).SetRaw("title='test1'").AsTable(a => "tb_topicAsTable").ToSql()); + Assert.Equal("UPDATE \"TB_TOPICASTABLE\" SET title='test1' \r\nWHERE (\"ID\" = 1 OR \"ID\" = 2)", g.dameng.Update(new[] { new Topic { Id = 1, Title = "test" }, new Topic { Id = 2, Title = "test" } }).SetRaw("title='test1'").AsTable(a => "tb_topicAsTable").ToSql()); + Assert.Equal("UPDATE \"TB_TOPICASTABLE\" SET title='test1' \r\nWHERE (\"ID\" = 1)", g.dameng.Update(new { id = 1 }).SetRaw("title='test1'").AsTable(a => "tb_topicAsTable").ToSql()); + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/DamengAdo/DamengAdoTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengAdo/DamengAdoTest.cs new file mode 100644 index 00000000..796e0a6e --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengAdo/DamengAdoTest.cs @@ -0,0 +1,66 @@ +using FreeSql.DataAnnotations; +using System; +using Xunit; + +namespace FreeSql.Tests.Dameng +{ + public class DamengAdoTest + { + [Fact] + public void Pool() + { + var t1 = g.dameng.Ado.MasterPool.StatisticsFullily; + } + + [Fact] + public void SlavePools() + { + var t2 = g.dameng.Ado.SlavePools.Count; + } + + [Fact] + public void ExecuteReader() + { + + } + [Fact] + public void ExecuteArray() + { + + } + [Fact] + public void ExecuteNonQuery() + { + + } + [Fact] + public void ExecuteScalar() + { + + } + + [Fact] + public void Query() + { + + var t3 = g.dameng.Ado.Query("select * from \"TB_TOPIC\""); + + var t4 = g.dameng.Ado.Query<(int, string, string)>("select * from \"TB_TOPIC\""); + + var t5 = g.dameng.Ado.Query("select * from \"TB_TOPIC\""); + } + + [Fact] + public void QueryMultipline() + { + //var t3 = g.dameng.Ado.Query("select * from \"TB_TOPIC\"; select * from \"TB_TOPIC\"; select * from \"TB_TOPIC\""); + } + + class xxx + { + public int Id { get; set; } + public string Path { get; set; } + public string Title2 { get; set; } + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/DamengAopTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengAopTest.cs new file mode 100644 index 00000000..61b2b2bd --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengAopTest.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using Xunit; + +namespace FreeSql.Tests.Dameng +{ + public class DamengAopTest + { + + class TestAuditValue + { + public Guid id { get; set; } + [Now] + public DateTime createtime { get; set; } + } + class NowAttribute: Attribute { } + + [Fact] + public void AuditValue() + { + var date = DateTime.Now.Date; + var item = new TestAuditValue(); + + EventHandler audit = (s, e) => + { + if (e.Property.GetCustomAttribute(false) != null) + e.Value = DateTime.Now.Date; + }; + g.dameng.Aop.AuditValue += audit; + + g.dameng.Insert(item).ExecuteAffrows(); + + g.dameng.Aop.AuditValue -= audit; + + Assert.Equal(item.createtime, date); + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/DamengCodeFirstTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengCodeFirstTest.cs new file mode 100644 index 00000000..e8b064db --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengCodeFirstTest.cs @@ -0,0 +1,352 @@ +using FreeSql.DataAnnotations; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Xunit; + +namespace FreeSql.Tests.Dameng +{ + public class DamengCodeFirstTest + { + [Fact] + public void StringLength() + { + var dll = g.dameng.CodeFirst.GetComparisonDDLStatements(); + g.dameng.CodeFirst.SyncStructure(); + } + class TS_SLTB + { + public Guid Id { get; set; } + [Column(StringLength = 50)] + public string Title { get; set; } + + [Column(IsNullable = false, StringLength = 50)] + public string TitleSub { get; set; } + } + + [Fact] + public void ֱ_ֶ() + { + var sql = g.dameng.CodeFirst.GetComparisonDDLStatements<ֱ>(); + g.dameng.CodeFirst.SyncStructure<ֱ>(); + + var item = new ֱ + { + = "Ա", + ʱ = DateTime.Now + }; + Assert.Equal(1, g.dameng.Insert<ֱ>().AppendData(item).ExecuteAffrows()); + Assert.NotEqual(Guid.Empty, item.); + var item2 = g.dameng.Select<ֱ>().Where(a => a. == item.).First(); + Assert.NotNull(item2); + Assert.Equal(item., item2.); + Assert.Equal(item., item2.); + + item. = "Ա"; + Assert.Equal(1, g.dameng.Update<ֱ>().SetSource(item).ExecuteAffrows()); + item2 = g.dameng.Select<ֱ>().Where(a => a. == item.).First(); + Assert.NotNull(item2); + Assert.Equal(item., item2.); + Assert.Equal(item., item2.); + + item. = "Ա_repo"; + var repo = g.dameng.GetRepository<ֱ>(); + Assert.Equal(1, repo.Update(item)); + item2 = g.dameng.Select<ֱ>().Where(a => a. == item.).First(); + Assert.NotNull(item2); + Assert.Equal(item., item2.); + Assert.Equal(item., item2.); + + item. = "Ա_repo22"; + Assert.Equal(1, repo.Update(item)); + item2 = g.dameng.Select<ֱ>().Where(a => a. == item.).First(); + Assert.NotNull(item2); + Assert.Equal(item., item2.); + Assert.Equal(item., item2.); + } + [Table(Name = "123ֱ")] + class ֱ + { + [Column(IsPrimary = true, Name = "123")] + public Guid { get; set; } + + [Column(Name = "123")] + public string { get; set; } + + [Column(Name = "123ʱ")] + public DateTime ʱ { get; set; } + } + + [Fact] + public void ı_ֶ() + { + var sql = g.dameng.CodeFirst.GetComparisonDDLStatements<ı>(); + g.dameng.CodeFirst.SyncStructure<ı>(); + + var item = new ı + { + = "Ա", + ʱ = DateTime.Now + }; + Assert.Equal(1, g.dameng.Insert<ı>().AppendData(item).ExecuteAffrows()); + Assert.NotEqual(Guid.Empty, item.); + var item2 = g.dameng.Select<ı>().Where(a => a. == item.).First(); + Assert.NotNull(item2); + Assert.Equal(item., item2.); + Assert.Equal(item., item2.); + + item. = "Ա"; + Assert.Equal(1, g.dameng.Update<ı>().SetSource(item).ExecuteAffrows()); + item2 = g.dameng.Select<ı>().Where(a => a. == item.).First(); + Assert.NotNull(item2); + Assert.Equal(item., item2.); + Assert.Equal(item., item2.); + + item. = "Ա_repo"; + var repo = g.dameng.GetRepository<ı>(); + Assert.Equal(1, repo.Update(item)); + item2 = g.dameng.Select<ı>().Where(a => a. == item.).First(); + Assert.NotNull(item2); + Assert.Equal(item., item2.); + Assert.Equal(item., item2.); + + item. = "Ա_repo22"; + Assert.Equal(1, repo.Update(item)); + item2 = g.dameng.Select<ı>().Where(a => a. == item.).First(); + Assert.NotNull(item2); + Assert.Equal(item., item2.); + Assert.Equal(item., item2.); + } + class ı + { + [Column(IsPrimary = true)] + public Guid { get; set; } + + public string { get; set; } + + public DateTime ʱ { get; set; } + } + + [Fact] + public void AddUniques() + { + var sql = g.dameng.CodeFirst.GetComparisonDDLStatements(); + g.dameng.CodeFirst.SyncStructure(); + } + [Table(Name = "AddUniquesInfo", OldName = "AddUniquesInfo2")] + [Index("uk_phone", "phone", true)] + [Index("uk_group_index", "group,index", true)] + [Index("uk_group_index22", "group, index22", true)] + class AddUniquesInfo + { + public Guid id { get; set; } + public string phone { get; set; } + + public string group { get; set; } + public int index { get; set; } + public string index22 { get; set; } + } + [Fact] + public void AddField() + { + var sql = g.dameng.CodeFirst.GetComparisonDDLStatements(); + + var id = g.dameng.Insert().AppendData(new TopicAddField { }).ExecuteIdentity(); + + //var inserted = g.dameng.Insert().AppendData(new TopicAddField { }).ExecuteInserted(); + } + + [Table(Name = "TopicAddField", OldName = "xxxtb.TopicAddField")] + public class TopicAddField + { + [Column(IsIdentity = true)] + public int Id { get; set; } + + public string name { get; set; } + + [Column(DbType = "varchar2(200) not null", OldName = "title")] + public string title2 { get; set; } = "10"; + + [Column(IsIgnore = true)] + public DateTime ct { get; set; } = DateTime.Now; + } + + [Fact] + public void GetComparisonDDLStatements() + { + + var sql = g.dameng.CodeFirst.GetComparisonDDLStatements(); + if (string.IsNullOrEmpty(sql) == false) + { + Assert.Equal(@"CREATE TABLE IF NOT EXISTS `cccddd`.`tb_alltype` ( + `Id` INT(11) NOT NULL AUTO_INCREMENT, + `Bool` BIT(1) NOT NULL, + `SByte` TINYINT(3) NOT NULL, + `Short` SMALLINT(6) NOT NULL, + `Int` INT(11) NOT NULL, + `Long` BIGINT(20) NOT NULL, + `Byte` TINYINT(3) UNSIGNED NOT NULL, + `UShort` SMALLINT(5) UNSIGNED NOT NULL, + `UInt` INT(10) UNSIGNED NOT NULL, + `ULong` BIGINT(20) UNSIGNED NOT NULL, + `Double` DOUBLE NOT NULL, + `Float` FLOAT NOT NULL, + `Decimal` DECIMAL(10,2) NOT NULL, + `TimeSpan` TIME NOT NULL, + `DateTime` DATETIME NOT NULL, + `Bytes` VARBINARY(255), + `String` VARCHAR(255), + `Guid` VARCHAR(36), + `BoolNullable` BIT(1), + `SByteNullable` TINYINT(3), + `ShortNullable` SMALLINT(6), + `IntNullable` INT(11), + `testFielLongNullable` BIGINT(20), + `ByteNullable` TINYINT(3) UNSIGNED, + `UShortNullable` SMALLINT(5) UNSIGNED, + `UIntNullable` INT(10) UNSIGNED, + `ULongNullable` BIGINT(20) UNSIGNED, + `DoubleNullable` DOUBLE, + `FloatNullable` FLOAT, + `DecimalNullable` DECIMAL(10,2), + `TimeSpanNullable` TIME, + `DateTimeNullable` DATETIME, + `GuidNullable` VARCHAR(36), + `Point` POINT, + `LineString` LINESTRING, + `Polygon` POLYGON, + `MultiPoint` MULTIPOINT, + `MultiLineString` MULTILINESTRING, + `MultiPolygon` MULTIPOLYGON, + `Enum1` ENUM('E1','E2','E3') NOT NULL, + `Enum1Nullable` ENUM('E1','E2','E3'), + `Enum2` SET('F1','F2','F3') NOT NULL, + `Enum2Nullable` SET('F1','F2','F3'), + PRIMARY KEY (`Id`) +) Engine=InnoDB; +", sql); + } + + //sql = g.dameng.CodeFirst.GetComparisonDDLStatements(); + } + + IInsert insert => g.dameng.Insert(); + ISelect select => g.dameng.Select(); + + [Fact] + public void CurdAllField() + { + var item = new TableAllType { }; + item.Id = (int)insert.AppendData(item).ExecuteIdentity(); + + var newitem = select.Where(a => a.Id == item.Id).ToOne(); + + var item2 = new TableAllType + { + Bool = true, + BoolNullable = true, + Byte = 255, + ByteNullable = 127, + Bytes = Encoding.UTF8.GetBytes("й"), + DateTime = DateTime.Now, + DateTimeNullable = DateTime.Now.AddHours(-1), + Decimal = 99.99M, + DecimalNullable = 99.98M, + Double = 999.99, + DoubleNullable = 999.98, + Enum1 = TableAllTypeEnumType1.e5, + Enum1Nullable = TableAllTypeEnumType1.e3, + Enum2 = TableAllTypeEnumType2.f2, + Enum2Nullable = TableAllTypeEnumType2.f3, + Float = 19.99F, + FloatNullable = 19.98F, + Guid = Guid.NewGuid(), + GuidNullable = Guid.NewGuid(), + Int = int.MaxValue, + IntNullable = int.MinValue, + SByte = 100, + SByteNullable = 99, + Short = short.MaxValue, + ShortNullable = short.MinValue, + String = "йstring'\\?!@#$%^&*()_+{}}{~?><<>", + TimeSpan = TimeSpan.FromSeconds(999), + TimeSpanNullable = TimeSpan.FromSeconds(60), + UInt = uint.MaxValue, + UIntNullable = uint.MinValue, + ULong = ulong.MaxValue, + ULongNullable = ulong.MinValue, + UShort = ushort.MaxValue, + UShortNullable = ushort.MinValue, + testFielLongNullable = long.MinValue + }; + var sqlPar = insert.AppendData(item2).ToSql(); + var sqlText = insert.AppendData(item2).NoneParameter().ToSql(); + var item3NP = insert.AppendData(item2).NoneParameter().ExecuteIdentity(); + + item2.Id = (int)insert.AppendData(item2).ExecuteIdentity(); + var newitem2 = select.Where(a => a.Id == item2.Id).ToOne(); + Assert.Equal(item2.String, newitem2.String); + + item2.Id = (int)insert.NoneParameter().AppendData(item2).ExecuteIdentity(); + newitem2 = select.Where(a => a.Id == item2.Id).ToOne(); + Assert.Equal(item2.String, newitem2.String); + + var items = select.ToList(); + } + + [Table(Name = "tb_alltype")] + class TableAllType + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + + public string id2 { get; set; } = "id2=10"; + + public bool Bool { get; set; } + public sbyte SByte { get; set; } + public short Short { get; set; } + public int Int { get; set; } + public long Long { get; set; } + public byte Byte { get; set; } + public ushort UShort { get; set; } + public uint UInt { get; set; } + public ulong ULong { get; set; } + public double Double { get; set; } + public float Float { get; set; } + public decimal Decimal { get; set; } + public TimeSpan TimeSpan { get; set; } + public DateTime DateTime { get; set; } + public DateTime DateTimeOffSet { get; set; } + public byte[] Bytes { get; set; } + public string String { get; set; } + public Guid Guid { get; set; } + + public bool? BoolNullable { get; set; } + public sbyte? SByteNullable { get; set; } + public short? ShortNullable { get; set; } + public int? IntNullable { get; set; } + public long? testFielLongNullable { get; set; } + public byte? ByteNullable { get; set; } + public ushort? UShortNullable { get; set; } + public uint? UIntNullable { get; set; } + public ulong? ULongNullable { get; set; } + public double? DoubleNullable { get; set; } + public float? FloatNullable { get; set; } + public decimal? DecimalNullable { get; set; } + public TimeSpan? TimeSpanNullable { get; set; } + public DateTime? DateTimeNullable { get; set; } + public DateTime? DateTimeOffSetNullable { get; set; } + public Guid? GuidNullable { get; set; } + + public TableAllTypeEnumType1 Enum1 { get; set; } + public TableAllTypeEnumType1? Enum1Nullable { get; set; } + public TableAllTypeEnumType2 Enum2 { get; set; } + public TableAllTypeEnumType2? Enum2Nullable { get; set; } + } + + public enum TableAllTypeEnumType1 { e1, e2, e3, e5 } + [Flags] public enum TableAllTypeEnumType2 { f1, f2, f3 } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/DamengDbFirstTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengDbFirstTest.cs new file mode 100644 index 00000000..833dff93 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengDbFirstTest.cs @@ -0,0 +1,25 @@ +using FreeSql.DataAnnotations; +using System; +using Xunit; + +namespace FreeSql.Tests.Dameng +{ + public class DamengDbFirstTest + { + [Fact] + public void GetDatabases() + { + + var t1 = g.dameng.DbFirst.GetDatabases(); + + } + + [Fact] + public void GetTablesByDatabase() + { + + var t2 = g.dameng.DbFirst.GetTablesByDatabase(); + //var tb = g.dameng.Ado.ExecuteArray(System.Data.CommandType.Text, "select * from \"tb_dbfirst\""); + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/ConvertTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/ConvertTest.cs new file mode 100644 index 00000000..881fc900 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/ConvertTest.cs @@ -0,0 +1,169 @@ +using FreeSql.DataAnnotations; +using System; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace FreeSql.Tests.DamengExpression +{ + public class ConvertTest + { + + ISelect select => g.dameng.Select(); + + [Table(Name = "tb_topic")] + class Topic + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + public int Clicks { get; set; } + public int TypeGuid { get; set; } + public TestTypeInfo Type { get; set; } + public string Title { get; set; } + public DateTime CreateTime { get; set; } + } + class TestTypeInfo + { + public int Guid { get; set; } + public int ParentId { get; set; } + public TestTypeParentInfo Parent { get; set; } + public string Name { get; set; } + } + class TestTypeParentInfo + { + public int Id { get; set; } + public string Name { get; set; } + + public List Types { get; set; } + } + + [Fact] + public void ToBoolean() + { + var data = new List(); + //data.Add(select.Where(a => (Convert.ToBoolean(a.Clicks) ? 1 : 0) > 0).ToList()); + //data.Add(select.Where(a => (bool.Parse(a.Clicks.ToString()) ? 1 : 0) > 0).ToList()); + } + [Fact] + public void ToByte() + { + var data = new List(); + data.Add(select.Where(a => Convert.ToByte(a.Clicks % 255) > 0).ToList()); + data.Add(select.Where(a => byte.Parse((a.Clicks % 255).ToString()) > 0).ToList()); + } + [Fact] + public void ToChar() + { + var data = new List(); + data.Add(select.Where(a => Convert.ToChar(a.Clicks) == '1').ToList()); + data.Add(select.Where(a => char.Parse(a.Clicks.ToString()) == '1').ToList()); + } + [Fact] + public void ToDateTime() + { + var data = new List(); + data.Add(select.Where(a => Convert.ToDateTime(a.CreateTime.ToString()).Year > 0).ToList()); + data.Add(select.Where(a => DateTime.Parse(a.CreateTime.ToString()).Year > 0).ToList()); + } + [Fact] + public void ToDecimal() + { + var data = new List(); + data.Add(select.Where(a => Convert.ToDecimal(a.Clicks) > 0).ToList()); + data.Add(select.Where(a => decimal.Parse(a.Clicks.ToString()) > 0).ToList()); + } + [Fact] + public void ToDouble() + { + var data = new List(); + data.Add(select.Where(a => Convert.ToDouble(a.Clicks) > 0).ToList()); + data.Add(select.Where(a => double.Parse(a.Clicks.ToString()) > 0).ToList()); + } + [Fact] + public void ToInt16() + { + var data = new List(); + data.Add(select.Where(a => Convert.ToInt16(a.Clicks) > 0).ToList()); + data.Add(select.Where(a => short.Parse(a.Clicks.ToString()) > 0).ToList()); + } + [Fact] + public void ToInt32() + { + var data = new List(); + data.Add(select.Where(a => (int)a.Clicks > 0).ToList()); + data.Add(select.Where(a => Convert.ToInt32(a.Clicks) > 0).ToList()); + data.Add(select.Where(a => int.Parse(a.Clicks.ToString()) > 0).ToList()); + } + [Fact] + public void ToInt64() + { + var data = new List(); + data.Add(select.Where(a => Convert.ToInt64(a.Clicks) > 0).ToList()); + data.Add(select.Where(a => long.Parse(a.Clicks.ToString()) > 0).ToList()); + } + [Fact] + public void ToSByte() + { + var data = new List(); + data.Add(select.Where(a => Convert.ToSByte(a.Clicks % 128) > 0).ToList()); + data.Add(select.Where(a => sbyte.Parse((a.Clicks % 128).ToString()) > 0).ToList()); + } + [Fact] + public void ToSingle() + { + var data = new List(); + data.Add(select.Where(a => Convert.ToSingle(a.Clicks) > 0).ToList()); + data.Add(select.Where(a => float.Parse(a.Clicks.ToString()) > 0).ToList()); + } + [Fact] + public void this_ToString() + { + var data = new List(); + data.Add(select.Where(a => Convert.ToString(a.Clicks).Equals("")).ToList()); + data.Add(select.Where(a => a.Clicks.ToString().Equals("")).ToList()); + } + [Fact] + public void ToUInt16() + { + var data = new List(); + data.Add(select.Where(a => Convert.ToUInt16(a.Clicks) > 0).ToList()); + data.Add(select.Where(a => ushort.Parse(a.Clicks.ToString()) > 0).ToList()); + } + [Fact] + public void ToUInt32() + { + var data = new List(); + data.Add(select.Where(a => Convert.ToUInt32(a.Clicks) > 0).ToList()); + data.Add(select.Where(a => uint.Parse(a.Clicks.ToString()) > 0).ToList()); + } + [Fact] + public void ToUInt64() + { + var data = new List(); + data.Add(select.Where(a => Convert.ToUInt64(a.Clicks) > 0).ToList()); + data.Add(select.Where(a => ulong.Parse(a.Clicks.ToString()) > 0).ToList()); + } + + [Fact] + public void Guid_Parse() + { + var data = new List(); + data.Add(select.Where(a => Guid.Parse(Guid.Empty.ToString()) == Guid.Empty).ToList()); + } + + [Fact] + public void Guid_NewGuid() + { + var data = new List(); + //data.Add(select.OrderBy(a => Guid.NewGuid()).Limit(10).ToList()); + } + + [Fact] + public void Random() + { + var data = new List(); + data.Add(select.Where(a => new Random().Next() > a.Clicks).Limit(10).ToList()); + data.Add(select.Where(a => new Random().NextDouble() > a.Clicks).Limit(10).ToList()); + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/DateTimeTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/DateTimeTest.cs new file mode 100644 index 00000000..6b7b49e5 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/DateTimeTest.cs @@ -0,0 +1,706 @@ +using FreeSql.DataAnnotations; +using System; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace FreeSql.Tests.DamengExpression +{ + public class DateTimeTest + { + + ISelect select => g.dameng.Select(); + + [Table(Name = "tb_topic111333")] + class Topic + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + public int Clicks { get; set; } + public int TypeGuid { get; set; } + public TestTypeInfo Type { get; set; } + public string Title { get; set; } + public DateTime CreateTime { get; set; } + } + [Table(Name = "TestTypeInfo333")] + class TestTypeInfo + { + [Column(IsIdentity = true)] + public int Guid { get; set; } + public int ParentId { get; set; } + public TestTypeParentInfo Parent { get; set; } + public string Name { get; set; } + public DateTime Time { get; set; } + } + [Table(Name = "TestTypeParentInf1")] + class TestTypeParentInfo + { + public int Id { get; set; } + public string Name { get; set; } + + public List Types { get; set; } + public DateTime Time2 { get; set; } + } + [Fact] + public void Now() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.Date == DateTime.Now.Date).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (cast(date_format(a.`CreateTime`, '%Y-%m-%d') as datetime) = cast(date_format(now(), '%Y-%m-%d') as datetime)) + } + [Fact] + public void UtcNow() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.Date == DateTime.UtcNow.Date).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (cast(date_format(a.`CreateTime`, '%Y-%m-%d') as datetime) = cast(date_format(utc_timestamp(), '%Y-%m-%d') as datetime)) + } + [Fact] + public void MinValue() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.Date == DateTime.MinValue.Date).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (cast(date_format(a.`CreateTime`, '%Y-%m-%d') as datetime) = cast(date_format(cast('0001/1/1 0:00:00' as datetime), '%Y-%m-%d') as datetime)) + } + [Fact] + public void MaxValue() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.Date == DateTime.MaxValue.Date).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (cast(date_format(a.`CreateTime`, '%Y-%m-%d') as datetime) = cast(date_format(cast('9999/12/31 23:59:59' as datetime), '%Y-%m-%d') as datetime)) + } + [Fact] + public void Date() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.Date == DateTime.Now.Date).ToList()); + data.Add(select.Where(a => a.Type.Time.Date > DateTime.Now.Date).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.Date > DateTime.Now.Date).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (cast(date_format(a.`CreateTime`, '%Y-%m-%d') as datetime) = cast(date_format(now(), '%Y-%m-%d') as datetime)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (cast(date_format(a__Type.`Time`, '%Y-%m-%d') as datetime) > cast(date_format(now(), '%Y-%m-%d') as datetime)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (cast(date_format(a__Type__Parent.`Time2`, '%Y-%m-%d') as datetime) > cast(date_format(now(), '%Y-%m-%d') as datetime)); + data.Add(select.Where(a => DateTime.Now.Subtract(a.CreateTime.Date).TotalSeconds > 0).ToList()); + data.Add(select.Where(a => DateTime.Now.Subtract(a.Type.Time.Date).TotalSeconds > 0).ToList()); + data.Add(select.Where(a => DateTime.Now.Subtract(a.Type.Parent.Time2.Date).TotalSeconds > 0).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (((timestampdiff(microsecond, cast(date_format(a.`CreateTime`, '%Y-%m-%d') as datetime), now())) / 1000000) > 0); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (((timestampdiff(microsecond, cast(date_format(a__Type.`Time`, '%Y-%m-%d') as datetime), now())) / 1000000) > 0); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (((timestampdiff(microsecond, cast(date_format(a__Type__Parent.`Time2`, '%Y-%m-%d') as datetime), now())) / 1000000) > 0) + } + [Fact] + public void TimeOfDay() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay == DateTime.Now.TimeOfDay).ToList()); + data.Add(select.Where(a => a.Type.Time.TimeOfDay > DateTime.Now.TimeOfDay).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.TimeOfDay > DateTime.Now.TimeOfDay).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE ((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000) = (timestampdiff(microsecond, date_format(now(), '1970-1-1 %H:%i:%s.%f'), now()) + 62135596800000000)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE ((timestampdiff(microsecond, date_format(a__Type.`Time`, '1970-1-1 %H:%i:%s.%f'), a__Type.`Time`) + 62135596800000000) > (timestampdiff(microsecond, date_format(now(), '1970-1-1 %H:%i:%s.%f'), now()) + 62135596800000000)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE ((timestampdiff(microsecond, date_format(a__Type__Parent.`Time2`, '1970-1-1 %H:%i:%s.%f'), a__Type__Parent.`Time2`) + 62135596800000000) > (timestampdiff(microsecond, date_format(now(), '1970-1-1 %H:%i:%s.%f'), now()) + 62135596800000000)) + } + [Fact] + public void DayOfWeek() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.DayOfWeek > DateTime.Now.DayOfWeek).ToList()); + data.Add(select.Where(a => a.Type.Time.DayOfWeek > DateTime.Now.DayOfWeek).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.DayOfWeek > DateTime.Now.DayOfWeek).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE ((dayofweek(a.`CreateTime`) - 1) > (dayofweek(now()) - 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE ((dayofweek(a__Type.`Time`) - 1) > (dayofweek(now()) - 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE ((dayofweek(a__Type__Parent.`Time2`) - 1) > (dayofweek(now()) - 1)) + } + [Fact] + public void Day() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.Day > DateTime.Now.Day).ToList()); + data.Add(select.Where(a => a.Type.Time.Day > DateTime.Now.Day).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.Day > DateTime.Now.Day).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (dayofmonth(a.`CreateTime`) > dayofmonth(now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (dayofmonth(a__Type.`Time`) > dayofmonth(now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (dayofmonth(a__Type__Parent.`Time2`) > dayofmonth(now())) + } + [Fact] + public void DayOfYear() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.DayOfYear > DateTime.Now.DayOfYear).ToList()); + data.Add(select.Where(a => a.Type.Time.DayOfYear > DateTime.Now.DayOfYear).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.DayOfYear > DateTime.Now.DayOfYear).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (dayofyear(a.`CreateTime`) > dayofyear(now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (dayofyear(a__Type.`Time`) > dayofyear(now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (dayofyear(a__Type__Parent.`Time2`) > dayofyear(now())) + } + [Fact] + public void Month() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.Month > DateTime.Now.Month).ToList()); + data.Add(select.Where(a => a.Type.Time.Month > DateTime.Now.Month).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.Month > DateTime.Now.Month).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (month(a.`CreateTime`) > month(now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (month(a__Type.`Time`) > month(now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (month(a__Type__Parent.`Time2`) > month(now())) + } + [Fact] + public void Year() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.Year > DateTime.Now.Year).ToList()); + data.Add(select.Where(a => a.Type.Time.Year > DateTime.Now.Year).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.Year > DateTime.Now.Year).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (year(a.`CreateTime`) > year(now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (year(a__Type.`Time`) > year(now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (year(a__Type__Parent.`Time2`) > year(now())) + } + [Fact] + public void Hour() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.Hour > DateTime.Now.Hour).ToList()); + data.Add(select.Where(a => a.Type.Time.Hour > DateTime.Now.Hour).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.Hour > DateTime.Now.Hour).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (hour(a.`CreateTime`) > hour(now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (hour(a__Type.`Time`) > hour(now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (hour(a__Type__Parent.`Time2`) > hour(now())) + } + [Fact] + public void Minute() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.Minute > DateTime.Now.Minute).ToList()); + data.Add(select.Where(a => a.Type.Time.Minute > DateTime.Now.Minute).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.Minute > DateTime.Now.Minute).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (minute(a.`CreateTime`) > minute(now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (minute(a__Type.`Time`) > minute(now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (minute(a__Type__Parent.`Time2`) > minute(now())) + } + [Fact] + public void Second() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.Second > DateTime.Now.Second).ToList()); + data.Add(select.Where(a => a.Type.Time.Second > DateTime.Now.Second).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.Second > DateTime.Now.Second).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (second(a.`CreateTime`) > second(now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (second(a__Type.`Time`) > second(now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (second(a__Type__Parent.`Time2`) > second(now())) + } + [Fact] + public void Millisecond() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.Millisecond > DateTime.Now.Millisecond).ToList()); + data.Add(select.Where(a => a.Type.Time.Millisecond > DateTime.Now.Millisecond).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.Millisecond > DateTime.Now.Millisecond).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (floor(microsecond(a.`CreateTime`) / 1000) > floor(microsecond(now()) / 1000)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (floor(microsecond(a__Type.`Time`) / 1000) > floor(microsecond(now()) / 1000)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (floor(microsecond(a__Type__Parent.`Time2`) / 1000) > floor(microsecond(now()) / 1000)) + } + [Fact] + public void Ticks() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.Ticks > DateTime.Now.Ticks).ToList()); + data.Add(select.Where(a => a.Type.Time.Ticks > DateTime.Now.Ticks).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.Ticks > DateTime.Now.Ticks).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE ((timestampdiff(microsecond, '1970-1-1', a.`CreateTime`) * 10 + 621355968000000000) > (timestampdiff(microsecond, '1970-1-1', now()) * 10 + 621355968000000000)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE ((timestampdiff(microsecond, '1970-1-1', a__Type.`Time`) * 10 + 621355968000000000) > (timestampdiff(microsecond, '1970-1-1', now()) * 10 + 621355968000000000)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE ((timestampdiff(microsecond, '1970-1-1', a__Type__Parent.`Time2`) * 10 + 621355968000000000) > (timestampdiff(microsecond, '1970-1-1', now()) * 10 + 621355968000000000)) + } + [Fact] + public void Add() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.Add(TimeSpan.FromDays(1)) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Time.Add(TimeSpan.FromDays(1)) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.Add(TimeSpan.FromDays(1)) > DateTime.Now).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (date_add(a.`CreateTime`, interval ((1 * 86400000000)) microsecond) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (date_add(a__Type.`Time`, interval ((1 * 86400000000)) microsecond) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (date_add(a__Type__Parent.`Time2`, interval ((1 * 86400000000)) microsecond) > now()) + } + [Fact] + public void AddDays() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.AddDays(1) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Time.AddDays(1) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.AddDays(1) > DateTime.Now).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (date_add(a.`CreateTime`, interval (1) day) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (date_add(a__Type.`Time`, interval (1) day) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (date_add(a__Type__Parent.`Time2`, interval (1) day) > now()) + } + [Fact] + public void AddHours() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.AddHours(1) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Time.AddHours(1) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.AddHours(1) > DateTime.Now).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (date_add(a.`CreateTime`, interval (1) hour) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (date_add(a__Type.`Time`, interval (1) hour) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (date_add(a__Type__Parent.`Time2`, interval (1) hour) > now()) + } + [Fact] + public void AddMilliseconds() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.AddMilliseconds(1) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Time.AddMilliseconds(1) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.AddMilliseconds(1) > DateTime.Now).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (date_add(a.`CreateTime`, interval (1) * 1000 microsecond) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (date_add(a__Type.`Time`, interval (1) * 1000 microsecond) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (date_add(a__Type__Parent.`Time2`, interval (1) * 1000 microsecond) > now()) + } + [Fact] + public void AddMinutes() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.AddMinutes(1) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Time.AddMinutes(1) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.AddMinutes(1) > DateTime.Now).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (date_add(a.`CreateTime`, interval (1) minute) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (date_add(a__Type.`Time`, interval (1) minute) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (date_add(a__Type__Parent.`Time2`, interval (1) minute) > now()) + } + [Fact] + public void AddMonths() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.AddMonths(1) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Time.AddMonths(1) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.AddMonths(1) > DateTime.Now).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (date_add(a.`CreateTime`, interval (1) month) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (date_add(a__Type.`Time`, interval (1) month) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (date_add(a__Type__Parent.`Time2`, interval (1) month) > now()) + } + [Fact] + public void AddSeconds() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.AddSeconds(1) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Time.AddSeconds(1) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.AddSeconds(1) > DateTime.Now).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (date_add(a.`CreateTime`, interval (1) second) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (date_add(a__Type.`Time`, interval (1) second) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (date_add(a__Type__Parent.`Time2`, interval (1) second) > now()) + } + [Fact] + public void AddTicks() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.AddTicks(1) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Time.AddTicks(1) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.AddTicks(1) > DateTime.Now).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (date_add(a.`CreateTime`, interval (1) / 10 microsecond) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (date_add(a__Type.`Time`, interval (1) / 10 microsecond) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (date_add(a__Type__Parent.`Time2`, interval (1) / 10 microsecond) > now()) + } + [Fact] + public void AddYears() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.AddYears(1) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Time.AddYears(1) > DateTime.Now).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.AddYears(1) > DateTime.Now).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (date_add(a.`CreateTime`, interval (1) year) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (date_add(a__Type.`Time`, interval (1) year) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (date_add(a__Type__Parent.`Time2`, interval (1) year) > now()) + } + [Fact] + public void Subtract() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.Subtract(DateTime.Now).TotalSeconds > 0).ToList()); + data.Add(select.Where(a => a.Type.Time.Subtract(DateTime.Now).TotalSeconds > 0).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.Subtract(DateTime.Now).TotalSeconds > 0).ToList()); + //SELECT a."ID", a."CLICKS", a."TYPEGUID", a."TITLE", a."CREATETIME" + //FROM "TB_TOPIC111333" a + //WHERE ((extract(day from (systimestamp-a."CREATETIME"))*86400+extract(hour from (systimestamp-a."CREATETIME"))*3600+extract(minute from (systimestamp-a."CREATETIME"))*60+extract(second from (systimestamp-a."CREATETIME"))) > 0) + + //SELECT a."ID", a."CLICKS", a."TYPEGUID", a__Type."GUID", a__Type."PARENTID", a__Type."NAME", a__Type."TIME", a."TITLE", a."CREATETIME" + //FROM "TB_TOPIC111333" a + //LEFT JOIN "TESTTYPEINFO333" a__Type ON a__Type."GUID" = a."TYPEGUID" + //WHERE ((extract(day from (systimestamp-a__Type."TIME"))*86400+extract(hour from (systimestamp-a__Type."TIME"))*3600+extract(minute from (systimestamp-a__Type."TIME"))*60+extract(second from (systimestamp-a__Type."TIME"))) > 0) + + //SELECT a."ID", a."CLICKS", a."TYPEGUID", a__Type."GUID", a__Type."PARENTID", a__Type."NAME", a__Type."TIME", a."TITLE", a."CREATETIME" + //FROM "TB_TOPIC111333" a + //LEFT JOIN "TESTTYPEINFO333" a__Type ON a__Type."GUID" = a."TYPEGUID" + //LEFT JOIN "TESTTYPEPARENTINF1" a__Type__Parent ON a__Type__Parent."ID" = a__Type."PARENTID" + //WHERE ((extract(day from (systimestamp-a__Type__Parent."TIME2"))*86400+extract(hour from (systimestamp-a__Type__Parent."TIME2"))*3600+extract(minute from (systimestamp-a__Type__Parent."TIME2"))*60+extract(second from (systimestamp-a__Type__Parent."TIME2"))) > 0) + data.Add(select.Where(a => a.CreateTime.Subtract(TimeSpan.FromDays(1)) > a.CreateTime).ToList()); + data.Add(select.Where(a => a.Type.Time.Subtract(TimeSpan.FromDays(1)) > a.CreateTime).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.Subtract(TimeSpan.FromDays(1)) > a.CreateTime).ToList()); + //SELECT a."ID", a."CLICKS", a."TYPEGUID", a."TITLE", a."CREATETIME" + //FROM "TB_TOPIC111333" a + //WHERE ((a."CREATETIME"-numtodsinterval((1)*86400,'second')) > a."CREATETIME") + //SELECT a."ID", a."CLICKS", a."TYPEGUID", a__Type."GUID", a__Type."PARENTID", a__Type."NAME", a__Type."TIME", a."TITLE", a."CREATETIME" + + //FROM "TB_TOPIC111333" a + //LEFT JOIN "TESTTYPEINFO333" a__Type ON a__Type."GUID" = a."TYPEGUID" + //WHERE ((a__Type."TIME"-numtodsinterval((1)*86400,'second')) > a."CREATETIME") + //SELECT a."ID", a."CLICKS", a."TYPEGUID", a__Type."GUID", a__Type."PARENTID", a__Type."NAME", a__Type."TIME", a."TITLE", a."CREATETIME" + + //FROM "TB_TOPIC111333" a + //LEFT JOIN "TESTTYPEINFO333" a__Type ON a__Type."GUID" = a."TYPEGUID" + //LEFT JOIN "TESTTYPEPARENTINF1" a__Type__Parent ON a__Type__Parent."ID" = a__Type."PARENTID" + //WHERE ((a__Type__Parent."TIME2"-numtodsinterval((1)*86400,'second')) > a."CREATETIME") + } + [Fact] + public void _ЧͬSubtract() + { + var data = new List(); + data.Add(select.Where(a => (a.CreateTime - DateTime.Now).TotalSeconds > 0).ToList()); + data.Add(select.Where(a => (a.Type.Time - DateTime.Now).TotalSeconds > 0).ToList()); + data.Add(select.Where(a => (a.Type.Parent.Time2 - DateTime.Now).TotalSeconds > 0).ToList()); + //SELECT a."ID", a."CLICKS", a."TYPEGUID", a."TITLE", a."CREATETIME" + //FROM "TB_TOPIC111333" a + //WHERE ((extract(day from (systimestamp-a."CREATETIME"))*86400+extract(hour from (systimestamp-a."CREATETIME"))*3600+extract(minute from (systimestamp-a."CREATETIME"))*60+extract(second from (systimestamp-a."CREATETIME"))) > 0) + + //SELECT a."ID", a."CLICKS", a."TYPEGUID", a__Type."GUID", a__Type."PARENTID", a__Type."NAME", a__Type."TIME", a."TITLE", a."CREATETIME" + //FROM "TB_TOPIC111333" a + //LEFT JOIN "TESTTYPEINFO333" a__Type ON a__Type."GUID" = a."TYPEGUID" + //WHERE ((extract(day from (systimestamp-a__Type."TIME"))*86400+extract(hour from (systimestamp-a__Type."TIME"))*3600+extract(minute from (systimestamp-a__Type."TIME"))*60+extract(second from (systimestamp-a__Type."TIME"))) > 0) + + //SELECT a."ID", a."CLICKS", a."TYPEGUID", a__Type."GUID", a__Type."PARENTID", a__Type."NAME", a__Type."TIME", a."TITLE", a."CREATETIME" + //FROM "TB_TOPIC111333" a + //LEFT JOIN "TESTTYPEINFO333" a__Type ON a__Type."GUID" = a."TYPEGUID" + //LEFT JOIN "TESTTYPEPARENTINF1" a__Type__Parent ON a__Type__Parent."ID" = a__Type."PARENTID" + //WHERE ((extract(day from (systimestamp-a__Type__Parent."TIME2"))*86400+extract(hour from (systimestamp-a__Type__Parent."TIME2"))*3600+extract(minute from (systimestamp-a__Type__Parent."TIME2"))*60+extract(second from (systimestamp-a__Type__Parent."TIME2"))) > 0) + data.Add(select.Where(a => (a.CreateTime - TimeSpan.FromDays(1)) > a.CreateTime).ToList()); + data.Add(select.Where(a => (a.Type.Time - TimeSpan.FromDays(1)) > a.CreateTime).ToList()); + data.Add(select.Where(a => (a.Type.Parent.Time2 - TimeSpan.FromDays(1)) > a.CreateTime).ToList()); + //SELECT a."ID", a."CLICKS", a."TYPEGUID", a."TITLE", a."CREATETIME" + //FROM "TB_TOPIC111333" a + //WHERE ((a."CREATETIME"-numtodsinterval((1)*86400,'second')) > a."CREATETIME") + //SELECT a."ID", a."CLICKS", a."TYPEGUID", a__Type."GUID", a__Type."PARENTID", a__Type."NAME", a__Type."TIME", a."TITLE", a."CREATETIME" + + //FROM "TB_TOPIC111333" a + //LEFT JOIN "TESTTYPEINFO333" a__Type ON a__Type."GUID" = a."TYPEGUID" + //WHERE ((a__Type."TIME"-numtodsinterval((1)*86400,'second')) > a."CREATETIME") + //SELECT a."ID", a."CLICKS", a."TYPEGUID", a__Type."GUID", a__Type."PARENTID", a__Type."NAME", a__Type."TIME", a."TITLE", a."CREATETIME" + + //FROM "TB_TOPIC111333" a + //LEFT JOIN "TESTTYPEINFO333" a__Type ON a__Type."GUID" = a."TYPEGUID" + //LEFT JOIN "TESTTYPEPARENTINF1" a__Type__Parent ON a__Type__Parent."ID" = a__Type."PARENTID" + //WHERE ((a__Type__Parent."TIME2"-numtodsinterval((1)*86400,'second')) > a."CREATETIME") + } + [Fact] + public void this_Equals() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.AddYears(1).Equals(DateTime.Now)).ToList()); + data.Add(select.Where(a => a.Type.Time.AddYears(1).Equals(DateTime.Now)).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.AddYears(1).Equals(DateTime.Now)).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE ((date_add(a.`CreateTime`, interval (1) year) = now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE ((date_add(a__Type.`Time`, interval (1) year) = now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE ((date_add(a__Type__Parent.`Time2`, interval (1) year) = now())) + } + [Fact] + public void this_ToString() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.ToString().Equals(DateTime.Now)).ToList()); + data.Add(select.Where(a => a.Type.Time.AddYears(1).ToString().Equals(DateTime.Now)).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.AddYears(1).ToString().Equals(DateTime.Now)).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE ((date_format(a.`CreateTime`, '%Y-%m-%d %H:%i:%s.%f') = now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE ((date_format(date_add(a__Type.`Time`, interval (1) year), '%Y-%m-%d %H:%i:%s.%f') = now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE ((date_format(date_add(a__Type__Parent.`Time2`, interval (1) year), '%Y-%m-%d %H:%i:%s.%f') = now())) + } + + [Fact] + public void DateTime_Compare() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.CompareTo(DateTime.Now) == 0).ToList()); + data.Add(select.Where(a => a.Type.Time.AddYears(1).CompareTo(DateTime.Now) == 0).ToList()); + data.Add(select.Where(a => a.Type.Parent.Time2.AddYears(1).CompareTo(DateTime.Now) == 0).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (((a.`CreateTime`) - (now())) = 0); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (((date_add(a__Type.`Time`, interval (1) year)) - (now())) = 0); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (((date_add(a__Type__Parent.`Time2`, interval (1) year)) - (now())) = 0) + } + [Fact] + public void DateTime_DaysInMonth() + { + var data = new List(); + data.Add(select.Where(a => DateTime.DaysInMonth(a.CreateTime.Year, a.CreateTime.Month) > 30).ToList()); + data.Add(select.Where(a => DateTime.DaysInMonth(a.Type.Time.Year, a.Type.Time.Month) > 30).ToList()); + data.Add(select.Where(a => DateTime.DaysInMonth(a.Type.Parent.Time2.Year, a.Type.Parent.Time2.Month) > 30).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (dayofmonth(last_day(concat(year(a.`CreateTime`), month(a.`CreateTime`), '-01'))) > 30); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (dayofmonth(last_day(concat(year(a__Type.`Time`), month(a__Type.`Time`), '-01'))) > 30); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (dayofmonth(last_day(concat(year(a__Type__Parent.`Time2`), month(a__Type__Parent.`Time2`), '-01'))) > 30) + } + [Fact] + public void DateTime_Equals() + { + var data = new List(); + data.Add(select.Where(a => DateTime.Equals(a.CreateTime.AddYears(1), DateTime.Now)).ToList()); + data.Add(select.Where(a => DateTime.Equals(a.Type.Time.AddYears(1), DateTime.Now)).ToList()); + data.Add(select.Where(a => DateTime.Equals(a.Type.Parent.Time2.AddYears(1), DateTime.Now)).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE ((date_add(a.`CreateTime`, interval (1) year) = now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE ((date_add(a__Type.`Time`, interval (1) year) = now())); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE ((date_add(a__Type__Parent.`Time2`, interval (1) year) = now())) + } + [Fact] + public void DateTime_IsLeapYear() + { + var data = new List(); + data.Add(select.Where(a => DateTime.IsLeapYear(a.CreateTime.Year)).ToList()); + data.Add(select.Where(a => DateTime.IsLeapYear(a.Type.Time.AddYears(1).Year)).ToList()); + data.Add(select.Where(a => DateTime.IsLeapYear(a.Type.Parent.Time2.AddYears(1).Year)).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (((year(a.`CreateTime`)) % 4 = 0 AND (year(a.`CreateTime`)) % 100 <> 0 OR (year(a.`CreateTime`)) % 400 = 0)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (((year(date_add(a__Type.`Time`, interval (1) year))) % 4 = 0 AND (year(date_add(a__Type.`Time`, interval (1) year))) % 100 <> 0 OR (year(date_add(a__Type.`Time`, interval (1) year))) % 400 = 0)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (((year(date_add(a__Type__Parent.`Time2`, interval (1) year))) % 4 = 0 AND (year(date_add(a__Type__Parent.`Time2`, interval (1) year))) % 100 <> 0 OR (year(date_add(a__Type__Parent.`Time2`, interval (1) year))) % 400 = 0)) + } + [Fact] + public void DateTime_Parse() + { + var data = new List(); + data.Add(select.Where(a => DateTime.Parse(a.CreateTime.ToString()) > DateTime.Now).ToList()); + data.Add(select.Where(a => DateTime.Parse(a.Type.Time.AddYears(1).ToString()) > DateTime.Now).ToList()); + data.Add(select.Where(a => DateTime.Parse(a.Type.Parent.Time2.AddYears(1).ToString()) > DateTime.Now).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic111333` a + //WHERE (cast(date_format(a.`CreateTime`, '%Y-%m-%d %H:%i:%s.%f') as datetime) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type + //WHERE (cast(date_format(date_add(a__Type.`Time`, interval (1) year), '%Y-%m-%d %H:%i:%s.%f') as datetime) > now()); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a__Type.`Time` as7, a.`Title` as8, a.`CreateTime` as9 + //FROM `tb_topic111333` a, `TestTypeInfo333` a__Type, `TestTypeParentInfo23123` a__Type__Parent + //WHERE (cast(date_format(date_add(a__Type__Parent.`Time2`, interval (1) year), '%Y-%m-%d %H:%i:%s.%f') as datetime) > now()) + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/MathTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/MathTest.cs new file mode 100644 index 00000000..c330662f --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/MathTest.cs @@ -0,0 +1,156 @@ +using FreeSql.DataAnnotations; +using System; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace FreeSql.Tests.DamengExpression +{ + public class MathTest + { + + ISelect select => g.dameng.Select(); + + [Table(Name = "tb_topic")] + class Topic + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + public int Clicks { get; set; } + public int TypeGuid { get; set; } + public TestTypeInfo Type { get; set; } + public string Title { get; set; } + public DateTime CreateTime { get; set; } + } + class TestTypeInfo + { + public int Guid { get; set; } + public int ParentId { get; set; } + public TestTypeParentInfo Parent { get; set; } + public string Name { get; set; } + } + class TestTypeParentInfo + { + public int Id { get; set; } + public string Name { get; set; } + + public List Types { get; set; } + } + + [Fact] + public void PI() + { + var data = new List(); + data.Add(select.Where(a => Math.PI + a.Clicks > 0).ToList()); + } + [Fact] + public void Abs() + { + var data = new List(); + data.Add(select.Where(a => Math.Abs(-a.Clicks) > 0).ToList()); + } + [Fact] + public void Sign() + { + var data = new List(); + data.Add(select.Where(a => Math.Sign(-a.Clicks) > 0).ToList()); + } + [Fact] + public void Floor() + { + var data = new List(); + data.Add(select.Where(a => Math.Floor(a.Clicks + 0.5) == a.Clicks).ToList()); + } + [Fact] + public void Ceiling() + { + var data = new List(); + data.Add(select.Where(a => Math.Ceiling(a.Clicks + 0.5) == a.Clicks + 1).ToList()); + } + [Fact] + public void Round() + { + var data = new List(); + data.Add(select.Where(a => Math.Round(a.Clicks + 0.5) == a.Clicks).ToList()); + data.Add(select.Where(a => Math.Round(a.Clicks + 0.5, 1) > a.Clicks).ToList()); + } + [Fact] + public void Exp() + { + var data = new List(); + data.Add(select.Where(a => Math.Exp(1) == a.Clicks + 1).ToList()); + } + [Fact] + public void Log() + { + var data = new List(); + data.Add(select.Where(a => Math.Log(a.Clicks + 0.5) == a.Clicks + 1).ToList()); + } + [Fact] + public void Log10() + { + var data = new List(); + data.Add(select.Where(a => Math.Log10(a.Clicks + 0.5) == a.Clicks + 1).ToList()); + } + [Fact] + public void Pow() + { + var data = new List(); + data.Add(select.Where(a => Math.Pow(2, a.Clicks % 5) == a.Clicks + 1).ToList()); + } + [Fact] + public void Sqrt() + { + var data = new List(); + data.Add(select.Where(a => Math.Sqrt(Math.Pow(2, a.Clicks % 5)) == a.Clicks + 1).ToList()); + } + [Fact] + public void Cos() + { + var data = new List(); + data.Add(select.Where(a => Math.Cos(Math.Pow(2, a.Clicks % 5)) == a.Clicks + 1).ToList()); + } + [Fact] + public void Sin() + { + var data = new List(); + data.Add(select.Where(a => Math.Sin(Math.Pow(2, a.Clicks % 5)) == a.Clicks + 1).ToList()); + } + [Fact] + public void Tan() + { + var data = new List(); + data.Add(select.Where(a => Math.Tan(Math.Pow(2, a.Clicks % 5)) == a.Clicks + 1).ToList()); + } + [Fact] + public void Acos() + { + var data = new List(); + //data.Add(select.Where(a => Math.Acos(Math.Pow(2, a.Clicks % 5)) == a.Clicks + 1).ToList()); + } + [Fact] + public void Asin() + { + var data = new List(); + //data.Add(select.Where(a => Math.Asin(Math.Pow(2, a.Clicks % 5)) == a.Clicks + 1).ToList()); + } + [Fact] + public void Atan() + { + var data = new List(); + data.Add(select.Where(a => Math.Atan(Math.Pow(2, a.Clicks % 5)) == a.Clicks + 1).ToList()); + } + [Fact] + public void Atan2() + { + var data = new List(); + //data.Add(select.Where(a => Math.Atan2(2, a.Clicks) == a.Clicks + 1).ToList()); + } + [Fact] + public void Truncate() + { + var data = new List(); + data.Add(select.Where(a => Math.Truncate(a.Clicks * 1.0 / 3) == a.Clicks + 1).ToList()); + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/OtherTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/OtherTest.cs new file mode 100644 index 00000000..eec18fe5 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/OtherTest.cs @@ -0,0 +1,165 @@ +using FreeSql.DataAnnotations; +using System; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace FreeSql.Tests.DamengExpression +{ + public class OtherTest + { + + ISelect select => g.dameng.Select(); + + public OtherTest() + { + } + + [Fact] + public void Div() + { + var t1 = select.Where(a => a.Int / 3 > 3).Limit(10).ToList(); + var t2 = select.Where(a => a.Long / 3 > 3).Limit(10).ToList(); + var t3 = select.Where(a => a.Short / 3 > 3).Limit(10).ToList(); + + var t4 = select.Where(a => a.Int / 3.0 > 3).Limit(10).ToList(); + var t5 = select.Where(a => a.Long / 3.0 > 3).Limit(10).ToList(); + var t6 = select.Where(a => a.Short / 3.0 > 3).Limit(10).ToList(); + + var t7 = select.Where(a => a.Double / 3 > 3).Limit(10).ToList(); + var t8 = select.Where(a => a.Decimal / 3 > 3).Limit(10).ToList(); + var t9 = select.Where(a => a.Float / 3 > 3).Limit(10).ToList(); + } + + [Fact] + public void Boolean() + { + var t1 = select.Where(a => a.Bool == true).ToList(); + var t2 = select.Where(a => a.Bool != true).ToList(); + var t3 = select.Where(a => a.Bool == false).ToList(); + var t4 = select.Where(a => !a.Bool).ToList(); + var t5 = select.Where(a => a.Bool).ToList(); + var t51 = select.WhereCascade(a => a.Bool).Limit(10).ToList(); + + var t11 = select.Where(a => a.BoolNullable == true).ToList(); + var t22 = select.Where(a => a.BoolNullable != true).ToList(); + var t33 = select.Where(a => a.BoolNullable == false).ToList(); + var t44 = select.Where(a => !a.BoolNullable.Value).ToList(); + var t55 = select.Where(a => a.BoolNullable.Value).ToList(); + + var t111 = select.Where(a => a.Bool == true && a.Id > 0).ToList(); + var t222 = select.Where(a => a.Bool != true && a.Id > 0).ToList(); + var t333 = select.Where(a => a.Bool == false && a.Id > 0).ToList(); + var t444 = select.Where(a => !a.Bool && a.Id > 0).ToList(); + var t555 = select.Where(a => a.Bool && a.Id > 0).ToList(); + + var t1111 = select.Where(a => a.BoolNullable == true && a.Id > 0).ToList(); + var t2222 = select.Where(a => a.BoolNullable != true && a.Id > 0).ToList(); + var t3333 = select.Where(a => a.BoolNullable == false && a.Id > 0).ToList(); + var t4444 = select.Where(a => !a.BoolNullable.Value && a.Id > 0).ToList(); + var t5555 = select.Where(a => a.BoolNullable.Value && a.Id > 0).ToList(); + + var t11111 = select.Where(a => a.Bool == true && a.Id > 0 && a.Bool == true).ToList(); + var t22222 = select.Where(a => a.Bool != true && a.Id > 0 && a.Bool != true).ToList(); + var t33333 = select.Where(a => a.Bool == false && a.Id > 0 && a.Bool == false).ToList(); + var t44444 = select.Where(a => !a.Bool && a.Id > 0 && !a.Bool).ToList(); + var t55555 = select.Where(a => a.Bool && a.Id > 0 && a.Bool).ToList(); + + var t111111 = select.Where(a => a.BoolNullable == true && a.Id > 0 && a.BoolNullable == true).ToList(); + var t222222 = select.Where(a => a.BoolNullable != true && a.Id > 0 && a.BoolNullable != true).ToList(); + var t333333 = select.Where(a => a.BoolNullable == false && a.Id > 0 && a.BoolNullable == false).ToList(); + var t444444 = select.Where(a => !a.BoolNullable.Value && a.Id > 0 && !a.BoolNullable.Value).ToList(); + var t555555 = select.Where(a => a.BoolNullable.Value && a.Id > 0 && a.BoolNullable.Value).ToList(); + } + + [Fact] + public void Array() + { + IEnumerable testlinqlist = new List(new[] { 1, 2, 3 }); + var testlinq = select.Where(a => testlinqlist.Contains(a.Int)).ToList(); + + //in not in + var sql111 = select.Where(a => new[] { 1, 2, 3 }.Contains(a.Int)).ToList(); + //var sql112 = select.Where(a => new[] { 1, 2, 3 }.Contains(a.Int) == false).ToList(); + var sql113 = select.Where(a => !new[] { 1, 2, 3 }.Contains(a.Int)).ToList(); + + var inarray = new[] { 1, 2, 3 }; + var sql1111 = select.Where(a => inarray.Contains(a.Int)).ToList(); + //var sql1122 = select.Where(a => inarray.Contains(a.Int) == false).ToList(); + var sql1133 = select.Where(a => !inarray.Contains(a.Int)).ToList(); + + + //in not in + var sql11111 = select.Where(a => new List() { 1, 2, 3 }.Contains(a.Int)).ToList(); + //var sql11222 = select.Where(a => new List() { 1, 2, 3 }.Contains(a.Int) == false).ToList(); + var sql11333 = select.Where(a => !new List() { 1, 2, 3 }.Contains(a.Int)).ToList(); + + var sql11111a = select.Where(a => new List(new[] { 1, 2, 3 }).Contains(a.Int)).ToList(); + //var sql11222b = select.Where(a => new List(new[] { 1, 2, 3 }).Contains(a.Int) == false).ToList(); + var sql11333c = select.Where(a => !new List(new[] { 1, 2, 3 }).Contains(a.Int)).ToList(); + + var inarray2 = new List() { 1, 2, 3 }; + var sql111111 = select.Where(a => inarray.Contains(a.Int)).ToList(); + //var sql112222 = select.Where(a => inarray.Contains(a.Int) == false).ToList(); + var sql113333 = select.Where(a => !inarray.Contains(a.Int)).ToList(); + + var inarray2n = Enumerable.Range(1, 3333).ToArray(); + var sql1111111 = select.Where(a => inarray2n.Contains(a.Int)).ToList(); + var sql1122222 = select.Where(a => inarray2n.Contains(a.Int) == false).ToList(); + var sql1133333 = select.Where(a => !inarray2n.Contains(a.Int)).ToList(); + } + + [Table(Name = "tb_alltype")] + class TableAllType + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + + public string id2 { get; set; } = "id2=10"; + + public bool Bool { get; set; } + public sbyte SByte { get; set; } + public short Short { get; set; } + public int Int { get; set; } + public long Long { get; set; } + public byte Byte { get; set; } + public ushort UShort { get; set; } + public uint UInt { get; set; } + public ulong ULong { get; set; } + public double Double { get; set; } + public float Float { get; set; } + public decimal Decimal { get; set; } + public TimeSpan TimeSpan { get; set; } + public DateTime DateTime { get; set; } + public DateTime DateTimeOffSet { get; set; } + public byte[] Bytes { get; set; } + public string String { get; set; } + public Guid Guid { get; set; } + + public bool? BoolNullable { get; set; } + public sbyte? SByteNullable { get; set; } + public short? ShortNullable { get; set; } + public int? IntNullable { get; set; } + public long? testFielLongNullable { get; set; } + public byte? ByteNullable { get; set; } + public ushort? UShortNullable { get; set; } + public uint? UIntNullable { get; set; } + public ulong? ULongNullable { get; set; } + public double? DoubleNullable { get; set; } + public float? FloatNullable { get; set; } + public decimal? DecimalNullable { get; set; } + public TimeSpan? TimeSpanNullable { get; set; } + public DateTime? DateTimeNullable { get; set; } + public DateTime? DateTimeOffSetNullable { get; set; } + public Guid? GuidNullable { get; set; } + + public TableAllTypeEnumType1 Enum1 { get; set; } + public TableAllTypeEnumType1? Enum1Nullable { get; set; } + public TableAllTypeEnumType2 Enum2 { get; set; } + public TableAllTypeEnumType2? Enum2Nullable { get; set; } + } + + public enum TableAllTypeEnumType1 { e1, e2, e3, e5 } + [Flags] public enum TableAllTypeEnumType2 { f1, f2, f3 } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/StringTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/StringTest.cs new file mode 100644 index 00000000..7ac61af1 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/StringTest.cs @@ -0,0 +1,726 @@ +using FreeSql.DataAnnotations; +using System; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace FreeSql.Tests.DamengExpression +{ + public class StringTest + { + + ISelect select => g.dameng.Select(); + + [Table(Name = "tb_topic")] + class Topic + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + public int Clicks { get; set; } + public int TypeGuid { get; set; } + public TestTypeInfo Type { get; set; } + public string Title { get; set; } + public DateTime CreateTime { get; set; } + } + class TestTypeInfo + { + [Column(IsIdentity = true)] + public int Guid { get; set; } + public int ParentId { get; set; } + public TestTypeParentInfo Parent { get; set; } + public string Name { get; set; } + } + class TestTypeParentInfo + { + public int Id { get; set; } + public string Name { get; set; } + + public List Types { get; set; } + } + class TestEqualsGuid + { + public Guid id { get; set; } + } + + [Fact] + public void Equals__() + { + var list = new List(); + list.Add(select.Where(a => a.Title.Equals("aaa")).ToList()); + list.Add(g.dameng.Select().Where(a => a.id.Equals(Guid.Empty)).ToList()); + } + + + [Fact] + public void Empty() + { + var data = new List(); + data.Add(select.Where(a => (a.Title ?? "") == string.Empty).ToSql()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (ifnull(a.`Title`, '') = '') + } + + [Fact] + public void StartsWith() + { + var list = new List(); + list.Add(select.Where(a => a.Title.StartsWith("aaa")).ToList()); + list.Add(select.Where(a => a.Title.StartsWith(a.Title)).ToList()); + list.Add(select.Where(a => a.Title.StartsWith(a.Title + 1)).ToList()); + list.Add(select.Where(a => a.Title.StartsWith(a.Type.Name)).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((a.`Title`) LIKE '%aaa') + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((a.`Title`) LIKE concat('%', a.`Title`)) + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((a.`Title`) LIKE concat('%', concat(a.`Title`, 1))) + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE((a.`Title`) LIKE concat('%', a__Type.`Name`)) + list.Add(select.Where(a => (a.Title + "aaa").StartsWith("aaa")).ToList()); + list.Add(select.Where(a => (a.Title + "aaa").StartsWith(a.Title)).ToList()); + list.Add(select.Where(a => (a.Title + "aaa").StartsWith(a.Title + 1)).ToList()); + list.Add(select.Where(a => (a.Title + "aaa").StartsWith(a.Type.Name)).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((concat(a.`Title`, 'aaa')) LIKE '%aaa') + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((concat(a.`Title`, 'aaa')) LIKE concat('%', a.`Title`)) + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((concat(a.`Title`, 'aaa')) LIKE concat('%', concat(a.`Title`, 1))) + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE((concat(a.`Title`, 'aaa')) LIKE concat('%', a__Type.`Name`)) + } + [Fact] + public void EndsWith() + { + var list = new List(); + list.Add(select.Where(a => a.Title.EndsWith("aaa")).ToList()); + list.Add(select.Where(a => a.Title.EndsWith(a.Title)).ToList()); + list.Add(select.Where(a => a.Title.EndsWith(a.Title + 1)).ToList()); + list.Add(select.Where(a => a.Title.EndsWith(a.Type.Name)).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((a.`Title`) LIKE 'aaa%') + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((a.`Title`) LIKE concat(a.`Title`, '%')) + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((a.`Title`) LIKE concat(concat(a.`Title`, 1), '%')) + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE((a.`Title`) LIKE concat(a__Type.`Name`, '%')) + list.Add(select.Where(a => (a.Title + "aaa").EndsWith("aaa")).ToList()); + list.Add(select.Where(a => (a.Title + "aaa").EndsWith(a.Title)).ToList()); + list.Add(select.Where(a => (a.Title + "aaa").EndsWith(a.Title + 1)).ToList()); + list.Add(select.Where(a => (a.Title + "aaa").EndsWith(a.Type.Name)).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((concat(a.`Title`, 'aaa')) LIKE 'aaa%') + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((concat(a.`Title`, 'aaa')) LIKE concat(a.`Title`, '%')) + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((concat(a.`Title`, 'aaa')) LIKE concat(concat(a.`Title`, 1), '%')) + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE((concat(a.`Title`, 'aaa')) LIKE concat(a__Type.`Name`, '%')) + } + [Fact] + public void Contains() + { + var list = new List(); + list.Add(select.Where(a => a.Title.Contains("aaa")).ToList()); + list.Add(select.Where(a => a.Title.Contains(a.Title)).ToList()); + list.Add(select.Where(a => a.Title.Contains(a.Title + 1)).ToList()); + list.Add(select.Where(a => a.Title.Contains(a.Type.Name)).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((a.`Title`) LIKE '%aaa%') + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((a.`Title`) LIKE concat('%', a.`Title`, '%')) + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((a.`Title`) LIKE concat('%', a.`Title` +1, '%')) + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE((a.`Title`) LIKE concat('%', a__Type.`Name`, '%')) + list.Add(select.Where(a => (a.Title + "aaa").Contains("aaa")).ToList()); + list.Add(select.Where(a => (a.Title + "aaa").Contains(a.Title)).ToList()); + list.Add(select.Where(a => (a.Title + "aaa").Contains(a.Title + 1)).ToList()); + list.Add(select.Where(a => (a.Title + "aaa").Contains(a.Type.Name)).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((concat(a.`Title`, 'aaa')) LIKE '%aaa%') + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((concat(a.`Title`, 'aaa')) LIKE concat('%', a.`Title`, '%')) + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE((concat(a.`Title`, 'aaa')) LIKE concat('%', concat(a.`Title`, 1), '%')) + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE((concat(a.`Title`, 'aaa')) LIKE concat('%', a__Type.`Name`, '%')) + } + [Fact] + public void ToLower() + { + var data = new List(); + data.Add(select.Where(a => a.Title.ToLower() == "aaa").ToList()); + data.Add(select.Where(a => a.Title.ToLower() == a.Title).ToList()); + data.Add(select.Where(a => a.Title.ToLower() == (a.Title + 1)).ToList()); + data.Add(select.Where(a => a.Title.ToLower() == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE(lower(a.`Title`) = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE(lower(a.`Title`) = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE(lower(a.`Title`) = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE(lower(a.`Title`) = a__Type.`Name`); + data.Add(select.Where(a => (a.Title.ToLower() + "aaa").ToLower() == "aaa").ToList()); + data.Add(select.Where(a => (a.Title.ToLower() + "aaa").ToLower() == a.Title).ToList()); + data.Add(select.Where(a => (a.Title.ToLower() + "aaa").ToLower() == (a.Title + 1)).ToList()); + data.Add(select.Where(a => (a.Title.ToLower() + "aaa").ToLower() == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE(lower(concat(lower(a.`Title`), 'aaa')) = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE(lower(concat(lower(a.`Title`), 'aaa')) = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE(lower(concat(lower(a.`Title`), 'aaa')) = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE(lower(concat(lower(a.`Title`), 'aaa')) = a__Type.`Name`) + } + [Fact] + public void ToUpper() + { + var data = new List(); + data.Add(select.Where(a => a.Title.ToUpper() == "aaa").ToList()); + data.Add(select.Where(a => a.Title.ToUpper() == a.Title).ToList()); + data.Add(select.Where(a => a.Title.ToUpper() == (a.Title + 1)).ToList()); + data.Add(select.Where(a => a.Title.ToUpper() == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (upper(a.`Title`) = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (upper(a.`Title`) = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (upper(a.`Title`) = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (upper(a.`Title`) = a__Type.`Name`); + data.Add(select.Where(a => (a.Title.ToUpper() + "aaa").ToUpper() == "aaa").ToList()); + data.Add(select.Where(a => (a.Title.ToUpper() + "aaa").ToUpper() == a.Title).ToList()); + data.Add(select.Where(a => (a.Title.ToUpper() + "aaa").ToUpper() == (a.Title + 1)).ToList()); + data.Add(select.Where(a => (a.Title.ToUpper() + "aaa").ToUpper() == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (upper(concat(upper(a.`Title`), 'aaa')) = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (upper(concat(upper(a.`Title`), 'aaa')) = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (upper(concat(upper(a.`Title`), 'aaa')) = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (upper(concat(upper(a.`Title`), 'aaa')) = a__Type.`Name`) + } + [Fact] + public void Substring() + { + var data = new List(); + data.Add(select.Where(a => a.Title.Substring(0) == "aaa").ToList()); + data.Add(select.Where(a => a.Title.Substring(0) == a.Title).ToList()); + data.Add(select.Where(a => a.Title.Substring(0) == (a.Title + 1)).ToList()); + data.Add(select.Where(a => a.Title.Substring(0) == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (substr(a.`Title`, 1) = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (substr(a.`Title`, 1) = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (substr(a.`Title`, 1) = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (substr(a.`Title`, 1) = a__Type.`Name`); + data.Add(select.Where(a => (a.Title.Substring(0) + "aaa").Substring(a.Title.Length) == "aaa").ToList()); + data.Add(select.Where(a => (a.Title.Substring(0) + "aaa").Substring(0, a.Title.Length) == a.Title).ToList()); + data.Add(select.Where(a => (a.Title.Substring(0) + "aaa").Substring(0, 3) == (a.Title + 1)).ToList()); + data.Add(select.Where(a => (a.Title.Substring(0) + "aaa").Substring(1, 2) == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (substr(concat(substr(a.`Title`, 1), 'aaa'), char_length(a.`Title`) + 1) = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (substr(concat(substr(a.`Title`, 1), 'aaa'), 1, char_length(a.`Title`)) = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (substr(concat(substr(a.`Title`, 1), 'aaa'), 1, 3) = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (substr(concat(substr(a.`Title`, 1), 'aaa'), 2, 2) = a__Type.`Name`) + } + [Fact] + public void Length() + { + var data = new List(); + data.Add(select.Where(a => a.Title.Length == 0).ToList()); + data.Add(select.Where(a => a.Title.Length == 1).ToList()); + data.Add(select.Where(a => a.Title.Length == a.Title.Length + 1).ToList()); + data.Add(select.Where(a => a.Title.Length == a.Type.Name.Length).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (char_length(a.`Title`) = 0); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (char_length(a.`Title`) = 1); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (char_length(a.`Title`) = char_length(a.`Title`) + 1); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (char_length(a.`Title`) = char_length(a__Type.`Name`)); + data.Add(select.Where(a => (a.Title + "aaa").Length == 0).ToList()); + data.Add(select.Where(a => (a.Title + "aaa").Length == 1).ToList()); + data.Add(select.Where(a => (a.Title + "aaa").Length == a.Title.Length + 1).ToList()); + data.Add(select.Where(a => (a.Title + "aaa").Length == a.Type.Name.Length).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (char_length(concat(a.`Title`, 'aaa')) = 0); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (char_length(concat(a.`Title`, 'aaa')) = 1); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (char_length(concat(a.`Title`, 'aaa')) = char_length(a.`Title`) + 1); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (char_length(concat(a.`Title`, 'aaa')) = char_length(a__Type.`Name`)) + } + [Fact] + public void IndexOf() + { + var data = new List(); + data.Add(select.Where(a => a.Title.IndexOf("aaa") == -1).ToList()); + data.Add(select.Where(a => a.Title.IndexOf("aaa", 2) == -1).ToList()); + data.Add(select.Where(a => a.Title.IndexOf("aaa", 2) == (a.Title.Length + 1)).ToList()); + data.Add(select.Where(a => a.Title.IndexOf("aaa", 2) == a.Type.Name.Length + 1).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE ((locate(a.`Title`, 'aaa') - 1) = -1); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE ((locate(a.`Title`, 'aaa', 3) - 1) = -1); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE ((locate(a.`Title`, 'aaa', 3) - 1) = char_length(a.`Title`) + 1); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE ((locate(a.`Title`, 'aaa', 3) - 1) = char_length(a__Type.`Name`) + 1); + data.Add(select.Where(a => (a.Title + "aaa").IndexOf("aaa") == -1).ToList()); + data.Add(select.Where(a => (a.Title + "aaa").IndexOf("aaa", 2) == -1).ToList()); + data.Add(select.Where(a => (a.Title + "aaa").IndexOf("aaa", 2) == (a.Title.Length + 1)).ToList()); + data.Add(select.Where(a => (a.Title + "aaa").IndexOf("aaa", 2) == a.Type.Name.Length + 1).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE ((locate(concat(a.`Title`, 'aaa'), 'aaa') - 1) = -1); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE ((locate(concat(a.`Title`, 'aaa'), 'aaa', 3) - 1) = -1); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE ((locate(concat(a.`Title`, 'aaa'), 'aaa', 3) - 1) = char_length(a.`Title`) + 1); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE ((locate(concat(a.`Title`, 'aaa'), 'aaa', 3) - 1) = char_length(a__Type.`Name`) + 1) + } + [Fact] + public void PadLeft() + { + var data = new List(); + data.Add(select.Where(a => a.Title.PadLeft(10, 'a') == "aaa").ToList()); + data.Add(select.Where(a => a.Title.PadLeft(10, 'a') == a.Title).ToList()); + data.Add(select.Where(a => a.Title.PadLeft(10, 'a') == (a.Title + 1)).ToList()); + data.Add(select.Where(a => a.Title.PadLeft(10, 'a') == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (lpad(a.`Title`, 10, 'a') = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (lpad(a.`Title`, 10, 'a') = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (lpad(a.`Title`, 10, 'a') = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (lpad(a.`Title`, 10, 'a') = a__Type.`Name`); + data.Add(select.Where(a => (a.Title.PadLeft(10, 'a') + "aaa").PadLeft(20, 'b') == "aaa").ToList()); + data.Add(select.Where(a => (a.Title.PadLeft(10, 'a') + "aaa").PadLeft(20, 'b') == a.Title).ToList()); + data.Add(select.Where(a => (a.Title.PadLeft(10, 'a') + "aaa").PadLeft(20, 'b') == (a.Title + 1)).ToList()); + data.Add(select.Where(a => (a.Title.PadLeft(10, 'a') + "aaa").PadLeft(20, 'b') == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (lpad(concat(lpad(a.`Title`, 10, 'a'), 'aaa'), 20, 'b') = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (lpad(concat(lpad(a.`Title`, 10, 'a'), 'aaa'), 20, 'b') = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (lpad(concat(lpad(a.`Title`, 10, 'a'), 'aaa'), 20, 'b') = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (lpad(concat(lpad(a.`Title`, 10, 'a'), 'aaa'), 20, 'b') = a__Type.`Name`) + } + [Fact] + public void PadRight() + { + var data = new List(); + data.Add(select.Where(a => a.Title.PadRight(10, 'a') == "aaa").ToList()); + data.Add(select.Where(a => a.Title.PadRight(10, 'a') == a.Title).ToList()); + data.Add(select.Where(a => a.Title.PadRight(10, 'a') == (a.Title + 1)).ToList()); + data.Add(select.Where(a => a.Title.PadRight(10, 'a') == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (rpad(a.`Title`, 10, 'a') = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (rpad(a.`Title`, 10, 'a') = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (rpad(a.`Title`, 10, 'a') = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (rpad(a.`Title`, 10, 'a') = a__Type.`Name`); + data.Add(select.Where(a => (a.Title.PadRight(10, 'a') + "aaa").PadRight(20, 'b') == "aaa").ToList()); + data.Add(select.Where(a => (a.Title.PadRight(10, 'a') + "aaa").PadRight(20, 'b') == a.Title).ToList()); + data.Add(select.Where(a => (a.Title.PadRight(10, 'a') + "aaa").PadRight(20, 'b') == (a.Title + 1)).ToList()); + data.Add(select.Where(a => (a.Title.PadRight(10, 'a') + "aaa").PadRight(20, 'b') == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (rpad(concat(rpad(a.`Title`, 10, 'a'), 'aaa'), 20, 'b') = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (rpad(concat(rpad(a.`Title`, 10, 'a'), 'aaa'), 20, 'b') = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (rpad(concat(rpad(a.`Title`, 10, 'a'), 'aaa'), 20, 'b') = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (rpad(concat(rpad(a.`Title`, 10, 'a'), 'aaa'), 20, 'b') = a__Type.`Name`) + } + [Fact] + public void Trim() + { + var data = new List(); + data.Add(select.Where(a => a.Title.Trim() == "aaa").ToList()); + data.Add(select.Where(a => a.Title.Trim('a') == a.Title).ToList()); + data.Add(select.Where(a => a.Title.Trim('a', 'b') == (a.Title + 1)).ToList()); + data.Add(select.Where(a => a.Title.Trim('a', 'b', 'c') == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (trim(a.`Title`) = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (trim('a' from a.`Title`) = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (trim('b' from trim('a' from a.`Title`)) = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (trim('c' from trim('b' from trim('a' from a.`Title`))) = a__Type.`Name`); + data.Add(select.Where(a => (a.Title.Trim() + "aaa").Trim() == "aaa").ToList()); + data.Add(select.Where(a => (a.Title.Trim('a') + "aaa").Trim('a') == a.Title).ToList()); + data.Add(select.Where(a => (a.Title.Trim('a', 'b') + "aaa").Trim('a', 'b') == (a.Title + 1)).ToList()); + data.Add(select.Where(a => (a.Title.Trim('a', 'b', 'c') + "aaa").Trim('a', 'b', 'c') == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (trim(concat(trim(a.`Title`), 'aaa')) = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (trim('a' from concat(trim('a' from a.`Title`), 'aaa')) = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (trim('b' from trim('a' from concat(trim('b' from trim('a' from a.`Title`)), 'aaa'))) = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (trim('c' from trim('b' from trim('a' from concat(trim('c' from trim('b' from trim('a' from a.`Title`))), 'aaa')))) = a__Type.`Name`) + } + [Fact] + public void TrimStart() + { + var data = new List(); + data.Add(select.Where(a => a.Title.TrimStart() == "aaa").ToList()); + data.Add(select.Where(a => a.Title.TrimStart('a') == a.Title).ToList()); + data.Add(select.Where(a => a.Title.TrimStart('a', 'b') == (a.Title + 1)).ToList()); + data.Add(select.Where(a => a.Title.TrimStart('a', 'b', 'c') == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (ltrim(a.`Title`) = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (trim(trailing 'a' from trim(leading 'a' from a.`Title`)) = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (trim(trailing 'b' from trim(leading 'b' from trim(trailing 'a' from trim(leading 'a' from a.`Title`)))) = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (trim(trailing 'c' from trim(leading 'c' from trim(trailing 'b' from trim(leading 'b' from trim(trailing 'a' from trim(leading 'a' from a.`Title`)))))) = a__Type.`Name`); + data.Add(select.Where(a => (a.Title.TrimStart() + "aaa").TrimStart() == "aaa").ToList()); + data.Add(select.Where(a => (a.Title.TrimStart('a') + "aaa").TrimStart('a') == a.Title).ToList()); + data.Add(select.Where(a => (a.Title.TrimStart('a', 'b') + "aaa").TrimStart('a', 'b') == (a.Title + 1)).ToList()); + data.Add(select.Where(a => (a.Title.TrimStart('a', 'b', 'c') + "aaa").TrimStart('a', 'b', 'c') == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (ltrim(concat(ltrim(a.`Title`), 'aaa')) = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (trim(trailing 'a' from trim(leading 'a' from concat(trim(trailing 'a' from trim(leading 'a' from a.`Title`)), 'aaa'))) = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (trim(trailing 'b' from trim(leading 'b' from trim(trailing 'a' from trim(leading 'a' from concat(trim(trailing 'b' from trim(leading 'b' from trim(trailing 'a' from trim(leading 'a' from a.`Title`)))), 'aaa'))))) = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (trim(trailing 'c' from trim(leading 'c' from trim(trailing 'b' from trim(leading 'b' from trim(trailing 'a' from trim(leading 'a' from concat(trim(trailing 'c' from trim(leading 'c' from trim(trailing 'b' from trim(leading 'b' from trim(trailing 'a' from trim(leading 'a' from a.`Title`)))))), 'aaa'))))))) = a__Type.`Name`) + } + [Fact] + public void TrimEnd() + { + var data = new List(); + data.Add(select.Where(a => a.Title.TrimEnd() == "aaa").ToList()); + data.Add(select.Where(a => a.Title.TrimEnd('a') == a.Title).ToList()); + data.Add(select.Where(a => a.Title.TrimEnd('a', 'b') == (a.Title + 1)).ToList()); + data.Add(select.Where(a => a.Title.TrimEnd('a', 'b', 'c') == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (rtrim(a.`Title`) = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (trim(trailing 'a' from a.`Title`) = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (trim(trailing 'b' from trim(trailing 'a' from a.`Title`)) = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (trim(trailing 'c' from trim(trailing 'b' from trim(trailing 'a' from a.`Title`))) = a__Type.`Name`); + data.Add(select.Where(a => (a.Title.TrimEnd() + "aaa").TrimEnd() == "aaa").ToList()); + data.Add(select.Where(a => (a.Title.TrimEnd('a') + "aaa").TrimEnd('a') == a.Title).ToList()); + data.Add(select.Where(a => (a.Title.TrimEnd('a', 'b') + "aaa").TrimEnd('a', 'b') == (a.Title + 1)).ToList()); + data.Add(select.Where(a => (a.Title.TrimEnd('a', 'b', 'c') + "aaa").TrimEnd('a', 'b', 'c') == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (rtrim(concat(rtrim(a.`Title`), 'aaa')) = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (trim(trailing 'a' from concat(trim(trailing 'a' from a.`Title`), 'aaa')) = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (trim(trailing 'b' from trim(trailing 'a' from concat(trim(trailing 'b' from trim(trailing 'a' from a.`Title`)), 'aaa'))) = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (trim(trailing 'c' from trim(trailing 'b' from trim(trailing 'a' from concat(trim(trailing 'c' from trim(trailing 'b' from trim(trailing 'a' from a.`Title`))), 'aaa')))) = a__Type.`Name`) + } + [Fact] + public void Replace() + { + var data = new List(); + data.Add(select.Where(a => a.Title.Replace("a", "b") == "aaa").ToList()); + data.Add(select.Where(a => a.Title.Replace("a", "b").Replace("b", "c") == a.Title).ToList()); + data.Add(select.Where(a => a.Title.Replace("a", "b").Replace("b", "c").Replace("c", "a") == (a.Title + 1)).ToList()); + data.Add(select.Where(a => a.Title.Replace("a", "b").Replace("b", "c").Replace(a.Type.Name, "a") == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (replace(a.`Title`, 'a', 'b') = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (replace(replace(a.`Title`, 'a', 'b'), 'b', 'c') = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (replace(replace(replace(a.`Title`, 'a', 'b'), 'b', 'c'), 'c', 'a') = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (replace(replace(replace(a.`Title`, 'a', 'b'), 'b', 'c'), a__Type.`Name`, 'a') = a__Type.`Name`); + data.Add(select.Where(a => (a.Title.Replace("a", "b") + "aaa").TrimEnd() == "aaa").ToList()); + data.Add(select.Where(a => (a.Title.Replace("a", "b").Replace("b", "c") + "aaa").TrimEnd('a') == a.Title).ToList()); + data.Add(select.Where(a => (a.Title.Replace("a", "b").Replace("b", "c").Replace("c", "a") + "aaa").TrimEnd('a', 'b') == (a.Title + 1)).ToList()); + data.Add(select.Where(a => (a.Title.Replace("a", "b").Replace("b", "c").Replace(a.Type.Name, "a") + "aaa").TrimEnd('a', 'b', 'c') == a.Type.Name).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (concat(replace(a.`Title`, 'a', 'b'), 'aaa') = 'aaa'); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (concat(replace(replace(a.`Title`, 'a', 'b'), 'b', 'c'), 'aaa') = a.`Title`); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (concat(replace(replace(replace(a.`Title`, 'a', 'b'), 'b', 'c'), 'c', 'a'), 'aaa') = concat(a.`Title`, 1)); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (concat(replace(replace(replace(a.`Title`, 'a', 'b'), 'b', 'c'), a__Type.`Name`, 'a'), 'aaa') = a__Type.`Name`) + } + [Fact] + public void CompareTo() + { + var data = new List(); + data.Add(select.Where(a => a.Title.CompareTo(a.Title) == 0).ToList()); + data.Add(select.Where(a => a.Title.CompareTo(a.Title) > 0).ToList()); + data.Add(select.Where(a => a.Title.CompareTo(a.Title + 1) == 0).ToList()); + data.Add(select.Where(a => a.Title.CompareTo(a.Title + a.Type.Name) == 0).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (strcmp(a.`Title`, a.`Title`) = 0); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (strcmp(a.`Title`, a.`Title`) > 0); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (strcmp(a.`Title`, concat(a.`Title`, 1)) = 0); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (strcmp(a.`Title`, concat(a.`Title`, a__Type.`Name`)) = 0); + data.Add(select.Where(a => (a.Title + "aaa").CompareTo("aaa") == 0).ToList()); + data.Add(select.Where(a => (a.Title + "aaa").CompareTo(a.Title) > 0).ToList()); + data.Add(select.Where(a => (a.Title + "aaa").CompareTo(a.Title + 1) == 0).ToList()); + data.Add(select.Where(a => (a.Title + "aaa").CompareTo(a.Type.Name) == 0).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (strcmp(concat(a.`Title`, 'aaa'), 'aaa') = 0); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (strcmp(concat(a.`Title`, 'aaa'), a.`Title`) > 0); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (strcmp(concat(a.`Title`, 'aaa'), concat(a.`Title`, 1)) = 0); + + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a__Type.`Guid` as4, a__Type.`ParentId` as5, a__Type.`Name` as6, a.`Title` as7, a.`CreateTime` as8 + //FROM `tb_topic` a, `TestTypeInfo` a__Type + //WHERE (strcmp(concat(a.`Title`, 'aaa'), a__Type.`Name`) = 0) + } + + [Fact] + public void string_IsNullOrEmpty() + { + var data = new List(); + data.Add(select.Where(a => string.IsNullOrEmpty(a.Title)).ToList()); + data.Add(select.Where(a => !string.IsNullOrEmpty(a.Title)).ToList()); + } + + [Fact] + public void string_IsNullOrWhiteSpace() + { + var data = new List(); + data.Add(select.Where(a => string.IsNullOrWhiteSpace(a.Title)).ToList()); + data.Add(select.Where(a => !string.IsNullOrWhiteSpace(a.Title)).ToList()); + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/TimeSpanTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/TimeSpanTest.cs new file mode 100644 index 00000000..1e8a081a --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/DamengExpression/TimeSpanTest.cs @@ -0,0 +1,293 @@ +using FreeSql.DataAnnotations; +using System; +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace FreeSql.Tests.DamengExpression +{ + public class TimeSpanTest + { + + ISelect select => g.dameng.Select(); + + [Table(Name = "tb_topic")] + class Topic + { + [Column(IsIdentity = true, IsPrimary = true)] + public int Id { get; set; } + public int Clicks { get; set; } + public int TypeGuid { get; set; } + public TestTypeInfo Type { get; set; } + public string Title { get; set; } + public DateTime CreateTime { get; set; } + } + class TestTypeInfo + { + public int Guid { get; set; } + public int ParentId { get; set; } + public TestTypeParentInfo Parent { get; set; } + public string Name { get; set; } + } + class TestTypeParentInfo + { + public int Id { get; set; } + public string Name { get; set; } + + public List Types { get; set; } + } + [Fact] + public void Zero() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay > TimeSpan.Zero).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000) > 0) + } + [Fact] + public void MinValue() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay > TimeSpan.MinValue).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000) > -922337203685477580) + } + [Fact] + public void MaxValue() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay < TimeSpan.MaxValue).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000) < 922337203685477580) + } + [Fact] + public void Days() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay.Days == 0).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000)) div 86400000000) = 0) + } + [Fact] + public void Hours() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay.Hours > 0).ToSql()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000)) div 3600000000) mod 24 > 0) + } + [Fact] + public void Milliseconds() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay.Milliseconds > 0).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000)) div 1000 mod 1000) > 0) + } + [Fact] + public void Minutes() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay.Minutes > 0).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000)) div 60000000 mod 60) > 0) + } + [Fact] + public void Seconds() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay.Seconds > 0).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000)) div 1000000 mod 60) > 0) + } + [Fact] + public void Ticks() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay.Ticks > 0).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000)) * 10) > 0) + } + [Fact] + public void TotalDays() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay.TotalDays > 0).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000)) / 86400000000) > 0) + } + [Fact] + public void TotalHours() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay.TotalHours > 0).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000)) / 3600000000) > 0) + } + [Fact] + public void TotalMilliseconds() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay.TotalMilliseconds > 0).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000)) / 1000) > 0) + } + [Fact] + public void TotalMinutes() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay.TotalMinutes > 0).ToSql()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000)) / 60000000) > 0) + } + [Fact] + public void TotalSeconds() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay.TotalSeconds > 0).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000)) / 1000000) > 0) + } + [Fact] + public void Add() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay.Add(TimeSpan.FromDays(1)) > TimeSpan.Zero).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE ((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000) + (1 * 86400000000)) > 0) + } + [Fact] + public void Subtract() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay.Subtract(TimeSpan.FromDays(1)) > TimeSpan.Zero).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE ((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000) - (1 * 86400000000)) > 0) + } + [Fact] + public void CompareTo() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay.CompareTo(TimeSpan.FromDays(1)) > 0).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000)) - ((1 * 86400000000))) > 0) + } + [Fact] + public void this_Equals() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay.Equals(TimeSpan.FromDays(1))).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE ((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000) = (1 * 86400000000))) + } + [Fact] + public void this_ToString() + { + var data = new List(); + data.Add(select.Where(a => a.CreateTime.TimeOfDay.ToString() == "ssss").ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (date_format(date_add(cast('0001/1/1 0:00:00' as datetime), interval (timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000)) microsecond), '%Y-%m-%d %H:%i:%s.%f') = 'ssss') + } + + [Fact] + public void TimeSpan_Compare() + { + var data = new List(); + data.Add(select.Where(a => TimeSpan.Compare(a.CreateTime.TimeOfDay, TimeSpan.FromDays(1)) > 0).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000)) - ((1 * 86400000000))) > 0) + } + [Fact] + public void TimeSpan_Equals() + { + var data = new List(); + data.Add(select.Where(a => TimeSpan.Equals(a.CreateTime.TimeOfDay, TimeSpan.FromDays(1))).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE ((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000) = (1 * 86400000000))) + } + [Fact] + public void TimeSpan_FromDays() + { + var data = new List(); + data.Add(select.Where(a => TimeSpan.Equals(a.CreateTime.TimeOfDay, TimeSpan.FromDays(1))).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE ((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000) = (1 * 86400000000))) + } + [Fact] + public void TimeSpan_FromHours() + { + var data = new List(); + data.Add(select.Where(a => TimeSpan.Equals(a.CreateTime.TimeOfDay, TimeSpan.FromHours(1))).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE ((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000) = (1 * 3600000000))) + } + [Fact] + public void TimeSpan_FromMilliseconds() + { + var data = new List(); + data.Add(select.Where(a => TimeSpan.Equals(a.CreateTime.TimeOfDay, TimeSpan.FromMilliseconds(1))).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE ((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000) = (1 * 1000))) + } + [Fact] + public void TimeSpan_FromMinutes() + { + var data = new List(); + data.Add(select.Where(a => TimeSpan.Equals(a.CreateTime.TimeOfDay, TimeSpan.FromMinutes(1))).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE ((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000) = (1 * 60000000))) + } + [Fact] + public void TimeSpan_FromSeconds() + { + var data = new List(); + data.Add(select.Where(a => TimeSpan.Equals(a.CreateTime.TimeOfDay, TimeSpan.FromSeconds(1))).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE ((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000) = (1 * 1000000))) + } + [Fact] + public void TimeSpan_FromTicks() + { + var data = new List(); + data.Add(select.Where(a => TimeSpan.Equals(a.CreateTime.TimeOfDay, TimeSpan.FromTicks(1))).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE ((timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000) = (1 / 10))) + } + [Fact] + public void TimeSpan_Parse() + { + var data = new List(); + data.Add(select.Where(a => TimeSpan.Parse(a.CreateTime.TimeOfDay.ToString()) > TimeSpan.Zero).ToList()); + //SELECT a.`Id` as1, a.`Clicks` as2, a.`TypeGuid` as3, a.`Title` as4, a.`CreateTime` as5 + //FROM `tb_topic` a + //WHERE (cast(date_format(date_add(cast('0001/1/1 0:00:00' as datetime), interval (timestampdiff(microsecond, date_format(a.`CreateTime`, '1970-1-1 %H:%i:%s.%f'), a.`CreateTime`) + 62135596800000000)) microsecond), '%Y-%m-%d %H:%i:%s.%f') as signed) > 0) + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/MapType/BoolNullableTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/MapType/BoolNullableTest.cs new file mode 100644 index 00000000..d9b748ac --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/MapType/BoolNullableTest.cs @@ -0,0 +1,1571 @@ +using FreeSql.DataAnnotations; +using System; +using Xunit; + +namespace FreeSql.Tests.DamengMapType +{ + public class BoolNullableTest + { + class BoolNullableMap + { + public Guid id { get; set; } + [Column(MapType = typeof(bool))] + public bool? tobool { get; set; } = true; + + [Column(MapType = typeof(sbyte))] + public bool? tosbyte { get; set; } = true; + [Column(MapType = typeof(sbyte?))] + public bool? tosbytenullable { get; set; } = true; + + [Column(MapType = typeof(short))] + public bool? toshort { get; set; } = true; + + [Column(MapType = typeof(short?))] + public bool? toshortnullable { get; set; } = true; + + [Column(MapType = typeof(int))] + public bool? toint { get; set; } = true; + + [Column(MapType = typeof(int?))] + public bool? tointnullable { get; set; } = true; + + [Column(MapType = typeof(long))] + public bool? tolong { get; set; } = true; + [Column(MapType = typeof(long?))] + public bool? tolongnullable { get; set; } = true; + + [Column(MapType = typeof(byte))] + public bool? tobyte { get; set; } = true; + [Column(MapType = typeof(byte?))] + public bool? tobytenullable { get; set; } = true; + + [Column(MapType = typeof(ushort))] + public bool? toushort { get; set; } = true; + + [Column(MapType = typeof(ushort?))] + public bool? toushortnullable { get; set; } = true; + + [Column(MapType = typeof(uint))] + public bool? touint { get; set; } = true; + + [Column(MapType = typeof(uint?))] + public bool? touintnullable { get; set; } = true; + + [Column(MapType = typeof(ulong))] + public bool? toulong { get; set; } = true; + [Column(MapType = typeof(ulong?))] + public bool? toulongnullable { get; set; } = true; + + [Column(MapType = typeof(string))] + public bool? tostring { get; set; } = true; + } + [Fact] + public void Bool() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.tobool == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobool, find.tobool); + Assert.Equal(true, find.tobool); + + item = new BoolNullableMap { tobool = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobool == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobool, find.tobool); + Assert.Equal(false, find.tobool); + + item = new BoolNullableMap { tobool = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tobool == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.tobool == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.tobool, find.tobool); + Assert.Equal(false, find.tobool); + + //update all + item.tobool = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobool == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobool, find.tobool); + Assert.Equal(true, find.tobool); + + item.tobool = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobool == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobool, find.tobool); + Assert.Equal(false, find.tobool); + + item.tobool = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tobool == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.tobool == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.tobool, find.tobool); + Assert.Equal(false, find.tobool); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tobool, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobool == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.tobool); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tobool, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobool == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.tobool); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tobool, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tobool == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.tobool == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.tobool); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tobool == true).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tobool == null).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.tobool == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void SByte() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.tosbyte == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbyte, find.tosbyte); + Assert.Equal(true, find.tosbyte); + + item = new BoolNullableMap { tosbyte = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbyte, find.tosbyte); + Assert.Equal(false, find.tosbyte); + + item = new BoolNullableMap { tosbyte = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tosbyte == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.tosbyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.tosbyte, find.tosbyte); + Assert.Equal(false, find.tosbyte); + + //update all + item.tosbyte = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbyte == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbyte, find.tosbyte); + Assert.Equal(true, find.tosbyte); + + item.tosbyte = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbyte, find.tosbyte); + Assert.Equal(false, find.tosbyte); + + item.tosbyte = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tosbyte == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.tosbyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.tosbyte, find.tosbyte); + Assert.Equal(false, find.tosbyte); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tosbyte, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbyte == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.tosbyte); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tosbyte, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.tosbyte); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tosbyte, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tosbyte == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.tosbyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.tosbyte); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tosbyte == true).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tosbyte == null).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.tosbyte == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void SByteNullable() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.tosbytenullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbytenullable, find.tosbytenullable); + Assert.Equal(true, find.tosbytenullable); + + item = new BoolNullableMap { tosbytenullable = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbytenullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbytenullable, find.tosbytenullable); + Assert.Equal(false, find.tosbytenullable); + + item = new BoolNullableMap { tosbytenullable = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tosbytenullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.tosbytenullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbytenullable, find.tosbytenullable); + Assert.Null(find.tosbytenullable); + + //update all + item.tosbytenullable = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbytenullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbytenullable, find.tosbytenullable); + Assert.Equal(true, find.tosbytenullable); + + item.tosbytenullable = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbytenullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbytenullable, find.tosbytenullable); + Assert.Equal(false, find.tosbytenullable); + + item.tosbytenullable = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tosbytenullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.tosbytenullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbytenullable, find.tosbytenullable); + Assert.Null(find.tosbytenullable); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tosbytenullable, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbytenullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.tosbytenullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tosbytenullable, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbytenullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.tosbytenullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tosbytenullable, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tosbytenullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.tosbytenullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Null(find.tosbytenullable); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tosbytenullable == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.tosbytenullable == null).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tosbytenullable == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void Short() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.toshort == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshort, find.toshort); + Assert.Equal(true, find.toshort); + + item = new BoolNullableMap { toshort = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshort, find.toshort); + Assert.Equal(false, find.toshort); + + item = new BoolNullableMap { toshort = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toshort == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.toshort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.toshort, find.toshort); + Assert.Equal(false, find.toshort); + + //update all + item.toshort = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshort == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshort, find.toshort); + Assert.Equal(true, find.toshort); + + item.toshort = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshort, find.toshort); + Assert.Equal(false, find.toshort); + + item.toshort = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toshort == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.toshort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.toshort, find.toshort); + Assert.Equal(false, find.toshort); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toshort, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshort == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.toshort); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toshort, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.toshort); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toshort, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toshort == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.toshort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.toshort); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toshort == true).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toshort == null).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.toshort == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void ShortNullable() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.toshortnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshortnullable, find.toshortnullable); + Assert.Equal(true, find.toshortnullable); + + item = new BoolNullableMap { toshortnullable = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshortnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshortnullable, find.toshortnullable); + Assert.Equal(false, find.toshortnullable); + + item = new BoolNullableMap { toshortnullable = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toshortnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.toshortnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshortnullable, find.toshortnullable); + Assert.Null(find.toshortnullable); + + //update all + item.toshortnullable = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshortnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshortnullable, find.toshortnullable); + Assert.Equal(true, find.toshortnullable); + + item.toshortnullable = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshortnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshortnullable, find.toshortnullable); + Assert.Equal(false, find.toshortnullable); + + item.toshortnullable = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toshortnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.toshortnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshortnullable, find.toshortnullable); + Assert.Null(find.toshortnullable); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toshortnullable, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshortnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.toshortnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toshortnullable, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshortnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.toshortnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toshortnullable, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toshortnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.toshortnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Null(find.toshortnullable); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toshortnullable == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.toshortnullable == null).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toshortnullable == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void Int() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.toint == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toint, find.toint); + Assert.Equal(true, find.toint); + + item = new BoolNullableMap { toint = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toint, find.toint); + Assert.Equal(false, find.toint); + + item = new BoolNullableMap { toint = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toint == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.toint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.toint, find.toint); + Assert.Equal(false, find.toint); + + //update all + item.toint = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toint == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toint, find.toint); + Assert.Equal(true, find.toint); + + item.toint = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toint, find.toint); + Assert.Equal(false, find.toint); + + item.toint = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toint == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.toint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.toint, find.toint); + Assert.Equal(false, find.toint); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toint, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toint == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.toint); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toint, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.toint); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toint, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toint == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.toint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.toint); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toint == true).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toint == null).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.toint == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void IntNullable() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.tointnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tointnullable, find.tointnullable); + Assert.Equal(true, find.tointnullable); + + item = new BoolNullableMap { tointnullable = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tointnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tointnullable, find.tointnullable); + Assert.Equal(false, find.tointnullable); + + item = new BoolNullableMap { tointnullable = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tointnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.tointnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tointnullable, find.tointnullable); + Assert.Null(find.tointnullable); + + //update all + item.tointnullable = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tointnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tointnullable, find.tointnullable); + Assert.Equal(true, find.tointnullable); + + item.tointnullable = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tointnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tointnullable, find.tointnullable); + Assert.Equal(false, find.tointnullable); + + item.tointnullable = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tointnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.tointnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tointnullable, find.tointnullable); + Assert.Null(find.tointnullable); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tointnullable, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tointnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.tointnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tointnullable, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tointnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.tointnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tointnullable, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tointnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.tointnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Null(find.tointnullable); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tointnullable == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.tointnullable == null).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tointnullable == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void Long() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.tolong == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolong, find.tolong); + Assert.Equal(true, find.tolong); + + item = new BoolNullableMap { tolong = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolong, find.tolong); + Assert.Equal(false, find.tolong); + + item = new BoolNullableMap { tolong = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tolong == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.tolong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.tolong, find.tolong); + Assert.Equal(false, find.tolong); + + //update all + item.tolong = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolong == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolong, find.tolong); + Assert.Equal(true, find.tolong); + + item.tolong = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolong, find.tolong); + Assert.Equal(false, find.tolong); + + item.tolong = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tolong == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.tolong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.tolong, find.tolong); + Assert.Equal(false, find.tolong); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tolong, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolong == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.tolong); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tolong, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.tolong); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tolong, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tolong == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.tolong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.tolong); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tolong == true).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tolong == null).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.tolong == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void LongNullable() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.tolongnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolongnullable, find.tolongnullable); + Assert.Equal(true, find.tolongnullable); + + item = new BoolNullableMap { tolongnullable = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolongnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolongnullable, find.tolongnullable); + Assert.Equal(false, find.tolongnullable); + + item = new BoolNullableMap { tolongnullable = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tolongnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.tolongnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolongnullable, find.tolongnullable); + Assert.Null(find.tolongnullable); + + //update all + item.tolongnullable = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolongnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolongnullable, find.tolongnullable); + Assert.Equal(true, find.tolongnullable); + + item.tolongnullable = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolongnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolongnullable, find.tolongnullable); + Assert.Equal(false, find.tolongnullable); + + item.tolongnullable = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tolongnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.tolongnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolongnullable, find.tolongnullable); + Assert.Null(find.tolongnullable); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tolongnullable, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolongnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.tolongnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tolongnullable, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolongnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.tolongnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tolongnullable, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tolongnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.tolongnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Null(find.tolongnullable); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tolongnullable == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.tolongnullable == null).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tolongnullable == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + + [Fact] + public void Byte() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.tobyte == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobyte, find.tobyte); + Assert.Equal(true, find.tobyte); + + item = new BoolNullableMap { tobyte = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobyte, find.tobyte); + Assert.Equal(false, find.tobyte); + + item = new BoolNullableMap { tobyte = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tobyte == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.tobyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.tobyte, find.tobyte); + Assert.Equal(false, find.tobyte); + + //update all + item.tobyte = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobyte == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobyte, find.tobyte); + Assert.Equal(true, find.tobyte); + + item.tobyte = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobyte, find.tobyte); + Assert.Equal(false, find.tobyte); + + item.tobyte = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tobyte == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.tobyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.tobyte, find.tobyte); + Assert.Equal(false, find.tobyte); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tobyte, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobyte == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.tobyte); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tobyte, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.tobyte); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tobyte, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tobyte == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.tobyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.tobyte); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tobyte == true).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tobyte == null).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.tobyte == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void ByteNullable() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.tobytenullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobytenullable, find.tobytenullable); + Assert.Equal(true, find.tobytenullable); + + item = new BoolNullableMap { tobytenullable = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobytenullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobytenullable, find.tobytenullable); + Assert.Equal(false, find.tobytenullable); + + item = new BoolNullableMap { tobytenullable = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tobytenullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.tobytenullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobytenullable, find.tobytenullable); + Assert.Null(find.tobytenullable); + + //update all + item.tobytenullable = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobytenullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobytenullable, find.tobytenullable); + Assert.Equal(true, find.tobytenullable); + + item.tobytenullable = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobytenullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobytenullable, find.tobytenullable); + Assert.Equal(false, find.tobytenullable); + + item.tobytenullable = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tobytenullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.tobytenullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobytenullable, find.tobytenullable); + Assert.Null(find.tobytenullable); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tobytenullable, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobytenullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.tobytenullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tobytenullable, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobytenullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.tobytenullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tobytenullable, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tobytenullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.tobytenullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Null(find.tobytenullable); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tobytenullable == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.tobytenullable == null).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tobytenullable == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void UShort() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.toushort == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushort, find.toushort); + Assert.Equal(true, find.toushort); + + item = new BoolNullableMap { toushort = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushort, find.toushort); + Assert.Equal(false, find.toushort); + + item = new BoolNullableMap { toushort = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toushort == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.toushort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.toushort, find.toushort); + Assert.Equal(false, find.toushort); + + //update all + item.toushort = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushort == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushort, find.toushort); + Assert.Equal(true, find.toushort); + + item.toushort = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushort, find.toushort); + Assert.Equal(false, find.toushort); + + item.toushort = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toushort == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.toushort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.toushort, find.toushort); + Assert.Equal(false, find.toushort); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toushort, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushort == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.toushort); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toushort, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.toushort); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toushort, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toushort == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.toushort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.toushort); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toushort == true).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toushort == null).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.toushort == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void UShortNullable() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.toushortnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushortnullable, find.toushortnullable); + Assert.Equal(true, find.toushortnullable); + + item = new BoolNullableMap { toushortnullable = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushortnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushortnullable, find.toushortnullable); + Assert.Equal(false, find.toushortnullable); + + item = new BoolNullableMap { toushortnullable = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toushortnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.toushortnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushortnullable, find.toushortnullable); + Assert.Null(find.toushortnullable); + + //update all + item.toushortnullable = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushortnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushortnullable, find.toushortnullable); + Assert.Equal(true, find.toushortnullable); + + item.toushortnullable = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushortnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushortnullable, find.toushortnullable); + Assert.Equal(false, find.toushortnullable); + + item.toushortnullable = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toushortnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.toushortnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushortnullable, find.toushortnullable); + Assert.Null(find.toushortnullable); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toushortnullable, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushortnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.toushortnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toushortnullable, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushortnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.toushortnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toushortnullable, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toushortnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.toushortnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Null(find.toushortnullable); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toushortnullable == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.toushortnullable == null).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toushortnullable == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void UInt() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.touint == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touint, find.touint); + Assert.Equal(true, find.touint); + + item = new BoolNullableMap { touint = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touint, find.touint); + Assert.Equal(false, find.touint); + + item = new BoolNullableMap { touint = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.touint == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.touint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.touint, find.touint); + Assert.Equal(false, find.touint); + + //update all + item.touint = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touint == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touint, find.touint); + Assert.Equal(true, find.touint); + + item.touint = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touint, find.touint); + Assert.Equal(false, find.touint); + + item.touint = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.touint == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.touint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.touint, find.touint); + Assert.Equal(false, find.touint); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.touint, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touint == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.touint); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.touint, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.touint); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.touint, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.touint == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.touint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.touint); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.touint == true).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.touint == null).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.touint == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void UIntNullable() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.touintnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touintnullable, find.touintnullable); + Assert.Equal(true, find.touintnullable); + + item = new BoolNullableMap { touintnullable = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touintnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touintnullable, find.touintnullable); + Assert.Equal(false, find.touintnullable); + + item = new BoolNullableMap { touintnullable = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.touintnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.touintnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touintnullable, find.touintnullable); + Assert.Null(find.touintnullable); + + //update all + item.touintnullable = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touintnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touintnullable, find.touintnullable); + Assert.Equal(true, find.touintnullable); + + item.touintnullable = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touintnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touintnullable, find.touintnullable); + Assert.Equal(false, find.touintnullable); + + item.touintnullable = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.touintnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.touintnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touintnullable, find.touintnullable); + Assert.Null(find.touintnullable); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.touintnullable, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touintnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.touintnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.touintnullable, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touintnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.touintnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.touintnullable, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.touintnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.touintnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Null(find.touintnullable); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.touintnullable == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.touintnullable == null).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.touintnullable == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void ULong() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.toulong == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulong, find.toulong); + Assert.Equal(true, find.toulong); + + item = new BoolNullableMap { toulong = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulong, find.toulong); + Assert.Equal(false, find.toulong); + + item = new BoolNullableMap { toulong = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toulong == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.toulong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.toulong, find.toulong); + Assert.Equal(false, find.toulong); + + //update all + item.toulong = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulong == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulong, find.toulong); + Assert.Equal(true, find.toulong); + + item.toulong = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulong, find.toulong); + Assert.Equal(false, find.toulong); + + item.toulong = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toulong == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.toulong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.NotEqual(item.toulong, find.toulong); + Assert.Equal(false, find.toulong); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toulong, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulong == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.toulong); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toulong, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.toulong); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toulong, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toulong == null).First()); + find = orm.Select().Where(a => a.id == item.id && a.toulong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.toulong); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toulong == true).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toulong == null).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.toulong == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void ULongNullable() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.toulongnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulongnullable, find.toulongnullable); + Assert.Equal(true, find.toulongnullable); + + item = new BoolNullableMap { toulongnullable = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulongnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulongnullable, find.toulongnullable); + Assert.Equal(false, find.toulongnullable); + + item = new BoolNullableMap { toulongnullable = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toulongnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.toulongnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulongnullable, find.toulongnullable); + Assert.Null(find.toulongnullable); + + //update all + item.toulongnullable = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulongnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulongnullable, find.toulongnullable); + Assert.Equal(true, find.toulongnullable); + + item.toulongnullable = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulongnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulongnullable, find.toulongnullable); + Assert.Equal(false, find.toulongnullable); + + item.toulongnullable = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toulongnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.toulongnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulongnullable, find.toulongnullable); + Assert.Null(find.toulongnullable); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toulongnullable, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulongnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.toulongnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toulongnullable, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulongnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.toulongnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toulongnullable, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.toulongnullable == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.toulongnullable == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Null(find.toulongnullable); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toulongnullable == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.toulongnullable == null).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toulongnullable == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + + [Fact] + public void TimeSpan() + { + } + [Fact] + public void TimeSpanNullable() + { + } + [Fact] + public void DateTime() + { + } + [Fact] + public void DateTimeNullable() + { + } + + [Fact] + public void ByteArray() + { + } + [Fact] + public void String() + { + //insert + var orm = g.dameng; + var item = new BoolNullableMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.tostring == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tostring, find.tostring); + Assert.Equal(true, find.tostring); + + item = new BoolNullableMap { tostring = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tostring == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tostring, find.tostring); + Assert.Equal(false, find.tostring); + + item = new BoolNullableMap { tostring = null }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tostring == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.tostring == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tostring, find.tostring); + Assert.Null(find.tostring); + + //update all + item.tostring = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tostring == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tostring, find.tostring); + Assert.Equal(true, find.tostring); + + item.tostring = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tostring == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tostring, find.tostring); + Assert.Equal(false, find.tostring); + + item.tostring = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tostring == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.tostring == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tostring, find.tostring); + Assert.Null(find.tostring); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tostring, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tostring == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(true, find.tostring); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tostring, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tostring == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(false, find.tostring); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tostring, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.tostring == false).First()); + find = orm.Select().Where(a => a.id == item.id && a.tostring == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Null(find.tostring); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tostring == true).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tostring == false).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.tostring == null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + + [Fact] + public void Guid() + { + } + [Fact] + public void GuidNullable() + { + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/MapType/BoolTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/MapType/BoolTest.cs new file mode 100644 index 00000000..98d9316e --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/MapType/BoolTest.cs @@ -0,0 +1,1105 @@ +using FreeSql.DataAnnotations; +using System; +using Xunit; + +namespace FreeSql.Tests.DamengMapType +{ + public class BoolTest + { + + class BoolMap + { + public Guid id { get; set; } + [Column(MapType = typeof(bool?))] + public bool toboolnullable { get; set; } = true; + + [Column(MapType = typeof(sbyte))] + public bool tosbyte { get; set; } = true; + [Column(MapType = typeof(sbyte?))] + public bool tosbytenullable { get; set; } = true; + + [Column(MapType = typeof(short))] + public bool toshort { get; set; } = true; + + [Column(MapType = typeof(short?))] + public bool toshortnullable { get; set; } = true; + + [Column(MapType = typeof(int))] + public bool toint { get; set; } = true; + + [Column(MapType = typeof(int?))] + public bool tointnullable { get; set; } = true; + + [Column(MapType = typeof(long))] + public bool tolong { get; set; } = true; + [Column(MapType = typeof(long?))] + public bool tolongnullable { get; set; } = true; + + [Column(MapType = typeof(byte))] + public bool tobyte { get; set; } = true; + [Column(MapType = typeof(byte?))] + public bool tobytenullable { get; set; } = true; + + [Column(MapType = typeof(ushort))] + public bool toushort { get; set; } = true; + + [Column(MapType = typeof(ushort?))] + public bool toushortnullable { get; set; } = true; + + [Column(MapType = typeof(uint))] + public bool touint { get; set; } = true; + + [Column(MapType = typeof(uint?))] + public bool touintnullable { get; set; } = true; + + [Column(MapType = typeof(ulong))] + public bool toulong { get; set; } = true; + [Column(MapType = typeof(ulong?))] + public bool toulongnullable { get; set; } = true; + + [Column(MapType = typeof(string))] + public bool tostring { get; set; } = true; + } + + [Fact] + public void BoolNullable() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.toboolnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toboolnullable, find.toboolnullable); + Assert.True(find.toboolnullable); + + item = new BoolMap { toboolnullable = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toboolnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toboolnullable, find.toboolnullable); + Assert.False(find.toboolnullable); + + //update all + item.toboolnullable = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toboolnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toboolnullable, find.toboolnullable); + Assert.True(find.toboolnullable); + + item.toboolnullable = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toboolnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toboolnullable, find.toboolnullable); + Assert.False(find.toboolnullable); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toboolnullable, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toboolnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.toboolnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toboolnullable, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toboolnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.toboolnullable); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toboolnullable == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.toboolnullable == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void SByte() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.tosbyte == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbyte, find.tosbyte); + Assert.True(find.tosbyte); + + item = new BoolMap { tosbyte = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbyte, find.tosbyte); + Assert.False(find.tosbyte); + + //update all + item.tosbyte = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbyte == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbyte, find.tosbyte); + Assert.True(find.tosbyte); + + item.tosbyte = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbyte, find.tosbyte); + Assert.False(find.tosbyte); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tosbyte, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbyte == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.tosbyte); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tosbyte, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.tosbyte); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tosbyte == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.tosbyte == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void SByteNullable() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.tosbytenullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbytenullable, find.tosbytenullable); + Assert.True(find.tosbytenullable); + + item = new BoolMap { tosbytenullable = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbytenullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbytenullable, find.tosbytenullable); + Assert.False(find.tosbytenullable); + + //update all + item.tosbytenullable = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbytenullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbytenullable, find.tosbytenullable); + Assert.True(find.tosbytenullable); + + item.tosbytenullable = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbytenullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tosbytenullable, find.tosbytenullable); + Assert.False(find.tosbytenullable); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tosbytenullable, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbytenullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.tosbytenullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tosbytenullable, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tosbytenullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.tosbytenullable); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tosbytenullable == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.tosbytenullable == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void Short() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.toshort == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshort, find.toshort); + Assert.True(find.toshort); + + item = new BoolMap { toshort = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshort, find.toshort); + Assert.False(find.toshort); + + //update all + item.toshort = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshort == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshort, find.toshort); + Assert.True(find.toshort); + + item.toshort = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshort, find.toshort); + Assert.False(find.toshort); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toshort, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshort == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.toshort); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toshort, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.toshort); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toshort == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.toshort == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void ShortNullable() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.toshortnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshortnullable, find.toshortnullable); + Assert.True(find.toshortnullable); + + item = new BoolMap { toshortnullable = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshortnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshortnullable, find.toshortnullable); + Assert.False(find.toshortnullable); + + //update all + item.toshortnullable = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshortnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshortnullable, find.toshortnullable); + Assert.True(find.toshortnullable); + + item.toshortnullable = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshortnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toshortnullable, find.toshortnullable); + Assert.False(find.toshortnullable); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toshortnullable, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshortnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.toshortnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toshortnullable, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toshortnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.toshortnullable); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toshortnullable == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.toshortnullable == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void Int() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.toint == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toint, find.toint); + Assert.True(find.toint); + + item = new BoolMap { toint = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toint, find.toint); + Assert.False(find.toint); + + //update all + item.toint = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toint == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toint, find.toint); + Assert.True(find.toint); + + item.toint = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toint, find.toint); + Assert.False(find.toint); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toint, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toint == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.toint); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toint, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.toint); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toint == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.toint == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void IntNullable() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.tointnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tointnullable, find.tointnullable); + Assert.True(find.tointnullable); + + item = new BoolMap { tointnullable = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tointnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tointnullable, find.tointnullable); + Assert.False(find.tointnullable); + + //update all + item.tointnullable = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tointnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tointnullable, find.tointnullable); + Assert.True(find.tointnullable); + + item.tointnullable = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tointnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tointnullable, find.tointnullable); + Assert.False(find.tointnullable); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tointnullable, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tointnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.tointnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tointnullable, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tointnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.tointnullable); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tointnullable == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.tointnullable == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void Long() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.tolong == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolong, find.tolong); + Assert.True(find.tolong); + + item = new BoolMap { tolong = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolong, find.tolong); + Assert.False(find.tolong); + + //update all + item.tolong = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolong == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolong, find.tolong); + Assert.True(find.tolong); + + item.tolong = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolong, find.tolong); + Assert.False(find.tolong); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tolong, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolong == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.tolong); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tolong, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.tolong); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tolong == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.tolong == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void LongNullable() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.tolongnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolongnullable, find.tolongnullable); + Assert.True(find.tolongnullable); + + item = new BoolMap { tolongnullable = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolongnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolongnullable, find.tolongnullable); + Assert.False(find.tolongnullable); + + //update all + item.tolongnullable = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolongnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolongnullable, find.tolongnullable); + Assert.True(find.tolongnullable); + + item.tolongnullable = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolongnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tolongnullable, find.tolongnullable); + Assert.False(find.tolongnullable); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tolongnullable, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolongnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.tolongnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tolongnullable, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tolongnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.tolongnullable); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tolongnullable == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.tolongnullable == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + + [Fact] + public void Byte() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.tobyte == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobyte, find.tobyte); + Assert.True(find.tobyte); + + item = new BoolMap { tobyte = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobyte, find.tobyte); + Assert.False(find.tobyte); + + //update all + item.tobyte = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobyte == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobyte, find.tobyte); + Assert.True(find.tobyte); + + item.tobyte = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobyte, find.tobyte); + Assert.False(find.tobyte); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tobyte, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobyte == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.tobyte); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tobyte, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobyte == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.tobyte); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tobyte == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.tobyte == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void ByteNullable() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.tobytenullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobytenullable, find.tobytenullable); + Assert.True(find.tobytenullable); + + item = new BoolMap { tobytenullable = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobytenullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobytenullable, find.tobytenullable); + Assert.False(find.tobytenullable); + + //update all + item.tobytenullable = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobytenullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobytenullable, find.tobytenullable); + Assert.True(find.tobytenullable); + + item.tobytenullable = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobytenullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tobytenullable, find.tobytenullable); + Assert.False(find.tobytenullable); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tobytenullable, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobytenullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.tobytenullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tobytenullable, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tobytenullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.tobytenullable); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tobytenullable == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.tobytenullable == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void UShort() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.toushort == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushort, find.toushort); + Assert.True(find.toushort); + + item = new BoolMap { toushort = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushort, find.toushort); + Assert.False(find.toushort); + + //update all + item.toushort = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushort == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushort, find.toushort); + Assert.True(find.toushort); + + item.toushort = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushort, find.toushort); + Assert.False(find.toushort); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toushort, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushort == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.toushort); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toushort, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushort == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.toushort); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toushort == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.toushort == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void UShortNullable() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.toushortnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushortnullable, find.toushortnullable); + Assert.True(find.toushortnullable); + + item = new BoolMap { toushortnullable = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushortnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushortnullable, find.toushortnullable); + Assert.False(find.toushortnullable); + + //update all + item.toushortnullable = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushortnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushortnullable, find.toushortnullable); + Assert.True(find.toushortnullable); + + item.toushortnullable = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushortnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toushortnullable, find.toushortnullable); + Assert.False(find.toushortnullable); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toushortnullable, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushortnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.toushortnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toushortnullable, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toushortnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.toushortnullable); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toushortnullable == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.toushortnullable == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void UInt() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.touint == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touint, find.touint); + Assert.True(find.touint); + + item = new BoolMap { touint = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touint, find.touint); + Assert.False(find.touint); + + //update all + item.touint = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touint == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touint, find.touint); + Assert.True(find.touint); + + item.touint = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touint, find.touint); + Assert.False(find.touint); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.touint, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touint == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.touint); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.touint, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touint == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.touint); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.touint == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.touint == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void UIntNullable() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.touintnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touintnullable, find.touintnullable); + Assert.True(find.touintnullable); + + item = new BoolMap { touintnullable = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touintnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touintnullable, find.touintnullable); + Assert.False(find.touintnullable); + + //update all + item.touintnullable = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touintnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touintnullable, find.touintnullable); + Assert.True(find.touintnullable); + + item.touintnullable = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touintnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.touintnullable, find.touintnullable); + Assert.False(find.touintnullable); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.touintnullable, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touintnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.touintnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.touintnullable, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.touintnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.touintnullable); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.touintnullable == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.touintnullable == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void ULong() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.toulong == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulong, find.toulong); + Assert.True(find.toulong); + + item = new BoolMap { toulong = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulong, find.toulong); + Assert.False(find.toulong); + + //update all + item.toulong = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulong == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulong, find.toulong); + Assert.True(find.toulong); + + item.toulong = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulong, find.toulong); + Assert.False(find.toulong); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toulong, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulong == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.toulong); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toulong, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulong == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.toulong); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toulong == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.toulong == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void ULongNullable() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.toulongnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulongnullable, find.toulongnullable); + Assert.True(find.toulongnullable); + + item = new BoolMap { toulongnullable = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulongnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulongnullable, find.toulongnullable); + Assert.False(find.toulongnullable); + + //update all + item.toulongnullable = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulongnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulongnullable, find.toulongnullable); + Assert.True(find.toulongnullable); + + item.toulongnullable = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulongnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.toulongnullable, find.toulongnullable); + Assert.False(find.toulongnullable); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toulongnullable, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulongnullable == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.toulongnullable); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.toulongnullable, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.toulongnullable == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.toulongnullable); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.toulongnullable == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.toulongnullable == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + + [Fact] + public void TimeSpan() + { + } + [Fact] + public void TimeSpanNullable() + { + } + [Fact] + public void DateTime() + { + } + [Fact] + public void DateTimeNullable() + { + } + + [Fact] + public void ByteArray() + { + } + [Fact] + public void String() + { + //insert + var orm = g.dameng; + var item = new BoolMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.tostring == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tostring, find.tostring); + Assert.True(find.tostring); + + item = new BoolMap { tostring = false }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tostring == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tostring, find.tostring); + Assert.False(find.tostring); + + //update all + item.tostring = true; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tostring == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tostring, find.tostring); + Assert.True(find.tostring); + + item.tostring = false; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tostring == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.tostring, find.tostring); + Assert.False(find.tostring); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tostring, true).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tostring == true).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.True(find.tostring); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.tostring, false).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.tostring == false).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.False(find.tostring); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.tostring == true).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.tostring == false).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + + [Fact] + public void Guid() + { + } + [Fact] + public void GuidNullable() + { + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/MapType/DateTimeOffSetTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/MapType/DateTimeOffSetTest.cs new file mode 100644 index 00000000..26a3e929 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/MapType/DateTimeOffSetTest.cs @@ -0,0 +1,54 @@ +using FreeSql.DataAnnotations; +using System; +using System.Numerics; +using Xunit; + +namespace FreeSql.Tests.DamengMapType +{ + public class DateTimeOffSetTest + { + class Dtos_dt + { + public Guid id { get; set; } + + [Column(MapType = typeof(DateTime))] + public DateTimeOffset dtos_to_dt { get; set; } + [Column(MapType = typeof(DateTime))] + public DateTimeOffset? dtofnil_to_dt { get; set; } + } + [Fact] + public void DateTimeToDateTimeOffSet() + { + //insert + var orm = g.dameng; + var item = new Dtos_dt { dtos_to_dt = DateTimeOffset.Now, dtofnil_to_dt = DateTimeOffset.Now }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.dtos_to_dt.ToString("g"), find.dtos_to_dt.ToString("g")); + Assert.Equal(item.dtofnil_to_dt.Value.ToString("g"), find.dtofnil_to_dt.Value.ToString("g")); + + //update all + item.dtos_to_dt = DateTimeOffset.Now; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.dtos_to_dt.ToString("g"), find.dtos_to_dt.ToString("g")); + Assert.Equal(item.dtofnil_to_dt.Value.ToString("g"), find.dtofnil_to_dt.Value.ToString("g")); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.dtos_to_dt, item.dtos_to_dt = DateTimeOffset.Now).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.dtos_to_dt.ToString("g"), find.dtos_to_dt.ToString("g")); + Assert.Equal(item.dtofnil_to_dt.Value.ToString("g"), find.dtofnil_to_dt.Value.ToString("g")); + + //delete + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/MapType/EnumTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/MapType/EnumTest.cs new file mode 100644 index 00000000..44e4c52b --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/MapType/EnumTest.cs @@ -0,0 +1,261 @@ +using FreeSql.DataAnnotations; +using System; +using System.Numerics; +using Xunit; + +namespace FreeSql.Tests.DamengMapType +{ + public class EnumTest + { + class EnumTestMap + { + public Guid id { get; set; } + + [Column(MapType = typeof(string))] + public ToStringMapEnum enum_to_string { get; set; } + [Column(MapType = typeof(string))] + public ToStringMapEnum? enumnullable_to_string { get; set; } + + [Column(MapType = typeof(int))] + public ToStringMapEnum enum_to_int { get; set; } + [Column(MapType = typeof(int?))] + public ToStringMapEnum? enumnullable_to_int { get; set; } + } + public enum ToStringMapEnum { й, abc, } + [Fact] + public void EnumToString() + { + //insert + var orm = g.dameng; + var item = new EnumTestMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.й).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enum_to_string, find.enum_to_string); + Assert.Equal(ToStringMapEnum.й, find.enum_to_string); + + item = new EnumTestMap { enum_to_string = ToStringMapEnum.abc }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.abc).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enum_to_string, find.enum_to_string); + Assert.Equal(ToStringMapEnum.abc, find.enum_to_string); + + //update all + item.enum_to_string = ToStringMapEnum.; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enum_to_string, find.enum_to_string); + Assert.Equal(ToStringMapEnum., find.enum_to_string); + + item.enum_to_string = ToStringMapEnum.й; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.й).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enum_to_string, find.enum_to_string); + Assert.Equal(ToStringMapEnum.й, find.enum_to_string); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enum_to_string, ToStringMapEnum.).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(ToStringMapEnum., find.enum_to_string); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enum_to_string, ToStringMapEnum.abc).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.abc).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(ToStringMapEnum.abc, find.enum_to_string); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.й).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.abc).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void EnumNullableToString() + { + //insert + var orm = g.dameng; + var item = new EnumTestMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string); + Assert.Null(find.enumnullable_to_string); + + item = new EnumTestMap { enumnullable_to_string = ToStringMapEnum.й }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.й).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string); + Assert.Equal(ToStringMapEnum.й, find.enumnullable_to_string); + + //update all + item.enumnullable_to_string = ToStringMapEnum.; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string); + Assert.Equal(ToStringMapEnum., find.enumnullable_to_string); + + item.enumnullable_to_string = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.).First()); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string); + Assert.Null(find.enumnullable_to_string); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enumnullable_to_string, ToStringMapEnum.abc).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.abc).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(ToStringMapEnum.abc, find.enumnullable_to_string); + + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enumnullable_to_string, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.abc).First()); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Null(find.enumnullable_to_string); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.й).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_string == null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + + [Fact] + public void EnumToInt() + { + //insert + var orm = g.dameng; + var item = new EnumTestMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.й).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enum_to_int, find.enum_to_int); + Assert.Equal(ToStringMapEnum.й, find.enum_to_int); + + item = new EnumTestMap { enum_to_int = ToStringMapEnum.abc }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.abc).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enum_to_int, find.enum_to_int); + Assert.Equal(ToStringMapEnum.abc, find.enum_to_int); + + //update all + item.enum_to_int = ToStringMapEnum.; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enum_to_int, find.enum_to_int); + Assert.Equal(ToStringMapEnum., find.enum_to_int); + + item.enum_to_int = ToStringMapEnum.й; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.й).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enum_to_int, find.enum_to_int); + Assert.Equal(ToStringMapEnum.й, find.enum_to_int); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enum_to_int, ToStringMapEnum.).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(ToStringMapEnum., find.enum_to_int); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enum_to_int, ToStringMapEnum.abc).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.abc).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(ToStringMapEnum.abc, find.enum_to_int); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.й).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.enum_to_int == ToStringMapEnum.abc).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void EnumNullableToInt() + { + //insert + var orm = g.dameng; + var item = new EnumTestMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_int == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enumnullable_to_int, find.enumnullable_to_int); + Assert.Null(find.enumnullable_to_int); + + item = new EnumTestMap { enumnullable_to_int = ToStringMapEnum.й }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.й).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enumnullable_to_int, find.enumnullable_to_int); + Assert.Equal(ToStringMapEnum.й, find.enumnullable_to_int); + + //update all + item.enumnullable_to_int = ToStringMapEnum.; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enumnullable_to_int, find.enumnullable_to_int); + Assert.Equal(ToStringMapEnum., find.enumnullable_to_int); + + item.enumnullable_to_int = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.).First()); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_int == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enumnullable_to_int, find.enumnullable_to_int); + Assert.Null(find.enumnullable_to_int); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enumnullable_to_int, ToStringMapEnum.abc).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.abc).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(ToStringMapEnum.abc, find.enumnullable_to_int); + + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enumnullable_to_int, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.abc).First()); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_int == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Null(find.enumnullable_to_int); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.й).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_int == ToStringMapEnum.).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_int == null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/MapType/ToStringTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/MapType/ToStringTest.cs new file mode 100644 index 00000000..fbe05387 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/MapType/ToStringTest.cs @@ -0,0 +1,570 @@ +using FreeSql.DataAnnotations; +using System; +using System.Numerics; +using Xunit; + +namespace FreeSql.Tests.DamengMapType +{ + public class ToStringTest + { + class ToStringMap + { + public Guid id { get; set; } + + [Column(MapType = typeof(string))] + public TimeSpan timespan_to_string { get; set; } + [Column(MapType = typeof(string))] + public TimeSpan? timespannullable_to_string { get; set; } + + [Column(MapType = typeof(string))] + public DateTime datetime_to_string { get; set; } + [Column(MapType = typeof(string))] + public DateTime? datetimenullable_to_string { get; set; } + + [Column(MapType = typeof(string))] + public Guid guid_to_string { get; set; } + [Column(MapType = typeof(string))] + public Guid? guidnullable_to_string { get; set; } + + [Column(MapType = typeof(string))] + public ToStringMapEnum enum_to_string { get; set; } + [Column(MapType = typeof(string))] + public ToStringMapEnum? enumnullable_to_string { get; set; } + + [Column(MapType = typeof(string))] + public BigInteger biginteger_to_string { get; set; } + [Column(MapType = typeof(string))] + public BigInteger? bigintegernullable_to_string { get; set; } + } + public enum ToStringMapEnum { й, abc, } + [Fact] + public void Enum1() + { + //insert + var orm = g.dameng; + var item = new ToStringMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.й).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enum_to_string, find.enum_to_string); + Assert.Equal(ToStringMapEnum.й, find.enum_to_string); + + item = new ToStringMap { enum_to_string = ToStringMapEnum.abc }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.abc).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enum_to_string, find.enum_to_string); + Assert.Equal(ToStringMapEnum.abc, find.enum_to_string); + + //update all + item.enum_to_string = ToStringMapEnum.; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enum_to_string, find.enum_to_string); + Assert.Equal(ToStringMapEnum., find.enum_to_string); + + item.enum_to_string = ToStringMapEnum.й; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.й).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enum_to_string, find.enum_to_string); + Assert.Equal(ToStringMapEnum.й, find.enum_to_string); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enum_to_string, ToStringMapEnum.).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(ToStringMapEnum., find.enum_to_string); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enum_to_string, ToStringMapEnum.abc).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.abc).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(ToStringMapEnum.abc, find.enum_to_string); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.й).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.enum_to_string == ToStringMapEnum.abc).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void EnumNullable() + { + //insert + var orm = g.dameng; + var item = new ToStringMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string); + Assert.Null(find.enumnullable_to_string); + + item = new ToStringMap { enumnullable_to_string = ToStringMapEnum.й }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.й).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string); + Assert.Equal(ToStringMapEnum.й, find.enumnullable_to_string); + + //update all + item.enumnullable_to_string = ToStringMapEnum.; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string); + Assert.Equal(ToStringMapEnum., find.enumnullable_to_string); + + item.enumnullable_to_string = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.).First()); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.enumnullable_to_string, find.enumnullable_to_string); + Assert.Null(find.enumnullable_to_string); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enumnullable_to_string, ToStringMapEnum.abc).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.abc).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(ToStringMapEnum.abc, find.enumnullable_to_string); + + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.enumnullable_to_string, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.abc).First()); + find = orm.Select().Where(a => a.id == item.id && a.enumnullable_to_string == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Null(find.enumnullable_to_string); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.й).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_string == ToStringMapEnum.).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.enumnullable_to_string == null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void BigInteger1() + { + //insert + var orm = g.dameng; + var item = new ToStringMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.biginteger_to_string == 0).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.biginteger_to_string, find.biginteger_to_string); + Assert.Equal(0, find.biginteger_to_string); + + item = new ToStringMap { biginteger_to_string = 100 }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.biginteger_to_string == 100).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.biginteger_to_string, find.biginteger_to_string); + Assert.Equal(100, find.biginteger_to_string); + + //update all + item.biginteger_to_string = 200; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.biginteger_to_string == 200).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.biginteger_to_string, find.biginteger_to_string); + Assert.Equal(200, find.biginteger_to_string); + + item.biginteger_to_string = 205; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.biginteger_to_string == 205).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.biginteger_to_string, find.biginteger_to_string); + Assert.Equal(205, find.biginteger_to_string); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.biginteger_to_string, 522).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.biginteger_to_string == 522).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(522, find.biginteger_to_string); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.biginteger_to_string, 10005).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.biginteger_to_string == 10005).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(10005, find.biginteger_to_string); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.biginteger_to_string == 522).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.biginteger_to_string == 205).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.biginteger_to_string == 10005).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void BigIntegerNullable() + { + //insert + var orm = g.dameng; + var item = new ToStringMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.bigintegernullable_to_string == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.bigintegernullable_to_string, find.bigintegernullable_to_string); + Assert.Null(find.bigintegernullable_to_string); + + item = new ToStringMap { bigintegernullable_to_string = 101 }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.bigintegernullable_to_string == 101).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.bigintegernullable_to_string, find.bigintegernullable_to_string); + Assert.Equal(101, find.bigintegernullable_to_string); + + //update all + item.bigintegernullable_to_string = 2004; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.bigintegernullable_to_string == 2004).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.bigintegernullable_to_string, find.bigintegernullable_to_string); + Assert.Equal(2004, find.bigintegernullable_to_string); + + item.bigintegernullable_to_string = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.bigintegernullable_to_string == 2004).First()); + find = orm.Select().Where(a => a.id == item.id && a.bigintegernullable_to_string == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.bigintegernullable_to_string, find.bigintegernullable_to_string); + Assert.Null(find.bigintegernullable_to_string); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.bigintegernullable_to_string, 998).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.bigintegernullable_to_string == 998).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(998, find.bigintegernullable_to_string); + + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.bigintegernullable_to_string, null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id && a.bigintegernullable_to_string == 998).First()); + find = orm.Select().Where(a => a.id == item.id && a.bigintegernullable_to_string == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Null(find.bigintegernullable_to_string); + + //delete + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.bigintegernullable_to_string == 998).ExecuteAffrows()); + Assert.Equal(0, orm.Delete().Where(a => a.id == item.id && a.bigintegernullable_to_string == 2004).ExecuteAffrows()); + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.bigintegernullable_to_string == null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void TimeSpan1() + { + //insert + var orm = g.dameng; + var item = new ToStringMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.timespan_to_string, find.timespan_to_string); + Assert.Equal(TimeSpan.Zero, find.timespan_to_string); + + item = new ToStringMap { timespan_to_string = TimeSpan.FromDays(1) }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.timespan_to_string, find.timespan_to_string); + Assert.Equal(TimeSpan.FromDays(1), find.timespan_to_string); + + //update all + item.timespan_to_string = TimeSpan.FromHours(10); + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.timespan_to_string, find.timespan_to_string); + Assert.Equal(TimeSpan.FromHours(10), find.timespan_to_string); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.timespan_to_string, TimeSpan.FromHours(11)).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(TimeSpan.FromHours(11), find.timespan_to_string); + + //delete + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void TimeSpanNullable() + { + //insert + var orm = g.dameng; + var item = new ToStringMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.timespannullable_to_string, find.timespannullable_to_string); + Assert.Null(find.timespannullable_to_string); + + item = new ToStringMap { timespannullable_to_string = TimeSpan.FromDays(1) }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.timespannullable_to_string, find.timespannullable_to_string); + Assert.Equal(TimeSpan.FromDays(1), find.timespannullable_to_string); + + //update all + item.timespannullable_to_string = TimeSpan.FromHours(10); + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.timespannullable_to_string, find.timespannullable_to_string); + Assert.Equal(TimeSpan.FromHours(10), find.timespannullable_to_string); + + item.timespannullable_to_string = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.timespannullable_to_string, find.timespannullable_to_string); + Assert.Null(find.timespannullable_to_string); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.timespannullable_to_string, TimeSpan.FromHours(11)).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(TimeSpan.FromHours(11), find.timespannullable_to_string); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.timespannullable_to_string, null).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Null(find.timespannullable_to_string); + + //delete + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void DateTime1() + { + //insert + var orm = g.dameng; + var item = new ToStringMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.datetime_to_string, find.datetime_to_string); + Assert.Equal(DateTime.MinValue, find.datetime_to_string); + + item = new ToStringMap { datetime_to_string = DateTime.Parse("2000-1-1") }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.datetime_to_string, find.datetime_to_string); + Assert.Equal(DateTime.Parse("2000-1-1"), find.datetime_to_string); + + //update all + item.datetime_to_string = DateTime.Parse("2000-1-11"); + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.datetime_to_string, find.datetime_to_string); + Assert.Equal(DateTime.Parse("2000-1-11"), find.datetime_to_string); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.datetime_to_string, DateTime.Parse("2000-1-12")).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(DateTime.Parse("2000-1-12"), find.datetime_to_string); + + //delete + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void DateTimeNullable() + { + //insert + var orm = g.dameng; + var item = new ToStringMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.datetimenullable_to_string, find.datetimenullable_to_string); + Assert.Null(find.datetimenullable_to_string); + + item = new ToStringMap { datetimenullable_to_string = DateTime.Parse("2000-1-1") }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.datetimenullable_to_string, find.datetimenullable_to_string); + Assert.Equal(DateTime.Parse("2000-1-1"), find.datetimenullable_to_string); + + //update all + item.datetimenullable_to_string = DateTime.Parse("2000-1-11"); + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.datetimenullable_to_string, find.datetimenullable_to_string); + Assert.Equal(DateTime.Parse("2000-1-11"), find.datetimenullable_to_string); + + item.datetimenullable_to_string = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.datetimenullable_to_string, find.datetimenullable_to_string); + Assert.Null(find.datetimenullable_to_string); + + //update set + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.datetimenullable_to_string, DateTime.Parse("2000-1-12")).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(DateTime.Parse("2000-1-12"), find.datetimenullable_to_string); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.datetimenullable_to_string, null).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Null(find.datetimenullable_to_string); + + //delete + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + + [Fact] + public void Guid1() + { + //insert + var orm = g.dameng; + var item = new ToStringMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.guid_to_string == Guid.Empty).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.guid_to_string, find.guid_to_string); + Assert.Equal(Guid.Empty, find.guid_to_string); + + var newid = Guid.NewGuid(); + item = new ToStringMap { guid_to_string = newid }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.guid_to_string == newid).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.guid_to_string, find.guid_to_string); + Assert.Equal(newid, find.guid_to_string); + + //update all + newid = Guid.NewGuid(); + item.guid_to_string = newid; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.guid_to_string == newid).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.guid_to_string, find.guid_to_string); + Assert.Equal(newid, find.guid_to_string); + + //update set + newid = Guid.NewGuid(); + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.guid_to_string, newid).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.guid_to_string == newid).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(newid, find.guid_to_string); + + //delete + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.guid_to_string == newid).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + [Fact] + public void GuidNullable() + { + //insert + var orm = g.dameng; + var item = new ToStringMap { }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + var find = orm.Select().Where(a => a.id == item.id && a.guidnullable_to_string == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.guidnullable_to_string, find.guidnullable_to_string); + Assert.Null(find.guidnullable_to_string); + + var newid = Guid.NewGuid(); + item = new ToStringMap { guidnullable_to_string = newid }; + Assert.Equal(1, orm.Insert().AppendData(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.guidnullable_to_string == newid).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.guidnullable_to_string, find.guidnullable_to_string); + Assert.Equal(newid, find.guidnullable_to_string); + + //update all + newid = Guid.NewGuid(); + item.guidnullable_to_string = newid; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.guidnullable_to_string == newid).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.guidnullable_to_string, find.guidnullable_to_string); + Assert.Equal(newid, find.guidnullable_to_string); + + item.guidnullable_to_string = null; + Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.guidnullable_to_string == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(item.guidnullable_to_string, find.guidnullable_to_string); + Assert.Null(find.guidnullable_to_string); + + //update set + newid = Guid.NewGuid(); + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.guidnullable_to_string, newid).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.guidnullable_to_string == newid).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Equal(newid, find.guidnullable_to_string); + + Assert.Equal(1, orm.Update().Where(a => a.id == item.id).Set(a => a.guidnullable_to_string, null).ExecuteAffrows()); + find = orm.Select().Where(a => a.id == item.id && a.guidnullable_to_string == null).First(); + Assert.NotNull(find); + Assert.Equal(item.id, find.id); + Assert.Null(find.guidnullable_to_string); + + //delete + Assert.Equal(1, orm.Delete().Where(a => a.id == item.id && a.guidnullable_to_string == null).ExecuteAffrows()); + Assert.Null(orm.Select().Where(a => a.id == item.id).First()); + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/FreeSql.Tests.csproj b/FreeSql.Tests/FreeSql.Tests/FreeSql.Tests.csproj index bad5f21c..1748585d 100644 --- a/FreeSql.Tests/FreeSql.Tests/FreeSql.Tests.csproj +++ b/FreeSql.Tests/FreeSql.Tests/FreeSql.Tests.csproj @@ -34,6 +34,7 @@ + @@ -42,4 +43,10 @@ + + + ..\..\Providers\FreeSql.Provider.Dameng\lib\DmProvider\netstandard2.0\DmProvider.dll + + + diff --git a/FreeSql.Tests/FreeSql.Tests/g.cs b/FreeSql.Tests/FreeSql.Tests/g.cs index e64f0553..61c209e1 100644 --- a/FreeSql.Tests/FreeSql.Tests/g.cs +++ b/FreeSql.Tests/FreeSql.Tests/g.cs @@ -105,4 +105,19 @@ public class g ) .Build()); public static IFreeSql msaccess => msaccessLazy.Value; + + + static Lazy damengLazy = new Lazy(() => new FreeSql.FreeSqlBuilder() + .UseConnectionString(FreeSql.DataType.Dameng, "server=127.0.0.1;port=5236;user id=2user;password=123456789;database=2user;poolsize=5") + //.UseConnectionFactory(FreeSql.DataType.Dameng, () => new Dm.DmConnection("data source=127.0.0.1:5236;user id=2user;password=123456789;Pooling=true;Max Pool Size=2")) + .UseAutoSyncStructure(true) + .UseLazyLoading(true) + .UseNameConvert(FreeSql.Internal.NameConvertType.ToUpper) + //.UseNoneCommandParameter(true) + + .UseMonitorCommand( + cmd => Trace.WriteLine(cmd.CommandText), //监听SQL命令对象,在执行前 + (cmd, traceLog) => Console.WriteLine(traceLog)) + .Build()); + public static IFreeSql dameng => damengLazy.Value; } diff --git a/FreeSql.sln b/FreeSql.sln index d7236979..3ffc7d3d 100644 --- a/FreeSql.sln +++ b/FreeSql.sln @@ -78,6 +78,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.All", "FreeSql.All\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Extensions.Linq", "Extensions\FreeSql.Extensions.Linq\FreeSql.Extensions.Linq.csproj", "{57B3F5B0-D46A-4442-8EC6-9A9A784404B7}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Provider.Dameng", "Providers\FreeSql.Provider.Dameng\FreeSql.Provider.Dameng.csproj", "{E74D90E8-1CBC-4677-817B-1CA05AB97937}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -472,6 +474,18 @@ Global {57B3F5B0-D46A-4442-8EC6-9A9A784404B7}.Release|x64.Build.0 = Release|Any CPU {57B3F5B0-D46A-4442-8EC6-9A9A784404B7}.Release|x86.ActiveCfg = Release|Any CPU {57B3F5B0-D46A-4442-8EC6-9A9A784404B7}.Release|x86.Build.0 = Release|Any CPU + {E74D90E8-1CBC-4677-817B-1CA05AB97937}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E74D90E8-1CBC-4677-817B-1CA05AB97937}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E74D90E8-1CBC-4677-817B-1CA05AB97937}.Debug|x64.ActiveCfg = Debug|Any CPU + {E74D90E8-1CBC-4677-817B-1CA05AB97937}.Debug|x64.Build.0 = Debug|Any CPU + {E74D90E8-1CBC-4677-817B-1CA05AB97937}.Debug|x86.ActiveCfg = Debug|Any CPU + {E74D90E8-1CBC-4677-817B-1CA05AB97937}.Debug|x86.Build.0 = Debug|Any CPU + {E74D90E8-1CBC-4677-817B-1CA05AB97937}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E74D90E8-1CBC-4677-817B-1CA05AB97937}.Release|Any CPU.Build.0 = Release|Any CPU + {E74D90E8-1CBC-4677-817B-1CA05AB97937}.Release|x64.ActiveCfg = Release|Any CPU + {E74D90E8-1CBC-4677-817B-1CA05AB97937}.Release|x64.Build.0 = Release|Any CPU + {E74D90E8-1CBC-4677-817B-1CA05AB97937}.Release|x86.ActiveCfg = Release|Any CPU + {E74D90E8-1CBC-4677-817B-1CA05AB97937}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -499,6 +513,7 @@ Global {B397A761-F646-41CF-A160-AB6C05DAF2FB} = {2A381C57-2697-427B-9F10-55DA11FD02E4} {773D5B63-DE6E-46DB-AF16-6FB1C1352B3F} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA} {57B3F5B0-D46A-4442-8EC6-9A9A784404B7} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA} + {E74D90E8-1CBC-4677-817B-1CA05AB97937} = {2A381C57-2697-427B-9F10-55DA11FD02E4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {089687FD-5D25-40AB-BA8A-A10D1E137F98} diff --git a/FreeSql/DataType.cs b/FreeSql/DataType.cs index 236f6325..4b60ed38 100644 --- a/FreeSql/DataType.cs +++ b/FreeSql/DataType.cs @@ -22,7 +22,7 @@ namespace FreeSql Odbc, /// - /// 武汉达梦数据库有限公司 + /// 武汉达梦数据库有限公司,基于 Odbc 的实现 /// OdbcDameng, @@ -30,5 +30,10 @@ namespace FreeSql /// Microsoft Office Access 是由微软发布的关联式数据库管理系统 /// MsAccess, + + /// + /// 武汉达梦数据库有限公司,基于 DmProvider.dll 的实现 + /// + Dameng } } diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 60f4a9ad..468cec8e 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -533,7 +533,7 @@ - 武汉达梦数据库有限公司 + 武汉达梦数据库有限公司,基于 Odbc 的实现 @@ -541,6 +541,11 @@ Microsoft Office Access 是由微软发布的关联式数据库管理系统 + + + 武汉达梦数据库有限公司,基于 DmProvider.dll 的实现 + + 获取实体的主键值,以 "*|_,[,_|*" 分割,当任意一个主键属性无值时,返回 null diff --git a/FreeSql/FreeSqlBuilder.cs b/FreeSql/FreeSqlBuilder.cs index b72283eb..51a13af8 100644 --- a/FreeSql/FreeSqlBuilder.cs +++ b/FreeSql/FreeSqlBuilder.cs @@ -216,6 +216,11 @@ namespace FreeSql if (type == null) throwNotFind("FreeSql.Provider.MsAccess.dll", "FreeSql.MsAccess.MsAccessProvider<>"); break; + case DataType.Dameng: + type = Type.GetType("FreeSql.Dameng.DamengProvider`1,FreeSql.Provider.Dameng")?.MakeGenericType(typeof(TMark)); + if (type == null) throwNotFind("FreeSql.Provider.Dameng.dll", "FreeSql.Dameng.DamengProvider<>"); + break; + default: throw new Exception("未指定 UseConnectionString 或者 UseConnectionFactory"); } } diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs index d25664fd..95ad2cc5 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs @@ -803,7 +803,7 @@ namespace FreeSql.Internal.CommonProvider var propGetSetMethod = prop.GetSetMethod(true); Expression readExpAssign = null; //加速缓存 if (prop.PropertyType.IsArray) readExpAssign = Expression.New(Utils.RowInfo.Constructor, - Utils.GetDataReaderValueBlockExpression(prop.PropertyType, Expression.Call(rowExp, Utils.MethodDataReaderGetValue, dataIndexExp)), + Utils.GetDataReaderValueBlockExpression(prop.PropertyType, Expression.Call(Utils.MethodDataReaderGetValue, new Expression[] { Expression.Constant(_commonUtils), rowExp, dataIndexExp })), //Expression.Call(Utils.MethodGetDataReaderValue, new Expression[] { Expression.Constant(prop.PropertyType), Expression.Call(rowExp, Utils.MethodDataReaderGetValue, dataIndexExp) }), Expression.Add(dataIndexExp, Expression.Constant(1)) ); @@ -813,7 +813,7 @@ namespace FreeSql.Internal.CommonProvider if (proptypeGeneric.IsNullableType()) proptypeGeneric = proptypeGeneric.GetGenericArguments().First(); if (proptypeGeneric.IsEnum || Utils.dicExecuteArrayRowReadClassOrTuple.ContainsKey(proptypeGeneric)) readExpAssign = Expression.New(Utils.RowInfo.Constructor, - Utils.GetDataReaderValueBlockExpression(prop.PropertyType, Expression.Call(rowExp, Utils.MethodDataReaderGetValue, dataIndexExp)), + Utils.GetDataReaderValueBlockExpression(prop.PropertyType, Expression.Call(Utils.MethodDataReaderGetValue, new Expression[] { Expression.Constant(_commonUtils), rowExp, dataIndexExp })), //Expression.Call(Utils.MethodGetDataReaderValue, new Expression[] { Expression.Constant(prop.PropertyType), Expression.Call(rowExp, Utils.MethodDataReaderGetValue, dataIndexExp) }), Expression.Add(dataIndexExp, Expression.Constant(1)) ); @@ -1069,6 +1069,7 @@ namespace FreeSql.Internal.CommonProvider case DataType.Sqlite: break; case DataType.OdbcDameng: + case DataType.Dameng: _tosqlAppendContent = $" for update{(noawait ? " nowait" : "")}"; break; } diff --git a/FreeSql/Internal/UtilsExpressionTree.cs b/FreeSql/Internal/UtilsExpressionTree.cs index 17e30fdd..98f4a128 100644 --- a/FreeSql/Internal/UtilsExpressionTree.cs +++ b/FreeSql/Internal/UtilsExpressionTree.cs @@ -1235,7 +1235,12 @@ namespace FreeSql.Internal public static PropertyInfo PropertyValue = typeof(RowInfo).GetProperty("Value"); public static PropertyInfo PropertyDataIndex = typeof(RowInfo).GetProperty("DataIndex"); } - internal static MethodInfo MethodDataReaderGetValue = typeof(DbDataReader).GetMethod("GetValue"); + internal static MethodInfo MethodDataReaderGetValue = typeof(Utils).GetMethod("InternalDataReaderGetValue", BindingFlags.Static | BindingFlags.NonPublic); + internal static object InternalDataReaderGetValue(CommonUtils commonUtil, DbDataReader dr, int index) + { + if (commonUtil._orm.Ado.DataType == DataType.Dameng && dr.IsDBNull(index)) return null; + return dr.GetValue(index); + } internal static RowInfo ExecuteArrayRowReadClassOrTuple(string flagStr, Type typeOrg, int[] indexes, DbDataReader row, int dataIndex, CommonUtils _commonUtils) { if (string.IsNullOrEmpty(flagStr)) flagStr = "all"; @@ -1252,8 +1257,8 @@ namespace FreeSql.Internal if (type.IsArray) return Expression.Lambda>( Expression.New(RowInfo.Constructor, - GetDataReaderValueBlockExpression(type, Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp)), - //Expression.Call(MethodGetDataReaderValue, new Expression[] { typeExp, Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp) }), + GetDataReaderValueBlockExpression(type, Expression.Call(MethodDataReaderGetValue, new Expression[] { commonUtilExp, rowExp, dataIndexExp })), + //Expression.Call(MethodGetDataReaderValue, new Expression[] { typeExp, Expression.Call(MethodDataReaderGetValue, new Expression[] { commonUtilExp, rowExp, dataIndexExp }) }), Expression.Add(dataIndexExp, Expression.Constant(1)) ), new[] { typeExp, indexesExp, rowExp, dataIndexExp, commonUtilExp }).Compile(); @@ -1263,8 +1268,8 @@ namespace FreeSql.Internal dicExecuteArrayRowReadClassOrTuple.ContainsKey(typeGeneric)) return Expression.Lambda>( Expression.New(RowInfo.Constructor, - GetDataReaderValueBlockExpression(type, Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp)), - //Expression.Call(MethodGetDataReaderValue, new Expression[] { typeExp, Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp) }), + GetDataReaderValueBlockExpression(type, Expression.Call(MethodDataReaderGetValue, new Expression[] { commonUtilExp, rowExp, dataIndexExp })), + //Expression.Call(MethodGetDataReaderValue, new Expression[] { typeExp, Expression.Call(MethodDataReaderGetValue, new Expression[] { commonUtilExp, rowExp, dataIndexExp }) }), Expression.Add(dataIndexExp, Expression.Constant(1)) ), new[] { typeExp, indexesExp, rowExp, dataIndexExp, commonUtilExp }).Compile(); @@ -1284,8 +1289,8 @@ namespace FreeSql.Internal { Expression read2ExpAssign = null; //加速缓存 if (field.FieldType.IsArray) read2ExpAssign = Expression.New(RowInfo.Constructor, - GetDataReaderValueBlockExpression(field.FieldType, Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp)), - //Expression.Call(MethodGetDataReaderValue, new Expression[] { Expression.Constant(field.FieldType), Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp) }), + GetDataReaderValueBlockExpression(field.FieldType, Expression.Call(MethodDataReaderGetValue, new Expression[] { commonUtilExp, rowExp, dataIndexExp })), + //Expression.Call(MethodGetDataReaderValue, new Expression[] { Expression.Constant(field.FieldType), Expression.Call(MethodDataReaderGetValue, new Expression[] { commonUtilExp, rowExp, dataIndexExp }) }), Expression.Add(dataIndexExp, Expression.Constant(1)) ); else @@ -1294,8 +1299,8 @@ namespace FreeSql.Internal if (fieldtypeGeneric.IsNullableType()) fieldtypeGeneric = fieldtypeGeneric.GetGenericArguments().First(); if (fieldtypeGeneric.IsEnum || dicExecuteArrayRowReadClassOrTuple.ContainsKey(fieldtypeGeneric)) read2ExpAssign = Expression.New(RowInfo.Constructor, - GetDataReaderValueBlockExpression(field.FieldType, Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp)), - //Expression.Call(MethodGetDataReaderValue, new Expression[] { Expression.Constant(field.FieldType), Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp) }), + GetDataReaderValueBlockExpression(field.FieldType, Expression.Call(MethodDataReaderGetValue, new Expression[] { commonUtilExp, rowExp, dataIndexExp })), + //Expression.Call(MethodGetDataReaderValue, new Expression[] { Expression.Constant(field.FieldType), Expression.Call(MethodDataReaderGetValue, new Expression[] { commonUtilExp, rowExp, dataIndexExp }) }), Expression.Add(dataIndexExp, Expression.Constant(1)) ); else @@ -1336,8 +1341,8 @@ namespace FreeSql.Internal Expression.IfThen( Expression.LessThan(dataIndexExp, rowLenExp), Expression.Return(returnTarget, Expression.New(RowInfo.Constructor, - GetDataReaderValueBlockExpression(type, Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp)), - //Expression.Call(MethodGetDataReaderValue, new Expression[] { typeExp, Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp) }), + GetDataReaderValueBlockExpression(type, Expression.Call(MethodDataReaderGetValue, new Expression[] { commonUtilExp, rowExp, dataIndexExp })), + //Expression.Call(MethodGetDataReaderValue, new Expression[] { typeExp, Expression.Call(MethodDataReaderGetValue, new Expression[] { commonUtilExp, rowExp, dataIndexExp }) }), Expression.Add(dataIndexExp, Expression.Constant(1)))) ), Expression.Label(returnTarget, Expression.Default(typeof(RowInfo))) @@ -1391,7 +1396,7 @@ namespace FreeSql.Internal var readType = typetb.ColumnsByCs.TryGetValue(ctorParm.Name, out var trycol) ? trycol.Attribute.MapType : ctorParm.ParameterType; var ispkExp = new List(); - Expression readVal = Expression.Assign(readpkvalExp, Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp)); + Expression readVal = Expression.Assign(readpkvalExp, Expression.Call(MethodDataReaderGetValue, new Expression[] { commonUtilExp, rowExp, dataIndexExp })); Expression readExpAssign = null; //加速缓存 if (readType.IsArray) readExpAssign = Expression.New(RowInfo.Constructor, GetDataReaderValueBlockExpression(readType, readpkvalExp), @@ -1407,7 +1412,7 @@ namespace FreeSql.Internal { //判断主键为空,则整个对象不读取 - //blockExp.Add(Expression.Assign(readpkvalExp, Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp))); + //blockExp.Add(Expression.Assign(readpkvalExp, Expression.Call(MethodDataReaderGetValue, new Expression[] { commonUtilExp, rowExp, dataIndexExp }))); if (trycol?.Attribute.IsPrimary == true) { ispkExp.Add( @@ -1498,7 +1503,7 @@ namespace FreeSql.Internal var ispkExp = new List(); var propGetSetMethod = prop.GetSetMethod(true); - Expression readVal = Expression.Assign(readpkvalExp, Expression.Call(rowExp, MethodDataReaderGetValue, tryidxExp)); + Expression readVal = Expression.Assign(readpkvalExp, Expression.Call(MethodDataReaderGetValue, new Expression[] { commonUtilExp, rowExp, tryidxExp })); Expression readExpAssign = null; //加速缓存 if (readType.IsArray) readExpAssign = Expression.New(RowInfo.Constructor, GetDataReaderValueBlockExpression(readType, readpkvalExp), @@ -1514,7 +1519,7 @@ namespace FreeSql.Internal { //判断主键为空,则整个对象不读取 - //blockExp.Add(Expression.Assign(readpkvalExp, Expression.Call(rowExp, MethodDataReaderGetValue, dataIndexExp))); + //blockExp.Add(Expression.Assign(readpkvalExp, Expression.Call(MethodDataReaderGetValue, new Expression[] { commonUtilExp, rowExp, dataIndexExp }))); if (flagStr.StartsWith("adoQuery") == false && //Ado.Query 的时候不作此判断 trycol?.Attribute.IsPrimary == true) //若主键值为 null,则整行读取出来的对象为 null { diff --git a/Providers/FreeSql.Provider.Dameng/Curd/DamengDelete.cs b/Providers/FreeSql.Provider.Dameng/Curd/DamengDelete.cs new file mode 100644 index 00000000..99141060 --- /dev/null +++ b/Providers/FreeSql.Provider.Dameng/Curd/DamengDelete.cs @@ -0,0 +1,31 @@ +using FreeSql.Internal; +using System; +using System.Collections.Generic; +using System.Data; +using System.Text; +using System.Threading.Tasks; + +namespace FreeSql.Dameng.Curd +{ + + class DamengDelete : Internal.CommonProvider.DeleteProvider where T1 : class + { + public DamengDelete(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) + : base(orm, commonUtils, commonExpression, dywhere) + { + } + + public override List ExecuteDeleted() + { + throw new NotImplementedException(); + } + +#if net40 +#else + public override Task> ExecuteDeletedAsync() + { + throw new NotImplementedException(); + } +#endif + } +} diff --git a/Providers/FreeSql.Provider.Dameng/Curd/DamengInsert.cs b/Providers/FreeSql.Provider.Dameng/Curd/DamengInsert.cs new file mode 100644 index 00000000..74b1bd6b --- /dev/null +++ b/Providers/FreeSql.Provider.Dameng/Curd/DamengInsert.cs @@ -0,0 +1,222 @@ +using FreeSql.Internal; +using FreeSql.Internal.Model; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FreeSql.Dameng.Curd +{ + + class DamengInsert : Internal.CommonProvider.InsertProvider where T1 : class + { + public DamengInsert(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) + : base(orm, commonUtils, commonExpression) + { + } + + public override int ExecuteAffrows() => base.SplitExecuteAffrows(_batchValuesLimit > 0 ? _batchValuesLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 999); + public override long ExecuteIdentity() => base.SplitExecuteIdentity(_batchValuesLimit > 0 ? _batchValuesLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 999); + public override List ExecuteInserted() => base.SplitExecuteInserted(_batchValuesLimit > 0 ? _batchValuesLimit : 500, _batchParameterLimit > 0 ? _batchParameterLimit : 999); + + public override string ToSql() + { + if (_source == null || _source.Any() == false) return null; + var sb = new StringBuilder(); + sb.Append("INSERT "); + if (_source.Count > 1) sb.Append("ALL"); + + _identCol = null; + var sbtb = new StringBuilder(); + sbtb.Append("INTO "); + sbtb.Append(_commonUtils.QuoteSqlName(TableRuleInvoke())).Append("("); + var colidx = 0; + foreach (var col in _table.Columns.Values) + { + if (col.Attribute.IsIdentity) _identCol = col; + if (col.Attribute.IsIdentity && _insertIdentity == false && string.IsNullOrEmpty(col.DbInsertValue)) continue; + if (col.Attribute.IsIdentity == false && _ignore.ContainsKey(col.Attribute.Name)) continue; + + if (colidx > 0) sbtb.Append(", "); + sbtb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name)); + ++colidx; + } + sbtb.Append(") "); + + _params = _noneParameter ? new DbParameter[0] : new DbParameter[colidx * _source.Count]; + var specialParams = new List(); + var didx = 0; + foreach (var d in _source) + { + if (_source.Count > 1) sb.Append("\r\n"); + sb.Append(sbtb); + sb.Append("VALUES"); + sb.Append("("); + var colidx2 = 0; + foreach (var col in _table.Columns.Values) + { + if (col.Attribute.IsIdentity && _insertIdentity == false && string.IsNullOrEmpty(col.DbInsertValue)) continue; + if (col.Attribute.IsIdentity == false && _ignore.ContainsKey(col.Attribute.Name)) continue; + + if (colidx2 > 0) sb.Append(", "); + if (string.IsNullOrEmpty(col.DbInsertValue) == false) + sb.Append(col.DbInsertValue); + else + { + object val = col.GetMapValue(d); + if (_noneParameter) + sb.Append(_commonUtils.GetNoneParamaterSqlValue(specialParams, col.Attribute.MapType, val)); + else + { + sb.Append(_commonUtils.QuoteWriteParamter(col.Attribute.MapType, _commonUtils.QuoteParamterName($"{col.CsName}_{didx}"))); + _params[didx * colidx + colidx2] = _commonUtils.AppendParamter(null, $"{col.CsName}_{didx}", col, col.Attribute.MapType, val); + } + } + ++colidx2; + } + sb.Append(")"); + ++didx; + } + if (_source.Count > 1) sb.Append("\r\n SELECT 1 FROM DUAL"); + return sb.ToString(); + } + + ColumnInfo _identCol; + protected override long RawExecuteIdentity() + { + var sql = this.ToSql(); + if (string.IsNullOrEmpty(sql)) return 0; + + long ret = 0; + Exception exception = null; + Aop.CurdBeforeEventArgs before = null; + + if (_identCol == null || _source.Count > 1) + { + before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, _params); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + try + { + ret = _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, sql, _params); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + return 0; + } + var identColName = _commonUtils.QuoteSqlName(_identCol.Attribute.Name); + var identParam = _commonUtils.AppendParamter(null, $"{_identCol.CsName}99", _identCol, _identCol.Attribute.MapType, 0); + identParam.Direction = ParameterDirection.Output; + sql = $"{sql} RETURNING {identColName} INTO {identParam.ParameterName}"; + var dbParms = _params.Concat(new[] { identParam }).ToArray(); + before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + try + { + _orm.Ado.ExecuteNonQuery(_connection, _transaction, CommandType.Text, sql, dbParms); + long.TryParse(string.Concat(identParam.Value), out ret); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + return ret; + } + + protected override List RawExecuteInserted() + { + var sql = this.ToSql(); + if (string.IsNullOrEmpty(sql)) return new List(); + + var ret = _source.ToList(); + this.RawExecuteAffrows(); + return ret; + } + +#if net40 +#else + public override Task ExecuteAffrowsAsync() => base.SplitExecuteAffrowsAsync(500, 999); + public override Task ExecuteIdentityAsync() => base.SplitExecuteIdentityAsync(500, 999); + public override Task> ExecuteInsertedAsync() => base.SplitExecuteInsertedAsync(500, 999); + + async protected override Task RawExecuteIdentityAsync() + { + var sql = this.ToSql(); + if (string.IsNullOrEmpty(sql)) return 0; + + long ret = 0; + Exception exception = null; + Aop.CurdBeforeEventArgs before = null; + + if (_identCol == null || _source.Count > 1) + { + before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, _params); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + try + { + ret = await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, sql, _params); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + return 0; + } + var identColName = _commonUtils.QuoteSqlName(_identCol.Attribute.Name); + var identParam = _commonUtils.AppendParamter(null, $"{_identCol.CsName}99", _identCol, _identCol.Attribute.MapType, 0); + identParam.Direction = ParameterDirection.Output; + sql = $"{sql} RETURNING {identColName} INTO {identParam.ParameterName}"; + var dbParms = _params.Concat(new[] { identParam }).ToArray(); + before = new Aop.CurdBeforeEventArgs(_table.Type, _table, Aop.CurdType.Insert, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + try + { + await _orm.Ado.ExecuteNonQueryAsync(_connection, _transaction, CommandType.Text, sql, dbParms); + long.TryParse(string.Concat(identParam.Value), out ret); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + return ret; + } + async protected override Task> RawExecuteInsertedAsync() + { + var sql = this.ToSql(); + if (string.IsNullOrEmpty(sql)) return new List(); + + var ret = _source.ToList(); + await this.RawExecuteAffrowsAsync(); + return ret; + } +#endif + } +} diff --git a/Providers/FreeSql.Provider.Dameng/Curd/DamengSelect.cs b/Providers/FreeSql.Provider.Dameng/Curd/DamengSelect.cs new file mode 100644 index 00000000..e93a68f6 --- /dev/null +++ b/Providers/FreeSql.Provider.Dameng/Curd/DamengSelect.cs @@ -0,0 +1,184 @@ +using FreeSql.Internal; +using FreeSql.Internal.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace FreeSql.Dameng.Curd +{ + + class DamengSelect : FreeSql.Internal.CommonProvider.Select1Provider where T1 : class + { + + internal static string ToSqlStatic(CommonUtils _commonUtils, CommonExpression _commonExpression, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, List> tbUnions, Func _aliasRule, string _tosqlAppendContent, List _whereCascadeExpression, IFreeSql _orm) + { + if (_orm.CodeFirst.IsAutoSyncStructure) + _orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray()); + + if (_whereCascadeExpression.Any()) + foreach (var tb in _tables.Where(a => a.Type != SelectTableInfoType.Parent)) + tb.Cascade = _commonExpression.GetWhereCascadeSql(tb, _whereCascadeExpression); + + var sb = new StringBuilder(); + var tbUnionsGt0 = tbUnions.Count > 1; + for (var tbUnionsIdx = 0; tbUnionsIdx < tbUnions.Count; tbUnionsIdx++) + { + if (tbUnionsIdx > 0) sb.Append(" \r\n\r\nUNION ALL\r\n\r\n"); + if (tbUnionsGt0) sb.Append(_select).Append(" * from ("); + var tbUnion = tbUnions[tbUnionsIdx]; + + var sbnav = new StringBuilder(); + sb.Append(_select); + if (_distinct) sb.Append("DISTINCT "); + sb.Append(field); + if (string.IsNullOrEmpty(_orderby) && _skip > 0) sb.Append(", ROWNUM AS \"__rownum__\""); + sb.Append(" \r\nFROM "); + var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray(); + var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray(); + for (var a = 0; a < tbsfrom.Length; a++) + { + sb.Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[a].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[a].Table.Type, tbsfrom[a].Alias) ?? tbsfrom[a].Alias); + if (tbsjoin.Length > 0) + { + //如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1 + for (var b = 1; b < tbsfrom.Length; b++) + { + sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbUnion[tbsfrom[b].Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tbsfrom[b].Table.Type, tbsfrom[b].Alias) ?? tbsfrom[b].Alias); + + if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); + else + { + var onSql = tbsfrom[b].NavigateCondition ?? tbsfrom[b].On; + sb.Append(" ON ").Append(onSql); + if (string.IsNullOrEmpty(tbsfrom[b].Cascade) == false) + { + if (string.IsNullOrEmpty(onSql)) sb.Append(tbsfrom[b].Cascade); + else sb.Append(" AND (").Append(tbsfrom[b].Cascade).Append(")"); + } + } + } + break; + } + else + { + if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")"); + if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")"); + if (a > 0 && !string.IsNullOrEmpty(tbsfrom[a].Cascade)) sbnav.Append(" AND (").Append(tbsfrom[a].Cascade).Append(")"); + } + if (a < tbsfrom.Length - 1) sb.Append(", "); + } + foreach (var tb in tbsjoin) + { + if (tb.Type == SelectTableInfoType.Parent) continue; + switch (tb.Type) + { + case SelectTableInfoType.LeftJoin: + sb.Append(" \r\nLEFT JOIN "); + break; + case SelectTableInfoType.InnerJoin: + sb.Append(" \r\nINNER JOIN "); + break; + case SelectTableInfoType.RightJoin: + sb.Append(" \r\nRIGHT JOIN "); + break; + } + sb.Append(_commonUtils.QuoteSqlName(tbUnion[tb.Table.Type])).Append(" ").Append(_aliasRule?.Invoke(tb.Table.Type, tb.Alias) ?? tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); + if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND (").Append(tb.Cascade).Append(")"); + if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); + } + if (_join.Length > 0) sb.Append(_join); + + sbnav.Append(_where); + if (!string.IsNullOrEmpty(_tables[0].Cascade)) + sbnav.Append(" AND (").Append(_tables[0].Cascade).Append(")"); + + if (string.IsNullOrEmpty(_orderby) && (_skip > 0 || _limit > 0)) + sbnav.Append(" AND ROWNUM < ").Append(_skip + _limit + 1); + if (sbnav.Length > 0) + sb.Append(" \r\nWHERE ").Append(sbnav.Remove(0, 5)); + if (string.IsNullOrEmpty(_groupby) == false) + { + sb.Append(_groupby); + if (string.IsNullOrEmpty(_having) == false) + sb.Append(" \r\nHAVING ").Append(_having.Substring(5)); + } + sb.Append(_orderby); + + if (string.IsNullOrEmpty(_orderby)) + { + if (_skip > 0) + sb.Insert(0, $"{_select} t.* FROM (").Append(") t WHERE t.\"__rownum__\" > ").Append(_skip); + } + else + { + if (_skip > 0 && _limit > 0) sb.Insert(0, $"{_select} t.* FROM (SELECT rt.*, ROWNUM AS \"__rownum__\" FROM (").Append(") rt WHERE ROWNUM < ").Append(_skip + _limit + 1).Append(") t WHERE t.\"__rownum__\" > ").Append(_skip); + else if (_skip > 0) sb.Insert(0, $"{_select} t.* FROM (").Append(") t WHERE ROWNUM > ").Append(_skip); + else if (_limit > 0) sb.Insert(0, $"{_select} t.* FROM (").Append(") t WHERE ROWNUM < ").Append(_limit + 1); + } + + sbnav.Clear(); + if (tbUnionsGt0) sb.Append(") ftb"); + } + return sb.Append(_tosqlAppendContent).ToString(); + } + + public DamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public override ISelect From(Expression, T2, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new DamengSelect(_orm, _commonUtils, _commonExpression, null); DamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override ISelect From(Expression, T2, T3, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new DamengSelect(_orm, _commonUtils, _commonExpression, null); DamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override ISelect From(Expression, T2, T3, T4, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new DamengSelect(_orm, _commonUtils, _commonExpression, null); DamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override ISelect From(Expression, T2, T3, T4, T5, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new DamengSelect(_orm, _commonUtils, _commonExpression, null); DamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override ISelect From(Expression, T2, T3, T4, T5, T6, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new DamengSelect(_orm, _commonUtils, _commonExpression, null); DamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override ISelect From(Expression, T2, T3, T4, T5, T6, T7, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new DamengSelect(_orm, _commonUtils, _commonExpression, null); DamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override ISelect From(Expression, T2, T3, T4, T5, T6, T7, T8, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new DamengSelect(_orm, _commonUtils, _commonExpression, null); DamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override ISelect From(Expression, T2, T3, T4, T5, T6, T7, T8, T9, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new DamengSelect(_orm, _commonUtils, _commonExpression, null); DamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override ISelect From(Expression, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new DamengSelect(_orm, _commonUtils, _commonExpression, null); DamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override string ToSql(string field = null) => ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); + } + class DamengSelect : FreeSql.Internal.CommonProvider.Select2Provider where T1 : class where T2 : class + { + public DamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public override string ToSql(string field = null) => DamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); + } + class DamengSelect : FreeSql.Internal.CommonProvider.Select3Provider where T1 : class where T2 : class where T3 : class + { + public DamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public override string ToSql(string field = null) => DamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); + } + class DamengSelect : FreeSql.Internal.CommonProvider.Select4Provider where T1 : class where T2 : class where T3 : class where T4 : class + { + public DamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public override string ToSql(string field = null) => DamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); + } + class DamengSelect : FreeSql.Internal.CommonProvider.Select5Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class + { + public DamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public override string ToSql(string field = null) => DamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); + } + class DamengSelect : FreeSql.Internal.CommonProvider.Select6Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class + { + public DamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public override string ToSql(string field = null) => DamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); + } + class DamengSelect : FreeSql.Internal.CommonProvider.Select7Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class + { + public DamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public override string ToSql(string field = null) => DamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); + } + class DamengSelect : FreeSql.Internal.CommonProvider.Select8Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class + { + public DamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public override string ToSql(string field = null) => DamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); + } + class DamengSelect : FreeSql.Internal.CommonProvider.Select9Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class + { + public DamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public override string ToSql(string field = null) => DamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); + } + class DamengSelect : FreeSql.Internal.CommonProvider.Select10Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class + { + public DamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public override string ToSql(string field = null) => DamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); + } +} diff --git a/Providers/FreeSql.Provider.Dameng/Curd/DamengUpdate.cs b/Providers/FreeSql.Provider.Dameng/Curd/DamengUpdate.cs new file mode 100644 index 00000000..db636a0f --- /dev/null +++ b/Providers/FreeSql.Provider.Dameng/Curd/DamengUpdate.cs @@ -0,0 +1,77 @@ +using FreeSql.Internal; +using FreeSql.Internal.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FreeSql.Dameng.Curd +{ + + class DamengUpdate : Internal.CommonProvider.UpdateProvider where T1 : class + { + + public DamengUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) + : base(orm, commonUtils, commonExpression, dywhere) + { + } + + public override int ExecuteAffrows() => base.SplitExecuteAffrows(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999); + public override List ExecuteUpdated() => base.SplitExecuteUpdated(_batchRowsLimit > 0 ? _batchRowsLimit : 200, _batchParameterLimit > 0 ? _batchParameterLimit : 999); + + + protected override List RawExecuteUpdated() + { + throw new NotImplementedException(); + } + + protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) + { + if (_table.Primarys.Length == 1) + { + var pk = _table.Primarys.First(); + caseWhen.Append(_commonUtils.QuoteReadColumn(pk.CsType, pk.Attribute.MapType, _commonUtils.QuoteSqlName(pk.Attribute.Name))); + return; + } + caseWhen.Append("("); + var pkidx = 0; + foreach (var pk in _table.Primarys) + { + if (pkidx > 0) caseWhen.Append(" || '+' || "); + caseWhen.Append(_commonUtils.QuoteReadColumn(pk.CsType, pk.Attribute.MapType, _commonUtils.QuoteSqlName(pk.Attribute.Name))); + ++pkidx; + } + caseWhen.Append(")"); + } + + protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d) + { + if (_table.Primarys.Length == 1) + { + sb.Append(_commonUtils.FormatSql("{0}", _table.Primarys.First().GetMapValue(d))); + return; + } + sb.Append("("); + var pkidx = 0; + foreach (var pk in _table.Primarys) + { + if (pkidx > 0) sb.Append(" || '+' || "); + sb.Append(_commonUtils.FormatSql("{0}", pk.GetMapValue(d))); + ++pkidx; + } + sb.Append(")"); + } + +#if net40 +#else + public override Task ExecuteAffrowsAsync() => base.SplitExecuteAffrowsAsync(200, 999); + public override Task> ExecuteUpdatedAsync() => base.SplitExecuteUpdatedAsync(200, 999); + + protected override Task> RawExecuteUpdatedAsync() + { + throw new NotImplementedException(); + } +#endif + } +} diff --git a/Providers/FreeSql.Provider.Dameng/DamengAdo/DamengAdo.cs b/Providers/FreeSql.Provider.Dameng/DamengAdo/DamengAdo.cs new file mode 100644 index 00000000..af9caf76 --- /dev/null +++ b/Providers/FreeSql.Provider.Dameng/DamengAdo/DamengAdo.cs @@ -0,0 +1,75 @@ +using Dm; +using FreeSql.Internal; +using FreeSql.Internal.Model; +using FreeSql.Internal.ObjectPool; +using System; +using System.Collections; +using System.Data.Common; +using System.Threading; + +namespace FreeSql.Dameng +{ + class DamengAdo : FreeSql.Internal.CommonProvider.AdoProvider + { + public DamengAdo() : base(DataType.Dameng, null, null) { } + public DamengAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings, Func connectionFactory) : base(DataType.Dameng, masterConnectionString, slaveConnectionStrings) + { + base._util = util; + if (connectionFactory != null) + { + MasterPool = new FreeSql.Internal.CommonProvider.DbConnectionPool(DataType.Dameng, connectionFactory); + return; + } + if (!string.IsNullOrEmpty(masterConnectionString)) + MasterPool = new DamengConnectionPool("主库", masterConnectionString, null, null); + if (slaveConnectionStrings != null) + { + foreach (var slaveConnectionString in slaveConnectionStrings) + { + var slavePool = new DamengConnectionPool($"从库{SlavePools.Count + 1}", slaveConnectionString, () => Interlocked.Decrement(ref slaveUnavailables), () => Interlocked.Increment(ref slaveUnavailables)); + SlavePools.Add(slavePool); + } + } + } + public override object AddslashesProcessParam(object param, Type mapType, ColumnInfo mapColumn) + { + if (param == null) return "NULL"; + if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false)) + param = Utils.GetDataReaderValue(mapType, param); + + if (param is byte[]) + return $"hextoraw('{CommonUtils.BytesSqlRaw(param as byte[])}')"; + else if (param is bool || param is bool?) + return (bool)param ? 1 : 0; + else if (param is string || param is char) + return string.Concat("'", param.ToString().Replace("'", "''"), "'"); + else if (param is Enum) + return ((Enum)param).ToInt64(); + else if (decimal.TryParse(string.Concat(param), out var trydec)) + return param; + else if (param is DateTime || param is DateTime?) + return string.Concat("to_timestamp('", ((DateTime)param).ToString("yyyy-MM-dd HH:mm:ss.ffffff"), "','YYYY-MM-DD HH24:MI:SS.FF6')"); + else if (param is TimeSpan || param is TimeSpan?) + return $"numtodsinterval({((TimeSpan)param).Ticks * 1.0 / 10000000},'second')"; + else if (param is IEnumerable) + return AddslashesIEnumerable(param, mapType, mapColumn); + + return string.Concat("'", param.ToString().Replace("'", "''"), "'"); + //if (param is string) return string.Concat('N', nparms[a]); + } + + protected override DbCommand CreateCommand() + { + return new DmCommand(); + } + + protected override void ReturnConnection(IObjectPool pool, Object conn, Exception ex) + { + var rawPool = pool as DamengConnectionPool; + if (rawPool != null) rawPool.Return(conn, ex); + else pool.Return(conn); + } + + protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj); + } +} diff --git a/Providers/FreeSql.Provider.Dameng/DamengAdo/DamengConnectionPool.cs b/Providers/FreeSql.Provider.Dameng/DamengAdo/DamengConnectionPool.cs new file mode 100644 index 00000000..b10d3749 --- /dev/null +++ b/Providers/FreeSql.Provider.Dameng/DamengAdo/DamengConnectionPool.cs @@ -0,0 +1,253 @@ +using Dm; +using FreeSql.Internal.ObjectPool; +using System; +using System.Collections.Concurrent; +using System.Data; +using System.Data.Common; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace FreeSql.Dameng +{ + + class DamengConnectionPool : ObjectPool + { + + internal Action availableHandler; + internal Action unavailableHandler; + internal string UserId { get; set; } + + public DamengConnectionPool(string name, string connectionString, Action availableHandler, Action unavailableHandler) : base(null) + { + this.UserId = DamengConnectionPool.GetUserId(connectionString); + + this.availableHandler = availableHandler; + this.unavailableHandler = unavailableHandler; + var policy = new DamengConnectionPoolPolicy + { + _pool = this, + Name = name + }; + this.Policy = policy; + policy.ConnectionString = connectionString; + } + + public static string GetUserId(string connectionString) + { + var userIdMatch = Regex.Match(connectionString, @"(User\s+Id|Uid)\s*=\s*([^;]+)", RegexOptions.IgnoreCase); + if (userIdMatch.Success == false) throw new Exception(@"从 ConnectionString 中无法匹配 (User\s+Id|Uid)\s*=\s*([^;]+)"); + return userIdMatch.Groups[2].Value.Trim().ToUpper(); + } + + public void Return(Object obj, Exception exception, bool isRecreate = false) + { + if (exception != null && exception is DmException) + { + if (exception is System.IO.IOException) + { + base.SetUnavailable(exception); + } + else if (obj.Value.Ping() == false) + { + base.SetUnavailable(exception); + } + } + base.Return(obj, isRecreate); + } + } + + class DamengConnectionPoolPolicy : IPolicy + { + + internal DamengConnectionPool _pool; + public string Name { get; set; } = "Dameng DmConnection 对象池"; + public int PoolSize { get; set; } = 100; + public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10); + public TimeSpan IdleTimeout { get; set; } = TimeSpan.FromSeconds(20); + public int AsyncGetCapacity { get; set; } = 10000; + public bool IsThrowGetTimeoutException { get; set; } = true; + public bool IsAutoDisposeWithSystem { get; set; } = true; + public int CheckAvailableInterval { get; set; } = 5; + + static ConcurrentDictionary dicConnStrIncr = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + private string _connectionString; + public string ConnectionString + { + get => _connectionString; + set + { + _connectionString = value ?? ""; + + var pattern = @"(Max\s*)?pool\s*size\s*=\s*(\d+)"; + Match m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase); + if (m.Success == false || int.TryParse(m.Groups[2].Value, out var poolsize) == false || poolsize <= 0) poolsize = 100; + var connStrIncr = dicConnStrIncr.AddOrUpdate(_connectionString, 1, (oldkey, oldval) => Math.Min(5, oldval + 1)); + PoolSize = poolsize + connStrIncr; + _connectionString = m.Success ? + Regex.Replace(_connectionString, pattern, $"poolsize={PoolSize}", RegexOptions.IgnoreCase) : + $"{_connectionString};poolsize={PoolSize}"; //NotSupportedException + //if (m.Success) _connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase); + + pattern = @"Connection\s*LifeTime\s*=\s*(\d+)"; + m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase); + if (m.Success) + { + IdleTimeout = TimeSpan.FromSeconds(int.Parse(m.Groups[1].Value)); + _connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase); + } + + var minPoolSize = 0; + pattern = @"Min\s*pool\s*size\s*=\s*(\d+)"; + m = Regex.Match(_connectionString, pattern, RegexOptions.IgnoreCase); + if (m.Success) + { + minPoolSize = int.Parse(m.Groups[1].Value); + _connectionString = Regex.Replace(_connectionString, pattern, "", RegexOptions.IgnoreCase); + } + + FreeSql.Internal.CommonUtils.PrevReheatConnectionPool(_pool, minPoolSize); + } + } + + public bool OnCheckAvailable(Object obj) + { + if (obj.Value.State == ConnectionState.Closed) obj.Value.Open(); + return obj.Value.Ping(true); + } + + public DbConnection OnCreate() + { + var conn = new DmConnection(_connectionString); + return conn; + } + + public void OnDestroy(DbConnection obj) + { + if (obj.State != ConnectionState.Closed) obj.Close(); + obj.Dispose(); + } + + public void OnGet(Object obj) + { + + if (_pool.IsAvailable) + { + if (obj.Value == null) + { + if (_pool.SetUnavailable(new Exception("连接字符串错误")) == true) + throw new Exception($"【{this.Name}】连接字符串错误,请检查。"); + return; + } + + if (obj.Value.State != ConnectionState.Open || DateTime.Now.Subtract(obj.LastReturnTime).TotalSeconds > 60 && obj.Value.Ping() == false) + { + + try + { + obj.Value.Open(); + } + catch (Exception ex) + { + if (_pool.SetUnavailable(ex) == true) + throw new Exception($"【{this.Name}】状态不可用,等待后台检查程序恢复方可使用。{ex.Message}"); + } + } + } + } + +#if net40 +#else + async public Task OnGetAsync(Object obj) + { + + if (_pool.IsAvailable) + { + if (obj.Value == null) + { + if (_pool.SetUnavailable(new Exception("连接字符串错误")) == true) + throw new Exception($"【{this.Name}】连接字符串错误,请检查。"); + return; + } + + if (obj.Value.State != ConnectionState.Open || DateTime.Now.Subtract(obj.LastReturnTime).TotalSeconds > 60 && (await obj.Value.PingAsync()) == false) + { + + try + { + await obj.Value.OpenAsync(); + } + catch (Exception ex) + { + if (_pool.SetUnavailable(ex) == true) + throw new Exception($"【{this.Name}】状态不可用,等待后台检查程序恢复方可使用。{ex.Message}"); + } + } + } + } +#endif + + public void OnGetTimeout() + { + + } + + public void OnReturn(Object obj) + { + //if (obj?.Value != null && obj.Value.State != ConnectionState.Closed) try { obj.Value.Close(); } catch { } + } + + public void OnAvailable() + { + _pool.availableHandler?.Invoke(); + } + + public void OnUnavailable() + { + _pool.unavailableHandler?.Invoke(); + } + } + + static class DbConnectionExtensions + { + + static DbCommand PingCommand(DbConnection conn) + { + var cmd = conn.CreateCommand(); + cmd.CommandTimeout = 5; + cmd.CommandText = "select 1 from dual"; + return cmd; + } + public static bool Ping(this DbConnection that, bool isThrow = false) + { + try + { + PingCommand(that).ExecuteNonQuery(); + return true; + } + catch + { + if (that.State != ConnectionState.Closed) try { that.Close(); } catch { } + if (isThrow) throw; + return false; + } + } + +#if net40 +#else + async public static Task PingAsync(this DbConnection that, bool isThrow = false) + { + try + { + await PingCommand(that).ExecuteNonQueryAsync(); + return true; + } + catch + { + if (that.State != ConnectionState.Closed) try { that.Close(); } catch { } + if (isThrow) throw; + return false; + } + } +#endif + } +} diff --git a/Providers/FreeSql.Provider.Dameng/DamengCodeFirst.cs b/Providers/FreeSql.Provider.Dameng/DamengCodeFirst.cs new file mode 100644 index 00000000..2378e7ab --- /dev/null +++ b/Providers/FreeSql.Provider.Dameng/DamengCodeFirst.cs @@ -0,0 +1,469 @@ +using Dm; +using FreeSql.DataAnnotations; +using FreeSql.Internal; +using FreeSql.Internal.Model; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; + +namespace FreeSql.Dameng +{ + + class DamengCodeFirst : Internal.CommonProvider.CodeFirstProvider + { + public override bool IsNoneCommandParameter { get => true; set => base.IsNoneCommandParameter = true; } + public DamengCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) : base(orm, commonUtils, commonExpression) { } + + static object _dicCsToDbLock = new object(); + static Dictionary> _dicCsToDb = new Dictionary>() { + { typeof(bool).FullName, CsToDb.New(DmDbType.Bit, "number","number(1) NOT NULL", null, false, false) },{ typeof(bool?).FullName, CsToDb.New(DmDbType.Bit, "number","number(1) NULL", null, true, null) }, + + { typeof(sbyte).FullName, CsToDb.New(DmDbType.SByte, "number", "number(4) NOT NULL", false, false, 0) },{ typeof(sbyte?).FullName, CsToDb.New(DmDbType.SByte, "number", "number(4) NULL", false, true, null) }, + { typeof(short).FullName, CsToDb.New(DmDbType.Int16, "number","number(6) NOT NULL", false, false, 0) },{ typeof(short?).FullName, CsToDb.New(DmDbType.Int16, "number", "number(6) NULL", false, true, null) }, + { typeof(int).FullName, CsToDb.New(DmDbType.Int32, "number", "number(11) NOT NULL", false, false, 0) },{ typeof(int?).FullName, CsToDb.New(DmDbType.Int32, "number", "number(11) NULL", false, true, null) }, + { typeof(long).FullName, CsToDb.New(DmDbType.Int64, "number","number(21) NOT NULL", false, false, 0) },{ typeof(long?).FullName, CsToDb.New(DmDbType.Int64, "number","number(21) NULL", false, true, null) }, + + { typeof(byte).FullName, CsToDb.New(DmDbType.Byte, "number","number(3) NOT NULL", true, false, 0) },{ typeof(byte?).FullName, CsToDb.New(DmDbType.Byte, "number","number(3) NULL", true, true, null) }, + { typeof(ushort).FullName, CsToDb.New(DmDbType.UInt16, "number","number(5) NOT NULL", true, false, 0) },{ typeof(ushort?).FullName, CsToDb.New(DmDbType.UInt16, "number", "number(5) NULL", true, true, null) }, + { typeof(uint).FullName, CsToDb.New(DmDbType.UInt32, "number", "number(10) NOT NULL", true, false, 0) },{ typeof(uint?).FullName, CsToDb.New(DmDbType.UInt32, "number", "number(10) NULL", true, true, null) }, + { typeof(ulong).FullName, CsToDb.New(DmDbType.UInt64, "number", "number(20) NOT NULL", true, false, 0) },{ typeof(ulong?).FullName, CsToDb.New(DmDbType.UInt64, "number", "number(20) NULL", true, true, null) }, + + { typeof(double).FullName, CsToDb.New(DmDbType.Double, "double", "double NOT NULL", false, false, 0) },{ typeof(double?).FullName, CsToDb.New(DmDbType.Double, "double", "double NULL", false, true, null) }, + { typeof(float).FullName, CsToDb.New(DmDbType.Float, "real","real NOT NULL", false, false, 0) },{ typeof(float?).FullName, CsToDb.New(DmDbType.Float, "real","real NULL", false, true, null) }, + { typeof(decimal).FullName, CsToDb.New(DmDbType.Decimal, "number", "number(10,2) NOT NULL", false, false, 0) },{ typeof(decimal?).FullName, CsToDb.New(DmDbType.Decimal, "number", "number(10,2) NULL", false, true, null) }, + + //达梦8 ODBC 不支持 TimeSpan + //{ typeof(TimeSpan).FullName, CsToDb.NewInfo(DmDbType.Time, "interval day to second","interval day(2) to second(6) NOT NULL", false, false, 0) },{ typeof(TimeSpan?).FullName, (DmDbType.Time, "interval day to second", "interval day(2) to second(6) NULL",false, true, null) }, + { typeof(DateTime).FullName, CsToDb.New(DmDbType.DateTime, "timestamp", "timestamp(6) NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, CsToDb.New(DmDbType.DateTime, "timestamp", "timestamp(6) NULL", false, true, null) }, + { typeof(DateTimeOffset).FullName, CsToDb.New(DmDbType.DateTime, "timestamp", "timestamp(6) NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTimeOffset?).FullName, CsToDb.New(DmDbType.DateTime, "timestamp", "timestamp(6) NULL", false, true, null) }, + + { typeof(byte[]).FullName, CsToDb.New(DmDbType.VarBinary, "blob", "blob NULL", false, null, new byte[0]) }, + { typeof(string).FullName, CsToDb.New(DmDbType.VarChar, "nvarchar2", "nvarchar2(255) NULL", false, null, "") }, + + { typeof(Guid).FullName, CsToDb.New(DmDbType.Char, "char", "char(36) NOT NULL", false, false, Guid.Empty) },{ typeof(Guid?).FullName, CsToDb.New(DmDbType.Char, "char", "char(36) NULL", false, true, null) }, + }; + + public override DbInfoResult GetDbInfo(Type type) + { + if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return new DbInfoResult((int)trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable, trydc.defaultValue); + if (type.IsArray) return null; + var enumType = type.IsEnum ? type : null; + if (enumType == null && type.IsNullableType()) + { + var genericTypes = type.GetGenericArguments(); + if (genericTypes.Length == 1 && genericTypes.First().IsEnum) enumType = genericTypes.First(); + } + if (enumType != null) + { + var newItem = enumType.GetCustomAttributes(typeof(FlagsAttribute), false).Any() ? + CsToDb.New(DmDbType.Int32, "number", $"number(16){(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true, Enum.GetValues(enumType).GetValue(0)) : + CsToDb.New(DmDbType.Int64, "number", $"number(32){(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true, Enum.GetValues(enumType).GetValue(0)); + if (_dicCsToDb.ContainsKey(type.FullName) == false) + { + lock (_dicCsToDbLock) + { + if (_dicCsToDb.ContainsKey(type.FullName) == false) + _dicCsToDb.Add(type.FullName, newItem); + } + } + return new DbInfoResult((int)newItem.type, newItem.dbtype, newItem.dbtypeFull, newItem.isnullable, newItem.defaultValue); + } + return null; + } + + protected override string GetComparisonDDLStatements(params TypeAndName[] objects) + { + var userId = (_orm.Ado.MasterPool as DamengConnectionPool)?.UserId; + if (string.IsNullOrEmpty(userId)) + using (var conn = _orm.Ado.MasterPool.Get()) + { + userId = DamengConnectionPool.GetUserId(conn.Value.ConnectionString); + } + var seqcols = new List>(); //序列:列,表,自增 + var seqnameDel = new List(); //要删除的序列+触发器 + + var sb = new StringBuilder(); + var sbDeclare = new StringBuilder(); + foreach (var obj in objects) + { + if (sb.Length > 0) sb.Append("\r\n"); + var tb = _commonUtils.GetTableByEntity(obj.entityType); + if (tb == null) throw new Exception($"类型 {obj.entityType.FullName} 不可迁移"); + if (tb.Columns.Any() == false) throw new Exception($"类型 {obj.entityType.FullName} 不可迁移,可迁移属性0个"); + var tbname = _commonUtils.SplitTableName(tb.DbName); + if (tbname?.Length == 1) tbname = new[] { userId, tbname[0] }; + + var tboldname = _commonUtils.SplitTableName(tb.DbOldName); //旧表名 + if (tboldname?.Length == 1) tboldname = new[] { userId, tboldname[0] }; + var primaryKeyName = (obj.entityType.GetCustomAttributes(typeof(OraclePrimaryKeyNameAttribute), false)?.FirstOrDefault() as OraclePrimaryKeyNameAttribute)?.Name; + if (string.IsNullOrEmpty(obj.tableName) == false) + { + var tbtmpname = _commonUtils.SplitTableName(obj.tableName); + if (tbtmpname?.Length == 1) tbtmpname = new[] { userId, tbtmpname[0] }; + if (tbname[0] != tbtmpname[0] || tbname[1] != tbtmpname[1]) + { + tbname = tbtmpname; + tboldname = null; + primaryKeyName = null; + } + } + //codefirst 不支持表名中带 . + + if (string.Compare(tbname[0], userId) != 0 && _orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(" select 1 from sys.dba_users where username={0}", tbname[0])) == null) //创建数据库 + throw new NotImplementedException($"达梦 CodeFirst 不支持代码创建 tablespace 与 schemas {tbname[0]}"); + + var sbalter = new StringBuilder(); + var istmpatler = false; //创建临时表,导入数据,删除旧表,修改 + if (_orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(" select 1 from all_tab_comments where owner={0} and table_name={1}", tbname)) == null) + { //表不存在 + if (tboldname != null) + { + if (_orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(" select 1 from all_tab_comments where owner={0} and table_name={1}", tboldname)) == null) + //模式或表不存在 + tboldname = null; + } + if (tboldname == null) + { + //创建表 + var createTableName = _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}"); + sb.Append("execute immediate 'CREATE TABLE ").Append(createTableName).Append(" ( "); + foreach (var tbcol in tb.ColumnsByPosition) + { + sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(","); + if (tbcol.Attribute.IsIdentity == true) seqcols.Add(NaviteTuple.Create(tbcol, tbname, true)); + } + if (tb.Primarys.Any()) + { + var pkname = primaryKeyName ?? $"{tbname[0]}_{tbname[1]}_pk1"; + sb.Append(" \r\n CONSTRAINT ").Append(_commonUtils.QuoteSqlName(pkname)).Append(" PRIMARY KEY ("); + foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", "); + sb.Remove(sb.Length - 2, 2).Append("),"); + } + sb.Remove(sb.Length - 1, 1); + sb.Append("\r\n) LOGGING ';\r\n"); + //创建表的索引 + foreach (var uk in tb.Indexes) + { + sb.Append("execute immediate 'CREATE "); + if (uk.IsUnique) sb.Append("UNIQUE "); + sb.Append("INDEX ").Append(_commonUtils.QuoteSqlName(uk.Name)).Append(" ON ").Append(createTableName).Append("("); + foreach (var tbcol in uk.Columns) + { + sb.Append(_commonUtils.QuoteSqlName(tbcol.Column.Attribute.Name)); + if (tbcol.IsDesc) sb.Append(" DESC"); + sb.Append(", "); + } + sb.Remove(sb.Length - 2, 2).Append(")';\r\n"); + } + //备注 + foreach (var tbcol in tb.ColumnsByPosition) + { + if (string.IsNullOrEmpty(tbcol.Comment) == false) + sb.Append("execute immediate 'COMMENT ON COLUMN ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbcol.Attribute.Name}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment).Replace("'", "''")).Append("';\r\n"); + } + if (string.IsNullOrEmpty(tb.Comment) == false) + sb.Append("execute immediate 'COMMENT ON TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tb.Comment).Replace("'", "''")).Append("';\r\n"); + continue; + } + //如果新表,旧表在一个模式下,直接修改表名 + if (string.Compare(tbname[0], tboldname[0], true) == 0) + sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}")).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[1]}")).Append("';\r\n"); + else + { + //如果新表,旧表不在一起,创建新表,导入数据,删除旧表 + istmpatler = true; + } + } + else + tboldname = null; //如果新表已经存在,不走改表名逻辑 + + //对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段 + var sql = _commonUtils.FormatSql($@" +select +a.column_name, +a.data_type, +a.data_length, +a.data_precision, +a.data_scale, +a.char_used, +case when a.nullable = 'N' then 0 else 1 end, +nvl((select 1 from user_sequences where upper(sequence_name)=upper('{Utils.GetCsName((tboldname ?? tbname).Last())}_seq_'||a.column_name) and rownum < 2), 0), +nvl((select 1 from user_triggers where upper(trigger_name)=upper('{Utils.GetCsName((tboldname ?? tbname).Last())}_seq_'||a.column_name||'TI') and rownum < 2), 0), +b.comments +from all_tab_columns a +left join all_col_comments b on b.owner = a.owner and b.table_name = a.table_name and b.column_name = a.column_name +where a.owner={{0}} and a.table_name={{1}}", tboldname ?? tbname); + var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql); + var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a => + { + var sqlType = GetDamengSqlTypeFullName(a); + return new + { + column = string.Concat(a[0]), + sqlType, + is_nullable = string.Concat(a[6]) == "1", + is_identity = string.Concat(a[7]) == "1" && string.Concat(a[8]) == "1", + comment = string.Concat(a[9]) + }; + }, StringComparer.CurrentCultureIgnoreCase); + + if (istmpatler == false) + { + foreach (var tbcol in tb.ColumnsByPosition) + { + var dbtypeNoneNotNull = Regex.Replace(tbcol.Attribute.DbType, @"NOT\s+NULL", "NULL"); + if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) || + string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) + { + var isCommentChanged = tbstructcol.comment != (tbcol.Comment ?? ""); + if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) + { + istmpatler = true; + if (istmpatler && tbcol.Attribute.DbType.StartsWith("varchar", StringComparison.CurrentCultureIgnoreCase) && tbstructcol.sqlType.StartsWith("varchar2", StringComparison.CurrentCultureIgnoreCase) + && Regex.Match(tbcol.Attribute.DbType, @"\(\d+").Groups[0].Value == Regex.Match(tbstructcol.sqlType, @"\(\d+").Groups[0].Value) + istmpatler = false; + if (istmpatler && Regex.IsMatch(tbcol.Attribute.DbType, @"\(\d+") == false && Regex.IsMatch(tbstructcol.sqlType, @"\(\d+") + && string.Compare(tbcol.Attribute.DbType, Regex.Replace(tbstructcol.sqlType, @"\([^\)]+\)", ""), StringComparison.CurrentCultureIgnoreCase) == 0) + istmpatler = false; + } + //sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY (").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(dbtypeNoneNotNull).Append(")';\r\n"); + if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) + { + if (tbcol.Attribute.IsNullable == false) + sbalter.Append("execute immediate 'UPDATE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" SET ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" = ").Append(tbcol.DbDefaultValue.Replace("'", "''")).Append(" WHERE ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" IS NULL';\r\n"); + sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(tbcol.Attribute.IsNullable == true ? "" : "NOT").Append(" NULL';\r\n"); + } + if (string.Compare(tbstructcol.column, tbcol.Attribute.OldName, true) == 0) + { + if (tbstructcol.is_identity) + seqnameDel.Add(Utils.GetCsName($"{tbname[1]}_seq_{tbstructcol.column}")); + //修改列名 + sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" RENAME COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" TO ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append("';\r\n"); + if (tbcol.Attribute.IsIdentity) + seqcols.Add(NaviteTuple.Create(tbcol, tbname, tbcol.Attribute.IsIdentity == true)); + } + else if (tbcol.Attribute.IsIdentity != tbstructcol.is_identity) + seqcols.Add(NaviteTuple.Create(tbcol, tbname, tbcol.Attribute.IsIdentity == true)); + if (isCommentChanged) + sbalter.Append("execute immediate 'COMMENT ON COLUMN ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbcol.Attribute.Name}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment ?? "").Replace("'", "''")).Append("';\r\n"); + continue; + } + //添加列 + sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD (").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(dbtypeNoneNotNull).Append(")';\r\n"); + if (tbcol.Attribute.IsNullable == false) + { + sbalter.Append("execute immediate 'UPDATE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" SET ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" = ").Append(tbcol.DbDefaultValue.Replace("'", "''")).Append("';\r\n"); + sbalter.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" NOT NULL';\r\n"); + } + if (tbcol.Attribute.IsIdentity == true) seqcols.Add(NaviteTuple.Create(tbcol, tbname, tbcol.Attribute.IsIdentity == true)); + if (string.IsNullOrEmpty(tbcol.Comment) == false) sbalter.Append("execute immediate 'COMMENT ON COLUMN ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbcol.Attribute.Name}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment ?? "").Replace("'", "''")).Append("';\r\n"); + } + + var dsuksql = _commonUtils.FormatSql(@" +select +c.column_name, +a.index_name, +case when c.descend = 'DESC' then 1 else 0 end, +case when a.uniqueness = 'UNIQUE' then 1 else 0 end +from all_indexes a, +all_ind_columns c +where a.index_name = c.index_name +and a.table_owner = c.table_owner +and a.table_name = c.table_name +and a.owner in ({0}) and a.table_name in ({1}) +and not exists(select 1 from all_constraints where index_name = a.index_name and constraint_type = 'P')", tboldname ?? tbname); + var dsuk = _orm.Ado.ExecuteArray(CommandType.Text, dsuksql).Select(a => new[] { string.Concat(a[0]).Trim('"'), string.Concat(a[1]), string.Concat(a[2]), string.Concat(a[3]) }).ToArray(); + foreach (var uk in tb.Indexes) + { + if (string.IsNullOrEmpty(uk.Name) || uk.Columns.Any() == false) continue; + var dsukfind1 = dsuk.Where(a => string.Compare(a[1], uk.Name, true) == 0).ToArray(); + if (dsukfind1.Any() == false || dsukfind1.Length != uk.Columns.Length || dsukfind1.Where(a => uk.Columns.Where(b => (a[3] == "1") == uk.IsUnique && string.Compare(b.Column.Attribute.Name, a[0], true) == 0 && (a[2] == "1") == b.IsDesc).Any()).Count() != uk.Columns.Length) + { + if (dsukfind1.Any()) sbalter.Append("execute immediate 'DROP INDEX ").Append(_commonUtils.QuoteSqlName(uk.Name)).Append("';\r\n"); + sbalter.Append("execute immediate 'CREATE "); + if (uk.IsUnique) sbalter.Append("UNIQUE "); + sbalter.Append("INDEX ").Append(_commonUtils.QuoteSqlName(uk.Name)).Append(" ON ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append("("); + foreach (var tbcol in uk.Columns) + { + sbalter.Append(_commonUtils.QuoteSqlName(tbcol.Column.Attribute.Name)); + if (tbcol.IsDesc) sbalter.Append(" DESC"); + sbalter.Append(", "); + } + sbalter.Remove(sbalter.Length - 2, 2).Append(")';\r\n"); + } + } + } + if (istmpatler == false) + { + var dbcomment = string.Concat(_orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(@" select comments from all_tab_comments where owner = {0} and table_name = {1} and table_type = 'TABLE'", tbname[0], tbname[1]))); + if (dbcomment != (tb.Comment ?? "")) + sb.Append("execute immediate 'COMMENT ON TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tb.Comment).Replace("'", "''")).Append("';\r\n"); + + sb.Append(sbalter); + continue; + } + var oldpk = _orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(@" select constraint_name from user_constraints where owner={0} and table_name={1} and constraint_type='P'", tbname))?.ToString(); + if (string.IsNullOrEmpty(oldpk) == false) + sb.Append("execute immediate 'ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" DROP CONSTRAINT ").Append(oldpk).Append("';\r\n"); + + //创建临时表,数据导进临时表,然后删除原表,将临时表改名为原表名 + var tablename = tboldname == null ? _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}") : _commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}"); + var tmptablename = _commonUtils.QuoteSqlName($"{tbname[0]}.FTmp_{tbname[1]}"); + //创建临时表 + sb.Append("execute immediate 'CREATE TABLE ").Append(tmptablename).Append(" ( "); + foreach (var tbcol in tb.ColumnsByPosition) + { + sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(","); + if (tbcol.Attribute.IsIdentity == true) seqcols.Add(NaviteTuple.Create(tbcol, tbname, true)); + } + if (tb.Primarys.Any()) + { + var pkname = primaryKeyName ?? $"{tbname[0]}_{tbname[1]}_pk2"; + sb.Append(" \r\n CONSTRAINT ").Append(_commonUtils.QuoteSqlName(pkname)).Append(" PRIMARY KEY ("); + foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", "); + sb.Remove(sb.Length - 2, 2).Append("),"); + } + sb.Remove(sb.Length - 1, 1); + sb.Append("\r\n) LOGGING ';\r\n"); + //备注 + foreach (var tbcol in tb.ColumnsByPosition) + { + if (string.IsNullOrEmpty(tbcol.Comment) == false) + sb.Append("execute immediate 'COMMENT ON COLUMN ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.FTmp_{tbname[1]}.{tbcol.Attribute.Name}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment).Replace("'", "''")).Append("';\r\n"); + } + if (string.IsNullOrEmpty(tb.Comment) == false) + sb.Append("execute immediate 'COMMENT ON TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.FTmp_{tbname[1]}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tb.Comment).Replace("'", "''")).Append("';\r\n"); + + sb.Append("execute immediate 'INSERT INTO ").Append(tmptablename).Append(" ("); + foreach (var tbcol in tb.ColumnsByPosition) + sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", "); + sb.Remove(sb.Length - 2, 2).Append(")\r\nSELECT "); + foreach (var tbcol in tb.ColumnsByPosition) + { + var insertvalue = "NULL"; + if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) || + string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) + { + insertvalue = _commonUtils.QuoteSqlName(tbstructcol.column); + if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) + { + var dbtypeNoneNotNull = Regex.Replace(tbcol.Attribute.DbType, @"(NOT\s+)?NULL", ""); + insertvalue = $"cast({insertvalue} as {dbtypeNoneNotNull})"; + } + if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) + insertvalue = $"nvl({insertvalue},{tbcol.DbDefaultValue})"; + } + else if (tbcol.Attribute.IsNullable == false) + insertvalue = tbcol.DbDefaultValue; + sb.Append(insertvalue.Replace("'", "''")).Append(", "); + } + sb.Remove(sb.Length - 2, 2).Append(" FROM ").Append(tablename).Append("';\r\n"); + sb.Append("execute immediate 'DROP TABLE ").Append(tablename).Append("';\r\n"); + sb.Append("execute immediate 'ALTER TABLE ").Append(tmptablename).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[1]}")).Append("';\r\n"); + //创建表的索引 + foreach (var uk in tb.Indexes) + { + sb.Append("execute immediate 'CREATE "); + if (uk.IsUnique) sb.Append("UNIQUE "); + sb.Append("INDEX ").Append(_commonUtils.QuoteSqlName(uk.Name)).Append(" ON ").Append(tablename).Append("("); + foreach (var tbcol in uk.Columns) + { + sb.Append(_commonUtils.QuoteSqlName(tbcol.Column.Attribute.Name)); + if (tbcol.IsDesc) sb.Append(" DESC"); + sb.Append(", "); + } + sb.Remove(sb.Length - 2, 2).Append(")';\r\n"); + } + } + Dictionary dicDeclare = new Dictionary(); + Action dropSequence = seqname => + { + if (dicDeclare.ContainsKey(seqname) == false) + { + sbDeclare.Append("\r\nIS").Append(seqname).Append(" NUMBER; \r\n"); + dicDeclare.Add(seqname, true); + } + sb.Append("IS").Append(seqname).Append(" := 0; \r\n") + .Append(" select count(1) into IS").Append(seqname).Append(_commonUtils.FormatSql(" from user_sequences where sequence_name={0}; \r\n", seqname)) + .Append("if IS").Append(seqname).Append(" > 0 then \r\n") + .Append(" execute immediate 'DROP SEQUENCE ").Append(_commonUtils.QuoteSqlName(seqname)).Append("';\r\n") + .Append("end if; \r\n"); + }; + Action dropTrigger = tiggerName => + { + if (dicDeclare.ContainsKey(tiggerName) == false) + { + sbDeclare.Append("\r\nIS").Append(tiggerName).Append(" NUMBER; \r\n"); + dicDeclare.Add(tiggerName, true); + } + sb.Append("IS").Append(tiggerName).Append(" := 0; \r\n") + .Append(" select count(1) into IS").Append(tiggerName).Append(_commonUtils.FormatSql(" from user_triggers where trigger_name={0}; \r\n", tiggerName)) + .Append("if IS").Append(tiggerName).Append(" > 0 then \r\n") + .Append(" execute immediate 'DROP TRIGGER ").Append(_commonUtils.QuoteSqlName(tiggerName)).Append("';\r\n") + .Append("end if; \r\n"); + }; + foreach (var seqname in seqnameDel) + { + dropSequence(seqname); + dropTrigger(seqname + "TI"); + } + foreach (var seqcol in seqcols) + { + var tbname = seqcol.Item2; + var seqname = Utils.GetCsName($"{tbname[1]}_seq_{seqcol.Item1.Attribute.Name}").ToUpper(); + var tiggerName = seqname + "TI"; + var tbname2 = _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}"); + var colname2 = _commonUtils.QuoteSqlName(seqcol.Item1.Attribute.Name); + dropSequence(seqname); + if (seqcol.Item3) + { + var startWith = _orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(" select 1 from all_tab_columns where owner={0} and table_name={1} and column_name={2}", tbname[0], tbname[1], seqcol.Item1.Attribute.Name)) == null ? 1 : + _orm.Ado.ExecuteScalar(CommandType.Text, $" select nvl(max({colname2})+1,1) from {tbname2}"); + sb.Append("execute immediate 'CREATE SEQUENCE ").Append(_commonUtils.QuoteSqlName(seqname)).Append(" start with ").Append(startWith).Append("';\r\n"); + sb.Append("execute immediate 'CREATE OR REPLACE TRIGGER ").Append(_commonUtils.QuoteSqlName(tiggerName)) + .Append(" \r\nbefore insert on ").Append(tbname2) + .Append(" \r\nfor each row \r\nbegin\r\nselect ").Append(_commonUtils.QuoteSqlName(seqname)) + .Append(".nextval into :new.").Append(colname2).Append(" from dual;\r\nend;';\r\n"); + } + else + dropTrigger(tiggerName); + } + if (sbDeclare.Length > 0) sbDeclare.Insert(0, "declare "); + return sb.Length == 0 ? null : sb.Insert(0, "BEGIN \r\n").Insert(0, sbDeclare.ToString()).Append("END;").ToString(); + } + + internal static string GetDamengSqlTypeFullName(object[] row) + { + var a = row; + var sqlType = string.Concat(a[1]).ToUpper(); + var data_length = long.Parse(string.Concat(a[2])); + long.TryParse(string.Concat(a[3]), out var data_precision); + long.TryParse(string.Concat(a[4]), out var data_scale); + //var char_used = string.Concat(a[5]); + if (sqlType.StartsWith("INTERVAL DAY TO SECOND")) + sqlType = $"INTERVAL DAY({(data_scale - 1536) / 16}) TO SECOND({(data_scale - 1536) % 16})"; + else if (Regex.IsMatch(sqlType, @"INTERVAL YEAR\(\d+\) TO MONTH", RegexOptions.IgnoreCase)) + { + } + else if (sqlType.StartsWith("TIMESTAMP", StringComparison.CurrentCultureIgnoreCase)) + sqlType += data_scale <= 0 ? "" : $"({data_scale})"; + else if (sqlType.StartsWith("BLOB")) + { + } + else if (sqlType == "REAL" || sqlType == "DOUBLE" || sqlType == "FLOAT") + { + } + else if (data_precision > 0 && data_scale > 0) + sqlType += $"({data_precision},{data_scale})"; + else if (data_precision > 0) + sqlType += $"({data_precision})"; + else + sqlType += $"({data_length})"; + return sqlType; + } + } +} \ No newline at end of file diff --git a/Providers/FreeSql.Provider.Dameng/DamengDbFirst.cs b/Providers/FreeSql.Provider.Dameng/DamengDbFirst.cs new file mode 100644 index 00000000..2b11cd9e --- /dev/null +++ b/Providers/FreeSql.Provider.Dameng/DamengDbFirst.cs @@ -0,0 +1,559 @@ +using Dm; +using FreeSql.DatabaseModel; +using FreeSql.Internal; +using FreeSql.Internal.Model; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace FreeSql.Dameng +{ + class DamengDbFirst : IDbFirst + { + IFreeSql _orm; + protected CommonUtils _commonUtils; + protected CommonExpression _commonExpression; + public DamengDbFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) + { + _orm = orm; + _commonUtils = commonUtils; + _commonExpression = commonExpression; + } + + public int GetDbType(DbColumnInfo column) => (int)GetSqlDbType(column); + DmDbType GetSqlDbType(DbColumnInfo column) + { + var dbfull = column.DbTypeTextFull.ToLower(); + switch (dbfull) + { + case "number(1)": return DmDbType.Bit; + + case "number(4)": return DmDbType.SByte; + case "number(6)": return DmDbType.Int16; + case "number(11)": return DmDbType.Int32; + case "number(21)": return DmDbType.Int64; + + case "number(3)": return DmDbType.Byte; + case "number(5)": return DmDbType.UInt16; + case "number(10)": return DmDbType.UInt32; + case "number(20)": return DmDbType.UInt64; + + case "float(126)": return DmDbType.Double; + case "float(63)": return DmDbType.Float; + case "number(10,2)": return DmDbType.Decimal; + + case "interval day(2) to second(6)": return DmDbType.Time; + case "timestamp(6)": return DmDbType.DateTime; + case "timestamp(6) with local time zone": return DmDbType.DateTime; + + case "blob": return DmDbType.VarBinary; + case "nvarchar2(255)": return DmDbType.VarChar; + + case "char(36)": return DmDbType.Char; + } + switch (column.DbTypeText.ToLower()) + { + case "bit": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["number(1)"]); + return DmDbType.Bit; + case "smallint": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["number(4)"]); + return DmDbType.UInt16; + case "byte": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["number(3)"]); + return DmDbType.Byte; + case "tinyint": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["number(3)"]); + return DmDbType.Byte; + case "integer": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["number(11)"]); + return DmDbType.Int32; + case "bigint": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["number(21)"]); + return DmDbType.Int64; + case "dec": + case "decimal": + case "numeric": + case "number": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["number(10,2)"]); + return DmDbType.Decimal; + case "time": + case "interval day to second": + case "interval year to month": + case "interval year": + case "interval month": + case "interval day": + case "interval day to hour": + case "interval day to minute": + case "interval hour": + case "interval hour to minute": + case "interval hour to second": + case "interval minute": + case "interval minute to second": + case "interval second": + case "time with time zone": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["interval day(2) to second(6)"]); + return DmDbType.Time; + case "date": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["date(7)"]); + return DmDbType.DateTime; + case "timestamp": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["timestamp(6)"]); + return DmDbType.DateTime; + case "timestamp with local time zone": + case "timestamp with time zone": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["timestamp(6) with local time zone"]); + return DmDbType.DateTime; + case "binary": + case "varbinary": + case "blob": + case "image": + case "longvarbinary": + case "bfile": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["blob"]); + return DmDbType.VarBinary; + case "nvarchar2": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["nvarchar2(255)"]); + return DmDbType.VarChar; + case "varchar": + case "varchar2": + case "text": + case "longvarchar": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["nvarchar2(255)"]); + return DmDbType.VarChar; + case "character": + case "char": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["nvarchar2(255)"]); + return DmDbType.Char; + case "nchar": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["nvarchar2(255)"]); + return DmDbType.Char; + case "clob": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["nvarchar2(255)"]); + return DmDbType.VarChar; + case "nclob": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["nvarchar2(255)"]); + return DmDbType.VarChar; + case "raw": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["blob"]); + return DmDbType.VarBinary; + case "long raw": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["blob"]); + return DmDbType.VarBinary; + case "real": + case "binary_float": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["float(63)"]); + return DmDbType.Float; + case "double": + case "float": + case "double precision": + case "binary_double": + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["float(126)"]); + return DmDbType.Double; + case "rowid": + default: + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["nvarchar2(255)"]); + return DmDbType.VarChar; + } + throw new NotImplementedException($"未实现 {column.DbTypeTextFull} 类型映射"); + } + + static ConcurrentDictionary _dicDbToCs = new ConcurrentDictionary(StringComparer.CurrentCultureIgnoreCase); + static DamengDbFirst() + { + var defaultDbToCs = new Dictionary() { + { "number(1)", new DbToCs("(bool?)", "{0} == \"1\"", "{0} == true ? \"1\" : \"0\"", "bool?", typeof(bool), typeof(bool?), "{0}.Value", "GetBoolean") }, + + { "number(4)", new DbToCs("(sbyte?)", "sbyte.Parse({0})", "{0}.ToString()", "sbyte?", typeof(sbyte), typeof(sbyte?), "{0}.Value", "GetInt16") }, + { "number(6)", new DbToCs("(short?)", "short.Parse({0})", "{0}.ToString()", "short?", typeof(short), typeof(short?), "{0}.Value", "GetInt16") }, + { "number(11)", new DbToCs("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") }, + { "number(21)", new DbToCs("(long?)", "long.Parse({0})", "{0}.ToString()", "long?", typeof(long), typeof(long?), "{0}.Value", "GetInt64") }, + + { "number(3)", new DbToCs("(byte?)", "byte.Parse({0})", "{0}.ToString()", "byte?", typeof(byte), typeof(byte?), "{0}.Value", "GetByte") }, + { "number(5)", new DbToCs("(ushort?)", "ushort.Parse({0})", "{0}.ToString()", "ushort?", typeof(ushort), typeof(ushort?), "{0}.Value", "GetInt32") }, + { "number(10)", new DbToCs("(uint?)", "uint.Parse({0})", "{0}.ToString()", "uint?", typeof(uint), typeof(uint?), "{0}.Value", "GetInt64") }, + { "number(20)", new DbToCs("(ulong?)", "ulong.Parse({0})", "{0}.ToString()", "ulong?", typeof(ulong), typeof(ulong?), "{0}.Value", "GetDecimal") }, + + { "float(126)", new DbToCs("(double?)", "double.Parse({0})", "{0}.ToString()", "double?", typeof(double), typeof(double?), "{0}.Value", "GetDouble") }, + { "float(63)", new DbToCs("(float?)", "float.Parse({0})", "{0}.ToString()", "float?", typeof(float), typeof(float?), "{0}.Value", "GetFloat") }, + { "number(10,2)", new DbToCs("(decimal?)", "decimal.Parse({0})", "{0}.ToString()", "decimal?", typeof(decimal), typeof(decimal?), "{0}.Value", "GetDecimal") }, + + { "interval day(2) to second(6)", new DbToCs("(TimeSpan?)", "TimeSpan.Parse(double.Parse({0}))", "{0}.Ticks.ToString()", "TimeSpan?", typeof(TimeSpan), typeof(TimeSpan?), "{0}.Value", "GetValue") }, + { "date(7)", new DbToCs("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetValue") }, + { "timestamp(6)", new DbToCs("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetValue") }, + { "timestamp(6) with local time zone", new DbToCs("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetValue") }, + + { "blob", new DbToCs("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") }, + + { "nvarchar2(255)", new DbToCs("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") }, + { "char(36 char)", new DbToCs("(Guid?)", "Guid.Parse({0})", "{0}.ToString()", "Guid?", typeof(Guid), typeof(Guid?), "{0}.Value", "GetGuid") }, + }; + foreach (var kv in defaultDbToCs) + _dicDbToCs.TryAdd(kv.Key, kv.Value); + } + + + public string GetCsConvert(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbTypeTextFull, out var trydc) ? (column.IsNullable ? trydc.csConvert : trydc.csConvert.Replace("?", "")) : null; + public string GetCsParse(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbTypeTextFull, out var trydc) ? trydc.csParse : null; + public string GetCsStringify(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbTypeTextFull, out var trydc) ? trydc.csStringify : null; + public string GetCsType(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbTypeTextFull, out var trydc) ? (column.IsNullable ? trydc.csType : trydc.csType.Replace("?", "")) : null; + public Type GetCsTypeInfo(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbTypeTextFull, out var trydc) ? trydc.csTypeInfo : null; + public string GetCsTypeValue(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbTypeTextFull, out var trydc) ? trydc.csTypeValue : null; + public string GetDataReaderMethod(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbTypeTextFull, out var trydc) ? trydc.dataReaderMethod : null; + + public List GetDatabases() + { + var sql = @" select username from all_users"; + var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql); + return ds.Select(a => a.FirstOrDefault()?.ToString()).ToList(); + } + + public List GetTablesByDatabase(params string[] database2) + { + var loc1 = new List(); + var loc2 = new Dictionary(); + var loc3 = new Dictionary>(); + var database = database2?.ToArray(); + + if (database == null || database.Any() == false) + { + var userUsers = _orm.Ado.ExecuteScalar(" select username from user_users")?.ToString(); + if (string.IsNullOrEmpty(userUsers)) return loc1; + database = new[] { userUsers }; + } + var databaseIn = string.Join(",", database.Select(a => _commonUtils.FormatSql("{0}", a))); + var sql = string.Format(@" +select +a.owner || '.' || a.table_name, +a.owner, +a.table_name, +b.comments, +'TABLE' +from all_tables a +left join all_tab_comments b on b.owner = a.owner and b.table_name = a.table_name and b.table_type = 'TABLE' +where a.owner in ({0})", databaseIn); + var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql); + if (ds == null) return loc1; + + var loc6 = new List(); + var loc66 = new List(); + var loc6_1000 = new List(); + var loc66_1000 = new List(); + foreach (var row in ds) + { + var table_id = string.Concat(row[0]); + var schema = string.Concat(row[1]); + var table = string.Concat(row[2]); + var comment = string.Concat(row[3]); + var type = string.Concat(row[4]) == "VIEW" ? DbTableType.VIEW : DbTableType.TABLE; + if (database.Length == 1) + { + table_id = table_id.Substring(table_id.IndexOf('.') + 1); + schema = ""; + } + loc2.Add(table_id, new DbTableInfo { Id = table_id, Schema = schema, Name = table, Comment = comment, Type = type }); + loc3.Add(table_id, new Dictionary()); + switch (type) + { + case DbTableType.TABLE: + case DbTableType.VIEW: + loc6_1000.Add(table.Replace("'", "''")); + if (loc6_1000.Count >= 999) + { + loc6.Add(loc6_1000.ToArray()); + loc6_1000.Clear(); + } + break; + case DbTableType.StoreProcedure: + loc66_1000.Add(table.Replace("'", "''")); + if (loc66_1000.Count >= 999) + { + loc66.Add(loc66_1000.ToArray()); + loc66_1000.Clear(); + } + break; + } + } + if (loc6_1000.Count > 0) loc6.Add(loc6_1000.ToArray()); + if (loc66_1000.Count > 0) loc66.Add(loc66_1000.ToArray()); + + if (loc6.Count == 0) return loc1; + var loc8 = new StringBuilder().Append("("); + for (var loc8idx = 0; loc8idx < loc6.Count; loc8idx++) + { + if (loc8idx > 0) loc8.Append(" OR "); + loc8.Append("a.table_name in ("); + for (var loc8idx2 = 0; loc8idx2 < loc6[loc8idx].Length; loc8idx2++) + { + if (loc8idx2 > 0) loc8.Append(","); + loc8.Append($"'{loc6[loc8idx][loc8idx2]}'"); + } + loc8.Append(")"); + } + loc8.Append(")"); + + sql = string.Format(@" +select +a.owner || '.' || a.table_name, +a.column_name, +a.data_type, +a.data_length, +a.data_precision, +a.data_scale, +a.char_used, +case when a.nullable = 'N' then 0 else 1 end, +nvl((select 1 from user_sequences where upper(sequence_name)=upper(a.table_name||'_seq_'||a.column_name) and rownum < 2), 0), +b.comments, +a.data_default +from all_tab_cols a +left join all_col_comments b on b.owner = a.owner and b.table_name = a.table_name and b.column_name = a.column_name +where a.owner in ({1}) and {0} +", loc8, databaseIn); + ds = _orm.Ado.ExecuteArray(CommandType.Text, sql); + if (ds == null) return loc1; + + var ds2 = new List(); + foreach (var row in ds) + { + var ds2item = new object[9]; + ds2item[0] = row[0]; + ds2item[1] = row[1]; + ds2item[2] = Regex.Replace(string.Concat(row[2]), @"\(\d+\)", ""); + ds2item[4] = DamengCodeFirst.GetDamengSqlTypeFullName(new object[] { row[1], row[2], row[3], row[4], row[5], row[6] }); + ds2item[5] = string.Concat(row[7]) == "1"; + ds2item[6] = string.Concat(row[8]) == "1"; + ds2item[7] = string.Concat(row[9]); + ds2item[8] = string.Concat(row[10]); + ds2.Add(ds2item); + } + foreach (var row in ds2) + { + string table_id = string.Concat(row[0]); + string column = string.Concat(row[1]); + string type = string.Concat(row[2]); + //long max_length = long.Parse(string.Concat(row[3])); + string sqlType = string.Concat(row[4]); + var m_len = Regex.Match(sqlType, @"\w+\((\d+)"); + int max_length = m_len.Success ? int.Parse(m_len.Groups[1].Value) : -1; + bool is_nullable = string.Concat(row[5]) == "1"; + bool is_identity = string.Concat(row[6]) == "1"; + string comment = string.Concat(row[7]); + string defaultValue = string.Concat(row[8]); + if (max_length == 0) max_length = -1; + if (database.Length == 1) + { + table_id = table_id.Substring(table_id.IndexOf('.') + 1); + } + loc3[table_id].Add(column, new DbColumnInfo + { + Name = column, + MaxLength = max_length, + IsIdentity = is_identity, + IsNullable = is_nullable, + IsPrimary = false, + DbTypeText = type, + DbTypeTextFull = sqlType, + Table = loc2[table_id], + Coment = comment, + DefaultValue = defaultValue + }); + loc3[table_id][column].DbType = this.GetDbType(loc3[table_id][column]); + loc3[table_id][column].CsType = this.GetCsTypeInfo(loc3[table_id][column]); + } + + sql = string.Format(@" +select +a.table_owner || '.' || a.table_name, +c.column_name, +c.index_name, +case when a.uniqueness = 'UNIQUE' then 1 else 0 end, +case when exists(select 1 from all_constraints where constraint_name = a.index_name and constraint_type = 'P') then 1 else 0 end, +0, +case when c.descend = 'DESC' then 1 else 0 end, +c.column_position +from all_indexes a, +all_ind_columns c +where a.index_name = c.index_name +and a.table_owner = c.table_owner +and a.table_name = c.table_name +and a.table_owner in ({1}) and {0} +", loc8, databaseIn); + ds = _orm.Ado.ExecuteArray(CommandType.Text, sql); + if (ds == null) return loc1; + + var indexColumns = new Dictionary>(); + var uniqueColumns = new Dictionary>(); + foreach (var row in ds) + { + string table_id = string.Concat(row[0]); + string column = string.Concat(row[1]).Trim('"'); + string index_id = string.Concat(row[2]); + bool is_unique = string.Concat(row[3]) == "1"; + bool is_primary_key = string.Concat(row[4]) == "1"; + bool is_clustered = string.Concat(row[5]) == "1"; + bool is_desc = string.Concat(row[6]) == "1"; + if (database.Length == 1) + table_id = table_id.Substring(table_id.IndexOf('.') + 1); + if (loc3.ContainsKey(table_id) == false || loc3[table_id].ContainsKey(column) == false) continue; + var loc9 = loc3[table_id][column]; + if (loc9.IsPrimary == false && is_primary_key) loc9.IsPrimary = is_primary_key; + if (is_primary_key) continue; + + Dictionary loc10 = null; + DbIndexInfo loc11 = null; + if (!indexColumns.TryGetValue(table_id, out loc10)) + indexColumns.Add(table_id, loc10 = new Dictionary()); + if (!loc10.TryGetValue(index_id, out loc11)) + loc10.Add(index_id, loc11 = new DbIndexInfo()); + loc11.Columns.Add(new DbIndexColumnInfo { Column = loc9, IsDesc = is_desc }); + if (is_unique && !is_primary_key) + { + if (!uniqueColumns.TryGetValue(table_id, out loc10)) + uniqueColumns.Add(table_id, loc10 = new Dictionary()); + if (!loc10.TryGetValue(index_id, out loc11)) + loc10.Add(index_id, loc11 = new DbIndexInfo()); + loc11.Columns.Add(new DbIndexColumnInfo { Column = loc9, IsDesc = is_desc }); + } + } + foreach (string table_id in indexColumns.Keys) + { + foreach (var column in indexColumns[table_id]) + loc2[table_id].IndexesDict.Add(column.Key, column.Value); + } + foreach (string table_id in uniqueColumns.Keys) + { + foreach (var column in uniqueColumns[table_id]) + { + column.Value.Columns.Sort((c1, c2) => c1.Column.Name.CompareTo(c2.Column.Name)); + loc2[table_id].UniquesDict.Add(column.Key, column.Value); + } + } + + sql = string.Format(@" +select +a.owner || '.' || a.table_name, +c.column_name, +c.constraint_name, +b.owner || '.' || b.table_name, +1, +d.column_name + +-- a.owner 外键拥有者, +-- a.table_name 外键表, +-- c.column_name 外键列, +-- b.owner 主键拥有者, +-- b.table_name 主键表, +-- d.column_name 主键列, +-- c.constraint_name 外键名, +-- d.constraint_name 主键名 + +from +all_constraints a, +all_constraints b, +all_cons_columns c, --外键表 +all_cons_columns d --主键表 +where +a.r_constraint_name = b.constraint_name    +and a.constraint_type = 'R'    +and b.constraint_type = 'P'    +and a.r_owner = b.owner    +and a.constraint_name = c.constraint_name    +and b.constraint_name = d.constraint_name    +and a.owner = c.owner    +and a.table_name = c.table_name    +and b.owner = d.owner    +and b.table_name = d.table_name +and a.owner in ({1}) and {0} +", loc8, databaseIn); + ds = _orm.Ado.ExecuteArray(CommandType.Text, sql); + if (ds == null) return loc1; + + var fkColumns = new Dictionary>(); + foreach (var row in ds) + { + string table_id = string.Concat(row[0]); + string column = string.Concat(row[1]); + string fk_id = string.Concat(row[2]); + string ref_table_id = string.Concat(row[3]); + bool is_foreign_key = string.Concat(row[4]) == "1"; + string referenced_column = string.Concat(row[5]); + if (database.Length == 1) + { + table_id = table_id.Substring(table_id.IndexOf('.') + 1); + ref_table_id = ref_table_id.Substring(ref_table_id.IndexOf('.') + 1); + } + if (loc3.ContainsKey(table_id) == false || loc3[table_id].ContainsKey(column) == false) continue; + var loc9 = loc3[table_id][column]; + if (loc2.ContainsKey(ref_table_id) == false) continue; + var loc10 = loc2[ref_table_id]; + var loc11 = loc3[ref_table_id][referenced_column]; + + Dictionary loc12 = null; + DbForeignInfo loc13 = null; + if (!fkColumns.TryGetValue(table_id, out loc12)) + fkColumns.Add(table_id, loc12 = new Dictionary()); + if (!loc12.TryGetValue(fk_id, out loc13)) + loc12.Add(fk_id, loc13 = new DbForeignInfo { Table = loc2[table_id], ReferencedTable = loc10 }); + loc13.Columns.Add(loc9); + loc13.ReferencedColumns.Add(loc11); + } + foreach (var table_id in fkColumns.Keys) + foreach (var fk in fkColumns[table_id]) + loc2[table_id].ForeignsDict.Add(fk.Key, fk.Value); + + foreach (var table_id in loc3.Keys) + { + foreach (var loc5 in loc3[table_id].Values) + { + loc2[table_id].Columns.Add(loc5); + if (loc5.IsIdentity) loc2[table_id].Identitys.Add(loc5); + if (loc5.IsPrimary) loc2[table_id].Primarys.Add(loc5); + } + } + foreach (var loc4 in loc2.Values) + { + //if (loc4.Primarys.Count == 0 && loc4.UniquesDict.Count > 0) + //{ + // foreach (var loc5 in loc4.UniquesDict.First().Value.Columns) + // { + // loc5.Column.IsPrimary = true; + // loc4.Primarys.Add(loc5.Column); + // } + //} + loc4.Primarys.Sort((c1, c2) => c1.Name.CompareTo(c2.Name)); + loc4.Columns.Sort((c1, c2) => + { + int compare = c2.IsPrimary.CompareTo(c1.IsPrimary); + if (compare == 0) + { + bool b1 = loc4.ForeignsDict.Values.Where(fk => fk.Columns.Where(c3 => c3.Name == c1.Name).Any()).Any(); + bool b2 = loc4.ForeignsDict.Values.Where(fk => fk.Columns.Where(c3 => c3.Name == c2.Name).Any()).Any(); + compare = b2.CompareTo(b1); + } + if (compare == 0) compare = c1.Name.CompareTo(c2.Name); + return compare; + }); + loc1.Add(loc4); + } + loc1.Sort((t1, t2) => + { + var ret = t1.Schema.CompareTo(t2.Schema); + if (ret == 0) ret = t1.Name.CompareTo(t2.Name); + return ret; + }); + + loc2.Clear(); + loc3.Clear(); + return loc1; + } + + public List GetEnumsByDatabase(params string[] database) + { + return new List(); + } + } +} \ No newline at end of file diff --git a/Providers/FreeSql.Provider.Dameng/DamengExpression.cs b/Providers/FreeSql.Provider.Dameng/DamengExpression.cs new file mode 100644 index 00000000..3ac2d3fd --- /dev/null +++ b/Providers/FreeSql.Provider.Dameng/DamengExpression.cs @@ -0,0 +1,469 @@ +using FreeSql.Internal; +using FreeSql.Internal.Model; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; + +namespace FreeSql.Dameng +{ + class DamengExpression : CommonExpression + { + + public DamengExpression(CommonUtils common) : base(common) { } + + public override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (exp.NodeType) + { + case ExpressionType.Convert: + var operandExp = (exp as UnaryExpression)?.Operand; + var gentype = exp.Type.NullableTypeOrThis(); + if (gentype != operandExp.Type.NullableTypeOrThis()) + { + switch (exp.Type.NullableTypeOrThis().ToString()) + { + //case "System.Boolean": return $"({getExp(operandExp)} not in ('0','false'))"; + case "System.Byte": return $"cast({getExp(operandExp)} as number)"; + case "System.Char": return $"substr(to_char({getExp(operandExp)}), 1, 1)"; + case "System.DateTime": return $"to_timestamp({getExp(operandExp)},'YYYY-MM-DD HH24:MI:SS.FF6')"; + case "System.Decimal": return $"cast({getExp(operandExp)} as number)"; + case "System.Double": return $"cast({getExp(operandExp)} as number)"; + case "System.Int16": + case "System.Int32": + case "System.Int64": + case "System.SByte": return $"cast({getExp(operandExp)} as number)"; + case "System.Single": return $"cast({getExp(operandExp)} as number)"; + case "System.String": return $"to_char({getExp(operandExp)})"; + case "System.UInt16": + case "System.UInt32": + case "System.UInt64": return $"cast({getExp(operandExp)} as number)"; + case "System.Guid": + if (tsc.mapType == typeof(byte[])) return $"hextoraw({getExp(operandExp)})"; + return $"to_char({getExp(operandExp)})"; + } + } + break; + case ExpressionType.Call: + var callExp = exp as MethodCallExpression; + + switch (callExp.Method.Name) + { + case "Parse": + case "TryParse": + switch (callExp.Method.DeclaringType.NullableTypeOrThis().ToString()) + { + //case "System.Boolean": return $"({getExp(callExp.Arguments[0])} not in ('0','false'))"; + case "System.Byte": return $"cast({getExp(callExp.Arguments[0])} as number)"; + case "System.Char": return $"substr(to_char({getExp(callExp.Arguments[0])}), 1, 1)"; + case "System.DateTime": return $"to_timestamp({getExp(callExp.Arguments[0])},'YYYY-MM-DD HH24:MI:SS.FF6')"; + case "System.Decimal": return $"cast({getExp(callExp.Arguments[0])} as number)"; + case "System.Double": return $"cast({getExp(callExp.Arguments[0])} as number)"; + case "System.Int16": + case "System.Int32": + case "System.Int64": + case "System.SByte": return $"cast({getExp(callExp.Arguments[0])} as number)"; + case "System.Single": return $"cast({getExp(callExp.Arguments[0])} as number)"; + case "System.UInt16": + case "System.UInt32": + case "System.UInt64": return $"cast({getExp(callExp.Arguments[0])} as number)"; + case "System.Guid": + if (tsc.mapType == typeof(byte[])) return $"hextoraw({getExp(callExp.Arguments[0])})"; + return $"to_char({getExp(callExp.Arguments[0])})"; + } + return null; + case "NewGuid": + return null; + case "Next": + if (callExp.Object?.Type == typeof(Random)) return "cast(dbms_random.value*1000000000 as smallint)"; + return null; + case "NextDouble": + if (callExp.Object?.Type == typeof(Random)) return "dbms_random.value"; + return null; + case "Random": + if (callExp.Method.DeclaringType.IsNumberType()) return "dbms_random.value"; + return null; + case "ToString": + if (callExp.Object != null) return callExp.Arguments.Count == 0 ? $"to_char({getExp(callExp.Object)})" : null; + return null; + } + + var objExp = callExp.Object; + var objType = objExp?.Type; + if (objType?.FullName == "System.Byte[]") return null; + + var argIndex = 0; + if (objType == null && callExp.Method.DeclaringType == typeof(Enumerable)) + { + objExp = callExp.Arguments.FirstOrDefault(); + objType = objExp?.Type; + argIndex++; + } + if (objType == null) objType = callExp.Method.DeclaringType; + if (objType != null || objType.IsArrayOrList()) + { + if (argIndex >= callExp.Arguments.Count) break; + tsc.SetMapColumnTmp(null); + var args1 = getExp(callExp.Arguments[argIndex]); + var oldMapType = tsc.SetMapTypeReturnOld(tsc.mapTypeTmp); + var oldDbParams = tsc.SetDbParamsReturnOld(null); + var left = objExp == null ? null : getExp(objExp); + tsc.SetMapColumnTmp(null).SetMapTypeReturnOld(oldMapType); + tsc.SetDbParamsReturnOld(oldDbParams); + switch (callExp.Method.Name) + { + case "Contains": + //判断 in //在各大 Provider AdoProvider 中已约定,500元素分割, 3空格\r\n4空格 + return $"(({args1}) in {left.Replace(", \r\n \r\n", $") \r\n OR ({args1}) in (")})"; + } + } + break; + case ExpressionType.NewArrayInit: + var arrExp = exp as NewArrayExpression; + var arrSb = new StringBuilder(); + arrSb.Append("("); + for (var a = 0; a < arrExp.Expressions.Count; a++) + { + if (a > 0) arrSb.Append(","); + arrSb.Append(getExp(arrExp.Expressions[a])); + } + if (arrSb.Length == 1) arrSb.Append("NULL"); + return arrSb.Append(")").ToString(); + case ExpressionType.ListInit: + var listExp = exp as ListInitExpression; + var listSb = new StringBuilder(); + listSb.Append("("); + for (var a = 0; a < listExp.Initializers.Count; a++) + { + if (listExp.Initializers[a].Arguments.Any() == false) continue; + if (a > 0) listSb.Append(","); + listSb.Append(getExp(listExp.Initializers[a].Arguments.FirstOrDefault())); + } + if (listSb.Length == 1) listSb.Append("NULL"); + return listSb.Append(")").ToString(); + case ExpressionType.New: + var newExp = exp as NewExpression; + if (typeof(IList).IsAssignableFrom(newExp.Type)) + { + if (newExp.Arguments.Count == 0) return "(NULL)"; + if (typeof(IEnumerable).IsAssignableFrom(newExp.Arguments[0].Type) == false) return "(NULL)"; + return getExp(newExp.Arguments[0]); + } + return null; + } + return null; + } + + public override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc) + { + if (exp.Expression == null) + { + switch (exp.Member.Name) + { + case "Empty": return "''"; + } + return null; + } + var left = ExpressionLambdaToSql(exp.Expression, tsc); + switch (exp.Member.Name) + { + case "Length": return $"length({left})"; + } + return null; + } + public override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc) + { + if (exp.Expression == null) + { + switch (exp.Member.Name) + { + case "Now": return _common.Now; + case "UtcNow": return _common.NowUtc; + case "Today": return "trunc(systimestamp)"; + case "MinValue": return "to_timestamp('0001-01-01 00:00:00','YYYY-MM-DD HH24:MI:SS.FF6')"; + case "MaxValue": return "to_timestamp('9999-12-31 23:59:59','YYYY-MM-DD HH24:MI:SS.FF6')"; + } + return null; + } + var left = ExpressionLambdaToSql(exp.Expression, tsc); + switch (exp.Member.Name) + { + case "Date": return $"trunc({left})"; + case "TimeOfDay": return $"(cast({left} as timestamp with time zone)-trunc({left}))"; + case "DayOfWeek": return $"case when to_char({left})='7' then 0 else cast(to_char({left}) as number) end"; + case "Day": return $"cast(to_char({left},'DD') as number)"; + case "DayOfYear": return $"cast(to_char({left},'DDD') as number)"; + case "Month": return $"cast(to_char({left},'MM') as number)"; + case "Year": return $"cast(to_char({left},'YYYY') as number)"; + case "Hour": return $"cast(to_char({left},'HH24') as number)"; + case "Minute": return $"cast(to_char({left},'MI') as number)"; + case "Second": return $"cast(to_char({left},'SS') as number)"; + case "Millisecond": return $"cast(to_char({left},'FF3') as number)"; + case "Ticks": return $"cast(to_char({left},'FF7') as number)"; + } + return null; + } + public override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc) + { + if (exp.Expression == null) + { + switch (exp.Member.Name) + { + case "Zero": return "numtodsinterval(0,'second')"; + case "MinValue": return "numtodsinterval(-233720368.5477580,'second')"; + case "MaxValue": return "numtodsinterval(233720368.5477580,'second')"; + } + return null; + } + var left = ExpressionLambdaToSql(exp.Expression, tsc); + switch (exp.Member.Name) + { + case "Days": return $"extract(day from {left})"; + case "Hours": return $"extract(hour from {left})"; + case "Milliseconds": return $"cast(substr(extract(second from {left})-floor(extract(second from {left})),2,3) as number)"; + case "Minutes": return $"extract(minute from {left})"; + case "Seconds": return $"floor(extract(second from {left}))"; + case "Ticks": return $"(extract(day from {left})*86400+extract(hour from {left})*3600+extract(minute from {left})*60+extract(second from {left}))*10000000"; + case "TotalDays": return $"extract(day from {left})"; + case "TotalHours": return $"(extract(day from {left})*24+extract(hour from {left}))"; + case "TotalMilliseconds": return $"(extract(day from {left})*86400+extract(hour from {left})*3600+extract(minute from {left})*60+extract(second from {left}))*1000"; + case "TotalMinutes": return $"(extract(day from {left})*1440+extract(hour from {left})*60+extract(minute from {left}))"; + case "TotalSeconds": return $"(extract(day from {left})*86400+extract(hour from {left})*3600+extract(minute from {left})*60+extract(second from {left}))"; + } + return null; + } + + public override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + if (exp.Object == null) + { + switch (exp.Method.Name) + { + case "IsNullOrEmpty": + var arg1 = getExp(exp.Arguments[0]); + return $"({arg1} is null or {arg1} = '')"; + case "IsNullOrWhiteSpace": + var arg2 = getExp(exp.Arguments[0]); + return $"({arg2} is null or {arg2} = '' or ltrim({arg2}) = '')"; + case "Concat": + return _common.StringConcat(exp.Arguments.Select(a => getExp(a)).ToArray(), null); + } + } + else + { + var left = getExp(exp.Object); + switch (exp.Method.Name) + { + case "StartsWith": + case "EndsWith": + case "Contains": + var args0Value = getExp(exp.Arguments[0]); + if (args0Value == "NULL") return $"({left}) IS NULL"; + if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(to_char({args0Value})||'%')")}"; + if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%'||to_char({args0Value}))")}"; + if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}"; + return $"({left}) LIKE ('%'||to_char({args0Value})||'%')"; + case "ToLower": return $"lower({left})"; + case "ToUpper": return $"upper({left})"; + case "Substring": + var substrArgs1 = getExp(exp.Arguments[0]); + if (long.TryParse(substrArgs1, out var testtrylng1)) substrArgs1 = (testtrylng1 + 1).ToString(); + else substrArgs1 += "+1"; + if (exp.Arguments.Count == 1) return $"substr({left}, {substrArgs1})"; + return $"substr({left}, {substrArgs1}, {getExp(exp.Arguments[1])})"; + case "IndexOf": + var indexOfFindStr = getExp(exp.Arguments[0]); + if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") + { + var locateArgs1 = getExp(exp.Arguments[1]); + if (long.TryParse(locateArgs1, out var testtrylng2)) locateArgs1 = (testtrylng2 + 1).ToString(); + else locateArgs1 += "+1"; + return $"(instr({left}, {indexOfFindStr}, {locateArgs1}, 1)-1)"; + } + return $"(instr({left}, {indexOfFindStr}, 1, 1))-1"; + case "PadLeft": + if (exp.Arguments.Count == 1) return $"lpad({left}, {getExp(exp.Arguments[0])}, ' ')"; + return $"lpad({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})"; + case "PadRight": + if (exp.Arguments.Count == 1) return $"rpad({left}, {getExp(exp.Arguments[0])}, ' ')"; + return $"rpad({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})"; + case "Trim": + case "TrimStart": + case "TrimEnd": + if (exp.Arguments.Count == 0) + { + if (exp.Method.Name == "Trim") return $"trim({left})"; + if (exp.Method.Name == "TrimStart") return $"ltrim({left})"; + if (exp.Method.Name == "TrimEnd") return $"rtrim({left})"; + } + foreach (var argsTrim02 in exp.Arguments) + { + var argsTrim01s = new[] { argsTrim02 }; + if (argsTrim02.NodeType == ExpressionType.NewArrayInit) + { + var arritem = argsTrim02 as NewArrayExpression; + argsTrim01s = arritem.Expressions.ToArray(); + } + foreach (var argsTrim01 in argsTrim01s) + { + if (exp.Method.Name == "Trim") left = $"trim(both {getExp(argsTrim01)} from {left})"; + if (exp.Method.Name == "TrimStart") left = $"ltrim({left},{getExp(argsTrim01)})"; + if (exp.Method.Name == "TrimEnd") left = $"rtrim({left},{getExp(argsTrim01)})"; + } + } + return left; + case "Replace": return $"replace({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})"; + case "CompareTo": return $"case when {left} = {getExp(exp.Arguments[0])} then 0 when {left} > {getExp(exp.Arguments[0])} then 1 else -1 end"; + case "Equals": return $"({left} = {getExp(exp.Arguments[0])})"; + } + } + return null; + } + public override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + switch (exp.Method.Name) + { + case "Abs": return $"abs({getExp(exp.Arguments[0])})"; + case "Sign": return $"sign({getExp(exp.Arguments[0])})"; + case "Floor": return $"floor({getExp(exp.Arguments[0])})"; + case "Ceiling": return $"ceil({getExp(exp.Arguments[0])})"; + case "Round": + if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"round({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})"; + return $"round({getExp(exp.Arguments[0])})"; + case "Exp": return $"exp({getExp(exp.Arguments[0])})"; + case "Log": + if (exp.Arguments.Count > 1) return $"log({getExp(exp.Arguments[1])},{getExp(exp.Arguments[0])})"; + return $"log(2.7182818284590451,{getExp(exp.Arguments[0])})"; + case "Log10": return $"log(10,{getExp(exp.Arguments[0])})"; + case "Pow": return $"power({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})"; + case "Sqrt": return $"sqrt({getExp(exp.Arguments[0])})"; + case "Cos": return $"cos({getExp(exp.Arguments[0])})"; + case "Sin": return $"sin({getExp(exp.Arguments[0])})"; + case "Tan": return $"tan({getExp(exp.Arguments[0])})"; + case "Acos": return $"acos({getExp(exp.Arguments[0])})"; + case "Asin": return $"asin({getExp(exp.Arguments[0])})"; + case "Atan": return $"atan({getExp(exp.Arguments[0])})"; + //case "Atan2": return $"atan2({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})"; + case "Truncate": return $"trunc({getExp(exp.Arguments[0])}, 0)"; + } + return null; + } + public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + if (exp.Object == null) + { + switch (exp.Method.Name) + { + case "Compare": return $"extract(day from ({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])})))"; + case "DaysInMonth": return $"cast(to_char(last_day(({getExp(exp.Arguments[0])})||'-'||({getExp(exp.Arguments[1])})||'-01'),'DD') as number)"; + case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})"; + + case "IsLeapYear": + var isLeapYearArgs1 = getExp(exp.Arguments[0]); + return $"(mod({isLeapYearArgs1},4)=0 AND mod({isLeapYearArgs1},100)<>0 OR mod({isLeapYearArgs1},400)=0)"; + + case "Parse": return $"to_timestamp({getExp(exp.Arguments[0])},'YYYY-MM-DD HH24:MI:SS.FF6')"; + case "ParseExact": + case "TryParse": + case "TryParseExact": return $"to_timestamp({getExp(exp.Arguments[0])},'YYYY-MM-DD HH24:MI:SS.FF6')"; + } + } + else + { + var left = getExp(exp.Object); + var args1 = exp.Arguments.Count == 0 ? null : getExp(exp.Arguments[0]); + switch (exp.Method.Name) + { + case "Add": return $"({left}+{args1})"; + case "AddDays": return $"({left}+{args1})"; + case "AddHours": return $"({left}+({args1})/24)"; + case "AddMilliseconds": return $"({left}+({args1})/86400000)"; + case "AddMinutes": return $"({left}+({args1})/1440)"; + case "AddMonths": return $"add_months({left},{args1})"; + case "AddSeconds": return $"({left}+({args1})/86400)"; + case "AddTicks": return $"({left}+({args1})/864000000000)"; + case "AddYears": return $"add_months({left},({args1})*12)"; + case "Subtract": + switch ((exp.Arguments[0].Type.IsNullableType() ? exp.Arguments[0].Type.GetGenericArguments().FirstOrDefault() : exp.Arguments[0].Type).FullName) + { + case "System.DateTime": return $"(cast({left} as timestamp with time zone)-{args1})"; + case "System.TimeSpan": return $"({left}-{args1})"; + } + break; + case "Equals": return $"({left} = {args1})"; + case "CompareTo": return $"extract(day from ({left}-({args1})))"; + case "ToString": return exp.Arguments.Count == 0 ? $"to_char({left},'YYYY-MM-DD HH24:MI:SS.FF6')" : null; + } + } + return null; + } + public override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + if (exp.Object == null) + { + switch (exp.Method.Name) + { + case "Compare": return $"extract(day from ({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])})))"; + case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})"; + case "FromDays": return $"numtodsinterval(({getExp(exp.Arguments[0])})*{(long)60 * 60 * 24},'second')"; + case "FromHours": return $"numtodsinterval(({getExp(exp.Arguments[0])})*{(long)60 * 60},'second')"; + case "FromMilliseconds": return $"numtodsinterval(({getExp(exp.Arguments[0])})/1000,'second')"; + case "FromMinutes": return $"numtodsinterval(({getExp(exp.Arguments[0])})*60,'second')"; + case "FromSeconds": return $"numtodsinterval(({getExp(exp.Arguments[0])}),'second')"; + case "FromTicks": return $"numtodsinterval(({getExp(exp.Arguments[0])})/10000000,'second')"; + case "Parse": return $"cast({getExp(exp.Arguments[0])} as interval day(9) to second(6))"; + case "ParseExact": + case "TryParse": + case "TryParseExact": return $"cast({getExp(exp.Arguments[0])} as interval day(9) to second(6))"; + } + } + else + { + var left = getExp(exp.Object); + var args1 = exp.Arguments.Count == 0 ? null : getExp(exp.Arguments[0]); + switch (exp.Method.Name) + { + case "Add": return $"({left}+{args1})"; + case "Subtract": return $"({left}-({args1}))"; + case "Equals": return $"({left} = {args1})"; + case "CompareTo": return $"extract(day from ({left}-({args1})))"; + case "ToString": return $"to_char({left})"; + } + } + return null; + } + public override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, ExpTSC tsc) + { + Func getExp = exparg => ExpressionLambdaToSql(exparg, tsc); + if (exp.Object == null) + { + switch (exp.Method.Name) + { + //case "ToBoolean": return $"({getExp(exp.Arguments[0])} not in ('0','false'))"; + case "ToByte": return $"cast({getExp(exp.Arguments[0])} as number)"; + case "ToChar": return $"substr(to_char({getExp(exp.Arguments[0])}), 1, 1)"; + case "ToDateTime": return $"to_timestamp({getExp(exp.Arguments[0])},'YYYY-MM-DD HH24:MI:SS.FF6')"; + case "ToDecimal": return $"cast({getExp(exp.Arguments[0])} as number)"; + case "ToDouble": return $"cast({getExp(exp.Arguments[0])} as number)"; + case "ToInt16": + case "ToInt32": + case "ToInt64": + case "ToSByte": return $"cast({getExp(exp.Arguments[0])} as number)"; + case "ToSingle": return $"cast({getExp(exp.Arguments[0])} as number)"; + case "ToString": return $"to_char({getExp(exp.Arguments[0])})"; + case "ToUInt16": + case "ToUInt32": + case "ToUInt64": return $"cast({getExp(exp.Arguments[0])} as number)"; + } + } + return null; + } + } +} diff --git a/Providers/FreeSql.Provider.Dameng/DamengExtensions.cs b/Providers/FreeSql.Provider.Dameng/DamengExtensions.cs new file mode 100644 index 00000000..a44e710b --- /dev/null +++ b/Providers/FreeSql.Provider.Dameng/DamengExtensions.cs @@ -0,0 +1,12 @@ +public static partial class FreeSqlDamengGlobalExtensions +{ + + /// + /// 特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换 + /// + /// + /// + /// + public static string FormatDameng(this string that, params object[] args) => _damengAdo.Addslashes(that, args); + static FreeSql.Dameng.DamengAdo _damengAdo = new FreeSql.Dameng.DamengAdo(); +} diff --git a/Providers/FreeSql.Provider.Dameng/DamengProvider.cs b/Providers/FreeSql.Provider.Dameng/DamengProvider.cs new file mode 100644 index 00000000..e8166066 --- /dev/null +++ b/Providers/FreeSql.Provider.Dameng/DamengProvider.cs @@ -0,0 +1,61 @@ +using FreeSql.Dameng.Curd; +using FreeSql.Internal; +using FreeSql.Internal.CommonProvider; +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Threading; + +namespace FreeSql.Dameng +{ + + public class DamengProvider : IFreeSql + { + + public ISelect Select() where T1 : class => new DamengSelect(this, this.InternalCommonUtils, this.InternalCommonExpression, null); + public ISelect Select(object dywhere) where T1 : class => new DamengSelect(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere); + public IInsert Insert() where T1 : class => new DamengInsert(this, this.InternalCommonUtils, this.InternalCommonExpression); + public IInsert Insert(T1 source) where T1 : class => this.Insert().AppendData(source); + public IInsert Insert(T1[] source) where T1 : class => this.Insert().AppendData(source); + public IInsert Insert(List source) where T1 : class => this.Insert().AppendData(source); + public IInsert Insert(IEnumerable source) where T1 : class => this.Insert().AppendData(source); + public IUpdate Update() where T1 : class => new DamengUpdate(this, this.InternalCommonUtils, this.InternalCommonExpression, null); + public IUpdate Update(object dywhere) where T1 : class => new DamengUpdate(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere); + public IDelete Delete() where T1 : class => new DamengDelete(this, this.InternalCommonUtils, this.InternalCommonExpression, null); + public IDelete Delete(object dywhere) where T1 : class => new DamengDelete(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere); + + public IAdo Ado { get; } + public IAop Aop { get; } + public ICodeFirst CodeFirst { get; } + public IDbFirst DbFirst { get; } + public DamengProvider(string masterConnectionString, string[] slaveConnectionString, Func connectionFactory = null) + { + this.InternalCommonUtils = new DamengUtils(this); + this.InternalCommonExpression = new DamengExpression(this.InternalCommonUtils); + + this.Ado = new DamengAdo(this.InternalCommonUtils, masterConnectionString, slaveConnectionString, connectionFactory); + this.Aop = new AopProvider(); + + this.DbFirst = new DamengDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); + this.CodeFirst = new DamengCodeFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); + } + + internal CommonUtils InternalCommonUtils { get; } + internal CommonExpression InternalCommonExpression { get; } + + public void Transaction(Action handler) => Ado.Transaction(handler); + public void Transaction(TimeSpan timeout, Action handler) => Ado.Transaction(timeout, handler); + public void Transaction(IsolationLevel isolationLevel, TimeSpan timeout, Action handler) => Ado.Transaction(isolationLevel, timeout, handler); + + public GlobalFilter GlobalFilter { get; } = new GlobalFilter(); + + ~DamengProvider() => this.Dispose(); + int _disposeCounter; + public void Dispose() + { + if (Interlocked.Increment(ref _disposeCounter) != 1) return; + (this.Ado as AdoProvider)?.Dispose(); + } + } +} diff --git a/Providers/FreeSql.Provider.Dameng/DamengUtils.cs b/Providers/FreeSql.Provider.Dameng/DamengUtils.cs new file mode 100644 index 00000000..e6c67977 --- /dev/null +++ b/Providers/FreeSql.Provider.Dameng/DamengUtils.cs @@ -0,0 +1,102 @@ +using Dm; +using FreeSql.Internal; +using FreeSql.Internal.Model; +using System; +using System.Collections.Generic; +using System.Data.Common; + +namespace FreeSql.Dameng +{ + + class DamengUtils : CommonUtils + { + public DamengUtils(IFreeSql orm) : base(orm) + { + } + + public override DbParameter AppendParamter(List _params, string parameterName, ColumnInfo col, Type type, object value) + { + if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}"; + var dbtype = (DmDbType)_orm.CodeFirst.GetDbInfo(type)?.type; + switch (dbtype) + { + case DmDbType.Bit: + if (value == null) value = null; + else value = (bool)value == true ? 1 : 0; + dbtype = DmDbType.Int32; + break; + + case DmDbType.Char: + case DmDbType.VarChar: + case DmDbType.Text: + value = string.Concat(value); + break; + } + var ret = new DmParameter { ParameterName = QuoteParamterName(parameterName), DmSqlType = dbtype, Value = value }; + _params?.Add(ret); + return ret; + } + + public override DbParameter[] GetDbParamtersByObject(string sql, object obj) => + Utils.GetDbParamtersByObject(sql, obj, null, (name, type, value) => + { + var dbtype = (DmDbType)_orm.CodeFirst.GetDbInfo(type)?.type; + switch (dbtype) + { + case DmDbType.Bit: + if (value == null) value = null; + else value = (bool)value == true ? 1 : 0; + dbtype = DmDbType.Int32; + break; + + case DmDbType.Char: + case DmDbType.VarChar: + case DmDbType.Text: + value = string.Concat(value); + break; + } + var ret = new DmParameter { ParameterName = $":{name}", DmSqlType = dbtype, Value = value }; + return ret; + }); + + public override string FormatSql(string sql, params object[] args) => sql?.FormatDameng(args); + public override string QuoteSqlName(params string[] name) + { + if (name.Length == 1) + { + var nametrim = name[0].Trim(); + if (nametrim.StartsWith("(") && nametrim.EndsWith(")")) + return nametrim; //原生SQL + if (nametrim.StartsWith("\"") && nametrim.EndsWith("\"")) + return nametrim; + return $"\"{nametrim.Replace(".", "\".\"")}\""; + } + return $"\"{string.Join("\".\"", name)}\""; + } + public override string TrimQuoteSqlName(string name) + { + var nametrim = name.Trim(); + if (nametrim.StartsWith("(") && nametrim.EndsWith(")")) + return nametrim; //原生SQL + return $"{nametrim.Trim('"').Replace("\".\"", ".").Replace(".\"", ".")}"; + } + public override string[] SplitTableName(string name) => GetSplitTableNames(name, '"', '"', 2); + public override string QuoteParamterName(string name) => $":{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}"; + public override string IsNull(string sql, object value) => $"nvl({sql}, {value})"; + public override string StringConcat(string[] objs, Type[] types) => $"{string.Join(" || ", objs)}"; + public override string Mod(string left, string right, Type leftType, Type rightType) => $"mod({left}, {right})"; + public override string Div(string left, string right, Type leftType, Type rightType) => $"trunc({left} / {right})"; + public override string Now => "systimestamp"; + public override string NowUtc => "getutcdate"; + + public override string QuoteWriteParamter(Type type, string paramterName) => paramterName; + public override string QuoteReadColumn(Type type, Type mapType, string columnName) => columnName; + + public override string GetNoneParamaterSqlValue(List specialParams, Type type, object value) + { + if (value == null) return "NULL"; + if (type == typeof(byte[])) return $"hextoraw('{CommonUtils.BytesSqlRaw(value as byte[])}')"; + return FormatSql("{0}", value, 1); + } + } +} diff --git a/Providers/FreeSql.Provider.Dameng/FreeSql.Provider.Dameng.csproj b/Providers/FreeSql.Provider.Dameng/FreeSql.Provider.Dameng.csproj new file mode 100644 index 00000000..35e83d0f --- /dev/null +++ b/Providers/FreeSql.Provider.Dameng/FreeSql.Provider.Dameng.csproj @@ -0,0 +1,50 @@ + + + + netstandard2.0;net45;net40 + 1.4.0-preview0414 + true + YeXiangQin + FreeSql 数据库实现,基于 达梦数据库 Ado.net (DmProvider) + https://github.com/2881099/FreeSql + https://github.com/2881099/FreeSql + git + MIT + FreeSql;ORM;DM8;Dameng;达梦 + $(AssemblyName) + logo.png + $(AssemblyName) + true + true + + + + + + + + + Always + + + + + + + + + + lib\DmProvider\netstandard2.0\DmProvider.dll + false + + + + + ns20;netstandard20 + + + net40 + + + + diff --git a/Providers/FreeSql.Provider.Dameng/lib/DmProvider/DmProvider.1.1.0.nuspec b/Providers/FreeSql.Provider.Dameng/lib/DmProvider/DmProvider.1.1.0.nuspec new file mode 100644 index 00000000..52b9ed57 --- /dev/null +++ b/Providers/FreeSql.Provider.Dameng/lib/DmProvider/DmProvider.1.1.0.nuspec @@ -0,0 +1,21 @@ + + + + DmProvider + 1.1.0 + DM + DM + false + DM .NET PROVIDER + Copy right(C) DM + + + + + + + + + + + \ No newline at end of file diff --git a/Providers/FreeSql.Provider.Dameng/lib/DmProvider/net20/DmProvider.dll b/Providers/FreeSql.Provider.Dameng/lib/DmProvider/net20/DmProvider.dll new file mode 100644 index 0000000000000000000000000000000000000000..865630a9d38d70bdafdbcc356fe7bfb579b8b735 GIT binary patch literal 379904 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 -MQLa*z>B8_WY+}>-^f#3`Ryer}5HgY&e z;B2yRUqQ%U8Vwtr#-w*Dk;Ma2-YIiHeR*7z0Wx?hreMj5m^K^k_5^-98tLq8q`Rxp z!EbkCGK}8SnCuCUR`eCqjY*uM2}6r+V=D4w8dJn=PUEw|j<*p%rB|5kQtIlbpi}fo zU`u)I>K8b25PkbAaPw;F+xf9oG*fd=k|qYXR=y53FSbV4a{N(nr!Rkp`iR09Jej_N z_8kLXeOt`akn}L1gpR=(D&)^G+HQQDlI{Wq-+{X=rGf3~y`@CkS{zm~D≫gvYEb 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 bp5v$;{xAI)mpNbRoTbM9|G)p|DDb}lhwwib literal 0 HcmV?d00001 diff --git a/Providers/FreeSql.Provider.Dameng/lib/DmProvider/net20/en/DmProvider.resources.dll b/Providers/FreeSql.Provider.Dameng/lib/DmProvider/net20/en/DmProvider.resources.dll new file mode 100644 index 0000000000000000000000000000000000000000..c6ba0ef66b5ebd8d3dd97cc05c45a7a28a220672 GIT binary patch literal 20480 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 literal 0 HcmV?d00001 diff --git a/Providers/FreeSql.Provider.Dameng/lib/DmProvider/net20/zh-CN/DmProvider.resources.dll b/Providers/FreeSql.Provider.Dameng/lib/DmProvider/net20/zh-CN/DmProvider.resources.dll new file mode 100644 index 0000000000000000000000000000000000000000..66bb2bee789aba2fb726a434d994c3881921afb6 GIT binary patch literal 21504 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 z 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

Ff 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

ac`dgWe)!;#hfP-``v%~OJj~w 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 literal 0 HcmV?d00001 diff --git a/Providers/FreeSql.Provider.Dameng/lib/DmProvider/netstandard2.0/en/DmProvider.resources.dll b/Providers/FreeSql.Provider.Dameng/lib/DmProvider/netstandard2.0/en/DmProvider.resources.dll new file mode 100644 index 0000000000000000000000000000000000000000..93f83654f5fc872c7627e2318ab0d19400830153 GIT binary patch literal 20480 zcmeHPd6*Q{wZ8=jBg_mi?8`tQgMdOa8*2b(rn?7PXYFoAA?l>2yLzUjH>#><7-N(u z#sxRrHNJ$XXiP+7J_D%4xWpyyON@RJBZ*6%iHR{rYASE>G!_;^SO3G>);2Xc;Y9f7gv~8L$Ju*aUt)LdZ=GBtQQ=gd^Gm2N>p6cRr!gfBW0K zq$YfJg73+6vIBD`MGXAxVXSyyTOrpnV?|kbMYyKvSRa?6ZZ~l8_68he0Chs{?2pXY zH(Z*oh0w@l+kq3B=!t-=PaVwV($rWIh+Nh^=pu%ZC61wK{@cpws z{Qj69hhDyU=~>Mcy?aMLbNZxXBjM8PUVmoh@f$|(Ek1HX_s7#+4|^`3QufdnhwnSE z?ygIh-4NPSIWye#tGY3V-&i>Pl~T9&@aAcU5^q-QoZ9`?&n{L=zj^e}_J6r&^Ue#7 zT>0KvBgg#H7dZ%7pL^xLS4`Bgoc)t*es$Es@>nn32}hbqO_XXi98}+?MW&MMEd4{lVl`HL5a|cT&jA&f7Mh~b4+2thwecI|h^uOf#*UlUH#xKv`zxTHn-rKQx*Y$7S zx@+q@lP>YaM_xMZ+{2f?-TCv&_H29hvQ_QAD~d1Me#M7JE!^$u`{K&mULA4OlJudg zuF{^l$~QKB_1)7)Usn`aecg_^-Pg}O@tzx>-}=ONM=o#skGj%Hd&eI)>y9tp+WuqD zqMz;y-E+%5zBS+9-*Cmf`&~zQ50u~k{K2PAaNpPY%8%|lrFGGx&Cgu>=%c64d2;EF z@~40JtNWjA4XuCiDfxjHHy`-pOYY>jmwRfy{qi;U?|%8heHXp4|EBJ@_0Ya|PTX{@iGRLu!)KqKb=!NNPc8Y&=S!Zr z@XJfu9{=*!t;^W)>;F0G_n()IIrQ1CqK$vvQ*`&`hl`#+r*G_%34!AD-t{HFdw=GX zi_dv}>RB(}I{hzC?42Q>a@x#McU8|`^I@ud_O2Vt+0$>%d-&-GD&Bki=M{h1{6@vu zz79B+m~+Xe`4u^z29{0-uUdY8Icc{jsNN2 zmmQqZQhC7{dzVif^ZnIl-@biKP20?MpY#XUf3NAL_17Kv?1X=vT2Xh=v}JXVjP0sF z?ZJyqs(U!xw08fFmT$X8x1S4m2=FN22;eP%{J`k;V*qcxJf?l``$g?n{9|srzhqwf z$B)c!zxl1NweRR|YTpUC0I&-nAJyDG53m4mEMOtP1y}~C+tJ+K0B{35056~sumN!7 zbI_ExwlCfhXg?0H1mFTJ1GE+g+xL8wXulb73*eD+lI=UMPqp7Nds}!0n&1< zeKepLPy*-zgaHviHy{r90pMo9vU~d4WAE;5|3%l~z}3}{2PZuHX>bx?GGGc|8ele{ z9FPKR0~mlbpcl{waDD5Q&HFBUeaoTbe}4V1Mem>f&;u2rf30Zm-nZh@=%mM{oncgj z&e-?2ooA%4{QQhZzwusT-5QpBX3;sRi+Haw%oqkqu@BL>T zczpf0UVSTg_6KtXK4RPx$H#%`F8 zSO$1=I%B=)kIe$!c*agDVXPW$Url3d`7w;$PuG(et3v;UGZ|CnGPW1zZQ$_+0_-!B z8M}54WA6g)#+cV)oJ-3XyKOdONwoa~ZTC%O>=f`jZ3bhjDZqn(UrUVb1AGV230MU<2JN5Y`%wnn04CymA--DxX~0c@cYs5mZ;xc`hk#g?-=Cnbd=zYe>oI^$fU^Miq0Ixh60j9;1n?BvZvh+z zT?G>BrO?kZ=;a}t{}FH!Km*(WC>;wQ1k8orKgIWXfKvf40)7NI0G%EKyF5&G15OFP zFNe+*_{zulUOJz#JyGL0iez42LFWs^mkfhAISFUmt!C}RbF0RnN+D<~n4TZ4 zh8wGr?aGfGsWST_}dR?YSek5+|% z^H?Eh$biG6QTX~}A!ya?zw)D53LcAkZb%PV&8&Y5@}X^Hn@yW8F9fZMxeGz7VP7u< zt(K(d* zBHYgPLz*E%p)=BB0@_m9!yt7HP8vbC0fHWok=gpN$xK5HpMzx1;3O%aX&{<~-R$h4 zQ2H?8Y9I`u6)}{KL4{$~0(FSV3HKt0=m#>9(6mA<203Z;AV`PsAK}0;t`iMM9a3u` zCr?s9wsvsoNpa-qgE?RTRw2h%`Nn<-rP>Uf-n%ECsMeSysFUocAREGK?U8g?CB(LZ z*kF%?UUy_UN0bk-xTIk@S zHe!@k{2+5K2x^BSAjSE(igF2egRmi&(92HYO7TGUPLS5)n(l50HTf_m&6#G{3<$DY z!DbL;S!_rJL$hh)Q|W|VXaGNZ5X{!+%4FNR6Jxf5VGw>m#Kf9(O>zby_eORYEb4Mu z__^3V96NwY;*(r%jO+(FS)C?n-Msk}OezayV%eq?H>Fk-PSk)ATObQL@NAG4EOY=w zG!?_YJAv$2Jt6Q(m|Qn-aRO-R#TjKG zN(2V?ou@(Q&{QFWEnr1){=I>-q3}z!0F506(417v&tM~QC(|(-C#n^WlbDae%7HvU zD7(h+fp0xWOTvJ5do#`{E-wRdUAEqwIl(HCNCmwRl&YyP^ht@8ss~EY{cKAiOxz%* zc&~y18AaHz0kTEW6J~v2;s}``bj1Nw{m_glH+w-S%Dx+cKEQ@)bWwh?c+=c-9qlI| zboip>bEF=crI^*g@ty_QnruZ`WRyr1u1gJ?j$w3h-H%z4im0Xxv$sL+uxNH&Cu$8_ zzsKN4vjbU$A}DkAJLW^WG}vk&I~K{nQjm%tVeAuu>hKhSs(~+Yrv;*7#gZRJxzedP ziQtSZbT)_`3XgDA_n}+kCQSfoFad7^VMVs)y1Cqq$jlyifjz=I17{)-gBU?9au-(t zDRmld&pSdjIjE?qsW#C-Ku7X7n|~#U9J$Zw)eT_K4UwoWqAH2JJ;+s~vPM2vYBN|H z*toLi<77i_L`7p95?M<>RXB+?;`tz{%QuSc?X;H3Z9Nd1ypQTm;lAGmlN>eKe&&Xl z){^Pq^QAKWeh@h_igSKq%Z7rOD~Z0zdz>ozEm$~`;!rGdNk0Rr!<`3`c4f3W8NcVO z9a=@Cj&1}C)-BBoPSVuxjqaR}&n)YUqykS~CNBLX z#mcQ7ELC*nA0dFnOFp5pGl7`LT7=jGGzv*V2?PCd7Z~L6jsS?aao?j|uF4(*dY-5@ z5S^6pI!GL8%BigY_}lC5gZ%TcqKOZFE*3{GSA^{e5`Lx4<3tt%%l_FBdp=0>I1yEq zRD=0=^$^3k6+hR5(6KLb&X8)Q7zioYi-dC;2prLiZY6Xhevqwb-|WR$qJS}g>hLwH zbwrSffWVH-7Xk5@>?lPAkq9D5E&!D+-R$Op{6s-n51v$bi90TIzCV{AW&B1ANv>ec z{Y9Y7aSki0XWJz20A+SI3KfM$)*Kh(S93?LB`Q{X!HXExj3}*hR~Gk(R)K5)Us0At z%&BYvg2T5{Pzl}D>cdQ_8gT)lJXDf+F`zqQ0af*6I;zY>@kLRdgdpD&3*sCQIqc&k zqDolY#=AB@cS54r?VQ2E+!!FZD6Sk>)XAT5fEn~V5bpu$`4V;2=M2cp#!=o6G0108!#?)qV08AX=m=-au zCc1M?3wyYEzX}F^rxZ>GK`{KEt8)~dZF1;GhdktJ*&EmV7Fh`vj>w8>NiM+&J1dkH9x&_XeTYDAGv!|WX(IF@}jg0&Z-xbYbf9XcQ> z#Xf~@fsjwQFf5fBN8=$Rhmq))g(PknQh{m*L#r&L?KNc!9sRTwq4+)Luo^m^>hf2 zhwIXqK1EAJ6W!8ucUsevnw(6jnquH2luShM__rZV^hEK{cp{;O3^}4iV`^9`Z`st; zB!^!3UQL6H7+6d8Nu{kRju7fm65SB5y57K3@F_z!lJs6iNR9Dn zVcLB?7#E{rP#urElhm4ur`{7%aUi6i3(7ITVRAs}RpkgFdjc)iv?p0YLC(0M^~+n; zeyPlz#AEM}GnS4gWR>KSX0>T*it9$-7L%iTVxb``;7uBqCR$v=ilN9xe@d06W|~wz zq($)(Ni-2ww@dS__O!0bVKt&aW*Ll?xN4}H3=O4KX^vYV{$1&4%%LtN(H~E0sx%Fj z)l`TGCfNwmWVfwbGK9K4svFXjfU5O^xu!;FR8#-b0u$NPg{esx08`MEgsuqFgJ(RR zPDDcrw}|O4)7)G;x|~SIyTCgh)#Hj0>XD{-x2KXCG%g!T7nGgpm=fTImbGYi5A29{ zYQRyICby`-g>q;BIDpVVNsC~sZV#bbnr3MY3RdZb1UZt_FdjVFYDi*+kr-TOj0YYU zmMe(}Dg{4SU46fK#k>5;+(&7n)Ju}sIDkhxa3rB%3|G}W9*OigqfJ@yR8 zG-&i%g)B|6NQ8gD#T6s1OEazJEcIG_WkFlzR@>CY!MiE+a#+Et{Y2s%c9X@riXgexFQi|=As!NOCCF`J6q)GT6mx2`ie=R= zD>1x+gqh?7hpu!a0w3oK+ja-U0p3!&DUr$w4ivj6;9{ZiKqZy6q+>BTm5h=*nnRWb zOlLB$%fyPO=!MtMKyUO*vNfM`;uB% zno8p9(KA&!8Ig@1yyyppsv(VYbLWBMA!1MVM1}Ra-b~k(7Wy;F;C7`jBT|v2qb?o{ zqzN>J)kb2{DzvUG(m}9_Herq}v}%hnjh>_q`RVG|)G-(lcnk2Q`}y!M{ce^ zMGkla0bgs2+~jNa1*KVo^t5^X@}_{-FU`v2MO}_2`C_w!?POm|M}3peBfB^G1Fe1; z;sw1@vDFG8>Je5<98ZJXQs3;AGDLy;4sTmaP_$06&;ss_-sXDISlrSoxA}b?z9#Pm z@TFLfv?W&Blue0rie^m-E>m|%a|gt06eY1F$`=iJnoy;3q+gAjQHB9hrW>M~fNREL z(rgg~$c@R=VOhs=DMKrXa1gI#@&Ji}MH-zzs}Mb6eI(O{ zv{-OKWfU`)=%U3~PcmQNV$E9VXO`tbrngeTmI+St+;*h_`Qc1dieOe0j(Ooi#YlGH zVCrrb!VrQFFJG|SXlz@9Qz%$~Spw08R~tg#YwKg=y8V1|icCo2?ME3ZOopNewqcn^ zeS==$HPt~CVgf56la0B>GLdM!7xiR+*5K7vXd;8?=@gF{Nm^}vJ;>@J=8?Rcf{ja8 z@i&2`V<{Ce3vGRWuPbVifzfsv0V|BqY7rP&r+SWc9ElyEIcrf2tx z=wMcbWnOouxu!ck4V`@HXS_Ka?T(_ubxF;hK$}?qAvjA05MVm{uyftm)VKx!VCleM;Q(Jnl z+r{di+k&-dIWnJ6W~B)OWy~gaOalvGTAqody_FddcE*eS71zf4btt%34X#DAhRmnH zj8o}WS%h&1ZOkpd>@tb=1y)8C<`sI#6o$M?a2USavVaKPF&=b$dNRg0JJJ-Z+w^O( z*+JQZjkbc#t|&4^keb$vybHhKD_E8NYQ!yehh;t#$0F(*Ns$ty8T>B|m|U^wX}5<8 ziLyXhqq*r8*{nt5cJV{$BZOKF6$+w`l)*rB%1SVUVGPNm zoU(wdCVHc&`e;Agt7Pp^q`5Ev&of#45q)_TL_t=X#!q>4#{t&Enx!NmEfrZ3f0IC^ zd_lJk%sf13ro&jySW#fWA{?Vgc3wiYbD>~g#Gp`pRr6knb@`BtT^3t>9#C z5+?`v{SxlmRA$p%oPKF$z}hk*rzgTFqrlfx+{7UHh`3omt*BZiWm!;1qK6lSr4n&w z4K%R{YNHwh4DNl|^nqVZbb0y0F2Obsc3NG@ejnxN|t506IQ< zF2X;NqFuaN3Ap{OO--EvZ%e=z^mTYicUzMQZ2luE%)x_dL*T>)iQyGNeDIVA>!m+L zQBzq{wVGOv!i`nDua55dXX8Cxe0%6TzzwYv#zDNWhDSWv{7nJ=#vFb$WAis`@_F$6 z0{ZB!&G`+nWEZaKgC=PV?tvbScJ|qV8ix0P=@d^KXTGg-YA0aq1M_<{Tfipa&$Be} zV<$gu=f~arcz_>Y!jV3LmS%S}Tg&FMiTpT&ALsGoVt%aR$JPAkV&mB3_>o}}UUGG@ zS?qlr=kxR9**|bz!@k1tYix=%Y6p#Aje&dH&{MgDH+eE2iQxe?4nh`LAmc}`=43b> zQ`a-=?|`t(AMuEo1q-X!bv51<>kp#hQ*kF1_akxpi@8GBDrP!8{6;0;ZrdmpB}(cP z?mp&rv}qVVWaM`E5~3J`rz^1z;qtjy?qsT;-w@30YQ(MD96IcKwIpuusT%%ZjP(~$ z!m$_|tb?fuw7WcUzFs^k?j%Ji!MoIiO-&jeDbtZXcm3^K?mg{o?+>rI=C#$OuP$Rn z2hKdTV@B7H^i^nyf?qN{lc_Szu~uAZv67qg_Y;;sd(@^QfI|!zwFz+ds^g`@o*hm zI}F~&Cg6^OtHm3{2Di1t=kfZnW+XPk(+m%j*ilukDp#dIB>RXvwu{`0af=9ld`M#B zID)ITdSz7==F9Hvrla^gN9VG6G2rW=EIhlb)1A~ju~;*d0E0bl?Y|P8{he_yB%T6OY-`^XiQ_ zr_awveek8Qv&3G#&0fVP@Luufj>svpKOS62{HZ1leCXLtmH${r4{Xw>f?NmB?TM#e zboAR#yl@2elTn8#_(3N7_tRWX*K-{E4<6Lw2TAAvv1uY`>5&6^x>@|xMFE&z;E)lK z#H$@Leu1PnFX&-%57z*Vy$FAm%A%!*I_Pzr7JL&Q`VbHL)FJjsnc2}pn>v14bG~6h zcpgxS$CZ1b33{4Oqh`FLUz|nX!P~805~;rmauQSmYVj8HN?egM2H6bI**|^KPnEGO z2?raGUU?$<=;0R)Qqnp7v`N2x(`O^sR}i zODCst+344F@!+G7&9WO^2`&C_Wb|+ug(kz82R$b=&@RK-wi4M;GOc0p7^rz$?_{GQ t;MYT2^wTXpVnvU#$nY4lqHQgkhV1ok{(M8!8b?n~!9+r~j*NgBvvfkFv(V`Pndg$QC4qzl z5(rD!2_TXMWguh$6-Vdk;68&-#~GEr-JKa7#?kTlT;H$GxwpG-mQKI#n}6Q-UMF?? z-gBzzRMn|dRp<8YUbeD=^=6Fq0sQ`H=V^LCXcK~Xy%*OG!pE?WUkNYQA3$7>;`OK&lmvw_HEJ%Uc+6%X)uEo5x5$0a}gJM^a)$<~YA z!d^5n_5i5Y!+ix#?s@wJafUiD`N&WW^z7EX&^wh*#!>)fZ^xXrmNg^Oq>gShS!rJ0S1cI2$Uy%C_kOUc_s6en zxlsGZ;`7T_Y~TCm6WiCwLrWtwdzTI0_)(cHv2DkZwbypcjf<@C-?5?M%UdSz)UW?> z*U9U>DyQeQR#sYmR~dP0URA@0zSVwd^QsHRrSBd0;JN*8t$FQ0?^&@27Y-U)J9yft zXMeo0;W@*U=j&3=9X}U2|L}#y73VMLZwbFRrunU=*Y6Lzl=%BImmZFpa&_77_FTRC z*x29BC>Zm`>3?s&7L&5zo!50O@2t4!csDG2zm%r+>ck?%QZhP%N-`@A#w@;pI|NhQ_ zUwl9Pwc?*jV_*I0{g|2To(2Ee=hN?p^lSZYyI;g#kN7o|f8_VpGwW}iew)!huXe$} zKYf1Jux-!0b?5n2F~gsH@5G2NUaK9cd-&12`qT%Hp8sXen9c`+s;OU}4Gd znG0XOHF?pamrIr|d?_{R-U|iMh5Ej68v!o@t^z&*+yLlW`o>KF+<32FTxS=}~c;0Y!lA0NpLi;>H6e0qzD&2Iv7Z0SgP3#VrPe0Stg} zz!Ja%fKR>$&6t?DsRhQkX@KbfJzypv#y=tM$X8i$#{kCxFF%tVw|Q?)-0{(C;{qnF zjhhURW?AC;0{j630m*<=KpG$&kO?>nI0l$`Zhf5DUK@8M`6FXh@T&>8UHdj+DBupj zFu-uYXuudi4qz?73djSj1FQ$=pZfiZx*Z>`Y|VDA`kUY9kG{pLH znNZvO!qfZwGM}EivClI}1I|A4?s&$&)iG8yjInuR7@K-GV>ZANq?8YC zN1mI=*n|M&fsu@zLjS>0h}DA`TRM=jlo5;t0uD@ItQptALm5j(|E0Sa+cl1{Kj1tT zJU&LC{qYXQUK`8UaI_Bt{tuHFD;vVt_0fzSLHkOy{pC)^N`^DG17qETF;;_SJZJ|3 zcOY;-!dNG8eK+tzLH9P=PC)i0=sylU>hYdAh%poTUxD1u;QA)?`VMlupAEd+iQ z^y>||B0wL3^HCUoJ>WZxTZu6zA_q=|?8AY39`dXO&K$Jo;dABOWQkmUk&`VYu56iIVF;17TXKoX!BaHt<+zX5y>_z~CZ z@g5793g`uh>;=An9KdD3`x0YyfUST;z+Autw11EHs|@o3xE<${@lNS94^RV;fkUst z-i)0F_ybk~LI7_8()z-FfHJ`SfG=->j(GnDePjACrpI+Zz(as10hiEb0PF&+0ek{@ z9qq>fAAv3aiM9;(c^r0m5$6uTQh)`p4>0If*bXobcK;Udn*fgh-T|BeIAK#G=H(^K zlLy_?}ESl6YrH1;ft{IX5gh^Uap}14;b&`N#KR~S`53t2tSC&d_-aXe+?d! zAxk{^cHsQO0LG5#VLJm`#uAy4#i3F$vIMpW5RR5W*B_b93tEtZ2w{3g3u5q{p3#EA z(+9K=w!jy(P?qcq+HAJf7qmI7x+gRvH_0(y(1KX2FKEH+bzjhCvyXg1o5P0Evgv;6 zgWw8*Y%Uw`3)(z3$2-~_ZjNBK)EBf_>@i=^X0sw+(B`pIJ)x1NL5vDZF9w;*RS04q z`GOYA{^<)^2pf!`)Z?I`Oy>*Q95$yXG@)snH?&}wLZF#^K?`O(y`#}WCi7nO1udAp z=?hv2``Q<@Im{2SyIb=HGa=htHlb&d0)^%*@wQM&0$~rf;N{8LUG&eoT{46W21XUqrx%77qlSufG=pl zEXfzN5cae$XrXMEFKDyaS)kozU`fmhNCxCG6VtOSoMqzdD!K!bSw1dP@TW(2J~|0` z1FlTWg1>CQXEa>*h-Q`nG86kRparMmBp2K=SPnR4fIbVn;?bJI&j~RFJ$j6ihxcsu z6UYL6C(GpGO~wXnde=lWPA2{`G@}?mFrjOLRMJHidzK4cjp6gDF}X2Dt}wgsg6u1V9-Z3V$<8|8$1kwfGInMg>j z6lR8;H2QRqcH=+7fz8||794XSwFTtlNs%DCw`=LiaOCM-IiL}$t9*jUs^kbmtRQ1Uwp6hNkc#*A~ zK$`1b(0c5n!{8s`*ik3q!-#0?uvg%Wwq3E)MufMAR-@#1v&Yh%H%#U>B4wjYi{Jm3g?D% zvq%7oPU|lb#!>w|5o6P$NyO;!FyeAR6l8e-uo}cVPyM5?s*@4aC?009bgb{yY#oq- zJ&`Eo<|4A1(QU*zrQAFOhg3v8cQ~yC+1;LG2?!~a{i8946|EUJt^RmrEq1Nq-se__GduVc#1%^a95=@OR}Z|naoW_r)nk* zXEZ~1;dZ;m;Az~{>(OoDQ&t^^DPVSuOQ(z)DAkjf440`~|TfvC|$ASPf05f${@ z1Z31BK-I){a!^r(Q!!%!0UgQT-25+sNRuqJUcDF$(jgLgK9yDE?dmFC!gZxKEBgp+ z^q%@?*^nDim6-{N)L8L@?Q~jM3dpz6AzeY#fOhq!_t@M^3Y{_S~BRVdKwxW|9LtTM;#BrHJG~OUr`9 zOOlbz$Ko?9FB267lq?=KW3V36coem=xggR+Os%QJmdrgy4A8xpE2c*wQ@}tI0kq?F z)=zc+r$Fe%9Xb=bg|6~Gre}B;;ZSwQ(;)O>Q6jW*_s{Z}hBrZ^2~}DR*p1`m}aUN1Z~qKO5x4Is-=WhRO*it;1``JPx1 zLqVjOA1x78!s5PPpm*+sM6p||fe}Ov#mHnz)M_+2BP1nj!|7 zkhYNFSb<_&lmh}ya-fwgcu}OJoDzX+s^>@~PiNTrHy>YlC(D-n9`(5B3T2V43gCaftqi}bVW!D zCWm_!Ee#rxJYEP)W}!tB3PR1=rV%?6s^dg-Mi)y@&5GL4pA2+O3>0CQtV9-Chi**? zqwS`TsmQpZwUT&|J5i=d;?tz(-6GtcL3cp+-L!cXcXzG;acoCKv5%%rEcx9vpxmuC z(b}MNBm9_dbkp5BHOgNHs?Lqt^{s;MfHd2UBuWEgr`e$;s|GpM;C^_dZkn4^_ygIF z{9y?Q#4=FPgMlvj+e=P4kCxhtE97m5C4XB}fwTCmv+kt4bDK28-qd72Qe>|zv$fU8 zTc3BFDFptWI=Qu=y=tGcp+TAu{ZLetT+k}loOae8x%vJ7r7C}}@>3DVfBF3IJ4rP+|m(NbwYRMUQ7tMf{geBhAd>{-(AXenB3 zm$u6#WzL4(@`20B*j!P`Uv4ZXC5nrnt8|B8Z@Y3(uG_mL!)($SjL|TSDwMqCh4!j? zxvpBeJuK#-=mebE>wm4tG+8d%DxWAK*&FKQa>!n0-`fBYY)xnErA2c6eqmy1tP}jp z%b>bkd;x>o%jzBHTI5696;+3c@$BX0&MS?MvnL(rkIAjOrBRO7W=Bn-T)q)B7)4;& z+O9aNPD>-?`eXLuix|_nsZDNac09LTSP&+yI}YOrJeOhRiZW@iYU46!3lwRXy{1gw zc2wSX+P;04qvfE=!PdMT&GwqZ?bYW+n|$J&^L(u|q`hFj?aEP2+cddxtG#@eyrq_W zrMTL8^t7#M2Tm}ydRZoyUTWV`CI!e1t#VN_P|)e9D{(ZR61bd5#To`L5N5jBS}K>n zU@tyHlNHcjQ{X&V2-7-FG{a1AgZ83wpxD~BlI_bYY?lvU@-Vw~)sV$`VT-eLlYHPj zd08#Au~%P!LiQuAa%;ITrnX1SuD$sfM3nl&z1t65z+6M?>htaUt2EtXo%Kf@_0?jY zU6TV860D#Vrd54N@Dn|qo14pFBWaXN;~NEq?YpnY%_pIeVzgnxedPL5`|k5t8jj|Z z@GVbPd?h=!U9cAvdNhk!RGR%YSEIz0t))ypvDwzV!+yR+-ga7xiWOyV(G0_vtkBqF zjR+?v{~FR>1b$^?4K9(k&C$BYaiE^Jxova$DCUCuCM#Lu&cc(Z=hRkO`4^vew3I8(K8m7F z$z{2?u`{AHSgbh^DA-Dai$)rZdD8InM}xb2_%9<9B6ML9;bBX4F|jKmW1?}G1SBIzC_cSW;4xUjUpV;r&Mlzf|icujKC$=>;3rY$z%_op5c^rpC2I<&>kPPNZxpz}`>}32ZGp zTmw0GTtq6P1+it5qlIiJjaRIrhVk~6z0Ud*Kyf_RAeSGP%P&g)uqYCR+_04d9O25D zq#>!z3k0wlC4{gaFQBC$qIX3p6rlJtRy9H`MbFY^cr4bLysK2KGnkqe4$wv3TGqji zB6y0}3j>KUd9qj9MtLKEJ98lgL1`gbh=*~hzoHn-KdOTnpqs6!#a`1)b2CvSP`UgJ z8~}P4GGmkQ#Zi;hWTC~>aLIY@s1zy|fzh-!&xG&NC7Bnc;9GpT7>e?XaQucAm|qkY zGzl=v5aB?gUoJj?JdCH zJ4#MM^H%DCj?zfi93!R+7sf)&$}^j#iOQ_-MIrBOgKV&rF=?GCCp#m{it|W=G*yGN zE5uR$4MgSF+ljCST`oYiEazcrxSRiccRx0GO~fPtZrD}KNmLBm}RfzDorl9gw;W#9_q*h?z0lYl8v-`VRIpB9>X^yfngg^euhR< z10dG-LkUY}%ypS-y1k^#Ue#bPEfk4M3DhGLJ+~c!SIK4N@@|y!yu^)i4WX{5=7bfo z;fYIP;(xg)-jEm*9kpV*u!!RnRZTFyT(MJx7dYpV@Px1kjvW(kkVcE3?UD}$SrTW6 zR%@JelQkhJ*=))cV<|~;!qV{g#o;kVgmPy?p<_pbd~B1;*%Z=o0vG%iXQUfUDH)kb zX2C?%w~~9ABT{J>E=6}fane|FdTt$ZdOppbN=dV@{!ku@9$KxXg(yH3OM-%LO{nbW z(+A@R!L5R&@h;&!3vZ2hqdK5yI^Cg16OlYd}ECB@p=pZlS3tzEho6X5dDQjFQeuftkv0+E;;g;H)h9Zi)ac8*8 zJYE;zCZ8|@CdX9-qcjsyO04x4c8jXln4Pl5WR*s`mN=FG-94n(BGwA++p+f(<+jFz zgT<{8x&tEa^C%TG-J&Zyrqq`j(;SCGO}9nW7zoP*SeZ?qjQ z(ZqS&RcP5M?w{a(zze74t%#fa4x31cL&z`Hl!!Z$*hY!MN)!#$Ag1fnK(*{v8GW~Ya8SfXKZadq@nY5Q=pVs>A1s&U^NxB55EyBE+s#4<95Cd zyS|2ts9&I=(HMo3_QFbK$*H`t>wC7@<$cl=mqhr95d7K*ejr58iyC8Cd`whSqA@($ z7?}{cJY2d1!A#tBNi$hfRtqihxR&w3#S+8UNb$nMYiu3;cu7cLNYFfLxdpey@!JOI zp7=ClR=h{hxzTFL$V$&8j8=R_5|5*^i4PgsD>%o;^K9Y+4@DaA{ywg!5dLCwb~3K% zg(j&VJ~io&cJ|$*5Jq>iaf&Z3xZc%sYA3)i7AWt1*(5d;Kk2iW9~1d;13&KM$BX>< zE{^mPw4_~sb}t*pZs*65{5YN;r}ASEKhEPvJsZGY#YaR#*&lEm#XiSzB0s-}eU0-F z_A`#ZV8f(71vG*>20od9oyJJ`!kX(PF+BdtLC7*uAmby;W!b5DX43+u{&oy={qReg z*_2|%kI1k^xw)pyWOIH(hSh9ZWQE0(^Q?GWFvXgU#~_tXgDE$~l959MZWOf>o12`Z zto+U$u@(%UV(r`!nU$7p$xI@4NoM8OY&v6wW#{BuGSXLf!GLbGccR0#+>*U613#97 z9~n}AMJLs4W?gl#U#*@I7L6{wAv4@!$+j3wX&G4=B$A$Yxq09RD|Fn}i>JI@e{|xj zQHKJr1-!oV?Kb9j@mG&59~t^d$sM}i-gk7!@|lv9l9oT|`@TzN%&FShM<+>x3XWjH zSf2v?LIrsAg25tKDkEe?BtcxD_%c`FGhT{ExuMm-%nYBb9%M)x%rb=uM)d{(jAfS=e=0rc&Ekf`7+=_;twTSz=s~a zHt~s&}$*` znB>xqp1G#)acaL&MtBBDAiiy|4wj&Y7A(|^-{kQ3pkL10)z9>)KL~OX1On(A)^l)0 zK_!8W1fBaK1bS$|>>*)SpUuoE|cur%>n>!R-}=_H@pTESCelNt<*$ z_-6%<+NSepor2b>u&8R2N4RYCT#I;aS;(f&oBDV|*EZ=%Mgx~oSdtzXqsRO@&Pz{o z8;HtAQf5Qt(b4j5yVD%`0e=y!MGsNX6O!~$nGPO9v*?~JHx13#zxegIs2gva|1akI L|Lp!(Sm3__boX?k literal 0 HcmV?d00001 diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengSelect.cs b/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengSelect.cs index 0f0c131c..fdba488e 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengSelect.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/Curd/OdbcDamengSelect.cs @@ -125,60 +125,60 @@ namespace FreeSql.Odbc.Dameng } public OdbcDamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } - public override ISelect From(Expression, T2, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcOracleSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } - public override ISelect From(Expression, T2, T3, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcOracleSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } - public override ISelect From(Expression, T2, T3, T4, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcOracleSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } - public override ISelect From(Expression, T2, T3, T4, T5, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcOracleSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } - public override ISelect From(Expression, T2, T3, T4, T5, T6, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcOracleSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } - public override ISelect From(Expression, T2, T3, T4, T5, T6, T7, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcOracleSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } - public override ISelect From(Expression, T2, T3, T4, T5, T6, T7, T8, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcOracleSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } - public override ISelect From(Expression, T2, T3, T4, T5, T6, T7, T8, T9, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcOracleSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } - public override ISelect From(Expression, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcOracleSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override ISelect From(Expression, T2, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcDamengSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override ISelect From(Expression, T2, T3, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcDamengSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override ISelect From(Expression, T2, T3, T4, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcDamengSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override ISelect From(Expression, T2, T3, T4, T5, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcDamengSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override ISelect From(Expression, T2, T3, T4, T5, T6, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcDamengSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override ISelect From(Expression, T2, T3, T4, T5, T6, T7, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcDamengSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override ISelect From(Expression, T2, T3, T4, T5, T6, T7, T8, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcDamengSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override ISelect From(Expression, T2, T3, T4, T5, T6, T7, T8, T9, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcDamengSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } + public override ISelect From(Expression, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression>> exp) { this.InternalFrom(exp); var ret = new OdbcDamengSelect(_orm, _commonUtils, _commonExpression, null); OdbcDamengSelect.CopyData(this, ret, exp?.Parameters); return ret; } public override string ToSql(string field = null) => ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); } - class OdbcOracleSelect : FreeSql.Internal.CommonProvider.Select2Provider where T1 : class where T2 : class + class OdbcDamengSelect : FreeSql.Internal.CommonProvider.Select2Provider where T1 : class where T2 : class { - public OdbcOracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public OdbcDamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } public override string ToSql(string field = null) => OdbcDamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); } - class OdbcOracleSelect : FreeSql.Internal.CommonProvider.Select3Provider where T1 : class where T2 : class where T3 : class + class OdbcDamengSelect : FreeSql.Internal.CommonProvider.Select3Provider where T1 : class where T2 : class where T3 : class { - public OdbcOracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public OdbcDamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } public override string ToSql(string field = null) => OdbcDamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); } - class OdbcOracleSelect : FreeSql.Internal.CommonProvider.Select4Provider where T1 : class where T2 : class where T3 : class where T4 : class + class OdbcDamengSelect : FreeSql.Internal.CommonProvider.Select4Provider where T1 : class where T2 : class where T3 : class where T4 : class { - public OdbcOracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public OdbcDamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } public override string ToSql(string field = null) => OdbcDamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); } - class OdbcOracleSelect : FreeSql.Internal.CommonProvider.Select5Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class + class OdbcDamengSelect : FreeSql.Internal.CommonProvider.Select5Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class { - public OdbcOracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public OdbcDamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } public override string ToSql(string field = null) => OdbcDamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); } - class OdbcOracleSelect : FreeSql.Internal.CommonProvider.Select6Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class + class OdbcDamengSelect : FreeSql.Internal.CommonProvider.Select6Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class { - public OdbcOracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public OdbcDamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } public override string ToSql(string field = null) => OdbcDamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); } - class OdbcOracleSelect : FreeSql.Internal.CommonProvider.Select7Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class + class OdbcDamengSelect : FreeSql.Internal.CommonProvider.Select7Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class { - public OdbcOracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public OdbcDamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } public override string ToSql(string field = null) => OdbcDamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); } - class OdbcOracleSelect : FreeSql.Internal.CommonProvider.Select8Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class + class OdbcDamengSelect : FreeSql.Internal.CommonProvider.Select8Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class { - public OdbcOracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public OdbcDamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } public override string ToSql(string field = null) => OdbcDamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); } - class OdbcOracleSelect : FreeSql.Internal.CommonProvider.Select9Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class + class OdbcDamengSelect : FreeSql.Internal.CommonProvider.Select9Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class { - public OdbcOracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public OdbcDamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } public override string ToSql(string field = null) => OdbcDamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); } - class OdbcOracleSelect : FreeSql.Internal.CommonProvider.Select10Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class + class OdbcDamengSelect : FreeSql.Internal.CommonProvider.Select10Provider where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class { - public OdbcOracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } + public OdbcDamengSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } public override string ToSql(string field = null) => OdbcDamengSelect.ToSqlStatic(_commonUtils, _commonExpression, _select, _distinct, field ?? this.GetAllFieldExpressionTreeLevel2().Field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, this.GetTableRuleUnions(), _aliasRule, _tosqlAppendContent, _whereCascadeExpression, _orm); } } diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengAdo/OdbcDamengConnectionPool.cs b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengAdo/OdbcDamengConnectionPool.cs index 919c9d6b..61ac9b87 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengAdo/OdbcDamengConnectionPool.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengAdo/OdbcDamengConnectionPool.cs @@ -25,7 +25,7 @@ namespace FreeSql.Odbc.Dameng this.availableHandler = availableHandler; this.unavailableHandler = unavailableHandler; - var policy = new OdbcOracleConnectionPoolPolicy + var policy = new OdbcDamengConnectionPoolPolicy { _pool = this, Name = name @@ -62,7 +62,7 @@ namespace FreeSql.Odbc.Dameng } } - class OdbcOracleConnectionPoolPolicy : IPolicy + class OdbcDamengConnectionPoolPolicy : IPolicy { internal OdbcDamengConnectionPool _pool; diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengCodeFirst.cs b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengCodeFirst.cs index a2a91981..55fc2af3 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengCodeFirst.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengCodeFirst.cs @@ -114,7 +114,7 @@ namespace FreeSql.Odbc.Dameng //codefirst 不支持表名中带 . if (string.Compare(tbname[0], userId) != 0 && _orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(" select 1 from sys.dba_users where username={0}", tbname[0])) == null) //创建数据库 - throw new NotImplementedException($"Oracle CodeFirst 不支持代码创建 tablespace 与 schemas {tbname[0]}"); + throw new NotImplementedException($"达梦 CodeFirst 不支持代码创建 tablespace 与 schemas {tbname[0]}"); var sbalter = new StringBuilder(); var istmpatler = false; //创建临时表,导入数据,删除旧表,修改 @@ -200,7 +200,7 @@ where a.owner={{0}} and a.table_name={{1}}", tboldname ?? tbname); var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql); var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a => { - var sqlType = GetOracleSqlTypeFullName(a); + var sqlType = GetDamengSqlTypeFullName(a); return new { column = string.Concat(a[0]), @@ -436,7 +436,7 @@ and not exists(select 1 from all_constraints where index_name = a.index_name and return sb.Length == 0 ? null : sb.Insert(0, "BEGIN \r\n").Insert(0, sbDeclare.ToString()).Append("END;").ToString(); } - internal static string GetOracleSqlTypeFullName(object[] row) + internal static string GetDamengSqlTypeFullName(object[] row) { var a = row; var sqlType = string.Concat(a[1]).ToUpper(); diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengDbFirst.cs b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengDbFirst.cs index ff398cc7..d6eccbdc 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengDbFirst.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengDbFirst.cs @@ -61,7 +61,7 @@ namespace FreeSql.Odbc.Dameng _dicDbToCs.TryAdd(dbfull, _dicDbToCs["number(1)"]); return OdbcType.Bit; case "smallint": - _dicDbToCs.TryAdd(dbfull, _dicDbToCs["number(5)"]); + _dicDbToCs.TryAdd(dbfull, _dicDbToCs["number(4)"]); return OdbcType.SmallInt; case "byte": _dicDbToCs.TryAdd(dbfull, _dicDbToCs["number(3)"]); @@ -323,7 +323,7 @@ where a.owner in ({1}) and {0} ds2item[0] = row[0]; ds2item[1] = row[1]; ds2item[2] = Regex.Replace(string.Concat(row[2]), @"\(\d+\)", ""); - ds2item[4] = OdbcDamengCodeFirst.GetOracleSqlTypeFullName(new object[] { row[1], row[2], row[3], row[4], row[5], row[6] }); + ds2item[4] = OdbcDamengCodeFirst.GetDamengSqlTypeFullName(new object[] { row[1], row[2], row[3], row[4], row[5], row[6] }); ds2item[5] = string.Concat(row[7]) == "1"; ds2item[6] = string.Concat(row[8]) == "1"; ds2item[7] = string.Concat(row[9]); diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengProvider.cs b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengProvider.cs index c1da688a..77e114ae 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengProvider.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengProvider.cs @@ -38,12 +38,6 @@ namespace FreeSql.Odbc.Dameng this.DbFirst = new OdbcDamengDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); this.CodeFirst = new OdbcDamengCodeFirst(this, this.InternalCommonUtils, this.InternalCommonExpression); - - //this.Aop.AuditValue += new EventHandler((_, e) => - //{ - // if (e.Value == null && e.Column.Attribute.IsPrimary == false && e.Column.Attribute.IsIdentity == false) - // e.Value = Utils.GetDataReaderValue(e.Property.PropertyType.NullableTypeOrThis(), e.Column.Attribute.DbDefautValue); - //}); } internal CommonUtils InternalCommonUtils { get; } diff --git a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengUtils.cs b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengUtils.cs index 1bfc029b..dd066373 100644 --- a/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengUtils.cs +++ b/Providers/FreeSql.Provider.Odbc/Dameng/OdbcDamengUtils.cs @@ -65,7 +65,7 @@ namespace FreeSql.Odbc.Dameng return ret; }); - public override string FormatSql(string sql, params object[] args) => sql?.FormatOdbcOracle(args); + public override string FormatSql(string sql, params object[] args) => sql?.FormatOdbcDameng(args); public override string QuoteSqlName(params string[] name) { if (name.Length == 1)