Permalink
Browse files

Handle selecting constant expressions in custom select list

  • Loading branch information...
mythz committed Nov 27, 2018
1 parent 1ef9185 commit 93c125104da549be7cd8ae34d8d85b6640f2f333
@@ -1894,13 +1894,39 @@ protected virtual object VisitNew(NewExpression nex)
return CachedExpressionCompiler.Evaluate(nex);
}

bool IsLambdaArg(Expression expr)
{
if (expr is ParameterExpression pe)
return IsLambdaArg(pe.Name);
if (expr is UnaryExpression ue && ue.Operand is ParameterExpression uepe)
return IsLambdaArg(uepe.Name);
return false;
}

bool IsLambdaArg(string name)
{
var args = originalLambda?.Parameters;
if (args != null)
{
foreach (var x in args)
{
if (x.Name == name)
return true;
}
}
return false;
}

private object SetAnonTypePropertyNamesForSelectExpression(object expr, Expression arg, MemberInfo member)
{
// When selecting a column use the anon type property name, rather than the table property name, as the returned column name
if (arg is MemberExpression propExpr && IsLambdaArg(propExpr.Expression))
{
if (propExpr.Member.Name != member.Name)
return new SelectItemExpression(DialectProvider, expr.ToString(), member.Name);

MemberExpression propertyExpr;
if ((propertyExpr = arg as MemberExpression) != null && propertyExpr.Member.Name != member.Name)
return new SelectItemExpression(DialectProvider, expr.ToString(), member.Name);
return expr;
}

// When selecting an entire table use the anon type property name as a prefix for the returned column name
// to allow the caller to distinguish properties with the same names from different tables
@@ -1933,12 +1959,19 @@ private object SetAnonTypePropertyNamesForSelectExpression(object expr, Expressi
var mi = methodCallExpr?.Method;
var declareType = mi?.DeclaringType;
if (declareType != null && declareType.Name == "Sql" && mi.Name != "Desc" && mi.Name != "Asc" && mi.Name != "As" && mi.Name != "AllFields")
return new PartialSqlString(expr + " AS " + member.Name); // new { Alias = Sql.Count("*") }
return new PartialSqlString(expr + " AS " + member.Name); // new { Alias = Sql.Count("*") }

if (arg is ConditionalExpression || // new { Alias = x.Value > 1 ? 1 : x.Value }
arg is BinaryExpression) // new { Alias = x.First + " " + x.Last }
if (arg is ConditionalExpression ce || // new { Alias = x.Value > 1 ? 1 : x.Value }
arg is BinaryExpression be || // new { Alias = x.First + " " + x.Last }
arg is MemberExpression me || // new { Alias = DateTime.UtcNow }
arg is ConstantExpression ct) // new { Alias = 1 }
{
return new PartialSqlString(expr + " AS " + member.Name);
IOrmLiteConverter converter;
var strExpr = !(expr is PartialSqlString) && (converter = DialectProvider.GetConverterBestMatch(expr.GetType())) != null
? converter.ToQuotedString(expr.GetType(), expr)
: expr.ToString();

return new PartialSqlString(strExpr + " AS " + member.Name);
}

return expr;
@@ -466,7 +466,7 @@ public void Can_Where_using_constant_orderBy2()
}

[Test]
public void Can_Where_using_constant_coniditionalOrderBy()
public void Can_Where_using_constant_conditionalOrderBy()
{
System.Linq.Expressions.Expression<Func<WaybillBase, bool>> filter = x => !x.BoolVirtProperty &&
x.VirtPropertyEmpty != "WaybillVirtPropertyValue" &&
@@ -502,7 +502,7 @@ public void Can_Select_using_constant()
}

[Test]
public void Can_Where_using_guid_constant_coniditional()
public void Can_Where_using_guid_constant_conditional()
{
System.Linq.Expressions.Expression<Func<WaybillBase, bool>> filter = x => (x.Number > 0 ? x.GuidVirtProperty : x.Id1) == Guid.Parse("00000000-0000-0000-0000-000000000000");
var q = Db.From<WaybillBase>().Where(filter);
@@ -511,7 +511,7 @@ public void Can_Where_using_guid_constant_coniditional()
}

[Test]
public void Can_Where_using_null_constant_coniditional()
public void Can_Where_using_null_constant_conditional()
{
System.Linq.Expressions.Expression<Func<WaybillBase, bool>> filter = x => (x.Number == 0 ? x.VirtPropertyNull : x.Name) == "first";
var q = Db.From<WaybillBase>().Where(filter);
@@ -520,7 +520,7 @@ public void Can_Where_using_null_constant_coniditional()
}

[Test]
public void Can_Where_using_datetime_constant_coniditional()
public void Can_Where_using_datetime_constant_conditional()
{
System.Linq.Expressions.Expression<Func<WaybillBase, bool>> filter = x => (x.Number > 0 ? x.DateVirtProperty : x.Date) == DateTime.Parse("2000-01-01");
var q = Db.From<WaybillBase>().Where(filter);
@@ -529,7 +529,7 @@ public void Can_Where_using_datetime_constant_coniditional()
}

[Test]
public void Can_Where_using_int_constant_coniditional()
public void Can_Where_using_int_constant_conditional()
{
System.Linq.Expressions.Expression<Func<WaybillBase, bool>> filter = x => (x.Number > 0 ? x.IntVirtProperty : x.Number) == 5;
var q = Db.From<WaybillBase>().Where(filter);
@@ -538,7 +538,7 @@ public void Can_Where_using_int_constant_coniditional()
}

[Test]
public void Can_Where_using_decimal_constant_coniditional()
public void Can_Where_using_decimal_constant_conditional()
{
System.Linq.Expressions.Expression<Func<WaybillBase, bool>> filter = x => (x.Number > 0 ? x.DecimalVirtProperty : x.Amount) == 10M;
var q = Db.From<WaybillBase>().Where(filter);
@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using NUnit.Framework;
using ServiceStack.DataAnnotations;
@@ -240,5 +242,32 @@ public void Can_Count_Distinct()
}
}

[Test]
public void Does_select_aliases_on_constant_expressions()
{
using (var db = OpenDbConnection())
{
db.DropAndCreateTable<LetterFrequency>();
db.Insert(new LetterFrequency { Letter = "A" });

var q = db.From<LetterFrequency>()
.Select(x => new
{
param = 1,
descr = x.Letter,
str = "hi",
date = DateTime.Now
});

var results = db.Select<Dictionary<string,object>>(q)[0];

Assert.That(results["param"], Is.EqualTo(1));
Assert.That(results["descr"], Is.EqualTo("A"));
Assert.That(results["str"], Is.EqualTo("hi"));
Assert.That(DateTime.Parse(results["date"].ToString()).Date, Is.EqualTo(DateTime.Now.Date));
}
}


}
}

0 comments on commit 93c1251

Please sign in to comment.