-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #396 from mk3008/303-proposal-make-it-easier-to-wr…
…ite-typesafe-descriptions Experimental: Allowed selection queries to have types.
- Loading branch information
Showing
5 changed files
with
252 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
namespace Carbunql.Postgres; | ||
|
||
public class SelectQuery<T> : SelectQuery | ||
{ | ||
public SelectQuery() : base() | ||
{ | ||
} | ||
|
||
public SelectQuery(string query) : base(query) | ||
{ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
namespace Carbunql.Postgres.Test; | ||
|
||
public static class SampleQuery | ||
{ | ||
public static string CommandText => | ||
""" | ||
SELECT | ||
a.a_id, | ||
a.text, | ||
b.value | ||
FROM | ||
table_a AS a | ||
INNER JOIN table_b AS b ON a.a_id = b.a_id | ||
"""; | ||
|
||
public static SelectQuery<Row> Query => GetQuery(); | ||
|
||
private static SelectQuery<Row>? QueryCache; | ||
|
||
private static SelectQuery<Row> GetQuery() | ||
{ | ||
if (QueryCache == null) QueryCache = new SelectQuery<Row>(CommandText); | ||
return QueryCache; | ||
} | ||
|
||
public readonly record struct Row( | ||
int a_id, | ||
string text, | ||
int value | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
using Carbunql.Building; | ||
using Carbunql.Postgres; | ||
using Xunit.Abstractions; | ||
|
||
namespace Carbunql.Postgres.Test; | ||
|
||
public class SubQueryText | ||
{ | ||
private readonly QueryCommandMonitor Monitor; | ||
|
||
public SubQueryText(ITestOutputHelper output) | ||
{ | ||
Monitor = new QueryCommandMonitor(output); | ||
Output = output; | ||
} | ||
|
||
private ITestOutputHelper Output { get; set; } | ||
|
||
[Fact] | ||
public void FromAs() | ||
{ | ||
var sq = new SelectQuery(); | ||
var (from, a) = sq.FromAs<RecordA>("a"); | ||
|
||
sq.Select("a", "a_id"); | ||
sq.Select(nameof(a), "a_id"); | ||
sq.Select(() => a.a_id); | ||
sq.Select(() => a.a_id).As("id"); | ||
|
||
Monitor.Log(sq); | ||
|
||
var sql = @"SELECT | ||
a.a_id, | ||
a.a_id, | ||
a.a_id, | ||
a.a_id AS id | ||
FROM | ||
RecordA AS a"; | ||
|
||
Assert.Equal(22, sq.GetTokens().ToList().Count); | ||
Assert.Equal(sql.ToValidateText(), sq.ToText().ToValidateText()); | ||
} | ||
|
||
[Fact] | ||
public void AliasAs() | ||
{ | ||
var sq = new SelectQuery(); | ||
var (from, a) = sq.From("table_a").As<RecordA>("a"); ; | ||
|
||
sq.Select("a", "a_id"); | ||
sq.Select(nameof(a), "a_id"); | ||
sq.Select(() => a.a_id); | ||
sq.Select(() => a.a_id).As("id"); | ||
|
||
Monitor.Log(sq); | ||
|
||
Assert.Equal(22, sq.GetTokens().ToList().Count); | ||
|
||
var sql = @"SELECT | ||
a.a_id, | ||
a.a_id, | ||
a.a_id, | ||
a.a_id AS id | ||
FROM | ||
table_a AS a"; | ||
Assert.Equal(sql, sq.ToText(), true, true, true); | ||
|
||
} | ||
[Fact] | ||
public void SubQueryTest() | ||
{ | ||
var sq = new SelectQuery(); | ||
var (from, a) = sq.From(new SelectQuery("select * from table_a")).As<RecordA>("a"); ; | ||
|
||
sq.Select("a", "a_id"); | ||
sq.Select(nameof(a), "a_id"); | ||
sq.Select(() => a.a_id); | ||
sq.Select(() => a.a_id).As("id"); | ||
|
||
Monitor.Log(sq); | ||
|
||
Assert.Equal(27, sq.GetTokens().ToList().Count); | ||
|
||
var sql = @"SELECT | ||
a.a_id, | ||
a.a_id, | ||
a.a_id, | ||
a.a_id AS id | ||
FROM | ||
( | ||
SELECT | ||
* | ||
FROM | ||
table_a | ||
) AS a"; | ||
Assert.Equal(sql, sq.ToText(), true, true, true); | ||
} | ||
|
||
[Fact] | ||
public void SubroutineTest() | ||
{ | ||
var sq = new SelectQuery(); | ||
var (from, a) = sq.FromAs(GetSelectQuery(), "a"); | ||
|
||
sq.Select("a", "a_id"); | ||
sq.Select(nameof(a), "a_id"); | ||
sq.Select(() => a.a_id); | ||
sq.Select(() => a.a_id).As("id"); | ||
|
||
Monitor.Log(sq); | ||
|
||
Assert.Equal(59, sq.GetTokens().ToList().Count); | ||
|
||
var sql = @"SELECT | ||
a.a_id, | ||
a.a_id, | ||
a.a_id, | ||
a.a_id AS id | ||
FROM | ||
( | ||
SELECT | ||
a.a_id, | ||
a.text, | ||
a.value | ||
FROM | ||
RecordA AS a | ||
INNER JOIN RecordB AS b ON (a.a_id = b.a_id AND b.text = 'test') | ||
) AS a"; | ||
|
||
Assert.Equal(sql, sq.ToText(), true, true, true); | ||
} | ||
|
||
public SelectQuery<SubQueryRow> GetSelectQuery() | ||
{ | ||
var sq = new SelectQuery<SubQueryRow>(); | ||
var (from, a) = sq.FromAs<RecordA>("a"); | ||
var b = from.InnerJoinAs<RecordB>(b => a.a_id == b.a_id && b.text == "test"); | ||
|
||
sq.Select(() => a.a_id); | ||
sq.Select(() => a.text); | ||
sq.Select(() => a.value); | ||
|
||
/* | ||
SELECT | ||
a.a_id, | ||
a.text, | ||
a.value | ||
FROM | ||
RecordA AS a | ||
INNER JOIN RecordB AS b ON (a.a_id = b.a_id AND b.text = 'test') | ||
*/ | ||
|
||
return sq; | ||
} | ||
|
||
|
||
[Fact] | ||
public void QueryClassTest() | ||
{ | ||
var sq = new SelectQuery(); | ||
var (from, a) = sq.FromAs(SampleQuery.Query, "a"); | ||
|
||
sq.Select(() => a.a_id); | ||
sq.Select(() => a.value * 2).As("value"); | ||
|
||
Monitor.Log(sq); | ||
|
||
Assert.Equal(45, sq.GetTokens().ToList().Count); | ||
|
||
var sql = @"SELECT | ||
a.a_id, | ||
a.value * 2 AS value | ||
FROM | ||
( | ||
SELECT | ||
a.a_id, | ||
a.text, | ||
b.value | ||
FROM | ||
table_a AS a | ||
INNER JOIN table_b AS b ON a.a_id = b.a_id | ||
) AS a"; | ||
|
||
Assert.Equal(sql, sq.ToText(), true, true, true); | ||
} | ||
|
||
public record struct RecordA(int a_id, string text, int value, bool is_enabled, double rate, DateTime timestamp, Gender gender); | ||
|
||
public record struct RecordB(int a_id, int b_id, string text, int value); | ||
|
||
public record struct SubQueryRow(int a_id, string text, int value); | ||
|
||
public enum Gender | ||
{ | ||
Male, | ||
Female, | ||
Other, | ||
Unknown | ||
} | ||
} |