diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs index 64cb632a..1874f482 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs @@ -1008,6 +1008,14 @@ FROM `tb_topic` a WHERE (((cast(a.`Id` as char)) in (SELECT b.`Title` FROM `tb_topic` b)))", subquery); var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + + subquery = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.`Id`, a.`Clicks`, a.`TypeGuid`, a.`Title`, a.`CreateTime` +FROM `tb_topic` a +WHERE (((cast(a.`Id` as char)) in ( SELECT * FROM (SELECT b.`Title` + FROM `tb_topic` b + limit 0,10) ftblmt50 )))", subquery); + subqueryList = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); } [Fact] public void As() diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs index 70ab536a..1a423cc6 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs @@ -933,6 +933,14 @@ 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(); + + subquery = select.Where(a => select.As("b").Limit(10).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 + WHERE ROWNUM < 11)))", subquery); + subqueryList = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); } [Fact] public void As() diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs index 51f384fb..0cac84eb 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs @@ -1019,6 +1019,14 @@ FROM `tb_topic` a WHERE (((cast(a.`Id` as char)) in (SELECT b.`Title` FROM `tb_topic` b)))", subquery); var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + + subquery = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.`Id`, a.`Clicks`, a.`TypeGuid`, a.`Title`, a.`CreateTime` +FROM `tb_topic` a +WHERE (((cast(a.`Id` as char)) in ( SELECT * FROM (SELECT b.`Title` + FROM `tb_topic` b + limit 0,10) ftblmt50 )))", subquery); + subqueryList = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); } [Fact] public void As() diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs index 1f89e0b5..f6d4b36f 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs @@ -934,6 +934,14 @@ 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(); + + subquery = select.Where(a => select.As("b").Limit(10).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 + WHERE ROWNUM < 11)))", subquery); + subqueryList = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); } [Fact] public void As() diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs index 12bb9058..2b0743dc 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs @@ -995,6 +995,14 @@ FROM ""tb_topic"" a WHERE ((((a.""id"")::text) in (SELECT b.""title"" FROM ""tb_topic"" b)))", subquery); var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + + subquery = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.""id"", a.""clicks"", a.""typeguid"", a.""title"", a.""createtime"" +FROM ""tb_topic"" a +WHERE ((((a.""id"")::text) in (SELECT b.""title"" + FROM ""tb_topic"" b + limit 10)))", subquery); + subqueryList = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); } [Fact] public void As() diff --git a/FreeSql.Tests/FreeSql.Tests/AdoNetExtensions/OracleConnectionExtensionsTest.cs b/FreeSql.Tests/FreeSql.Tests/AdoNetExtensions/OracleConnectionExtensionsTest.cs index 359e5451..78a1a402 100644 --- a/FreeSql.Tests/FreeSql.Tests/AdoNetExtensions/OracleConnectionExtensionsTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/AdoNetExtensions/OracleConnectionExtensionsTest.cs @@ -6,7 +6,7 @@ using Xunit; namespace FreeSql.Tests.AdoNetExtensions.OracleConnectionExtensions { public class Methods { - string _connectString = "user id=user1;password=123456;data source=//127.0.0.1:1521/XE;Pooling=true;Max Pool Size=5"; + string _connectString = "user id=1user;password=123456;data source=//127.0.0.1:1521/XE;Pooling=true;Max Pool Size=5"; public Methods() { g.oracle.CodeFirst.SyncStructure(); diff --git a/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs index 792f9b14..07867836 100644 --- a/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Dameng/Curd/DamengSelectTest.cs @@ -951,6 +951,14 @@ 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(); + + subquery = select.Where(a => select.As("b").Limit(10).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 + WHERE ROWNUM < 11)))", subquery); + subqueryList = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); } [Fact] public void As() diff --git a/FreeSql.Tests/FreeSql.Tests/Firebird/Curd/FirebirdSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Firebird/Curd/FirebirdSelectTest.cs index 5017c5d6..c06dc6a9 100644 --- a/FreeSql.Tests/FreeSql.Tests/Firebird/Curd/FirebirdSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Firebird/Curd/FirebirdSelectTest.cs @@ -934,6 +934,13 @@ FROM ""TB_TOPIC22"" a WHERE (((cast(a.""ID"" as blob sub_type 1)) 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(); + + subquery = select.Where(a => select.As("b").Limit(10).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 (((cast(a.""ID"" as blob sub_type 1)) in (SELECT FIRST 10 b.""TITLE"" + FROM ""TB_TOPIC22"" b)))", subquery); + subqueryList = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); } [Fact] public void As() diff --git a/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs index 17b9102f..6b720747 100644 --- a/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs @@ -899,6 +899,13 @@ FROM [tb_topic22] a WHERE (((cstr(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(); + + subquery = select.Where(a => select.As("b").Limit(10).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 (((cstr(a.[Id])) in (SELECT TOP 10 b.[Title] + FROM [tb_topic22] b)))", subquery); + subqueryList = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); } [Fact] public void As() diff --git a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs index ca9dc749..6ef0c1f6 100644 --- a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs @@ -1071,6 +1071,14 @@ FROM `tb_topic` a WHERE (((cast(a.`Id` as char)) in (SELECT b.`Title` FROM `tb_topic` b)))", subquery); var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + + subquery = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.`Id`, a.`Clicks`, a.`TypeGuid`, a.`Title`, a.`CreateTime` +FROM `tb_topic` a +WHERE (((cast(a.`Id` as char)) in ( SELECT * FROM (SELECT b.`Title` + FROM `tb_topic` b + limit 0,10) ftblmt50 )))", subquery); + subqueryList = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); } [Fact] public void As() diff --git a/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs index ca4df59c..b75967ff 100644 --- a/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs @@ -938,6 +938,14 @@ 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(); + + subquery = select.Where(a => select.As("b").Limit(10).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 + WHERE ROWNUM < 11)))", subquery); + subqueryList = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); } [Fact] public void As() diff --git a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs index 41f395e1..b5df0468 100644 --- a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs @@ -1012,6 +1012,14 @@ FROM ""tb_topic"" a WHERE ((((a.""id"")::text) in (SELECT b.""title"" FROM ""tb_topic"" b)))", subquery); var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); + + subquery = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToSql(); + Assert.Equal(@"SELECT a.""id"", a.""clicks"", a.""typeguid"", a.""title"", a.""createtime"" +FROM ""tb_topic"" a +WHERE ((((a.""id"")::text) in (SELECT b.""title"" + FROM ""tb_topic"" b + limit 10)))", subquery); + subqueryList = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); } [Fact] public void As() diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs index 514bbebd..2679f9c7 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs @@ -945,6 +945,13 @@ FROM [tb_topic22] a WHERE (((cast(a.[Id] as nvarchar(100))) 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(); + + subquery = select.Where(a => select.As("b").Limit(10).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 (((cast(a.[Id] as nvarchar(100))) in (SELECT TOP 10 b.[Title] + FROM [tb_topic22] b)))", subquery); + subqueryList = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); } [Fact] public void As() diff --git a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs index 6a31fd5d..815b7646 100644 --- a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs @@ -922,6 +922,14 @@ FROM ""tb_topic22"" a WHERE (((cast(a.""Id"" as character)) 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(); + + subquery = select.Where(a => select.As("b").Limit(10).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 (((cast(a.""Id"" as character)) in (SELECT b.""Title"" + FROM ""tb_topic22"" b + limit 0,10)))", subquery); + subqueryList = select.Where(a => select.As("b").Limit(10).ToList(b => b.Title).Contains(a.Id.ToString())).ToList(); } [Fact] public void As() diff --git a/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs b/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs index 348e0692..c5f0c9ca 100644 --- a/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs +++ b/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs @@ -633,7 +633,7 @@ INNER JOIN ""userinfo"" p ON p.""userid"" = o.""userid""", select16Sql2); .UseLazyLoading(true) .Build()); ib.Register("db2", () => new FreeSql.FreeSqlBuilder() - .UseConnectionString(FreeSql.DataType.Oracle, "user id=user1;password=123456;data source=//127.0.0.1:1521/XE;Pooling=true;Max Pool Size=3") + .UseConnectionString(FreeSql.DataType.Oracle, "user id=1user;password=123456;data source=//127.0.0.1:1521/XE;Pooling=true;Max Pool Size=3") .UseAutoSyncStructure(true) .UseGenerateCommandParameterWithLambda(true) .UseLazyLoading(true) diff --git a/FreeSql.Tests/FreeSql.Tests/UnitTest5.cs b/FreeSql.Tests/FreeSql.Tests/UnitTest5.cs index edadaa48..90f19686 100644 --- a/FreeSql.Tests/FreeSql.Tests/UnitTest5.cs +++ b/FreeSql.Tests/FreeSql.Tests/UnitTest5.cs @@ -3,6 +3,7 @@ using FreeSql.DataAnnotations; using FreeSql.Internal; using FreeSql.Internal.CommonProvider; using MySql.Data.MySqlClient; +using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Diagnostics; @@ -15,6 +16,35 @@ namespace FreeSql.Tests { public class UnitTest5 { + + [Fact] + public void TestJsonb01() + { + var fsql = g.pgsql; + fsql.Delete().Where("1=1").ExecuteAffrows(); + + var item = new TestJsonb01Cls1 + { + jsonb01 = new List { 1, 5, 10, 20 }, + jsonb02 = new List { 11, 51, 101, 201 }, + jsonb03 = new List { "12", "52", "102", "202" }, + }; + fsql.Insert(item).ExecuteAffrows(); + + var items = fsql.Select().ToList(); + } + + public class TestJsonb01Cls1 + { + public Guid id { get; set; } + [Column(MapType = typeof(JArray))] + public List jsonb01 { get; set; } + [Column(MapType = typeof(JToken))] + public List jsonb02 { get; set; } + [Column(MapType = typeof(JToken))] + public List jsonb03 { get; set; } + } + [Fact] public void DebugUpdateSet01() { diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index d2092d9d..b4c8352f 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -378,6 +378,7 @@ namespace FreeSql.Internal objval = Utils.GetDataReaderValue(parent.CsType, objval); if (parent.Property != null && parent.CsType != parent.Property.PropertyType) objval = Utils.GetDataReaderValue(parent.Property.PropertyType, objval); + if (objval == DBNull.Value) objval = null; return objval; } var ctorParmsLength = 0; @@ -1116,7 +1117,7 @@ namespace FreeSql.Internal if (fsql != null) { if (asSelectParentExp != null) - { //执行 asSelect() 的关联,OneToMany,ManyToMany + { //执行 AsSelect() 的关联,OneToMany,ManyToMany if (fsqltables[0].Parameter == null) { fsqltables[0].Alias = $"tb_{fsqltables.Count}"; @@ -1287,15 +1288,30 @@ namespace FreeSql.Internal case "ToOne": case "First": var tscClone2 = tsc.CloneDisableDiyParse(); - tscClone2.subSelect001 = fsql as Select0Provider; //#405 Oracle within group(order by ..) + var fsqlSelect0p = fsql as Select0Provider; + tscClone2.subSelect001 = fsqlSelect0p; //#405 Oracle within group(order by ..) tscClone2.isDisableDiyParse = false; tscClone2._tables = fsqltables; var exp3Args02 = (exp3.Arguments.FirstOrDefault() as UnaryExpression)?.Operand as LambdaExpression; if (exp3Args02.Parameters.Count == 1 && exp3Args02.Parameters[0].Type.FullName.StartsWith("FreeSql.Internal.Model.HzyTuple`")) exp3Args02 = new ReplaceHzyTupleToMultiParam().Modify(exp3Args02, fsqltables); - var sqlFirst = fsqlType.GetMethod("ToSql", new Type[] { typeof(string) })?.Invoke(fsql, new object[] { ExpressionLambdaToSql(exp3Args02, tscClone2) })?.ToString(); + var sqlFirstField = ExpressionLambdaToSql(exp3Args02, tscClone2); + var sqlFirst = fsqlType.GetMethod("ToSql", new Type[] { typeof(string) })?.Invoke(fsql, new object[] { sqlFirstField })?.ToString(); if (string.IsNullOrEmpty(sqlFirst) == false) + { + if (fsqlSelect0p._limit > 0) + { + switch (_ado.DataType) //使用 Limit 后的 IN 子查询需要套一层 + { + case DataType.MySql: + case DataType.OdbcMySql: + if (exp3.Method.Name == "ToList") + return $"( SELECT * FROM ({sqlFirst.Replace(" \r\n", " \r\n ")}) ftblmt50 )"; + break; + } + } return $"({sqlFirst.Replace(" \r\n", " \r\n ")})"; + } break; } } diff --git a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs index 06d6d80a..70036198 100644 --- a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs +++ b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProvider.cs @@ -557,7 +557,7 @@ namespace FreeSql.Internal.CommonProvider public void ExecuteReader(Action> fetchHandler, CommandType cmdType, string cmdText, params DbParameter[] cmdParms) => ExecuteReader(null, null, fetchHandler, cmdType, cmdText, 0, cmdParms); public void ExecuteReader(DbTransaction transaction, Action> fetchHandler, CommandType cmdType, string cmdText, params DbParameter[] cmdParms) => ExecuteReader(null, transaction, fetchHandler, cmdType, cmdText, 0, cmdParms); public void ExecuteReader(DbConnection connection, DbTransaction transaction, Action> fetchHandler, CommandType cmdType, string cmdText, int cmdTimeout, params DbParameter[] cmdParms) => ExecuteReaderMultiple(1, connection, transaction, (fetch, result) => fetchHandler(fetch), null, cmdType, cmdText, cmdTimeout, cmdParms); - void ExecuteReaderMultiple(int multipleResult, DbConnection connection, DbTransaction transaction, Action, int> fetchHandler, Action schemaHandler, CommandType cmdType, string cmdText, int cmdTimeout, params DbParameter[] cmdParms) + public void ExecuteReaderMultiple(int multipleResult, DbConnection connection, DbTransaction transaction, Action, int> fetchHandler, Action schemaHandler, CommandType cmdType, string cmdText, int cmdTimeout, params DbParameter[] cmdParms) { if (string.IsNullOrEmpty(cmdText)) return; var dt = DateTime.Now; diff --git a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs index bfb147d2..941e6ae9 100644 --- a/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs +++ b/FreeSql/Internal/CommonProvider/AdoProvider/AdoProviderAsync.cs @@ -476,7 +476,7 @@ namespace FreeSql.Internal.CommonProvider public Task ExecuteReaderAsync(Func, Task> fetchHandler, CommandType cmdType, string cmdText, DbParameter[] cmdParms, CancellationToken cancellationToken = default) => ExecuteReaderAsync(null, null, fetchHandler, cmdType, cmdText, 0, cmdParms, cancellationToken); public Task ExecuteReaderAsync(DbTransaction transaction, Func, Task> fetchHandler, CommandType cmdType, string cmdText, DbParameter[] cmdParms, CancellationToken cancellationToken = default) => ExecuteReaderAsync(null, transaction, fetchHandler, cmdType, cmdText, 0, cmdParms, cancellationToken); public Task ExecuteReaderAsync(DbConnection connection, DbTransaction transaction, Func, Task> fetchHandler, CommandType cmdType, string cmdText, int cmdTimeout, DbParameter[] cmdParms, CancellationToken cancellationToken = default) => ExecuteReaderMultipleAsync(1, connection, transaction, (fetch, result) => fetchHandler(fetch), null, cmdType, cmdText, cmdTimeout, cmdParms, cancellationToken); - async Task ExecuteReaderMultipleAsync(int multipleResult, DbConnection connection, DbTransaction transaction, Func, int, Task> fetchHandler, Action schemaHandler, CommandType cmdType, string cmdText, int cmdTimeout, DbParameter[] cmdParms, CancellationToken cancellationToken = default) + public async Task ExecuteReaderMultipleAsync(int multipleResult, DbConnection connection, DbTransaction transaction, Func, int, Task> fetchHandler, Action schemaHandler, CommandType cmdType, string cmdText, int cmdTimeout, DbParameter[] cmdParms, CancellationToken cancellationToken = default) { if (string.IsNullOrEmpty(cmdText)) return; var dt = DateTime.Now; diff --git a/FreeSql/Internal/CommonProvider/CodeFirstProvider.cs b/FreeSql/Internal/CommonProvider/CodeFirstProvider.cs index 2ce2889e..30cec779 100644 --- a/FreeSql/Internal/CommonProvider/CodeFirstProvider.cs +++ b/FreeSql/Internal/CommonProvider/CodeFirstProvider.cs @@ -128,7 +128,7 @@ namespace FreeSql.Internal.CommonProvider } } - public virtual int ExecuteDDLStatements(string ddl) => _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl); + public virtual int ExecuteDDLStatements(string ddl) => string.IsNullOrWhiteSpace(ddl) ? 0 : _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl); public static string ReplaceIndexName(string indexName, string tbname) => string.IsNullOrEmpty(indexName) ? indexName : Regex.Replace(indexName, @"\{\s*TableName\s*\}", tbname, RegexOptions.IgnoreCase); } diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs index 262e8b9a..1c4785a2 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs @@ -702,7 +702,7 @@ namespace FreeSql.Internal.CommonProvider { case DataType.MySql: case DataType.OdbcMySql: - _tosqlAppendContent = " for update"; + _tosqlAppendContent = $"{_tosqlAppendContent} for update"; break; case DataType.SqlServer: case DataType.OdbcSqlServer: @@ -712,21 +712,21 @@ namespace FreeSql.Internal.CommonProvider case DataType.OdbcPostgreSQL: case DataType.KingbaseES: case DataType.OdbcKingbaseES: - _tosqlAppendContent = $" for update{(noawait ? " nowait" : "")}"; + _tosqlAppendContent = $"{_tosqlAppendContent} for update{(noawait ? " nowait" : "")}"; break; case DataType.Oracle: case DataType.OdbcOracle: case DataType.Dameng: case DataType.OdbcDameng: - _tosqlAppendContent = $" for update{(noawait ? " nowait" : "")}"; + _tosqlAppendContent = $"{_tosqlAppendContent} for update{(noawait ? " nowait" : "")}"; break; case DataType.Sqlite: break; case DataType.ShenTong: //神通测试中发现,不支持 nowait - _tosqlAppendContent = " for update"; + _tosqlAppendContent = $"{_tosqlAppendContent} for update"; break; case DataType.Firebird: - _tosqlAppendContent = " for update with lock"; + _tosqlAppendContent = $"{_tosqlAppendContent} for update with lock"; break; } return this as TSelect; diff --git a/FreeSql/Internal/UtilsExpressionTree.cs b/FreeSql/Internal/UtilsExpressionTree.cs index 9b84beed..ffe5d765 100644 --- a/FreeSql/Internal/UtilsExpressionTree.cs +++ b/FreeSql/Internal/UtilsExpressionTree.cs @@ -1348,7 +1348,12 @@ namespace FreeSql.Internal orm.Aop.AuditDataReaderHandler(orm, args); return args.Value; } - if (orm.Ado.DataType == DataType.Dameng && dr.IsDBNull(index)) return null; //OdbcDameng 不会报错 + switch (orm.Ado.DataType) + { + case DataType.Dameng: //OdbcDameng 不会报错 + if (dr.IsDBNull(index)) return null; + break; + } return dr.GetValue(index); } internal static RowInfo ExecuteArrayRowReadClassOrTuple(string flagStr, Type typeOrg, int[] indexes, DbDataReader row, int dataIndex, CommonUtils _commonUtils) diff --git a/Providers/FreeSql.Provider.MsAccess/MsAccessCodeFirst.cs b/Providers/FreeSql.Provider.MsAccess/MsAccessCodeFirst.cs index 6f419a8e..7fc0c12e 100644 --- a/Providers/FreeSql.Provider.MsAccess/MsAccessCodeFirst.cs +++ b/Providers/FreeSql.Provider.MsAccess/MsAccessCodeFirst.cs @@ -471,7 +471,6 @@ namespace FreeSql.MsAccess var scripts = ddl.Split(new string[] { ";\r\n" }, StringSplitOptions.None).Where(a => string.IsNullOrEmpty(a.Trim()) == false).ToArray(); if (scripts.Any() == false) return 0; - if (scripts.Length == 1) return base.ExecuteDDLStatements(ddl); var affrows = 0; foreach (var script in scripts) diff --git a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlCodeFirst.cs b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlCodeFirst.cs index 0bb333da..8130a503 100644 --- a/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlCodeFirst.cs +++ b/Providers/FreeSql.Provider.Odbc/MySql/OdbcMySqlCodeFirst.cs @@ -399,7 +399,6 @@ where a.table_schema IN ({0}) and a.table_name IN ({1}) and a.index_name <> 'PRI var scripts = ddl.Split(new string[] { ";\r\n" }, StringSplitOptions.None).Where(a => string.IsNullOrEmpty(a.Trim()) == false).ToArray(); if (scripts.Any() == false) return 0; - if (scripts.Length == 1) return base.ExecuteDDLStatements(ddl); var affrows = 0; foreach (var script in scripts) diff --git a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLProvider.cs b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLProvider.cs index 951b8373..95df5ad2 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLProvider.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/PostgreSQLProvider.cs @@ -1,13 +1,13 @@ using FreeSql.Internal; using FreeSql.Internal.CommonProvider; using FreeSql.PostgreSQL.Curd; +using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Npgsql.LegacyPostgis; using NpgsqlTypes; using System; using System.Collections; using System.Collections.Generic; -using System.Data; using System.Data.Common; using System.Linq.Expressions; using System.Net; @@ -63,19 +63,39 @@ namespace FreeSql.PostgreSQL Utils.dicExecuteArrayRowReadClassOrTuple[typeof(JObject)] = true; Utils.dicExecuteArrayRowReadClassOrTuple[typeof(JArray)] = true; + var MethodJTokenFromObject = typeof(JToken).GetMethod("FromObject", new[] { typeof(object) }); + var MethodJObjectFromObject = typeof(JObject).GetMethod("FromObject", new[] { typeof(object) }); + var MethodJArrayFromObject = typeof(JArray).GetMethod("FromObject", new[] { typeof(object) }); var MethodJTokenParse = typeof(JToken).GetMethod("Parse", new[] { typeof(string) }); var MethodJObjectParse = typeof(JObject).GetMethod("Parse", new[] { typeof(string) }); var MethodJArrayParse = typeof(JArray).GetMethod("Parse", new[] { typeof(string) }); + var MethodJsonConvertDeserializeObject = typeof(JsonConvert).GetMethod("DeserializeObject", new[] { typeof(string), typeof(Type) }); Utils.GetDataReaderValueBlockExpressionSwitchTypeFullName.Add((LabelTarget returnTarget, Expression valueExp, Type type) => { switch (type.FullName) { - case "Newtonsoft.Json.Linq.JToken": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJTokenParse, Expression.Convert(valueExp, typeof(string))), typeof(JToken))); - case "Newtonsoft.Json.Linq.JObject": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJObjectParse, Expression.Convert(valueExp, typeof(string))), typeof(JObject))); - case "Newtonsoft.Json.Linq.JArray": return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJArrayParse, Expression.Convert(valueExp, typeof(string))), typeof(JArray))); - case "Npgsql.LegacyPostgis.PostgisGeometry": return Expression.Return(returnTarget, valueExp); - case "NetTopologySuite.Geometries.Geometry": return Expression.Return(returnTarget, valueExp); + case "Newtonsoft.Json.Linq.JToken": + return Expression.IfThenElse( + Expression.TypeIs(valueExp, typeof(string)), + Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJTokenParse, Expression.Convert(valueExp, typeof(string))), typeof(JToken))), + Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJTokenFromObject, valueExp), typeof(JToken)))); + case "Newtonsoft.Json.Linq.JObject": + return Expression.IfThenElse( + Expression.TypeIs(valueExp, typeof(string)), + Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJObjectParse, Expression.Convert(valueExp, typeof(string))), typeof(JObject))), + Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJObjectFromObject, valueExp), typeof(JObject)))); + case "Newtonsoft.Json.Linq.JArray": + return Expression.IfThenElse( + Expression.TypeIs(valueExp, typeof(string)), + Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJArrayParse, Expression.Convert(valueExp, typeof(string))), typeof(JArray))), + Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJArrayFromObject, valueExp), typeof(JArray)))); + case "Npgsql.LegacyPostgis.PostgisGeometry": + return Expression.Return(returnTarget, valueExp); + case "NetTopologySuite.Geometries.Geometry": + return Expression.Return(returnTarget, valueExp); } + if (typeof(IList).IsAssignableFrom(type)) + return Expression.Return(returnTarget, Expression.TypeAs(Expression.Call(MethodJsonConvertDeserializeObject, Expression.Convert(valueExp, typeof(string)), Expression.Constant(type, typeof(Type))), type)); return null; }); }