From 6a112120e26946c6006f5a9b4e8ad50e4c3112bb Mon Sep 17 00:00:00 2001 From: mk3008 Date: Mon, 21 Oct 2024 21:12:36 +0900 Subject: [PATCH] Handle Extract function units (e.g., YEAR, MONTH) as reserved keywords. Modified the parser to treat units within the EXTRACT function, such as YEAR and MONTH, as reserved keywords instead of column names, preventing parsing errors when these units are encountered in queries. --- .../Analysis/Parser/FromArgumentParser.cs | 4 +- .../Analysis/Parser/ValueCollectionParser.cs | 2 +- src/Carbunql/Carbunql.csproj | 2 +- src/Carbunql/Values/FromArgument.cs | 33 ++------ test/Carbunql.Fluent.Test/FluentWhereTest.cs | 80 +++++++++++++++++++ 5 files changed, 89 insertions(+), 32 deletions(-) create mode 100644 test/Carbunql.Fluent.Test/FluentWhereTest.cs diff --git a/src/Carbunql/Analysis/Parser/FromArgumentParser.cs b/src/Carbunql/Analysis/Parser/FromArgumentParser.cs index 25e99e2a..1c77a549 100644 --- a/src/Carbunql/Analysis/Parser/FromArgumentParser.cs +++ b/src/Carbunql/Analysis/Parser/FromArgumentParser.cs @@ -14,7 +14,7 @@ public static class FromArgumentParser /// The unit value. /// The SQL text containing the FROM argument. /// The parsed FROM argument. - public static FromArgument Parse(ValueBase unit, string argument) + public static FromArgument Parse(string unit, string argument) { var r = new SqlTokenReader(argument); return Parse(unit, r); @@ -26,7 +26,7 @@ public static FromArgument Parse(ValueBase unit, string argument) /// The unit value. /// The token reader. /// The parsed FROM argument. - public static FromArgument Parse(ValueBase unit, ITokenReader r) + public static FromArgument Parse(string unit, ITokenReader r) { var value = ValueParser.Parse(r); return new FromArgument(unit, value); diff --git a/src/Carbunql/Analysis/Parser/ValueCollectionParser.cs b/src/Carbunql/Analysis/Parser/ValueCollectionParser.cs index 376f7c2e..89b81885 100644 --- a/src/Carbunql/Analysis/Parser/ValueCollectionParser.cs +++ b/src/Carbunql/Analysis/Parser/ValueCollectionParser.cs @@ -58,7 +58,7 @@ internal static IEnumerable ReadValues(ITokenReader r) if (r.ReadOrDefault("from") != null) { - yield return FromArgumentParser.Parse(v, r); + yield return FromArgumentParser.Parse(v.ToText(), r); } else if (r.ReadOrDefault("as") != null) { diff --git a/src/Carbunql/Carbunql.csproj b/src/Carbunql/Carbunql.csproj index 87f11871..ef52a863 100644 --- a/src/Carbunql/Carbunql.csproj +++ b/src/Carbunql/Carbunql.csproj @@ -8,7 +8,7 @@ mk3008net Carbunql is an advanced Raw SQL editing library. - 0.8.13 + 0.8.13.1 mk3008net https://github.com/mk3008/Carbunql README.md diff --git a/src/Carbunql/Values/FromArgument.cs b/src/Carbunql/Values/FromArgument.cs index 2856b4f6..61ffdfa0 100644 --- a/src/Carbunql/Values/FromArgument.cs +++ b/src/Carbunql/Values/FromArgument.cs @@ -22,7 +22,7 @@ public FromArgument() /// /// The unit value. /// The value. - public FromArgument(ValueBase unit, ValueBase value) + public FromArgument(string unit, ValueBase value) { Unit = unit; Value = value; @@ -31,7 +31,7 @@ public FromArgument(ValueBase unit, ValueBase value) /// /// Gets or sets the unit value. /// - public ValueBase Unit { get; init; } + public string Unit { get; init; } /// /// Gets or sets the value. @@ -41,10 +41,6 @@ public FromArgument(ValueBase unit, ValueBase value) /// protected override IEnumerable GetInternalQueriesCore() { - foreach (var item in Unit.GetInternalQueries()) - { - yield return item; - } foreach (var item in Value.GetInternalQueries()) { yield return item; @@ -54,7 +50,9 @@ protected override IEnumerable GetInternalQueriesCore() /// public override IEnumerable GetCurrentTokens(Token? parent) { - foreach (var item in Unit.GetTokens(parent)) yield return item; + if (string.IsNullOrEmpty(Unit)) throw new InvalidProgramException(); + + yield return Token.Reserved(this, parent, Unit); yield return Token.Reserved(this, parent, "from"); foreach (var item in Value.GetTokens(parent)) yield return item; } @@ -62,10 +60,6 @@ public override IEnumerable GetCurrentTokens(Token? parent) /// protected override IEnumerable GetParametersCore() { - foreach (var item in Unit.GetParameters()) - { - yield return item; - } foreach (var item in Value.GetParameters()) { yield return item; @@ -75,10 +69,6 @@ protected override IEnumerable GetParametersCore() /// protected override IEnumerable GetPhysicalTablesCore() { - foreach (var item in Unit.GetPhysicalTables()) - { - yield return item; - } foreach (var item in Value.GetPhysicalTables()) { yield return item; @@ -88,10 +78,6 @@ protected override IEnumerable GetPhysicalTablesCore() /// protected override IEnumerable GetCommonTablesCore() { - foreach (var item in Unit.GetCommonTables()) - { - yield return item; - } foreach (var item in Value.GetCommonTables()) { yield return item; @@ -100,10 +86,6 @@ protected override IEnumerable GetCommonTablesCore() internal override IEnumerable GetColumnsCore() { - foreach (var item in Unit.GetColumns()) - { - yield return item; - } foreach (var item in Value.GetColumns()) { yield return item; @@ -114,11 +96,6 @@ public override IEnumerable GetValues() { yield return this; - foreach (var item in Unit.GetValues()) - { - yield return item; - } - foreach (var item in Value.GetValues()) { yield return item; diff --git a/test/Carbunql.Fluent.Test/FluentWhereTest.cs b/test/Carbunql.Fluent.Test/FluentWhereTest.cs new file mode 100644 index 00000000..0ac62c4e --- /dev/null +++ b/test/Carbunql.Fluent.Test/FluentWhereTest.cs @@ -0,0 +1,80 @@ +using Xunit.Abstractions; + +namespace Carbunql.Fluent.Test; + +public class FluentWhereTest +{ + private readonly QueryCommandMonitor Monitor; + + public FluentWhereTest(ITestOutputHelper output) + { + Monitor = new QueryCommandMonitor(output); + } + + [Fact] + public void EqualTest() + { + var sq = new SelectQuery(""" + select + a.id + , a.value + from + table_a a + """) + .Equal("id", 1); + ; + + Monitor.Log(sq); + + var expect = """ + SELECT + a.id, + a.value + FROM + table_a AS a + WHERE + a.id = 1 + """; + + Assert.Equal(expect, sq.ToText()); + } + + [Fact] + public void EqualTest_ExtractYear() + { + var sq = new SelectQuery(""" + SELECT + o.order_id, + c.customer_name, + o.order_date, + EXTRACT(YEAR FROM o.order_date) AS order_year, + EXTRACT(MONTH FROM o.order_date) AS order_month, + o.amount + FROM + orders o + JOIN + customers c ON o.customer_id = c.customer_id + """) + .Equal("order_year", 1); + ; + + Monitor.Log(sq); + + var expect = """ + SELECT + o.order_id, + c.customer_name, + o.order_date, + EXTRACT(YEAR FROM o.order_date) AS order_year, + EXTRACT(MONTH FROM o.order_date) AS order_month, + o.amount + FROM + orders AS o + JOIN customers AS c ON o.customer_id = c.customer_id + WHERE + EXTRACT(YEAR FROM o.order_date) = 1 + """; + + Assert.Equal(expect, sq.ToText()); + } +} \ No newline at end of file