refactor(dedup): TryMatchTwoCharOperator helper in PG StatementReader
The PostgreSql-specific operator dispatch in
`StatementReader.TryHandleAdditionalCharacter` had four similar 4-7
line blocks (each handling a single-char operator with one or more
two-char variants — \<, \>, \|, \=). Sonar flagged it as a
self-duplication.
Extract a small `TryMatchTwoCharOperator(char, string)` helper that
encapsulates the "if next char matches, advance and emit two-char
operator" pattern. Each operator handler now reads as a small list:
if (CurrentCharacter == '<')
{
MovePosition();
if (TryMatchTwoCharOperator('=', "<=")) return true;
if (TryMatchTwoCharOperator('>', "<>")) return true;
if (TryMatchTwoCharOperator('<', "<<")) return true;
_currentToken = new Token(TokenType.Operator, "<");
return true;
}
Reverses my earlier "extracting would obscure intent" call after
re-reading — the helper-based form actually surfaces the intent
("two-char operator dispatch") more clearly than the original.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
85cc79d5a1
commit
4b6b3edc87
@@ -104,76 +104,39 @@ public class StatementReader : SqlServerStatementReader
|
|||||||
|
|
||||||
if (CurrentCharacter == '=')
|
if (CurrentCharacter == '=')
|
||||||
{
|
{
|
||||||
// Handle => operator (used in PostgreSQL for hstore and other operations)
|
// =, => (PostgreSQL hstore + other operations)
|
||||||
MovePosition();
|
MovePosition();
|
||||||
if (CurrentCharacter == '>')
|
if (TryMatchTwoCharOperator('>', "=>")) return true;
|
||||||
{
|
|
||||||
MovePosition();
|
|
||||||
_currentToken = new Token(TokenType.Operator, "=>");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Single = is handled as regular operator
|
|
||||||
_currentToken = new Token(TokenType.Operator, "=");
|
_currentToken = new Token(TokenType.Operator, "=");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurrentCharacter == '|')
|
if (CurrentCharacter == '|')
|
||||||
{
|
{
|
||||||
// Handle || concatenation operator
|
// |, ||
|
||||||
MovePosition();
|
MovePosition();
|
||||||
if (CurrentCharacter == '|')
|
if (TryMatchTwoCharOperator('|', "||")) return true;
|
||||||
{
|
|
||||||
MovePosition();
|
|
||||||
_currentToken = new Token(TokenType.Operator, "||");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Single | is also an operator
|
|
||||||
_currentToken = new Token(TokenType.Operator, "|");
|
_currentToken = new Token(TokenType.Operator, "|");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurrentCharacter == '<')
|
if (CurrentCharacter == '<')
|
||||||
{
|
{
|
||||||
// Handle <, <=, <>, << operators
|
// <, <=, <>, <<
|
||||||
MovePosition();
|
MovePosition();
|
||||||
if (CurrentCharacter == '=')
|
if (TryMatchTwoCharOperator('=', "<=")) return true;
|
||||||
{
|
if (TryMatchTwoCharOperator('>', "<>")) return true;
|
||||||
MovePosition();
|
if (TryMatchTwoCharOperator('<', "<<")) return true;
|
||||||
_currentToken = new Token(TokenType.Operator, "<=");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (CurrentCharacter == '>')
|
|
||||||
{
|
|
||||||
MovePosition();
|
|
||||||
_currentToken = new Token(TokenType.Operator, "<>");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (CurrentCharacter == '<')
|
|
||||||
{
|
|
||||||
MovePosition();
|
|
||||||
_currentToken = new Token(TokenType.Operator, "<<");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
_currentToken = new Token(TokenType.Operator, "<");
|
_currentToken = new Token(TokenType.Operator, "<");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurrentCharacter == '>')
|
if (CurrentCharacter == '>')
|
||||||
{
|
{
|
||||||
// Handle >, >=, >> operators
|
// >, >=, >>
|
||||||
MovePosition();
|
MovePosition();
|
||||||
if (CurrentCharacter == '=')
|
if (TryMatchTwoCharOperator('=', ">=")) return true;
|
||||||
{
|
if (TryMatchTwoCharOperator('>', ">>")) return true;
|
||||||
MovePosition();
|
|
||||||
_currentToken = new Token(TokenType.Operator, ">=");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (CurrentCharacter == '>')
|
|
||||||
{
|
|
||||||
MovePosition();
|
|
||||||
_currentToken = new Token(TokenType.Operator, ">>");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
_currentToken = new Token(TokenType.Operator, ">");
|
_currentToken = new Token(TokenType.Operator, ">");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -244,6 +207,23 @@ public class StatementReader : SqlServerStatementReader
|
|||||||
|
|
||||||
return stringValue.ToString();
|
return stringValue.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If the position is currently sitting on <paramref name="nextChar"/>, advances past it,
|
||||||
|
/// emits <paramref name="twoCharOperator"/> as the current Operator token, and returns
|
||||||
|
/// <c>true</c>. Otherwise leaves position untouched and returns <c>false</c>. Used by the
|
||||||
|
/// multi-character operator dispatch (e.g. <c><</c>/<c><=</c>/<c><></c>/<c><<</c>).
|
||||||
|
/// </summary>
|
||||||
|
private bool TryMatchTwoCharOperator(char nextChar, string twoCharOperator)
|
||||||
|
{
|
||||||
|
if (CurrentCharacter != nextChar)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MovePosition();
|
||||||
|
_currentToken = new Token(TokenType.Operator, twoCharOperator);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user