From 6c5cb8040f722d178d9b938dfbaeba6fd1aaf87f Mon Sep 17 00:00:00 2001 From: MSugiura Date: Sat, 16 Nov 2024 17:29:37 +0900 Subject: [PATCH] Feat: Interpret AS as an operator within CAST function Changed the interpretation of the AS keyword within the CAST function to be treated as an operator rather than an alias. This ensures that type casting using CAST is handled correctly without confusion between aliases and type conversions. --- .../Lexer.Expression.cs | 38 ++++++++++++++++--- .../Lexer.Operator.StringOperator.cs | 2 +- src/Carbunql.LexicalAnalyzer/Lexer.Select.cs | 2 +- .../SelectQueryParseTest.cs | 7 ++-- 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/src/Carbunql.LexicalAnalyzer/Lexer.Expression.cs b/src/Carbunql.LexicalAnalyzer/Lexer.Expression.cs index 373c2f14..6a8162c8 100644 --- a/src/Carbunql.LexicalAnalyzer/Lexer.Expression.cs +++ b/src/Carbunql.LexicalAnalyzer/Lexer.Expression.cs @@ -1,5 +1,4 @@ -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; namespace Carbunql.LexicalAnalyzer; @@ -9,7 +8,7 @@ public static partial class Lexer - public static IEnumerable ReadExpressionLexes(ReadOnlyMemory memory, int position) + public static IEnumerable ReadExpressionLexes(ReadOnlyMemory memory, int position, Lex? owner = null) { memory.SkipWhiteSpacesAndComment(ref position); @@ -67,6 +66,7 @@ public static IEnumerable ReadExpressionLexes(ReadOnlyMemory memory, // operator check memory.SkipWhiteSpacesAndComment(ref position); + if (TryParseOperator(memory, ref position, out lex)) { yield return lex; @@ -74,6 +74,7 @@ public static IEnumerable ReadExpressionLexes(ReadOnlyMemory memory, continue; } + // alias, expression separator, or 'from' keyword break; } @@ -97,12 +98,37 @@ public static IEnumerable ReadExpressionLexes(ReadOnlyMemory memory, yield return ParseLeftParen(memory, ref position); // read arguments - foreach (var argument in ReadExpressionLexes(memory, position)) + foreach (var argument in ReadExpressionLexes(memory, position, owner = lex)) { yield return argument; position = argument.EndPosition; } + memory.SkipWhiteSpacesAndComment(ref position); + + if (lex.Value.ToLowerInvariant() == "cast") + { + if (memory.TryParseKeywordIgnoreCase(ref position, "as", LexType.Operator, out lex)) + { + yield return lex; + } + else + { + throw new FormatException(); + } + + memory.SkipWhiteSpacesAndComment(ref position); + + if (TryParseDbType(memory, position, out lex, out position)) + { + yield return lex; + } + else + { + throw new FormatException(); + } + } + // close paren memory.SkipWhiteSpacesAndComment(ref position); yield return ParseRightParen(memory, ref position); @@ -178,7 +204,7 @@ public static bool TryParseExpressionName(ReadOnlyMemory memory, ref int p { throw new FormatException(); } - lex = new Lex(memory, LexType.Column, start, position - start); + lex = new Lex(memory, LexType.Alias, start, position - start); return true; } else @@ -194,7 +220,7 @@ public static bool TryParseExpressionName(ReadOnlyMemory memory, ref int p return false; } position = p; - lex = new Lex(memory, LexType.Column, start, position - start, name); + lex = new Lex(memory, LexType.Alias, start, position - start, name); return true; } } diff --git a/src/Carbunql.LexicalAnalyzer/Lexer.Operator.StringOperator.cs b/src/Carbunql.LexicalAnalyzer/Lexer.Operator.StringOperator.cs index 05e016ce..aed107c5 100644 --- a/src/Carbunql.LexicalAnalyzer/Lexer.Operator.StringOperator.cs +++ b/src/Carbunql.LexicalAnalyzer/Lexer.Operator.StringOperator.cs @@ -8,7 +8,7 @@ public static partial class Lexer "not", "and", "or", - "as", //type cast "as" + //"as", //type cast "as" }; private static bool TryParseStringOperator(ReadOnlyMemory memory, ref int position, out Lex lex) diff --git a/src/Carbunql.LexicalAnalyzer/Lexer.Select.cs b/src/Carbunql.LexicalAnalyzer/Lexer.Select.cs index 5f4fefa9..e78fad64 100644 --- a/src/Carbunql.LexicalAnalyzer/Lexer.Select.cs +++ b/src/Carbunql.LexicalAnalyzer/Lexer.Select.cs @@ -39,7 +39,7 @@ internal static bool TryParseSelect(ReadOnlyMemory memory, ref int positio } // If neither "all" nor "distinct", return simple "select" lex - lex = new Lex(memory, LexType.Select, start, position - start); + lex = new Lex(memory, LexType.Select, start, position - start, "select"); return true; } diff --git a/test/Carbunql.LexicalAnalyzer.Test/SelectQueryParseTest.cs b/test/Carbunql.LexicalAnalyzer.Test/SelectQueryParseTest.cs index f025a896..c01e9ed6 100644 --- a/test/Carbunql.LexicalAnalyzer.Test/SelectQueryParseTest.cs +++ b/test/Carbunql.LexicalAnalyzer.Test/SelectQueryParseTest.cs @@ -11,9 +11,10 @@ public void Default() { var text = """ select - a.id, - a.value, - a.quantity * a.price as total_price + a.id + , a.value v1 + , a.value as v2 + , a.quantity * a.price as total_price from table as a """;