in module/apmsql/signature.go [35:161]
func QuerySignature(query string) string {
s := sqlutil.NewScanner(query)
for s.Scan() {
if s.Token() != sqlutil.COMMENT {
break
}
}
scanUntil := func(until sqlutil.Token) bool {
for s.Scan() {
if s.Token() == until {
return true
}
}
return false
}
scanToken := func(tok sqlutil.Token) bool {
for s.Scan() {
switch s.Token() {
case tok:
return true
case sqlutil.COMMENT:
default:
return false
}
}
return false
}
switch s.Token() {
case sqlutil.CALL:
if !scanUntil(sqlutil.IDENT) {
break
}
return "CALL " + s.Text()
case sqlutil.DELETE:
if !scanUntil(sqlutil.FROM) {
break
}
if !scanToken(sqlutil.IDENT) {
break
}
tableName := s.Text()
for scanToken(sqlutil.PERIOD) && scanToken(sqlutil.IDENT) {
tableName += "." + s.Text()
}
return "DELETE FROM " + tableName
case sqlutil.INSERT, sqlutil.REPLACE:
action := s.Text()
if !scanUntil(sqlutil.INTO) {
break
}
if !scanToken(sqlutil.IDENT) {
break
}
tableName := s.Text()
for scanToken(sqlutil.PERIOD) && scanToken(sqlutil.IDENT) {
tableName += "." + s.Text()
}
return action + " INTO " + tableName
case sqlutil.SELECT:
var level int
scanLoop:
for s.Scan() {
switch tok := s.Token(); tok {
case sqlutil.LPAREN:
level++
case sqlutil.RPAREN:
level--
case sqlutil.FROM:
if level != 0 {
continue scanLoop
}
if !scanToken(sqlutil.IDENT) {
break scanLoop
}
tableName := s.Text()
for scanToken(sqlutil.PERIOD) && scanToken(sqlutil.IDENT) {
tableName += "." + s.Text()
}
return "SELECT FROM " + tableName
}
}
case sqlutil.UPDATE:
// Scan for the table name. Some dialects allow
// option keywords before the table name.
var havePeriod, haveFirstPeriod bool
if !scanToken(sqlutil.IDENT) {
return "UPDATE"
}
tableName := s.Text()
for s.Scan() {
switch tok := s.Token(); tok {
case sqlutil.IDENT:
if havePeriod {
tableName += s.Text()
havePeriod = false
}
if !haveFirstPeriod {
tableName = s.Text()
} else {
// Two adjacent identifiers found
// after the first period. Ignore
// the secondary ones, in case they
// are unknown keywords.
}
case sqlutil.PERIOD:
haveFirstPeriod = true
havePeriod = true
tableName += "."
default:
return "UPDATE " + tableName
}
}
}
// If all else fails, just return the first token of the query.
fields := strings.Fields(query)
if len(fields) == 0 {
return ""
}
return strings.ToUpper(fields[0])
}