Skip to content

Commit

Permalink
Partial implementation of query compilation (#1)
Browse files Browse the repository at this point in the history
* Add link to source for Sql AST

* Remove generics from QueryParser, since it is not necessary

* Remove 'NotImplementedException'

* Remove new() and Table constraints until it becomes necessary

* Remove NoParameters from Union and Union All
  • Loading branch information
weelink committed Jul 17, 2019
1 parent b54d9e7 commit 8c589fa
Show file tree
Hide file tree
Showing 56 changed files with 903 additions and 739 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@

[![Documentation Status](https://readthedocs.org/projects/fluent-sql/badge/?version=latest)](https://fluent-sql.readthedocs.io/en/latest/?badge=latest)

[SQL Abstract Syntax Trees Vocabulary](http://ns.inria.fr/ast/sql/)
232 changes: 91 additions & 141 deletions docs/api/FluentSQL.xml

Large diffs are not rendered by default.

37 changes: 17 additions & 20 deletions src/FluentSQL.Tests/Api/ApiDesign.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,29 @@
using FluentSQL.Querying.Statements.Extensions;
using FluentSQL.Tests.Examples;

using Xunit;

namespace FluentSQL.Tests.Api
{
public sealed class ApiDesign
public class ExampleParameters
{
public class ExampleParameters
{
public int Limit { get; set; }
public string InvoiceNumber { get; set; }
}
public int Limit { get; set; }
public string InvoiceNumber { get; set; }
}

public class UnionResult
{
public string CustomerName { get; set; }
public int TotalAmount { get; set; }
}
public class UnionResult
{
public string CustomerName { get; set; }
public int TotalAmount { get; set; }
}

public class SubqueryResult
{
public int InvoiceIdFromSubquery { get; set; }
}
public class SubqueryResult
{
public int InvoiceIdFromSubquery { get; set; }
}

public sealed class ApiDesign
{
private IDbConnection SomeConnection { get; }

[Fact]
public async Task TestApi()
{
var model = new ExampleModel(new SqlServerDatabase());
Expand All @@ -44,7 +41,7 @@ public async Task TestApi()
Invoices i2 = model.Invoices;

/*
* SELECT customers.name
* SELECT customers.*
* FROM dbo.customers
* WHERE dbo.customers.id > 0
*/
Expand All @@ -53,7 +50,7 @@ public async Task TestApi()
.Query<int>()
.From(() => model.Customers)
.Where(() => model.Customers.Id > 0)
.Select(() => model.Customers.Name)
.Select(() => model.Customers.All())
.Compile();

int parameterlessResult = await SomeConnection.ExecuteAsync(parameterless);
Expand Down
45 changes: 43 additions & 2 deletions src/FluentSQL.Tests/Compilation/Builders/QueryCompilerBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,57 @@
using FluentSQL.Compilation;
using System;

using FluentSQL.Compilation;
using FluentSQL.Compilation.Parser;

namespace FluentSQL.Tests.Compilation.Builders
{
public class QueryCompilerBuilder : TestDataBuilder<QueryCompiler>
{
protected override void OnPreBuild()
{
if (Compiler == null)
{
ThatCompiles(_ => { });
}
}

protected override QueryCompiler OnBuild()
{
return new QueryCompilerStub();
return new QueryCompilerStub(this);
}

public QueryCompilerBuilder ThatCompiles(Func<AstNode, string> compiler)
{
Compiler = compiler;
return this;
}

public QueryCompilerBuilder ThatCompiles(Action<AstNode> compiler)
{
return ThatCompiles(x =>
{
compiler(x);
return string.Empty;
});
}

private Func<AstNode, string> Compiler { get; set; }

private class QueryCompilerStub : QueryCompiler
{
public QueryCompilerStub(QueryCompilerBuilder builder)
{
Builder = builder;
}

public override CompilationResult Compile(AstNode node)
{
string sql = Builder.Compiler(node);

return new CompilationResult(sql);
}

private QueryCompilerBuilder Builder { get; }
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using FluentAssertions;
using FluentAssertions.Execution;
using FluentAssertions.Primitives;

using FluentSQL.Compilation.Parser;

namespace FluentSQL.Tests.Compilation.Parser.Assertions
{
public class AstNodeAssertions : ReferenceTypeAssertions<AstNode, AstNodeAssertions>
{
public AstNodeAssertions(AstNode instance)
{
Subject = instance;
}

protected override string Identifier
{
get { return "astNode"; }
}

public AndConstraint<AstNodeAssertions> BeEmpty(string because = "", params object[] becauseArgs)
{
Execute.Assertion
.BecauseOf(because, becauseArgs)
.Given(() => Subject.ChildNodes)
.ForCondition(astNodes => astNodes.Count == 0)
.FailWith("Expected {context:astNode} to be empty, but found {0}", astNodes => astNodes);

return new AndConstraint<AstNodeAssertions>(this);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using FluentSQL.Compilation.Parser;

namespace FluentSQL.Tests.Compilation.Parser.Builders
{
public class QueryParserBuilder : TestDataBuilder<QueryParser>
{
protected override QueryParser OnBuild()
{
return new QueryParser();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using FluentSQL.Compilation.Parser;
using FluentSQL.Tests.Compilation.Parser.Assertions;

namespace FluentSQL.Tests.Compilation.Parser.Extensions
{
public static class AstNodeExtensions
{
public static AstNodeAssertions Should(this AstNode instance)
{
return new AstNodeAssertions(instance);
}
}
}

0 comments on commit 8c589fa

Please sign in to comment.