in src/Elastic.Apm/Model/SignatureParser.cs [73:192]
private void Parse(Scanner scanner, string query, StringBuilder signature, StringBuilder dbLink)
{
var firstToken = scanner.ScanWhile(Scanner.Token.Comment);
switch (firstToken)
{
case Scanner.Token.Call:
signature.Append("CALL");
if (scanner.ScanUntil(Scanner.Token.Ident))
AppendIdentifiers(scanner, signature, dbLink);
return;
case Scanner.Token.Delete:
signature.Append("DELETE");
if (scanner.ScanUntil(Scanner.Token.From) && scanner.ScanUntil(Scanner.Token.Ident))
{
signature.Append(" FROM");
AppendIdentifiers(scanner, signature, dbLink);
}
return;
case Scanner.Token.Insert:
case Scanner.Token.Replace:
signature.Append(firstToken.ToString().ToUpperInvariant());
if (scanner.ScanUntil(Scanner.Token.Into) && scanner.ScanUntil(Scanner.Token.Ident))
{
signature.Append(" INTO");
AppendIdentifiers(scanner, signature, dbLink);
}
return;
case Scanner.Token.Select:
signature.Append("SELECT");
var level = 0;
for (var t = scanner.Scan(); t != Scanner.Token.Eof; t = scanner.Scan())
{
if (t == Scanner.Token.Lparen)
level++;
else if (t == Scanner.Token.Rparen)
level--;
else if (t == Scanner.Token.From)
{
if (level == 0)
{
if (scanner.ScanToken(Scanner.Token.Ident))
{
signature.Append(" FROM");
AppendIdentifiers(scanner, signature, dbLink);
}
else
return;
}
}
}
return;
case Scanner.Token.Update:
signature.Append("UPDATE");
// Scan for the table name
var hasPeriod = false;
var hasFirstPeriod = false;
var isDbLink = false;
if (scanner.ScanToken(Scanner.Token.Ident))
{
signature.Append(' ');
scanner.AppendCurrentTokenText(signature);
for (var t = scanner.Scan(); t != Scanner.Token.Eof; t = scanner.Scan())
{
switch (t)
{
case Scanner.Token.Ident:
if (hasPeriod)
{
scanner.AppendCurrentTokenText(signature);
hasPeriod = false;
}
if (!hasFirstPeriod)
{
// Some dialects allow option keywords before the table name
// example: UPDATE IGNORE foo.bar
signature.Length = 0;
signature.Append("UPDATE ");
scanner.AppendCurrentTokenText(signature);
}
else if (isDbLink)
{
if (dbLink != null)
scanner.AppendCurrentTokenText(dbLink);
isDbLink = false;
}
// Two adjacent identifiers found after the first period.
// Ignore the secondary ones, in case they are unknown keywords.
break;
case Scanner.Token.Period:
hasFirstPeriod = true;
hasPeriod = true;
signature.Append('.');
break;
default:
if ("@".Equals(scanner.ToString()))
{
isDbLink = true;
break;
}
else
return;
}
}
}
return;
case Scanner.Token.Merge:
signature.Append("MERGE");
if (scanner.ScanToken(Scanner.Token.Into) && scanner.ScanUntil(Scanner.Token.Ident))
{
signature.Append(" INTO");
AppendIdentifiers(scanner, signature, dbLink);
}
return;
default:
query = query.Trim();
var indexOfWhitespace = query.IndexOf(' ');
signature.Append(query, 0, indexOfWhitespace > 0 ? indexOfWhitespace : query.Length);
break;
}
}