Skip to content

Commit

Permalink
Feat: Interpret AS as an operator within CAST function
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mk3008 committed Nov 16, 2024
1 parent 96b1caf commit 6c5cb80
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 11 deletions.
38 changes: 32 additions & 6 deletions src/Carbunql.LexicalAnalyzer/Lexer.Expression.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.CodeAnalysis;

namespace Carbunql.LexicalAnalyzer;

Expand All @@ -9,7 +8,7 @@ public static partial class Lexer



public static IEnumerable<Lex> ReadExpressionLexes(ReadOnlyMemory<char> memory, int position)
public static IEnumerable<Lex> ReadExpressionLexes(ReadOnlyMemory<char> memory, int position, Lex? owner = null)
{
memory.SkipWhiteSpacesAndComment(ref position);

Expand Down Expand Up @@ -67,13 +66,15 @@ public static IEnumerable<Lex> ReadExpressionLexes(ReadOnlyMemory<char> memory,

// operator check
memory.SkipWhiteSpacesAndComment(ref position);

if (TryParseOperator(memory, ref position, out lex))
{
yield return lex;
memory.SkipWhiteSpacesAndComment(ref position);
continue;
}


// alias, expression separator, or 'from' keyword
break;
}
Expand All @@ -97,12 +98,37 @@ public static IEnumerable<Lex> ReadExpressionLexes(ReadOnlyMemory<char> 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);
Expand Down Expand Up @@ -178,7 +204,7 @@ public static bool TryParseExpressionName(ReadOnlyMemory<char> 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
Expand All @@ -194,7 +220,7 @@ public static bool TryParseExpressionName(ReadOnlyMemory<char> 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;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<char> memory, ref int position, out Lex lex)
Expand Down
2 changes: 1 addition & 1 deletion src/Carbunql.LexicalAnalyzer/Lexer.Select.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ internal static bool TryParseSelect(ReadOnlyMemory<char> 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;
}

Expand Down
7 changes: 4 additions & 3 deletions test/Carbunql.LexicalAnalyzer.Test/SelectQueryParseTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
""";
Expand Down

0 comments on commit 6c5cb80

Please sign in to comment.