From dc8f575b18bd3e495f5afebba64f1605d3ecece2 Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Fri, 26 Jun 2020 07:58:09 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E4=BF=AE=E5=A4=8D=20sqlserver=20=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=20cast(..=20as=20nvarchar)=20=E6=88=AA=E6=96=AD?= =?UTF-8?q?=E9=95=BF=E5=BA=A6=2030=20=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=9B#?= =?UTF-8?q?335?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SqlServer/Curd/SqlServerSelectTest.cs | 2 +- .../SqlServer/Curd/SqlServerSelectTest.cs | 2 +- .../SqlServer/OdbcSqlServerExpression.cs | 26 +++++++++++++------ .../SqlServerExpression.cs | 25 ++++++++++++------ 4 files changed, 37 insertions(+), 18 deletions(-) diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs index ff5031e9..ffd98967 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs @@ -876,7 +876,7 @@ FROM [tb_topic22] a", subquery); 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 (((cast(a.[Id] as nvarchar)) in (SELECT b.[Title] +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(); } diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs index d21f844e..dd8daa73 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs @@ -925,7 +925,7 @@ FROM [tb_topic22] a", subquery); 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 (((cast(a.[Id] as nvarchar)) in (SELECT b.[Title] +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(); } diff --git a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs index 086a6daf..1f4bb307 100644 --- a/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs +++ b/Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs @@ -36,7 +36,10 @@ namespace FreeSql.Odbc.SqlServer case "System.Int64": return $"cast({getExp(operandExp)} as bigint)"; case "System.SByte": return $"cast({getExp(operandExp)} as tinyint)"; case "System.Single": return $"cast({getExp(operandExp)} as decimal(14,7))"; - case "System.String": return operandExp.Type.NullableTypeOrThis() == typeof(Guid) ? $"cast({getExp(operandExp)} as varchar(36))" : $"cast({getExp(operandExp)} as nvarchar)"; + case "System.String": + return gentype == typeof(Guid) ? + $"cast({getExp(operandExp)} as varchar(36))" : + $"cast({getExp(operandExp)} as nvarchar{(gentype.IsNumberType() || gentype.IsEnum ? "(100)" : "(max)")})"; case "System.UInt16": return $"cast({getExp(operandExp)} as smallint)"; case "System.UInt32": return $"cast({getExp(operandExp)} as int)"; case "System.UInt64": return $"cast({getExp(operandExp)} as bigint)"; @@ -86,7 +89,10 @@ namespace FreeSql.Odbc.SqlServer if (callExp.Method.DeclaringType.IsNumberType()) return "rand()"; return null; case "ToString": - if (callExp.Object != null) return callExp.Arguments.Count == 0 ? (callExp.Object.Type.NullableTypeOrThis() == typeof(Guid) ? $"cast({getExp(callExp.Object)} as varchar(36))" : $"cast({getExp(callExp.Object)} as nvarchar)") : null; + var gentype2 = callExp.Object.Type.NullableTypeOrThis(); + if (callExp.Object != null) return callExp.Arguments.Count == 0 ? (gentype2 == typeof(Guid) ? + $"cast({getExp(callExp.Object)} as varchar(36))" : + $"cast({getExp(callExp.Object)} as nvarchar{(gentype2.IsNumberType() || gentype2.IsEnum ? "(100)" : "(max)")})") : null; return null; } @@ -262,10 +268,10 @@ namespace FreeSql.Odbc.SqlServer 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, "%") : $"(cast({args0Value} as nvarchar)+'%')")}"; - if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%'+cast({args0Value} as nvarchar))")}"; + if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(cast({args0Value} as nvarchar(max))+'%')")}"; + if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%'+cast({args0Value} as nvarchar(max)))")}"; if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}"; - return $"({left}) LIKE ('%'+cast({args0Value} as nvarchar)+'%')"; + return $"({left}) LIKE ('%'+cast({args0Value} as nvarchar(max))+'%')"; case "ToLower": return $"lower({left})"; case "ToUpper": return $"upper({left})"; case "Substring": @@ -336,7 +342,7 @@ namespace FreeSql.Odbc.SqlServer switch (exp.Method.Name) { case "Compare": return $"({getExp(exp.Arguments[0])} - ({getExp(exp.Arguments[1])}))"; - case "DaysInMonth": return $"datepart(day, dateadd(day, -1, dateadd(month, 1, cast({getExp(exp.Arguments[0])} as varchar) + '-' + cast({getExp(exp.Arguments[1])} as varchar) + '-1')))"; + case "DaysInMonth": return $"datepart(day, dateadd(day, -1, dateadd(month, 1, cast({getExp(exp.Arguments[0])} as varchar(100)) + '-' + cast({getExp(exp.Arguments[1])} as varchar(100)) + '-1')))"; case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})"; case "IsLeapYear": @@ -454,7 +460,7 @@ namespace FreeSql.Odbc.SqlServer case "Subtract": return $"({left}-({args1}))"; case "Equals": return $"({left} = {args1})"; case "CompareTo": return $"({left}-({args1}))"; - case "ToString": return $"cast({left} as varchar)"; + case "ToString": return $"cast({left} as varchar(100))"; } } return null; @@ -477,7 +483,11 @@ namespace FreeSql.Odbc.SqlServer case "ToInt64": return $"cast({getExp(exp.Arguments[0])} as bigint)"; case "ToSByte": return $"cast({getExp(exp.Arguments[0])} as tinyint)"; case "ToSingle": return $"cast({getExp(exp.Arguments[0])} as decimal(14,7))"; - case "ToString": return exp.Arguments[0].Type.NullableTypeOrThis() == typeof(Guid) ? $"cast({getExp(exp.Arguments[0])} as varchar(36))" : $"cast({getExp(exp.Arguments[0])} as nvarchar)"; + case "ToString": + var gentype = exp.Arguments[0].Type.NullableTypeOrThis(); + return gentype == typeof(Guid) ? + $"cast({getExp(exp.Arguments[0])} as varchar(36))" : + $"cast({getExp(exp.Arguments[0])} as nvarchar{(gentype.IsNumberType() || gentype.IsEnum ? "(100)" : "(max)")})"; case "ToUInt16": return $"cast({getExp(exp.Arguments[0])} as smallint)"; case "ToUInt32": return $"cast({getExp(exp.Arguments[0])} as int)"; case "ToUInt64": return $"cast({getExp(exp.Arguments[0])} as bigint)"; diff --git a/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs b/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs index a657b039..78f44002 100644 --- a/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs +++ b/Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs @@ -36,7 +36,9 @@ namespace FreeSql.SqlServer case "System.Int64": return $"cast({getExp(operandExp)} as bigint)"; case "System.SByte": return $"cast({getExp(operandExp)} as tinyint)"; case "System.Single": return $"cast({getExp(operandExp)} as decimal(14,7))"; - case "System.String": return operandExp.Type.NullableTypeOrThis() == typeof(Guid) ? $"cast({getExp(operandExp)} as varchar(36))" : $"cast({getExp(operandExp)} as nvarchar)"; + case "System.String": return gentype == typeof(Guid) ? + $"cast({getExp(operandExp)} as varchar(36))" : + $"cast({getExp(operandExp)} as nvarchar{(gentype.IsNumberType() || gentype.IsEnum ? "(100)" : "(max)")})"; case "System.UInt16": return $"cast({getExp(operandExp)} as smallint)"; case "System.UInt32": return $"cast({getExp(operandExp)} as int)"; case "System.UInt64": return $"cast({getExp(operandExp)} as bigint)"; @@ -86,7 +88,10 @@ namespace FreeSql.SqlServer if (callExp.Method.DeclaringType.IsNumberType()) return "rand()"; return null; case "ToString": - if (callExp.Object != null) return callExp.Arguments.Count == 0 ? (callExp.Object.Type.NullableTypeOrThis() == typeof(Guid) ? $"cast({getExp(callExp.Object)} as varchar(36))" : $"cast({getExp(callExp.Object)} as nvarchar)") : null; + var gentype2 = callExp.Object.Type.NullableTypeOrThis(); + if (callExp.Object != null) return callExp.Arguments.Count == 0 ? (gentype2 == typeof(Guid) ? + $"cast({getExp(callExp.Object)} as varchar(36))" : + $"cast({getExp(callExp.Object)} as nvarchar{(gentype2.IsNumberType() || gentype2.IsEnum ? "(100)" : "(max)")})") : null; return null; } @@ -262,10 +267,10 @@ namespace FreeSql.SqlServer 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, "%") : $"(cast({args0Value} as nvarchar)+'%')")}"; - if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%'+cast({args0Value} as nvarchar))")}"; + if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(cast({args0Value} as nvarchar(max))+'%')")}"; + if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%'+cast({args0Value} as nvarchar(max)))")}"; if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}"; - return $"({left}) LIKE ('%'+cast({args0Value} as nvarchar)+'%')"; + return $"({left}) LIKE ('%'+cast({args0Value} as nvarchar(max))+'%')"; case "ToLower": return $"lower({left})"; case "ToUpper": return $"upper({left})"; case "Substring": @@ -336,7 +341,7 @@ namespace FreeSql.SqlServer switch (exp.Method.Name) { case "Compare": return $"({getExp(exp.Arguments[0])} - ({getExp(exp.Arguments[1])}))"; - case "DaysInMonth": return $"datepart(day, dateadd(day, -1, dateadd(month, 1, cast({getExp(exp.Arguments[0])} as varchar) + '-' + cast({getExp(exp.Arguments[1])} as varchar) + '-1')))"; + case "DaysInMonth": return $"datepart(day, dateadd(day, -1, dateadd(month, 1, cast({getExp(exp.Arguments[0])} as varchar(100)) + '-' + cast({getExp(exp.Arguments[1])} as varchar(100)) + '-1')))"; case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})"; case "IsLeapYear": @@ -452,7 +457,7 @@ namespace FreeSql.SqlServer case "Subtract": return $"({left}-({args1}))"; case "Equals": return $"({left} = {args1})"; case "CompareTo": return $"({left}-({args1}))"; - case "ToString": return $"cast({left} as varchar)"; + case "ToString": return $"cast({left} as varchar(100))"; } } return null; @@ -475,7 +480,11 @@ namespace FreeSql.SqlServer case "ToInt64": return $"cast({getExp(exp.Arguments[0])} as bigint)"; case "ToSByte": return $"cast({getExp(exp.Arguments[0])} as tinyint)"; case "ToSingle": return $"cast({getExp(exp.Arguments[0])} as decimal(14,7))"; - case "ToString": return exp.Arguments[0].Type.NullableTypeOrThis() == typeof(Guid) ? $"cast({getExp(exp.Arguments[0])} as varchar(36))" : $"cast({getExp(exp.Arguments[0])} as nvarchar)"; + case "ToString": + var gentype = exp.Arguments[0].Type.NullableTypeOrThis(); + return gentype == typeof(Guid) ? + $"cast({getExp(exp.Arguments[0])} as varchar(36))" : + $"cast({getExp(exp.Arguments[0])} as nvarchar{(gentype.IsNumberType() || gentype.IsEnum ? "(100)" : "(max)")})"; case "ToUInt16": return $"cast({getExp(exp.Arguments[0])} as smallint)"; case "ToUInt32": return $"cast({getExp(exp.Arguments[0])} as int)"; case "ToUInt64": return $"cast({getExp(exp.Arguments[0])} as bigint)";