mirror of https://github.com/jackc/pgx.git
parent
6052227803
commit
fb90fb2729
41
conn.go
41
conn.go
|
@ -47,6 +47,13 @@ func init() {
|
|||
})
|
||||
}
|
||||
|
||||
// NoticeHandler is a function that can handle notices received from the
|
||||
// PostgreSQL server. Notices can be received at any time, usually during
|
||||
// handling of a query response. The *Conn is provided so the handler is aware
|
||||
// of the origin of the notice, but it must not invoke any query method. Be
|
||||
// aware that this is distinct from LISTEN/NOTIFY notification.
|
||||
type NoticeHandler func(*Conn, *Notice)
|
||||
|
||||
// DialFunc is a function that can be used to connect to a PostgreSQL server
|
||||
type DialFunc func(network, addr string) (net.Conn, error)
|
||||
|
||||
|
@ -64,6 +71,7 @@ type ConnConfig struct {
|
|||
LogLevel int
|
||||
Dial DialFunc
|
||||
RuntimeParams map[string]string // Run-time parameters to set on connection as session default values (e.g. search_path or application_name)
|
||||
OnNotice NoticeHandler // Callback function called when a notice response is received.
|
||||
}
|
||||
|
||||
func (cc *ConnConfig) networkAddress() (network, address string) {
|
||||
|
@ -102,6 +110,7 @@ type Conn struct {
|
|||
fp *fastpath
|
||||
poolResetCount int
|
||||
preallocatedRows []Rows
|
||||
onNotice NoticeHandler
|
||||
|
||||
mux sync.Mutex
|
||||
status byte // One of connStatus* constants
|
||||
|
@ -235,6 +244,8 @@ func connect(config ConnConfig, connInfo *pgtype.ConnInfo) (c *Conn, err error)
|
|||
}
|
||||
}
|
||||
|
||||
c.onNotice = config.OnNotice
|
||||
|
||||
network, address := c.config.networkAddress()
|
||||
if c.config.Dial == nil {
|
||||
c.config.Dial = (&net.Dialer{KeepAlive: 5 * time.Minute}).Dial
|
||||
|
@ -1079,6 +1090,8 @@ func (c *Conn) processContextFreeMsg(msg pgproto3.BackendMessage) (err error) {
|
|||
switch msg := msg.(type) {
|
||||
case *pgproto3.ErrorResponse:
|
||||
return c.rxErrorResponse(msg)
|
||||
case *pgproto3.NoticeResponse:
|
||||
c.rxNoticeResponse(msg)
|
||||
case *pgproto3.NotificationResponse:
|
||||
c.rxNotificationResponse(msg)
|
||||
case *pgproto3.ReadyForQuery:
|
||||
|
@ -1163,6 +1176,34 @@ func (c *Conn) rxErrorResponse(msg *pgproto3.ErrorResponse) PgError {
|
|||
return err
|
||||
}
|
||||
|
||||
func (c *Conn) rxNoticeResponse(msg *pgproto3.NoticeResponse) {
|
||||
if c.onNotice == nil {
|
||||
return
|
||||
}
|
||||
|
||||
notice := &Notice{
|
||||
Severity: msg.Severity,
|
||||
Code: msg.Code,
|
||||
Message: msg.Message,
|
||||
Detail: msg.Detail,
|
||||
Hint: msg.Hint,
|
||||
Position: msg.Position,
|
||||
InternalPosition: msg.InternalPosition,
|
||||
InternalQuery: msg.InternalQuery,
|
||||
Where: msg.Where,
|
||||
SchemaName: msg.SchemaName,
|
||||
TableName: msg.TableName,
|
||||
ColumnName: msg.ColumnName,
|
||||
DataTypeName: msg.DataTypeName,
|
||||
ConstraintName: msg.ConstraintName,
|
||||
File: msg.File,
|
||||
Line: msg.Line,
|
||||
Routine: msg.Routine,
|
||||
}
|
||||
|
||||
c.onNotice(c, notice)
|
||||
}
|
||||
|
||||
func (c *Conn) rxBackendKeyData(msg *pgproto3.BackendKeyData) {
|
||||
c.pid = msg.ProcessID
|
||||
c.secretKey = msg.SecretKey
|
||||
|
|
27
conn_test.go
27
conn_test.go
|
@ -1898,3 +1898,30 @@ func TestIdentifierSanitize(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnOnNotice(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var msg string
|
||||
|
||||
connConfig := *defaultConnConfig
|
||||
connConfig.OnNotice = func(c *pgx.Conn, notice *pgx.Notice) {
|
||||
msg = notice.Message
|
||||
}
|
||||
conn := mustConnect(t, connConfig)
|
||||
defer closeConn(t, conn)
|
||||
|
||||
_, err := conn.Exec(`do $$
|
||||
begin
|
||||
raise notice 'hello, world';
|
||||
end$$;`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if msg != "hello, world" {
|
||||
t.Errorf("msg => %v, want %v", msg, "hello, world")
|
||||
}
|
||||
|
||||
ensureConnValid(t, conn)
|
||||
}
|
||||
|
|
|
@ -49,6 +49,10 @@ func (pe PgError) Error() string {
|
|||
return pe.Severity + ": " + pe.Message + " (SQLSTATE " + pe.Code + ")"
|
||||
}
|
||||
|
||||
// Notice represents a notice response message reported by the PostgreSQL
|
||||
// server. Be aware that this is distinct from LISTEN/NOTIFY notification.
|
||||
type Notice PgError
|
||||
|
||||
// appendParse appends a PostgreSQL wire protocol parse message to buf and returns it.
|
||||
func appendParse(buf []byte, name string, query string, parameterOIDs []pgtype.OID) []byte {
|
||||
buf = append(buf, 'P')
|
||||
|
|
Loading…
Reference in New Issue