Skip to content

Commit

Permalink
#253 refactoring FromTableInfoParser
Browse files Browse the repository at this point in the history
  • Loading branch information
mk3008 committed Nov 5, 2023
1 parent 89fc037 commit 491f163
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 42 deletions.
89 changes: 48 additions & 41 deletions src/QueryBuilderByLinq/Analysis/FromTableInfoParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ public static class FromTableInfoParser
var method = (MethodCallExpression)exp;
if (method.Arguments.Count != 2) return null;

var queryExpression = method.GetArgument<ConstantExpression>(0);
if (queryExpression == null) return null;
var ce = method.GetArgument<ConstantExpression>(0);
if (ce == null) return null;

var operand = method.GetArgument<UnaryExpression>(1).GetOperand<LambdaExpression>();
if (operand == null) return null;
Expand All @@ -45,23 +45,12 @@ public static class FromTableInfoParser
var parameter = operand.Parameters[0];
if (parameter.Type == typeof(DualTable)) return null;

if (queryExpression.Value is IQueryable q && q.Provider is TableQuery provider)
if (TryParse(ce, parameter, out var f))
{
// root syntax
if (provider.InnerQuery != null)
{
return new FromTableInfo(provider.InnerQuery.ToQueryAsPostgres(), parameter.Name!);
}
else
{
return new FromTableInfo(provider.TableName, parameter.Name!);
}
}
else
{
// nest sytax
return new FromTableInfo(parameter.ToTypeTable(), parameter.Name!);
return f;
}
// nest sytax
return new FromTableInfo(parameter.ToTypeTable(), parameter.Name!);
}

/// <summary>
Expand All @@ -77,42 +66,60 @@ public static class FromTableInfoParser
var method = (MethodCallExpression)exp;
if (method.Arguments.Count != 3) return null;

//query
var lambda = method.GetArgument<UnaryExpression>(1).GetOperand<LambdaExpression>();
if (lambda == null) return null;

var body = lambda.GetBody<MethodCallExpression>();
var ce = method.GetArgument<ConstantExpression>(0);
var body = method.GetArgument<UnaryExpression>(1).GetOperand<LambdaExpression>().GetBody<MethodCallExpression>(); ;
if (body == null) return null;

// no relation pattern.
var operand = method.GetArgument<UnaryExpression>(2).GetOperand<LambdaExpression>();
if (operand == null) return null;
if (operand.Parameters.Count != 2) return null;
var parameter = operand.Parameters[1];

if (body.Method.Name == nameof(Sql.FromTable))
{
// no relation pattern.
var operand = method.GetArgument<UnaryExpression>(2).GetOperand<LambdaExpression>();
if (operand == null) return null;
if (operand.Parameters.Count != 2) return null;

var parameter = operand.Parameters[1];
return ParseCore3ArgumentsFromTable(body, parameter);
}
else if (body.Method.Name == nameof(Sql.InnerJoinTable) || body.Method.Name == nameof(Sql.LeftJoinTable) || body.Method.Name == nameof(Sql.CrossJoinTable))
else if (ce != null && (body.Method.Name == nameof(Sql.InnerJoinTable) || body.Method.Name == nameof(Sql.LeftJoinTable) || body.Method.Name == nameof(Sql.CrossJoinTable)))
{
/*
has relation pattern.
'body' is relation conditions.
'parameter' is relation alias.
*/

//query
lambda = method.GetArgument<UnaryExpression>(2).GetOperand<LambdaExpression>();
if (lambda == null || lambda.Parameters.Count != 2) return null;

var prm = lambda.Parameters[0];
return new FromTableInfo(prm.ToTypeTable(), prm.Name!);
// has relation pattern.
var operand = method.GetArgument<UnaryExpression>(2).GetOperand<LambdaExpression>();
if (operand == null || operand.Parameters.Count != 2) return null;

var parameter = operand.Parameters[0];

if (TryParse(ce, parameter, out var f))
{
return f;
}
return new FromTableInfo(parameter.ToTypeTable(), parameter.Name!);
}

return null;
}

private static bool TryParse(ConstantExpression methodBody, ParameterExpression parameter, out FromTableInfo from)
{
from = null!;

if (methodBody.Value is IQueryable q && q.Provider is TableQuery provider)
{
if (provider.InnerQuery != null)
{
// subquery pattern.
from = new FromTableInfo(provider.InnerQuery.ToQueryAsPostgres(), parameter.Name!);
return true;
}
else
{
// override table name pattern.
from = new FromTableInfo(provider.TableName, parameter.Name!);
return true;
}
}
return false;
}

private static FromTableInfo? ParseCore3ArgumentsFromTable(MethodCallExpression body, ParameterExpression parameter)
{
if (body.Method.Name != nameof(Sql.FromTable)) throw new InvalidProgramException();
Expand Down
21 changes: 20 additions & 1 deletion test/QueryBuilderByLinq.Test/Analysis/JoinTableInfoParserTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public void NoRelationTest()
}

[Fact]
public void InnerJoinTest()
public void InnerJoinTypeTableTest()
{
var query = from s in FromTable<sale>()
from a in InnerJoinTable<article>(x => s.article_id == x.article_id)
Expand All @@ -48,6 +48,25 @@ from a in InnerJoinTable<article>(x => s.article_id == x.article_id)
Assert.Empty(joins);
}

[Fact]
public void InnerJoinStringTableTest()
{
var query = from s in FromTable<sale>("sales")
from a in InnerJoinTable<article>("articles", x => s.article_id == x.article_id)
select a;

Monitor.Log(query);

var from = FromTableInfoParser.Parse(query.Expression);
Assert.Equal("s", from?.Alias);
Assert.Equal("sales AS s", from?.ToSelectable().ToText());


var joins = JoinTableInfoParser.Parse(query.Expression);

Assert.Empty(joins);
}

[Fact]
public void LeftJoinTest()
{
Expand Down

0 comments on commit 491f163

Please sign in to comment.