Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit 859118b

Browse files
authored
Merge pull request #521 from OlegNadymov/master
Extracted method for checking Expression for the parameter.
2 parents 795bc73 + c6fe8aa commit 859118b

File tree

2 files changed

+241
-36
lines changed

2 files changed

+241
-36
lines changed

src/ServiceStack.OrmLite/Expressions/SqlExpression.cs

Lines changed: 111 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public abstract partial class SqlExpression<T> : ISqlExpression, IHasUntypedSqlE
4141
public bool PrefixFieldWithTableName { get; set; }
4242
public bool WhereStatementWithoutWhereString { get; set; }
4343
public IOrmLiteDialectProvider DialectProvider { get; set; }
44-
public List<IDbDataParameter> Params { get; set; }
44+
public List<IDbDataParameter> Params { get; set; }
4545

4646
protected string Sep
4747
{
@@ -107,7 +107,7 @@ public virtual SqlExpression<T> Select(string selectExpression)
107107
{
108108
if (selectExpression != null)
109109
selectExpression.SqlVerifyFragment();
110-
110+
111111
return UnsafeSelect(selectExpression);
112112
}
113113

@@ -590,7 +590,7 @@ private SqlExpression<T> OrderByFields(string orderBySuffix, string[] fieldNames
590590
foreach (var fieldName in fieldNames)
591591
{
592592
var reverse = fieldName.StartsWith("-");
593-
var useSuffix = reverse
593+
var useSuffix = reverse
594594
? (orderBySuffix == OrderBySuffix.Asc ? OrderBySuffix.Desc : OrderBySuffix.Asc)
595595
: orderBySuffix;
596596
var useName = reverse ? fieldName.Substring(1) : fieldName;
@@ -980,7 +980,7 @@ public virtual void PrepareUpdateStatement(IDbCommand dbCmd, T item, bool exclud
980980
{
981981
if (fieldDef.ShouldSkipUpdate()) continue;
982982
if (fieldDef.IsRowVersion) continue;
983-
if (UpdateFields.Count > 0
983+
if (UpdateFields.Count > 0
984984
&& !UpdateFields.Contains(fieldDef.Name)) continue; // added
985985

986986
var value = fieldDef.GetValue(item);
@@ -1238,17 +1238,13 @@ protected virtual object VisitBinary(BinaryExpression b)
12381238
var operand = BindOperant(b.NodeType); //sep= " " ??
12391239
if (operand == "AND" || operand == "OR")
12401240
{
1241-
var m = b.Left as MemberExpression;
1242-
if (m != null && m.Expression != null
1243-
&& m.Expression.NodeType == ExpressionType.Parameter)
1244-
left = new PartialSqlString(string.Format("{0}={1}", VisitMemberAccess(m), GetQuotedTrueValue()));
1241+
if (IsNeedCompareToTrue(b.Left))
1242+
left = new PartialSqlString(string.Format("{0}={1}", VisitMemberAccess((MemberExpression) b.Left), GetQuotedTrueValue()));
12451243
else
12461244
left = Visit(b.Left);
12471245

1248-
m = b.Right as MemberExpression;
1249-
if (m != null && m.Expression != null
1250-
&& m.Expression.NodeType == ExpressionType.Parameter)
1251-
right = new PartialSqlString(string.Format("{0}={1}", VisitMemberAccess(m), GetQuotedTrueValue()));
1246+
if (IsNeedCompareToTrue(b.Right))
1247+
right = new PartialSqlString(string.Format("{0}={1}", VisitMemberAccess((MemberExpression) b.Right), GetQuotedTrueValue()));
12521248
else
12531249
right = Visit(b.Right);
12541250

@@ -1355,6 +1351,90 @@ protected virtual object VisitBinary(BinaryExpression b)
13551351
}
13561352
}
13571353

1354+
/// <summary>
1355+
/// Determines whether the expression is the parameter inside MemberExpression which should be compared with TrueExpression.
1356+
/// </summary>
1357+
/// <param name="e">The specified expression.</param>
1358+
/// <returns>Returns true if the specified expression is the parameter inside MemberExpression which should be compared with TrueExpression;
1359+
/// otherwise, false.</returns>
1360+
protected virtual bool IsNeedCompareToTrue(Expression e)
1361+
{
1362+
if (!(e is MemberExpression)) return false;
1363+
1364+
var m = (MemberExpression)e;
1365+
1366+
if (m.Member.DeclaringType.IsNullableType() &&
1367+
m.Member.Name == "HasValue") //nameof(Nullable<bool>.HasValue))
1368+
return false;
1369+
1370+
return IsParameterAccess(m);
1371+
}
1372+
1373+
/// <summary>
1374+
/// Determines whether the expression is the parameter.
1375+
/// </summary>
1376+
/// <param name="e">The specified expression.</param>
1377+
/// <returns>Returns true if the specified expression is parameter;
1378+
/// otherwise, false.</returns>
1379+
protected virtual bool IsParameterAccess(Expression e)
1380+
{
1381+
return CheckExpressionForTypes(e, new[] { ExpressionType.Parameter });
1382+
}
1383+
1384+
/// <summary>
1385+
/// Determines whether the expression is the parameter or convert.
1386+
/// </summary>
1387+
/// <param name="e">The specified expression.</param>
1388+
/// <returns>Returns true if the specified expression is parameter or convert;
1389+
/// otherwise, false.</returns>
1390+
protected virtual bool IsParameterOrConvertAccess(Expression e)
1391+
{
1392+
return CheckExpressionForTypes(e, new[] { ExpressionType.Parameter, ExpressionType.Convert });
1393+
}
1394+
1395+
protected bool CheckExpressionForTypes(Expression e, ExpressionType[] types)
1396+
{
1397+
while (e != null)
1398+
{
1399+
if (types.Contains(e.NodeType))
1400+
{
1401+
var isSubExprAccess = e is UnaryExpression &&
1402+
((UnaryExpression)e).Operand is IndexExpression;
1403+
1404+
if (!isSubExprAccess)
1405+
return true;
1406+
}
1407+
1408+
if (e is BinaryExpression)
1409+
{
1410+
if (CheckExpressionForTypes(((BinaryExpression)e).Left, types))
1411+
return true;
1412+
1413+
if (CheckExpressionForTypes(((BinaryExpression)e).Right, types))
1414+
return true;
1415+
}
1416+
1417+
if (e is MethodCallExpression)
1418+
{
1419+
for (int i = 0; i < ((MethodCallExpression)e).Arguments.Count; i++)
1420+
{
1421+
if (CheckExpressionForTypes(((MethodCallExpression)e).Arguments[0], types))
1422+
return true;
1423+
}
1424+
}
1425+
1426+
if (e is UnaryExpression)
1427+
{
1428+
if (CheckExpressionForTypes(((UnaryExpression)e).Operand, types))
1429+
return true;
1430+
}
1431+
1432+
e = e is MemberExpression ? ((MemberExpression)e).Expression : null;
1433+
}
1434+
1435+
return false;
1436+
}
1437+
13581438
private static void Swap(ref object left, ref object right)
13591439
{
13601440
var temp = right;
@@ -1403,19 +1483,14 @@ protected virtual object VisitMemberAccess(MemberExpression m)
14031483
throw new ArgumentException(string.Format("Expression '{0}' accesses unsupported property '{1}' of Nullable<T>", m, m.Member));
14041484
}
14051485

1406-
if (m.Expression.NodeType == ExpressionType.Parameter || m.Expression.NodeType == ExpressionType.Convert)
1407-
{
1408-
var isSubExprAccess = m.Expression is UnaryExpression &&
1409-
((UnaryExpression)m.Expression).Operand is IndexExpression;
1410-
if (!isSubExprAccess)
1411-
return GetMemberExpression(m);
1412-
}
1486+
if (IsParameterOrConvertAccess(m))
1487+
return GetMemberExpression(m);
14131488
}
14141489

14151490
return CachedExpressionCompiler.Evaluate(m);
14161491
}
14171492

1418-
private object GetMemberExpression(MemberExpression m)
1493+
protected virtual object GetMemberExpression(MemberExpression m)
14191494
{
14201495
var propertyInfo = m.Member as PropertyInfo;
14211496

@@ -1482,8 +1557,8 @@ private object SetAnonTypePropertyNamesForSelectExpression(object expr, Expressi
14821557
// to allow the caller to distinguish properties with the same names from different tables
14831558

14841559
var paramExpr = arg as ParameterExpression;
1485-
var selectList = paramExpr != null && paramExpr.Name != member.Name
1486-
? expr as SelectList
1560+
var selectList = paramExpr != null && paramExpr.Name != member.Name
1561+
? expr as SelectList
14871562
: null;
14881563
if (selectList != null)
14891564
{
@@ -1567,7 +1642,13 @@ protected virtual object VisitUnary(UnaryExpression u)
15671642
return GetNotValue(o);
15681643
case ExpressionType.Convert:
15691644
if (u.Method != null)
1645+
{
1646+
var e = u.Operand;
1647+
if (IsParameterAccess(e))
1648+
return Visit(e);
1649+
15701650
return CachedExpressionCompiler.Evaluate(u);
1651+
}
15711652
break;
15721653
}
15731654
return Visit(u.Operand);
@@ -1587,7 +1668,7 @@ protected virtual object VisitIndexExpression(IndexExpression e)
15871668
var list = oCollection as List<object>;
15881669
if (list != null)
15891670
return list[index];
1590-
1671+
15911672
throw new NotImplementedException("Unknown Expression: " + e);
15921673
}
15931674

@@ -1606,12 +1687,10 @@ private bool IsColumnAccess(MethodCallExpression m)
16061687
{
16071688
if (m.Object != null && m.Object as MethodCallExpression != null)
16081689
return IsColumnAccess(m.Object as MethodCallExpression);
1609-
1690+
16101691
var exp = m.Object as MemberExpression;
1611-
return exp != null
1612-
&& exp.Expression != null
1613-
&& IsJoinedTable(exp.Expression.Type)
1614-
&& exp.Expression.NodeType == ExpressionType.Parameter;
1692+
return IsParameterAccess(exp)
1693+
&& IsJoinedTable(exp.Expression.Type);
16151694
}
16161695

16171696
protected virtual object VisitMethodCall(MethodCallExpression m)
@@ -1732,11 +1811,11 @@ protected virtual string GetQuotedColumnName(ModelDefinition tableDef, string me
17321811
if (useFieldName)
17331812
{
17341813
var fd = tableDef.FieldDefinitions.FirstOrDefault(x => x.Name == memberName);
1735-
var fieldName = fd != null
1736-
? fd.FieldName
1814+
var fieldName = fd != null
1815+
? fd.FieldName
17371816
: memberName;
17381817

1739-
return PrefixFieldWithTableName
1818+
return PrefixFieldWithTableName
17401819
? DialectProvider.GetQuotedColumnName(tableDef, fieldName)
17411820
: DialectProvider.GetQuotedColumnName(fieldName);
17421821
}
@@ -1941,7 +2020,7 @@ protected string ConvertInExpressionToSql(MethodCallExpression m, object quotedC
19412020
string sqlIn = CreateInParamSql(inArgs);
19422021
return string.Format("{0} {1} ({2})", quotedColName, m.Method.Name, sqlIn);
19432022
}
1944-
2023+
19452024
var exprArg = argValue as ISqlExpression;
19462025
if (exprArg != null)
19472026
{

0 commit comments

Comments
 (0)