func (c *FrontendConnection) readDescribeMessage(msg *fbcore.Message) (byte, error) { typ, err := fbbuf.ReadByte(msg.Payload()) if err != nil { return 0, err } if typ != 'S' && typ != 'P' { return 0, fmt.Errorf("invalid type %q", typ) } statementName, err := fbbuf.ReadCString(msg.Payload()) if err != nil { return 0, err } if statementName != "" { return 0, fmt.Errorf("tried to use statement/portal name %q; only unnamed statements and portals are supported") } // TODO: ensure we're at the end of the packet return typ, nil }
func parseLogRecord( dst *logRecord, data []byte, exit exitFn) { b := bytes.NewBuffer(data) // Read the next nullable string from b, returning a 'nil' // *string should it be null. nextNullableString := func() *string { np, err := buf.ReadByte(b) if err != nil { exit(err) } switch np { case 'P': s, err := buf.ReadCString(b) if err != nil { exit(err) } return &s case 'N': // 'N' is still followed by a NUL byte that // must be consumed. _, err := buf.ReadCString(b) if err != nil { exit(err) } return nil default: exit("Expected nullable string "+ "control character, got %c", np) } exit("Prior switch should always return") panic("exit should panic/return, " + "but the compiler doesn't know that") } // Read a non-nullable string from b nextString := func() string { s, err := buf.ReadCString(b) if err != nil { exit(err) } return s } nextInt32 := func() int32 { i32, err := buf.ReadInt32(b) if err != nil { exit(err) } return i32 } nextInt64 := func() int64 { i64, err := readInt64(b) if err != nil { exit(err) } return i64 } nextUint64 := func() uint64 { ui64, err := readUint64(b) if err != nil { exit(err) } return ui64 } dst.LogTime = nextString() dst.UserName = nextNullableString() dst.DatabaseName = nextNullableString() dst.Pid = nextInt32() dst.ClientAddr = nextNullableString() dst.SessionID = nextString() dst.SeqNum = nextInt64() dst.PsDisplay = nextNullableString() dst.SessionStart = nextString() dst.Vxid = nextNullableString() dst.Txid = nextUint64() dst.ELevel = nextInt32() dst.SQLState = nextNullableString() dst.ErrMessage = nextNullableString() dst.ErrDetail = nextNullableString() dst.ErrHint = nextNullableString() dst.InternalQuery = nextNullableString() dst.InternalQueryPos = nextInt32() dst.ErrContext = nextNullableString() dst.UserQuery = nextNullableString() dst.UserQueryPos = nextInt32() dst.FileErrPos = nextNullableString() dst.ApplicationName = nextNullableString() if b.Len() != 0 { exit("LogRecord message has mismatched "+ "length header and cString contents: remaining %d", b.Len()) } }