Skip to content

Commit dc8f575

Browse files
2881028810
authored andcommitted
- 修复 sqlserver 解析 cast(.. as nvarchar) 截断长度 30 的问题;#335
1 parent 889af5e commit dc8f575

File tree

4 files changed

+37
-18
lines changed

4 files changed

+37
-18
lines changed

FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,7 @@ public void WhereIn()
876876
var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql();
877877
Assert.Equal(@"SELECT a.[Id], a.[Clicks], a.[TypeGuid], a.[Title], a.[CreateTime]
878878
FROM [tb_topic22] a
879-
WHERE (((cast(a.[Id] as nvarchar)) in (SELECT b.[Title]
879+
WHERE (((cast(a.[Id] as nvarchar(100))) in (SELECT b.[Title]
880880
FROM [tb_topic22] b)))", subquery);
881881
var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList();
882882
}

FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ public void WhereIn()
925925
var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql();
926926
Assert.Equal(@"SELECT a.[Id], a.[Clicks], a.[TypeGuid], a.[Title], a.[CreateTime]
927927
FROM [tb_topic22] a
928-
WHERE (((cast(a.[Id] as nvarchar)) in (SELECT b.[Title]
928+
WHERE (((cast(a.[Id] as nvarchar(100))) in (SELECT b.[Title]
929929
FROM [tb_topic22] b)))", subquery);
930930
var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList();
931931
}

Providers/FreeSql.Provider.Odbc/SqlServer/OdbcSqlServerExpression.cs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ public override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc)
3636
case "System.Int64": return $"cast({getExp(operandExp)} as bigint)";
3737
case "System.SByte": return $"cast({getExp(operandExp)} as tinyint)";
3838
case "System.Single": return $"cast({getExp(operandExp)} as decimal(14,7))";
39-
case "System.String": return operandExp.Type.NullableTypeOrThis() == typeof(Guid) ? $"cast({getExp(operandExp)} as varchar(36))" : $"cast({getExp(operandExp)} as nvarchar)";
39+
case "System.String":
40+
return gentype == typeof(Guid) ?
41+
$"cast({getExp(operandExp)} as varchar(36))" :
42+
$"cast({getExp(operandExp)} as nvarchar{(gentype.IsNumberType() || gentype.IsEnum ? "(100)" : "(max)")})";
4043
case "System.UInt16": return $"cast({getExp(operandExp)} as smallint)";
4144
case "System.UInt32": return $"cast({getExp(operandExp)} as int)";
4245
case "System.UInt64": return $"cast({getExp(operandExp)} as bigint)";
@@ -86,7 +89,10 @@ public override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc)
8689
if (callExp.Method.DeclaringType.IsNumberType()) return "rand()";
8790
return null;
8891
case "ToString":
89-
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;
92+
var gentype2 = callExp.Object.Type.NullableTypeOrThis();
93+
if (callExp.Object != null) return callExp.Arguments.Count == 0 ? (gentype2 == typeof(Guid) ?
94+
$"cast({getExp(callExp.Object)} as varchar(36))" :
95+
$"cast({getExp(callExp.Object)} as nvarchar{(gentype2.IsNumberType() || gentype2.IsEnum ? "(100)" : "(max)")})") : null;
9096
return null;
9197
}
9298

@@ -262,10 +268,10 @@ public override string ExpressionLambdaToSqlCallString(MethodCallExpression exp,
262268
case "Contains":
263269
var args0Value = getExp(exp.Arguments[0]);
264270
if (args0Value == "NULL") return $"({left}) IS NULL";
265-
if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(cast({args0Value} as nvarchar)+'%')")}";
266-
if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%'+cast({args0Value} as nvarchar))")}";
271+
if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(cast({args0Value} as nvarchar(max))+'%')")}";
272+
if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%'+cast({args0Value} as nvarchar(max)))")}";
267273
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
268-
return $"({left}) LIKE ('%'+cast({args0Value} as nvarchar)+'%')";
274+
return $"({left}) LIKE ('%'+cast({args0Value} as nvarchar(max))+'%')";
269275
case "ToLower": return $"lower({left})";
270276
case "ToUpper": return $"upper({left})";
271277
case "Substring":
@@ -336,7 +342,7 @@ public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression ex
336342
switch (exp.Method.Name)
337343
{
338344
case "Compare": return $"({getExp(exp.Arguments[0])} - ({getExp(exp.Arguments[1])}))";
339-
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')))";
345+
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')))";
340346
case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})";
341347

342348
case "IsLeapYear":
@@ -454,7 +460,7 @@ public override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression ex
454460
case "Subtract": return $"({left}-({args1}))";
455461
case "Equals": return $"({left} = {args1})";
456462
case "CompareTo": return $"({left}-({args1}))";
457-
case "ToString": return $"cast({left} as varchar)";
463+
case "ToString": return $"cast({left} as varchar(100))";
458464
}
459465
}
460466
return null;
@@ -477,7 +483,11 @@ public override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp
477483
case "ToInt64": return $"cast({getExp(exp.Arguments[0])} as bigint)";
478484
case "ToSByte": return $"cast({getExp(exp.Arguments[0])} as tinyint)";
479485
case "ToSingle": return $"cast({getExp(exp.Arguments[0])} as decimal(14,7))";
480-
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)";
486+
case "ToString":
487+
var gentype = exp.Arguments[0].Type.NullableTypeOrThis();
488+
return gentype == typeof(Guid) ?
489+
$"cast({getExp(exp.Arguments[0])} as varchar(36))" :
490+
$"cast({getExp(exp.Arguments[0])} as nvarchar{(gentype.IsNumberType() || gentype.IsEnum ? "(100)" : "(max)")})";
481491
case "ToUInt16": return $"cast({getExp(exp.Arguments[0])} as smallint)";
482492
case "ToUInt32": return $"cast({getExp(exp.Arguments[0])} as int)";
483493
case "ToUInt64": return $"cast({getExp(exp.Arguments[0])} as bigint)";

Providers/FreeSql.Provider.SqlServer/SqlServerExpression.cs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ public override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc)
3636
case "System.Int64": return $"cast({getExp(operandExp)} as bigint)";
3737
case "System.SByte": return $"cast({getExp(operandExp)} as tinyint)";
3838
case "System.Single": return $"cast({getExp(operandExp)} as decimal(14,7))";
39-
case "System.String": return operandExp.Type.NullableTypeOrThis() == typeof(Guid) ? $"cast({getExp(operandExp)} as varchar(36))" : $"cast({getExp(operandExp)} as nvarchar)";
39+
case "System.String": return gentype == typeof(Guid) ?
40+
$"cast({getExp(operandExp)} as varchar(36))" :
41+
$"cast({getExp(operandExp)} as nvarchar{(gentype.IsNumberType() || gentype.IsEnum ? "(100)" : "(max)")})";
4042
case "System.UInt16": return $"cast({getExp(operandExp)} as smallint)";
4143
case "System.UInt32": return $"cast({getExp(operandExp)} as int)";
4244
case "System.UInt64": return $"cast({getExp(operandExp)} as bigint)";
@@ -86,7 +88,10 @@ public override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc)
8688
if (callExp.Method.DeclaringType.IsNumberType()) return "rand()";
8789
return null;
8890
case "ToString":
89-
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;
91+
var gentype2 = callExp.Object.Type.NullableTypeOrThis();
92+
if (callExp.Object != null) return callExp.Arguments.Count == 0 ? (gentype2 == typeof(Guid) ?
93+
$"cast({getExp(callExp.Object)} as varchar(36))" :
94+
$"cast({getExp(callExp.Object)} as nvarchar{(gentype2.IsNumberType() || gentype2.IsEnum ? "(100)" : "(max)")})") : null;
9095
return null;
9196
}
9297

@@ -262,10 +267,10 @@ public override string ExpressionLambdaToSqlCallString(MethodCallExpression exp,
262267
case "Contains":
263268
var args0Value = getExp(exp.Arguments[0]);
264269
if (args0Value == "NULL") return $"({left}) IS NULL";
265-
if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(cast({args0Value} as nvarchar)+'%')")}";
266-
if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%'+cast({args0Value} as nvarchar))")}";
270+
if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(cast({args0Value} as nvarchar(max))+'%')")}";
271+
if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%'+cast({args0Value} as nvarchar(max)))")}";
267272
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
268-
return $"({left}) LIKE ('%'+cast({args0Value} as nvarchar)+'%')";
273+
return $"({left}) LIKE ('%'+cast({args0Value} as nvarchar(max))+'%')";
269274
case "ToLower": return $"lower({left})";
270275
case "ToUpper": return $"upper({left})";
271276
case "Substring":
@@ -336,7 +341,7 @@ public override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression ex
336341
switch (exp.Method.Name)
337342
{
338343
case "Compare": return $"({getExp(exp.Arguments[0])} - ({getExp(exp.Arguments[1])}))";
339-
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')))";
344+
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')))";
340345
case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})";
341346

342347
case "IsLeapYear":
@@ -452,7 +457,7 @@ public override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression ex
452457
case "Subtract": return $"({left}-({args1}))";
453458
case "Equals": return $"({left} = {args1})";
454459
case "CompareTo": return $"({left}-({args1}))";
455-
case "ToString": return $"cast({left} as varchar)";
460+
case "ToString": return $"cast({left} as varchar(100))";
456461
}
457462
}
458463
return null;
@@ -475,7 +480,11 @@ public override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp
475480
case "ToInt64": return $"cast({getExp(exp.Arguments[0])} as bigint)";
476481
case "ToSByte": return $"cast({getExp(exp.Arguments[0])} as tinyint)";
477482
case "ToSingle": return $"cast({getExp(exp.Arguments[0])} as decimal(14,7))";
478-
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)";
483+
case "ToString":
484+
var gentype = exp.Arguments[0].Type.NullableTypeOrThis();
485+
return gentype == typeof(Guid) ?
486+
$"cast({getExp(exp.Arguments[0])} as varchar(36))" :
487+
$"cast({getExp(exp.Arguments[0])} as nvarchar{(gentype.IsNumberType() || gentype.IsEnum ? "(100)" : "(max)")})";
479488
case "ToUInt16": return $"cast({getExp(exp.Arguments[0])} as smallint)";
480489
case "ToUInt32": return $"cast({getExp(exp.Arguments[0])} as int)";
481490
case "ToUInt64": return $"cast({getExp(exp.Arguments[0])} as bigint)";

0 commit comments

Comments
 (0)