| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- package l7
- import (
- "bytes"
- "fmt"
- )
- const (
- PostgresFrameQuery byte = 'Q'
- PostgresFrameBind byte = 'B'
- PostgresFrameParse byte = 'P'
- PostgresFrameClose byte = 'C'
- )
- type PostgresParser struct {
- preparedStatements map[string]string
- }
- func NewPostgresParser() *PostgresParser {
- return &PostgresParser{preparedStatements: map[string]string{}}
- }
- func (p *PostgresParser) Parse(payload []byte) string {
- l := len(payload)
- if l < 5 {
- return ""
- }
- cmd := payload[0]
- switch cmd {
- case PostgresFrameQuery:
- var query string
- if q, _, ok := bytes.Cut(payload[5:], []byte{0}); ok {
- query = string(q)
- } else {
- query = string(q) + "..."
- }
- return query
- case PostgresFrameBind:
- _, rest, ok := bytes.Cut(payload[5:], []byte{0})
- if !ok {
- return ""
- }
- preparedStatementName, _, ok := bytes.Cut(rest, []byte{0})
- if !ok {
- return ""
- }
- preparedStatementNameStr := string(preparedStatementName)
- statement, ok := p.preparedStatements[preparedStatementNameStr]
- if !ok {
- statement = fmt.Sprintf(`EXECUTE %s /* unknown */`, preparedStatementNameStr)
- }
- return statement
- case PostgresFrameParse:
- preparedStatementName, rest, ok := bytes.Cut(payload[5:], []byte{0})
- if !ok {
- return ""
- }
- var query string
- q, _, ok := bytes.Cut(rest, []byte{0})
- if ok {
- query = string(q)
- } else {
- query = string(q) + "..."
- }
- preparedStatementNameStr := string(preparedStatementName)
- p.preparedStatements[preparedStatementNameStr] = query
- return fmt.Sprintf("PREPARE %s AS %s", preparedStatementNameStr, query)
- case PostgresFrameClose:
- if l < 7 {
- return ""
- }
- if payload[5] != 'S' {
- return ""
- }
- preparedStatementName, _, ok := bytes.Cut(payload[6:], []byte{0})
- if !ok {
- return ""
- }
- delete(p.preparedStatements, string(preparedStatementName))
- }
- return ""
- }
|