187 lines
6.1 KiB
Go
187 lines
6.1 KiB
Go
// From src/include/libpq/protocol.h and src/include/libpq/pqcomm.h – PostgreSQL 18.1
|
||
|
||
package proto
|
||
|
||
import (
|
||
"fmt"
|
||
"strconv"
|
||
)
|
||
|
||
// Constants from pqcomm.h
|
||
const (
|
||
ProtocolVersion30 = (3 << 16) | 0 //lint:ignore SA4016 x
|
||
ProtocolVersion32 = (3 << 16) | 2 // PostgreSQL ≥18; not yet supported.
|
||
CancelRequestCode = (1234 << 16) | 5678
|
||
NegotiateSSLCode = (1234 << 16) | 5679
|
||
NegotiateGSSCode = (1234 << 16) | 5680
|
||
)
|
||
|
||
// Constants from fe-connect.c
|
||
const (
|
||
MaxErrlen = 30_000 // https://github.com/postgres/postgres/blob/c6a10a89f/src/interfaces/libpq/fe-connect.c#L4067
|
||
)
|
||
|
||
// RequestCode is a request codes sent by the frontend.
|
||
type RequestCode byte
|
||
|
||
// These are the request codes sent by the frontend.
|
||
const (
|
||
Bind = RequestCode('B')
|
||
Close = RequestCode('C')
|
||
Describe = RequestCode('D')
|
||
Execute = RequestCode('E')
|
||
FunctionCall = RequestCode('F')
|
||
Flush = RequestCode('H')
|
||
Parse = RequestCode('P')
|
||
Query = RequestCode('Q')
|
||
Sync = RequestCode('S')
|
||
Terminate = RequestCode('X')
|
||
CopyFail = RequestCode('f')
|
||
GSSResponse = RequestCode('p')
|
||
PasswordMessage = RequestCode('p')
|
||
SASLInitialResponse = RequestCode('p')
|
||
SASLResponse = RequestCode('p')
|
||
CopyDoneRequest = RequestCode('c')
|
||
CopyDataRequest = RequestCode('d')
|
||
)
|
||
|
||
func (r RequestCode) String() string {
|
||
s, ok := map[RequestCode]string{
|
||
Bind: "Bind",
|
||
Close: "Close",
|
||
Describe: "Describe",
|
||
Execute: "Execute",
|
||
FunctionCall: "FunctionCall",
|
||
Flush: "Flush",
|
||
Parse: "Parse",
|
||
Query: "Query",
|
||
Sync: "Sync",
|
||
Terminate: "Terminate",
|
||
CopyFail: "CopyFail",
|
||
// These are all the same :-/
|
||
//GSSResponse: "GSSResponse",
|
||
PasswordMessage: "PasswordMessage",
|
||
//SASLInitialResponse: "SASLInitialResponse",
|
||
//SASLResponse: "SASLResponse",
|
||
CopyDoneRequest: "CopyDone",
|
||
CopyDataRequest: "CopyData",
|
||
}[r]
|
||
if !ok {
|
||
s = "<unknown>"
|
||
}
|
||
c := string(r)
|
||
if r <= 0x1f || r == 0x7f {
|
||
c = fmt.Sprintf("0x%x", string(r))
|
||
}
|
||
return "(" + c + ") " + s
|
||
}
|
||
|
||
// ResponseCode is a response codes sent by the backend.
|
||
type ResponseCode byte
|
||
|
||
// These are the response codes sent by the backend.
|
||
const (
|
||
ParseComplete = ResponseCode('1')
|
||
BindComplete = ResponseCode('2')
|
||
CloseComplete = ResponseCode('3')
|
||
NotificationResponse = ResponseCode('A')
|
||
CommandComplete = ResponseCode('C')
|
||
DataRow = ResponseCode('D')
|
||
ErrorResponse = ResponseCode('E')
|
||
CopyInResponse = ResponseCode('G')
|
||
CopyOutResponse = ResponseCode('H')
|
||
EmptyQueryResponse = ResponseCode('I')
|
||
BackendKeyData = ResponseCode('K')
|
||
NoticeResponse = ResponseCode('N')
|
||
AuthenticationRequest = ResponseCode('R')
|
||
ParameterStatus = ResponseCode('S')
|
||
RowDescription = ResponseCode('T')
|
||
FunctionCallResponse = ResponseCode('V')
|
||
CopyBothResponse = ResponseCode('W')
|
||
ReadyForQuery = ResponseCode('Z')
|
||
NoData = ResponseCode('n')
|
||
PortalSuspended = ResponseCode('s')
|
||
ParameterDescription = ResponseCode('t')
|
||
NegotiateProtocolVersion = ResponseCode('v')
|
||
CopyDoneResponse = ResponseCode('c')
|
||
CopyDataResponse = ResponseCode('d')
|
||
)
|
||
|
||
func (r ResponseCode) String() string {
|
||
s, ok := map[ResponseCode]string{
|
||
ParseComplete: "ParseComplete",
|
||
BindComplete: "BindComplete",
|
||
CloseComplete: "CloseComplete",
|
||
NotificationResponse: "NotificationResponse",
|
||
CommandComplete: "CommandComplete",
|
||
DataRow: "DataRow",
|
||
ErrorResponse: "ErrorResponse",
|
||
CopyInResponse: "CopyInResponse",
|
||
CopyOutResponse: "CopyOutResponse",
|
||
EmptyQueryResponse: "EmptyQueryResponse",
|
||
BackendKeyData: "BackendKeyData",
|
||
NoticeResponse: "NoticeResponse",
|
||
AuthenticationRequest: "AuthRequest",
|
||
ParameterStatus: "ParamStatus",
|
||
RowDescription: "RowDescription",
|
||
FunctionCallResponse: "FunctionCallResponse",
|
||
CopyBothResponse: "CopyBothResponse",
|
||
ReadyForQuery: "ReadyForQuery",
|
||
NoData: "NoData",
|
||
PortalSuspended: "PortalSuspended",
|
||
ParameterDescription: "ParamDescription",
|
||
NegotiateProtocolVersion: "NegotiateProtocolVersion",
|
||
CopyDoneResponse: "CopyDone",
|
||
CopyDataResponse: "CopyData",
|
||
}[r]
|
||
if !ok {
|
||
s = "<unknown>"
|
||
}
|
||
c := string(r)
|
||
if r <= 0x1f || r == 0x7f {
|
||
c = fmt.Sprintf("0x%x", string(r))
|
||
}
|
||
return "(" + c + ") " + s
|
||
}
|
||
|
||
// AuthCode are authentication request codes sent by the backend.
|
||
type AuthCode int32
|
||
|
||
// These are the authentication request codes sent by the backend.
|
||
const (
|
||
AuthReqOk = AuthCode(0) // User is authenticated
|
||
AuthReqKrb4 = AuthCode(1) // Kerberos V4. Not supported any more.
|
||
AuthReqKrb5 = AuthCode(2) // Kerberos V5. Not supported any more.
|
||
AuthReqPassword = AuthCode(3) // Password
|
||
AuthReqCrypt = AuthCode(4) // crypt password. Not supported any more.
|
||
AuthReqMD5 = AuthCode(5) // md5 password
|
||
_ = AuthCode(6) // 6 is available. It was used for SCM creds, not supported any more.
|
||
AuthReqGSS = AuthCode(7) // GSSAPI without wrap()
|
||
AuthReqGSSCont = AuthCode(8) // Continue GSS exchanges
|
||
AuthReqSSPI = AuthCode(9) // SSPI negotiate without wrap()
|
||
AuthReqSASL = AuthCode(10) // Begin SASL authentication
|
||
AuthReqSASLCont = AuthCode(11) // Continue SASL authentication
|
||
AuthReqSASLFin = AuthCode(12) // Final SASL message
|
||
)
|
||
|
||
func (a AuthCode) String() string {
|
||
s, ok := map[AuthCode]string{
|
||
AuthReqOk: "ok",
|
||
AuthReqKrb4: "krb4",
|
||
AuthReqKrb5: "krb5",
|
||
AuthReqPassword: "password",
|
||
AuthReqCrypt: "crypt",
|
||
AuthReqMD5: "md5",
|
||
AuthReqGSS: "GDD",
|
||
AuthReqGSSCont: "GSSCont",
|
||
AuthReqSSPI: "SSPI",
|
||
AuthReqSASL: "SASL",
|
||
AuthReqSASLCont: "SASLCont",
|
||
AuthReqSASLFin: "SASLFin",
|
||
}[a]
|
||
if !ok {
|
||
s = "<unknown>"
|
||
}
|
||
return s + " (" + strconv.Itoa(int(a)) + ")"
|
||
}
|