// 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 = "" } 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 = "" } 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 = "" } return s + " (" + strconv.Itoa(int(a)) + ")" }